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
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
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.
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>
47 class DocumentTest
: public ::testing::Test
{
49 void SetUp() override
;
52 void TearDown() override
54 Heap::collectAllGarbage();
58 Document
& document() const { return m_dummyPageHolder
->document(); }
59 Page
& page() const { return m_dummyPageHolder
->page(); }
61 void setHtmlInnerHTML(const char*);
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
);
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
));
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
)
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());
266 ReferrerPolicy expected
;
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
290 TEST_F(DocumentTest
, FrameTimingRelayout
)
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
)
331 " .a * { color: green }"
332 " .b .c { color: green }"
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());