Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / core / dom / DocumentTest.cpp
blob6cf14d3437a471a5fa88f45e1dfe78406bee296a
1 /*
2 * Copyright (c) 2014, Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "config.h"
32 #include "core/dom/Document.h"
34 #include "core/dom/DocumentVisibilityObserver.h"
35 #include "core/frame/FrameView.h"
36 #include "core/html/HTMLHeadElement.h"
37 #include "core/html/HTMLLinkElement.h"
38 #include "core/testing/DummyPageHolder.h"
39 #include "platform/heap/Handle.h"
40 #include "platform/weborigin/ReferrerPolicy.h"
41 #include "platform/weborigin/SecurityOrigin.h"
42 #include <gmock/gmock.h>
43 #include <gtest/gtest.h>
45 namespace blink {
47 class DocumentTest : public ::testing::Test {
48 protected:
49 void SetUp() override;
51 #if ENABLE(OILPAN)
52 void TearDown() override
54 Heap::collectAllGarbage();
56 #endif
58 Document& document() const { return m_dummyPageHolder->document(); }
59 Page& page() const { return m_dummyPageHolder->page(); }
61 void setHtmlInnerHTML(const char*);
63 private:
64 OwnPtr<DummyPageHolder> m_dummyPageHolder;
67 void DocumentTest::SetUp()
69 m_dummyPageHolder = DummyPageHolder::create(IntSize(800, 600));
72 void DocumentTest::setHtmlInnerHTML(const char* htmlContent)
74 document().documentElement()->setInnerHTML(String::fromUTF8(htmlContent), ASSERT_NO_EXCEPTION);
75 document().view()->updateAllLifecyclePhases();
78 class MockDocumentVisibilityObserver
79 : public NoBaseWillBeGarbageCollectedFinalized<MockDocumentVisibilityObserver>
80 , public DocumentVisibilityObserver {
81 WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(MockDocumentVisibilityObserver);
82 public:
83 static PassOwnPtrWillBeRawPtr<MockDocumentVisibilityObserver> create(Document& document)
85 return adoptPtrWillBeNoop(new MockDocumentVisibilityObserver(document));
88 DEFINE_INLINE_VIRTUAL_TRACE()
90 DocumentVisibilityObserver::trace(visitor);
93 MOCK_METHOD1(didChangeVisibilityState, void(PageVisibilityState));
95 private:
96 MockDocumentVisibilityObserver(Document& document) : DocumentVisibilityObserver(document) { }
99 TEST_F(DocumentTest, VisibilityOberver)
101 page().setVisibilityState(PageVisibilityStateVisible, true); // initial state
102 OwnPtrWillBeRawPtr<MockDocumentVisibilityObserver> observer1 = MockDocumentVisibilityObserver::create(document());
105 OwnPtrWillBeRawPtr<MockDocumentVisibilityObserver> observer2 = MockDocumentVisibilityObserver::create(document());
106 EXPECT_CALL(*observer1, didChangeVisibilityState(PageVisibilityStateHidden)).Times(0);
107 EXPECT_CALL(*observer1, didChangeVisibilityState(PageVisibilityStateVisible)).Times(0);
108 EXPECT_CALL(*observer2, didChangeVisibilityState(PageVisibilityStateHidden)).Times(0);
109 EXPECT_CALL(*observer2, didChangeVisibilityState(PageVisibilityStateVisible)).Times(0);
110 ::testing::Mock::VerifyAndClearExpectations(observer1.get());
111 ::testing::Mock::VerifyAndClearExpectations(observer2.get());
113 EXPECT_CALL(*observer1, didChangeVisibilityState(PageVisibilityStateHidden)).Times(1);
114 EXPECT_CALL(*observer1, didChangeVisibilityState(PageVisibilityStateVisible)).Times(0);
115 EXPECT_CALL(*observer2, didChangeVisibilityState(PageVisibilityStateHidden)).Times(1);
116 EXPECT_CALL(*observer2, didChangeVisibilityState(PageVisibilityStateVisible)).Times(0);
117 page().setVisibilityState(PageVisibilityStateHidden, false);
118 ::testing::Mock::VerifyAndClearExpectations(observer1.get());
119 ::testing::Mock::VerifyAndClearExpectations(observer2.get());
121 EXPECT_CALL(*observer1, didChangeVisibilityState(PageVisibilityStateHidden)).Times(0);
122 EXPECT_CALL(*observer1, didChangeVisibilityState(PageVisibilityStateVisible)).Times(0);
123 EXPECT_CALL(*observer2, didChangeVisibilityState(PageVisibilityStateHidden)).Times(0);
124 EXPECT_CALL(*observer2, didChangeVisibilityState(PageVisibilityStateVisible)).Times(0);
125 page().setVisibilityState(PageVisibilityStateHidden, false);
126 ::testing::Mock::VerifyAndClearExpectations(observer1.get());
127 ::testing::Mock::VerifyAndClearExpectations(observer2.get());
129 EXPECT_CALL(*observer1, didChangeVisibilityState(PageVisibilityStateHidden)).Times(0);
130 EXPECT_CALL(*observer1, didChangeVisibilityState(PageVisibilityStateVisible)).Times(1);
131 EXPECT_CALL(*observer2, didChangeVisibilityState(PageVisibilityStateHidden)).Times(0);
132 EXPECT_CALL(*observer2, didChangeVisibilityState(PageVisibilityStateVisible)).Times(0);
133 OwnPtr<DummyPageHolder> alternatePage = DummyPageHolder::create(IntSize(800, 600));
134 Document& alternateDocument = alternatePage->document();
135 observer2->setObservedDocument(alternateDocument);
136 page().setVisibilityState(PageVisibilityStateVisible, false);
137 ::testing::Mock::VerifyAndClearExpectations(observer1.get());
138 ::testing::Mock::VerifyAndClearExpectations(observer2.get());
140 EXPECT_CALL(*observer1, didChangeVisibilityState(PageVisibilityStateHidden)).Times(1);
141 EXPECT_CALL(*observer1, didChangeVisibilityState(PageVisibilityStateVisible)).Times(0);
142 EXPECT_CALL(*observer2, didChangeVisibilityState(PageVisibilityStateHidden)).Times(1);
143 EXPECT_CALL(*observer2, didChangeVisibilityState(PageVisibilityStateVisible)).Times(0);
144 observer2->setObservedDocument(document());
145 page().setVisibilityState(PageVisibilityStateHidden, false);
146 ::testing::Mock::VerifyAndClearExpectations(observer1.get());
147 ::testing::Mock::VerifyAndClearExpectations(observer2.get());
150 // observer2 destroyed
151 EXPECT_CALL(*observer1, didChangeVisibilityState(PageVisibilityStateHidden)).Times(0);
152 EXPECT_CALL(*observer1, didChangeVisibilityState(PageVisibilityStateVisible)).Times(1);
153 page().setVisibilityState(PageVisibilityStateVisible, false);
156 // This tests that we properly resize and re-layout pages for printing in the presence of
157 // media queries effecting elements in a subtree layout boundary
158 TEST_F(DocumentTest, PrintRelayout)
160 setHtmlInnerHTML(
161 "<style>"
162 " div {"
163 " width: 100px;"
164 " height: 100px;"
165 " overflow: hidden;"
166 " }"
167 " span {"
168 " width: 50px;"
169 " height: 50px;"
170 " }"
171 " @media screen {"
172 " span {"
173 " width: 20px;"
174 " }"
175 " }"
176 "</style>"
177 "<p><div><span></span></div></p>");
178 FloatSize pageSize(400, 400);
179 float maximumShrinkRatio = 1.6;
181 document().frame()->setPrinting(true, pageSize, pageSize, maximumShrinkRatio);
182 EXPECT_EQ(document().documentElement()->offsetWidth(), 400);
183 document().frame()->setPrinting(false, FloatSize(), FloatSize(), 0);
184 EXPECT_EQ(document().documentElement()->offsetWidth(), 800);
188 // This test checks that Documunt::linkManifest() returns a value conform to the specification.
189 TEST_F(DocumentTest, LinkManifest)
191 // Test the default result.
192 EXPECT_EQ(0, document().linkManifest());
194 // Check that we use the first manifest with <link rel=manifest>
195 RefPtrWillBeRawPtr<HTMLLinkElement> link = HTMLLinkElement::create(document(), false);
196 link->setAttribute(blink::HTMLNames::relAttr, "manifest");
197 link->setAttribute(blink::HTMLNames::hrefAttr, "foo.json");
198 document().head()->appendChild(link);
199 EXPECT_EQ(link, document().linkManifest());
201 RefPtrWillBeRawPtr<HTMLLinkElement> link2 = HTMLLinkElement::create(document(), false);
202 link2->setAttribute(blink::HTMLNames::relAttr, "manifest");
203 link2->setAttribute(blink::HTMLNames::hrefAttr, "bar.json");
204 document().head()->insertBefore(link2, link.get());
205 EXPECT_EQ(link2, document().linkManifest());
206 document().head()->appendChild(link2);
207 EXPECT_EQ(link, document().linkManifest());
209 // Check that crazy URLs are accepted.
210 link->setAttribute(blink::HTMLNames::hrefAttr, "http:foo.json");
211 EXPECT_EQ(link, document().linkManifest());
213 // Check that empty URLs are accepted.
214 link->setAttribute(blink::HTMLNames::hrefAttr, "");
215 EXPECT_EQ(link, document().linkManifest());
217 // Check that URLs from different origins are accepted.
218 link->setAttribute(blink::HTMLNames::hrefAttr, "http://example.org/manifest.json");
219 EXPECT_EQ(link, document().linkManifest());
220 link->setAttribute(blink::HTMLNames::hrefAttr, "http://foo.example.org/manifest.json");
221 EXPECT_EQ(link, document().linkManifest());
222 link->setAttribute(blink::HTMLNames::hrefAttr, "http://foo.bar/manifest.json");
223 EXPECT_EQ(link, document().linkManifest());
225 // More than one token in @rel is accepted.
226 link->setAttribute(blink::HTMLNames::relAttr, "foo bar manifest");
227 EXPECT_EQ(link, document().linkManifest());
229 // Such as spaces around the token.
230 link->setAttribute(blink::HTMLNames::relAttr, " manifest ");
231 EXPECT_EQ(link, document().linkManifest());
233 // Check that rel=manifest actually matters.
234 link->setAttribute(blink::HTMLNames::relAttr, "");
235 EXPECT_EQ(link2, document().linkManifest());
236 link->setAttribute(blink::HTMLNames::relAttr, "manifest");
238 // Check that link outside of the <head> are ignored.
239 document().head()->removeChild(link.get(), ASSERT_NO_EXCEPTION);
240 document().head()->removeChild(link2.get(), ASSERT_NO_EXCEPTION);
241 EXPECT_EQ(0, document().linkManifest());
242 document().body()->appendChild(link);
243 EXPECT_EQ(0, document().linkManifest());
244 document().head()->appendChild(link);
245 document().head()->appendChild(link2);
247 // Check that some attribute values do not have an effect.
248 link->setAttribute(blink::HTMLNames::crossoriginAttr, "use-credentials");
249 EXPECT_EQ(link, document().linkManifest());
250 link->setAttribute(blink::HTMLNames::hreflangAttr, "klingon");
251 EXPECT_EQ(link, document().linkManifest());
252 link->setAttribute(blink::HTMLNames::typeAttr, "image/gif");
253 EXPECT_EQ(link, document().linkManifest());
254 link->setAttribute(blink::HTMLNames::sizesAttr, "16x16");
255 EXPECT_EQ(link, document().linkManifest());
256 link->setAttribute(blink::HTMLNames::mediaAttr, "print");
257 EXPECT_EQ(link, document().linkManifest());
260 TEST_F(DocumentTest, referrerPolicyParsing)
262 EXPECT_EQ(ReferrerPolicyDefault, document().referrerPolicy());
264 struct TestCase {
265 const char* policy;
266 ReferrerPolicy expected;
267 } tests[] = {
268 { "always", ReferrerPolicyAlways },
269 { "default", ReferrerPolicyNoReferrerWhenDowngrade },
270 { "never", ReferrerPolicyNever },
271 { "no-referrer", ReferrerPolicyNever },
272 { "no-referrer-when-downgrade", ReferrerPolicyNoReferrerWhenDowngrade },
273 { "not-a-real-policy", ReferrerPolicyDefault },
274 { "origin", ReferrerPolicyOrigin },
275 { "origin-when-crossorigin", ReferrerPolicyOriginWhenCrossOrigin },
276 { "origin-when-cross-origin", ReferrerPolicyOriginWhenCrossOrigin },
277 { "unsafe-url", ReferrerPolicyAlways },
280 for (auto test : tests) {
281 document().setReferrerPolicy(ReferrerPolicyDefault);
283 document().processReferrerPolicy(test.policy);
284 EXPECT_EQ(test.expected, document().referrerPolicy()) << test.policy;
288 // This tests that we mark Frame Timing requests as dirty correctly when we
289 // update style.
290 TEST_F(DocumentTest, FrameTimingRelayout)
292 setHtmlInnerHTML(
293 "<style>"
294 " #div1 {"
295 " width: 100px;"
296 " height: 100px;"
297 " }"
298 "</style>"
299 "<p><div id='div1'><span>test</span></div></p>");
301 EXPECT_FALSE(document().view()->frameTimingRequestsDirty());
303 // Just calling update should have no effect.
304 document().updateLayoutTreeIfNeeded();
305 EXPECT_FALSE(document().view()->frameTimingRequestsDirty());
307 // Calling update with a style change should flag Frame Timing as dirty.
308 document().setChildNeedsStyleRecalc();
309 document().updateLayoutTreeIfNeeded();
310 EXPECT_TRUE(document().view()->frameTimingRequestsDirty());
313 TEST_F(DocumentTest, OutgoingReferrer)
315 document().setURL(KURL(KURL(), "https://www.example.com/hoge#fuga?piyo"));
316 document().setSecurityOrigin(SecurityOrigin::create(KURL(KURL(), "https://www.example.com/")));
317 EXPECT_EQ("https://www.example.com/hoge", document().outgoingReferrer());
320 TEST_F(DocumentTest, OutgoingReferrerWithUniqueOrigin)
322 document().setURL(KURL(KURL(), "https://www.example.com/hoge#fuga?piyo"));
323 document().setSecurityOrigin(SecurityOrigin::createUnique());
324 EXPECT_EQ(String(), document().outgoingReferrer());
327 TEST_F(DocumentTest, StyleVersion)
329 setHtmlInnerHTML(
330 "<style>"
331 " .a * { color: green }"
332 " .b .c { color: green }"
333 "</style>"
334 "<div id='x'><span class='c'></span></div>");
336 Element* element = document().getElementById("x");
337 EXPECT_TRUE(element);
339 uint64_t previousStyleVersion = document().styleVersion();
340 element->setAttribute(blink::HTMLNames::classAttr, "notfound");
341 EXPECT_EQ(previousStyleVersion, document().styleVersion());
343 document().view()->updateAllLifecyclePhases();
345 previousStyleVersion = document().styleVersion();
346 element->setAttribute(blink::HTMLNames::classAttr, "a");
347 EXPECT_NE(previousStyleVersion, document().styleVersion());
349 document().view()->updateAllLifecyclePhases();
351 previousStyleVersion = document().styleVersion();
352 element->setAttribute(blink::HTMLNames::classAttr, "a b");
353 EXPECT_NE(previousStyleVersion, document().styleVersion());
356 } // namespace blink