Chromium Code Reviews| 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 |