author | Sebastian Hengst <archaeopteryx@coole-files.de> |
Wed, 13 Sep 2017 23:58:43 +0200 | |
changeset 380724 | 8645a74bbbd06b67699317df1abf3897db0e43d5 |
parent 380634 | 0b3646aa9cbf3f77ee574a553ade9685e9229ab5 (current diff) |
parent 380723 | c777acbcd2a9f0bcf14cbb0fffcdf399d8d6c8d2 (diff) |
child 380725 | c15e2f280729b6503f9455cd4448ab2852eb5806 |
child 380781 | 9d99ac9ae088bcee2b7f89f2aff10ff0bea73f56 |
child 380834 | 2cc3aa0395485e7139c5ab1fd5b515f976f5c074 |
push id | 32492 |
push user | archaeopteryx@coole-files.de |
push date | Wed, 13 Sep 2017 21:59:20 +0000 |
treeherder | mozilla-central@8645a74bbbd0 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | merge, merge |
milestone | 57.0a1 |
first release with | nightly linux32
8645a74bbbd0
/
57.0a1
/
20170913220121
/
files
nightly linux64
8645a74bbbd0
/
57.0a1
/
20170913220121
/
files
nightly mac
8645a74bbbd0
/
57.0a1
/
20170913220121
/
files
nightly win32
8645a74bbbd0
/
57.0a1
/
20170913220121
/
files
nightly win64
8645a74bbbd0
/
57.0a1
/
20170913220121
/
files
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly linux32
57.0a1
/
20170913220121
/
pushlog to previous
nightly linux64
57.0a1
/
20170913220121
/
pushlog to previous
nightly mac
57.0a1
/
20170913220121
/
pushlog to previous
nightly win32
57.0a1
/
20170913220121
/
pushlog to previous
nightly win64
57.0a1
/
20170913220121
/
pushlog to previous
|
--- a/accessible/mac/mozAccessible.mm +++ b/accessible/mac/mozAccessible.mm @@ -1101,17 +1101,21 @@ struct RoleDescrComparator return [NSString stringWithFormat:@"(%p) %@", self, [self role]]; NS_OBJC_END_TRY_ABORT_BLOCK_NIL; } - (BOOL)isFocused { - return FocusMgr()->IsFocused([self getGeckoAccessible]); + if (AccessibleWrap* accWrap = [self getGeckoAccessible]) { + return FocusMgr()->IsFocused(accWrap); + } + + return false; //XXX: proxy implementation is needed. } - (BOOL)canBeFocused { if (AccessibleWrap* accWrap = [self getGeckoAccessible]) return accWrap->InteractiveState() & states::FOCUSABLE; if (ProxyAccessible* proxy = [self getProxyAccessible])
--- a/browser/base/content/test/general/browser.ini +++ b/browser/base/content/test/general/browser.ini @@ -27,16 +27,18 @@ support-files = bug792517.html bug792517.sjs bug839103.css clipboard_pastefile.html contextmenu_common.js ctxmenu-image.png discovery.html download_page.html + download_page_1.txt + download_page_2.txt dummy_page.html feed_tab.html file_generic_favicon.ico file_with_favicon.html file_mediaPlayback.html file_bug970276_popup1.html file_bug970276_popup2.html file_bug970276_favicon1.ico
--- a/browser/base/content/test/general/browser_bug575561.js +++ b/browser/base/content/test/general/browser_bug575561.js @@ -1,15 +1,20 @@ requestLongerTimeout(2); const TEST_URL = "http://example.com/browser/browser/base/content/test/general/app_bug575561.html"; add_task(async function() { SimpleTest.requestCompleteLog(); + // allow top level data: URI navigations, otherwise clicking data: link fails + await SpecialPowers.pushPrefEnv({ + "set": [["security.data_uri.block_toplevel_data_uri_navigations", false]] + }); + // Pinned: Link to the same domain should not open a new tab // Tests link to http://example.com/browser/browser/base/content/test/general/dummy_page.html await testLink(0, true, false); // Pinned: Link to a different subdomain should open a new tab // Tests link to http://test1.example.com/browser/browser/base/content/test/general/dummy_page.html await testLink(1, true, true); // Pinned: Link to a different domain should open a new tab
--- a/browser/base/content/test/general/browser_bug734076.js +++ b/browser/base/content/test/general/browser_bug734076.js @@ -1,12 +1,19 @@ /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ add_task(async function() { + + // allow top level data: URI navigations, otherwise loading data: URIs + // in toplevel windows fail. + await SpecialPowers.pushPrefEnv({ + "set": [["security.data_uri.block_toplevel_data_uri_navigations", false]] + }); + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, null, false); let browser = tab.linkedBrowser; browser.stop(); // stop the about:blank load let writeDomainURL = encodeURI("data:text/html,<script>document.write(document.domain);</script>"); let tests = [
--- a/browser/base/content/test/general/browser_fullscreen-window-open.js +++ b/browser/base/content/test/general/browser_fullscreen-window-open.js @@ -1,29 +1,31 @@ /* eslint-disable mozilla/no-arbitrary-setTimeout */ Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); Components.utils.import("resource://gre/modules/Services.jsm"); var Cc = Components.classes; var Ci = Components.interfaces; const PREF_DISABLE_OPEN_NEW_WINDOW = "browser.link.open_newwindow.disabled_in_fullscreen"; +const PREF_BLOCK_TOPLEVEL_DATA = "security.data_uri.block_toplevel_data_uri_navigations"; const isOSX = (Services.appinfo.OS === "Darwin"); const TEST_FILE = "file_fullscreen-window-open.html"; const gHttpTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); var newWin; var newBrowser; async function test() { waitForExplicitFinish(); Services.prefs.setBoolPref(PREF_DISABLE_OPEN_NEW_WINDOW, true); + Services.prefs.setBoolPref(PREF_BLOCK_TOPLEVEL_DATA, false); newWin = await BrowserTestUtils.openNewBrowserWindow(); newBrowser = newWin.gBrowser; await promiseTabLoadEvent(newBrowser.selectedTab, gHttpTestRoot + TEST_FILE); // Enter browser fullscreen mode. newWin.BrowserFullScreen(); @@ -32,16 +34,17 @@ async function test() { registerCleanupFunction(async function() { // Exit browser fullscreen mode. newWin.BrowserFullScreen(); await BrowserTestUtils.closeWindow(newWin); Services.prefs.clearUserPref(PREF_DISABLE_OPEN_NEW_WINDOW); + Services.prefs.clearUserPref(PREF_BLOCK_TOPLEVEL_DATA); }); var gTests = [ test_open, test_open_with_size, test_open_with_pos, test_open_with_outerSize, test_open_with_innerSize,
--- a/browser/base/content/test/general/download_page.html +++ b/browser/base/content/test/general/download_page.html @@ -6,23 +6,23 @@ https://bugzilla.mozilla.org/show_bug.cg <head> <title>Test for the download attribute</title> </head> <body> <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=676619">Bug 676619</a> <br/> <ul> - <li><a href="data:text/plain,Hey What are you looking for?" + <li><a href="download_page_1.txt" download="test.txt" id="link1">Download "test.txt"</a></li> <li><a href="video.ogg" download id="link2">Download "video.ogg"</a></li> <li><a href="video.ogg" download="just some video" id="link3">Download "just some video"</a></li> - <li><a href="data:text/plain,test" + <li><a href="download_page_2.txt" download="with-target.txt" id="link4">Download "with-target.txt"</a></li> <li><a href="javascript:(1+2)+''" download="javascript.txt" id="link5">Download "javascript.txt"</a></li> </ul> <script> var li = document.createElement("li"); var a = document.createElement("a");
new file mode 100644 --- /dev/null +++ b/browser/base/content/test/general/download_page_1.txt @@ -0,0 +1,1 @@ +Hey What are you looking for?
new file mode 100644 --- /dev/null +++ b/browser/base/content/test/general/download_page_2.txt @@ -0,0 +1,1 @@ +test
--- a/browser/base/content/test/popups/browser.ini +++ b/browser/base/content/test/popups/browser.ini @@ -1,6 +1,12 @@ [browser_popupUI.js] [browser_popup_blocker.js] -support-files = popup_blocker.html +support-files = + popup_blocker.html + popup_blocker_a.html + popup_blocker_b.html skip-if = (os == 'linux') || (e10s && debug) # Frequent bug 1081925 and bug 1125520 failures [browser_popup_frames.js] -support-files = popup_blocker.html +support-files = + popup_blocker.html + popup_blocker_a.html + popup_blocker_b.html
--- a/browser/base/content/test/popups/browser_popup_blocker.js +++ b/browser/base/content/test/popups/browser_popup_blocker.js @@ -59,18 +59,18 @@ add_task(async function test_opening_blo let allow = menu.querySelector("[observes='blockedPopupAllowSite']"); allow.doCommand(); await BrowserTestUtils.waitForCondition(() => popupTabs.length == 2 && popupTabs.every(aTab => aTab.linkedBrowser.currentURI.spec != "about:blank")); gBrowser.tabContainer.removeEventListener("TabOpen", onTabOpen); - is(popupTabs[0].linkedBrowser.currentURI.spec, "data:text/plain;charset=utf-8,a", "Popup a"); - is(popupTabs[1].linkedBrowser.currentURI.spec, "data:text/plain;charset=utf-8,b", "Popup b"); + ok(popupTabs[0].linkedBrowser.currentURI.spec.endsWith("popup_blocker_a.html"), "Popup a"); + ok(popupTabs[1].linkedBrowser.currentURI.spec.endsWith("popup_blocker_b.html"), "Popup b"); // Clean up. gBrowser.removeTab(tab); for (let popup of popupTabs) { gBrowser.removeTab(popup); } clearAllPermissionsByPrefix("popup"); // Ensure the menu closes.
--- a/browser/base/content/test/popups/popup_blocker.html +++ b/browser/base/content/test/popups/popup_blocker.html @@ -1,13 +1,13 @@ <!doctype html> <html> <head> <meta charset="UTF-8"> <title>Page creating two popups</title> </head> <body> <script type="text/javascript"> - window.open("data:text/plain;charset=utf-8,a", "a"); - window.open("data:text/plain;charset=utf-8,b", "b"); + window.open("popup_blocker_a.html", "a"); + window.open("popup_blocker_b.html", "b"); </script> </body> </html>
new file mode 100644 --- /dev/null +++ b/browser/base/content/test/popups/popup_blocker_a.html @@ -0,0 +1,1 @@ +<html><body>a</body></html>
new file mode 100644 --- /dev/null +++ b/browser/base/content/test/popups/popup_blocker_b.html @@ -0,0 +1,1 @@ +<html><body>b</body></html>
--- a/browser/base/content/test/urlbar/browser.ini +++ b/browser/base/content/test/urlbar/browser.ini @@ -24,16 +24,17 @@ support-files = [browser_bug1024133-switchtab-override-keynav.js] [browser_bug1025195_switchToTabHavingURI_aOpenParams.js] [browser_bug1070778.js] [browser_bug1225194-remotetab.js] [browser_bug304198.js] [browser_bug556061.js] subsuite = clipboard [browser_bug562649.js] +support-files = file_bug562649.html [browser_bug623155.js] support-files = redirect_bug623155.sjs [browser_bug783614.js] [browser_canonizeURL.js] [browser_dragdropURL.js] [browser_locationBarCommand.js] [browser_locationBarExternalLoad.js] @@ -114,17 +115,16 @@ support-files = file_urlbar_edit_dos.html [browser_urlbar_searchsettings.js] [browser_urlbar_search_speculative_connect.js] [browser_urlbar_search_speculative_connect_engine.js] support-files = searchSuggestionEngine2.xml searchSuggestionEngine.sjs [browser_urlbar_search_speculative_connect_mousedown.js] -[browser_urlbar_search_no_speculative_connect_with_client_cert.js] [browser_urlbar_stop_pending.js] support-files = slow-page.sjs [browser_urlbar_remoteness_switch.js] run-if = e10s [browser_urlHighlight.js] [browser_wyciwyg_urlbarCopying.js] subsuite = clipboard
--- a/browser/base/content/test/urlbar/browser_bug562649.js +++ b/browser/base/content/test/urlbar/browser_bug562649.js @@ -1,10 +1,11 @@ function test() { - const URI = "data:text/plain,bug562649"; + const TEST_PATH = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "https://example.com"); + const URI = TEST_PATH + "file_bug562649.html"; window.browserDOMWindow.openURI(makeURI(URI), null, Ci.nsIBrowserDOMWindow.OPEN_NEWTAB, Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL, Services.scriptSecurityManager.getSystemPrincipal()); is(gBrowser.userTypedValue, URI, "userTypedValue matches test URI"); is(gURLBar.value, URI, "location bar value matches test URI");
deleted file mode 100644 --- a/browser/base/content/test/urlbar/browser_urlbar_search_no_speculative_connect_with_client_cert.js +++ /dev/null @@ -1,182 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -"use strict"; - -// Test that if we're attempting to speculatively connect to a site but it -// requests a client certificate, we cancel the speculative connection (this -// avoids an unexpected "select a client certificate" dialog). - -const { MockRegistrar } = - Cu.import("resource://testing-common/MockRegistrar.jsm", {}); - -const certService = Cc["@mozilla.org/security/local-cert-service;1"] - .getService(Ci.nsILocalCertService); -const certOverrideService = Cc["@mozilla.org/security/certoverride;1"] - .getService(Ci.nsICertOverrideService); - -const host = "localhost"; -let uri; -let handshakeDone = false; -let expectingChooseCertificate = false; -let chooseCertificateCalled = false; - -const clientAuthDialogs = { - chooseCertificate(ctx, hostname, port, organization, issuerOrg, certList, - selectedIndex) { - ok(expectingChooseCertificate, - `${expectingChooseCertificate ? "" : "not "}expecting chooseCertificate to be called`); - is(certList.length, 1, "should have only one client certificate available"); - selectedIndex.value = 0; - chooseCertificateCalled = true; - return true; - }, - - QueryInterface: XPCOMUtils.generateQI([Ci.nsIClientAuthDialogs]), -}; - -function startServer(cert) { - let tlsServer = Cc["@mozilla.org/network/tls-server-socket;1"] - .createInstance(Ci.nsITLSServerSocket); - tlsServer.init(-1, true, -1); - tlsServer.serverCert = cert; - - let input, output; - - let listener = { - onSocketAccepted(socket, transport) { - info("Accepted TLS client connection"); - let connectionInfo = transport.securityInfo - .QueryInterface(Ci.nsITLSServerConnectionInfo); - connectionInfo.setSecurityObserver(listener); - input = transport.openInputStream(0, 0, 0); - output = transport.openOutputStream(0, 0, 0); - }, - - onHandshakeDone(socket, status) { - info("TLS handshake done"); - handshakeDone = true; - - input.asyncWait({ - onInputStreamReady(readyInput) { - try { - let request = NetUtil.readInputStreamToString(readyInput, - readyInput.available()); - ok(request.startsWith("GET /") && request.includes("HTTP/1.1"), - "expecting an HTTP/1.1 GET request"); - let response = "HTTP/1.1 200 OK\r\nContent-Type:text/plain\r\n" + - "Connection:Close\r\nContent-Length:2\r\n\r\nOK"; - output.write(response, response.length); - } catch (e) { - // This will fail when we close the speculative connection. - } - } - }, 0, 0, Services.tm.currentThread); - }, - - onStopListening() { - info("onStopListening"); - input.close(); - output.close(); - } - }; - - tlsServer.setSessionCache(false); - tlsServer.setSessionTickets(false); - tlsServer.setRequestClientCertificate(Ci.nsITLSServerSocket.REQUEST_ALWAYS); - - tlsServer.asyncListen(listener); - - return tlsServer; -} - -let server; - -add_task(async function setup() { - await SpecialPowers.pushPrefEnv({ - set: [["browser.urlbar.autoFill", true], - // Turn off search suggestion so we won't speculative connect to the search engine. - ["browser.search.suggest.enabled", false], - ["browser.urlbar.speculativeConnect.enabled", true], - // In mochitest this number is 0 by default but we have to turn it on. - ["network.http.speculative-parallel-limit", 6], - // The http server is using IPv4, so it's better to disable IPv6 to avoid weird - // networking problem. - ["network.dns.disableIPv6", true], - ["security.default_personal_cert", "Ask Every Time"]], - }); - - let clientAuthDialogsCID = - MockRegistrar.register("@mozilla.org/nsClientAuthDialogs;1", - clientAuthDialogs); - - let cert = await new Promise((resolve, reject) => { - certService.getOrCreateCert("speculative-connect", { - handleCert(c, rv) { - if (!Components.isSuccessCode(rv)) { - reject(rv); - return; - } - resolve(c); - } - }); - }); - server = startServer(cert); - uri = `https://${host}:${server.port}/`; - info(`running tls server at ${uri}`); - await PlacesTestUtils.addVisits([{ - uri, - title: "test visit for speculative connection", - transition: Ci.nsINavHistoryService.TRANSITION_TYPED, - }]); - - let overrideBits = Ci.nsICertOverrideService.ERROR_UNTRUSTED | - Ci.nsICertOverrideService.ERROR_MISMATCH; - certOverrideService.rememberValidityOverride("localhost", server.port, cert, - overrideBits, true); - - registerCleanupFunction(async function() { - await PlacesUtils.history.clear(); - MockRegistrar.unregister(clientAuthDialogsCID); - certOverrideService.clearValidityOverride("localhost", server.port); - }); -}); - -add_task(async function popup_mousedown_no_client_cert_dialog_until_navigate_test() { - const test = { - // To not trigger autofill, search keyword starts from the second character. - search: host.substr(1, 4), - completeValue: uri - }; - info(`Searching for '${test.search}'`); - await promiseAutocompleteResultPopup(test.search, window, true); - let controller = gURLBar.popup.input.controller; - // The first item should be 'Search with ...' thus we want the second. - let value = controller.getFinalCompleteValueAt(1); - info(`The value of the second item is ${value}`); - is(value, test.completeValue, "The second item has the url we visited."); - - await BrowserTestUtils.waitForCondition(() => { - return !!gURLBar.popup.richlistbox.childNodes[1] && - is_visible(gURLBar.popup.richlistbox.childNodes[1]); - }, "the node is there."); - - let listitem = gURLBar.popup.richlistbox.childNodes[1]; - EventUtils.synthesizeMouse(listitem, 10, 10, {type: "mousedown"}, window); - is(gURLBar.popup.richlistbox.selectedIndex, 1, "The second item is selected"); - // Since we don't know before connecting that a server will request a client - // certificate, we actually do make a speculative connection. The trick is - // that we cancel it and don't re-use it if we are asked for a certificate - // (and of course we don't show the certificate-picking UI). So, the TLS - // server will actually complete the handshake. - await BrowserTestUtils.waitForCondition(() => handshakeDone, - "waiting for handshake to complete"); - // Now mouseup, expect that we choose a client certificate, and expect that we - // successfully load a page. - expectingChooseCertificate = true; - EventUtils.synthesizeMouse(listitem, 10, 10, {type: "mouseup"}, window); - await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser); - ok(chooseCertificateCalled, "chooseCertificate must have been called"); - server.close(); -});
new file mode 100644 --- /dev/null +++ b/browser/base/content/test/urlbar/file_bug562649.html @@ -0,0 +1,1 @@ +<html><body>bug562649</body></html>
--- a/browser/components/extensions/test/browser/browser_ext_tabs_executeScript_bad.js +++ b/browser/components/extensions/test/browser/browser_ext_tabs_executeScript_bad.js @@ -198,16 +198,22 @@ add_task(async function testBadPermissio }, }); await BrowserTestUtils.removeTab(tab2); await BrowserTestUtils.removeTab(tab1); }); add_task(async function testMatchDataURI() { + // allow top level data: URI navigations, otherwise + // window.location.href = data: would be blocked + await SpecialPowers.pushPrefEnv({ + "set": [["security.data_uri.block_toplevel_data_uri_navigations", false]], + }); + const target = ExtensionTestUtils.loadExtension({ files: { "page.html": `<!DOCTYPE html> <meta charset="utf-8"> <script src="page.js"></script> <iframe id="inherited" src="data:text/html;charset=utf-8,inherited"></iframe> `, "page.js": function() {
--- a/browser/components/originattributes/test/browser/browser_firstPartyIsolation_aboutPages.js +++ b/browser/components/originattributes/test/browser/browser_firstPartyIsolation_aboutPages.js @@ -63,16 +63,21 @@ function frame_script() { let element = content.document.getElementById("test"); element.click(); } /** * Check if data: URI inherits firstPartyDomain from about:blank correctly. */ add_task(async function test_remote_window_open_data_uri() { + // allow top level data: URI navigations, otherwise + // <a href="data:" would fail. + await SpecialPowers.pushPrefEnv({ + "set": [["security.data_uri.block_toplevel_data_uri_navigations", false]] + }); let win = await BrowserTestUtils.openNewBrowserWindow({ remote: true }); let browser = win.gBrowser.selectedBrowser; let mm = browser.messageManager; mm.loadFrameScript("data:,(" + frame_script.toString() + ")();", true); await BrowserTestUtils.browserLoaded(browser, false, function(url) { return url == "data:text/plain,hello"; });
--- a/browser/components/places/content/controller.js +++ b/browser/components/places/content/controller.js @@ -1593,29 +1593,36 @@ var PlacesControllerDragHelper = { let parentGuid = insertionPoint.guid; let tagName = insertionPoint.tagName; // Following flavors may contain duplicated data. let duplicable = new Map(); duplicable.set(PlacesUtils.TYPE_UNICODE, new Set()); duplicable.set(PlacesUtils.TYPE_X_MOZ_URL, new Set()); + // Collect all data from the DataTransfer before processing it, as the + // DataTransfer is only valid during the synchronous handling of the `drop` + // event handler callback. + let dtItems = []; for (let i = 0; i < dropCount; ++i) { let flavor = this.getFirstValidFlavor(dt.mozTypesAt(i)); if (!flavor) return; let data = dt.mozGetDataAt(flavor, i); if (duplicable.has(flavor)) { let handled = duplicable.get(flavor); if (handled.has(data)) continue; handled.add(data); } + dtItems.push({flavor, data}); + } + for (let {flavor, data} of dtItems) { let nodes; if (flavor != TAB_DROP_TYPE) { nodes = PlacesUtils.unwrapNodes(data, flavor); } else if (data instanceof XULElement && data.localName == "tab" && data.ownerGlobal instanceof ChromeWindow) { let uri = data.linkedBrowser.currentURI; let spec = uri ? uri.spec : "about:blank"; nodes = [{ uri: spec,
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_newtab_from_popup.js +++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_newtab_from_popup.js @@ -17,16 +17,20 @@ const POPUP_LINK = `data:text/html;chars const WINDOW_BODY = `data:text/html, <a href="%23" id="first" onclick="window.open('${POPUP_LINK}', '_blank', 'width=630,height=500')"> First click this. </a>`; add_task(async function test_private_popup_window_opens_private_tabs() { + // allow top level data: URI navigations, otherwise clicking a data: link fails + await SpecialPowers.pushPrefEnv({ + "set": [["security.data_uri.block_toplevel_data_uri_navigations", false]] + }); let privWin = await BrowserTestUtils.openNewBrowserWindow({ private: true }); // Sanity check - this browser better be private. ok(PrivateBrowsingUtils.isWindowPrivate(privWin), "Opened a private browsing window."); // First, open a private browsing window, and load our // testing page.
--- a/browser/components/sessionstore/content/content-sessionStore.js +++ b/browser/components/sessionstore/content/content-sessionStore.js @@ -46,16 +46,18 @@ var gCurrentEpoch = 0; // A bound to the size of data to store for DOM Storage. const DOM_STORAGE_LIMIT_PREF = "browser.sessionstore.dom_storage_limit"; // This pref controls whether or not we send updates to the parent on a timeout // or not, and should only be used for tests or debugging. const TIMEOUT_DISABLED_PREF = "browser.sessionstore.debug.no_auto_updates"; +const PREF_INTERVAL = "browser.sessionstore.interval"; + const kNoIndex = Number.MAX_SAFE_INTEGER; const kLastIndex = Number.MAX_SAFE_INTEGER - 1; /** * A function that will recursively call |cb| to collected data for all * non-dynamic frames in the current frame/docShell tree. */ function mapFrameTree(callback) { @@ -728,29 +730,46 @@ var MessageQueue = { /** * The delay (in ms) used to delay sending changes after data has been * invalidated. */ BATCH_DELAY_MS: 1000, /** + * The minimum idle period (in ms) we need for sending data to chrome process. + */ + NEEDED_IDLE_PERIOD_MS: 5, + + /** + * Timeout for waiting an idle period to send data. We will set this from + * the pref "browser.sessionstore.interval". + */ + _timeoutWaitIdlePeriodMs: null, + + /** * The current timeout ID, null if there is no queue data. We use timeouts * to damp a flood of data changes and send lots of changes as one batch. */ _timeout: null, /** * Whether or not sending batched messages on a timer is disabled. This should * only be used for debugging or testing. If you need to access this value, * you should probably use the timeoutDisabled getter. */ _timeoutDisabled: false, /** + * The idle callback ID referencing an active idle callback. When no idle + * callback is pending, this is null. + * */ + _idleCallbackID: null, + + /** * True if batched messages are not being fired on a timer. This should only * ever be true when debugging or during tests. */ get timeoutDisabled() { return this._timeoutDisabled; }, /** @@ -766,28 +785,58 @@ var MessageQueue = { } return val; }, init() { this.timeoutDisabled = Services.prefs.getBoolPref(TIMEOUT_DISABLED_PREF); + this._timeoutWaitIdlePeriodMs = + Services.prefs.getIntPref(PREF_INTERVAL); Services.prefs.addObserver(TIMEOUT_DISABLED_PREF, this); + Services.prefs.addObserver(PREF_INTERVAL, this); }, uninit() { Services.prefs.removeObserver(TIMEOUT_DISABLED_PREF, this); + Services.prefs.removeObserver(PREF_INTERVAL, this); + this.cleanupTimers(); + }, + + /** + * Cleanup pending idle callback and timer. + */ + cleanupTimers() { + if (this._idleCallbackID) { + content.cancelIdleCallback(this._idleCallbackID); + this._idleCallbackID = null; + } + if (this._timeout) { + clearTimeout(this._timeout); + this._timeout = null; + } }, observe(subject, topic, data) { - if (topic == "nsPref:changed" && data == TIMEOUT_DISABLED_PREF) { - this.timeoutDisabled = - Services.prefs.getBoolPref(TIMEOUT_DISABLED_PREF); + if (topic == "nsPref:changed") { + switch (data) { + case TIMEOUT_DISABLED_PREF: + this.timeoutDisabled = + Services.prefs.getBoolPref(TIMEOUT_DISABLED_PREF); + break; + case PREF_INTERVAL: + this._timeoutWaitIdlePeriodMs = + Services.prefs.getIntPref(PREF_INTERVAL); + break; + default: + debug("received unknown message '" + data + "'"); + break; + } } }, /** * Pushes a given |value| onto the queue. The given |key| represents the type * of data that is stored and can override data that has been queued before * but has not been sent to the parent process, yet. * @@ -798,39 +847,58 @@ var MessageQueue = { * process. */ push(key, fn) { this._data.set(key, fn); if (!this._timeout && !this._timeoutDisabled) { // Wait a little before sending the message to batch multiple changes. this._timeout = setTimeoutWithTarget( - () => this.send(), this.BATCH_DELAY_MS, tabEventTarget); + () => this.sendWhenIdle(), this.BATCH_DELAY_MS, tabEventTarget); } }, /** + * Sends queued data when the remaining idle time is enough or waiting too + * long; otherwise, request an idle time again. If the |deadline| is not + * given, this function is going to schedule the first request. + * + * @param deadline (object) + * An IdleDeadline object passed by requestIdleCallback(). + */ + sendWhenIdle(deadline) { + if (deadline) { + if (deadline.didTimeout || deadline.timeRemaining() > MessageQueue.NEEDED_IDLE_PERIOD_MS) { + MessageQueue.send(); + return; + } + } else if (MessageQueue._idleCallbackID) { + // Bail out if there's a pending run. + return; + } + MessageQueue._idleCallbackID = + content.requestIdleCallback(MessageQueue.sendWhenIdle, {timeout: MessageQueue._timeoutWaitIdlePeriodMs}); + }, + + /** * Sends queued data to the chrome process. * * @param options (object) * {flushID: 123} to specify that this is a flush * {isFinal: true} to signal this is the final message sent on unload */ send(options = {}) { // Looks like we have been called off a timeout after the tab has been // closed. The docShell is gone now and we can just return here as there // is nothing to do. if (!docShell) { return; } - if (this._timeout) { - clearTimeout(this._timeout); - this._timeout = null; - } + this.cleanupTimers(); let flushID = (options && options.flushID) || 0; let histID = "FX_SESSION_RESTORE_CONTENT_COLLECT_DATA_MS"; let data = {}; for (let [key, func] of this._data) { if (key != "isPrivate") { TelemetryStopwatch.startKeyed(histID, key);
--- a/browser/components/sessionstore/test/browser.ini +++ b/browser/components/sessionstore/test/browser.ini @@ -65,17 +65,19 @@ support-files = #disabled-for-intermittent-failures--bug-766044, browser_459906_empty.html #disabled-for-intermittent-failures--bug-766044, browser_459906_sample.html #disabled-for-intermittent-failures--bug-765389, browser_461743_sample.html [browser_aboutPrivateBrowsing.js] [browser_aboutSessionRestore.js] [browser_async_duplicate_tab.js] +support-files = file_async_duplicate_tab.html [browser_async_flushes.js] +support-files = file_async_flushes.html run-if = e10s && crashreporter skip-if = debug # bug 1167933 [browser_async_remove_tab.js] run-if = e10s skip-if = debug # bug 1211084 [browser_attributes.js] [browser_backup_recovery.js] [browser_broadcast.js] @@ -106,16 +108,18 @@ skip-if = (os == 'win') # bug 1331853 [browser_purge_shistory.js] skip-if = e10s # Bug 1271024 [browser_replace_load.js] [browser_restore_redirect.js] [browser_restore_cookies_noOriginAttributes.js] [browser_scrollPositions.js] [browser_scrollPositionsReaderMode.js] [browser_sessionHistory.js] +support-files = + file_sessionHistory_hashchange.html [browser_sessionStorage.js] [browser_sessionStorage_size.js] [browser_tab_label_during_restore.js] [browser_swapDocShells.js] [browser_switch_remoteness.js] run-if = e10s [browser_upgrade_backup.js] [browser_windowRestore_perwindowpb.js]
--- a/browser/components/sessionstore/test/browser_911547.js +++ b/browser/components/sessionstore/test/browser_911547.js @@ -6,16 +6,20 @@ // this tests that session restore component does restore the right // content security policy with the document. (The policy being // tested disallows inline scripts). // b) if security.data_uri.unique_opaque_origin == true, then // this tests that data: URIs do not inherit the CSP from // it's enclosing context. add_task(async function test() { + // allow top level data: URI navigations, otherwise clicking a data: link fails + await SpecialPowers.pushPrefEnv({ + "set": [["security.data_uri.block_toplevel_data_uri_navigations", false]] + }); let dataURIPref = Services.prefs.getBoolPref("security.data_uri.unique_opaque_origin"); // create a tab that has a CSP let testURL = "http://mochi.test:8888/browser/browser/components/sessionstore/test/browser_911547_sample.html"; let tab = gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, testURL); gBrowser.selectedTab = tab; let browser = tab.linkedBrowser; await promiseBrowserLoaded(browser);
--- a/browser/components/sessionstore/test/browser_async_duplicate_tab.js +++ b/browser/components/sessionstore/test/browser_async_duplicate_tab.js @@ -1,11 +1,13 @@ "use strict"; -const URL = "data:text/html;charset=utf-8,<a href=%23>clickme</a>"; +const PATH = getRootDirectory(gTestPath) + .replace("chrome://mochitests/content/", "http://example.com/"); +const URL = PATH + "file_async_duplicate_tab.html"; add_task(async function test_duplicate() { // Create new tab. let tab = BrowserTestUtils.addTab(gBrowser, URL); let browser = tab.linkedBrowser; await promiseBrowserLoaded(browser); // Flush to empty any queued update messages.
--- a/browser/components/sessionstore/test/browser_async_flushes.js +++ b/browser/components/sessionstore/test/browser_async_flushes.js @@ -1,11 +1,13 @@ "use strict"; -const URL = "data:text/html;charset=utf-8,<a href=%23>clickme</a>"; +const PATH = getRootDirectory(gTestPath) + .replace("chrome://mochitests/content/", "http://example.com/"); +const URL = PATH + "file_async_flushes.html"; add_task(async function test_flush() { // Create new tab. let tab = BrowserTestUtils.addTab(gBrowser, URL); let browser = tab.linkedBrowser; await promiseBrowserLoaded(browser); // Flush to empty any queued update messages.
--- a/browser/components/sessionstore/test/browser_dynamic_frames.js +++ b/browser/components/sessionstore/test/browser_dynamic_frames.js @@ -3,16 +3,20 @@ "use strict"; /** * Ensure that static frames of framesets are serialized but dynamically * inserted iframes are ignored. */ add_task(async function() { + // allow top level data: URI navigations, otherwise clicking a data: link fails + await SpecialPowers.pushPrefEnv({ + "set": [["security.data_uri.block_toplevel_data_uri_navigations", false]] + }); // This URL has the following frames: // + data:text/html,A (static) // + data:text/html,B (static) // + data:text/html,C (dynamic iframe) const URL = "data:text/html;charset=utf-8," + "<frameset cols=50%25,50%25><frame src='data:text/html,A'>" + "<frame src='data:text/html,B'></frameset>" + "<script>var i=document.createElement('iframe');" + @@ -41,16 +45,20 @@ add_task(async function() { }); /** * Ensure that iframes created by the network parser are serialized but * dynamically inserted iframes are ignored. Navigating a subframe should * create a second root entry that doesn't contain any dynamic children either. */ add_task(async function() { + // allow top level data: URI navigations, otherwise clicking a data: link fails + await SpecialPowers.pushPrefEnv({ + "set": [["security.data_uri.block_toplevel_data_uri_navigations", false]] + }); // This URL has the following frames: // + data:text/html,A (static) // + data:text/html,C (dynamic iframe) const URL = "data:text/html;charset=utf-8," + "<iframe name=t src='data:text/html,A'></iframe>" + "<a id=lnk href='data:text/html,B' target=t>clickme</a>" + "<script>var i=document.createElement('iframe');" + "i.setAttribute('src', 'data:text/html,C');" +
--- a/browser/components/sessionstore/test/browser_sessionHistory.js +++ b/browser/components/sessionstore/test/browser_sessionHistory.js @@ -32,18 +32,19 @@ add_task(async function test_load_start( // Cleanup. gBrowser.removeTab(tab); }); /** * Ensure that anchor navigation invalidates shistory. */ add_task(async function test_hashchange() { - const URL = "data:text/html;charset=utf-8,<a id=a href=%23>clickme</a>"; - + const PATH = getRootDirectory(gTestPath) + .replace("chrome://mochitests/content/", "http://example.com/"); + const URL = PATH + "file_sessionHistory_hashchange.html"; // Create a new tab. let tab = BrowserTestUtils.addTab(gBrowser, URL); let browser = tab.linkedBrowser; await promiseBrowserLoaded(browser); // Check that we start with a single shistory entry. await TabStateFlusher.flush(browser); let {entries} = JSON.parse(ss.getTabState(tab));
new file mode 100644 --- /dev/null +++ b/browser/components/sessionstore/test/file_async_duplicate_tab.html @@ -0,0 +1,1 @@ +<a href=#>clickme</a>
new file mode 100644 --- /dev/null +++ b/browser/components/sessionstore/test/file_async_flushes.html @@ -0,0 +1,1 @@ +<a href=#>clickme</a>
new file mode 100644 --- /dev/null +++ b/browser/components/sessionstore/test/file_sessionHistory_hashchange.html @@ -0,0 +1,1 @@ +<a id=a href=#>clickme</a>
--- a/browser/installer/windows/nsis/stub.nsi +++ b/browser/installer/windows/nsis/stub.nsi @@ -743,22 +743,22 @@ Function createInstall FindWindow $7 "#32770" "" $HWNDPARENT ${GetDlgItemWidthHeight} $HWNDPARENT $8 $9 ; Resize the Dialog to fill the entire window System::Call 'user32::MoveWindow(i$Dialog,i0,i0,i $8,i $9,i0)' ; The header string may need more than half the width of the window, but it's ; currently not close to needing multiple lines in any localization. - ${NSD_CreateLabelCenter} 0% ${NOW_INSTALLING_TOP_DU} 100% 47u "$(STUB_INSTALLING_LABEL)" + ${NSD_CreateLabelCenter} 0% ${NOW_INSTALLING_TOP_DU} 100% 47u "$(STUB_INSTALLING_LABEL2)" Pop $0 SendMessage $0 ${WM_SETFONT} $FontInstalling 0 SetCtlColors $0 ${INSTALL_BLURB_TEXT_COLOR} transparent - ${NSD_CreateLabelCenter} 0% ${INSTALL_BLURB_TOP_DU} 100% 60u "$(STUB_BLURB1)" + ${NSD_CreateLabelCenter} 0% ${INSTALL_BLURB_TOP_DU} 100% 60u "$(STUB_BLURB_FIRST1)" Pop $LabelBlurb SendMessage $LabelBlurb ${WM_SETFONT} $FontBlurb 0 SetCtlColors $LabelBlurb ${INSTALL_BLURB_TEXT_COLOR} transparent StrCpy $CurrentBlurbIdx "0" ${GetTextWidthHeight} "$(STUB_BLURB_FOOTER2)" $FontFooter \ ${INSTALL_FOOTER_WIDTH_DU} $R1 $R2 @@ -891,21 +891,21 @@ FunctionEnd Function NextBlurb ${NSD_KillTimer} NextBlurb IntOp $CurrentBlurbIdx $CurrentBlurbIdx + 1 IntOp $CurrentBlurbIdx $CurrentBlurbIdx % 3 ${If} $CurrentBlurbIdx == "0" - StrCpy $0 "$(STUB_BLURB1)" + StrCpy $0 "$(STUB_BLURB_FIRST1)" ${ElseIf} $CurrentBlurbIdx == "1" - StrCpy $0 "$(STUB_BLURB2)" + StrCpy $0 "$(STUB_BLURB_SECOND1)" ${ElseIf} $CurrentBlurbIdx == "2" - StrCpy $0 "$(STUB_BLURB3)" + StrCpy $0 "$(STUB_BLURB_THIRD1)" ${EndIf} SendMessage $LabelBlurb ${WM_SETTEXT} 0 "STR:$0" ${NSD_CreateTimer} ClearBlurb ${BlurbDisplayMS} FunctionEnd Function ClearBlurb
--- a/browser/locales/en-US/installer/nsisstrings.properties +++ b/browser/locales/en-US/installer/nsisstrings.properties @@ -23,21 +23,17 @@ INSTALLER_WIN_CAPTION=$BrandShortName In # The \n in the next two strings can be moved or deleted as needed to make # the string fit in the 3 lines of space available. STUB_CLEANUP_PAVEOVER_HEADER=$BrandShortName is already installed.\nLet's update it. STUB_CLEANUP_REINSTALL_HEADER=$BrandShortName has been installed before.\nLet's get you a new copy. STUB_CLEANUP_PAVEOVER_BUTTON=&Update STUB_CLEANUP_REINSTALL_BUTTON=Re-&install STUB_CLEANUP_CHECKBOX_LABEL=&Restore default settings and remove old add-ons for optimal performance -STUB_INSTALLING_LABEL=Now installing STUB_INSTALLING_LABEL2=Now installing… -STUB_BLURB1=Fast, responsive online experiences -STUB_BLURB2=Compatibility with more of your favorite sites -STUB_BLURB3=Built-in privacy tools for safer browsing STUB_BLURB_FIRST1=The fastest, most responsive $BrandShortName yet STUB_BLURB_SECOND1=Faster page loading and tab switching STUB_BLURB_THIRD1=Powerful private browsing STUB_BLURB_FOOTER2=Built for people, not for profit WARN_MIN_SUPPORTED_OSVER_MSG=Sorry, $BrandShortName can't be installed. This version of $BrandShortName requires ${MinSupportedVer} or newer. Please click the OK button for additional information. WARN_MIN_SUPPORTED_CPU_MSG=Sorry, $BrandShortName can't be installed. This version of $BrandShortName requires a processor with ${MinSupportedCPU} support. Please click the OK button for additional information. WARN_MIN_SUPPORTED_OSVER_CPU_MSG=Sorry, $BrandShortName can't be installed. This version of $BrandShortName requires ${MinSupportedVer} or newer and a processor with ${MinSupportedCPU} support. Please click the OK button for additional information.
--- a/build/moz.configure/windows.configure +++ b/build/moz.configure/windows.configure @@ -217,16 +217,21 @@ def valid_ucrt_sdk_dir(windows_sdk_dir, 'CRT.' % windows_sdk_dir_env) valid_sdks = sorted(sdks, key=lambda x: sdks[x][0], reverse=True) if not valid_sdks: raise FatalCheckError('Cannot find the Universal CRT SDK. ' 'Please install it.') version, sdk = sdks[valid_sdks[0]] + minimum_ucrt_version = Version('10.0.10586.0') + if version < minimum_ucrt_version: + raise FatalCheckError('Latest Universal CRT SDK version found %s' + ' and minimum required is %s.' + % (version, minimum_ucrt_version)) return namespace( path=sdk.path, include=sdk.include, lib=sdk.lib, version=version, )
--- a/devtools/client/framework/options-panel.css +++ b/devtools/client/framework/options-panel.css @@ -113,11 +113,11 @@ #screenshot-options legend::after { content: ""; display: inline-block; background-image: url("chrome://devtools/skin/images/command-screenshot.svg"); width: 16px; height: 16px; vertical-align: sub; margin-inline-start: 5px; - filter: var(--icon-filter); + filter: var(--theme-icon-filter); opacity: 0.6; }
--- a/devtools/client/inspector/layout/components/Accordion.css +++ b/devtools/client/inspector/layout/components/Accordion.css @@ -34,17 +34,17 @@ width: 100%; align-items: center; display: flex; -moz-user-select: none; } .accordion ._header:hover { - background-color: var(--theme-toolbar-background-hover); + background-color: var(--theme-toolbar-hover); } .accordion ._header:hover svg { fill: var(--theme-comment-alt); } .accordion ._content { border-bottom: 1px solid var(--theme-splitter-color);
--- a/devtools/client/netmonitor/src/assets/styles/netmonitor.css +++ b/devtools/client/netmonitor/src/assets/styles/netmonitor.css @@ -1177,17 +1177,17 @@ body, padding-inline-end: 0; margin-top: 3px; margin-bottom: 3px; margin-inline-end: 1em; } .requests-list-network-summary-button > .summary-info-icon { background: url(chrome://devtools/skin/images/profiler-stopwatch.svg) no-repeat; - filter: var(--icon-filter); + filter: var(--theme-icon-filter); width: 16px; height: 16px; opacity: 0.8; } .requests-list-network-summary-button:hover > .summary-info-icon { opacity: 1; }
--- a/devtools/client/responsive.html/index.css +++ b/devtools/client/responsive.html/index.css @@ -71,17 +71,17 @@ body, .toolbar-button:empty:hover:not(:disabled), .toolbar-button:empty:-moz-any(:hover:active, .checked):not(:disabled) { /* Reset background from .devtools-button */ background: none; } .toolbar-button:active::before { - filter: var(--checked-icon-filter); + filter: var(--theme-icon-checked-filter); } select { -moz-appearance: none; background-color: var(--theme-toolbar-background); background-image: var(--viewport-selection-arrow); -moz-context-properties: fill; fill: currentColor; @@ -161,17 +161,17 @@ select > option.divider { background-image: url("./images/screenshot.svg"); } #global-exit-button::before { background-image: url("chrome://devtools/skin/images/close.svg"); } #global-screenshot-button:disabled { - filter: var(--checked-icon-filter); + filter: var(--theme-icon-checked-filter); opacity: 1 !important; } #global-network-throttling-selector { height: 15px; padding-left: 0; width: 103px; }
--- a/devtools/client/shared/components/tabs/tabs.css +++ b/devtools/client/shared/components/tabs/tabs.css @@ -79,16 +79,21 @@ .theme-dark .tabs .tabs-menu-item, .theme-light .tabs .tabs-menu-item { margin: 0; padding: 0; color: var(--theme-toolbar-color); } +.theme-dark .tabs .tabs-menu-item.is-active, +.theme-light .tabs .tabs-menu-item.is-active { + color: var(--theme-toolbar-selected-color); +} + .theme-dark .tabs .tabs-menu-item:last-child, .theme-light:not(.theme-firebug) .tabs .tabs-menu-item:last-child { border-inline-end-width: 1px; } .theme-dark .tabs .tabs-menu-item a, .theme-light .tabs .tabs-menu-item a { padding: 3px 15px;
--- a/devtools/client/shared/test/browser_theme.js +++ b/devtools/client/shared/test/browser_theme.js @@ -96,12 +96,12 @@ function testColorExistence() { "comment", "body-color", "body-color-alt", "content-color1", "content-color2", "content-color3", "highlight-green", "highlight-blue", "highlight-bluegrey", "highlight-purple", "highlight-lightorange", "highlight-orange", "highlight-red", "highlight-pink" ]; for (let type of vars) { ok(getColor(type, "light"), `${type} is a valid color in light theme`); - ok(getColor(type, "dark"), `${type} is a valid color in light theme`); - ok(getColor(type, "firebug"), `${type} is a valid color in light theme`); + ok(getColor(type, "dark"), `${type} is a valid color in dark theme`); + ok(getColor(type, "firebug"), `${type} is a valid color in firebug theme`); } }
--- a/devtools/client/shared/widgets/filter-widget.css +++ b/devtools/client/shared/widgets/filter-widget.css @@ -226,14 +226,14 @@ #toggle-presets { background: url(chrome://devtools/skin/images/pseudo-class.svg); } #filter-container .add, #filter-container .remove-button, #toggle-presets { - filter: var(--icon-filter); + filter: var(--theme-icon-filter); } .show-presets #toggle-presets { filter: url(chrome://devtools/skin/images/filters.svg#checked-icon-state); }
--- a/devtools/client/sourceeditor/editor.js +++ b/devtools/client/sourceeditor/editor.js @@ -546,17 +546,17 @@ Editor.prototype = { /** * Replaces whatever is in the text area with the contents of * the 'value' argument. */ setText: function (value) { let cm = editors.get(this); - if (typeof value !== "string") { // wasm? + if (typeof value !== "string" && "binary" in value) { // wasm? // binary does not survive as Uint8Array, converting from string let binary = value.binary; let data = new Uint8Array(binary.length); for (let i = 0; i < data.length; i++) { data[i] = binary.charCodeAt(i); } let { lines, done } = getWasmText(this.getDoc(), data); const MAX_LINES = 10000000;
--- a/devtools/client/themes/common.css +++ b/devtools/client/themes/common.css @@ -289,38 +289,33 @@ checkbox:-moz-focusring { } /* Icon button styles */ .devtools-toolbarbutton:not([label]) > .toolbarbutton-text { display: none; } /* Icon-only buttons */ -.devtools-button:empty::before, -.devtools-toolbarbutton:not([label]):not([disabled]) > image { - opacity: 0.8; -} - .devtools-button:hover:empty:not(:disabled):before, .devtools-button.checked:empty::before, .devtools-toolbarbutton:not([label]):not([disabled=true]):hover > image, .devtools-toolbarbutton:not([label])[checked=true] > image, .devtools-toolbarbutton:not([label])[open=true] > image { opacity: 1; } .devtools-button:disabled, .devtools-toolbarbutton[disabled] { opacity: 0.5 !important; } .devtools-button.checked::before, .devtools-toolbarbutton:not([label])[checked=true] > image, .devtools-toolbarbutton:not([label])[open=true] > image { - filter: var(--checked-icon-filter); + filter: var(--theme-icon-checked-filter); } /* Button states */ .devtools-toolbarbutton[label]:not([type=menu-button]), .devtools-toolbarbutton[standalone], .devtools-button[data-standalone], .devtools-button:not(:empty) { background: var(--toolbarbutton-background);
--- a/devtools/client/themes/images/filters.svg +++ b/devtools/client/themes/images/filters.svg @@ -1,25 +1,59 @@ <!-- 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/. --> <svg height="0" xmlns="http://www.w3.org/2000/svg"> - <filter id="checked-icon-state"> + <!-- DevTools icon filter: Grey 90 + 0.8 opacity (light theme normal) --> + <filter id="icon-normal-light"> <feColorMatrix in="SourceGraphic" type="matrix" - values="0 0 0 0 0.043 - 0 0 0 0 0.415 - 0 0 0 0 0.79 + values="0 0 0 0 0.01 + 0 0 0 0 0.01 + 0 0 0 0 0.01 + 0 0 0 0.8 0"/> + </filter> + <!-- DevTools icon filter: Photon Blue 60 (light theme selected) --> + <filter id="icon-selected-light"> + <feColorMatrix in="SourceGraphic" type="matrix" + values="0 0 0 0 0 + 0 0 0 0 0.122 + 0 0 0 0 0.74 0 0 0 1 0"/> </filter> - <filter id="dark-theme-checked-icon-state"> + <!-- DevTools icon filter: Photon Blue 60 (light theme checked) --> + <filter id="icon-checked-light"> <feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 0 + 0 0 0 0 0.122 + 0 0 0 0 0.74 + 0 0 0 1 0"/> + </filter> + <!-- DevTools icon filter: Grey 10 + 0.8 opacity (dark theme normal) --> + <filter id="icon-normal-dark"> + <feColorMatrix in="SourceGraphic" type="matrix" + values="0 0 0 0 0.945 + 0 0 0 0 0.945 + 0 0 0 0 0.95 + 0 0 0 0.8 0"/> + </filter> + <!-- DevTools icon filter: white (dark theme selected) --> + <filter id="icon-selected-dark"> + <feColorMatrix in="SourceGraphic" type="matrix" + values="0 0 0 0 1 0 0 0 0 1 - 0 0 0 0 0.212 + 0 0 0 0 1 + 0 0 0 1 0"/> + </filter> + <!-- DevTools icon filter: syntax blue #75BFFF (dark theme checked) --> + <filter id="icon-checked-dark"> + <feColorMatrix in="SourceGraphic" type="matrix" + values="0 0 0 0.18 0 + 0 0 0 0.52 0 + 0 0 0 1 0 0 0 0 1 0"/> </filter> <!-- Web Audio Gradients --> <linearGradient id="bypass-light" x1="8%" y1="10%" x2="16%" y2="16%" spreadMethod="repeat"> <stop offset="0%" stop-color="#dde1e4a0"/> <!-- theme-splitter-color (0.5 opacity) --> <stop offset="50%" stop-color="transparent"/> </linearGradient>
--- a/devtools/client/themes/shadereditor.css +++ b/devtools/client/themes/shadereditor.css @@ -52,17 +52,17 @@ } .side-menu-widget-item-checkbox:not([checked]) .checkbox-check, .side-menu-widget-item-checkbox:not([checked]) + vbox { opacity: 0.3; } .side-menu-widget-item:not(.selected) .checkbox-check { - filter: var(--icon-filter); + filter: var(--theme-icon-filter); } /* Make sure icon is white when the item is selected */ .side-menu-widget-item.selected .checkbox-check { filter: invert(1); } /* Shader source editors */
--- a/devtools/client/themes/styleeditor.css +++ b/devtools/client/themes/styleeditor.css @@ -168,17 +168,17 @@ li.error > .stylesheet-info > .styleshee margin: 0 8px; background-image: url(images/item-toggle.svg); background-repeat: no-repeat; background-clip: content-box; background-position: center; background-size: 16px; width: 24px; height: 40px; - filter: var(--icon-filter); + filter: var(--theme-icon-filter); } .disabled > .stylesheet-enabled { opacity: 0.3; } /* Invert the toggle icon in the active row for light theme */ .theme-light .splitview-nav > li.splitview-active .stylesheet-enabled {
--- a/devtools/client/themes/toolbars.css +++ b/devtools/client/themes/toolbars.css @@ -9,44 +9,35 @@ --searchbox-border-color: #ffbf00; --searcbox-no-match-background-color: #ffe5e5; --searcbox-no-match-border-color: #e52e2e; --magnifying-glass-image: url(chrome://devtools/skin/images/search.svg); --filter-image: url(chrome://devtools/skin/images/filter.svg); --tool-options-image: url(chrome://devtools/skin/images/tool-options.svg); - --icon-filter: none; - --checked-icon-filter: url(chrome://devtools/skin/images/filters.svg#checked-icon-state); - --separator-border-image: linear-gradient(transparent 4px, rgba(0,0,0,.1) 4px, rgba(0,0,0,.1) calc(100% - 4px), transparent calc(100% - 4px)); } .theme-dark { --searchbox-background-color: #4d4222; --searchbox-border-color: #d99f2b; --searcbox-no-match-background-color: #402325; --searcbox-no-match-border-color: #cc3d3d; --magnifying-glass-image: url(chrome://devtools/skin/images/search.svg); --filter-image: url(chrome://devtools/skin/images/filter.svg); --tool-options-image: url(chrome://devtools/skin/images/tool-options.svg); - --icon-filter: invert(1); - --checked-icon-filter: url(chrome://devtools/skin/images/filters.svg#dark-theme-checked-icon-state); - - --separator-border-image: linear-gradient(transparent 4px, rgba(100%,100%,100%,.2) 4px, rgba(100%,100%,100%,.2) calc(100% - 4px), transparent calc(100% - 4px)) + --separator-border-image: linear-gradient(transparent 4px, rgba(100%,100%,100%,.2) 4px, rgba(100%,100%,100%,.2) calc(100% - 4px), transparent calc(100% - 4px)); } .theme-firebug { --magnifying-glass-image: url(chrome://devtools/skin/images/search.svg); --tool-options-image: url(chrome://devtools/skin/images/firebug/tool-options.svg); - - --icon-filter: none; - --checked-icon-filter: none; } /* Toolbars */ .devtools-toolbar, .devtools-sidebar-tabs tabs { -moz-appearance: none; padding: 0; @@ -196,17 +187,17 @@ .devtools-toolbarbutton > image, .devtools-button::before, .scrollbutton-up > .toolbarbutton-icon, .scrollbutton-down > .toolbarbutton-icon, #black-boxed-message-button .button-icon, #canvas-debugging-empty-notice-button .button-icon, #toggle-breakpoints[checked] > image, .event-tooltip-debugger-icon { - filter: var(--icon-filter); + filter: var(--theme-icon-filter); } .hidden-labels-box:not(.visible) > label, .hidden-labels-box.visible ~ .hidden-labels-box > label:last-child { display: none; } .devtools-invisible-splitter {
--- a/devtools/client/themes/toolbox.css +++ b/devtools/client/themes/toolbox.css @@ -139,52 +139,47 @@ .theme-firebug .devtools-tab { -moz-box-flex: initial; } .devtools-tab { color: var(--theme-toolbar-color); } -.theme-dark .devtools-tab:hover { - color: #ced3d9; -} - .devtools-tab:hover { background-color: var(--theme-toolbar-hover); } -.theme-dark .devtools-tab:hover:active { - color: var(--theme-selection-color); -} - .devtools-tab:hover:active { background-color: var(--theme-toolbar-hover-active); } .devtools-tab:not(.selected).highlighted { background-color: var(--theme-toolbar-background-alt); } +.devtools-tab.selected { + color: var(--theme-toolbar-selected-color); +} + /* Display execution pointer in the Debugger tab to indicate that the debugger is paused. */ .theme-firebug #toolbox-tab-jsdebugger.devtools-tab:not(.selected).highlighted { background-color: rgba(89, 178, 234, .2); background-image: url(chrome://devtools/skin/images/firebug/tool-debugger-paused.svg); background-repeat: no-repeat; padding-left: 13px !important; background-position: 3px 6px; } .devtools-tab > img { border: none; margin: 0; margin-inline-start: 10px; margin-inline-end: 5px; - opacity: 0.8; max-height: 16px; width: 16px; /* Prevents collapse during theme switching */ vertical-align: text-top; flex-shrink: 0; } /* Don't apply any filter to non-invertable command button icons */ .command-button:not(.command-button-invertable), @@ -195,20 +190,19 @@ filter: none; } .devtools-tab > label { white-space: nowrap; margin: 0 4px; } -.devtools-tab:hover > img, -.devtools-tab:active > img, -.devtools-tab.selected > img { - opacity: 1; +/* Apply selected icon filter to `invertable` icons */ +.devtools-tab.selected.icon-invertable > img { + filter: var(--theme-icon-selected-filter) !important; } .devtools-tab:not(.highlighted) > .highlighted-icon, .devtools-tab.selected > .highlighted-icon, .devtools-tab:not(.selected).highlighted > .default-icon { display: none; }
--- a/devtools/client/themes/variables.css +++ b/devtools/client/themes/variables.css @@ -20,20 +20,21 @@ --theme-body-background: white; --theme-sidebar-background: white; --theme-contrast-background: #e6b064; /* Toolbar */ --theme-tab-toolbar-background: var(--grey-10); --theme-toolbar-background: var(--grey-10); --theme-toolbar-color: var(--grey-90); + --theme-toolbar-selected-color: var(--blue-60); --theme-toolbar-background-hover: rgba(221, 225, 228, 0.66); --theme-toolbar-background-alt: #f5f5f5; - --theme-toolbar-hover: rgba(170, 170, 170, .2); - --theme-toolbar-hover-active: rgba(170, 170, 170, .4); + --theme-toolbar-hover: var(--grey-20); + --theme-toolbar-hover-active: var(--grey-20); /* Selection */ --theme-selection-background: var(--blue-55); --theme-selection-background-hover: #F0F9FE; --theme-selection-color: #f5f7fa; /* Border color that splits the toolbars/panels/headers. * This needs to be sync with commandline.css and commandline-browser.css. */ @@ -75,16 +76,21 @@ --theme-graphs-grey: #cccccc; --theme-graphs-full-red: #f00; --theme-graphs-full-blue: #00f; /* Images */ --theme-pane-collapse-image: url(chrome://devtools/skin/images/pane-collapse.svg); --theme-pane-expand-image: url(chrome://devtools/skin/images/pane-expand.svg); + /* Icon filters */ + --theme-icon-filter: url(chrome://devtools/skin/images/filters.svg#icon-normal-light); + --theme-icon-selected-filter: url(chrome://devtools/skin/images/filters.svg#icon-selected-light); + --theme-icon-checked-filter: url(chrome://devtools/skin/images/filters.svg#icon-checked-light); + /* Tooltips */ --theme-tooltip-border: #d9e1e8; --theme-tooltip-background: rgba(255, 255, 255, .9); --theme-tooltip-shadow: rgba(155, 155, 155, 0.26); /* Command line */ --theme-command-line-image: url(chrome://devtools/skin/images/commandline-icon.svg#light-theme); --theme-command-line-image-focus: url(chrome://devtools/skin/images/commandline-icon.svg#light-theme-focus); @@ -96,20 +102,21 @@ --theme-body-background: var(--grey-80); --theme-sidebar-background: var(--grey-90); --theme-contrast-background: #ffb35b; /* Toolbar */ --theme-tab-toolbar-background: var(--grey-90); --theme-toolbar-background: var(--grey-90); --theme-toolbar-color: var(--grey-40); + --theme-toolbar-selected-color: white; --theme-toolbar-background-hover: #20232B; --theme-toolbar-background-alt: #2F343E; - --theme-toolbar-hover: rgba(110, 120, 130, 0.1); - --theme-toolbar-hover-active: rgba(110, 120, 130, 0.2); + --theme-toolbar-hover: #252526; + --theme-toolbar-hover-active: #252526; /* Selection */ --theme-selection-background: #204E8A; --theme-selection-background-hover: #353B48; --theme-selection-color: #f5f7fa; /* Border color that splits the toolbars/panels/headers. * This needs to be sync with commandline.css and commandline-browser.css. */ @@ -151,16 +158,21 @@ --theme-graphs-grey: #757873; --theme-graphs-full-red: #f00; --theme-graphs-full-blue: #00f; /* Images */ --theme-pane-collapse-image: url(chrome://devtools/skin/images/pane-collapse.svg); --theme-pane-expand-image: url(chrome://devtools/skin/images/pane-expand.svg); + /* Icon filters */ + --theme-icon-filter: url(chrome://devtools/skin/images/filters.svg#icon-normal-dark); + --theme-icon-selected-filter: url(chrome://devtools/skin/images/filters.svg#icon-selected-dark); + --theme-icon-checked-filter: url(chrome://devtools/skin/images/filters.svg#icon-checked-dark); + /* Tooltips */ --theme-tooltip-border: #434850; --theme-tooltip-background: rgba(19, 28, 38, .9); --theme-tooltip-shadow: rgba(25, 25, 25, 0.76); /* Command line */ --theme-command-line-image: url(chrome://devtools/skin/images/commandline-icon.svg#dark-theme); --theme-command-line-image-focus: url(chrome://devtools/skin/images/commandline-icon.svg#dark-theme-focus); @@ -209,16 +221,21 @@ --theme-graphs-grey: #cccccc; --theme-graphs-full-red: #f00; --theme-graphs-full-blue: #00f; /* Images */ --theme-pane-collapse-image: url(chrome://devtools/skin/images/firebug/pane-collapse.svg); --theme-pane-expand-image: url(chrome://devtools/skin/images/firebug/pane-expand.svg); + /* Icon filters */ + --theme-icon-filter: none; + --theme-icon-selected-filter: none; + --theme-icon-checked-filter: none; + /* Font size */ --theme-toolbar-font-size: 12px; /* Header */ --theme-header-background: #F0F0F0 linear-gradient(to top, rgba(0, 0, 0, 0.1), transparent) repeat-x; @@ -248,17 +265,17 @@ --theme-focus-border-color-textbox: #0675d3; --theme-textbox-box-shadow: rgba(97,181,255,.75); /* For accessibility purposes we want to enhance the focus styling. This * should improve keyboard navigation usability. */ --theme-focus-outline: 1px dotted var(--theme-focus-outline-color); --theme-focus-box-shadow-textbox: 0 0 0 1px var(--theme-textbox-box-shadow); - --toolbarbutton-background: rgba(110,120,130,0.1); + --toolbarbutton-background: var(--theme-toolbar-hover); --toolbarbutton-border-color: transparent; --toolbarbutton-hover-background: rgba(110,120,130,0.2); --toolbarbutton-hover-border-color: var(--toolbarbutton-border-color); --toolbarbutton-checked-background: var(--theme-selection-background); --toolbarbutton-checked-color: var(--theme-selection-color); --toolbarbutton-checked-border-color: var(--toolbarbutton-border-color); /* The photon animation curve */
--- a/dom/base/PostMessageEvent.cpp +++ b/dom/base/PostMessageEvent.cpp @@ -138,60 +138,86 @@ PostMessageEvent::Run() nsContentUtils::eDOM_PROPERTIES, "TargetPrincipalDoesNotMatch", params, ArrayLength(params)); return NS_OK; } } - ErrorResult rv; + IgnoredErrorResult rv; JS::Rooted<JS::Value> messageData(cx); - nsCOMPtr<nsPIDOMWindowInner> window = targetWindow->AsInner(); + nsCOMPtr<mozilla::dom::EventTarget> eventTarget = do_QueryObject(targetWindow); - Read(window, cx, &messageData, rv); + Read(targetWindow->AsInner(), cx, &messageData, rv); if (NS_WARN_IF(rv.Failed())) { - return rv.StealNSResult(); + DispatchError(cx, targetWindow, eventTarget); + return NS_OK; } // Create the event - nsCOMPtr<mozilla::dom::EventTarget> eventTarget = do_QueryObject(targetWindow); - RefPtr<MessageEvent> event = - new MessageEvent(eventTarget, nullptr, nullptr); + RefPtr<MessageEvent> event = new MessageEvent(eventTarget, nullptr, nullptr); Nullable<WindowProxyOrMessagePortOrServiceWorker> source; source.SetValue().SetAsWindowProxy() = mSource ? mSource->AsOuter() : nullptr; Sequence<OwningNonNull<MessagePort>> ports; if (!TakeTransferredPortsAsSequence(ports)) { - return NS_ERROR_OUT_OF_MEMORY; + DispatchError(cx, targetWindow, eventTarget); + return NS_OK; } event->InitMessageEvent(nullptr, NS_LITERAL_STRING("message"), false /*non-bubbling */, false /*cancelable */, messageData, mCallerOrigin, EmptyString(), source, ports); + Dispatch(targetWindow, event); + return NS_OK; +} + +void +PostMessageEvent::DispatchError(JSContext* aCx, nsGlobalWindow* aTargetWindow, + mozilla::dom::EventTarget* aEventTarget) +{ + RootedDictionary<MessageEventInit> init(aCx); + init.mBubbles = false; + init.mCancelable = false; + init.mOrigin = mCallerOrigin; + + if (mSource) { + init.mSource.SetValue().SetAsWindowProxy() = mSource->AsOuter(); + } + + RefPtr<Event> event = + MessageEvent::Constructor(aEventTarget, NS_LITERAL_STRING("messageerror"), + init); + Dispatch(aTargetWindow, event); +} + +void +PostMessageEvent::Dispatch(nsGlobalWindow* aTargetWindow, Event* aEvent) +{ // We can't simply call dispatchEvent on the window because doing so ends // up flipping the trusted bit on the event, and we don't want that to // happen because then untrusted content can call postMessage on a chrome // window if it can get a reference to it. - nsIPresShell *shell = targetWindow->GetExtantDoc()->GetShell(); + nsIPresShell *shell = aTargetWindow->GetExtantDoc()->GetShell(); RefPtr<nsPresContext> presContext; - if (shell) + if (shell) { presContext = shell->GetPresContext(); + } - event->SetTrusted(mTrustedCaller); - WidgetEvent* internalEvent = event->WidgetEventPtr(); + aEvent->SetTrusted(mTrustedCaller); + WidgetEvent* internalEvent = aEvent->WidgetEventPtr(); nsEventStatus status = nsEventStatus_eIgnore; - EventDispatcher::Dispatch(window, + EventDispatcher::Dispatch(aTargetWindow->AsInner(), presContext, internalEvent, - static_cast<dom::Event*>(event.get()), + aEvent, &status); - return NS_OK; } } // namespace dom } // namespace mozilla
--- a/dom/base/PostMessageEvent.h +++ b/dom/base/PostMessageEvent.h @@ -35,16 +35,23 @@ public: nsGlobalWindow* aTargetWindow, nsIPrincipal* aProvidedPrincipal, nsIDocument* aSourceDocument, bool aTrustedCaller); private: ~PostMessageEvent(); + void + Dispatch(nsGlobalWindow* aTargetWindow, Event* aEvent); + + void + DispatchError(JSContext* aCx, nsGlobalWindow* aTargetWindow, + mozilla::dom::EventTarget* aEventTarget); + RefPtr<nsGlobalWindow> mSource; nsString mCallerOrigin; RefPtr<nsGlobalWindow> mTargetWindow; nsCOMPtr<nsIPrincipal> mProvidedPrincipal; nsCOMPtr<nsIDocument> mSourceDocument; bool mTrustedCaller; };
--- a/dom/base/nsCopySupport.cpp +++ b/dom/base/nsCopySupport.cpp @@ -840,18 +840,26 @@ nsCopySupport::FireClipboardEvent(EventM doDefault = (status != nsEventStatus_eConsumeNoDefault); } // When this function exits, the event dispatch is over. We want to disconnect // our DataTransfer, which means setting its mode to `Protected` and clearing // all stored data, before we return. auto clearAfter = MakeScopeExit([&] { if (clipboardData) { - clipboardData->SetMode(DataTransfer::Mode::Protected); - clipboardData->ClearAll(); + clipboardData->Disconnect(); + + // NOTE: Disconnect may not actually clear the DataTransfer if the + // dom.events.dataTransfer.protected.enabled pref is not on, so we make + // sure we clear here, as not clearing could provide the DataTransfer + // access to information from the system clipboard at an arbitrary point + // in the future. + if (originalEventMessage == ePaste) { + clipboardData->ClearAll(); + } } }); // No need to do anything special during a paste. Either an event listener // took care of it and cancelled the event, or the caller will handle it. // Return true to indicate that the event wasn't cancelled. if (originalEventMessage == ePaste) { if (aActionTaken) {
--- a/dom/base/nsGkAtomList.h +++ b/dom/base/nsGkAtomList.h @@ -915,16 +915,17 @@ GK_ATOM(onlevelchange, "onlevelchange") GK_ATOM(onLoad, "onLoad") GK_ATOM(onload, "onload") GK_ATOM(onloading, "onloading") GK_ATOM(onloadingdone, "onloadingdone") GK_ATOM(onloadingerror, "onloadingerror") GK_ATOM(onpopstate, "onpopstate") GK_ATOM(only, "only") // this one is not an event GK_ATOM(onmessage, "onmessage") +GK_ATOM(onmessageerror, "onmessageerror") GK_ATOM(onmousedown, "onmousedown") GK_ATOM(onmouseenter, "onmouseenter") GK_ATOM(onmouseleave, "onmouseleave") GK_ATOM(onmouselongtap, "onmouselongtap") GK_ATOM(onmousemove, "onmousemove") GK_ATOM(onmouseout, "onmouseout") GK_ATOM(onmouseover, "onmouseover") GK_ATOM(onMozMouseHittest, "onMozMouseHittest")
--- a/dom/bindings/BindingUtils.h +++ b/dom/bindings/BindingUtils.h @@ -2820,17 +2820,17 @@ ToSupportsIsOnPrimaryInheritanceChain(T* } // Get the size of allocated memory to associate with a binding JSObject for a // native object. This is supplied to the JS engine to allow it to schedule GC // when necessary. // // This function supplies a default value and is overloaded for specific native // object types. -inline uint64_t +inline size_t BindingJSObjectMallocBytes(void *aNativePtr) { return 0; } // The BindingJSObjectCreator class is supposed to be used by a caller that // wants to create and initialise a binding JSObject. After initialisation has // been successfully completed it should call ForgetObject(). @@ -2869,34 +2869,34 @@ public: aReflector.set(js::NewProxyObject(aCx, aHandler, aExpandoValue, aProto, options)); if (aReflector) { js::SetProxyReservedSlot(aReflector, DOM_OBJECT_SLOT, JS::PrivateValue(aNative)); mNative = aNative; mReflector = aReflector; } - if (uint64_t mallocBytes = BindingJSObjectMallocBytes(aNative)) { + if (size_t mallocBytes = BindingJSObjectMallocBytes(aNative)) { JS_updateMallocCounter(aCx, mallocBytes); } } void CreateObject(JSContext* aCx, const JSClass* aClass, JS::Handle<JSObject*> aProto, T* aNative, JS::MutableHandle<JSObject*> aReflector) { aReflector.set(JS_NewObjectWithGivenProto(aCx, aClass, aProto)); if (aReflector) { js::SetReservedSlot(aReflector, DOM_OBJECT_SLOT, JS::PrivateValue(aNative)); mNative = aNative; mReflector = aReflector; } - if (uint64_t mallocBytes = BindingJSObjectMallocBytes(aNative)) { + if (size_t mallocBytes = BindingJSObjectMallocBytes(aNative)) { JS_updateMallocCounter(aCx, mallocBytes); } } void InitializationSucceeded() { void* dummy;
--- a/dom/broadcastchannel/BroadcastChannel.h +++ b/dom/broadcastchannel/BroadcastChannel.h @@ -63,16 +63,17 @@ public: } void PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage, ErrorResult& aRv); void Close(); IMPL_EVENT_HANDLER(message) + IMPL_EVENT_HANDLER(messageerror) void Shutdown(); private: BroadcastChannel(nsPIDOMWindowInner* aWindow, const PrincipalInfo& aPrincipalInfo, const nsACString& aOrigin, const nsAString& aChannel);
--- a/dom/broadcastchannel/BroadcastChannelChild.cpp +++ b/dom/broadcastchannel/BroadcastChannelChild.cpp @@ -75,20 +75,20 @@ BroadcastChannelChild::RecvNotify(const if (!globalObject || !jsapi.Init(globalObject)) { NS_WARNING("Failed to initialize AutoJSAPI object."); return IPC_OK(); } JSContext* cx = jsapi.cx(); JS::Rooted<JS::Value> value(cx, JS::NullValue()); if (cloneData.DataLength()) { - ErrorResult rv; + IgnoredErrorResult rv; cloneData.Read(cx, &value, rv); if (NS_WARN_IF(rv.Failed())) { - rv.SuppressException(); + DispatchError(cx); return IPC_OK(); } } RootedDictionary<MessageEventInit> init(cx); init.mBubbles = false; init.mCancelable = false; init.mOrigin = mOrigin; @@ -106,10 +106,26 @@ BroadcastChannelChild::RecvNotify(const } void BroadcastChannelChild::ActorDestroy(ActorDestroyReason aWhy) { mActorDestroyed = true; } +void +BroadcastChannelChild::DispatchError(JSContext* aCx) +{ + RootedDictionary<MessageEventInit> init(aCx); + init.mBubbles = false; + init.mCancelable = false; + init.mOrigin = mOrigin; + + RefPtr<Event> event = + MessageEvent::Constructor(mBC, NS_LITERAL_STRING("messageerror"), init); + event->SetTrusted(true); + + bool dummy; + mBC->DispatchEvent(event, &dummy); +} + } // namespace dom } // namespace mozilla
--- a/dom/broadcastchannel/BroadcastChannelChild.h +++ b/dom/broadcastchannel/BroadcastChannelChild.h @@ -39,16 +39,18 @@ public: } private: explicit BroadcastChannelChild(const nsACString& aOrigin); ~BroadcastChannelChild(); virtual void ActorDestroy(ActorDestroyReason aWhy) override; + void DispatchError(JSContext* aCx); + // This raw pointer is actually the parent object. // It's set to null when the parent object is deleted. BroadcastChannel* mBC; nsString mOrigin; bool mActorDestroyed; };
--- a/dom/browser-element/mochitest/browserElement_Iconchange.js +++ b/dom/browser-element/mochitest/browserElement_Iconchange.js @@ -2,16 +2,17 @@ http://creativecommons.org/publicdomain/zero/1.0/ */ // Test that the onmozbrowsericonchange event works. "use strict"; SimpleTest.waitForExplicitFinish(); browserElementTestHelpers.setEnabledPref(true); browserElementTestHelpers.addPermission(); +browserElementTestHelpers.allowTopLevelDataURINavigation(); function createHtml(link) { return 'data:text/html,<html><head>' + link + '<body></body></html>'; } function createLink(name, sizes, rel) { var s = sizes ? 'sizes="' + sizes + '"' : ''; if (!rel) {
--- a/dom/browser-element/mochitest/browserElement_Manifestchange.js +++ b/dom/browser-element/mochitest/browserElement_Manifestchange.js @@ -2,16 +2,17 @@ http://creativecommons.org/publicdomain/zero/1.0/ */ // Test that the onmozbrowsermanifestchange event works. "use strict"; SimpleTest.waitForExplicitFinish(); browserElementTestHelpers.setEnabledPref(true); browserElementTestHelpers.addPermission(); +browserElementTestHelpers.allowTopLevelDataURINavigation(); function createHtml(manifest) { return 'data:text/html,<html xmlns:xml="http://www.w3.org/XML/1998/namespace"><head>' + manifest + '<body></body></html>'; } function createManifest(href) { return '<link rel="manifest" href="' + href + '">'; }
--- a/dom/browser-element/mochitest/browserElement_Metachange.js +++ b/dom/browser-element/mochitest/browserElement_Metachange.js @@ -2,16 +2,17 @@ http://creativecommons.org/publicdomain/zero/1.0/ */ // Test that the onmozbrowsermetachange event works. "use strict"; SimpleTest.waitForExplicitFinish(); browserElementTestHelpers.setEnabledPref(true); browserElementTestHelpers.addPermission(); +browserElementTestHelpers.allowTopLevelDataURINavigation(); function createHtml(meta) { return 'data:text/html,<html xmlns:xml="http://www.w3.org/XML/1998/namespace"><head>' + meta + '<body></body></html>'; } function createHtmlWithLang(meta, lang) { return 'data:text/html,<html xmlns:xml="http://www.w3.org/XML/1998/namespace" lang="' + lang + '"><head>' + meta + '<body></body></html>'; }
--- a/dom/browser-element/mochitest/browserElement_Opensearch.js +++ b/dom/browser-element/mochitest/browserElement_Opensearch.js @@ -2,16 +2,17 @@ http://creativecommons.org/publicdomain/zero/1.0/ */ // Test that the onmozbrowseropensearch event works. "use strict"; SimpleTest.waitForExplicitFinish(); browserElementTestHelpers.setEnabledPref(true); browserElementTestHelpers.addPermission(); +browserElementTestHelpers.allowTopLevelDataURINavigation(); function createHtml(link) { return 'data:text/html,<html><head>' + link + '<body></body></html>'; } function createLink(name) { return '<link rel="search" title="Test OpenSearch" type="application/opensearchdescription+xml" href="http://example.com/' + name + '.xml">'; }
--- a/dom/canvas/CanvasRenderingContext2D.cpp +++ b/dom/canvas/CanvasRenderingContext2D.cpp @@ -1784,22 +1784,16 @@ CanvasRenderingContext2D::RegisterAlloca // PeristentBufferProvider, rather than here. static bool registered = false; // FIXME: Disable the reporter for now, see bug 1241865 if (!registered && false) { registered = true; RegisterStrongMemoryReporter(new Canvas2dPixelsReporter()); } - gCanvasAzureMemoryUsed += mWidth * mHeight * 4; - JSContext* context = nsContentUtils::GetCurrentJSContext(); - if (context) { - JS_updateMallocCounter(context, mWidth * mHeight * 4); - } - JSObject* wrapper = GetWrapperPreserveColor(); if (wrapper) { CycleCollectedJSRuntime::Get()-> AddZoneWaitingForGC(JS::GetObjectZone(wrapper)); } } static already_AddRefed<LayerManager> @@ -6549,10 +6543,16 @@ CanvasPath::EnsurePathBuilder() const } // if there is not pathbuilder, there must be a path MOZ_ASSERT(mPath); mPathBuilder = mPath->CopyToBuilder(); mPath = nullptr; } +size_t +BindingJSObjectMallocBytes(CanvasRenderingContext2D* aContext) +{ + return aContext->GetWidth() * aContext->GetHeight() * 4; +} + } // namespace dom } // namespace mozilla
--- a/dom/canvas/CanvasRenderingContext2D.h +++ b/dom/canvas/CanvasRenderingContext2D.h @@ -1164,12 +1164,14 @@ protected: if (aPerCSSPixel) *aPerCSSPixel = cssPixel; } friend struct CanvasBidiProcessor; friend class CanvasDrawObserver; }; +size_t BindingJSObjectMallocBytes(CanvasRenderingContext2D* aContext); + } // namespace dom } // namespace mozilla #endif /* CanvasRenderingContext2D_h */
--- a/dom/canvas/ImageBitmap.cpp +++ b/dom/canvas/ImageBitmap.cpp @@ -30,55 +30,16 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Im NS_IMPL_CYCLE_COLLECTING_ADDREF(ImageBitmap) NS_IMPL_CYCLE_COLLECTING_RELEASE(ImageBitmap) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ImageBitmap) NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_END /* - * This helper function is used to notify DOM that aBytes memory is allocated - * here so that we could trigger GC appropriately. - */ -static void -RegisterAllocation(nsIGlobalObject* aGlobal, size_t aBytes) -{ - AutoJSAPI jsapi; - if (jsapi.Init(aGlobal)) { - JS_updateMallocCounter(jsapi.cx(), aBytes); - } -} - -static void -RegisterAllocation(nsIGlobalObject* aGlobal, SourceSurface* aSurface) -{ - // Calculate how many bytes are used. - const int bytesPerPixel = BytesPerPixel(aSurface->GetFormat()); - const size_t bytes = - aSurface->GetSize().height * aSurface->GetSize().width * bytesPerPixel; - - // Register. - RegisterAllocation(aGlobal, bytes); -} - -static void -RegisterAllocation(nsIGlobalObject* aGlobal, layers::Image* aImage) -{ - // Calculate how many bytes are used. - if (aImage->GetFormat() == mozilla::ImageFormat::PLANAR_YCBCR) { - RegisterAllocation(aGlobal, aImage->AsPlanarYCbCrImage()->GetDataSize()); - } else if (aImage->GetFormat() == mozilla::ImageFormat::NV_IMAGE) { - RegisterAllocation(aGlobal, aImage->AsNVImage()->GetBufferSize()); - } else { - RefPtr<SourceSurface> surface = aImage->GetAsSourceSurface(); - RegisterAllocation(aGlobal, surface); - } -} - -/* * If either aRect.width or aRect.height are negative, then return a new IntRect * which represents the same rectangle as the aRect does but with positive width * and height. */ static IntRect FixUpNegativeDimension(const IntRect& aRect, ErrorResult& aRv) { gfx::IntRect rect = aRect; @@ -439,16 +400,17 @@ ImageBitmap::ImageBitmap(nsIGlobalObject gfxAlphaType aAlphaType) : mParent(aGlobal) , mData(aData) , mSurface(nullptr) , mDataWrapper(new ImageUtils(mData)) , mPictureRect(0, 0, aData->GetSize().width, aData->GetSize().height) , mAlphaType(aAlphaType) , mIsCroppingAreaOutSideOfSourceImage(false) + , mAllocatedImageData(false) { MOZ_ASSERT(aData, "aData is null in ImageBitmap constructor."); } ImageBitmap::~ImageBitmap() { } @@ -706,18 +668,17 @@ ImageBitmap::ToCloneData() const /* static */ already_AddRefed<ImageBitmap> ImageBitmap::CreateFromCloneData(nsIGlobalObject* aGlobal, ImageBitmapCloneData* aData) { RefPtr<layers::Image> data = CreateImageFromSurface(aData->mSurface); RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, aData->mAlphaType); - // Report memory allocation. - RegisterAllocation(aGlobal, aData->mSurface); + ret->mAllocatedImageData = true; ret->mIsCroppingAreaOutSideOfSourceImage = aData->mIsCroppingAreaOutSideOfSourceImage; ErrorResult rv; ret->SetPictureRect(aData->mPictureRect, rv); return ret.forget(); } @@ -744,18 +705,17 @@ ImageBitmap::CreateFromOffscreenCanvas(n return nullptr; } RefPtr<layers::Image> data = CreateImageFromSurface(surface); RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data); - // Report memory allocation. - RegisterAllocation(aGlobal, surface); + ret->mAllocatedImageData = true; return ret.forget(); } /* static */ already_AddRefed<ImageBitmap> ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, HTMLImageElement& aImageEl, const Maybe<IntRect>& aCropRect, ErrorResult& aRv) { @@ -891,19 +851,18 @@ ImageBitmap::CreateInternal(nsIGlobalObj if (NS_WARN_IF(!data)) { aRv.Throw(NS_ERROR_NOT_AVAILABLE); return nullptr; } RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data); - // Report memory allocation if needed. if (needToReportMemoryAllocation) { - RegisterAllocation(aGlobal, croppedSurface); + ret->mAllocatedImageData = true; } // Set the picture rectangle. if (ret && aCropRect.isSome()) { ret->SetPictureRect(cropRect, aRv); } // Set mIsCroppingAreaOutSideOfSourceImage. @@ -960,18 +919,17 @@ ImageBitmap::CreateInternal(nsIGlobalObj if (NS_WARN_IF(!data)) { aRv.Throw(NS_ERROR_NOT_AVAILABLE); return nullptr; } // Create an ImageBimtap. RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, alphaType); - // Report memory allocation. - RegisterAllocation(aGlobal, data); + ret->mAllocatedImageData = true; // The cropping information has been handled in the CreateImageFromRawData() // function. // Set mIsCroppingAreaOutSideOfSourceImage. ret->SetIsCroppingAreaOutSideOfSourceImage(imageSize, aCropRect); return ret.forget(); @@ -1004,18 +962,17 @@ ImageBitmap::CreateInternal(nsIGlobalObj if (NS_WARN_IF(!data)) { aRv.Throw(NS_ERROR_NOT_AVAILABLE); return nullptr; } RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data); - // Report memory allocation. - RegisterAllocation(aGlobal, surface); + ret->mAllocatedImageData = true; // Set the picture rectangle. if (ret && aCropRect.isSome()) { ret->SetPictureRect(aCropRect.ref(), aRv); } // Set mIsCroppingAreaOutSideOfSourceImage. ret->SetIsCroppingAreaOutSideOfSourceImage(surface->GetSize(), aCropRect); @@ -1249,18 +1206,17 @@ protected: imageBitmap->SetPictureRect(mCropRect.ref(), rv); if (rv.Failed()) { mPromise->MaybeReject(rv); return false; } } - // Report memory allocation. - RegisterAllocation(mGlobalObject, imageBitmap->mData); + imageBitmap->mAllocatedImageData = true; mPromise->MaybeResolve(imageBitmap); return true; } // Will return null on failure. In that case, mPromise will already // be rejected with the right thing. virtual already_AddRefed<ImageBitmap> CreateImageBitmap() = 0; @@ -1539,18 +1495,17 @@ ImageBitmap::ReadStructuredClone(JSConte error.SuppressException(); return nullptr; } if (!GetOrCreateDOMReflector(aCx, imageBitmap, &value)) { return nullptr; } - // Report memory allocation. - RegisterAllocation(aParent, aClonedSurfaces[aIndex]); + imageBitmap->mAllocatedImageData = true; } return &(value.toObject()); } /*static*/ bool ImageBitmap::WriteStructuredClone(JSStructuredCloneWriter* aWriter, nsTArray<RefPtr<DataSourceSurface>>& aClonedSurfaces, @@ -2139,26 +2094,52 @@ ImageBitmap::Create(nsIGlobalObject* aGl return promise.forget(); } // Create an ImageBimtap. // Assume the data from an external buffer is not alpha-premultiplied. RefPtr<ImageBitmap> imageBitmap = new ImageBitmap(aGlobal, data, gfxAlphaType::NonPremult); - // Report memory allocation. - RegisterAllocation(aGlobal, data); + imageBitmap->mAllocatedImageData = true; // We don't need to call SetPictureRect() here because there is no cropping // supported and the ImageBitmap's mPictureRect is the size of the source // image in default // We don't need to set mIsCroppingAreaOutSideOfSourceImage here because there // is no cropping supported and the mIsCroppingAreaOutSideOfSourceImage is // false in default. AsyncFulfillImageBitmapPromise(promise, imageBitmap); return promise.forget(); } +size_t +ImageBitmap::GetAllocatedSize() const +{ + if (!mAllocatedImageData) { + return 0; + } + + // Calculate how many bytes are used. + if (mData->GetFormat() == mozilla::ImageFormat::PLANAR_YCBCR) { + return mData->AsPlanarYCbCrImage()->GetDataSize(); + } + + if (mData->GetFormat() == mozilla::ImageFormat::NV_IMAGE) { + return mData->AsNVImage()->GetBufferSize(); + } + + RefPtr<SourceSurface> surface = mData->GetAsSourceSurface(); + const int bytesPerPixel = BytesPerPixel(surface->GetFormat()); + return surface->GetSize().height * surface->GetSize().width * bytesPerPixel; +} + +size_t +BindingJSObjectMallocBytes(ImageBitmap* aBitmap) +{ + return aBitmap->GetAllocatedSize(); +} + } // namespace dom } // namespace mozilla
--- a/dom/canvas/ImageBitmap.h +++ b/dom/canvas/ImageBitmap.h @@ -174,16 +174,18 @@ public: MappedDataLength(ImageBitmapFormat aFormat, ErrorResult& aRv); already_AddRefed<Promise> MapDataInto(JSContext* aCx, ImageBitmapFormat aFormat, const ArrayBufferViewOrArrayBuffer& aBuffer, int32_t aOffset, ErrorResult& aRv); + size_t GetAllocatedSize() const; + protected: /* * The default value of aIsPremultipliedAlpha is TRUE because that the * data stored in HTMLImageElement, HTMLVideoElement, HTMLCanvasElement, * CanvasRenderingContext2D are alpha-premultiplied in default. * * Actually, if one HTMLCanvasElement's rendering context is WebGLContext, it @@ -279,16 +281,20 @@ protected: * Set mIsCroppingAreaOutSideOfSourceImage if image bitmap was cropped to the * source rectangle so that it contains any transparent black pixels (cropping * area is outside of the source image). * This is used in mapDataInto() to check if we should reject promise with * IndexSizeError. */ bool mIsCroppingAreaOutSideOfSourceImage; + /* + * Whether this object allocated allocated and owns the image data. + */ + bool mAllocatedImageData; }; } // namespace dom } // namespace mozilla #endif // mozilla_dom_ImageBitmap_h
--- a/dom/events/DataTransfer.cpp +++ b/dom/events/DataTransfer.cpp @@ -76,16 +76,33 @@ const char DataTransfer::sEffects[8][9] }; // Used for custom clipboard types. enum CustomClipboardTypeId { eCustomClipboardTypeId_None, eCustomClipboardTypeId_String }; +// The dom.events.dataTransfer.protected.enabled preference controls whether or +// not the `protected` dataTransfer state is enabled. If the `protected` +// dataTransfer stae is disabled, then the DataTransfer will be read-only +// whenever it should be protected, and will not be disconnected after a drag +// event is completed. +static bool +PrefProtected() +{ + static bool sInitialized = false; + static bool sValue = false; + if (!sInitialized) { + sInitialized = true; + Preferences::AddBoolVarCache(&sValue, "dom.events.dataTransfer.protected.enabled"); + } + return sValue; +} + static DataTransfer::Mode ModeForEvent(EventMessage aEventMessage) { switch (aEventMessage) { case eCut: case eCopy: case eDragStart: // For these events, we want to be able to add data to the data transfer, @@ -93,17 +110,19 @@ ModeForEvent(EventMessage aEventMessage) return DataTransfer::Mode::ReadWrite; case eDrop: case ePaste: case ePasteNoFormatting: // For these events we want to be able to read the data which is stored in // the DataTransfer, rather than just the type information. return DataTransfer::Mode::ReadOnly; default: - return DataTransfer::Mode::Protected; + return PrefProtected() + ? DataTransfer::Mode::Protected + : DataTransfer::Mode::ReadOnly; } } DataTransfer::DataTransfer(nsISupports* aParent, EventMessage aEventMessage, bool aIsExternal, int32_t aClipboardType) : mParent(aParent) , mDropEffect(nsIDragService::DRAGDROP_ACTION_NONE) , mEffectAllowed(nsIDragService::DRAGDROP_ACTION_UNINITIALIZED) @@ -1272,16 +1291,25 @@ DataTransfer::ConvertFromVariant(nsIVari // each character is two bytes *aLength = str.Length() << 1; return true; } void +DataTransfer::Disconnect() +{ + SetMode(Mode::Protected); + if (PrefProtected()) { + ClearAll(); + } +} + +void DataTransfer::ClearAll() { mItems->ClearAllItems(); } uint32_t DataTransfer::MozItemCount() const { @@ -1603,10 +1631,20 @@ DataTransfer::FillInExternalCustomTypes( rv = variant->SetAsAString(data); NS_ENSURE_SUCCESS_VOID(rv); SetDataWithPrincipal(format, variant, aIndex, aPrincipal); } } while (type != eCustomClipboardTypeId_None); } +void +DataTransfer::SetMode(DataTransfer::Mode aMode) +{ + if (!PrefProtected() && aMode == Mode::Protected) { + mMode = Mode::ReadOnly; + } else { + mMode = aMode; + } +} + } // namespace dom } // namespace mozilla
--- a/dom/events/DataTransfer.h +++ b/dom/events/DataTransfer.h @@ -224,19 +224,17 @@ public: } // Returns the current "Drag Data Store Mode" of the DataTransfer. This // determines what modifications may be performed on the DataTransfer, and // what data may be read from it. Mode GetMode() const { return mMode; } - void SetMode(Mode aMode) { - mMode = aMode; - } + void SetMode(Mode aMode); // Helper method. Is true if the DataTransfer's mode is ReadOnly or Protected, // which means that the DataTransfer cannot be modified. bool IsReadOnly() const { return mMode != Mode::ReadWrite; } // Helper method. Is true if the DataTransfer's mode is Protected, which means // that DataTransfer type information may be read, but data may not be. @@ -267,16 +265,22 @@ public: GetTransferable(uint32_t aIndex, nsILoadContext* aLoadContext); // converts the data in the variant to an nsISupportString if possible or // an nsISupports or null otherwise. bool ConvertFromVariant(nsIVariant* aVariant, nsISupports** aSupports, uint32_t* aLength) const; + // Disconnects the DataTransfer from the Drag Data Store. If the + // dom.dataTransfer.disconnect pref is enabled, this will clear the + // DataTransfer and set it to the `Protected` state, otherwise this method is + // a no-op. + void Disconnect(); + // clears all of the data void ClearAll(); // Similar to SetData except also specifies the principal to store. // aData may be null when called from CacheExternalDragFormats or // CacheExternalClipboardFormats. nsresult SetDataWithPrincipal(const nsAString& aFormat, nsIVariant* aData,
--- a/dom/events/EventNameList.h +++ b/dom/events/EventNameList.h @@ -546,16 +546,20 @@ WINDOW_EVENT(languagechange, eBasicEventClass) // XXXbz Should the onmessage attribute on <body> really not work? If so, do we // need a different macro to flag things like that (IDL, but not content // attributes on body/frameset), or is just using EventNameType_None enough? WINDOW_EVENT(message, eMessage, EventNameType_None, eBasicEventClass) +WINDOW_EVENT(messageerror, + eMessageError, + EventNameType_HTMLBodyOrFramesetOnly, + eBasicEventClass) WINDOW_EVENT(offline, eOffline, EventNameType_XUL | EventNameType_HTMLBodyOrFramesetOnly, eBasicEventClass) WINDOW_EVENT(online, eOnline, EventNameType_XUL | EventNameType_HTMLBodyOrFramesetOnly, eBasicEventClass)
--- a/dom/events/EventStateManager.cpp +++ b/dom/events/EventStateManager.cpp @@ -1769,18 +1769,17 @@ EventStateManager::GenerateDragGesture(n nsCOMPtr<nsPIDOMWindowOuter> window = docshell->GetWindow(); if (!window) return; RefPtr<DataTransfer> dataTransfer = new DataTransfer(window, eDragStart, false, -1); auto protectDataTransfer = MakeScopeExit([&] { if (dataTransfer) { - dataTransfer->SetMode(DataTransfer::Mode::Protected); - dataTransfer->ClearAll(); + dataTransfer->Disconnect(); } }); nsCOMPtr<nsISelection> selection; nsCOMPtr<nsIContent> eventContent, targetContent; mCurrentTarget->GetContentForEvent(aEvent, getter_AddRefs(eventContent)); if (eventContent) DetermineDragTargetAndDefaultData(window, eventContent, dataTransfer,
--- a/dom/events/IMEContentObserver.cpp +++ b/dom/events/IMEContentObserver.cpp @@ -1371,17 +1371,20 @@ IMEContentObserver::MaybeNotifyIMEOfAdde void IMEContentObserver::BeginDocumentUpdate() { MOZ_LOG(sIMECOLog, LogLevel::Debug, ("0x%p IMEContentObserver::BeginDocumentUpdate(), " "HasAddedNodesDuringDocumentChange()=%s", this, ToChar(HasAddedNodesDuringDocumentChange()))); - MOZ_ASSERT(!HasAddedNodesDuringDocumentChange()); + // If we're not in a nested document update, this will return early, + // otherwise, it will handle flusing any changes currently pending before + // entering a nested document update. + MaybeNotifyIMEOfAddedTextDuringDocumentChange(); } void IMEContentObserver::EndDocumentUpdate() { MOZ_LOG(sIMECOLog, LogLevel::Debug, ("0x%p IMEContentObserver::EndDocumentUpdate(), " "HasAddedNodesDuringDocumentChange()=%s",
--- a/dom/events/test/test_bug508479.html +++ b/dom/events/test/test_bug508479.html @@ -69,17 +69,17 @@ function runTests() is(gGotNotHandlingDrop, false, "Didn't get drop on unaccepting element (1)"); // reset gGotHandlingDrop = false; gGotNotHandlingDrop = false; SpecialPowers.addChromeEventListener("drop", chromeListener, true, false); var targetNotHandling = document.getElementById("nothandling_target"); - fireDrop(targetNotHandling, false, true); + fireDrop(targetNotHandling, true, true); SpecialPowers.removeChromeEventListener("drop", chromeListener, true); ok(chromeGotEvent, "Chrome should have got drop event!"); is(gGotHandlingDrop, false, "Didn't get drop on accepting element (2)"); is(gGotNotHandlingDrop, false, "Didn't get drop on unaccepting element (2)"); SimpleTest.finish(); }
--- a/dom/file/Blob.cpp +++ b/dom/file/Blob.cpp @@ -287,17 +287,17 @@ Blob::IsMemoryFile() const } void Blob::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv) { mImpl->GetInternalStream(aStream, aRv); } -uint64_t +size_t BindingJSObjectMallocBytes(Blob* aBlob) { MOZ_ASSERT(aBlob); return aBlob->GetAllocationSize(); } } // namespace dom } // namespace mozilla
--- a/dom/file/Blob.h +++ b/dom/file/Blob.h @@ -146,14 +146,14 @@ protected: RefPtr<BlobImpl> mImpl; private: nsCOMPtr<nsISupports> mParent; }; // Override BindingJSObjectMallocBytes for blobs to tell the JS GC how much // memory is held live by the binding object. -uint64_t BindingJSObjectMallocBytes(Blob* aBlob); +size_t BindingJSObjectMallocBytes(Blob* aBlob); } // namespace dom } // namespace mozilla #endif // mozilla_dom_Blob_h
--- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -2305,18 +2305,16 @@ ContentChild::ActorDestroy(ActorDestroyR } if (AbnormalShutdown == why) { NS_WARNING("shutting down early because of crash!"); ProcessChild::QuickExit(); } #ifndef NS_FREE_PERMANENT_DATA - CompositorManagerChild::Shutdown(); - // In release builds, there's no point in the content process // going through the full XPCOM shutdown path, because it doesn't // keep persistent state. ProcessChild::QuickExit(); #else if (gFirstIdleTask) { gFirstIdleTask->Cancel(); }
--- a/dom/media/mediasource/test/mochitest.ini +++ b/dom/media/mediasource/test/mochitest.ini @@ -154,10 +154,10 @@ skip-if = android_version == '22' # bug skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 [test_WaitingOnMissingData.html] skip-if = (toolkit == 'android') #timeout android only bug 1101187 [test_WaitingOnMissingData_mp4.html] skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 [test_WaitingOnMissingDataEnded_mp4.html] skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 [test_WaitingToEndedTransition_mp4.html] -skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +skip-if = ((os == "win" && os_version >= "10.0") || (toolkit == 'android')) # Not supported on android 2.3, failing on windows 10
--- a/dom/messagechannel/MessagePort.cpp +++ b/dom/messagechannel/MessagePort.cpp @@ -132,27 +132,29 @@ private: end = MakeUnique<MessagePortTimelineMarker>( ProfileTimelineMessagePortOperationType::DeserializeData, MarkerTracingType::END); timelines->AddMarkerForAllObservedDocShells(start); timelines->AddMarkerForAllObservedDocShells(end); } if (NS_WARN_IF(rv.Failed())) { + mPort->DispatchError(); return rv.StealNSResult(); } // Create the event nsCOMPtr<mozilla::dom::EventTarget> eventTarget = do_QueryInterface(mPort->GetOwner()); RefPtr<MessageEvent> event = new MessageEvent(eventTarget, nullptr, nullptr); Sequence<OwningNonNull<MessagePort>> ports; if (!mData->TakeTransferredPortsAsSequence(ports)) { + mPort->DispatchError(); return NS_ERROR_OUT_OF_MEMORY; } event->InitMessageEvent(nullptr, NS_LITERAL_STRING("message"), false /* non-bubbling */, false /* cancelable */, value, EmptyString(), EmptyString(), nullptr, ports); event->SetTrusted(true); @@ -689,17 +691,17 @@ MessagePort::Entangled(nsTArray<ClonedMe // only clear after `messages` have gone out of scope. mMessagesForTheOtherPort.Clear(); } // We must convert the messages into SharedMessagePortMessages to avoid leaks. FallibleTArray<RefPtr<SharedMessagePortMessage>> data; if (NS_WARN_IF(!SharedMessagePortMessage::FromMessagesToSharedChild(aMessages, data))) { - // OOM, we cannot continue. + DispatchError(); return; } // If the next step is to close the port, we do it ignoring the received // messages. if (oldState == eStateEntanglingForClose) { CloseForced(); return; @@ -743,17 +745,17 @@ MessagePort::MessagesReceived(nsTArray<C mState == eStateDisentangledForClose); MOZ_ASSERT(mMessagesForTheOtherPort.IsEmpty()); RemoveDocFromBFCache(); FallibleTArray<RefPtr<SharedMessagePortMessage>> data; if (NS_WARN_IF(!SharedMessagePortMessage::FromMessagesToSharedChild(aMessages, data))) { - // OOM, We cannot continue. + DispatchError(); return; } mMessages.AppendElements(data); if (mState == eStateEntangled) { Dispatch(); } @@ -999,10 +1001,33 @@ MessagePort::RemoveDocFromBFCache() } /* static */ void MessagePort::ForceClose(const MessagePortIdentifier& aIdentifier) { ForceCloseHelper::ForceClose(aIdentifier); } +void +MessagePort::DispatchError() +{ + nsCOMPtr<nsIGlobalObject> globalObject = GetParentObject(); + + AutoJSAPI jsapi; + if (!globalObject || !jsapi.Init(globalObject)) { + NS_WARNING("Failed to initialize AutoJSAPI object."); + return; + } + + RootedDictionary<MessageEventInit> init(jsapi.cx()); + init.mBubbles = false; + init.mCancelable = false; + + RefPtr<Event> event = + MessageEvent::Constructor(this, NS_LITERAL_STRING("messageerror"), init); + event->SetTrusted(true); + + bool dummy; + DispatchEvent(event, &dummy); +} + } // namespace dom } // namespace mozilla
--- a/dom/messagechannel/MessagePort.h +++ b/dom/messagechannel/MessagePort.h @@ -69,16 +69,18 @@ public: void Start(); void Close(); EventHandlerNonNull* GetOnmessage(); void SetOnmessage(EventHandlerNonNull* aCallback); + IMPL_EVENT_HANDLER(messageerror) + // Non WebIDL methods void UnshippedEntangle(MessagePort* aEntangledPort); void CloneAndDisentangle(MessagePortIdentifier& aIdentifier); void CloseForced(); @@ -142,16 +144,18 @@ private: uint32_t aSequenceID, bool mNeutered, State aState, ErrorResult& aRv); void ConnectToPBackground(); // Dispatch events from the Message Queue using a nsRunnable. void Dispatch(); + void DispatchError(); + void StartDisentangling(); void Disentangle(); void RemoveDocFromBFCache(); void CloseInternal(bool aSoftly); // This method is meant to keep alive the MessagePort when this object is
--- a/dom/tests/mochitest/general/test_clipboard_events.html +++ b/dom/tests/mochitest/general/test_clipboard_events.html @@ -741,14 +741,20 @@ function test_image_dataTransfer() { try { synthesizeKey("v", {accelKey: 1}); ok(onpasteCalled, "The paste event listener must have been called"); } finally { document.onpaste = null; } } -SimpleTest.waitForFocus(doTests); +SimpleTest.waitForFocus(() => { + SpecialPowers.pushPrefEnv({ + // NOTE: These tests operate under the assumption that the protected mode of + // DataTransfer is enabled. + "set": [["dom.events.dataTransfer.protected.enabled", true]] + }, doTests); +}); </script> </pre> </body> </html>
--- a/dom/tests/mochitest/general/test_interfaces.js +++ b/dom/tests/mochitest/general/test_interfaces.js @@ -869,17 +869,17 @@ var interfaceNamesInGlobalScope = {name: "SpecialPowers", xbl: false}, // IMPORTANT: Do not change this list without review from a DOM peer! "StereoPannerNode", // IMPORTANT: Do not change this list without review from a DOM peer! "Storage", // IMPORTANT: Do not change this list without review from a DOM peer! "StorageEvent", // IMPORTANT: Do not change this list without review from a DOM peer! - {name: "StorageManager", nightly: true, isSecureContext: true, android: false}, + {name: "StorageManager", isSecureContext: true, android: false}, // IMPORTANT: Do not change this list without review from a DOM peer! "StyleSheet", // IMPORTANT: Do not change this list without review from a DOM peer! "StyleSheetList", // IMPORTANT: Do not change this list without review from a DOM peer! "SubtleCrypto", // IMPORTANT: Do not change this list without review from a DOM peer! "SVGAElement",
--- a/dom/webidl/BroadcastChannel.webidl +++ b/dom/webidl/BroadcastChannel.webidl @@ -1,21 +1,22 @@ /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * For more information on this interface, please see - * http://www.whatwg.org/specs/web-apps/current-work/multipage/web-messaging.html#broadcasting-to-other-browsing-contexts + * https://html.spec.whatwg.org/#broadcastchannel */ [Constructor(DOMString channel), Exposed=(Window,Worker)] interface BroadcastChannel : EventTarget { readonly attribute DOMString name; [Throws] void postMessage(any message); void close(); - attribute EventHandler onmessage; + attribute EventHandler onmessage; + attribute EventHandler onmessageerror; };
--- a/dom/webidl/DedicatedWorkerGlobalScope.webidl +++ b/dom/webidl/DedicatedWorkerGlobalScope.webidl @@ -19,9 +19,10 @@ interface DedicatedWorkerGlobalScope : W readonly attribute DOMString name; [Throws] void postMessage(any message, optional sequence<object> transfer = []); void close(); attribute EventHandler onmessage; + attribute EventHandler onmessageerror; };
--- a/dom/webidl/EventHandler.webidl +++ b/dom/webidl/EventHandler.webidl @@ -142,16 +142,17 @@ interface GlobalEventHandlers { [NoInterfaceObject] interface WindowEventHandlers { attribute EventHandler onafterprint; attribute EventHandler onbeforeprint; attribute OnBeforeUnloadEventHandler onbeforeunload; attribute EventHandler onhashchange; attribute EventHandler onlanguagechange; attribute EventHandler onmessage; + attribute EventHandler onmessageerror; attribute EventHandler onoffline; attribute EventHandler ononline; attribute EventHandler onpagehide; attribute EventHandler onpageshow; attribute EventHandler onpopstate; attribute EventHandler onstorage; attribute EventHandler onunload; };
--- a/dom/webidl/MessagePort.webidl +++ b/dom/webidl/MessagePort.webidl @@ -12,10 +12,11 @@ interface MessagePort : EventTarget { [Throws] void postMessage(any message, optional sequence<object> transferable = []); void start(); void close(); // event handlers attribute EventHandler onmessage; + attribute EventHandler onmessageerror; }; // MessagePort implements Transferable;
--- a/dom/webidl/Worker.webidl +++ b/dom/webidl/Worker.webidl @@ -17,16 +17,17 @@ Exposed=(Window,DedicatedWorker,SharedWorker,System)] interface Worker : EventTarget { void terminate(); [Throws] void postMessage(any message, optional sequence<object> transfer = []); attribute EventHandler onmessage; + attribute EventHandler onmessageerror; }; Worker implements AbstractWorker; dictionary WorkerOptions { // WorkerType type = "classic"; TODO: Bug 1247687 // RequestCredentials credentials = "omit"; // credentials is only used if type is "module" TODO: Bug 1247687 DOMString name = "";
--- a/dom/workers/ScriptLoader.cpp +++ b/dom/workers/ScriptLoader.cpp @@ -675,17 +675,22 @@ private: if (mCanceledMainThread || !mCacheCreator) { aRequest->Cancel(NS_ERROR_FAILURE); return NS_ERROR_FAILURE; } ScriptLoadInfo& loadInfo = mLoadInfos[aIndex]; nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest); - MOZ_ASSERT(channel == loadInfo.mChannel); + + // Note that importScripts() can redirect. In theory the main + // script could also encounter an internal redirect, but currently + // the assert does not allow that. + MOZ_ASSERT_IF(mIsMainScript, channel == loadInfo.mChannel); + loadInfo.mChannel = channel; // We synthesize the result code, but its never exposed to content. RefPtr<mozilla::dom::InternalResponse> ir = new mozilla::dom::InternalResponse(200, NS_LITERAL_CSTRING("OK")); ir->SetBody(loadInfo.mCacheReadStream, InternalResponse::UNKNOWN_BODY_SIZE); // Drop our reference to the stream now that we've passed it along, so it // doesn't hang around once the cache is done with it and keep data alive.
--- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -724,17 +724,17 @@ public: if (NS_WARN_IF(!parent)) { return false; } } MOZ_ASSERT(parent); JS::Rooted<JS::Value> messageData(aCx); - ErrorResult rv; + IgnoredErrorResult rv; UniquePtr<AbstractTimelineMarker> start; UniquePtr<AbstractTimelineMarker> end; RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get(); bool isTimelineRecording = timelines && !timelines->IsEmpty(); if (isTimelineRecording) { start = MakeUnique<WorkerTimelineMarker>(aIsMainThread @@ -750,22 +750,23 @@ public: ? ProfileTimelineWorkerOperationType::DeserializeDataOnMainThread : ProfileTimelineWorkerOperationType::DeserializeDataOffMainThread, MarkerTracingType::END); timelines->AddMarkerForAllObservedDocShells(start); timelines->AddMarkerForAllObservedDocShells(end); } if (NS_WARN_IF(rv.Failed())) { - xpc::Throw(aCx, rv.StealNSResult()); + DispatchError(aCx, aTarget); return false; } Sequence<OwningNonNull<MessagePort>> ports; if (!TakeTransferredPortsAsSequence(ports)) { + DispatchError(aCx, aTarget); return false; } nsCOMPtr<nsIDOMEvent> domEvent; RefPtr<MessageEvent> event = new MessageEvent(aTarget, nullptr, nullptr); event->InitMessageEvent(nullptr, NS_LITERAL_STRING("message"), false /* non-bubbling */, @@ -809,16 +810,31 @@ private: !aWorkerPrivate->GetParent()); } MOZ_ASSERT(aWorkerPrivate == GetWorkerPrivateFromContext(aCx)); return DispatchDOMEvent(aCx, aWorkerPrivate, aWorkerPrivate->GlobalScope(), false); } + + void + DispatchError(JSContext* aCx, DOMEventTargetHelper* aTarget) + { + RootedDictionary<MessageEventInit> init(aCx); + init.mBubbles = false; + init.mCancelable = false; + + RefPtr<Event> event = + MessageEvent::Constructor(aTarget, NS_LITERAL_STRING("messageerror"), init); + event->SetTrusted(true); + + bool dummy; + aTarget->DispatchEvent(event, &dummy); + } }; class DebuggerMessageEventRunnable : public WorkerDebuggerRunnable { nsString mMessage; public: DebuggerMessageEventRunnable(WorkerPrivate* aWorkerPrivate, const nsAString& aMessage)
--- a/dom/workers/WorkerPrivate.h +++ b/dom/workers/WorkerPrivate.h @@ -877,16 +877,17 @@ public: { return mLoadInfo.mLoadFailedAsyncRunnable.forget(); } void FlushReportsToSharedWorkers(nsIConsoleReportCollector* aReporter); IMPL_EVENT_HANDLER(message) + IMPL_EVENT_HANDLER(messageerror) IMPL_EVENT_HANDLER(error) // Check whether this worker is a secure context. For use from the parent // thread only; the canonical "is secure context" boolean is stored on the // compartment of the worker global. The only reason we don't // AssertIsOnParentThread() here is so we can assert that this value matches // the one on the compartment, which has to be done from the worker thread. bool IsSecureContext() const
--- a/dom/workers/WorkerScope.h +++ b/dom/workers/WorkerScope.h @@ -246,16 +246,17 @@ public: PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage, const Sequence<JSObject*>& aTransferable, ErrorResult& aRv); void Close(JSContext* aCx); IMPL_EVENT_HANDLER(message) + IMPL_EVENT_HANDLER(messageerror) }; class SharedWorkerGlobalScope final : public WorkerGlobalScope { const nsString mName; ~SharedWorkerGlobalScope() { } @@ -391,16 +392,17 @@ public: void LeaveEventLoop(); void PostMessage(const nsAString& aMessage); IMPL_EVENT_HANDLER(message) + IMPL_EVENT_HANDLER(messageerror) void SetImmediate(Function& aHandler, ErrorResult& aRv); void ReportError(JSContext* aCx, const nsAString& aMessage); void
--- a/dom/workers/test/navigator_worker.js +++ b/dom/workers/test/navigator_worker.js @@ -10,17 +10,17 @@ var supportedProps = [ "appVersion", "platform", "product", "userAgent", "onLine", "language", "languages", "hardwareConcurrency", - { name: "storage", nightly: true, isSecureContext: true }, + { name: "storage", isSecureContext: true }, "connection", ]; self.onmessage = function(event) { if (!event || !event.data) { return; }
--- a/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js +++ b/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js @@ -207,17 +207,17 @@ var interfaceNamesInGlobalScope = "Response", // IMPORTANT: Do not change this list without review from a DOM peer! "ServiceWorker", // IMPORTANT: Do not change this list without review from a DOM peer! "ServiceWorkerGlobalScope", // IMPORTANT: Do not change this list without review from a DOM peer! "ServiceWorkerRegistration", // IMPORTANT: Do not change this list without review from a DOM peer! - {name: "StorageManager", nightly: true, android: false}, + {name: "StorageManager", android: false}, // IMPORTANT: Do not change this list without review from a DOM peer! "SubtleCrypto", // IMPORTANT: Do not change this list without review from a DOM peer! "TextDecoder", // IMPORTANT: Do not change this list without review from a DOM peer! "TextEncoder", // IMPORTANT: Do not change this list without review from a DOM peer! "URL",
--- a/dom/workers/test/test_worker_interfaces.js +++ b/dom/workers/test/test_worker_interfaces.js @@ -193,17 +193,17 @@ var interfaceNamesInGlobalScope = "PushSubscriptionOptions", // IMPORTANT: Do not change this list without review from a DOM peer! "Request", // IMPORTANT: Do not change this list without review from a DOM peer! "Response", // IMPORTANT: Do not change this list without review from a DOM peer! "ServiceWorkerRegistration", // IMPORTANT: Do not change this list without review from a DOM peer! - {name: "StorageManager", nightly: true, isSecureContext: true, android: false}, + {name: "StorageManager", isSecureContext: true, android: false}, // IMPORTANT: Do not change this list without review from a DOM peer! "SubtleCrypto", // IMPORTANT: Do not change this list without review from a DOM peer! "TextDecoder", // IMPORTANT: Do not change this list without review from a DOM peer! "TextEncoder", // IMPORTANT: Do not change this list without review from a DOM peer! "XMLHttpRequest",
--- a/gfx/ipc/VsyncBridgeParent.cpp +++ b/gfx/ipc/VsyncBridgeParent.cpp @@ -23,17 +23,17 @@ VsyncBridgeParent::Start(Endpoint<PVsync return parent; } VsyncBridgeParent::VsyncBridgeParent() : mOpen(false) { MOZ_COUNT_CTOR(VsyncBridgeParent); - mCompositorThreadRef = CompositorThreadHolder::GetSingleton(); + mCompositorThreadRef = new CompositorThreadHolderDebug("VsyncBridge"); } VsyncBridgeParent::~VsyncBridgeParent() { MOZ_COUNT_DTOR(VsyncBridgeParent); } void
--- a/gfx/ipc/VsyncBridgeParent.h +++ b/gfx/ipc/VsyncBridgeParent.h @@ -33,15 +33,15 @@ private: VsyncBridgeParent(); ~VsyncBridgeParent(); void Open(Endpoint<PVsyncBridgeParent>&& aEndpoint); void ShutdownImpl(); private: bool mOpen; - RefPtr<layers::CompositorThreadHolder> mCompositorThreadRef; + RefPtr<layers::CompositorThreadHolderDebug> mCompositorThreadRef; }; } // namespace gfx } // namespace mozilla #endif // include_gfx_ipc_VsyncBridgeParent_h
--- a/gfx/layers/d3d11/MLGDeviceD3D11.cpp +++ b/gfx/layers/d3d11/MLGDeviceD3D11.cpp @@ -1088,16 +1088,27 @@ MLGDeviceD3D11::InitSamplerStates() desc.AddressW = D3D11_TEXTURE_ADDRESS_BORDER; memset(desc.BorderColor, 0, sizeof(desc.BorderColor)); HRESULT hr = mDevice->CreateSamplerState(&desc, getter_AddRefs(mSamplerStates[SamplerMode::LinearClampToZero])); if (FAILED(hr)) { return Fail("FEATURE_FAILURE_LINEAR_CLAMP_ZERO_SAMPLER", "Could not create linear clamp to zero sampler (%x)", hr); } } + { + CD3D11_SAMPLER_DESC desc = CD3D11_SAMPLER_DESC(CD3D11_DEFAULT()); + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + HRESULT hr = mDevice->CreateSamplerState(&desc, getter_AddRefs(mSamplerStates[SamplerMode::LinearRepeat])); + if (FAILED(hr)) { + return Fail("FEATURE_FAILURE_LINEAR_CLAMP_ZERO_SAMPLER", + "Could not create linear clamp to zero sampler (%x)", hr); + } + } { CD3D11_SAMPLER_DESC desc = CD3D11_SAMPLER_DESC(CD3D11_DEFAULT()); desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; HRESULT hr = mDevice->CreateSamplerState(&desc, getter_AddRefs(mSamplerStates[SamplerMode::Point])); if (FAILED(hr)) { return Fail("FEATURE_FAILURE_POINT_SAMPLER", "Could not create point sampler (%x)", hr);
--- a/gfx/layers/ipc/CompositorManagerParent.cpp +++ b/gfx/layers/ipc/CompositorManagerParent.cpp @@ -31,16 +31,18 @@ CompositorManagerParent::CreateSameProce MOZ_ASSERT_UNREACHABLE("Already initialized"); return nullptr; } // The child is responsible for setting up the IPC channel in the same // process case because if we open from the child perspective, we can do it // on the main thread and complete before we return the manager handles. RefPtr<CompositorManagerParent> parent = new CompositorManagerParent(); + parent->mCompositorThreadHolder = + new CompositorThreadHolderDebug("CompositorManagerSame"); parent->SetOtherProcessId(base::GetCurrentProcId()); // CompositorManagerParent::Bind would normally add a reference for IPDL but // we don't use that in the same process case. parent.get()->AddRef(); sInstance = parent; return parent.forget(); } @@ -50,16 +52,18 @@ CompositorManagerParent::Create(Endpoint { MOZ_ASSERT(NS_IsMainThread()); // We are creating a manager for the another process, inside the GPU process // (or UI process if it subsumbed the GPU process). MOZ_ASSERT(aEndpoint.OtherPid() != base::GetCurrentProcId()); RefPtr<CompositorManagerParent> bridge = new CompositorManagerParent(); + bridge->mCompositorThreadHolder = + new CompositorThreadHolderDebug("CompositorManagerContent"); RefPtr<Runnable> runnable = NewRunnableMethod<Endpoint<PCompositorManagerParent>&&>( "CompositorManagerParent::Bind", bridge, &CompositorManagerParent::Bind, Move(aEndpoint)); CompositorThreadHolder::Loop()->PostTask(runnable.forget()); } @@ -100,17 +104,16 @@ CompositorManagerParent::CreateSameProce new CompositorBridgeParent(sInstance, aScale, vsyncRate, aOptions, aUseExternalSurfaceSize, aSurfaceSize); sInstance->mPendingCompositorBridges.AppendElement(bridge); return bridge.forget(); } CompositorManagerParent::CompositorManagerParent() - : mCompositorThreadHolder(CompositorThreadHolder::GetSingleton()) { } CompositorManagerParent::~CompositorManagerParent() { } void
--- a/gfx/layers/ipc/CompositorManagerParent.h +++ b/gfx/layers/ipc/CompositorManagerParent.h @@ -13,17 +13,17 @@ #include "mozilla/RefPtr.h" // for already_AddRefed #include "mozilla/layers/PCompositorManagerParent.h" #include "nsTArray.h" // for AutoTArray namespace mozilla { namespace layers { class CompositorBridgeParent; -class CompositorThreadHolder; +class CompositorThreadHolderDebug; class CompositorManagerParent final : public PCompositorManagerParent { NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorManagerParent) public: static already_AddRefed<CompositorManagerParent> CreateSameProcess(); static void Create(Endpoint<PCompositorManagerParent>&& aEndpoint); @@ -47,17 +47,17 @@ private: ~CompositorManagerParent() override; void Bind(Endpoint<PCompositorManagerParent>&& aEndpoint); void DeallocPCompositorManagerParent() override; void DeferredDestroy(); - RefPtr<CompositorThreadHolder> mCompositorThreadHolder; + RefPtr<CompositorThreadHolderDebug> mCompositorThreadHolder; AutoTArray<RefPtr<CompositorBridgeParent>, 1> mPendingCompositorBridges; }; } // namespace layers } // namespace mozilla #endif
--- a/gfx/layers/ipc/CompositorThread.cpp +++ b/gfx/layers/ipc/CompositorThread.cpp @@ -4,26 +4,56 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "CompositorThread.h" #include "MainThreadUtils.h" #include "nsThreadUtils.h" #include "CompositorBridgeParent.h" #include "mozilla/layers/ImageBridgeParent.h" #include "mozilla/media/MediaSystemResourceService.h" +#ifdef MOZ_CRASHREPORTER +#include "nsExceptionHandler.h" // for CrashReporter +#endif namespace mozilla { namespace gfx { // See VRManagerChild.cpp void ReleaseVRManagerParentSingleton(); } // namespace gfx namespace layers { +#ifdef MOZ_CRASHREPORTER +static Atomic<int32_t> sHoldersNextId(0); +#endif + +CompositorThreadHolderDebug::CompositorThreadHolderDebug(const char* aName) + : mHolder(CompositorThreadHolder::GetSingleton()) +{ +#ifdef MOZ_CRASHREPORTER + if (XRE_IsParentProcess()) { + mId.AppendLiteral("gfxCompositorThread:"); + mId.Append(aName); + mId.AppendLiteral(":"); + mId.AppendInt(++sHoldersNextId); + CrashReporter::AnnotateCrashReport(mId, NS_LITERAL_CSTRING("1")); + } +#endif +} + +CompositorThreadHolderDebug::~CompositorThreadHolderDebug() +{ +#ifdef MOZ_CRASHREPORTER + if (XRE_IsParentProcess()) { + CrashReporter::AnnotateCrashReport(mId, NS_LITERAL_CSTRING("0")); + } +#endif +} + static StaticRefPtr<CompositorThreadHolder> sCompositorThreadHolder; static bool sFinishedCompositorShutDown = false; // See ImageBridgeChild.cpp void ReleaseImageBridgeParentSingleton(); CompositorThreadHolder* GetCompositorThreadHolder() {
--- a/gfx/layers/ipc/CompositorThread.h +++ b/gfx/layers/ipc/CompositorThread.h @@ -55,14 +55,30 @@ private: base::Thread* const mCompositorThread; static base::Thread* CreateCompositorThread(); static void DestroyCompositorThread(base::Thread* aCompositorThread); friend class CompositorBridgeParent; }; +class CompositorThreadHolderDebug final +{ + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorThreadHolderDebug) + +public: + explicit CompositorThreadHolderDebug(const char* aName); + +private: + ~CompositorThreadHolderDebug(); + + RefPtr<CompositorThreadHolder> mHolder; +#ifdef MOZ_CRASHREPORTER + nsAutoCString mId; +#endif +}; + base::Thread* CompositorThread(); } // namespace layers } // namespace mozilla #endif // mozilla_layers_CompositorThread_h
--- a/gfx/layers/ipc/ImageBridgeParent.cpp +++ b/gfx/layers/ipc/ImageBridgeParent.cpp @@ -362,17 +362,19 @@ ImageBridgeParent::GetInstance(ProcessId MonitorAutoLock lock(*sImageBridgesLock); NS_ASSERTION(sImageBridges.count(aId) == 1, "ImageBridgeParent for the process"); return sImageBridges[aId]; } void ImageBridgeParent::OnChannelConnected(int32_t aPid) { - mCompositorThreadHolder = GetCompositorThreadHolder(); + mCompositorThreadHolder = + new CompositorThreadHolderDebug(IsSameProcess() ? "ImageBridgeSame" + : "ImageBridge"); } bool ImageBridgeParent::AllocShmem(size_t aSize, ipc::SharedMemory::SharedMemoryType aType, ipc::Shmem* aShmem) {
--- a/gfx/layers/ipc/ImageBridgeParent.h +++ b/gfx/layers/ipc/ImageBridgeParent.h @@ -136,15 +136,15 @@ private: bool mSetChildThreadPriority; bool mClosed; /** * Map of all living ImageBridgeParent instances */ static std::map<base::ProcessId, ImageBridgeParent*> sImageBridges; - RefPtr<CompositorThreadHolder> mCompositorThreadHolder; + RefPtr<CompositorThreadHolderDebug> mCompositorThreadHolder; }; } // namespace layers } // namespace mozilla #endif // gfx_layers_ipc_ImageBridgeParent_h_
--- a/gfx/layers/ipc/VideoBridgeParent.cpp +++ b/gfx/layers/ipc/VideoBridgeParent.cpp @@ -16,17 +16,17 @@ using namespace mozilla::gfx; static VideoBridgeParent* sVideoBridgeSingleton; VideoBridgeParent::VideoBridgeParent() : mClosed(false) { mSelfRef = this; sVideoBridgeSingleton = this; - mCompositorThreadRef = CompositorThreadHolder::GetSingleton(); + mCompositorThreadRef = new CompositorThreadHolderDebug("VideoBridge"); } VideoBridgeParent::~VideoBridgeParent() { sVideoBridgeSingleton = nullptr; } /* static */ VideoBridgeParent*
--- a/gfx/layers/ipc/VideoBridgeParent.h +++ b/gfx/layers/ipc/VideoBridgeParent.h @@ -7,17 +7,17 @@ #define gfx_layers_ipc_VideoBridgeParent_h_ #include "mozilla/layers/PVideoBridgeParent.h" #include "mozilla/layers/ISurfaceAllocator.h" namespace mozilla { namespace layers { -class CompositorThreadHolder; +class CompositorThreadHolderDebug; class VideoBridgeParent final : public PVideoBridgeParent, public HostIPCAllocator, public ShmemAllocator { public: VideoBridgeParent(); ~VideoBridgeParent(); @@ -58,17 +58,17 @@ public: void DeallocShmem(ipc::Shmem& aShmem) override; private: void DeallocPVideoBridgeParent() override; // This keeps us alive until ActorDestroy(), at which point we do a // deferred destruction of ourselves. RefPtr<VideoBridgeParent> mSelfRef; - RefPtr<CompositorThreadHolder> mCompositorThreadRef; + RefPtr<CompositorThreadHolderDebug> mCompositorThreadRef; std::map<uint64_t, PTextureParent*> mTextureMap; bool mClosed; }; } // namespace layers } // namespace mozilla
--- a/gfx/layers/mlgpu/ImageLayerMLGPU.cpp +++ b/gfx/layers/mlgpu/ImageLayerMLGPU.cpp @@ -72,19 +72,26 @@ ImageLayerMLGPU::IsContentOpaque() return gfx::IsOpaque(mHost->CurrentTextureHost()->GetFormat()); } return false; } void ImageLayerMLGPU::SetRegionToRender(LayerIntRegion&& aRegion) { - // See bug 1264142. - if (mScaleMode == ScaleMode::STRETCH) { + switch (mScaleMode) { + case ScaleMode::STRETCH: + // See bug 1264142. aRegion.AndWith(LayerIntRect(0, 0, mScaleToSize.width, mScaleToSize.height)); + break; + default: + // Clamp the visible region to the texture size. (see bug 1396507) + MOZ_ASSERT(mScaleMode == ScaleMode::SCALE_NONE); + aRegion.AndWith(LayerIntRect(0, 0, mPictureRect.width, mPictureRect.height)); + break; } LayerMLGPU::SetRegionToRender(Move(aRegion)); } void ImageLayerMLGPU::CleanupResources() { if (mHost) {
--- a/gfx/layers/mlgpu/MLGDevice.cpp +++ b/gfx/layers/mlgpu/MLGDevice.cpp @@ -233,31 +233,16 @@ MLGDevice::SetPSTexturesYUV(uint32_t aSl } void MLGDevice::SetPSTexture(uint32_t aSlot, TextureSource* aSource) { SetPSTextures(aSlot, 1, &aSource); } -static inline SamplerMode -FilterToSamplerMode(gfx::SamplingFilter aFilter) -{ - switch (aFilter) { - case gfx::SamplingFilter::POINT: - return SamplerMode::Point; - case gfx::SamplingFilter::LINEAR: - case gfx::SamplingFilter::GOOD: - return SamplerMode::LinearClamp; - default: - MOZ_ASSERT_UNREACHABLE("Unknown sampler mode"); - return SamplerMode::LinearClamp; - } -} - void MLGDevice::SetSamplerMode(uint32_t aIndex, gfx::SamplingFilter aFilter) { SetSamplerMode(aIndex, FilterToSamplerMode(aFilter)); } bool MLGDevice::Fail(const nsCString& aFailureId, const nsCString* aMessage)
--- a/gfx/layers/mlgpu/MLGDeviceTypes.h +++ b/gfx/layers/mlgpu/MLGDeviceTypes.h @@ -2,16 +2,17 @@ * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_gfx_layers_mlgpu_MLGDeviceTypes_h #define mozilla_gfx_layers_mlgpu_MLGDeviceTypes_h #include "mozilla/TypedEnumBits.h" +#include "mozilla/gfx/Types.h" namespace mozilla { namespace layers { enum class MLGUsage { // GPU read-only, CPU write once on creation and read/write never. Immutable, @@ -42,16 +43,18 @@ enum class MLGBufferType : uint32_t }; enum class SamplerMode { // Linear filter, clamped to border. LinearClamp = 0, // Linear filter, clamped to transparent pixels. LinearClampToZero, + // Linear filter, wrap edges. + LinearRepeat, // Point filter, clamped to border. Point, MaxModes }; enum class MLGBlendState { Copy = 0, @@ -99,12 +102,27 @@ enum class MLGRenderTargetFlags : uint32 ZBuffer = (1 << 0) }; MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(MLGRenderTargetFlags); // NVIDIA drivers crash when we supply too many rects to ClearView - it // seems to cause a stack overflow >= 20 rects. We cap to 12 for now. static const size_t kMaxClearViewRects = 12; +static inline SamplerMode +FilterToSamplerMode(gfx::SamplingFilter aFilter) +{ + switch (aFilter) { + case gfx::SamplingFilter::POINT: + return SamplerMode::Point; + case gfx::SamplingFilter::LINEAR: + case gfx::SamplingFilter::GOOD: + return SamplerMode::LinearClamp; + default: + MOZ_ASSERT_UNREACHABLE("Unknown sampler mode"); + return SamplerMode::LinearClamp; + } +} + } // namespace layers } // namespace mozilla #endif // mozilla_gfx_layers_mlgpu_MLGDeviceTypes_h
--- a/gfx/layers/mlgpu/PaintedLayerMLGPU.h +++ b/gfx/layers/mlgpu/PaintedLayerMLGPU.h @@ -3,16 +3,17 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef MOZILLA_GFX_PAINTEDLAYERMLGPU_H #define MOZILLA_GFX_PAINTEDLAYERMLGPU_H #include "LayerManagerMLGPU.h" #include "mozilla/layers/ContentHost.h" +#include "MLGDeviceTypes.h" #include "nsRegionFwd.h" #include <functional> namespace mozilla { namespace layers { class PaintedLayerMLGPU final : public PaintedLayer, @@ -44,16 +45,24 @@ public: } TextureSource* GetTextureOnWhite() const { MOZ_ASSERT(HasComponentAlpha()); return mTextureOnWhite; } ContentHostTexture* GetContentHost() const { return mHost; } + SamplerMode GetSamplerMode() { + // Note that when resamping, we must break the texture coordinates into + // no-repeat rects. When we have simple integer translations we can + // simply wrap around the edge of the buffer texture. + return MayResample() + ? SamplerMode::LinearClamp + : SamplerMode::LinearRepeat; + } // This can return a different region than GetShadowVisibleRegion or // GetLocalVisibleRegion, since we make sure to clamp it to the // texture size and account for resampling. nsIntRegion GetRenderRegion(); MOZ_LAYER_DECL_NAME("PaintedLayerMLGPU", TYPE_PAINTED)
--- a/gfx/layers/mlgpu/RenderPassMLGPU.cpp +++ b/gfx/layers/mlgpu/RenderPassMLGPU.cpp @@ -443,163 +443,191 @@ SolidColorPass::SetupPipeline() } TexturedRenderPass::TexturedRenderPass(FrameBuilder* aBuilder, const ItemInfo& aItem) : BatchRenderPass(aBuilder, aItem), mTextureFlags(TextureFlags::NO_FLAGS) { } +TexturedRenderPass::Info::Info(const ItemInfo& aItem, PaintedLayerMLGPU* aLayer) + : item(aItem), + textureSize(aLayer->GetTexture()->GetSize()), + destOrigin(aLayer->GetContentHost()->GetOriginOffset()), + decomposeIntoNoRepeatRects(aLayer->MayResample()) +{ +} + +TexturedRenderPass::Info::Info(const ItemInfo& aItem, TexturedLayerMLGPU* aLayer) + : item(aItem), + textureSize(aLayer->GetTexture()->GetSize()), + scale(aLayer->GetPictureScale()), + decomposeIntoNoRepeatRects(false) +{ +} + +TexturedRenderPass::Info::Info(const ItemInfo& aItem, ContainerLayerMLGPU* aLayer) + : item(aItem), + textureSize(aLayer->GetTargetSize()), + destOrigin(aLayer->GetTargetOffset()), + decomposeIntoNoRepeatRects(false) +{ +} + bool TexturedRenderPass::AddItem(Txn& aTxn, - const ItemInfo& aInfo, - const Rect& aDrawRect, - const Point& aDestOrigin, - const IntSize& aTextureSize, - const Maybe<Size>& aScale) + const Info& aInfo, + const Rect& aDrawRect) { - if (mGeometry == GeometryMode::Polygon) { // This path will not clamp the draw rect to the layer clip, so we can pass // the draw rect texture rects straight through. - return AddClippedItem(aTxn, aInfo, aDrawRect, aDestOrigin, aTextureSize, aScale); + return AddClippedItem(aTxn, aInfo, aDrawRect); } - MOZ_ASSERT(!aInfo.geometry); - MOZ_ASSERT(aInfo.HasRectTransformAndClip()); + const ItemInfo& item = aInfo.item; + + MOZ_ASSERT(!item.geometry); + MOZ_ASSERT(item.HasRectTransformAndClip()); MOZ_ASSERT(mHasRectTransformAndClip); - const Matrix4x4& fullTransform = aInfo.layer->GetLayer()->GetEffectiveTransformForBuffer(); + const Matrix4x4& fullTransform = item.layer->GetLayer()->GetEffectiveTransformForBuffer(); Matrix transform = fullTransform.As2D(); Matrix inverse = transform; if (!inverse.Invert()) { // Degenerate transforms are not visible, since there is no mapping to // screen space. Just return without adding any draws. return true; } MOZ_ASSERT(inverse.IsRectilinear()); // Transform the clip rect. - IntRect clipRect = aInfo.layer->GetComputedClipRect().ToUnknownRect(); - clipRect += aInfo.view->GetTargetOffset(); + IntRect clipRect = item.layer->GetComputedClipRect().ToUnknownRect(); + clipRect += item.view->GetTargetOffset(); // Clip and adjust the texture rect. Rect localClip = inverse.TransformBounds(Rect(clipRect)); Rect clippedDrawRect = aDrawRect.Intersect(localClip); if (clippedDrawRect.IsEmpty()) { return true; } - return AddClippedItem(aTxn, aInfo, clippedDrawRect, aDestOrigin, aTextureSize, aScale); + return AddClippedItem(aTxn, aInfo, clippedDrawRect); } bool TexturedRenderPass::AddClippedItem(Txn& aTxn, - const ItemInfo& aInfo, - const gfx::Rect& aDrawRect, - const gfx::Point& aDestOrigin, - const gfx::IntSize& aTextureSize, - const Maybe<gfx::Size>& aScale) + const Info& aInfo, + const gfx::Rect& aDrawRect) { - float xScale = aScale ? aScale->width : 1.0f; - float yScale = aScale ? aScale->height : 1.0f; + float xScale = 1.0; + float yScale = 1.0; + if (aInfo.scale) { + xScale = aInfo.scale->width; + yScale = aInfo.scale->height; + } - Point offset = aDrawRect.TopLeft() - aDestOrigin; + Point offset = aDrawRect.TopLeft() - aInfo.destOrigin; Rect textureRect( offset.x * xScale, offset.y * yScale, aDrawRect.Width() * xScale, aDrawRect.Height() * yScale); - Rect textureCoords = TextureRectToCoords(textureRect, aTextureSize); + Rect textureCoords = TextureRectToCoords(textureRect, aInfo.textureSize); if (mTextureFlags & TextureFlags::ORIGIN_BOTTOM_LEFT) { textureCoords.y = 1.0 - textureCoords.y; textureCoords.SetHeight(-textureCoords.Height()); } - Rect layerRects[4]; - Rect textureRects[4]; - size_t numRects = - DecomposeIntoNoRepeatRects(aDrawRect, textureCoords, &layerRects, &textureRects); - - for (size_t i = 0; i < numRects; i++) { - TexturedTraits traits(aInfo, layerRects[i], textureRects[i]); + if (!aInfo.decomposeIntoNoRepeatRects) { + // Fast, normal case, we can use the texture coordinates as-s and the caller + // will use a repeat sampler if needed. + TexturedTraits traits(aInfo.item, aDrawRect, textureCoords); if (!aTxn.Add(traits)) { return false; } + } else { + Rect layerRects[4]; + Rect textureRects[4]; + size_t numRects = + DecomposeIntoNoRepeatRects(aDrawRect, textureCoords, &layerRects, &textureRects); + + for (size_t i = 0; i < numRects; i++) { + TexturedTraits traits(aInfo.item, layerRects[i], textureRects[i]); + if (!aTxn.Add(traits)) { + return false; + } + } } return true; } SingleTexturePass::SingleTexturePass(FrameBuilder* aBuilder, const ItemInfo& aItem) : TexturedRenderPass(aBuilder, aItem), mOpacity(1.0f) { SetDefaultGeometry(aItem); } bool -SingleTexturePass::AddToPass(LayerMLGPU* aLayer, ItemInfo& aInfo) +SingleTexturePass::AddToPass(LayerMLGPU* aLayer, ItemInfo& aItem) { RefPtr<TextureSource> texture; - gfx::SamplingFilter filter; + SamplerMode sampler; TextureFlags flags = TextureFlags::NO_FLAGS; if (PaintedLayerMLGPU* paintedLayer = aLayer->AsPaintedLayerMLGPU()) { if (paintedLayer->HasComponentAlpha()) { return false; } texture = paintedLayer->GetTexture(); - filter = SamplingFilter::LINEAR; + sampler = paintedLayer->GetSamplerMode(); } else if (TexturedLayerMLGPU* texLayer = aLayer->AsTexturedLayerMLGPU()) { texture = texLayer->GetTexture(); - filter = texLayer->GetSamplingFilter(); + sampler = FilterToSamplerMode(texLayer->GetSamplingFilter()); TextureHost* host = texLayer->GetImageHost()->CurrentTextureHost(); flags = host->GetFlags(); } else { return false; } // We should not assign a texture-based layer to tiles if it has no texture. MOZ_ASSERT(texture); float opacity = aLayer->GetComputedOpacity(); if (mTexture) { if (texture != mTexture) { return false; } - if (mFilter != filter) { + if (mSamplerMode != sampler) { return false; } if (mOpacity != opacity) { return false; } // Note: premultiplied, origin-bottom-left are already implied by the texture source. } else { mTexture = texture; - mFilter = filter; + mSamplerMode = sampler; mOpacity = opacity; mTextureFlags = flags; } Txn txn(this); if (PaintedLayerMLGPU* layer = aLayer->AsPaintedLayerMLGPU()) { - nsIntRegion visible = layer->GetRenderRegion(); - IntPoint offset = layer->GetContentHost()->GetOriginOffset(); - - if (!AddItems(txn, aInfo, visible, offset, mTexture->GetSize())) { + Info info(aItem, layer); + if (!AddItems(txn, info, layer->GetRenderRegion())) { return false; } } else if (TexturedLayerMLGPU* layer = aLayer->AsTexturedLayerMLGPU()) { - IntPoint origin(0, 0); - Maybe<Size> pictureScale = layer->GetPictureScale(); + Info info(aItem, layer); nsIntRegion visible = layer->GetShadowVisibleRegion().ToUnknownRegion(); - - if (!AddItems(txn, aInfo, visible, origin, mTexture->GetSize(), pictureScale)) { + if (!AddItems(txn, info, visible)) { return false; } } return txn.Commit(); } Maybe<MLGBlendState> @@ -617,17 +645,17 @@ SingleTexturePass::SetupPipeline() if (mGeometry == GeometryMode::UnitQuad) { mDevice->SetVertexShader(VertexShaderID::TexturedQuad); } else { mDevice->SetVertexShader(VertexShaderID::TexturedVertex); } mDevice->SetPSTexture(0, mTexture); - mDevice->SetSamplerMode(kDefaultSamplerSlot, mFilter); + mDevice->SetSamplerMode(kDefaultSamplerSlot, mSamplerMode); switch (mTexture.get()->GetFormat()) { case SurfaceFormat::B8G8R8A8: case SurfaceFormat::R8G8B8A8: if (mGeometry == GeometryMode::UnitQuad) mDevice->SetPixelShader(PixelShaderID::TexturedQuadRGBA); else mDevice->SetPixelShader(PixelShaderID::TexturedVertexRGBA); break; @@ -643,36 +671,34 @@ SingleTexturePass::SetupPipeline() ComponentAlphaPass::ComponentAlphaPass(FrameBuilder* aBuilder, const ItemInfo& aItem) : TexturedRenderPass(aBuilder, aItem), mAssignedLayer(nullptr) { SetDefaultGeometry(aItem); } bool -ComponentAlphaPass::AddToPass(LayerMLGPU* aItem, ItemInfo& aInfo) +ComponentAlphaPass::AddToPass(LayerMLGPU* aLayer, ItemInfo& aItem) { - PaintedLayerMLGPU* layer = aItem->AsPaintedLayerMLGPU(); + PaintedLayerMLGPU* layer = aLayer->AsPaintedLayerMLGPU(); MOZ_ASSERT(layer); if (mAssignedLayer && mAssignedLayer != layer) { return false; } if (!mAssignedLayer) { mAssignedLayer = layer; mTextureOnBlack = layer->GetTexture(); mTextureOnWhite = layer->GetTextureOnWhite(); } Txn txn(this); - nsIntRegion visible = layer->GetRenderRegion(); - IntPoint offset = layer->GetContentHost()->GetOriginOffset(); - - if (!AddItems(txn, aInfo, visible, offset, mTextureOnWhite->GetSize())) { + Info info(aItem, layer); + if (!AddItems(txn, info, layer->GetRenderRegion())) { return false; } return txn.Commit(); } float ComponentAlphaPass::GetOpacity() const { @@ -692,70 +718,68 @@ ComponentAlphaPass::SetupPipeline() if (mGeometry == GeometryMode::UnitQuad) { mDevice->SetVertexShader(VertexShaderID::TexturedQuad); mDevice->SetPixelShader(PixelShaderID::ComponentAlphaQuad); } else { mDevice->SetVertexShader(VertexShaderID::TexturedVertex); mDevice->SetPixelShader(PixelShaderID::ComponentAlphaVertex); } - mDevice->SetSamplerMode(kDefaultSamplerSlot, SamplerMode::LinearClamp); + mDevice->SetSamplerMode(kDefaultSamplerSlot, mAssignedLayer->GetSamplerMode()); mDevice->SetPSTextures(0, 2, textures); } VideoRenderPass::VideoRenderPass(FrameBuilder* aBuilder, const ItemInfo& aItem) : TexturedRenderPass(aBuilder, aItem), mOpacity(1.0f) { SetDefaultGeometry(aItem); } bool -VideoRenderPass::AddToPass(LayerMLGPU* aItem, ItemInfo& aInfo) +VideoRenderPass::AddToPass(LayerMLGPU* aLayer, ItemInfo& aItem) { - ImageLayerMLGPU* layer = aItem->AsImageLayerMLGPU(); + ImageLayerMLGPU* layer = aLayer->AsImageLayerMLGPU(); if (!layer) { return false; } RefPtr<TextureHost> host = layer->GetImageHost()->CurrentTextureHost(); RefPtr<TextureSource> source = layer->GetTexture(); float opacity = layer->GetComputedOpacity(); - SamplingFilter filter = layer->GetSamplingFilter(); + SamplerMode sampler = FilterToSamplerMode(layer->GetSamplingFilter()); if (mHost) { if (mHost != host) { return false; } if (mTexture != source) { return false; } if (mOpacity != opacity) { return false; } - if (mFilter != filter) { + if (mSamplerMode != sampler) { return false; } } else { mHost = host; mTexture = source; mOpacity = opacity; - mFilter = filter; + mSamplerMode = sampler; } MOZ_ASSERT(!mTexture->AsBigImageIterator()); MOZ_ASSERT(!(mHost->GetFlags() & TextureFlags::NON_PREMULTIPLIED)); MOZ_ASSERT(!(mHost->GetFlags() & TextureFlags::ORIGIN_BOTTOM_LEFT)); Txn txn(this); - IntPoint origin(0, 0); - Maybe<Size> pictureScale = layer->GetPictureScale(); + Info info(aItem, layer); nsIntRegion visible = layer->GetShadowVisibleRegion().ToUnknownRegion(); - - if (!AddItems(txn, aInfo, visible, origin, mTexture->GetSize(), pictureScale)) { + if (!AddItems(txn, info, visible)) { return false; } return txn.Commit(); } void VideoRenderPass::SetupPipeline() { @@ -802,17 +826,17 @@ VideoRenderPass::SetupPipeline() mDevice->SetPixelShader(PixelShaderID::TexturedVertexNV12); mDevice->SetPSTexturesNV12(0, mTexture); break; default: MOZ_ASSERT_UNREACHABLE("Unknown video format"); break; } - mDevice->SetSamplerMode(kDefaultSamplerSlot, mFilter); + mDevice->SetSamplerMode(kDefaultSamplerSlot, mSamplerMode); mDevice->SetPSConstantBuffer(1, ps1); } RenderViewPass::RenderViewPass(FrameBuilder* aBuilder, const ItemInfo& aItem) : TexturedRenderPass(aBuilder, aItem), mParentView(nullptr) { mAssignedLayer = aItem.layer->AsContainerLayerMLGPU(); @@ -826,41 +850,42 @@ RenderViewPass::RenderViewPass(FrameBuil // We do not have fast-path rect shaders for blending. SetGeometry(aItem, GeometryMode::Polygon); } else { SetDefaultGeometry(aItem); } } bool -RenderViewPass::AddToPass(LayerMLGPU* aLayer, ItemInfo& aInfo) +RenderViewPass::AddToPass(LayerMLGPU* aLayer, ItemInfo& aItem) { // We bake in the layer ahead of time, which also guarantees the blend mode // is baked in, as well as the geometry requirement. if (mAssignedLayer != aLayer) { return false; } mSource = mAssignedLayer->GetRenderTarget(); if (!mSource) { return false; } - mParentView = aInfo.view; + mParentView = aItem.view; Txn txn(this); IntPoint offset = mAssignedLayer->GetTargetOffset(); IntSize size = mAssignedLayer->GetTargetSize(); // Clamp the visible region to the texture size. nsIntRegion visible = mAssignedLayer->GetShadowVisibleRegion().ToUnknownRegion(); visible.AndWith(IntRect(offset, size)); - if (!AddItems(txn, aInfo, visible, offset, size)) { + Info info(aItem, mAssignedLayer); + if (!AddItems(txn, info, visible)) { return false; } return txn.Commit(); } float RenderViewPass::GetOpacity() const {
--- a/gfx/layers/mlgpu/RenderPassMLGPU.h +++ b/gfx/layers/mlgpu/RenderPassMLGPU.h @@ -287,63 +287,61 @@ protected: // Shaders which sample from a texture should inherit from this. class TexturedRenderPass : public BatchRenderPass<TexturedTraits> { public: explicit TexturedRenderPass(FrameBuilder* aBuilder, const ItemInfo& aItem); protected: + struct Info { + Info(const ItemInfo& aItem, PaintedLayerMLGPU* aLayer); + Info(const ItemInfo& aItem, TexturedLayerMLGPU* aLayer); + Info(const ItemInfo& aItem, ContainerLayerMLGPU* aLayer); + + const ItemInfo& item; + gfx::IntSize textureSize; + gfx::Point destOrigin; + Maybe<gfx::Size> scale; + bool decomposeIntoNoRepeatRects; + }; + // Add a set of draw rects based on a visible region. The texture size and // scaling factor are used to compute uv-coordinates. // // The origin is the offset from the draw rect to the layer bounds. You can // also think of it as the translation from layer space into texture space, // pre-scaling. For example, ImageLayers use the texture bounds as their // draw rect, so the origin will be (0, 0). ContainerLayer intermediate // surfaces, on the other hand, are relative to the target offset of the // layer. In all cases the visible region may be partially occluded, so // knowing the true origin is important. bool AddItems(Txn& aTxn, - const ItemInfo& aInfo, - const nsIntRegion& aDrawRects, - const gfx::IntPoint& aDestOrigin, - const gfx::IntSize& aTextureSize, - const Maybe<gfx::Size>& aScale = Nothing()) + const Info& aInfo, + const nsIntRegion& aDrawRegion) { - gfx::Point origin(aDestOrigin); - for (auto iter = aDrawRects.RectIter(); !iter.Done(); iter.Next()) { + for (auto iter = aDrawRegion.RectIter(); !iter.Done(); iter.Next()) { gfx::Rect drawRect = gfx::Rect(iter.Get()); - if (!AddItem(aTxn, aInfo, drawRect, origin, aTextureSize, aScale)) { + if (!AddItem(aTxn, aInfo, drawRect)) { return false; } } return true; } private: // Add a draw instance to the given destination rect. Texture coordinates // are built from the given texture size, optional scaling factor, and // texture origin relative to the draw rect. This will ultimately call // AddClippedItem, potentially clipping the draw rect if needed. - bool AddItem(Txn& aTxn, - const ItemInfo& aInfo, - const gfx::Rect& aDrawRect, - const gfx::Point& aDestOrigin, - const gfx::IntSize& aTextureSize, - const Maybe<gfx::Size>& aTextureScale = Nothing()); + bool AddItem(Txn& aTxn, const Info& aInfo, const gfx::Rect& aDrawRect); // Add an item that has gone through any necessary clipping already. This // is the final destination for handling textured items. - bool AddClippedItem(Txn& aTxn, - const ItemInfo& aInfo, - const gfx::Rect& aDrawRect, - const gfx::Point& aDestOrigin, - const gfx::IntSize& aTextureSize, - const Maybe<gfx::Size>& aScale); + bool AddClippedItem(Txn& aTxn, const Info& aInfo, const gfx::Rect& aDrawRect); protected: TextureFlags mTextureFlags; }; // This is only available when MLGDevice::CanUseClearView returns true. class ClearViewPass final : public RenderPassMLGPU { @@ -398,17 +396,17 @@ private: void SetupPipeline() override; float GetOpacity() const override { return mOpacity; } Maybe<MLGBlendState> GetBlendState() const override; private: RefPtr<TextureSource> mTexture; - gfx::SamplingFilter mFilter; + SamplerMode mSamplerMode; float mOpacity; }; class ComponentAlphaPass final : public TexturedRenderPass { public: explicit ComponentAlphaPass(FrameBuilder* aBuilder, const ItemInfo& aItem); @@ -444,17 +442,17 @@ private: void SetupPipeline() override; float GetOpacity() const override { return mOpacity; } private: RefPtr<TextureHost> mHost; RefPtr<TextureSource> mTexture; - gfx::SamplingFilter mFilter; + SamplerMode mSamplerMode; float mOpacity; }; class RenderViewPass final : public TexturedRenderPass { public: RenderViewPass(FrameBuilder* aBuilder, const ItemInfo& aItem);
--- a/gfx/layers/wr/StackingContextHelper.cpp +++ b/gfx/layers/wr/StackingContextHelper.cpp @@ -91,30 +91,30 @@ StackingContextHelper::StackingContextHe , mYScale(1.0f) { nsRect visibleRect; if (aTransformPtr) { mTransform = *aTransformPtr; } + // Apply the inherited scale from parent + mTransform.PostScale(aParentSC.mXScale, aParentSC.mYScale, 1.0); + mTransform.NudgeToIntegersFixedEpsilon(); + if (aPerspectivePtr) { mHasPerspectiveTransform = true; } bool is2d = !aTransformPtr || (aTransformPtr->Is2D() && !aPerspectivePtr); if (is2d) { nsRect itemBounds = aDisplayList->GetClippedBoundsWithRespectToASR(aDisplayListBuilder, aItem->GetActiveScrolledRoot()); nsRect childrenVisible = aItem->GetVisibleRectForChildren(); visibleRect = itemBounds.Intersect(childrenVisible); - // Apply the inherited scale from parent - mTransform.PostScale(aParentSC.mXScale, aParentSC.mYScale, 1.0); - mTransform.NudgeToIntegersFixedEpsilon(); - // Calculate the correct scale for current stacking context gfx::Size scale = mTransform.As2D().ScaleFactors(true); // Restore the scale to default if the scale is too small if (FuzzyEqualsAdditive(scale.width, 0.0f) || FuzzyEqualsAdditive(scale.height, 0.0f)) { scale = gfx::Size(1.0f, 1.0f); }
--- a/gfx/vr/ipc/VRManagerParent.cpp +++ b/gfx/vr/ipc/VRManagerParent.cpp @@ -182,29 +182,29 @@ VRManagerParent::RegisterVRManagerInComp aVRManager->RegisterWithManager(); } /*static*/ VRManagerParent* VRManagerParent::CreateSameProcess() { MessageLoop* loop = mozilla::layers::CompositorThreadHolder::Loop(); RefPtr<VRManagerParent> vmp = new VRManagerParent(base::GetCurrentProcId(), false); - vmp->mCompositorThreadHolder = layers::CompositorThreadHolder::GetSingleton(); + vmp->mCompositorThreadHolder = new layers::CompositorThreadHolderDebug("VRManagerSame"); vmp->mSelfRef = vmp; loop->PostTask(NewRunnableFunction(RegisterVRManagerInCompositorThread, vmp.get())); return vmp.get(); } bool VRManagerParent::CreateForGPUProcess(Endpoint<PVRManagerParent>&& aEndpoint) { MessageLoop* loop = mozilla::layers::CompositorThreadHolder::Loop(); RefPtr<VRManagerParent> vmp = new VRManagerParent(aEndpoint.OtherPid(), false); - vmp->mCompositorThreadHolder = layers::CompositorThreadHolder::GetSingleton(); + vmp->mCompositorThreadHolder = new layers::CompositorThreadHolderDebug("VRManager"); loop->PostTask(NewRunnableMethod<Endpoint<PVRManagerParent>&&>( "gfx::VRManagerParent::Bind", vmp, &VRManagerParent::Bind, Move(aEndpoint))); return true; } @@ -223,17 +223,19 @@ VRManagerParent::ActorDestroy(ActorDestr NewRunnableMethod("gfx::VRManagerParent::DeferredDestroy", this, &VRManagerParent::DeferredDestroy)); } void VRManagerParent::OnChannelConnected(int32_t aPid) { - mCompositorThreadHolder = layers::CompositorThreadHolder::GetSingleton(); + mCompositorThreadHolder = + new layers::CompositorThreadHolderDebug(IsSameProcess() ? "VRManagerSame" + : "VRManager"); } mozilla::ipc::IPCResult VRManagerParent::RecvRefreshDisplays() { // This is called to refresh the VR Displays for Navigator.GetVRDevices(). // We must pass "true" to VRManager::RefreshVRDisplays() // to ensure that the promise returned by Navigator.GetVRDevices
--- a/gfx/vr/ipc/VRManagerParent.h +++ b/gfx/vr/ipc/VRManagerParent.h @@ -119,17 +119,17 @@ private: void DeferredDestroy(); // This keeps us alive until ActorDestroy(), at which point we do a // deferred destruction of ourselves. RefPtr<VRManagerParent> mSelfRef; // Keep the compositor thread alive, until we have destroyed ourselves. - RefPtr<layers::CompositorThreadHolder> mCompositorThreadHolder; + RefPtr<layers::CompositorThreadHolderDebug> mCompositorThreadHolder; // Keep the VRManager alive, until we have destroyed ourselves. RefPtr<VRManager> mVRManagerHolder; nsRefPtrHashtable<nsUint32HashKey, impl::VRDisplayPuppet> mVRDisplayTests; nsRefPtrHashtable<nsUint32HashKey, impl::VRControllerPuppet> mVRControllerTests; uint32_t mDisplayTestID; uint32_t mControllerTestID; bool mHaveEventListener;
--- a/image/StreamingLexer.h +++ b/image/StreamingLexer.h @@ -424,17 +424,20 @@ public: // Since the current iterator has already advanced to this point, we // know that the state can only be READY or COMPLETE. That does not mean // everything is stored in a single chunk, and may require multiple Advance // calls to get where we want to be. SourceBufferIterator::State state; do { state = other.Advance(pos); if (state != SourceBufferIterator::READY) { - MOZ_ASSERT_UNREACHABLE("Cannot advance to existing position"); + // The only way we should fail to advance over data we already seen is + // if we hit an error while inserting data into the buffer. This will + // cause an early exit. + MOZ_ASSERT(NS_FAILED(other.CompletionStatus())); return Nothing(); } MOZ_ASSERT(pos >= other.Length()); pos -= other.Length(); } while (pos > 0); // Force the data pointer to be where we expect it to be. state = other.Advance(0);
new file mode 100644 --- /dev/null +++ b/js/src/jit-test/tests/ion/array-push-multiple-with-funapply.js @@ -0,0 +1,80 @@ +// |jit-test| --no-threads + +// This test case check's Ion ability to inline Array.prototype.push, when +// fun.apply is used and inlined with the set of arguments of the current +// function. Note, that the following are not equivalent in case of failures: +// +// arr = []; +// arr.push(1,2,3); // OOM ---> arr == [] +// +// arr = []; +// arr.push(1); +// arr.push(2); // OOM --> arr == [1] +// arr.push(3); + +function canIoncompile() { + while (true) { + var i = inIon(); + if (i) + return i; + } +} + +if (!("oomAtAllocation" in this)) + quit(); +if (canIoncompile() != true) + quit(); +if ("gczeal" in this) + gczeal(0); + +function pushLimits(limit, offset) { + function pusher() { + Array.prototype.push.apply(arr, arguments) + } + var arr = [0,1,2,3,4,5,6,7]; + arr.length = offset; + var l = arr.length; + var was = inIon(); + oomAtAllocation(limit); + try { + for (var i = 0; i < 100; i++) + pusher(0,1,2,3,4,5,6,7); + } catch (e) { + // Catch OOM. + } + resetOOMFailure(); + assertEq(arr.length % 8, l); + // Check for a bailout. + var is = inIon(); + return was ? is ? 1 : 2 : 0; +} + + + +// We need this limit to be high enough to be able to OSR in the for-loop of +// pushLimits. +var limit = 1024 * 1024 * 1024; +while(true) { + var res = pushLimits(limit, 0); + print(limit, res); + + if (res == 0) { + limit = 1024 * 1024 * 1024; + } else if (res == 1) { // Started and finished in Ion. + // We want to converge quickly to a state where the memory is limited + // enough to cause failures in array.prototype.push. + limit = (limit / 1.5) | 0; + if (limit == 0) // If we are not in the Jit. + break; + } else if (res == 2) { // Started in Ion, and finished in Baseline. + if (limit < 10) { + // This is used to offset the OOM location, such that we can test + // each steps of the Array.push function, when it is jitted. + for (var off = 1; off < 8; off++) + pushLimits(limit, off); + } + if (limit == 1) + break; + limit--; + } +}
--- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -3726,33 +3726,26 @@ IonBuilder::inlineScriptedCall(CallInfo& MOZ_ASSERT(IsIonInlinablePC(pc)); MBasicBlock::BackupPoint backup(current); if (!backup.init(alloc())) return abort(AbortReason::Alloc); callInfo.setImplicitlyUsedUnchecked(); - // Ensure sufficient space in the slots: needed for inlining from FUNAPPLY. - uint32_t depth = current->stackDepth() + callInfo.numFormals(); - if (depth > current->nslots()) { - if (!current->increaseSlots(depth - current->nslots())) - return abort(AbortReason::Alloc); - } - // Create new |this| on the caller-side for inlined constructors. if (callInfo.constructing()) { MDefinition* thisDefn = createThis(target, callInfo.fun(), callInfo.getNewTarget()); if (!thisDefn) return abort(AbortReason::Alloc); callInfo.setThis(thisDefn); } // Capture formals in the outer resume point. - callInfo.pushFormals(current); + MOZ_TRY(callInfo.pushFormals(this, current)); MResumePoint* outerResumePoint = MResumePoint::New(alloc(), current, pc, MResumePoint::Outer); if (!outerResumePoint) return abort(AbortReason::Alloc); current->setOuterResumePoint(outerResumePoint); // Pop formals again, except leave |fun| on stack for duration of call. @@ -4405,17 +4398,17 @@ AbortReasonOr<Ok> IonBuilder::inlineGenericFallback(JSFunction* target, CallInfo& callInfo, MBasicBlock* dispatchBlock) { // Generate a new block with all arguments on-stack. MBasicBlock* fallbackBlock; MOZ_TRY_VAR(fallbackBlock, newBlock(dispatchBlock, pc)); graph().addBlock(fallbackBlock); // Create a new CallInfo to track modified state within this block. - CallInfo fallbackInfo(alloc(), callInfo.constructing(), callInfo.ignoresReturnValue()); + CallInfo fallbackInfo(alloc(), pc, callInfo.constructing(), callInfo.ignoresReturnValue()); if (!fallbackInfo.init(callInfo)) return abort(AbortReason::Alloc); fallbackInfo.popFormals(fallbackBlock); // Generate an MCall, which uses stateful |current|. MOZ_TRY(setCurrentAndSpecializePhis(fallbackBlock)); MOZ_TRY(makeCall(target, fallbackInfo)); @@ -4442,17 +4435,17 @@ IonBuilder::inlineObjectGroupFallback(Ca MOZ_ASSERT_IF(callInfo.fun()->isTypeBarrier(), cache->hasOneUse()); // This means that no resume points yet capture the MGetPropertyCache, // so everything from the MGetPropertyCache up until the call is movable. // We now move the MGetPropertyCache and friends into a fallback path. MOZ_ASSERT(cache->idempotent()); // Create a new CallInfo to track modified state within the fallback path. - CallInfo fallbackInfo(alloc(), callInfo.constructing(), callInfo.ignoresReturnValue()); + CallInfo fallbackInfo(alloc(), pc, callInfo.constructing(), callInfo.ignoresReturnValue()); if (!fallbackInfo.init(callInfo)) return abort(AbortReason::Alloc); // Capture stack prior to the call operation. This captures the function. MResumePoint* preCallResumePoint = MResumePoint::New(alloc(), dispatchBlock, pc, MResumePoint::ResumeAt); if (!preCallResumePoint) return abort(AbortReason::Alloc); @@ -4528,17 +4521,17 @@ IonBuilder::inlineCalls(CallInfo& callIn MOZ_ASSERT(IsIonInlinablePC(pc)); MOZ_ASSERT(choiceSet.length() == targets.length()); MOZ_ASSERT_IF(!maybeCache, targets.length() >= 2); MOZ_ASSERT_IF(maybeCache, targets.length() >= 1); MOZ_ASSERT_IF(maybeCache, maybeCache->value()->type() == MIRType::Object); MBasicBlock* dispatchBlock = current; callInfo.setImplicitlyUsedUnchecked(); - callInfo.pushFormals(dispatchBlock); + MOZ_TRY(callInfo.pushFormals(this, dispatchBlock)); // Patch any InlinePropertyTable to only contain functions that are // inlineable. The InlinePropertyTable will also be patched at the end to // exclude native functions that vetoed inlining. if (maybeCache) { InlinePropertyTable* propTable = maybeCache->propTable(); propTable->trimToTargets(targets); if (propTable->numEntries() == 0) @@ -4621,17 +4614,17 @@ IonBuilder::inlineCalls(CallInfo& callIn dispatchBlock->add(funcDef); // Use the inlined callee in the inline resume point and on stack. int funIndex = inlineBlock->entryResumePoint()->stackDepth() - callInfo.numFormals(); inlineBlock->entryResumePoint()->replaceOperand(funIndex, funcDef); inlineBlock->rewriteSlot(funIndex, funcDef); // Create a new CallInfo to track modified state within the inline block. - CallInfo inlineInfo(alloc(), callInfo.constructing(), callInfo.ignoresReturnValue()); + CallInfo inlineInfo(alloc(), pc, callInfo.constructing(), callInfo.ignoresReturnValue()); if (!inlineInfo.init(callInfo)) return abort(AbortReason::Alloc); inlineInfo.popFormals(inlineBlock); inlineInfo.setFun(funcDef); if (maybeCache) { // Assign the 'this' value a TypeSet specialized to the groups that // can generate this inlining target. @@ -5068,17 +5061,17 @@ IonBuilder::jsop_funcall(uint32_t argc) int calleeDepth = -((int)argc + 2); int funcDepth = -((int)argc + 1); // If |Function.prototype.call| may be overridden, don't optimize callsite. TemporaryTypeSet* calleeTypes = current->peek(calleeDepth)->resultTypeSet(); JSFunction* native = getSingleCallTarget(calleeTypes); if (!native || !native->isNative() || native->native() != &fun_call) { - CallInfo callInfo(alloc(), /* constructing = */ false, + CallInfo callInfo(alloc(), pc, /* constructing = */ false, /* ignoresReturnValue = */ BytecodeIsPopped(pc)); if (!callInfo.init(current, argc)) return abort(AbortReason::Alloc); return makeCall(native, callInfo); } current->peek(calleeDepth)->setImplicitlyUsedUnchecked(); // Extract call target. @@ -5094,17 +5087,17 @@ IonBuilder::jsop_funcall(uint32_t argc) // Pushing is safe here, since one stack slot has been removed. if (zeroArguments) { pushConstant(UndefinedValue()); } else { // |this| becomes implicit in the call. argc -= 1; } - CallInfo callInfo(alloc(), /* constructing = */ false, + CallInfo callInfo(alloc(), pc, /* constructing = */ false, /* ignoresReturnValue = */ BytecodeIsPopped(pc)); if (!callInfo.init(current, argc)) return abort(AbortReason::Alloc); // Try to inline the call. if (!zeroArguments) { InliningDecision decision = makeInliningDecision(target, callInfo); switch (decision) { @@ -5130,17 +5123,17 @@ IonBuilder::jsop_funcall(uint32_t argc) AbortReasonOr<Ok> IonBuilder::jsop_funapply(uint32_t argc) { int calleeDepth = -((int)argc + 2); TemporaryTypeSet* calleeTypes = current->peek(calleeDepth)->resultTypeSet(); JSFunction* native = getSingleCallTarget(calleeTypes); if (argc != 2 || info().analysisMode() == Analysis_ArgumentsUsage) { - CallInfo callInfo(alloc(), /* constructing = */ false, + CallInfo callInfo(alloc(), pc, /* constructing = */ false, /* ignoresReturnValue = */ BytecodeIsPopped(pc)); if (!callInfo.init(current, argc)) return abort(AbortReason::Alloc); return makeCall(native, callInfo); } // Disable compilation if the second argument to |apply| cannot be guaranteed // to be either definitely |arguments| or definitely not |arguments|. @@ -5160,17 +5153,17 @@ IonBuilder::jsop_funapply(uint32_t argc) objTypes && objTypes->getKnownClass(constraints()) == &ArrayObject::class_ && !objTypes->hasObjectFlags(constraints(), OBJECT_FLAG_LENGTH_OVERFLOW) && ElementAccessIsPacked(constraints(), argument)) { return jsop_funapplyarray(argc); } - CallInfo callInfo(alloc(), /* constructing = */ false, + CallInfo callInfo(alloc(), pc, /* constructing = */ false, /* ignoresReturnValue = */ BytecodeIsPopped(pc)); if (!callInfo.init(current, argc)) return abort(AbortReason::Alloc); return makeCall(native, callInfo); } if ((!native || !native->isNative() || native->native() != fun_apply) && @@ -5307,17 +5300,17 @@ IonBuilder::jsop_funapplyarguments(uint3 } // When inlining we have the arguments the function gets called with // and can optimize even more, by just calling the functions with the args. // We also try this path when doing the definite properties analysis, as we // can inline the apply() target and don't care about the actual arguments // that were passed in. - CallInfo callInfo(alloc(), /* constructing = */ false, + CallInfo callInfo(alloc(), pc, /* constructing = */ false, /* ignoresReturnValue = */ BytecodeIsPopped(pc)); // Vp MDefinition* vp = current->pop(); vp->setImplicitlyUsedUnchecked(); // Arguments if (inliningDepth_) { @@ -5378,17 +5371,17 @@ IonBuilder::jsop_call(uint32_t argc, boo int calleeDepth = -((int)argc + 2 + constructing); // Acquire known call target if existent. InliningTargets targets(alloc()); TemporaryTypeSet* calleeTypes = current->peek(calleeDepth)->resultTypeSet(); if (calleeTypes) MOZ_TRY(getPolyCallTargets(calleeTypes, constructing, targets, 4)); - CallInfo callInfo(alloc(), constructing, ignoresReturnValue); + CallInfo callInfo(alloc(), pc, constructing, ignoresReturnValue); if (!callInfo.init(current, argc)) return abort(AbortReason::Alloc); // Try inlining InliningStatus status; MOZ_TRY_VAR(status, inlineCallsite(targets, callInfo)); if (status == InliningStatus_Inlined) return Ok(); @@ -5630,17 +5623,17 @@ IonBuilder::jsop_eval(uint32_t argc) return abort(AbortReason::Disable, "Direct eval with more than one argument"); if (!info().funMaybeLazy()) return abort(AbortReason::Disable, "Direct eval in global code"); if (info().funMaybeLazy()->isArrow()) return abort(AbortReason::Disable, "Direct eval from arrow function"); - CallInfo callInfo(alloc(), /* constructing = */ false, + CallInfo callInfo(alloc(), pc, /* constructing = */ false, /* ignoresReturnValue = */ BytecodeIsPopped(pc)); if (!callInfo.init(current, argc)) return abort(AbortReason::Alloc); callInfo.setImplicitlyUsedUnchecked(); callInfo.fun()->setImplicitlyUsedUnchecked(); MDefinition* envChain = current->environmentChain(); @@ -5669,17 +5662,17 @@ IonBuilder::jsop_eval(uint32_t argc) if (StringEqualsAscii(atom, "()")) { MDefinition* name = string->getOperand(0); MInstruction* dynamicName = MGetDynamicName::New(alloc(), envChain, name); current->add(dynamicName); current->push(dynamicName); current->push(constant(UndefinedValue())); // thisv - CallInfo evalCallInfo(alloc(), /* constructing = */ false, + CallInfo evalCallInfo(alloc(), pc, /* constructing = */ false, /* ignoresReturnValue = */ BytecodeIsPopped(pc)); if (!evalCallInfo.init(current, /* argc = */ 0)) return abort(AbortReason::Alloc); return makeCall(nullptr, evalCallInfo); } } @@ -11096,17 +11089,17 @@ IonBuilder::getPropTryCommonGetter(bool* // Make sure there's enough room if (!current->ensureHasSlots(2)) return abort(AbortReason::Alloc); current->push(constant(ObjectValue(*commonGetter))); current->push(obj); - CallInfo callInfo(alloc(), /* constructing = */ false, + CallInfo callInfo(alloc(), pc, /* constructing = */ false, /* ignoresReturnValue = */ BytecodeIsPopped(pc)); if (!callInfo.init(current, 0)) return abort(AbortReason::Alloc); if (commonGetter->isNative()) { InliningStatus status; MOZ_TRY_VAR(status, inlineNativeGetter(callInfo, commonGetter)); switch (status) { @@ -11637,17 +11630,17 @@ IonBuilder::setPropTryCommonSetter(bool* return abort(AbortReason::Alloc); current->push(constant(ObjectValue(*commonSetter))); current->push(obj); current->push(value); // Call the setter. Note that we have to push the original value, not // the setter's return value. - CallInfo callInfo(alloc(), /* constructing = */ false, + CallInfo callInfo(alloc(), pc, /* constructing = */ false, /* ignoresReturnValue = */ BytecodeIsPopped(pc)); if (!callInfo.init(current, 1)) return abort(AbortReason::Alloc); // Ensure that we know we are calling a setter in case we inline it. callInfo.markAsSetter(); // Inline the setter if we can.
--- a/js/src/jit/IonBuilder.h +++ b/js/src/jit/IonBuilder.h @@ -1190,26 +1190,28 @@ class CallInfo MDefinitionVector args_; bool constructing_:1; // True if the caller does not use the return value. bool ignoresReturnValue_:1; bool setter_:1; + bool apply_:1; public: - CallInfo(TempAllocator& alloc, bool constructing, bool ignoresReturnValue) + CallInfo(TempAllocator& alloc, jsbytecode* pc, bool constructing, bool ignoresReturnValue) : fun_(nullptr), thisArg_(nullptr), newTargetArg_(nullptr), args_(alloc), constructing_(constructing), ignoresReturnValue_(ignoresReturnValue), - setter_(false) + setter_(false), + apply_(JSOp(*pc) == JSOP_FUNAPPLY) { } MOZ_MUST_USE bool init(CallInfo& callInfo) { MOZ_ASSERT(constructing_ == callInfo.constructing()); fun_ = callInfo.fun(); thisArg_ = callInfo.thisArg(); ignoresReturnValue_ = callInfo.ignoresReturnValue(); @@ -1243,25 +1245,36 @@ class CallInfo return true; } void popFormals(MBasicBlock* current) { current->popn(numFormals()); } - void pushFormals(MBasicBlock* current) { + AbortReasonOr<Ok> pushFormals(MIRGenerator* mir, MBasicBlock* current) { + // Ensure sufficient space in the slots: needed for inlining from FUNAPPLY. + if (apply_) { + uint32_t depth = current->stackDepth() + numFormals(); + if (depth > current->nslots()) { + if (!current->increaseSlots(depth - current->nslots())) + return mir->abort(AbortReason::Alloc); + } + } + current->push(fun()); current->push(thisArg()); for (uint32_t i = 0; i < argc(); i++) current->push(getArg(i)); if (constructing()) current->push(getNewTarget()); + + return Ok(); } uint32_t argc() const { return args_.length(); } uint32_t numFormals() const { return argc() + 2 + constructing(); }
--- a/js/src/jit/MCallOptimize.cpp +++ b/js/src/jit/MCallOptimize.cpp @@ -873,17 +873,17 @@ IonBuilder::inlineArrayPush(CallInfo& ca truncate->setRecoveredOnBailout(); current->add(elements); current->add(length); current->add(truncate); // Restore the stack, such that resume points are created with the stack // as it was before the call. - callInfo.pushFormals(current); + MOZ_TRY(callInfo.pushFormals(this, current)); } MInstruction* ins = nullptr; for (uint32_t i = 0; i < callInfo.argc(); i++) { MDefinition* value = callInfo.getArg(i); if (toDouble) { MInstruction* valueDouble = MToDouble::New(alloc(), value); current->add(valueDouble);
--- a/layout/base/PresShell.cpp +++ b/layout/base/PresShell.cpp @@ -8241,18 +8241,17 @@ PresShell::HandleEventInternal(WidgetEve case eDragLeave: case eDragOver: case eDrop: { // After any drag event other than dragstart (which is handled separately, // as we need to collect the data first), the DataTransfer needs to be // made protected, and then disconnected. DataTransfer* dataTransfer = aEvent->AsDragEvent()->mDataTransfer; if (dataTransfer) { - dataTransfer->SetMode(DataTransfer::Mode::Protected); - dataTransfer->ClearAll(); + dataTransfer->Disconnect(); } break; } default: break; } if (aEvent->IsTrusted() && aEvent->mTimeStamp > mLastOSWake) {
--- a/layout/painting/nsCSSRendering.cpp +++ b/layout/painting/nsCSSRendering.cpp @@ -746,23 +746,23 @@ ConstructBorderRenderer(nsPresContext* a "Should not skip sides for box-decoration-break:clone except " "::first-letter/line continuations or other frame types that " "don't have borders but those shouldn't reach this point. " "Overflow containers do reach this point though."); border.ApplySkipSides(aSkipSides); } // Convert to dev pixels. - nscoord twipsPerPixel = aPresContext->DevPixelsToAppUnits(1); - Rect joinedBorderAreaPx = NSRectToRect(joinedBorderArea, twipsPerPixel); - Float borderWidths[4] = { Float(border.top) / twipsPerPixel, - Float(border.right) / twipsPerPixel, - Float(border.bottom) / twipsPerPixel, - Float(border.left) / twipsPerPixel }; - Rect dirtyRect = NSRectToRect(aDirtyRect, twipsPerPixel); + nscoord oneDevPixel = aPresContext->DevPixelsToAppUnits(1); + Rect joinedBorderAreaPx = NSRectToRect(joinedBorderArea, oneDevPixel); + Float borderWidths[4] = { Float(border.top) / oneDevPixel, + Float(border.right) / oneDevPixel, + Float(border.bottom) / oneDevPixel, + Float(border.left) / oneDevPixel }; + Rect dirtyRect = NSRectToRect(aDirtyRect, oneDevPixel); uint8_t borderStyles[4]; nscolor borderColors[4]; nsBorderColors* compositeColors[4]; // pull out styles, colors, composite colors NS_FOR_CSS_SIDES (i) { borderStyles[i] = aStyleBorder.GetBorderStyle(i); @@ -996,25 +996,25 @@ nsCSSRendering::CreateBorderRendererForO nsRect outerRect = innerRect; outerRect.Inflate(width, width); // get the radius for our outline nsIFrame::ComputeBorderRadii(ourOutline->mOutlineRadius, aBorderArea.Size(), outerRect.Size(), Sides(), twipsRadii); // Get our conversion values - nscoord twipsPerPixel = aPresContext->DevPixelsToAppUnits(1); + nscoord oneDevPixel = aPresContext->DevPixelsToAppUnits(1); // get the outer rectangles - Rect oRect(NSRectToRect(outerRect, twipsPerPixel)); + Rect oRect(NSRectToRect(outerRect, oneDevPixel)); // convert the radii nsMargin outlineMargin(width, width, width, width); RectCornerRadii outlineRadii; - ComputePixelRadii(twipsRadii, twipsPerPixel, &outlineRadii); + ComputePixelRadii(twipsRadii, oneDevPixel, &outlineRadii); uint8_t outlineStyle = ourOutline->mOutlineStyle; if (outlineStyle == NS_STYLE_BORDER_STYLE_AUTO) { if (nsLayoutUtils::IsOutlineStyleAutoEnabled()) { nsITheme* theme = aPresContext->GetTheme(); if (theme && theme->ThemeSupportsWidget(aPresContext, aForFrame, NS_THEME_FOCUS_OUTLINE)) { theme->DrawWidgetBackground(aRenderingContext, aForFrame, @@ -1039,21 +1039,21 @@ nsCSSRendering::CreateBorderRendererForO nscolor outlineColor = aStyleContext->GetVisitedDependentColor(&nsStyleOutline::mOutlineColor); nscolor outlineColors[4] = { outlineColor, outlineColor, outlineColor, outlineColor }; // convert the border widths - Float outlineWidths[4] = { Float(width) / twipsPerPixel, - Float(width) / twipsPerPixel, - Float(width) / twipsPerPixel, - Float(width) / twipsPerPixel }; - Rect dirtyRect = NSRectToRect(aDirtyRect, twipsPerPixel); + Float outlineWidths[4] = { Float(width) / oneDevPixel, + Float(width) / oneDevPixel, + Float(width) / oneDevPixel, + Float(width) / oneDevPixel }; + Rect dirtyRect = NSRectToRect(aDirtyRect, oneDevPixel); nsIDocument* document = nullptr; nsIContent* content = aForFrame->GetContent(); if (content) { document = content->OwnerDoc(); } DrawTarget* dt = aRenderingContext ? aRenderingContext->GetDrawTarget() : nullptr; @@ -1437,24 +1437,24 @@ nsCSSRendering::GetShadowRect(const nsRe } bool nsCSSRendering::GetBorderRadii(const nsRect& aFrameRect, const nsRect& aBorderRect, nsIFrame* aFrame, RectCornerRadii& aOutRadii) { - const nscoord twipsPerPixel = aFrame->PresContext()->DevPixelsToAppUnits(1); + const nscoord oneDevPixel = aFrame->PresContext()->DevPixelsToAppUnits(1); nscoord twipsRadii[8]; NS_ASSERTION(aBorderRect.Size() == aFrame->VisualBorderRectRelativeToSelf().Size(), "unexpected size"); nsSize sz = aFrameRect.Size(); bool hasBorderRadius = aFrame->GetBorderRadii(sz, sz, Sides(), twipsRadii); if (hasBorderRadius) { - ComputePixelRadii(twipsRadii, twipsPerPixel, &aOutRadii); + ComputePixelRadii(twipsRadii, oneDevPixel, &aOutRadii); } return hasBorderRadius; } void nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext, gfxContext& aRenderingContext, @@ -1473,44 +1473,44 @@ nsCSSRendering::PaintBoxShadowOuter(nsPr bool nativeTheme = HasBoxShadowNativeTheme(aForFrame, hasBorderRadius); const nsStyleDisplay* styleDisplay = aForFrame->StyleDisplay(); nsRect frameRect = GetShadowRect(aFrameArea, nativeTheme, aForFrame); // Get any border radius, since box-shadow must also have rounded corners if // the frame does. RectCornerRadii borderRadii; - const nscoord twipsPerPixel = aPresContext->DevPixelsToAppUnits(1); + const nscoord oneDevPixel = aPresContext->DevPixelsToAppUnits(1); if (hasBorderRadius) { nscoord twipsRadii[8]; NS_ASSERTION(aFrameArea.Size() == aForFrame->VisualBorderRectRelativeToSelf().Size(), "unexpected size"); nsSize sz = frameRect.Size(); hasBorderRadius = aForFrame->GetBorderRadii(sz, sz, Sides(), twipsRadii); if (hasBorderRadius) { - ComputePixelRadii(twipsRadii, twipsPerPixel, &borderRadii); + ComputePixelRadii(twipsRadii, oneDevPixel, &borderRadii); } } // We don't show anything that intersects with the frame we're blurring on. So tell the // blurrer not to do unnecessary work there. - gfxRect skipGfxRect = ThebesRect(NSRectToRect(frameRect, twipsPerPixel)); + gfxRect skipGfxRect = ThebesRect(NSRectToRect(frameRect, oneDevPixel)); skipGfxRect.Round(); bool useSkipGfxRect = true; if (nativeTheme) { // Optimize non-leaf native-themed frames by skipping computing pixels // in the padding-box. We assume the padding-box is going to be painted // opaquely for non-leaf frames. // XXX this may not be a safe assumption; we should make this go away // by optimizing box-shadow drawing more for the cases where we don't have a skip-rect. useSkipGfxRect = !aForFrame->IsLeaf(); nsRect paddingRect = aForFrame->GetPaddingRect() - aForFrame->GetPosition() + aFrameArea.TopLeft(); - skipGfxRect = nsLayoutUtils::RectToGfxRect(paddingRect, twipsPerPixel); + skipGfxRect = nsLayoutUtils::RectToGfxRect(paddingRect, oneDevPixel); } else if (hasBorderRadius) { skipGfxRect.Deflate(gfxMargin( std::max(borderRadii[C_TL].height, borderRadii[C_TR].height), 0, std::max(borderRadii[C_BL].height, borderRadii[C_BR].height), 0)); } for (uint32_t i = shadows->Length(); i > 0; --i) { @@ -1524,35 +1524,35 @@ nsCSSRendering::PaintBoxShadowOuter(nsPr shadowRect.Inflate(shadowItem->mSpread, shadowItem->mSpread); } // shadowRect won't include the blur, so make an extra rect here that includes the blur // for use in the even-odd rule below. nsRect shadowRectPlusBlur = shadowRect; nscoord blurRadius = shadowItem->mRadius; shadowRectPlusBlur.Inflate( - nsContextBoxBlur::GetBlurRadiusMargin(blurRadius, twipsPerPixel)); + nsContextBoxBlur::GetBlurRadiusMargin(blurRadius, oneDevPixel)); Rect shadowGfxRectPlusBlur = - NSRectToRect(shadowRectPlusBlur, twipsPerPixel); + NSRectToRect(shadowRectPlusBlur, oneDevPixel); shadowGfxRectPlusBlur.RoundOut(); MaybeSnapToDevicePixels(shadowGfxRectPlusBlur, aDrawTarget, true); Color gfxShadowColor = GetShadowColor(shadowItem, aForFrame, aOpacity); if (nativeTheme) { nsContextBoxBlur blurringArea; // When getting the widget shape from the native theme, we're going // to draw the widget into the shadow surface to create a mask. // We need to ensure that there actually *is* a shadow surface // and that we're not going to draw directly into aRenderingContext. gfxContext* shadowContext = blurringArea.Init(shadowRect, shadowItem->mSpread, blurRadius, - twipsPerPixel, &aRenderingContext, aDirtyRect, + oneDevPixel, &aRenderingContext, aDirtyRect, useSkipGfxRect ? &skipGfxRect : nullptr, nsContextBoxBlur::FORCE_MASK); if (!shadowContext) continue; MOZ_ASSERT(shadowContext == blurringArea.GetContext()); aRenderingContext.Save(); @@ -1583,17 +1583,17 @@ nsCSSRendering::PaintBoxShadowOuter(nsPr styleDisplay->mAppearance, aFrameArea, nativeRect); blurringArea.DoPaint(); aRenderingContext.Restore(); } else { aRenderingContext.Save(); { - Rect innerClipRect = NSRectToRect(frameRect, twipsPerPixel); + Rect innerClipRect = NSRectToRect(frameRect, oneDevPixel); if (!MaybeSnapToDevicePixels(innerClipRect, aDrawTarget, true)) { innerClipRect.Round(); } // Clip out the interior of the frame's border edge so that the shadow // is only painted outside that area. RefPtr<PathBuilder> builder = aDrawTarget.CreatePathBuilder(FillRule::FILL_EVEN_ODD); @@ -1639,32 +1639,32 @@ nsCSSRendering::PaintBoxShadowOuter(nsPr fragmentClip = fragmentClip.Intersect(aDirtyRect); aRenderingContext. Clip(NSRectToSnappedRect(fragmentClip, aForFrame->PresContext()->AppUnitsPerDevPixel(), aDrawTarget)); RectCornerRadii clipRectRadii; if (hasBorderRadius) { - Float spreadDistance = Float(shadowItem->mSpread) / twipsPerPixel; + Float spreadDistance = Float(shadowItem->mSpread) / oneDevPixel; Float borderSizes[4]; borderSizes[eSideLeft] = spreadDistance; borderSizes[eSideTop] = spreadDistance; borderSizes[eSideRight] = spreadDistance; borderSizes[eSideBottom] = spreadDistance; nsCSSBorderRenderer::ComputeOuterRadii(borderRadii, borderSizes, &clipRectRadii); } nsContextBoxBlur::BlurRectangle(&aRenderingContext, shadowRect, - twipsPerPixel, + oneDevPixel, hasBorderRadius ? &clipRectRadii : nullptr, blurRadius, gfxShadowColor, aDirtyRect, skipGfxRect); aRenderingContext.Restore(); } @@ -1712,29 +1712,29 @@ nsCSSRendering::GetShadowInnerRadii(nsIF // Get any border radius, since box-shadow must also have rounded corners // if the frame does. nscoord twipsRadii[8]; nsRect frameRect = ::BoxDecorationRectForBorder(aFrame, aFrameArea, aFrame->GetSkipSides()); nsSize sz = frameRect.Size(); nsMargin border = aFrame->GetUsedBorder(); bool hasBorderRadius = aFrame->GetBorderRadii(sz, sz, Sides(), twipsRadii); - const nscoord twipsPerPixel = aFrame->PresContext()->DevPixelsToAppUnits(1); + const nscoord oneDevPixel = aFrame->PresContext()->DevPixelsToAppUnits(1); RectCornerRadii borderRadii; hasBorderRadius = GetBorderRadii(frameRect, aFrameArea, aFrame, borderRadii); if (hasBorderRadius) { - ComputePixelRadii(twipsRadii, twipsPerPixel, &borderRadii); + ComputePixelRadii(twipsRadii, oneDevPixel, &borderRadii); Float borderSizes[4] = { - Float(border.top) / twipsPerPixel, - Float(border.right) / twipsPerPixel, - Float(border.bottom) / twipsPerPixel, - Float(border.left) / twipsPerPixel + Float(border.top) / oneDevPixel, + Float(border.right) / oneDevPixel, + Float(border.bottom) / oneDevPixel, + Float(border.left) / oneDevPixel }; nsCSSBorderRenderer::ComputeInnerRadii(borderRadii, borderSizes, &aOutInnerRadii); } return hasBorderRadius; } @@ -1755,45 +1755,45 @@ nsCSSRendering::PaintBoxShadowInner(nsPr nsRect paddingRect = GetBoxShadowInnerPaddingRect(aForFrame, aFrameArea); RectCornerRadii innerRadii; bool hasBorderRadius = GetShadowInnerRadii(aForFrame, aFrameArea, innerRadii); - const nscoord twipsPerPixel = aPresContext->DevPixelsToAppUnits(1); + const nscoord oneDevPixel = aPresContext->DevPixelsToAppUnits(1); for (uint32_t i = shadows->Length(); i > 0; --i) { nsCSSShadowItem* shadowItem = shadows->ShadowAt(i - 1); if (!shadowItem->mInset) continue; // shadowPaintRect: the area to paint on the temp surface // shadowClipRect: the area on the temporary surface within shadowPaintRect // that we will NOT paint in nscoord blurRadius = shadowItem->mRadius; nsMargin blurMargin = - nsContextBoxBlur::GetBlurRadiusMargin(blurRadius, twipsPerPixel); + nsContextBoxBlur::GetBlurRadiusMargin(blurRadius, oneDevPixel); nsRect shadowPaintRect = paddingRect; shadowPaintRect.Inflate(blurMargin); // Round the spread radius to device pixels (by truncation). // This mostly matches what we do for borders, except that we don't round // up values between zero and one device pixels to one device pixel. // This way of rounding is symmetric around zero, which makes sense for // the spread radius. - int32_t spreadDistance = shadowItem->mSpread / twipsPerPixel; + int32_t spreadDistance = shadowItem->mSpread / oneDevPixel; nscoord spreadDistanceAppUnits = aPresContext->DevPixelsToAppUnits(spreadDistance); nsRect shadowClipRect = paddingRect; shadowClipRect.MoveBy(shadowItem->mXOffset, shadowItem->mYOffset); shadowClipRect.Deflate(spreadDistanceAppUnits, spreadDistanceAppUnits); - Rect shadowClipGfxRect = NSRectToRect(shadowClipRect, twipsPerPixel); + Rect shadowClipGfxRect = NSRectToRect(shadowClipRect, oneDevPixel); shadowClipGfxRect.Round(); RectCornerRadii clipRectRadii; if (hasBorderRadius) { // Calculate the radii the inner clipping rect will have Float borderSizes[4] = {0, 0, 0, 0}; // See PaintBoxShadowOuter and bug 514670 @@ -1816,57 +1816,57 @@ nsCSSRendering::PaintBoxShadowInner(nsPr nsCSSBorderRenderer::ComputeInnerRadii(innerRadii, borderSizes, &clipRectRadii); } // Set the "skip rect" to the area within the frame that we don't paint in, // including after blurring. nsRect skipRect = shadowClipRect; skipRect.Deflate(blurMargin); - gfxRect skipGfxRect = nsLayoutUtils::RectToGfxRect(skipRect, twipsPerPixel); + gfxRect skipGfxRect = nsLayoutUtils::RectToGfxRect(skipRect, oneDevPixel); if (hasBorderRadius) { skipGfxRect.Deflate(gfxMargin( std::max(clipRectRadii[C_TL].height, clipRectRadii[C_TR].height), 0, std::max(clipRectRadii[C_BL].height, clipRectRadii[C_BR].height), 0)); } // When there's a blur radius, gfxAlphaBoxBlur leaves the skiprect area // unchanged. And by construction the gfxSkipRect is not touched by the // rendered shadow (even after blurring), so those pixels must be completely // transparent in the shadow, so drawing them changes nothing. DrawTarget* drawTarget = aRenderingContext.GetDrawTarget(); // Clip the context to the area of the frame's padding rect, so no part of the // shadow is painted outside. Also cut out anything beyond where the inset shadow // will be. - Rect shadowGfxRect = NSRectToRect(paddingRect, twipsPerPixel); + Rect shadowGfxRect = NSRectToRect(paddingRect, oneDevPixel); shadowGfxRect.Round(); Color shadowColor = GetShadowColor(shadowItem, aForFrame, 1.0); aRenderingContext.Save(); // This clips the outside border radius. // clipRectRadii is the border radius inside the inset shadow. if (hasBorderRadius) { RefPtr<Path> roundedRect = MakePathForRoundedRect(*drawTarget, shadowGfxRect, innerRadii); aRenderingContext.Clip(roundedRect); } else { aRenderingContext.Clip(shadowGfxRect); } nsContextBoxBlur insetBoxBlur; - gfxRect destRect = nsLayoutUtils::RectToGfxRect(shadowPaintRect, twipsPerPixel); - Point shadowOffset(shadowItem->mXOffset / twipsPerPixel, - shadowItem->mYOffset / twipsPerPixel); + gfxRect destRect = nsLayoutUtils::RectToGfxRect(shadowPaintRect, oneDevPixel); + Point shadowOffset(shadowItem->mXOffset / oneDevPixel, + shadowItem->mYOffset / oneDevPixel); insetBoxBlur.InsetBoxBlur(&aRenderingContext, ToRect(destRect), shadowClipGfxRect, shadowColor, blurRadius, spreadDistanceAppUnits, - twipsPerPixel, hasBorderRadius, + oneDevPixel, hasBorderRadius, clipRectRadii, ToRect(skipGfxRect), shadowOffset); aRenderingContext.Restore(); } } /* static */ nsCSSRendering::PaintBGParams @@ -3295,36 +3295,37 @@ nsCSSRendering::GetBackgroundLayerRect(n } // Begin table border-collapsing section // These functions were written to not disrupt the normal ones and yet satisfy some additional requirements // At some point, all functions should be unified to include the additional functionality that these provide static nscoord RoundIntToPixel(nscoord aValue, - nscoord aTwipsPerPixel, + nscoord aOneDevPixel, bool aRoundDown = false) { - if (aTwipsPerPixel <= 0) - // We must be rendering to a device that has a resolution greater than Twips! + if (aOneDevPixel <= 0) + // We must be rendering to a device that has a resolution greater than + // one device pixel! // In that case, aValue is as accurate as it's going to get. return aValue; - nscoord halfPixel = NSToCoordRound(aTwipsPerPixel / 2.0f); - nscoord extra = aValue % aTwipsPerPixel; - nscoord finalValue = (!aRoundDown && (extra >= halfPixel)) ? aValue + (aTwipsPerPixel - extra) : aValue - extra; + nscoord halfPixel = NSToCoordRound(aOneDevPixel / 2.0f); + nscoord extra = aValue % aOneDevPixel; + nscoord finalValue = (!aRoundDown && (extra >= halfPixel)) ? aValue + (aOneDevPixel - extra) : aValue - extra; return finalValue; } static nscoord RoundFloatToPixel(float aValue, - nscoord aTwipsPerPixel, + nscoord aOneDevPixel, bool aRoundDown = false) { - return RoundIntToPixel(NSToCoordRound(aValue), aTwipsPerPixel, aRoundDown); + return RoundIntToPixel(NSToCoordRound(aValue), aOneDevPixel, aRoundDown); } static void SetPoly(const Rect& aRect, Point* poly) { poly[0].x = aRect.x; poly[0].y = aRect.y; poly[1].x = aRect.x + aRect.width; poly[1].y = aRect.y; @@ -3335,17 +3336,16 @@ static void SetPoly(const Rect& aRect, P } static void DrawDashedSegment(DrawTarget& aDrawTarget, nsRect aRect, nscoord aDashLength, nscolor aColor, int32_t aAppUnitsPerDevPixel, - nscoord aTwipsPerPixel, bool aHorizontal) { ColorPattern color(ToDeviceColor(aColor)); DrawOptions drawOptions(1.f, CompositionOp::OP_OVER, AntialiasMode::NONE); StrokeOptions strokeOptions; Float dash[2]; dash[0] = Float(aDashLength) / aAppUnitsPerDevPixel; @@ -3371,27 +3371,27 @@ DrawDashedSegment(DrawTarget& a } } static void DrawSolidBorderSegment(DrawTarget& aDrawTarget, nsRect aRect, nscolor aColor, int32_t aAppUnitsPerDevPixel, - nscoord aTwipsPerPixel, mozilla::Side aStartBevelSide = mozilla::eSideTop, nscoord aStartBevelOffset = 0, mozilla::Side aEndBevelSide = mozilla::eSideTop, nscoord aEndBevelOffset = 0) { ColorPattern color(ToDeviceColor(aColor)); DrawOptions drawOptions(1.f, CompositionOp::OP_OVER, AntialiasMode::NONE); + nscoord oneDevPixel = NSIntPixelsToAppUnits(1, aAppUnitsPerDevPixel); // We don't need to bevel single pixel borders - if ((aRect.width == aTwipsPerPixel) || (aRect.height == aTwipsPerPixel) || + if ((aRect.width == oneDevPixel) || (aRect.height == oneDevPixel) || ((0 == aStartBevelOffset) && (0 == aEndBevelOffset))) { // simple rectangle aDrawTarget.FillRect(NSRectToSnappedRect(aRect, aAppUnitsPerDevPixel, aDrawTarget), color, drawOptions); } else { // polygon with beveling @@ -3440,55 +3440,54 @@ DrawSolidBorderSegment(DrawTarget& RefPtr<Path> path = builder->Finish(); aDrawTarget.Fill(path, color, drawOptions); } } static void GetDashInfo(nscoord aBorderLength, nscoord aDashLength, - nscoord aTwipsPerPixel, + nscoord aOneDevPixel, int32_t& aNumDashSpaces, nscoord& aStartDashLength, nscoord& aEndDashLength) { aNumDashSpaces = 0; if (aStartDashLength + aDashLength + aEndDashLength >= aBorderLength) { aStartDashLength = aBorderLength; aEndDashLength = 0; } else { aNumDashSpaces = (aBorderLength - aDashLength)/ (2 * aDashLength); // round down nscoord extra = aBorderLength - aStartDashLength - aEndDashLength - (((2 * aNumDashSpaces) - 1) * aDashLength); if (extra > 0) { - nscoord half = RoundIntToPixel(extra / 2, aTwipsPerPixel); + nscoord half = RoundIntToPixel(extra / 2, aOneDevPixel); aStartDashLength += half; aEndDashLength += (extra - half); } } } void nsCSSRendering::DrawTableBorderSegment(DrawTarget& aDrawTarget, uint8_t aBorderStyle, nscolor aBorderColor, nscolor aBGColor, const nsRect& aBorder, int32_t aAppUnitsPerDevPixel, - int32_t aAppUnitsPerCSSPixel, mozilla::Side aStartBevelSide, nscoord aStartBevelOffset, mozilla::Side aEndBevelSide, nscoord aEndBevelOffset) { bool horizontal = ((eSideTop == aStartBevelSide) || (eSideBottom == aStartBevelSide)); - nscoord twipsPerPixel = NSIntPixelsToAppUnits(1, aAppUnitsPerCSSPixel); + nscoord oneDevPixel = NSIntPixelsToAppUnits(1, aAppUnitsPerDevPixel); uint8_t ridgeGroove = NS_STYLE_BORDER_STYLE_RIDGE; - if ((twipsPerPixel >= aBorder.width) || (twipsPerPixel >= aBorder.height) || + if ((oneDevPixel >= aBorder.width) || (oneDevPixel >= aBorder.height) || (NS_STYLE_BORDER_STYLE_DASHED == aBorderStyle) || (NS_STYLE_BORDER_STYLE_DOTTED == aBorderStyle)) { // no beveling for 1 pixel border, dash or dot aStartBevelOffset = 0; aEndBevelOffset = 0; } switch (aBorderStyle) { case NS_STYLE_BORDER_STYLE_NONE: @@ -3498,110 +3497,116 @@ nsCSSRendering::DrawTableBorderSegment(D case NS_STYLE_BORDER_STYLE_DOTTED: case NS_STYLE_BORDER_STYLE_DASHED: { nscoord dashLength = (NS_STYLE_BORDER_STYLE_DASHED == aBorderStyle) ? DASH_LENGTH : DOT_LENGTH; // make the dash length proportional to the border thickness dashLength *= (horizontal) ? aBorder.height : aBorder.width; // make the min dash length for the ends 1/2 the dash length nscoord minDashLength = (NS_STYLE_BORDER_STYLE_DASHED == aBorderStyle) - ? RoundFloatToPixel(((float)dashLength) / 2.0f, twipsPerPixel) : dashLength; - minDashLength = std::max(minDashLength, twipsPerPixel); + ? RoundFloatToPixel(((float)dashLength) / 2.0f, + aAppUnitsPerDevPixel) + : dashLength; + minDashLength = std::max(minDashLength, oneDevPixel); nscoord numDashSpaces = 0; nscoord startDashLength = minDashLength; nscoord endDashLength = minDashLength; if (horizontal) { - GetDashInfo(aBorder.width, dashLength, twipsPerPixel, numDashSpaces, - startDashLength, endDashLength); + GetDashInfo(aBorder.width, dashLength, aAppUnitsPerDevPixel, + numDashSpaces, startDashLength, endDashLength); nsRect rect(aBorder.x, aBorder.y, startDashLength, aBorder.height); DrawSolidBorderSegment(aDrawTarget, rect, aBorderColor, - aAppUnitsPerDevPixel, twipsPerPixel); + aAppUnitsPerDevPixel); rect.x += startDashLength + dashLength; rect.width = aBorder.width - (startDashLength + endDashLength + dashLength); DrawDashedSegment(aDrawTarget, rect, dashLength, aBorderColor, - aAppUnitsPerDevPixel, twipsPerPixel, horizontal); + aAppUnitsPerDevPixel, horizontal); rect.x += rect.width; rect.width = endDashLength; DrawSolidBorderSegment(aDrawTarget, rect, aBorderColor, - aAppUnitsPerDevPixel, twipsPerPixel); + aAppUnitsPerDevPixel); } else { - GetDashInfo(aBorder.height, dashLength, twipsPerPixel, numDashSpaces, - startDashLength, endDashLength); + GetDashInfo(aBorder.height, dashLength, aAppUnitsPerDevPixel, + numDashSpaces, startDashLength, endDashLength); nsRect rect(aBorder.x, aBorder.y, aBorder.width, startDashLength); DrawSolidBorderSegment(aDrawTarget, rect, aBorderColor, - aAppUnitsPerDevPixel, twipsPerPixel); + aAppUnitsPerDevPixel); rect.y += rect.height + dashLength; rect.height = aBorder.height - (startDashLength + endDashLength + dashLength); DrawDashedSegment(aDrawTarget, rect, dashLength, aBorderColor, - aAppUnitsPerDevPixel, twipsPerPixel, horizontal); + aAppUnitsPerDevPixel, horizontal); rect.y += rect.height; rect.height = endDashLength; DrawSolidBorderSegment(aDrawTarget, rect, aBorderColor, - aAppUnitsPerDevPixel, twipsPerPixel); + aAppUnitsPerDevPixel); } } break; case NS_STYLE_BORDER_STYLE_GROOVE: ridgeGroove = NS_STYLE_BORDER_STYLE_GROOVE; // and fall through to ridge MOZ_FALLTHROUGH; case NS_STYLE_BORDER_STYLE_RIDGE: - if ((horizontal && (twipsPerPixel >= aBorder.height)) || - (!horizontal && (twipsPerPixel >= aBorder.width))) { + if ((horizontal && (oneDevPixel >= aBorder.height)) || + (!horizontal && (oneDevPixel >= aBorder.width))) { // a one pixel border DrawSolidBorderSegment(aDrawTarget, aBorder, aBorderColor, - aAppUnitsPerDevPixel, twipsPerPixel, + aAppUnitsPerDevPixel, aStartBevelSide, aStartBevelOffset, aEndBevelSide, aEndBevelOffset); } else { nscoord startBevel = (aStartBevelOffset > 0) - ? RoundFloatToPixel(0.5f * (float)aStartBevelOffset, twipsPerPixel, true) : 0; + ? RoundFloatToPixel(0.5f * (float)aStartBevelOffset, + aAppUnitsPerDevPixel, true) : 0; nscoord endBevel = (aEndBevelOffset > 0) - ? RoundFloatToPixel(0.5f * (float)aEndBevelOffset, twipsPerPixel, true) : 0; + ? RoundFloatToPixel(0.5f * (float)aEndBevelOffset, + aAppUnitsPerDevPixel, true) : 0; mozilla::Side ridgeGrooveSide = (horizontal) ? eSideTop : eSideLeft; // FIXME: In theory, this should use the visited-dependent // background color, but I don't care. nscolor bevelColor = MakeBevelColor(ridgeGrooveSide, ridgeGroove, aBGColor, aBorderColor); nsRect rect(aBorder); nscoord half; if (horizontal) { // top, bottom - half = RoundFloatToPixel(0.5f * (float)aBorder.height, twipsPerPixel); + half = RoundFloatToPixel(0.5f * (float)aBorder.height, + aAppUnitsPerDevPixel); rect.height = half; if (eSideTop == aStartBevelSide) { rect.x += startBevel; rect.width -= startBevel; } if (eSideTop == aEndBevelSide) { rect.width -= endBevel; } DrawSolidBorderSegment(aDrawTarget, rect, bevelColor, - aAppUnitsPerDevPixel, twipsPerPixel, + aAppUnitsPerDevPixel, aStartBevelSide, startBevel, aEndBevelSide, endBevel); } else { // left, right - half = RoundFloatToPixel(0.5f * (float)aBorder.width, twipsPerPixel); + half = RoundFloatToPixel(0.5f * (float)aBorder.width, + aAppUnitsPerDevPixel); rect.width = half; if (eSideLeft == aStartBevelSide) { rect.y += startBevel; rect.height -= startBevel; } if (eSideLeft == aEndBevelSide) { rect.height -= endBevel; } DrawSolidBorderSegment(aDrawTarget, rect, bevelColor, - aAppUnitsPerDevPixel, twipsPerPixel, + aAppUnitsPerDevPixel, aStartBevelSide, startBevel, aEndBevelSide, endBevel); } rect = aBorder; ridgeGrooveSide = (eSideTop == ridgeGrooveSide) ? eSideBottom : eSideRight; // FIXME: In theory, this should use the visited-dependent // background color, but I don't care. @@ -3613,116 +3618,123 @@ nsCSSRendering::DrawTableBorderSegment(D if (eSideBottom == aStartBevelSide) { rect.x += startBevel; rect.width -= startBevel; } if (eSideBottom == aEndBevelSide) { rect.width -= endBevel; } DrawSolidBorderSegment(aDrawTarget, rect, bevelColor, - aAppUnitsPerDevPixel, twipsPerPixel, + aAppUnitsPerDevPixel, aStartBevelSide, startBevel, aEndBevelSide, endBevel); } else { rect.x = rect.x + half; rect.width = aBorder.width - half; if (eSideRight == aStartBevelSide) { rect.y += aStartBevelOffset - startBevel; rect.height -= startBevel; } if (eSideRight == aEndBevelSide) { rect.height -= endBevel; } DrawSolidBorderSegment(aDrawTarget, rect, bevelColor, - aAppUnitsPerDevPixel, twipsPerPixel, + aAppUnitsPerDevPixel, aStartBevelSide, startBevel, aEndBevelSide, endBevel); } } break; case NS_STYLE_BORDER_STYLE_DOUBLE: // We can only do "double" borders if the thickness of the border // is more than 2px. Otherwise, we fall through to painting a // solid border. - if ((aBorder.width > 2*twipsPerPixel || horizontal) && - (aBorder.height > 2*twipsPerPixel || !horizontal)) { + if ((aBorder.width > 2 * oneDevPixel || horizontal) && + (aBorder.height > 2 * oneDevPixel || !horizontal)) { nscoord startBevel = (aStartBevelOffset > 0) - ? RoundFloatToPixel(0.333333f * (float)aStartBevelOffset, twipsPerPixel) : 0; + ? RoundFloatToPixel(0.333333f * + (float)aStartBevelOffset, + aAppUnitsPerDevPixel) : 0; nscoord endBevel = (aEndBevelOffset > 0) - ? RoundFloatToPixel(0.333333f * (float)aEndBevelOffset, twipsPerPixel) : 0; + ? RoundFloatToPixel(0.333333f * + (float)aEndBevelOffset, + aAppUnitsPerDevPixel) : 0; if (horizontal) { // top, bottom - nscoord thirdHeight = RoundFloatToPixel(0.333333f * (float)aBorder.height, twipsPerPixel); + nscoord thirdHeight = RoundFloatToPixel(0.333333f * + (float)aBorder.height, + aAppUnitsPerDevPixel); // draw the top line or rect nsRect topRect(aBorder.x, aBorder.y, aBorder.width, thirdHeight); if (eSideTop == aStartBevelSide) { topRect.x += aStartBevelOffset - startBevel; topRect.width -= aStartBevelOffset - startBevel; } if (eSideTop == aEndBevelSide) { topRect.width -= aEndBevelOffset - endBevel; } DrawSolidBorderSegment(aDrawTarget, topRect, aBorderColor, - aAppUnitsPerDevPixel, twipsPerPixel, + aAppUnitsPerDevPixel, aStartBevelSide, startBevel, aEndBevelSide, endBevel); // draw the botom line or rect nscoord heightOffset = aBorder.height - thirdHeight; nsRect bottomRect(aBorder.x, aBorder.y + heightOffset, aBorder.width, aBorder.height - heightOffset); if (eSideBottom == aStartBevelSide) { bottomRect.x += aStartBevelOffset - startBevel; bottomRect.width -= aStartBevelOffset - startBevel; } if (eSideBottom == aEndBevelSide) { bottomRect.width -= aEndBevelOffset - endBevel; } DrawSolidBorderSegment(aDrawTarget, bottomRect, aBorderColor, - aAppUnitsPerDevPixel, twipsPerPixel, + aAppUnitsPerDevPixel, aStartBevelSide, startBevel, aEndBevelSide, endBevel); } else { // left, right - nscoord thirdWidth = RoundFloatToPixel(0.333333f * (float)aBorder.width, twipsPerPixel); + nscoord thirdWidth = RoundFloatToPixel(0.333333f * (float)aBorder.width, + aAppUnitsPerDevPixel); nsRect leftRect(aBorder.x, aBorder.y, thirdWidth, aBorder.height); if (eSideLeft == aStartBevelSide) { leftRect.y += aStartBevelOffset - startBevel; leftRect.height -= aStartBevelOffset - startBevel; } if (eSideLeft == aEndBevelSide) { leftRect.height -= aEndBevelOffset - endBevel; } DrawSolidBorderSegment(aDrawTarget, leftRect, aBorderColor, - aAppUnitsPerDevPixel, twipsPerPixel, + aAppUnitsPerDevPixel, aStartBevelSide, startBevel, aEndBevelSide, endBevel); nscoord widthOffset = aBorder.width - thirdWidth; nsRect rightRect(aBorder.x + widthOffset, aBorder.y, aBorder.width - widthOffset, aBorder.height); if (eSideRight == aStartBevelSide) { rightRect.y += aStartBevelOffset - startBevel; rightRect.height -= aStartBevelOffset - startBevel; } if (eSideRight == aEndBevelSide) { rightRect.height -= aEndBevelOffset - endBevel; } DrawSolidBorderSegment(aDrawTarget, rightRect, aBorderColor, - aAppUnitsPerDevPixel, twipsPerPixel, + aAppUnitsPerDevPixel, aStartBevelSide, startBevel, aEndBevelSide, endBevel); } break; } // else fall through to solid MOZ_FALLTHROUGH; case NS_STYLE_BORDER_STYLE_SOLID: DrawSolidBorderSegment(aDrawTarget, aBorder, aBorderColor, - aAppUnitsPerDevPixel, twipsPerPixel, aStartBevelSide, + aAppUnitsPerDevPixel, aStartBevelSide, aStartBevelOffset, aEndBevelSide, aEndBevelOffset); break; case NS_STYLE_BORDER_STYLE_OUTSET: case NS_STYLE_BORDER_STYLE_INSET: NS_ASSERTION(false, "inset, outset should have been converted to groove, ridge"); break; case NS_STYLE_BORDER_STYLE_AUTO: NS_ASSERTION(false, "Unexpected 'auto' table border");
--- a/layout/painting/nsCSSRendering.h +++ b/layout/painting/nsCSSRendering.h @@ -545,17 +545,16 @@ struct nsCSSRendering { // Draw a border segment in the table collapsing border model without // beveling corners static void DrawTableBorderSegment(DrawTarget& aDrawTarget, uint8_t aBorderStyle, nscolor aBorderColor, nscolor aBGColor, const nsRect& aBorderRect, int32_t aAppUnitsPerDevPixel, - int32_t aAppUnitsPerCSSPixel, mozilla::Side aStartBevelSide = mozilla::eSideTop, nscoord aStartBevelOffset = 0, mozilla::Side aEndBevelSide = mozilla::eSideTop, nscoord aEndBevelOffset = 0); // NOTE: pt, dirtyRect, lineSize, ascent, offset in the following // structs are non-rounded device pixels, not app units. struct DecorationRectParams
--- a/layout/tables/celldata.h +++ b/layout/tables/celldata.h @@ -139,16 +139,17 @@ enum BCBorderOwner eRowGroupOwner = 5, eAjaRowGroupOwner = 6, // row group above eRowOwner = 7, eAjaRowOwner = 8, // row above eCellOwner = 9, eAjaCellOwner = 10 // cell to the top or to the left }; +// BCPixelSize is in device pixels. typedef uint16_t BCPixelSize; // These are the max sizes that are stored. If they are exceeded, then the max is stored and // the actual value is computed when needed. #define MAX_BORDER_WIDTH nscoord((1u << (sizeof(BCPixelSize) * 8)) - 1) // The half of border on inline/block-axis start side static inline BCPixelSize
--- a/layout/tables/nsTableCellFrame.cpp +++ b/layout/tables/nsTableCellFrame.cpp @@ -1137,22 +1137,22 @@ nsBCTableCellFrame::GetFrameName(nsAStri { return MakeFrameName(NS_LITERAL_STRING("BCTableCell"), aResult); } #endif LogicalMargin nsBCTableCellFrame::GetBorderWidth(WritingMode aWM) const { - int32_t pixelsToTwips = nsPresContext::AppUnitsPerCSSPixel(); + int32_t d2a = PresContext()->AppUnitsPerDevPixel(); return LogicalMargin(aWM, - BC_BORDER_END_HALF_COORD(pixelsToTwips, mBStartBorder), - BC_BORDER_START_HALF_COORD(pixelsToTwips, mIEndBorder), - BC_BORDER_START_HALF_COORD(pixelsToTwips, mBEndBorder), - BC_BORDER_END_HALF_COORD(pixelsToTwips, mIStartBorder)); + BC_BORDER_END_HALF_COORD(d2a, mBStartBorder), + BC_BORDER_START_HALF_COORD(d2a, mIEndBorder), + BC_BORDER_START_HALF_COORD(d2a, mBEndBorder), + BC_BORDER_END_HALF_COORD(d2a, mIStartBorder)); } BCPixelSize nsBCTableCellFrame::GetBorderWidth(LogicalSide aSide) const { switch(aSide) { case eLogicalSideBStart: return BC_BORDER_END_HALF(mBStartBorder); @@ -1182,22 +1182,22 @@ nsBCTableCellFrame::SetBorderWidth(Logic mIStartBorder = aValue; } } /* virtual */ nsMargin nsBCTableCellFrame::GetBorderOverflow() { WritingMode wm = GetWritingMode(); - int32_t p2t = nsPresContext::AppUnitsPerCSSPixel(); + int32_t d2a = PresContext()->AppUnitsPerDevPixel(); LogicalMargin halfBorder(wm, - BC_BORDER_START_HALF_COORD(p2t, mBStartBorder), - BC_BORDER_END_HALF_COORD(p2t, mIEndBorder), - BC_BORDER_END_HALF_COORD(p2t, mBEndBorder), - BC_BORDER_START_HALF_COORD(p2t, mIStartBorder)); + BC_BORDER_START_HALF_COORD(d2a, mBStartBorder), + BC_BORDER_END_HALF_COORD(d2a, mIEndBorder), + BC_BORDER_END_HALF_COORD(d2a, mBEndBorder), + BC_BORDER_START_HALF_COORD(d2a, mIStartBorder)); return halfBorder.GetPhysicalMargin(wm); } DrawResult nsBCTableCellFrame::PaintBackground(gfxContext& aRenderingContext, const nsRect& aDirtyRect, nsPoint aPt, uint32_t aFlags)
--- a/layout/tables/nsTableColFrame.h +++ b/layout/tables/nsTableColFrame.h @@ -322,20 +322,20 @@ inline void nsTableColFrame::SetColIndex { mColIndex = aColIndex; } inline nscoord nsTableColFrame::GetContinuousBCBorderWidth(mozilla::WritingMode aWM, mozilla::LogicalMargin& aBorder) { - int32_t aPixelsToTwips = nsPresContext::AppUnitsPerCSSPixel(); - aBorder.BStart(aWM) = BC_BORDER_END_HALF_COORD(aPixelsToTwips, + int32_t d2a = PresContext()->AppUnitsPerDevPixel(); + aBorder.BStart(aWM) = BC_BORDER_END_HALF_COORD(d2a, mBStartContBorderWidth); - aBorder.IEnd(aWM) = BC_BORDER_START_HALF_COORD(aPixelsToTwips, + aBorder.IEnd(aWM) = BC_BORDER_START_HALF_COORD(d2a, mIEndContBorderWidth); - aBorder.BEnd(aWM) = BC_BORDER_START_HALF_COORD(aPixelsToTwips, + aBorder.BEnd(aWM) = BC_BORDER_START_HALF_COORD(d2a, mBEndContBorderWidth); - return BC_BORDER_END_HALF_COORD(aPixelsToTwips, mIEndContBorderWidth); + return BC_BORDER_END_HALF_COORD(d2a, mIEndContBorderWidth); } #endif
--- a/layout/tables/nsTableColGroupFrame.cpp +++ b/layout/tables/nsTableColGroupFrame.cpp @@ -439,23 +439,23 @@ void nsTableColGroupFrame::SetContinuous default: NS_ERROR("invalid side arg"); } } void nsTableColGroupFrame::GetContinuousBCBorderWidth(WritingMode aWM, LogicalMargin& aBorder) { - int32_t aPixelsToTwips = nsPresContext::AppUnitsPerCSSPixel(); + int32_t d2a = PresContext()->AppUnitsPerDevPixel(); nsTableColFrame* col = GetTableFrame()-> GetColFrame(mStartColIndex + mColCount - 1); col->GetContinuousBCBorderWidth(aWM, aBorder); - aBorder.BStart(aWM) = BC_BORDER_END_HALF_COORD(aPixelsToTwips, + aBorder.BStart(aWM) = BC_BORDER_END_HALF_COORD(d2a, mBStartContBorderWidth); - aBorder.BEnd(aWM) = BC_BORDER_START_HALF_COORD(aPixelsToTwips, + aBorder.BEnd(aWM) = BC_BORDER_START_HALF_COORD(d2a, mBEndContBorderWidth); } /* ----- global methods ----- */ nsTableColGroupFrame* NS_NewTableColGroupFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) {
--- a/layout/tables/nsTableFrame.cpp +++ b/layout/tables/nsTableFrame.cpp @@ -168,16 +168,19 @@ nsTableFrame::Init(nsIContent* aCo // Let the base class do its processing nsContainerFrame::Init(aContent, aParent, aPrevInFlow); // see if border collapse is on, if so set it const nsStyleTableBorder* tableStyle = StyleTableBorder(); bool borderCollapse = (NS_STYLE_BORDER_COLLAPSE == tableStyle->mBorderCollapse); SetBorderCollapse(borderCollapse); + if (borderCollapse) { + SetNeedToCalcHasBCBorders(true); + } if (!aPrevInFlow) { // If we're the first-in-flow, we manage the cell map & layout strategy that // get used by our continuation chain: mCellMap = new nsTableCellMap(*this, borderCollapse); if (IsAutoLayout()) { mTableLayoutStrategy = new BasicTableLayoutStrategy(this); } else { @@ -2917,44 +2920,43 @@ DivideBCBorderSize(BCPixelSize aPixelSi } LogicalMargin nsTableFrame::GetOuterBCBorder(const WritingMode aWM) const { if (NeedToCalcBCBorders()) { const_cast<nsTableFrame*>(this)->CalcBCBorders(); } - - int32_t p2t = nsPresContext::AppUnitsPerCSSPixel(); + int32_t d2a = PresContext()->AppUnitsPerDevPixel(); BCPropertyData* propData = GetBCProperty(); if (propData) { return LogicalMargin(aWM, - BC_BORDER_START_HALF_COORD(p2t, propData->mBStartBorderWidth), - BC_BORDER_END_HALF_COORD(p2t, propData->mIEndBorderWidth), - BC_BORDER_END_HALF_COORD(p2t, propData->mBEndBorderWidth), - BC_BORDER_START_HALF_COORD(p2t, propData->mIStartBorderWidth)); + BC_BORDER_START_HALF_COORD(d2a, propData->mBStartBorderWidth), + BC_BORDER_END_HALF_COORD(d2a, propData->mIEndBorderWidth), + BC_BORDER_END_HALF_COORD(d2a, propData->mBEndBorderWidth), + BC_BORDER_START_HALF_COORD(d2a, propData->mIStartBorderWidth)); } return LogicalMargin(aWM); } LogicalMargin nsTableFrame::GetIncludedOuterBCBorder(const WritingMode aWM) const { if (NeedToCalcBCBorders()) { const_cast<nsTableFrame*>(this)->CalcBCBorders(); } - int32_t p2t = nsPresContext::AppUnitsPerCSSPixel(); + int32_t d2a = PresContext()->AppUnitsPerDevPixel(); BCPropertyData* propData = GetBCProperty(); if (propData) { return LogicalMargin(aWM, - BC_BORDER_START_HALF_COORD(p2t, propData->mBStartBorderWidth), - BC_BORDER_END_HALF_COORD(p2t, propData->mIEndCellBorderWidth), - BC_BORDER_END_HALF_COORD(p2t, propData->mBEndBorderWidth), - BC_BORDER_START_HALF_COORD(p2t, propData->mIStartCellBorderWidth)); + BC_BORDER_START_HALF_COORD(d2a, propData->mBStartBorderWidth), + BC_BORDER_END_HALF_COORD(d2a, propData->mIEndCellBorderWidth), + BC_BORDER_END_HALF_COORD(d2a, propData->mBEndBorderWidth), + BC_BORDER_START_HALF_COORD(d2a, propData->mIStartCellBorderWidth)); } return LogicalMargin(aWM); } LogicalMargin nsTableFrame::GetExcludedOuterBCBorder(const WritingMode aWM) const { return GetOuterBCBorder(aWM) - GetIncludedOuterBCBorder(aWM); @@ -5048,17 +5050,17 @@ GetColorAndStyle(const nsIFrame* aFrame, (NS_STYLE_BORDER_STYLE_HIDDEN == *aStyle)) { return; } *aColor = aFrame->StyleContext()-> GetVisitedDependentColor(nsStyleBorder::BorderColorFieldFor(physicalSide)); if (aWidth) { nscoord width = styleData->GetComputedBorderWidth(physicalSide); - *aWidth = nsPresContext::AppUnitsToIntCSSPixels(width); + *aWidth = aFrame->PresContext()->AppUnitsToDevPixels(width); } } /** coerce the paint style as required by CSS2.1 * @param aFrame - query the info for this frame * @param aTableWM - the writing mode of the frame * @param aSide - the side of the frame * @param aStyle - the border style @@ -6816,37 +6818,41 @@ BCPaintBorderIterator::SetDamageArea(con nsSize containerSize = mTable->GetSize(); LogicalRect dirtyRect(mTableWM, aDirtyRect, containerSize); uint32_t startRowIndex, endRowIndex, startColIndex, endColIndex; startRowIndex = endRowIndex = startColIndex = endColIndex = 0; bool done = false; bool haveIntersect = false; // find startRowIndex, endRowIndex nscoord rowB = mInitialOffsetB; + nsPresContext* presContext = mTable->PresContext(); for (uint32_t rgIdx = 0; rgIdx < mRowGroups.Length() && !done; rgIdx++) { nsTableRowGroupFrame* rgFrame = mRowGroups[rgIdx]; for (nsTableRowFrame* rowFrame = rgFrame->GetFirstRow(); rowFrame; rowFrame = rowFrame->GetNextRow()) { // get the row rect relative to the table rather than the row group nscoord rowBSize = rowFrame->BSize(mTableWM); if (haveIntersect) { // conservatively estimate the half border widths outside the row - nscoord borderHalf = mTable->GetPrevInFlow() ? 0 : nsPresContext:: - CSSPixelsToAppUnits(rowFrame->GetBStartBCBorderWidth() + 1); + nscoord borderHalf = mTable->GetPrevInFlow() ? 0 : + presContext->DevPixelsToAppUnits( + rowFrame->GetBStartBCBorderWidth() + 1); + if (dirtyRect.BEnd(mTableWM) >= rowB - borderHalf) { nsTableRowFrame* fifRow = static_cast<nsTableRowFrame*>(rowFrame->FirstInFlow()); endRowIndex = fifRow->GetRowIndex(); } else done = true; } else { // conservatively estimate the half border widths outside the row - nscoord borderHalf = mTable->GetNextInFlow() ? 0 : nsPresContext:: - CSSPixelsToAppUnits(rowFrame->GetBEndBCBorderWidth() + 1); + nscoord borderHalf = mTable->GetNextInFlow() ? 0 : + presContext->DevPixelsToAppUnits( + rowFrame->GetBEndBCBorderWidth() + 1); if (rowB + rowBSize + borderHalf >= dirtyRect.BStart(mTableWM)) { mStartRg = rgFrame; mStartRow = rowFrame; nsTableRowFrame* fifRow = static_cast<nsTableRowFrame*>(rowFrame->FirstInFlow()); startRowIndex = endRowIndex = fifRow->GetRowIndex(); haveIntersect = true; } @@ -6880,27 +6886,27 @@ BCPaintBorderIterator::SetDamageArea(con int32_t colIdx; for (colIdx = 0; colIdx != mNumTableCols; colIdx++) { nsTableColFrame* colFrame = mTableFirstInFlow->GetColFrame(colIdx); if (!colFrame) ABORT1(false); // get the col rect relative to the table rather than the col group nscoord colISize = colFrame->ISize(mTableWM); if (haveIntersect) { // conservatively estimate the iStart half border width outside the col - nscoord iStartBorderHalf = nsPresContext:: - CSSPixelsToAppUnits(colFrame->GetIStartBorderWidth() + 1); + nscoord iStartBorderHalf = presContext->DevPixelsToAppUnits( + colFrame->GetIStartBorderWidth() + 1); if (dirtyRect.IEnd(mTableWM) >= x - iStartBorderHalf) { endColIndex = colIdx; } else break; } else { // conservatively estimate the iEnd half border width outside the col - nscoord iEndBorderHalf = nsPresContext:: - CSSPixelsToAppUnits(colFrame->GetIEndBorderWidth() + 1); + nscoord iEndBorderHalf = presContext->DevPixelsToAppUnits( + colFrame->GetIEndBorderWidth() + 1); if (x + colISize + iEndBorderHalf >= dirtyRect.IStart(mTableWM)) { startColIndex = endColIndex = colIdx; haveIntersect = true; } else { mInitialOffsetI += colISize; } } @@ -7129,17 +7135,18 @@ BCPaintBorderIterator::Next() * @param aCornerOwnerSide - which side owns the corner * @param aCornerSubWidth - how wide is the nonwinning side of the corner * @param aHorWidth - how wide is the horizontal edge of the corner * @param aIsStartOfSeg - does this corner start a new segment * @param aIsBevel - is this corner beveled * @return - offset in twips */ static nscoord -CalcVerCornerOffset(LogicalSide aCornerOwnerSide, +CalcVerCornerOffset(nsPresContext* aPresContext, + LogicalSide aCornerOwnerSide, BCPixelSize aCornerSubWidth, BCPixelSize aHorWidth, bool aIsStartOfSeg, bool aIsBevel) { nscoord offset = 0; // XXX These should be replaced with appropriate side-specific macros (which?) BCPixelSize smallHalf, largeHalf; @@ -7156,29 +7163,30 @@ CalcVerCornerOffset(LogicalSide aCornerO DivideBCBorderSize(aHorWidth, smallHalf, largeHalf); if (aIsBevel) { offset = (aIsStartOfSeg) ? -largeHalf : smallHalf; } else { offset = (aIsStartOfSeg) ? smallHalf : -largeHalf; } } - return nsPresContext::CSSPixelsToAppUnits(offset); + return aPresContext->DevPixelsToAppUnits(offset); } /** Compute the horizontal offset of a horizontal border segment * @param aCornerOwnerSide - which side owns the corner * @param aCornerSubWidth - how wide is the nonwinning side of the corner * @param aVerWidth - how wide is the vertical edge of the corner * @param aIsStartOfSeg - does this corner start a new segment * @param aIsBevel - is this corner beveled * @return - offset in twips */ static nscoord -CalcHorCornerOffset(LogicalSide aCornerOwnerSide, +CalcHorCornerOffset(nsPresContext* aPresContext, + LogicalSide aCornerOwnerSide, BCPixelSize aCornerSubWidth, BCPixelSize aVerWidth, bool aIsStartOfSeg, bool aIsBevel) { nscoord offset = 0; // XXX These should be replaced with appropriate side-specific macros (which?) BCPixelSize smallHalf, largeHalf; @@ -7195,17 +7203,17 @@ CalcHorCornerOffset(LogicalSide aCornerO DivideBCBorderSize(aVerWidth, smallHalf, largeHalf); if (aIsBevel) { offset = (aIsStartOfSeg) ? -largeHalf : smallHalf; } else { offset = (aIsStartOfSeg) ? smallHalf : -largeHalf; } } - return nsPresContext::CSSPixelsToAppUnits(offset); + return aPresContext->DevPixelsToAppUnits(offset); } BCBlockDirSeg::BCBlockDirSeg() { mCol = nullptr; mFirstCell = mLastCell = mAjaCell = nullptr; mOffsetI = mOffsetB = mLength = mWidth = mBStartBevelOffset = 0; mBStartBevelSide = eLogicalSideBStart; @@ -7229,22 +7237,24 @@ BCBlockDirSeg::Start(BCPaintBorderIterat LogicalSide ownerSide = eLogicalSideBStart; bool bevel = false; nscoord cornerSubWidth = (aIter.mBCData) ? aIter.mBCData->GetCorner(ownerSide, bevel) : 0; bool bStartBevel = (aBlockSegISize > 0) ? bevel : false; BCPixelSize maxInlineSegBSize = std::max(aIter.mPrevInlineSegBSize, aInlineSegBSize); - nscoord offset = CalcVerCornerOffset(ownerSide, cornerSubWidth, + nsPresContext* presContext = aIter.mTable->PresContext(); + nscoord offset = CalcVerCornerOffset(presContext, + ownerSide, cornerSubWidth, maxInlineSegBSize, true, bStartBevel); mBStartBevelOffset = bStartBevel ? - nsPresContext::CSSPixelsToAppUnits(maxInlineSegBSize): 0; + presContext->DevPixelsToAppUnits(maxInlineSegBSize): 0; // XXX this assumes that only corners where 2 segments join can be beveled mBStartBevelSide = (aInlineSegBSize > 0) ? eLogicalSideIEnd : eLogicalSideIStart; mOffsetB += offset; mLength = -offset; mWidth = aBlockSegISize; mOwner = aBorderOwner; mFirstCell = aIter.mCell; mFirstRowGroup = aIter.mRg; @@ -7291,17 +7301,18 @@ BCBlockDirSeg::GetBEndCorner(BCPaintBord LogicalSide ownerSide = eLogicalSideBStart; nscoord cornerSubWidth = 0; bool bevel = false; if (aIter.mBCData) { cornerSubWidth = aIter.mBCData->GetCorner(ownerSide, bevel); } mIsBEndBevel = (mWidth > 0) ? bevel : false; mBEndInlineSegBSize = std::max(aIter.mPrevInlineSegBSize, aInlineSegBSize); - mBEndOffset = CalcVerCornerOffset(ownerSide, cornerSubWidth, + mBEndOffset = CalcVerCornerOffset(aIter.mTable->PresContext(), + ownerSide, cornerSubWidth, mBEndInlineSegBSize, false, mIsBEndBevel); mLength += mBEndOffset; } Maybe<BCBorderParameters> BCBlockDirSeg::BuildBorderParameters(BCPaintBorderIterator& aIter, BCPixelSize aInlineSegBSize) @@ -7316,17 +7327,18 @@ BCBlockDirSeg::BuildBorderParameters(BCP nsTableCellFrame* cell = mFirstCell; // ??? nsIFrame* owner = nullptr; result.mBorderStyle = NS_STYLE_BORDER_STYLE_SOLID; result.mBorderColor = 0xFFFFFFFF; result.mBGColor = aIter.mTableBgColor; // All the tables frames have the same presContext, so we just use any one // that exists here: - result.mAppUnitsPerDevPixel = col->PresContext()->AppUnitsPerDevPixel(); + nsPresContext* presContext = aIter.mTable->PresContext(); + result.mAppUnitsPerDevPixel = presContext->AppUnitsPerDevPixel(); switch (mOwner) { case eTableOwner: owner = aIter.mTable; break; case eAjaColGroupOwner: side = eLogicalSideIEnd; if (!aIter.IsTableIEndMost() && (relColIndex > 0)) { @@ -7372,21 +7384,21 @@ BCBlockDirSeg::BuildBorderParameters(BCP break; } if (owner) { ::GetPaintStyleInfo(owner, aIter.mTableWM, side, &result.mBorderStyle, &result.mBorderColor); } BCPixelSize smallHalf, largeHalf; DivideBCBorderSize(mWidth, smallHalf, largeHalf); LogicalRect segRect(aIter.mTableWM, - mOffsetI - nsPresContext::CSSPixelsToAppUnits(largeHalf), + mOffsetI - presContext->DevPixelsToAppUnits(largeHalf), mOffsetB, - nsPresContext::CSSPixelsToAppUnits(mWidth), mLength); + presContext->DevPixelsToAppUnits(mWidth), mLength); nscoord bEndBevelOffset = (mIsBEndBevel) ? - nsPresContext::CSSPixelsToAppUnits(mBEndInlineSegBSize) : 0; + presContext->DevPixelsToAppUnits(mBEndInlineSegBSize) : 0; LogicalSide bEndBevelSide = (aInlineSegBSize > 0) ? eLogicalSideIEnd : eLogicalSideIStart; // Convert logical to physical sides/coordinates for DrawTableBorderSegment. result.mBorderRect = segRect.GetPhysicalRect(aIter.mTableWM, aIter.mTable->GetSize()); // XXX For reversed vertical writing-modes (with direction:rtl), we need to // invert physicalRect's y-position here, with respect to the table. @@ -7430,17 +7442,16 @@ BCBlockDirSeg::Paint(BCPaintBorderIterat Maybe<BCBorderParameters> param = BuildBorderParameters(aIter, aInlineSegBSize); if (param.isNothing()) { return; } nsCSSRendering::DrawTableBorderSegment(aDrawTarget, param->mBorderStyle, param->mBorderColor, param->mBGColor, param->mBorderRect, param->mAppUnitsPerDevPixel, - nsPresContext::AppUnitsPerCSSPixel(), param->mStartBevelSide, param->mStartBevelOffset, param->mEndBevelSide, param->mEndBevelOffset); } void BCBlockDirSeg::CreateWebRenderCommands(BCPaintBorderIterator& aIter, BCPixelSize aInlineSegBSize, wr::DisplayListBuilder& aBuilder, @@ -7525,17 +7536,18 @@ BCInlineDirSeg::Start(BCPaintBorderItera nscoord cornerSubWidth = (aIter.mBCData) ? aIter.mBCData->GetCorner(cornerOwnerSide, bevel) : 0; bool iStartBevel = (aInlineSegBSize > 0) ? bevel : false; int32_t relColIndex = aIter.GetRelativeColIndex(); nscoord maxBlockSegISize = std::max(aIter.mBlockDirInfo[relColIndex].mWidth, aBEndBlockSegISize); - nscoord offset = CalcHorCornerOffset(cornerOwnerSide, cornerSubWidth, + nscoord offset = CalcHorCornerOffset(aIter.mTable->PresContext(), + cornerOwnerSide, cornerSubWidth, maxBlockSegISize, true, iStartBevel); mIStartBevelOffset = (iStartBevel && (aInlineSegBSize > 0)) ? maxBlockSegISize : 0; // XXX this assumes that only corners where 2 segments join can be beveled mIStartBevelSide = (aBEndBlockSegISize > 0) ? eLogicalSideBEnd : eLogicalSideBStart; mOffsetI += offset; mLength = -offset; mWidth = aInlineSegBSize; mFirstCell = aIter.mCell; @@ -7559,21 +7571,22 @@ BCInlineDirSeg::GetIEndCorner(BCPaintBor if (aIter.mBCData) { cornerSubWidth = aIter.mBCData->GetCorner(ownerSide, bevel); } mIsIEndBevel = (mWidth > 0) ? bevel : 0; int32_t relColIndex = aIter.GetRelativeColIndex(); nscoord verWidth = std::max(aIter.mBlockDirInfo[relColIndex].mWidth, aIStartSegISize); - mEndOffset = CalcHorCornerOffset(ownerSide, cornerSubWidth, verWidth, - false, mIsIEndBevel); + nsPresContext* presContext = aIter.mTable->PresContext(); + mEndOffset = CalcHorCornerOffset(presContext, ownerSide, cornerSubWidth, + verWidth, false, mIsIEndBevel); mLength += mEndOffset; mIEndBevelOffset = (mIsIEndBevel) ? - nsPresContext::CSSPixelsToAppUnits(verWidth) : 0; + presContext->DevPixelsToAppUnits(verWidth) : 0; mIEndBevelSide = (aIStartSegISize > 0) ? eLogicalSideBEnd : eLogicalSideBStart; } Maybe<BCBorderParameters> BCInlineDirSeg::BuildBorderParameters(BCPaintBorderIterator& aIter) { BCBorderParameters result; @@ -7583,17 +7596,18 @@ BCInlineDirSeg::BuildBorderParameters(BC nsIFrame* rg = aIter.mRg; if (!rg) ABORT1(Nothing()); nsIFrame* row = aIter.mRow; if (!row) ABORT1(Nothing()); nsIFrame* cell = mFirstCell; nsIFrame* col; nsIFrame* owner = nullptr; // All the tables frames have the same presContext, so we just use any one // that exists here: - result.mAppUnitsPerDevPixel = row->PresContext()->AppUnitsPerDevPixel(); + nsPresContext* presContext = aIter.mTable->PresContext(); + result.mAppUnitsPerDevPixel = presContext->AppUnitsPerDevPixel(); result.mBorderStyle = NS_STYLE_BORDER_STYLE_SOLID; result.mBorderColor = 0xFFFFFFFF; result.mBGColor = aIter.mTableBgColor; switch (mOwner) { case eTableOwner: owner = aIter.mTable; @@ -7641,26 +7655,26 @@ BCInlineDirSeg::BuildBorderParameters(BC break; } if (owner) { ::GetPaintStyleInfo(owner, aIter.mTableWM, side, &result.mBorderStyle, &result.mBorderColor); } BCPixelSize smallHalf, largeHalf; DivideBCBorderSize(mWidth, smallHalf, largeHalf); LogicalRect segRect(aIter.mTableWM, mOffsetI, - mOffsetB - nsPresContext::CSSPixelsToAppUnits(largeHalf), + mOffsetB - presContext->DevPixelsToAppUnits(largeHalf), mLength, - nsPresContext::CSSPixelsToAppUnits(mWidth)); + presContext->DevPixelsToAppUnits(mWidth)); // Convert logical to physical sides/coordinates for DrawTableBorderSegment. result.mBorderRect = segRect.GetPhysicalRect(aIter.mTableWM, aIter.mTable->GetSize()); result.mStartBevelSide = aIter.mTableWM.PhysicalSide(mIStartBevelSide); result.mEndBevelSide = aIter.mTableWM.PhysicalSide(mIEndBevelSide); result.mStartBevelOffset = - nsPresContext::CSSPixelsToAppUnits(mIStartBevelOffset); + presContext->DevPixelsToAppUnits(mIStartBevelOffset); result.mEndBevelOffset = mIEndBevelOffset; // With inline-RTL directionality, the 'start' and 'end' of the inline-dir // border segment need to be swapped because DrawTableBorderSegment will // apply the 'start' bevel physically at the left or top edge, and 'end' at // the right or bottom. // (Note: startBevelSide/endBevelSide will be "top" or "bottom" in horizontal // writing mode, or "left" or "right" in vertical mode. // DrawTableBorderSegment works purely with physical coordinates, so it @@ -7688,17 +7702,16 @@ BCInlineDirSeg::Paint(BCPaintBorderItera Maybe<BCBorderParameters> param = BuildBorderParameters(aIter); if (param.isNothing()) { return; } nsCSSRendering::DrawTableBorderSegment(aDrawTarget, param->mBorderStyle, param->mBorderColor, param->mBGColor, param->mBorderRect, param->mAppUnitsPerDevPixel, - nsPresContext::AppUnitsPerCSSPixel(), param->mStartBevelSide, param->mStartBevelOffset, param->mEndBevelSide, param->mEndBevelOffset); } void BCInlineDirSeg::CreateWebRenderCommands(BCPaintBorderIterator& aIter, wr::DisplayListBuilder& aBuilder, const layers::StackingContextHelper& aSc,
--- a/layout/tables/nsTableFrame.h +++ b/layout/tables/nsTableFrame.h @@ -1023,18 +1023,18 @@ inline bool nsTableFrame::HasBCBorders() inline void nsTableFrame::SetHasBCBorders(bool aValue) { mBits.mHasBCBorders = (unsigned)aValue; } inline nscoord nsTableFrame::GetContinuousIStartBCBorderWidth() const { - int32_t aPixelsToTwips = nsPresContext::AppUnitsPerCSSPixel(); - return BC_BORDER_END_HALF_COORD(aPixelsToTwips, mBits.mIStartContBCBorder); + int32_t d2a = PresContext()->AppUnitsPerDevPixel(); + return BC_BORDER_END_HALF_COORD(d2a, mBits.mIStartContBCBorder); } inline void nsTableFrame::SetContinuousIStartBCBorderWidth(nscoord aValue) { mBits.mIStartContBCBorder = (unsigned) aValue; } #define ABORT0() \
--- a/layout/tables/nsTableRowFrame.h +++ b/layout/tables/nsTableRowFrame.h @@ -419,31 +419,32 @@ inline void nsTableRowFrame::SetHasUnpag } else { RemoveStateBits(NS_TABLE_ROW_HAS_UNPAGINATED_BSIZE); } } inline mozilla::LogicalMargin nsTableRowFrame::GetBCBorderWidth(mozilla::WritingMode aWM) { + nsPresContext* presContext = PresContext(); return mozilla::LogicalMargin( - aWM, nsPresContext::CSSPixelsToAppUnits(mBStartBorderWidth), 0, - nsPresContext::CSSPixelsToAppUnits(mBEndBorderWidth), 0); + aWM, presContext->DevPixelsToAppUnits(mBStartBorderWidth), 0, + presContext->DevPixelsToAppUnits(mBEndBorderWidth), 0); } inline void nsTableRowFrame::GetContinuousBCBorderWidth(mozilla::WritingMode aWM, mozilla::LogicalMargin& aBorder) { - int32_t aPixelsToTwips = nsPresContext::AppUnitsPerCSSPixel(); - aBorder.IEnd(aWM) = BC_BORDER_START_HALF_COORD(aPixelsToTwips, + int32_t d2a = PresContext()->AppUnitsPerDevPixel(); + aBorder.IEnd(aWM) = BC_BORDER_START_HALF_COORD(d2a, mIStartContBorderWidth); - aBorder.BStart(aWM) = BC_BORDER_END_HALF_COORD(aPixelsToTwips, + aBorder.BStart(aWM) = BC_BORDER_END_HALF_COORD(d2a, mBStartContBorderWidth); - aBorder.IStart(aWM) = BC_BORDER_END_HALF_COORD(aPixelsToTwips, + aBorder.IStart(aWM) = BC_BORDER_END_HALF_COORD(d2a, mIEndContBorderWidth); } inline nscoord nsTableRowFrame::GetOuterBStartContBCBorderWidth() { int32_t aPixelsToTwips = nsPresContext::AppUnitsPerCSSPixel(); return BC_BORDER_START_HALF_COORD(aPixelsToTwips, mBStartContBorderWidth); }
--- a/layout/tables/nsTableRowGroupFrame.cpp +++ b/layout/tables/nsTableRowGroupFrame.cpp @@ -1679,20 +1679,20 @@ nsTableRowGroupFrame::GetBCBorderWidth(W nsTableRowFrame* lastRowFrame = nullptr; for (nsTableRowFrame* rowFrame = GetFirstRow(); rowFrame; rowFrame = rowFrame->GetNextRow()) { if (!firstRowFrame) { firstRowFrame = rowFrame; } lastRowFrame = rowFrame; } if (firstRowFrame) { - border.BStart(aWM) = nsPresContext:: - CSSPixelsToAppUnits(firstRowFrame->GetBStartBCBorderWidth()); - border.BEnd(aWM) = nsPresContext:: - CSSPixelsToAppUnits(lastRowFrame->GetBEndBCBorderWidth()); + border.BStart(aWM) = PresContext()->DevPixelsToAppUnits( + firstRowFrame->GetBStartBCBorderWidth()); + border.BEnd(aWM) = PresContext()->DevPixelsToAppUnits( + lastRowFrame->GetBEndBCBorderWidth()); } return border; } void nsTableRowGroupFrame::SetContinuousBCBorderWidth(LogicalSide aForSide, BCPixelSize aPixelValue) { switch (aForSide) {
--- a/layout/tables/nsTableRowGroupFrame.h +++ b/layout/tables/nsTableRowGroupFrame.h @@ -445,17 +445,17 @@ inline void nsTableRowGroupFrame::SetHas RemoveStateBits(NS_ROWGROUP_HAS_STYLE_BSIZE); } } inline void nsTableRowGroupFrame::GetContinuousBCBorderWidth(mozilla::WritingMode aWM, mozilla::LogicalMargin& aBorder) { - int32_t aPixelsToTwips = nsPresContext::AppUnitsPerCSSPixel(); - aBorder.IEnd(aWM) = BC_BORDER_START_HALF_COORD(aPixelsToTwips, + int32_t d2a = PresContext()->AppUnitsPerDevPixel(); + aBorder.IEnd(aWM) = BC_BORDER_START_HALF_COORD(d2a, mIEndContBorderWidth); - aBorder.BEnd(aWM) = BC_BORDER_START_HALF_COORD(aPixelsToTwips, + aBorder.BEnd(aWM) = BC_BORDER_START_HALF_COORD(d2a, mBEndContBorderWidth); - aBorder.IStart(aWM) = BC_BORDER_END_HALF_COORD(aPixelsToTwips, + aBorder.IStart(aWM) = BC_BORDER_END_HALF_COORD(d2a, mIStartContBorderWidth); } #endif
--- a/media/webrtc/signaling/gtest/mediaconduit_unittests.cpp +++ b/media/webrtc/signaling/gtest/mediaconduit_unittests.cpp @@ -536,168 +536,16 @@ class TransportConduitTest : public ::te cerr << " *************************************************" << endl; cerr << " 3. Null Codec Parameter " << endl; cerr << " *************************************************" << endl; err = videoSession->ConfigureSendMediaCodec(nullptr); EXPECT_TRUE(err != mozilla::kMediaConduitNoError); } - void DumpMaxFs(int orig_width, int orig_height, int max_fs, - int new_width, int new_height) - { - cerr << "Applying max_fs=" << max_fs << " to input resolution " << - orig_width << "x" << orig_height << endl; - cerr << "New resolution: " << new_width << "x" << new_height << endl; - cerr << endl; - } - - // Calculate new resolution for sending video by applying max-fs constraint. - void GetVideoResolutionWithMaxFs(unsigned short orig_width, - unsigned short orig_height, - int max_fs, - unsigned short &new_width, - unsigned short &new_height) - { - int err = 0; - - // Get pointer to VideoSessionConduit. - mVideoSession = VideoSessionConduit::Create(WebRtcCallWrapper::Create()); - if( !mVideoSession ) { - ASSERT_NE(mVideoSession, (void*)nullptr); - } - - std::vector<unsigned int> ssrcs = {SSRC}; - mVideoSession->SetLocalSSRCs(ssrcs); - - mozilla::EncodingConstraints constraints; - constraints.maxFs = max_fs; - // Configure send codecs on the conduit. - mozilla::VideoCodecConfig cinst1(120, "VP8", constraints); - VideoCodecConfig::SimulcastEncoding encoding; - cinst1.mSimulcastEncodings.push_back(encoding); - - err = mVideoSession->ConfigureSendMediaCodec(&cinst1); - ASSERT_EQ(mozilla::kMediaConduitNoError, err); - err = mVideoSession->StartTransmitting(); - ASSERT_EQ(mozilla::kMediaConduitNoError, err); - - // Send one frame. - MOZ_ASSERT(!(orig_width & 1)); - MOZ_ASSERT(!(orig_height & 1)); - - // Get the new resolution as adjusted by the max-fs constraint. - mVideoSession->SetSendingWidthAndHeight(orig_width, orig_height, - new_width, new_height); - } - - void TestVideoConduitMaxFs() - { - unsigned short orig_width, orig_height, width, height; - int max_fs; - - // No limitation. - cerr << "Test no max-fs limition" << endl; - orig_width = 640; - orig_height = 480; - max_fs = 0; - GetVideoResolutionWithMaxFs(orig_width, orig_height, max_fs, width, height); - DumpMaxFs(orig_width, orig_height, max_fs, width, height); - ASSERT_EQ(width, 640); - ASSERT_EQ(height, 480); - - // VGA to QVGA. - cerr << "Test resizing from VGA to QVGA" << endl; - orig_width = 640; - orig_height = 480; - max_fs = 300; - GetVideoResolutionWithMaxFs(orig_width, orig_height, max_fs, width, height); - DumpMaxFs(orig_width, orig_height, max_fs, width, height); - ASSERT_EQ(width, 320); - ASSERT_EQ(height, 240); - - // Extreme input resolution. - cerr << "Test extreme input resolution" << endl; - orig_width = 3072; - orig_height = 100; - max_fs = 300; - GetVideoResolutionWithMaxFs(orig_width, orig_height, max_fs, width, height); - DumpMaxFs(orig_width, orig_height, max_fs, width, height); - ASSERT_EQ(width, 768); - ASSERT_EQ(height, 25); - - // Small max-fs. - cerr << "Test small max-fs (case 1)" << endl; - orig_width = 8; - orig_height = 32; - max_fs = 1; - GetVideoResolutionWithMaxFs(orig_width, orig_height, max_fs, width, height); - DumpMaxFs(orig_width, orig_height, max_fs, width, height); - ASSERT_EQ(width, 4); - ASSERT_EQ(height, 16); - - // Small max-fs. - cerr << "Test small max-fs (case 2)" << endl; - orig_width = 4; - orig_height = 50; - max_fs = 1; - GetVideoResolutionWithMaxFs(orig_width, orig_height, max_fs, width, height); - DumpMaxFs(orig_width, orig_height, max_fs, width, height); - ASSERT_EQ(width, 1); - ASSERT_EQ(height, 16); - - // Small max-fs. - cerr << "Test small max-fs (case 3)" << endl; - orig_width = 872; - orig_height = 136; - max_fs = 3; - GetVideoResolutionWithMaxFs(orig_width, orig_height, max_fs, width, height); - DumpMaxFs(orig_width, orig_height, max_fs, width, height); - ASSERT_EQ(width, 48); - ASSERT_EQ(height, 7); - - // Small max-fs. - cerr << "Test small max-fs (case 4)" << endl; - orig_width = 160; - orig_height = 8; - max_fs = 5; - GetVideoResolutionWithMaxFs(orig_width, orig_height, max_fs, width, height); - DumpMaxFs(orig_width, orig_height, max_fs, width, height); - ASSERT_EQ(width, 80); - ASSERT_EQ(height, 4); - - // Extremely small width and height(see bug 919979). - cerr << "Test with extremely small width and height" << endl; - orig_width = 2; - orig_height = 2; - max_fs = 5; - GetVideoResolutionWithMaxFs(orig_width, orig_height, max_fs, width, height); - DumpMaxFs(orig_width, orig_height, max_fs, width, height); - ASSERT_EQ(width, 2); - ASSERT_EQ(height, 2); - - // Random values. - cerr << "Test with random values" << endl; - for (int i = 0; i < 30; i++) { - cerr << "."; - max_fs = rand() % 1000; - orig_width = ((rand() % 2000) & ~1) + 2; - orig_height = ((rand() % 2000) & ~1) + 2; - - GetVideoResolutionWithMaxFs(orig_width, orig_height, max_fs, - width, height); - if (max_fs > 0 && - ceil(width / 16.) * ceil(height / 16.) > max_fs) { - DumpMaxFs(orig_width, orig_height, max_fs, width, height); - ADD_FAILURE(); - } - } - cerr << endl; - } - private: //Audio Conduit Test Objects RefPtr<mozilla::AudioSessionConduit> mAudioSession; RefPtr<mozilla::AudioSessionConduit> mAudioSession2; RefPtr<mozilla::TransportInterface> mAudioTransport; AudioSendAndReceive audioTester; //Video Conduit Test Objects @@ -715,15 +563,11 @@ class TransportConduitTest : public ::te // Disabled, see Bug 1319121 TEST_F(TransportConduitTest, DISABLED_TestDummyAudioWithTransport) { TestDummyAudioAndTransport(); } TEST_F(TransportConduitTest, TestVideoConduitCodecAPI) { TestVideoConduitCodecAPI(); - } - -TEST_F(TransportConduitTest, TestVideoConduitMaxFs) { - TestVideoConduitMaxFs(); - } +} } // end namespace
--- a/media/webrtc/signaling/src/media-conduit/MediaConduitInterface.h +++ b/media/webrtc/signaling/src/media-conduit/MediaConduitInterface.h @@ -389,25 +389,16 @@ public: * @param sendSessionConfig: CodecConfiguration * NOTE: This API can be invoked multiple time. Invoking this API may involve restarting * reception sub-system on the engine * */ virtual MediaConduitErrorCode ConfigureRecvMediaCodecs( const std::vector<VideoCodecConfig* >& recvCodecConfigList) = 0; - /** - * This method allows unit tests to double-check that the - * max-fs and max-fr related settings are as expected. - */ - virtual void SetSendingWidthAndHeight(unsigned short frame_width, - unsigned short frame_height, - unsigned short &result_width, - unsigned short &result_height) = 0; - virtual unsigned int SendingMaxFs() = 0; virtual unsigned int SendingMaxFr() = 0; /** * These methods allow unit tests to double-check that the * rtcp-fb settings are as expected. */
--- a/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp +++ b/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp @@ -1686,60 +1686,28 @@ WebrtcVideoConduit::SelectSendResolution uint16_t max_width = mCurSendCodecConfig->mEncodingConstraints.maxWidth; uint16_t max_height = mCurSendCodecConfig->mEncodingConstraints.maxHeight; if (max_width || max_height) { max_width = max_width ? max_width : UINT16_MAX; max_height = max_height ? max_height : UINT16_MAX; ConstrainPreservingAspectRatio(max_width, max_height, &width, &height); } - // Limit resolution to max-fs while keeping same aspect ratio as the - // incoming image. + // Limit resolution to max-fs if (mCurSendCodecConfig->mEncodingConstraints.maxFs) { - uint32_t max_fs = mCurSendCodecConfig->mEncodingConstraints.maxFs; - unsigned int cur_fs, mb_width, mb_height, mb_max; - - // Could we make this simpler by picking the larger of width and height, - // calculating a max for just that value based on the scale parameter, - // and then let ConstrainPreservingAspectRatio do the rest? - mb_width = (width + 15) >> 4; - mb_height = (height + 15) >> 4; - - cur_fs = mb_width * mb_height; - - // Limit resolution to max_fs, but don't scale up. - if (cur_fs > max_fs) { - double scale_ratio; - - scale_ratio = sqrt((double)max_fs / (double)cur_fs); - - mb_width = mb_width * scale_ratio; - mb_height = mb_height * scale_ratio; - - // Adjust mb_width and mb_height if they were truncated to zero. - if (mb_width == 0) { - mb_width = 1; - mb_height = std::min(mb_height, max_fs); - } - if (mb_height == 0) { - mb_height = 1; - mb_width = std::min(mb_width, max_fs); - } + // max-fs is in macroblocks, convert to pixels + int max_fs(mCurSendCodecConfig->mEncodingConstraints.maxFs*(16*16)); + if (max_fs > mLastSinkWanted.max_pixel_count.value_or(max_fs)) { + max_fs = mLastSinkWanted.max_pixel_count.value_or(max_fs); } - - // Limit width/height seperately to limit effect of extreme aspect ratios. - mb_max = (unsigned)sqrt(8 * (double)max_fs); - - max_width = 16 * std::min(mb_width, mb_max); - max_height = 16 * std::min(mb_height, mb_max); - ConstrainPreservingAspectRatio(max_width, max_height, &width, &height); + mVideoAdapter.OnResolutionRequest(rtc::Optional<int>(max_fs), + rtc::Optional<int>()); } } - // Adapt to getUserMedia resolution changes // check if we need to reconfigure the sending resolution. // NOTE: mSendingWidth != mLastWidth, because of maxwidth/height/etc above bool changed = false; if (mSendingWidth != width || mSendingHeight != height) { CSFLogDebug(logTag, "%s: resolution changing to %ux%u (from %ux%u)", __FUNCTION__, width, height, mSendingWidth, mSendingHeight); // This will avoid us continually retrying this operation if it fails. @@ -1929,18 +1897,33 @@ WebrtcVideoConduit::RemoveSink( OnSinkWantsChanged(mVideoBroadcaster.wants()); } void WebrtcVideoConduit::OnSinkWantsChanged( const rtc::VideoSinkWants& wants) { NS_ASSERTION(NS_IsMainThread(), "Only call on main thread"); if (!mLockScaling) { - mVideoAdapter.OnResolutionRequest(wants.max_pixel_count, - wants.max_pixel_count_step_up); + mLastSinkWanted = wants; + + // limit sink wants based upon max-fs constraint + int max_fs = mCurSendCodecConfig->mEncodingConstraints.maxFs*(16*16); + rtc::Optional<int> max_pixel_count = wants.max_pixel_count; + rtc::Optional<int> max_pixel_count_step_up = wants.max_pixel_count_step_up; + + if (max_pixel_count.value_or(max_fs) > max_fs) { + max_pixel_count = rtc::Optional<int>(max_fs); + } + + if (max_pixel_count_step_up.value_or(max_fs) > max_fs) { + max_pixel_count_step_up = rtc::Optional<int>(max_fs); + } + + mVideoAdapter.OnResolutionRequest(max_pixel_count, + max_pixel_count_step_up); } } MediaConduitErrorCode WebrtcVideoConduit::SendVideoFrame(webrtc::VideoFrame& frame) { // XXX Google uses a "timestamp_aligner" to translate timestamps from the // camera via TranslateTimestamp(); we should look at doing the same. This @@ -2412,30 +2395,16 @@ WebrtcVideoConduit::CodecPluginID() } if (mRecvCodecPlugin) { return mRecvCodecPlugin->PluginID(); } return 0; } -void -WebrtcVideoConduit::SetSendingWidthAndHeight(unsigned short frame_width, - unsigned short frame_height, - unsigned short &result_width, - unsigned short &result_height) -{ - MutexAutoLock lock(mCodecMutex); - result_width = 0; - result_height = 0; - (void)SelectSendResolution(frame_width, frame_height, nullptr); - result_width = mSendingWidth; - result_height = mSendingHeight; -} - bool WebrtcVideoConduit::RequiresNewSendStream(const VideoCodecConfig& newConfig) const { return !mCurSendCodecConfig || mCurSendCodecConfig->mName != newConfig.mName || mCurSendCodecConfig->mType != newConfig.mType || mCurSendCodecConfig->RtcpFbNackIsSet("") != newConfig.RtcpFbNackIsSet("") || mCurSendCodecConfig->RtcpFbFECIsSet() != newConfig.RtcpFbFECIsSet()
--- a/media/webrtc/signaling/src/media-conduit/VideoConduit.h +++ b/media/webrtc/signaling/src/media-conduit/VideoConduit.h @@ -251,25 +251,16 @@ public: void OnSinkWantsChanged(const rtc::VideoSinkWants& wants); virtual uint64_t CodecPluginID() override; virtual void SetPCHandle(const std::string& aPCHandle) override { mPCHandle = aPCHandle; } - /** - * This method allows unit tests to double-check that the - * max-fs and max-fr related settings are as expected. - */ - virtual void SetSendingWidthAndHeight(unsigned short frame_width, - unsigned short frame_height, - unsigned short &result_width, - unsigned short &result_height) override; - unsigned int SendingMaxFs() override { if(mCurSendCodecConfig) { return mCurSendCodecConfig->mEncodingConstraints.maxFs; } return 0; } unsigned int SendingMaxFr() override { @@ -544,16 +535,18 @@ private: int mPrefMaxBitrate; int mNegotiatedMaxBitrate; int mMinBitrateEstimate; bool mDenoising; bool mLockScaling; // for tests that care about output resolution uint8_t mSpatialLayers; uint8_t mTemporalLayers; + rtc::VideoSinkWants mLastSinkWanted; + static const unsigned int sAlphaNum = 7; static const unsigned int sAlphaDen = 8; static const unsigned int sRoundingPadding = 1024; RefPtr<WebrtcAudioConduit> mSyncedTo; webrtc::VideoCodecMode mCodecMode;
--- a/mobile/android/chrome/geckoview/geckoview.js +++ b/mobile/android/chrome/geckoview/geckoview.js @@ -57,9 +57,11 @@ function startup() { ModuleManager.add("resource://gre/modules/GeckoViewSettings.jsm", "GeckoViewSettings"); ModuleManager.add("resource://gre/modules/GeckoViewContent.jsm", "GeckoViewContent"); ModuleManager.add("resource://gre/modules/GeckoViewProgress.jsm", "GeckoViewProgress"); ModuleManager.add("resource://gre/modules/GeckoViewScroll.jsm", "GeckoViewScroll"); + ModuleManager.add("resource://gre/modules/GeckoViewTab.jsm", + "GeckoViewTab"); }
new file mode 100644 --- /dev/null +++ b/mobile/android/modules/geckoview/GeckoViewTab.jsm @@ -0,0 +1,48 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +this.EXPORTED_SYMBOLS = ["GeckoViewTab"]; + +const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; + +Cu.import("resource://gre/modules/GeckoViewModule.jsm"); +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); + +XPCOMUtils.defineLazyGetter(this, "dump", () => + Cu.import("resource://gre/modules/AndroidLog.jsm", + {}).AndroidLog.d.bind(null, "ViewTab")); + +function debug(aMsg) { + // dump(aMsg); +} + +// Stub BrowserApp implementation for WebExtensions support. +class GeckoViewTab extends GeckoViewModule { + init() { + this.browser.tab = { id: 0 }; + + this.window.BrowserApp = { + tabs: [this.browser.tab], + selectedTab: this.browser.tab, + + getTabForId: function(aId) { + return this.selectedTab; + }, + + getTabForBrowser: function(aBrowser) { + return this.selectedTab; + }, + + getTabForWindow: function(aWindow) { + return this.selectedTab; + }, + + getTabForDocument: function(aDocument) { + return this.selectedTab; + }, + }; + } +}
--- a/mobile/android/modules/geckoview/moz.build +++ b/mobile/android/modules/geckoview/moz.build @@ -8,10 +8,11 @@ EXTRA_JS_MODULES += [ 'AndroidLog.jsm', 'GeckoViewContent.jsm', 'GeckoViewContentModule.jsm', 'GeckoViewModule.jsm', 'GeckoViewNavigation.jsm', 'GeckoViewProgress.jsm', 'GeckoViewScroll.jsm', 'GeckoViewSettings.jsm', + 'GeckoViewTab.jsm', 'Messaging.jsm', ]
--- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -5825,23 +5825,22 @@ pref("security.mixed_content.hsts_primin pref("security.data_uri.unique_opaque_origin", true); // TODO: Bug 1380959: Block toplevel data: URI navigations // If true, all toplevel data: URI navigations will be blocked. // Please note that manually entering a data: URI in the // URL-Bar will not be blocked when flipping this pref. pref("security.data_uri.block_toplevel_data_uri_navigations", false); -// Disable Storage api in release builds. -#if defined(NIGHTLY_BUILD) && !defined(MOZ_WIDGET_ANDROID) +// Enable Storage API for all platforms except Android. +#if !defined(MOZ_WIDGET_ANDROID) pref("dom.storageManager.enabled", true); #else pref("dom.storageManager.enabled", false); #endif - pref("dom.storageManager.prompt.testing", false); pref("dom.storageManager.prompt.testing.allow", false); // Enable the Storage management in about:preferences and persistent-storage permission request // To enable the DOM implementation, turn on "dom.storageManager.enabled" #ifdef NIGHTLY_BUILD pref("browser.storageManager.enabled", true); #else
--- a/netwerk/base/nsISocketTransport.idl +++ b/netwerk/base/nsISocketTransport.idl @@ -233,21 +233,16 @@ interface nsISocketTransport : nsITransp /** * If set, do not use newer protocol features that might have interop problems * on the Internet. Intended only for use with critical infra like the updater. * default is false. */ const unsigned long BE_CONSERVATIVE = (1 << 7); /** - * This transport has been created by a speculative connection attempt. - */ - const unsigned long SPECULATIVE = (1 << 8); - - /** * An opaque flags for non-standard behavior of the TLS system. * It is unlikely this will need to be set outside of telemetry studies * relating to the TLS implementation. */ attribute unsigned long tlsFlags; /** * Socket QoS/ToS markings. Valid values are IPTOS_DSCP_AFxx or
--- a/netwerk/base/nsSocketTransport2.cpp +++ b/netwerk/base/nsSocketTransport2.cpp @@ -1258,22 +1258,18 @@ nsSocketTransport::BuildSocket(PRFileDes { MutexAutoLock lock(mLock); mSecInfo = secinfo; callbacks = mCallbacks; SOCKET_LOG((" [secinfo=%p callbacks=%p]\n", mSecInfo.get(), mCallbacks.get())); } // don't call into PSM while holding mLock!! nsCOMPtr<nsISSLSocketControl> secCtrl(do_QueryInterface(secinfo)); - if (secCtrl) { - if (mConnectionFlags & nsISocketTransport::SPECULATIVE) { - secCtrl->SetSpeculative(true); - } + if (secCtrl) secCtrl->SetNotificationCallbacks(callbacks); - } // remember if socket type is SSL so we can ProxyStartSSL if need be. usingSSL = isSSL; } else if ((strcmp(mTypes[i], "socks") == 0) || (strcmp(mTypes[i], "socks4") == 0)) { // since socks is transparent, any layers above // it do not have to worry about proxy stuff proxyInfo = nullptr;
--- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -4432,17 +4432,26 @@ nsHttpChannel::OnCacheEntryAvailable(nsI if (!mIsPending) { mCacheInputStream.CloseAndRelease(); return NS_OK; } rv = OnCacheEntryAvailableInternal(entry, aNew, aAppCache, status); if (NS_FAILED(rv)) { CloseCacheEntry(false); - Unused << AsyncAbort(rv); + if (mRaceCacheWithNetwork && mNetworkTriggered && + mFirstResponseSource != RESPONSE_FROM_CACHE) { + // Ignore the error if we're racing cache with network and the cache + // didn't win, The network part will handle cancelation or any other + // error. Otherwise we could end up calling the listener twice, see + // bug 1397593. + LOG((" not calling AsyncAbort() because we're racing cache with network")); + } else { + Unused << AsyncAbort(rv); + } } return NS_OK; } nsresult nsHttpChannel::OnCacheEntryAvailableInternal(nsICacheEntry *entry, bool aNew,
--- a/netwerk/protocol/http/nsHttpConnection.cpp +++ b/netwerk/protocol/http/nsHttpConnection.cpp @@ -951,28 +951,16 @@ nsHttpConnection::CanReuse() return false; } if ((mTransaction ? (mTransaction->IsDone() ? 0U : 1U) : 0U) >= mRemainingConnectionUses) { return false; } - if (!mExperienced) { - uint32_t flags = 0; - mSocketTransport->GetConnectionFlags(&flags); - if (flags & nsISocketTransport::SPECULATIVE) { - if (gHttpHandler->ConnMgr()->IsSpeculativeConnectDisabled(mConnInfo)) { - LOG(("nsHttpConnection::CanReuse %p can't reuse because speculative" - " connections are disabled for this host", this)); - return false; - } - } - } - bool canReuse; if (mSpdySession) { canReuse = mSpdySession->CanReuse(); } else { canReuse = IsKeepAlive(); } canReuse = canReuse && (IdleTime() < mIdleTimeout) && IsAlive();
--- a/netwerk/protocol/http/nsHttpConnectionInfo.h +++ b/netwerk/protocol/http/nsHttpConnectionInfo.h @@ -80,17 +80,16 @@ public: void SetNetworkInterfaceId(const nsACString& aNetworkInterfaceId); // OK to treat these as an infalible allocation nsHttpConnectionInfo* Clone() const; void CloneAsDirectRoute(nsHttpConnectionInfo **outParam); MOZ_MUST_USE nsresult CreateWildCard(nsHttpConnectionInfo **outParam); const char *ProxyHost() const { return mProxyInfo ? mProxyInfo->Host().get() : nullptr; } - const nsCString& GetProxyHost() const { return mProxyInfo ? mProxyInfo->Host() : EmptyCString(); } int32_t ProxyPort() const { return mProxyInfo ? mProxyInfo->Port() : -1; } const char *ProxyType() const { return mProxyInfo ? mProxyInfo->Type() : nullptr; } const char *ProxyUsername() const { return mProxyInfo ? mProxyInfo->Username().get() : nullptr; } const char *ProxyPassword() const { return mProxyInfo ? mProxyInfo->Password().get() : nullptr; } // Compare this connection info to another... // Two connections are 'equal' if they end up talking the same // protocol to the same server. This is needed to properly manage
--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp +++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp @@ -3227,42 +3227,16 @@ bool nsHttpConnectionMgr::IsConnEntryUnd } nsTArray<RefPtr<PendingTransactionInfo>> *transactions = ent->mPendingTransactionTable.Get(mCurrentTopLevelOuterContentWindowId); return transactions && !transactions->IsEmpty(); } -void nsHttpConnectionMgr::DontPreconnect(nsACString const & host, int32_t port) -{ - MOZ_ASSERT(OnSocketThread(), "not on socket thread"); - - for (auto iter = mCT.Iter(); !iter.Done(); iter.Next()) { - RefPtr<nsConnectionEntry> ent = iter.Data(); - nsHttpConnectionInfo* info = ent->mConnInfo; - - if ((info->GetOrigin() == host && info->OriginPort() == port) || - (info->ProxyInfo() && info->GetProxyHost() == host && info->ProxyPort() == port)) { - - LOG(("nsHttpConnectionMgr::DontPreconnect disabling preconnects on %s", - info->HashKey().get())); - - ent->mDisallowPreconnects = true; - } - } -} - -bool nsHttpConnectionMgr::IsSpeculativeConnectDisabled(nsHttpConnectionInfo *connInfo) -{ - nsConnectionEntry *ent = mCT.GetWeak(connInfo->HashKey()); - return ent && ent->mDisallowPreconnects; -} - - bool nsHttpConnectionMgr::IsThrottleTickerNeeded() { LOG(("nsHttpConnectionMgr::IsThrottleTickerNeeded")); if (mActiveTabUnthrottledTransactionsExist && mActiveTransactions[false].Count() > 1) { LOG((" there are unthrottled transactions for both active and bck")); return true; @@ -3696,21 +3670,16 @@ nsHttpConnectionMgr::OnMsgSpeculativeCon SpeculativeConnectArgs *args = static_cast<SpeculativeConnectArgs *>(param); LOG(("nsHttpConnectionMgr::OnMsgSpeculativeConnect [ci=%s]\n", args->mTrans->ConnectionInfo()->HashKey().get())); nsConnectionEntry *ent = GetOrCreateConnectionEntry(args->mTrans->ConnectionInfo(), false); - if (ent->mDisallowPreconnects) { - LOG((" explicitely disabled for this host:port")); - return; - } - uint32_t parallelSpeculativeConnectLimit = gHttpHandler->ParallelSpeculativeConnectLimit(); bool ignoreIdle = false; bool isFromPredictor = false; bool allow1918 = false; if (args->mOverridesOK) { parallelSpeculativeConnectLimit = args->mParallelSpeculativeConnectLimit; @@ -3920,20 +3889,16 @@ nsHalfOpenSocket::SetupStreams(nsISocket (isBackup && gHttpHandler->FastFallbackToIPv4())) { tmpFlags |= nsISocketTransport::DISABLE_IPV6; } if (!Allow1918()) { tmpFlags |= nsISocketTransport::DISABLE_RFC1918; } - if (mSpeculative) { - tmpFlags |= nsISocketTransport::SPECULATIVE; - } - if (!isBackup && mEnt->mUseFastOpen) { socketTransport->SetFastOpenCallback(this); } socketTransport->SetConnectionFlags(tmpFlags); socketTransport->SetTlsFlags(ci->GetTlsFlags()); const OriginAttributes& originAttributes = mEnt->mConnInfo->GetOriginAttributes(); @@ -4988,17 +4953,16 @@ ConnectionHandle::TopLevelOuterContentWi nsHttpConnectionMgr:: nsConnectionEntry::nsConnectionEntry(nsHttpConnectionInfo *ci) : mConnInfo(ci) , mUsingSpdy(false) , mPreferIPv4(false) , mPreferIPv6(false) , mUsedForConnection(false) , mDoNotDestroy(false) - , mDisallowPreconnects(false) { MOZ_COUNT_CTOR(nsConnectionEntry); if (mConnInfo->FirstHopSSL()) { #if defined(_WIN64) && defined(WIN95) mUseFastOpen = gHttpHandler->UseFastOpen() && gSocketTransportService->HasFileDesc2PlatformOverlappedIOHandleFunc(); #else
--- a/netwerk/protocol/http/nsHttpConnectionMgr.h +++ b/netwerk/protocol/http/nsHttpConnectionMgr.h @@ -237,25 +237,16 @@ public: void TouchThrottlingTimeWindow(bool aEnsureTicker = true); // return true iff the connection has pending transactions for the active tab. // it's mainly used to disallow throttling (stop reading) of a response // belonging to the same conn info to free up a connection ASAP. // NOTE: relatively expensive to call, there are two hashtable lookups. bool IsConnEntryUnderPressure(nsHttpConnectionInfo*); - // This disables preconnecting for all existing connection entries matching - // the host and port. Existing speculative connections that have never been - // used will not be used. - void DontPreconnect(nsACString const &host, int32_t port); - - // The information is stored on the entry, not on conn-info (which is just - // a passive descriptor). - bool IsSpeculativeConnectDisabled(nsHttpConnectionInfo*); - uint64_t CurrentTopLevelOuterContentWindowId() { return mCurrentTopLevelOuterContentWindowId; } private: virtual ~nsHttpConnectionMgr(); @@ -323,18 +314,16 @@ private: // True if this connection entry has initiated a socket bool mUsedForConnection : 1; // Try using TCP Fast Open. bool mUseFastOpen : 1; bool mDoNotDestroy : 1; - bool mDisallowPreconnects : 1; - // Set the IP family preference flags according the connected family void RecordIPFamilyPreference(uint16_t family); // Resets all flags to their default values void ResetIPFamilyPreference(); // Return the count of pending transactions for all window ids. size_t PendingQLength() const;
--- a/netwerk/protocol/http/nsHttpHandler.cpp +++ b/netwerk/protocol/http/nsHttpHandler.cpp @@ -2270,25 +2270,16 @@ nsHttpHandler::GetOscpu(nsACString &valu NS_IMETHODIMP nsHttpHandler::GetMisc(nsACString &value) { value = mMisc; return NS_OK; } -NS_IMETHODIMP -nsHttpHandler::DontPreconnect(nsACString const &host, int32_t port) -{ - if (mConnMgr) { - mConnMgr->DontPreconnect(host, port); - } - return NS_OK; -}; - //----------------------------------------------------------------------------- // nsHttpHandler::nsIObserver //----------------------------------------------------------------------------- NS_IMETHODIMP nsHttpHandler::Observe(nsISupports *subject, const char *topic, const char16_t *data)
--- a/netwerk/protocol/http/nsIHttpProtocolHandler.idl +++ b/netwerk/protocol/http/nsIHttpProtocolHandler.idl @@ -42,22 +42,16 @@ interface nsIHttpProtocolHandler : nsIPr */ [must_use] readonly attribute ACString oscpu; /** * Get the application comment misc portion. */ [must_use] readonly attribute ACString misc; - /** - * Blocks preconnection for the given host:port - * This is used mainly to prevent client cert selection dialogs - * to pop-up too early. - */ - void dontPreconnect(in ACString host, in int32_t port); }; %{C++ // ----------- Categories ----------- /** * At initialization time, the HTTP handler will initialize each service * registered under this category: */
--- a/netwerk/socket/nsISSLSocketControl.idl +++ b/netwerk/socket/nsISSLSocketControl.idl @@ -17,23 +17,16 @@ interface nsIX509Cert; [scriptable, builtinclass, uuid(418265c8-654e-4fbb-ba62-4eed27de1f03)] interface nsISSLSocketControl : nsISupports { attribute nsIInterfaceRequestor notificationCallbacks; void proxyStartSSL(); void StartTLS(); - /** - * Whether this socket has been created by a speculative connection - * attempt. This will mainly prevent client certificate dialog to - * pop-up. - */ - attribute boolean speculative; - /* NPN (Next Protocol Negotiation) is a mechanism for negotiating the protocol to be spoken inside the SSL tunnel during the SSL handshake. The NPNList is the list of offered client side protocols. setNPNList() needs to be called before any data is read or written (including the handshake to be setup correctly. The server determines the priority when multiple matches occur, but if there is no overlap the first protocol in the list is used. */
--- a/parser/html/nsHtml5TreeOperation.cpp +++ b/parser/html/nsHtml5TreeOperation.cpp @@ -440,17 +440,19 @@ nsHtml5TreeOperation::CreateHTMLElement( } else { newContent->SetAttr(nsuri, localName, prefix, value, false); // Custom element setup may be needed if there is an "is" attribute. - if (kNameSpaceID_None == nsuri && !prefix && nsGkAtoms::is == localName) { + if (nsContentUtils::IsWebComponentsEnabled() && + kNameSpaceID_None == nsuri && + !prefix && nsGkAtoms::is == localName) { nsContentUtils::SetupCustomElement(newContent, &value); } } } } return newContent; }
--- a/security/manager/ssl/nsNSSIOLayer.cpp +++ b/security/manager/ssl/nsNSSIOLayer.cpp @@ -24,17 +24,16 @@ #include "nsArray.h" #include "nsArrayUtils.h" #include "nsCRT.h" #include "nsCharSeparatedTokenizer.h" #include "nsClientAuthRemember.h" #include "nsContentUtils.h" #include "nsIClientAuthDialogs.h" #include "nsIConsoleService.h" -#include "nsIHttpProtocolHandler.h" #include "nsIPrefService.h" #include "nsISocketProvider.h" #include "nsIWebProgressListener.h" #include "nsNSSCertHelper.h" #include "nsNSSComponent.h" #include "nsPrintfCString.h" #include "nsServiceManagerUtils.h" #include "pkix/pkixtypes.h" @@ -119,17 +118,16 @@ nsNSSSocketInfo::nsNSSSocketInfo(SharedS uint32_t providerTlsFlags) : mFd(nullptr), mCertVerificationState(before_cert_verification), mSharedState(aState), mForSTARTTLS(false), mHandshakePending(true), mRememberClientAuthCertificate(false), mPreliminaryHandshakeDone(false), - mSpeculative(false), mNPNCompleted(false), mEarlyDataAccepted(false), mFalseStartCallbackCalled(false), mFalseStarted(false), mIsFullHandshake(false), mHandshakeCompleted(false), mJoined(false), mSentClientCert(false), @@ -332,30 +330,16 @@ nsNSSSocketInfo::SetHandshakeCompleted() mHandshakeCompleted = true; MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("[%p] nsNSSSocketInfo::SetHandshakeCompleted\n", (void*) mFd)); mIsFullHandshake = false; // reset for next handshake on this connection } -NS_IMETHODIMP -nsNSSSocketInfo::GetSpeculative(bool *aSpeculative) -{ - *aSpeculative = mSpeculative; - return NS_OK; -} - -NS_IMETHODIMP -nsNSSSocketInfo::SetSpeculative(bool aSpeculative) -{ - mSpeculative = aSpeculative; - return NS_OK; -} - void nsNSSSocketInfo::SetNegotiatedNPN(const char* value, uint32_t length) { if (!value) { mNegotiatedNPN.Truncate(); } else { mNegotiatedNPN.Assign(value, length); } @@ -2187,47 +2171,31 @@ nsNSS_SSLGetClientAuthData(void* arg, PR if (!socket || !caNames || !pRetCert || !pRetKey) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return SECFailure; } RefPtr<nsNSSSocketInfo> info( BitwiseCast<nsNSSSocketInfo*, PRFilePrivate*>(socket->higher->secret)); - if (info->IsSpeculative()) { - MOZ_LOG(gPIPNSSLog, LogLevel::Debug, - ("[%p] Blocking speculative SSL connections that ask for client cert creds\n", socket->higher)); - - nsCOMPtr<nsIHttpProtocolHandler> handler( - do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http")); - - if (handler) { - handler->DontPreconnect(info->GetHostName(), info->GetPort()); - - // Bail, this socket will not be used anyway. - PR_SetError(SSL_ERROR_NO_CERTIFICATE, 0); - return SECFailure; - } - } - UniqueCERTCertificate serverCert(SSL_PeerCertificate(socket)); if (!serverCert) { MOZ_ASSERT_UNREACHABLE( "Missing server cert should have been detected during server cert auth."); PR_SetError(SSL_ERROR_NO_CERTIFICATE, 0); return SECFailure; } if (info->GetJoined()) { // We refuse to send a client certificate when there are multiple hostnames // joined on this connection, because we only show the user one hostname // (mHostName) in the client certificate UI. MOZ_LOG(gPIPNSSLog, LogLevel::Debug, - ("[%p] Not returning client cert due to previous join\n", socket->higher)); + ("[%p] Not returning client cert due to previous join\n", socket)); *pRetCert = nullptr; *pRetKey = nullptr; return SECSuccess; } // XXX: This should be done asynchronously; see bug 696976 RefPtr<ClientAuthDataRunnable> runnable( new ClientAuthDataRunnable(caNames, pRetCert, pRetKey, info, serverCert));
--- a/security/manager/ssl/nsNSSIOLayer.h +++ b/security/manager/ssl/nsNSSIOLayer.h @@ -44,18 +44,16 @@ public: NS_DECL_NSICLIENTAUTHUSERDECISION void SetForSTARTTLS(bool aForSTARTTLS); bool GetForSTARTTLS(); nsresult GetFileDescPtr(PRFileDesc** aFilePtr); nsresult SetFileDescPtr(PRFileDesc* aFilePtr); - bool IsSpeculative() { return mSpeculative; } - bool IsHandshakePending() const { return mHandshakePending; } void SetHandshakeNotPending() { mHandshakePending = false; } void SetTLSVersionRange(SSLVersionRange range) { mTLSVersionRange = range; } SSLVersionRange GetTLSVersionRange() const { return mTLSVersionRange; }; PRStatus CloseSocketAndDestroy( const nsNSSShutDownPreventionLock& proofOfLock); @@ -181,17 +179,16 @@ private: SSLVersionRange mTLSVersionRange; bool mHandshakePending; bool mRememberClientAuthCertificate; bool mPreliminaryHandshakeDone; // after false start items are complete nsresult ActivateSSL(); nsCString mNegotiatedNPN; - bool mSpeculative; bool mNPNCompleted; bool mEarlyDataAccepted; bool mFalseStartCallbackCalled; bool mFalseStarted; bool mIsFullHandshake; bool mHandshakeCompleted; bool mJoined; bool mSentClientCert;
--- a/security/nss.symbols +++ b/security/nss.symbols @@ -709,16 +709,17 @@ VFY_Update VFY_VerifyData VFY_VerifyDataWithAlgorithmID VFY_VerifyDigestDirect _SGN_VerifyPKCS1DigestInfo __PK11_SetCertificateNickname # These symbols are not used by Firefox but are used across NSS library boundaries. NSS_SecureMemcmpZero PORT_ZAllocAlignedOffset_Util +CERT_FindCertByNicknameOrEmailAddrCX # These symbols are not used by Firefox itself, but are used by Java's security # libraries, which in turn are used by Java applets/plugins/etc. Provide them # to make Java code happy. NSS_VersionCheck NSS_Initialize #ifdef NSS_EXTRA_SYMBOLS_FILE #include @NSS_EXTRA_SYMBOLS_FILE@ #endif
--- a/security/nss/.taskcluster.yml +++ b/security/nss/.taskcluster.yml @@ -52,17 +52,17 @@ tasks: tags: createdForUser: {{owner}} routes: - "tc-treeherder-stage.v2.{{project}}.{{revision}}.{{pushlog_id}}" - "tc-treeherder.v2.{{project}}.{{revision}}.{{pushlog_id}}" payload: - image: ttaubert/nss-decision:0.0.2 + image: nssdev/nss-decision:0.0.2 env: TC_OWNER: {{owner}} TC_SOURCE: {{{source}}} TC_PROJECT: {{project}} TC_COMMENT: '{{comment}}' NSS_PUSHLOG_ID: '{{pushlog_id}}' NSS_HEAD_REPOSITORY: '{{{url}}}'
--- a/security/nss/automation/taskcluster/docker-decision/Dockerfile +++ b/security/nss/automation/taskcluster/docker-decision/Dockerfile @@ -7,16 +7,19 @@ WORKDIR /home/worker # Add build and test scripts. ADD bin /home/worker/bin RUN chmod +x /home/worker/bin/* # Install dependencies. ADD setup.sh /tmp/setup.sh RUN bash /tmp/setup.sh +# Change user. +USER worker + # Env variables. ENV HOME /home/worker ENV SHELL /bin/bash ENV USER worker ENV LOGNAME worker ENV HOSTNAME taskcluster-worker ENV LANG en_US.UTF-8 ENV LC_ALL en_US.UTF-8
--- a/security/nss/automation/taskcluster/docker-decision/bin/checkout.sh +++ b/security/nss/automation/taskcluster/docker-decision/bin/checkout.sh @@ -1,17 +1,12 @@ #!/usr/bin/env bash set -v -e -x -if [ $(id -u) = 0 ]; then - # Drop privileges by re-running this script. - exec su worker $0 -fi - # Default values for testing. REVISION=${NSS_HEAD_REVISION:-default} REPOSITORY=${NSS_HEAD_REPOSITORY:-https://hg.mozilla.org/projects/nss} # Clone NSS. for i in 0 2 5; do sleep $i hg clone -r $REVISION $REPOSITORY nss && exit 0
--- a/security/nss/automation/taskcluster/graph/src/context_hash.js +++ b/security/nss/automation/taskcluster/graph/src/context_hash.js @@ -22,22 +22,32 @@ function collectFilesInDirectory(dir) { if (fs.lstatSync(entry_path).isDirectory()) { return collectFilesInDirectory(entry_path); } return [entry_path]; }); } -// Compute a context hash for the given context path. -export default function (context_path) { +// A list of hashes for each file in the given path. +function collectFileHashes(context_path) { let root = path.join(__dirname, "../../../.."); let dir = path.join(root, context_path); let files = collectFilesInDirectory(dir).sort(); - let hashes = files.map(file => { + + return files.map(file => { return sha256(file + "|" + fs.readFileSync(file, "utf-8")); }); +} + +// Compute a context hash for the given context path. +export default function (context_path) { + // Regenerate all images when the image_builder changes. + let hashes = collectFileHashes("automation/taskcluster/image_builder"); + + // Regenerate images when the image itself changes. + hashes = hashes.concat(collectFileHashes(context_path)); // Generate a new prefix every month to ensure the image stays buildable. let now = new Date(); let prefix = `${now.getUTCFullYear()}-${now.getUTCMonth() + 1}:`; return sha256(prefix + hashes.join(",")); }
--- a/security/nss/automation/taskcluster/graph/src/extend.js +++ b/security/nss/automation/taskcluster/graph/src/extend.js @@ -554,22 +554,23 @@ async function scheduleFuzzing() { // Schedule fuzzing runs. let run_base = merge(base, {parent: task_build, kind: "test"}); scheduleFuzzingRun(run_base, "CertDN", "certDN", 4096); scheduleFuzzingRun(run_base, "QuickDER", "quickder", 10000); // Schedule MPI fuzzing runs. let mpi_base = merge(run_base, {group: "MPI"}); - let mpi_names = ["add", "addmod", "div", "expmod", "mod", "mulmod", "sqr", + let mpi_names = ["add", "addmod", "div", "mod", "mulmod", "sqr", "sqrmod", "sub", "submod"]; for (let name of mpi_names) { scheduleFuzzingRun(mpi_base, `MPI (${name})`, `mpi-${name}`, 4096, name); } scheduleFuzzingRun(mpi_base, `MPI (invmod)`, `mpi-invmod`, 256, "invmod"); + scheduleFuzzingRun(mpi_base, `MPI (expmod)`, `mpi-expmod`, 2048, "expmod"); // Schedule TLS fuzzing runs (non-fuzzing mode). let tls_base = merge(run_base, {group: "TLS"}); scheduleFuzzingRun(tls_base, "TLS Client", "tls-client", 20000, "client-nfm", "tls-client-no_fuzzer_mode"); scheduleFuzzingRun(tls_base, "TLS Server", "tls-server", 20000, "server-nfm", "tls-server-no_fuzzer_mode"); scheduleFuzzingRun(tls_base, "DTLS Client", "dtls-client", 20000,
--- a/security/nss/automation/taskcluster/graph/src/image_builder.js +++ b/security/nss/automation/taskcluster/graph/src/image_builder.js @@ -26,37 +26,35 @@ export async function findTask({name, pa } export async function buildTask({name, path}) { let hash = await context_hash(path); let ns = `docker.images.v1.${process.env.TC_PROJECT}.${name}.hash.${hash}`; return { name: "Image Builder", - image: "taskcluster/image_builder:0.1.5", + image: "nssdev/image_builder:0.1.5", routes: ["index." + ns], env: { - HEAD_REPOSITORY: process.env.NSS_HEAD_REPOSITORY, - BASE_REPOSITORY: process.env.NSS_HEAD_REPOSITORY, - HEAD_REV: process.env.NSS_HEAD_REVISION, - HEAD_REF: process.env.NSS_HEAD_REVISION, + NSS_HEAD_REPOSITORY: process.env.NSS_HEAD_REPOSITORY, + NSS_HEAD_REVISION: process.env.NSS_HEAD_REVISION, PROJECT: process.env.TC_PROJECT, CONTEXT_PATH: path, HASH: hash }, artifacts: { "public/image.tar": { type: "file", expires: 24 * 90, path: "/artifacts/image.tar" } }, command: [ "/bin/bash", "-c", - "/home/worker/bin/build_image.sh" + "bin/checkout.sh && nss/automation/taskcluster/scripts/build_image.sh" ], platform: "nss-decision", features: ["dind"], kind: "build", symbol: "I" }; }
new file mode 100644 --- /dev/null +++ b/security/nss/automation/taskcluster/image_builder/Dockerfile @@ -0,0 +1,23 @@ +FROM ubuntu:16.04 +MAINTAINER Tim Taubert <ttaubert@mozilla.com> + +WORKDIR /home/worker + +ENV DEBIAN_FRONTEND noninteractive + +RUN apt-get update && apt-get install -y apt-transport-https apt-utils +RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9 && \ + sh -c "echo deb https://get.docker.io/ubuntu docker main \ + > /etc/apt/sources.list.d/docker.list" +RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 41BD8711B1F0EC2B0D85B91CF59CE3A8323293EE && \ + sh -c "echo deb http://ppa.launchpad.net/mercurial-ppa/releases/ubuntu xenial main \ + > /etc/apt/sources.list.d/mercurial.list" +RUN apt-get update && apt-get install -y \ + lxc-docker-1.6.1 \ + mercurial + +ADD bin /home/worker/bin +RUN chmod +x /home/worker/bin/* + +# Set a default command useful for debugging +CMD ["/bin/bash", "--login"]
new file mode 100644 --- /dev/null +++ b/security/nss/automation/taskcluster/image_builder/VERSION @@ -0,0 +1,1 @@ +0.1.5
new file mode 100644 --- /dev/null +++ b/security/nss/automation/taskcluster/image_builder/bin/checkout.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +set -v -e -x + +# Default values for testing. +REVISION=${NSS_HEAD_REVISION:-default} +REPOSITORY=${NSS_HEAD_REPOSITORY:-https://hg.mozilla.org/projects/nss} + +# Clone NSS. +for i in 0 2 5; do + sleep $i + hg clone -r $REVISION $REPOSITORY nss && exit 0 + rm -rf nss +done +exit 1
new file mode 100755 --- /dev/null +++ b/security/nss/automation/taskcluster/scripts/build_image.sh @@ -0,0 +1,24 @@ +#!/bin/bash -vex + +set -x -e -v + +# Prefix errors with taskcluster error prefix so that they are parsed by Treeherder +raise_error() { + echo + echo "[taskcluster-image-build:error] $1" + exit 1 +} + +# Ensure that the PROJECT is specified so the image can be indexed +test -n "$PROJECT" || raise_error "Project must be provided." +test -n "$HASH" || raise_error "Context Hash must be provided." + +CONTEXT_PATH=/home/worker/nss/$CONTEXT_PATH + +test -d $CONTEXT_PATH || raise_error "Context Path $CONTEXT_PATH does not exist." +test -f "$CONTEXT_PATH/Dockerfile" || raise_error "Dockerfile must be present in $CONTEXT_PATH." + +docker build -t $PROJECT:$HASH $CONTEXT_PATH + +mkdir /artifacts +docker save $PROJECT:$HASH > /artifacts/image.tar
--- a/security/nss/cmd/bltest/blapitest.c +++ b/security/nss/cmd/bltest/blapitest.c @@ -15,26 +15,24 @@ #include "nssb64.h" #include "basicutil.h" #include "plgetopt.h" #include "softoken.h" #include "nspr.h" #include "secport.h" #include "secoid.h" #include "nssutil.h" +#include "ecl-curve.h" #include "pkcs1_vectors.h" -#ifndef NSS_DISABLE_ECC -#include "ecl-curve.h" SECStatus EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams); SECStatus EC_CopyParams(PLArenaPool *arena, ECParams *dstParams, const ECParams *srcParams); -#endif char *progName; char *testdir = NULL; #define BLTEST_DEFAULT_CHUNKSIZE 4096 #define WORDSIZE sizeof(unsigned long) @@ -130,28 +128,24 @@ Usage() PRINTUSAGE("", "-b", "size of input buffer"); PRINTUSAGE("", "-p", "do performance test"); PRINTUSAGE("", "-4", "run test in multithread mode. th_num number of parallel threads"); PRINTUSAGE("", "-5", "run test for specified time interval(in seconds)"); fprintf(stderr, "\n"); PRINTUSAGE(progName, "-S -m mode", "Sign a buffer"); PRINTUSAGE("", "", "[-i plaintext] [-o signature] [-k key]"); PRINTUSAGE("", "", "[-b bufsize]"); -#ifndef NSS_DISABLE_ECC PRINTUSAGE("", "", "[-n curvename]"); -#endif PRINTUSAGE("", "", "[-p repetitions | -5 time_interval] [-4 th_num]"); PRINTUSAGE("", "-m", "cipher mode to use"); PRINTUSAGE("", "-i", "file which contains input buffer"); PRINTUSAGE("", "-o", "file for signature"); PRINTUSAGE("", "-k", "file which contains key"); -#ifndef NSS_DISABLE_ECC PRINTUSAGE("", "-n", "name of curve for EC key generation; one of:"); PRINTUSAGE("", "", " nistp256, nistp384, nistp521"); -#endif PRINTUSAGE("", "-p", "do performance test"); PRINTUSAGE("", "-4", "run test in multithread mode. th_num number of parallel threads"); PRINTUSAGE("", "-5", "run test for specified time interval(in seconds)"); fprintf(stderr, "\n"); PRINTUSAGE(progName, "-V -m mode", "Verify a signed buffer"); PRINTUSAGE("", "", "[-i plaintext] [-s signature] [-k key]"); PRINTUSAGE("", "", "[-p repetitions | -5 time_interval] [-4 th_num]"); PRINTUSAGE("", "-m", "cipher mode to use"); @@ -364,17 +358,16 @@ dsakey_from_filedata(PLArenaPool *arena, { DSAPrivateKey *key; key = (DSAPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(DSAPrivateKey)); key->params.arena = arena; key_from_filedata(arena, &key->params.prime, 0, 5, filedata); return key; } -#ifndef NSS_DISABLE_ECC static ECPrivateKey * eckey_from_filedata(PLArenaPool *arena, SECItem *filedata) { ECPrivateKey *key; SECStatus rv; ECParams *tmpECParams = NULL; key = (ECPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(ECPrivateKey)); /* read and convert params */ @@ -514,17 +507,16 @@ getECParams(const char *curve) * oidData->oid.data so we simply prepend 0x06 and OID length */ ecparams->data[0] = SEC_ASN1_OBJECT_ID; ecparams->data[1] = oidData->oid.len; memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len); return ecparams; } -#endif /* NSS_DISABLE_ECC */ static void dump_pqg(PQGParams *pqg) { SECU_PrintInteger(stdout, &pqg->prime, "PRIME:", 0); SECU_PrintInteger(stdout, &pqg->subPrime, "SUBPRIME:", 0); SECU_PrintInteger(stdout, &pqg->base, "BASE:", 0); } @@ -532,32 +524,30 @@ dump_pqg(PQGParams *pqg) static void dump_dsakey(DSAPrivateKey *key) { dump_pqg(&key->params); SECU_PrintInteger(stdout, &key->publicValue, "PUBLIC VALUE:", 0); SECU_PrintInteger(stdout, &key->privateValue, "PRIVATE VALUE:", 0); } -#ifndef NSS_DISABLE_ECC static void dump_ecp(ECParams *ecp) { /* TODO other fields */ SECU_PrintInteger(stdout, &ecp->base, "BASE POINT:", 0); } static void dump_eckey(ECPrivateKey *key) { dump_ecp(&key->ecParams); SECU_PrintInteger(stdout, &key->publicValue, "PUBLIC VALUE:", 0); SECU_PrintInteger(stdout, &key->privateValue, "PRIVATE VALUE:", 0); } -#endif static void dump_rsakey(RSAPrivateKey *key) { SECU_PrintInteger(stdout, &key->version, "VERSION:", 0); SECU_PrintInteger(stdout, &key->modulus, "MODULUS:", 0); SECU_PrintInteger(stdout, &key->publicExponent, "PUBLIC EXP:", 0); SECU_PrintInteger(stdout, &key->privateExponent, "PRIVATE EXP:", 0); @@ -633,27 +623,25 @@ typedef enum { bltestCAMELLIA_ECB, /* . */ bltestCAMELLIA_CBC, /* . */ bltestSEED_ECB, /* SEED algorithm */ bltestSEED_CBC, /* SEED algorithm */ bltestCHACHA20, /* ChaCha20 + Poly1305 */ bltestRSA, /* Public Key Ciphers */ bltestRSA_OAEP, /* . (Public Key Enc.) */ bltestRSA_PSS, /* . (Public Key Sig.) */ -#ifndef NSS_DISABLE_ECC - bltestECDSA, /* . (Public Key Sig.) */ -#endif - bltestDSA, /* . (Public Key Sig.) */ - bltestMD2, /* Hash algorithms */ - bltestMD5, /* . */ - bltestSHA1, /* . */ - bltestSHA224, /* . */ - bltestSHA256, /* . */ - bltestSHA384, /* . */ - bltestSHA512, /* . */ + bltestECDSA, /* . (Public Key Sig.) */ + bltestDSA, /* . (Public Key Sig.) */ + bltestMD2, /* Hash algorithms */ + bltestMD5, /* . */ + bltestSHA1, /* . */ + bltestSHA224, /* . */ + bltestSHA256, /* . */ + bltestSHA384, /* . */ + bltestSHA512, /* . */ NUMMODES } bltestCipherMode; static char *mode_strings[] = { "des_ecb", "des_cbc", "des3_ecb", @@ -673,19 +661,17 @@ static char *mode_strings[] = "camellia_ecb", "camellia_cbc", "seed_ecb", "seed_cbc", "chacha20_poly1305", "rsa", "rsa_oaep", "rsa_pss", -#ifndef NSS_DISABLE_ECC "ecdsa", -#endif /*"pqg",*/ "dsa", "md2", "md5", "sha1", "sha224", "sha256", "sha384", @@ -727,38 +713,34 @@ typedef struct { bltestIO pqgdata; unsigned int keysize; bltestIO keyseed; bltestIO sigseed; PQGParams *pqg; } bltestDSAParams; -#ifndef NSS_DISABLE_ECC typedef struct { char *curveName; bltestIO sigseed; } bltestECDSAParams; -#endif typedef struct { bltestIO key; void *privKey; void *pubKey; bltestIO sig; /* if doing verify, the signature (which may come * from sigfile. */ union { bltestRSAParams rsa; bltestDSAParams dsa; -#ifndef NSS_DISABLE_ECC bltestECDSAParams ecdsa; -#endif } cipherParams; } bltestAsymKeyParams; typedef struct { bltestIO key; /* unused */ PRBool restart; } bltestHashParams; @@ -1305,17 +1287,16 @@ dsa_signDigest(void *cx, SECItem *output SECStatus dsa_verifyDigest(void *cx, SECItem *output, const SECItem *input) { bltestAsymKeyParams *params = (bltestAsymKeyParams *)cx; return DSA_VerifyDigest((DSAPublicKey *)params->pubKey, output, input); } -#ifndef NSS_DISABLE_ECC SECStatus ecdsa_signDigest(void *cx, SECItem *output, const SECItem *input) { bltestAsymKeyParams *params = (bltestAsymKeyParams *)cx; if (params->cipherParams.ecdsa.sigseed.buf.len > 0) { return ECDSA_SignDigestWithSeed( (ECPrivateKey *)params->privKey, output, input, @@ -1326,17 +1307,16 @@ ecdsa_signDigest(void *cx, SECItem *outp } SECStatus ecdsa_verifyDigest(void *cx, SECItem *output, const SECItem *input) { bltestAsymKeyParams *params = (bltestAsymKeyParams *)cx; return ECDSA_VerifyDigest((ECPublicKey *)params->pubKey, output, input); } -#endif SECStatus bltest_des_init(bltestCipherInfo *cipherInfo, PRBool encrypt) { PRIntervalTime time1, time2; bltestSymmKeyParams *desp = &cipherInfo->params.sk; int minorMode; int i; @@ -1806,17 +1786,16 @@ bltest_dsa_init(bltestCipherInfo *cipher pubkey->publicValue.len = key->publicValue.len; pubkey->publicValue.data = key->publicValue.data; asymk->pubKey = pubkey; cipherInfo->cipher.pubkeyCipher = dsa_verifyDigest; } return SECSuccess; } -#ifndef NSS_DISABLE_ECC SECStatus bltest_ecdsa_init(bltestCipherInfo *cipherInfo, PRBool encrypt) { int i; ECPrivateKey **dummyKey; PRIntervalTime time1, time2; bltestAsymKeyParams *asymk = &cipherInfo->params.asymk; cipherInfo->cx = asymk; @@ -1872,17 +1851,16 @@ bltest_ecdsa_init(bltestCipherInfo *ciph pubkey->ecParams.name = key->ecParams.name; pubkey->publicValue.len = key->publicValue.len; pubkey->publicValue.data = key->publicValue.data; asymk->pubKey = pubkey; cipherInfo->cipher.pubkeyCipher = ecdsa_verifyDigest; } return SECSuccess; } -#endif /* XXX unfortunately, this is not defined in blapi.h */ SECStatus md2_HashBuf(unsigned char *dest, const unsigned char *src, PRUint32 src_length) { unsigned int len; MD2Context *cx = MD2_NewContext(); if (cx == NULL) @@ -2164,35 +2142,29 @@ SHA512_restart(unsigned char *dest, cons SHA512_End(cx, dest, &len, MD5_LENGTH); finish: SHA512_DestroyContext(cx, PR_TRUE); return rv; } SECStatus pubkeyInitKey(bltestCipherInfo *cipherInfo, PRFileDesc *file, -#ifndef NSS_DISABLE_ECC int keysize, int exponent, char *curveName) -#else - int keysize, int exponent) -#endif { int i; SECStatus rv = SECSuccess; bltestAsymKeyParams *asymk = &cipherInfo->params.asymk; bltestRSAParams *rsap; RSAPrivateKey **rsaKey = NULL; bltestDSAParams *dsap; DSAPrivateKey **dsaKey = NULL; -#ifndef NSS_DISABLE_ECC SECItem *tmpECParamsDER; ECParams *tmpECParams = NULL; SECItem ecSerialize[3]; ECPrivateKey **ecKey = NULL; -#endif switch (cipherInfo->mode) { case bltestRSA: case bltestRSA_PSS: case bltestRSA_OAEP: rsap = &asymk->cipherParams.rsa; rsaKey = (RSAPrivateKey **)&asymk->privKey; if (keysize > 0) { SECItem expitem = { 0, 0, 0 }; @@ -2219,17 +2191,16 @@ pubkeyInitKey(bltestCipherInfo *cipherIn CHECKERROR(rv, __LINE__); serialize_key(&(*dsaKey)->params.prime, 5, file); } else { setupIO(cipherInfo->arena, &asymk->key, file, NULL, 0); *dsaKey = dsakey_from_filedata(cipherInfo->arena, &asymk->key.buf); dsap->keysize = (*dsaKey)->params.prime.len * 8; } break; -#ifndef NSS_DISABLE_ECC case bltestECDSA: ecKey = (ECPrivateKey **)&asymk->privKey; if (curveName != NULL) { tmpECParamsDER = getECParams(curveName); rv = SECOID_Init(); CHECKERROR(rv, __LINE__); rv = EC_DecodeParams(tmpECParamsDER, &tmpECParams) == SECFailure; CHECKERROR(rv, __LINE__); @@ -2249,17 +2220,16 @@ pubkeyInitKey(bltestCipherInfo *cipherIn PORT_FreeArena(tmpECParams->arena, PR_TRUE); rv = SECOID_Shutdown(); CHECKERROR(rv, __LINE__); } else { setupIO(cipherInfo->arena, &asymk->key, file, NULL, 0); *ecKey = eckey_from_filedata(cipherInfo->arena, &asymk->key.buf); } break; -#endif default: return SECFailure; } return SECSuccess; } SECStatus cipherInit(bltestCipherInfo *cipherInfo, PRBool encrypt) @@ -2336,25 +2306,23 @@ cipherInit(bltestCipherInfo *cipherInfo, break; case bltestDSA: if (encrypt) { SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf, DSA_MAX_SIGNATURE_LEN); } return bltest_dsa_init(cipherInfo, encrypt); break; -#ifndef NSS_DISABLE_ECC case bltestECDSA: if (encrypt) { SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf, 2 * MAX_ECKEY_LEN); } return bltest_ecdsa_init(cipherInfo, encrypt); break; -#endif case bltestMD2: restart = cipherInfo->params.hash.restart; SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf, MD2_LENGTH); cipherInfo->cipher.hashCipher = (restart) ? md2_restart : md2_HashBuf; return SECSuccess; break; case bltestMD5: @@ -2639,19 +2607,17 @@ cipherFinish(bltestCipherInfo *cipherInf case bltestRC5_CBC: RC5_DestroyContext((RC5Context *)cipherInfo->cx, PR_TRUE); break; #endif case bltestRSA: /* keys are alloc'ed within cipherInfo's arena, */ case bltestRSA_PSS: /* will be freed with it. */ case bltestRSA_OAEP: case bltestDSA: -#ifndef NSS_DISABLE_ECC case bltestECDSA: -#endif case bltestMD2: /* hash contexts are ephemeral */ case bltestMD5: case bltestSHA1: case bltestSHA224: case bltestSHA256: case bltestSHA384: case bltestSHA512: return SECSuccess; @@ -2817,28 +2783,26 @@ print_td: break; case bltestDSA: if (td) { fprintf(stdout, "%8s", "pqg_mod"); } else { fprintf(stdout, "%8d", info->params.asymk.cipherParams.dsa.keysize); } break; -#ifndef NSS_DISABLE_ECC case bltestECDSA: if (td) { fprintf(stdout, "%12s", "ec_curve"); } else { ECPrivateKey *key = (ECPrivateKey *)info->params.asymk.privKey; ECCurveName curveName = key->ecParams.name; fprintf(stdout, "%12s", ecCurve_map[curveName] ? ecCurve_map[curveName]->text : "Unsupported curve"); } break; -#endif case bltestMD2: case bltestMD5: case bltestSHA1: case bltestSHA256: case bltestSHA384: case bltestSHA512: default: break; @@ -3058,29 +3022,27 @@ get_params(PLArenaPool *arena, bltestPar load_file_data(arena, ¶ms->asymk.cipherParams.dsa.keyseed, filename, bltestBase64Encoded); sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "sigseed", j); load_file_data(arena, ¶ms->asymk.cipherParams.dsa.sigseed, filename, bltestBase64Encoded); sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "ciphertext", j); load_file_data(arena, ¶ms->asymk.sig, filename, bltestBase64Encoded); break; -#ifndef NSS_DISABLE_ECC case bltestECDSA: sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "key", j); load_file_data(arena, ¶ms->asymk.key, filename, bltestBase64Encoded); params->asymk.privKey = (void *)eckey_from_filedata(arena, ¶ms->asymk.key.buf); sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "sigseed", j); load_file_data(arena, ¶ms->asymk.cipherParams.ecdsa.sigseed, filename, bltestBase64Encoded); sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "ciphertext", j); load_file_data(arena, ¶ms->asymk.sig, filename, bltestBase64Encoded); break; -#endif case bltestMD2: case bltestMD5: case bltestSHA1: case bltestSHA224: case bltestSHA256: case bltestSHA384: case bltestSHA512: /*params->hash.restart = PR_TRUE;*/ @@ -3292,23 +3254,21 @@ dump_file(bltestCipherMode mode, char *f get_file_data(filename, &item, PR_TRUE); pqg = pqg_from_filedata(&item); dump_pqg(pqg); #endif DSAPrivateKey *key; load_file_data(arena, &keydata, filename, bltestBase64Encoded); key = dsakey_from_filedata(arena, &keydata.buf); dump_dsakey(key); -#ifndef NSS_DISABLE_ECC } else if (mode == bltestECDSA) { ECPrivateKey *key; load_file_data(arena, &keydata, filename, bltestBase64Encoded); key = eckey_from_filedata(arena, &keydata.buf); dump_eckey(key); -#endif } PORT_FreeArena(arena, PR_FALSE); return SECFailure; } void ThreadExecTest(void *data) { @@ -3585,19 +3545,17 @@ enum { opt_SigFile, opt_KeySize, opt_Hex, opt_Input, opt_PQGFile, opt_Key, opt_HexWSpc, opt_Mode, -#ifndef NSS_DISABLE_ECC opt_CurveName, -#endif opt_Output, opt_Repetitions, opt_ZeroBuf, opt_Rounds, opt_Seed, opt_SigSeedFile, opt_CXReps, opt_IV, @@ -3639,19 +3597,17 @@ static secuCommandFlag bltest_options[] { /* opt_SigFile */ 'f', PR_TRUE, 0, PR_FALSE }, { /* opt_KeySize */ 'g', PR_TRUE, 0, PR_FALSE }, { /* opt_Hex */ 'h', PR_FALSE, 0, PR_FALSE }, { /* opt_Input */ 'i', PR_TRUE, 0, PR_FALSE }, { /* opt_PQGFile */ 'j', PR_TRUE, 0, PR_FALSE }, { /* opt_Key */ 'k', PR_TRUE, 0, PR_FALSE }, { /* opt_HexWSpc */ 'l', PR_FALSE, 0, PR_FALSE }, { /* opt_Mode */ 'm', PR_TRUE, 0, PR_FALSE }, -#ifndef NSS_DISABLE_ECC { /* opt_CurveName */ 'n', PR_TRUE, 0, PR_FALSE }, -#endif { /* opt_Output */ 'o', PR_TRUE, 0, PR_FALSE }, { /* opt_Repetitions */ 'p', PR_TRUE, 0, PR_FALSE }, { /* opt_ZeroBuf */ 'q', PR_FALSE, 0, PR_FALSE }, { /* opt_Rounds */ 'r', PR_TRUE, 0, PR_FALSE }, { /* opt_Seed */ 's', PR_TRUE, 0, PR_FALSE }, { /* opt_SigSeedFile */ 't', PR_TRUE, 0, PR_FALSE }, { /* opt_CXReps */ 'u', PR_TRUE, 0, PR_FALSE }, { /* opt_IV */ 'v', PR_TRUE, 0, PR_FALSE }, @@ -3674,19 +3630,17 @@ main(int argc, char **argv) SECStatus rv = SECFailure; double totalTime = 0.0; PRIntervalTime time1, time2; PRFileDesc *outfile = NULL; bltestCipherInfo *cipherInfoListHead, *cipherInfo = NULL; bltestIOMode ioMode; int bufsize, exponent, curThrdNum; -#ifndef NSS_DISABLE_ECC char *curveName = NULL; -#endif int i, commandsEntered; int inoff, outoff; int threads = 1; secuCommand bltest; bltest.numCommands = sizeof(bltest_commands) / sizeof(secuCommandFlag); bltest.numOptions = sizeof(bltest_options) / sizeof(secuCommandFlag); bltest.commands = bltest_commands; @@ -3912,22 +3866,20 @@ main(int argc, char **argv) : (bltest.options[opt_HexWSpc].activated) ? bltestHexSpaceDelim : bltestBinary; if (bltest.options[opt_Exponent].activated) exponent = PORT_Atoi(bltest.options[opt_Exponent].arg); else exponent = 65537; -#ifndef NSS_DISABLE_ECC if (bltest.options[opt_CurveName].activated) curveName = PORT_Strdup(bltest.options[opt_CurveName].arg); else curveName = NULL; -#endif if (bltest.commands[cmd_Verify].activated && !bltest.options[opt_SigFile].activated) { fprintf(stderr, "%s: You must specify a signature file with -f.\n", progName); print_usage: if (cipherInfo) { @@ -4003,21 +3955,17 @@ main(int argc, char **argv) } else { if (bltest.options[opt_KeySize].activated) keysize = PORT_Atoi(bltest.options[opt_KeySize].arg); else keysize = 64; /* use 512-bit default */ file = PR_Open("tmp.key", PR_WRONLY | PR_CREATE_FILE, 00660); } params->key.mode = bltestBase64Encoded; -#ifndef NSS_DISABLE_ECC pubkeyInitKey(cipherInfo, file, keysize, exponent, curveName); -#else - pubkeyInitKey(cipherInfo, file, keysize, exponent); -#endif PR_Close(file); } /* set up an initialization vector. */ if (cipher_requires_IV(cipherInfo->mode)) { char *ivstr = NULL; bltestSymmKeyParams *skp; file = NULL;
--- a/security/nss/cmd/certutil/certutil.c +++ b/security/nss/cmd/certutil/certutil.c @@ -360,17 +360,17 @@ CertReq(SECKEYPrivateKey *privk, SECKEYP static SECStatus ChangeTrustAttributes(CERTCertDBHandle *handle, PK11SlotInfo *slot, char *name, char *trusts, void *pwdata) { SECStatus rv; CERTCertificate *cert; CERTCertTrust *trust; - cert = CERT_FindCertByNicknameOrEmailAddr(handle, name); + cert = CERT_FindCertByNicknameOrEmailAddrCX(handle, name, pwdata); if (!cert) { SECU_PrintError(progName, "could not find certificate named \"%s\"", name); return SECFailure; } trust = (CERTCertTrust *)PORT_ZAlloc(sizeof(CERTCertTrust)); if (!trust) { @@ -1043,25 +1043,20 @@ PrintSyntax(char *progName) FPS "\t%s -E -n cert-name -t trustargs [-d certdir] [-P dbprefix] [-a] [-i input]\n", progName); FPS "\t%s -F -n nickname [-d certdir] [-P dbprefix]\n", progName); FPS "\t%s -G -n key-name [-h token-name] [-k rsa] [-g key-size] [-y exp]\n" "\t\t [-f pwfile] [-z noisefile] [-d certdir] [-P dbprefix]\n", progName); FPS "\t%s -G [-h token-name] -k dsa [-q pqgfile -g key-size] [-f pwfile]\n" "\t\t [-z noisefile] [-d certdir] [-P dbprefix]\n", progName); -#ifndef NSS_DISABLE_ECC FPS "\t%s -G [-h token-name] -k ec -q curve [-f pwfile]\n" "\t\t [-z noisefile] [-d certdir] [-P dbprefix]\n", progName); FPS "\t%s -K [-n key-name] [-h token-name] [-k dsa|ec|rsa|all]\n", progName); -#else - FPS "\t%s -K [-n key-name] [-h token-name] [-k dsa|rsa|all]\n", - progName); -#endif /* NSS_DISABLE_ECC */ FPS "\t\t [-f pwfile] [-X] [-d certdir] [-P dbprefix]\n"); FPS "\t%s --upgrade-merge --source-dir upgradeDir --upgrade-id uniqueID\n", progName); FPS "\t\t [--upgrade-token-name tokenName] [-d targetDBDir]\n"); FPS "\t\t [-P targetDBPrefix] [--source-prefix upgradeDBPrefix]\n"); FPS "\t\t [-f targetPWfile] [-@ upgradePWFile]\n"); FPS "\t%s --merge --source-dir sourceDBDir [-d targetDBdir]\n", progName); @@ -1243,36 +1238,28 @@ luG(enum usage_level ul, const char *com int is_my_command = (command && 0 == strcmp(command, "G")); if (ul == usage_all || !command || is_my_command) FPS "%-15s Generate a new key pair\n", "-G"); if (ul == usage_selected && !is_my_command) return; FPS "%-20s Name of token in which to generate key (default is internal)\n", " -h token-name"); -#ifndef NSS_DISABLE_ECC FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n", " -k key-type"); FPS "%-20s Key size in bits, (min %d, max %d, default %d) (not for ec)\n", " -g key-size", MIN_KEY_BITS, MAX_KEY_BITS, DEFAULT_KEY_BITS); -#else - FPS "%-20s Type of key pair to generate (\"dsa\", \"rsa\" (default))\n", - " -k key-type"); - FPS "%-20s Key size in bits, (min %d, max %d, default %d)\n", - " -g key-size", MIN_KEY_BITS, MAX_KEY_BITS, DEFAULT_KEY_BITS); -#endif /* NSS_DISABLE_ECC */ FPS "%-20s Set the public exponent value (3, 17, 65537) (rsa only)\n", " -y exp"); FPS "%-20s Specify the password file\n", " -f password-file"); FPS "%-20s Specify the noise file to be used\n", " -z noisefile"); FPS "%-20s read PQG value from pqgfile (dsa only)\n", " -q pqgfile"); -#ifndef NSS_DISABLE_ECC FPS "%-20s Elliptic curve name (ec only)\n", " -q curve-name"); FPS "%-20s One of nistp256, nistp384, nistp521, curve25519.\n", ""); FPS "%-20s If a custom token is present, the following curves are also supported:\n", ""); FPS "%-20s sect163k1, nistk163, sect163r1, sect163r2,\n", ""); FPS "%-20s nistb163, sect193r1, sect193r2, sect233k1, nistk233,\n", ""); FPS "%-20s sect233r1, nistb233, sect239k1, sect283k1, nistk283,\n", ""); FPS "%-20s sect283r1, nistb283, sect409k1, nistk409, sect409r1,\n", ""); @@ -1284,17 +1271,16 @@ luG(enum usage_level ul, const char *com FPS "%-20s prime239v1, prime239v2, prime239v3, c2pnb163v1, \n", ""); FPS "%-20s c2pnb163v2, c2pnb163v3, c2pnb176v1, c2tnb191v1, \n", ""); FPS "%-20s c2tnb191v2, c2tnb191v3, \n", ""); FPS "%-20s c2pnb208w1, c2tnb239v1, c2tnb239v2, c2tnb239v3, \n", ""); FPS "%-20s c2pnb272w1, c2pnb304w1, \n", ""); FPS "%-20s c2tnb359w1, c2pnb368w1, c2tnb431r1, secp112r1, \n", ""); FPS "%-20s secp112r2, secp128r1, secp128r2, sect113r1, sect113r2\n", ""); FPS "%-20s sect131r1, sect131r2\n", ""); -#endif FPS "%-20s Key database directory (default is ~/.netscape)\n", " -d keydir"); FPS "%-20s Cert & Key database prefix\n", " -P dbprefix"); FPS "%-20s\n" "%-20s PKCS #11 key Attributes.\n", " --keyAttrFlags attrflags", ""); FPS "%-20s Comma separated list of key attribute attribute flags,\n", ""); @@ -1374,19 +1360,17 @@ luK(enum usage_level ul, const char *com FPS "%-15s List all private keys\n", "-K"); if (ul == usage_selected && !is_my_command) return; FPS "%-20s Name of token to search (\"all\" for all tokens)\n", " -h token-name "); FPS "%-20s Key type (\"all\" (default), \"dsa\"," -#ifndef NSS_DISABLE_ECC " \"ec\"," -#endif " \"rsa\")\n", " -k key-type"); FPS "%-20s The nickname of the key or associated certificate\n", " -n name"); FPS "%-20s Specify the password file\n", " -f password-file"); FPS "%-20s Key database directory (default is ~/.netscape)\n", " -d keydir"); @@ -1519,36 +1503,30 @@ luR(enum usage_level ul, const char *com FPS "%-15s Generate a certificate request (stdout)\n", "-R"); if (ul == usage_selected && !is_my_command) return; FPS "%-20s Specify the subject name (using RFC1485)\n", " -s subject"); FPS "%-20s Output the cert request to this file\n", " -o output-req"); -#ifndef NSS_DISABLE_ECC FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n", -#else - FPS "%-20s Type of key pair to generate (\"dsa\", \"rsa\" (default))\n", -#endif /* NSS_DISABLE_ECC */ " -k key-type-or-id"); FPS "%-20s or nickname of the cert key to use \n", ""); FPS "%-20s Name of token in which to generate key (default is internal)\n", " -h token-name"); FPS "%-20s Key size in bits, RSA keys only (min %d, max %d, default %d)\n", " -g key-size", MIN_KEY_BITS, MAX_KEY_BITS, DEFAULT_KEY_BITS); FPS "%-20s Name of file containing PQG parameters (dsa only)\n", " -q pqgfile"); -#ifndef NSS_DISABLE_ECC FPS "%-20s Elliptic curve name (ec only)\n", " -q curve-name"); FPS "%-20s See the \"-G\" option for a full list of supported names.\n", ""); -#endif /* NSS_DISABLE_ECC */ FPS "%-20s Specify the password file\n", " -f pwfile"); FPS "%-20s Key database directory (default is ~/.netscape)\n", " -d keydir"); FPS "%-20s Cert & Key database prefix\n", " -P dbprefix"); FPS "%-20s Specify the contact phone number (\"123-456-7890\")\n", " -p phone"); @@ -1704,34 +1682,28 @@ luS(enum usage_level ul, const char *com FPS "%-20s Specify the nickname of the cert\n", " -n key-name"); FPS "%-20s Specify the subject name (using RFC1485)\n", " -s subject"); FPS "%-20s The nickname of the issuer cert\n", " -c issuer-name"); FPS "%-20s Set the certificate trust attributes (see -A above)\n", " -t trustargs"); -#ifndef NSS_DISABLE_ECC FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n", -#else - FPS "%-20s Type of key pair to generate (\"dsa\", \"rsa\" (default))\n", -#endif /* NSS_DISABLE_ECC */ " -k key-type-or-id"); FPS "%-20s Name of token in which to generate key (default is internal)\n", " -h token-name"); FPS "%-20s Key size in bits, RSA keys only (min %d, max %d, default %d)\n", " -g key-size", MIN_KEY_BITS, MAX_KEY_BITS, DEFAULT_KEY_BITS); FPS "%-20s Name of file containing PQG parameters (dsa only)\n", " -q pqgfile"); -#ifndef NSS_DISABLE_ECC FPS "%-20s Elliptic curve name (ec only)\n", " -q curve-name"); FPS "%-20s See the \"-G\" option for a full list of supported names.\n", ""); -#endif /* NSS_DISABLE_ECC */ FPS "%-20s Self sign\n", " -x"); FPS "%-20s Cert serial number\n", " -m serial-number"); FPS "%-20s Time Warp\n", " -w warp-months"); FPS "%-20s Months valid (default is 3)\n", " -v months-valid"); @@ -2620,22 +2592,20 @@ certutil_main(int argc, char **argv, PRB if (certutil.options[opt_KeySize].activated) { keysize = PORT_Atoi(certutil.options[opt_KeySize].arg); if ((keysize < MIN_KEY_BITS) || (keysize > MAX_KEY_BITS)) { PR_fprintf(PR_STDERR, "%s -g: Keysize must be between %d and %d.\n", progName, MIN_KEY_BITS, MAX_KEY_BITS); return 255; } -#ifndef NSS_DISABLE_ECC if (keytype == ecKey) { PR_fprintf(PR_STDERR, "%s -g: Not for ec keys.\n", progName); return 255; } -#endif /* NSS_DISABLE_ECC */ } /* -h specify token name */ if (certutil.options[opt_TokenName].activated) { if (PL_strcmp(certutil.options[opt_TokenName].arg, "all") == 0) slotname = NULL; else slotname = certutil.options[opt_TokenName].arg; @@ -2654,20 +2624,18 @@ certutil_main(int argc, char **argv, PRB /* -k key type */ if (certutil.options[opt_KeyType].activated) { char *arg = certutil.options[opt_KeyType].arg; if (PL_strcmp(arg, "rsa") == 0) { keytype = rsaKey; } else if (PL_strcmp(arg, "dsa") == 0) { keytype = dsaKey; -#ifndef NSS_DISABLE_ECC } else if (PL_strcmp(arg, "ec") == 0) { keytype = ecKey; -#endif /* NSS_DISABLE_ECC */ } else if (PL_strcmp(arg, "all") == 0) { keytype = nullKey; } else { /* use an existing private/public key pair */ keysource = arg; } } else if (certutil.commands[cmd_ListKeys].activated) { keytype = nullKey; @@ -2710,26 +2678,20 @@ certutil_main(int argc, char **argv, PRB srcCertPrefix = certutil.options[opt_SourcePrefix].arg; } else { Usage(progName); } } /* -q PQG file or curve name */ if (certutil.options[opt_PQGFile].activated) { -#ifndef NSS_DISABLE_ECC if ((keytype != dsaKey) && (keytype != ecKey)) { PR_fprintf(PR_STDERR, "%s -q: specifies a PQG file for DSA keys" " (-k dsa) or a named curve for EC keys (-k ec)\n)", progName); -#else /* } */ - if (keytype != dsaKey) { - PR_fprintf(PR_STDERR, "%s -q: PQG file is for DSA key (-k dsa).\n)", - progName); -#endif /* NSS_DISABLE_ECC */ return 255; } } /* -s subject name */ if (certutil.options[opt_Subject].activated) { subject = CERT_AsciiToName(certutil.options[opt_Subject].arg); if (!subject) {
--- a/security/nss/cmd/certutil/keystuff.c +++ b/security/nss/cmd/certutil/keystuff.c @@ -375,17 +375,16 @@ CERTUTIL_FileForRNG(const char *noise) PK11_RandomUpdate(buf, count); } } while (count > 0); PR_Close(fd); return SECSuccess; } -#ifndef NSS_DISABLE_ECC typedef struct curveNameTagPairStr { char *curveName; SECOidTag curveOidTag; } CurveNameTagPair; static CurveNameTagPair nameTagPair[] = { { "sect163k1", SEC_OID_SECG_EC_SECT163K1 }, @@ -490,28 +489,27 @@ getECParams(const char *curve) if ((curveOidTag == SEC_OID_UNKNOWN) || (oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) { fprintf(stderr, "Unrecognized elliptic curve %s\n", curve); return NULL; } ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len)); - /* + /* * ecparams->data needs to contain the ASN encoding of an object ID (OID) - * representing the named curve. The actual OID is in + * representing the named curve. The actual OID is in * oidData->oid.data so we simply prepend 0x06 and OID length */ ecparams->data[0] = SEC_ASN1_OBJECT_ID; ecparams->data[1] = oidData->oid.len; memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len); return ecparams; } -#endif /* NSS_DISABLE_ECC */ SECKEYPrivateKey * CERTUTIL_GeneratePrivateKey(KeyType keytype, PK11SlotInfo *slot, int size, int publicExponent, const char *noise, SECKEYPublicKey **pubkeyp, const char *pqgFile, PK11AttrFlags attrFlags, CK_FLAGS opFlagsOn, CK_FLAGS opFlagsOff, secuPWData *pwdata) { @@ -559,24 +557,22 @@ CERTUTIL_GeneratePrivateKey(KeyType keyt if (dsaparams == NULL) return NULL; params = dsaparams; } else { /* cast away const, and don't set dsaparams */ params = (void *)&default_pqg_params; } break; -#ifndef NSS_DISABLE_ECC case ecKey: mechanism = CKM_EC_KEY_PAIR_GEN; /* For EC keys, PQGFile determines EC parameters */ if ((params = (void *)getECParams(pqgFile)) == NULL) return NULL; break; -#endif /* NSS_DISABLE_ECC */ default: return NULL; } fprintf(stderr, "\n\n"); fprintf(stderr, "Generating key. This may take a few moments...\n\n"); privKey = PK11_GenerateKeyPairWithOpFlags(slot, mechanism, params, pubkeyp, @@ -584,18 +580,16 @@ CERTUTIL_GeneratePrivateKey(KeyType keyt opFlagsOff, pwdata /*wincx*/); /* free up the params */ switch (keytype) { case dsaKey: if (dsaparams) CERTUTIL_DestroyParamsPQG(dsaparams); break; -#ifndef NSS_DISABLE_ECC case ecKey: SECITEM_FreeItem((SECItem *)params, PR_TRUE); break; -#endif default: /* nothing to free */ break; } return privKey; }
--- a/security/nss/cmd/fipstest/fipstest.c +++ b/security/nss/cmd/fipstest/fipstest.c @@ -30,23 +30,21 @@ #undef CK_NEED_ARG_LIST #undef __PASTE #define SSL3_RANDOM_LENGTH 32 #if 0 #include "../../lib/freebl/mpi/mpi.h" #endif -#ifndef NSS_DISABLE_ECC extern SECStatus EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams); extern SECStatus EC_CopyParams(PLArenaPool *arena, ECParams *dstParams, const ECParams *srcParams); -#endif #define ENCRYPT 1 #define DECRYPT 0 #define BYTE unsigned char #define DEFAULT_RSA_PUBLIC_EXPONENT 0x10001 #define RSA_MAX_TEST_MODULUS_BITS 4096 #define RSA_MAX_TEST_MODULUS_BYTES RSA_MAX_TEST_MODULUS_BITS / 8 #define RSA_MAX_TEST_EXPONENT_BYTES 8 @@ -2089,17 +2087,16 @@ get_next_line(FILE *req, char *key, char } else { writeto[w++] = c; } } writeto[w] = '\0'; return (c == EOF) ? -1 : ignore; } -#ifndef NSS_DISABLE_ECC typedef struct curveNameTagPairStr { char *curveName; SECOidTag curveOidTag; } CurveNameTagPair; #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP192R1 /* #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP160R1 */ @@ -2953,17 +2950,16 @@ ecdsa_sigver_test(char *reqfn) } } loser: if (ecpub.ecParams.arena != NULL) { PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE); } fclose(ecdsareq); } -#endif /* NSS_DISABLE_ECC */ PRBool isblankline(char *b) { while (isspace(*b)) b++; if ((*b == '\n') || (*b == 0)) { return PR_TRUE; @@ -6089,17 +6085,16 @@ main(int argc, char **argv) dsa_pqgver_test(argv[3]); } else if (strcmp(argv[2], "siggen") == 0) { /* Signature Generation Test */ dsa_siggen_test(argv[3]); } else if (strcmp(argv[2], "sigver") == 0) { /* Signature Verification Test */ dsa_sigver_test(argv[3]); } -#ifndef NSS_DISABLE_ECC /*************/ /* ECDSA */ /*************/ } else if (strcmp(argv[1], "ecdsa") == 0) { /* argv[2]=keypair|pkv|siggen|sigver argv[3]=<test name>.req */ if (strcmp(argv[2], "keypair") == 0) { /* Key Pair Generation Test */ ecdsa_keypair_test(argv[3]); @@ -6108,17 +6103,16 @@ main(int argc, char **argv) ecdsa_pkv_test(argv[3]); } else if (strcmp(argv[2], "siggen") == 0) { /* Signature Generation Test */ ecdsa_siggen_test(argv[3]); } else if (strcmp(argv[2], "sigver") == 0) { /* Signature Verification Test */ ecdsa_sigver_test(argv[3]); } -#endif /* NSS_DISABLE_ECC */ /*************/ /* RNG */ /*************/ } else if (strcmp(argv[1], "rng") == 0) { /* argv[2]=vst|mct argv[3]=<test name>.req */ if (strcmp(argv[2], "vst") == 0) { /* Variable Seed Test */ rng_vst(argv[3]);
--- a/security/nss/cmd/lib/secutil.c +++ b/security/nss/cmd/lib/secutil.c @@ -479,58 +479,16 @@ SECU_ConfigDirectory(const char *base) if (buf[strlen(buf) - 1] == '/') buf[strlen(buf) - 1] = 0; } initted = PR_TRUE; return buf; } -/*Turn off SSL for now */ -/* This gets called by SSL when server wants our cert & key */ -int -SECU_GetClientAuthData(void *arg, PRFileDesc *fd, - struct CERTDistNamesStr *caNames, - struct CERTCertificateStr **pRetCert, - struct SECKEYPrivateKeyStr **pRetKey) -{ - SECKEYPrivateKey *key; - CERTCertificate *cert; - int errsave; - - if (arg == NULL) { - fprintf(stderr, "no key/cert name specified for client auth\n"); - return -1; - } - cert = PK11_FindCertFromNickname(arg, NULL); - errsave = PORT_GetError(); - if (!cert) { - if (errsave == SEC_ERROR_BAD_PASSWORD) - fprintf(stderr, "Bad password\n"); - else if (errsave > 0) - fprintf(stderr, "Unable to read cert (error %d)\n", errsave); - else if (errsave == SEC_ERROR_BAD_DATABASE) - fprintf(stderr, "Unable to get cert from database (%d)\n", errsave); - else - fprintf(stderr, "SECKEY_FindKeyByName: internal error %d\n", errsave); - return -1; - } - - key = PK11_FindKeyByAnyCert(arg, NULL); - if (!key) { - fprintf(stderr, "Unable to get key (%d)\n", PORT_GetError()); - return -1; - } - - *pRetCert = cert; - *pRetKey = key; - - return 0; -} - SECStatus SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii, PRBool warnOnPrivateKeyInAsciiFile) { SECStatus rv; if (ascii) { /* First convert ascii to binary */ SECItem filedata; @@ -1404,17 +1362,16 @@ secu_PrintAttribute(FILE *out, SEC_PKCS7 SECU_PrintTimeChoice(out, value, om, level + 1); break; } } } } } -#ifndef NSS_DISABLE_ECC static void secu_PrintECPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level) { SECItem curveOID = { siBuffer, NULL, 0 }; SECU_Indent(out, level); fprintf(out, "%s:\n", m); SECU_PrintInteger(out, &pk->u.ec.publicValue, "PublicValue", level + 1); @@ -1423,17 +1380,16 @@ secu_PrintECPublicKey(FILE *out, SECKEYP */ if ((pk->u.ec.DEREncodedParams.len > 2) && (pk->u.ec.DEREncodedParams.data[0] == 0x06)) { curveOID.len = pk->u.ec.DEREncodedParams.data[1]; curveOID.data = pk->u.ec.DEREncodedParams.data + 2; SECU_PrintObjectID(out, &curveOID, "Curve", level + 1); } } -#endif /* NSS_DISABLE_ECC */ void SECU_PrintRSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level) { SECU_Indent(out, level); fprintf(out, "%s:\n", m); SECU_PrintInteger(out, &pk->u.rsa.modulus, "Modulus", level + 1); SECU_PrintInteger(out, &pk->u.rsa.publicExponent, "Exponent", level + 1); @@ -1471,21 +1427,19 @@ secu_PrintSubjectPublicKeyInfo(FILE *out case rsaKey: SECU_PrintRSAPublicKey(out, pk, "RSA Public Key", level + 1); break; case dsaKey: SECU_PrintDSAPublicKey(out, pk, "DSA Public Key", level + 1); break; -#ifndef NSS_DISABLE_ECC case ecKey: secu_PrintECPublicKey(out, pk, "EC Public Key", level + 1); break; -#endif case dhKey: case fortezzaKey: case keaKey: SECU_Indent(out, level); fprintf(out, "unable to format this SPKI algorithm type\n"); goto loser; default: @@ -3628,54 +3582,16 @@ SECU_DerSignDataCRL(PLArenaPool *arena, goto loser; } loser: PORT_Free(it.data); return rv; } -#if 0 - -/* we need access to the private function cert_FindExtension for this code to work */ - -CERTAuthKeyID * -SECU_FindCRLAuthKeyIDExten (PLArenaPool *arena, CERTSignedCrl *scrl) -{ - SECItem encodedExtenValue; - SECStatus rv; - CERTAuthKeyID *ret; - CERTCrl* crl; - - if (!scrl) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return NULL; - } - - crl = &scrl->crl; - - encodedExtenValue.data = NULL; - encodedExtenValue.len = 0; - - rv = cert_FindExtension(crl->extensions, SEC_OID_X509_AUTH_KEY_ID, - &encodedExtenValue); - if ( rv != SECSuccess ) { - return (NULL); - } - - ret = CERT_DecodeAuthKeyID (arena, &encodedExtenValue); - - PORT_Free(encodedExtenValue.data); - encodedExtenValue.data = NULL; - - return(ret); -} - -#endif - /* * Find the issuer of a Crl. Use the authorityKeyID if it exists. */ CERTCertificate * SECU_FindCrlIssuer(CERTCertDBHandle *dbhandle, SECItem *subject, CERTAuthKeyID *authorityKeyID, PRTime validTime) { CERTCertificate *issuerCert = NULL; @@ -3739,17 +3655,17 @@ SECU_EncodeAndAddExtensionValue(PLArenaP } CERTCertificate * SECU_FindCertByNicknameOrFilename(CERTCertDBHandle *handle, char *name, PRBool ascii, void *pwarg) { CERTCertificate *the_cert; - the_cert = CERT_FindCertByNicknameOrEmailAddr(handle, name); + the_cert = CERT_FindCertByNicknameOrEmailAddrCX(handle, name, pwarg); if (the_cert) { return the_cert; } the_cert = PK11_FindCertFromNickname(name, pwarg); if (!the_cert) { /* Don't have a cert with name "name" in the DB. Try to * open a file with such name and get the cert from there.*/ SECStatus rv;
--- a/security/nss/cmd/selfserv/selfserv.c +++ b/security/nss/cmd/selfserv/selfserv.c @@ -160,19 +160,17 @@ PrintUsageHeader(const char *progName) { fprintf(stderr, "Usage: %s -n rsa_nickname -p port [-BDENRZbjlmrsuvx] [-w password]\n" " [-t threads] [-i pid_file] [-c ciphers] [-Y] [-d dbdir] [-g numblocks]\n" " [-f password_file] [-L [seconds]] [-M maxProcs] [-P dbprefix]\n" " [-V [min-version]:[max-version]] [-a sni_name]\n" " [ T <good|revoked|unknown|badsig|corrupted|none|ocsp>] [-A ca]\n" " [-C SSLCacheEntries] [-S dsa_nickname] -Q [-I groups]" -#ifndef NSS_DISABLE_ECC " [-e ec_nickname]" -#endif /* NSS_DISABLE_ECC */ "\n" " -U [0|1] -H [0|1|2] -W [0|1]\n" "\n", progName); } static void PrintParameterUsage() @@ -2338,25 +2336,23 @@ main(int argc, char **argv) case 'c': cipherString = PORT_Strdup(optstate->value); break; case 'd': dir = optstate->value; break; -#ifndef NSS_DISABLE_ECC case 'e': if (certNicknameIndex >= MAX_CERT_NICKNAME_ARRAY_INDEX) { Usage(progName); break; } certNicknameArray[certNicknameIndex++] = PORT_Strdup(optstate->value); break; -#endif /* NSS_DISABLE_ECC */ case 'f': pwdata.source = PW_FROMFILE; pwdata.data = pwfile = PORT_Strdup(optstate->value); break; case 'g': testBulk = PR_TRUE; @@ -2676,19 +2672,17 @@ main(int argc, char **argv) exit(10); } privKey[i] = PK11_FindKeyByAnyCert(cert[i], &pwdata); if (privKey[i] == NULL) { fprintf(stderr, "selfserv: Can't find Private Key for cert %s\n", certNicknameArray[i]); exit(11); } -#ifdef NSS_DISABLE_ECC if (privKey[i]->keyType != ecKey) -#endif setupCertStatus(certStatusArena, ocspStaplingMode, cert[i], i, &pwdata); } if (configureWeakDHE > 0) { fprintf(stderr, "selfserv: Creating dynamic weak DH parameters\n"); rv = SSL_EnableWeakDHEPrimeGroup(NULL, PR_TRUE); if (rv != SECSuccess) { goto cleanup;
--- a/security/nss/coreconf/config.mk +++ b/security/nss/coreconf/config.mk @@ -141,20 +141,16 @@ endif ####################################################################### -include $(MKDEPENDENCIES) ####################################################################### # [16.0] Global environ ment defines ####################################################################### -ifdef NSS_DISABLE_ECC -DEFINES += -DNSS_DISABLE_ECC -endif - ifdef NSS_ALLOW_UNSUPPORTED_CRITICAL DEFINES += -DNSS_ALLOW_UNSUPPORTED_CRITICAL endif ifdef BUILD_LIBPKIX_TESTS DEFINES += -DBUILD_LIBPKIX_TESTS endif
--- a/security/nss/coreconf/coreconf.dep +++ b/security/nss/coreconf/coreconf.dep @@ -5,8 +5,9 @@ /* * A dummy header file that is a dependency for all the object files. * Used to force a full recompilation of NSS in Mozilla's Tinderbox * depend builds. See comments in rules.mk. */ #error "Do not include this header file." +
--- a/security/nss/fuzz/mpi_expmod_target.cc +++ b/security/nss/fuzz/mpi_expmod_target.cc @@ -14,19 +14,22 @@ extern "C" int LLVMFuzzerTestOneInput(co if (size < 3) { return 0; } INIT_FOUR_NUMBERS auto modulus = get_modulus(data, size, ctx); // Compare with OpenSSL exp mod m1 = &std::get<1>(modulus); - print_bn("A", A); - print_bn("B", B); - print_bn("m", std::get<0>(modulus)); + // The exponent b (B) can get really big. Make it smaller if necessary. + if (MP_USED(&b) > 100) { + size_t shift = (MP_USED(&b) - 100) * MP_DIGIT_BIT; + mp_div_2d(&b, shift, &b, nullptr); + BN_rshift(B, B, shift); + } check_equal(A, &a, max_size); check_equal(B, &b, max_size); check_equal(std::get<0>(modulus), m1, 3 * max_size); assert(mp_exptmod(&a, &b, m1, &c) == MP_OKAY); (void)BN_mod_exp(C, A, B, std::get<0>(modulus), ctx); check_equal(C, &c, 2 * max_size); CLEANUP_AND_RETURN
new file mode 100644 --- /dev/null +++ b/security/nss/gtests/freebl_gtest/blake2b_unittest.cc @@ -0,0 +1,277 @@ +/* + * blake2b_unittest.cc - unittests for blake2b hash function + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "blapi.h" +#include "nspr.h" +#include "nss.h" +#include "secerr.h" + +#include <cstdlib> +#include <iostream> +#include <memory> + +#define GTEST_HAS_RTTI 0 +#include "gtest/gtest.h" + +#include "kat/blake2b_kat.h" + +template <class T> +struct ScopedDelete { + void operator()(T* ptr) { + if (ptr) { + BLAKE2B_DestroyContext(ptr, PR_TRUE); + } + } +}; + +typedef std::unique_ptr<BLAKE2BContext, ScopedDelete<BLAKE2BContext>> + ScopedBLAKE2BContext; + +class Blake2BTests : public ::testing::Test {}; + +class Blake2BKAT + : public ::testing::TestWithParam<std::pair<int, std::vector<uint8_t>>> {}; + +class Blake2BKATUnkeyed : public Blake2BKAT {}; +class Blake2BKATKeyed : public Blake2BKAT {}; + +TEST_P(Blake2BKATUnkeyed, Unkeyed) { + std::vector<uint8_t> values(BLAKE2B512_LENGTH); + SECStatus rv = + BLAKE2B_HashBuf(values.data(), kat_data.data(), std::get<0>(GetParam())); + ASSERT_EQ(SECSuccess, rv); + EXPECT_EQ(values, std::get<1>(GetParam())); +} + +TEST_P(Blake2BKATKeyed, Keyed) { + std::vector<uint8_t> values(BLAKE2B512_LENGTH); + SECStatus rv = BLAKE2B_MAC_HashBuf(values.data(), kat_data.data(), + std::get<0>(GetParam()), key.data(), + BLAKE2B_KEY_SIZE); + ASSERT_EQ(SECSuccess, rv); + EXPECT_EQ(values, std::get<1>(GetParam())); +} + +INSTANTIATE_TEST_CASE_P(UnkeyedKAT, Blake2BKATUnkeyed, + ::testing::ValuesIn(TestcasesUnkeyed)); +INSTANTIATE_TEST_CASE_P(KeyedKAT, Blake2BKATKeyed, + ::testing::ValuesIn(TestcasesKeyed)); + +TEST_F(Blake2BTests, ContextTest) { + ScopedBLAKE2BContext ctx(BLAKE2B_NewContext()); + ASSERT_TRUE(ctx) << "BLAKE2B_NewContext failed!"; + + SECStatus rv = BLAKE2B_Begin(ctx.get()); + ASSERT_EQ(SECSuccess, rv); + + size_t src_length = 252; + const size_t quarter = 63; + + for (int i = 0; i < 4 && src_length > 0; i++) { + rv = BLAKE2B_Update(ctx.get(), kat_data.data() + i * quarter, + PR_MIN(quarter, src_length)); + ASSERT_EQ(SECSuccess, rv); + + size_t len = BLAKE2B_FlattenSize(ctx.get()); + std::vector<unsigned char> ctxbytes(len); + rv = BLAKE2B_Flatten(ctx.get(), ctxbytes.data()); + ASSERT_EQ(SECSuccess, rv); + ScopedBLAKE2BContext ctx_cpy(BLAKE2B_Resurrect(ctxbytes.data(), NULL)); + ASSERT_TRUE(ctx_cpy) << "BLAKE2B_Resurrect failed!"; + ASSERT_EQ(SECSuccess, PORT_Memcmp(ctx.get(), ctx_cpy.get(), len)); + src_length -= quarter; + } + ASSERT_EQ(0U, src_length); + + std::vector<uint8_t> digest(BLAKE2B512_LENGTH); + rv = BLAKE2B_End(ctx.get(), digest.data(), nullptr, BLAKE2B512_LENGTH); + ASSERT_EQ(SECSuccess, rv); + ASSERT_EQ(std::get<1>(TestcasesUnkeyed[252]), digest) + << "BLAKE2B_End failed!"; +} + +TEST_F(Blake2BTests, ContextTest2) { + ScopedBLAKE2BContext ctx(BLAKE2B_NewContext()); + ASSERT_TRUE(ctx) << "BLAKE2B_NewContext failed!"; + + SECStatus rv = BLAKE2B_Begin(ctx.get()); + ASSERT_EQ(SECSuccess, rv); + + rv = BLAKE2B_Update(ctx.get(), kat_data.data(), 128); + ASSERT_EQ(SECSuccess, rv); + rv = BLAKE2B_Update(ctx.get(), kat_data.data() + 128, 127); + ASSERT_EQ(SECSuccess, rv); + + std::vector<uint8_t> digest(BLAKE2B512_LENGTH); + rv = BLAKE2B_End(ctx.get(), digest.data(), nullptr, BLAKE2B512_LENGTH); + ASSERT_EQ(SECSuccess, rv); + ASSERT_EQ(std::get<1>(TestcasesUnkeyed[255]), digest) + << "BLAKE2B_End failed!"; +} + +TEST_F(Blake2BTests, CloneTest) { + ScopedBLAKE2BContext ctx(BLAKE2B_NewContext()); + ScopedBLAKE2BContext cloned_ctx(BLAKE2B_NewContext()); + ASSERT_TRUE(ctx) << "BLAKE2B_NewContext failed!"; + ASSERT_TRUE(cloned_ctx) << "BLAKE2B_NewContext failed!"; + + SECStatus rv = BLAKE2B_Begin(ctx.get()); + ASSERT_EQ(SECSuccess, rv); + rv = BLAKE2B_Update(ctx.get(), kat_data.data(), 255); + ASSERT_EQ(SECSuccess, rv); + BLAKE2B_Clone(cloned_ctx.get(), ctx.get()); + + std::vector<uint8_t> digest(BLAKE2B512_LENGTH); + rv = BLAKE2B_End(cloned_ctx.get(), digest.data(), nullptr, BLAKE2B512_LENGTH); + ASSERT_EQ(SECSuccess, rv); + ASSERT_EQ(std::get<1>(TestcasesUnkeyed[255]), digest) + << "BLAKE2B_End failed!"; +} + +TEST_F(Blake2BTests, NullTest) { + std::vector<uint8_t> digest(BLAKE2B512_LENGTH); + SECStatus rv = BLAKE2B_HashBuf(digest.data(), nullptr, 0); + ASSERT_EQ(SECSuccess, rv); + EXPECT_EQ(std::get<1>(TestcasesUnkeyed[0]), digest); + + digest = std::vector<uint8_t>(BLAKE2B512_LENGTH); + rv = BLAKE2B_MAC_HashBuf(digest.data(), nullptr, 0, key.data(), + BLAKE2B_KEY_SIZE); + ASSERT_EQ(SECSuccess, rv); + EXPECT_EQ(std::get<1>(TestcasesKeyed[0]), digest); +} + +TEST_F(Blake2BTests, HashTest) { + ScopedBLAKE2BContext ctx(BLAKE2B_NewContext()); + ASSERT_TRUE(ctx) << "BLAKE2B_NewContext failed!"; + + std::vector<uint8_t> digest(BLAKE2B512_LENGTH); + SECStatus rv = BLAKE2B_Hash(digest.data(), "abc"); + std::vector<uint8_t> expected = { + 0xba, 0x80, 0xa5, 0x3f, 0x98, 0x1c, 0x4d, 0x0d, 0x6a, 0x27, 0x97, + 0xb6, 0x9f, 0x12, 0xf6, 0xe9, 0x4c, 0x21, 0x2f, 0x14, 0x68, 0x5a, + 0xc4, 0xb7, 0x4b, 0x12, 0xbb, 0x6f, 0xdb, 0xff, 0xa2, 0xd1, 0x7d, + 0x87, 0xc5, 0x39, 0x2a, 0xab, 0x79, 0x2d, 0xc2, 0x52, 0xd5, 0xde, + 0x45, 0x33, 0xcc, 0x95, 0x18, 0xd3, 0x8a, 0xa8, 0xdb, 0xf1, 0x92, + 0x5a, 0xb9, 0x23, 0x86, 0xed, 0xd4, 0x00, 0x99, 0x23}; + ASSERT_EQ(SECSuccess, rv); + EXPECT_EQ(expected, digest); +} + +TEST_F(Blake2BTests, LongHashTest) { + ScopedBLAKE2BContext ctx(BLAKE2B_NewContext()); + ASSERT_TRUE(ctx) << "BLAKE2B_NewContext failed!"; + + std::vector<uint8_t> digest(BLAKE2B512_LENGTH); + SECStatus rv = BLAKE2B_Hash( + digest.data(), + "qwertzuiopasdfghjklyxcvbnm123456789qwertzuiopasdfghjklyxcvbnm123456789qw" + "ertzuiopasdfghjklyxcvbnm123456789qwertzuiopasdfghjklyxcvbnm123456789qwer" + "tzuiopasdfghjklyxcvbnm123456789qwertzuiopasdfghjklyxcvbnm123456789qwertz" + "uiopasdfghjklyxcvbnm123456789qwertzuiopasdfghjklyxcvbnm123456789"); + std::vector<uint8_t> expected = { + 0x1f, 0x9e, 0xe6, 0x5a, 0xa0, 0x36, 0x05, 0xfc, 0x41, 0x0e, 0x2f, + 0x55, 0x96, 0xfd, 0xb5, 0x9d, 0x85, 0x95, 0x5e, 0x24, 0x37, 0xe7, + 0x0d, 0xe4, 0xa0, 0x22, 0x4a, 0xe1, 0x59, 0x1f, 0x97, 0x03, 0x57, + 0x54, 0xf0, 0xca, 0x92, 0x75, 0x2f, 0x9e, 0x86, 0xeb, 0x82, 0x4f, + 0x9c, 0xf4, 0x02, 0x17, 0x7f, 0x76, 0x56, 0x26, 0x46, 0xf4, 0x07, + 0xfd, 0x1f, 0x78, 0xdb, 0x7b, 0x0d, 0x24, 0x43, 0xf0}; + ASSERT_EQ(SECSuccess, rv); + EXPECT_EQ(expected, digest); +} + +TEST_F(Blake2BTests, TruncatedHashTest) { + ScopedBLAKE2BContext ctx(BLAKE2B_NewContext()); + ASSERT_TRUE(ctx) << "BLAKE2B_NewContext failed!"; + + SECStatus rv = BLAKE2B_Begin(ctx.get()); + ASSERT_EQ(SECSuccess, rv); + + rv = BLAKE2B_Update(ctx.get(), kat_data.data(), 128); + ASSERT_EQ(SECSuccess, rv); + rv = BLAKE2B_Update(ctx.get(), kat_data.data() + 128, 127); + ASSERT_EQ(SECSuccess, rv); + + size_t max_digest_len = BLAKE2B512_LENGTH - 5; + std::vector<uint8_t> digest(max_digest_len); + unsigned int digest_len; + rv = BLAKE2B_End(ctx.get(), digest.data(), &digest_len, max_digest_len); + ASSERT_EQ(SECSuccess, rv); + ASSERT_EQ(digest.size(), digest_len); + ASSERT_EQ(0, memcmp(std::get<1>(TestcasesUnkeyed[255]).data(), digest.data(), + max_digest_len)) + << "BLAKE2B_End failed!"; +} + +TEST_F(Blake2BTests, TruncatedHashTest2) { + ScopedBLAKE2BContext ctx(BLAKE2B_NewContext()); + ASSERT_TRUE(ctx) << "BLAKE2B_NewContext failed!"; + + SECStatus rv = BLAKE2B_Begin(ctx.get()); + ASSERT_EQ(SECSuccess, rv); + + rv = BLAKE2B_Update(ctx.get(), kat_data.data(), 128); + ASSERT_EQ(SECSuccess, rv); + rv = BLAKE2B_Update(ctx.get(), kat_data.data() + 128, 127); + ASSERT_EQ(SECSuccess, rv); + + size_t max_digest_len = BLAKE2B512_LENGTH - 60; + std::vector<uint8_t> digest(max_digest_len); + unsigned int digest_len; + rv = BLAKE2B_End(ctx.get(), digest.data(), &digest_len, max_digest_len); + ASSERT_EQ(SECSuccess, rv); + ASSERT_EQ(digest.size(), digest_len); +} + +TEST_F(Blake2BTests, OverlongKeyTest) { + ScopedBLAKE2BContext ctx(BLAKE2B_NewContext()); + ASSERT_TRUE(ctx) << "BLAKE2B_NewContext failed!"; + + std::vector<uint8_t> key = { + 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, + 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, + 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, + 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, + 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35}; + std::vector<uint8_t> data = {0x61, 0x62, 0x63}; + + std::vector<uint8_t> digest(BLAKE2B512_LENGTH); + SECStatus rv = + BLAKE2B_MAC_HashBuf(digest.data(), data.data(), 3, key.data(), 65); + EXPECT_EQ(SECFailure, rv); + EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); +} + +TEST_F(Blake2BTests, EmptyKeyTest) { + ScopedBLAKE2BContext ctx(BLAKE2B_NewContext()); + ASSERT_TRUE(ctx) << "BLAKE2B_NewContext failed!"; + + uint8_t key[1]; // A vector.data() would give us a nullptr. + std::vector<uint8_t> data = {0x61, 0x62, 0x63}; + + std::vector<uint8_t> digest(BLAKE2B512_LENGTH); + SECStatus rv = BLAKE2B_MAC_HashBuf(digest.data(), data.data(), 3, key, 0); + EXPECT_EQ(SECFailure, rv); + EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); +} + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + + if (NSS_NoDB_Init(nullptr) != SECSuccess) { + return 1; + } + + int rv = RUN_ALL_TESTS(); + + if (NSS_Shutdown() != SECSuccess) { + return 1; + } + + return rv; +}
--- a/security/nss/gtests/freebl_gtest/freebl_gtest.gyp +++ b/security/nss/gtests/freebl_gtest/freebl_gtest.gyp @@ -3,91 +3,103 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. { 'includes': [ '../../coreconf/config.gypi', '../common/gtest.gypi', ], 'targets': [ { - 'target_name': 'freebl_gtest', - 'type': 'executable', - 'sources': [ - 'mpi_unittest.cc', - 'dh_unittest.cc', - 'ecl_unittest.cc', - 'ghash_unittest.cc', - '<(DEPTH)/gtests/common/gtests.cc' - ], + # Dependencies for tests. + 'target_name': 'freebl_gtest_deps', + 'type': 'none', 'dependencies': [ - '<(DEPTH)/exports.gyp:nss_exports', '<(DEPTH)/lib/util/util.gyp:nssutil3', '<(DEPTH)/gtests/google_test/google_test.gyp:gtest', '<(DEPTH)/lib/nss/nss.gyp:nss_static', '<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap_static', '<(DEPTH)/lib/cryptohi/cryptohi.gyp:cryptohi', '<(DEPTH)/lib/certhigh/certhigh.gyp:certhi', '<(DEPTH)/lib/certdb/certdb.gyp:certdb', '<(DEPTH)/lib/base/base.gyp:nssb', '<(DEPTH)/lib/dev/dev.gyp:nssdev', '<(DEPTH)/lib/pki/pki.gyp:nsspki', '<(DEPTH)/lib/ssl/ssl.gyp:ssl', ], }, { + 'target_name': 'freebl_gtest', + 'type': 'executable', + 'sources': [ + 'mpi_unittest.cc', + 'dh_unittest.cc', + 'ecl_unittest.cc', + 'ghash_unittest.cc', + '<(DEPTH)/gtests/common/gtests.cc' + ], + 'dependencies': [ + 'freebl_gtest_deps', + '<(DEPTH)/exports.gyp:nss_exports', + ], + }, + { 'target_name': 'prng_gtest', 'type': 'executable', 'sources': [ 'prng_kat_unittest.cc', ], 'dependencies': [ + 'freebl_gtest_deps', '<(DEPTH)/exports.gyp:nss_exports', - '<(DEPTH)/lib/util/util.gyp:nssutil3', - '<(DEPTH)/gtests/google_test/google_test.gyp:gtest', - '<(DEPTH)/lib/nss/nss.gyp:nss_static', - '<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap_static', - '<(DEPTH)/lib/cryptohi/cryptohi.gyp:cryptohi', - '<(DEPTH)/lib/certhigh/certhigh.gyp:certhi', - '<(DEPTH)/lib/certdb/certdb.gyp:certdb', - '<(DEPTH)/lib/base/base.gyp:nssb', - '<(DEPTH)/lib/dev/dev.gyp:nssdev', - '<(DEPTH)/lib/pki/pki.gyp:nsspki', - '<(DEPTH)/lib/ssl/ssl.gyp:ssl', - '<(DEPTH)/lib/libpkix/libpkix.gyp:libpkix', ], - 'conditions': [ - [ 'OS=="win"', { - 'libraries': [ - 'advapi32.lib', - ], - }], + }, + { + 'target_name': 'blake2b_gtest', + 'type': 'executable', + 'sources': [ + 'blake2b_unittest.cc', ], - 'defines': [ - 'NSS_USE_STATIC_LIBS' + 'dependencies': [ + 'freebl_gtest_deps', + '<(DEPTH)/exports.gyp:nss_exports', ], }, ], 'target_defaults': { 'include_dirs': [ + '<(DEPTH)/lib/freebl/ecl', '<(DEPTH)/lib/freebl/mpi', '<(DEPTH)/lib/freebl/', + '<(DEPTH)/lib/ssl/', + '<(DEPTH)/lib/util/', + '<(DEPTH)/lib/certdb/', + '<(DEPTH)/lib/cryptohi/', + '<(DEPTH)/lib/pk11wrap/', + ], + 'defines': [ + 'NSS_USE_STATIC_LIBS', ], # For test builds we have to set MPI defines. 'conditions': [ [ 'ct_verif==1', { 'defines': [ 'CT_VERIF', ], }], [ 'target_arch=="ia32"', { 'defines': [ 'MP_USE_UINT_DIGIT', 'MP_ASSEMBLY_MULTIPLY', 'MP_ASSEMBLY_SQUARE', 'MP_ASSEMBLY_DIV_2DX1D', ], }], + [ 'OS=="win"', { + 'libraries': [ + 'advapi32.lib', + ], + }], ], }, 'variables': { 'module': 'nss' } }
new file mode 100644 --- /dev/null +++ b/security/nss/gtests/freebl_gtest/kat/blake2b_kat.h @@ -0,0 +1,4646 @@ +/* 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/. */ + +/* https://github.com/BLAKE2/BLAKE2/blob/master/testvectors/blake2b-kat.txt */ + +#include <vector> +#include <stdint.h> + +const std::vector<uint8_t> key = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63}; + +const std::vector<uint8_t> kat_data = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 255}; + +std::vector<std::pair<int, std::vector<uint8_t>>> TestcasesUnkeyed = { + std::make_pair( + 0, + std::vector<uint8_t>( + {0x78, 0x6a, 0x02, 0xf7, 0x42, 0x01, 0x59, 0x03, 0xc6, 0xc6, 0xfd, + 0x85, 0x25, 0x52, 0xd2, 0x72, 0x91, 0x2f, 0x47, 0x40, 0xe1, 0x58, + 0x47, 0x61, 0x8a, 0x86, 0xe2, 0x17, 0xf7, 0x1f, 0x54, 0x19, 0xd2, + 0x5e, 0x10, 0x31, 0xaf, 0xee, 0x58, 0x53, 0x13, 0x89, 0x64, 0x44, + 0x93, 0x4e, 0xb0, 0x4b, 0x90, 0x3a, 0x68, 0x5b, 0x14, 0x48, 0xb7, + 0x55, 0xd5, 0x6f, 0x70, 0x1a, 0xfe, 0x9b, 0xe2, 0xce})), + std::make_pair( + 1, + std::vector<uint8_t>( + {0x2f, 0xa3, 0xf6, 0x86, 0xdf, 0x87, 0x69, 0x95, 0x16, 0x7e, 0x7c, + 0x2e, 0x5d, 0x74, 0xc4, 0xc7, 0xb6, 0xe4, 0x8f, 0x80, 0x68, 0xfe, + 0x0e, 0x44, 0x20, 0x83, 0x44, 0xd4, 0x80, 0xf7, 0x90, 0x4c, 0x36, + 0x96, 0x3e, 0x44, 0x11, 0x5f, 0xe3, 0xeb, 0x2a, 0x3a, 0xc8, 0x69, + 0x4c, 0x28, 0xbc, 0xb4, 0xf5, 0xa0, 0xf3, 0x27, 0x6f, 0x2e, 0x79, + 0x48, 0x7d, 0x82, 0x19, 0x05, 0x7a, 0x50, 0x6e, 0x4b})), + std::make_pair( + 2, + std::vector<uint8_t>( + {0x1c, 0x08, 0x79, 0x8d, 0xc6, 0x41, 0xab, 0xa9, 0xde, 0xe4, 0x35, + 0xe2, 0x25, 0x19, 0xa4, 0x72, 0x9a, 0x09, 0xb2, 0xbf, 0xe0, 0xff, + 0x00, 0xef, 0x2d, 0xcd, 0x8e, 0xd6, 0xf8, 0xa0, 0x7d, 0x15, 0xea, + 0xf4, 0xae, 0xe5, 0x2b, 0xbf, 0x18, 0xab, 0x56, 0x08, 0xa6, 0x19, + 0x0f, 0x70, 0xb9, 0x04, 0x86, 0xc8, 0xa7, 0xd4, 0x87, 0x37, 0x10, + 0xb1, 0x11, 0x5d, 0x3d, 0xeb, 0xbb, 0x43, 0x27, 0xb5})), + std::make_pair( + 3, + std::vector<uint8_t>( + {0x40, 0xa3, 0x74, 0x72, 0x73, 0x02, 0xd9, 0xa4, 0x76, 0x9c, 0x17, + 0xb5, 0xf4, 0x09, 0xff, 0x32, 0xf5, 0x8a, 0xa2, 0x4f, 0xf1, 0x22, + 0xd7, 0x60, 0x3e, 0x4f, 0xda, 0x15, 0x09, 0xe9, 0x19, 0xd4, 0x10, + 0x7a, 0x52, 0xc5, 0x75, 0x70, 0xa6, 0xd9, 0x4e, 0x50, 0x96, 0x7a, + 0xea, 0x57, 0x3b, 0x11, 0xf8, 0x6f, 0x47, 0x3f, 0x53, 0x75, 0x65, + 0xc6, 0x6f, 0x70, 0x39, 0x83, 0x0a, 0x85, 0xd1, 0x86})), + std::make_pair( + 4, + std::vector<uint8_t>( + {0x77, 0xdd, 0xf4, 0xb1, 0x44, 0x25, 0xeb, 0x3d, 0x05, 0x3c, 0x1e, + 0x84, 0xe3, 0x46, 0x9d, 0x92, 0xc4, 0xcd, 0x91, 0x0e, 0xd2, 0x0f, + 0x92, 0x03, 0x5e, 0x0c, 0x99, 0xd8, 0xa7, 0xa8, 0x6c, 0xec, 0xaf, + 0x69, 0xf9, 0x66, 0x3c, 0x20, 0xa7, 0xaa, 0x23, 0x0b, 0xc8, 0x2f, + 0x60, 0xd2, 0x2f, 0xb4, 0xa0, 0x0b, 0x09, 0xd3, 0xeb, 0x8f, 0xc6, + 0x5e, 0xf5, 0x47, 0xfe, 0x63, 0xc8, 0xd3, 0xdd, 0xce})), + std::make_pair( + 5, + std::vector<uint8_t>( + {0xcb, 0xaa, 0x0b, 0xa7, 0xd4, 0x82, 0xb1, 0xf3, 0x01, 0x10, 0x9a, + 0xe4, 0x10, 0x51, 0x99, 0x1a, 0x32, 0x89, 0xbc, 0x11, 0x98, 0x00, + 0x5a, 0xf2, 0x26, 0xc5, 0xe4, 0xf1, 0x03, 0xb6, 0x65, 0x79, 0xf4, + 0x61, 0x36, 0x10, 0x44, 0xc8, 0xba, 0x34, 0x39, 0xff, 0x12, 0xc5, + 0x15, 0xfb, 0x29, 0xc5, 0x21, 0x61, 0xb7, 0xeb, 0x9c, 0x28, 0x37, + 0xb7, 0x6a, 0x5d, 0xc3, 0x3f, 0x7c, 0xb2, 0xe2, 0xe8})), + std::make_pair( + 6, + std::vector<uint8_t>( + {0xf9, 0x5d, 0x45, 0xcf, 0x69, 0xaf, 0x5c, 0x20, 0x23, 0xbd, 0xb5, + 0x05, 0x82, 0x1e, 0x62, 0xe8, 0x5d, 0x7c, 0xae, 0xdf, 0x7b, 0xed, + 0xa1, 0x2c, 0x02, 0x48, 0x77, 0x5b, 0x0c, 0x88, 0x20, 0x5e, 0xeb, + 0x35, 0xaf, 0x3a, 0x90, 0x81, 0x6f, 0x66, 0x08, 0xce, 0x7d, 0xd4, + 0x4e, 0xc2, 0x8d, 0xb1, 0x14, 0x06, 0x14, 0xe1, 0xdd, 0xeb, 0xf3, + 0xaa, 0x9c, 0xd1, 0x84, 0x3e, 0x0f, 0xad, 0x2c, 0x36})), + std::make_pair( + 7, + std::vector<uint8_t>( + {0x8f, 0x94, 0x5b, 0xa7, 0x00, 0xf2, 0x53, 0x0e, 0x5c, 0x2a, 0x7d, + 0xf7, 0xd5, 0xdc, 0xe0, 0xf8, 0x3f, 0x9e, 0xfc, 0x78, 0xc0, 0x73, + 0xfe, 0x71, 0xae, 0x1f, 0x88, 0x20, 0x4a, 0x4f, 0xd1, 0xcf, 0x70, + 0xa0, 0x73, 0xf5, 0xd1, 0xf9, 0x42, 0xed, 0x62, 0x3a, 0xa1, 0x6e, + 0x90, 0xa8, 0x71, 0x24, 0x6c, 0x90, 0xc4, 0x5b, 0x62, 0x1b, 0x34, + 0x01, 0xa5, 0xdd, 0xbd, 0x9d, 0xf6, 0x26, 0x41, 0x65})), + std::make_pair( + 8, + std::vector<uint8_t>( + {0xe9, 0x98, 0xe0, 0xdc, 0x03, 0xec, 0x30, 0xeb, 0x99, 0xbb, 0x6b, + 0xfa, 0xaf, 0x66, 0x18, 0xac, 0xc6, 0x20, 0x32, 0x0d, 0x72, 0x20, + 0xb3, 0xaf, 0x2b, 0x23, 0xd1, 0x12, 0xd8, 0xe9, 0xcb, 0x12, 0x62, + 0xf3, 0xc0, 0xd6, 0x0d, 0x18, 0x3b, 0x1e, 0xe7, 0xf0, 0x96, 0xd1, + 0x2d, 0xae, 0x42, 0xc9, 0x58, 0x41, 0x86, 0x00, 0x21, 0x4d, 0x04, + 0xf5, 0xed, 0x6f, 0x5e, 0x71, 0x8b, 0xe3, 0x55, 0x66})), + std::make_pair( + 9, + std::vector<uint8_t>( + {0x6a, 0x9a, 0x09, 0x0c, 0x61, 0xb3, 0x41, 0x0a, 0xed, 0xe7, 0xec, + 0x91, 0x38, 0x14, 0x6c, 0xeb, 0x2c, 0x69, 0x66, 0x2f, 0x46, 0x0c, + 0x3d, 0xa5, 0x3c, 0x65, 0x15, 0xc1, 0xeb, 0x31, 0xf4, 0x1c, 0xa3, + 0xd2, 0x80, 0xe5, 0x67, 0x88, 0x2f, 0x95, 0xcf, 0x66, 0x4a, 0x94, + 0x14, 0x7d, 0x78, 0xf4, 0x2c, 0xfc, 0x71, 0x4a, 0x40, 0xd2, 0x2e, + 0xf1, 0x94, 0x70, 0xe0, 0x53, 0x49, 0x35, 0x08, 0xa2})), + std::make_pair( + 10, + std::vector<uint8_t>( + {0x29, 0x10, 0x25, 0x11, 0xd7, 0x49, 0xdb, 0x3c, 0xc9, 0xb4, 0xe3, + 0x35, 0xfa, 0x1f, 0x5e, 0x8f, 0xac, 0xa8, 0x42, 0x1d, 0x55, 0x8f, + 0x6a, 0x3f, 0x33, 0x21, 0xd5, 0x0d, 0x04, 0x4a, 0x24, 0x8b, 0xa5, + 0x95, 0xcf, 0xc3, 0xef, 0xd3, 0xd2, 0xad, 0xc9, 0x73, 0x34, 0xda, + 0x73, 0x24, 0x13, 0xf5, 0xcb, 0xf4, 0x75, 0x1c, 0x36, 0x2b, 0xa1, + 0xd5, 0x38, 0x62, 0xac, 0x1e, 0x8d, 0xab, 0xee, 0xe8})), + std::make_pair( + 11, + std::vector<uint8_t>( + {0xc9, 0x7a, 0x47, 0x79, 0xd4, 0x7e, 0x6f, 0x77, 0x72, 0x9b, 0x59, + 0x17, 0xd0, 0x13, 0x8a, 0xbb, 0x35, 0x98, 0x0a, 0xb6, 0x41, 0xbd, + 0x73, 0xa8, 0x85, 0x9e, 0xb1, 0xac, 0x98, 0xc0, 0x53, 0x62, 0xed, + 0x7d, 0x60, 0x8f, 0x2e, 0x95, 0x87, 0xd6, 0xba, 0x9e, 0x27, 0x1d, + 0x34, 0x31, 0x25, 0xd4, 0x0d, 0x93, 0x3a, 0x8e, 0xd0, 0x4e, 0xc1, + 0xfe, 0x75, 0xec, 0x40, 0x7c, 0x7a, 0x53, 0xc3, 0x4e})), + std::make_pair( + 12, + std::vector<uint8_t>( + {0x10, 0xf0, 0xdc, 0x91, 0xb9, 0xf8, 0x45, 0xfb, 0x95, 0xfa, 0xd6, + 0x86, 0x0e, 0x6c, 0xe1, 0xad, 0xfa, 0x00, 0x2c, 0x7f, 0xc3, 0x27, + 0x11, 0x6d, 0x44, 0xd0, 0x47, 0xcd, 0x7d, 0x58, 0x70, 0xd7, 0x72, + 0xbb, 0x12, 0xb5, 0xfa, 0xc0, 0x0e, 0x02, 0xb0, 0x8a, 0xc2, 0xa0, + 0x17, 0x4d, 0x04, 0x46, 0xc3, 0x6a, 0xb3, 0x5f, 0x14, 0xca, 0x31, + 0x89, 0x4c, 0xd6, 0x1c, 0x78, 0xc8, 0x49, 0xb4, 0x8a})), + std::make_pair( + 13, + std::vector<uint8_t>( + {0xde, 0xa9, 0x10, 0x1c, 0xac, 0x62, 0xb8, 0xf6, 0xa3, 0xc6, 0x50, + 0xf9, 0x0e, 0xea, 0x5b, 0xfa, 0xe2, 0x65, 0x3a, 0x4e, 0xaf, 0xd6, + 0x3a, 0x6d, 0x1f, 0x0f, 0x13, 0x2d, 0xb9, 0xe4, 0xf2, 0xb1, 0xb6, + 0x62, 0x43, 0x2e, 0xc8, 0x5b, 0x17, 0xbc, 0xac, 0x41, 0xe7, 0x75, + 0x63, 0x78, 0x81, 0xf6, 0xaa, 0xb3, 0x8d, 0xd6, 0x6d, 0xcb, 0xd0, + 0x80, 0xf0, 0x99, 0x0a, 0x7a, 0x6e, 0x98, 0x54, 0xfe})), + std::make_pair( + 14, + std::vector<uint8_t>( + {0x44, 0x1f, 0xfa, 0xa0, 0x8c, 0xd7, 0x9d, 0xff, 0x4a, 0xfc, 0x9b, + 0x9e, 0x5b, 0x56, 0x20, 0xee, 0xc0, 0x86, 0x73, 0x0c, 0x25, 0xf6, + 0x61, 0xb1, 0xd6, 0xfb, 0xfb, 0xd1, 0xce, 0xc3, 0x14, 0x8d, 0xd7, + 0x22, 0x58, 0xc6, 0x56, 0x41, 0xf2, 0xfc, 0xa5, 0xeb, 0x15, 0x5f, + 0xad, 0xbc, 0xab, 0xb1, 0x3c, 0x6e, 0x21, 0xdc, 0x11, 0xfa, 0xf7, + 0x2c, 0x2a, 0x28, 0x1b, 0x7d, 0x56, 0x14, 0x5f, 0x19})), + std::make_pair( + 15, + std::vector<uint8_t>( + {0x44, 0x4b, 0x24, 0x0f, 0xe3, 0xed, 0x86, 0xd0, 0xe2, 0xef, 0x4c, + 0xe7, 0xd8, 0x51, 0xed, 0xde, 0x22, 0x15, 0x55, 0x82, 0xaa, 0x09, + 0x14, 0x79, 0x7b, 0x72, 0x6c, 0xd0, 0x58, 0xb6, 0xf4, 0x59, 0x32, + 0xe0, 0xe1, 0x29, 0x51, 0x68, 0x76, 0x52, 0x7b, 0x1d, 0xd8, 0x8f, + 0xc6, 0x6d, 0x71, 0x19, 0xf4, 0xab, 0x3b, 0xed, 0x93, 0xa6, 0x1a, + 0x0e, 0x2d, 0x2d, 0x2a, 0xea, 0xc3, 0x36, 0xd9, 0x58})), + std::make_pair( + 16, + std::vector<uint8_t>( + {0xbf, 0xba, 0xbb, 0xef, 0x45, 0x55, 0x4c, 0xcf, 0xa0, 0xdc, 0x83, + 0x75, 0x2a, 0x19, 0xcc, 0x35, 0xd5, 0x92, 0x09, 0x56, 0xb3, 0x01, + 0xd5, 0x58, 0xd7, 0x72, 0x28, 0x2b, 0xc8, 0x67, 0x00, 0x91, 0x68, + 0xe9, 0xe9, 0x86, 0x06, 0xbb, 0x5b, 0xa7, 0x3a, 0x38, 0x5d, 0xe5, + 0x74, 0x92, 0x28, 0xc9, 0x25, 0xa8, 0x50, 0x19, 0xb7, 0x1f, 0x72, + 0xfe, 0x29, 0xb3, 0xcd, 0x37, 0xca, 0x52, 0xef, 0xe6})), + std::make_pair( + 17, + std::vector<uint8_t>( + {0x9c, 0x4d, 0x0c, 0x3e, 0x1c, 0xdb, 0xbf, 0x48, 0x5b, 0xec, 0x86, + 0xf4, 0x1c, 0xec, 0x7c, 0x98, 0x37, 0x3f, 0x0e, 0x09, 0xf3, 0x92, + 0x84, 0x9a, 0xaa, 0x22, 0x9e, 0xbf, 0xbf, 0x39, 0x7b, 0x22, 0x08, + 0x55, 0x29, 0xcb, 0x7e, 0xf3, 0x9f, 0x9c, 0x7c, 0x22, 0x22, 0xa5, + 0x14, 0x18, 0x2b, 0x1e, 0xff, 0xaa, 0x17, 0x8c, 0xc3, 0x68, 0x7b, + 0x1b, 0x2b, 0x6c, 0xbc, 0xb6, 0xfd, 0xeb, 0x96, 0xf8})), + std::make_pair( + 18, + std::vector<uint8_t>( + {0x47, 0x71, 0x76, 0xb3, 0xbf, 0xcb, 0xad, 0xd7, 0x65, 0x7c, 0x23, + 0xc2, 0x46, 0x25, 0xe4, 0xd0, 0xd6, 0x74, 0xd1, 0x86, 0x8f, 0x00, + 0x60, 0x06, 0x39, 0x8a, 0xf9, 0x7a, 0xa4, 0x18, 0x77, 0xc8, 0xe7, + 0x0d, 0x3d, 0x14, 0xc3, 0xbb, 0xc9, 0xbb, 0xcd, 0xce, 0xa8, 0x01, + 0xbd, 0x0e, 0x15, 0x99, 0xaf, 0x1f, 0x3e, 0xec, 0x67, 0x40, 0x51, + 0x70, 0xf4, 0xe2, 0x6c, 0x96, 0x4a, 0x57, 0xa8, 0xb7})), + std::make_pair( + 19, + std::vector<uint8_t>( + {0xa7, 0x8c, 0x49, 0x0e, 0xda, 0x31, 0x73, 0xbb, 0x3f, 0x10, 0xde, + 0xe5, 0x2f, 0x11, 0x0f, 0xb1, 0xc0, 0x8e, 0x03, 0x02, 0x23, 0x0b, + 0x85, 0xdd, 0xd7, 0xc1, 0x12, 0x57, 0xd9, 0x2d, 0xe1, 0x48, 0x78, + 0x5e, 0xf0, 0x0c, 0x03, 0x9c, 0x0b, 0xb8, 0xeb, 0x98, 0x08, 0xa3, + 0x5b, 0x2d, 0x8c, 0x08, 0x0f, 0x57, 0x28, 0x59, 0x71, 0x4c, 0x9d, + 0x40, 0x69, 0xc5, 0xbc, 0xaf, 0x09, 0x0e, 0x89, 0x8e})), + std::make_pair( + 20, + std::vector<uint8_t>( + {0x58, 0xd0, 0x23, 0x39, 0x7b, 0xeb, 0x5b, 0x41, 0x45, 0xcb, 0x22, + 0x55, 0xb0, 0x7d, 0x74, 0x29, 0x0b, 0x36, 0xd9, 0xfd, 0x1e, 0x59, + 0x4a, 0xfb, 0xd8, 0xee, 0xa4, 0x7c, 0x20, 0x5b, 0x2e, 0xfb, 0xfe, + 0x6f, 0x46, 0x19, 0x0f, 0xaf, 0x95, 0xaf, 0x50, 0x4a, 0xb0, 0x72, + 0xe3, 0x6f, 0x6c, 0x85, 0xd7, 0x67, 0xa3, 0x21, 0xbf, 0xd7, 0xf2, + 0x26, 0x87, 0xa4, 0xab, 0xbf, 0x49, 0x4a, 0x68, 0x9c})), + std::make_pair( + 21, + std::vector<uint8_t>( + {0x40, 0x01, 0xec, 0x74, 0xd5, 0xa4, 0x6f, 0xd2, 0x9c, 0x2c, 0x3c, + 0xdb, 0xe5, 0xd1, 0xb9, 0xf2, 0x0e, 0x51, 0xa9, 0x41, 0xbe, 0x98, + 0xd2, 0xa4, 0xe1, 0xe2, 0xfb, 0xf8, 0x66, 0xa6, 0x72, 0x12, 0x1d, + 0xb6, 0xf8, 0x1a, 0x51, 0x4c, 0xfd, 0x10, 0xe7, 0x35, 0x8d, 0x57, + 0x1b, 0xdb, 0xa4, 0x8e, 0x4c, 0xe7, 0x08, 0xb9, 0xd1, 0x24, 0x89, + 0x4b, 0xc0, 0xb5, 0xed, 0x55, 0x49, 0x35, 0xf7, 0x3a})), + std::make_pair( + 22, + std::vector<uint8_t>( + {0xcc, 0xd1, 0xb2, 0x2d, 0xab, 0x65, 0x11, 0x22, 0x5d, 0x24, 0x01, + 0xea, 0x2d, 0x86, 0x25, 0xd2, 0x06, 0xa1, 0x24, 0x73, 0xcc, 0x73, + 0x2b, 0x61, 0x5e, 0x56, 0x40, 0xce, 0xff, 0xf0, 0xa4, 0xad, 0xf9, + 0x71, 0xb0, 0xe8, 0x27, 0xa6, 0x19, 0xe0, 0xa8, 0x0f, 0x5d, 0xb9, + 0xcc, 0xd0, 0x96, 0x23, 0x29, 0x01, 0x0d, 0x07, 0xe3, 0x4a, 0x20, + 0x64, 0xe7, 0x31, 0xc5, 0x20, 0x81, 0x7b, 0x21, 0x83})), + std::make_pair( + 23, + std::vector<uint8_t>( + {0xb4, 0xa0, 0xa9, 0xe3, 0x57, 0x4e, 0xdb, 0x9e, 0x1e, 0x72, 0xaa, + 0x31, 0xe3, 0x9c, 0xc5, 0xf3, 0x0d, 0xbf, 0x94, 0x3f, 0x8c, 0xab, + 0xc4, 0x08, 0x44, 0x96, 0x54, 0xa3, 0x91, 0x31, 0xe6, 0x6d, 0x71, + 0x8a, 0x18, 0x81, 0x91, 0x43, 0xe3, 0xea, 0x96, 0xb4, 0xa1, 0x89, + 0x59, 0x88, 0xa1, 0xc0, 0x05, 0x6c, 0xf2, 0xb6, 0xe0, 0x4f, 0x9a, + 0xc1, 0x9d, 0x65, 0x73, 0x83, 0xc2, 0x91, 0x0c, 0x44})), + std::make_pair( + 24, + std::vector<uint8_t>( + {0x44, 0x7b, 0xec, 0xab, 0x16, 0x63, 0x06, 0x08, 0xd3, 0x9f, 0x4f, + 0x05, 0x8b, 0x16, 0xf7, 0xaf, 0x95, 0xb8, 0x5a, 0x76, 0xaa, 0x0f, + 0xa7, 0xce, 0xa2, 0xb8, 0x07, 0x55, 0xfb, 0x76, 0xe9, 0xc8, 0x04, + 0xf2, 0xca, 0x78, 0xf0, 0x26, 0x43, 0xc9, 0x15, 0xfb, 0xf2, 0xfc, + 0xe5, 0xe1, 0x9d, 0xe8, 0x60, 0x00, 0xde, 0x03, 0xb1, 0x88, 0x61, + 0x81, 0x5a, 0x83, 0x12, 0x60, 0x71, 0xf8, 0xa3, 0x7b})), + std::make_pair( + 25, + std::vector<uint8_t>( + {0x54, 0xe6, 0xda, 0xb9, 0x97, 0x73, 0x80, 0xa5, 0x66, 0x58, 0x22, + 0xdb, 0x93, 0x37, 0x4e, 0xda, 0x52, 0x8d, 0x9b, 0xeb, 0x62, 0x6f, + 0x9b, 0x94, 0x02, 0x70, 0x71, 0xcb, 0x26, 0x67, 0x5e, 0x11, 0x2b, + 0x4a, 0x7f, 0xec, 0x94, 0x1e, 0xe6, 0x0a, 0x81, 0xe4, 0xd2, 0xea, + 0x3f, 0xf7, 0xbc, 0x52, 0xcf, 0xc4, 0x5d, 0xfb, 0xfe, 0x73, 0x5a, + 0x1c, 0x64, 0x6b, 0x2c, 0xf6, 0xd6, 0xa4, 0x9b, 0x62})), + std::make_pair( + 26, + std::vector<uint8_t>( + {0x3e, 0xa6, 0x26, 0x25, 0x94, 0x9e, 0x36, 0x46, 0x70, 0x4d, 0x7e, + 0x3c, 0x90, 0x6f, 0x82, 0xf6, 0xc0, 0x28, 0xf5, 0x40, 0xf5, 0xf7, + 0x2a, 0x79, 0x4b, 0x0c, 0x57, 0xbf, 0x97, 0xb7, 0x64, 0x9b, 0xfe, + 0xb9, 0x0b, 0x01, 0xd3, 0xca, 0x3e, 0x82, 0x9d, 0xe2, 0x1b, 0x38, + 0x26, 0xe6, 0xf8, 0x70, 0x14, 0xd3, 0xc7, 0x73, 0x50, 0xcb, 0x5a, + 0x15, 0xff, 0x5d, 0x46, 0x8a, 0x81, 0xbe, 0xc1, 0x60})), + std::make_pair( + 27, + std::vector<uint8_t>( + {0x21, 0x3c, 0xfe, 0x14, 0x5c, 0x54, 0xa3, 0x36, 0x91, 0x56, 0x99, + 0x80, 0xe5, 0x93, 0x8c, 0x88, 0x83, 0xa4, 0x6d, 0x84, 0xd1, 0x49, + 0xc8, 0xff, 0x1a, 0x67, 0xcd, 0x28, 0x7b, 0x4d, 0x49, 0xc6, 0xda, + 0x69, 0xd3, 0xa0, 0x35, 0x44, 0x3d, 0xb0, 0x85, 0x98, 0x3d, 0x0e, + 0xfe, 0x63, 0x70, 0x6b, 0xd5, 0xb6, 0xf1, 0x5a, 0x7d, 0xa4, 0x59, + 0xe8, 0xd5, 0x0a, 0x19, 0x09, 0x3d, 0xb5, 0x5e, 0x80})), + std::make_pair( + 28, + std::vector<uint8_t>( + {0x57, 0x16, 0xc4, 0xa3, 0x8f, 0x38, 0xdb, 0x10, 0x4e, 0x49, 0x4a, + 0x0a, 0x27, 0xcb, 0xe8, 0x9a, 0x26, 0xa6, 0xbb, 0x6f, 0x49, 0x9e, + 0xc0, 0x1c, 0x8c, 0x01, 0xaa, 0x7c, 0xb8, 0x84, 0x97, 0xe7, 0x51, + 0x48, 0xcd, 0x6e, 0xee, 0x12, 0xa7, 0x16, 0x8b, 0x6f, 0x78, 0xab, + 0x74, 0xe4, 0xbe, 0x74, 0x92, 0x51, 0xa1, 0xa7, 0x4c, 0x38, 0xc8, + 0x6d, 0x61, 0x29, 0x17, 0x7e, 0x28, 0x89, 0xe0, 0xb6})), + std::make_pair( + 29, + std::vector<uint8_t>( + {0x03, 0x04, 0x60, 0xa9, 0x8b, 0xdf, 0x9f, 0xf1, 0x7c, 0xd9, 0x64, + 0x04, 0xf2, 0x8f, 0xc3, 0x04, 0xf2, 0xb7, 0xc0, 0x4e, 0xaa, 0xde, + 0x53, 0x67, 0x7f, 0xd2, 0x8f, 0x78, 0x8c, 0xa2, 0x21, 0x86, 0xb8, + 0xbc, 0x80, 0xdd, 0x21, 0xd1, 0x7f, 0x85, 0x49, 0xc7, 0x11, 0xaf, + 0xf0, 0xe5, 0x14, 0xe1, 0x9d, 0x4e, 0x15, 0xf5, 0x99, 0x02, 0x52, + 0xa0, 0x3e, 0x08, 0x2f, 0x28, 0xdc, 0x20, 0x52, 0xf6})), + std::make_pair( + 30, + std::vector<uint8_t>( + {0x19, 0xe7, 0xf1, 0xcc, 0xee, 0x88, 0xa1, 0x06, 0x72, 0x33, 0x3e, + 0x39, 0x0c, 0xf2, 0x20, 0x13, 0xa8, 0xc7, 0x34, 0xc6, 0xcb, 0x9e, + 0xab, 0x41, 0xf1, 0x7c, 0x3c, 0x80, 0x32, 0xa2, 0xe4, 0xac, 0xa0, + 0x56, 0x9e, 0xa3, 0x6f, 0x08, 0x60, 0xc7, 0xa1, 0xaf, 0x28, 0xfa, + 0x47, 0x68, 0x40, 0xd6, 0x60, 0x11, 0x16, 0x88, 0x59, 0x33, 0x4a, + 0x9e, 0x4e, 0xf9, 0xcc, 0x2e, 0x61, 0xa0, 0xe2, 0x9e})), + std::make_pair( + 31, + std::vector<uint8_t>( + {0x29, 0xf8, 0xb8, 0xc7, 0x8c, 0x80, 0xf2, 0xfc, 0xb4, 0xbd, 0xf7, + 0x82, 0x5e, 0xd9, 0x0a, 0x70, 0xd6, 0x25, 0xff, 0x78, 0x5d, 0x26, + 0x26, 0x77, 0xe2, 0x50, 0xc0, 0x4f, 0x37, 0x20, 0xc8, 0x88, 0xd0, + 0x3f, 0x80, 0x45, 0xe4, 0xed, 0xf3, 0xf5, 0x28, 0x5b, 0xd3, 0x9d, + 0x92, 0x8a, 0x10, 0xa7, 0xd0, 0xa5, 0xdf, 0x00, 0xb8, 0x48, 0x4a, + 0xc2, 0x86, 0x81, 0x42, 0xa1, 0xe8, 0xbe, 0xa3, 0x51})), + std::make_pair( + 32, + std::vector<uint8_t>( + {0x5c, 0x52, 0x92, 0x0a, 0x72, 0x63, 0xe3, 0x9d, 0x57, 0x92, 0x0c, + 0xa0, 0xcb, 0x75, 0x2a, 0xc6, 0xd7, 0x9a, 0x04, 0xfe, 0xf8, 0xa7, + 0xa2, 0x16, 0xa1, 0xec, 0xb7, 0x11, 0x5c, 0xe0, 0x6d, 0x89, 0xfd, + 0x7d, 0x73, 0x5b, 0xd6, 0xf4, 0x27, 0x25, 0x55, 0xdb, 0xa2, 0x2c, + 0x2d, 0x1c, 0x96, 0xe6, 0x35, 0x23, 0x22, 0xc6, 0x2c, 0x56, 0x30, + 0xfd, 0xe0, 0xf4, 0x77, 0x7a, 0x76, 0xc3, 0xde, 0x2c})), + std::make_pair( + 33, + std::vector<uint8_t>( + {0x83, 0xb0, 0x98, 0xf2, 0x62, 0x25, 0x1b, 0xf6, 0x60, 0x06, 0x4a, + 0x9d, 0x35, 0x11, 0xce, 0x76, 0x87, 0xa0, 0x9e, 0x6d, 0xfb, 0xb8, + 0x78, 0x29, 0x9c, 0x30, 0xe9, 0x3d, 0xfb, 0x43, 0xa9, 0x31, 0x4d, + 0xb9, 0xa6, 0x00, 0x33, 0x7d, 0xb2, 0x6e, 0xbe, 0xed, 0xaf, 0x22, + 0x56, 0xa9, 0x6d, 0xab, 0xe9, 0xb2, 0x9e, 0x75, 0x73, 0xad, 0x11, + 0xc3, 0x52, 0x3d, 0x87, 0x4d, 0xde, 0x5b, 0xe7, 0xed})), + std::make_pair( + 34, + std::vector<uint8_t>( + {0x94, 0x47, 0xd9, 0x8a, 0xa5, 0xc9, 0x33, 0x13, 0x52, 0xf4, 0x3d, + 0x3e, 0x56, 0xd0, 0xa9, 0xa9, 0xf9, 0x58, 0x18, 0x65, 0x99, 0x8e, + 0x28, 0x85, 0xcc, 0x56, 0xdd, 0x0a, 0x0b, 0xd5, 0xa7, 0xb5, 0x05, + 0x95, 0xbd, 0x10, 0xf7, 0x52, 0x9b, 0xcd, 0x31, 0xf3, 0x7d, 0xc1, + 0x6a, 0x14, 0x65, 0xd5, 0x94, 0x07, 0x96, 0x67, 0xda, 0x2a, 0x3f, + 0xcb, 0x70, 0x40, 0x14, 0x98, 0x83, 0x7c, 0xed, 0xeb})), + std::make_pair( + 35, + std::vector<uint8_t>( + {0x86, 0x77, 0x32, 0xf2, 0xfe, 0xeb, 0x23, 0x89, 0x30, 0x97, 0x56, + 0x1a, 0xc7, 0x10, 0xa4, 0xbf, 0xf4, 0x53, 0xbe, 0x9c, 0xfb, 0xed, + 0xba, 0x8b, 0xa3, 0x24, 0xf9, 0xd3, 0x12, 0xa8, 0x2d, 0x73, 0x2e, + 0x1b, 0x83, 0xb8, 0x29, 0xfd, 0xcd, 0x17, 0x7b, 0x88, 0x2c, 0xa0, + 0xc1, 0xbf, 0x54, 0x4b, 0x22, 0x3b, 0xe5, 0x29, 0x92, 0x4a, 0x24, + 0x6a, 0x63, 0xcf, 0x05, 0x9b, 0xfd, 0xc5, 0x0a, 0x1b})), + std::make_pair( + 36, + std::vector<uint8_t>( + {0xf1, 0x5a, 0xb2, 0x6d, 0x4c, 0xdf, 0xcf, 0x56, 0xe1, 0x96, 0xbb, + 0x6b, 0xa1, 0x70, 0xa8, 0xfc, 0xcc, 0x41, 0x4d, 0xe9, 0x28, 0x5a, + 0xfd, 0x98, 0xa3, 0xd3, 0xcf, 0x2f, 0xb8, 0x8f, 0xcb, 0xc0, 0xf1, + 0x98, 0x32, 0xac, 0x43, 0x3a, 0x5b, 0x2c, 0xc2, 0x39, 0x2a, 0x4c, + 0xe3, 0x43, 0x32, 0x98, 0x7d, 0x8d, 0x2c, 0x2b, 0xef, 0x6c, 0x34, + 0x66, 0x13, 0x8d, 0xb0, 0xc6, 0xe4, 0x2f, 0xa4, 0x7b})), + std::make_pair( + 37, + std::vector<uint8_t>( + {0x28, 0x13, 0x51, 0x6d, 0x68, 0xed, 0x4a, 0x08, 0xb3, 0x9d, 0x64, + 0x8a, 0xa6, 0xaa, 0xcd, 0x81, 0xe9, 0xd6, 0x55, 0xec, 0xd5, 0xf0, + 0xc1, 0x35, 0x56, 0xc6, 0x0f, 0xdf, 0x0d, 0x33, 0x3e, 0xa3, 0x84, + 0x64, 0xb3, 0x6c, 0x02, 0xba, 0xcc, 0xd7, 0x46, 0xe9, 0x57, 0x5e, + 0x96, 0xc6, 0x30, 0x14, 0xf0, 0x74, 0xae, 0x34, 0xa0, 0xa2, 0x5b, + 0x32, 0x0f, 0x0f, 0xbe, 0xdd, 0x6a, 0xcf, 0x76, 0x65})), + std::make_pair( + 38, + std::vector<uint8_t>( + {0xd3, 0x25, 0x9a, 0xfc, 0xa8, 0xa4, 0x89, 0x62, 0xfa, 0x89, 0x2e, + 0x14, 0x5a, 0xcf, 0x54, 0x7f, 0x26, 0x92, 0x3a, 0xe8, 0xd4, 0x92, + 0x4c, 0x8a, 0x53, 0x15, 0x81, 0x52, 0x6b, 0x04, 0xb4, 0x4c, 0x7a, + 0xf8, 0x3c, 0x64, 0x3e, 0xf5, 0xa0, 0xbc, 0x28, 0x2d, 0x36, 0xf3, + 0xfb, 0x04, 0xc8, 0x4e, 0x28, 0xb3, 0x51, 0xf4, 0x0c, 0x74, 0xb6, + 0x9d, 0xc7, 0x84, 0x0b, 0xc7, 0x17, 0xb6, 0xf1, 0x5f})), + std::make_pair( + 39, + std::vector<uint8_t>( + {0xf1, 0x4b, 0x06, 0x1a, 0xe3, 0x59, 0xfa, 0x31, 0xb9, 0x89, 0xe3, + 0x03, 0x32, 0xbf, 0xe8, 0xde, 0x8c, 0xc8, 0xcd, 0xb5, 0x68, 0xe1, + 0x4b, 0xe2, 0x14, 0xa2, 0x22, 0x3b, 0x84, 0xca, 0xab, 0x74, 0x19, + 0x54, 0x9e, 0xcf, 0xcc, 0x96, 0xce, 0x2a, 0xce, 0xc1, 0x19, 0x48, + 0x5d, 0x87, 0xd1, 0x57, 0xd3, 0xa8, 0x73, 0x4f, 0xc4, 0x26, 0x59, + 0x7d, 0x64, 0xf3, 0x65, 0x70, 0xce, 0xaf, 0x22, 0x4d})), + std::make_pair( + 40, + std::vector<uint8_t>( + {0x55, 0xe7, 0x0b, 0x01, 0xd1, 0xfb, 0xf8, 0xb2, 0x3b, 0x57, 0xfb, + 0x62, 0xe2, 0x6c, 0x2c, 0xe5, 0x4f, 0x13, 0xf8, 0xfa, 0x24, 0x64, + 0xe6, 0xeb, 0x98, 0xd1, 0x6a, 0x61, 0x17, 0x02, 0x6d, 0x8b, 0x90, + 0x81, 0x90, 0x12, 0x49, 0x6d, 0x40, 0x71, 0xeb, 0xe2, 0xe5, 0x95, + 0x57, 0xec, 0xe3, 0x51, 0x9a, 0x7a, 0xa4, 0x58, 0x02, 0xf9, 0x61, + 0x53, 0x74, 0x87, 0x73, 0x32, 0xb7, 0x34, 0x90, 0xb3})), + std::make_pair( + 41, + std::vector<uint8_t>( + {0x25, 0x26, 0x1e, 0xb2, 0x96, 0x97, 0x1d, 0x6e, 0x4a, 0x71, 0xb2, + 0x92, 0x8e, 0x64, 0x83, 0x9c, 0x67, 0xd4, 0x22, 0x87, 0x2b, 0xf9, + 0xf3, 0xc3, 0x19, 0x93, 0x61, 0x52, 0x22, 0xde, 0x9f, 0x8f, 0x0b, + 0x2c, 0x4b, 0xe8, 0x54, 0x85, 0x59, 0xb4, 0xb3, 0x54, 0xe7, 0x36, + 0x41, 0x6e, 0x32, 0x18, 0xd4, 0xe8, 0xa1, 0xe2, 0x19, 0xa4, 0xa6, + 0xd4, 0x3e, 0x1a, 0x9a, 0x52, 0x1d, 0x0e, 0x75, 0xfc})), + std::make_pair( + 42, + std::vector<uint8_t>( + {0x08, 0x30, 0x7f, 0x34, 0x7c, 0x41, 0x29, 0x4e, 0x34, 0xbb, 0x54, + 0xcb, 0x42, 0xb1, 0x52, 0x2d, 0x22, 0xf8, 0x24, 0xf7, 0xb6, 0xe5, + 0xdb, 0x50, 0xfd, 0xa0, 0x96, 0x79, 0x8e, 0x18, 0x1a, 0x8f, 0x02, + 0x6f, 0xa2, 0x7b, 0x4a, 0xe4, 0x5d, 0x52, 0xa6, 0x2c, 0xaf, 0x9d, + 0x51, 0x98, 0xe2, 0x4a, 0x49, 0x13, 0xc6, 0x67, 0x17, 0x75, 0xb2, + 0xd7, 0x23, 0xc1, 0x23, 0x9b, 0xfb, 0xf0, 0x16, 0xd7})), + std::make_pair( + 43, + std::vector<uint8_t>( + {0x1e, 0x5c, 0x62, 0xe7, 0xe9, 0xbf, 0xa1, 0xb1, 0x18, 0x74, 0x7a, + 0x2d, 0xe0, 0x8b, 0x3c, 0xa1, 0x01, 0x12, 0xaf, 0x96, 0xa4, 0x6e, + 0x4b, 0x22, 0xc3, 0xfc, 0x06, 0xf9, 0xbf, 0xee, 0x4e, 0xb5, 0xc4, + 0x9e, 0x05, 0x7a, 0x4a, 0x48, 0x86, 0x23, 0x43, 0x24, 0x57, 0x25, + 0x76, 0xbb, 0x9b, 0x5e, 0xcf, 0xde, 0x0d, 0x99, 0xb0, 0xde, 0x4f, + 0x98, 0xec, 0x16, 0xe4, 0xd1, 0xb8, 0x5f, 0xa9, 0x47})), + std::make_pair( + 44, + std::vector<uint8_t>( + {0xc7, 0x4a, 0x77, 0x39, 0x5f, 0xb8, 0xbc, 0x12, 0x64, 0x47, 0x45, + 0x48, 0x38, 0xe5, 0x61, 0xe9, 0x62, 0x85, 0x3d, 0xc7, 0xeb, 0x49, + 0xa1, 0xe3, 0xcb, 0x67, 0xc3, 0xd0, 0x85, 0x1f, 0x3e, 0x39, 0x51, + 0x7b, 0xe8, 0xc3, 0x50, 0xac, 0x91, 0x09, 0x03, 0xd4, 0x9c, 0xd2, + 0xbf, 0xdf, 0x54, 0x5c, 0x99, 0x31, 0x6d, 0x03, 0x46, 0x17, 0x0b, + 0x73, 0x9f, 0x0a, 0xdd, 0x5d, 0x53, 0x3c, 0x2c, 0xfc})), + std::make_pair( + 45, + std::vector<uint8_t>( + {0x0d, 0xd5, 0x7b, 0x42, 0x3c, 0xc0, 0x1e, 0xb2, 0x86, 0x13, 0x91, + 0xeb, 0x88, 0x6a, 0x0d, 0x17, 0x07, 0x9b, 0x93, 0x3f, 0xc7, 0x6e, + 0xb3, 0xfc, 0x08, 0xa1, 0x9f, 0x8a, 0x74, 0x95, 0x2c, 0xb6, 0x8f, + 0x6b, 0xcd, 0xc6, 0x44, 0xf7, 0x73, 0x70, 0x96, 0x6e, 0x4d, 0x13, + 0xe8, 0x05, 0x60, 0xbc, 0xf0, 0x82, 0xef, 0x04, 0x79, 0xd4, 0x8f, + 0xbb, 0xab, 0x4d, 0xf0, 0x3b, 0x53, 0xa4, 0xe1, 0x78})), + std::make_pair( + 46, + std::vector<uint8_t>( + {0x4d, 0x8d, 0xc3, 0x92, 0x3e, 0xdc, 0xcd, 0xfc, 0xe7, 0x00, 0x72, + 0x39, 0x8b, 0x8a, 0x3d, 0xa5, 0xc3, 0x1f, 0xcb, 0x3e, 0xe3, 0xb6, + 0x45, 0xc8, 0x5f, 0x71, 0x7c, 0xba, 0xeb, 0x4b, 0x67, 0x3a, 0x19, + 0x39, 0x44, 0x25, 0xa5, 0x85, 0xbf, 0xb4, 0x64, 0xd9, 0x2f, 0x15, + 0x97, 0xd0, 0xb7, 0x54, 0xd1, 0x63, 0xf9, 0x7c, 0xed, 0x34, 0x3b, + 0x25, 0xdb, 0x5a, 0x70, 0xef, 0x48, 0xeb, 0xb3, 0x4f})), + std::make_pair( + 47, + std::vector<uint8_t>( + {0xf0, 0xa5, 0x05, 0x53, 0xe4, 0xdf, 0xb0, 0xc4, 0xe3, 0xe3, 0xd3, + 0xba, 0x82, 0x03, 0x48, 0x57, 0xe3, 0xb1, 0xe5, 0x09, 0x18, 0xf5, + 0xb8, 0xa7, 0xd6, 0x98, 0xe1, 0x0d, 0x24, 0x2b, 0x0f, 0xb5, 0x44, + 0xaf, 0x6c, 0x92, 0xd0, 0xc3, 0xaa, 0xf9, 0x93, 0x22, 0x20, 0x41, + 0x61, 0x17, 0xb4, 0xe7, 0x8e, 0xcb, 0x8a, 0x8f, 0x43, 0x0e, 0x13, + 0xb8, 0x2a, 0x59, 0x15, 0x29, 0x0a, 0x58, 0x19, 0xc5})), + std::make_pair( + 48, + std::vector<uint8_t>( + {0xb1, 0x55, 0x43, 0xf3, 0xf7, 0x36, 0x08, 0x66, 0x27, 0xcc, 0x53, + 0x65, 0xe7, 0xe8, 0x98, 0x8c, 0x2e, 0xf1, 0x55, 0xc0, 0xfd, 0x4f, + 0x42, 0x89, 0x61, 0xb0, 0x0d, 0x15, 0x26, 0xf0, 0x4d, 0x6d, 0x6a, + 0x65, 0x8b, 0x4b, 0x8e, 0xd3, 0x2c, 0x5d, 0x86, 0x21, 0xe7, 0xf4, + 0xf8, 0xe8, 0xa9, 0x33, 0xd9, 0xec, 0xc9, 0xdd, 0x1b, 0x83, 0x33, + 0xcb, 0xe2, 0x8c, 0xfc, 0x37, 0xd9, 0x71, 0x9e, 0x1c})), + std::make_pair( + 49, + std::vector<uint8_t>( + {0x7b, 0x4f, 0xa1, 0x58, 0xe4, 0x15, 0xfe, 0xf0, 0x23, 0x24, 0x72, + 0x64, 0xcb, 0xbe, 0x15, 0xd1, 0x6d, 0x91, 0xa4, 0x44, 0x24, 0xa8, + 0xdb, 0x70, 0x7e, 0xb1, 0xe2, 0x03, 0x3c, 0x30, 0xe9, 0xe1, 0xe7, + 0xc8, 0xc0, 0x86, 0x45, 0x95, 0xd2, 0xcb, 0x8c, 0x58, 0x0e, 0xb4, + 0x7e, 0x9d, 0x16, 0xab, 0xbd, 0x7e, 0x44, 0xe8, 0x24, 0xf7, 0xce, + 0xdb, 0x7d, 0xef, 0x57, 0x13, 0x0e, 0x52, 0xcf, 0xe9})), + std::make_pair( + 50, + std::vector<uint8_t>( + {0x60, 0x42, 0x4f, 0xf2, 0x32, 0x34, 0xc3, 0x4d, 0xc9, 0x68, 0x7a, + 0xd5, 0x02, 0x86, 0x93, 0x72, 0xcc, 0x31, 0xa5, 0x93, 0x80, 0x18, + 0x6b, 0xc2, 0x36, 0x1c, 0x83, 0x5d, 0x97, 0x2f, 0x49, 0x66, 0x6e, + 0xb1, 0xac, 0x69, 0x62, 0x9d, 0xe6, 0x46, 0xf0, 0x3f, 0x9b, 0x4d, + 0xb9, 0xe2, 0xac, 0xe0, 0x93, 0xfb, 0xfd, 0xf8, 0xf2, 0x0a, 0xb5, + 0xf9, 0x85, 0x41, 0x97, 0x8b, 0xe8, 0xef, 0x54, 0x9f})), + std::make_pair( + 51, + std::vector<uint8_t>( + {0x74, 0x06, 0x01, 0x8c, 0xe7, 0x04, 0xd8, 0x4f, 0x5e, 0xb9, 0xc7, + 0x9f, 0xea, 0x97, 0xda, 0x34, 0x56, 0x99, 0x46, 0x8a, 0x35, 0x0e, + 0xe0, 0xb2, 0xd0, 0xf3, 0xa4, 0xbf, 0x20, 0x70, 0x30, 0x4e, 0xa8, + 0x62, 0xd7, 0x2a, 0x51, 0xc5, 0x7d, 0x30, 0x64, 0x94, 0x72, 0x86, + 0xf5, 0x31, 0xe0, 0xea, 0xf7, 0x56, 0x37, 0x02, 0x26, 0x2e, 0x6c, + 0x72, 0x4a, 0xbf, 0x5e, 0xd8, 0xc8, 0x39, 0x8d, 0x17})), + std::make_pair( + 52, + std::vector<uint8_t>( + {0x14, 0xef, 0x5c, 0x6d, 0x64, 0x7b, 0x3b, 0xd1, 0xe6, 0xe3, 0x20, + 0x06, 0xc2, 0x31, 0x19, 0x98, 0x10, 0xde, 0x5c, 0x4d, 0xc8, 0x8e, + 0x70, 0x24, 0x02, 0x73, 0xb0, 0xea, 0x18, 0xe6, 0x51, 0xa3, 0xeb, + 0x4f, 0x5c, 0xa3, 0x11, 0x4b, 0x8a, 0x56, 0x71, 0x69, 0x69, 0xc7, + 0xcd, 0xa2, 0x7e, 0x0c, 0x8d, 0xb8, 0x32, 0xad, 0x5e, 0x89, 0xa2, + 0xdc, 0x6c, 0xb0, 0xad, 0xbe, 0x7d, 0x93, 0xab, 0xd1})), + std::make_pair( + 53, + std::vector<uint8_t>( + {0x38, 0xcf, 0x6c, 0x24, 0xe3, 0xe0, 0x8b, 0xcf, 0x1f, 0x6c, 0xf3, + 0xd1, 0xb1, 0xf6, 0x5b, 0x90, 0x52, 0x39, 0xa3, 0x11, 0x80, 0x33, + 0x24, 0x9e, 0x44, 0x81, 0x13, 0xec, 0x63, 0x2e, 0xa6, 0xdc, 0x34, + 0x6f, 0xee, 0xb2, 0x57, 0x1c, 0x38, 0xbd, 0x9a, 0x73, 0x98, 0xb2, + 0x22, 0x12, 0x80, 0x32, 0x80, 0x02, 0xb2, 0x3e, 0x1a, 0x45, 0xad, + 0xaf, 0xfe, 0x66, 0xd9, 0x3f, 0x65, 0x64, 0xea, 0xa2})), + std::make_pair( + 54, + std::vector<uint8_t>( + {0x6c, 0xd7, 0x20, 0x8a, 0x4b, 0xc7, 0xe7, 0xe5, 0x62, 0x01, 0xbb, + 0xba, 0x02, 0xa0, 0xf4, 0x89, 0xcd, 0x38, 0x4a, 0xbe, 0x40, 0xaf, + 0xd4, 0x22, 0x2f, 0x15, 0x8b, 0x3d, 0x98, 0x6e, 0xe7, 0x2a, 0x54, + 0xc5, 0x0f, 0xb6, 0x4f, 0xd4, 0xed, 0x25, 0x30, 0xed, 0xa2, 0xc8, + 0xaf, 0x29, 0x28, 0xa0, 0xda, 0x6d, 0x4f, 0x83, 0x0a, 0xe1, 0xc9, + 0xdb, 0x46, 0x9d, 0xfd, 0x97, 0x0f, 0x12, 0xa5, 0x6f})), + std::make_pair( + 55, + std::vector<uint8_t>( + {0x65, 0x98, 0x58, 0xf0, 0xb5, 0xc9, 0xed, 0xab, 0x5b, 0x94, 0xfd, + 0x73, 0x2f, 0x6e, 0x6b, 0x17, 0xc5, 0x1c, 0xc0, 0x96, 0x10, 0x4f, + 0x09, 0xbe, 0xb3, 0xaf, 0xc3, 0xaa, 0x46, 0x7c, 0x2e, 0xcf, 0x88, + 0x5c, 0x4c, 0x65, 0x41, 0xef, 0xfa, 0x90, 0x23, 0xd3, 0xb5, 0x73, + 0x8a, 0xe5, 0xa1, 0x4d, 0x86, 0x7e, 0x15, 0xdb, 0x06, 0xfe, 0x1f, + 0x9d, 0x11, 0x27, 0xb7, 0x7e, 0x1a, 0xab, 0xb5, 0x16})), + std::make_pair( + 56, + std::vector<uint8_t>( + {0x26, 0xcc, 0xa0, 0x12, 0x6f, 0x5d, 0x1a, 0x81, 0x3c, 0x62, 0xe5, + 0xc7, 0x10, 0x01, 0xc0, 0x46, 0xf9, 0xc9, 0x20, 0x95, 0x70, 0x45, + 0x50, 0xbe, 0x58, 0x73, 0xa4, 0x95, 0xa9, 0x99, 0xad, 0x01, 0x0a, + 0x4f, 0x79, 0x49, 0x1f, 0x24, 0xf2, 0x86, 0x50, 0x0a, 0xdc, 0xe1, + 0xa1, 0x37, 0xbc, 0x20, 0x84, 0xe4, 0x94, 0x9f, 0x5b, 0x72, 0x94, + 0xce, 0xfe, 0x51, 0xec, 0xaf, 0xf8, 0xe9, 0x5c, 0xba})), + std::make_pair( + 57, + std::vector<uint8_t>( + {0x41, 0x47, 0xc1, 0xf5, 0x51, 0x72, 0x78, 0x8c, 0x55, 0x67, 0xc5, + 0x61, 0xfe, 0xef, 0x87, 0x6f, 0x62, 0x1f, 0xff, 0x1c, 0xe8, 0x77, + 0x86, 0xb8, 0x46, 0x76, 0x37, 0xe7, 0x0d, 0xfb, 0xcd, 0x0d, 0xbd, + 0xb6, 0x41, 0x5c, 0xb6, 0x00, 0x95, 0x4a, 0xb9, 0xc0, 0x4c, 0x0e, + 0x45, 0x7e, 0x62, 0x5b, 0x40, 0x72, 0x22, 0xc0, 0xfe, 0x1a, 0xe2, + 0x1b, 0x21, 0x43, 0x68, 0x8a, 0xda, 0x94, 0xdc, 0x58})), + std::make_pair( + 58, + std::vector<uint8_t>( + {0x5b, 0x1b, 0xf1, 0x54, 0xc6, 0x2a, 0x8a, 0xf6, 0xe9, 0x3d, 0x35, + 0xf1, 0x8f, 0x7f, 0x90, 0xab, 0xb1, 0x6a, 0x6e, 0xf0, 0xe8, 0xd1, + 0xae, 0xcd, 0x11, 0x8b, 0xf7, 0x01, 0x67, 0xba, 0xb2, 0xaf, 0x08, + 0x93, 0x5c, 0x6f, 0xdc, 0x06, 0x63, 0xce, 0x74, 0x48, 0x2d, 0x17, + 0xa8, 0xe5, 0x4b, 0x54, 0x6d, 0x1c, 0x29, 0x66, 0x31, 0xc6, 0x5f, + 0x3b, 0x52, 0x2a, 0x51, 0x58, 0x39, 0xd4, 0x3d, 0x71})), + std::make_pair( + 59, + std::vector<uint8_t>( + {0x9f, 0x60, 0x04, 0x19, 0xa4, 0xe8, 0xf4, 0xfb, 0x83, 0x4c, 0x24, + 0xb0, 0xf7, 0xfc, 0x13, 0xbf, 0x4e, 0x27, 0x9d, 0x98, 0xe8, 0xa3, + 0xc7, 0x65, 0xee, 0x93, 0x49, 0x17, 0x40, 0x3e, 0x3a, 0x66, 0x09, + 0x71, 0x82, 0xea, 0x21, 0x45, 0x3c, 0xb6, 0x3e, 0xbb, 0xe8, 0xb7, + 0x3a, 0x9c, 0x21, 0x67, 0x59, 0x64, 0x46, 0x43, 0x8c, 0x57, 0x62, + 0x7f, 0x33, 0x0b, 0xad, 0xd4, 0xf5, 0x69, 0xf7, 0xd6})), + std::make_pair( + 60, + std::vector<uint8_t>( + {0x45, 0x7e, 0xf6, 0x46, 0x6a, 0x89, 0x24, 0xfd, 0x80, 0x11, 0xa3, + 0x44, 0x71, 0xa5, 0xa1, 0xac, 0x8c, 0xcd, 0x9b, 0xd0, 0xd0, 0x7a, + 0x97, 0x41, 0x4a, 0xc9, 0x43, 0x02, 0x1c, 0xe4, 0xb9, 0xe4, 0xb9, + 0xc8, 0xdb, 0x0a, 0x28, 0xf0, 0x16, 0xed, 0x43, 0xb1, 0x54, 0x24, + 0x81, 0x99, 0x00, 0x22, 0x14, 0x7b, 0x31, 0x3e, 0x19, 0x46, 0x71, + 0x13, 0x1e, 0x70, 0x8d, 0xd4, 0x3a, 0x3e, 0xd7, 0xdc})), + std::make_pair( + 61, + std::vector<uint8_t>( + {0x99, 0x97, 0xb2, 0x19, 0x4d, 0x9a, 0xf6, 0xdf, 0xcb, 0x91, 0x43, + 0xf4, 0x1c, 0x0e, 0xd8, 0x3d, 0x3a, 0x3f, 0x43, 0x88, 0x36, 0x11, + 0x03, 0xd3, 0x8c, 0x2a, 0x49, 0xb2, 0x80, 0xa5, 0x81, 0x21, 0x27, + 0x15, 0xfd, 0x90, 0x8d, 0x41, 0xc6, 0x51, 0xf5, 0xc7, 0x15, 0xca, + 0x38, 0xc0, 0xce, 0x28, 0x30, 0xa3, 0x7e, 0x00, 0xe5, 0x08, 0xce, + 0xd1, 0xbc, 0xdc, 0x32, 0x0e, 0x5e, 0x4d, 0x1e, 0x2e})), + std::make_pair( + 62, + std::vector<uint8_t>( + {0x5c, 0x6b, 0xbf, 0x16, 0xba, 0xa1, 0x80, 0xf9, 0x86, 0xbd, 0x40, + 0xa1, 0x28, 0x7e, 0xd4, 0xc5, 0x49, 0x77, 0x0e, 0x72, 0x84, 0x85, + 0x8f, 0xc4, 0x7b, 0xc2, 0x1a, 0xb9, 0x5e, 0xbb, 0xf3, 0x37, 0x4b, + 0x4e, 0xe3, 0xfd, 0x9f, 0x2a, 0xf6, 0x0f, 0x33, 0x95, 0x22, 0x1b, + 0x2a, 0xcc, 0x76, 0xf2, 0xd3, 0x4c, 0x13, 0x29, 0x54, 0x04, 0x9f, + 0x8a, 0x3a, 0x99, 0x6f, 0x1e, 0x32, 0xec, 0x84, 0xe5})), + std::make_pair( + 63, + std::vector<uint8_t>( + {0xd1, 0x0b, 0xf9, 0xa1, 0x5b, 0x1c, 0x9f, 0xc8, 0xd4, 0x1f, 0x89, + 0xbb, 0x14, 0x0b, 0xf0, 0xbe, 0x08, 0xd2, 0xf3, 0x66, 0x61, 0x76, + 0xd1, 0x3b, 0xaa, 0xc4, 0xd3, 0x81, 0x35, 0x8a, 0xd0, 0x74, 0xc9, + 0xd4, 0x74, 0x8c, 0x30, 0x05, 0x20, 0xeb, 0x02, 0x6d, 0xae, 0xae, + 0xa7, 0xc5, 0xb1, 0x58, 0x89, 0x2f, 0xde, 0x4e, 0x8e, 0xc1, 0x7d, + 0xc9, 0x98, 0xdc, 0xd5, 0x07, 0xdf, 0x26, 0xeb, 0x63})), + std::make_pair( + 64, + std::vector<uint8_t>( + {0x2f, 0xc6, 0xe6, 0x9f, 0xa2, 0x6a, 0x89, 0xa5, 0xed, 0x26, 0x90, + 0x92, 0xcb, 0x9b, 0x2a, 0x44, 0x9a, 0x44, 0x09, 0xa7, 0xa4, 0x40, + 0x11, 0xee, 0xca, 0xd1, 0x3d, 0x7c, 0x4b, 0x04, 0x56, 0x60, 0x2d, + 0x40, 0x2f, 0xa5, 0x84, 0x4f, 0x1a, 0x7a, 0x75, 0x81, 0x36, 0xce, + 0x3d, 0x5d, 0x8d, 0x0e, 0x8b, 0x86, 0x92, 0x1f, 0xff, 0xf4, 0xf6, + 0x92, 0xdd, 0x95, 0xbd, 0xc8, 0xe5, 0xff, 0x00, 0x52})), + std::make_pair( + 65, + std::vector<uint8_t>( + {0xfc, 0xbe, 0x8b, 0xe7, 0xdc, 0xb4, 0x9a, 0x32, 0xdb, 0xdf, 0x23, + 0x94, 0x59, 0xe2, 0x63, 0x08, 0xb8, 0x4d, 0xff, 0x1e, 0xa4, 0x80, + 0xdf, 0x8d, 0x10, 0x4e, 0xef, 0xf3, 0x4b, 0x46, 0xfa, 0xe9, 0x86, + 0x27, 0xb4, 0x50, 0xc2, 0x26, 0x7d, 0x48, 0xc0, 0x94, 0x6a, 0x69, + 0x7c, 0x5b, 0x59, 0x53, 0x14, 0x52, 0xac, 0x04, 0x84, 0xf1, 0xc8, + 0x4e, 0x3a, 0x33, 0xd0, 0xc3, 0x39, 0xbb, 0x2e, 0x28})), + std::make_pair( + 66, + std::vector<uint8_t>( + {0xa1, 0x90, 0x93, 0xa6, 0xe3, 0xbc, 0xf5, 0x95, 0x2f, 0x85, 0x0f, + 0x20, 0x30, 0xf6, 0x9b, 0x96, 0x06, 0xf1, 0x47, 0xf9, 0x0b, 0x8b, + 0xae, 0xe3, 0x36, 0x2d, 0xa7, 0x1d, 0x9f, 0x35, 0xb4, 0x4e, 0xf9, + 0xd8, 0xf0, 0xa7, 0x71, 0x2b, 0xa1, 0x87, 0x7f, 0xdd, 0xcd, 0x2d, + 0x8e, 0xa8, 0xf1, 0xe5, 0xa7, 0x73, 0xd0, 0xb7, 0x45, 0xd4, 0x72, + 0x56, 0x05, 0x98, 0x3a, 0x2d, 0xe9, 0x01, 0xf8, 0x03})), + std::make_pair( + 67, + std::vector<uint8_t>( + {0x3c, 0x20, 0x06, 0x42, 0x3f, 0x73, 0xe2, 0x68, 0xfa, 0x59, 0xd2, + 0x92, 0x03, 0x77, 0xeb, 0x29, 0xa4, 0xf9, 0xa8, 0xb4, 0x62, 0xbe, + 0x15, 0x98, 0x3e, 0xe3, 0xb8, 0x5a, 0xe8, 0xa7, 0x8e, 0x99, 0x26, + 0x33, 0x58, 0x1a, 0x90, 0x99, 0x89, 0x3b, 0x63, 0xdb, 0x30, 0x24, + 0x1c, 0x34, 0xf6, 0x43, 0x02, 0x7d, 0xc8, 0x78, 0x27, 0x9a, 0xf5, + 0x85, 0x0d, 0x7e, 0x2d, 0x4a, 0x26, 0x53, 0x07, 0x3a})), + std::make_pair( + 68, + std::vector<uint8_t>( + {0xd0, 0xf2, 0xf2, 0xe3, 0x78, 0x76, 0x53, 0xf7, 0x7c, 0xce, 0x2f, + 0xa2, 0x48, 0x35, 0x78, 0x5b, 0xbd, 0x0c, 0x43, 0x3f, 0xc7, 0x79, + 0x46, 0x5a, 0x11, 0x51, 0x49, 0x90, 0x5a, 0x9d, 0xd1, 0xcb, 0x82, + 0x7a, 0x62, 0x85, 0x06, 0xd4, 0x57, 0xfc, 0xf1, 0x24, 0xa0, 0xc2, + 0xae, 0xf9, 0xce, 0x2d, 0x2a, 0x0a, 0x0f, 0x63, 0x54, 0x55, 0x70, + 0xd8, 0x66, 0x7f, 0xf9, 0xe2, 0xeb, 0xa0, 0x73, 0x34})), + std::make_pair( + 69, + std::vector<uint8_t>( + {0x78, 0xa9, 0xfc, 0x04, 0x8e, 0x25, 0xc6, 0xdc, 0xb5, 0xde, 0x45, + 0x66, 0x7d, 0xe8, 0xff, 0xdd, 0x3a, 0x93, 0x71, 0x11, 0x41, 0xd5, + 0x94, 0xe9, 0xfa, 0x62, 0xa9, 0x59, 0x47, 0x5d, 0xa6, 0x07, 0x5e, + 0xa8, 0xf0, 0x91, 0x6e, 0x84, 0xe4, 0x5a, 0xd9, 0x11, 0xb7, 0x54, + 0x67, 0x07, 0x7e, 0xe5, 0x2d, 0x2c, 0x9a, 0xeb, 0xf4, 0xd5, 0x8f, + 0x20, 0xce, 0x4a, 0x3a, 0x00, 0x45, 0x8b, 0x05, 0xd4})), + std::make_pair( + 70, + std::vector<uint8_t>( + {0x45, 0x81, 0x3f, 0x44, 0x17, 0x69, 0xab, 0x6e, 0xd3, 0x7d, 0x34, + 0x9f, 0xf6, 0xe7, 0x22, 0x67, 0xd7, 0x6a, 0xe6, 0xbb, 0x3e, 0x3c, + 0x61, 0x2e, 0xc0, 0x5c, 0x6e, 0x02, 0xa1, 0x2a, 0xf5, 0xa3, 0x7c, + 0x91, 0x8b, 0x52, 0xbf, 0x74, 0x26, 0x7c, 0x3f, 0x6a, 0x3f, 0x18, + 0x3a, 0x80, 0x64, 0xff, 0x84, 0xc0, 0x7b, 0x19, 0x3d, 0x08, 0x06, + 0x67, 0x89, 0xa0, 0x1a, 0xcc, 0xdb, 0x6f, 0x93, 0x40})), + std::make_pair( + 71, + std::vector<uint8_t>( + {0x95, 0x6d, 0xa1, 0xc6, 0x8d, 0x83, 0xa7, 0xb8, 0x81, 0xe0, 0x1b, + 0x9a, 0x96, 0x6c, 0x3c, 0x0b, 0xf2, 0x7f, 0x68, 0x60, 0x6a, 0x8b, + 0x71, 0xd4, 0x57, 0xbd, 0x01, 0x6d, 0x4c, 0x41, 0xdd, 0x8a, 0x38, + 0x0c, 0x70, 0x9a, 0x29, 0x6c, 0xb4, 0xc6, 0x54, 0x47, 0x92, 0x92, + 0x0f, 0xd7, 0x88, 0x83, 0x57, 0x71, 0xa0, 0x7d, 0x4a, 0x16, 0xfb, + 0x52, 0xed, 0x48, 0x05, 0x03, 0x31, 0xdc, 0x4c, 0x8b})), + std::make_pair( + 72, + std::vector<uint8_t>( + {0xdf, 0x18, 0x6c, 0x2d, 0xc0, 0x9c, 0xaa, 0x48, 0xe1, 0x4e, 0x94, + 0x2f, 0x75, 0xde, 0x5a, 0xc1, 0xb7, 0xa2, 0x1e, 0x4f, 0x9f, 0x07, + 0x2a, 0x5b, 0x37, 0x1e, 0x09, 0xe0, 0x73, 0x45, 0xb0, 0x74, 0x0c, + 0x76, 0x17, 0x7b, 0x01, 0x27, 0x88, 0x08, 0xfe, 0xc0, 0x25, 0xed, + 0xed, 0x98, 0x22, 0xc1, 0x22, 0xaf, 0xd1, 0xc6, 0x3e, 0x6f, 0x0c, + 0xe2, 0xe3, 0x26, 0x31, 0x04, 0x10, 0x63, 0x14, 0x5c})), + std::make_pair( + 73, + std::vector<uint8_t>( + {0x87, 0x47, 0x56, 0x40, 0x96, 0x6a, 0x9f, 0xdc, 0xd6, 0xd3, 0xa3, + 0xb5, 0xa2, 0xcc, 0xa5, 0xc0, 0x8f, 0x0d, 0x88, 0x2b, 0x10, 0x24, + 0x3c, 0x0e, 0xc1, 0xbf, 0x3c, 0x6b, 0x1c, 0x37, 0xf2, 0xcd, 0x32, + 0x12, 0xf1, 0x9a, 0x05, 0x78, 0x64, 0x47, 0x7d, 0x5e, 0xaf, 0x8f, + 0xae, 0xd7, 0x3f, 0x29, 0x37, 0xc7, 0x68, 0xa0, 0xaf, 0x41, 0x5e, + 0x84, 0xbb, 0xce, 0x6b, 0xd7, 0xde, 0x23, 0xb6, 0x60})), + std::make_pair( + 74, + std::vector<uint8_t>( + {0xc3, 0xb5, 0x73, 0xbb, 0xe1, 0x09, 0x49, 0xa0, 0xfb, 0xd4, 0xff, + 0x88, 0x4c, 0x44, 0x6f, 0x22, 0x29, 0xb7, 0x69, 0x02, 0xf9, 0xdf, + 0xdb, 0xb8, 0xa0, 0x35, 0x3d, 0xa5, 0xc8, 0x3c, 0xa1, 0x4e, 0x81, + 0x51, 0xbb, 0xaa, 0xc8, 0x2f, 0xd1, 0x57, 0x6a, 0x00, 0x9a, 0xdc, + 0x6f, 0x19, 0x35, 0xcf, 0x26, 0xed, 0xd4, 0xf1, 0xfb, 0x8d, 0xa4, + 0x83, 0xe6, 0xc5, 0xcd, 0x9d, 0x89, 0x23, 0xad, 0xc3})), + std::make_pair( + 75, + std::vector<uint8_t>( + {0xb0, 0x9d, 0x8d, 0x0b, 0xba, 0x8a, 0x72, 0x86, 0xe4, 0x35, 0x68, + 0xf7, 0x90, 0x75, 0x50, 0xe4, 0x20, 0x36, 0xd6, 0x74, 0xe3, 0xc8, + 0xfc, 0x34, 0xd8, 0xca, 0x46, 0xf7, 0x71, 0xd6, 0x46, 0x6b, 0x70, + 0xfb, 0x60, 0x58, 0x75,