OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (c) 2013, Google Inc. All rights reserved. | |
3 * | |
4 * Redistribution and use in source and binary forms, with or without | |
5 * modification, are permitted provided that the following conditions are | |
6 * met: | |
7 * | |
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. | |
17 * | |
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. | |
29 */ | |
30 | |
31 #include "config.h" | |
32 #include "core/dom/DocumentMarkerController.h" | |
33 | |
34 #include "bindings/core/v8/ExceptionStatePlaceholder.h" | |
35 #include "core/dom/Document.h" | |
36 #include "core/dom/Range.h" | |
37 #include "core/dom/RenderedDocumentMarker.h" | |
38 #include "core/dom/Text.h" | |
39 #include "core/editing/EphemeralRange.h" | |
40 #include "core/html/HTMLElement.h" | |
41 #include "core/testing/DummyPageHolder.h" | |
42 #include "wtf/PassRefPtr.h" | |
43 #include "wtf/RefPtr.h" | |
44 #include <gtest/gtest.h> | |
45 | |
46 namespace blink { | |
47 | |
48 class DocumentMarkerControllerTest : public ::testing::Test { | |
49 protected: | |
50 void SetUp() override; | |
51 | |
52 Document& document() const { return *m_document; } | |
53 DocumentMarkerController& markerController() const { return m_document->mark
ers(); } | |
54 | |
55 PassRefPtrWillBeRawPtr<Text> createTextNode(const char*); | |
56 void markNodeContents(PassRefPtrWillBeRawPtr<Node>); | |
57 void setBodyInnerHTML(const char*); | |
58 | |
59 private: | |
60 OwnPtr<DummyPageHolder> m_dummyPageHolder; | |
61 RefPtrWillBePersistent<Document> m_document; | |
62 }; | |
63 | |
64 void DocumentMarkerControllerTest::SetUp() | |
65 { | |
66 m_dummyPageHolder = DummyPageHolder::create(IntSize(800, 600)); | |
67 m_document = &m_dummyPageHolder->document(); | |
68 ASSERT(m_document); | |
69 } | |
70 | |
71 PassRefPtrWillBeRawPtr<Text> DocumentMarkerControllerTest::createTextNode(const
char* textContents) | |
72 { | |
73 return document().createTextNode(String::fromUTF8(textContents)); | |
74 } | |
75 | |
76 void DocumentMarkerControllerTest::markNodeContents(PassRefPtrWillBeRawPtr<Node>
node) | |
77 { | |
78 // Force layoutObjects to be created; TextIterator, which is used in | |
79 // DocumentMarkerControllerTest::addMarker(), needs them. | |
80 document().updateLayout(); | |
81 auto range = EphemeralRange::rangeOfContents(*node); | |
82 markerController().addMarker(range.startPosition(), range.endPosition(), Doc
umentMarker::Spelling); | |
83 } | |
84 | |
85 void DocumentMarkerControllerTest::setBodyInnerHTML(const char* bodyContent) | |
86 { | |
87 document().body()->setInnerHTML(String::fromUTF8(bodyContent), ASSERT_NO_EXC
EPTION); | |
88 } | |
89 | |
90 TEST_F(DocumentMarkerControllerTest, DidMoveToNewDocument) | |
91 { | |
92 setBodyInnerHTML("<b><i>foo</i></b>"); | |
93 RefPtrWillBeRawPtr<Element> parent = toElement(document().body()->firstChild
()->firstChild()); | |
94 markNodeContents(parent.get()); | |
95 EXPECT_EQ(1u, markerController().markers().size()); | |
96 RefPtrWillBePersistent<Document> anotherDocument = Document::create(); | |
97 anotherDocument->adoptNode(parent.get(), ASSERT_NO_EXCEPTION); | |
98 | |
99 // No more reference to marked node. | |
100 Heap::collectAllGarbage(); | |
101 EXPECT_EQ(0u, markerController().markers().size()); | |
102 EXPECT_EQ(0u, anotherDocument->markers().markers().size()); | |
103 } | |
104 | |
105 TEST_F(DocumentMarkerControllerTest, NodeWillBeRemovedMarkedByNormalize) | |
106 { | |
107 setBodyInnerHTML("<b><i>foo</i></b>"); | |
108 { | |
109 RefPtrWillBeRawPtr<Element> parent = toElement(document().body()->firstC
hild()->firstChild()); | |
110 parent->appendChild(createTextNode("bar").get()); | |
111 markNodeContents(parent.get()); | |
112 EXPECT_EQ(2u, markerController().markers().size()); | |
113 parent->normalize(); | |
114 } | |
115 // No more reference to marked node. | |
116 Heap::collectAllGarbage(); | |
117 EXPECT_EQ(1u, markerController().markers().size()); | |
118 } | |
119 | |
120 TEST_F(DocumentMarkerControllerTest, NodeWillBeRemovedMarkedByRemoveChildren) | |
121 { | |
122 setBodyInnerHTML("<b><i>foo</i></b>"); | |
123 RefPtrWillBeRawPtr<Element> parent = toElement(document().body()->firstChild
()->firstChild()); | |
124 markNodeContents(parent.get()); | |
125 EXPECT_EQ(1u, markerController().markers().size()); | |
126 parent->removeChildren(); | |
127 // No more reference to marked node. | |
128 Heap::collectAllGarbage(); | |
129 EXPECT_EQ(0u, markerController().markers().size()); | |
130 } | |
131 | |
132 TEST_F(DocumentMarkerControllerTest, NodeWillBeRemovedByRemoveMarked) | |
133 { | |
134 setBodyInnerHTML("<b><i>foo</i></b>"); | |
135 { | |
136 RefPtrWillBeRawPtr<Element> parent = toElement(document().body()->firstC
hild()->firstChild()); | |
137 markNodeContents(parent); | |
138 EXPECT_EQ(1u, markerController().markers().size()); | |
139 parent->removeChild(parent->firstChild()); | |
140 } | |
141 // No more reference to marked node. | |
142 Heap::collectAllGarbage(); | |
143 EXPECT_EQ(0u, markerController().markers().size()); | |
144 } | |
145 | |
146 TEST_F(DocumentMarkerControllerTest, NodeWillBeRemovedMarkedByRemoveAncestor) | |
147 { | |
148 setBodyInnerHTML("<b><i>foo</i></b>"); | |
149 { | |
150 RefPtrWillBeRawPtr<Element> parent = toElement(document().body()->firstC
hild()->firstChild()); | |
151 markNodeContents(parent); | |
152 EXPECT_EQ(1u, markerController().markers().size()); | |
153 parent->parentNode()->parentNode()->removeChild(parent->parentNode()); | |
154 } | |
155 // No more reference to marked node. | |
156 Heap::collectAllGarbage(); | |
157 EXPECT_EQ(0u, markerController().markers().size()); | |
158 } | |
159 | |
160 TEST_F(DocumentMarkerControllerTest, NodeWillBeRemovedMarkedByRemoveParent) | |
161 { | |
162 setBodyInnerHTML("<b><i>foo</i></b>"); | |
163 { | |
164 RefPtrWillBeRawPtr<Element> parent = toElement(document().body()->firstC
hild()->firstChild()); | |
165 markNodeContents(parent); | |
166 EXPECT_EQ(1u, markerController().markers().size()); | |
167 parent->parentNode()->removeChild(parent.get()); | |
168 } | |
169 // No more reference to marked node. | |
170 Heap::collectAllGarbage(); | |
171 EXPECT_EQ(0u, markerController().markers().size()); | |
172 } | |
173 | |
174 TEST_F(DocumentMarkerControllerTest, NodeWillBeRemovedMarkedByReplaceChild) | |
175 { | |
176 setBodyInnerHTML("<b><i>foo</i></b>"); | |
177 { | |
178 RefPtrWillBeRawPtr<Element> parent = toElement(document().body()->firstC
hild()->firstChild()); | |
179 markNodeContents(parent.get()); | |
180 EXPECT_EQ(1u, markerController().markers().size()); | |
181 parent->replaceChild(createTextNode("bar").get(), parent->firstChild()); | |
182 } | |
183 // No more reference to marked node. | |
184 Heap::collectAllGarbage(); | |
185 EXPECT_EQ(0u, markerController().markers().size()); | |
186 } | |
187 | |
188 TEST_F(DocumentMarkerControllerTest, NodeWillBeRemovedBySetInnerHTML) | |
189 { | |
190 setBodyInnerHTML("<b><i>foo</i></b>"); | |
191 { | |
192 RefPtrWillBeRawPtr<Element> parent = toElement(document().body()->firstC
hild()->firstChild()); | |
193 markNodeContents(parent); | |
194 EXPECT_EQ(1u, markerController().markers().size()); | |
195 setBodyInnerHTML(""); | |
196 } | |
197 // No more reference to marked node. | |
198 Heap::collectAllGarbage(); | |
199 EXPECT_EQ(0u, markerController().markers().size()); | |
200 } | |
201 | |
202 TEST_F(DocumentMarkerControllerTest, UpdateRenderedRects) | |
203 { | |
204 LayoutRect invalidRect = RenderedDocumentMarker::create(DocumentMarker(0, 0,
false))->renderedRect(); | |
205 | |
206 setBodyInnerHTML("<div style='margin: 100px'>foo</div>"); | |
207 RefPtrWillBeRawPtr<Element> div = toElement(document().body()->firstChild())
; | |
208 markNodeContents(div); | |
209 Vector<IntRect> renderedRects = markerController().renderedRectsForMarkers(D
ocumentMarker::Spelling); | |
210 EXPECT_EQ(1u, renderedRects.size()); | |
211 EXPECT_NE(invalidRect, renderedRects[0]); | |
212 | |
213 div->setAttribute(HTMLNames::styleAttr, "margin: 200px"); | |
214 document().updateLayout(); | |
215 Vector<IntRect> newRenderedRects = markerController().renderedRectsForMarker
s(DocumentMarker::Spelling); | |
216 EXPECT_EQ(1u, newRenderedRects.size()); | |
217 EXPECT_NE(renderedRects[0], newRenderedRects[0]); | |
218 } | |
219 | |
220 } // namespace blink | |
OLD | NEW |