summaryrefslogtreecommitdiffstats
path: root/dom
diff options
context:
space:
mode:
Diffstat (limited to 'dom')
-rw-r--r--dom/fetch/InternalHeaders.cpp58
-rw-r--r--dom/fetch/InternalHeaders.h31
-rw-r--r--dom/html/nsTextEditorState.cpp31
-rw-r--r--dom/html/nsTextEditorState.h2
-rw-r--r--dom/security/nsCSPContext.cpp8
-rw-r--r--dom/security/test/csp/file_frame_ancestors_ro.html1
-rw-r--r--dom/security/test/csp/file_frame_ancestors_ro.html^headers^1
-rw-r--r--dom/security/test/csp/mochitest.ini3
-rw-r--r--dom/security/test/csp/test_frame_ancestors_ro.html69
-rw-r--r--dom/tests/mochitest/fetch/test_headers_common.js10
10 files changed, 175 insertions, 39 deletions
diff --git a/dom/fetch/InternalHeaders.cpp b/dom/fetch/InternalHeaders.cpp
index e81863173..11585615e 100644
--- a/dom/fetch/InternalHeaders.cpp
+++ b/dom/fetch/InternalHeaders.cpp
@@ -21,12 +21,14 @@ InternalHeaders::InternalHeaders(const nsTArray<Entry>&& aHeaders,
HeadersGuardEnum aGuard)
: mGuard(aGuard)
, mList(aHeaders)
+ , mListDirty(true)
{
}
InternalHeaders::InternalHeaders(const nsTArray<HeadersEntry>& aHeadersEntryList,
HeadersGuardEnum aGuard)
: mGuard(aGuard)
+ , mListDirty(true)
{
for (const HeadersEntry& headersEntry : aHeadersEntryList) {
mList.AppendElement(Entry(headersEntry.name(), headersEntry.value()));
@@ -56,6 +58,8 @@ InternalHeaders::Append(const nsACString& aName, const nsACString& aValue,
return;
}
+ SetListDirty();
+
mList.AppendElement(Entry(lowerName, aValue));
}
@@ -69,6 +73,8 @@ InternalHeaders::Delete(const nsACString& aName, ErrorResult& aRv)
return;
}
+ SetListDirty();
+
// remove in reverse order to minimize copying
for (int32_t i = mList.Length() - 1; i >= 0; --i) {
if (lowerName == mList[i].mName) {
@@ -155,6 +161,8 @@ InternalHeaders::Set(const nsACString& aName, const nsACString& aValue, ErrorRes
return;
}
+ SetListDirty();
+
int32_t firstIndex = INT32_MAX;
// remove in reverse order to minimize copying
@@ -177,6 +185,7 @@ InternalHeaders::Set(const nsACString& aName, const nsACString& aValue, ErrorRes
void
InternalHeaders::Clear()
{
+ SetListDirty();
mList.Clear();
}
@@ -419,5 +428,54 @@ InternalHeaders::GetUnsafeHeaders(nsTArray<nsCString>& aNames) const
}
}
+void
+InternalHeaders::MaybeSortList()
+{
+ class Comparator {
+ public:
+ bool Equals(const Entry& aA, const Entry& aB) const
+ {
+ return aA.mName == aB.mName;
+ }
+
+ bool LessThan(const Entry& aA, const Entry& aB) const
+ {
+ return aA.mName < aB.mName;
+ }
+ };
+
+ if (!mListDirty) {
+ return;
+ }
+
+ mListDirty = false;
+
+ Comparator comparator;
+
+ mSortedList.Clear();
+ for (const Entry& entry : mList) {
+ bool found = false;
+ for (Entry& sortedEntry : mSortedList) {
+ if (sortedEntry.mName == entry.mName) {
+ sortedEntry.mValue += ", ";
+ sortedEntry.mValue += entry.mValue;
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ mSortedList.InsertElementSorted(entry, comparator);
+ }
+ }
+}
+
+void
+InternalHeaders::SetListDirty()
+{
+ mSortedList.Clear();
+ mListDirty = true;
+}
+
} // namespace dom
} // namespace mozilla
diff --git a/dom/fetch/InternalHeaders.h b/dom/fetch/InternalHeaders.h
index e47066669..9a6d6dae7 100644
--- a/dom/fetch/InternalHeaders.h
+++ b/dom/fetch/InternalHeaders.h
@@ -45,14 +45,23 @@ private:
HeadersGuardEnum mGuard;
nsTArray<Entry> mList;
+ nsTArray<Entry> mSortedList;
+
+ // This boolean is set to true at any writing operation to mList. It's set to
+ // false when mSortedList is regenerated. This happens when the header is
+ // iterated.
+ bool mListDirty;
+
public:
explicit InternalHeaders(HeadersGuardEnum aGuard = HeadersGuardEnum::None)
: mGuard(aGuard)
+ , mListDirty(false)
{
}
explicit InternalHeaders(const InternalHeaders& aOther)
: mGuard(HeadersGuardEnum::None)
+ , mListDirty(true)
{
ErrorResult result;
Fill(aOther, result);
@@ -79,19 +88,22 @@ public:
bool Has(const nsACString& aName, ErrorResult& aRv) const;
void Set(const nsACString& aName, const nsACString& aValue, ErrorResult& aRv);
- uint32_t GetIterableLength() const
+ uint32_t GetIterableLength()
{
- return mList.Length();
+ MaybeSortList();
+ return mSortedList.Length();
}
- const NS_ConvertASCIItoUTF16 GetKeyAtIndex(unsigned aIndex) const
+ const NS_ConvertASCIItoUTF16 GetKeyAtIndex(unsigned aIndex)
{
- MOZ_ASSERT(aIndex < mList.Length());
- return NS_ConvertASCIItoUTF16(mList[aIndex].mName);
+ MaybeSortList();
+ MOZ_ASSERT(aIndex < mSortedList.Length());
+ return NS_ConvertASCIItoUTF16(mSortedList[aIndex].mName);
}
- const NS_ConvertASCIItoUTF16 GetValueAtIndex(unsigned aIndex) const
+ const NS_ConvertASCIItoUTF16 GetValueAtIndex(unsigned aIndex)
{
- MOZ_ASSERT(aIndex < mList.Length());
- return NS_ConvertASCIItoUTF16(mList[aIndex].mValue);
+ MaybeSortList();
+ MOZ_ASSERT(aIndex < mSortedList.Length());
+ return NS_ConvertASCIItoUTF16(mSortedList[aIndex].mValue);
}
void Clear();
@@ -152,6 +164,9 @@ private:
const nsACString& aValue);
static bool IsRevalidationHeader(const nsACString& aName);
+
+ void MaybeSortList();
+ void SetListDirty();
};
} // namespace dom
diff --git a/dom/html/nsTextEditorState.cpp b/dom/html/nsTextEditorState.cpp
index d70199362..187afb66d 100644
--- a/dom/html/nsTextEditorState.cpp
+++ b/dom/html/nsTextEditorState.cpp
@@ -1418,19 +1418,16 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue)
}
}
- if (shouldInitializeEditor) {
- // Initialize the plaintext editor
- nsCOMPtr<nsIPlaintextEditor> textEditor(do_QueryInterface(newEditor));
- if (textEditor) {
+ // Initialize the plaintext editor
+ nsCOMPtr<nsIPlaintextEditor> textEditor = do_QueryInterface(newEditor);
+ if (textEditor) {
+ if (shouldInitializeEditor) {
// Set up wrapping
textEditor->SetWrapColumn(GetWrapCols());
-
- // Set max text field length
- int32_t maxLength;
- if (GetMaxLength(&maxLength)) {
- textEditor->SetMaxTextLength(maxLength);
- }
}
+
+ // Set max text field length
+ textEditor->SetMaxTextLength(GetMaxLength());
}
nsCOMPtr<nsIContent> content = do_QueryInterface(mTextCtrlElement);
@@ -1895,22 +1892,22 @@ be called if @placeholder is the empty string when trimmed from line breaks");
return NS_OK;
}
-bool
-nsTextEditorState::GetMaxLength(int32_t* aMaxLength)
+int32_t
+nsTextEditorState::GetMaxLength()
{
nsCOMPtr<nsIContent> content = do_QueryInterface(mTextCtrlElement);
nsGenericHTMLElement* element =
nsGenericHTMLElement::FromContentOrNull(content);
- NS_ENSURE_TRUE(element, false);
+ if (NS_WARN_IF(!element)) {
+ return -1;
+ }
const nsAttrValue* attr = element->GetParsedAttr(nsGkAtoms::maxlength);
if (attr && attr->Type() == nsAttrValue::eInteger) {
- *aMaxLength = attr->GetIntegerValue();
-
- return true;
+ return attr->GetIntegerValue();
}
- return false;
+ return -1;
}
void
diff --git a/dom/html/nsTextEditorState.h b/dom/html/nsTextEditorState.h
index 11494f155..caf5e8eed 100644
--- a/dom/html/nsTextEditorState.h
+++ b/dom/html/nsTextEditorState.h
@@ -203,7 +203,7 @@ public:
* @param aMaxLength the value of the max length attr
* @returns false if attr not defined
*/
- bool GetMaxLength(int32_t* aMaxLength);
+ int32_t GetMaxLength();
void ClearValueCache() { mCachedValue.Truncate(); }
diff --git a/dom/security/nsCSPContext.cpp b/dom/security/nsCSPContext.cpp
index 5e435d4ca..a7517f65e 100644
--- a/dom/security/nsCSPContext.cpp
+++ b/dom/security/nsCSPContext.cpp
@@ -219,14 +219,6 @@ nsCSPContext::permitsInternal(CSPDirective aDir,
nsAutoString violatedDirective;
for (uint32_t p = 0; p < mPolicies.Length(); p++) {
-
- // According to the W3C CSP spec, frame-ancestors checks are ignored for
- // report-only policies (when "monitoring").
- if (aDir == nsIContentSecurityPolicy::FRAME_ANCESTORS_DIRECTIVE &&
- mPolicies[p]->getReportOnlyFlag()) {
- continue;
- }
-
if (!mPolicies[p]->permits(aDir,
aContentLocation,
aNonce,
diff --git a/dom/security/test/csp/file_frame_ancestors_ro.html b/dom/security/test/csp/file_frame_ancestors_ro.html
new file mode 100644
index 000000000..ff5ae9cf9
--- /dev/null
+++ b/dom/security/test/csp/file_frame_ancestors_ro.html
@@ -0,0 +1 @@
+<html><body>Child Document</body></html>
diff --git a/dom/security/test/csp/file_frame_ancestors_ro.html^headers^ b/dom/security/test/csp/file_frame_ancestors_ro.html^headers^
new file mode 100644
index 000000000..d018af3a9
--- /dev/null
+++ b/dom/security/test/csp/file_frame_ancestors_ro.html^headers^
@@ -0,0 +1 @@
+Content-Security-Policy-Report-Only: frame-ancestors 'none'; report-uri http://mochi.test:8888/foo.sjs
diff --git a/dom/security/test/csp/mochitest.ini b/dom/security/test/csp/mochitest.ini
index ca5c2c6ea..33b112020 100644
--- a/dom/security/test/csp/mochitest.ini
+++ b/dom/security/test/csp/mochitest.ini
@@ -91,6 +91,8 @@ support-files =
file_bug941404.html
file_bug941404_xhr.html
file_bug941404_xhr.html^headers^
+ file_frame_ancestors_ro.html
+ file_frame_ancestors_ro.html^headers^
file_hash_source.html
file_dual_header_testserver.sjs
file_hash_source.html^headers^
@@ -240,6 +242,7 @@ skip-if = toolkit == 'android' # Times out, not sure why (bug 1008445)
[test_bug910139.html]
[test_bug909029.html]
[test_bug1229639.html]
+[test_frame_ancestors_ro.html]
[test_policyuri_regression_from_multipolicy.html]
[test_nonce_source.html]
[test_bug941404.html]
diff --git a/dom/security/test/csp/test_frame_ancestors_ro.html b/dom/security/test/csp/test_frame_ancestors_ro.html
new file mode 100644
index 000000000..90f68e25e
--- /dev/null
+++ b/dom/security/test/csp/test_frame_ancestors_ro.html
@@ -0,0 +1,69 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for frame-ancestors support in Content-Security-Policy-Report-Only</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<iframe style="width: 100%" id="cspframe"></iframe>
+<script type="text/javascript">
+const docUri = "http://mochi.test:8888/tests/dom/security/test/csp/file_frame_ancestors_ro.html";
+const frame = document.getElementById("cspframe");
+
+let testResults = {
+ reportFired: false,
+ frameLoaded: false
+};
+
+function checkResults(reportObj) {
+ let cspReport = reportObj["csp-report"];
+ is(cspReport["document-uri"], docUri, "Incorrect document-uri");
+
+ // we can not test for the whole referrer since it includes platform specific information
+ is(cspReport["referrer"], document.location.toString(), "Incorrect referrer");
+ is(cspReport["blocked-uri"], document.location.toString(), "Incorrect blocked-uri");
+ is(cspReport["violated-directive"], "frame-ancestors 'none'", "Incorrect violated-directive");
+ is(cspReport["original-policy"], "frame-ancestors 'none'; report-uri http://mochi.test:8888/foo.sjs", "Incorrect original-policy");
+ testResults.reportFired = true;
+}
+
+let chromeScriptUrl = SimpleTest.getTestFileURL("file_report_chromescript.js");
+let script = SpecialPowers.loadChromeScript(chromeScriptUrl);
+
+script.addMessageListener('opening-request-completed', function ml(msg) {
+ if (msg.error) {
+ ok(false, "Could not query report (exception: " + msg.error + ")");
+ } else {
+ try {
+ let reportObj = JSON.parse(msg.report);
+ // test for the proper values in the report object
+ checkResults(reportObj);
+ } catch (e) {
+ ok(false, "Error verifying report object (exception: " + e + ")");
+ }
+ }
+
+ script.removeMessageListener('opening-request-completed', ml);
+ script.sendAsyncMessage("finish");
+ checkTestResults();
+});
+
+frame.addEventListener( 'load', () => {
+ // Make sure the frame is still loaded
+ testResults.frameLoaded = true;
+ checkTestResults()
+} );
+
+function checkTestResults() {
+ if( testResults.reportFired && testResults.frameLoaded ) {
+ SimpleTest.finish();
+ }
+}
+
+SimpleTest.waitForExplicitFinish();
+frame.src = docUri;
+
+</script>
+</body>
+</html>
diff --git a/dom/tests/mochitest/fetch/test_headers_common.js b/dom/tests/mochitest/fetch/test_headers_common.js
index fe792b25b..8b17b6b12 100644
--- a/dom/tests/mochitest/fetch/test_headers_common.js
+++ b/dom/tests/mochitest/fetch/test_headers_common.js
@@ -213,12 +213,12 @@ function TestHeadersIterator() {
var value_iter = headers.values();
var entries_iter = headers.entries();
- arrayEquals(iterate(key_iter), ["foo", "foo", "foo2"], "Correct key iterator");
- arrayEquals(iterate(value_iter), ["bar", ehsanInflated, "baz2"], "Correct value iterator");
- arrayEquals(iterate(entries_iter), [["foo", "bar"], ["foo", ehsanInflated], ["foo2", "baz2"]], "Correct entries iterator");
+ arrayEquals(iterate(key_iter), ["foo", "foo2"], "Correct key iterator");
+ arrayEquals(iterate(value_iter), ["bar, " + ehsanInflated, "baz2"], "Correct value iterator");
+ arrayEquals(iterate(entries_iter), [["foo", "bar, " + ehsanInflated], ["foo2", "baz2"]], "Correct entries iterator");
- arrayEquals(iterateForOf(headers), [["foo", "bar"], ["foo", ehsanInflated], ["foo2", "baz2"]], "Correct entries iterator");
- arrayEquals(iterateForOf(new Headers(headers)), [["foo", "bar"], ["foo", ehsanInflated], ["foo2", "baz2"]], "Correct entries iterator");
+ arrayEquals(iterateForOf(headers), [["foo", "bar, " + ehsanInflated], ["foo2", "baz2"]], "Correct entries iterator");
+ arrayEquals(iterateForOf(new Headers(headers)), [["foo", "bar, " + ehsanInflated], ["foo2", "baz2"]], "Correct entries iterator");
}
function runTest() {