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..21184dddf98f8ab59cd092f23b774dec236f06ff 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) { |
+ struct TestCase { |
+ const std::vector<const char*> policies; |
Mike West
2016/11/17 11:25:15
If you move the |listA| definition above this stru
|
+ bool expected; |
+ bool expectedFirstPolicyOpposite; |
Mike West
2016/11/17 11:25:16
This is a strange name. :)
|
+ } 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}, |
+ }; |
+ |
+ Member<CSPDirectiveList> A = createList( |
+ "script-src http://*.one.com; img-src https://one.com " |
+ "http://two.com/imgs/", |
+ ContentSecurityPolicyHeaderTypeReport); |
+ |
+ Member<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, GetSourceList) { |
+ 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::getSourceList(ContentSecurityPolicy::DefaultSrc, |
+ policyVector); |
+ EXPECT_EQ(result.size(), 0u); |
+ result = CSPDirectiveList::getSourceList(ContentSecurityPolicy::ChildSrc, |
+ policyVector); |
+ EXPECT_EQ(result.size(), 3u); |
+ result = CSPDirectiveList::getSourceList(ContentSecurityPolicy::BaseURI, |
+ policyVector); |
+ EXPECT_EQ(result.size(), 1u); |
+ result = CSPDirectiveList::getSourceList(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::getSourceList(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::getSourceList(test.directive, policyVector).size(), |
+ udpatedTotal); |
+ size_t expectedChildSrc = |
+ test.directive == ContentSecurityPolicy::ChildSrc ? 5u : 4u; |
+ EXPECT_EQ(CSPDirectiveList::getSourceList(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::getSourceList(test.directive, policyVector).size(), |
+ udpatedTotal); |
+ expectedChildSrc = expectedChildSrc + 1u; |
+ EXPECT_EQ(CSPDirectiveList::getSourceList(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::getSourceList(test.directive, policyVector).size(), |
+ udpatedTotal); |
+ EXPECT_EQ(CSPDirectiveList::getSourceList(ContentSecurityPolicy::ChildSrc, |
+ policyVector) |
+ .size(), |
+ expectedChildSrc); |
+ } |
+} |
+ |
} // namespace blink |