Commit 5541d74f authored by mkwst@chromium.org's avatar mkwst@chromium.org

Define "opaque" FormData objects.

As defined at [1], opaque FormData objects block JavaScript access to
'get()', 'getAll()', 'has()', and iteration. The data is available
internally for consumption in Fetch, but can't be directly accessed by
JavaScript in a page's context.

[1]: https://w3c.github.io/webappsec/specs/credentialmanagement/#opaque-formdata

BUG=526995

Review URL: https://codereview.chromium.org/1323043002

git-svn-id: svn://svn.chromium.org/blink/trunk@201559 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent da0b52a6
......@@ -3797,6 +3797,7 @@
'frame/csp/CSPSourceListTest.cpp',
'frame/csp/CSPSourceTest.cpp',
'frame/csp/ContentSecurityPolicyTest.cpp',
'html/DOMFormDataTest.cpp',
'html/HTMLDimensionTest.cpp',
'html/HTMLFormControlElementTest.cpp',
'html/HTMLImageElementTest.cpp',
......
......@@ -77,11 +77,13 @@ private:
DOMFormData::DOMFormData(const WTF::TextEncoding& encoding)
: FormDataList(encoding)
, m_opaque(false)
{
}
DOMFormData::DOMFormData(HTMLFormElement* form)
: FormDataList(UTF8Encoding())
, m_opaque(false)
{
if (!form)
return;
......@@ -120,6 +122,8 @@ void DOMFormData::append(ExecutionContext* context, const String& name, Blob* bl
void DOMFormData::get(const String& name, FormDataEntryValue& result)
{
if (m_opaque)
return;
Entry entry = getEntry(name);
if (entry.isString())
result.setUSVString(entry.string());
......@@ -132,6 +136,10 @@ void DOMFormData::get(const String& name, FormDataEntryValue& result)
HeapVector<FormDataEntryValue> DOMFormData::getAll(const String& name)
{
HeapVector<FormDataEntryValue> results;
if (m_opaque)
return results;
HeapVector<FormDataList::Entry> entries = FormDataList::getAll(name);
for (const FormDataList::Entry& entry : entries) {
ASSERT(entry.name() == name);
......@@ -148,6 +156,13 @@ HeapVector<FormDataEntryValue> DOMFormData::getAll(const String& name)
return results;
}
bool DOMFormData::has(const String& name)
{
if (m_opaque)
return false;
return hasEntry(name);
}
void DOMFormData::set(const String& name, const String& value)
{
setData(name, value);
......@@ -160,6 +175,9 @@ void DOMFormData::set(const String& name, Blob* blob, const String& filename)
PairIterable<String, FormDataEntryValue>::IterationSource* DOMFormData::startIteration(ScriptState*, ExceptionState&)
{
if (m_opaque)
return new DOMFormDataIterationSource(new DOMFormData(nullptr));
return new DOMFormDataIterationSource(this);
}
......
......@@ -70,14 +70,18 @@ public:
void append(ExecutionContext*, const String& name, Blob*, const String& filename = String());
void get(const String& name, FormDataEntryValue& result);
HeapVector<FormDataEntryValue> getAll(const String& name);
bool has(const String& name);
void set(const String& name, const String& value);
void set(const String& name, Blob*, const String& filename = String());
void makeOpaque() { m_opaque = true; }
private:
explicit DOMFormData(const WTF::TextEncoding&);
explicit DOMFormData(HTMLFormElement*);
IterationSource* startIteration(ScriptState*, ExceptionState&) override;
bool m_opaque;
};
} // namespace blink
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "config.h"
#include "core/html/DOMFormData.h"
#include "core/html/FormDataList.h"
#include <gtest/gtest.h>
namespace blink {
TEST(DOMFormDataTest, opacityGet)
{
DOMFormData* fd = DOMFormData::create(UTF8Encoding());
fd->append("name1", "value1");
FileOrUSVString result;
fd->get("name1", result);
EXPECT_TRUE(result.isUSVString());
EXPECT_EQ("value1", result.getAsUSVString());
FormDataList::Entry entry = fd->getEntry("name1");
EXPECT_EQ("value1", entry.string());
fd->makeOpaque();
// Web-exposed interface should be opaque.
FileOrUSVString opaqueResult;
fd->get("name1", opaqueResult);
EXPECT_TRUE(opaqueResult.isNull());
// Internal interface should be uneffected.
FormDataList::Entry opaqueEntry = fd->getEntry("name1");
EXPECT_EQ("value1", opaqueEntry.string());
}
TEST(DOMFormDataTest, opacityGetAll)
{
DOMFormData* fd = DOMFormData::create(UTF8Encoding());
fd->append("name1", "value1");
HeapVector<FormDataEntryValue> results = fd->getAll("name1");
EXPECT_EQ(1u, results.size());
EXPECT_TRUE(results[0].isUSVString());
EXPECT_EQ("value1", results[0].getAsUSVString());
EXPECT_EQ(1u, fd->size());
fd->makeOpaque();
// Web-exposed interface should be opaque.
results = fd->getAll("name1");
EXPECT_EQ(0u, results.size());
// Internal interface should be uneffected.
EXPECT_EQ(1u, fd->size());
}
TEST(DOMFormDataTest, opacityHas)
{
DOMFormData* fd = DOMFormData::create(UTF8Encoding());
fd->append("name1", "value1");
EXPECT_TRUE(fd->has("name1"));
EXPECT_TRUE(fd->hasEntry("name1"));
fd->makeOpaque();
// Web-exposed interface should be opaque.
EXPECT_FALSE(fd->has("name1"));
// Internal interface should be uneffected.
EXPECT_TRUE(fd->hasEntry("name1"));
}
} // namespace blink
......@@ -47,7 +47,7 @@ typedef (File or USVString) FormDataEntryValue;
[RuntimeEnabled=FormDataNewMethods, ImplementedAs=deleteEntry] void delete(USVString name);
[RuntimeEnabled=FormDataNewMethods] FormDataEntryValue? get(USVString name);
[RuntimeEnabled=FormDataNewMethods] sequence<FormDataEntryValue> getAll(USVString name);
[RuntimeEnabled=FormDataNewMethods, ImplementedAs=hasEntry] boolean has(USVString name);
[RuntimeEnabled=FormDataNewMethods] boolean has(USVString name);
// TODO(philipj): The value argument should be FormDataEntryValue and there
// should be no optional filename argument.
[RuntimeEnabled=FormDataNewMethods] void set(USVString name, Blob value, optional USVString filename);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment