зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to autoland. r=merge a=merge CLOSED TREE
This commit is contained in:
Коммит
f8979ebb32
|
@ -2539,19 +2539,22 @@
|
|||
|
||||
<method name="discardBrowser">
|
||||
<parameter name="aBrowser"/>
|
||||
<parameter name="aForceDiscard"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
"use strict";
|
||||
|
||||
let tab = this.getTabForBrowser(aBrowser);
|
||||
|
||||
let permitUnloadFlags = aForceDiscard ? aBrowser.dontPromptAndUnload : aBrowser.dontPromptAndDontUnload;
|
||||
|
||||
if (!tab ||
|
||||
tab.selected ||
|
||||
tab.closing ||
|
||||
this._windowIsClosing ||
|
||||
!aBrowser.isConnected ||
|
||||
!aBrowser.isRemoteBrowser ||
|
||||
aBrowser.frameLoader.tabParent.hasBeforeUnload) {
|
||||
!aBrowser.permitUnload(permitUnloadFlags).permitUnload) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ support-files =
|
|||
restore_redirect_target.html
|
||||
browser_1234021_page.html
|
||||
browser_1284886_suspend_tab.html
|
||||
browser_1284886_suspend_tab_2.html
|
||||
|
||||
#NB: the following are disabled
|
||||
# browser_464620_a.html
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
add_task(async function test() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
"set": [
|
||||
["dom.require_user_interaction_for_beforeunload", false],
|
||||
]
|
||||
});
|
||||
|
||||
let url = "about:robots";
|
||||
let tab0 = gBrowser.tabs[0];
|
||||
let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
|
||||
|
@ -23,18 +29,35 @@ add_task(async function test() {
|
|||
|
||||
gBrowser._endRemoveTab(tab1);
|
||||
|
||||
// Test that tab with beforeunload handler is not able to be suspended.
|
||||
// Open tab containing a page which has a beforeunload handler which shows a prompt.
|
||||
url = "http://example.com/browser/browser/components/sessionstore/test/browser_1284886_suspend_tab.html";
|
||||
|
||||
tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
|
||||
let browser1 = tab1.linkedBrowser;
|
||||
await BrowserTestUtils.switchTab(gBrowser, tab0);
|
||||
|
||||
gBrowser.discardBrowser(tab1.linkedBrowser);
|
||||
ok(tab1.linkedPanel, "cannot suspend a tab with beforeunload handler");
|
||||
// Test that tab with beforeunload handler which would show a prompt cannot be suspended.
|
||||
gBrowser.discardBrowser(browser1);
|
||||
ok(tab1.linkedPanel, "cannot suspend a tab with beforeunload handler which would show a prompt");
|
||||
|
||||
// Test that tab with beforeunload handler which would show a prompt will be suspended if forced.
|
||||
gBrowser.discardBrowser(browser1, true);
|
||||
ok(!tab1.linkedPanel, "force suspending a tab with beforeunload handler which would show a prompt");
|
||||
|
||||
await promiseRemoveTab(tab1);
|
||||
|
||||
// Test that remote tab is not able to be suspended.
|
||||
// Open tab containing a page which has a beforeunload handler which does not show a prompt.
|
||||
url = "http://example.com/browser/browser/components/sessionstore/test/browser_1284886_suspend_tab_2.html";
|
||||
tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
|
||||
browser1 = tab1.linkedBrowser;
|
||||
await BrowserTestUtils.switchTab(gBrowser, tab0);
|
||||
|
||||
// Test that tab with beforeunload handler which would not show a prompt can be suspended.
|
||||
gBrowser.discardBrowser(browser1);
|
||||
ok(!tab1.linkedPanel, "can suspend a tab with beforeunload handler which would not show a prompt");
|
||||
|
||||
await promiseRemoveTab(tab1);
|
||||
|
||||
// Test that non-remote tab is not able to be suspended.
|
||||
url = "about:robots";
|
||||
tab1 = BrowserTestUtils.addTab(gBrowser, url, { forceNotRemote: true });
|
||||
await promiseBrowserLoaded(tab1.linkedBrowser, true, url);
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<html>
|
||||
<head>
|
||||
<script>
|
||||
window.onbeforeunload = function() {
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
TEST PAGE
|
||||
</body>
|
||||
</html>
|
|
@ -181,7 +181,15 @@ void CanRunScriptChecker::check(const MatchFinder::MatchResult &Result) {
|
|||
Result.Nodes.getNodeAs<FunctionDecl>("nonCanRunScriptParentFunction");
|
||||
// If the parent function can run script, consider that we didn't find a match
|
||||
// because we only care about parent functions which can't run script.
|
||||
if (ParentFunction && CanRunScriptFuncs.count(ParentFunction)) {
|
||||
//
|
||||
// In addition, If the parent function is annotated as a
|
||||
// CAN_RUN_SCRIPT_BOUNDARY, we don't want to complain about it calling a
|
||||
// CAN_RUN_SCRIPT function. This is a mechanism to opt out of the infectious
|
||||
// nature of CAN_RUN_SCRIPT which is necessary in some tricky code like
|
||||
// Bindings.
|
||||
if (ParentFunction &&
|
||||
(CanRunScriptFuncs.count(ParentFunction) ||
|
||||
hasCustomAnnotation(ParentFunction, "moz_can_run_script_boundary"))) {
|
||||
ParentFunction = nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include <mozilla/RefPtr.h>
|
||||
|
||||
#define MOZ_CAN_RUN_SCRIPT __attribute__((annotate("moz_can_run_script")))
|
||||
#define MOZ_CAN_RUN_SCRIPT_BOUNDARY __attribute__((annotate("moz_can_run_script_boundary")))
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT void test() {
|
||||
|
||||
|
@ -104,4 +105,23 @@ MOZ_CAN_RUN_SCRIPT void test4() {
|
|||
|
||||
RefPtr<RefCountedSubChild> refptr4 = new RefCountedSubChild;
|
||||
refptr4->method_test3();
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY void test5() {
|
||||
RefPtr<RefCountedBase> refptr1 = new RefCountedChild;
|
||||
refptr1->method_test3();
|
||||
|
||||
RefPtr<RefCountedBase> refptr2 = new RefCountedSubChild;
|
||||
refptr2->method_test3();
|
||||
|
||||
RefPtr<RefCountedChild> refptr3 = new RefCountedSubChild;
|
||||
refptr3->method_test3();
|
||||
|
||||
RefPtr<RefCountedSubChild> refptr4 = new RefCountedSubChild;
|
||||
refptr4->method_test3();
|
||||
}
|
||||
|
||||
// We should be able to call test5 from a non-can_run_script function.
|
||||
void test5_b() {
|
||||
test5();
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ With Mercurial:
|
|||
|
||||
With Git, the process is similar, but you first need to add an alias to create Mercurial-style patches. Have a look at [the detailed documentation](https://developer.mozilla.org/en-US/docs/Tools/Contributing#Creating_a_patch_to_check_in).
|
||||
|
||||
## Commit messags
|
||||
## Commit messages
|
||||
|
||||
Commit messages should follow the pattern `Bug 1234567 - change description. r=reviewer`
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
# Getting started
|
||||
|
||||
1. Learn [where the code is](./getting-started/where-is-the-code.md) and about the [architecture](./getting-started/servers-and-actors.md) of the tools.
|
||||
2. [Set up your machine](./getting-started/build.md) to build the tools, then [configure a development profile](getting-started/development-profiles.md).
|
||||
3. You can now experiment by changing things and rebuilding, look at the [files and directories overview](../files/README.md) or you could also [find something to work on](./bugs-issues.md).
|
||||
1. Learn [where the code is](./where-is-the-code.md) and about the [architecture](./architecture-overview.md) of the tools.
|
||||
2. [Set up your machine](./build.md) to build the tools, then [configure a development profile](development-profiles.md).
|
||||
3. You can now experiment by changing things and rebuilding, look at the [files and directories overview](../files/README.md) or you could also [find something to work on](../bugs-issues.md).
|
||||
|
||||
## Additional documentation
|
||||
|
||||
* [Mozilla Developer Network](http://developer.mozilla.org/) (also known as *MDN*) has a lot of information about XUL elements, HTML, JS, DOM, Web APIs, Gecko-specific APIs, and more.
|
||||
* [MDN Web Docs](http://developer.mozilla.org/) (also known as *MDN*) has a lot of information about XUL elements, HTML, JS, DOM, Web APIs, Gecko-specific APIs, and more.
|
||||
* [DXR](http://dxr.mozilla.org/mozilla-central/source/) is a source code search engine - search for symbols you want to learn about, eg. `nsIDocument`. [Searchfox](http://searchfox.org/mozilla-central/source) is an alternative.
|
||||
|
||||
It is a good idea to [add smart keyword searches](https://support.mozilla.org/en-US/kb/how-search-from-address-bar) for DXR and MDN, so you can search faster.
|
||||
|
|
|
@ -50,10 +50,35 @@ interface nsIContentViewer : nsISupports
|
|||
[noscript] readonly attribute boolean isStopped;
|
||||
|
||||
/**
|
||||
* Checks if the document wants to prevent unloading by firing beforeunload on
|
||||
* the document, and if it does, prompts the user. The result is returned.
|
||||
* aPermitUnloadFlags are passed to PermitUnload to indicate what action to take
|
||||
* if a beforeunload handler wants to prompt the user. It is also used by
|
||||
* permitUnloadInternal to ensure we only prompt once.
|
||||
*
|
||||
* ePrompt: Prompt and return the user's choice (default).
|
||||
* eDontPromptAndDontUnload: Don't prompt and return false (unload not permitted)
|
||||
* if the document (or its children) asks us to prompt.
|
||||
* eDontPromptAndUnload: Don't prompt and return true (unload permitted) no matter what.
|
||||
*/
|
||||
boolean permitUnload();
|
||||
const unsigned long ePrompt = 0;
|
||||
const unsigned long eDontPromptAndDontUnload = 1;
|
||||
const unsigned long eDontPromptAndUnload = 2;
|
||||
|
||||
/**
|
||||
* Overload PermitUnload method for C++ consumers with no aPermitUnloadFlags
|
||||
* argument.
|
||||
*/
|
||||
%{C++
|
||||
nsresult PermitUnload(bool* canUnload) {
|
||||
return PermitUnload(ePrompt, canUnload);
|
||||
}
|
||||
%}
|
||||
|
||||
/**
|
||||
* Checks if the document wants to prevent unloading by firing beforeunload on
|
||||
* the document, and if it does, takes action directed by aPermitUnloadFlags.
|
||||
* The result is returned.
|
||||
*/
|
||||
boolean permitUnload([optional] in unsigned long aPermitUnloadFlags);
|
||||
|
||||
/**
|
||||
* Exposes whether we're blocked in a call to permitUnload.
|
||||
|
@ -61,11 +86,11 @@ interface nsIContentViewer : nsISupports
|
|||
readonly attribute boolean inPermitUnload;
|
||||
|
||||
/**
|
||||
* As above, but this passes around the aShouldPrompt argument to keep
|
||||
* As above, but this passes around the aPermitUnloadFlags argument to keep
|
||||
* track of whether the user has responded to a prompt.
|
||||
* Used internally by the scriptable version to ensure we only prompt once.
|
||||
*/
|
||||
[noscript,nostdcall] boolean permitUnloadInternal(inout boolean aShouldPrompt);
|
||||
[noscript,nostdcall] boolean permitUnloadInternal(inout unsigned long aPermitUnloadFlags);
|
||||
|
||||
/**
|
||||
* Exposes whether we're in the process of firing the beforeunload event.
|
||||
|
|
|
@ -39,6 +39,11 @@ support-files =
|
|||
file_bug1328501.html
|
||||
file_bug1328501_frame.html
|
||||
file_bug1328501_framescript.js
|
||||
file_bug1415918_beforeunload_2.html
|
||||
file_bug1415918_beforeunload_3.html
|
||||
file_bug1415918_beforeunload_iframe_2.html
|
||||
file_bug1415918_beforeunload_iframe.html
|
||||
file_bug1415918_beforeunload.html
|
||||
file_multiple_pushState.html
|
||||
print_postdata.sjs
|
||||
test-form_sjis.html
|
||||
|
@ -56,6 +61,7 @@ support-files =
|
|||
[browser_bug1328501.js]
|
||||
[browser_bug1347823.js]
|
||||
[browser_bug134911.js]
|
||||
[browser_bug1415918_beforeunload_options.js]
|
||||
[browser_bug234628-1.js]
|
||||
[browser_bug234628-10.js]
|
||||
[browser_bug234628-11.js]
|
||||
|
|
|
@ -0,0 +1,242 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const TEST_PATH = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "http://example.com");
|
||||
|
||||
add_task(async function test() {
|
||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
"set": [
|
||||
["dom.require_user_interaction_for_beforeunload", false],
|
||||
]
|
||||
});
|
||||
|
||||
let url = TEST_PATH + "file_bug1415918_beforeunload.html";
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
|
||||
let browser = tab.linkedBrowser;
|
||||
let stack = browser.parentNode;
|
||||
let buttonId;
|
||||
let promptShown = false;
|
||||
|
||||
let observer = new MutationObserver(function(mutations) {
|
||||
mutations.forEach(function(mutation) {
|
||||
if (buttonId && mutation.type == "attributes" && browser.hasAttribute("tabmodalPromptShowing")) {
|
||||
let prompt = stack.getElementsByTagNameNS(XUL_NS, "tabmodalprompt")[0];
|
||||
document.getAnonymousElementByAttribute(prompt, "anonid", buttonId).click();
|
||||
promptShown = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
observer.observe(browser, { attributes: true });
|
||||
|
||||
/*
|
||||
* Check condition where beforeunload handlers request a prompt.
|
||||
*/
|
||||
|
||||
// Prompt is shown, user clicks OK.
|
||||
buttonId = "button0";
|
||||
promptShown = false;
|
||||
ok(browser.permitUnload().permitUnload, "permit unload should be true");
|
||||
ok(promptShown, "prompt should have been displayed");
|
||||
|
||||
// Check that all beforeunload handlers fired and reset attributes.
|
||||
await ContentTask.spawn(browser, null, () => {
|
||||
ok(content.window.document.body.hasAttribute("fired"), "parent document beforeunload handler should fire");
|
||||
content.window.document.body.removeAttribute("fired");
|
||||
|
||||
for (let frame of Array.from(content.window.frames)) {
|
||||
ok(frame.document.body.hasAttribute("fired"), "frame document beforeunload handler should fire");
|
||||
frame.document.body.removeAttribute("fired");
|
||||
}
|
||||
});
|
||||
|
||||
// Prompt is shown, user clicks CANCEL.
|
||||
buttonId = "button1";
|
||||
promptShown = false;
|
||||
ok(!browser.permitUnload().permitUnload, "permit unload should be false");
|
||||
ok(promptShown, "prompt should have been displayed");
|
||||
buttonId = "";
|
||||
|
||||
// Check that only the parent beforeunload handler fired, and reset attribute.
|
||||
await ContentTask.spawn(browser, null, () => {
|
||||
ok(content.window.document.body.hasAttribute("fired"), "parent document beforeunload handler should fire");
|
||||
content.window.document.body.removeAttribute("fired");
|
||||
|
||||
for (let frame of Array.from(content.window.frames)) {
|
||||
ok(!frame.document.body.hasAttribute("fired"), "frame document beforeunload handler should not fire");
|
||||
}
|
||||
});
|
||||
|
||||
// Prompt is not shown, don't permit unload.
|
||||
promptShown = false;
|
||||
ok(!browser.permitUnload(browser.dontPromptAndDontUnload).permitUnload, "permit unload should be false");
|
||||
ok(!promptShown, "prompt should not have been displayed");
|
||||
|
||||
// Check that only the parent beforeunload handler fired, and reset attribute.
|
||||
await ContentTask.spawn(browser, null, () => {
|
||||
ok(content.window.document.body.hasAttribute("fired"), "parent document beforeunload handler should fire");
|
||||
content.window.document.body.removeAttribute("fired");
|
||||
|
||||
for (let frame of Array.from(content.window.frames)) {
|
||||
ok(!frame.document.body.hasAttribute("fired"), "frame document beforeunload handler should not fire");
|
||||
}
|
||||
});
|
||||
|
||||
// Prompt is not shown, permit unload.
|
||||
promptShown = false;
|
||||
ok(browser.permitUnload(browser.dontPromptAndUnload).permitUnload, "permit unload should be true");
|
||||
ok(!promptShown, "prompt should not have been displayed");
|
||||
|
||||
// Check that all beforeunload handlers fired.
|
||||
await ContentTask.spawn(browser, null, () => {
|
||||
ok(content.window.document.body.hasAttribute("fired"), "parent document beforeunload handler should fire");
|
||||
|
||||
for (let frame of Array.from(content.window.frames)) {
|
||||
ok(frame.document.body.hasAttribute("fired"), "frame document beforeunload handler should fire");
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* Check condition where no one requests a prompt. In all cases,
|
||||
* permitUnload should be true, and all handlers fired.
|
||||
*/
|
||||
|
||||
buttonId = "button0";
|
||||
url = TEST_PATH + "file_bug1415918_beforeunload_2.html";
|
||||
browser.loadURI(url);
|
||||
await BrowserTestUtils.browserLoaded(browser, false, url);
|
||||
buttonId = "";
|
||||
|
||||
promptShown = false;
|
||||
ok(browser.permitUnload().permitUnload, "permit unload should be true");
|
||||
ok(!promptShown, "prompt should not have been displayed");
|
||||
|
||||
// Check that all beforeunload handlers fired and reset attributes.
|
||||
await ContentTask.spawn(browser, null, () => {
|
||||
ok(content.window.document.body.hasAttribute("fired"), "parent document beforeunload handler should fire");
|
||||
content.window.document.body.removeAttribute("fired");
|
||||
|
||||
for (let frame of Array.from(content.window.frames)) {
|
||||
ok(frame.document.body.hasAttribute("fired"), "frame document beforeunload handler should fire");
|
||||
frame.document.body.removeAttribute("fired");
|
||||
}
|
||||
});
|
||||
|
||||
promptShown = false;
|
||||
ok(browser.permitUnload(browser.dontPromptAndDontUnload).permitUnload, "permit unload should be true");
|
||||
ok(!promptShown, "prompt should not have been displayed");
|
||||
|
||||
// Check that all beforeunload handlers fired and reset attributes.
|
||||
await ContentTask.spawn(browser, null, () => {
|
||||
ok(content.window.document.body.hasAttribute("fired"), "parent document beforeunload handler should fire");
|
||||
content.window.document.body.removeAttribute("fired");
|
||||
|
||||
for (let frame of Array.from(content.window.frames)) {
|
||||
ok(frame.document.body.hasAttribute("fired"), "frame document beforeunload handler should fire");
|
||||
frame.document.body.removeAttribute("fired");
|
||||
}
|
||||
});
|
||||
|
||||
promptShown = false;
|
||||
ok(browser.permitUnload(browser.dontPromptAndUnload).permitUnload, "permit unload should be true");
|
||||
ok(!promptShown, "prompt should not have been displayed");
|
||||
|
||||
// Check that all beforeunload handlers fired.
|
||||
await ContentTask.spawn(browser, null, () => {
|
||||
ok(content.window.document.body.hasAttribute("fired"), "parent document beforeunload handler should fire");
|
||||
|
||||
for (let frame of Array.from(content.window.frames)) {
|
||||
ok(frame.document.body.hasAttribute("fired"), "frame document beforeunload handler should fire");
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* Check condition where the parent beforeunload handler does not request a prompt,
|
||||
* but a child beforeunload handler does.
|
||||
*/
|
||||
|
||||
buttonId = "button0";
|
||||
url = TEST_PATH + "file_bug1415918_beforeunload_3.html";
|
||||
browser.loadURI(url);
|
||||
await BrowserTestUtils.browserLoaded(browser, false, url);
|
||||
|
||||
// Prompt is shown, user clicks OK.
|
||||
promptShown = false;
|
||||
ok(browser.permitUnload().permitUnload, "permit unload should be true");
|
||||
ok(promptShown, "prompt should have been displayed");
|
||||
|
||||
// Check that all beforeunload handlers fired and reset attributes.
|
||||
await ContentTask.spawn(browser, null, () => {
|
||||
ok(content.window.document.body.hasAttribute("fired"), "parent document beforeunload handler should fire");
|
||||
content.window.document.body.removeAttribute("fired");
|
||||
|
||||
for (let frame of Array.from(content.window.frames)) {
|
||||
ok(frame.document.body.hasAttribute("fired"), "frame document beforeunload handler should fire");
|
||||
frame.document.body.removeAttribute("fired");
|
||||
}
|
||||
});
|
||||
|
||||
// Prompt is shown, user clicks CANCEL.
|
||||
buttonId = "button1";
|
||||
promptShown = false;
|
||||
ok(!browser.permitUnload().permitUnload, "permit unload should be false");
|
||||
ok(promptShown, "prompt should have been displayed");
|
||||
buttonId = "";
|
||||
|
||||
// Check that the parent beforeunload handler fired, and only one child beforeunload
|
||||
// handler fired. Reset attributes.
|
||||
await ContentTask.spawn(browser, null, () => {
|
||||
ok(content.window.document.body.hasAttribute("fired"), "parent document beforeunload handler should fire");
|
||||
content.window.document.body.removeAttribute("fired");
|
||||
|
||||
let count = 0;
|
||||
for (let frame of Array.from(content.window.frames)) {
|
||||
if (frame.document.body.hasAttribute("fired")) {
|
||||
count++;
|
||||
frame.document.body.removeAttribute("fired");
|
||||
}
|
||||
}
|
||||
is(count, 1, "only one frame document beforeunload handler should fire");
|
||||
});
|
||||
|
||||
// Prompt is not shown, don't permit unload.
|
||||
promptShown = false;
|
||||
ok(!browser.permitUnload(browser.dontPromptAndDontUnload).permitUnload, "permit unload should be false");
|
||||
ok(!promptShown, "prompt should not have been displayed");
|
||||
|
||||
// Check that the parent beforeunload handler fired, and only one child beforeunload
|
||||
// handler fired. Reset attributes.
|
||||
await ContentTask.spawn(browser, null, () => {
|
||||
ok(content.window.document.body.hasAttribute("fired"), "parent document beforeunload handler should fire");
|
||||
content.window.document.body.removeAttribute("fired");
|
||||
|
||||
let count = 0;
|
||||
for (let frame of Array.from(content.window.frames)) {
|
||||
if (frame.document.body.hasAttribute("fired")) {
|
||||
count++;
|
||||
frame.document.body.removeAttribute("fired");
|
||||
}
|
||||
}
|
||||
is(count, 1, "only one frame document beforeunload handler should fire");
|
||||
});
|
||||
|
||||
// Prompt is not shown, permit unload.
|
||||
promptShown = false;
|
||||
ok(browser.permitUnload(browser.dontPromptAndUnload).permitUnload, "permit unload should be true");
|
||||
ok(!promptShown, "prompt should not have been displayed");
|
||||
|
||||
// Check that all beforeunload handlers fired.
|
||||
await ContentTask.spawn(browser, null, () => {
|
||||
ok(content.window.document.body.hasAttribute("fired"), "parent document beforeunload handler should fire");
|
||||
|
||||
for (let frame of Array.from(content.window.frames)) {
|
||||
ok(frame.document.body.hasAttribute("fired"), "frame document beforeunload handler should fire");
|
||||
}
|
||||
});
|
||||
|
||||
// Remove tab.
|
||||
buttonId = "button0";
|
||||
BrowserTestUtils.removeTab(tab);
|
||||
});
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body[fired] {
|
||||
background-color: #f00;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
window.onbeforeunload = function() {
|
||||
document.body.setAttribute("fired", true);
|
||||
return "Parent document prompt";
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
TEST PAGE
|
||||
<iframe style="width: 150px; height: 60px" src="file_bug1415918_beforeunload_iframe.html">
|
||||
</iframe>
|
||||
<iframe style="width: 150px; height: 60px" src="file_bug1415918_beforeunload_iframe.html">
|
||||
</iframe>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,21 @@
|
|||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body[fired] {
|
||||
background-color: #f00;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
window.onbeforeunload = function() {
|
||||
document.body.setAttribute("fired", true);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
TEST PAGE
|
||||
<iframe style="width: 150px; height: 60px" src="file_bug1415918_beforeunload_iframe_2.html">
|
||||
</iframe>
|
||||
<iframe style="width: 150px; height: 60px" src="file_bug1415918_beforeunload_iframe_2.html">
|
||||
</iframe>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,21 @@
|
|||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body[fired] {
|
||||
background-color: #f00;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
window.onbeforeunload = function() {
|
||||
document.body.setAttribute("fired", true);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
TEST PAGE
|
||||
<iframe style="width: 150px; height: 60px" src="file_bug1415918_beforeunload_iframe.html">
|
||||
</iframe>
|
||||
<iframe style="width: 150px; height: 60px" src="file_bug1415918_beforeunload_iframe.html">
|
||||
</iframe>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,18 @@
|
|||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body[fired] {
|
||||
background-color: #0f0;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
window.onbeforeunload = function() {
|
||||
document.body.setAttribute("fired", true);
|
||||
return "Frame document prompt";
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
</body>
|
||||
FRAME
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,17 @@
|
|||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body[fired] {
|
||||
background-color: #0f0;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
window.onbeforeunload = function() {
|
||||
document.body.setAttribute("fired", true);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
</body>
|
||||
FRAME
|
||||
</body>
|
||||
</html>
|
|
@ -36,6 +36,7 @@ class gfxVarReceiver;
|
|||
_(DXInterop2Blocked, bool, false) \
|
||||
_(UseWebRender, bool, false) \
|
||||
_(UseWebRenderANGLE, bool, false) \
|
||||
_(UseWebRenderProgramBinary, bool, false) \
|
||||
_(WebRenderDebugFlags, int32_t, 0) \
|
||||
_(ScreenDepth, int32_t, 0) \
|
||||
_(GREDirectory, nsCString, nsCString()) \
|
||||
|
|
|
@ -55,10 +55,6 @@ public:
|
|||
|
||||
FT_Library GetFTLibrary() override;
|
||||
|
||||
virtual bool CanRenderContentToDataSurface() const override {
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual already_AddRefed<mozilla::gfx::VsyncSource> CreateHardwareVsyncSource() override;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -2553,6 +2553,10 @@ gfxPlatform::InitWebRenderConfig()
|
|||
}
|
||||
#endif
|
||||
|
||||
if (Preferences::GetBool("gfx.webrender.program-binary", false)) {
|
||||
gfx::gfxVars::SetUseWebRenderProgramBinary(gfxConfig::IsEnabled(Feature::WEBRENDER));
|
||||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
featureWebRender.ForceDisable(
|
||||
FeatureStatus::Unavailable,
|
||||
|
|
|
@ -259,16 +259,6 @@ public:
|
|||
mozilla::gfx::SurfaceFormat aFormat,
|
||||
bool aUninitialized = false);
|
||||
|
||||
/**
|
||||
* Returns true if rendering to data surfaces produces the same results as
|
||||
* rendering to offscreen surfaces on this platform, making it safe to
|
||||
* render content to data surfaces. This is generally false on platforms
|
||||
* which use different backends for each type of DrawTarget.
|
||||
*/
|
||||
virtual bool CanRenderContentToDataSurface() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if we should use Azure to render content with aTarget. For
|
||||
* example, it is possible that we are using Direct2D for rendering and thus
|
||||
|
|
|
@ -57,10 +57,6 @@ public:
|
|||
gfxFontStyle &aFontStyle,
|
||||
float aDevPixPerCSSPixel);
|
||||
|
||||
virtual bool CanRenderContentToDataSurface() const override {
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool SupportsApzWheelInput() const override {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -118,7 +118,7 @@ RenderThread::AddRenderer(wr::WindowId aWindowId, UniquePtr<RendererOGL> aRender
|
|||
mRenderers[aWindowId] = Move(aRenderer);
|
||||
|
||||
MutexAutoLock lock(mFrameCountMapLock);
|
||||
mPendingFrameCounts.Put(AsUint64(aWindowId), FrameCount());
|
||||
mWindowInfos.Put(AsUint64(aWindowId), WindowInfo());
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -133,7 +133,7 @@ RenderThread::RemoveRenderer(wr::WindowId aWindowId)
|
|||
mRenderers.erase(aWindowId);
|
||||
|
||||
MutexAutoLock lock(mFrameCountMapLock);
|
||||
mPendingFrameCounts.Remove(AsUint64(aWindowId));
|
||||
mWindowInfos.Remove(AsUint64(aWindowId));
|
||||
}
|
||||
|
||||
RendererOGL*
|
||||
|
@ -167,6 +167,10 @@ RenderThread::NewFrameReady(wr::WindowId aWindowId)
|
|||
return;
|
||||
}
|
||||
|
||||
if (IsDestroyed(aWindowId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateAndRender(aWindowId);
|
||||
DecPendingFrameCount(aWindowId);
|
||||
}
|
||||
|
@ -274,17 +278,42 @@ RenderThread::TooManyPendingFrames(wr::WindowId aWindowId)
|
|||
// or if RenderBackend is still processing a frame.
|
||||
|
||||
MutexAutoLock lock(mFrameCountMapLock);
|
||||
FrameCount count;
|
||||
if (!mPendingFrameCounts.Get(AsUint64(aWindowId), &count)) {
|
||||
WindowInfo info;
|
||||
if (!mWindowInfos.Get(AsUint64(aWindowId), &info)) {
|
||||
MOZ_ASSERT(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (count.mPendingCount > maxFrameCount) {
|
||||
if (info.mPendingCount > maxFrameCount) {
|
||||
return true;
|
||||
}
|
||||
MOZ_ASSERT(count.mPendingCount >= count.mRenderingCount);
|
||||
return count.mPendingCount > count.mRenderingCount;
|
||||
MOZ_ASSERT(info.mPendingCount >= info.mRenderingCount);
|
||||
return info.mPendingCount > info.mRenderingCount;
|
||||
}
|
||||
|
||||
bool
|
||||
RenderThread::IsDestroyed(wr::WindowId aWindowId)
|
||||
{
|
||||
MutexAutoLock lock(mFrameCountMapLock);
|
||||
WindowInfo info;
|
||||
if (!mWindowInfos.Get(AsUint64(aWindowId), &info)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return info.mIsDestroyed;
|
||||
}
|
||||
|
||||
void
|
||||
RenderThread::SetDestroyed(wr::WindowId aWindowId)
|
||||
{
|
||||
MutexAutoLock lock(mFrameCountMapLock);
|
||||
WindowInfo info;
|
||||
if (!mWindowInfos.Get(AsUint64(aWindowId), &info)) {
|
||||
MOZ_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
info.mIsDestroyed = true;
|
||||
mWindowInfos.Put(AsUint64(aWindowId), info);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -292,14 +321,14 @@ RenderThread::IncPendingFrameCount(wr::WindowId aWindowId)
|
|||
{
|
||||
MutexAutoLock lock(mFrameCountMapLock);
|
||||
// Get the old count.
|
||||
FrameCount count;
|
||||
if (!mPendingFrameCounts.Get(AsUint64(aWindowId), &count)) {
|
||||
WindowInfo info;
|
||||
if (!mWindowInfos.Get(AsUint64(aWindowId), &info)) {
|
||||
MOZ_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
// Update pending frame count.
|
||||
count.mPendingCount = count.mPendingCount + 1;
|
||||
mPendingFrameCounts.Put(AsUint64(aWindowId), count);
|
||||
info.mPendingCount = info.mPendingCount + 1;
|
||||
mWindowInfos.Put(AsUint64(aWindowId), info);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -307,14 +336,14 @@ RenderThread::IncRenderingFrameCount(wr::WindowId aWindowId)
|
|||
{
|
||||
MutexAutoLock lock(mFrameCountMapLock);
|
||||
// Get the old count.
|
||||
FrameCount count;
|
||||
if (!mPendingFrameCounts.Get(AsUint64(aWindowId), &count)) {
|
||||
WindowInfo info;
|
||||
if (!mWindowInfos.Get(AsUint64(aWindowId), &info)) {
|
||||
MOZ_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
// Update rendering frame count.
|
||||
count.mRenderingCount = count.mRenderingCount + 1;
|
||||
mPendingFrameCounts.Put(AsUint64(aWindowId), count);
|
||||
info.mRenderingCount = info.mRenderingCount + 1;
|
||||
mWindowInfos.Put(AsUint64(aWindowId), info);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -322,20 +351,20 @@ RenderThread::DecPendingFrameCount(wr::WindowId aWindowId)
|
|||
{
|
||||
MutexAutoLock lock(mFrameCountMapLock);
|
||||
// Get the old count.
|
||||
FrameCount count;
|
||||
if (!mPendingFrameCounts.Get(AsUint64(aWindowId), &count)) {
|
||||
WindowInfo info;
|
||||
if (!mWindowInfos.Get(AsUint64(aWindowId), &info)) {
|
||||
MOZ_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(count.mPendingCount > 0);
|
||||
MOZ_ASSERT(count.mRenderingCount > 0);
|
||||
if (count.mPendingCount <= 0) {
|
||||
MOZ_ASSERT(info.mPendingCount > 0);
|
||||
MOZ_ASSERT(info.mRenderingCount > 0);
|
||||
if (info.mPendingCount <= 0) {
|
||||
return;
|
||||
}
|
||||
// Update frame counts.
|
||||
count.mPendingCount = count.mPendingCount - 1;
|
||||
count.mRenderingCount = count.mRenderingCount - 1;
|
||||
mPendingFrameCounts.Put(AsUint64(aWindowId), count);
|
||||
info.mPendingCount = info.mPendingCount - 1;
|
||||
info.mRenderingCount = info.mRenderingCount - 1;
|
||||
mWindowInfos.Put(AsUint64(aWindowId), info);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -393,6 +422,17 @@ RenderThread::GetRenderTexture(wr::WrExternalImageId aExternalImageId)
|
|||
return mRenderTextures.GetWeak(aExternalImageId.mHandle);
|
||||
}
|
||||
|
||||
WebRenderProgramCache*
|
||||
RenderThread::ProgramCache()
|
||||
{
|
||||
MOZ_ASSERT(IsInRenderThread());
|
||||
|
||||
if (!mProgramCache) {
|
||||
mProgramCache = MakeUnique<WebRenderProgramCache>();
|
||||
}
|
||||
return mProgramCache.get();
|
||||
}
|
||||
|
||||
WebRenderThreadPool::WebRenderThreadPool()
|
||||
{
|
||||
mThreadPool = wr_thread_pool_new();
|
||||
|
@ -403,6 +443,16 @@ WebRenderThreadPool::~WebRenderThreadPool()
|
|||
wr_thread_pool_delete(mThreadPool);
|
||||
}
|
||||
|
||||
WebRenderProgramCache::WebRenderProgramCache()
|
||||
{
|
||||
mProgramCache = wr_program_cache_new();
|
||||
}
|
||||
|
||||
WebRenderProgramCache::~WebRenderProgramCache()
|
||||
{
|
||||
wr_program_cache_delete(mProgramCache);
|
||||
}
|
||||
|
||||
} // namespace wr
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -40,6 +40,17 @@ protected:
|
|||
wr::WrThreadPool* mThreadPool;
|
||||
};
|
||||
|
||||
class WebRenderProgramCache {
|
||||
public:
|
||||
WebRenderProgramCache();
|
||||
|
||||
~WebRenderProgramCache();
|
||||
|
||||
wr::WrProgramCache* Raw() { return mProgramCache; }
|
||||
|
||||
protected:
|
||||
wr::WrProgramCache* mProgramCache;
|
||||
};
|
||||
|
||||
/// Base class for an event that can be scheduled to run on the render thread.
|
||||
///
|
||||
|
@ -127,6 +138,10 @@ public:
|
|||
/// Can only be called from the render thread.
|
||||
RenderTextureHost* GetRenderTexture(WrExternalImageId aExternalImageId);
|
||||
|
||||
/// Can be called from any thread.
|
||||
bool IsDestroyed(wr::WindowId aWindowId);
|
||||
/// Can be called from any thread.
|
||||
void SetDestroyed(wr::WindowId aWindowId);
|
||||
/// Can be called from any thread.
|
||||
bool TooManyPendingFrames(wr::WindowId aWindowId);
|
||||
/// Can be called from any thread.
|
||||
|
@ -139,6 +154,9 @@ public:
|
|||
/// Can be called from any thread.
|
||||
WebRenderThreadPool& ThreadPool() { return mThreadPool; }
|
||||
|
||||
/// Can only be called from the render thread.
|
||||
WebRenderProgramCache* ProgramCache();
|
||||
|
||||
private:
|
||||
explicit RenderThread(base::Thread* aThread);
|
||||
|
||||
|
@ -150,16 +168,18 @@ private:
|
|||
base::Thread* const mThread;
|
||||
|
||||
WebRenderThreadPool mThreadPool;
|
||||
UniquePtr<WebRenderProgramCache> mProgramCache;
|
||||
|
||||
std::map<wr::WindowId, UniquePtr<RendererOGL>> mRenderers;
|
||||
|
||||
struct FrameCount {
|
||||
struct WindowInfo {
|
||||
bool mIsDestroyed = false;
|
||||
int64_t mPendingCount = 0;
|
||||
int64_t mRenderingCount = 0;
|
||||
};
|
||||
|
||||
Mutex mFrameCountMapLock;
|
||||
nsDataHashtable<nsUint64HashKey, FrameCount> mPendingFrameCounts;
|
||||
nsDataHashtable<nsUint64HashKey, WindowInfo> mWindowInfos;
|
||||
|
||||
Mutex mRenderTextureMapLock;
|
||||
nsRefPtrHashtable<nsUint64HashKey, RenderTextureHost> mRenderTextures;
|
||||
|
|
|
@ -90,6 +90,9 @@ public:
|
|||
if (wrRenderer && renderer) {
|
||||
wr::WrExternalImageHandler handler = renderer->GetExternalImageHandler();
|
||||
wr_renderer_set_external_image_handler(wrRenderer, &handler);
|
||||
if (gfx::gfxVars::UseWebRenderProgramBinary()) {
|
||||
wr_renderer_update_program_cache(wrRenderer, aRenderThread.ProgramCache()->Raw());
|
||||
}
|
||||
}
|
||||
|
||||
if (renderer) {
|
||||
|
@ -204,6 +207,9 @@ WebRenderAPI::GetNamespace() {
|
|||
WebRenderAPI::~WebRenderAPI()
|
||||
{
|
||||
if (!mRootApi) {
|
||||
|
||||
RenderThread::Get()->SetDestroyed(GetId());
|
||||
|
||||
layers::SynchronousTask task("Destroy WebRenderAPI");
|
||||
auto event = MakeUnique<RemoveRenderer>(&task);
|
||||
RunOnRenderThread(Move(event));
|
||||
|
|
|
@ -2,6 +2,7 @@ use std::ffi::{CStr, CString};
|
|||
use std::{mem, slice};
|
||||
use std::path::PathBuf;
|
||||
use std::ptr;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use std::os::raw::{c_void, c_char, c_float};
|
||||
use gleam::gl;
|
||||
|
@ -11,6 +12,7 @@ use webrender::{ReadPixelsFormat, Renderer, RendererOptions, ThreadListener};
|
|||
use webrender::{ExternalImage, ExternalImageHandler, ExternalImageSource};
|
||||
use webrender::DebugFlags;
|
||||
use webrender::{ApiRecordingReceiver, BinaryRecorder};
|
||||
use webrender::ProgramCache;
|
||||
use thread_profiler::register_thread_with_profiler;
|
||||
use moz2d_renderer::Moz2dImageRenderer;
|
||||
use app_units::Au;
|
||||
|
@ -660,6 +662,26 @@ pub unsafe extern "C" fn wr_thread_pool_delete(thread_pool: *mut WrThreadPool) {
|
|||
Box::from_raw(thread_pool);
|
||||
}
|
||||
|
||||
pub struct WrProgramCache(Rc<ProgramCache>);
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wr_program_cache_new() -> *mut WrProgramCache {
|
||||
let program_cache = ProgramCache::new();
|
||||
Box::into_raw(Box::new(WrProgramCache(program_cache)))
|
||||
}
|
||||
|
||||
/// cbindgen:postfix=WR_DESTRUCTOR_SAFE_FUNC
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wr_program_cache_delete(program_cache: *mut WrProgramCache) {
|
||||
Rc::from_raw(program_cache);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_renderer_update_program_cache(renderer: &mut Renderer, program_cache: &mut WrProgramCache) {
|
||||
let program_cache = Rc::clone(&program_cache.0);
|
||||
renderer.update_program_cache(program_cache);
|
||||
}
|
||||
|
||||
// Call MakeCurrent before this.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_window_new(window_id: WrWindowId,
|
||||
|
|
|
@ -250,6 +250,8 @@ struct ResourceUpdates;
|
|||
|
||||
struct Vec_u8;
|
||||
|
||||
struct WrProgramCache;
|
||||
|
||||
struct WrRenderedEpochs;
|
||||
|
||||
struct WrState;
|
||||
|
@ -1409,6 +1411,14 @@ extern void wr_notifier_new_frame_ready(WrWindowId aWindowId);
|
|||
extern void wr_notifier_new_scroll_frame_ready(WrWindowId aWindowId,
|
||||
bool aCompositeNeeded);
|
||||
|
||||
WR_INLINE
|
||||
void wr_program_cache_delete(WrProgramCache *aProgramCache)
|
||||
WR_DESTRUCTOR_SAFE_FUNC;
|
||||
|
||||
WR_INLINE
|
||||
WrProgramCache *wr_program_cache_new()
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE
|
||||
void wr_rendered_epochs_delete(WrRenderedEpochs *aPipelineEpochs)
|
||||
WR_DESTRUCTOR_SAFE_FUNC;
|
||||
|
@ -1465,6 +1475,11 @@ WR_INLINE
|
|||
void wr_renderer_update(Renderer *aRenderer)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE
|
||||
void wr_renderer_update_program_cache(Renderer *aRenderer,
|
||||
WrProgramCache *aProgramCache)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE
|
||||
void wr_resource_updates_add_blob_image(ResourceUpdates *aResources,
|
||||
WrImageKey aImageKey,
|
||||
|
|
|
@ -324,9 +324,7 @@ imgFrame::InitWithDrawable(gfxDrawable* aDrawable,
|
|||
|
||||
RefPtr<DrawTarget> target;
|
||||
|
||||
bool canUseDataSurface =
|
||||
gfxPlatform::GetPlatform()->CanRenderContentToDataSurface();
|
||||
|
||||
bool canUseDataSurface = Factory::DoesBackendSupportDataDrawtarget(aBackend);
|
||||
if (canUseDataSurface) {
|
||||
// It's safe to use data surfaces for content on this platform, so we can
|
||||
// get away with using volatile buffers.
|
||||
|
|
|
@ -242,8 +242,11 @@ function GetModuleEnvironment(module)
|
|||
if (module.status === MODULE_STATUS_ERRORED)
|
||||
ThrowInternalError(JSMSG_MODULE_INSTANTIATE_FAILED, module.status);
|
||||
|
||||
assert(module.status >= MODULE_STATUS_INSTANTIATING,
|
||||
"Attempt to access module environement before instantation");
|
||||
|
||||
let env = UnsafeGetReservedSlot(module, MODULE_OBJECT_ENVIRONMENT_SLOT);
|
||||
assert(env === undefined || IsModuleEnvironment(env),
|
||||
assert(IsModuleEnvironment(env),
|
||||
"Module environment slot contains unexpected value");
|
||||
|
||||
return env;
|
||||
|
@ -443,7 +446,7 @@ function ModuleDeclarationEnvironmentSetup(module)
|
|||
}
|
||||
|
||||
// Steps 5-6
|
||||
CreateModuleEnvironment(module);
|
||||
// Note that we have already created the environment by this point.
|
||||
let env = GetModuleEnvironment(module);
|
||||
|
||||
// Step 8
|
||||
|
|
|
@ -383,7 +383,8 @@ ModuleNamespaceObject::isInstance(HandleValue value)
|
|||
}
|
||||
|
||||
/* static */ ModuleNamespaceObject*
|
||||
ModuleNamespaceObject::create(JSContext* cx, HandleModuleObject module)
|
||||
ModuleNamespaceObject::create(JSContext* cx, HandleModuleObject module, HandleObject exports,
|
||||
UniquePtr<IndirectBindingMap> bindings)
|
||||
{
|
||||
RootedValue priv(cx, ObjectValue(*module));
|
||||
ProxyOptions options;
|
||||
|
@ -393,6 +394,9 @@ ModuleNamespaceObject::create(JSContext* cx, HandleModuleObject module)
|
|||
if (!object)
|
||||
return nullptr;
|
||||
|
||||
SetProxyReservedSlot(object, ExportsSlot, ObjectValue(*exports));
|
||||
SetProxyReservedSlot(object, BindingsSlot, PrivateValue(bindings.release()));
|
||||
|
||||
return &object->as<ModuleNamespaceObject>();
|
||||
}
|
||||
|
||||
|
@ -405,15 +409,14 @@ ModuleNamespaceObject::module()
|
|||
JSObject&
|
||||
ModuleNamespaceObject::exports()
|
||||
{
|
||||
JSObject* exports = module().namespaceExports();
|
||||
MOZ_ASSERT(exports);
|
||||
return *exports;
|
||||
return GetProxyReservedSlot(this, ExportsSlot).toObject();
|
||||
}
|
||||
|
||||
IndirectBindingMap&
|
||||
ModuleNamespaceObject::bindings()
|
||||
{
|
||||
IndirectBindingMap* bindings = module().namespaceBindings();
|
||||
Value value = GetProxyReservedSlot(this, BindingsSlot);
|
||||
auto bindings = static_cast<IndirectBindingMap*>(value.toPrivate());
|
||||
MOZ_ASSERT(bindings);
|
||||
return *bindings;
|
||||
}
|
||||
|
@ -422,13 +425,10 @@ bool
|
|||
ModuleNamespaceObject::addBinding(JSContext* cx, HandleAtom exportedName,
|
||||
HandleModuleObject targetModule, HandleAtom localName)
|
||||
{
|
||||
IndirectBindingMap* bindings(this->module().namespaceBindings());
|
||||
MOZ_ASSERT(bindings);
|
||||
|
||||
RootedModuleEnvironmentObject environment(cx, &targetModule->initialEnvironment());
|
||||
RootedId exportedNameId(cx, AtomToId(exportedName));
|
||||
RootedId localNameId(cx, AtomToId(localName));
|
||||
return bindings->putNew(cx, exportedNameId, environment, localNameId);
|
||||
return bindings().putNew(cx, exportedNameId, environment, localNameId);
|
||||
}
|
||||
|
||||
const char ModuleNamespaceObject::ProxyHandler::family = 0;
|
||||
|
@ -676,6 +676,19 @@ ModuleNamespaceObject::ProxyHandler::ownPropertyKeys(JSContext* cx, HandleObject
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ModuleNamespaceObject::ProxyHandler::trace(JSTracer* trc, JSObject* proxy) const
|
||||
{
|
||||
auto& self = proxy->as<ModuleNamespaceObject>();
|
||||
self.bindings().trace(trc);
|
||||
}
|
||||
|
||||
void ModuleNamespaceObject::ProxyHandler::finalize(JSFreeOp* fop, JSObject* proxy) const
|
||||
{
|
||||
auto& self = proxy->as<ModuleNamespaceObject>();
|
||||
js_delete(&self.bindings());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// FunctionDeclaration
|
||||
|
||||
|
@ -772,22 +785,28 @@ ModuleObject::finalize(js::FreeOp* fop, JSObject* obj)
|
|||
ModuleObject* self = &obj->as<ModuleObject>();
|
||||
if (self->hasImportBindings())
|
||||
fop->delete_(&self->importBindings());
|
||||
if (IndirectBindingMap* bindings = self->namespaceBindings())
|
||||
fop->delete_(bindings);
|
||||
if (FunctionDeclarationVector* funDecls = self->functionDeclarations())
|
||||
fop->delete_(funDecls);
|
||||
}
|
||||
|
||||
ModuleEnvironmentObject&
|
||||
ModuleObject::initialEnvironment() const
|
||||
{
|
||||
Value value = getReservedSlot(EnvironmentSlot);
|
||||
return value.toObject().as<ModuleEnvironmentObject>();
|
||||
}
|
||||
|
||||
ModuleEnvironmentObject*
|
||||
ModuleObject::environment() const
|
||||
{
|
||||
MOZ_ASSERT(status() != MODULE_STATUS_ERRORED);
|
||||
|
||||
Value value = getReservedSlot(EnvironmentSlot);
|
||||
if (value.isUndefined())
|
||||
// According to the spec the environment record is created during
|
||||
// instantiation, but we create it earlier than that.
|
||||
if (status() < MODULE_STATUS_INSTANTIATED)
|
||||
return nullptr;
|
||||
|
||||
return &value.toObject().as<ModuleEnvironmentObject>();
|
||||
return &initialEnvironment();
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -803,26 +822,6 @@ ModuleObject::importBindings()
|
|||
return *static_cast<IndirectBindingMap*>(getReservedSlot(ImportBindingsSlot).toPrivate());
|
||||
}
|
||||
|
||||
JSObject*
|
||||
ModuleObject::namespaceExports()
|
||||
{
|
||||
Value value = getReservedSlot(NamespaceExportsSlot);
|
||||
if (value.isUndefined())
|
||||
return nullptr;
|
||||
|
||||
return &value.toObject();
|
||||
}
|
||||
|
||||
IndirectBindingMap*
|
||||
ModuleObject::namespaceBindings()
|
||||
{
|
||||
Value value = getReservedSlot(NamespaceBindingsSlot);
|
||||
if (value.isUndefined())
|
||||
return nullptr;
|
||||
|
||||
return static_cast<IndirectBindingMap*>(value.toPrivate());
|
||||
}
|
||||
|
||||
ModuleNamespaceObject*
|
||||
ModuleObject::namespace_()
|
||||
{
|
||||
|
@ -852,7 +851,7 @@ ModuleObject::init(HandleScript script)
|
|||
void
|
||||
ModuleObject::setInitialEnvironment(HandleModuleEnvironmentObject initialEnvironment)
|
||||
{
|
||||
initReservedSlot(InitialEnvironmentSlot, ObjectValue(*initialEnvironment));
|
||||
initReservedSlot(EnvironmentSlot, ObjectValue(*initialEnvironment));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -992,12 +991,6 @@ ModuleObject::setHostDefinedField(const JS::Value& value)
|
|||
setReservedSlot(HostDefinedSlot, value);
|
||||
}
|
||||
|
||||
ModuleEnvironmentObject&
|
||||
ModuleObject::initialEnvironment() const
|
||||
{
|
||||
return getReservedSlot(InitialEnvironmentSlot).toObject().as<ModuleEnvironmentObject>();
|
||||
}
|
||||
|
||||
Scope*
|
||||
ModuleObject::enclosingScope() const
|
||||
{
|
||||
|
@ -1016,23 +1009,11 @@ ModuleObject::trace(JSTracer* trc, JSObject* obj)
|
|||
|
||||
if (module.hasImportBindings())
|
||||
module.importBindings().trace(trc);
|
||||
if (IndirectBindingMap* bindings = module.namespaceBindings())
|
||||
bindings->trace(trc);
|
||||
|
||||
if (FunctionDeclarationVector* funDecls = module.functionDeclarations())
|
||||
funDecls->trace(trc);
|
||||
}
|
||||
|
||||
void
|
||||
ModuleObject::createEnvironment()
|
||||
{
|
||||
// The environment has already been created, we just neet to set it in the
|
||||
// right slot.
|
||||
MOZ_ASSERT(!getReservedSlot(InitialEnvironmentSlot).isUndefined());
|
||||
MOZ_ASSERT(getReservedSlot(EnvironmentSlot).isUndefined());
|
||||
setReservedSlot(EnvironmentSlot, getReservedSlot(InitialEnvironmentSlot));
|
||||
}
|
||||
|
||||
bool
|
||||
ModuleObject::noteFunctionDeclaration(JSContext* cx, HandleAtom name, HandleFunction fun)
|
||||
{
|
||||
|
@ -1049,6 +1030,7 @@ ModuleObject::noteFunctionDeclaration(JSContext* cx, HandleAtom name, HandleFunc
|
|||
ModuleObject::instantiateFunctionDeclarations(JSContext* cx, HandleModuleObject self)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
MOZ_ASSERT(self->status() == MODULE_STATUS_INSTANTIATING);
|
||||
if (!AssertFrozen(cx, self))
|
||||
return false;
|
||||
#endif
|
||||
|
@ -1094,6 +1076,7 @@ ModuleObject::instantiateFunctionDeclarations(JSContext* cx, HandleModuleObject
|
|||
ModuleObject::execute(JSContext* cx, HandleModuleObject self, MutableHandleValue rval)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
MOZ_ASSERT(self->status() == MODULE_STATUS_EVALUATING);
|
||||
if (!AssertFrozen(cx, self))
|
||||
return false;
|
||||
#endif
|
||||
|
@ -1114,21 +1097,18 @@ ModuleObject::createNamespace(JSContext* cx, HandleModuleObject self, HandleObje
|
|||
MOZ_ASSERT(!self->namespace_());
|
||||
MOZ_ASSERT(exports->is<ArrayObject>());
|
||||
|
||||
RootedModuleNamespaceObject ns(cx, ModuleNamespaceObject::create(cx, self));
|
||||
if (!ns)
|
||||
return nullptr;
|
||||
|
||||
Zone* zone = cx->zone();
|
||||
IndirectBindingMap* bindings = zone->new_<IndirectBindingMap>(zone);
|
||||
auto bindings = zone->make_unique<IndirectBindingMap>(zone);
|
||||
if (!bindings || !bindings->init()) {
|
||||
ReportOutOfMemory(cx);
|
||||
js_delete<IndirectBindingMap>(bindings);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto ns = ModuleNamespaceObject::create(cx, self, exports, Move(bindings));
|
||||
if (!ns)
|
||||
return nullptr;
|
||||
|
||||
self->initReservedSlot(NamespaceSlot, ObjectValue(*ns));
|
||||
self->initReservedSlot(NamespaceExportsSlot, ObjectValue(*exports));
|
||||
self->initReservedSlot(NamespaceBindingsSlot, PrivateValue(bindings));
|
||||
return ns;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "builtin/SelfHostingDefines.h"
|
||||
#include "js/GCVector.h"
|
||||
#include "js/Id.h"
|
||||
#include "js/UniquePtr.h"
|
||||
#include "vm/NativeObject.h"
|
||||
#include "vm/ProxyObject.h"
|
||||
|
||||
|
@ -167,8 +168,16 @@ class IndirectBindingMap
|
|||
class ModuleNamespaceObject : public ProxyObject
|
||||
{
|
||||
public:
|
||||
enum ModuleNamespaceSlot
|
||||
{
|
||||
ExportsSlot = 0,
|
||||
BindingsSlot
|
||||
};
|
||||
|
||||
static bool isInstance(HandleValue value);
|
||||
static ModuleNamespaceObject* create(JSContext* cx, HandleModuleObject module);
|
||||
static ModuleNamespaceObject* create(JSContext* cx, HandleModuleObject module,
|
||||
HandleObject exports,
|
||||
UniquePtr<IndirectBindingMap> bindings);
|
||||
|
||||
ModuleObject& module();
|
||||
JSObject& exports();
|
||||
|
@ -209,6 +218,9 @@ class ModuleNamespaceObject : public ProxyObject
|
|||
bool set(JSContext* cx, HandleObject proxy, HandleId id, HandleValue v,
|
||||
HandleValue receiver, ObjectOpResult& result) const override;
|
||||
|
||||
void trace(JSTracer* trc, JSObject* proxy) const override;
|
||||
void finalize(JSFreeOp* fop, JSObject* proxy) const override;
|
||||
|
||||
static const char family;
|
||||
};
|
||||
|
||||
|
@ -239,7 +251,6 @@ class ModuleObject : public NativeObject
|
|||
enum ModuleSlot
|
||||
{
|
||||
ScriptSlot = 0,
|
||||
InitialEnvironmentSlot,
|
||||
EnvironmentSlot,
|
||||
NamespaceSlot,
|
||||
StatusSlot,
|
||||
|
@ -251,8 +262,6 @@ class ModuleObject : public NativeObject
|
|||
IndirectExportEntriesSlot,
|
||||
StarExportEntriesSlot,
|
||||
ImportBindingsSlot,
|
||||
NamespaceExportsSlot,
|
||||
NamespaceBindingsSlot,
|
||||
FunctionDeclarationsSlot,
|
||||
DFSIndexSlot,
|
||||
DFSAncestorIndexSlot,
|
||||
|
@ -302,17 +311,12 @@ class ModuleObject : public NativeObject
|
|||
ArrayObject& indirectExportEntries() const;
|
||||
ArrayObject& starExportEntries() const;
|
||||
IndirectBindingMap& importBindings();
|
||||
JSObject* namespaceExports();
|
||||
IndirectBindingMap* namespaceBindings();
|
||||
|
||||
static bool Instantiate(JSContext* cx, HandleModuleObject self);
|
||||
static bool Evaluate(JSContext* cx, HandleModuleObject self);
|
||||
|
||||
void setHostDefinedField(const JS::Value& value);
|
||||
|
||||
// For intrinsic_CreateModuleEnvironment.
|
||||
void createEnvironment();
|
||||
|
||||
// For BytecodeEmitter.
|
||||
bool noteFunctionDeclaration(JSContext* cx, HandleAtom name, HandleFunction fun);
|
||||
|
||||
|
|
|
@ -46,30 +46,6 @@ Reflect_deleteProperty(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* ES6 26.1.6 Reflect.get(target, propertyKey [, receiver]) */
|
||||
static bool
|
||||
Reflect_get(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
// Step 1.
|
||||
RootedObject obj(cx, NonNullObjectArg(cx, "`target`", "Reflect.get", args.get(0)));
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
// Steps 2-3.
|
||||
RootedValue propertyKey(cx, args.get(1));
|
||||
RootedId key(cx);
|
||||
if (!ToPropertyKey(cx, propertyKey, &key))
|
||||
return false;
|
||||
|
||||
// Step 4.
|
||||
RootedValue receiver(cx, args.length() > 2 ? args[2] : args.get(0));
|
||||
|
||||
// Step 5.
|
||||
return GetProperty(cx, obj, receiver, key, args.rval());
|
||||
}
|
||||
|
||||
/* ES6 26.1.8 Reflect.getPrototypeOf(target) */
|
||||
bool
|
||||
js::Reflect_getPrototypeOf(JSContext* cx, unsigned argc, Value* vp)
|
||||
|
@ -210,7 +186,7 @@ static const JSFunctionSpec methods[] = {
|
|||
JS_SELF_HOSTED_FN("construct", "Reflect_construct", 2, 0),
|
||||
JS_SELF_HOSTED_FN("defineProperty", "Reflect_defineProperty", 3, 0),
|
||||
JS_FN("deleteProperty", Reflect_deleteProperty, 2, 0),
|
||||
JS_FN("get", Reflect_get, 2, 0),
|
||||
JS_SELF_HOSTED_FN("get", "Reflect_get", 2, 0),
|
||||
JS_SELF_HOSTED_FN("getOwnPropertyDescriptor", "Reflect_getOwnPropertyDescriptor", 2, 0),
|
||||
JS_INLINABLE_FN("getPrototypeOf", Reflect_getPrototypeOf, 1, 0, ReflectGetPrototypeOf),
|
||||
JS_SELF_HOSTED_FN("has", "Reflect_has", 2, 0),
|
||||
|
|
|
@ -127,10 +127,30 @@ function Reflect_getOwnPropertyDescriptor(target, propertyKey) {
|
|||
// 26.1.8 Reflect.has ( target, propertyKey )
|
||||
function Reflect_has(target, propertyKey) {
|
||||
// Step 1.
|
||||
if (!IsObject(target))
|
||||
if (!IsObject(target)) {
|
||||
ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT_ARG, "`target`", "Reflect.has",
|
||||
ToSource(target));
|
||||
}
|
||||
|
||||
// Steps 2-3 are identical to the runtime semantics of the "in" operator.
|
||||
return propertyKey in target;
|
||||
}
|
||||
|
||||
// ES2018 draft rev 0525bb33861c7f4e9850f8a222c89642947c4b9c
|
||||
// 26.1.5 Reflect.get ( target, propertyKey [ , receiver ] )
|
||||
function Reflect_get(target, propertyKey/*, receiver*/) {
|
||||
// Step 1.
|
||||
if (!IsObject(target)) {
|
||||
ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT_ARG, "`target`", "Reflect.get",
|
||||
ToSource(target));
|
||||
}
|
||||
|
||||
// Step 3 (reordered).
|
||||
if (arguments.length > 2) {
|
||||
// Steps 2, 4.
|
||||
return getPropertySuper(target, propertyKey, arguments[2]);
|
||||
}
|
||||
|
||||
// Steps 2, 4.
|
||||
return target[propertyKey];
|
||||
}
|
||||
|
|
|
@ -100,11 +100,11 @@
|
|||
#define REGEXP_STICKY_FLAG 0x08
|
||||
#define REGEXP_UNICODE_FLAG 0x10
|
||||
|
||||
#define MODULE_OBJECT_ENVIRONMENT_SLOT 2
|
||||
#define MODULE_OBJECT_STATUS_SLOT 4
|
||||
#define MODULE_OBJECT_ERROR_SLOT 5
|
||||
#define MODULE_OBJECT_DFS_INDEX_SLOT 16
|
||||
#define MODULE_OBJECT_DFS_ANCESTOR_INDEX_SLOT 17
|
||||
#define MODULE_OBJECT_ENVIRONMENT_SLOT 1
|
||||
#define MODULE_OBJECT_STATUS_SLOT 3
|
||||
#define MODULE_OBJECT_ERROR_SLOT 4
|
||||
#define MODULE_OBJECT_DFS_INDEX_SLOT 13
|
||||
#define MODULE_OBJECT_DFS_ANCESTOR_INDEX_SLOT 14
|
||||
|
||||
#define MODULE_STATUS_ERRORED 0
|
||||
#define MODULE_STATUS_UNINSTANTIATED 1
|
||||
|
|
|
@ -4304,8 +4304,6 @@ GetModuleEnvironment(JSContext* cx, HandleModuleObject module)
|
|||
// before they have been instantiated.
|
||||
RootedModuleEnvironmentObject env(cx, &module->initialEnvironment());
|
||||
MOZ_ASSERT(env);
|
||||
MOZ_ASSERT_IF(module->environment(), module->environment() == env);
|
||||
|
||||
return env;
|
||||
}
|
||||
|
||||
|
|
|
@ -9100,6 +9100,32 @@ BytecodeEmitter::emitSelfHostedHasOwn(ParseNode* pn)
|
|||
return emit1(JSOP_HASOWN);
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitSelfHostedGetPropertySuper(ParseNode* pn)
|
||||
{
|
||||
if (pn->pn_count != 4) {
|
||||
reportError(pn, JSMSG_MORE_ARGS_NEEDED, "getPropertySuper", "3", "");
|
||||
return false;
|
||||
}
|
||||
|
||||
ParseNode* funNode = pn->pn_head; // The getPropertySuper node.
|
||||
|
||||
ParseNode* objNode = funNode->pn_next;
|
||||
ParseNode* idNode = objNode->pn_next;
|
||||
ParseNode* receiverNode = idNode->pn_next;
|
||||
|
||||
if (!emitTree(idNode))
|
||||
return false;
|
||||
|
||||
if (!emitTree(receiverNode))
|
||||
return false;
|
||||
|
||||
if (!emitTree(objNode))
|
||||
return false;
|
||||
|
||||
return emitElemOpBase(JSOP_GETELEM_SUPER);
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::isRestParameter(ParseNode* pn)
|
||||
{
|
||||
|
@ -9291,6 +9317,8 @@ BytecodeEmitter::emitCallOrNew(ParseNode* pn, ValueUsage valueUsage /* = ValueUs
|
|||
return emitSelfHostedDefineDataProperty(pn);
|
||||
if (pn2->name() == cx->names().hasOwn)
|
||||
return emitSelfHostedHasOwn(pn);
|
||||
if (pn2->name() == cx->names().getPropertySuper)
|
||||
return emitSelfHostedGetPropertySuper(pn);
|
||||
// Fall through
|
||||
}
|
||||
|
||||
|
|
|
@ -791,6 +791,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
MOZ_MUST_USE bool emitSelfHostedForceInterpreter(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitSelfHostedAllowContentIter(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitSelfHostedDefineDataProperty(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitSelfHostedGetPropertySuper(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitSelfHostedHasOwn(ParseNode* pn);
|
||||
|
||||
MOZ_MUST_USE bool emitDo(ParseNode* pn);
|
||||
|
|
|
@ -163,6 +163,7 @@
|
|||
macro(getOwnPropertyNames, getOwnPropertyNames, "getOwnPropertyNames") \
|
||||
macro(getPrefix, getPrefix, "get ") \
|
||||
macro(getPropertyDescriptor, getPropertyDescriptor, "getPropertyDescriptor") \
|
||||
macro(getPropertySuper, getPropertySuper, "getPropertySuper") \
|
||||
macro(getPrototypeOf, getPrototypeOf, "getPrototypeOf") \
|
||||
macro(global, global, "global") \
|
||||
macro(group, group, "group") \
|
||||
|
|
|
@ -2002,17 +2002,6 @@ intrinsic_HostResolveImportedModule(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
intrinsic_CreateModuleEnvironment(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
MOZ_ASSERT(args.length() == 1);
|
||||
RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
|
||||
module->createEnvironment();
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
intrinsic_CreateImportBinding(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
|
@ -2532,7 +2521,6 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
|||
CallNonGenericSelfhostedMethod<Is<ModuleObject>>, 2, 0),
|
||||
JS_FN("HostResolveImportedModule", intrinsic_HostResolveImportedModule, 2, 0),
|
||||
JS_FN("IsModuleEnvironment", intrinsic_IsInstanceOfBuiltin<ModuleEnvironmentObject>, 1, 0),
|
||||
JS_FN("CreateModuleEnvironment", intrinsic_CreateModuleEnvironment, 1, 0),
|
||||
JS_FN("CreateImportBinding", intrinsic_CreateImportBinding, 4, 0),
|
||||
JS_FN("CreateNamespaceBinding", intrinsic_CreateNamespaceBinding, 3, 0),
|
||||
JS_FN("InstantiateModuleFunctionDeclarations",
|
||||
|
|
|
@ -1144,15 +1144,14 @@ nsDocumentViewer::GetIsStopped(bool* aOutIsStopped)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocumentViewer::PermitUnload(bool *aPermitUnload)
|
||||
nsDocumentViewer::PermitUnload(uint32_t aPermitUnloadFlags, bool *aPermitUnload)
|
||||
{
|
||||
bool shouldPrompt = true;
|
||||
return PermitUnloadInternal(&shouldPrompt, aPermitUnload);
|
||||
return PermitUnloadInternal(&aPermitUnloadFlags, aPermitUnload);
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsDocumentViewer::PermitUnloadInternal(bool *aShouldPrompt,
|
||||
nsDocumentViewer::PermitUnloadInternal(uint32_t *aPermitUnloadFlags,
|
||||
bool *aPermitUnload)
|
||||
{
|
||||
AutoDontWarnAboutSyncXHR disableSyncXHRWarning;
|
||||
|
@ -1238,12 +1237,23 @@ nsDocumentViewer::PermitUnloadInternal(bool *aShouldPrompt,
|
|||
nsAutoString text;
|
||||
event->GetReturnValue(text);
|
||||
|
||||
if (sIsBeforeUnloadDisabled) {
|
||||
*aPermitUnloadFlags = eDontPromptAndUnload;
|
||||
}
|
||||
|
||||
// NB: we nullcheck mDocument because it might now be dead as a result of
|
||||
// the event being dispatched.
|
||||
if (!sIsBeforeUnloadDisabled && *aShouldPrompt && dialogsAreEnabled &&
|
||||
if (*aPermitUnloadFlags != eDontPromptAndUnload && dialogsAreEnabled &&
|
||||
mDocument && !(mDocument->GetSandboxFlags() & SANDBOXED_MODALS) &&
|
||||
(!sBeforeUnloadRequiresInteraction || mDocument->UserHasInteracted()) &&
|
||||
(event->WidgetEventPtr()->DefaultPrevented() || !text.IsEmpty())) {
|
||||
// If the consumer wants prompt requests to just stop unloading, we don't
|
||||
// need to prompt and can return immediately.
|
||||
if (*aPermitUnloadFlags == eDontPromptAndDontUnload) {
|
||||
*aPermitUnload = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Ask the user if it's ok to unload the current page
|
||||
|
||||
nsCOMPtr<nsIPrompt> prompt = do_GetInterface(docShell);
|
||||
|
@ -1322,7 +1332,7 @@ nsDocumentViewer::PermitUnloadInternal(bool *aShouldPrompt,
|
|||
// If the user decided to go ahead, make sure not to prompt the user again
|
||||
// by toggling the internal prompting bool to false:
|
||||
if (*aPermitUnload) {
|
||||
*aShouldPrompt = false;
|
||||
*aPermitUnloadFlags = eDontPromptAndUnload;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1342,7 +1352,7 @@ nsDocumentViewer::PermitUnloadInternal(bool *aShouldPrompt,
|
|||
docShell->GetContentViewer(getter_AddRefs(cv));
|
||||
|
||||
if (cv) {
|
||||
cv->PermitUnloadInternal(aShouldPrompt, aPermitUnload);
|
||||
cv->PermitUnloadInternal(aPermitUnloadFlags, aPermitUnload);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -215,6 +215,15 @@ public:
|
|||
MOZ_ASSERT(IsPathType());
|
||||
}
|
||||
|
||||
BulletRenderer(const LayoutDeviceRect& aPathRect, nscolor color, int32_t listStyleType)
|
||||
: mPathRect(aPathRect)
|
||||
, mColor(color)
|
||||
, mListStyleType(listStyleType)
|
||||
{
|
||||
MOZ_ASSERT(IsPathType());
|
||||
}
|
||||
|
||||
|
||||
BulletRenderer(const nsString& text,
|
||||
nsFontMetrics* fm,
|
||||
nscolor color,
|
||||
|
@ -251,12 +260,11 @@ public:
|
|||
bool
|
||||
IsPathType() const
|
||||
{
|
||||
return (mListStyleType == NS_STYLE_LIST_STYLE_DISC ||
|
||||
mListStyleType == NS_STYLE_LIST_STYLE_CIRCLE ||
|
||||
mListStyleType == NS_STYLE_LIST_STYLE_SQUARE ||
|
||||
mListStyleType == NS_STYLE_LIST_STYLE_DISCLOSURE_OPEN ||
|
||||
mListStyleType == NS_STYLE_LIST_STYLE_DISCLOSURE_CLOSED) &&
|
||||
mPath;
|
||||
return mListStyleType == NS_STYLE_LIST_STYLE_DISC ||
|
||||
mListStyleType == NS_STYLE_LIST_STYLE_CIRCLE ||
|
||||
mListStyleType == NS_STYLE_LIST_STYLE_SQUARE ||
|
||||
mListStyleType == NS_STYLE_LIST_STYLE_DISCLOSURE_OPEN ||
|
||||
mListStyleType == NS_STYLE_LIST_STYLE_DISCLOSURE_CLOSED;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -313,6 +321,15 @@ private:
|
|||
RefPtr<imgIContainer> mImage;
|
||||
nsRect mDest;
|
||||
|
||||
// Some bullet types are stored as a rect (in device pixels) instead of a Path to allow
|
||||
// generating proper WebRender commands. When webrender is disabled the Path is lazily created
|
||||
// for these items before painting.
|
||||
// TODO: The size of this structure doesn't seem to be an issue since it has so many fields
|
||||
// that are specific to a bullet style or another, but if it becomes one we can easily
|
||||
// store mDest and mPathRect into the same memory location since they are never used by
|
||||
// the same bullet types.
|
||||
LayoutDeviceRect mPathRect;
|
||||
|
||||
// mColor indicate the color of list-style. Both text and path type would use this memeber.
|
||||
nscolor mColor;
|
||||
|
||||
|
@ -369,16 +386,31 @@ BulletRenderer::Paint(gfxContext& aRenderingContext, nsPoint aPt,
|
|||
|
||||
if (IsPathType()) {
|
||||
DrawTarget* drawTarget = aRenderingContext.GetDrawTarget();
|
||||
|
||||
if (!mPath) {
|
||||
RefPtr<PathBuilder> builder = drawTarget->CreatePathBuilder();
|
||||
switch (mListStyleType) {
|
||||
case NS_STYLE_LIST_STYLE_CIRCLE:
|
||||
case NS_STYLE_LIST_STYLE_DISC:
|
||||
AppendEllipseToPath(builder, mPathRect.Center().ToUnknownPoint(), mPathRect.Size().ToUnknownSize());
|
||||
break;
|
||||
case NS_STYLE_LIST_STYLE_SQUARE:
|
||||
AppendRectToPath(builder, mPathRect.ToUnknownRect());
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT(false, "Should have a parth.");
|
||||
}
|
||||
mPath = builder->Finish();
|
||||
}
|
||||
|
||||
switch (mListStyleType) {
|
||||
case NS_STYLE_LIST_STYLE_CIRCLE:
|
||||
MOZ_ASSERT(mPath);
|
||||
drawTarget->Stroke(mPath, ColorPattern(ToDeviceColor(mColor)));
|
||||
break;
|
||||
case NS_STYLE_LIST_STYLE_DISC:
|
||||
case NS_STYLE_LIST_STYLE_SQUARE:
|
||||
case NS_STYLE_LIST_STYLE_DISCLOSURE_CLOSED:
|
||||
case NS_STYLE_LIST_STYLE_DISCLOSURE_OPEN:
|
||||
MOZ_ASSERT(mPath);
|
||||
drawTarget->Fill(mPath, ColorPattern(ToDeviceColor(mColor)));
|
||||
break;
|
||||
default:
|
||||
|
@ -511,10 +543,42 @@ BulletRenderer::CreateWebRenderCommandsForPath(nsDisplayItem* aItem,
|
|||
nsDisplayListBuilder* aDisplayListBuilder)
|
||||
{
|
||||
MOZ_ASSERT(IsPathType());
|
||||
|
||||
if (!aManager->CommandBuilder().PushItemAsImage(aItem, aBuilder, aResources, aSc, aDisplayListBuilder)) {
|
||||
NS_WARNING("Fail to create WebRender commands for Bullet path.");
|
||||
return false;
|
||||
wr::LayoutRect dest = aSc.ToRelativeLayoutRect(mPathRect);
|
||||
auto color = wr::ToColorF(ToDeviceColor(mColor));
|
||||
bool isBackfaceVisible = !aItem->BackfaceIsHidden();
|
||||
switch (mListStyleType) {
|
||||
case NS_STYLE_LIST_STYLE_CIRCLE: {
|
||||
LayoutDeviceSize radii = mPathRect.Size() / 2.0;
|
||||
auto borderWidths = wr::ToBorderWidths(1.0, 1.0, 1.0, 1.0);
|
||||
wr::BorderSide side = { color, wr::BorderStyle::Solid };
|
||||
wr::BorderSide sides[4] = { side, side, side, side };
|
||||
Range<const wr::BorderSide> sidesRange(sides, 4);
|
||||
aBuilder.PushBorder(dest, dest, isBackfaceVisible, borderWidths,
|
||||
sidesRange,
|
||||
wr::ToBorderRadius(radii, radii, radii, radii));
|
||||
return true;
|
||||
}
|
||||
case NS_STYLE_LIST_STYLE_DISC: {
|
||||
nsTArray<wr::ComplexClipRegion> clips;
|
||||
clips.AppendElement(wr::ToComplexClipRegion(
|
||||
RoundedRect(ThebesRect(mPathRect.ToUnknownRect()),
|
||||
RectCornerRadii(dest.size.width / 2.0))
|
||||
));
|
||||
auto clipId = aBuilder.DefineClip(Nothing(), Nothing(), dest, &clips, nullptr);
|
||||
aBuilder.PushClip(clipId);
|
||||
aBuilder.PushRect(dest, dest, isBackfaceVisible, color);
|
||||
aBuilder.PopClip();
|
||||
return true;
|
||||
}
|
||||
case NS_STYLE_LIST_STYLE_SQUARE: {
|
||||
aBuilder.PushRect(dest, dest, isBackfaceVisible, color);
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
if (!aManager->CommandBuilder().PushItemAsImage(aItem, aBuilder, aResources, aSc, aDisplayListBuilder)) {
|
||||
NS_WARNING("Fail to create WebRender commands for Bullet path.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -766,13 +830,8 @@ nsBulletFrame::CreateBulletRenderer(gfxContext& aRenderingContext, nsPoint aPt)
|
|||
padding.top + aPt.y,
|
||||
mRect.width - (padding.left + padding.right),
|
||||
mRect.height - (padding.top + padding.bottom));
|
||||
Rect devPxRect = NSRectToRect(rect, appUnitsPerDevPixel);
|
||||
RefPtr<PathBuilder> builder = drawTarget->CreatePathBuilder();
|
||||
AppendEllipseToPath(builder, devPxRect.Center(), devPxRect.Size());
|
||||
|
||||
RefPtr<Path> path = builder->Finish();
|
||||
BulletRenderer br(path, color, listStyleType->GetStyle());
|
||||
return Some(br);
|
||||
auto devPxRect = LayoutDeviceRect::FromAppUnits(rect, appUnitsPerDevPixel);
|
||||
return Some(BulletRenderer(devPxRect, color, listStyleType->GetStyle()));
|
||||
}
|
||||
|
||||
case NS_STYLE_LIST_STYLE_SQUARE:
|
||||
|
@ -792,14 +851,8 @@ nsBulletFrame::CreateBulletRenderer(gfxContext& aRenderingContext, nsPoint aPt)
|
|||
pc->RoundAppUnitsToNearestDevPixels(rect.height));
|
||||
snapRect.MoveBy((rect.width - snapRect.width) / 2,
|
||||
(rect.height - snapRect.height) / 2);
|
||||
Rect devPxRect =
|
||||
NSRectToSnappedRect(snapRect, appUnitsPerDevPixel, *drawTarget);
|
||||
RefPtr<PathBuilder> builder = drawTarget->CreatePathBuilder();
|
||||
AppendRectToPath(builder, devPxRect);
|
||||
|
||||
RefPtr<Path> path = builder->Finish();
|
||||
BulletRenderer br(path, color, listStyleType->GetStyle());
|
||||
return Some(br);
|
||||
auto devPxRect = LayoutDeviceRect::FromAppUnits(snapRect, appUnitsPerDevPixel);
|
||||
return Some(BulletRenderer(devPxRect, color, listStyleType->GetStyle()));
|
||||
}
|
||||
|
||||
case NS_STYLE_LIST_STYLE_DISCLOSURE_CLOSED:
|
||||
|
|
|
@ -438,6 +438,10 @@
|
|||
* MOZ_CAN_RUN_SCRIPT: Applies to functions which can run script. Callers of
|
||||
* this function must also be marked as MOZ_CAN_RUN_SCRIPT, and all refcounted
|
||||
* arguments must be strongly held in the caller.
|
||||
* MOZ_CAN_RUN_SCRIPT_BOUNDARY: Applies to functions which need to call
|
||||
* MOZ_CAN_RUN_SCRIPT functions, but should not themselves be considered
|
||||
* MOZ_CAN_RUN_SCRIPT. This is important for some bindings and low level code
|
||||
* which need to opt out of the safety checks performed by MOZ_CAN_RUN_SCRIPT.
|
||||
* MOZ_MUST_OVERRIDE: Applies to all C++ member functions. All immediate
|
||||
* subclasses must provide an exact override of this method; if a subclass
|
||||
* does not override this method, the compiler will emit an error. This
|
||||
|
@ -597,6 +601,7 @@
|
|||
*/
|
||||
#ifdef MOZ_CLANG_PLUGIN
|
||||
# define MOZ_CAN_RUN_SCRIPT __attribute__((annotate("moz_can_run_script")))
|
||||
# define MOZ_CAN_RUN_SCRIPT_BOUNDARY __attribute__((annotate("moz_can_run_script_boundary")))
|
||||
# define MOZ_MUST_OVERRIDE __attribute__((annotate("moz_must_override")))
|
||||
# define MOZ_STACK_CLASS __attribute__((annotate("moz_stack_class")))
|
||||
# define MOZ_NONHEAP_CLASS __attribute__((annotate("moz_nonheap_class")))
|
||||
|
@ -652,6 +657,7 @@
|
|||
_Pragma("clang diagnostic pop")
|
||||
#else
|
||||
# define MOZ_CAN_RUN_SCRIPT /* nothing */
|
||||
# define MOZ_CAN_RUN_SCRIPT_BOUNDARY /* nothing */
|
||||
# define MOZ_MUST_OVERRIDE /* nothing */
|
||||
# define MOZ_STACK_CLASS /* nothing */
|
||||
# define MOZ_NONHEAP_CLASS /* nothing */
|
||||
|
|
|
@ -860,6 +860,7 @@ pref("gfx.webrender.enabled", false);
|
|||
#endif
|
||||
#ifdef XP_WIN
|
||||
pref("gfx.webrender.force-angle", true);
|
||||
pref("gfx.webrender.program-binary", true);
|
||||
#endif
|
||||
|
||||
pref("gfx.webrender.highlight-painted-layers", false);
|
||||
|
|
|
@ -1159,4 +1159,4 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
|
|||
|
||||
static const int32_t kUnknownId = -1;
|
||||
|
||||
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1519932871378000);
|
||||
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1520019278178000);
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -8,7 +8,7 @@
|
|||
/*****************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
const PRTime gPreloadListExpirationTime = INT64_C(1522352058278000);
|
||||
const PRTime gPreloadListExpirationTime = INT64_C(1522438465145000);
|
||||
%%
|
||||
0-1.party, 1
|
||||
0.me.uk, 1
|
||||
|
@ -88,6 +88,7 @@ const PRTime gPreloadListExpirationTime = INT64_C(1522352058278000);
|
|||
1001.best, 1
|
||||
1001kerstpakketten.com, 0
|
||||
100and1.jp, 1
|
||||
100kredite.de, 1
|
||||
100mani.it, 1
|
||||
100onrainkajino.com, 1
|
||||
100rembourse.be, 1
|
||||
|
@ -366,7 +367,6 @@ const PRTime gPreloadListExpirationTime = INT64_C(1522352058278000);
|
|||
50lakeshore.com, 1
|
||||
50north.de, 1
|
||||
50plusnet.nl, 1
|
||||
513vpn.net, 1
|
||||
525.info, 1
|
||||
52neptune.com, 1
|
||||
5432.cc, 1
|
||||
|
@ -1123,6 +1123,7 @@ akr.io, 1
|
|||
akritikos.info, 1
|
||||
akropolis-ravensburg.de, 1
|
||||
akselinurmio.fi, 1
|
||||
akstudentsfirst.org, 1
|
||||
aktiv-naturheilmittel.at, 1
|
||||
aktiv-naturheilmittel.ch, 1
|
||||
aktiv-naturheilmittel.de, 1
|
||||
|
@ -1479,6 +1480,7 @@ amiciidogrescue.org.uk, 1
|
|||
amicsdelbus.com, 1
|
||||
amihub.com, 1
|
||||
amilum.org, 1
|
||||
amin.one, 1
|
||||
aminafrance.com, 1
|
||||
amineptine.com, 1
|
||||
amisharingstuff.com, 1
|
||||
|
@ -1508,6 +1510,7 @@ anacruz.es, 1
|
|||
anadoluefessk.org, 1
|
||||
anaethelion.fr, 1
|
||||
anaiscoachpersonal.es, 1
|
||||
anaisypirueta.es, 1
|
||||
anajianu.ro, 1
|
||||
anakros.me, 0
|
||||
analangelsteen.com, 1
|
||||
|
@ -2220,7 +2223,6 @@ astaninki.com, 1
|
|||
astarbouncycastles.co.uk, 1
|
||||
astarmathsandphysics.com, 1
|
||||
astec-informatica.com, 1
|
||||
astengox.com, 1
|
||||
astenotarili.online, 1
|
||||
astenretail.com, 1
|
||||
asthon.cn, 1
|
||||
|
@ -2514,7 +2516,6 @@ awsmdev.de, 1
|
|||
ax25.org, 1
|
||||
axel-fischer.net, 1
|
||||
axel-fischer.science, 1
|
||||
axelchv.fr, 1
|
||||
axelteichmann.net, 1
|
||||
axem.co.jp, 1
|
||||
axialsports.com, 1
|
||||
|
@ -2671,6 +2672,7 @@ balade-commune.ch, 1
|
|||
baladecommune.ch, 1
|
||||
balancascia.com.br, 1
|
||||
balancenaturalhealthclinic.ca, 1
|
||||
balatoni-nyar.hu, 1
|
||||
balboa.io, 1
|
||||
balcaonet.com.br, 1
|
||||
baldur.cc, 1
|
||||
|
@ -3256,6 +3258,7 @@ bgtgames.com, 1
|
|||
bharath-g.in, 1
|
||||
bhodisoft.com, 1
|
||||
bhost.net, 1
|
||||
bhtelecom.ba, 1
|
||||
bhuntr.com, 1
|
||||
bi.search.yahoo.com, 0
|
||||
bia.gov, 0
|
||||
|
@ -4299,7 +4302,6 @@ bs-network.net, 1
|
|||
bs-security.com, 1
|
||||
bs.sb, 1
|
||||
bs.to, 1
|
||||
bs12v.ru, 1
|
||||
bsagan.fr, 1
|
||||
bsalyzer.com, 1
|
||||
bsc-rietz.at, 1
|
||||
|
@ -5765,7 +5767,6 @@ clr3.com, 1
|
|||
clsimage.com, 1
|
||||
clsimplex.com, 1
|
||||
clu-in.org, 1
|
||||
club-adulti.ro, 1
|
||||
club-is.ru, 1
|
||||
club-reduc.com, 1
|
||||
club103.ch, 1
|
||||
|
@ -6307,6 +6308,7 @@ corrupted.io, 1
|
|||
corsa-b.uk, 1
|
||||
cortexitrecruitment.com, 1
|
||||
cortis-consulting.ch, 1
|
||||
cortisolsupplement.com, 1
|
||||
corvus.eu.org, 1
|
||||
coryadum.com, 1
|
||||
corytyburski.com, 1
|
||||
|
@ -6555,7 +6557,7 @@ crustytoothpaste.net, 1
|
|||
crute.me, 1
|
||||
cruzeiropedia.org, 1
|
||||
crvv.me, 1
|
||||
cry.nu, 1
|
||||
cry.nu, 0
|
||||
cryoit.com, 1
|
||||
cryothanasia.com, 1
|
||||
cryp.no, 1
|
||||
|
@ -7245,6 +7247,7 @@ debitpaie.com, 1
|
|||
deborahmarinelli.eu, 1
|
||||
debron-ot.nl, 1
|
||||
debrusoft.ch, 1
|
||||
debt.com, 1
|
||||
debtrecycling.com.au, 1
|
||||
debuemon.com, 1
|
||||
debuis.nl, 1
|
||||
|
@ -7649,7 +7652,6 @@ dicionarioetimologico.com.br, 1
|
|||
dick.red, 1
|
||||
dickieslife.com, 1
|
||||
dickpics.ru, 1
|
||||
dicoding.com, 1
|
||||
didacte.com, 1
|
||||
didche.net, 1
|
||||
diddens.de, 1
|
||||
|
@ -8318,7 +8320,7 @@ drschruefer.de, 1
|
|||
drsturgeonfreitas.com, 1
|
||||
drtti.io, 1
|
||||
drturner.com.au, 1
|
||||
drubn.de, 1
|
||||
drubn.de, 0
|
||||
drugagodba.si, 1
|
||||
drumbe.at, 1
|
||||
drummondframing.com, 1
|
||||
|
@ -9099,6 +9101,7 @@ energyled.com.br, 1
|
|||
enersec.co.uk, 1
|
||||
enet-navigator.de, 1
|
||||
enfantsdelarue.ch, 1
|
||||
enfield-kitchens.co.uk, 1
|
||||
enflow.nl, 1
|
||||
enfoqueseguro.com, 1
|
||||
enfu.se, 1
|
||||
|
@ -9380,7 +9383,7 @@ espanol.search.yahoo.com, 0
|
|||
espanova.com, 1
|
||||
espci.fr, 1
|
||||
especificosba.com.ar, 1
|
||||
espenandersen.no, 1
|
||||
espenandersen.no, 0
|
||||
espgg.org, 1
|
||||
esphigmenou.gr, 1
|
||||
espigol.org, 1
|
||||
|
@ -9807,7 +9810,6 @@ faehler.de, 1
|
|||
faeriecakes.be, 1
|
||||
fafatiger.com, 1
|
||||
fag.wtf, 1
|
||||
fahmed.de, 1
|
||||
fahrenwal.de, 1
|
||||
fahrenwalde.de, 1
|
||||
fail.coach, 1
|
||||
|
@ -10252,6 +10254,7 @@ firstchoicepool.com, 1
|
|||
firstclasscastles.com, 1
|
||||
firstclassleisure.co.uk, 1
|
||||
firstderm.com, 1
|
||||
firstfinca.de, 1
|
||||
firstmall.de, 1
|
||||
firstq.xyz, 1
|
||||
fischer-its.com, 0
|
||||
|
@ -10441,6 +10444,7 @@ flyingrub.me, 1
|
|||
flymns.fr, 1
|
||||
flynn.io, 1
|
||||
flyp.me, 1
|
||||
flyserver.co.il, 1
|
||||
flyspace.ga, 1
|
||||
flyspace.ml, 1
|
||||
flyss.net, 1
|
||||
|
@ -10765,6 +10769,7 @@ freesnowden.is, 1
|
|||
freesolitaire.win, 1
|
||||
freesounding.com, 1
|
||||
freesounding.ru, 1
|
||||
freesourcestl.org, 1
|
||||
freethetv.ie, 1
|
||||
freetsa.org, 1
|
||||
freevps.us, 1
|
||||
|
@ -11297,7 +11302,7 @@ gemeentemolenwaard.nl, 1
|
|||
gemeinfreie-lieder.de, 1
|
||||
gemini.com, 1
|
||||
gemquery.com, 1
|
||||
gemuplay.com, 1
|
||||
gemuplay.com, 0
|
||||
gencmedya.com, 1
|
||||
gendrin.com, 1
|
||||
gendundrupa.ch, 1
|
||||
|
@ -12106,7 +12111,6 @@ gumi.ca, 1
|
|||
gummibande.noip.me, 1
|
||||
gunhunter.com, 1
|
||||
gunwatch.co.uk, 1
|
||||
guochang.xyz, 1
|
||||
guoke.com, 1
|
||||
guphi.net, 0
|
||||
gurkan.in, 1
|
||||
|
@ -12583,7 +12587,6 @@ helenelefauconnier.com, 1
|
|||
helenkellersimulator.org, 1
|
||||
helichat.de, 1
|
||||
helikon.ro, 1
|
||||
helioanodyne.eu, 1
|
||||
heliosnet.com, 1
|
||||
heliosvoting.org, 1
|
||||
helix.am, 1
|
||||
|
@ -12878,7 +12881,6 @@ hlfh.space, 1
|
|||
hloe0xff.ru, 1
|
||||
hlucas.de, 1
|
||||
hm1ch.com, 1
|
||||
hm773.net, 1
|
||||
hmhotelec.com, 0
|
||||
hmksq.ae, 1
|
||||
hmoegirl.com, 1
|
||||
|
@ -13015,6 +13017,7 @@ hopglass.net, 1
|
|||
hoplongtech.com, 1
|
||||
hopps.me, 1
|
||||
hoppyx.com, 1
|
||||
horace.li, 1
|
||||
horaceli.com, 1
|
||||
horackova.info, 1
|
||||
hord.ca, 1
|
||||
|
@ -13482,7 +13485,6 @@ ieeespmb.org, 1
|
|||
ieji.de, 0
|
||||
iemas.azurewebsites.net, 1
|
||||
iemb.cf, 1
|
||||
iemb.tk, 1
|
||||
ienakanote.com, 0
|
||||
ieval.ro, 1
|
||||
iewar.com, 1
|
||||
|
@ -13663,7 +13665,6 @@ imlinan.net, 1
|
|||
imlonghao.com, 1
|
||||
immanuel60.hu, 1
|
||||
immaterium.de, 1
|
||||
immersion-pictures.com, 1
|
||||
immersionwealth.com, 1
|
||||
immersivewebportal.com, 1
|
||||
immigrationdirect.com.au, 1
|
||||
|
@ -14565,7 +14566,6 @@ jardin-exotique-rennes.fr, 1
|
|||
jardinderline.ch, 1
|
||||
jardiniersduminotaure.fr, 1
|
||||
jardins-utopie.net, 1
|
||||
jaredbates.net, 0
|
||||
jaredeberle.org, 0
|
||||
jaredfernandez.com, 1
|
||||
jaredfraser.com, 1
|
||||
|
@ -14817,7 +14817,6 @@ jm-bea.net, 1
|
|||
jmalarcon.es, 1
|
||||
jmarciniak.it, 1
|
||||
jmb.lc, 1
|
||||
jmbelloteau.com, 1
|
||||
jmcashngold.com.au, 1
|
||||
jmcleaning.services, 1
|
||||
jmedved.com, 1
|
||||
|
@ -17061,6 +17060,7 @@ liul.in, 1
|
|||
liushuyu.tk, 1
|
||||
liv3ly.com, 1
|
||||
livebetterwith.com, 1
|
||||
livecards.co.uk, 1
|
||||
livedesign.at, 1
|
||||
livedesign24.de, 1
|
||||
liveflightapp.com, 1
|
||||
|
@ -17416,12 +17416,14 @@ luisyr.com, 1
|
|||
luizkowalski.net, 1
|
||||
luk.earth, 1
|
||||
luk.photo, 1
|
||||
lukas-oppermann.de, 1
|
||||
lukas-schauer.de, 1
|
||||
lukas.im, 1
|
||||
lukas2511.de, 1
|
||||
lukasberan.com, 1
|
||||
lukasberan.cz, 1
|
||||
lukasfunk.com, 1
|
||||
lukasoppermann.com, 1
|
||||
lukasoppermann.de, 1
|
||||
lukasschauer.de, 1
|
||||
lukasschick.de, 1
|
||||
|
@ -18584,6 +18586,7 @@ mhjuma.com, 1
|
|||
mhmfoundationrepair.com, 1
|
||||
mi-beratung.de, 1
|
||||
mi-so-ji.com, 1
|
||||
mi80.com, 1
|
||||
miagexport.com, 1
|
||||
miamicityballet.org, 1
|
||||
miaoubox.com, 1
|
||||
|
@ -19027,7 +19030,6 @@ moefactory.com, 1
|
|||
moefi.xyz, 1
|
||||
moehrke.cc, 1
|
||||
moellers.systems, 1
|
||||
moeloli.pw, 1
|
||||
moetrack.com, 1
|
||||
moevenpick-cafe.com, 1
|
||||
moeyi.xyz, 0
|
||||
|
@ -19234,7 +19236,6 @@ moveek.com, 1
|
|||
moveisfit.com.br, 1
|
||||
moveltix.net, 1
|
||||
movember.com, 0
|
||||
movepin.com, 1
|
||||
movie-cross.net, 1
|
||||
movie4k.fyi, 1
|
||||
movie4k.life, 1
|
||||
|
@ -19858,12 +19859,10 @@ naroska.name, 1
|
|||
narrativasdigitais.pt, 1
|
||||
narrenverein-wolkenschieber.de, 1
|
||||
narthollis.net, 1
|
||||
narviz.com, 1
|
||||
nasarawanewsonline.com, 1
|
||||
nasbi.pl, 1
|
||||
nasbnation.com, 1
|
||||
nascher.org, 0
|
||||
nasmocopati.com, 1
|
||||
nasrsolar.com, 1
|
||||
nassi.me, 1
|
||||
nastoletni.pl, 1
|
||||
|
@ -20553,7 +20552,6 @@ nordakademie.de, 1
|
|||
nordic-survival.de, 1
|
||||
nordiccasinocommunity.com, 1
|
||||
nordinfo.fi, 1
|
||||
nordmoregatebilklubb.com, 1
|
||||
nordnetz-hamburg.de, 1
|
||||
nordor.homeip.net, 1
|
||||
nordseeblicke.de, 1
|
||||
|
@ -20642,7 +20640,6 @@ novaopcaofestas.com.br, 1
|
|||
novascan.net, 1
|
||||
novawave.ca, 1
|
||||
novecity.com, 1
|
||||
novelabs.eu, 1
|
||||
novelfeed.com, 1
|
||||
novelinglife.net, 1
|
||||
novelvyretraite.fr, 1
|
||||
|
@ -20650,7 +20647,6 @@ novfishing.ru, 1
|
|||
novilaw.com, 1
|
||||
novinhabucetuda.com, 1
|
||||
novoresume.com, 1
|
||||
novtest.ru, 1
|
||||
nowcost.com, 1
|
||||
nowhere.dk, 1
|
||||
nowlas.org, 1
|
||||
|
@ -21051,6 +21047,7 @@ oneononeonone.de, 1
|
|||
oneononeonone.tv, 1
|
||||
onestepfootcare.com, 1
|
||||
onestopcastles.co.uk, 1
|
||||
onetech.it, 1
|
||||
onetime.info, 1
|
||||
oneway.ga, 1
|
||||
onewaymail.com, 1
|
||||
|
@ -21150,7 +21147,7 @@ openacademies.com, 1
|
|||
openacte.ch, 1
|
||||
openblox.org, 1
|
||||
openbsd.id, 1
|
||||
opencad.io, 1
|
||||
opencad.io, 0
|
||||
opencluster.at, 1
|
||||
openconcept.no, 1
|
||||
openconnect.com.au, 1
|
||||
|
@ -21297,6 +21294,7 @@ osao.org, 1
|
|||
osbi.pl, 1
|
||||
osborneinn.com, 1
|
||||
osburn.com, 1
|
||||
oscamp.eu, 1
|
||||
oscarvk.ch, 1
|
||||
oscsdp.cz, 0
|
||||
osereso.tn, 1
|
||||
|
@ -23683,11 +23681,10 @@ recruitsecuritytraining.co.uk, 1
|
|||
recruitsecuritytraining.com, 1
|
||||
rectoraudiparts.com, 1
|
||||
recuerdafilms.com, 1
|
||||
recurly.com, 1
|
||||
recurly.com, 0
|
||||
recyclingpromotions.us, 1
|
||||
red-t-shirt.ru, 1
|
||||
redable.hosting, 1
|
||||
redable.nl, 1
|
||||
redb.cz, 1
|
||||
redballoonsecurity.com, 1
|
||||
redburn.com, 1
|
||||
|
@ -24180,7 +24177,6 @@ robert-flynn.de, 1
|
|||
robertabittle.com, 1
|
||||
robertattfield.com, 1
|
||||
robertg.me, 1
|
||||
roberthurlbut.com, 1
|
||||
robertkrueger.de, 1
|
||||
robertlysik.com, 1
|
||||
roberto-webhosting.nl, 1
|
||||
|
@ -24624,6 +24620,7 @@ sadbox.es, 1
|
|||
sadbox.org, 1
|
||||
sadhawkict.org, 1
|
||||
sadmansh.com, 1
|
||||
sadsu.com, 1
|
||||
saengsook.com, 1
|
||||
saengsuk.com, 1
|
||||
safar.sk, 1
|
||||
|
@ -26594,7 +26591,6 @@ sourcebox.be, 1
|
|||
sourcecode.love, 1
|
||||
sourcely.net, 1
|
||||
sourceway.de, 1
|
||||
sourcitec.com, 1
|
||||
souris.ch, 1
|
||||
sous-surveillance.net, 1
|
||||
southafrican.dating, 1
|
||||
|
@ -26706,7 +26702,6 @@ spinspin.wtf, 1
|
|||
spiralschneiderkaufen.de, 1
|
||||
spirella-shop.ch, 1
|
||||
spiritbionic.ro, 1
|
||||
spiritfanfics.com, 1
|
||||
spiritual.dating, 1
|
||||
spiritualife.net, 1
|
||||
spiritualregression.com.au, 1
|
||||
|
@ -26738,7 +26733,6 @@ spornkuller.de, 1
|
|||
sport-in-sundern.de, 1
|
||||
sport-potreby.cz, 1
|
||||
sport-potreby.sk, 1
|
||||
sport-socken.net, 1
|
||||
sporter.com, 1
|
||||
sportflash.info, 1
|
||||
sportnesia.com, 1
|
||||
|
@ -26795,6 +26789,7 @@ squaddraft.com, 1
|
|||
square-gaming.org, 1
|
||||
square-src.de, 0
|
||||
square.com, 0
|
||||
squarelab.it, 1
|
||||
squareonebgc.com.ph, 1
|
||||
squareup.com, 0
|
||||
squawk.cc, 1
|
||||
|
@ -27146,6 +27141,7 @@ stonemanbrasil.com.br, 1
|
|||
stony.com, 1
|
||||
stonystratford.org, 1
|
||||
stopakwardhandshakes.org, 1
|
||||
stopbreakupnow.org, 1
|
||||
stopbullying.gov, 1
|
||||
stopfraud.gov, 1
|
||||
stopthethyroidmadness.com, 1
|
||||
|
@ -27227,7 +27223,6 @@ stuco.co, 1
|
|||
studenckiemetody.pl, 1
|
||||
student-eshop.cz, 1
|
||||
student-eshop.sk, 1
|
||||
student.andover.edu, 1
|
||||
studentforums.biz, 1
|
||||
studentite.bg, 0
|
||||
studentloans.gov, 1
|
||||
|
@ -28310,7 +28305,6 @@ themostexpensiveworkofart.com, 1
|
|||
themusecollaborative.org, 1
|
||||
themusicinnoise.net, 1
|
||||
themusthaves.nl, 1
|
||||
thenanfang.com, 1
|
||||
thenexwork.com, 1
|
||||
thenib.com, 1
|
||||
thenichecast.com, 1
|
||||
|
@ -28690,11 +28684,10 @@ tkn.tokyo, 1
|
|||
tkts.cl, 1
|
||||
tkusano.jp, 1
|
||||
tkw01536.de, 1
|
||||
tlach.cz, 1
|
||||
tlca.org, 1
|
||||
tlcnet.info, 1
|
||||
tlehseasyads.com, 1
|
||||
tlo.xyz, 1
|
||||
tloxygen.com, 1
|
||||
tls.builders, 1
|
||||
tls.care, 1
|
||||
tls1914.org, 1
|
||||
|
@ -29190,6 +29183,7 @@ treker.us, 1
|
|||
trekfriend.com, 1
|
||||
tremlor.com, 1
|
||||
tremolosoftware.com, 1
|
||||
tremoureux.fr, 1
|
||||
trendingpulse.com, 1
|
||||
trendisland.de, 1
|
||||
trendkraft.de, 1
|
||||
|
@ -29356,7 +29350,7 @@ tudiennhakhoa.com, 1
|
|||
tudorproject.org, 1
|
||||
tueche.com.ar, 1
|
||||
tufilo.com, 1
|
||||
tuincentersnaet.be, 0
|
||||
tuincentersnaet.be, 1
|
||||
tuingereedschappen.net, 0
|
||||
tuitle.com, 1
|
||||
tuja.hu, 1
|
||||
|
@ -29549,6 +29543,7 @@ ucch.be, 1
|
|||
ucfirst.nl, 1
|
||||
uchargeapp.com, 1
|
||||
uclanmasterplan.co.uk, 1
|
||||
ucppe.org, 1
|
||||
ucrdatatool.gov, 1
|
||||
uctarna.online, 1
|
||||
udbhav.me, 1
|
||||
|
@ -30398,12 +30393,13 @@ vleij.se, 1
|
|||
vloeck.de, 1
|
||||
vlogge.com, 1
|
||||
vlovgr.se, 1
|
||||
vlsk.eu, 1
|
||||
vlsm.se, 1
|
||||
vm-0.com, 1
|
||||
vm-co.ch, 1
|
||||
vmc.co.id, 1
|
||||
vmem.jp, 0
|
||||
vmhydro.ru, 1
|
||||
vmgirls.com, 1
|
||||
vmis.nl, 1
|
||||
vmoagents.com, 0
|
||||
vmug.pl, 1
|
||||
|
@ -31628,7 +31624,6 @@ www.theguardian.com, 1
|
|||
www.therapynotes.com, 1
|
||||
www.tinfoilsecurity.com, 0
|
||||
www.torproject.org, 0
|
||||
www.tumblr.com, 0
|
||||
www.twitter.com, 0
|
||||
www.united.com, 1
|
||||
www.usaa.com, 0
|
||||
|
@ -32329,6 +32324,7 @@ zappbuildapps.com, 1
|
|||
zaratan.fr, 1
|
||||
zarmarket.org, 1
|
||||
zarpo.com.br, 1
|
||||
zary.me, 1
|
||||
zaufanatrzeciastrona.pl, 1
|
||||
zavec.com.ec, 1
|
||||
zavetaji.lv, 1
|
||||
|
@ -32353,8 +32349,6 @@ zdorovayasimya.com, 1
|
|||
zdravesteny.cz, 1
|
||||
zdrojak.cz, 1
|
||||
zdx.ch, 1
|
||||
ze3kr.com, 1
|
||||
zebbra.ro, 1
|
||||
zebedeescastles.co.uk, 1
|
||||
zeds-official.com, 1
|
||||
zeebrieshoekvanholland.nl, 1
|
||||
|
@ -32368,6 +32362,7 @@ zeitpunkt-kulturmagazin.de, 1
|
|||
zeitzer-turngala.de, 1
|
||||
zekinteractive.com, 1
|
||||
zelezny.uk, 0
|
||||
zelfrijdendeautos.com, 1
|
||||
zellari.ru, 1
|
||||
zeloz.xyz, 1
|
||||
zemlova.cz, 1
|
||||
|
|
|
@ -123,6 +123,6 @@ function run_test() {
|
|||
checkTestModuleNotPresent();
|
||||
|
||||
// Check miscellaneous module DB methods and attributes.
|
||||
ok(gModuleDB.canToggleFIPS, "It should be possible to toggle FIPS");
|
||||
ok(!gModuleDB.canToggleFIPS, "It should NOT be possible to toggle FIPS");
|
||||
ok(!gModuleDB.isFIPSEnabled, "FIPS should not be enabled");
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
NSS_3_34_BETA5
|
||||
ceb8b9290b35
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
Functions changes summary: 0 Removed, 0 Changed, 4 Added functions
|
||||
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
|
||||
|
||||
4 Added functions:
|
||||
|
||||
'function SECItem* SEC_CreateSignatureAlgorithmParameters(SECItem*, SECOidTag, SECOidTag, const SECItem*, const SECKEYPrivateKey*)' {SEC_CreateSignatureAlgorithmParameters@@NSS_3.34}
|
||||
'function SECStatus SEC_DerSignDataWithAlgorithmID(SECItem*, const unsigned char*, int, SECKEYPrivateKey*, SECAlgorithmID*)' {SEC_DerSignDataWithAlgorithmID@@NSS_3.34}
|
||||
'function SECStatus SEC_SignDataWithAlgorithmID(SECItem*, const unsigned char*, int, SECKEYPrivateKey*, SECAlgorithmID*)' {SEC_SignDataWithAlgorithmID@@NSS_3.34}
|
||||
'function void SGN_NewContextWithAlgorithmID(SECAlgorithmID*, SECKEYPrivateKey*)' {SGN_NewContextWithAlgorithmID@@NSS_3.34}
|
||||
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
Functions changes summary: 0 Removed, 1 Changed, 0 Added function
|
||||
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
|
||||
|
||||
1 function with some indirect sub-type change:
|
||||
|
||||
[C]'function SECStatus SSL_GetChannelInfo(SSLChannelInfo*, PRUintn)' at sslinfo.c:26:1 has some indirect sub-type changes:
|
||||
parameter 1 of type 'SSLChannelInfo*' has sub-type changes:
|
||||
in pointed to type 'typedef SSLChannelInfo' at sslt.h:288:1:
|
||||
underlying type 'struct SSLChannelInfoStr' at sslt.h:229:1 changed:
|
||||
type size changed from 896 to 960 bits
|
||||
2 data member insertions:
|
||||
'SSLNamedGroup SSLChannelInfoStr::originalKeaGroup', at offset 864 (in bits) at sslt.h:281:1
|
||||
'PRBool SSLChannelInfoStr::resumed', at offset 896 (in bits) at sslt.h:284:1
|
||||
|
||||
|
|
@ -1 +1 @@
|
|||
NSS_3_33_BRANCH
|
||||
NSS_3_34_BRANCH
|
||||
|
|
|
@ -4,18 +4,16 @@ MAINTAINER Franziskus Kiefer <franziskuskiefer@gmail.com>
|
|||
# Based on the HACL* image from Benjamin Beurdouche and
|
||||
# the original F* formula with Daniel Fabian
|
||||
|
||||
# Pinned versions of HaCl* (F* and KreMLin are pinned as submodules)
|
||||
# Pinned versions of HACL* (F* and KreMLin are pinned as submodules)
|
||||
ENV haclrepo https://github.com/mitls/hacl-star.git
|
||||
|
||||
# Define versions of dependencies
|
||||
ENV opamv 4.04.2
|
||||
ENV z3v 4.5.1.1f29cebd4df6-x64-ubuntu-14.04
|
||||
ENV haclversion 0030539598cde15d1a0e5f93b32e121f7b7b5a1c
|
||||
ENV haclbranch production-nss
|
||||
ENV haclversion daa7e159f0adf252b5e6962967bc0f27dbac243b
|
||||
|
||||
# Install required packages and set versions
|
||||
RUN apt-get -qq update
|
||||
RUN apt-get install --yes sudo libssl-dev libsqlite3-dev g++-5 gcc-5 m4 make opam pkg-config python libgmp3-dev cmake curl libtool-bin autoconf
|
||||
RUN apt-get install --yes sudo libssl-dev libsqlite3-dev g++-5 gcc-5 m4 make opam pkg-config python libgmp3-dev cmake curl libtool-bin autoconf wget
|
||||
RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 200
|
||||
RUN update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-5 200
|
||||
|
||||
|
@ -29,13 +27,6 @@ ADD bin /home/worker/bin
|
|||
RUN chmod +x /home/worker/bin/*
|
||||
USER worker
|
||||
|
||||
# Add "known-good" version of Z3
|
||||
RUN curl -LO https://github.com/FStarLang/binaries/raw/master/z3-tested/z3-${z3v}.zip
|
||||
RUN unzip z3-${z3v}.zip
|
||||
RUN rm z3-${z3v}.zip
|
||||
RUN mv z3-${z3v} z3
|
||||
ENV PATH "/home/worker/z3/bin:$PATH"
|
||||
|
||||
# Prepare build (OCaml packages)
|
||||
ENV OPAMYES true
|
||||
RUN opam init
|
||||
|
@ -43,14 +34,19 @@ RUN echo ". /home/worker/.opam/opam-init/init.sh > /dev/null 2> /dev/null || tru
|
|||
RUN opam switch -v ${opamv}
|
||||
RUN opam install ocamlfind batteries sqlite3 fileutils yojson ppx_deriving_yojson zarith pprint menhir ulex process fix wasm stdint
|
||||
|
||||
# Get the HaCl* code
|
||||
# Get the HACL* code
|
||||
RUN git clone ${haclrepo} hacl-star
|
||||
RUN git -C hacl-star checkout ${haclversion}
|
||||
|
||||
# Prepare submodules, and build, verify, test, and extract c code
|
||||
# This caches the extracted c code (pins the HaCl* version). All we need to do
|
||||
# This caches the extracted c code (pins the HACL* version). All we need to do
|
||||
# on CI now is comparing the code in this docker image with the one in NSS.
|
||||
RUN opam config exec -- make -C hacl-star nss -j$(nproc)
|
||||
RUN opam config exec -- make -C hacl-star prepare -j$(nproc)
|
||||
ENV PATH "/home/worker/hacl-star/dependencies/z3/bin:$PATH"
|
||||
RUN make -C hacl-star verify-nss -j$(nproc)
|
||||
RUN make -C hacl-star -f Makefile.build snapshots/nss -j$(nproc)
|
||||
RUN KOPTS="-funroll-loops 5" make -C hacl-star/code/curve25519 test -j$(nproc)
|
||||
RUN make -C hacl-star/code/salsa-family test -j$(nproc)
|
||||
|
||||
# Get clang-format-3.9
|
||||
RUN curl -LO http://releases.llvm.org/3.9.1/clang+llvm-3.9.1-x86_64-linux-gnu-ubuntu-16.04.tar.xz
|
||||
|
@ -65,6 +61,7 @@ RUN rm *.tar.xz*
|
|||
|
||||
# Cleanup
|
||||
RUN rm -rf ~/.ccache ~/.cache
|
||||
RUN rm -rf /home/worker/hacl-star/dependencies
|
||||
RUN sudo apt-get autoremove -y
|
||||
RUN sudo apt-get clean
|
||||
RUN sudo apt-get autoclean
|
||||
|
|
|
@ -13,7 +13,7 @@ set -e -x -v
|
|||
# successfully executed.
|
||||
|
||||
# Format the extracted C code.
|
||||
cd ~/hacl-star/snapshots/nss-production
|
||||
cd ~/hacl-star/snapshots/nss
|
||||
cp ~/nss/.clang-format .
|
||||
find . -type f -name '*.[ch]' -exec clang-format -i {} \+
|
||||
|
||||
|
@ -22,3 +22,10 @@ files=($(find ~/nss/lib/freebl/verified/ -type f -name '*.[ch]'))
|
|||
for f in "${files[@]}"; do
|
||||
diff $f $(basename "$f")
|
||||
done
|
||||
|
||||
# Check that the specs didn't change either.
|
||||
cd ~/hacl-star/specs
|
||||
files=($(find ~/nss/lib/freebl/verified/specs -type f))
|
||||
for f in "${files[@]}"; do
|
||||
diff $f $(basename "$f")
|
||||
done
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
[
|
||||
{
|
||||
"version": "Visual Studio 2015 Update 3 14.0.25425.01 / SDK 10.0.14393.0",
|
||||
"size": 326656969,
|
||||
"digest": "babc414ffc0457d27f5a1ed24a8e4873afbe2f1c1a4075469a27c005e1babc3b2a788f643f825efedff95b79686664c67ec4340ed535487168a3482e68559bc7",
|
||||
"version": "Visual Studio 2017 15.4.2 / SDK 10.0.15063.0",
|
||||
"size": 303146863,
|
||||
"digest": "18700889e6b5e81613b9cf57ce4e0d46a6ee45bb4c5c33bae2604a5275326128775b8a032a1eb178c5db973746d565340c4e36d98375789e1d5bd836ab16ba58",
|
||||
"algorithm": "sha512",
|
||||
"filename": "vs2015u3.zip",
|
||||
"filename": "vs2017_15.4.2.zip",
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
|
||||
set -v -e -x
|
||||
|
||||
export VSPATH="$(pwd)/vs2015u3"
|
||||
export VSPATH="$(pwd)/vs2017_15.4.2"
|
||||
export NINJA_PATH="$(pwd)/ninja/bin"
|
||||
|
||||
export WINDOWSSDKDIR="${VSPATH}/SDK"
|
||||
export VS90COMNTOOLS="${VSPATH}/VC"
|
||||
export INCLUDE="${VSPATH}/VC/include:${VSPATH}/SDK/Include/10.0.14393.0/ucrt:${VSPATH}/SDK/Include/10.0.14393.0/shared:${VSPATH}/SDK/Include/10.0.14393.0/um"
|
||||
export INCLUDE="${VSPATH}/VC/include:${VSPATH}/SDK/Include/10.0.15063.0/ucrt:${VSPATH}/SDK/Include/10.0.15063.0/shared:${VSPATH}/SDK/Include/10.0.15063.0/um"
|
||||
|
||||
# Usage: hg_clone repo dir [revision=@]
|
||||
hg_clone() {
|
||||
|
|
|
@ -4,7 +4,7 @@ set -v -e -x
|
|||
|
||||
source $(dirname $0)/setup.sh
|
||||
|
||||
export WIN32_REDIST_DIR="${VSPATH}/VC/redist/x86/Microsoft.VC140.CRT"
|
||||
export WIN32_REDIST_DIR="${VSPATH}/VC/redist/x86/Microsoft.VC141.CRT"
|
||||
export WIN_UCRT_REDIST_DIR="${VSPATH}/SDK/Redist/ucrt/DLLs/x86"
|
||||
export PATH="${NINJA_PATH}:${VSPATH}/VC/bin/amd64_x86:${VSPATH}/VC/bin/amd64:${VSPATH}/VC/bin:${VSPATH}/SDK/bin/x86:${VSPATH}/SDK/bin/x64:${VSPATH}/VC/redist/x86/Microsoft.VC140.CRT:${VSPATH}/VC/redist/x64/Microsoft.VC140.CRT:${VSPATH}/SDK/Redist/ucrt/DLLs/x86:${VSPATH}/SDK/Redist/ucrt/DLLs/x64:${PATH}"
|
||||
export LIB="${VSPATH}/VC/lib:${VSPATH}/SDK/lib/10.0.14393.0/ucrt/x86:${VSPATH}/SDK/lib/10.0.14393.0/um/x86"
|
||||
export PATH="${NINJA_PATH}:${VSPATH}/VC/bin/Hostx64/x86:${VSPATH}/VC/bin/Hostx64/x64:${VSPATH}/VC/Hostx86/x86:${VSPATH}/SDK/bin/10.0.15063.0/x64:${VSPATH}/VC/redist/x86/Microsoft.VC141.CRT:${VSPATH}/SDK/Redist/ucrt/DLLs/x86:${PATH}"
|
||||
export LIB="${VSPATH}/VC/lib/x86:${VSPATH}/SDK/lib/10.0.15063.0/ucrt/x86:${VSPATH}/SDK/lib/10.0.15063.0/um/x86"
|
||||
|
|
|
@ -4,7 +4,7 @@ set -v -e -x
|
|||
|
||||
source $(dirname $0)/setup.sh
|
||||
|
||||
export WIN32_REDIST_DIR="${VSPATH}/VC/redist/x64/Microsoft.VC140.CRT"
|
||||
export WIN32_REDIST_DIR="${VSPATH}/VC/redist/x64/Microsoft.VC141.CRT"
|
||||
export WIN_UCRT_REDIST_DIR="${VSPATH}/SDK/Redist/ucrt/DLLs/x64"
|
||||
export PATH="${NINJA_PATH}:${VSPATH}/VC/bin/amd64:${VSPATH}/VC/bin:${VSPATH}/SDK/bin/x64:${VSPATH}/VC/redist/x64/Microsoft.VC140.CRT:${VSPATH}/SDK/Redist/ucrt/DLLs/x64:${PATH}"
|
||||
export LIB="${VSPATH}/VC/lib/amd64:${VSPATH}/SDK/lib/10.0.14393.0/ucrt/x64:${VSPATH}/SDK/lib/10.0.14393.0/um/x64"
|
||||
export PATH="${NINJA_PATH}:${VSPATH}/VC/bin/Hostx64/x64:${VSPATH}/VC/bin/Hostx86/x86:${VSPATH}/SDK/bin/10.0.15063.0/x64:${VSPATH}/VC/redist/x64/Microsoft.VC141.CRT:${VSPATH}/SDK/Redist/ucrt/DLLs/x64:${PATH}"
|
||||
export LIB="${VSPATH}/VC/lib/x64:${VSPATH}/SDK/lib/10.0.15063.0/ucrt/x64:${VSPATH}/SDK/lib/10.0.15063.0/um/x64"
|
||||
|
|
|
@ -68,6 +68,7 @@ fi
|
|||
while [ $# -gt 0 ]; do
|
||||
case $1 in
|
||||
-c) clean=1 ;;
|
||||
-cc) clean_only=1 ;;
|
||||
--gyp|-g) rebuild_gyp=1 ;;
|
||||
--nspr) nspr_clean; rebuild_nspr=1 ;;
|
||||
-j) ninja_params+=(-j "$2"); shift ;;
|
||||
|
@ -124,10 +125,15 @@ dist_dir=$(mkdir -p "$dist_dir"; cd "$dist_dir"; pwd -P)
|
|||
gyp_params+=(-Dnss_dist_dir="$dist_dir")
|
||||
|
||||
# -c = clean first
|
||||
if [ "$clean" = 1 ]; then
|
||||
if [ "$clean" = 1 -o "$clean_only" = 1 ]; then
|
||||
nspr_clean
|
||||
rm -rf "$cwd"/out
|
||||
rm -rf "$dist_dir"
|
||||
# -cc = only clean, don't build
|
||||
if [ "$clean_only" = 1 ]; then
|
||||
echo "Cleaned"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# This saves a canonical representation of arguments that we are passing to gyp
|
||||
|
|
|
@ -233,8 +233,7 @@ make_datastruct(char *data, int len)
|
|||
if (remaining == 1) {
|
||||
remaining += fields;
|
||||
fields = fields * 2;
|
||||
datastruct = (Pair *)PORT_Realloc(datastruct, fields *
|
||||
sizeof(Pair));
|
||||
datastruct = (Pair *)PORT_Realloc(datastruct, fields * sizeof(Pair));
|
||||
if (datastruct == NULL) {
|
||||
error_allocate();
|
||||
}
|
||||
|
|
|
@ -576,8 +576,7 @@ CERTUTIL_GeneratePrivateKey(KeyType keytype, PK11SlotInfo *slot, int size,
|
|||
fprintf(stderr, "Generating key. This may take a few moments...\n\n");
|
||||
|
||||
privKey = PK11_GenerateKeyPairWithOpFlags(slot, mechanism, params, pubkeyp,
|
||||
attrFlags, opFlagsOn, opFlagsOn |
|
||||
opFlagsOff,
|
||||
attrFlags, opFlagsOn, opFlagsOn | opFlagsOff,
|
||||
pwdata /*wincx*/);
|
||||
/* free up the params */
|
||||
switch (keytype) {
|
||||
|
|
|
@ -616,8 +616,7 @@ crlgen_CreateInvalidityDate(PLArenaPool *arena, const char **dataArr,
|
|||
goto loser;
|
||||
}
|
||||
|
||||
PORT_Memcpy(encodedItem->data, dataArr[2], (encodedItem->len = length) *
|
||||
sizeof(char));
|
||||
PORT_Memcpy(encodedItem->data, dataArr[2], (encodedItem->len = length) * sizeof(char));
|
||||
|
||||
*extCode = SEC_OID_X509_INVALID_DATE;
|
||||
return encodedItem;
|
||||
|
|
|
@ -5922,8 +5922,7 @@ tls(char *reqfn)
|
|||
goto loser;
|
||||
}
|
||||
crv = NSC_DeriveKey(session, &master_mech, pms_handle,
|
||||
derive_template, derive_template_count -
|
||||
1,
|
||||
derive_template, derive_template_count - 1,
|
||||
&master_handle);
|
||||
if (crv != CKR_OK) {
|
||||
fprintf(stderr, "NSC_DeriveKey(master) failed crv=0x%x\n",
|
||||
|
|
|
@ -7,9 +7,6 @@
|
|||
TESTDIR=${1-.}
|
||||
COMMAND=${2-run}
|
||||
TESTS="aes aesgcm dsa ecdsa hmac tls rng rsa sha tdea"
|
||||
if [ ${NSS_ENABLE_ECC}x = 1x ]; then
|
||||
TESTS=${TESTS} ecdsa
|
||||
fi
|
||||
for i in $TESTS
|
||||
do
|
||||
echo "********************Running $i tests"
|
||||
|
|
|
@ -240,7 +240,8 @@ SECU_GetModulePassword(PK11SlotInfo *slot, PRBool retry, void *arg)
|
|||
sprintf(prompt,
|
||||
"Press Enter, then enter PIN for \"%s\" on external device.\n",
|
||||
PK11_GetTokenName(slot));
|
||||
(void)SECU_GetPasswordString(NULL, prompt);
|
||||
char *pw = SECU_GetPasswordString(NULL, prompt);
|
||||
PORT_Free(pw);
|
||||
/* Fall Through */
|
||||
case PW_PLAINTEXT:
|
||||
return PL_strdup(pwdata->data);
|
||||
|
@ -1192,7 +1193,7 @@ secu_PrintRSAPSSParams(FILE *out, SECItem *value, char *m, int level)
|
|||
SECU_Indent(out, level + 1);
|
||||
fprintf(out, "Salt length: default, %i (0x%2X)\n", 20, 20);
|
||||
} else {
|
||||
SECU_PrintInteger(out, ¶m.saltLength, "Salt Length", level + 1);
|
||||
SECU_PrintInteger(out, ¶m.saltLength, "Salt length", level + 1);
|
||||
}
|
||||
} else {
|
||||
SECU_Indent(out, level + 1);
|
||||
|
|
|
@ -78,16 +78,14 @@ test_list2(int argc, char *argv[])
|
|||
for (i = 0; i < size; i++)
|
||||
for (j = 9; j > i; j--) {
|
||||
PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(list, j, &obj, plContext));
|
||||
PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(list, j -
|
||||
1,
|
||||
PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(list, j - 1,
|
||||
&obj2, plContext));
|
||||
|
||||
PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Compare(obj, obj2, &cmpResult, plContext));
|
||||
if (cmpResult < 0) {
|
||||
/* Exchange the items */
|
||||
PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_SetItem(list, j, obj2, plContext));
|
||||
PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_SetItem(list, j -
|
||||
1,
|
||||
PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_SetItem(list, j - 1,
|
||||
obj, plContext));
|
||||
}
|
||||
/* DecRef objects */
|
||||
|
|
|
@ -975,8 +975,7 @@ Pk11Install_Platform_Print(Pk11Install_Platform* _this, int pad)
|
|||
printf("Doesn't use equiv\n");
|
||||
}
|
||||
PAD(pad);
|
||||
printf("Module File: %s\n", _this->moduleFile ? _this->moduleFile
|
||||
: "<NULL>");
|
||||
printf("Module File: %s\n", _this->moduleFile ? _this->moduleFile : "<NULL>");
|
||||
PAD(pad);
|
||||
printf("mechFlags: %lx\n", _this->mechFlags);
|
||||
PAD(pad);
|
||||
|
|
|
@ -728,7 +728,7 @@ ChangePW(char *tokenName, char *pwFile, char *newpwFile)
|
|||
ret = BAD_PW_ERR;
|
||||
goto loser;
|
||||
}
|
||||
} else {
|
||||
} else if (PK11_NeedLogin(slot)) {
|
||||
for (matching = PR_FALSE; !matching;) {
|
||||
oldpw = SECU_GetPasswordString(NULL, "Enter old password: ");
|
||||
if (PK11_CheckUserPassword(slot, oldpw) == SECSuccess) {
|
||||
|
|
|
@ -502,8 +502,7 @@ do_list_certs(const char *progName, int log)
|
|||
|
||||
SECU_PrintCertNickname(node, stderr);
|
||||
if (log) {
|
||||
fprintf(stderr, "* Slot=%s*\n", cert->slot ? PK11_GetTokenName(cert->slot)
|
||||
: "none");
|
||||
fprintf(stderr, "* Slot=%s*\n", cert->slot ? PK11_GetTokenName(cert->slot) : "none");
|
||||
fprintf(stderr, "* Nickname=%s*\n", cert->nickname);
|
||||
fprintf(stderr, "* Subject=<%s>*\n", cert->subjectName);
|
||||
fprintf(stderr, "* Issuer=<%s>*\n", cert->issuerName);
|
||||
|
|
|
@ -2169,36 +2169,22 @@ PKM_Mechanism(CK_FUNCTION_LIST_PTR pFunctionList,
|
|||
PKM_LogIt(" ulMinKeySize = %lu\n", minfo.ulMinKeySize);
|
||||
PKM_LogIt(" ulMaxKeySize = %lu\n", minfo.ulMaxKeySize);
|
||||
PKM_LogIt(" flags = 0x%08x\n", minfo.flags);
|
||||
PKM_LogIt(" -> HW = %s\n", minfo.flags & CKF_HW ? "TRUE"
|
||||
: "FALSE");
|
||||
PKM_LogIt(" -> ENCRYPT = %s\n", minfo.flags & CKF_ENCRYPT ? "TRUE"
|
||||
: "FALSE");
|
||||
PKM_LogIt(" -> DECRYPT = %s\n", minfo.flags & CKF_DECRYPT ? "TRUE"
|
||||
: "FALSE");
|
||||
PKM_LogIt(" -> DIGEST = %s\n", minfo.flags & CKF_DIGEST ? "TRUE"
|
||||
: "FALSE");
|
||||
PKM_LogIt(" -> SIGN = %s\n", minfo.flags & CKF_SIGN ? "TRUE"
|
||||
: "FALSE");
|
||||
PKM_LogIt(" -> SIGN_RECOVER = %s\n", minfo.flags &
|
||||
CKF_SIGN_RECOVER
|
||||
? "TRUE"
|
||||
: "FALSE");
|
||||
PKM_LogIt(" -> VERIFY = %s\n", minfo.flags & CKF_VERIFY ? "TRUE"
|
||||
: "FALSE");
|
||||
PKM_LogIt(" -> HW = %s\n", minfo.flags & CKF_HW ? "TRUE" : "FALSE");
|
||||
PKM_LogIt(" -> ENCRYPT = %s\n", minfo.flags & CKF_ENCRYPT ? "TRUE" : "FALSE");
|
||||
PKM_LogIt(" -> DECRYPT = %s\n", minfo.flags & CKF_DECRYPT ? "TRUE" : "FALSE");
|
||||
PKM_LogIt(" -> DIGEST = %s\n", minfo.flags & CKF_DIGEST ? "TRUE" : "FALSE");
|
||||
PKM_LogIt(" -> SIGN = %s\n", minfo.flags & CKF_SIGN ? "TRUE" : "FALSE");
|
||||
PKM_LogIt(" -> SIGN_RECOVER = %s\n", minfo.flags & CKF_SIGN_RECOVER ? "TRUE" : "FALSE");
|
||||
PKM_LogIt(" -> VERIFY = %s\n", minfo.flags & CKF_VERIFY ? "TRUE" : "FALSE");
|
||||
PKM_LogIt(" -> VERIFY_RECOVER = %s\n",
|
||||
minfo.flags & CKF_VERIFY_RECOVER ? "TRUE" : "FALSE");
|
||||
PKM_LogIt(" -> GENERATE = %s\n", minfo.flags & CKF_GENERATE ? "TRUE"
|
||||
: "FALSE");
|
||||
PKM_LogIt(" -> GENERATE = %s\n", minfo.flags & CKF_GENERATE ? "TRUE" : "FALSE");
|
||||
PKM_LogIt(" -> GENERATE_KEY_PAIR = %s\n",
|
||||
minfo.flags & CKF_GENERATE_KEY_PAIR ? "TRUE" : "FALSE");
|
||||
PKM_LogIt(" -> WRAP = %s\n", minfo.flags & CKF_WRAP ? "TRUE"
|
||||
: "FALSE");
|
||||
PKM_LogIt(" -> UNWRAP = %s\n", minfo.flags & CKF_UNWRAP ? "TRUE"
|
||||
: "FALSE");
|
||||
PKM_LogIt(" -> DERIVE = %s\n", minfo.flags & CKF_DERIVE ? "TRUE"
|
||||
: "FALSE");
|
||||
PKM_LogIt(" -> EXTENSION = %s\n", minfo.flags & CKF_EXTENSION ? "TRUE"
|
||||
: "FALSE");
|
||||
PKM_LogIt(" -> WRAP = %s\n", minfo.flags & CKF_WRAP ? "TRUE" : "FALSE");
|
||||
PKM_LogIt(" -> UNWRAP = %s\n", minfo.flags & CKF_UNWRAP ? "TRUE" : "FALSE");
|
||||
PKM_LogIt(" -> DERIVE = %s\n", minfo.flags & CKF_DERIVE ? "TRUE" : "FALSE");
|
||||
PKM_LogIt(" -> EXTENSION = %s\n", minfo.flags & CKF_EXTENSION ? "TRUE" : "FALSE");
|
||||
|
||||
PKM_LogIt("\n");
|
||||
}
|
||||
|
@ -3604,24 +3590,12 @@ PKM_FindAllObjects(CK_FUNCTION_LIST_PTR pFunctionList,
|
|||
PKM_LogIt(" state = %lu\n", sinfo.state);
|
||||
PKM_LogIt(" flags = 0x%08x\n", sinfo.flags);
|
||||
#ifdef CKF_EXCLUSIVE_SESSION
|
||||
PKM_LogIt(" -> EXCLUSIVE SESSION = %s\n", sinfo.flags &
|
||||
CKF_EXCLUSIVE_SESSION
|
||||
? "TRUE"
|
||||
: "FALSE");
|
||||
PKM_LogIt(" -> EXCLUSIVE SESSION = %s\n", sinfo.flags & CKF_EXCLUSIVE_SESSION ? "TRUE" : "FALSE");
|
||||
#endif /* CKF_EXCLUSIVE_SESSION */
|
||||
PKM_LogIt(" -> RW SESSION = %s\n", sinfo.flags &
|
||||
CKF_RW_SESSION
|
||||
? "TRUE"
|
||||
: "FALSE");
|
||||
PKM_LogIt(" -> SERIAL SESSION = %s\n", sinfo.flags &
|
||||
CKF_SERIAL_SESSION
|
||||
? "TRUE"
|
||||
: "FALSE");
|
||||
PKM_LogIt(" -> RW SESSION = %s\n", sinfo.flags & CKF_RW_SESSION ? "TRUE" : "FALSE");
|
||||
PKM_LogIt(" -> SERIAL SESSION = %s\n", sinfo.flags & CKF_SERIAL_SESSION ? "TRUE" : "FALSE");
|
||||
#ifdef CKF_INSERTION_CALLBACK
|
||||
PKM_LogIt(" -> INSERTION CALLBACK = %s\n", sinfo.flags &
|
||||
CKF_INSERTION_CALLBACK
|
||||
? "TRUE"
|
||||
: "FALSE");
|
||||
PKM_LogIt(" -> INSERTION CALLBACK = %s\n", sinfo.flags & CKF_INSERTION_CALLBACK ? "TRUE" : "FALSE");
|
||||
#endif /* CKF_INSERTION_CALLBACK */
|
||||
PKM_LogIt(" ulDeviceError = %lu\n", sinfo.ulDeviceError);
|
||||
PKM_LogIt("\n");
|
||||
|
|
|
@ -671,8 +671,7 @@ main(int argc, char **argv)
|
|||
|
||||
printf("%ld iterations in %s\n",
|
||||
iters, TimingGenerateString(timeCtx));
|
||||
printf("%.2f operations/s .\n", ((double)(iters) * (double)1000000.0) /
|
||||
(double)timeCtx->interval);
|
||||
printf("%.2f operations/s .\n", ((double)(iters) * (double)1000000.0) / (double)timeCtx->interval);
|
||||
TimingDivide(timeCtx, iters);
|
||||
printf("one operation every %s\n", TimingGenerateString(timeCtx));
|
||||
|
||||
|
|
|
@ -216,7 +216,7 @@ rsaKeysAreEqual(PK11ObjectType srcType, void *src,
|
|||
printf("Could read source key\n");
|
||||
return PR_FALSE;
|
||||
}
|
||||
readKey(destType, dest, destTemplate, 0, RSA_ATTRIBUTES);
|
||||
rv = readKey(destType, dest, destTemplate, 0, RSA_ATTRIBUTES);
|
||||
if (rv != SECSuccess) {
|
||||
printf("Could read dest key\n");
|
||||
return PR_FALSE;
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "nss.h"
|
||||
#include "ssl.h"
|
||||
#include "sslproto.h"
|
||||
#include "sslexp.h"
|
||||
#include "cert.h"
|
||||
#include "certt.h"
|
||||
#include "ocsp.h"
|
||||
|
@ -1953,6 +1954,10 @@ server_main(
|
|||
if (enabledVersions.max < SSL_LIBRARY_VERSION_TLS_1_3) {
|
||||
errExit("You tried enabling 0RTT without enabling TLS 1.3!");
|
||||
}
|
||||
rv = SSL_SetupAntiReplay(10 * PR_USEC_PER_SEC, 7, 14);
|
||||
if (rv != SECSuccess) {
|
||||
errExit("error configuring anti-replay ");
|
||||
}
|
||||
rv = SSL_OptionSet(model_sock, SSL_ENABLE_0RTT_DATA, PR_TRUE);
|
||||
if (rv != SECSuccess) {
|
||||
errExit("error enabling 0RTT ");
|
||||
|
@ -2549,6 +2554,14 @@ main(int argc, char **argv)
|
|||
tmp = PR_GetEnvSecure("TMPDIR");
|
||||
if (!tmp)
|
||||
tmp = PR_GetEnvSecure("TEMP");
|
||||
|
||||
/* Call the NSS initialization routines */
|
||||
rv = NSS_Initialize(dir, certPrefix, certPrefix, SECMOD_DB, NSS_INIT_READONLY);
|
||||
if (rv != SECSuccess) {
|
||||
fputs("NSS_Init failed.\n", stderr);
|
||||
exit(8);
|
||||
}
|
||||
|
||||
if (envString) {
|
||||
/* we're one of the children in a multi-process server. */
|
||||
listen_sock = PR_GetInheritedFD(inheritableSockName);
|
||||
|
@ -2603,13 +2616,6 @@ main(int argc, char **argv)
|
|||
/* set our password function */
|
||||
PK11_SetPasswordFunc(SECU_GetModulePassword);
|
||||
|
||||
/* Call the NSS initialization routines */
|
||||
rv = NSS_Initialize(dir, certPrefix, certPrefix, SECMOD_DB, NSS_INIT_READONLY);
|
||||
if (rv != SECSuccess) {
|
||||
fputs("NSS_Init failed.\n", stderr);
|
||||
exit(8);
|
||||
}
|
||||
|
||||
/* all SSL3 cipher suites are enabled by default. */
|
||||
if (cipherString) {
|
||||
char *cstringSaved = cipherString;
|
||||
|
|
|
@ -1115,8 +1115,7 @@ extract_js(char *filename)
|
|||
|
||||
textStart = 0;
|
||||
startLine = 0;
|
||||
while (linenum = FB_GetLineNum(fb), (curchar = FB_GetChar(fb)) !=
|
||||
EOF) {
|
||||
while (linenum = FB_GetLineNum(fb), (curchar = FB_GetChar(fb)) != EOF) {
|
||||
switch (state) {
|
||||
case TEXT_HTML_STATE:
|
||||
if (curchar == '<') {
|
||||
|
|
|
@ -1033,9 +1033,7 @@ main(int argc, char *argv[])
|
|||
if (errorCount > 0 || warningCount > 0) {
|
||||
PR_fprintf(outputFD, "%d error%s, %d warning%s.\n",
|
||||
errorCount,
|
||||
errorCount == 1 ? "" : "s", warningCount, warningCount == 1
|
||||
? ""
|
||||
: "s");
|
||||
errorCount == 1 ? "" : "s", warningCount, warningCount == 1 ? "" : "s");
|
||||
} else {
|
||||
PR_fprintf(outputFD, "Directory %s signed successfully.\n",
|
||||
jartree);
|
||||
|
|
|
@ -1572,10 +1572,7 @@ main(int argc, char **argv)
|
|||
{
|
||||
unsigned int j;
|
||||
for (j = 0; j < input.len; j++)
|
||||
fprintf(stderr, "%2x%c", input.data[j], (j > 0 &&
|
||||
j % 35 == 0)
|
||||
? '\n'
|
||||
: ' ');
|
||||
fprintf(stderr, "%2x%c", input.data[j], (j > 0 && j % 35 == 0) ? '\n' : ' ');
|
||||
}
|
||||
}
|
||||
if (input.len > 0) { /* skip if certs-only (or other zero content) */
|
||||
|
|
|
@ -1637,8 +1637,7 @@ print_ssl3_handshake(unsigned char *recordBuf,
|
|||
PR_snprintf(certFileName, sizeof certFileName, "cert.%03d",
|
||||
++certFileNumber);
|
||||
cfd =
|
||||
PR_Open(certFileName, PR_WRONLY |
|
||||
PR_CREATE_FILE | PR_TRUNCATE,
|
||||
PR_Open(certFileName, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
|
||||
0664);
|
||||
if (!cfd) {
|
||||
PR_fprintf(PR_STDOUT,
|
||||
|
@ -1722,8 +1721,7 @@ print_ssl3_handshake(unsigned char *recordBuf,
|
|||
0 &&
|
||||
sslhexparse) {
|
||||
PR_fprintf(PR_STDOUT, " = {\n");
|
||||
print_hex(dnLen, hsdata +
|
||||
pos);
|
||||
print_hex(dnLen, hsdata + pos);
|
||||
PR_fprintf(PR_STDOUT, " }\n");
|
||||
} else {
|
||||
PR_fprintf(PR_STDOUT, "\n");
|
||||
|
@ -1796,8 +1794,7 @@ print_ssl3_handshake(unsigned char *recordBuf,
|
|||
|
||||
PR_snprintf(ocspFileName, sizeof ocspFileName, "ocsp.%03d",
|
||||
++ocspFileNumber);
|
||||
ofd = PR_Open(ocspFileName, PR_WRONLY |
|
||||
PR_CREATE_FILE | PR_TRUNCATE,
|
||||
ofd = PR_Open(ocspFileName, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
|
||||
0664);
|
||||
if (!ofd) {
|
||||
PR_fprintf(PR_STDOUT,
|
||||
|
@ -2167,8 +2164,7 @@ print_ssl(DataBufferList *s, int length, unsigned char *buffer)
|
|||
break;
|
||||
|
||||
case 22: /* handshake */
|
||||
print_ssl3_handshake(recordBuf, recordLen -
|
||||
s->hMACsize,
|
||||
print_ssl3_handshake(recordBuf, recordLen - s->hMACsize,
|
||||
&sr, s);
|
||||
break;
|
||||
|
||||
|
|
|
@ -96,7 +96,6 @@
|
|||
'mozilla_client%': 0,
|
||||
'moz_fold_libs%': 0,
|
||||
'moz_folded_library_name%': '',
|
||||
'ssl_enable_zlib%': 1,
|
||||
'sanitizer_flags%': 0,
|
||||
'test_build%': 0,
|
||||
'no_zdefs%': 0,
|
||||
|
|
|
@ -172,7 +172,7 @@ endif
|
|||
|
||||
# FIPS support requires startup tests to be executed at load time of shared modules.
|
||||
# For performance reasons, these tests are disabled by default.
|
||||
# When compiling binaries that must support FIPS mode,
|
||||
# When compiling binaries that must support FIPS mode,
|
||||
# you should define NSS_FORCE_FIPS
|
||||
#
|
||||
# NSS_NO_INIT_SUPPORT is always defined on platforms that don't support
|
||||
|
@ -199,8 +199,3 @@ DEFINES += -DNO_NSPR_10_SUPPORT
|
|||
|
||||
# Hide old, deprecated, TLS cipher suite names when building NSS
|
||||
DEFINES += -DSSL_DISABLE_DEPRECATED_CIPHER_SUITE_NAMES
|
||||
|
||||
# Mozilla's mozilla/modules/zlib/src/zconf.h adds the MOZ_Z_ prefix to zlib
|
||||
# exported symbols, which causes problem when NSS is built as part of Mozilla.
|
||||
# So we add a NSS_SSL_ENABLE_ZLIB variable to allow Mozilla to turn this off.
|
||||
NSS_SSL_ENABLE_ZLIB = 1
|
||||
|
|
|
@ -10,4 +10,3 @@
|
|||
*/
|
||||
|
||||
#error "Do not include this header file."
|
||||
|
||||
|
|
|
@ -62,21 +62,6 @@ size_t DataBuffer::Write(size_t index, uint32_t val, size_t count) {
|
|||
return Write(index, addr + sizeof(uint32_t) - count, count);
|
||||
}
|
||||
|
||||
// This can't use the same trick as Write(), since we might be reading from a
|
||||
// smaller data source.
|
||||
bool DataBuffer::Read(size_t index, size_t count, uint32_t* val) const {
|
||||
assert(count < sizeof(uint32_t));
|
||||
assert(val);
|
||||
if ((index > len()) || (count > (len() - index))) {
|
||||
return false;
|
||||
}
|
||||
*val = 0;
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
*val = (*val << 8) | data()[index + i];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void DataBuffer::Splice(const uint8_t* ins, size_t ins_len, size_t index,
|
||||
size_t remove) {
|
||||
assert(ins);
|
||||
|
@ -107,6 +92,32 @@ void DataBuffer::Splice(const uint8_t* ins, size_t ins_len, size_t index,
|
|||
delete[] old_value;
|
||||
}
|
||||
|
||||
// This can't use the same trick as Write(), since we might be reading from a
|
||||
// smaller data source.
|
||||
bool DataBuffer::Read(size_t index, size_t count, uint64_t* val) const {
|
||||
assert(count <= sizeof(uint64_t));
|
||||
assert(val);
|
||||
if ((index > len()) || (count > (len() - index))) {
|
||||
return false;
|
||||
}
|
||||
*val = 0;
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
*val = (*val << 8) | data()[index + i];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DataBuffer::Read(size_t index, size_t count, uint32_t* val) const {
|
||||
assert(count <= sizeof(uint32_t));
|
||||
uint64_t tmp;
|
||||
|
||||
if (!Read(index, count, &tmp)) {
|
||||
return false;
|
||||
}
|
||||
*val = tmp & 0xffffffff;
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t DataBuffer::logging_limit = 32;
|
||||
|
||||
/* static */ void DataBuffer::SetLogLimit(size_t limit) {
|
||||
|
|
|
@ -55,9 +55,6 @@ class DataBuffer {
|
|||
// Returns the offset of the end of the write.
|
||||
size_t Write(size_t index, uint32_t val, size_t count);
|
||||
|
||||
// This can't use the same trick as Write(), since we might be reading from a
|
||||
// smaller data source.
|
||||
bool Read(size_t index, size_t count, uint32_t* val) const;
|
||||
// Starting at |index|, remove |remove| bytes and replace them with the
|
||||
// contents of |buf|.
|
||||
void Splice(const DataBuffer& buf, size_t index, size_t remove = 0) {
|
||||
|
@ -68,6 +65,9 @@ class DataBuffer {
|
|||
size_t remove = 0);
|
||||
void Append(const DataBuffer& buf) { Splice(buf, len_); }
|
||||
|
||||
bool Read(size_t index, size_t count, uint64_t* val) const;
|
||||
bool Read(size_t index, size_t count, uint32_t* val) const;
|
||||
|
||||
const uint8_t* data() const { return data_; }
|
||||
uint8_t* data() { return data_; }
|
||||
size_t len() const { return len_; }
|
||||
|
|
|
@ -25,6 +25,7 @@ const uint8_t kTlsAlertType = 21;
|
|||
const uint8_t kTlsHandshakeType = 22;
|
||||
const uint8_t kTlsApplicationDataType = 23;
|
||||
const uint8_t kTlsAltHandshakeType = 24;
|
||||
const uint8_t kTlsAckType = 25;
|
||||
|
||||
const uint8_t kTlsHandshakeClientHello = 1;
|
||||
const uint8_t kTlsHandshakeServerHello = 2;
|
||||
|
@ -42,7 +43,6 @@ const uint8_t kTlsAlertWarning = 1;
|
|||
const uint8_t kTlsAlertFatal = 2;
|
||||
|
||||
const uint8_t kTlsAlertCloseNotify = 0;
|
||||
const uint8_t kTlsAlertEndOfEarlyData = 1;
|
||||
const uint8_t kTlsAlertUnexpectedMessage = 10;
|
||||
const uint8_t kTlsAlertBadRecordMac = 20;
|
||||
const uint8_t kTlsAlertRecordOverflow = 22;
|
||||
|
@ -51,6 +51,7 @@ const uint8_t kTlsAlertIllegalParameter = 47;
|
|||
const uint8_t kTlsAlertDecodeError = 50;
|
||||
const uint8_t kTlsAlertDecryptError = 51;
|
||||
const uint8_t kTlsAlertProtocolVersion = 70;
|
||||
const uint8_t kTlsAlertInternalError = 80;
|
||||
const uint8_t kTlsAlertInappropriateFallback = 86;
|
||||
const uint8_t kTlsAlertMissingExtension = 109;
|
||||
const uint8_t kTlsAlertUnsupportedExtension = 110;
|
||||
|
|
|
@ -7,7 +7,9 @@
|
|||
#include "tls_parser.h"
|
||||
|
||||
#include "ssl.h"
|
||||
extern "C" {
|
||||
#include "sslimpl.h"
|
||||
}
|
||||
|
||||
using namespace nss_test;
|
||||
|
||||
|
@ -40,7 +42,9 @@ class Record {
|
|||
void truncate(size_t length) {
|
||||
assert(length >= 5 + gExtraHeaderBytes);
|
||||
uint8_t *dest = const_cast<uint8_t *>(data_);
|
||||
(void)ssl_EncodeUintX(length - 5 - gExtraHeaderBytes, 2, &dest[3]);
|
||||
size_t l = length - (5 + gExtraHeaderBytes);
|
||||
dest[3] = (l >> 8) & 0xff;
|
||||
dest[4] = l & 0xff;
|
||||
memmove(dest + length, data_ + size_, remaining_);
|
||||
}
|
||||
|
||||
|
@ -223,8 +227,8 @@ size_t FragmentRecord(uint8_t *data, size_t size, size_t max_size,
|
|||
}
|
||||
|
||||
// Pick a record to fragment at random.
|
||||
std::uniform_int_distribution<size_t> dist(0, records.size() - 1);
|
||||
auto &rec = records.at(dist(rng));
|
||||
std::uniform_int_distribution<size_t> rand_record(0, records.size() - 1);
|
||||
auto &rec = records.at(rand_record(rng));
|
||||
uint8_t *rdata = const_cast<uint8_t *>(rec->data());
|
||||
size_t length = rec->size();
|
||||
size_t content_length = length - 5;
|
||||
|
@ -234,17 +238,21 @@ size_t FragmentRecord(uint8_t *data, size_t size, size_t max_size,
|
|||
}
|
||||
|
||||
// Assign a new length to the first fragment.
|
||||
size_t new_length = content_length / 2;
|
||||
uint8_t *content = ssl_EncodeUintX(new_length, 2, &rdata[3]);
|
||||
std::uniform_int_distribution<size_t> rand_size(1, content_length - 1);
|
||||
size_t first_length = rand_size(rng);
|
||||
size_t second_length = content_length - first_length;
|
||||
rdata[3] = (first_length >> 8) & 0xff;
|
||||
rdata[4] = first_length & 0xff;
|
||||
uint8_t *second_record = rdata + 5 + first_length;
|
||||
|
||||
// Make room for one more header.
|
||||
memmove(content + new_length + 5, content + new_length,
|
||||
rec->remaining() + content_length - new_length);
|
||||
// Make room for the header of the second record.
|
||||
memmove(second_record + 5, second_record,
|
||||
rec->remaining() + content_length - first_length);
|
||||
|
||||
// Write second header.
|
||||
memcpy(content + new_length, rdata, 3);
|
||||
(void)ssl_EncodeUintX(content_length - new_length, 2,
|
||||
&content[new_length + 3]);
|
||||
memcpy(second_record, rdata, 3);
|
||||
second_record[3] = (second_length >> 8) & 0xff;
|
||||
second_record[4] = second_length & 0xff;
|
||||
|
||||
return size + 5;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
std::vector<uint8_t> hex_string_to_bytes(std::string s) {
|
||||
static inline std::vector<uint8_t> hex_string_to_bytes(std::string s) {
|
||||
std::vector<uint8_t> bytes;
|
||||
for (size_t i = 0; i < s.length(); i += 2) {
|
||||
bytes.push_back(std::stoul(s.substr(i, 2), nullptr, 16));
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
'dh_unittest.cc',
|
||||
'ecl_unittest.cc',
|
||||
'ghash_unittest.cc',
|
||||
'rsa_unittest.cc',
|
||||
'<(DEPTH)/gtests/common/gtests.cc'
|
||||
],
|
||||
'dependencies': [
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
// 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 "gtest/gtest.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "blapi.h"
|
||||
#include "secitem.h"
|
||||
|
||||
template <class T>
|
||||
struct ScopedDelete {
|
||||
void operator()(T* ptr) {
|
||||
if (ptr) {
|
||||
PORT_FreeArena(ptr->arena, PR_TRUE);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::unique_ptr<RSAPrivateKey, ScopedDelete<RSAPrivateKey>>
|
||||
ScopedRSAPrivateKey;
|
||||
|
||||
class RSANewKeyTest : public ::testing::Test {
|
||||
protected:
|
||||
RSAPrivateKey* CreateKeyWithExponent(int keySizeInBits,
|
||||
unsigned char publicExponent) {
|
||||
SECItem exp = {siBuffer, 0, 0};
|
||||
unsigned char pubExp[1] = {publicExponent};
|
||||
exp.data = pubExp;
|
||||
exp.len = 1;
|
||||
|
||||
return RSA_NewKey(keySizeInBits, &exp);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(RSANewKeyTest, expOneTest) {
|
||||
ScopedRSAPrivateKey key(CreateKeyWithExponent(2048, 0x01));
|
||||
ASSERT_TRUE(key == nullptr);
|
||||
}
|
||||
TEST_F(RSANewKeyTest, expTwoTest) {
|
||||
ScopedRSAPrivateKey key(CreateKeyWithExponent(2048, 0x02));
|
||||
ASSERT_TRUE(key == nullptr);
|
||||
}
|
||||
TEST_F(RSANewKeyTest, expFourTest) {
|
||||
ScopedRSAPrivateKey key(CreateKeyWithExponent(2048, 0x04));
|
||||
ASSERT_TRUE(key == nullptr);
|
||||
}
|
||||
TEST_F(RSANewKeyTest, WrongKeysizeTest) {
|
||||
ScopedRSAPrivateKey key(CreateKeyWithExponent(2047, 0x03));
|
||||
ASSERT_TRUE(key == nullptr);
|
||||
}
|
||||
|
||||
TEST_F(RSANewKeyTest, expThreeTest) {
|
||||
ScopedRSAPrivateKey key(CreateKeyWithExponent(2048, 0x03));
|
||||
ASSERT_TRUE(key != nullptr);
|
||||
}
|
|
@ -30,10 +30,6 @@ include ../common/gtest.mk
|
|||
|
||||
CFLAGS += -I$(CORE_DEPTH)/lib/ssl
|
||||
|
||||
ifdef NSS_SSL_ENABLE_ZLIB
|
||||
include $(CORE_DEPTH)/coreconf/zlib.mk
|
||||
endif
|
||||
|
||||
#######################################################################
|
||||
# (5) Execute "global" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
@ -48,5 +44,3 @@ include $(CORE_DEPTH)/coreconf/rules.mk
|
|||
#######################################################################
|
||||
# (7) Execute "local" rules. (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
{
|
||||
"DisabledTests": {
|
||||
"### These tests break whenever we rev versions, so just leave them here for easy uncommenting":"",
|
||||
"#*TLS13*":"(NSS=18, BoGo=16)",
|
||||
"#*HelloRetryRequest*":"(NSS=18, BoGo=16)",
|
||||
"#*KeyShare*":"(NSS=18, BoGo=16)",
|
||||
"#*EncryptedExtensions*":"(NSS=18, BoGo=16)",
|
||||
"#*SecondClientHello*":"(NSS=18, BoGo=16)",
|
||||
"#*IgnoreClientVersionOrder*":"(NSS=18, BoGo=16)",
|
||||
"*TLS13*":"(NSS=19, BoGo=18)",
|
||||
"*HelloRetryRequest*":"(NSS=19, BoGo=18)",
|
||||
"*KeyShare*":"(NSS=19, BoGo=18)",
|
||||
"*EncryptedExtensions*":"(NSS=19, BoGo=18)",
|
||||
"*SecondClientHello*":"(NSS=19, BoGo=18)",
|
||||
"*IgnoreClientVersionOrder*":"(NSS=19, BoGo=18)",
|
||||
"SkipEarlyData*":"(NSS=19, BoGo=18)",
|
||||
"*Binder*":"(NSS=19, BoGo=18)",
|
||||
"Resume-Server-BinderWrongLength":"Alert disagreement (Bug 1317633)",
|
||||
"Resume-Server-NoPSKBinder":"Alert disagreement (Bug 1317633)",
|
||||
"CheckRecordVersion-TLS*":"Bug 1317634",
|
||||
|
@ -66,4 +68,3 @@
|
|||
":DIGEST_CHECK_FAILED:":"SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ CPPSRCS = \
|
|||
pk11_chacha20poly1305_unittest.cc \
|
||||
pk11_curve25519_unittest.cc \
|
||||
pk11_ecdsa_unittest.cc \
|
||||
pk11_encrypt_derive_unittest.cc \
|
||||
pk11_export_unittest.cc \
|
||||
pk11_pbkdf2_unittest.cc \
|
||||
pk11_prf_unittest.cc \
|
||||
|
|
|
@ -0,0 +1,210 @@
|
|||
/* 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 "pk11pub.h"
|
||||
#include "nssutil.h"
|
||||
#include <stdio.h>
|
||||
#include "prerror.h"
|
||||
#include "nss.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "scoped_ptrs.h"
|
||||
#include "cpputil.h"
|
||||
#include "databuffer.h"
|
||||
#include "util.h"
|
||||
|
||||
#define MAX_KEY_SIZE 24
|
||||
|
||||
namespace nss_test {
|
||||
|
||||
static const uint8_t kIv[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
||||
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
|
||||
static const uint8_t kInput[] = {
|
||||
0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00, 0xff, 0xee, 0xdd, 0xcc,
|
||||
0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00};
|
||||
|
||||
class EncryptDeriveTest
|
||||
: public ::testing::Test,
|
||||
public ::testing::WithParamInterface<CK_MECHANISM_TYPE> {
|
||||
public:
|
||||
void TestEncryptDerive() {
|
||||
ScopedPK11SymKey derived_key(PK11_Derive(key_.get(), derive_mech(),
|
||||
derive_param(), encrypt_mech(),
|
||||
CKA_DECRYPT, keysize()));
|
||||
ASSERT_TRUE(derived_key);
|
||||
|
||||
uint8_t derived_key_data[MAX_KEY_SIZE];
|
||||
ASSERT_GE(sizeof(derived_key_data), keysize());
|
||||
GetKeyData(derived_key, derived_key_data, keysize());
|
||||
RemoveChecksum(derived_key_data);
|
||||
|
||||
uint8_t reference_key_data[MAX_KEY_SIZE];
|
||||
unsigned int reference_len = 0;
|
||||
SECStatus rv = PK11_Encrypt(key_.get(), encrypt_mech(), encrypt_param(),
|
||||
reference_key_data, &reference_len, keysize(),
|
||||
kInput, keysize());
|
||||
ASSERT_EQ(SECSuccess, rv);
|
||||
ASSERT_EQ(keysize(), static_cast<size_t>(reference_len));
|
||||
RemoveChecksum(reference_key_data);
|
||||
|
||||
EXPECT_EQ(DataBuffer(reference_key_data, keysize()),
|
||||
DataBuffer(derived_key_data, keysize()));
|
||||
}
|
||||
|
||||
protected:
|
||||
unsigned int keysize() const { return 16; }
|
||||
|
||||
private:
|
||||
CK_MECHANISM_TYPE encrypt_mech() const { return GetParam(); }
|
||||
|
||||
CK_MECHANISM_TYPE derive_mech() const {
|
||||
switch (encrypt_mech()) {
|
||||
case CKM_DES3_ECB:
|
||||
return CKM_DES3_ECB_ENCRYPT_DATA;
|
||||
case CKM_DES3_CBC:
|
||||
return CKM_DES3_CBC_ENCRYPT_DATA;
|
||||
case CKM_AES_ECB:
|
||||
return CKM_AES_ECB_ENCRYPT_DATA;
|
||||
case CKM_AES_CBC:
|
||||
return CKM_AES_CBC_ENCRYPT_DATA;
|
||||
case CKM_CAMELLIA_ECB:
|
||||
return CKM_CAMELLIA_ECB_ENCRYPT_DATA;
|
||||
case CKM_CAMELLIA_CBC:
|
||||
return CKM_CAMELLIA_CBC_ENCRYPT_DATA;
|
||||
case CKM_SEED_ECB:
|
||||
return CKM_SEED_ECB_ENCRYPT_DATA;
|
||||
case CKM_SEED_CBC:
|
||||
return CKM_SEED_CBC_ENCRYPT_DATA;
|
||||
default:
|
||||
ADD_FAILURE() << "Unknown mechanism";
|
||||
break;
|
||||
}
|
||||
return CKM_INVALID_MECHANISM;
|
||||
}
|
||||
|
||||
SECItem* derive_param() const {
|
||||
static CK_AES_CBC_ENCRYPT_DATA_PARAMS aes_data;
|
||||
static CK_DES_CBC_ENCRYPT_DATA_PARAMS des_data;
|
||||
static CK_KEY_DERIVATION_STRING_DATA string_data;
|
||||
static SECItem param = {siBuffer, NULL, 0};
|
||||
|
||||
switch (encrypt_mech()) {
|
||||
case CKM_DES3_ECB:
|
||||
case CKM_AES_ECB:
|
||||
case CKM_CAMELLIA_ECB:
|
||||
case CKM_SEED_ECB:
|
||||
string_data.pData = toUcharPtr(kInput);
|
||||
string_data.ulLen = keysize();
|
||||
param.data = reinterpret_cast<uint8_t*>(&string_data);
|
||||
param.len = sizeof(string_data);
|
||||
break;
|
||||
|
||||
case CKM_DES3_CBC:
|
||||
des_data.pData = toUcharPtr(kInput);
|
||||
des_data.length = keysize();
|
||||
PORT_Memcpy(des_data.iv, kIv, 8);
|
||||
param.data = reinterpret_cast<uint8_t*>(&des_data);
|
||||
param.len = sizeof(des_data);
|
||||
break;
|
||||
|
||||
case CKM_AES_CBC:
|
||||
case CKM_CAMELLIA_CBC:
|
||||
case CKM_SEED_CBC:
|
||||
aes_data.pData = toUcharPtr(kInput);
|
||||
aes_data.length = keysize();
|
||||
PORT_Memcpy(aes_data.iv, kIv, keysize());
|
||||
param.data = reinterpret_cast<uint8_t*>(&aes_data);
|
||||
param.len = sizeof(aes_data);
|
||||
break;
|
||||
|
||||
default:
|
||||
ADD_FAILURE() << "Unknown mechanism";
|
||||
break;
|
||||
}
|
||||
return ¶m;
|
||||
}
|
||||
|
||||
SECItem* encrypt_param() const {
|
||||
static SECItem param = {siBuffer, NULL, 0};
|
||||
|
||||
switch (encrypt_mech()) {
|
||||
case CKM_DES3_ECB:
|
||||
case CKM_AES_ECB:
|
||||
case CKM_CAMELLIA_ECB:
|
||||
case CKM_SEED_ECB:
|
||||
// No parameter needed here.
|
||||
break;
|
||||
|
||||
case CKM_DES3_CBC:
|
||||
case CKM_AES_CBC:
|
||||
case CKM_CAMELLIA_CBC:
|
||||
case CKM_SEED_CBC:
|
||||
param.data = toUcharPtr(kIv);
|
||||
param.len = keysize();
|
||||
break;
|
||||
|
||||
default:
|
||||
ADD_FAILURE() << "Unknown mechanism";
|
||||
break;
|
||||
}
|
||||
return ¶m;
|
||||
}
|
||||
|
||||
virtual void SetUp() {
|
||||
slot_.reset(PK11_GetBestSlot(derive_mech(), NULL));
|
||||
ASSERT_TRUE(slot_);
|
||||
|
||||
key_.reset(PK11_TokenKeyGenWithFlags(slot_.get(), encrypt_mech(), NULL,
|
||||
keysize(), NULL,
|
||||
CKF_ENCRYPT | CKF_DERIVE, 0, NULL));
|
||||
ASSERT_TRUE(key_);
|
||||
}
|
||||
|
||||
void GetKeyData(ScopedPK11SymKey& key, uint8_t* buf, size_t max_len) const {
|
||||
ASSERT_EQ(SECSuccess, PK11_ExtractKeyValue(key.get()));
|
||||
SECItem* data = PK11_GetKeyData(key.get());
|
||||
ASSERT_TRUE(data);
|
||||
ASSERT_EQ(max_len, static_cast<size_t>(data->len));
|
||||
PORT_Memcpy(buf, data->data, data->len);
|
||||
}
|
||||
|
||||
// Remove checksum if the key is a 3DES key.
|
||||
void RemoveChecksum(uint8_t* key_data) const {
|
||||
if (encrypt_mech() != CKM_DES3_CBC && encrypt_mech() != CKM_DES3_ECB) {
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i < keysize(); ++i) {
|
||||
key_data[i] &= 0xfe;
|
||||
}
|
||||
}
|
||||
|
||||
ScopedPK11SlotInfo slot_;
|
||||
ScopedPK11SymKey key_;
|
||||
};
|
||||
|
||||
TEST_P(EncryptDeriveTest, Test) { TestEncryptDerive(); }
|
||||
|
||||
static const CK_MECHANISM_TYPE kEncryptDeriveMechanisms[] = {
|
||||
CKM_DES3_ECB, CKM_DES3_CBC, CKM_AES_ECB, CKM_AES_ECB, CKM_AES_CBC,
|
||||
CKM_CAMELLIA_ECB, CKM_CAMELLIA_CBC, CKM_SEED_ECB, CKM_SEED_CBC};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(EncryptDeriveTests, EncryptDeriveTest,
|
||||
::testing::ValuesIn(kEncryptDeriveMechanisms));
|
||||
|
||||
// This class handles the case where 3DES takes a 192-bit key
|
||||
// where all 24 octets will be used.
|
||||
class EncryptDerive3Test : public EncryptDeriveTest {
|
||||
protected:
|
||||
unsigned int keysize() const { return 24; }
|
||||
};
|
||||
|
||||
TEST_P(EncryptDerive3Test, Test) { TestEncryptDerive(); }
|
||||
|
||||
static const CK_MECHANISM_TYPE kDES3EncryptDeriveMechanisms[] = {CKM_DES3_ECB,
|
||||
CKM_DES3_CBC};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(Encrypt3DeriveTests, EncryptDerive3Test,
|
||||
::testing::ValuesIn(kDES3EncryptDeriveMechanisms));
|
||||
|
||||
} // namespace nss_test
|
|
@ -16,6 +16,7 @@
|
|||
'pk11_chacha20poly1305_unittest.cc',
|
||||
'pk11_curve25519_unittest.cc',
|
||||
'pk11_ecdsa_unittest.cc',
|
||||
'pk11_encrypt_derive_unittest.cc',
|
||||
'pk11_pbkdf2_unittest.cc',
|
||||
'pk11_prf_unittest.cc',
|
||||
'pk11_prng_unittest.cc',
|
||||
|
|
|
@ -29,10 +29,6 @@ include ../common/gtest.mk
|
|||
|
||||
CFLAGS += -I$(CORE_DEPTH)/lib/ssl
|
||||
|
||||
ifdef NSS_SSL_ENABLE_ZLIB
|
||||
include $(CORE_DEPTH)/coreconf/zlib.mk
|
||||
endif
|
||||
|
||||
ifdef NSS_DISABLE_TLS_1_3
|
||||
NSS_DISABLE_TLS_1_3=1
|
||||
# Run parameterized tests only, for which we can easily exclude TLS 1.3
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
extern "C" {
|
||||
#include "sslbloom.h"
|
||||
}
|
||||
|
||||
#include "gtest_utils.h"
|
||||
|
||||
namespace nss_test {
|
||||
|
||||
// Some random-ish inputs to test with. These don't result in collisions in any
|
||||
// of the configurations that are tested below.
|
||||
static const uint8_t kHashes1[] = {
|
||||
0x79, 0x53, 0xb8, 0xdd, 0x6b, 0x98, 0xce, 0x00, 0xb7, 0xdc, 0xe8,
|
||||
0x03, 0x70, 0x8c, 0xe3, 0xac, 0x06, 0x8b, 0x22, 0xfd, 0x0e, 0x34,
|
||||
0x48, 0xe6, 0xe5, 0xe0, 0x8a, 0xd6, 0x16, 0x18, 0xe5, 0x48};
|
||||
static const uint8_t kHashes2[] = {
|
||||
0xc6, 0xdd, 0x6e, 0xc4, 0x76, 0xb8, 0x55, 0xf2, 0xa4, 0xfc, 0x59,
|
||||
0x04, 0xa4, 0x90, 0xdc, 0xa7, 0xa7, 0x0d, 0x94, 0x8f, 0xc2, 0xdc,
|
||||
0x15, 0x6d, 0x48, 0x93, 0x9d, 0x05, 0xbb, 0x9a, 0xbc, 0xc1};
|
||||
|
||||
typedef struct {
|
||||
unsigned int k;
|
||||
unsigned int bits;
|
||||
} BloomFilterConfig;
|
||||
|
||||
class BloomFilterTest
|
||||
: public ::testing::Test,
|
||||
public ::testing::WithParamInterface<BloomFilterConfig> {
|
||||
public:
|
||||
BloomFilterTest() : filter_() {}
|
||||
|
||||
void SetUp() { Init(); }
|
||||
|
||||
void TearDown() { sslBloom_Destroy(&filter_); }
|
||||
|
||||
protected:
|
||||
void Init() {
|
||||
if (filter_.filter) {
|
||||
sslBloom_Destroy(&filter_);
|
||||
}
|
||||
ASSERT_EQ(SECSuccess,
|
||||
sslBloom_Init(&filter_, GetParam().k, GetParam().bits));
|
||||
}
|
||||
|
||||
bool Check(const uint8_t* hashes) {
|
||||
return sslBloom_Check(&filter_, hashes) ? true : false;
|
||||
}
|
||||
|
||||
void Add(const uint8_t* hashes, bool expect_collision = false) {
|
||||
EXPECT_EQ(expect_collision, sslBloom_Add(&filter_, hashes) ? true : false);
|
||||
EXPECT_TRUE(Check(hashes));
|
||||
}
|
||||
|
||||
sslBloomFilter filter_;
|
||||
};
|
||||
|
||||
TEST_P(BloomFilterTest, InitOnly) {}
|
||||
|
||||
TEST_P(BloomFilterTest, AddToEmpty) {
|
||||
EXPECT_FALSE(Check(kHashes1));
|
||||
Add(kHashes1);
|
||||
}
|
||||
|
||||
TEST_P(BloomFilterTest, AddTwo) {
|
||||
Add(kHashes1);
|
||||
Add(kHashes2);
|
||||
}
|
||||
|
||||
TEST_P(BloomFilterTest, AddOneTwice) {
|
||||
Add(kHashes1);
|
||||
Add(kHashes1, true);
|
||||
}
|
||||
|
||||
TEST_P(BloomFilterTest, Zero) {
|
||||
Add(kHashes1);
|
||||
sslBloom_Zero(&filter_);
|
||||
EXPECT_FALSE(Check(kHashes1));
|
||||
EXPECT_FALSE(Check(kHashes2));
|
||||
}
|
||||
|
||||
TEST_P(BloomFilterTest, Fill) {
|
||||
sslBloom_Fill(&filter_);
|
||||
EXPECT_TRUE(Check(kHashes1));
|
||||
EXPECT_TRUE(Check(kHashes2));
|
||||
}
|
||||
|
||||
static const BloomFilterConfig kBloomFilterConfigurations[] = {
|
||||
{1, 1}, // 1 hash, 1 bit input - high chance of collision.
|
||||
{1, 2}, // 1 hash, 2 bits - smaller than the basic unit size.
|
||||
{1, 3}, // 1 hash, 3 bits - same as basic unit size.
|
||||
{1, 4}, // 1 hash, 4 bits - 2 octets each.
|
||||
{3, 10}, // 3 hashes over a reasonable number of bits.
|
||||
{3, 3}, // Test that we can read multiple bits.
|
||||
{4, 15}, // A credible filter.
|
||||
{2, 18}, // A moderately large allocation.
|
||||
{16, 16}, // Insane, use all of the bits from the hashes.
|
||||
{16, 9}, // This also uses all of the bits from the hashes.
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(BloomFilterConfigurations, BloomFilterTest,
|
||||
::testing::ValuesIn(kBloomFilterConfigurations));
|
||||
|
||||
} // namespace nspr_test
|
|
@ -34,7 +34,6 @@ SECStatus SSLInt_UpdateSSLv2ClientRandom(PRFileDesc *fd, uint8_t *rnd,
|
|||
return SECFailure;
|
||||
}
|
||||
|
||||
ssl3_InitState(ss);
|
||||
ssl3_RestartHandshakeHashes(ss);
|
||||
|
||||
// Ensure we don't overrun hs.client_random.
|
||||
|
@ -73,10 +72,11 @@ SECStatus SSLInt_SetMTU(PRFileDesc *fd, PRUint16 mtu) {
|
|||
return SECFailure;
|
||||
}
|
||||
ss->ssl3.mtu = mtu;
|
||||
ss->ssl3.hs.rtRetries = 0; /* Avoid DTLS shrinking the MTU any more. */
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
PRInt32 SSLInt_CountTls13CipherSpecs(PRFileDesc *fd) {
|
||||
PRInt32 SSLInt_CountCipherSpecs(PRFileDesc *fd) {
|
||||
PRCList *cur_p;
|
||||
PRInt32 ct = 0;
|
||||
|
||||
|
@ -92,7 +92,7 @@ PRInt32 SSLInt_CountTls13CipherSpecs(PRFileDesc *fd) {
|
|||
return ct;
|
||||
}
|
||||
|
||||
void SSLInt_PrintTls13CipherSpecs(PRFileDesc *fd) {
|
||||
void SSLInt_PrintCipherSpecs(const char *label, PRFileDesc *fd) {
|
||||
PRCList *cur_p;
|
||||
|
||||
sslSocket *ss = ssl_FindSocket(fd);
|
||||
|
@ -100,27 +100,31 @@ void SSLInt_PrintTls13CipherSpecs(PRFileDesc *fd) {
|
|||
return;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Cipher specs\n");
|
||||
fprintf(stderr, "Cipher specs for %s\n", label);
|
||||
for (cur_p = PR_NEXT_LINK(&ss->ssl3.hs.cipherSpecs);
|
||||
cur_p != &ss->ssl3.hs.cipherSpecs; cur_p = PR_NEXT_LINK(cur_p)) {
|
||||
ssl3CipherSpec *spec = (ssl3CipherSpec *)cur_p;
|
||||
fprintf(stderr, " %s\n", spec->phase);
|
||||
fprintf(stderr, " %s spec epoch=%d (%s) refct=%d\n", SPEC_DIR(spec),
|
||||
spec->epoch, spec->phase, spec->refCt);
|
||||
}
|
||||
}
|
||||
|
||||
/* Force a timer expiry by backdating when the timer was started.
|
||||
* We could set the remaining time to 0 but then backoff would not
|
||||
* work properly if we decide to test it. */
|
||||
void SSLInt_ForceTimerExpiry(PRFileDesc *fd) {
|
||||
/* Force a timer expiry by backdating when all active timers were started. We
|
||||
* could set the remaining time to 0 but then backoff would not work properly if
|
||||
* we decide to test it. */
|
||||
SECStatus SSLInt_ShiftDtlsTimers(PRFileDesc *fd, PRIntervalTime shift) {
|
||||
size_t i;
|
||||
sslSocket *ss = ssl_FindSocket(fd);
|
||||
if (!ss) {
|
||||
return;
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
if (!ss->ssl3.hs.rtTimerCb) return;
|
||||
|
||||
ss->ssl3.hs.rtTimerStarted =
|
||||
PR_IntervalNow() - PR_MillisecondsToInterval(ss->ssl3.hs.rtTimeoutMs + 1);
|
||||
for (i = 0; i < PR_ARRAY_SIZE(ss->ssl3.hs.timers); ++i) {
|
||||
if (ss->ssl3.hs.timers[i].cb) {
|
||||
ss->ssl3.hs.timers[i].started -= shift;
|
||||
}
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
#define CHECK_SECRET(secret) \
|
||||
|
@ -136,7 +140,6 @@ PRBool SSLInt_CheckSecretsDestroyed(PRFileDesc *fd) {
|
|||
}
|
||||
|
||||
CHECK_SECRET(currentSecret);
|
||||
CHECK_SECRET(resumptionMasterSecret);
|
||||
CHECK_SECRET(dheSecret);
|
||||
CHECK_SECRET(clientEarlyTrafficSecret);
|
||||
CHECK_SECRET(clientHsTrafficSecret);
|
||||
|
@ -226,28 +229,7 @@ PRBool SSLInt_SendAlert(PRFileDesc *fd, uint8_t level, uint8_t type) {
|
|||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool SSLInt_SendNewSessionTicket(PRFileDesc *fd) {
|
||||
sslSocket *ss = ssl_FindSocket(fd);
|
||||
if (!ss) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
ssl_GetSSL3HandshakeLock(ss);
|
||||
ssl_GetXmitBufLock(ss);
|
||||
|
||||
SECStatus rv = tls13_SendNewSessionTicket(ss);
|
||||
if (rv == SECSuccess) {
|
||||
rv = ssl3_FlushHandshake(ss, 0);
|
||||
}
|
||||
|
||||
ssl_ReleaseXmitBufLock(ss);
|
||||
ssl_ReleaseSSL3HandshakeLock(ss);
|
||||
|
||||
return rv == SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus SSLInt_AdvanceReadSeqNum(PRFileDesc *fd, PRUint64 to) {
|
||||
PRUint64 epoch;
|
||||
sslSocket *ss;
|
||||
ssl3CipherSpec *spec;
|
||||
|
||||
|
@ -255,43 +237,40 @@ SECStatus SSLInt_AdvanceReadSeqNum(PRFileDesc *fd, PRUint64 to) {
|
|||
if (!ss) {
|
||||
return SECFailure;
|
||||
}
|
||||
if (to >= (1ULL << 48)) {
|
||||
if (to >= RECORD_SEQ_MAX) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
ssl_GetSpecWriteLock(ss);
|
||||
spec = ss->ssl3.crSpec;
|
||||
epoch = spec->read_seq_num >> 48;
|
||||
spec->read_seq_num = (epoch << 48) | to;
|
||||
spec->seqNum = to;
|
||||
|
||||
/* For DTLS, we need to fix the record sequence number. For this, we can just
|
||||
* scrub the entire structure on the assumption that the new sequence number
|
||||
* is far enough past the last received sequence number. */
|
||||
if (to <= spec->recvdRecords.right + DTLS_RECVD_RECORDS_WINDOW) {
|
||||
if (spec->seqNum <= spec->recvdRecords.right + DTLS_RECVD_RECORDS_WINDOW) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
dtls_RecordSetRecvd(&spec->recvdRecords, to);
|
||||
dtls_RecordSetRecvd(&spec->recvdRecords, spec->seqNum);
|
||||
|
||||
ssl_ReleaseSpecWriteLock(ss);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus SSLInt_AdvanceWriteSeqNum(PRFileDesc *fd, PRUint64 to) {
|
||||
PRUint64 epoch;
|
||||
sslSocket *ss;
|
||||
|
||||
ss = ssl_FindSocket(fd);
|
||||
if (!ss) {
|
||||
return SECFailure;
|
||||
}
|
||||
if (to >= (1ULL << 48)) {
|
||||
if (to >= RECORD_SEQ_MAX) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
ssl_GetSpecWriteLock(ss);
|
||||
epoch = ss->ssl3.cwSpec->write_seq_num >> 48;
|
||||
ss->ssl3.cwSpec->write_seq_num = (epoch << 48) | to;
|
||||
ss->ssl3.cwSpec->seqNum = to;
|
||||
ssl_ReleaseSpecWriteLock(ss);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
@ -305,9 +284,9 @@ SECStatus SSLInt_AdvanceWriteSeqByAWindow(PRFileDesc *fd, PRInt32 extra) {
|
|||
return SECFailure;
|
||||
}
|
||||
ssl_GetSpecReadLock(ss);
|
||||
to = ss->ssl3.cwSpec->write_seq_num + DTLS_RECVD_RECORDS_WINDOW + extra;
|
||||
to = ss->ssl3.cwSpec->seqNum + DTLS_RECVD_RECORDS_WINDOW + extra;
|
||||
ssl_ReleaseSpecReadLock(ss);
|
||||
return SSLInt_AdvanceWriteSeqNum(fd, to & RECORD_SEQ_MAX);
|
||||
return SSLInt_AdvanceWriteSeqNum(fd, to);
|
||||
}
|
||||
|
||||
SSLKEAType SSLInt_GetKEAType(SSLNamedGroup group) {
|
||||
|
@ -333,46 +312,20 @@ SECStatus SSLInt_SetCipherSpecChangeFunc(PRFileDesc *fd,
|
|||
return SECSuccess;
|
||||
}
|
||||
|
||||
static ssl3KeyMaterial *GetKeyingMaterial(PRBool isServer,
|
||||
ssl3CipherSpec *spec) {
|
||||
return isServer ? &spec->server : &spec->client;
|
||||
PK11SymKey *SSLInt_CipherSpecToKey(const ssl3CipherSpec *spec) {
|
||||
return spec->keyMaterial.key;
|
||||
}
|
||||
|
||||
PK11SymKey *SSLInt_CipherSpecToKey(PRBool isServer, ssl3CipherSpec *spec) {
|
||||
return GetKeyingMaterial(isServer, spec)->write_key;
|
||||
SSLCipherAlgorithm SSLInt_CipherSpecToAlgorithm(const ssl3CipherSpec *spec) {
|
||||
return spec->cipherDef->calg;
|
||||
}
|
||||
|
||||
SSLCipherAlgorithm SSLInt_CipherSpecToAlgorithm(PRBool isServer,
|
||||
ssl3CipherSpec *spec) {
|
||||
return spec->cipher_def->calg;
|
||||
const PRUint8 *SSLInt_CipherSpecToIv(const ssl3CipherSpec *spec) {
|
||||
return spec->keyMaterial.iv;
|
||||
}
|
||||
|
||||
unsigned char *SSLInt_CipherSpecToIv(PRBool isServer, ssl3CipherSpec *spec) {
|
||||
return GetKeyingMaterial(isServer, spec)->write_iv;
|
||||
}
|
||||
|
||||
SECStatus SSLInt_EnableShortHeaders(PRFileDesc *fd) {
|
||||
sslSocket *ss;
|
||||
|
||||
ss = ssl_FindSocket(fd);
|
||||
if (!ss) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
ss->opt.enableShortHeaders = PR_TRUE;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus SSLInt_UsingShortHeaders(PRFileDesc *fd, PRBool *result) {
|
||||
sslSocket *ss;
|
||||
|
||||
ss = ssl_FindSocket(fd);
|
||||
if (!ss) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
*result = ss->ssl3.hs.shortHeaders;
|
||||
return SECSuccess;
|
||||
PRUint16 SSLInt_CipherSpecToEpoch(const ssl3CipherSpec *spec) {
|
||||
return spec->epoch;
|
||||
}
|
||||
|
||||
void SSLInt_SetTicketLifetime(uint32_t lifetime) {
|
||||
|
@ -405,3 +358,7 @@ SECStatus SSLInt_SetSocketMaxEarlyDataSize(PRFileDesc *fd, uint32_t size) {
|
|||
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
void SSLInt_RolloverAntiReplay(void) {
|
||||
tls13_AntiReplayRollover(ssl_TimeUsec());
|
||||
}
|
||||
|
|
|
@ -24,9 +24,9 @@ SECStatus SSLInt_UpdateSSLv2ClientRandom(PRFileDesc *fd, uint8_t *rnd,
|
|||
PRBool SSLInt_ExtensionNegotiated(PRFileDesc *fd, PRUint16 ext);
|
||||
void SSLInt_ClearSelfEncryptKey();
|
||||
void SSLInt_SetSelfEncryptMacKey(PK11SymKey *key);
|
||||
PRInt32 SSLInt_CountTls13CipherSpecs(PRFileDesc *fd);
|
||||
void SSLInt_PrintTls13CipherSpecs(PRFileDesc *fd);
|
||||
void SSLInt_ForceTimerExpiry(PRFileDesc *fd);
|
||||
PRInt32 SSLInt_CountCipherSpecs(PRFileDesc *fd);
|
||||
void SSLInt_PrintCipherSpecs(const char *label, PRFileDesc *fd);
|
||||
SECStatus SSLInt_ShiftDtlsTimers(PRFileDesc *fd, PRIntervalTime shift);
|
||||
SECStatus SSLInt_SetMTU(PRFileDesc *fd, PRUint16 mtu);
|
||||
PRBool SSLInt_CheckSecretsDestroyed(PRFileDesc *fd);
|
||||
PRBool SSLInt_DamageClientHsTrafficSecret(PRFileDesc *fd);
|
||||
|
@ -35,7 +35,6 @@ PRBool SSLInt_DamageEarlyTrafficSecret(PRFileDesc *fd);
|
|||
SECStatus SSLInt_Set0RttAlpn(PRFileDesc *fd, PRUint8 *data, unsigned int len);
|
||||
PRBool SSLInt_HasCertWithAuthType(PRFileDesc *fd, SSLAuthType authType);
|
||||
PRBool SSLInt_SendAlert(PRFileDesc *fd, uint8_t level, uint8_t type);
|
||||
PRBool SSLInt_SendNewSessionTicket(PRFileDesc *fd);
|
||||
SECStatus SSLInt_AdvanceWriteSeqNum(PRFileDesc *fd, PRUint64 to);
|
||||
SECStatus SSLInt_AdvanceReadSeqNum(PRFileDesc *fd, PRUint64 to);
|
||||
SECStatus SSLInt_AdvanceWriteSeqByAWindow(PRFileDesc *fd, PRInt32 extra);
|
||||
|
@ -44,14 +43,13 @@ SSLKEAType SSLInt_GetKEAType(SSLNamedGroup group);
|
|||
SECStatus SSLInt_SetCipherSpecChangeFunc(PRFileDesc *fd,
|
||||
sslCipherSpecChangedFunc func,
|
||||
void *arg);
|
||||
PK11SymKey *SSLInt_CipherSpecToKey(PRBool isServer, ssl3CipherSpec *spec);
|
||||
SSLCipherAlgorithm SSLInt_CipherSpecToAlgorithm(PRBool isServer,
|
||||
ssl3CipherSpec *spec);
|
||||
unsigned char *SSLInt_CipherSpecToIv(PRBool isServer, ssl3CipherSpec *spec);
|
||||
SECStatus SSLInt_EnableShortHeaders(PRFileDesc *fd);
|
||||
SECStatus SSLInt_UsingShortHeaders(PRFileDesc *fd, PRBool *result);
|
||||
PRUint16 SSLInt_CipherSpecToEpoch(const ssl3CipherSpec *spec);
|
||||
PK11SymKey *SSLInt_CipherSpecToKey(const ssl3CipherSpec *spec);
|
||||
SSLCipherAlgorithm SSLInt_CipherSpecToAlgorithm(const ssl3CipherSpec *spec);
|
||||
const PRUint8 *SSLInt_CipherSpecToIv(const ssl3CipherSpec *spec);
|
||||
void SSLInt_SetTicketLifetime(uint32_t lifetime);
|
||||
void SSLInt_SetMaxEarlyDataSize(uint32_t size);
|
||||
SECStatus SSLInt_SetSocketMaxEarlyDataSize(PRFileDesc *fd, uint32_t size);
|
||||
void SSLInt_RolloverAntiReplay(void);
|
||||
|
||||
#endif // ndef libssl_internals_h_
|
||||
|
|
|
@ -12,12 +12,13 @@ CSRCS = \
|
|||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
bloomfilter_unittest.cc \
|
||||
ssl_0rtt_unittest.cc \
|
||||
ssl_agent_unittest.cc \
|
||||
ssl_alths_unittest.cc \
|
||||
ssl_auth_unittest.cc \
|
||||
ssl_cert_ext_unittest.cc \
|
||||
ssl_ciphersuite_unittest.cc \
|
||||
ssl_custext_unittest.cc \
|
||||
ssl_damage_unittest.cc \
|
||||
ssl_dhe_unittest.cc \
|
||||
ssl_drop_unittest.cc \
|
||||
|
@ -38,6 +39,7 @@ CPPSRCS = \
|
|||
ssl_renegotiation_unittest.cc \
|
||||
ssl_skip_unittest.cc \
|
||||
ssl_staticrsa_unittest.cc \
|
||||
ssl_tls13compat_unittest.cc \
|
||||
ssl_v2_client_hello_unittest.cc \
|
||||
ssl_version_unittest.cc \
|
||||
ssl_versionpolicy_unittest.cc \
|
||||
|
|
|
@ -45,6 +45,93 @@ TEST_P(TlsConnectTls13, ZeroRttServerRejectByOption) {
|
|||
SendReceive();
|
||||
}
|
||||
|
||||
TEST_P(TlsConnectTls13, ZeroRttApparentReplayAfterRestart) {
|
||||
// The test fixtures call SSL_SetupAntiReplay() in SetUp(). This results in
|
||||
// 0-RTT being rejected until at least one window passes. SetupFor0Rtt()
|
||||
// forces a rollover of the anti-replay filters, which clears this state.
|
||||
// Here, we do the setup manually here without that forced rollover.
|
||||
|
||||
ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
|
||||
ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
|
||||
server_->Set0RttEnabled(true); // So we signal that we allow 0-RTT.
|
||||
Connect();
|
||||
SendReceive(); // Need to read so that we absorb the session ticket.
|
||||
CheckKeys();
|
||||
|
||||
Reset();
|
||||
StartConnect();
|
||||
client_->Set0RttEnabled(true);
|
||||
server_->Set0RttEnabled(true);
|
||||
ExpectResumption(RESUME_TICKET);
|
||||
ZeroRttSendReceive(true, false);
|
||||
Handshake();
|
||||
CheckConnected();
|
||||
SendReceive();
|
||||
}
|
||||
|
||||
class TlsZeroRttReplayTest : public TlsConnectTls13 {
|
||||
private:
|
||||
class SaveFirstPacket : public PacketFilter {
|
||||
public:
|
||||
PacketFilter::Action Filter(const DataBuffer& input,
|
||||
DataBuffer* output) override {
|
||||
if (!packet_.len() && input.len()) {
|
||||
packet_ = input;
|
||||
}
|
||||
return KEEP;
|
||||
}
|
||||
|
||||
const DataBuffer& packet() const { return packet_; }
|
||||
|
||||
private:
|
||||
DataBuffer packet_;
|
||||
};
|
||||
|
||||
protected:
|
||||
void RunTest(bool rollover) {
|
||||
// Run the initial handshake
|
||||
SetupForZeroRtt();
|
||||
|
||||
// Now run a true 0-RTT handshake, but capture the first packet.
|
||||
auto first_packet = std::make_shared<SaveFirstPacket>();
|
||||
client_->SetPacketFilter(first_packet);
|
||||
client_->Set0RttEnabled(true);
|
||||
server_->Set0RttEnabled(true);
|
||||
ExpectResumption(RESUME_TICKET);
|
||||
ZeroRttSendReceive(true, true);
|
||||
Handshake();
|
||||
EXPECT_LT(0U, first_packet->packet().len());
|
||||
ExpectEarlyDataAccepted(true);
|
||||
CheckConnected();
|
||||
SendReceive();
|
||||
|
||||
if (rollover) {
|
||||
SSLInt_RolloverAntiReplay();
|
||||
}
|
||||
|
||||
// Now replay that packet against the server.
|
||||
Reset();
|
||||
server_->StartConnect();
|
||||
server_->Set0RttEnabled(true);
|
||||
|
||||
// Capture the early_data extension, which should not appear.
|
||||
auto early_data_ext =
|
||||
std::make_shared<TlsExtensionCapture>(ssl_tls13_early_data_xtn);
|
||||
server_->SetPacketFilter(early_data_ext);
|
||||
|
||||
// Finally, replay the ClientHello and force the server to consume it. Stop
|
||||
// after the server sends its first flight; the client will not be able to
|
||||
// complete this handshake.
|
||||
server_->adapter()->PacketReceived(first_packet->packet());
|
||||
server_->Handshake();
|
||||
EXPECT_FALSE(early_data_ext->captured());
|
||||
}
|
||||
};
|
||||
|
||||
TEST_P(TlsZeroRttReplayTest, ZeroRttReplay) { RunTest(false); }
|
||||
|
||||
TEST_P(TlsZeroRttReplayTest, ZeroRttReplayAfterRollover) { RunTest(true); }
|
||||
|
||||
// Test that we don't try to send 0-RTT data when the server sent
|
||||
// us a ticket without the 0-RTT flags.
|
||||
TEST_P(TlsConnectTls13, ZeroRttOptionsSetLate) {
|
||||
|
@ -53,8 +140,7 @@ TEST_P(TlsConnectTls13, ZeroRttOptionsSetLate) {
|
|||
SendReceive(); // Need to read so that we absorb the session ticket.
|
||||
CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
|
||||
Reset();
|
||||
server_->StartConnect();
|
||||
client_->StartConnect();
|
||||
StartConnect();
|
||||
// Now turn on 0-RTT but too late for the ticket.
|
||||
client_->Set0RttEnabled(true);
|
||||
server_->Set0RttEnabled(true);
|
||||
|
@ -81,8 +167,7 @@ TEST_P(TlsConnectTls13, ZeroRttServerForgetTicket) {
|
|||
TEST_P(TlsConnectTls13, ZeroRttServerOnly) {
|
||||
ExpectResumption(RESUME_NONE);
|
||||
server_->Set0RttEnabled(true);
|
||||
client_->StartConnect();
|
||||
server_->StartConnect();
|
||||
StartConnect();
|
||||
|
||||
// Client sends ordinary ClientHello.
|
||||
client_->Handshake();
|
||||
|
@ -100,6 +185,61 @@ TEST_P(TlsConnectTls13, ZeroRttServerOnly) {
|
|||
CheckKeys();
|
||||
}
|
||||
|
||||
// A small sleep after sending the ClientHello means that the ticket age that
|
||||
// arrives at the server is too low. With a small tolerance for variation in
|
||||
// ticket age (which is determined by the |window| parameter that is passed to
|
||||
// SSL_SetupAntiReplay()), the server then rejects early data.
|
||||
TEST_P(TlsConnectTls13, ZeroRttRejectOldTicket) {
|
||||
SetupForZeroRtt();
|
||||
client_->Set0RttEnabled(true);
|
||||
server_->Set0RttEnabled(true);
|
||||
EXPECT_EQ(SECSuccess, SSL_SetupAntiReplay(1, 1, 3));
|
||||
SSLInt_RolloverAntiReplay(); // Make sure to flush replay state.
|
||||
SSLInt_RolloverAntiReplay();
|
||||
ExpectResumption(RESUME_TICKET);
|
||||
ZeroRttSendReceive(true, false, []() {
|
||||
PR_Sleep(PR_MillisecondsToInterval(10));
|
||||
return true;
|
||||
});
|
||||
Handshake();
|
||||
ExpectEarlyDataAccepted(false);
|
||||
CheckConnected();
|
||||
SendReceive();
|
||||
}
|
||||
|
||||
// In this test, we falsely inflate the estimate of the RTT by delaying the
|
||||
// ServerHello on the first handshake. This results in the server estimating a
|
||||
// higher value of the ticket age than the client ultimately provides. Add a
|
||||
// small tolerance for variation in ticket age and the ticket will appear to
|
||||
// arrive prematurely, causing the server to reject early data.
|
||||
TEST_P(TlsConnectTls13, ZeroRttRejectPrematureTicket) {
|
||||
ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
|
||||
ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
|
||||
server_->Set0RttEnabled(true);
|
||||
StartConnect();
|
||||
client_->Handshake(); // ClientHello
|
||||
server_->Handshake(); // ServerHello
|
||||
PR_Sleep(PR_MillisecondsToInterval(10));
|
||||
Handshake(); // Remainder of handshake
|
||||
CheckConnected();
|
||||
SendReceive();
|
||||
CheckKeys();
|
||||
|
||||
Reset();
|
||||
client_->Set0RttEnabled(true);
|
||||
server_->Set0RttEnabled(true);
|
||||
EXPECT_EQ(SECSuccess, SSL_SetupAntiReplay(1, 1, 3));
|
||||
SSLInt_RolloverAntiReplay(); // Make sure to flush replay state.
|
||||
SSLInt_RolloverAntiReplay();
|
||||
ExpectResumption(RESUME_TICKET);
|
||||
ExpectEarlyDataAccepted(false);
|
||||
StartConnect();
|
||||
ZeroRttSendReceive(true, false);
|
||||
Handshake();
|
||||
CheckConnected();
|
||||
SendReceive();
|
||||
}
|
||||
|
||||
TEST_P(TlsConnectTls13, TestTls13ZeroRttAlpn) {
|
||||
EnableAlpn();
|
||||
SetupForZeroRtt();
|
||||
|
@ -118,6 +258,14 @@ TEST_P(TlsConnectTls13, TestTls13ZeroRttAlpn) {
|
|||
CheckAlpn("a");
|
||||
}
|
||||
|
||||
// NOTE: In this test and those below, the client always sends
|
||||
// post-ServerHello alerts with the handshake keys, even if the server
|
||||
// has accepted 0-RTT. In some cases, as with errors in
|
||||
// EncryptedExtensions, the client can't know the server's behavior,
|
||||
// and in others it's just simpler. What the server is expecting
|
||||
// depends on whether it accepted 0-RTT or not. Eventually, we may
|
||||
// make the server trial decrypt.
|
||||
//
|
||||
// Have the server negotiate a different ALPN value, and therefore
|
||||
// reject 0-RTT.
|
||||
TEST_P(TlsConnectTls13, TestTls13ZeroRttAlpnChangeServer) {
|
||||
|
@ -156,12 +304,17 @@ TEST_P(TlsConnectTls13, TestTls13ZeroRttNoAlpnServer) {
|
|||
client_->CheckAlpn(SSL_NEXT_PROTO_EARLY_VALUE, "a");
|
||||
EXPECT_EQ(SECSuccess, SSLInt_Set0RttAlpn(client_->ssl_fd(), b, sizeof(b)));
|
||||
client_->CheckAlpn(SSL_NEXT_PROTO_EARLY_VALUE, "b");
|
||||
ExpectAlert(client_, kTlsAlertIllegalParameter);
|
||||
client_->ExpectSendAlert(kTlsAlertIllegalParameter);
|
||||
return true;
|
||||
});
|
||||
Handshake();
|
||||
if (variant_ == ssl_variant_stream) {
|
||||
server_->ExpectSendAlert(kTlsAlertBadRecordMac);
|
||||
Handshake();
|
||||
server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
|
||||
} else {
|
||||
client_->Handshake();
|
||||
}
|
||||
client_->CheckErrorCode(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
|
||||
server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
|
||||
}
|
||||
|
||||
// Set up with no ALPN and then set the client so it thinks it has ALPN.
|
||||
|
@ -176,12 +329,17 @@ TEST_P(TlsConnectTls13, TestTls13ZeroRttNoAlpnClient) {
|
|||
PRUint8 b[] = {'b'};
|
||||
EXPECT_EQ(SECSuccess, SSLInt_Set0RttAlpn(client_->ssl_fd(), b, 1));
|
||||
client_->CheckAlpn(SSL_NEXT_PROTO_EARLY_VALUE, "b");
|
||||
ExpectAlert(client_, kTlsAlertIllegalParameter);
|
||||
client_->ExpectSendAlert(kTlsAlertIllegalParameter);
|
||||
return true;
|
||||
});
|
||||
Handshake();
|
||||
if (variant_ == ssl_variant_stream) {
|
||||
server_->ExpectSendAlert(kTlsAlertBadRecordMac);
|
||||
Handshake();
|
||||
server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
|
||||
} else {
|
||||
client_->Handshake();
|
||||
}
|
||||
client_->CheckErrorCode(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
|
||||
server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
|
||||
}
|
||||
|
||||
// Remove the old ALPN value and so the client will not offer early data.
|
||||
|
@ -219,9 +377,7 @@ TEST_P(TlsConnectTls13, TestTls13ZeroRttDowngrade) {
|
|||
SSL_LIBRARY_VERSION_TLS_1_3);
|
||||
server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2);
|
||||
client_->StartConnect();
|
||||
server_->StartConnect();
|
||||
|
||||
StartConnect();
|
||||
// We will send the early data xtn without sending actual early data. Thus
|
||||
// a 1.2 server shouldn't fail until the client sends an alert because the
|
||||
// client sends end_of_early_data only after reading the server's flight.
|
||||
|
@ -262,9 +418,7 @@ TEST_P(TlsConnectTls13, TestTls13ZeroRttDowngradeEarlyData) {
|
|||
SSL_LIBRARY_VERSION_TLS_1_3);
|
||||
server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2);
|
||||
client_->StartConnect();
|
||||
server_->StartConnect();
|
||||
|
||||
StartConnect();
|
||||
// Send the early data xtn in the CH, followed by early app data. The server
|
||||
// will fail right after sending its flight, when receiving the early data.
|
||||
client_->Set0RttEnabled(true);
|
||||
|
@ -311,7 +465,6 @@ TEST_P(TlsConnectTls13, SendTooMuchEarlyData) {
|
|||
server_->Set0RttEnabled(true);
|
||||
ExpectResumption(RESUME_TICKET);
|
||||
|
||||
ExpectAlert(client_, kTlsAlertEndOfEarlyData);
|
||||
client_->Handshake();
|
||||
CheckEarlyDataLimit(client_, short_size);
|
||||
|
||||
|
@ -365,7 +518,6 @@ TEST_P(TlsConnectTls13, ReceiveTooMuchEarlyData) {
|
|||
server_->Set0RttEnabled(true);
|
||||
ExpectResumption(RESUME_TICKET);
|
||||
|
||||
client_->ExpectSendAlert(kTlsAlertEndOfEarlyData);
|
||||
client_->Handshake(); // Send ClientHello
|
||||
CheckEarlyDataLimit(client_, limit);
|
||||
|
||||
|
@ -440,7 +592,6 @@ TEST_P(TlsConnectTls13, ZeroRttOrdering) {
|
|||
|
||||
// Send (and hold) the second client handshake flight.
|
||||
// The client sends EndOfEarlyData after seeing the server Finished.
|
||||
ExpectAlert(client_, kTlsAlertEndOfEarlyData);
|
||||
server_->Handshake();
|
||||
client_->Handshake();
|
||||
|
||||
|
@ -484,4 +635,9 @@ TEST_P(TlsConnectTls13, ZeroRttOrdering) {
|
|||
EXPECT_EQ(2U, step);
|
||||
}
|
||||
|
||||
#ifndef NSS_DISABLE_TLS_1_3
|
||||
INSTANTIATE_TEST_CASE_P(Tls13ZeroRttReplayTest, TlsZeroRttReplayTest,
|
||||
TlsConnectTestBase::kTlsVariantsAll);
|
||||
#endif
|
||||
|
||||
} // namespace nss_test
|
||||
|
|
|
@ -44,13 +44,14 @@ const static uint8_t kCannedTls13ClientHello[] = {
|
|||
0x02, 0x05, 0x02, 0x06, 0x02, 0x02, 0x02};
|
||||
|
||||
const static uint8_t kCannedTls13ServerHello[] = {
|
||||
0x7f, kD13, 0x9c, 0xbc, 0x14, 0x9b, 0x0e, 0x2e, 0xfa, 0x0d, 0xf3, 0xf0,
|
||||
0x5c, 0x70, 0x7a, 0xe0, 0xd1, 0x9b, 0x3e, 0x5a, 0x44, 0x6b, 0xdf, 0xe5,
|
||||
0xc2, 0x28, 0x64, 0xf7, 0x00, 0xc1, 0x9c, 0x08, 0x76, 0x08, 0x13, 0x01,
|
||||
0x00, 0x28, 0x00, 0x28, 0x00, 0x24, 0x00, 0x1d, 0x00, 0x20, 0xc2, 0xcf,
|
||||
0x23, 0x17, 0x64, 0x23, 0x03, 0xf0, 0xfb, 0x45, 0x98, 0x26, 0xd1, 0x65,
|
||||
0x24, 0xa1, 0x6c, 0xa9, 0x80, 0x8f, 0x2c, 0xac, 0x0a, 0xea, 0x53, 0x3a,
|
||||
0xcb, 0xe3, 0x08, 0x84, 0xae, 0x19};
|
||||
0x03, 0x03, 0x9c, 0xbc, 0x14, 0x9b, 0x0e, 0x2e, 0xfa, 0x0d, 0xf3,
|
||||
0xf0, 0x5c, 0x70, 0x7a, 0xe0, 0xd1, 0x9b, 0x3e, 0x5a, 0x44, 0x6b,
|
||||
0xdf, 0xe5, 0xc2, 0x28, 0x64, 0xf7, 0x00, 0xc1, 0x9c, 0x08, 0x76,
|
||||
0x08, 0x00, 0x13, 0x01, 0x00, 0x00, 0x2e, 0x00, 0x28, 0x00, 0x24,
|
||||
0x00, 0x1d, 0x00, 0x20, 0xc2, 0xcf, 0x23, 0x17, 0x64, 0x23, 0x03,
|
||||
0xf0, 0xfb, 0x45, 0x98, 0x26, 0xd1, 0x65, 0x24, 0xa1, 0x6c, 0xa9,
|
||||
0x80, 0x8f, 0x2c, 0xac, 0x0a, 0xea, 0x53, 0x3a, 0xcb, 0xe3, 0x08,
|
||||
0x84, 0xae, 0x19, 0x00, 0x2b, 0x00, 0x02, 0x7f, kD13};
|
||||
static const char *k0RttData = "ABCDEF";
|
||||
|
||||
TEST_P(TlsAgentTest, EarlyFinished) {
|
||||
|
|
|
@ -1,189 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "ssl.h"
|
||||
#include "sslerr.h"
|
||||
#include "sslproto.h"
|
||||
|
||||
#include "gtest_utils.h"
|
||||
#include "tls_connect.h"
|
||||
#include "tls_filter.h"
|
||||
#include "tls_parser.h"
|
||||
|
||||
namespace nss_test {
|
||||
|
||||
static const uint32_t kServerHelloVersionAlt = SSL_LIBRARY_VERSION_TLS_1_2;
|
||||
static const uint16_t kServerHelloVersionRegular =
|
||||
0x7f00 | TLS_1_3_DRAFT_VERSION;
|
||||
|
||||
class AltHandshakeTest : public TlsConnectStreamTls13 {
|
||||
protected:
|
||||
void SetUp() {
|
||||
TlsConnectStreamTls13::SetUp();
|
||||
client_ccs_recorder_ =
|
||||
std::make_shared<TlsRecordRecorder>(kTlsChangeCipherSpecType);
|
||||
server_handshake_recorder_ =
|
||||
std::make_shared<TlsRecordRecorder>(kTlsHandshakeType);
|
||||
server_ccs_recorder_ =
|
||||
std::make_shared<TlsRecordRecorder>(kTlsChangeCipherSpecType);
|
||||
server_hello_recorder_ =
|
||||
std::make_shared<TlsInspectorRecordHandshakeMessage>(
|
||||
kTlsHandshakeServerHello);
|
||||
}
|
||||
|
||||
void SetAltHandshakeTypeEnabled() {
|
||||
client_->SetAltHandshakeTypeEnabled();
|
||||
server_->SetAltHandshakeTypeEnabled();
|
||||
}
|
||||
|
||||
void InstallFilters() {
|
||||
client_->SetPacketFilter(client_ccs_recorder_);
|
||||
auto chain = std::make_shared<ChainedPacketFilter>(ChainedPacketFilterInit(
|
||||
{server_handshake_recorder_, server_ccs_recorder_,
|
||||
server_hello_recorder_}));
|
||||
server_->SetPacketFilter(chain);
|
||||
}
|
||||
|
||||
void CheckServerHelloRecordVersion(uint16_t record_version) {
|
||||
ASSERT_EQ(record_version,
|
||||
server_handshake_recorder_->record(0).header.version());
|
||||
}
|
||||
|
||||
void CheckServerHelloVersion(uint16_t server_hello_version) {
|
||||
uint32_t ver;
|
||||
ASSERT_TRUE(server_hello_recorder_->buffer().Read(0, 2, &ver));
|
||||
ASSERT_EQ(server_hello_version, ver);
|
||||
}
|
||||
|
||||
void CheckForRegularHandshake() {
|
||||
EXPECT_EQ(0U, client_ccs_recorder_->count());
|
||||
EXPECT_EQ(0U, server_ccs_recorder_->count());
|
||||
CheckServerHelloVersion(kServerHelloVersionRegular);
|
||||
CheckServerHelloRecordVersion(SSL_LIBRARY_VERSION_TLS_1_0);
|
||||
}
|
||||
|
||||
void CheckForAltHandshake() {
|
||||
EXPECT_EQ(1U, client_ccs_recorder_->count());
|
||||
EXPECT_EQ(1U, server_ccs_recorder_->count());
|
||||
CheckServerHelloVersion(kServerHelloVersionAlt);
|
||||
CheckServerHelloRecordVersion(SSL_LIBRARY_VERSION_TLS_1_2);
|
||||
}
|
||||
|
||||
std::shared_ptr<TlsRecordRecorder> client_ccs_recorder_;
|
||||
std::shared_ptr<TlsRecordRecorder> server_handshake_recorder_;
|
||||
std::shared_ptr<TlsRecordRecorder> server_ccs_recorder_;
|
||||
std::shared_ptr<TlsInspectorRecordHandshakeMessage> server_hello_recorder_;
|
||||
};
|
||||
|
||||
TEST_F(AltHandshakeTest, ClientOnly) {
|
||||
client_->SetAltHandshakeTypeEnabled();
|
||||
InstallFilters();
|
||||
Connect();
|
||||
CheckForRegularHandshake();
|
||||
}
|
||||
|
||||
TEST_F(AltHandshakeTest, ServerOnly) {
|
||||
server_->SetAltHandshakeTypeEnabled();
|
||||
InstallFilters();
|
||||
Connect();
|
||||
CheckForRegularHandshake();
|
||||
}
|
||||
|
||||
TEST_F(AltHandshakeTest, Enabled) {
|
||||
SetAltHandshakeTypeEnabled();
|
||||
InstallFilters();
|
||||
Connect();
|
||||
CheckForAltHandshake();
|
||||
}
|
||||
|
||||
TEST_F(AltHandshakeTest, ZeroRtt) {
|
||||
SetAltHandshakeTypeEnabled();
|
||||
SetupForZeroRtt();
|
||||
SetAltHandshakeTypeEnabled();
|
||||
client_->Set0RttEnabled(true);
|
||||
server_->Set0RttEnabled(true);
|
||||
|
||||
InstallFilters();
|
||||
|
||||
ExpectResumption(RESUME_TICKET);
|
||||
ZeroRttSendReceive(true, true);
|
||||
Handshake();
|
||||
ExpectEarlyDataAccepted(true);
|
||||
CheckConnected();
|
||||
|
||||
CheckForAltHandshake();
|
||||
}
|
||||
|
||||
// Neither client nor server has the extension prior to resumption, so the
|
||||
// client doesn't send a CCS before its 0-RTT data.
|
||||
TEST_F(AltHandshakeTest, DisabledBeforeZeroRtt) {
|
||||
SetupForZeroRtt();
|
||||
SetAltHandshakeTypeEnabled();
|
||||
client_->Set0RttEnabled(true);
|
||||
server_->Set0RttEnabled(true);
|
||||
|
||||
InstallFilters();
|
||||
|
||||
ExpectResumption(RESUME_TICKET);
|
||||
ZeroRttSendReceive(true, true);
|
||||
Handshake();
|
||||
ExpectEarlyDataAccepted(true);
|
||||
CheckConnected();
|
||||
|
||||
EXPECT_EQ(0U, client_ccs_recorder_->count());
|
||||
EXPECT_EQ(1U, server_ccs_recorder_->count());
|
||||
CheckServerHelloVersion(kServerHelloVersionAlt);
|
||||
}
|
||||
|
||||
// Both use the alternative in the initial handshake but only the server enables
|
||||
// it on resumption.
|
||||
TEST_F(AltHandshakeTest, ClientDisabledAfterZeroRtt) {
|
||||
SetAltHandshakeTypeEnabled();
|
||||
SetupForZeroRtt();
|
||||
server_->SetAltHandshakeTypeEnabled();
|
||||
client_->Set0RttEnabled(true);
|
||||
server_->Set0RttEnabled(true);
|
||||
|
||||
InstallFilters();
|
||||
|
||||
ExpectResumption(RESUME_TICKET);
|
||||
ZeroRttSendReceive(true, true);
|
||||
Handshake();
|
||||
ExpectEarlyDataAccepted(true);
|
||||
CheckConnected();
|
||||
|
||||
CheckForRegularHandshake();
|
||||
}
|
||||
|
||||
// If the alternative handshake isn't negotiated after 0-RTT, and the client has
|
||||
// it enabled, it will send a ChangeCipherSpec. The server chokes on it if it
|
||||
// hasn't negotiated the alternative handshake.
|
||||
TEST_F(AltHandshakeTest, ServerDisabledAfterZeroRtt) {
|
||||
SetAltHandshakeTypeEnabled();
|
||||
SetupForZeroRtt();
|
||||
client_->SetAltHandshakeTypeEnabled();
|
||||
client_->Set0RttEnabled(true);
|
||||
server_->Set0RttEnabled(true);
|
||||
|
||||
client_->ExpectSendAlert(kTlsAlertEndOfEarlyData);
|
||||
client_->Handshake(); // Send ClientHello (and CCS)
|
||||
|
||||
server_->Handshake(); // Consume the ClientHello, which is OK.
|
||||
client_->ExpectResumption();
|
||||
client_->Handshake(); // Read the server handshake.
|
||||
EXPECT_EQ(TlsAgent::STATE_CONNECTED, client_->state());
|
||||
|
||||
// Now the server reads the CCS instead of more handshake messages.
|
||||
ExpectAlert(server_, kTlsAlertBadRecordMac);
|
||||
server_->Handshake();
|
||||
EXPECT_EQ(TlsAgent::STATE_ERROR, server_->state());
|
||||
client_->Handshake(); // Consume the alert.
|
||||
EXPECT_EQ(TlsAgent::STATE_ERROR, client_->state());
|
||||
}
|
||||
|
||||
} // nss_test
|
|
@ -159,13 +159,11 @@ TEST_P(TlsConnectTls12, ClientAuthBigRsaCheckSigAlg) {
|
|||
|
||||
class TlsZeroCertificateRequestSigAlgsFilter : public TlsHandshakeFilter {
|
||||
public:
|
||||
TlsZeroCertificateRequestSigAlgsFilter()
|
||||
: TlsHandshakeFilter({kTlsHandshakeCertificateRequest}) {}
|
||||
virtual PacketFilter::Action FilterHandshake(
|
||||
const TlsHandshakeFilter::HandshakeHeader& header,
|
||||
const DataBuffer& input, DataBuffer* output) {
|
||||
if (header.handshake_type() != kTlsHandshakeCertificateRequest) {
|
||||
return KEEP;
|
||||
}
|
||||
|
||||
TlsParser parser(input);
|
||||
std::cerr << "Zeroing CertReq.supported_signature_algorithms" << std::endl;
|
||||
|
||||
|
@ -599,8 +597,7 @@ class EnforceNoActivity : public PacketFilter {
|
|||
TEST_P(TlsConnectGenericPre13, AuthCompleteDelayed) {
|
||||
client_->SetAuthCertificateCallback(AuthCompleteBlock);
|
||||
|
||||
server_->StartConnect();
|
||||
client_->StartConnect();
|
||||
StartConnect();
|
||||
client_->Handshake(); // Send ClientHello
|
||||
server_->Handshake(); // Send ServerHello
|
||||
client_->Handshake(); // Send ClientKeyExchange and Finished
|
||||
|
@ -628,8 +625,7 @@ TEST_P(TlsConnectGenericPre13, AuthCompleteDelayed) {
|
|||
TEST_P(TlsConnectTls13, AuthCompleteDelayed) {
|
||||
client_->SetAuthCertificateCallback(AuthCompleteBlock);
|
||||
|
||||
server_->StartConnect();
|
||||
client_->StartConnect();
|
||||
StartConnect();
|
||||
client_->Handshake(); // Send ClientHello
|
||||
server_->Handshake(); // Send ServerHello
|
||||
EXPECT_EQ(TlsAgent::STATE_CONNECTING, client_->state());
|
||||
|
|
|
@ -31,11 +31,11 @@ class TlsCipherSuiteTestBase : public TlsConnectTestBase {
|
|||
public:
|
||||
TlsCipherSuiteTestBase(SSLProtocolVariant variant, uint16_t version,
|
||||
uint16_t cipher_suite, SSLNamedGroup group,
|
||||
SSLSignatureScheme signature_scheme)
|
||||
SSLSignatureScheme sig_scheme)
|
||||
: TlsConnectTestBase(variant, version),
|
||||
cipher_suite_(cipher_suite),
|
||||
group_(group),
|
||||
signature_scheme_(signature_scheme),
|
||||
sig_scheme_(sig_scheme),
|
||||
csinfo_({0}) {
|
||||
SECStatus rv =
|
||||
SSL_GetCipherSuiteInfo(cipher_suite_, &csinfo_, sizeof(csinfo_));
|
||||
|
@ -60,14 +60,14 @@ class TlsCipherSuiteTestBase : public TlsConnectTestBase {
|
|||
server_->ConfigNamedGroups(groups);
|
||||
kea_type_ = SSLInt_GetKEAType(group_);
|
||||
|
||||
client_->SetSignatureSchemes(&signature_scheme_, 1);
|
||||
server_->SetSignatureSchemes(&signature_scheme_, 1);
|
||||
client_->SetSignatureSchemes(&sig_scheme_, 1);
|
||||
server_->SetSignatureSchemes(&sig_scheme_, 1);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void SetupCertificate() {
|
||||
if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
|
||||
switch (signature_scheme_) {
|
||||
switch (sig_scheme_) {
|
||||
case ssl_sig_rsa_pkcs1_sha256:
|
||||
case ssl_sig_rsa_pkcs1_sha384:
|
||||
case ssl_sig_rsa_pkcs1_sha512:
|
||||
|
@ -93,8 +93,7 @@ class TlsCipherSuiteTestBase : public TlsConnectTestBase {
|
|||
auth_type_ = ssl_auth_ecdsa;
|
||||
break;
|
||||
default:
|
||||
ASSERT_TRUE(false) << "Unsupported signature scheme: "
|
||||
<< signature_scheme_;
|
||||
ADD_FAILURE() << "Unsupported signature scheme: " << sig_scheme_;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
@ -187,7 +186,7 @@ class TlsCipherSuiteTestBase : public TlsConnectTestBase {
|
|||
SSLAuthType auth_type_;
|
||||
SSLKEAType kea_type_;
|
||||
SSLNamedGroup group_;
|
||||
SSLSignatureScheme signature_scheme_;
|
||||
SSLSignatureScheme sig_scheme_;
|
||||
SSLCipherSuiteInfo csinfo_;
|
||||
};
|
||||
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче