1 /*
2 * Copyright (C) 2010 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
33 #include "public/web/WebFrame.h"
34
35 #include "SkBitmap.h"
36 #include "SkCanvas.h"
37 #include "core/UserAgentStyleSheets.h"
38 #include "core/clipboard/Clipboard.h"
39 #include "core/css/StyleSheetContents.h"
40 #include "core/css/resolver/ViewportStyleResolver.h"
41 #include "core/dom/DocumentMarkerController.h"
42 #include "core/dom/FullscreenElementStack.h"
43 #include "core/dom/Range.h"
44 #include "core/editing/Editor.h"
45 #include "core/editing/FrameSelection.h"
46 #include "core/editing/SpellChecker.h"
47 #include "core/editing/VisiblePosition.h"
48 #include "core/events/MouseEvent.h"
49 #include "core/frame/FrameView.h"
50 #include "core/frame/LocalFrame.h"
51 #include "core/frame/Settings.h"
52 #include "core/html/HTMLFormElement.h"
53 #include "core/loader/FrameLoadRequest.h"
54 #include "core/page/EventHandler.h"
55 #include "core/rendering/HitTestResult.h"
56 #include "core/rendering/RenderView.h"
57 #include "core/rendering/TextAutosizer.h"
58 #include "core/rendering/compositing/RenderLayerCompositor.h"
59 #include "platform/DragImage.h"
60 #include "platform/RuntimeEnabledFeatures.h"
61 #include "platform/UserGestureIndicator.h"
62 #include "platform/geometry/FloatRect.h"
63 #include "platform/network/ResourceError.h"
64 #include "platform/scroll/ScrollbarTheme.h"
65 #include "public/platform/Platform.h"
66 #include "public/platform/WebFloatRect.h"
67 #include "public/platform/WebThread.h"
68 #include "public/platform/WebURL.h"
69 #include "public/platform/WebURLResponse.h"
70 #include "public/platform/WebUnitTestSupport.h"
71 #include "public/web/WebDataSource.h"
72 #include "public/web/WebDocument.h"
73 #include "public/web/WebFindOptions.h"
74 #include "public/web/WebFormElement.h"
75 #include "public/web/WebFrameClient.h"
76 #include "public/web/WebHistoryItem.h"
77 #include "public/web/WebRange.h"
78 #include "public/web/WebScriptSource.h"
79 #include "public/web/WebSearchableFormData.h"
80 #include "public/web/WebSecurityOrigin.h"
81 #include "public/web/WebSecurityPolicy.h"
82 #include "public/web/WebSettings.h"
83 #include "public/web/WebSpellCheckClient.h"
84 #include "public/web/WebTextCheckingCompletion.h"
85 #include "public/web/WebTextCheckingResult.h"
86 #include "public/web/WebViewClient.h"
87 #include "web/WebLocalFrameImpl.h"
88 #include "web/WebViewImpl.h"
89 #include "web/tests/FrameTestHelpers.h"
90 #include "web/tests/URLTestHelpers.h"
91 #include "wtf/Forward.h"
92 #include "wtf/dtoa/utils.h"
93 #include <gmock/gmock.h>
94 #include <gtest/gtest.h>
95 #include <map>
96 #include <v8.h>
97
98 using namespace blink;
99 using WebCore::Document;
100 using WebCore::DocumentMarker;
101 using WebCore::Element;
102 using WebCore::FloatRect;
103 using WebCore::HitTestRequest;
104 using WebCore::Range;
105 using blink::URLTestHelpers::toKURL;
106 using blink::FrameTestHelpers::runPendingTasks;
107
108 namespace {
109
110 const int touchPointPadding = 32;
111
112 #define EXPECT_EQ_RECT(a, b) \
113 EXPECT_EQ(a.x(), b.x()); \
114 EXPECT_EQ(a.y(), b.y()); \
115 EXPECT_EQ(a.width(), b.width()); \
116 EXPECT_EQ(a.height(), b.height());
117
118 class FakeCompositingWebViewClient : public FrameTestHelpers::TestWebViewClient {
119 public:
enterFullScreen()120 virtual bool enterFullScreen() OVERRIDE { return true; }
121 };
122
123 class WebFrameTest : public testing::Test {
124 protected:
WebFrameTest()125 WebFrameTest()
126 : m_baseURL("http://www.test.com/")
127 , m_chromeURL("chrome://")
128 {
129 }
130
~WebFrameTest()131 virtual ~WebFrameTest()
132 {
133 Platform::current()->unitTestSupport()->unregisterAllMockedURLs();
134 }
135
registerMockedHttpURLLoad(const std::string & fileName)136 void registerMockedHttpURLLoad(const std::string& fileName)
137 {
138 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8(fileName.c_str()));
139 }
140
registerMockedChromeURLLoad(const std::string & fileName)141 void registerMockedChromeURLLoad(const std::string& fileName)
142 {
143 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_chromeURL.c_str()), WebString::fromUTF8(fileName.c_str()));
144 }
145
applyViewportStyleOverride(FrameTestHelpers::WebViewHelper * webViewHelper)146 void applyViewportStyleOverride(FrameTestHelpers::WebViewHelper* webViewHelper)
147 {
148 RefPtrWillBeRawPtr<WebCore::StyleSheetContents> styleSheet = WebCore::StyleSheetContents::create(WebCore::CSSParserContext(WebCore::UASheetMode, 0));
149 styleSheet->parseString(String(WebCore::viewportAndroidUserAgentStyleSheet, sizeof(WebCore::viewportAndroidUserAgentStyleSheet)));
150 OwnPtrWillBeRawPtr<WebCore::RuleSet> ruleSet = WebCore::RuleSet::create();
151 ruleSet->addRulesFromSheet(styleSheet.get(), WebCore::MediaQueryEvaluator("screen"));
152
153 Document* document = toLocalFrame(webViewHelper->webViewImpl()->page()->mainFrame())->document();
154 document->ensureStyleResolver().viewportStyleResolver()->collectViewportRules(ruleSet.get(), WebCore::ViewportStyleResolver::UserAgentOrigin);
155 document->ensureStyleResolver().viewportStyleResolver()->resolve();
156 }
157
configueCompositingWebView(WebSettings * settings)158 static void configueCompositingWebView(WebSettings* settings)
159 {
160 settings->setAcceleratedCompositingEnabled(true);
161 settings->setAcceleratedCompositingForFixedPositionEnabled(true);
162 settings->setAcceleratedCompositingForOverflowScrollEnabled(true);
163 settings->setCompositedScrollingForFramesEnabled(true);
164 }
165
initializeTextSelectionWebView(const std::string & url,FrameTestHelpers::WebViewHelper * webViewHelper)166 void initializeTextSelectionWebView(const std::string& url, FrameTestHelpers::WebViewHelper* webViewHelper)
167 {
168 webViewHelper->initializeAndLoad(url, true);
169 webViewHelper->webView()->settings()->setDefaultFontSize(12);
170 webViewHelper->webView()->resize(WebSize(640, 480));
171 }
172
nodeImageTestSetup(FrameTestHelpers::WebViewHelper * webViewHelper,const std::string & testcase)173 PassOwnPtr<WebCore::DragImage> nodeImageTestSetup(FrameTestHelpers::WebViewHelper* webViewHelper, const std::string& testcase)
174 {
175 registerMockedHttpURLLoad("nodeimage.html");
176 webViewHelper->initializeAndLoad(m_baseURL + "nodeimage.html");
177 webViewHelper->webView()->resize(WebSize(640, 480));
178 webViewHelper->webView()->layout();
179 RefPtr<WebCore::LocalFrame> frame = toLocalFrame(webViewHelper->webViewImpl()->page()->mainFrame());
180 WebCore::Element* element = frame->document()->getElementById(testcase.c_str());
181 return frame->nodeImage(*element);
182 }
183
184 std::string m_baseURL;
185 std::string m_chromeURL;
186 };
187
188 class UseMockScrollbarSettings {
189 public:
UseMockScrollbarSettings()190 UseMockScrollbarSettings()
191 {
192 WebCore::Settings::setMockScrollbarsEnabled(true);
193 WebCore::RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(true);
194 EXPECT_TRUE(WebCore::ScrollbarTheme::theme()->usesOverlayScrollbars());
195 }
196
~UseMockScrollbarSettings()197 ~UseMockScrollbarSettings()
198 {
199 WebCore::Settings::setMockScrollbarsEnabled(false);
200 WebCore::RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(false);
201 }
202 };
203
TEST_F(WebFrameTest,ContentText)204 TEST_F(WebFrameTest, ContentText)
205 {
206 registerMockedHttpURLLoad("iframes_test.html");
207 registerMockedHttpURLLoad("visible_iframe.html");
208 registerMockedHttpURLLoad("invisible_iframe.html");
209 registerMockedHttpURLLoad("zero_sized_iframe.html");
210
211 FrameTestHelpers::WebViewHelper webViewHelper;
212 webViewHelper.initializeAndLoad(m_baseURL + "iframes_test.html");
213
214 // Now retrieve the frames text and test it only includes visible elements.
215 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
216 EXPECT_NE(std::string::npos, content.find(" visible paragraph"));
217 EXPECT_NE(std::string::npos, content.find(" visible iframe"));
218 EXPECT_EQ(std::string::npos, content.find(" invisible pararaph"));
219 EXPECT_EQ(std::string::npos, content.find(" invisible iframe"));
220 EXPECT_EQ(std::string::npos, content.find("iframe with zero size"));
221 }
222
TEST_F(WebFrameTest,FrameForEnteredContext)223 TEST_F(WebFrameTest, FrameForEnteredContext)
224 {
225 registerMockedHttpURLLoad("iframes_test.html");
226 registerMockedHttpURLLoad("visible_iframe.html");
227 registerMockedHttpURLLoad("invisible_iframe.html");
228 registerMockedHttpURLLoad("zero_sized_iframe.html");
229
230 FrameTestHelpers::WebViewHelper webViewHelper;
231 webViewHelper.initializeAndLoad(m_baseURL + "iframes_test.html", true);
232
233 v8::HandleScope scope(v8::Isolate::GetCurrent());
234 EXPECT_EQ(webViewHelper.webView()->mainFrame(), WebLocalFrame::frameForContext(webViewHelper.webView()->mainFrame()->mainWorldScriptContext()));
235 EXPECT_EQ(webViewHelper.webView()->mainFrame()->firstChild(), WebLocalFrame::frameForContext(webViewHelper.webView()->mainFrame()->firstChild()->mainWorldScriptContext()));
236 }
237
TEST_F(WebFrameTest,FormWithNullFrame)238 TEST_F(WebFrameTest, FormWithNullFrame)
239 {
240 registerMockedHttpURLLoad("form.html");
241
242 FrameTestHelpers::WebViewHelper webViewHelper;
243 webViewHelper.initializeAndLoad(m_baseURL + "form.html");
244
245 WebVector<WebFormElement> forms;
246 webViewHelper.webView()->mainFrame()->document().forms(forms);
247 webViewHelper.reset();
248
249 EXPECT_EQ(forms.size(), 1U);
250
251 // This test passes if this doesn't crash.
252 WebSearchableFormData searchableDataForm(forms[0]);
253 }
254
TEST_F(WebFrameTest,ChromePageJavascript)255 TEST_F(WebFrameTest, ChromePageJavascript)
256 {
257 registerMockedChromeURLLoad("history.html");
258
259 // Pass true to enable JavaScript.
260 FrameTestHelpers::WebViewHelper webViewHelper;
261 webViewHelper.initializeAndLoad(m_chromeURL + "history.html", true);
262
263 // Try to run JS against the chrome-style URL.
264 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.appendChild(document.createTextNode('Clobbered'))");
265
266 // Required to see any updates in contentAsText.
267 webViewHelper.webView()->layout();
268
269 // Now retrieve the frame's text and ensure it was modified by running javascript.
270 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
271 EXPECT_NE(std::string::npos, content.find("Clobbered"));
272 }
273
TEST_F(WebFrameTest,ChromePageNoJavascript)274 TEST_F(WebFrameTest, ChromePageNoJavascript)
275 {
276 registerMockedChromeURLLoad("history.html");
277
278 /// Pass true to enable JavaScript.
279 FrameTestHelpers::WebViewHelper webViewHelper;
280 webViewHelper.initializeAndLoad(m_chromeURL + "history.html", true);
281
282 // Try to run JS against the chrome-style URL after prohibiting it.
283 WebSecurityPolicy::registerURLSchemeAsNotAllowingJavascriptURLs("chrome");
284 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.appendChild(document.createTextNode('Clobbered'))");
285
286 // Required to see any updates in contentAsText.
287 webViewHelper.webView()->layout();
288
289 // Now retrieve the frame's text and ensure it wasn't modified by running javascript.
290 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
291 EXPECT_EQ(std::string::npos, content.find("Clobbered"));
292 }
293
TEST_F(WebFrameTest,LocationSetHostWithMissingPort)294 TEST_F(WebFrameTest, LocationSetHostWithMissingPort)
295 {
296 std::string fileName = "print-location-href.html";
297 registerMockedHttpURLLoad(fileName);
298 URLTestHelpers::registerMockedURLLoad(toKURL("http://www.test.com:0/" + fileName), WebString::fromUTF8(fileName));
299
300 FrameTestHelpers::WebViewHelper webViewHelper;
301
302 /// Pass true to enable JavaScript.
303 webViewHelper.initializeAndLoad(m_baseURL + fileName, true);
304
305 // Setting host to "hostname:" should be treated as "hostname:0".
306 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:location.host = 'www.test.com:'; void 0;");
307
308 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.textContent = location.href; void 0;");
309
310 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
311 EXPECT_EQ("http://www.test.com:0/" + fileName, content);
312 }
313
TEST_F(WebFrameTest,LocationSetEmptyPort)314 TEST_F(WebFrameTest, LocationSetEmptyPort)
315 {
316 std::string fileName = "print-location-href.html";
317 registerMockedHttpURLLoad(fileName);
318 URLTestHelpers::registerMockedURLLoad(toKURL("http://www.test.com:0/" + fileName), WebString::fromUTF8(fileName));
319
320 FrameTestHelpers::WebViewHelper webViewHelper;
321
322 /// Pass true to enable JavaScript.
323 webViewHelper.initializeAndLoad(m_baseURL + fileName, true);
324
325 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:location.port = ''; void 0;");
326
327 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.textContent = location.href; void 0;");
328
329 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
330 EXPECT_EQ("http://www.test.com:0/" + fileName, content);
331 }
332
333 class CSSCallbackWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
334 public:
CSSCallbackWebFrameClient()335 CSSCallbackWebFrameClient() : m_updateCount(0) { }
336 virtual void didMatchCSS(WebLocalFrame*, const WebVector<WebString>& newlyMatchingSelectors, const WebVector<WebString>& stoppedMatchingSelectors) OVERRIDE;
337
338 std::map<WebLocalFrame*, std::set<std::string> > m_matchedSelectors;
339 int m_updateCount;
340 };
341
didMatchCSS(WebLocalFrame * frame,const WebVector<WebString> & newlyMatchingSelectors,const WebVector<WebString> & stoppedMatchingSelectors)342 void CSSCallbackWebFrameClient::didMatchCSS(WebLocalFrame* frame, const WebVector<WebString>& newlyMatchingSelectors, const WebVector<WebString>& stoppedMatchingSelectors)
343 {
344 ++m_updateCount;
345 std::set<std::string>& frameSelectors = m_matchedSelectors[frame];
346 for (size_t i = 0; i < newlyMatchingSelectors.size(); ++i) {
347 std::string selector = newlyMatchingSelectors[i].utf8();
348 EXPECT_EQ(0U, frameSelectors.count(selector)) << selector;
349 frameSelectors.insert(selector);
350 }
351 for (size_t i = 0; i < stoppedMatchingSelectors.size(); ++i) {
352 std::string selector = stoppedMatchingSelectors[i].utf8();
353 EXPECT_EQ(1U, frameSelectors.count(selector)) << selector;
354 frameSelectors.erase(selector);
355 }
356 }
357
358 class WebFrameCSSCallbackTest : public testing::Test {
359 protected:
WebFrameCSSCallbackTest()360 WebFrameCSSCallbackTest()
361 {
362
363 m_frame = m_helper.initializeAndLoad("about:blank", true, &m_client)->mainFrame()->toWebLocalFrame();
364 }
365
~WebFrameCSSCallbackTest()366 ~WebFrameCSSCallbackTest()
367 {
368 EXPECT_EQ(1U, m_client.m_matchedSelectors.size());
369 }
370
doc() const371 WebDocument doc() const
372 {
373 return m_frame->document();
374 }
375
updateCount() const376 int updateCount() const
377 {
378 return m_client.m_updateCount;
379 }
380
matchedSelectors()381 const std::set<std::string>& matchedSelectors()
382 {
383 return m_client.m_matchedSelectors[m_frame];
384 }
385
loadHTML(const std::string & html)386 void loadHTML(const std::string& html)
387 {
388 FrameTestHelpers::loadHTMLString(m_frame, html, toKURL("about:blank"));
389 }
390
executeScript(const WebString & code)391 void executeScript(const WebString& code)
392 {
393 m_frame->executeScript(WebScriptSource(code));
394 m_frame->view()->layout();
395 runPendingTasks();
396 }
397
398 CSSCallbackWebFrameClient m_client;
399 FrameTestHelpers::WebViewHelper m_helper;
400 WebLocalFrame* m_frame;
401 };
402
TEST_F(WebFrameCSSCallbackTest,AuthorStyleSheet)403 TEST_F(WebFrameCSSCallbackTest, AuthorStyleSheet)
404 {
405 loadHTML(
406 "<style>"
407 // This stylesheet checks that the internal property and value can't be
408 // set by a stylesheet, only WebDocument::watchCSSSelectors().
409 "div.initial_on { -internal-callback: none; }"
410 "div.initial_off { -internal-callback: -internal-presence; }"
411 "</style>"
412 "<div class=\"initial_on\"></div>"
413 "<div class=\"initial_off\"></div>");
414
415 std::vector<WebString> selectors;
416 selectors.push_back(WebString::fromUTF8("div.initial_on"));
417 m_frame->document().watchCSSSelectors(WebVector<WebString>(selectors));
418 m_frame->view()->layout();
419 runPendingTasks();
420 EXPECT_EQ(1, updateCount());
421 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("div.initial_on"));
422
423 // Check that adding a watched selector calls back for already-present nodes.
424 selectors.push_back(WebString::fromUTF8("div.initial_off"));
425 doc().watchCSSSelectors(WebVector<WebString>(selectors));
426 m_frame->view()->layout();
427 runPendingTasks();
428 EXPECT_EQ(2, updateCount());
429 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("div.initial_off", "div.initial_on"));
430
431 // Check that we can turn off callbacks for certain selectors.
432 doc().watchCSSSelectors(WebVector<WebString>());
433 m_frame->view()->layout();
434 runPendingTasks();
435 EXPECT_EQ(3, updateCount());
436 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
437 }
438
TEST_F(WebFrameCSSCallbackTest,SharedRenderStyle)439 TEST_F(WebFrameCSSCallbackTest, SharedRenderStyle)
440 {
441 // Check that adding an element calls back when it matches an existing rule.
442 std::vector<WebString> selectors;
443 selectors.push_back(WebString::fromUTF8("span"));
444 doc().watchCSSSelectors(WebVector<WebString>(selectors));
445
446 executeScript(
447 "i1 = document.createElement('span');"
448 "i1.id = 'first_span';"
449 "document.body.appendChild(i1)");
450 EXPECT_EQ(1, updateCount());
451 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
452
453 // Adding a second element that shares a RenderStyle shouldn't call back.
454 // We use <span>s to avoid default style rules that can set
455 // RenderStyle::unique().
456 executeScript(
457 "i2 = document.createElement('span');"
458 "i2.id = 'second_span';"
459 "i1 = document.getElementById('first_span');"
460 "i1.parentNode.insertBefore(i2, i1.nextSibling);");
461 EXPECT_EQ(1, updateCount());
462 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
463
464 // Removing the first element shouldn't call back.
465 executeScript(
466 "i1 = document.getElementById('first_span');"
467 "i1.parentNode.removeChild(i1);");
468 EXPECT_EQ(1, updateCount());
469 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
470
471 // But removing the second element *should* call back.
472 executeScript(
473 "i2 = document.getElementById('second_span');"
474 "i2.parentNode.removeChild(i2);");
475 EXPECT_EQ(2, updateCount());
476 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
477 }
478
TEST_F(WebFrameCSSCallbackTest,CatchesAttributeChange)479 TEST_F(WebFrameCSSCallbackTest, CatchesAttributeChange)
480 {
481 loadHTML("<span></span>");
482
483 std::vector<WebString> selectors;
484 selectors.push_back(WebString::fromUTF8("span[attr=\"value\"]"));
485 doc().watchCSSSelectors(WebVector<WebString>(selectors));
486 runPendingTasks();
487
488 EXPECT_EQ(0, updateCount());
489 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
490
491 executeScript(
492 "document.querySelector('span').setAttribute('attr', 'value');");
493 EXPECT_EQ(1, updateCount());
494 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span[attr=\"value\"]"));
495 }
496
TEST_F(WebFrameCSSCallbackTest,DisplayNone)497 TEST_F(WebFrameCSSCallbackTest, DisplayNone)
498 {
499 loadHTML("<div style='display:none'><span></span></div>");
500
501 std::vector<WebString> selectors;
502 selectors.push_back(WebString::fromUTF8("span"));
503 doc().watchCSSSelectors(WebVector<WebString>(selectors));
504 runPendingTasks();
505
506 EXPECT_EQ(0, updateCount()) << "Don't match elements in display:none trees.";
507
508 executeScript(
509 "d = document.querySelector('div');"
510 "d.style.display = 'block';");
511 EXPECT_EQ(1, updateCount()) << "Match elements when they become displayed.";
512 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
513
514 executeScript(
515 "d = document.querySelector('div');"
516 "d.style.display = 'none';");
517 EXPECT_EQ(2, updateCount()) << "Unmatch elements when they become undisplayed.";
518 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
519
520 executeScript(
521 "s = document.querySelector('span');"
522 "s.style.display = 'none';");
523 EXPECT_EQ(2, updateCount()) << "No effect from no-display'ing a span that's already undisplayed.";
524
525 executeScript(
526 "d = document.querySelector('div');"
527 "d.style.display = 'block';");
528 EXPECT_EQ(2, updateCount()) << "No effect from displaying a div whose span is display:none.";
529
530 executeScript(
531 "s = document.querySelector('span');"
532 "s.style.display = 'inline';");
533 EXPECT_EQ(3, updateCount()) << "Now the span is visible and produces a callback.";
534 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
535
536 executeScript(
537 "s = document.querySelector('span');"
538 "s.style.display = 'none';");
539 EXPECT_EQ(4, updateCount()) << "Undisplaying the span directly should produce another callback.";
540 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
541 }
542
TEST_F(WebFrameCSSCallbackTest,Reparenting)543 TEST_F(WebFrameCSSCallbackTest, Reparenting)
544 {
545 loadHTML(
546 "<div id='d1'><span></span></div>"
547 "<div id='d2'></div>");
548
549 std::vector<WebString> selectors;
550 selectors.push_back(WebString::fromUTF8("span"));
551 doc().watchCSSSelectors(WebVector<WebString>(selectors));
552 m_frame->view()->layout();
553 runPendingTasks();
554
555 EXPECT_EQ(1, updateCount());
556 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
557
558 executeScript(
559 "s = document.querySelector('span');"
560 "d2 = document.getElementById('d2');"
561 "d2.appendChild(s);");
562 EXPECT_EQ(1, updateCount()) << "Just moving an element that continues to match shouldn't send a spurious callback.";
563 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
564 }
565
TEST_F(WebFrameCSSCallbackTest,MultiSelector)566 TEST_F(WebFrameCSSCallbackTest, MultiSelector)
567 {
568 loadHTML("<span></span>");
569
570 // Check that selector lists match as the whole list, not as each element
571 // independently.
572 std::vector<WebString> selectors;
573 selectors.push_back(WebString::fromUTF8("span"));
574 selectors.push_back(WebString::fromUTF8("span,p"));
575 doc().watchCSSSelectors(WebVector<WebString>(selectors));
576 m_frame->view()->layout();
577 runPendingTasks();
578
579 EXPECT_EQ(1, updateCount());
580 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span", "span, p"));
581 }
582
TEST_F(WebFrameCSSCallbackTest,InvalidSelector)583 TEST_F(WebFrameCSSCallbackTest, InvalidSelector)
584 {
585 loadHTML("<p><span></span></p>");
586
587 // Build a list with one valid selector and one invalid.
588 std::vector<WebString> selectors;
589 selectors.push_back(WebString::fromUTF8("span"));
590 selectors.push_back(WebString::fromUTF8("[")); // Invalid.
591 selectors.push_back(WebString::fromUTF8("p span")); // Not compound.
592 doc().watchCSSSelectors(WebVector<WebString>(selectors));
593 m_frame->view()->layout();
594 runPendingTasks();
595
596 EXPECT_EQ(1, updateCount());
597 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"))
598 << "An invalid selector shouldn't prevent other selectors from matching.";
599 }
600
TEST_F(WebFrameTest,DispatchMessageEventWithOriginCheck)601 TEST_F(WebFrameTest, DispatchMessageEventWithOriginCheck)
602 {
603 registerMockedHttpURLLoad("postmessage_test.html");
604
605 // Pass true to enable JavaScript.
606 FrameTestHelpers::WebViewHelper webViewHelper;
607 webViewHelper.initializeAndLoad(m_baseURL + "postmessage_test.html", true);
608
609 // Send a message with the correct origin.
610 WebSecurityOrigin correctOrigin(WebSecurityOrigin::create(toKURL(m_baseURL)));
611 WebDOMEvent event = webViewHelper.webView()->mainFrame()->document().createEvent("MessageEvent");
612 WebDOMMessageEvent message = event.to<WebDOMMessageEvent>();
613 WebSerializedScriptValue data(WebSerializedScriptValue::fromString("foo"));
614 message.initMessageEvent("message", false, false, data, "http://origin.com", 0, "");
615 webViewHelper.webView()->mainFrame()->dispatchMessageEventWithOriginCheck(correctOrigin, message);
616
617 // Send another message with incorrect origin.
618 WebSecurityOrigin incorrectOrigin(WebSecurityOrigin::create(toKURL(m_chromeURL)));
619 webViewHelper.webView()->mainFrame()->dispatchMessageEventWithOriginCheck(incorrectOrigin, message);
620
621 // Required to see any updates in contentAsText.
622 webViewHelper.webView()->layout();
623
624 // Verify that only the first addition is in the body of the page.
625 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
626 EXPECT_NE(std::string::npos, content.find("Message 1."));
627 EXPECT_EQ(std::string::npos, content.find("Message 2."));
628 }
629
TEST_F(WebFrameTest,PostMessageThenDetach)630 TEST_F(WebFrameTest, PostMessageThenDetach)
631 {
632 FrameTestHelpers::WebViewHelper webViewHelper;
633 webViewHelper.initializeAndLoad("about:blank");
634
635 RefPtr<WebCore::LocalFrame> frame = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame());
636 WebCore::NonThrowableExceptionState exceptionState;
637 frame->domWindow()->postMessage(WebCore::SerializedScriptValue::create("message"), 0, "*", frame->domWindow(), exceptionState);
638 webViewHelper.reset();
639 EXPECT_FALSE(exceptionState.hadException());
640
641 // Success is not crashing.
642 runPendingTasks();
643 }
644
645 class FixedLayoutTestWebViewClient : public FrameTestHelpers::TestWebViewClient {
646 public:
screenInfo()647 virtual WebScreenInfo screenInfo() OVERRIDE { return m_screenInfo; }
648
649 WebScreenInfo m_screenInfo;
650 };
651
652 // Viewport settings need to be set before the page gets loaded
enableViewportSettings(WebSettings * settings)653 static void enableViewportSettings(WebSettings* settings)
654 {
655 settings->setViewportMetaEnabled(true);
656 settings->setViewportEnabled(true);
657 settings->setMainFrameResizesAreOrientationChanges(true);
658 settings->setShrinksViewportContentToFit(true);
659 }
660
TEST_F(WebFrameTest,FrameViewNeedsLayoutOnFixedLayoutResize)661 TEST_F(WebFrameTest, FrameViewNeedsLayoutOnFixedLayoutResize)
662 {
663 UseMockScrollbarSettings mockScrollbarSettings;
664 registerMockedHttpURLLoad("fixed_layout.html");
665
666 FixedLayoutTestWebViewClient client;
667 int viewportWidth = 640;
668 int viewportHeight = 480;
669
670 // Make sure we initialize to minimum scale, even if the window size
671 // only becomes available after the load begins.
672 FrameTestHelpers::WebViewHelper webViewHelper;
673 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
674 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
675 webViewHelper.webView()->layout();
676
677 webViewHelper.webViewImpl()->setFixedLayoutSize(WebCore::IntSize(100, 100));
678 EXPECT_TRUE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
679
680 int prevLayoutCount = webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount();
681 webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->setFrameRect(WebCore::IntRect(0, 0, 641, 481));
682 EXPECT_EQ(prevLayoutCount, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount());
683
684 webViewHelper.webViewImpl()->layout();
685 }
686
687 // Helper function to check or set text autosizing multipliers on a document.
checkOrSetTextAutosizingMultiplier(Document * document,float multiplier,bool setMultiplier)688 static bool checkOrSetTextAutosizingMultiplier(Document* document, float multiplier, bool setMultiplier)
689 {
690 bool multiplierCheckedOrSetAtLeastOnce = false;
691 for (WebCore::RenderObject* renderer = document->renderView(); renderer; renderer = renderer->nextInPreOrder()) {
692 if (renderer->style()) {
693 if (setMultiplier)
694 renderer->style()->setTextAutosizingMultiplier(multiplier);
695 EXPECT_EQ(multiplier, renderer->style()->textAutosizingMultiplier());
696 multiplierCheckedOrSetAtLeastOnce = true;
697 }
698 }
699 return multiplierCheckedOrSetAtLeastOnce;
700
701 }
702
setTextAutosizingMultiplier(Document * document,float multiplier)703 static bool setTextAutosizingMultiplier(Document* document, float multiplier)
704 {
705 return checkOrSetTextAutosizingMultiplier(document, multiplier, true);
706 }
707
checkTextAutosizingMultiplier(Document * document,float multiplier)708 static bool checkTextAutosizingMultiplier(Document* document, float multiplier)
709 {
710 return checkOrSetTextAutosizingMultiplier(document, multiplier, false);
711 }
712
TEST_F(WebFrameTest,ChangeInFixedLayoutResetsTextAutosizingMultipliers)713 TEST_F(WebFrameTest, ChangeInFixedLayoutResetsTextAutosizingMultipliers)
714 {
715 UseMockScrollbarSettings mockScrollbarSettings;
716 registerMockedHttpURLLoad("fixed_layout.html");
717
718 FixedLayoutTestWebViewClient client;
719 int viewportWidth = 640;
720 int viewportHeight = 480;
721
722 FrameTestHelpers::WebViewHelper webViewHelper;
723 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
724
725 WebCore::Document* document = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document();
726 document->settings()->setTextAutosizingEnabled(true);
727 EXPECT_TRUE(document->settings()->textAutosizingEnabled());
728 webViewHelper.webViewImpl()->resize(WebSize(viewportWidth, viewportHeight));
729 webViewHelper.webViewImpl()->layout();
730
731 EXPECT_TRUE(setTextAutosizingMultiplier(document, 2));
732
733 WebCore::ViewportDescription description = document->viewportDescription();
734 // Choose a width that's not going match the viewport width of the loaded document.
735 description.minWidth = WebCore::Length(100, WebCore::Fixed);
736 description.maxWidth = WebCore::Length(100, WebCore::Fixed);
737 webViewHelper.webViewImpl()->updatePageDefinedViewportConstraints(description);
738
739 EXPECT_TRUE(checkTextAutosizingMultiplier(document, 1));
740 }
741
TEST_F(WebFrameTest,SetFrameRectInvalidatesTextAutosizingMultipliers)742 TEST_F(WebFrameTest, SetFrameRectInvalidatesTextAutosizingMultipliers)
743 {
744 UseMockScrollbarSettings mockScrollbarSettings;
745 registerMockedHttpURLLoad("iframe_reload.html");
746 registerMockedHttpURLLoad("visible_iframe.html");
747
748 FixedLayoutTestWebViewClient client;
749 int viewportWidth = 640;
750 int viewportHeight = 480;
751
752 FrameTestHelpers::WebViewHelper webViewHelper;
753 webViewHelper.initializeAndLoad(m_baseURL + "iframe_reload.html", true, 0, &client, enableViewportSettings);
754
755 WebCore::LocalFrame* mainFrame = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame());
756 WebCore::Document* document = mainFrame->document();
757 WebCore::FrameView* frameView = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
758 document->settings()->setTextAutosizingEnabled(true);
759 EXPECT_TRUE(document->settings()->textAutosizingEnabled());
760 webViewHelper.webViewImpl()->resize(WebSize(viewportWidth, viewportHeight));
761 webViewHelper.webViewImpl()->layout();
762
763 for (WebCore::Frame* frame = mainFrame; frame; frame = frame->tree().traverseNext()) {
764 if (!frame->isLocalFrame())
765 continue;
766 EXPECT_TRUE(setTextAutosizingMultiplier(toLocalFrame(frame)->document(), 2));
767 for (WebCore::RenderObject* renderer = toLocalFrame(frame)->document()->renderView(); renderer; renderer = renderer->nextInPreOrder()) {
768 if (renderer->isText())
769 EXPECT_FALSE(renderer->needsLayout());
770 }
771 }
772
773 frameView->setFrameRect(WebCore::IntRect(0, 0, 200, 200));
774 for (WebCore::Frame* frame = mainFrame; frame; frame = frame->tree().traverseNext()) {
775 if (!frame->isLocalFrame())
776 continue;
777 for (WebCore::RenderObject* renderer = toLocalFrame(frame)->document()->renderView(); renderer; renderer = renderer->nextInPreOrder()) {
778 if (renderer->isText())
779 EXPECT_TRUE(renderer->needsLayout());
780 }
781 }
782 }
783
TEST_F(WebFrameTest,FixedLayoutSizeStopsResizeFromChangingLayoutSize)784 TEST_F(WebFrameTest, FixedLayoutSizeStopsResizeFromChangingLayoutSize)
785 {
786 UseMockScrollbarSettings mockScrollbarSettings;
787 registerMockedHttpURLLoad("fixed_layout.html");
788
789 int viewportWidth = 640;
790 int viewportHeight = 480;
791
792 int fixedLayoutWidth = viewportWidth / 2;
793 int fixedLayoutHeight = viewportHeight / 2;
794
795 FrameTestHelpers::WebViewHelper webViewHelper;
796 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, 0, enableViewportSettings);
797 webViewHelper.webView()->setFixedLayoutSize(WebSize(fixedLayoutWidth, fixedLayoutHeight));
798 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
799 webViewHelper.webView()->layout();
800
801 EXPECT_EQ(fixedLayoutWidth, toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->view()->layoutSize().width());
802 EXPECT_EQ(fixedLayoutHeight, toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->view()->layoutSize().height());
803 }
804
TEST_F(WebFrameTest,FixedLayoutSizePreventsResizeFromChangingPageScale)805 TEST_F(WebFrameTest, FixedLayoutSizePreventsResizeFromChangingPageScale)
806 {
807 UseMockScrollbarSettings mockScrollbarSettings;
808 registerMockedHttpURLLoad("fixed_layout.html");
809
810 int viewportWidth = 640;
811 int viewportHeight = 480;
812
813 int fixedLayoutWidth = viewportWidth / 2;
814 int fixedLayoutHeight = viewportHeight / 2;
815
816 FrameTestHelpers::WebViewHelper webViewHelper;
817 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, 0, enableViewportSettings);
818 webViewHelper.webView()->setFixedLayoutSize(WebSize(fixedLayoutWidth, fixedLayoutHeight));
819 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
820 webViewHelper.webView()->layout();
821 float pageScaleFactor = webViewHelper.webView()->pageScaleFactor();
822
823 webViewHelper.webView()->resize(WebSize(viewportWidth * 2, viewportHeight * 2));
824
825 EXPECT_EQ(pageScaleFactor, webViewHelper.webView()->pageScaleFactor());
826 }
827
TEST_F(WebFrameTest,FixedLayoutSizePreventsLayoutFromChangingPageScale)828 TEST_F(WebFrameTest, FixedLayoutSizePreventsLayoutFromChangingPageScale)
829 {
830 UseMockScrollbarSettings mockScrollbarSettings;
831 registerMockedHttpURLLoad("fixed_layout.html");
832
833 int viewportWidth = 640;
834 int viewportHeight = 480;
835
836 int fixedLayoutWidth = viewportWidth * 2;
837 int fixedLayoutHeight = viewportHeight * 2;
838
839 FrameTestHelpers::WebViewHelper webViewHelper;
840 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, 0, enableViewportSettings);
841 webViewHelper.webView()->setFixedLayoutSize(WebSize(viewportWidth, viewportHeight));
842 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
843 webViewHelper.webView()->layout();
844 float pageScaleFactor = webViewHelper.webView()->pageScaleFactor();
845
846 webViewHelper.webView()->setFixedLayoutSize(WebSize(fixedLayoutWidth, fixedLayoutHeight));
847 webViewHelper.webView()->layout();
848
849 EXPECT_EQ(pageScaleFactor, webViewHelper.webView()->pageScaleFactor());
850 }
851
TEST_F(WebFrameTest,PreferredSizeAndContentSizeReportedCorrectlyWithZeroHeightFixedLayout)852 TEST_F(WebFrameTest, PreferredSizeAndContentSizeReportedCorrectlyWithZeroHeightFixedLayout)
853 {
854 UseMockScrollbarSettings mockScrollbarSettings;
855 registerMockedHttpURLLoad("200-by-300.html");
856
857 int windowWidth = 100;
858 int windowHeight = 100;
859 int viewportWidth = 100;
860 int viewportHeight = 0;
861 int divWidth = 200;
862 int divHeight = 300;
863
864 FixedLayoutTestWebViewClient client;
865 client.m_screenInfo.deviceScaleFactor = 1;
866
867 FrameTestHelpers::WebViewHelper webViewHelper;
868 webViewHelper.initializeAndLoad(m_baseURL + "200-by-300.html", true, 0, &client, enableViewportSettings);
869 webViewHelper.webView()->resize(WebSize(windowWidth, windowHeight));
870 webViewHelper.webView()->setFixedLayoutSize(WebSize(viewportWidth, viewportHeight));
871 webViewHelper.webView()->layout();
872
873 EXPECT_EQ(divWidth, webViewHelper.webView()->mainFrame()->contentsSize().width);
874 EXPECT_EQ(divHeight, webViewHelper.webView()->mainFrame()->contentsSize().height);
875
876 EXPECT_EQ(divWidth, webViewHelper.webView()->contentsPreferredMinimumSize().width);
877 EXPECT_EQ(divHeight, webViewHelper.webView()->contentsPreferredMinimumSize().height);
878 }
879
TEST_F(WebFrameTest,DisablingFixedLayoutSizeSetsCorrectLayoutSize)880 TEST_F(WebFrameTest, DisablingFixedLayoutSizeSetsCorrectLayoutSize)
881 {
882 UseMockScrollbarSettings mockScrollbarSettings;
883 registerMockedHttpURLLoad("no_viewport_tag.html");
884
885 FixedLayoutTestWebViewClient client;
886 client.m_screenInfo.deviceScaleFactor = 1;
887 int viewportWidth = 640;
888 int viewportHeight = 480;
889
890 FrameTestHelpers::WebViewHelper webViewHelper;
891 webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client, enableViewportSettings);
892 applyViewportStyleOverride(&webViewHelper);
893 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
894 webViewHelper.webView()->settings()->setUseWideViewport(true);
895 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
896
897 webViewHelper.webView()->setFixedLayoutSize(WebSize(viewportWidth, viewportHeight));
898 EXPECT_TRUE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
899 webViewHelper.webView()->layout();
900 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
901
902 webViewHelper.webView()->setFixedLayoutSize(WebSize(0, 0));
903 EXPECT_TRUE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
904 webViewHelper.webView()->layout();
905 EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
906 }
907
TEST_F(WebFrameTest,ZeroHeightPositiveWidthNotIgnored)908 TEST_F(WebFrameTest, ZeroHeightPositiveWidthNotIgnored)
909 {
910 UseMockScrollbarSettings mockScrollbarSettings;
911
912 FixedLayoutTestWebViewClient client;
913 client.m_screenInfo.deviceScaleFactor = 1;
914 int viewportWidth = 1280;
915 int viewportHeight = 0;
916
917 FrameTestHelpers::WebViewHelper webViewHelper;
918 webViewHelper.initialize(true, 0, &client, enableViewportSettings);
919 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
920
921 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
922 EXPECT_EQ(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
923 }
924
TEST_F(WebFrameTest,DeviceScaleFactorUsesDefaultWithoutViewportTag)925 TEST_F(WebFrameTest, DeviceScaleFactorUsesDefaultWithoutViewportTag)
926 {
927 UseMockScrollbarSettings mockScrollbarSettings;
928 registerMockedHttpURLLoad("no_viewport_tag.html");
929
930 int viewportWidth = 640;
931 int viewportHeight = 480;
932
933 FixedLayoutTestWebViewClient client;
934 client.m_screenInfo.deviceScaleFactor = 2;
935
936 FrameTestHelpers::WebViewHelper webViewHelper;
937 webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client, enableViewportSettings);
938
939 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
940 webViewHelper.webView()->layout();
941
942 EXPECT_EQ(2, webViewHelper.webView()->deviceScaleFactor());
943
944 // Device scale factor should be independent of page scale.
945 webViewHelper.webView()->setPageScaleFactorLimits(1, 2);
946 webViewHelper.webView()->setPageScaleFactor(0.5);
947 webViewHelper.webView()->layout();
948 EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor());
949
950 // Force the layout to happen before leaving the test.
951 webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
952 }
953
TEST_F(WebFrameTest,FixedLayoutInitializeAtMinimumScale)954 TEST_F(WebFrameTest, FixedLayoutInitializeAtMinimumScale)
955 {
956 UseMockScrollbarSettings mockScrollbarSettings;
957
958 registerMockedHttpURLLoad("fixed_layout.html");
959
960 FixedLayoutTestWebViewClient client;
961 client.m_screenInfo.deviceScaleFactor = 1;
962 int viewportWidth = 640;
963 int viewportHeight = 480;
964
965 // Make sure we initialize to minimum scale, even if the window size
966 // only becomes available after the load begins.
967 FrameTestHelpers::WebViewHelper webViewHelper;
968 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
969 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
970
971 int defaultFixedLayoutWidth = 980;
972 float minimumPageScaleFactor = viewportWidth / (float) defaultFixedLayoutWidth;
973 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
974 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->minimumPageScaleFactor());
975
976 // Assume the user has pinch zoomed to page scale factor 2.
977 float userPinchPageScaleFactor = 2;
978 webViewHelper.webView()->setPageScaleFactor(userPinchPageScaleFactor);
979 webViewHelper.webView()->layout();
980
981 // Make sure we don't reset to initial scale if the page continues to load.
982 webViewHelper.webViewImpl()->didCommitLoad(false, false);
983 webViewHelper.webViewImpl()->didChangeContentsSize();
984 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
985
986 // Make sure we don't reset to initial scale if the viewport size changes.
987 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight + 100));
988 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
989 }
990
TEST_F(WebFrameTest,WideDocumentInitializeAtMinimumScale)991 TEST_F(WebFrameTest, WideDocumentInitializeAtMinimumScale)
992 {
993 UseMockScrollbarSettings mockScrollbarSettings;
994
995 registerMockedHttpURLLoad("wide_document.html");
996
997 FixedLayoutTestWebViewClient client;
998 client.m_screenInfo.deviceScaleFactor = 1;
999 int viewportWidth = 640;
1000 int viewportHeight = 480;
1001
1002 // Make sure we initialize to minimum scale, even if the window size
1003 // only becomes available after the load begins.
1004 FrameTestHelpers::WebViewHelper webViewHelper;
1005 webViewHelper.initializeAndLoad(m_baseURL + "wide_document.html", true, 0, &client, enableViewportSettings);
1006 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1007
1008 int wideDocumentWidth = 1500;
1009 float minimumPageScaleFactor = viewportWidth / (float) wideDocumentWidth;
1010 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1011 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->minimumPageScaleFactor());
1012
1013 // Assume the user has pinch zoomed to page scale factor 2.
1014 float userPinchPageScaleFactor = 2;
1015 webViewHelper.webView()->setPageScaleFactor(userPinchPageScaleFactor);
1016 webViewHelper.webView()->layout();
1017
1018 // Make sure we don't reset to initial scale if the page continues to load.
1019 webViewHelper.webViewImpl()->didCommitLoad(false, false);
1020 webViewHelper.webViewImpl()->didChangeContentsSize();
1021 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1022
1023 // Make sure we don't reset to initial scale if the viewport size changes.
1024 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight + 100));
1025 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1026 }
1027
TEST_F(WebFrameTest,DelayedViewportInitialScale)1028 TEST_F(WebFrameTest, DelayedViewportInitialScale)
1029 {
1030 UseMockScrollbarSettings mockScrollbarSettings;
1031 registerMockedHttpURLLoad("viewport-auto-initial-scale.html");
1032
1033 FixedLayoutTestWebViewClient client;
1034 client.m_screenInfo.deviceScaleFactor = 1;
1035 int viewportWidth = 640;
1036 int viewportHeight = 480;
1037
1038 FrameTestHelpers::WebViewHelper webViewHelper;
1039 webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings);
1040 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1041
1042 EXPECT_EQ(0.25f, webViewHelper.webView()->pageScaleFactor());
1043
1044 WebCore::Document* document = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document();
1045 WebCore::ViewportDescription description = document->viewportDescription();
1046 description.zoom = 2;
1047 document->setViewportDescription(description);
1048 webViewHelper.webView()->layout();
1049 EXPECT_EQ(2, webViewHelper.webView()->pageScaleFactor());
1050 }
1051
TEST_F(WebFrameTest,setLoadWithOverviewModeToFalse)1052 TEST_F(WebFrameTest, setLoadWithOverviewModeToFalse)
1053 {
1054 UseMockScrollbarSettings mockScrollbarSettings;
1055 registerMockedHttpURLLoad("viewport-auto-initial-scale.html");
1056
1057 FixedLayoutTestWebViewClient client;
1058 client.m_screenInfo.deviceScaleFactor = 1;
1059 int viewportWidth = 640;
1060 int viewportHeight = 480;
1061
1062 FrameTestHelpers::WebViewHelper webViewHelper;
1063 webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings);
1064 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1065 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1066 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1067
1068 // The page must be displayed at 100% zoom.
1069 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
1070 }
1071
TEST_F(WebFrameTest,SetLoadWithOverviewModeToFalseAndNoWideViewport)1072 TEST_F(WebFrameTest, SetLoadWithOverviewModeToFalseAndNoWideViewport)
1073 {
1074 UseMockScrollbarSettings mockScrollbarSettings;
1075 registerMockedHttpURLLoad("large-div.html");
1076
1077 FixedLayoutTestWebViewClient client;
1078 client.m_screenInfo.deviceScaleFactor = 1;
1079 int viewportWidth = 640;
1080 int viewportHeight = 480;
1081
1082 FrameTestHelpers::WebViewHelper webViewHelper;
1083 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client, enableViewportSettings);
1084 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1085 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1086 webViewHelper.webView()->settings()->setUseWideViewport(false);
1087 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1088
1089 // The page must be displayed at 100% zoom, despite that it hosts a wide div element.
1090 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
1091 }
1092
TEST_F(WebFrameTest,NoWideViewportIgnoresPageViewportWidth)1093 TEST_F(WebFrameTest, NoWideViewportIgnoresPageViewportWidth)
1094 {
1095 UseMockScrollbarSettings mockScrollbarSettings;
1096 registerMockedHttpURLLoad("viewport-auto-initial-scale.html");
1097
1098 FixedLayoutTestWebViewClient client;
1099 client.m_screenInfo.deviceScaleFactor = 1;
1100 int viewportWidth = 640;
1101 int viewportHeight = 480;
1102
1103 FrameTestHelpers::WebViewHelper webViewHelper;
1104 webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings);
1105 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1106 webViewHelper.webView()->settings()->setUseWideViewport(false);
1107 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1108
1109 // The page sets viewport width to 3000, but with UseWideViewport == false is must be ignored.
1110 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1111 EXPECT_EQ(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
1112 }
1113
TEST_F(WebFrameTest,NoWideViewportIgnoresPageViewportWidthButAccountsScale)1114 TEST_F(WebFrameTest, NoWideViewportIgnoresPageViewportWidthButAccountsScale)
1115 {
1116 UseMockScrollbarSettings mockScrollbarSettings;
1117 registerMockedHttpURLLoad("viewport-wide-2x-initial-scale.html");
1118
1119 FixedLayoutTestWebViewClient client;
1120 client.m_screenInfo.deviceScaleFactor = 1;
1121 int viewportWidth = 640;
1122 int viewportHeight = 480;
1123
1124 FrameTestHelpers::WebViewHelper webViewHelper;
1125 webViewHelper.initializeAndLoad(m_baseURL + "viewport-wide-2x-initial-scale.html", true, 0, &client, enableViewportSettings);
1126 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1127 webViewHelper.webView()->settings()->setUseWideViewport(false);
1128 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1129
1130 // The page sets viewport width to 3000, but with UseWideViewport == false it must be ignored.
1131 // While the initial scale specified by the page must be accounted.
1132 EXPECT_EQ(viewportWidth / 2, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1133 EXPECT_EQ(viewportHeight / 2, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
1134 }
1135
TEST_F(WebFrameTest,WideViewportSetsTo980WithoutViewportTag)1136 TEST_F(WebFrameTest, WideViewportSetsTo980WithoutViewportTag)
1137 {
1138 UseMockScrollbarSettings mockScrollbarSettings;
1139 registerMockedHttpURLLoad("no_viewport_tag.html");
1140
1141 FixedLayoutTestWebViewClient client;
1142 client.m_screenInfo.deviceScaleFactor = 1;
1143 int viewportWidth = 640;
1144 int viewportHeight = 480;
1145
1146 FrameTestHelpers::WebViewHelper webViewHelper;
1147 webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client, enableViewportSettings);
1148 applyViewportStyleOverride(&webViewHelper);
1149 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1150 webViewHelper.webView()->settings()->setUseWideViewport(true);
1151 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1152
1153 EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1154 EXPECT_EQ(980.0 / viewportWidth * viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
1155 }
1156
TEST_F(WebFrameTest,NoWideViewportAndHeightInMeta)1157 TEST_F(WebFrameTest, NoWideViewportAndHeightInMeta)
1158 {
1159 UseMockScrollbarSettings mockScrollbarSettings;
1160 registerMockedHttpURLLoad("viewport-height-1000.html");
1161
1162 FixedLayoutTestWebViewClient client;
1163 client.m_screenInfo.deviceScaleFactor = 1;
1164 int viewportWidth = 640;
1165 int viewportHeight = 480;
1166
1167 FrameTestHelpers::WebViewHelper webViewHelper;
1168 webViewHelper.initializeAndLoad(m_baseURL + "viewport-height-1000.html", true, 0, &client, enableViewportSettings);
1169 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1170 webViewHelper.webView()->settings()->setUseWideViewport(false);
1171 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1172
1173 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1174 }
1175
TEST_F(WebFrameTest,WideViewportSetsTo980WithAutoWidth)1176 TEST_F(WebFrameTest, WideViewportSetsTo980WithAutoWidth)
1177 {
1178 UseMockScrollbarSettings mockScrollbarSettings;
1179 registerMockedHttpURLLoad("viewport-2x-initial-scale.html");
1180
1181 FixedLayoutTestWebViewClient client;
1182 client.m_screenInfo.deviceScaleFactor = 1;
1183 int viewportWidth = 640;
1184 int viewportHeight = 480;
1185
1186 FrameTestHelpers::WebViewHelper webViewHelper;
1187 webViewHelper.initializeAndLoad(m_baseURL + "viewport-2x-initial-scale.html", true, 0, &client, enableViewportSettings);
1188 applyViewportStyleOverride(&webViewHelper);
1189 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1190 webViewHelper.webView()->settings()->setUseWideViewport(true);
1191 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1192
1193 EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1194 EXPECT_EQ(980.0 / viewportWidth * viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
1195 }
1196
TEST_F(WebFrameTest,PageViewportInitialScaleOverridesLoadWithOverviewMode)1197 TEST_F(WebFrameTest, PageViewportInitialScaleOverridesLoadWithOverviewMode)
1198 {
1199 UseMockScrollbarSettings mockScrollbarSettings;
1200 registerMockedHttpURLLoad("viewport-wide-2x-initial-scale.html");
1201
1202 FixedLayoutTestWebViewClient client;
1203 client.m_screenInfo.deviceScaleFactor = 1;
1204 int viewportWidth = 640;
1205 int viewportHeight = 480;
1206
1207 FrameTestHelpers::WebViewHelper webViewHelper;
1208 webViewHelper.initializeAndLoad(m_baseURL + "viewport-wide-2x-initial-scale.html", true, 0, &client, enableViewportSettings);
1209 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1210 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1211
1212 // The page must be displayed at 200% zoom, as specified in its viewport meta tag.
1213 EXPECT_EQ(2.0f, webViewHelper.webView()->pageScaleFactor());
1214 }
1215
TEST_F(WebFrameTest,setInitialPageScaleFactorPermanently)1216 TEST_F(WebFrameTest, setInitialPageScaleFactorPermanently)
1217 {
1218 UseMockScrollbarSettings mockScrollbarSettings;
1219
1220 registerMockedHttpURLLoad("fixed_layout.html");
1221
1222 FixedLayoutTestWebViewClient client;
1223 client.m_screenInfo.deviceScaleFactor = 1;
1224 float enforcedPageScaleFactor = 2.0f;
1225
1226 FrameTestHelpers::WebViewHelper webViewHelper;
1227 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1228 applyViewportStyleOverride(&webViewHelper);
1229 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1230 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1231 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1232 webViewHelper.webView()->layout();
1233
1234 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1235
1236 int viewportWidth = 640;
1237 int viewportHeight = 480;
1238 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1239 webViewHelper.webView()->layout();
1240
1241 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1242
1243 webViewHelper.webView()->setInitialPageScaleOverride(-1);
1244 webViewHelper.webView()->layout();
1245 EXPECT_EQ(1.0, webViewHelper.webView()->pageScaleFactor());
1246 }
1247
TEST_F(WebFrameTest,PermanentInitialPageScaleFactorOverridesLoadWithOverviewMode)1248 TEST_F(WebFrameTest, PermanentInitialPageScaleFactorOverridesLoadWithOverviewMode)
1249 {
1250 UseMockScrollbarSettings mockScrollbarSettings;
1251 registerMockedHttpURLLoad("viewport-auto-initial-scale.html");
1252
1253 FixedLayoutTestWebViewClient client;
1254 client.m_screenInfo.deviceScaleFactor = 1;
1255 int viewportWidth = 640;
1256 int viewportHeight = 480;
1257 float enforcedPageScaleFactor = 0.5f;
1258
1259 FrameTestHelpers::WebViewHelper webViewHelper;
1260 webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings);
1261 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1262 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1263 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1264
1265 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1266 }
1267
TEST_F(WebFrameTest,PermanentInitialPageScaleFactorOverridesPageViewportInitialScale)1268 TEST_F(WebFrameTest, PermanentInitialPageScaleFactorOverridesPageViewportInitialScale)
1269 {
1270 UseMockScrollbarSettings mockScrollbarSettings;
1271 registerMockedHttpURLLoad("viewport-wide-2x-initial-scale.html");
1272
1273 FixedLayoutTestWebViewClient client;
1274 client.m_screenInfo.deviceScaleFactor = 1;
1275 int viewportWidth = 640;
1276 int viewportHeight = 480;
1277 float enforcedPageScaleFactor = 0.5f;
1278
1279 FrameTestHelpers::WebViewHelper webViewHelper;
1280 webViewHelper.initializeAndLoad(m_baseURL + "viewport-wide-2x-initial-scale.html", true, 0, &client, enableViewportSettings);
1281 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1282 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1283
1284 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1285 }
1286
TEST_F(WebFrameTest,SmallPermanentInitialPageScaleFactorIsClobbered)1287 TEST_F(WebFrameTest, SmallPermanentInitialPageScaleFactorIsClobbered)
1288 {
1289 UseMockScrollbarSettings mockScrollbarSettings;
1290 const char* pages[] = {
1291 // These pages trigger the clobbering condition. There must be a matching item in "pageScaleFactors" array.
1292 "viewport-device-0.5x-initial-scale.html",
1293 "viewport-initial-scale-1.html",
1294 // These ones do not.
1295 "viewport-auto-initial-scale.html",
1296 "viewport-target-densitydpi-device-and-fixed-width.html"
1297 };
1298 float pageScaleFactors[] = { 0.5f, 1.0f };
1299 for (size_t i = 0; i < ARRAY_SIZE(pages); ++i)
1300 registerMockedHttpURLLoad(pages[i]);
1301
1302 FixedLayoutTestWebViewClient client;
1303 client.m_screenInfo.deviceScaleFactor = 1;
1304 int viewportWidth = 400;
1305 int viewportHeight = 300;
1306 float enforcedPageScaleFactor = 0.75f;
1307
1308 for (size_t i = 0; i < ARRAY_SIZE(pages); ++i) {
1309 for (int quirkEnabled = 0; quirkEnabled <= 1; ++quirkEnabled) {
1310 FrameTestHelpers::WebViewHelper webViewHelper;
1311 webViewHelper.initializeAndLoad(m_baseURL + pages[i], true, 0, &client, enableViewportSettings);
1312 applyViewportStyleOverride(&webViewHelper);
1313 webViewHelper.webView()->settings()->setClobberUserAgentInitialScaleQuirk(quirkEnabled);
1314 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1315 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1316
1317 float expectedPageScaleFactor = quirkEnabled && i < ARRAY_SIZE(pageScaleFactors) ? pageScaleFactors[i] : enforcedPageScaleFactor;
1318 EXPECT_EQ(expectedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1319 }
1320 }
1321 }
1322
TEST_F(WebFrameTest,PermanentInitialPageScaleFactorAffectsLayoutWidth)1323 TEST_F(WebFrameTest, PermanentInitialPageScaleFactorAffectsLayoutWidth)
1324 {
1325 UseMockScrollbarSettings mockScrollbarSettings;
1326
1327 FixedLayoutTestWebViewClient client;
1328 client.m_screenInfo.deviceScaleFactor = 1;
1329 int viewportWidth = 640;
1330 int viewportHeight = 480;
1331 float enforcedPageScaleFactor = 0.5;
1332
1333 FrameTestHelpers::WebViewHelper webViewHelper;
1334 webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings);
1335 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1336 webViewHelper.webView()->settings()->setUseWideViewport(false);
1337 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1338 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1339 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1340
1341 EXPECT_EQ(viewportWidth / enforcedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1342 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1343 }
1344
TEST_F(WebFrameTest,WideViewportInitialScaleDoesNotExpandFixedLayoutWidth)1345 TEST_F(WebFrameTest, WideViewportInitialScaleDoesNotExpandFixedLayoutWidth)
1346 {
1347 UseMockScrollbarSettings mockScrollbarSettings;
1348 registerMockedHttpURLLoad("viewport-device-0.5x-initial-scale.html");
1349
1350 FixedLayoutTestWebViewClient client;
1351 client.m_screenInfo.deviceScaleFactor = 1;
1352 int viewportWidth = 640;
1353 int viewportHeight = 480;
1354
1355 FrameTestHelpers::WebViewHelper webViewHelper;
1356 webViewHelper.initializeAndLoad(m_baseURL + "viewport-device-0.5x-initial-scale.html", true, 0, &client, enableViewportSettings);
1357 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1358 webViewHelper.webView()->settings()->setUseWideViewport(true);
1359 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1360 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1361
1362 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1363 EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor());
1364
1365 webViewHelper.webView()->setFixedLayoutSize(WebSize(2000, 1500));
1366 webViewHelper.webView()->layout();
1367 EXPECT_EQ(2000, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1368 EXPECT_EQ(0.5f, webViewHelper.webView()->pageScaleFactor());
1369 }
1370
TEST_F(WebFrameTest,SetForceZeroLayoutHeight)1371 TEST_F(WebFrameTest, SetForceZeroLayoutHeight)
1372 {
1373 UseMockScrollbarSettings mockScrollbarSettings;
1374 registerMockedHttpURLLoad("200-by-300.html");
1375
1376 FixedLayoutTestWebViewClient client;
1377 client.m_screenInfo.deviceScaleFactor = 1;
1378 int viewportWidth = 640;
1379 int viewportHeight = 480;
1380
1381 FrameTestHelpers::WebViewHelper webViewHelper;
1382
1383 webViewHelper.initializeAndLoad(m_baseURL + "200-by-300.html", true, 0, &client, enableViewportSettings);
1384 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1385 webViewHelper.webView()->layout();
1386
1387 EXPECT_LE(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1388 webViewHelper.webView()->settings()->setForceZeroLayoutHeight(true);
1389 EXPECT_TRUE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
1390
1391 EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1392
1393 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight * 2));
1394 EXPECT_FALSE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
1395 EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1396
1397 webViewHelper.webView()->resize(WebSize(viewportWidth * 2, viewportHeight));
1398 webViewHelper.webView()->layout();
1399 EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1400
1401 webViewHelper.webView()->settings()->setForceZeroLayoutHeight(false);
1402 EXPECT_LE(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1403 }
1404
TEST_F(WebFrameTest,SetForceZeroLayoutHeightWorksAcrossNavigations)1405 TEST_F(WebFrameTest, SetForceZeroLayoutHeightWorksAcrossNavigations)
1406 {
1407 UseMockScrollbarSettings mockScrollbarSettings;
1408 registerMockedHttpURLLoad("200-by-300.html");
1409 registerMockedHttpURLLoad("large-div.html");
1410
1411 FixedLayoutTestWebViewClient client;
1412 client.m_screenInfo.deviceScaleFactor = 1;
1413 int viewportWidth = 640;
1414 int viewportHeight = 480;
1415
1416 FrameTestHelpers::WebViewHelper webViewHelper;
1417
1418 webViewHelper.initializeAndLoad(m_baseURL + "200-by-300.html", true, 0, &client, enableViewportSettings);
1419 webViewHelper.webView()->settings()->setForceZeroLayoutHeight(true);
1420 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1421 webViewHelper.webView()->layout();
1422
1423 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "large-div.html");
1424 webViewHelper.webView()->layout();
1425
1426 EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1427 }
1428
TEST_F(WebFrameTest,SetForceZeroLayoutHeightWithWideViewportQuirk)1429 TEST_F(WebFrameTest, SetForceZeroLayoutHeightWithWideViewportQuirk)
1430 {
1431 UseMockScrollbarSettings mockScrollbarSettings;
1432 registerMockedHttpURLLoad("200-by-300.html");
1433
1434 FixedLayoutTestWebViewClient client;
1435 client.m_screenInfo.deviceScaleFactor = 1;
1436 int viewportWidth = 640;
1437 int viewportHeight = 480;
1438
1439 FrameTestHelpers::WebViewHelper webViewHelper;
1440
1441 webViewHelper.initializeAndLoad(m_baseURL + "200-by-300.html", true, 0, &client, enableViewportSettings);
1442 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1443 webViewHelper.webView()->settings()->setUseWideViewport(true);
1444 webViewHelper.webView()->settings()->setForceZeroLayoutHeight(true);
1445 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1446 webViewHelper.webView()->layout();
1447
1448 EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1449 }
1450
TEST_F(WebFrameTest,WideViewportAndWideContentWithInitialScale)1451 TEST_F(WebFrameTest, WideViewportAndWideContentWithInitialScale)
1452 {
1453 UseMockScrollbarSettings mockScrollbarSettings;
1454 registerMockedHttpURLLoad("wide_document_width_viewport.html");
1455
1456 FixedLayoutTestWebViewClient client;
1457 client.m_screenInfo.deviceScaleFactor = 1;
1458 int viewportWidth = 600;
1459 int viewportHeight = 800;
1460
1461 FrameTestHelpers::WebViewHelper webViewHelper;
1462 webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings);
1463 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1464 webViewHelper.webView()->settings()->setUseWideViewport(true);
1465 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1466 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1467
1468 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "wide_document_width_viewport.html");
1469 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1470
1471 int wideDocumentWidth = 800;
1472 float minimumPageScaleFactor = viewportWidth / (float) wideDocumentWidth;
1473 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1474 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->minimumPageScaleFactor());
1475 }
1476
TEST_F(WebFrameTest,WideViewportQuirkClobbersHeight)1477 TEST_F(WebFrameTest, WideViewportQuirkClobbersHeight)
1478 {
1479 UseMockScrollbarSettings mockScrollbarSettings;
1480 registerMockedHttpURLLoad("viewport-height-1000.html");
1481
1482 FixedLayoutTestWebViewClient client;
1483 client.m_screenInfo.deviceScaleFactor = 1;
1484 int viewportWidth = 600;
1485 int viewportHeight = 800;
1486
1487 FrameTestHelpers::WebViewHelper webViewHelper;
1488 webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings);
1489 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1490 webViewHelper.webView()->settings()->setUseWideViewport(false);
1491 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1492 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1493
1494 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport-height-1000.html");
1495 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1496
1497 EXPECT_EQ(800, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1498 EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor());
1499 }
1500
TEST_F(WebFrameTest,LayoutSize320Quirk)1501 TEST_F(WebFrameTest, LayoutSize320Quirk)
1502 {
1503 UseMockScrollbarSettings mockScrollbarSettings;
1504 registerMockedHttpURLLoad("viewport/viewport-30.html");
1505
1506 FixedLayoutTestWebViewClient client;
1507 client.m_screenInfo.deviceScaleFactor = 1;
1508 int viewportWidth = 600;
1509 int viewportHeight = 800;
1510
1511 FrameTestHelpers::WebViewHelper webViewHelper;
1512 webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings);
1513 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1514 webViewHelper.webView()->settings()->setUseWideViewport(true);
1515 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1516 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1517
1518 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport/viewport-30.html");
1519 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1520
1521 EXPECT_EQ(600, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1522 EXPECT_EQ(800, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1523 EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor());
1524
1525 // The magic number to snap to device-width is 320, so test that 321 is
1526 // respected.
1527 WebCore::Document* document = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document();
1528 WebCore::ViewportDescription description = document->viewportDescription();
1529 description.minWidth = WebCore::Length(321, WebCore::Fixed);
1530 description.maxWidth = WebCore::Length(321, WebCore::Fixed);
1531 document->setViewportDescription(description);
1532 webViewHelper.webView()->layout();
1533 EXPECT_EQ(321, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1534
1535 description.minWidth = WebCore::Length(320, WebCore::Fixed);
1536 description.maxWidth = WebCore::Length(320, WebCore::Fixed);
1537 document->setViewportDescription(description);
1538 webViewHelper.webView()->layout();
1539 EXPECT_EQ(600, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1540
1541 description = document->viewportDescription();
1542 description.maxHeight = WebCore::Length(1000, WebCore::Fixed);
1543 document->setViewportDescription(description);
1544 webViewHelper.webView()->layout();
1545 EXPECT_EQ(1000, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1546
1547 description.maxHeight = WebCore::Length(320, WebCore::Fixed);
1548 document->setViewportDescription(description);
1549 webViewHelper.webView()->layout();
1550 EXPECT_EQ(800, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1551 }
1552
TEST_F(WebFrameTest,ZeroValuesQuirk)1553 TEST_F(WebFrameTest, ZeroValuesQuirk)
1554 {
1555 UseMockScrollbarSettings mockScrollbarSettings;
1556 registerMockedHttpURLLoad("viewport-zero-values.html");
1557
1558 FixedLayoutTestWebViewClient client;
1559 client.m_screenInfo.deviceScaleFactor = 1;
1560 int viewportWidth = 640;
1561 int viewportHeight = 480;
1562
1563 FrameTestHelpers::WebViewHelper webViewHelper;
1564 webViewHelper.initialize(true, 0, &client, enableViewportSettings);
1565 webViewHelper.webView()->settings()->setViewportMetaZeroValuesQuirk(true);
1566 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1567 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1568 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport-zero-values.html");
1569 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1570
1571 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1572 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
1573
1574 webViewHelper.webView()->settings()->setUseWideViewport(true);
1575 webViewHelper.webView()->layout();
1576 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1577 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
1578 }
1579
TEST_F(WebFrameTest,OverflowHiddenDisablesScrolling)1580 TEST_F(WebFrameTest, OverflowHiddenDisablesScrolling)
1581 {
1582 registerMockedHttpURLLoad("body-overflow-hidden.html");
1583
1584 FixedLayoutTestWebViewClient client;
1585 client.m_screenInfo.deviceScaleFactor = 1;
1586 int viewportWidth = 640;
1587 int viewportHeight = 480;
1588
1589 FrameTestHelpers::WebViewHelper webViewHelper;
1590 webViewHelper.initialize(true, 0, &client);
1591 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "body-overflow-hidden.html");
1592 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1593
1594 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
1595 EXPECT_FALSE(view->userInputScrollable(WebCore::VerticalScrollbar));
1596 }
1597
TEST_F(WebFrameTest,IgnoreOverflowHiddenQuirk)1598 TEST_F(WebFrameTest, IgnoreOverflowHiddenQuirk)
1599 {
1600 registerMockedHttpURLLoad("body-overflow-hidden.html");
1601
1602 FixedLayoutTestWebViewClient client;
1603 client.m_screenInfo.deviceScaleFactor = 1;
1604 int viewportWidth = 640;
1605 int viewportHeight = 480;
1606
1607 FrameTestHelpers::WebViewHelper webViewHelper;
1608 webViewHelper.initialize(true, 0, &client);
1609 webViewHelper.webView()->settings()->setIgnoreMainFrameOverflowHiddenQuirk(true);
1610 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "body-overflow-hidden.html");
1611 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1612
1613 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
1614 EXPECT_TRUE(view->userInputScrollable(WebCore::VerticalScrollbar));
1615 }
1616
TEST_F(WebFrameTest,NonZeroValuesNoQuirk)1617 TEST_F(WebFrameTest, NonZeroValuesNoQuirk)
1618 {
1619 UseMockScrollbarSettings mockScrollbarSettings;
1620 registerMockedHttpURLLoad("viewport-nonzero-values.html");
1621
1622 FixedLayoutTestWebViewClient client;
1623 client.m_screenInfo.deviceScaleFactor = 1;
1624 int viewportWidth = 640;
1625 int viewportHeight = 480;
1626 float expectedPageScaleFactor = 0.5f;
1627
1628 FrameTestHelpers::WebViewHelper webViewHelper;
1629 webViewHelper.initialize(true, 0, &client, enableViewportSettings);
1630 webViewHelper.webView()->settings()->setViewportMetaZeroValuesQuirk(true);
1631 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1632 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport-nonzero-values.html");
1633 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1634
1635 EXPECT_EQ(viewportWidth / expectedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1636 EXPECT_EQ(expectedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1637
1638 webViewHelper.webView()->settings()->setUseWideViewport(true);
1639 webViewHelper.webView()->layout();
1640 EXPECT_EQ(viewportWidth / expectedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1641 EXPECT_EQ(expectedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1642 }
1643
TEST_F(WebFrameTest,setPageScaleFactorDoesNotLayout)1644 TEST_F(WebFrameTest, setPageScaleFactorDoesNotLayout)
1645 {
1646 UseMockScrollbarSettings mockScrollbarSettings;
1647 registerMockedHttpURLLoad("fixed_layout.html");
1648
1649 FixedLayoutTestWebViewClient client;
1650 client.m_screenInfo.deviceScaleFactor = 1;
1651 // Small viewport to ensure there are always scrollbars.
1652 int viewportWidth = 64;
1653 int viewportHeight = 48;
1654
1655 FrameTestHelpers::WebViewHelper webViewHelper;
1656 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1657 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1658 webViewHelper.webView()->layout();
1659
1660 int prevLayoutCount = webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount();
1661 webViewHelper.webViewImpl()->setPageScaleFactor(3);
1662 EXPECT_FALSE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
1663 EXPECT_EQ(prevLayoutCount, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount());
1664 }
1665
TEST_F(WebFrameTest,setPageScaleFactorWithOverlayScrollbarsDoesNotLayout)1666 TEST_F(WebFrameTest, setPageScaleFactorWithOverlayScrollbarsDoesNotLayout)
1667 {
1668 UseMockScrollbarSettings mockScrollbarSettings;
1669
1670 registerMockedHttpURLLoad("fixed_layout.html");
1671
1672 FixedLayoutTestWebViewClient client;
1673 client.m_screenInfo.deviceScaleFactor = 1;
1674 int viewportWidth = 640;
1675 int viewportHeight = 480;
1676
1677 FrameTestHelpers::WebViewHelper webViewHelper;
1678 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1679 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1680 webViewHelper.webView()->layout();
1681
1682 int prevLayoutCount = webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount();
1683 webViewHelper.webViewImpl()->setPageScaleFactor(30);
1684 EXPECT_FALSE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
1685 EXPECT_EQ(prevLayoutCount, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount());
1686
1687 }
1688
TEST_F(WebFrameTest,pageScaleFactorWrittenToHistoryItem)1689 TEST_F(WebFrameTest, pageScaleFactorWrittenToHistoryItem)
1690 {
1691 UseMockScrollbarSettings mockScrollbarSettings;
1692 registerMockedHttpURLLoad("fixed_layout.html");
1693
1694 FixedLayoutTestWebViewClient client;
1695 client.m_screenInfo.deviceScaleFactor = 1;
1696 int viewportWidth = 640;
1697 int viewportHeight = 480;
1698
1699 FrameTestHelpers::WebViewHelper webViewHelper;
1700 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1701 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1702 webViewHelper.webView()->layout();
1703
1704 webViewHelper.webView()->setPageScaleFactor(3);
1705 EXPECT_EQ(3, toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->loader().currentItem()->pageScaleFactor());
1706 }
1707
TEST_F(WebFrameTest,initialScaleWrittenToHistoryItem)1708 TEST_F(WebFrameTest, initialScaleWrittenToHistoryItem)
1709 {
1710 UseMockScrollbarSettings mockScrollbarSettings;
1711 registerMockedHttpURLLoad("fixed_layout.html");
1712
1713 FixedLayoutTestWebViewClient client;
1714 client.m_screenInfo.deviceScaleFactor = 1;
1715 int viewportWidth = 640;
1716 int viewportHeight = 480;
1717
1718 FrameTestHelpers::WebViewHelper webViewHelper;
1719 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1720 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1721 webViewHelper.webView()->layout();
1722
1723 int defaultFixedLayoutWidth = 980;
1724 float minimumPageScaleFactor = viewportWidth / (float) defaultFixedLayoutWidth;
1725 EXPECT_EQ(minimumPageScaleFactor, toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->loader().currentItem()->pageScaleFactor());
1726 }
1727
TEST_F(WebFrameTest,pageScaleFactorShrinksViewport)1728 TEST_F(WebFrameTest, pageScaleFactorShrinksViewport)
1729 {
1730 UseMockScrollbarSettings mockScrollbarSettings;
1731 registerMockedHttpURLLoad("large-div.html");
1732
1733 FixedLayoutTestWebViewClient client;
1734 client.m_screenInfo.deviceScaleFactor = 1;
1735 // Small viewport to ensure there are always scrollbars.
1736 int viewportWidth = 64;
1737 int viewportHeight = 48;
1738
1739 FrameTestHelpers::WebViewHelper webViewHelper;
1740 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client, enableViewportSettings);
1741 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1742 webViewHelper.webView()->layout();
1743
1744 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
1745 int viewportWidthMinusScrollbar = viewportWidth - (view->verticalScrollbar()->isOverlayScrollbar() ? 0 : 15);
1746 int viewportHeightMinusScrollbar = viewportHeight - (view->horizontalScrollbar()->isOverlayScrollbar() ? 0 : 15);
1747
1748 webViewHelper.webView()->setPageScaleFactor(2);
1749
1750 WebCore::IntSize unscaledSize = view->unscaledVisibleContentSize(WebCore::IncludeScrollbars);
1751 EXPECT_EQ(viewportWidth, unscaledSize.width());
1752 EXPECT_EQ(viewportHeight, unscaledSize.height());
1753
1754 WebCore::IntSize unscaledSizeMinusScrollbar = view->unscaledVisibleContentSize(WebCore::ExcludeScrollbars);
1755 EXPECT_EQ(viewportWidthMinusScrollbar, unscaledSizeMinusScrollbar.width());
1756 EXPECT_EQ(viewportHeightMinusScrollbar, unscaledSizeMinusScrollbar.height());
1757
1758 WebCore::IntSize scaledSize = view->visibleContentRect().size();
1759 EXPECT_EQ(ceil(viewportWidthMinusScrollbar / 2.0), scaledSize.width());
1760 EXPECT_EQ(ceil(viewportHeightMinusScrollbar / 2.0), scaledSize.height());
1761 }
1762
TEST_F(WebFrameTest,pageScaleFactorDoesNotApplyCssTransform)1763 TEST_F(WebFrameTest, pageScaleFactorDoesNotApplyCssTransform)
1764 {
1765 UseMockScrollbarSettings mockScrollbarSettings;
1766 registerMockedHttpURLLoad("fixed_layout.html");
1767
1768 FixedLayoutTestWebViewClient client;
1769 client.m_screenInfo.deviceScaleFactor = 1;
1770 int viewportWidth = 640;
1771 int viewportHeight = 480;
1772
1773 FrameTestHelpers::WebViewHelper webViewHelper;
1774 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1775 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1776 webViewHelper.webView()->layout();
1777
1778 webViewHelper.webView()->setPageScaleFactor(2);
1779
1780 EXPECT_EQ(980, toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->contentRenderer()->unscaledDocumentRect().width());
1781 EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1782 }
1783
TEST_F(WebFrameTest,targetDensityDpiHigh)1784 TEST_F(WebFrameTest, targetDensityDpiHigh)
1785 {
1786 UseMockScrollbarSettings mockScrollbarSettings;
1787 registerMockedHttpURLLoad("viewport-target-densitydpi-high.html");
1788
1789 FixedLayoutTestWebViewClient client;
1790 // high-dpi = 240
1791 float targetDpi = 240.0f;
1792 float deviceScaleFactors[] = { 1.0f, 4.0f / 3.0f, 2.0f };
1793 int viewportWidth = 640;
1794 int viewportHeight = 480;
1795
1796 for (size_t i = 0; i < ARRAY_SIZE(deviceScaleFactors); ++i) {
1797 float deviceScaleFactor = deviceScaleFactors[i];
1798 float deviceDpi = deviceScaleFactor * 160.0f;
1799 client.m_screenInfo.deviceScaleFactor = deviceScaleFactor;
1800
1801 FrameTestHelpers::WebViewHelper webViewHelper;
1802 webViewHelper.initializeAndLoad(m_baseURL + "viewport-target-densitydpi-high.html", true, 0, &client, enableViewportSettings);
1803 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1804 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1805 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1806
1807 // We need to account for the fact that logical pixels are unconditionally multiplied by deviceScaleFactor to produce
1808 // physical pixels.
1809 float densityDpiScaleRatio = deviceScaleFactor * targetDpi / deviceDpi;
1810 EXPECT_NEAR(viewportWidth * densityDpiScaleRatio, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1811 EXPECT_NEAR(viewportHeight * densityDpiScaleRatio, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1812 EXPECT_NEAR(1.0f / densityDpiScaleRatio, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1813 }
1814 }
1815
TEST_F(WebFrameTest,targetDensityDpiDevice)1816 TEST_F(WebFrameTest, targetDensityDpiDevice)
1817 {
1818 UseMockScrollbarSettings mockScrollbarSettings;
1819 registerMockedHttpURLLoad("viewport-target-densitydpi-device.html");
1820
1821 float deviceScaleFactors[] = { 1.0f, 4.0f / 3.0f, 2.0f };
1822
1823 FixedLayoutTestWebViewClient client;
1824 int viewportWidth = 640;
1825 int viewportHeight = 480;
1826
1827 for (size_t i = 0; i < ARRAY_SIZE(deviceScaleFactors); ++i) {
1828 client.m_screenInfo.deviceScaleFactor = deviceScaleFactors[i];
1829
1830 FrameTestHelpers::WebViewHelper webViewHelper;
1831 webViewHelper.initializeAndLoad(m_baseURL + "viewport-target-densitydpi-device.html", true, 0, &client, enableViewportSettings);
1832 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1833 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1834 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1835
1836 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1837 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1838 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1839 }
1840 }
1841
TEST_F(WebFrameTest,targetDensityDpiDeviceAndFixedWidth)1842 TEST_F(WebFrameTest, targetDensityDpiDeviceAndFixedWidth)
1843 {
1844 UseMockScrollbarSettings mockScrollbarSettings;
1845 registerMockedHttpURLLoad("viewport-target-densitydpi-device-and-fixed-width.html");
1846
1847 float deviceScaleFactors[] = { 1.0f, 4.0f / 3.0f, 2.0f };
1848
1849 FixedLayoutTestWebViewClient client;
1850 int viewportWidth = 640;
1851 int viewportHeight = 480;
1852
1853 for (size_t i = 0; i < ARRAY_SIZE(deviceScaleFactors); ++i) {
1854 client.m_screenInfo.deviceScaleFactor = deviceScaleFactors[i];
1855
1856 FrameTestHelpers::WebViewHelper webViewHelper;
1857 webViewHelper.initializeAndLoad(m_baseURL + "viewport-target-densitydpi-device-and-fixed-width.html", true, 0, &client, enableViewportSettings);
1858 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1859 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1860 webViewHelper.webView()->settings()->setUseWideViewport(true);
1861 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1862
1863 EXPECT_NEAR(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1864 EXPECT_NEAR(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1865 EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1866 }
1867 }
1868
TEST_F(WebFrameTest,NoWideViewportAndScaleLessThanOne)1869 TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOne)
1870 {
1871 UseMockScrollbarSettings mockScrollbarSettings;
1872 registerMockedHttpURLLoad("viewport-initial-scale-less-than-1.html");
1873
1874 FixedLayoutTestWebViewClient client;
1875 client.m_screenInfo.deviceScaleFactor = 1.33f;
1876 int viewportWidth = 640;
1877 int viewportHeight = 480;
1878
1879 FrameTestHelpers::WebViewHelper webViewHelper;
1880 webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-less-than-1.html", true, 0, &client, enableViewportSettings);
1881 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1882 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1883 webViewHelper.webView()->settings()->setUseWideViewport(false);
1884 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1885 webViewHelper.webView()->layout();
1886
1887 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1888 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1889 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1890 }
1891
TEST_F(WebFrameTest,NoWideViewportAndScaleLessThanOneWithDeviceWidth)1892 TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOneWithDeviceWidth)
1893 {
1894 UseMockScrollbarSettings mockScrollbarSettings;
1895 registerMockedHttpURLLoad("viewport-initial-scale-less-than-1-device-width.html");
1896
1897 FixedLayoutTestWebViewClient client;
1898 client.m_screenInfo.deviceScaleFactor = 1.33f;
1899 int viewportWidth = 640;
1900 int viewportHeight = 480;
1901
1902 FrameTestHelpers::WebViewHelper webViewHelper;
1903 webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-less-than-1-device-width.html", true, 0, &client, enableViewportSettings);
1904 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1905 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1906 webViewHelper.webView()->settings()->setUseWideViewport(false);
1907 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1908 webViewHelper.webView()->layout();
1909
1910 const float pageZoom = 0.25f;
1911 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor / pageZoom, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1912 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor / pageZoom, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1913 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1914 }
1915
TEST_F(WebFrameTest,NoWideViewportAndNoViewportWithInitialPageScaleOverride)1916 TEST_F(WebFrameTest, NoWideViewportAndNoViewportWithInitialPageScaleOverride)
1917 {
1918 UseMockScrollbarSettings mockScrollbarSettings;
1919 registerMockedHttpURLLoad("large-div.html");
1920
1921 FixedLayoutTestWebViewClient client;
1922 int viewportWidth = 640;
1923 int viewportHeight = 480;
1924 float enforcedPageScaleFactor = 5.0f;
1925
1926 FrameTestHelpers::WebViewHelper webViewHelper;
1927 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client, enableViewportSettings);
1928 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1929 webViewHelper.webView()->settings()->setUseWideViewport(false);
1930 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1931 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1932 webViewHelper.webView()->layout();
1933
1934 EXPECT_NEAR(viewportWidth / enforcedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1935 EXPECT_NEAR(viewportHeight / enforcedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1936 EXPECT_NEAR(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1937 }
1938
TEST_F(WebFrameTest,NoUserScalableQuirkIgnoresViewportScale)1939 TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScale)
1940 {
1941 UseMockScrollbarSettings mockScrollbarSettings;
1942 registerMockedHttpURLLoad("viewport-initial-scale-and-user-scalable-no.html");
1943
1944 FixedLayoutTestWebViewClient client;
1945 int viewportWidth = 640;
1946 int viewportHeight = 480;
1947
1948 FrameTestHelpers::WebViewHelper webViewHelper;
1949 webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-and-user-scalable-no.html", true, 0, &client, enableViewportSettings);
1950 webViewHelper.webView()->settings()->setViewportMetaNonUserScalableQuirk(true);
1951 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1952 webViewHelper.webView()->layout();
1953
1954 EXPECT_NEAR(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1955 EXPECT_NEAR(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1956 EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1957 }
1958
TEST_F(WebFrameTest,NoUserScalableQuirkIgnoresViewportScaleForNonWideViewport)1959 TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScaleForNonWideViewport)
1960 {
1961 UseMockScrollbarSettings mockScrollbarSettings;
1962 registerMockedHttpURLLoad("viewport-initial-scale-and-user-scalable-no.html");
1963
1964 FixedLayoutTestWebViewClient client;
1965 client.m_screenInfo.deviceScaleFactor = 1.33f;
1966 int viewportWidth = 640;
1967 int viewportHeight = 480;
1968
1969 FrameTestHelpers::WebViewHelper webViewHelper;
1970 webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-and-user-scalable-no.html", true, 0, &client, enableViewportSettings);
1971 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1972 webViewHelper.webView()->settings()->setViewportMetaNonUserScalableQuirk(true);
1973 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1974 webViewHelper.webView()->settings()->setUseWideViewport(false);
1975 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1976 webViewHelper.webView()->layout();
1977
1978 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1979 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1980 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1981 }
1982
TEST_F(WebFrameTest,NoUserScalableQuirkIgnoresViewportScaleForWideViewport)1983 TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScaleForWideViewport)
1984 {
1985 UseMockScrollbarSettings mockScrollbarSettings;
1986 registerMockedHttpURLLoad("viewport-2x-initial-scale-non-user-scalable.html");
1987
1988 FixedLayoutTestWebViewClient client;
1989 int viewportWidth = 640;
1990 int viewportHeight = 480;
1991
1992 FrameTestHelpers::WebViewHelper webViewHelper;
1993 webViewHelper.initializeAndLoad(m_baseURL + "viewport-2x-initial-scale-non-user-scalable.html", true, 0, &client, enableViewportSettings);
1994 webViewHelper.webView()->settings()->setViewportMetaNonUserScalableQuirk(true);
1995 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1996 webViewHelper.webView()->settings()->setUseWideViewport(true);
1997 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1998
1999 EXPECT_NEAR(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
2000 EXPECT_NEAR(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
2001 EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f);
2002 }
2003
TEST_F(WebFrameTest,DesktopPageCanBeZoomedInWhenWideViewportIsTurnedOff)2004 TEST_F(WebFrameTest, DesktopPageCanBeZoomedInWhenWideViewportIsTurnedOff)
2005 {
2006 UseMockScrollbarSettings mockScrollbarSettings;
2007 registerMockedHttpURLLoad("no_viewport_tag.html");
2008
2009 FixedLayoutTestWebViewClient client;
2010 int viewportWidth = 640;
2011 int viewportHeight = 480;
2012
2013 FrameTestHelpers::WebViewHelper webViewHelper;
2014 webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client, enableViewportSettings);
2015 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
2016 webViewHelper.webView()->settings()->setUseWideViewport(false);
2017 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2018
2019 EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f);
2020 EXPECT_NEAR(1.0f, webViewHelper.webView()->minimumPageScaleFactor(), 0.01f);
2021 EXPECT_NEAR(5.0f, webViewHelper.webView()->maximumPageScaleFactor(), 0.01f);
2022 }
2023
2024 class WebFrameResizeTest : public WebFrameTest {
2025 protected:
2026
computeRelativeOffset(const WebCore::IntPoint & absoluteOffset,const WebCore::LayoutRect & rect)2027 static WebCore::FloatSize computeRelativeOffset(const WebCore::IntPoint& absoluteOffset, const WebCore::LayoutRect& rect)
2028 {
2029 WebCore::FloatSize relativeOffset = WebCore::FloatPoint(absoluteOffset) - rect.location();
2030 relativeOffset.scale(1.f / rect.width(), 1.f / rect.height());
2031 return relativeOffset;
2032 }
2033
testResizeYieldsCorrectScrollAndScale(const char * url,const float initialPageScaleFactor,const WebSize scrollOffset,const WebSize viewportSize,const bool shouldScaleRelativeToViewportWidth)2034 void testResizeYieldsCorrectScrollAndScale(const char* url,
2035 const float initialPageScaleFactor,
2036 const WebSize scrollOffset,
2037 const WebSize viewportSize,
2038 const bool shouldScaleRelativeToViewportWidth) {
2039 UseMockScrollbarSettings mockScrollbarSettings;
2040 registerMockedHttpURLLoad(url);
2041
2042 const float aspectRatio = static_cast<float>(viewportSize.width) / viewportSize.height;
2043
2044 FrameTestHelpers::WebViewHelper webViewHelper;
2045 webViewHelper.initializeAndLoad(m_baseURL + url, true, 0, 0, enableViewportSettings);
2046
2047 // Origin scrollOffsets preserved under resize.
2048 {
2049 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height));
2050 webViewHelper.webViewImpl()->setPageScaleFactor(initialPageScaleFactor);
2051 ASSERT_EQ(viewportSize, webViewHelper.webViewImpl()->size());
2052 ASSERT_EQ(initialPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor());
2053 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.height, viewportSize.width));
2054 float expectedPageScaleFactor = initialPageScaleFactor * (shouldScaleRelativeToViewportWidth ? 1 / aspectRatio : 1);
2055 EXPECT_NEAR(expectedPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor(), 0.05f);
2056 EXPECT_EQ(WebSize(), webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
2057 }
2058
2059 // Resizing just the height should not affect pageScaleFactor or scrollOffset.
2060 {
2061 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height));
2062 webViewHelper.webViewImpl()->setPageScaleFactor(initialPageScaleFactor);
2063 webViewHelper.webViewImpl()->setMainFrameScrollOffset(WebPoint(scrollOffset.width, scrollOffset.height));
2064 webViewHelper.webViewImpl()->layout();
2065 const WebSize expectedScrollOffset = webViewHelper.webViewImpl()->mainFrame()->scrollOffset();
2066 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height * 0.8f));
2067 EXPECT_EQ(initialPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor());
2068 EXPECT_EQ(expectedScrollOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
2069 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height * 0.8f));
2070 EXPECT_EQ(initialPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor());
2071 EXPECT_EQ(expectedScrollOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
2072 }
2073
2074 // Generic resize preserves scrollOffset relative to anchor node located
2075 // the top center of the screen.
2076 {
2077 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.height, viewportSize.width));
2078 float pageScaleFactor = webViewHelper.webViewImpl()->pageScaleFactor();
2079 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height));
2080 float expectedPageScaleFactor = pageScaleFactor * (shouldScaleRelativeToViewportWidth ? aspectRatio : 1);
2081 EXPECT_NEAR(expectedPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor(), 0.05f);
2082 webViewHelper.webViewImpl()->mainFrame()->setScrollOffset(scrollOffset);
2083
2084 WebCore::IntPoint anchorPoint = WebCore::IntPoint(scrollOffset) + WebCore::IntPoint(viewportSize.width / 2, 0);
2085 RefPtrWillBeRawPtr<WebCore::Node> anchorNode = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->eventHandler().hitTestResultAtPoint(anchorPoint, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent).innerNode();
2086 ASSERT(anchorNode);
2087
2088 pageScaleFactor = webViewHelper.webViewImpl()->pageScaleFactor();
2089 const WebCore::FloatSize preResizeRelativeOffset
2090 = computeRelativeOffset(anchorPoint, anchorNode->boundingBox());
2091 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.height, viewportSize.width));
2092 WebCore::IntPoint newAnchorPoint = WebCore::IntPoint(webViewHelper.webViewImpl()->mainFrame()->scrollOffset()) + WebCore::IntPoint(viewportSize.height / 2, 0);
2093 const WebCore::FloatSize postResizeRelativeOffset
2094 = computeRelativeOffset(newAnchorPoint, anchorNode->boundingBox());
2095 EXPECT_NEAR(preResizeRelativeOffset.width(), postResizeRelativeOffset.width(), 0.15f);
2096 expectedPageScaleFactor = pageScaleFactor * (shouldScaleRelativeToViewportWidth ? 1 / aspectRatio : 1);
2097 EXPECT_NEAR(expectedPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor(), 0.05f);
2098 }
2099 }
2100 };
2101
TEST_F(WebFrameResizeTest,ResizeYieldsCorrectScrollAndScaleForWidthEqualsDeviceWidth)2102 TEST_F(WebFrameResizeTest, ResizeYieldsCorrectScrollAndScaleForWidthEqualsDeviceWidth)
2103 {
2104 // With width=device-width, pageScaleFactor is preserved across resizes as
2105 // long as the content adjusts according to the device-width.
2106 const char* url = "resize_scroll_mobile.html";
2107 const float initialPageScaleFactor = 1;
2108 const WebSize scrollOffset(0, 50);
2109 const WebSize viewportSize(120, 160);
2110 const bool shouldScaleRelativeToViewportWidth = true;
2111
2112 testResizeYieldsCorrectScrollAndScale(
2113 url, initialPageScaleFactor, scrollOffset, viewportSize, shouldScaleRelativeToViewportWidth);
2114 }
2115
TEST_F(WebFrameResizeTest,ResizeYieldsCorrectScrollAndScaleForFixedWidth)2116 TEST_F(WebFrameResizeTest, ResizeYieldsCorrectScrollAndScaleForFixedWidth)
2117 {
2118 // With a fixed width, pageScaleFactor scales by the relative change in viewport width.
2119 const char* url = "resize_scroll_fixed_width.html";
2120 const float initialPageScaleFactor = 2;
2121 const WebSize scrollOffset(0, 200);
2122 const WebSize viewportSize(240, 320);
2123 const bool shouldScaleRelativeToViewportWidth = true;
2124
2125 testResizeYieldsCorrectScrollAndScale(
2126 url, initialPageScaleFactor, scrollOffset, viewportSize, shouldScaleRelativeToViewportWidth);
2127 }
2128
TEST_F(WebFrameResizeTest,ResizeYieldsCorrectScrollAndScaleForFixedLayout)2129 TEST_F(WebFrameResizeTest, ResizeYieldsCorrectScrollAndScaleForFixedLayout)
2130 {
2131 // With a fixed layout, pageScaleFactor scales by the relative change in viewport width.
2132 const char* url = "resize_scroll_fixed_layout.html";
2133 const float initialPageScaleFactor = 2;
2134 const WebSize scrollOffset(200, 400);
2135 const WebSize viewportSize(320, 240);
2136 const bool shouldScaleRelativeToViewportWidth = true;
2137
2138 testResizeYieldsCorrectScrollAndScale(
2139 url, initialPageScaleFactor, scrollOffset, viewportSize, shouldScaleRelativeToViewportWidth);
2140 }
2141
TEST_F(WebFrameTest,pageScaleFactorScalesPaintClip)2142 TEST_F(WebFrameTest, pageScaleFactorScalesPaintClip)
2143 {
2144 UseMockScrollbarSettings mockScrollbarSettings;
2145 registerMockedHttpURLLoad("large-div.html");
2146
2147 FixedLayoutTestWebViewClient client;
2148 client.m_screenInfo.deviceScaleFactor = 1;
2149 int viewportWidth = 50;
2150 int viewportHeight = 50;
2151
2152 FrameTestHelpers::WebViewHelper webViewHelper;
2153 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client);
2154 // FIXME: This test breaks if the viewport is enabled before loading the page due to the paint
2155 // calls below not working on composited layers. For some reason, enabling the viewport here
2156 // doesn't cause compositing
2157 webViewHelper.webView()->settings()->setViewportEnabled(true);
2158 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2159 webViewHelper.webView()->layout();
2160
2161 // Set <1 page scale so that the clip rect should be larger than
2162 // the viewport size as passed into resize().
2163 webViewHelper.webView()->setPageScaleFactor(0.5);
2164
2165 SkBitmap bitmap;
2166 ASSERT_TRUE(bitmap.allocN32Pixels(200, 200));
2167 bitmap.eraseColor(0);
2168 SkCanvas canvas(bitmap);
2169
2170 WebCore::GraphicsContext context(&canvas);
2171 context.setTrackOpaqueRegion(true);
2172
2173 EXPECT_EQ_RECT(WebCore::IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
2174
2175 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
2176 WebCore::IntRect paintRect(0, 0, 200, 200);
2177 view->paint(&context, paintRect);
2178
2179 // FIXME: This test broke in release builds when changing the FixedLayoutTestWebViewClient
2180 // to return a non-null layerTreeView, which is what all our shipping configurations do,
2181 // so this is just exposing an existing bug.
2182 // crbug.com/365812
2183 #ifndef NDEBUG
2184 int viewportWidthMinusScrollbar = 50 - (view->verticalScrollbar()->isOverlayScrollbar() ? 0 : 15);
2185 int viewportHeightMinusScrollbar = 50 - (view->horizontalScrollbar()->isOverlayScrollbar() ? 0 : 15);
2186 WebCore::IntRect clippedRect(0, 0, viewportWidthMinusScrollbar * 2, viewportHeightMinusScrollbar * 2);
2187 EXPECT_EQ_RECT(clippedRect, context.opaqueRegion().asRect());
2188 #endif
2189 }
2190
TEST_F(WebFrameTest,pageScaleFactorUpdatesScrollbars)2191 TEST_F(WebFrameTest, pageScaleFactorUpdatesScrollbars)
2192 {
2193 UseMockScrollbarSettings mockScrollbarSettings;
2194 registerMockedHttpURLLoad("fixed_layout.html");
2195
2196 FixedLayoutTestWebViewClient client;
2197 client.m_screenInfo.deviceScaleFactor = 1;
2198 int viewportWidth = 640;
2199 int viewportHeight = 480;
2200
2201 FrameTestHelpers::WebViewHelper webViewHelper;
2202 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
2203 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2204 webViewHelper.webView()->layout();
2205
2206 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
2207 EXPECT_EQ(view->scrollSize(WebCore::HorizontalScrollbar), view->contentsSize().width() - view->visibleContentRect().width());
2208 EXPECT_EQ(view->scrollSize(WebCore::VerticalScrollbar), view->contentsSize().height() - view->visibleContentRect().height());
2209
2210 webViewHelper.webView()->setPageScaleFactor(10);
2211
2212 EXPECT_EQ(view->scrollSize(WebCore::HorizontalScrollbar), view->contentsSize().width() - view->visibleContentRect().width());
2213 EXPECT_EQ(view->scrollSize(WebCore::VerticalScrollbar), view->contentsSize().height() - view->visibleContentRect().height());
2214 }
2215
TEST_F(WebFrameTest,CanOverrideScaleLimits)2216 TEST_F(WebFrameTest, CanOverrideScaleLimits)
2217 {
2218 UseMockScrollbarSettings mockScrollbarSettings;
2219
2220 registerMockedHttpURLLoad("no_scale_for_you.html");
2221
2222 FixedLayoutTestWebViewClient client;
2223 client.m_screenInfo.deviceScaleFactor = 1;
2224 int viewportWidth = 640;
2225 int viewportHeight = 480;
2226
2227 FrameTestHelpers::WebViewHelper webViewHelper;
2228 webViewHelper.initializeAndLoad(m_baseURL + "no_scale_for_you.html", true, 0, &client, enableViewportSettings);
2229 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2230
2231 EXPECT_EQ(2.0f, webViewHelper.webView()->minimumPageScaleFactor());
2232 EXPECT_EQ(2.0f, webViewHelper.webView()->maximumPageScaleFactor());
2233
2234 webViewHelper.webView()->setIgnoreViewportTagScaleLimits(true);
2235 webViewHelper.webView()->layout();
2236
2237 EXPECT_EQ(1.0f, webViewHelper.webView()->minimumPageScaleFactor());
2238 EXPECT_EQ(5.0f, webViewHelper.webView()->maximumPageScaleFactor());
2239
2240 webViewHelper.webView()->setIgnoreViewportTagScaleLimits(false);
2241 webViewHelper.webView()->layout();
2242
2243 EXPECT_EQ(2.0f, webViewHelper.webView()->minimumPageScaleFactor());
2244 EXPECT_EQ(2.0f, webViewHelper.webView()->maximumPageScaleFactor());
2245 }
2246
TEST_F(WebFrameTest,updateOverlayScrollbarLayers)2247 TEST_F(WebFrameTest, updateOverlayScrollbarLayers)
2248 {
2249 UseMockScrollbarSettings mockScrollbarSettings;
2250
2251 registerMockedHttpURLLoad("large-div.html");
2252
2253 int viewWidth = 500;
2254 int viewHeight = 500;
2255
2256 OwnPtr<FakeCompositingWebViewClient> fakeCompositingWebViewClient = adoptPtr(new FakeCompositingWebViewClient());
2257 FrameTestHelpers::WebViewHelper webViewHelper;
2258 webViewHelper.initialize(true, 0, fakeCompositingWebViewClient.get(), &configueCompositingWebView);
2259
2260 webViewHelper.webView()->setPageScaleFactorLimits(1, 1);
2261 webViewHelper.webView()->resize(WebSize(viewWidth, viewHeight));
2262 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "large-div.html");
2263
2264 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
2265 EXPECT_TRUE(view->renderView()->compositor()->layerForHorizontalScrollbar());
2266 EXPECT_TRUE(view->renderView()->compositor()->layerForVerticalScrollbar());
2267
2268 webViewHelper.webView()->resize(WebSize(viewWidth * 10, viewHeight * 10));
2269 webViewHelper.webView()->layout();
2270 EXPECT_FALSE(view->renderView()->compositor()->layerForHorizontalScrollbar());
2271 EXPECT_FALSE(view->renderView()->compositor()->layerForVerticalScrollbar());
2272 }
2273
setScaleAndScrollAndLayout(blink::WebView * webView,WebPoint scroll,float scale)2274 void setScaleAndScrollAndLayout(blink::WebView* webView, WebPoint scroll, float scale)
2275 {
2276 webView->setPageScaleFactor(scale);
2277 webView->setMainFrameScrollOffset(WebPoint(scroll.x, scroll.y));
2278 webView->layout();
2279 }
2280
TEST_F(WebFrameTest,DivAutoZoomParamsTest)2281 TEST_F(WebFrameTest, DivAutoZoomParamsTest)
2282 {
2283 registerMockedHttpURLLoad("get_scale_for_auto_zoom_into_div_test.html");
2284
2285 const float deviceScaleFactor = 2.0f;
2286 int viewportWidth = 640 / deviceScaleFactor;
2287 int viewportHeight = 1280 / deviceScaleFactor;
2288 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2289 FrameTestHelpers::WebViewHelper webViewHelper;
2290 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_for_auto_zoom_into_div_test.html");
2291 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2292 webViewHelper.webView()->setPageScaleFactorLimits(0.01f, 4);
2293 webViewHelper.webView()->setPageScaleFactor(0.5f);
2294 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2295 webViewHelper.webView()->layout();
2296
2297 WebRect wideDiv(200, 100, 400, 150);
2298 WebRect tallDiv(200, 300, 400, 800);
2299 WebRect doubleTapPointWide(wideDiv.x + 50, wideDiv.y + 50, touchPointPadding, touchPointPadding);
2300 WebRect doubleTapPointTall(tallDiv.x + 50, tallDiv.y + 50, touchPointPadding, touchPointPadding);
2301 WebRect wideBlockBounds;
2302 WebRect tallBlockBounds;
2303 float scale;
2304 WebPoint scroll;
2305
2306 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2307
2308 // Test double-tap zooming into wide div.
2309 wideBlockBounds = webViewHelper.webViewImpl()->computeBlockBounds(doubleTapPointWide, false);
2310 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(doubleTapPointWide.x, doubleTapPointWide.y), wideBlockBounds, touchPointPadding, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2311 // The div should horizontally fill the screen (modulo margins), and
2312 // vertically centered (modulo integer rounding).
2313 EXPECT_NEAR(viewportWidth / (float) wideDiv.width, scale, 0.1);
2314 EXPECT_NEAR(wideDiv.x, scroll.x, 20);
2315 EXPECT_EQ(0, scroll.y);
2316
2317 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), scroll, scale);
2318
2319 // Test zoom out back to minimum scale.
2320 wideBlockBounds = webViewHelper.webViewImpl()->computeBlockBounds(doubleTapPointWide, false);
2321 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(doubleTapPointWide.x, doubleTapPointWide.y), wideBlockBounds, touchPointPadding, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2322
2323 scale = webViewHelper.webViewImpl()->minimumPageScaleFactor();
2324 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), scale);
2325
2326 // Test double-tap zooming into tall div.
2327 tallBlockBounds = webViewHelper.webViewImpl()->computeBlockBounds(doubleTapPointTall, false);
2328 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(doubleTapPointTall.x, doubleTapPointTall.y), tallBlockBounds, touchPointPadding, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2329 // The div should start at the top left of the viewport.
2330 EXPECT_NEAR(viewportWidth / (float) tallDiv.width, scale, 0.1);
2331 EXPECT_NEAR(tallDiv.x, scroll.x, 20);
2332 EXPECT_NEAR(tallDiv.y, scroll.y, 20);
2333
2334 // Test for Non-doubletap scaling
2335 // Test zooming into div.
2336 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(250, 250), webViewHelper.webViewImpl()->computeBlockBounds(WebRect(250, 250, 10, 10), true), 0, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2337 EXPECT_NEAR(viewportWidth / (float) wideDiv.width, scale, 0.1);
2338 }
2339
simulatePageScale(WebViewImpl * webViewImpl,float & scale)2340 void simulatePageScale(WebViewImpl* webViewImpl, float& scale)
2341 {
2342 WebCore::IntSize scrollDelta = webViewImpl->fakePageScaleAnimationTargetPositionForTesting() - webViewImpl->mainFrameImpl()->frameView()->scrollPosition();
2343 float scaleDelta = webViewImpl->fakePageScaleAnimationPageScaleForTesting() / webViewImpl->pageScaleFactor();
2344 webViewImpl->applyScrollAndScale(scrollDelta, scaleDelta);
2345 scale = webViewImpl->pageScaleFactor();
2346 }
2347
simulateMultiTargetZoom(WebViewImpl * webViewImpl,const WebRect & rect,float & scale)2348 void simulateMultiTargetZoom(WebViewImpl* webViewImpl, const WebRect& rect, float& scale)
2349 {
2350 if (webViewImpl->zoomToMultipleTargetsRect(rect))
2351 simulatePageScale(webViewImpl, scale);
2352 }
2353
simulateDoubleTap(WebViewImpl * webViewImpl,WebPoint & point,float & scale)2354 void simulateDoubleTap(WebViewImpl* webViewImpl, WebPoint& point, float& scale)
2355 {
2356 webViewImpl->animateDoubleTapZoom(point);
2357 EXPECT_TRUE(webViewImpl->fakeDoubleTapAnimationPendingForTesting());
2358 simulatePageScale(webViewImpl, scale);
2359 }
2360
TEST_F(WebFrameTest,DivAutoZoomWideDivTest)2361 TEST_F(WebFrameTest, DivAutoZoomWideDivTest)
2362 {
2363 registerMockedHttpURLLoad("get_wide_div_for_auto_zoom_test.html");
2364
2365 const float deviceScaleFactor = 2.0f;
2366 int viewportWidth = 640 / deviceScaleFactor;
2367 int viewportHeight = 1280 / deviceScaleFactor;
2368 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2369 FrameTestHelpers::WebViewHelper webViewHelper;
2370 webViewHelper.initializeAndLoad(m_baseURL + "get_wide_div_for_auto_zoom_test.html");
2371 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2372 webViewHelper.webView()->setPageScaleFactorLimits(1.0f, 4);
2373 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2374 webViewHelper.webView()->setPageScaleFactor(1.0f);
2375 webViewHelper.webView()->layout();
2376
2377 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2378
2379 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2380
2381 WebRect div(0, 100, viewportWidth, 150);
2382 WebPoint point(div.x + 50, div.y + 50);
2383 float scale;
2384 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2385
2386 simulateDoubleTap(webViewHelper.webViewImpl(), point, scale);
2387 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2388 simulateDoubleTap(webViewHelper.webViewImpl(), point, scale);
2389 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2390 }
2391
TEST_F(WebFrameTest,DivAutoZoomVeryTallTest)2392 TEST_F(WebFrameTest, DivAutoZoomVeryTallTest)
2393 {
2394 // When a block is taller than the viewport and a zoom targets a lower part
2395 // of it, then we should keep the target point onscreen instead of snapping
2396 // back up the top of the block.
2397 registerMockedHttpURLLoad("very_tall_div.html");
2398
2399 const float deviceScaleFactor = 2.0f;
2400 int viewportWidth = 640 / deviceScaleFactor;
2401 int viewportHeight = 1280 / deviceScaleFactor;
2402 FrameTestHelpers::WebViewHelper webViewHelper;
2403 webViewHelper.initializeAndLoad(m_baseURL + "very_tall_div.html", true, 0, 0, enableViewportSettings);
2404 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2405 webViewHelper.webView()->setPageScaleFactorLimits(1.0f, 4);
2406 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2407 webViewHelper.webView()->setPageScaleFactor(1.0f);
2408 webViewHelper.webView()->layout();
2409
2410 WebRect div(200, 300, 400, 5000);
2411 WebPoint point(div.x + 50, div.y + 3000);
2412 float scale;
2413 WebPoint scroll;
2414
2415 WebRect blockBounds = webViewHelper.webViewImpl()->computeBlockBounds(WebRect(point.x, point.y, 0, 0), true);
2416 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(point, blockBounds, 0, 1.0f, scale, scroll);
2417 EXPECT_EQ(scale, 1.0f);
2418 EXPECT_EQ(scroll.y, 2660);
2419 }
2420
TEST_F(WebFrameTest,DivAutoZoomMultipleDivsTest)2421 TEST_F(WebFrameTest, DivAutoZoomMultipleDivsTest)
2422 {
2423 registerMockedHttpURLLoad("get_multiple_divs_for_auto_zoom_test.html");
2424
2425 const float deviceScaleFactor = 2.0f;
2426 int viewportWidth = 640 / deviceScaleFactor;
2427 int viewportHeight = 1280 / deviceScaleFactor;
2428 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2429 FrameTestHelpers::WebViewHelper webViewHelper;
2430 webViewHelper.initializeAndLoad(m_baseURL + "get_multiple_divs_for_auto_zoom_test.html");
2431 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2432 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2433 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2434 webViewHelper.webView()->setPageScaleFactor(0.5f);
2435 webViewHelper.webView()->layout();
2436
2437 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2438
2439 WebRect topDiv(200, 100, 200, 150);
2440 WebRect bottomDiv(200, 300, 200, 150);
2441 WebPoint topPoint(topDiv.x + 50, topDiv.y + 50);
2442 WebPoint bottomPoint(bottomDiv.x + 50, bottomDiv.y + 50);
2443 float scale;
2444 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2445
2446 // Test double tap on two different divs
2447 // After first zoom, we should go back to minimum page scale with a second double tap.
2448 simulateDoubleTap(webViewHelper.webViewImpl(), topPoint, scale);
2449 EXPECT_FLOAT_EQ(1, scale);
2450 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2451 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2452
2453 // If the user pinch zooms after double tap, a second double tap should zoom back to the div.
2454 simulateDoubleTap(webViewHelper.webViewImpl(), topPoint, scale);
2455 EXPECT_FLOAT_EQ(1, scale);
2456 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 0.6f);
2457 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2458 EXPECT_FLOAT_EQ(1, scale);
2459 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2460 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2461
2462 // If we didn't yet get an auto-zoom update and a second double-tap arrives, should go back to minimum scale.
2463 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2464 webViewHelper.webViewImpl()->animateDoubleTapZoom(topPoint);
2465 EXPECT_TRUE(webViewHelper.webViewImpl()->fakeDoubleTapAnimationPendingForTesting());
2466 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2467 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2468 }
2469
TEST_F(WebFrameTest,DivAutoZoomScaleBoundsTest)2470 TEST_F(WebFrameTest, DivAutoZoomScaleBoundsTest)
2471 {
2472 registerMockedHttpURLLoad("get_scale_bounds_check_for_auto_zoom_test.html");
2473
2474 int viewportWidth = 320;
2475 int viewportHeight = 480;
2476 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2477 FrameTestHelpers::WebViewHelper webViewHelper;
2478 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_bounds_check_for_auto_zoom_test.html");
2479 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2480 webViewHelper.webView()->setDeviceScaleFactor(1.5f);
2481 webViewHelper.webView()->layout();
2482
2483 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2484
2485 WebRect div(200, 100, 200, 150);
2486 WebPoint doubleTapPoint(div.x + 50, div.y + 50);
2487 float scale;
2488
2489 // Test double tap scale bounds.
2490 // minimumPageScale < doubleTapZoomAlreadyLegibleScale < 1
2491 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2492 webViewHelper.webView()->layout();
2493 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2494 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2495 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2496 EXPECT_FLOAT_EQ(1, scale);
2497 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2498 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2499 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2500 EXPECT_FLOAT_EQ(1, scale);
2501
2502 // Zoom in to reset double_tap_zoom_in_effect flag.
2503 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2504 // 1 < minimumPageScale < doubleTapZoomAlreadyLegibleScale
2505 webViewHelper.webView()->setPageScaleFactorLimits(1.1f, 4);
2506 webViewHelper.webView()->layout();
2507 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2508 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2509 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2510 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2511 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2512 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2513 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2514 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2515
2516 // Zoom in to reset double_tap_zoom_in_effect flag.
2517 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2518 // minimumPageScale < 1 < doubleTapZoomAlreadyLegibleScale
2519 webViewHelper.webView()->setPageScaleFactorLimits(0.95f, 4);
2520 webViewHelper.webView()->layout();
2521 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2522 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2523 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2524 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2525 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2526 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2527 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2528 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2529 }
2530
TEST_F(WebFrameTest,DivAutoZoomScaleFontScaleFactorTest)2531 TEST_F(WebFrameTest, DivAutoZoomScaleFontScaleFactorTest)
2532 {
2533 registerMockedHttpURLLoad("get_scale_bounds_check_for_auto_zoom_test.html");
2534
2535 int viewportWidth = 320;
2536 int viewportHeight = 480;
2537 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2538 float accessibilityFontScaleFactor = 1.13f;
2539 FrameTestHelpers::WebViewHelper webViewHelper;
2540 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_bounds_check_for_auto_zoom_test.html");
2541 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2542 webViewHelper.webView()->layout();
2543
2544 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2545 webViewHelper.webViewImpl()->page()->settings().setTextAutosizingEnabled(true);
2546 webViewHelper.webViewImpl()->page()->settings().setAccessibilityFontScaleFactor(accessibilityFontScaleFactor);
2547
2548 WebRect div(200, 100, 200, 150);
2549 WebPoint doubleTapPoint(div.x + 50, div.y + 50);
2550 float scale;
2551
2552 // Test double tap scale bounds.
2553 // minimumPageScale < doubleTapZoomAlreadyLegibleScale < 1 < accessibilityFontScaleFactor
2554 float legibleScale = accessibilityFontScaleFactor;
2555 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2556 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2557 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2558 webViewHelper.webView()->layout();
2559 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2560 EXPECT_FLOAT_EQ(legibleScale, scale);
2561 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2562 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2563 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2564 EXPECT_FLOAT_EQ(legibleScale, scale);
2565
2566 // Zoom in to reset double_tap_zoom_in_effect flag.
2567 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2568 // 1 < accessibilityFontScaleFactor < minimumPageScale < doubleTapZoomAlreadyLegibleScale
2569 webViewHelper.webView()->setPageScaleFactorLimits(1.0f, 4);
2570 webViewHelper.webView()->layout();
2571 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2572 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2573 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2574 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2575 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2576 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2577 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2578 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2579
2580 // Zoom in to reset double_tap_zoom_in_effect flag.
2581 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2582 // minimumPageScale < 1 < accessibilityFontScaleFactor < doubleTapZoomAlreadyLegibleScale
2583 webViewHelper.webView()->setPageScaleFactorLimits(0.95f, 4);
2584 webViewHelper.webView()->layout();
2585 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2586 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2587 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2588 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2589 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2590 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2591 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2592 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2593
2594 // Zoom in to reset double_tap_zoom_in_effect flag.
2595 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2596 // minimumPageScale < 1 < doubleTapZoomAlreadyLegibleScale < accessibilityFontScaleFactor
2597 webViewHelper.webView()->setPageScaleFactorLimits(0.9f, 4);
2598 webViewHelper.webView()->layout();
2599 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2600 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2601 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2602 EXPECT_FLOAT_EQ(legibleScale, scale);
2603 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2604 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2605 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2606 EXPECT_FLOAT_EQ(legibleScale, scale);
2607 }
2608
TEST_F(WebFrameTest,DivMultipleTargetZoomMultipleDivsTest)2609 TEST_F(WebFrameTest, DivMultipleTargetZoomMultipleDivsTest)
2610 {
2611 registerMockedHttpURLLoad("get_multiple_divs_for_auto_zoom_test.html");
2612
2613 const float deviceScaleFactor = 2.0f;
2614 int viewportWidth = 640 / deviceScaleFactor;
2615 int viewportHeight = 1280 / deviceScaleFactor;
2616 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2617 FrameTestHelpers::WebViewHelper webViewHelper;
2618 webViewHelper.initializeAndLoad(m_baseURL + "get_multiple_divs_for_auto_zoom_test.html");
2619 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2620 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2621 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2622 webViewHelper.webView()->setPageScaleFactor(0.5f);
2623 webViewHelper.webView()->layout();
2624
2625 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2626
2627 WebRect viewportRect(0, 0, viewportWidth, viewportHeight);
2628 WebRect topDiv(200, 100, 200, 150);
2629 WebRect bottomDiv(200, 300, 200, 150);
2630 float scale;
2631 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2632
2633 simulateMultiTargetZoom(webViewHelper.webViewImpl(), topDiv, scale);
2634 EXPECT_FLOAT_EQ(1, scale);
2635 simulateMultiTargetZoom(webViewHelper.webViewImpl(), bottomDiv, scale);
2636 EXPECT_FLOAT_EQ(1, scale);
2637 simulateMultiTargetZoom(webViewHelper.webViewImpl(), viewportRect, scale);
2638 EXPECT_FLOAT_EQ(1, scale);
2639 webViewHelper.webViewImpl()->setPageScaleFactor(webViewHelper.webViewImpl()->minimumPageScaleFactor());
2640 simulateMultiTargetZoom(webViewHelper.webViewImpl(), topDiv, scale);
2641 EXPECT_FLOAT_EQ(1, scale);
2642 }
2643
TEST_F(WebFrameTest,DivScrollIntoEditableTest)2644 TEST_F(WebFrameTest, DivScrollIntoEditableTest)
2645 {
2646 registerMockedHttpURLLoad("get_scale_for_zoom_into_editable_test.html");
2647
2648 int viewportWidth = 450;
2649 int viewportHeight = 300;
2650 float leftBoxRatio = 0.3f;
2651 int caretPadding = 10;
2652 float minReadableCaretHeight = 18.0f;
2653 FrameTestHelpers::WebViewHelper webViewHelper;
2654 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_for_zoom_into_editable_test.html");
2655 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2656 webViewHelper.webView()->setPageScaleFactorLimits(1, 4);
2657 webViewHelper.webView()->layout();
2658 webViewHelper.webView()->setDeviceScaleFactor(1.5f);
2659 webViewHelper.webView()->settings()->setAutoZoomFocusedNodeToLegibleScale(true);
2660
2661 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2662
2663 WebRect editBoxWithText(200, 200, 250, 20);
2664 WebRect editBoxWithNoText(200, 250, 250, 20);
2665
2666 // Test scrolling the focused node
2667 // The edit box is shorter and narrower than the viewport when legible.
2668 webViewHelper.webView()->advanceFocus(false);
2669 // Set the caret to the end of the input box.
2670 webViewHelper.webView()->mainFrame()->document().getElementById("EditBoxWithText").to<WebInputElement>().setSelectionRange(1000, 1000);
2671 setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), 1);
2672 WebRect rect, caret;
2673 webViewHelper.webViewImpl()->selectionBounds(caret, rect);
2674
2675 float scale;
2676 WebCore::IntPoint scroll;
2677 bool needAnimation;
2678 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2679 EXPECT_TRUE(needAnimation);
2680 // The edit box should be left aligned with a margin for possible label.
2681 int hScroll = editBoxWithText.x - leftBoxRatio * viewportWidth / scale;
2682 EXPECT_NEAR(hScroll, scroll.x(), 1);
2683 int vScroll = editBoxWithText.y - (viewportHeight / scale - editBoxWithText.height) / 2;
2684 EXPECT_NEAR(vScroll, scroll.y(), 1);
2685 EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1);
2686
2687 // The edit box is wider than the viewport when legible.
2688 viewportWidth = 200;
2689 viewportHeight = 150;
2690 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2691 setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), 1);
2692 webViewHelper.webViewImpl()->selectionBounds(caret, rect);
2693 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2694 EXPECT_TRUE(needAnimation);
2695 // The caret should be right aligned since the caret would be offscreen when the edit box is left aligned.
2696 hScroll = caret.x + caret.width + caretPadding - viewportWidth / scale;
2697 EXPECT_NEAR(hScroll, scroll.x(), 1);
2698 EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1);
2699
2700 setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), 1);
2701 // Move focus to edit box with text.
2702 webViewHelper.webView()->advanceFocus(false);
2703 webViewHelper.webViewImpl()->selectionBounds(caret, rect);
2704 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2705 EXPECT_TRUE(needAnimation);
2706 // The edit box should be left aligned.
2707 hScroll = editBoxWithNoText.x;
2708 EXPECT_NEAR(hScroll, scroll.x(), 1);
2709 vScroll = editBoxWithNoText.y - (viewportHeight / scale - editBoxWithNoText.height) / 2;
2710 EXPECT_NEAR(vScroll, scroll.y(), 1);
2711 EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1);
2712
2713 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), scroll, scale);
2714
2715 // Move focus back to the first edit box.
2716 webViewHelper.webView()->advanceFocus(true);
2717 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2718 // The position should have stayed the same since this box was already on screen with the right scale.
2719 EXPECT_FALSE(needAnimation);
2720 }
2721
2722 class TestReloadDoesntRedirectWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
2723 public:
decidePolicyForNavigation(WebLocalFrame *,WebDataSource::ExtraData *,const WebURLRequest &,WebNavigationType,WebNavigationPolicy defaultPolicy,bool isRedirect)2724 virtual WebNavigationPolicy decidePolicyForNavigation(
2725 WebLocalFrame*, WebDataSource::ExtraData*, const WebURLRequest&, WebNavigationType,
2726 WebNavigationPolicy defaultPolicy, bool isRedirect) OVERRIDE
2727 {
2728 EXPECT_FALSE(isRedirect);
2729 return WebNavigationPolicyCurrentTab;
2730 }
2731 };
2732
TEST_F(WebFrameTest,ReloadDoesntSetRedirect)2733 TEST_F(WebFrameTest, ReloadDoesntSetRedirect)
2734 {
2735 // Test for case in http://crbug.com/73104. Reloading a frame very quickly
2736 // would sometimes call decidePolicyForNavigation with isRedirect=true
2737 registerMockedHttpURLLoad("form.html");
2738
2739 TestReloadDoesntRedirectWebFrameClient webFrameClient;
2740 FrameTestHelpers::WebViewHelper webViewHelper;
2741 webViewHelper.initializeAndLoad(m_baseURL + "form.html", false, &webFrameClient);
2742
2743 webViewHelper.webView()->mainFrame()->reload(true);
2744 // start another reload before request is delivered.
2745 FrameTestHelpers::reloadFrameIgnoringCache(webViewHelper.webView()->mainFrame());
2746 }
2747
2748 class ReloadWithOverrideURLTask : public WebThread::Task {
2749 public:
ReloadWithOverrideURLTask(WebFrame * frame,const WebCore::KURL & url,bool ignoreCache)2750 ReloadWithOverrideURLTask(WebFrame* frame, const WebCore::KURL& url, bool ignoreCache)
2751 : m_frame(frame), m_url(url), m_ignoreCache(ignoreCache)
2752 {
2753 }
2754
run()2755 virtual void run() OVERRIDE
2756 {
2757 m_frame->reloadWithOverrideURL(m_url, m_ignoreCache);
2758 }
2759
2760 private:
2761 WebFrame* const m_frame;
2762 const WebCore::KURL m_url;
2763 const bool m_ignoreCache;
2764 };
2765
TEST_F(WebFrameTest,ReloadWithOverrideURLPreservesState)2766 TEST_F(WebFrameTest, ReloadWithOverrideURLPreservesState)
2767 {
2768 const std::string firstURL = "find.html";
2769 const std::string secondURL = "form.html";
2770 const std::string thirdURL = "history.html";
2771 const float pageScaleFactor = 1.1684f;
2772 const int pageWidth = 640;
2773 const int pageHeight = 480;
2774
2775 registerMockedHttpURLLoad(firstURL);
2776 registerMockedHttpURLLoad(secondURL);
2777 registerMockedHttpURLLoad(thirdURL);
2778
2779 FrameTestHelpers::WebViewHelper webViewHelper;
2780 webViewHelper.initializeAndLoad(m_baseURL + firstURL, true);
2781 webViewHelper.webViewImpl()->resize(WebSize(pageWidth, pageHeight));
2782 webViewHelper.webViewImpl()->mainFrame()->setScrollOffset(WebSize(pageWidth / 4, pageHeight / 4));
2783 webViewHelper.webViewImpl()->setPageScaleFactor(pageScaleFactor);
2784
2785 WebSize previousOffset = webViewHelper.webViewImpl()->mainFrame()->scrollOffset();
2786 float previousScale = webViewHelper.webViewImpl()->pageScaleFactor();
2787
2788 // Reload the page using the cache.
2789 Platform::current()->currentThread()->postTask(
2790 new ReloadWithOverrideURLTask(webViewHelper.webViewImpl()->mainFrame(), toKURL(m_baseURL + secondURL), false));
2791 FrameTestHelpers::pumpPendingRequestsDoNotUse(webViewHelper.webViewImpl()->mainFrame());
2792 ASSERT_EQ(previousOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
2793 ASSERT_EQ(previousScale, webViewHelper.webViewImpl()->pageScaleFactor());
2794
2795 // Reload the page while ignoring the cache.
2796 Platform::current()->currentThread()->postTask(
2797 new ReloadWithOverrideURLTask(webViewHelper.webViewImpl()->mainFrame(), toKURL(m_baseURL + thirdURL), true));
2798 FrameTestHelpers::pumpPendingRequestsDoNotUse(webViewHelper.webViewImpl()->mainFrame());
2799 ASSERT_EQ(previousOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
2800 ASSERT_EQ(previousScale, webViewHelper.webViewImpl()->pageScaleFactor());
2801 }
2802
TEST_F(WebFrameTest,ReloadWhileProvisional)2803 TEST_F(WebFrameTest, ReloadWhileProvisional)
2804 {
2805 // Test that reloading while the previous load is still pending does not cause the initial
2806 // request to get lost.
2807 registerMockedHttpURLLoad("fixed_layout.html");
2808
2809 FrameTestHelpers::WebViewHelper webViewHelper;
2810 webViewHelper.initialize();
2811 WebURLRequest request;
2812 request.initialize();
2813 request.setURL(toKURL(m_baseURL + "fixed_layout.html"));
2814 webViewHelper.webView()->mainFrame()->loadRequest(request);
2815 // start reload before first request is delivered.
2816 FrameTestHelpers::reloadFrameIgnoringCache(webViewHelper.webView()->mainFrame());
2817
2818 WebDataSource* dataSource = webViewHelper.webView()->mainFrame()->dataSource();
2819 ASSERT_TRUE(dataSource);
2820 EXPECT_EQ(toKURL(m_baseURL + "fixed_layout.html"), toKURL(dataSource->request().url().spec()));
2821 }
2822
TEST_F(WebFrameTest,AppendRedirects)2823 TEST_F(WebFrameTest, AppendRedirects)
2824 {
2825 const std::string firstURL = "about:blank";
2826 const std::string secondURL = "http://www.test.com";
2827
2828 FrameTestHelpers::WebViewHelper webViewHelper;
2829 webViewHelper.initializeAndLoad(firstURL, true);
2830
2831 WebDataSource* dataSource = webViewHelper.webView()->mainFrame()->dataSource();
2832 ASSERT_TRUE(dataSource);
2833 dataSource->appendRedirect(toKURL(secondURL));
2834
2835 WebVector<WebURL> redirects;
2836 dataSource->redirectChain(redirects);
2837 ASSERT_EQ(2U, redirects.size());
2838 EXPECT_EQ(toKURL(firstURL), toKURL(redirects[0].spec().data()));
2839 EXPECT_EQ(toKURL(secondURL), toKURL(redirects[1].spec().data()));
2840 }
2841
TEST_F(WebFrameTest,IframeRedirect)2842 TEST_F(WebFrameTest, IframeRedirect)
2843 {
2844 registerMockedHttpURLLoad("iframe_redirect.html");
2845 registerMockedHttpURLLoad("visible_iframe.html");
2846
2847 FrameTestHelpers::WebViewHelper webViewHelper;
2848 webViewHelper.initializeAndLoad(m_baseURL + "iframe_redirect.html", true);
2849 // Pump pending requests one more time. The test page loads script that navigates.
2850 FrameTestHelpers::pumpPendingRequestsDoNotUse(webViewHelper.webView()->mainFrame());
2851
2852 WebFrame* iframe = webViewHelper.webView()->findFrameByName(WebString::fromUTF8("ifr"));
2853 ASSERT_TRUE(iframe);
2854 WebDataSource* iframeDataSource = iframe->dataSource();
2855 ASSERT_TRUE(iframeDataSource);
2856 WebVector<WebURL> redirects;
2857 iframeDataSource->redirectChain(redirects);
2858 ASSERT_EQ(2U, redirects.size());
2859 EXPECT_EQ(toKURL("about:blank"), toKURL(redirects[0].spec().data()));
2860 EXPECT_EQ(toKURL("http://www.test.com/visible_iframe.html"), toKURL(redirects[1].spec().data()));
2861 }
2862
TEST_F(WebFrameTest,ClearFocusedNodeTest)2863 TEST_F(WebFrameTest, ClearFocusedNodeTest)
2864 {
2865 registerMockedHttpURLLoad("iframe_clear_focused_node_test.html");
2866 registerMockedHttpURLLoad("autofocus_input_field_iframe.html");
2867
2868 FrameTestHelpers::WebViewHelper webViewHelper;
2869 webViewHelper.initializeAndLoad(m_baseURL + "iframe_clear_focused_node_test.html", true);
2870
2871 // Clear the focused node.
2872 webViewHelper.webView()->clearFocusedElement();
2873
2874 // Now retrieve the FocusedNode and test it should be null.
2875 EXPECT_EQ(0, webViewHelper.webViewImpl()->focusedElement());
2876 }
2877
2878 // Implementation of WebFrameClient that tracks the v8 contexts that are created
2879 // and destroyed for verification.
2880 class ContextLifetimeTestWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
2881 public:
2882 struct Notification {
2883 public:
Notification__anonf4dfb8060111::ContextLifetimeTestWebFrameClient::Notification2884 Notification(WebLocalFrame* frame, v8::Handle<v8::Context> context, int worldId)
2885 : frame(frame)
2886 , context(context->GetIsolate(), context)
2887 , worldId(worldId)
2888 {
2889 }
2890
~Notification__anonf4dfb8060111::ContextLifetimeTestWebFrameClient::Notification2891 ~Notification()
2892 {
2893 context.Reset();
2894 }
2895
Equals__anonf4dfb8060111::ContextLifetimeTestWebFrameClient::Notification2896 bool Equals(Notification* other)
2897 {
2898 return other && frame == other->frame && context == other->context && worldId == other->worldId;
2899 }
2900
2901 WebLocalFrame* frame;
2902 v8::Persistent<v8::Context> context;
2903 int worldId;
2904 };
2905
~ContextLifetimeTestWebFrameClient()2906 virtual ~ContextLifetimeTestWebFrameClient()
2907 {
2908 reset();
2909 }
2910
reset()2911 void reset()
2912 {
2913 for (size_t i = 0; i < createNotifications.size(); ++i)
2914 delete createNotifications[i];
2915
2916 for (size_t i = 0; i < releaseNotifications.size(); ++i)
2917 delete releaseNotifications[i];
2918
2919 createNotifications.clear();
2920 releaseNotifications.clear();
2921 }
2922
2923 std::vector<Notification*> createNotifications;
2924 std::vector<Notification*> releaseNotifications;
2925
2926 private:
didCreateScriptContext(WebLocalFrame * frame,v8::Handle<v8::Context> context,int extensionGroup,int worldId)2927 virtual void didCreateScriptContext(WebLocalFrame* frame, v8::Handle<v8::Context> context, int extensionGroup, int worldId) OVERRIDE
2928 {
2929 createNotifications.push_back(new Notification(frame, context, worldId));
2930 }
2931
willReleaseScriptContext(WebLocalFrame * frame,v8::Handle<v8::Context> context,int worldId)2932 virtual void willReleaseScriptContext(WebLocalFrame* frame, v8::Handle<v8::Context> context, int worldId) OVERRIDE
2933 {
2934 releaseNotifications.push_back(new Notification(frame, context, worldId));
2935 }
2936 };
2937
2938 // TODO(aa): Deflake this test.
TEST_F(WebFrameTest,FLAKY_ContextNotificationsLoadUnload)2939 TEST_F(WebFrameTest, FLAKY_ContextNotificationsLoadUnload)
2940 {
2941 v8::HandleScope handleScope(v8::Isolate::GetCurrent());
2942
2943 registerMockedHttpURLLoad("context_notifications_test.html");
2944 registerMockedHttpURLLoad("context_notifications_test_frame.html");
2945
2946 // Load a frame with an iframe, make sure we get the right create notifications.
2947 ContextLifetimeTestWebFrameClient webFrameClient;
2948 FrameTestHelpers::WebViewHelper webViewHelper;
2949 webViewHelper.initializeAndLoad(m_baseURL + "context_notifications_test.html", true, &webFrameClient);
2950
2951 WebFrame* mainFrame = webViewHelper.webView()->mainFrame();
2952 WebFrame* childFrame = mainFrame->firstChild();
2953
2954 ASSERT_EQ(2u, webFrameClient.createNotifications.size());
2955 EXPECT_EQ(0u, webFrameClient.releaseNotifications.size());
2956
2957 ContextLifetimeTestWebFrameClient::Notification* firstCreateNotification = webFrameClient.createNotifications[0];
2958 ContextLifetimeTestWebFrameClient::Notification* secondCreateNotification = webFrameClient.createNotifications[1];
2959
2960 EXPECT_EQ(mainFrame, firstCreateNotification->frame);
2961 EXPECT_EQ(mainFrame->mainWorldScriptContext(), firstCreateNotification->context);
2962 EXPECT_EQ(0, firstCreateNotification->worldId);
2963
2964 EXPECT_EQ(childFrame, secondCreateNotification->frame);
2965 EXPECT_EQ(childFrame->mainWorldScriptContext(), secondCreateNotification->context);
2966 EXPECT_EQ(0, secondCreateNotification->worldId);
2967
2968 // Close the view. We should get two release notifications that are exactly the same as the create ones, in reverse order.
2969 webViewHelper.reset();
2970
2971 ASSERT_EQ(2u, webFrameClient.releaseNotifications.size());
2972 ContextLifetimeTestWebFrameClient::Notification* firstReleaseNotification = webFrameClient.releaseNotifications[0];
2973 ContextLifetimeTestWebFrameClient::Notification* secondReleaseNotification = webFrameClient.releaseNotifications[1];
2974
2975 ASSERT_TRUE(firstCreateNotification->Equals(secondReleaseNotification));
2976 ASSERT_TRUE(secondCreateNotification->Equals(firstReleaseNotification));
2977 }
2978
TEST_F(WebFrameTest,ContextNotificationsReload)2979 TEST_F(WebFrameTest, ContextNotificationsReload)
2980 {
2981 v8::HandleScope handleScope(v8::Isolate::GetCurrent());
2982
2983 registerMockedHttpURLLoad("context_notifications_test.html");
2984 registerMockedHttpURLLoad("context_notifications_test_frame.html");
2985
2986 ContextLifetimeTestWebFrameClient webFrameClient;
2987 FrameTestHelpers::WebViewHelper webViewHelper;
2988 webViewHelper.initializeAndLoad(m_baseURL + "context_notifications_test.html", true, &webFrameClient);
2989
2990 // Refresh, we should get two release notifications and two more create notifications.
2991 FrameTestHelpers::reloadFrame(webViewHelper.webView()->mainFrame());
2992 ASSERT_EQ(4u, webFrameClient.createNotifications.size());
2993 ASSERT_EQ(2u, webFrameClient.releaseNotifications.size());
2994
2995 // The two release notifications we got should be exactly the same as the first two create notifications.
2996 for (size_t i = 0; i < webFrameClient.releaseNotifications.size(); ++i) {
2997 EXPECT_TRUE(webFrameClient.releaseNotifications[i]->Equals(
2998 webFrameClient.createNotifications[webFrameClient.createNotifications.size() - 3 - i]));
2999 }
3000
3001 // The last two create notifications should be for the current frames and context.
3002 WebFrame* mainFrame = webViewHelper.webView()->mainFrame();
3003 WebFrame* childFrame = mainFrame->firstChild();
3004 ContextLifetimeTestWebFrameClient::Notification* firstRefreshNotification = webFrameClient.createNotifications[2];
3005 ContextLifetimeTestWebFrameClient::Notification* secondRefreshNotification = webFrameClient.createNotifications[3];
3006
3007 EXPECT_EQ(mainFrame, firstRefreshNotification->frame);
3008 EXPECT_EQ(mainFrame->mainWorldScriptContext(), firstRefreshNotification->context);
3009 EXPECT_EQ(0, firstRefreshNotification->worldId);
3010
3011 EXPECT_EQ(childFrame, secondRefreshNotification->frame);
3012 EXPECT_EQ(childFrame->mainWorldScriptContext(), secondRefreshNotification->context);
3013 EXPECT_EQ(0, secondRefreshNotification->worldId);
3014 }
3015
TEST_F(WebFrameTest,ContextNotificationsIsolatedWorlds)3016 TEST_F(WebFrameTest, ContextNotificationsIsolatedWorlds)
3017 {
3018 v8::Isolate* isolate = v8::Isolate::GetCurrent();
3019 v8::HandleScope handleScope(isolate);
3020
3021 registerMockedHttpURLLoad("context_notifications_test.html");
3022 registerMockedHttpURLLoad("context_notifications_test_frame.html");
3023
3024 ContextLifetimeTestWebFrameClient webFrameClient;
3025 FrameTestHelpers::WebViewHelper webViewHelper;
3026 webViewHelper.initializeAndLoad(m_baseURL + "context_notifications_test.html", true, &webFrameClient);
3027
3028 // Add an isolated world.
3029 webFrameClient.reset();
3030
3031 int isolatedWorldId = 42;
3032 WebScriptSource scriptSource("hi!");
3033 int numSources = 1;
3034 int extensionGroup = 0;
3035 webViewHelper.webView()->mainFrame()->executeScriptInIsolatedWorld(isolatedWorldId, &scriptSource, numSources, extensionGroup);
3036
3037 // We should now have a new create notification.
3038 ASSERT_EQ(1u, webFrameClient.createNotifications.size());
3039 ContextLifetimeTestWebFrameClient::Notification* notification = webFrameClient.createNotifications[0];
3040 ASSERT_EQ(isolatedWorldId, notification->worldId);
3041 ASSERT_EQ(webViewHelper.webView()->mainFrame(), notification->frame);
3042
3043 // We don't have an API to enumarate isolated worlds for a frame, but we can at least assert that the context we got is *not* the main world's context.
3044 ASSERT_NE(webViewHelper.webView()->mainFrame()->mainWorldScriptContext(), v8::Local<v8::Context>::New(isolate, notification->context));
3045
3046 webViewHelper.reset();
3047
3048 // We should have gotten three release notifications (one for each of the frames, plus one for the isolated context).
3049 ASSERT_EQ(3u, webFrameClient.releaseNotifications.size());
3050
3051 // And one of them should be exactly the same as the create notification for the isolated context.
3052 int matchCount = 0;
3053 for (size_t i = 0; i < webFrameClient.releaseNotifications.size(); ++i) {
3054 if (webFrameClient.releaseNotifications[i]->Equals(webFrameClient.createNotifications[0]))
3055 ++matchCount;
3056 }
3057 EXPECT_EQ(1, matchCount);
3058 }
3059
TEST_F(WebFrameTest,FindInPage)3060 TEST_F(WebFrameTest, FindInPage)
3061 {
3062 registerMockedHttpURLLoad("find.html");
3063 FrameTestHelpers::WebViewHelper webViewHelper;
3064 webViewHelper.initializeAndLoad(m_baseURL + "find.html");
3065 WebFrame* frame = webViewHelper.webView()->mainFrame();
3066 const int findIdentifier = 12345;
3067 WebFindOptions options;
3068
3069 // Find in a <div> element.
3070 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar1"), options, false, 0));
3071 frame->stopFinding(false);
3072 WebRange range = frame->selectionRange();
3073 EXPECT_EQ(5, range.startOffset());
3074 EXPECT_EQ(9, range.endOffset());
3075 EXPECT_TRUE(frame->document().focusedElement().isNull());
3076
3077 // Find in an <input> value.
3078 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar2"), options, false, 0));
3079 // Confirm stopFinding(false) sets the selection on the found text.
3080 frame->stopFinding(false);
3081 range = frame->selectionRange();
3082 ASSERT_FALSE(range.isNull());
3083 EXPECT_EQ(5, range.startOffset());
3084 EXPECT_EQ(9, range.endOffset());
3085 EXPECT_EQ(WebString::fromUTF8("INPUT"), frame->document().focusedElement().tagName());
3086
3087 // Find in a <textarea> content.
3088 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar3"), options, false, 0));
3089 // Confirm stopFinding(false) sets the selection on the found text.
3090 frame->stopFinding(false);
3091 range = frame->selectionRange();
3092 ASSERT_FALSE(range.isNull());
3093 EXPECT_EQ(5, range.startOffset());
3094 EXPECT_EQ(9, range.endOffset());
3095 EXPECT_EQ(WebString::fromUTF8("TEXTAREA"), frame->document().focusedElement().tagName());
3096
3097 // Find in a contentEditable element.
3098 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar4"), options, false, 0));
3099 // Confirm stopFinding(false) sets the selection on the found text.
3100 frame->stopFinding(false);
3101 range = frame->selectionRange();
3102 ASSERT_FALSE(range.isNull());
3103 EXPECT_EQ(0, range.startOffset());
3104 EXPECT_EQ(4, range.endOffset());
3105 // "bar4" is surrounded by <span>, but the focusable node should be the parent <div>.
3106 EXPECT_EQ(WebString::fromUTF8("DIV"), frame->document().focusedElement().tagName());
3107
3108 // Find in <select> content.
3109 EXPECT_FALSE(frame->find(findIdentifier, WebString::fromUTF8("bar5"), options, false, 0));
3110 // If there are any matches, stopFinding will set the selection on the found text.
3111 // However, we do not expect any matches, so check that the selection is null.
3112 frame->stopFinding(false);
3113 range = frame->selectionRange();
3114 ASSERT_TRUE(range.isNull());
3115 }
3116
TEST_F(WebFrameTest,GetContentAsPlainText)3117 TEST_F(WebFrameTest, GetContentAsPlainText)
3118 {
3119 FrameTestHelpers::WebViewHelper webViewHelper;
3120 webViewHelper.initializeAndLoad("about:blank", true);
3121 // We set the size because it impacts line wrapping, which changes the
3122 // resulting text value.
3123 webViewHelper.webView()->resize(WebSize(640, 480));
3124 WebFrame* frame = webViewHelper.webView()->mainFrame();
3125
3126 // Generate a simple test case.
3127 const char simpleSource[] = "<div>Foo bar</div><div></div>baz";
3128 WebCore::KURL testURL = toKURL("about:blank");
3129 FrameTestHelpers::loadHTMLString(frame, simpleSource, testURL);
3130
3131 // Make sure it comes out OK.
3132 const std::string expected("Foo bar\nbaz");
3133 WebString text = frame->contentAsText(std::numeric_limits<size_t>::max());
3134 EXPECT_EQ(expected, text.utf8());
3135
3136 // Try reading the same one with clipping of the text.
3137 const int length = 5;
3138 text = frame->contentAsText(length);
3139 EXPECT_EQ(expected.substr(0, length), text.utf8());
3140
3141 // Now do a new test with a subframe.
3142 const char outerFrameSource[] = "Hello<iframe></iframe> world";
3143 FrameTestHelpers::loadHTMLString(frame, outerFrameSource, testURL);
3144
3145 // Load something into the subframe.
3146 WebFrame* subframe = frame->firstChild();
3147 ASSERT_TRUE(subframe);
3148 FrameTestHelpers::loadHTMLString(subframe, "sub<p>text", testURL);
3149
3150 text = frame->contentAsText(std::numeric_limits<size_t>::max());
3151 EXPECT_EQ("Hello world\n\nsub\ntext", text.utf8());
3152
3153 // Get the frame text where the subframe separator falls on the boundary of
3154 // what we'll take. There used to be a crash in this case.
3155 text = frame->contentAsText(12);
3156 EXPECT_EQ("Hello world", text.utf8());
3157 }
3158
TEST_F(WebFrameTest,GetFullHtmlOfPage)3159 TEST_F(WebFrameTest, GetFullHtmlOfPage)
3160 {
3161 FrameTestHelpers::WebViewHelper webViewHelper;
3162 webViewHelper.initializeAndLoad("about:blank", true);
3163 WebFrame* frame = webViewHelper.webView()->mainFrame();
3164
3165 // Generate a simple test case.
3166 const char simpleSource[] = "<p>Hello</p><p>World</p>";
3167 WebCore::KURL testURL = toKURL("about:blank");
3168 FrameTestHelpers::loadHTMLString(frame, simpleSource, testURL);
3169
3170 WebString text = frame->contentAsText(std::numeric_limits<size_t>::max());
3171 EXPECT_EQ("Hello\n\nWorld", text.utf8());
3172
3173 const std::string html = frame->contentAsMarkup().utf8();
3174
3175 // Load again with the output html.
3176 FrameTestHelpers::loadHTMLString(frame, html, testURL);
3177
3178 EXPECT_EQ(html, frame->contentAsMarkup().utf8());
3179
3180 text = frame->contentAsText(std::numeric_limits<size_t>::max());
3181 EXPECT_EQ("Hello\n\nWorld", text.utf8());
3182
3183 // Test selection check
3184 EXPECT_FALSE(frame->hasSelection());
3185 frame->executeCommand(WebString::fromUTF8("SelectAll"));
3186 EXPECT_TRUE(frame->hasSelection());
3187 frame->executeCommand(WebString::fromUTF8("Unselect"));
3188 EXPECT_FALSE(frame->hasSelection());
3189 WebString selectionHtml = frame->selectionAsMarkup();
3190 EXPECT_TRUE(selectionHtml.isEmpty());
3191 }
3192
3193 class TestExecuteScriptDuringDidCreateScriptContext : public FrameTestHelpers::TestWebFrameClient {
3194 public:
didCreateScriptContext(WebLocalFrame * frame,v8::Handle<v8::Context> context,int extensionGroup,int worldId)3195 virtual void didCreateScriptContext(WebLocalFrame* frame, v8::Handle<v8::Context> context, int extensionGroup, int worldId) OVERRIDE
3196 {
3197 frame->executeScript(WebScriptSource("window.history = 'replaced';"));
3198 }
3199 };
3200
TEST_F(WebFrameTest,ExecuteScriptDuringDidCreateScriptContext)3201 TEST_F(WebFrameTest, ExecuteScriptDuringDidCreateScriptContext)
3202 {
3203 registerMockedHttpURLLoad("hello_world.html");
3204
3205 TestExecuteScriptDuringDidCreateScriptContext webFrameClient;
3206 FrameTestHelpers::WebViewHelper webViewHelper;
3207 webViewHelper.initializeAndLoad(m_baseURL + "hello_world.html", true, &webFrameClient);
3208
3209 FrameTestHelpers::reloadFrame(webViewHelper.webView()->mainFrame());
3210 }
3211
3212 class FindUpdateWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
3213 public:
FindUpdateWebFrameClient()3214 FindUpdateWebFrameClient()
3215 : m_findResultsAreReady(false)
3216 , m_count(-1)
3217 {
3218 }
3219
reportFindInPageMatchCount(int,int count,bool finalUpdate)3220 virtual void reportFindInPageMatchCount(int, int count, bool finalUpdate) OVERRIDE
3221 {
3222 m_count = count;
3223 if (finalUpdate)
3224 m_findResultsAreReady = true;
3225 }
3226
findResultsAreReady() const3227 bool findResultsAreReady() const { return m_findResultsAreReady; }
count() const3228 int count() const { return m_count; }
3229
3230 private:
3231 bool m_findResultsAreReady;
3232 int m_count;
3233 };
3234
3235 // This fails on Mac https://bugs.webkit.org/show_bug.cgi?id=108574
3236 // Also failing on Android: http://crbug.com/341314
3237 #if OS(MACOSX) || OS(ANDROID)
TEST_F(WebFrameTest,DISABLED_FindInPageMatchRects)3238 TEST_F(WebFrameTest, DISABLED_FindInPageMatchRects)
3239 #else
3240 TEST_F(WebFrameTest, FindInPageMatchRects)
3241 #endif
3242 {
3243 registerMockedHttpURLLoad("find_in_page.html");
3244 registerMockedHttpURLLoad("find_in_page_frame.html");
3245
3246 FindUpdateWebFrameClient client;
3247 FrameTestHelpers::WebViewHelper webViewHelper;
3248 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3249 webViewHelper.webView()->resize(WebSize(640, 480));
3250 webViewHelper.webView()->layout();
3251 runPendingTasks();
3252
3253 // Note that the 'result 19' in the <select> element is not expected to produce a match.
3254 static const char* kFindString = "result";
3255 static const int kFindIdentifier = 12345;
3256 static const int kNumResults = 19;
3257
3258 WebFindOptions options;
3259 WebString searchText = WebString::fromUTF8(kFindString);
3260 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3261 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
3262
3263 mainFrame->resetMatchCount();
3264
3265 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3266 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3267
3268 runPendingTasks();
3269 EXPECT_TRUE(client.findResultsAreReady());
3270
3271 WebVector<WebFloatRect> webMatchRects;
3272 mainFrame->findMatchRects(webMatchRects);
3273 ASSERT_EQ(webMatchRects.size(), static_cast<size_t>(kNumResults));
3274 int rectsVersion = mainFrame->findMatchMarkersVersion();
3275
3276 for (int resultIndex = 0; resultIndex < kNumResults; ++resultIndex) {
3277 FloatRect resultRect = static_cast<FloatRect>(webMatchRects[resultIndex]);
3278
3279 // Select the match by the center of its rect.
3280 EXPECT_EQ(mainFrame->selectNearestFindMatch(resultRect.center(), 0), resultIndex + 1);
3281
3282 // Check that the find result ordering matches with our expectations.
3283 Range* result = mainFrame->activeMatchFrame()->activeMatch();
3284 ASSERT_TRUE(result);
3285 result->setEnd(result->endContainer(), result->endOffset() + 3);
3286 EXPECT_EQ(result->text(), String::format("%s %02d", kFindString, resultIndex));
3287
3288 // Verify that the expected match rect also matches the currently active match.
3289 // Compare the enclosing rects to prevent precision issues caused by CSS transforms.
3290 FloatRect activeMatch = mainFrame->activeFindMatchRect();
3291 EXPECT_EQ(enclosingIntRect(activeMatch), enclosingIntRect(resultRect));
3292
3293 // The rects version should not have changed.
3294 EXPECT_EQ(mainFrame->findMatchMarkersVersion(), rectsVersion);
3295 }
3296
3297 // All results after the first two ones should be below between them in find-in-page coordinates.
3298 // This is because results 2 to 9 are inside an iframe located between results 0 and 1. This applies to the fixed div too.
3299 EXPECT_TRUE(webMatchRects[0].y < webMatchRects[1].y);
3300 for (int resultIndex = 2; resultIndex < kNumResults; ++resultIndex) {
3301 EXPECT_TRUE(webMatchRects[0].y < webMatchRects[resultIndex].y);
3302 EXPECT_TRUE(webMatchRects[1].y > webMatchRects[resultIndex].y);
3303 }
3304
3305 // Result 3 should be below both 2 and 4. This is caused by the CSS transform in the containing div.
3306 // If the transform doesn't work then 3 will be between 2 and 4.
3307 EXPECT_TRUE(webMatchRects[3].y > webMatchRects[2].y);
3308 EXPECT_TRUE(webMatchRects[3].y > webMatchRects[4].y);
3309
3310 // Results 6, 7, 8 and 9 should be one below the other in that same order.
3311 // If overflow:scroll is not properly handled then result 8 would be below result 9 or
3312 // result 7 above result 6 depending on the scroll.
3313 EXPECT_TRUE(webMatchRects[6].y < webMatchRects[7].y);
3314 EXPECT_TRUE(webMatchRects[7].y < webMatchRects[8].y);
3315 EXPECT_TRUE(webMatchRects[8].y < webMatchRects[9].y);
3316
3317 // Results 11, 12, 13 and 14 should be between results 10 and 15, as they are inside the table.
3318 EXPECT_TRUE(webMatchRects[11].y > webMatchRects[10].y);
3319 EXPECT_TRUE(webMatchRects[12].y > webMatchRects[10].y);
3320 EXPECT_TRUE(webMatchRects[13].y > webMatchRects[10].y);
3321 EXPECT_TRUE(webMatchRects[14].y > webMatchRects[10].y);
3322 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[15].y);
3323 EXPECT_TRUE(webMatchRects[12].y < webMatchRects[15].y);
3324 EXPECT_TRUE(webMatchRects[13].y < webMatchRects[15].y);
3325 EXPECT_TRUE(webMatchRects[14].y < webMatchRects[15].y);
3326
3327 // Result 11 should be above 12, 13 and 14 as it's in the table header.
3328 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[12].y);
3329 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[13].y);
3330 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[14].y);
3331
3332 // Result 11 should also be right to 12, 13 and 14 because of the colspan.
3333 EXPECT_TRUE(webMatchRects[11].x > webMatchRects[12].x);
3334 EXPECT_TRUE(webMatchRects[11].x > webMatchRects[13].x);
3335 EXPECT_TRUE(webMatchRects[11].x > webMatchRects[14].x);
3336
3337 // Result 12 should be left to results 11, 13 and 14 in the table layout.
3338 EXPECT_TRUE(webMatchRects[12].x < webMatchRects[11].x);
3339 EXPECT_TRUE(webMatchRects[12].x < webMatchRects[13].x);
3340 EXPECT_TRUE(webMatchRects[12].x < webMatchRects[14].x);
3341
3342 // Results 13, 12 and 14 should be one above the other in that order because of the rowspan
3343 // and vertical-align: middle by default.
3344 EXPECT_TRUE(webMatchRects[13].y < webMatchRects[12].y);
3345 EXPECT_TRUE(webMatchRects[12].y < webMatchRects[14].y);
3346
3347 // Result 16 should be below result 15.
3348 EXPECT_TRUE(webMatchRects[15].y > webMatchRects[14].y);
3349
3350 // Result 18 should be normalized with respect to the position:relative div, and not it's
3351 // immediate containing div. Consequently, result 18 should be above result 17.
3352 EXPECT_TRUE(webMatchRects[17].y > webMatchRects[18].y);
3353
3354 // Resizing should update the rects version.
3355 webViewHelper.webView()->resize(WebSize(800, 600));
3356 runPendingTasks();
3357 EXPECT_TRUE(mainFrame->findMatchMarkersVersion() != rectsVersion);
3358 }
3359
TEST_F(WebFrameTest,FindInPageSkipsHiddenFrames)3360 TEST_F(WebFrameTest, FindInPageSkipsHiddenFrames)
3361 {
3362 registerMockedHttpURLLoad("find_in_hidden_frame.html");
3363
3364 FindUpdateWebFrameClient client;
3365 FrameTestHelpers::WebViewHelper webViewHelper;
3366 webViewHelper.initializeAndLoad(m_baseURL + "find_in_hidden_frame.html", true, &client);
3367 webViewHelper.webView()->resize(WebSize(640, 480));
3368 webViewHelper.webView()->layout();
3369 runPendingTasks();
3370
3371 static const char* kFindString = "hello";
3372 static const int kFindIdentifier = 12345;
3373 static const int kNumResults = 1;
3374
3375 WebFindOptions options;
3376 WebString searchText = WebString::fromUTF8(kFindString);
3377 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3378 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
3379
3380 mainFrame->resetMatchCount();
3381
3382 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3383 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3384
3385 runPendingTasks();
3386 EXPECT_TRUE(client.findResultsAreReady());
3387 EXPECT_EQ(kNumResults, client.count());
3388 }
3389
TEST_F(WebFrameTest,FindOnDetachedFrame)3390 TEST_F(WebFrameTest, FindOnDetachedFrame)
3391 {
3392 registerMockedHttpURLLoad("find_in_page.html");
3393 registerMockedHttpURLLoad("find_in_page_frame.html");
3394
3395 FindUpdateWebFrameClient client;
3396 FrameTestHelpers::WebViewHelper webViewHelper;
3397 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3398 webViewHelper.webView()->resize(WebSize(640, 480));
3399 webViewHelper.webView()->layout();
3400 runPendingTasks();
3401
3402 static const char* kFindString = "result";
3403 static const int kFindIdentifier = 12345;
3404
3405 WebFindOptions options;
3406 WebString searchText = WebString::fromUTF8(kFindString);
3407 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3408 RefPtr<WebLocalFrameImpl> secondFrame = toWebLocalFrameImpl(mainFrame->traverseNext(false));
3409 RefPtr<WebCore::LocalFrame> holdSecondFrame = secondFrame->frame();
3410
3411 // Detach the frame before finding.
3412 EXPECT_TRUE(mainFrame->document().getElementById("frame").remove());
3413
3414 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
3415 EXPECT_FALSE(secondFrame->find(kFindIdentifier, searchText, options, false, 0));
3416
3417 runPendingTasks();
3418 EXPECT_FALSE(client.findResultsAreReady());
3419
3420 mainFrame->resetMatchCount();
3421
3422 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3423 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3424
3425 runPendingTasks();
3426 EXPECT_TRUE(client.findResultsAreReady());
3427
3428 holdSecondFrame.release();
3429 }
3430
TEST_F(WebFrameTest,FindDetachFrameBeforeScopeStrings)3431 TEST_F(WebFrameTest, FindDetachFrameBeforeScopeStrings)
3432 {
3433 registerMockedHttpURLLoad("find_in_page.html");
3434 registerMockedHttpURLLoad("find_in_page_frame.html");
3435
3436 FindUpdateWebFrameClient client;
3437 FrameTestHelpers::WebViewHelper webViewHelper;
3438 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3439 webViewHelper.webView()->resize(WebSize(640, 480));
3440 webViewHelper.webView()->layout();
3441 runPendingTasks();
3442
3443 static const char* kFindString = "result";
3444 static const int kFindIdentifier = 12345;
3445
3446 WebFindOptions options;
3447 WebString searchText = WebString::fromUTF8(kFindString);
3448 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3449 WebLocalFrameImpl* secondFrame = toWebLocalFrameImpl(mainFrame->traverseNext(false));
3450 RefPtr<WebCore::LocalFrame> holdSecondFrame = secondFrame->frame();
3451
3452 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3453 EXPECT_TRUE(frame->find(kFindIdentifier, searchText, options, false, 0));
3454
3455 runPendingTasks();
3456 EXPECT_FALSE(client.findResultsAreReady());
3457
3458 // Detach the frame between finding and scoping.
3459 EXPECT_TRUE(mainFrame->document().getElementById("frame").remove());
3460
3461 mainFrame->resetMatchCount();
3462
3463 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3464 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3465
3466 runPendingTasks();
3467 EXPECT_TRUE(client.findResultsAreReady());
3468
3469 holdSecondFrame.release();
3470 }
3471
TEST_F(WebFrameTest,FindDetachFrameWhileScopingStrings)3472 TEST_F(WebFrameTest, FindDetachFrameWhileScopingStrings)
3473 {
3474 registerMockedHttpURLLoad("find_in_page.html");
3475 registerMockedHttpURLLoad("find_in_page_frame.html");
3476
3477 FindUpdateWebFrameClient client;
3478 FrameTestHelpers::WebViewHelper webViewHelper;
3479 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3480 webViewHelper.webView()->resize(WebSize(640, 480));
3481 webViewHelper.webView()->layout();
3482 runPendingTasks();
3483
3484 static const char* kFindString = "result";
3485 static const int kFindIdentifier = 12345;
3486
3487 WebFindOptions options;
3488 WebString searchText = WebString::fromUTF8(kFindString);
3489 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3490 WebLocalFrameImpl* secondFrame = toWebLocalFrameImpl(mainFrame->traverseNext(false));
3491 RefPtr<WebCore::LocalFrame> holdSecondFrame = secondFrame->frame();
3492
3493 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3494 EXPECT_TRUE(frame->find(kFindIdentifier, searchText, options, false, 0));
3495
3496 runPendingTasks();
3497 EXPECT_FALSE(client.findResultsAreReady());
3498
3499 mainFrame->resetMatchCount();
3500
3501 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3502 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3503
3504 // The first scopeStringMatches will have reset the state. Detach before it actually scopes.
3505 EXPECT_TRUE(mainFrame->document().getElementById("frame").remove());
3506
3507 runPendingTasks();
3508 EXPECT_TRUE(client.findResultsAreReady());
3509
3510 holdSecondFrame.release();
3511 }
3512
TEST_F(WebFrameTest,ResetMatchCount)3513 TEST_F(WebFrameTest, ResetMatchCount)
3514 {
3515 registerMockedHttpURLLoad("find_in_generated_frame.html");
3516
3517 FindUpdateWebFrameClient client;
3518 FrameTestHelpers::WebViewHelper webViewHelper;
3519 webViewHelper.initializeAndLoad(m_baseURL + "find_in_generated_frame.html", true, &client);
3520 webViewHelper.webView()->resize(WebSize(640, 480));
3521 webViewHelper.webView()->layout();
3522 runPendingTasks();
3523
3524 static const char* kFindString = "result";
3525 static const int kFindIdentifier = 12345;
3526
3527 WebFindOptions options;
3528 WebString searchText = WebString::fromUTF8(kFindString);
3529 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3530
3531 // Check that child frame exists.
3532 EXPECT_TRUE(!!mainFrame->traverseNext(false));
3533
3534 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false)) {
3535 EXPECT_FALSE(frame->find(kFindIdentifier, searchText, options, false, 0));
3536 }
3537
3538 runPendingTasks();
3539 EXPECT_FALSE(client.findResultsAreReady());
3540
3541 mainFrame->resetMatchCount();
3542 }
3543
TEST_F(WebFrameTest,SetTickmarks)3544 TEST_F(WebFrameTest, SetTickmarks)
3545 {
3546 registerMockedHttpURLLoad("find.html");
3547
3548 FindUpdateWebFrameClient client;
3549 FrameTestHelpers::WebViewHelper webViewHelper;
3550 webViewHelper.initializeAndLoad(m_baseURL + "find.html", true, &client);
3551 webViewHelper.webView()->resize(WebSize(640, 480));
3552 webViewHelper.webView()->layout();
3553 runPendingTasks();
3554
3555 static const char* kFindString = "foo";
3556 static const int kFindIdentifier = 12345;
3557
3558 WebFindOptions options;
3559 WebString searchText = WebString::fromUTF8(kFindString);
3560 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3561 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
3562
3563 mainFrame->resetMatchCount();
3564 mainFrame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3565
3566 runPendingTasks();
3567 EXPECT_TRUE(client.findResultsAreReady());
3568
3569 // Get the tickmarks for the original find request.
3570 WebCore::FrameView* frameView = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
3571 RefPtr<WebCore::Scrollbar> scrollbar = frameView->createScrollbar(WebCore::HorizontalScrollbar);
3572 Vector<WebCore::IntRect> originalTickmarks;
3573 scrollbar->getTickmarks(originalTickmarks);
3574 EXPECT_EQ(4u, originalTickmarks.size());
3575
3576 // Override the tickmarks.
3577 Vector<WebCore::IntRect> overridingTickmarksExpected;
3578 overridingTickmarksExpected.append(WebCore::IntRect(0, 0, 100, 100));
3579 overridingTickmarksExpected.append(WebCore::IntRect(0, 20, 100, 100));
3580 overridingTickmarksExpected.append(WebCore::IntRect(0, 30, 100, 100));
3581 mainFrame->setTickmarks(overridingTickmarksExpected);
3582
3583 // Check the tickmarks are overriden correctly.
3584 Vector<WebCore::IntRect> overridingTickmarksActual;
3585 scrollbar->getTickmarks(overridingTickmarksActual);
3586 EXPECT_EQ(overridingTickmarksExpected, overridingTickmarksActual);
3587
3588 // Reset the tickmark behavior.
3589 Vector<WebCore::IntRect> resetTickmarks;
3590 mainFrame->setTickmarks(resetTickmarks);
3591
3592 // Check that the original tickmarks are returned
3593 Vector<WebCore::IntRect> originalTickmarksAfterReset;
3594 scrollbar->getTickmarks(originalTickmarksAfterReset);
3595 EXPECT_EQ(originalTickmarks, originalTickmarksAfterReset);
3596 }
3597
topLeft(const WebRect & rect)3598 static WebPoint topLeft(const WebRect& rect)
3599 {
3600 return WebPoint(rect.x, rect.y);
3601 }
3602
bottomRightMinusOne(const WebRect & rect)3603 static WebPoint bottomRightMinusOne(const WebRect& rect)
3604 {
3605 // FIXME: If we don't subtract 1 from the x- and y-coordinates of the
3606 // selection bounds, selectRange() will select the *next* element. That's
3607 // strictly correct, as hit-testing checks the pixel to the lower-right of
3608 // the input coordinate, but it's a wart on the API.
3609 return WebPoint(rect.x + rect.width - 1, rect.y + rect.height - 1);
3610 }
3611
elementBounds(WebFrame * frame,const WebString & id)3612 static WebRect elementBounds(WebFrame* frame, const WebString& id)
3613 {
3614 return frame->document().getElementById(id).boundsInViewportSpace();
3615 }
3616
selectionAsString(WebFrame * frame)3617 static std::string selectionAsString(WebFrame* frame)
3618 {
3619 return frame->selectionAsText().utf8();
3620 }
3621
TEST_F(WebFrameTest,SelectRange)3622 TEST_F(WebFrameTest, SelectRange)
3623 {
3624 WebFrame* frame;
3625 WebRect startWebRect;
3626 WebRect endWebRect;
3627
3628 registerMockedHttpURLLoad("select_range_basic.html");
3629 registerMockedHttpURLLoad("select_range_scroll.html");
3630
3631 FrameTestHelpers::WebViewHelper webViewHelper;
3632 initializeTextSelectionWebView(m_baseURL + "select_range_basic.html", &webViewHelper);
3633 frame = webViewHelper.webView()->mainFrame();
3634 EXPECT_EQ("Some test text for testing.", selectionAsString(frame));
3635 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3636 frame->executeCommand(WebString::fromUTF8("Unselect"));
3637 EXPECT_EQ("", selectionAsString(frame));
3638 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3639 EXPECT_EQ("Some test text for testing.", selectionAsString(frame));
3640
3641 initializeTextSelectionWebView(m_baseURL + "select_range_scroll.html", &webViewHelper);
3642 frame = webViewHelper.webView()->mainFrame();
3643 EXPECT_EQ("Some offscreen test text for testing.", selectionAsString(frame));
3644 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3645 frame->executeCommand(WebString::fromUTF8("Unselect"));
3646 EXPECT_EQ("", selectionAsString(frame));
3647 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3648 EXPECT_EQ("Some offscreen test text for testing.", selectionAsString(frame));
3649 }
3650
TEST_F(WebFrameTest,SelectRangeInIframe)3651 TEST_F(WebFrameTest, SelectRangeInIframe)
3652 {
3653 WebFrame* frame;
3654 WebRect startWebRect;
3655 WebRect endWebRect;
3656
3657 registerMockedHttpURLLoad("select_range_iframe.html");
3658 registerMockedHttpURLLoad("select_range_basic.html");
3659
3660 FrameTestHelpers::WebViewHelper webViewHelper;
3661 initializeTextSelectionWebView(m_baseURL + "select_range_iframe.html", &webViewHelper);
3662 frame = webViewHelper.webView()->mainFrame();
3663 WebFrame* subframe = frame->firstChild();
3664 EXPECT_EQ("Some test text for testing.", selectionAsString(subframe));
3665 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3666 subframe->executeCommand(WebString::fromUTF8("Unselect"));
3667 EXPECT_EQ("", selectionAsString(subframe));
3668 subframe->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3669 EXPECT_EQ("Some test text for testing.", selectionAsString(subframe));
3670 }
3671
TEST_F(WebFrameTest,SelectRangeDivContentEditable)3672 TEST_F(WebFrameTest, SelectRangeDivContentEditable)
3673 {
3674 WebFrame* frame;
3675 WebRect startWebRect;
3676 WebRect endWebRect;
3677
3678 registerMockedHttpURLLoad("select_range_div_editable.html");
3679
3680 // Select the middle of an editable element, then try to extend the selection to the top of the document.
3681 // The selection range should be clipped to the bounds of the editable element.
3682 FrameTestHelpers::WebViewHelper webViewHelper;
3683 initializeTextSelectionWebView(m_baseURL + "select_range_div_editable.html", &webViewHelper);
3684 frame = webViewHelper.webView()->mainFrame();
3685 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3686 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3687
3688 frame->selectRange(bottomRightMinusOne(endWebRect), WebPoint(0, 0));
3689 EXPECT_EQ("16-char header. This text is initially selected.", selectionAsString(frame));
3690
3691 // As above, but extending the selection to the bottom of the document.
3692 initializeTextSelectionWebView(m_baseURL + "select_range_div_editable.html", &webViewHelper);
3693 frame = webViewHelper.webView()->mainFrame();
3694
3695 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3696 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3697 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3698 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3699
3700 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3701 frame->selectRange(topLeft(startWebRect), WebPoint(640, 480));
3702 EXPECT_EQ("This text is initially selected. 16-char footer.", selectionAsString(frame));
3703 }
3704
3705 // positionForPoint returns the wrong values for contenteditable spans. See
3706 // http://crbug.com/238334.
TEST_F(WebFrameTest,DISABLED_SelectRangeSpanContentEditable)3707 TEST_F(WebFrameTest, DISABLED_SelectRangeSpanContentEditable)
3708 {
3709 WebFrame* frame;
3710 WebRect startWebRect;
3711 WebRect endWebRect;
3712
3713 registerMockedHttpURLLoad("select_range_span_editable.html");
3714
3715 // Select the middle of an editable element, then try to extend the selection to the top of the document.
3716 // The selection range should be clipped to the bounds of the editable element.
3717 FrameTestHelpers::WebViewHelper webViewHelper;
3718 initializeTextSelectionWebView(m_baseURL + "select_range_span_editable.html", &webViewHelper);
3719 frame = webViewHelper.webView()->mainFrame();
3720 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3721 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3722
3723 frame->selectRange(bottomRightMinusOne(endWebRect), WebPoint(0, 0));
3724 EXPECT_EQ("16-char header. This text is initially selected.", selectionAsString(frame));
3725
3726 // As above, but extending the selection to the bottom of the document.
3727 initializeTextSelectionWebView(m_baseURL + "select_range_span_editable.html", &webViewHelper);
3728 frame = webViewHelper.webView()->mainFrame();
3729
3730 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3731 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3732 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3733 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3734
3735 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3736 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3737 frame->selectRange(topLeft(startWebRect), WebPoint(640, 480));
3738 EXPECT_EQ("This text is initially selected. 16-char footer.", selectionAsString(frame));
3739 }
3740
TEST_F(WebFrameTest,SelectRangeCanMoveSelectionStart)3741 TEST_F(WebFrameTest, SelectRangeCanMoveSelectionStart)
3742 {
3743 registerMockedHttpURLLoad("text_selection.html");
3744 FrameTestHelpers::WebViewHelper webViewHelper;
3745 initializeTextSelectionWebView(m_baseURL + "text_selection.html", &webViewHelper);
3746 WebFrame* frame = webViewHelper.webView()->mainFrame();
3747
3748 // Select second span. We can move the start to include the first span.
3749 frame->executeScript(WebScriptSource("selectElement('header_2');"));
3750 EXPECT_EQ("Header 2.", selectionAsString(frame));
3751 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "header_2")), topLeft(elementBounds(frame, "header_1")));
3752 EXPECT_EQ("Header 1. Header 2.", selectionAsString(frame));
3753
3754 // We can move the start and end together.
3755 frame->executeScript(WebScriptSource("selectElement('header_1');"));
3756 EXPECT_EQ("Header 1.", selectionAsString(frame));
3757 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "header_1")));
3758 EXPECT_EQ("", selectionAsString(frame));
3759 // Selection is a caret, not empty.
3760 EXPECT_FALSE(frame->selectionRange().isNull());
3761
3762 // We can move the start across the end.
3763 frame->executeScript(WebScriptSource("selectElement('header_1');"));
3764 EXPECT_EQ("Header 1.", selectionAsString(frame));
3765 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "header_2")));
3766 EXPECT_EQ(" Header 2.", selectionAsString(frame));
3767
3768 // Can't extend the selection part-way into an editable element.
3769 frame->executeScript(WebScriptSource("selectElement('footer_2');"));
3770 EXPECT_EQ("Footer 2.", selectionAsString(frame));
3771 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "footer_2")), topLeft(elementBounds(frame, "editable_2")));
3772 EXPECT_EQ(" [ Footer 1. Footer 2.", selectionAsString(frame));
3773
3774 // Can extend the selection completely across editable elements.
3775 frame->executeScript(WebScriptSource("selectElement('footer_2');"));
3776 EXPECT_EQ("Footer 2.", selectionAsString(frame));
3777 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "footer_2")), topLeft(elementBounds(frame, "header_2")));
3778 EXPECT_EQ("Header 2. ] [ Editable 1. Editable 2. ] [ Footer 1. Footer 2.", selectionAsString(frame));
3779
3780 // If the selection is editable text, we can't extend it into non-editable text.
3781 frame->executeScript(WebScriptSource("selectElement('editable_2');"));
3782 EXPECT_EQ("Editable 2.", selectionAsString(frame));
3783 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "editable_2")), topLeft(elementBounds(frame, "header_2")));
3784 // positionForPoint returns the wrong values for contenteditable spans. See
3785 // http://crbug.com/238334.
3786 // EXPECT_EQ("[ Editable 1. Editable 2.", selectionAsString(frame));
3787 }
3788
TEST_F(WebFrameTest,SelectRangeCanMoveSelectionEnd)3789 TEST_F(WebFrameTest, SelectRangeCanMoveSelectionEnd)
3790 {
3791 registerMockedHttpURLLoad("text_selection.html");
3792 FrameTestHelpers::WebViewHelper webViewHelper;
3793 initializeTextSelectionWebView(m_baseURL + "text_selection.html", &webViewHelper);
3794 WebFrame* frame = webViewHelper.webView()->mainFrame();
3795
3796 // Select first span. We can move the end to include the second span.
3797 frame->executeScript(WebScriptSource("selectElement('header_1');"));
3798 EXPECT_EQ("Header 1.", selectionAsString(frame));
3799 frame->selectRange(topLeft(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "header_2")));
3800 EXPECT_EQ("Header 1. Header 2.", selectionAsString(frame));
3801
3802 // We can move the start and end together.
3803 frame->executeScript(WebScriptSource("selectElement('header_2');"));
3804 EXPECT_EQ("Header 2.", selectionAsString(frame));
3805 frame->selectRange(topLeft(elementBounds(frame, "header_2")), topLeft(elementBounds(frame, "header_2")));
3806 EXPECT_EQ("", selectionAsString(frame));
3807 // Selection is a caret, not empty.
3808 EXPECT_FALSE(frame->selectionRange().isNull());
3809
3810 // We can move the end across the start.
3811 frame->executeScript(WebScriptSource("selectElement('header_2');"));
3812 EXPECT_EQ("Header 2.", selectionAsString(frame));
3813 frame->selectRange(topLeft(elementBounds(frame, "header_2")), topLeft(elementBounds(frame, "header_1")));
3814 EXPECT_EQ("Header 1. ", selectionAsString(frame));
3815
3816 // Can't extend the selection part-way into an editable element.
3817 frame->executeScript(WebScriptSource("selectElement('header_1');"));
3818 EXPECT_EQ("Header 1.", selectionAsString(frame));
3819 frame->selectRange(topLeft(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "editable_1")));
3820 EXPECT_EQ("Header 1. Header 2. ] ", selectionAsString(frame));
3821
3822 // Can extend the selection completely across editable elements.
3823 frame->executeScript(WebScriptSource("selectElement('header_1');"));
3824 EXPECT_EQ("Header 1.", selectionAsString(frame));
3825 frame->selectRange(topLeft(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "footer_1")));
3826 EXPECT_EQ("Header 1. Header 2. ] [ Editable 1. Editable 2. ] [ Footer 1.", selectionAsString(frame));
3827
3828 // If the selection is editable text, we can't extend it into non-editable text.
3829 frame->executeScript(WebScriptSource("selectElement('editable_1');"));
3830 EXPECT_EQ("Editable 1.", selectionAsString(frame));
3831 frame->selectRange(topLeft(elementBounds(frame, "editable_1")), bottomRightMinusOne(elementBounds(frame, "footer_1")));
3832 // positionForPoint returns the wrong values for contenteditable spans. See
3833 // http://crbug.com/238334.
3834 // EXPECT_EQ("Editable 1. Editable 2. ]", selectionAsString(frame));
3835 }
3836
computeOffset(WebCore::RenderObject * renderer,int x,int y)3837 static int computeOffset(WebCore::RenderObject* renderer, int x, int y)
3838 {
3839 return WebCore::VisiblePosition(renderer->positionForPoint(WebCore::LayoutPoint(x, y))).deepEquivalent().computeOffsetInContainerNode();
3840 }
3841
3842 // positionForPoint returns the wrong values for contenteditable spans. See
3843 // http://crbug.com/238334.
TEST_F(WebFrameTest,DISABLED_PositionForPointTest)3844 TEST_F(WebFrameTest, DISABLED_PositionForPointTest)
3845 {
3846 registerMockedHttpURLLoad("select_range_span_editable.html");
3847 FrameTestHelpers::WebViewHelper webViewHelper;
3848 initializeTextSelectionWebView(m_baseURL + "select_range_span_editable.html", &webViewHelper);
3849 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3850 WebCore::RenderObject* renderer = mainFrame->frame()->selection().rootEditableElement()->renderer();
3851 EXPECT_EQ(0, computeOffset(renderer, -1, -1));
3852 EXPECT_EQ(64, computeOffset(renderer, 1000, 1000));
3853
3854 registerMockedHttpURLLoad("select_range_div_editable.html");
3855 initializeTextSelectionWebView(m_baseURL + "select_range_div_editable.html", &webViewHelper);
3856 mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3857 renderer = mainFrame->frame()->selection().rootEditableElement()->renderer();
3858 EXPECT_EQ(0, computeOffset(renderer, -1, -1));
3859 EXPECT_EQ(64, computeOffset(renderer, 1000, 1000));
3860 }
3861
3862 #if !OS(MACOSX) && !OS(LINUX)
TEST_F(WebFrameTest,SelectRangeStaysHorizontallyAlignedWhenMoved)3863 TEST_F(WebFrameTest, SelectRangeStaysHorizontallyAlignedWhenMoved)
3864 {
3865 registerMockedHttpURLLoad("move_caret.html");
3866
3867 FrameTestHelpers::WebViewHelper webViewHelper;
3868 initializeTextSelectionWebView(m_baseURL + "move_caret.html", &webViewHelper);
3869 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3870
3871 WebRect initialStartRect;
3872 WebRect initialEndRect;
3873 WebRect startRect;
3874 WebRect endRect;
3875
3876 frame->executeScript(WebScriptSource("selectRange();"));
3877 webViewHelper.webView()->selectionBounds(initialStartRect, initialEndRect);
3878 WebPoint movedStart(topLeft(initialStartRect));
3879
3880 movedStart.y += 40;
3881 frame->selectRange(movedStart, bottomRightMinusOne(initialEndRect));
3882 webViewHelper.webView()->selectionBounds(startRect, endRect);
3883 EXPECT_EQ(startRect, initialStartRect);
3884 EXPECT_EQ(endRect, initialEndRect);
3885
3886 movedStart.y -= 80;
3887 frame->selectRange(movedStart, bottomRightMinusOne(initialEndRect));
3888 webViewHelper.webView()->selectionBounds(startRect, endRect);
3889 EXPECT_EQ(startRect, initialStartRect);
3890 EXPECT_EQ(endRect, initialEndRect);
3891
3892 WebPoint movedEnd(bottomRightMinusOne(initialEndRect));
3893
3894 movedEnd.y += 40;
3895 frame->selectRange(topLeft(initialStartRect), movedEnd);
3896 webViewHelper.webView()->selectionBounds(startRect, endRect);
3897 EXPECT_EQ(startRect, initialStartRect);
3898 EXPECT_EQ(endRect, initialEndRect);
3899
3900 movedEnd.y -= 80;
3901 frame->selectRange(topLeft(initialStartRect), movedEnd);
3902 webViewHelper.webView()->selectionBounds(startRect, endRect);
3903 EXPECT_EQ(startRect, initialStartRect);
3904 EXPECT_EQ(endRect, initialEndRect);
3905 }
3906
TEST_F(WebFrameTest,MoveCaretStaysHorizontallyAlignedWhenMoved)3907 TEST_F(WebFrameTest, MoveCaretStaysHorizontallyAlignedWhenMoved)
3908 {
3909 WebLocalFrameImpl* frame;
3910 registerMockedHttpURLLoad("move_caret.html");
3911
3912 FrameTestHelpers::WebViewHelper webViewHelper;
3913 initializeTextSelectionWebView(m_baseURL + "move_caret.html", &webViewHelper);
3914 frame = (WebLocalFrameImpl*)webViewHelper.webView()->mainFrame();
3915
3916 WebRect initialStartRect;
3917 WebRect initialEndRect;
3918 WebRect startRect;
3919 WebRect endRect;
3920
3921 frame->executeScript(WebScriptSource("selectCaret();"));
3922 webViewHelper.webView()->selectionBounds(initialStartRect, initialEndRect);
3923 WebPoint moveTo(topLeft(initialStartRect));
3924
3925 moveTo.y += 40;
3926 frame->moveCaretSelection(moveTo);
3927 webViewHelper.webView()->selectionBounds(startRect, endRect);
3928 EXPECT_EQ(startRect, initialStartRect);
3929 EXPECT_EQ(endRect, initialEndRect);
3930
3931 moveTo.y -= 80;
3932 frame->moveCaretSelection(moveTo);
3933 webViewHelper.webView()->selectionBounds(startRect, endRect);
3934 EXPECT_EQ(startRect, initialStartRect);
3935 EXPECT_EQ(endRect, initialEndRect);
3936 }
3937 #endif
3938
3939 class DisambiguationPopupTestWebViewClient : public FrameTestHelpers::TestWebViewClient {
3940 public:
didTapMultipleTargets(const WebGestureEvent &,const WebVector<WebRect> & targetRects)3941 virtual bool didTapMultipleTargets(const WebGestureEvent&, const WebVector<WebRect>& targetRects) OVERRIDE
3942 {
3943 EXPECT_GE(targetRects.size(), 2u);
3944 m_triggered = true;
3945 return true;
3946 }
3947
triggered() const3948 bool triggered() const { return m_triggered; }
resetTriggered()3949 void resetTriggered() { m_triggered = false; }
3950 bool m_triggered;
3951 };
3952
fatTap(int x,int y)3953 static WebGestureEvent fatTap(int x, int y)
3954 {
3955 WebGestureEvent event;
3956 event.type = WebInputEvent::GestureTap;
3957 event.x = x;
3958 event.y = y;
3959 event.data.tap.width = 50;
3960 event.data.tap.height = 50;
3961 return event;
3962 }
3963
TEST_F(WebFrameTest,DisambiguationPopup)3964 TEST_F(WebFrameTest, DisambiguationPopup)
3965 {
3966 const std::string htmlFile = "disambiguation_popup.html";
3967 registerMockedHttpURLLoad(htmlFile);
3968
3969 DisambiguationPopupTestWebViewClient client;
3970
3971 // Make sure we initialize to minimum scale, even if the window size
3972 // only becomes available after the load begins.
3973 FrameTestHelpers::WebViewHelper webViewHelper;
3974 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client);
3975 webViewHelper.webView()->resize(WebSize(1000, 1000));
3976 webViewHelper.webView()->layout();
3977
3978 client.resetTriggered();
3979 webViewHelper.webView()->handleInputEvent(fatTap(0, 0));
3980 EXPECT_FALSE(client.triggered());
3981
3982 client.resetTriggered();
3983 webViewHelper.webView()->handleInputEvent(fatTap(200, 115));
3984 EXPECT_FALSE(client.triggered());
3985
3986 for (int i = 0; i <= 46; i++) {
3987 client.resetTriggered();
3988 webViewHelper.webView()->handleInputEvent(fatTap(120, 230 + i * 5));
3989
3990 int j = i % 10;
3991 if (j >= 7 && j <= 9)
3992 EXPECT_TRUE(client.triggered());
3993 else
3994 EXPECT_FALSE(client.triggered());
3995 }
3996
3997 for (int i = 0; i <= 46; i++) {
3998 client.resetTriggered();
3999 webViewHelper.webView()->handleInputEvent(fatTap(10 + i * 5, 590));
4000
4001 int j = i % 10;
4002 if (j >= 7 && j <= 9)
4003 EXPECT_TRUE(client.triggered());
4004 else
4005 EXPECT_FALSE(client.triggered());
4006 }
4007 }
4008
TEST_F(WebFrameTest,DisambiguationPopupNoContainer)4009 TEST_F(WebFrameTest, DisambiguationPopupNoContainer)
4010 {
4011 registerMockedHttpURLLoad("disambiguation_popup_no_container.html");
4012
4013 DisambiguationPopupTestWebViewClient client;
4014
4015 // Make sure we initialize to minimum scale, even if the window size
4016 // only becomes available after the load begins.
4017 FrameTestHelpers::WebViewHelper webViewHelper;
4018 webViewHelper.initializeAndLoad(m_baseURL + "disambiguation_popup_no_container.html", true, 0, &client);
4019 webViewHelper.webView()->resize(WebSize(1000, 1000));
4020 webViewHelper.webView()->layout();
4021
4022 client.resetTriggered();
4023 webViewHelper.webView()->handleInputEvent(fatTap(50, 50));
4024 EXPECT_FALSE(client.triggered());
4025 }
4026
TEST_F(WebFrameTest,DisambiguationPopupMobileSite)4027 TEST_F(WebFrameTest, DisambiguationPopupMobileSite)
4028 {
4029 UseMockScrollbarSettings mockScrollbarSettings;
4030 const std::string htmlFile = "disambiguation_popup_mobile_site.html";
4031 registerMockedHttpURLLoad(htmlFile);
4032
4033 DisambiguationPopupTestWebViewClient client;
4034
4035 // Make sure we initialize to minimum scale, even if the window size
4036 // only becomes available after the load begins.
4037 FrameTestHelpers::WebViewHelper webViewHelper;
4038 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client, enableViewportSettings);
4039 webViewHelper.webView()->resize(WebSize(1000, 1000));
4040 webViewHelper.webView()->layout();
4041
4042 client.resetTriggered();
4043 webViewHelper.webView()->handleInputEvent(fatTap(0, 0));
4044 EXPECT_FALSE(client.triggered());
4045
4046 client.resetTriggered();
4047 webViewHelper.webView()->handleInputEvent(fatTap(200, 115));
4048 EXPECT_FALSE(client.triggered());
4049
4050 for (int i = 0; i <= 46; i++) {
4051 client.resetTriggered();
4052 webViewHelper.webView()->handleInputEvent(fatTap(120, 230 + i * 5));
4053 EXPECT_FALSE(client.triggered());
4054 }
4055
4056 for (int i = 0; i <= 46; i++) {
4057 client.resetTriggered();
4058 webViewHelper.webView()->handleInputEvent(fatTap(10 + i * 5, 590));
4059 EXPECT_FALSE(client.triggered());
4060 }
4061 }
4062
TEST_F(WebFrameTest,DisambiguationPopupViewportSite)4063 TEST_F(WebFrameTest, DisambiguationPopupViewportSite)
4064 {
4065 UseMockScrollbarSettings mockScrollbarSettings;
4066 const std::string htmlFile = "disambiguation_popup_viewport_site.html";
4067 registerMockedHttpURLLoad(htmlFile);
4068
4069 DisambiguationPopupTestWebViewClient client;
4070
4071 // Make sure we initialize to minimum scale, even if the window size
4072 // only becomes available after the load begins.
4073 FrameTestHelpers::WebViewHelper webViewHelper;
4074 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client, enableViewportSettings);
4075 webViewHelper.webView()->resize(WebSize(1000, 1000));
4076 webViewHelper.webView()->layout();
4077
4078 client.resetTriggered();
4079 webViewHelper.webView()->handleInputEvent(fatTap(0, 0));
4080 EXPECT_FALSE(client.triggered());
4081
4082 client.resetTriggered();
4083 webViewHelper.webView()->handleInputEvent(fatTap(200, 115));
4084 EXPECT_FALSE(client.triggered());
4085
4086 for (int i = 0; i <= 46; i++) {
4087 client.resetTriggered();
4088 webViewHelper.webView()->handleInputEvent(fatTap(120, 230 + i * 5));
4089 EXPECT_FALSE(client.triggered());
4090 }
4091
4092 for (int i = 0; i <= 46; i++) {
4093 client.resetTriggered();
4094 webViewHelper.webView()->handleInputEvent(fatTap(10 + i * 5, 590));
4095 EXPECT_FALSE(client.triggered());
4096 }
4097 }
4098
TEST_F(WebFrameTest,DisambiguationPopupBlacklist)4099 TEST_F(WebFrameTest, DisambiguationPopupBlacklist)
4100 {
4101 const unsigned viewportWidth = 500;
4102 const unsigned viewportHeight = 1000;
4103 const unsigned divHeight = 100;
4104 const std::string htmlFile = "disambiguation_popup_blacklist.html";
4105 registerMockedHttpURLLoad(htmlFile);
4106
4107 DisambiguationPopupTestWebViewClient client;
4108
4109 // Make sure we initialize to minimum scale, even if the window size
4110 // only becomes available after the load begins.
4111 FrameTestHelpers::WebViewHelper webViewHelper;
4112 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client);
4113 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
4114 webViewHelper.webView()->layout();
4115
4116 // Click somewhere where the popup shouldn't appear.
4117 client.resetTriggered();
4118 webViewHelper.webView()->handleInputEvent(fatTap(viewportWidth / 2, 0));
4119 EXPECT_FALSE(client.triggered());
4120
4121 // Click directly in between two container divs with click handlers, with children that don't handle clicks.
4122 client.resetTriggered();
4123 webViewHelper.webView()->handleInputEvent(fatTap(viewportWidth / 2, divHeight));
4124 EXPECT_TRUE(client.triggered());
4125
4126 // The third div container should be blacklisted if you click on the link it contains.
4127 client.resetTriggered();
4128 webViewHelper.webView()->handleInputEvent(fatTap(viewportWidth / 2, divHeight * 3.25));
4129 EXPECT_FALSE(client.triggered());
4130 }
4131
TEST_F(WebFrameTest,DisambiguationPopupPageScale)4132 TEST_F(WebFrameTest, DisambiguationPopupPageScale)
4133 {
4134 registerMockedHttpURLLoad("disambiguation_popup_page_scale.html");
4135
4136 DisambiguationPopupTestWebViewClient client;
4137
4138 // Make sure we initialize to minimum scale, even if the window size
4139 // only becomes available after the load begins.
4140 FrameTestHelpers::WebViewHelper webViewHelper;
4141 webViewHelper.initializeAndLoad(m_baseURL + "disambiguation_popup_page_scale.html", true, 0, &client);
4142 webViewHelper.webView()->resize(WebSize(1000, 1000));
4143 webViewHelper.webView()->layout();
4144
4145 client.resetTriggered();
4146 webViewHelper.webView()->handleInputEvent(fatTap(80, 80));
4147 EXPECT_TRUE(client.triggered());
4148
4149 client.resetTriggered();
4150 webViewHelper.webView()->handleInputEvent(fatTap(230, 190));
4151 EXPECT_TRUE(client.triggered());
4152
4153 webViewHelper.webView()->setPageScaleFactor(3.0f);
4154 webViewHelper.webView()->layout();
4155
4156 client.resetTriggered();
4157 webViewHelper.webView()->handleInputEvent(fatTap(240, 240));
4158 EXPECT_TRUE(client.triggered());
4159
4160 client.resetTriggered();
4161 webViewHelper.webView()->handleInputEvent(fatTap(690, 570));
4162 EXPECT_FALSE(client.triggered());
4163 }
4164
4165 class TestSubstituteDataWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
4166 public:
TestSubstituteDataWebFrameClient()4167 TestSubstituteDataWebFrameClient()
4168 : m_commitCalled(false)
4169 {
4170 }
4171
didFailProvisionalLoad(WebLocalFrame * frame,const WebURLError & error)4172 virtual void didFailProvisionalLoad(WebLocalFrame* frame, const WebURLError& error)
4173 {
4174 frame->loadHTMLString("This should appear", toKURL("data:text/html,chromewebdata"), error.unreachableURL, true);
4175 }
4176
didCommitProvisionalLoad(WebLocalFrame * frame,const WebHistoryItem &,WebHistoryCommitType)4177 virtual void didCommitProvisionalLoad(WebLocalFrame* frame, const WebHistoryItem&, WebHistoryCommitType)
4178 {
4179 if (frame->dataSource()->response().url() != WebURL(URLTestHelpers::toKURL("about:blank")))
4180 m_commitCalled = true;
4181 }
4182
commitCalled() const4183 bool commitCalled() const { return m_commitCalled; }
4184
4185 private:
4186 bool m_commitCalled;
4187 };
4188
TEST_F(WebFrameTest,ReplaceNavigationAfterHistoryNavigation)4189 TEST_F(WebFrameTest, ReplaceNavigationAfterHistoryNavigation)
4190 {
4191 TestSubstituteDataWebFrameClient webFrameClient;
4192
4193 FrameTestHelpers::WebViewHelper webViewHelper;
4194 webViewHelper.initializeAndLoad("about:blank", true, &webFrameClient);
4195 WebFrame* frame = webViewHelper.webView()->mainFrame();
4196
4197 // Load a url as a history navigation that will return an error. TestSubstituteDataWebFrameClient
4198 // will start a SubstituteData load in response to the load failure, which should get fully committed.
4199 // Due to https://bugs.webkit.org/show_bug.cgi?id=91685, FrameLoader::didReceiveData() wasn't getting
4200 // called in this case, which resulted in the SubstituteData document not getting displayed.
4201 WebURLError error;
4202 error.reason = 1337;
4203 error.domain = "WebFrameTest";
4204 std::string errorURL = "http://0.0.0.0";
4205 WebURLResponse response;
4206 response.initialize();
4207 response.setURL(URLTestHelpers::toKURL(errorURL));
4208 response.setMIMEType("text/html");
4209 response.setHTTPStatusCode(500);
4210 WebHistoryItem errorHistoryItem;
4211 errorHistoryItem.initialize();
4212 errorHistoryItem.setURLString(WebString::fromUTF8(errorURL.c_str(), errorURL.length()));
4213 Platform::current()->unitTestSupport()->registerMockedErrorURL(URLTestHelpers::toKURL(errorURL), response, error);
4214 FrameTestHelpers::loadHistoryItem(frame, errorHistoryItem, WebHistoryDifferentDocumentLoad, WebURLRequest::UseProtocolCachePolicy);
4215
4216 WebString text = frame->contentAsText(std::numeric_limits<size_t>::max());
4217 EXPECT_EQ("This should appear", text.utf8());
4218 EXPECT_TRUE(webFrameClient.commitCalled());
4219 }
4220
4221 class TestWillInsertBodyWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
4222 public:
TestWillInsertBodyWebFrameClient()4223 TestWillInsertBodyWebFrameClient() : m_numBodies(0), m_didLoad(false)
4224 {
4225 }
4226
didCommitProvisionalLoad(WebLocalFrame *,const WebHistoryItem &,WebHistoryCommitType)4227 virtual void didCommitProvisionalLoad(WebLocalFrame*, const WebHistoryItem&, WebHistoryCommitType) OVERRIDE
4228 {
4229 m_numBodies = 0;
4230 m_didLoad = true;
4231 }
4232
didCreateDocumentElement(WebLocalFrame *)4233 virtual void didCreateDocumentElement(WebLocalFrame*) OVERRIDE
4234 {
4235 EXPECT_EQ(0, m_numBodies);
4236 }
4237
willInsertBody(WebLocalFrame *)4238 virtual void willInsertBody(WebLocalFrame*) OVERRIDE
4239 {
4240 m_numBodies++;
4241 }
4242
4243 int m_numBodies;
4244 bool m_didLoad;
4245 };
4246
TEST_F(WebFrameTest,HTMLDocument)4247 TEST_F(WebFrameTest, HTMLDocument)
4248 {
4249 registerMockedHttpURLLoad("clipped-body.html");
4250
4251 TestWillInsertBodyWebFrameClient webFrameClient;
4252 FrameTestHelpers::WebViewHelper webViewHelper;
4253 webViewHelper.initializeAndLoad(m_baseURL + "clipped-body.html", false, &webFrameClient);
4254
4255 EXPECT_TRUE(webFrameClient.m_didLoad);
4256 EXPECT_EQ(1, webFrameClient.m_numBodies);
4257 }
4258
TEST_F(WebFrameTest,EmptyDocument)4259 TEST_F(WebFrameTest, EmptyDocument)
4260 {
4261 registerMockedHttpURLLoad("pageserializer/green_rectangle.svg");
4262
4263 TestWillInsertBodyWebFrameClient webFrameClient;
4264 FrameTestHelpers::WebViewHelper webViewHelper;
4265 webViewHelper.initialize(false, &webFrameClient);
4266
4267 EXPECT_FALSE(webFrameClient.m_didLoad);
4268 EXPECT_EQ(1, webFrameClient.m_numBodies); // The empty document that a new frame starts with triggers this.
4269 }
4270
TEST_F(WebFrameTest,MoveCaretSelectionTowardsWindowPointWithNoSelection)4271 TEST_F(WebFrameTest, MoveCaretSelectionTowardsWindowPointWithNoSelection)
4272 {
4273 FrameTestHelpers::WebViewHelper webViewHelper;
4274 webViewHelper.initializeAndLoad("about:blank", true);
4275 WebFrame* frame = webViewHelper.webView()->mainFrame();
4276
4277 // This test passes if this doesn't crash.
4278 frame->moveCaretSelection(WebPoint(0, 0));
4279 }
4280
4281 class SpellCheckClient : public WebSpellCheckClient {
4282 public:
SpellCheckClient(uint32_t hash=0)4283 explicit SpellCheckClient(uint32_t hash = 0) : m_numberOfTimesChecked(0), m_hash(hash) { }
~SpellCheckClient()4284 virtual ~SpellCheckClient() { }
requestCheckingOfText(const blink::WebString &,const blink::WebVector<uint32_t> &,const blink::WebVector<unsigned> &,blink::WebTextCheckingCompletion * completion)4285 virtual void requestCheckingOfText(const blink::WebString&, const blink::WebVector<uint32_t>&, const blink::WebVector<unsigned>&, blink::WebTextCheckingCompletion* completion) OVERRIDE
4286 {
4287 ++m_numberOfTimesChecked;
4288 Vector<WebTextCheckingResult> results;
4289 const int misspellingStartOffset = 1;
4290 const int misspellingLength = 8;
4291 results.append(WebTextCheckingResult(WebTextDecorationTypeSpelling, misspellingStartOffset, misspellingLength, WebString(), m_hash));
4292 completion->didFinishCheckingText(results);
4293 }
numberOfTimesChecked() const4294 int numberOfTimesChecked() const { return m_numberOfTimesChecked; }
4295 private:
4296 int m_numberOfTimesChecked;
4297 uint32_t m_hash;
4298 };
4299
TEST_F(WebFrameTest,ReplaceMisspelledRange)4300 TEST_F(WebFrameTest, ReplaceMisspelledRange)
4301 {
4302 registerMockedHttpURLLoad("spell.html");
4303 FrameTestHelpers::WebViewHelper webViewHelper;
4304 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4305 SpellCheckClient spellcheck;
4306 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4307
4308 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4309 Document* document = frame->frame()->document();
4310 Element* element = document->getElementById("data");
4311
4312 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4313 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4314 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4315
4316 element->focus();
4317 document->execCommand("InsertText", false, "_wellcome_.");
4318
4319 const int allTextBeginOffset = 0;
4320 const int allTextLength = 11;
4321 frame->selectRange(WebRange::fromDocumentRange(frame, allTextBeginOffset, allTextLength));
4322 RefPtrWillBeRawPtr<Range> selectionRange = frame->frame()->selection().toNormalizedRange();
4323
4324 EXPECT_EQ(1, spellcheck.numberOfTimesChecked());
4325 EXPECT_EQ(1U, document->markers().markersInRange(selectionRange.get(), DocumentMarker::Spelling).size());
4326
4327 frame->replaceMisspelledRange("welcome");
4328 EXPECT_EQ("_welcome_.", frame->contentAsText(std::numeric_limits<size_t>::max()).utf8());
4329 }
4330
TEST_F(WebFrameTest,RemoveSpellingMarkers)4331 TEST_F(WebFrameTest, RemoveSpellingMarkers)
4332 {
4333 registerMockedHttpURLLoad("spell.html");
4334 FrameTestHelpers::WebViewHelper webViewHelper;
4335 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4336 SpellCheckClient spellcheck;
4337 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4338
4339 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4340 Document* document = frame->frame()->document();
4341 Element* element = document->getElementById("data");
4342
4343 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4344 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4345 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4346
4347 element->focus();
4348 document->execCommand("InsertText", false, "_wellcome_.");
4349
4350 frame->removeSpellingMarkers();
4351
4352 const int allTextBeginOffset = 0;
4353 const int allTextLength = 11;
4354 frame->selectRange(WebRange::fromDocumentRange(frame, allTextBeginOffset, allTextLength));
4355 RefPtrWillBeRawPtr<Range> selectionRange = frame->frame()->selection().toNormalizedRange();
4356
4357 EXPECT_EQ(0U, document->markers().markersInRange(selectionRange.get(), DocumentMarker::Spelling).size());
4358 }
4359
TEST_F(WebFrameTest,MarkerHashIdentifiers)4360 TEST_F(WebFrameTest, MarkerHashIdentifiers) {
4361 registerMockedHttpURLLoad("spell.html");
4362 FrameTestHelpers::WebViewHelper webViewHelper;
4363 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4364
4365 static const uint32_t kHash = 42;
4366 SpellCheckClient spellcheck(kHash);
4367 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4368
4369 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4370 Document* document = frame->frame()->document();
4371 Element* element = document->getElementById("data");
4372
4373 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4374 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4375 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4376
4377 element->focus();
4378 document->execCommand("InsertText", false, "wellcome.");
4379
4380 WebVector<uint32_t> documentMarkers;
4381 webViewHelper.webView()->spellingMarkers(&documentMarkers);
4382 EXPECT_EQ(1U, documentMarkers.size());
4383 EXPECT_EQ(kHash, documentMarkers[0]);
4384 }
4385
4386 class StubbornSpellCheckClient : public WebSpellCheckClient {
4387 public:
StubbornSpellCheckClient()4388 StubbornSpellCheckClient() : m_completion(0) { }
~StubbornSpellCheckClient()4389 virtual ~StubbornSpellCheckClient() { }
4390
requestCheckingOfText(const blink::WebString &,const blink::WebVector<uint32_t> &,const blink::WebVector<unsigned> &,blink::WebTextCheckingCompletion * completion)4391 virtual void requestCheckingOfText(
4392 const blink::WebString&,
4393 const blink::WebVector<uint32_t>&,
4394 const blink::WebVector<unsigned>&,
4395 blink::WebTextCheckingCompletion* completion) OVERRIDE
4396 {
4397 m_completion = completion;
4398 }
4399
kickNoResults()4400 void kickNoResults()
4401 {
4402 kick(-1, -1, WebTextDecorationTypeSpelling);
4403 }
4404
kick()4405 void kick()
4406 {
4407 kick(1, 8, WebTextDecorationTypeSpelling);
4408 }
4409
kickGrammar()4410 void kickGrammar()
4411 {
4412 kick(1, 8, WebTextDecorationTypeGrammar);
4413 }
4414
kickInvisibleSpellcheck()4415 void kickInvisibleSpellcheck()
4416 {
4417 kick(1, 8, WebTextDecorationTypeInvisibleSpellcheck);
4418 }
4419
4420 private:
kick(int misspellingStartOffset,int misspellingLength,WebTextDecorationType type)4421 void kick(int misspellingStartOffset, int misspellingLength, WebTextDecorationType type)
4422 {
4423 if (!m_completion)
4424 return;
4425 Vector<WebTextCheckingResult> results;
4426 if (misspellingStartOffset >= 0 && misspellingLength > 0)
4427 results.append(WebTextCheckingResult(type, misspellingStartOffset, misspellingLength));
4428 m_completion->didFinishCheckingText(results);
4429 m_completion = 0;
4430 }
4431
4432 blink::WebTextCheckingCompletion* m_completion;
4433 };
4434
TEST_F(WebFrameTest,SlowSpellcheckMarkerPosition)4435 TEST_F(WebFrameTest, SlowSpellcheckMarkerPosition)
4436 {
4437 registerMockedHttpURLLoad("spell.html");
4438 FrameTestHelpers::WebViewHelper webViewHelper;
4439 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4440
4441 StubbornSpellCheckClient spellcheck;
4442 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4443
4444 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4445 WebInputElement webInputElement = frame->document().getElementById("data").to<WebInputElement>();
4446 Document* document = frame->frame()->document();
4447 Element* element = document->getElementById("data");
4448
4449 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4450 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4451 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4452
4453 element->focus();
4454 document->execCommand("InsertText", false, "wellcome ");
4455 webInputElement.setSelectionRange(0, 0);
4456 document->execCommand("InsertText", false, "he");
4457
4458 spellcheck.kick();
4459
4460 WebVector<uint32_t> documentMarkers;
4461 webViewHelper.webView()->spellingMarkers(&documentMarkers);
4462 EXPECT_EQ(0U, documentMarkers.size());
4463 }
4464
4465 // This test verifies that cancelling spelling request does not cause a
4466 // write-after-free when there's no spellcheck client set.
TEST_F(WebFrameTest,CancelSpellingRequestCrash)4467 TEST_F(WebFrameTest, CancelSpellingRequestCrash)
4468 {
4469 registerMockedHttpURLLoad("spell.html");
4470 FrameTestHelpers::WebViewHelper webViewHelper;
4471 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4472 webViewHelper.webView()->setSpellCheckClient(0);
4473
4474 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4475 Document* document = frame->frame()->document();
4476 Element* element = document->getElementById("data");
4477
4478 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4479 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4480 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4481
4482 element->focus();
4483 frame->frame()->editor().replaceSelectionWithText("A", false, false);
4484 frame->frame()->spellChecker().cancelCheck();
4485 }
4486
TEST_F(WebFrameTest,SpellcheckResultErasesMarkers)4487 TEST_F(WebFrameTest, SpellcheckResultErasesMarkers)
4488 {
4489 registerMockedHttpURLLoad("spell.html");
4490 FrameTestHelpers::WebViewHelper webViewHelper;
4491 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4492
4493 StubbornSpellCheckClient spellcheck;
4494 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4495
4496 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4497 WebInputElement webInputElement = frame->document().getElementById("data").to<WebInputElement>();
4498 Document* document = frame->frame()->document();
4499 Element* element = document->getElementById("data");
4500
4501 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4502 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4503 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4504
4505 element->focus();
4506 document->execCommand("InsertText", false, "welcome ");
4507 document->markers().addMarker(rangeOfContents(element->toNode()).get(), DocumentMarker::Spelling);
4508 document->markers().addMarker(rangeOfContents(element->toNode()).get(), DocumentMarker::Grammar);
4509 document->markers().addMarker(rangeOfContents(element->toNode()).get(), DocumentMarker::InvisibleSpellcheck);
4510 EXPECT_EQ(3U, document->markers().markers().size());
4511
4512 spellcheck.kickNoResults();
4513 EXPECT_EQ(0U, document->markers().markers().size());
4514 }
4515
TEST_F(WebFrameTest,SpellcheckResultsSavedInDocument)4516 TEST_F(WebFrameTest, SpellcheckResultsSavedInDocument)
4517 {
4518 registerMockedHttpURLLoad("spell.html");
4519 FrameTestHelpers::WebViewHelper webViewHelper;
4520 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4521
4522 StubbornSpellCheckClient spellcheck;
4523 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4524
4525 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4526 WebInputElement webInputElement = frame->document().getElementById("data").to<WebInputElement>();
4527 Document* document = frame->frame()->document();
4528 Element* element = document->getElementById("data");
4529
4530 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4531 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4532 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4533
4534 element->focus();
4535 document->execCommand("InsertText", false, "wellcome ");
4536
4537 spellcheck.kick();
4538 ASSERT_EQ(1U, document->markers().markers().size());
4539 ASSERT_NE(static_cast<DocumentMarker*>(0), document->markers().markers()[0]);
4540 EXPECT_EQ(DocumentMarker::Spelling, document->markers().markers()[0]->type());
4541
4542 document->execCommand("InsertText", false, "wellcome ");
4543
4544 spellcheck.kickGrammar();
4545 ASSERT_EQ(1U, document->markers().markers().size());
4546 ASSERT_NE(static_cast<DocumentMarker*>(0), document->markers().markers()[0]);
4547 EXPECT_EQ(DocumentMarker::Grammar, document->markers().markers()[0]->type());
4548
4549 document->execCommand("InsertText", false, "wellcome ");
4550
4551 spellcheck.kickInvisibleSpellcheck();
4552 ASSERT_EQ(1U, document->markers().markers().size());
4553 ASSERT_NE(static_cast<DocumentMarker*>(0), document->markers().markers()[0]);
4554 EXPECT_EQ(DocumentMarker::InvisibleSpellcheck, document->markers().markers()[0]->type());
4555 }
4556
4557 class TestAccessInitialDocumentWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
4558 public:
TestAccessInitialDocumentWebFrameClient()4559 TestAccessInitialDocumentWebFrameClient() : m_didAccessInitialDocument(false)
4560 {
4561 }
4562
didAccessInitialDocument(WebLocalFrame * frame)4563 virtual void didAccessInitialDocument(WebLocalFrame* frame)
4564 {
4565 EXPECT_TRUE(!m_didAccessInitialDocument);
4566 m_didAccessInitialDocument = true;
4567 }
4568
4569 bool m_didAccessInitialDocument;
4570 };
4571
TEST_F(WebFrameTest,DidAccessInitialDocumentBody)4572 TEST_F(WebFrameTest, DidAccessInitialDocumentBody)
4573 {
4574 // FIXME: Why is this local webViewClient needed instead of the default
4575 // WebViewHelper one? With out it there's some mysterious crash in the
4576 // WebViewHelper destructor.
4577 FrameTestHelpers::TestWebViewClient webViewClient;
4578 TestAccessInitialDocumentWebFrameClient webFrameClient;
4579 FrameTestHelpers::WebViewHelper webViewHelper;
4580 webViewHelper.initialize(true, &webFrameClient, &webViewClient);
4581 runPendingTasks();
4582 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4583
4584 // Create another window that will try to access it.
4585 FrameTestHelpers::WebViewHelper newWebViewHelper;
4586 WebView* newView = newWebViewHelper.initialize(true);
4587 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
4588 runPendingTasks();
4589 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4590
4591 // Access the initial document by modifying the body.
4592 newView->mainFrame()->executeScript(
4593 WebScriptSource("window.opener.document.body.innerHTML += 'Modified';"));
4594 runPendingTasks();
4595 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4596
4597 // Access the initial document again, to ensure we don't notify twice.
4598 newView->mainFrame()->executeScript(
4599 WebScriptSource("window.opener.document.body.innerHTML += 'Modified';"));
4600 runPendingTasks();
4601 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4602 }
4603
TEST_F(WebFrameTest,DidAccessInitialDocumentNavigator)4604 TEST_F(WebFrameTest, DidAccessInitialDocumentNavigator)
4605 {
4606 // FIXME: Why is this local webViewClient needed instead of the default
4607 // WebViewHelper one? With out it there's some mysterious crash in the
4608 // WebViewHelper destructor.
4609 FrameTestHelpers::TestWebViewClient webViewClient;
4610 TestAccessInitialDocumentWebFrameClient webFrameClient;
4611 FrameTestHelpers::WebViewHelper webViewHelper;
4612 webViewHelper.initialize(true, &webFrameClient, &webViewClient);
4613 runPendingTasks();
4614 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4615
4616 // Create another window that will try to access it.
4617 FrameTestHelpers::WebViewHelper newWebViewHelper;
4618 WebView* newView = newWebViewHelper.initialize(true);
4619 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
4620 runPendingTasks();
4621 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4622
4623 // Access the initial document to get to the navigator object.
4624 newView->mainFrame()->executeScript(
4625 WebScriptSource("console.log(window.opener.navigator);"));
4626 runPendingTasks();
4627 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4628 }
4629
TEST_F(WebFrameTest,DidAccessInitialDocumentViaJavascriptUrl)4630 TEST_F(WebFrameTest, DidAccessInitialDocumentViaJavascriptUrl)
4631 {
4632 TestAccessInitialDocumentWebFrameClient webFrameClient;
4633 FrameTestHelpers::WebViewHelper webViewHelper;
4634 webViewHelper.initialize(true, &webFrameClient);
4635 runPendingTasks();
4636 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4637
4638 // Access the initial document from a javascript: URL.
4639 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.appendChild(document.createTextNode('Modified'))");
4640 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4641 }
4642
4643 // Fails on the WebKit XP (deps) bot. http://crbug.com/312192
4644 #if OS(WIN)
TEST_F(WebFrameTest,DISABLED_DidAccessInitialDocumentBodyBeforeModalDialog)4645 TEST_F(WebFrameTest, DISABLED_DidAccessInitialDocumentBodyBeforeModalDialog)
4646 #else
4647 TEST_F(WebFrameTest, DidAccessInitialDocumentBodyBeforeModalDialog)
4648 #endif
4649 {
4650 // FIXME: Why is this local webViewClient needed instead of the default
4651 // WebViewHelper one? With out it there's some mysterious crash in the
4652 // WebViewHelper destructor.
4653 FrameTestHelpers::TestWebViewClient webViewClient;
4654 TestAccessInitialDocumentWebFrameClient webFrameClient;
4655 FrameTestHelpers::WebViewHelper webViewHelper;
4656 webViewHelper.initialize(true, &webFrameClient, &webViewClient);
4657 runPendingTasks();
4658 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4659
4660 // Create another window that will try to access it.
4661 FrameTestHelpers::WebViewHelper newWebViewHelper;
4662 WebView* newView = newWebViewHelper.initialize(true);
4663 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
4664 runPendingTasks();
4665 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4666
4667 // Access the initial document by modifying the body. We normally set a
4668 // timer to notify the client.
4669 newView->mainFrame()->executeScript(
4670 WebScriptSource("window.opener.document.body.innerHTML += 'Modified';"));
4671 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4672
4673 // Make sure that a modal dialog forces us to notify right away.
4674 newView->mainFrame()->executeScript(
4675 WebScriptSource("window.opener.confirm('Modal');"));
4676 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4677
4678 // Ensure that we don't notify again later.
4679 runPendingTasks();
4680 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4681 }
4682
4683 // Fails on the WebKit XP (deps) bot. http://crbug.com/312192
4684 #if OS(WIN)
TEST_F(WebFrameTest,DISABLED_DidWriteToInitialDocumentBeforeModalDialog)4685 TEST_F(WebFrameTest, DISABLED_DidWriteToInitialDocumentBeforeModalDialog)
4686 #else
4687 TEST_F(WebFrameTest, DidWriteToInitialDocumentBeforeModalDialog)
4688 #endif
4689 {
4690 // FIXME: Why is this local webViewClient needed instead of the default
4691 // WebViewHelper one? With out it there's some mysterious crash in the
4692 // WebViewHelper destructor.
4693 FrameTestHelpers::TestWebViewClient webViewClient;
4694 TestAccessInitialDocumentWebFrameClient webFrameClient;
4695 FrameTestHelpers::WebViewHelper webViewHelper;
4696 webViewHelper.initialize(true, &webFrameClient, &webViewClient);
4697 runPendingTasks();
4698 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4699
4700 // Create another window that will try to access it.
4701 FrameTestHelpers::WebViewHelper newWebViewHelper;
4702 WebView* newView = newWebViewHelper.initialize(true);
4703 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
4704 runPendingTasks();
4705 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4706
4707 // Access the initial document with document.write, which moves us past the
4708 // initial empty document state of the state machine. We normally set a
4709 // timer to notify the client.
4710 newView->mainFrame()->executeScript(
4711 WebScriptSource("window.opener.document.write('Modified');"));
4712 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4713
4714 // Make sure that a modal dialog forces us to notify right away.
4715 newView->mainFrame()->executeScript(
4716 WebScriptSource("window.opener.confirm('Modal');"));
4717 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4718
4719 // Ensure that we don't notify again later.
4720 runPendingTasks();
4721 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4722 }
4723
4724 class TestMainFrameUserOrProgrammaticScrollFrameClient : public FrameTestHelpers::TestWebFrameClient {
4725 public:
TestMainFrameUserOrProgrammaticScrollFrameClient()4726 TestMainFrameUserOrProgrammaticScrollFrameClient() { reset(); }
reset()4727 void reset()
4728 {
4729 m_didScrollMainFrame = false;
4730 m_wasProgrammaticScroll = false;
4731 }
wasUserScroll() const4732 bool wasUserScroll() const { return m_didScrollMainFrame && !m_wasProgrammaticScroll; }
wasProgrammaticScroll() const4733 bool wasProgrammaticScroll() const { return m_didScrollMainFrame && m_wasProgrammaticScroll; }
4734
4735 // WebFrameClient:
didChangeScrollOffset(WebLocalFrame * frame)4736 virtual void didChangeScrollOffset(WebLocalFrame* frame) OVERRIDE
4737 {
4738 if (frame->parent())
4739 return;
4740 EXPECT_FALSE(m_didScrollMainFrame);
4741 WebCore::FrameView* view = toWebLocalFrameImpl(frame)->frameView();
4742 // FrameView can be scrolled in FrameView::setFixedVisibleContentRect
4743 // which is called from LocalFrame::createView (before the frame is associated
4744 // with the the view).
4745 if (view) {
4746 m_didScrollMainFrame = true;
4747 m_wasProgrammaticScroll = view->inProgrammaticScroll();
4748 }
4749 }
4750 private:
4751 bool m_didScrollMainFrame;
4752 bool m_wasProgrammaticScroll;
4753 };
4754
TEST_F(WebFrameTest,CompositorScrollIsUserScrollLongPage)4755 TEST_F(WebFrameTest, CompositorScrollIsUserScrollLongPage)
4756 {
4757 registerMockedHttpURLLoad("long_scroll.html");
4758 TestMainFrameUserOrProgrammaticScrollFrameClient client;
4759
4760 // Make sure we initialize to minimum scale, even if the window size
4761 // only becomes available after the load begins.
4762 FrameTestHelpers::WebViewHelper webViewHelper;
4763 webViewHelper.initializeAndLoad(m_baseURL + "long_scroll.html", true, &client);
4764 webViewHelper.webView()->resize(WebSize(1000, 1000));
4765 webViewHelper.webView()->layout();
4766
4767 EXPECT_FALSE(client.wasUserScroll());
4768 EXPECT_FALSE(client.wasProgrammaticScroll());
4769
4770 // Do a compositor scroll, verify that this is counted as a user scroll.
4771 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(0, 1), 1.1f);
4772 EXPECT_TRUE(client.wasUserScroll());
4773 client.reset();
4774
4775 EXPECT_FALSE(client.wasUserScroll());
4776 EXPECT_FALSE(client.wasProgrammaticScroll());
4777
4778 // The page scale 1.0f and scroll.
4779 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(0, 1), 1.0f);
4780 EXPECT_TRUE(client.wasUserScroll());
4781 client.reset();
4782
4783 // No scroll event if there is no scroll delta.
4784 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.0f);
4785 EXPECT_FALSE(client.wasUserScroll());
4786 EXPECT_FALSE(client.wasProgrammaticScroll());
4787 client.reset();
4788
4789 // Non zero page scale and scroll.
4790 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(9, 13), 0.6f);
4791 EXPECT_TRUE(client.wasUserScroll());
4792 client.reset();
4793
4794 // Programmatic scroll.
4795 WebLocalFrameImpl* frameImpl = webViewHelper.webViewImpl()->mainFrameImpl();
4796 frameImpl->executeScript(WebScriptSource("window.scrollTo(0, 20);"));
4797 EXPECT_FALSE(client.wasUserScroll());
4798 EXPECT_TRUE(client.wasProgrammaticScroll());
4799 client.reset();
4800
4801 // Programmatic scroll to same offset. No scroll event should be generated.
4802 frameImpl->executeScript(WebScriptSource("window.scrollTo(0, 20);"));
4803 EXPECT_FALSE(client.wasProgrammaticScroll());
4804 EXPECT_FALSE(client.wasUserScroll());
4805 client.reset();
4806 }
4807
TEST_F(WebFrameTest,CompositorScrollIsUserScrollShortPage)4808 TEST_F(WebFrameTest, CompositorScrollIsUserScrollShortPage)
4809 {
4810 registerMockedHttpURLLoad("short_scroll.html");
4811
4812 TestMainFrameUserOrProgrammaticScrollFrameClient client;
4813
4814 // Short page tests.
4815 FrameTestHelpers::WebViewHelper webViewHelper;
4816 webViewHelper.initializeAndLoad(m_baseURL + "short_scroll.html", true, &client);
4817
4818 webViewHelper.webView()->resize(WebSize(1000, 1000));
4819 webViewHelper.webView()->layout();
4820
4821 EXPECT_FALSE(client.wasUserScroll());
4822 EXPECT_FALSE(client.wasProgrammaticScroll());
4823
4824 // Non zero page scale and scroll.
4825 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(9, 13), 2.0f);
4826 EXPECT_FALSE(client.wasProgrammaticScroll());
4827 EXPECT_TRUE(client.wasUserScroll());
4828 client.reset();
4829 }
4830
TEST_F(WebFrameTest,FirstPartyForCookiesForRedirect)4831 TEST_F(WebFrameTest, FirstPartyForCookiesForRedirect)
4832 {
4833 WTF::String filePath = Platform::current()->unitTestSupport()->webKitRootDir();
4834 filePath.append("/Source/web/tests/data/first_party.html");
4835
4836 WebURL testURL(toKURL("http://www.test.com/first_party_redirect.html"));
4837 char redirect[] = "http://www.test.com/first_party.html";
4838 WebURL redirectURL(toKURL(redirect));
4839 WebURLResponse redirectResponse;
4840 redirectResponse.initialize();
4841 redirectResponse.setMIMEType("text/html");
4842 redirectResponse.setHTTPStatusCode(302);
4843 redirectResponse.setHTTPHeaderField("Location", redirect);
4844 Platform::current()->unitTestSupport()->registerMockedURL(testURL, redirectResponse, filePath);
4845
4846 WebURLResponse finalResponse;
4847 finalResponse.initialize();
4848 finalResponse.setMIMEType("text/html");
4849 Platform::current()->unitTestSupport()->registerMockedURL(redirectURL, finalResponse, filePath);
4850
4851 FrameTestHelpers::WebViewHelper webViewHelper;
4852 webViewHelper.initializeAndLoad(m_baseURL + "first_party_redirect.html", true);
4853 EXPECT_TRUE(webViewHelper.webView()->mainFrame()->document().firstPartyForCookies() == redirectURL);
4854 }
4855
4856 class TestNavigationPolicyWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
4857 public:
4858
didNavigateWithinPage(WebLocalFrame *,const WebHistoryItem &,WebHistoryCommitType)4859 virtual void didNavigateWithinPage(WebLocalFrame*, const WebHistoryItem&, WebHistoryCommitType) OVERRIDE
4860 {
4861 EXPECT_TRUE(false);
4862 }
4863 };
4864
TEST_F(WebFrameTest,SimulateFragmentAnchorMiddleClick)4865 TEST_F(WebFrameTest, SimulateFragmentAnchorMiddleClick)
4866 {
4867 registerMockedHttpURLLoad("fragment_middle_click.html");
4868 TestNavigationPolicyWebFrameClient client;
4869 FrameTestHelpers::WebViewHelper webViewHelper;
4870 webViewHelper.initializeAndLoad(m_baseURL + "fragment_middle_click.html", true, &client);
4871
4872 WebCore::Document* document = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document();
4873 WebCore::KURL destination = document->url();
4874 destination.setFragmentIdentifier("test");
4875
4876 RefPtrWillBeRawPtr<WebCore::Event> event = WebCore::MouseEvent::create(WebCore::EventTypeNames::click, false, false,
4877 document->domWindow(), 0, 0, 0, 0, 0, 0, 0, false, false, false, false, 1, nullptr, nullptr);
4878 WebCore::FrameLoadRequest frameRequest(document, WebCore::ResourceRequest(destination));
4879 frameRequest.setTriggeringEvent(event);
4880 toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->loader().load(frameRequest);
4881 }
4882
4883 class TestNewWindowWebViewClient : public FrameTestHelpers::TestWebViewClient {
4884 public:
createView(WebLocalFrame *,const WebURLRequest &,const WebWindowFeatures &,const WebString &,WebNavigationPolicy,bool)4885 virtual WebView* createView(WebLocalFrame*, const WebURLRequest&, const WebWindowFeatures&,
4886 const WebString&, WebNavigationPolicy, bool) OVERRIDE
4887 {
4888 EXPECT_TRUE(false);
4889 return 0;
4890 }
4891 };
4892
4893 class TestNewWindowWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
4894 public:
TestNewWindowWebFrameClient()4895 TestNewWindowWebFrameClient()
4896 : m_decidePolicyCallCount(0)
4897 {
4898 }
4899
decidePolicyForNavigation(WebLocalFrame *,WebDataSource::ExtraData *,const WebURLRequest &,WebNavigationType,WebNavigationPolicy policy,bool)4900 virtual WebNavigationPolicy decidePolicyForNavigation(WebLocalFrame*, WebDataSource::ExtraData*, const WebURLRequest&,
4901 WebNavigationType, WebNavigationPolicy policy, bool) OVERRIDE
4902 {
4903 m_decidePolicyCallCount++;
4904 return policy;
4905 }
4906
decidePolicyCallCount() const4907 int decidePolicyCallCount() const { return m_decidePolicyCallCount; }
4908
4909 private:
4910 int m_decidePolicyCallCount;
4911 };
4912
TEST_F(WebFrameTest,ModifiedClickNewWindow)4913 TEST_F(WebFrameTest, ModifiedClickNewWindow)
4914 {
4915 registerMockedHttpURLLoad("ctrl_click.html");
4916 registerMockedHttpURLLoad("hello_world.html");
4917 TestNewWindowWebViewClient webViewClient;
4918 TestNewWindowWebFrameClient webFrameClient;
4919 FrameTestHelpers::WebViewHelper webViewHelper;
4920 webViewHelper.initializeAndLoad(m_baseURL + "ctrl_click.html", true, &webFrameClient, &webViewClient);
4921
4922 WebCore::Document* document = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document();
4923 WebCore::KURL destination = toKURL(m_baseURL + "hello_world.html");
4924
4925 // ctrl+click event
4926 RefPtrWillBeRawPtr<WebCore::Event> event = WebCore::MouseEvent::create(WebCore::EventTypeNames::click, false, false,
4927 document->domWindow(), 0, 0, 0, 0, 0, 0, 0, true, false, false, false, 0, nullptr, nullptr);
4928 WebCore::FrameLoadRequest frameRequest(document, WebCore::ResourceRequest(destination));
4929 frameRequest.setTriggeringEvent(event);
4930 WebCore::UserGestureIndicator gesture(WebCore::DefinitelyProcessingUserGesture);
4931 toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->loader().load(frameRequest);
4932 FrameTestHelpers::pumpPendingRequestsDoNotUse(webViewHelper.webView()->mainFrame());
4933
4934 // decidePolicyForNavigation should be called both for the original request and the ctrl+click.
4935 EXPECT_EQ(2, webFrameClient.decidePolicyCallCount());
4936 }
4937
TEST_F(WebFrameTest,BackToReload)4938 TEST_F(WebFrameTest, BackToReload)
4939 {
4940 registerMockedHttpURLLoad("fragment_middle_click.html");
4941 FrameTestHelpers::WebViewHelper webViewHelper;
4942 webViewHelper.initializeAndLoad(m_baseURL + "fragment_middle_click.html", true);
4943 WebFrame* frame = webViewHelper.webView()->mainFrame();
4944 const WebCore::FrameLoader& mainFrameLoader = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->loader();
4945 RefPtr<WebCore::HistoryItem> firstItem = mainFrameLoader.currentItem();
4946 EXPECT_TRUE(firstItem);
4947
4948 registerMockedHttpURLLoad("white-1x1.png");
4949 FrameTestHelpers::loadFrame(frame, m_baseURL + "white-1x1.png");
4950 EXPECT_NE(firstItem.get(), mainFrameLoader.currentItem());
4951
4952 FrameTestHelpers::loadHistoryItem(frame, WebHistoryItem(firstItem.get()), WebHistoryDifferentDocumentLoad, WebURLRequest::UseProtocolCachePolicy);
4953 EXPECT_EQ(firstItem.get(), mainFrameLoader.currentItem());
4954
4955 FrameTestHelpers::reloadFrame(frame);
4956 EXPECT_EQ(WebURLRequest::ReloadIgnoringCacheData, frame->dataSource()->request().cachePolicy());
4957 }
4958
TEST_F(WebFrameTest,BackDuringChildFrameReload)4959 TEST_F(WebFrameTest, BackDuringChildFrameReload)
4960 {
4961 registerMockedHttpURLLoad("page_with_blank_iframe.html");
4962 FrameTestHelpers::WebViewHelper webViewHelper;
4963 webViewHelper.initializeAndLoad(m_baseURL + "page_with_blank_iframe.html", true);
4964 WebFrame* mainFrame = webViewHelper.webView()->mainFrame();
4965 const WebCore::FrameLoader& mainFrameLoader = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->loader();
4966 WebFrame* childFrame = mainFrame->firstChild();
4967 ASSERT_TRUE(childFrame);
4968
4969 // Start a history navigation, then have a different frame commit a navigation.
4970 // In this case, reload an about:blank frame, which will commit synchronously.
4971 // After the history navigation completes, both the appropriate document url and
4972 // the current history item should reflect the history navigation.
4973 registerMockedHttpURLLoad("white-1x1.png");
4974 WebHistoryItem item;
4975 item.initialize();
4976 WebURL historyURL(toKURL(m_baseURL + "white-1x1.png"));
4977 item.setURLString(historyURL.string());
4978 mainFrame->loadHistoryItem(item, WebHistoryDifferentDocumentLoad, WebURLRequest::UseProtocolCachePolicy);
4979
4980 FrameTestHelpers::reloadFrame(childFrame);
4981 EXPECT_EQ(item.urlString(), mainFrame->document().url().string());
4982 EXPECT_EQ(item.urlString(), WebString(mainFrameLoader.currentItem()->urlString()));
4983 }
4984
TEST_F(WebFrameTest,ReloadPost)4985 TEST_F(WebFrameTest, ReloadPost)
4986 {
4987 registerMockedHttpURLLoad("reload_post.html");
4988 FrameTestHelpers::WebViewHelper webViewHelper;
4989 webViewHelper.initializeAndLoad(m_baseURL + "reload_post.html", true);
4990 WebFrame* frame = webViewHelper.webView()->mainFrame();
4991
4992 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.forms[0].submit()");
4993 // Pump requests one more time after the javascript URL has executed to
4994 // trigger the actual POST load request.
4995 FrameTestHelpers::pumpPendingRequestsDoNotUse(webViewHelper.webView()->mainFrame());
4996 EXPECT_EQ(WebString::fromUTF8("POST"), frame->dataSource()->request().httpMethod());
4997
4998 FrameTestHelpers::reloadFrame(frame);
4999 EXPECT_EQ(WebURLRequest::ReloadIgnoringCacheData, frame->dataSource()->request().cachePolicy());
5000 EXPECT_EQ(WebNavigationTypeFormResubmitted, frame->dataSource()->navigationType());
5001 }
5002
TEST_F(WebFrameTest,LoadHistoryItemReload)5003 TEST_F(WebFrameTest, LoadHistoryItemReload)
5004 {
5005 registerMockedHttpURLLoad("fragment_middle_click.html");
5006 FrameTestHelpers::WebViewHelper webViewHelper;
5007 webViewHelper.initializeAndLoad(m_baseURL + "fragment_middle_click.html", true);
5008 WebFrame* frame = webViewHelper.webView()->mainFrame();
5009 const WebCore::FrameLoader& mainFrameLoader = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->loader();
5010 RefPtr<WebCore::HistoryItem> firstItem = mainFrameLoader.currentItem();
5011 EXPECT_TRUE(firstItem);
5012
5013 registerMockedHttpURLLoad("white-1x1.png");
5014 FrameTestHelpers::loadFrame(frame, m_baseURL + "white-1x1.png");
5015 EXPECT_NE(firstItem.get(), mainFrameLoader.currentItem());
5016
5017 // Cache policy overrides should take.
5018 FrameTestHelpers::loadHistoryItem(frame, WebHistoryItem(firstItem), WebHistoryDifferentDocumentLoad, WebURLRequest::ReloadIgnoringCacheData);
5019 EXPECT_EQ(firstItem.get(), mainFrameLoader.currentItem());
5020 EXPECT_EQ(WebURLRequest::ReloadIgnoringCacheData, frame->dataSource()->request().cachePolicy());
5021 }
5022
5023
5024 class TestCachePolicyWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5025 public:
TestCachePolicyWebFrameClient(TestCachePolicyWebFrameClient * parentClient)5026 explicit TestCachePolicyWebFrameClient(TestCachePolicyWebFrameClient* parentClient)
5027 : m_parentClient(parentClient)
5028 , m_policy(WebURLRequest::UseProtocolCachePolicy)
5029 , m_childClient(0)
5030 , m_willSendRequestCallCount(0)
5031 , m_childFrameCreationCount(0)
5032 {
5033 }
5034
setChildWebFrameClient(TestCachePolicyWebFrameClient * client)5035 void setChildWebFrameClient(TestCachePolicyWebFrameClient* client) { m_childClient = client; }
cachePolicy() const5036 WebURLRequest::CachePolicy cachePolicy() const { return m_policy; }
willSendRequestCallCount() const5037 int willSendRequestCallCount() const { return m_willSendRequestCallCount; }
childFrameCreationCount() const5038 int childFrameCreationCount() const { return m_childFrameCreationCount; }
5039
createChildFrame(WebLocalFrame * parent,const WebString &)5040 virtual WebFrame* createChildFrame(WebLocalFrame* parent, const WebString&)
5041 {
5042 ASSERT(m_childClient);
5043 m_childFrameCreationCount++;
5044 WebFrame* frame = WebLocalFrame::create(m_childClient);
5045 parent->appendChild(frame);
5046 return frame;
5047 }
5048
didStartLoading(bool toDifferentDocument)5049 virtual void didStartLoading(bool toDifferentDocument)
5050 {
5051 if (m_parentClient) {
5052 m_parentClient->didStartLoading(toDifferentDocument);
5053 return;
5054 }
5055 TestWebFrameClient::didStartLoading(toDifferentDocument);
5056 }
5057
didStopLoading()5058 virtual void didStopLoading()
5059 {
5060 if (m_parentClient) {
5061 m_parentClient->didStopLoading();
5062 return;
5063 }
5064 TestWebFrameClient::didStopLoading();
5065 }
5066
willSendRequest(WebLocalFrame * frame,unsigned,WebURLRequest & request,const WebURLResponse &)5067 virtual void willSendRequest(WebLocalFrame* frame, unsigned, WebURLRequest& request, const WebURLResponse&) OVERRIDE
5068 {
5069 m_policy = request.cachePolicy();
5070 m_willSendRequestCallCount++;
5071 }
5072
5073 private:
5074 TestCachePolicyWebFrameClient* m_parentClient;
5075
5076 WebURLRequest::CachePolicy m_policy;
5077 TestCachePolicyWebFrameClient* m_childClient;
5078 int m_willSendRequestCallCount;
5079 int m_childFrameCreationCount;
5080 };
5081
TEST_F(WebFrameTest,ReloadIframe)5082 TEST_F(WebFrameTest, ReloadIframe)
5083 {
5084 registerMockedHttpURLLoad("iframe_reload.html");
5085 registerMockedHttpURLLoad("visible_iframe.html");
5086 TestCachePolicyWebFrameClient mainClient(0);
5087 TestCachePolicyWebFrameClient childClient(&mainClient);
5088 mainClient.setChildWebFrameClient(&childClient);
5089
5090 FrameTestHelpers::WebViewHelper webViewHelper;
5091 webViewHelper.initializeAndLoad(m_baseURL + "iframe_reload.html", true, &mainClient);
5092
5093 WebLocalFrameImpl* mainFrame = webViewHelper.webViewImpl()->mainFrameImpl();
5094 RefPtr<WebLocalFrameImpl> childFrame = toWebLocalFrameImpl(mainFrame->firstChild());
5095 ASSERT_EQ(childFrame->client(), &childClient);
5096 EXPECT_EQ(mainClient.childFrameCreationCount(), 1);
5097 EXPECT_EQ(childClient.willSendRequestCallCount(), 1);
5098 EXPECT_EQ(childClient.cachePolicy(), WebURLRequest::UseProtocolCachePolicy);
5099
5100 FrameTestHelpers::reloadFrame(mainFrame);
5101
5102 // A new WebFrame should have been created, but the child WebFrameClient should be reused.
5103 ASSERT_NE(childFrame, toWebLocalFrameImpl(mainFrame->firstChild()));
5104 ASSERT_EQ(toWebLocalFrameImpl(mainFrame->firstChild())->client(), &childClient);
5105
5106 EXPECT_EQ(mainClient.childFrameCreationCount(), 2);
5107 EXPECT_EQ(childClient.willSendRequestCallCount(), 2);
5108 EXPECT_EQ(childClient.cachePolicy(), WebURLRequest::ReloadIgnoringCacheData);
5109 }
5110
5111 class TestSameDocumentWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5112 public:
TestSameDocumentWebFrameClient()5113 TestSameDocumentWebFrameClient()
5114 : m_frameLoadTypeSameSeen(false)
5115 {
5116 }
5117
willSendRequest(WebLocalFrame * frame,unsigned,WebURLRequest &,const WebURLResponse &)5118 virtual void willSendRequest(WebLocalFrame* frame, unsigned, WebURLRequest&, const WebURLResponse&)
5119 {
5120 if (toWebLocalFrameImpl(frame)->frame()->loader().loadType() == WebCore::FrameLoadTypeSame)
5121 m_frameLoadTypeSameSeen = true;
5122 }
5123
frameLoadTypeSameSeen() const5124 bool frameLoadTypeSameSeen() const { return m_frameLoadTypeSameSeen; }
5125
5126 private:
5127 bool m_frameLoadTypeSameSeen;
5128 };
5129
TEST_F(WebFrameTest,NavigateToSame)5130 TEST_F(WebFrameTest, NavigateToSame)
5131 {
5132 registerMockedHttpURLLoad("navigate_to_same.html");
5133 TestSameDocumentWebFrameClient client;
5134 FrameTestHelpers::WebViewHelper webViewHelper;
5135 webViewHelper.initializeAndLoad(m_baseURL + "navigate_to_same.html", true, &client);
5136 EXPECT_FALSE(client.frameLoadTypeSameSeen());
5137
5138 WebCore::FrameLoadRequest frameRequest(0, WebCore::ResourceRequest(toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document()->url()));
5139 toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->loader().load(frameRequest);
5140 FrameTestHelpers::pumpPendingRequestsDoNotUse(webViewHelper.webView()->mainFrame());
5141
5142 EXPECT_TRUE(client.frameLoadTypeSameSeen());
5143 }
5144
TEST_F(WebFrameTest,WebNodeImageContents)5145 TEST_F(WebFrameTest, WebNodeImageContents)
5146 {
5147 FrameTestHelpers::WebViewHelper webViewHelper;
5148 webViewHelper.initializeAndLoad("about:blank", true);
5149 WebFrame* frame = webViewHelper.webView()->mainFrame();
5150
5151 static const char bluePNG[] = "<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAGElEQVQYV2NkYPj/n4EIwDiqEF8oUT94AFIQE/cCn90IAAAAAElFTkSuQmCC\">";
5152
5153 // Load up the image and test that we can extract the contents.
5154 WebCore::KURL testURL = toKURL("about:blank");
5155 FrameTestHelpers::loadHTMLString(frame, bluePNG, testURL);
5156
5157 WebNode node = frame->document().body().firstChild();
5158 EXPECT_TRUE(node.isElementNode());
5159 WebElement element = node.to<WebElement>();
5160 WebImage image = element.imageContents();
5161 ASSERT_FALSE(image.isNull());
5162 EXPECT_EQ(image.size().width, 10);
5163 EXPECT_EQ(image.size().height, 10);
5164 // FIXME: The rest of this test is disabled since the ImageDecodeCache state may be inconsistent when this test runs.
5165 // crbug.com/266088
5166 // SkBitmap bitmap = image.getSkBitmap();
5167 // SkAutoLockPixels locker(bitmap);
5168 // EXPECT_EQ(bitmap.getColor(0, 0), SK_ColorBLUE);
5169 }
5170
5171 class TestStartStopCallbackWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5172 public:
TestStartStopCallbackWebFrameClient()5173 TestStartStopCallbackWebFrameClient()
5174 : m_startLoadingCount(0)
5175 , m_stopLoadingCount(0)
5176 , m_differentDocumentStartCount(0)
5177 {
5178 }
5179
didStartLoading(bool toDifferentDocument)5180 virtual void didStartLoading(bool toDifferentDocument) OVERRIDE
5181 {
5182 TestWebFrameClient::didStartLoading(toDifferentDocument);
5183 m_startLoadingCount++;
5184 if (toDifferentDocument)
5185 m_differentDocumentStartCount++;
5186 }
5187
didStopLoading()5188 virtual void didStopLoading() OVERRIDE
5189 {
5190 TestWebFrameClient::didStopLoading();
5191 m_stopLoadingCount++;
5192 }
5193
startLoadingCount() const5194 int startLoadingCount() const { return m_startLoadingCount; }
stopLoadingCount() const5195 int stopLoadingCount() const { return m_stopLoadingCount; }
differentDocumentStartCount() const5196 int differentDocumentStartCount() const { return m_differentDocumentStartCount; }
5197
5198 private:
5199 int m_startLoadingCount;
5200 int m_stopLoadingCount;
5201 int m_differentDocumentStartCount;
5202 };
5203
TEST_F(WebFrameTest,PushStateStartsAndStops)5204 TEST_F(WebFrameTest, PushStateStartsAndStops)
5205 {
5206 registerMockedHttpURLLoad("push_state.html");
5207 TestStartStopCallbackWebFrameClient client;
5208 FrameTestHelpers::WebViewHelper webViewHelper;
5209 webViewHelper.initializeAndLoad(m_baseURL + "push_state.html", true, &client);
5210
5211 EXPECT_EQ(client.startLoadingCount(), 2);
5212 EXPECT_EQ(client.stopLoadingCount(), 2);
5213 EXPECT_EQ(client.differentDocumentStartCount(), 1);
5214 }
5215
5216 class TestDidNavigateCommitTypeWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5217 public:
TestDidNavigateCommitTypeWebFrameClient()5218 TestDidNavigateCommitTypeWebFrameClient()
5219 : m_lastCommitType(WebHistoryInertCommit)
5220 {
5221 }
5222
didNavigateWithinPage(WebLocalFrame *,const WebHistoryItem &,WebHistoryCommitType type)5223 virtual void didNavigateWithinPage(WebLocalFrame*, const WebHistoryItem&, WebHistoryCommitType type) OVERRIDE
5224 {
5225 m_lastCommitType = type;
5226 }
5227
lastCommitType() const5228 WebHistoryCommitType lastCommitType() const { return m_lastCommitType; }
5229
5230 private:
5231 WebHistoryCommitType m_lastCommitType;
5232 };
5233
TEST_F(WebFrameTest,SameDocumentHistoryNavigationCommitType)5234 TEST_F(WebFrameTest, SameDocumentHistoryNavigationCommitType)
5235 {
5236 registerMockedHttpURLLoad("push_state.html");
5237 TestDidNavigateCommitTypeWebFrameClient client;
5238 FrameTestHelpers::WebViewHelper webViewHelper;
5239 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "push_state.html", true, &client);
5240 RefPtr<WebCore::HistoryItem> item = toLocalFrame(webViewImpl->page()->mainFrame())->loader().currentItem();
5241 runPendingTasks();
5242
5243 toLocalFrame(webViewImpl->page()->mainFrame())->loader().loadHistoryItem(item.get(), WebCore::HistorySameDocumentLoad);
5244 EXPECT_EQ(WebBackForwardCommit, client.lastCommitType());
5245 }
5246
5247 class TestHistoryWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5248 public:
TestHistoryWebFrameClient()5249 TestHistoryWebFrameClient()
5250 {
5251 m_replacesCurrentHistoryItem = false;
5252 m_frame = 0;
5253 }
didStartProvisionalLoad(WebLocalFrame * frame)5254 void didStartProvisionalLoad(WebLocalFrame* frame)
5255 {
5256 WebDataSource* ds = frame->provisionalDataSource();
5257 m_replacesCurrentHistoryItem = ds->replacesCurrentHistoryItem();
5258 m_frame = frame;
5259 }
5260
replacesCurrentHistoryItem()5261 bool replacesCurrentHistoryItem() { return m_replacesCurrentHistoryItem; }
frame()5262 WebFrame* frame() { return m_frame; }
5263
5264 private:
5265 bool m_replacesCurrentHistoryItem;
5266 WebFrame* m_frame;
5267 };
5268
5269 // Test which ensures that the first navigation in a subframe will always
5270 // result in history entry being replaced and not a new one added.
TEST_F(WebFrameTest,DISABLED_FirstFrameNavigationReplacesHistory)5271 TEST_F(WebFrameTest, DISABLED_FirstFrameNavigationReplacesHistory)
5272 {
5273 registerMockedHttpURLLoad("history.html");
5274 registerMockedHttpURLLoad("find.html");
5275
5276 FrameTestHelpers::WebViewHelper webViewHelper;
5277 TestHistoryWebFrameClient client;
5278 webViewHelper.initializeAndLoad("about:blank", true, &client);
5279 EXPECT_TRUE(client.replacesCurrentHistoryItem());
5280
5281 WebFrame* frame = webViewHelper.webView()->mainFrame();
5282
5283 FrameTestHelpers::loadFrame(frame,
5284 "javascript:document.body.appendChild(document.createElement('iframe'))");
5285 WebFrame* iframe = frame->firstChild();
5286 EXPECT_EQ(client.frame(), iframe);
5287 EXPECT_TRUE(client.replacesCurrentHistoryItem());
5288
5289 FrameTestHelpers::loadFrame(frame,
5290 "javascript:window.frames[0].location.assign('" + m_baseURL + "history.html')");
5291 EXPECT_EQ(client.frame(), iframe);
5292 EXPECT_TRUE(client.replacesCurrentHistoryItem());
5293
5294 FrameTestHelpers::loadFrame(frame,
5295 "javascript:window.frames[0].location.assign('" + m_baseURL + "find.html')");
5296 EXPECT_EQ(client.frame(), iframe);
5297 EXPECT_FALSE(client.replacesCurrentHistoryItem());
5298
5299 // Repeat the test, but start out the iframe with initial URL, which is not
5300 // "about:blank".
5301 FrameTestHelpers::loadFrame(frame,
5302 "javascript:var f = document.createElement('iframe'); "
5303 "f.src = '" + m_baseURL + "history.html';"
5304 "document.body.appendChild(f)");
5305
5306 iframe = frame->firstChild()->nextSibling();
5307 EXPECT_EQ(client.frame(), iframe);
5308 EXPECT_TRUE(client.replacesCurrentHistoryItem());
5309
5310 FrameTestHelpers::loadFrame(frame,
5311 "javascript:window.frames[1].location.assign('" + m_baseURL + "find.html')");
5312 EXPECT_EQ(client.frame(), iframe);
5313 EXPECT_FALSE(client.replacesCurrentHistoryItem());
5314 }
5315
5316 // Test verifies that layout will change a layer's scrollable attibutes
TEST_F(WebFrameTest,overflowHiddenRewrite)5317 TEST_F(WebFrameTest, overflowHiddenRewrite)
5318 {
5319 registerMockedHttpURLLoad("non-scrollable.html");
5320 TestMainFrameUserOrProgrammaticScrollFrameClient client;
5321 OwnPtr<FakeCompositingWebViewClient> fakeCompositingWebViewClient = adoptPtr(new FakeCompositingWebViewClient());
5322 FrameTestHelpers::WebViewHelper webViewHelper;
5323 webViewHelper.initialize(true, 0, fakeCompositingWebViewClient.get(), &configueCompositingWebView);
5324
5325 webViewHelper.webView()->resize(WebSize(100, 100));
5326 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "non-scrollable.html");
5327
5328 WebCore::RenderLayerCompositor* compositor = webViewHelper.webViewImpl()->compositor();
5329 ASSERT_TRUE(compositor->scrollLayer());
5330
5331 // Verify that the WebLayer is not scrollable initially.
5332 WebCore::GraphicsLayer* scrollLayer = compositor->scrollLayer();
5333 WebLayer* webScrollLayer = scrollLayer->platformLayer();
5334 ASSERT_FALSE(webScrollLayer->userScrollableHorizontal());
5335 ASSERT_FALSE(webScrollLayer->userScrollableVertical());
5336
5337 // Call javascript to make the layer scrollable, and verify it.
5338 WebLocalFrameImpl* frame = (WebLocalFrameImpl*)webViewHelper.webView()->mainFrame();
5339 frame->executeScript(WebScriptSource("allowScroll();"));
5340 webViewHelper.webView()->layout();
5341 ASSERT_TRUE(webScrollLayer->userScrollableHorizontal());
5342 ASSERT_TRUE(webScrollLayer->userScrollableVertical());
5343 }
5344
5345 // Test that currentHistoryItem reflects the current page, not the provisional load.
TEST_F(WebFrameTest,CurrentHistoryItem)5346 TEST_F(WebFrameTest, CurrentHistoryItem)
5347 {
5348 registerMockedHttpURLLoad("fixed_layout.html");
5349 std::string url = m_baseURL + "fixed_layout.html";
5350
5351 FrameTestHelpers::WebViewHelper webViewHelper;
5352 webViewHelper.initialize();
5353 WebFrame* frame = webViewHelper.webView()->mainFrame();
5354 const WebCore::FrameLoader& mainFrameLoader = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->loader();
5355 WebURLRequest request;
5356 request.initialize();
5357 request.setURL(toKURL(url));
5358 frame->loadRequest(request);
5359
5360 // Before commit, there is no history item.
5361 EXPECT_FALSE(mainFrameLoader.currentItem());
5362
5363 FrameTestHelpers::pumpPendingRequestsDoNotUse(frame);
5364
5365 // After commit, there is.
5366 WebCore::HistoryItem* item = mainFrameLoader.currentItem();
5367 ASSERT_TRUE(item);
5368 EXPECT_EQ(WTF::String(url.data()), item->urlString());
5369 }
5370
5371 class FailCreateChildFrame : public FrameTestHelpers::TestWebFrameClient {
5372 public:
FailCreateChildFrame()5373 FailCreateChildFrame() : m_callCount(0) { }
5374
createChildFrame(WebLocalFrame * parent,const WebString & frameName)5375 virtual WebFrame* createChildFrame(WebLocalFrame* parent, const WebString& frameName) OVERRIDE
5376 {
5377 ++m_callCount;
5378 return 0;
5379 }
5380
callCount() const5381 int callCount() const { return m_callCount; }
5382
5383 private:
5384 int m_callCount;
5385 };
5386
5387 // Test that we don't crash if WebFrameClient::createChildFrame() fails.
TEST_F(WebFrameTest,CreateChildFrameFailure)5388 TEST_F(WebFrameTest, CreateChildFrameFailure)
5389 {
5390 registerMockedHttpURLLoad("create_child_frame_fail.html");
5391 FailCreateChildFrame client;
5392 FrameTestHelpers::WebViewHelper webViewHelper;
5393 webViewHelper.initializeAndLoad(m_baseURL + "create_child_frame_fail.html", true, &client);
5394
5395 EXPECT_EQ(1, client.callCount());
5396 }
5397
TEST_F(WebFrameTest,fixedPositionInFixedViewport)5398 TEST_F(WebFrameTest, fixedPositionInFixedViewport)
5399 {
5400 UseMockScrollbarSettings mockScrollbarSettings;
5401 registerMockedHttpURLLoad("fixed-position-in-fixed-viewport.html");
5402 FrameTestHelpers::WebViewHelper webViewHelper;
5403 webViewHelper.initializeAndLoad(m_baseURL + "fixed-position-in-fixed-viewport.html", true, 0, 0, enableViewportSettings);
5404
5405 WebView* webView = webViewHelper.webView();
5406 webView->resize(WebSize(100, 100));
5407 webView->layout();
5408
5409 Document* document = toWebLocalFrameImpl(webView->mainFrame())->frame()->document();
5410 Element* bottomFixed = document->getElementById("bottom-fixed");
5411 Element* topBottomFixed = document->getElementById("top-bottom-fixed");
5412 Element* rightFixed = document->getElementById("right-fixed");
5413 Element* leftRightFixed = document->getElementById("left-right-fixed");
5414
5415 webView->resize(WebSize(100, 200));
5416 webView->layout();
5417 EXPECT_EQ(200, bottomFixed->offsetTop() + bottomFixed->offsetHeight());
5418 EXPECT_EQ(200, topBottomFixed->offsetHeight());
5419
5420 webView->settings()->setMainFrameResizesAreOrientationChanges(false);
5421 webView->resize(WebSize(200, 200));
5422 webView->layout();
5423 EXPECT_EQ(200, rightFixed->offsetLeft() + rightFixed->offsetWidth());
5424 EXPECT_EQ(200, leftRightFixed->offsetWidth());
5425
5426 webView->settings()->setMainFrameResizesAreOrientationChanges(true);
5427 // Will scale the page by 1.5.
5428 webView->resize(WebSize(300, 330));
5429 webView->layout();
5430 EXPECT_EQ(220, bottomFixed->offsetTop() + bottomFixed->offsetHeight());
5431 EXPECT_EQ(220, topBottomFixed->offsetHeight());
5432 EXPECT_EQ(200, rightFixed->offsetLeft() + rightFixed->offsetWidth());
5433 EXPECT_EQ(200, leftRightFixed->offsetWidth());
5434 }
5435
TEST_F(WebFrameTest,FrameViewSetFrameRect)5436 TEST_F(WebFrameTest, FrameViewSetFrameRect)
5437 {
5438 FrameTestHelpers::WebViewHelper webViewHelper;
5439 webViewHelper.initializeAndLoad("about:blank");
5440
5441 WebCore::FrameView* frameView = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
5442 frameView->setFrameRect(WebCore::IntRect(0, 0, 200, 200));
5443 EXPECT_EQ_RECT(WebCore::IntRect(0, 0, 200, 200), frameView->frameRect());
5444 frameView->setFrameRect(WebCore::IntRect(100, 100, 200, 200));
5445 EXPECT_EQ_RECT(WebCore::IntRect(100, 100, 200, 200), frameView->frameRect());
5446 }
5447
TEST_F(WebFrameTest,FullscreenLayerNonScrollable)5448 TEST_F(WebFrameTest, FullscreenLayerNonScrollable)
5449 {
5450 FakeCompositingWebViewClient client;
5451 registerMockedHttpURLLoad("fullscreen_div.html");
5452 FrameTestHelpers::WebViewHelper webViewHelper;
5453 int viewportWidth = 640;
5454 int viewportHeight = 480;
5455 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "fullscreen_div.html", true, 0, &client, &configueCompositingWebView);
5456 webViewImpl->resize(WebSize(viewportWidth, viewportHeight));
5457 webViewImpl->layout();
5458
5459 Document* document = toWebLocalFrameImpl(webViewImpl->mainFrame())->frame()->document();
5460 WebCore::UserGestureIndicator gesture(WebCore::DefinitelyProcessingUserGesture);
5461 Element* divFullscreen = document->getElementById("div1");
5462 divFullscreen->webkitRequestFullscreen();
5463 webViewImpl->willEnterFullScreen();
5464 webViewImpl->didEnterFullScreen();
5465 webViewImpl->layout();
5466
5467 // Verify that the main frame is not scrollable.
5468 ASSERT_TRUE(WebCore::FullscreenElementStack::isFullScreen(*document));
5469 WebLayer* webScrollLayer = webViewImpl->compositor()->scrollLayer()->platformLayer();
5470 ASSERT_FALSE(webScrollLayer->scrollable());
5471
5472 // Verify that the main frame is scrollable upon exiting fullscreen.
5473 webViewImpl->willExitFullScreen();
5474 webViewImpl->didExitFullScreen();
5475 webViewImpl->layout();
5476 ASSERT_FALSE(WebCore::FullscreenElementStack::isFullScreen(*document));
5477 webScrollLayer = webViewImpl->compositor()->scrollLayer()->platformLayer();
5478 ASSERT_TRUE(webScrollLayer->scrollable());
5479 }
5480
TEST_F(WebFrameTest,FullscreenMainFrameScrollable)5481 TEST_F(WebFrameTest, FullscreenMainFrameScrollable)
5482 {
5483 FakeCompositingWebViewClient client;
5484 registerMockedHttpURLLoad("fullscreen_div.html");
5485 FrameTestHelpers::WebViewHelper webViewHelper;
5486 int viewportWidth = 640;
5487 int viewportHeight = 480;
5488 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "fullscreen_div.html", true, 0, &client, &configueCompositingWebView);
5489 webViewImpl->resize(WebSize(viewportWidth, viewportHeight));
5490 webViewImpl->layout();
5491
5492 Document* document = toWebLocalFrameImpl(webViewImpl->mainFrame())->frame()->document();
5493 WebCore::UserGestureIndicator gesture(WebCore::DefinitelyProcessingUserGesture);
5494 document->documentElement()->webkitRequestFullscreen();
5495 webViewImpl->willEnterFullScreen();
5496 webViewImpl->didEnterFullScreen();
5497 webViewImpl->layout();
5498
5499 // Verify that the main frame is still scrollable.
5500 ASSERT_TRUE(WebCore::FullscreenElementStack::isFullScreen(*document));
5501 WebLayer* webScrollLayer = webViewImpl->compositor()->scrollLayer()->platformLayer();
5502 ASSERT_TRUE(webScrollLayer->scrollable());
5503 }
5504
TEST_F(WebFrameTest,RenderBlockPercentHeightDescendants)5505 TEST_F(WebFrameTest, RenderBlockPercentHeightDescendants)
5506 {
5507 registerMockedHttpURLLoad("percent-height-descendants.html");
5508 FrameTestHelpers::WebViewHelper webViewHelper;
5509 webViewHelper.initializeAndLoad(m_baseURL + "percent-height-descendants.html");
5510
5511 WebView* webView = webViewHelper.webView();
5512 webView->resize(WebSize(800, 800));
5513 webView->layout();
5514
5515 Document* document = toWebLocalFrameImpl(webView->mainFrame())->frame()->document();
5516 WebCore::RenderBlock* container = WebCore::toRenderBlock(document->getElementById("container")->renderer());
5517 WebCore::RenderBox* percentHeightInAnonymous = WebCore::toRenderBox(document->getElementById("percent-height-in-anonymous")->renderer());
5518 WebCore::RenderBox* percentHeightDirectChild = WebCore::toRenderBox(document->getElementById("percent-height-direct-child")->renderer());
5519
5520 EXPECT_TRUE(WebCore::RenderBlock::hasPercentHeightDescendant(percentHeightInAnonymous));
5521 EXPECT_TRUE(WebCore::RenderBlock::hasPercentHeightDescendant(percentHeightDirectChild));
5522
5523 ASSERT_TRUE(container->percentHeightDescendants());
5524 ASSERT_TRUE(container->hasPercentHeightDescendants());
5525 EXPECT_EQ(2U, container->percentHeightDescendants()->size());
5526 EXPECT_TRUE(container->percentHeightDescendants()->contains(percentHeightInAnonymous));
5527 EXPECT_TRUE(container->percentHeightDescendants()->contains(percentHeightDirectChild));
5528
5529 WebCore::RenderBlock* anonymousBlock = percentHeightInAnonymous->containingBlock();
5530 EXPECT_TRUE(anonymousBlock->isAnonymous());
5531 EXPECT_FALSE(anonymousBlock->hasPercentHeightDescendants());
5532 }
5533
TEST_F(WebFrameTest,HasVisibleContentOnVisibleFrames)5534 TEST_F(WebFrameTest, HasVisibleContentOnVisibleFrames)
5535 {
5536 registerMockedHttpURLLoad("visible_frames.html");
5537 FrameTestHelpers::WebViewHelper webViewHelper;
5538 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "visible_frames.html");
5539 for (WebFrame* frame = webViewImpl->mainFrameImpl()->traverseNext(false); frame; frame = frame->traverseNext(false)) {
5540 EXPECT_TRUE(frame->hasVisibleContent());
5541 }
5542 }
5543
TEST_F(WebFrameTest,HasVisibleContentOnHiddenFrames)5544 TEST_F(WebFrameTest, HasVisibleContentOnHiddenFrames)
5545 {
5546 registerMockedHttpURLLoad("hidden_frames.html");
5547 FrameTestHelpers::WebViewHelper webViewHelper;
5548 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "hidden_frames.html");
5549 for (WebFrame* frame = webViewImpl->mainFrameImpl()->traverseNext(false); frame; frame = frame->traverseNext(false)) {
5550 EXPECT_FALSE(frame->hasVisibleContent());
5551 }
5552 }
5553
5554 class ManifestChangeWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5555 public:
ManifestChangeWebFrameClient()5556 ManifestChangeWebFrameClient() : m_manifestChangeCount(0) { }
didChangeManifest(WebLocalFrame *)5557 virtual void didChangeManifest(WebLocalFrame*) OVERRIDE
5558 {
5559 ++m_manifestChangeCount;
5560 }
5561
manifestChangeCount()5562 int manifestChangeCount() { return m_manifestChangeCount; }
5563
5564 private:
5565 int m_manifestChangeCount;
5566 };
5567
TEST_F(WebFrameTest,NotifyManifestChange)5568 TEST_F(WebFrameTest, NotifyManifestChange)
5569 {
5570 registerMockedHttpURLLoad("link-manifest-change.html");
5571
5572 ManifestChangeWebFrameClient webFrameClient;
5573 FrameTestHelpers::WebViewHelper webViewHelper;
5574 webViewHelper.initializeAndLoad(m_baseURL + "link-manifest-change.html", true, &webFrameClient);
5575
5576 EXPECT_EQ(14, webFrameClient.manifestChangeCount());
5577 }
5578
TEST_F(WebFrameTest,ReloadBypassingCache)5579 TEST_F(WebFrameTest, ReloadBypassingCache)
5580 {
5581 // Check that a reload ignoring cache on a frame will result in the cache
5582 // policy of the request being set to ReloadBypassingCache.
5583 registerMockedHttpURLLoad("foo.html");
5584 FrameTestHelpers::WebViewHelper webViewHelper;
5585 webViewHelper.initializeAndLoad(m_baseURL + "foo.html", true);
5586 WebFrame* frame = webViewHelper.webView()->mainFrame();
5587 FrameTestHelpers::reloadFrameIgnoringCache(frame);
5588 EXPECT_EQ(WebURLRequest::ReloadBypassingCache, frame->dataSource()->request().cachePolicy());
5589 }
5590
nodeImageTestValidation(const WebCore::IntSize & referenceBitmapSize,WebCore::DragImage * dragImage)5591 static void nodeImageTestValidation(const WebCore::IntSize& referenceBitmapSize, WebCore::DragImage* dragImage)
5592 {
5593 // Prepare the reference bitmap.
5594 SkBitmap bitmap;
5595 ASSERT_TRUE(bitmap.allocN32Pixels(referenceBitmapSize.width(), referenceBitmapSize.height()));
5596 SkCanvas canvas(bitmap);
5597 canvas.drawColor(SK_ColorGREEN);
5598
5599 EXPECT_EQ(referenceBitmapSize.width(), dragImage->size().width());
5600 EXPECT_EQ(referenceBitmapSize.height(), dragImage->size().height());
5601 const SkBitmap& dragBitmap = dragImage->bitmap();
5602 SkAutoLockPixels lockPixel(dragBitmap);
5603 EXPECT_EQ(0, memcmp(bitmap.getPixels(), dragBitmap.getPixels(), bitmap.getSize()));
5604 }
5605
TEST_F(WebFrameTest,NodeImageTestCSSTransform)5606 TEST_F(WebFrameTest, NodeImageTestCSSTransform)
5607 {
5608 FrameTestHelpers::WebViewHelper webViewHelper;
5609 OwnPtr<WebCore::DragImage> dragImage = nodeImageTestSetup(&webViewHelper, std::string("case-css-transform"));
5610 EXPECT_TRUE(dragImage);
5611
5612 nodeImageTestValidation(WebCore::IntSize(40, 40), dragImage.get());
5613 }
5614
TEST_F(WebFrameTest,NodeImageTestCSS3DTransform)5615 TEST_F(WebFrameTest, NodeImageTestCSS3DTransform)
5616 {
5617 FrameTestHelpers::WebViewHelper webViewHelper;
5618 OwnPtr<WebCore::DragImage> dragImage = nodeImageTestSetup(&webViewHelper, std::string("case-css-3dtransform"));
5619 EXPECT_TRUE(dragImage);
5620
5621 nodeImageTestValidation(WebCore::IntSize(20, 40), dragImage.get());
5622 }
5623
TEST_F(WebFrameTest,NodeImageTestInlineBlock)5624 TEST_F(WebFrameTest, NodeImageTestInlineBlock)
5625 {
5626 FrameTestHelpers::WebViewHelper webViewHelper;
5627 OwnPtr<WebCore::DragImage> dragImage = nodeImageTestSetup(&webViewHelper, std::string("case-inlineblock"));
5628 EXPECT_TRUE(dragImage);
5629
5630 nodeImageTestValidation(WebCore::IntSize(40, 40), dragImage.get());
5631 }
5632
TEST_F(WebFrameTest,NodeImageTestFloatLeft)5633 TEST_F(WebFrameTest, NodeImageTestFloatLeft)
5634 {
5635 FrameTestHelpers::WebViewHelper webViewHelper;
5636 OwnPtr<WebCore::DragImage> dragImage = nodeImageTestSetup(&webViewHelper, std::string("case-float-left-overflow-hidden"));
5637 EXPECT_TRUE(dragImage);
5638
5639 nodeImageTestValidation(WebCore::IntSize(40, 40), dragImage.get());
5640 }
5641
5642 class ThemeColorTestWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5643 public:
ThemeColorTestWebFrameClient()5644 ThemeColorTestWebFrameClient()
5645 : m_didNotify(false)
5646 {
5647 }
5648
reset()5649 void reset()
5650 {
5651 m_didNotify = false;
5652 }
5653
didNotify() const5654 bool didNotify() const
5655 {
5656 return m_didNotify;
5657 }
5658
5659 private:
didChangeThemeColor()5660 virtual void didChangeThemeColor()
5661 {
5662 m_didNotify = true;
5663 }
5664
5665 bool m_didNotify;
5666 };
5667
TEST_F(WebFrameTest,ThemeColor)5668 TEST_F(WebFrameTest, ThemeColor)
5669 {
5670 registerMockedHttpURLLoad("theme_color_test.html");
5671 FrameTestHelpers::WebViewHelper webViewHelper;
5672 ThemeColorTestWebFrameClient client;
5673 webViewHelper.initializeAndLoad(m_baseURL + "theme_color_test.html", true, &client);
5674 EXPECT_TRUE(client.didNotify());
5675 WebLocalFrameImpl* frame = webViewHelper.webViewImpl()->mainFrameImpl();
5676 EXPECT_EQ(0xff0000ff, frame->document().themeColor());
5677 // Change color by rgb.
5678 client.reset();
5679 frame->executeScript(WebScriptSource("document.getElementById('tc1').setAttribute('content', 'rgb(0, 0, 0)');"));
5680 EXPECT_TRUE(client.didNotify());
5681 EXPECT_EQ(0xff000000, frame->document().themeColor());
5682 // Change color by hsl.
5683 client.reset();
5684 frame->executeScript(WebScriptSource("document.getElementById('tc1').setAttribute('content', 'hsl(240,100%, 50%)');"));
5685 EXPECT_TRUE(client.didNotify());
5686 EXPECT_EQ(0xff0000ff, frame->document().themeColor());
5687 // Change of second theme-color meta tag will not change frame's theme
5688 // color.
5689 client.reset();
5690 frame->executeScript(WebScriptSource("document.getElementById('tc2').setAttribute('content', '#00FF00');"));
5691 EXPECT_TRUE(client.didNotify());
5692 EXPECT_EQ(0xff0000ff, frame->document().themeColor());
5693 }
5694
5695 } // namespace
5696