| Index: third_party/WebKit/Source/core/frame/csp/CSPDirectiveListTest.cpp
|
| diff --git a/third_party/WebKit/Source/core/frame/csp/CSPDirectiveListTest.cpp b/third_party/WebKit/Source/core/frame/csp/CSPDirectiveListTest.cpp
|
| index 2fcde837e88b691ee4073c580e1ce9c8423735d5..4722459b2914b7f781969cddffd86a6c8ff563f3 100644
|
| --- a/third_party/WebKit/Source/core/frame/csp/CSPDirectiveListTest.cpp
|
| +++ b/third_party/WebKit/Source/core/frame/csp/CSPDirectiveListTest.cpp
|
| @@ -435,4 +435,229 @@ TEST_F(CSPDirectiveListTest, workerSrc) {
|
| }
|
| }
|
|
|
| +TEST_F(CSPDirectiveListTest, SubsumesBasedOnCSPSourcesOnly) {
|
| + CSPDirectiveList* A = createList(
|
| + "script-src http://*.one.com; img-src https://one.com "
|
| + "http://two.com/imgs/",
|
| + ContentSecurityPolicyHeaderTypeReport);
|
| +
|
| + struct TestCase {
|
| + const std::vector<const char*> policies;
|
| + bool expected;
|
| + bool expectedFirstPolicyOpposite;
|
| + } cases[] = {
|
| + // `listB`, which is not as restrictive as `A`, is not subsumed.
|
| + {{""}, false, true},
|
| + {{"script-src http://example.com"}, false, false},
|
| + {{"img-src http://example.com"}, false, false},
|
| + {{"script-src http://*.one.com"}, false, true},
|
| + {{"img-src https://one.com http://two.com/imgs/"}, false, true},
|
| + {{"default-src http://example.com"}, false, false},
|
| + {{"default-src https://one.com http://two.com/imgs/"}, false, false},
|
| + {{"default-src http://one.com"}, false, false},
|
| + {{"script-src http://*.one.com; img-src http://two.com/"}, false, false},
|
| + {{"script-src http://*.one.com", "img-src http://one.com"}, false, true},
|
| + {{"script-src http://*.one.com", "script-src https://two.com"},
|
| + false,
|
| + true},
|
| + {{"script-src http://*.random.com", "script-src https://random.com"},
|
| + false,
|
| + false},
|
| + {{"script-src http://one.com", "script-src https://random.com"},
|
| + false,
|
| + false},
|
| + {{"script-src http://*.random.com; default-src http://one.com "
|
| + "http://two.com/imgs/",
|
| + "default-src https://random.com"},
|
| + false,
|
| + false},
|
| + // `listB`, which is as restrictive as `A`, is subsumed.
|
| + {{"default-src https://one.com"}, true, false},
|
| + {{"default-src http://random.com",
|
| + "default-src https://non-random.com:*"},
|
| + true,
|
| + false},
|
| + {{"script-src http://*.one.com; img-src https://one.com"}, true, false},
|
| + {{"script-src http://*.one.com; img-src https://one.com "
|
| + "http://two.com/imgs/"},
|
| + true,
|
| + true},
|
| + {{"script-src http://*.one.com",
|
| + "img-src https://one.com http://two.com/imgs/"},
|
| + true,
|
| + true},
|
| + {{"script-src http://*.random.com; default-src https://one.com "
|
| + "http://two.com/imgs/",
|
| + "default-src https://else.com"},
|
| + true,
|
| + false},
|
| + {{"script-src http://*.random.com; default-src https://one.com "
|
| + "http://two.com/imgs/",
|
| + "default-src https://one.com"},
|
| + true,
|
| + false},
|
| + };
|
| +
|
| + CSPDirectiveList* emptyA =
|
| + createList("", ContentSecurityPolicyHeaderTypeReport);
|
| +
|
| + for (const auto& test : cases) {
|
| + HeapVector<Member<CSPDirectiveList>> listB;
|
| + for (const auto& policy : test.policies) {
|
| + listB.append(createList(policy, ContentSecurityPolicyHeaderTypeReport));
|
| + }
|
| +
|
| + EXPECT_EQ(test.expected, A->subsumes(listB));
|
| + // Empty CSPDirective subsumes any list.
|
| + EXPECT_TRUE(emptyA->subsumes(listB));
|
| + // Check if first policy of `listB` subsumes `A`.
|
| + EXPECT_EQ(test.expectedFirstPolicyOpposite,
|
| + listB[0]->subsumes(HeapVector<Member<CSPDirectiveList>>(1, A)));
|
| + }
|
| +}
|
| +
|
| +TEST_F(CSPDirectiveListTest, GetSourceVector) {
|
| + const std::vector<const char*> policies = {
|
| + // Policy 1
|
| + "default-src https://default-src.com",
|
| + // Policy 2
|
| + "child-src http://child-src.com",
|
| + // Policy 3
|
| + "child-src http://child-src.com; default-src https://default-src.com",
|
| + // Policy 4
|
| + "base-uri http://base-uri.com",
|
| + // Policy 5
|
| + "frame-src http://frame-src.com"};
|
| +
|
| + // Check expectations on the initial set-up.
|
| + HeapVector<Member<CSPDirectiveList>> policyVector;
|
| + for (const auto& policy : policies) {
|
| + policyVector.append(
|
| + createList(policy, ContentSecurityPolicyHeaderTypeReport));
|
| + }
|
| + HeapVector<Member<SourceListDirective>> result =
|
| + CSPDirectiveList::getSourceVector(ContentSecurityPolicy::DefaultSrc,
|
| + policyVector);
|
| + EXPECT_EQ(result.size(), 2u);
|
| + result = CSPDirectiveList::getSourceVector(ContentSecurityPolicy::ChildSrc,
|
| + policyVector);
|
| + EXPECT_EQ(result.size(), 3u);
|
| + result = CSPDirectiveList::getSourceVector(ContentSecurityPolicy::BaseURI,
|
| + policyVector);
|
| + EXPECT_EQ(result.size(), 1u);
|
| + result = CSPDirectiveList::getSourceVector(ContentSecurityPolicy::FrameSrc,
|
| + policyVector);
|
| + EXPECT_EQ(result.size(), 4u);
|
| +
|
| + enum DefaultBehaviour { Default, NoDefault, ChildAndDefault };
|
| +
|
| + struct TestCase {
|
| + const char* directive;
|
| + const DefaultBehaviour type;
|
| + size_t expectedTotal;
|
| + int expectedCurrent;
|
| + int expectedDefaultSrc;
|
| + int expectedChildSrc;
|
| + } cases[] = {
|
| + // Directives with default directive.
|
| + {ContentSecurityPolicy::ChildSrc, Default, 4u, 3, 1, 3},
|
| + {ContentSecurityPolicy::ConnectSrc, Default, 3u, 1, 2, 0},
|
| + {ContentSecurityPolicy::FontSrc, Default, 3u, 1, 2, 0},
|
| + {ContentSecurityPolicy::ImgSrc, Default, 3u, 1, 2, 0},
|
| + {ContentSecurityPolicy::ManifestSrc, Default, 3u, 1, 2, 0},
|
| + {ContentSecurityPolicy::MediaSrc, Default, 3u, 1, 2, 0},
|
| + {ContentSecurityPolicy::ObjectSrc, Default, 3u, 1, 2, 0},
|
| + {ContentSecurityPolicy::ScriptSrc, Default, 3u, 1, 2, 0},
|
| + {ContentSecurityPolicy::StyleSrc, Default, 3u, 1, 2, 0},
|
| + // Directives with no default directive.
|
| + {ContentSecurityPolicy::BaseURI, NoDefault, 2u, 2, 0, 0},
|
| + {ContentSecurityPolicy::FrameAncestors, NoDefault, 1u, 1, 0, 0},
|
| + {ContentSecurityPolicy::FormAction, NoDefault, 1u, 1, 0, 0},
|
| + // Directive with multiple default directives.
|
| + {ContentSecurityPolicy::FrameSrc, ChildAndDefault, 5u, 2, 1, 2},
|
| + };
|
| +
|
| + for (const auto& test : cases) {
|
| + // Initial set-up.
|
| + HeapVector<Member<CSPDirectiveList>> policyVector;
|
| + for (const auto& policy : policies) {
|
| + policyVector.append(
|
| + createList(policy, ContentSecurityPolicyHeaderTypeReport));
|
| + }
|
| + // Append current test's policy.
|
| + std::stringstream currentDirective;
|
| + currentDirective << test.directive << " http://" << test.directive
|
| + << ".com;";
|
| + policyVector.append(createList(currentDirective.str().c_str(),
|
| + ContentSecurityPolicyHeaderTypeReport));
|
| +
|
| + HeapVector<Member<SourceListDirective>> result =
|
| + CSPDirectiveList::getSourceVector(test.directive, policyVector);
|
| +
|
| + EXPECT_EQ(result.size(), test.expectedTotal);
|
| +
|
| + int actualCurrent = 0, actualDefault = 0, actualChild = 0;
|
| + for (const auto& srcList : result) {
|
| + HeapVector<Member<CSPSource>> sources = srcList->m_list;
|
| + for (const auto& source : sources) {
|
| + if (source->m_host.startsWith(test.directive))
|
| + actualCurrent += 1;
|
| + else if (source->m_host == "default-src.com")
|
| + actualDefault += 1;
|
| +
|
| + if (source->m_host == "child-src.com")
|
| + actualChild += 1;
|
| + }
|
| + }
|
| +
|
| + EXPECT_EQ(actualDefault, test.expectedDefaultSrc);
|
| + EXPECT_EQ(actualCurrent, test.expectedCurrent);
|
| + EXPECT_EQ(actualChild, test.expectedChildSrc);
|
| +
|
| + // If another default-src is added that should only impact Fetch Directives
|
| + policyVector.append(createList("default-src https://default-src.com;",
|
| + ContentSecurityPolicyHeaderTypeReport));
|
| + size_t udpatedTotal =
|
| + test.type != NoDefault ? test.expectedTotal + 1 : test.expectedTotal;
|
| + EXPECT_EQ(
|
| + CSPDirectiveList::getSourceVector(test.directive, policyVector).size(),
|
| + udpatedTotal);
|
| + size_t expectedChildSrc =
|
| + test.directive == ContentSecurityPolicy::ChildSrc ? 5u : 4u;
|
| + EXPECT_EQ(CSPDirectiveList::getSourceVector(ContentSecurityPolicy::ChildSrc,
|
| + policyVector)
|
| + .size(),
|
| + expectedChildSrc);
|
| +
|
| + // If another child-src is added that should only impact frame-src and
|
| + // child-src
|
| + policyVector.append(createList("child-src http://child-src.com;",
|
| + ContentSecurityPolicyHeaderTypeReport));
|
| + udpatedTotal = test.type == ChildAndDefault ||
|
| + test.directive == ContentSecurityPolicy::ChildSrc
|
| + ? udpatedTotal + 1
|
| + : udpatedTotal;
|
| + EXPECT_EQ(
|
| + CSPDirectiveList::getSourceVector(test.directive, policyVector).size(),
|
| + udpatedTotal);
|
| + expectedChildSrc = expectedChildSrc + 1u;
|
| + EXPECT_EQ(CSPDirectiveList::getSourceVector(ContentSecurityPolicy::ChildSrc,
|
| + policyVector)
|
| + .size(),
|
| + expectedChildSrc);
|
| +
|
| + // If we add sandbox, nothing should change since it is currenly not
|
| + // considered.
|
| + policyVector.append(createList("sandbox http://sandbox.com;",
|
| + ContentSecurityPolicyHeaderTypeReport));
|
| + EXPECT_EQ(
|
| + CSPDirectiveList::getSourceVector(test.directive, policyVector).size(),
|
| + udpatedTotal);
|
| + EXPECT_EQ(CSPDirectiveList::getSourceVector(ContentSecurityPolicy::ChildSrc,
|
| + policyVector)
|
| + .size(),
|
| + expectedChildSrc);
|
| + }
|
| +}
|
| +
|
| } // namespace blink
|
|
|