2 * Copyright (C) 2010 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include "public/web/WebFrame.h"
35 #include "RuntimeEnabledFeatures.h"
38 #include "UserAgentStyleSheets.h"
39 #include "core/clipboard/Clipboard.h"
40 #include "core/css/StyleSheetContents.h"
41 #include "core/css/resolver/ViewportStyleResolver.h"
42 #include "core/dom/DocumentMarkerController.h"
43 #include "core/dom/FullscreenElementStack.h"
44 #include "core/dom/Range.h"
45 #include "core/editing/Editor.h"
46 #include "core/editing/FrameSelection.h"
47 #include "core/editing/SpellChecker.h"
48 #include "core/editing/VisiblePosition.h"
49 #include "core/events/MouseEvent.h"
50 #include "core/frame/FrameView.h"
51 #include "core/frame/LocalFrame.h"
52 #include "core/frame/Settings.h"
53 #include "core/html/HTMLFormElement.h"
54 #include "core/loader/FrameLoadRequest.h"
55 #include "core/page/EventHandler.h"
56 #include "core/rendering/HitTestResult.h"
57 #include "core/rendering/RenderView.h"
58 #include "core/rendering/TextAutosizer.h"
59 #include "core/rendering/compositing/RenderLayerCompositor.h"
60 #include "platform/UserGestureIndicator.h"
61 #include "platform/geometry/FloatRect.h"
62 #include "platform/network/ResourceError.h"
63 #include "platform/scroll/ScrollbarTheme.h"
64 #include "public/platform/Platform.h"
65 #include "public/platform/WebFloatRect.h"
66 #include "public/platform/WebThread.h"
67 #include "public/platform/WebURL.h"
68 #include "public/platform/WebURLResponse.h"
69 #include "public/platform/WebUnitTestSupport.h"
70 #include "public/web/WebDataSource.h"
71 #include "public/web/WebDocument.h"
72 #include "public/web/WebFindOptions.h"
73 #include "public/web/WebFormElement.h"
74 #include "public/web/WebFrameClient.h"
75 #include "public/web/WebHistoryItem.h"
76 #include "public/web/WebRange.h"
77 #include "public/web/WebScriptSource.h"
78 #include "public/web/WebSearchableFormData.h"
79 #include "public/web/WebSecurityOrigin.h"
80 #include "public/web/WebSecurityPolicy.h"
81 #include "public/web/WebSettings.h"
82 #include "public/web/WebSpellCheckClient.h"
83 #include "public/web/WebTextCheckingCompletion.h"
84 #include "public/web/WebTextCheckingResult.h"
85 #include "public/web/WebViewClient.h"
86 #include "web/WebLocalFrameImpl.h"
87 #include "web/WebViewImpl.h"
88 #include "web/tests/FrameTestHelpers.h"
89 #include "web/tests/URLTestHelpers.h"
90 #include "wtf/Forward.h"
91 #include "wtf/dtoa/utils.h"
92 #include <gmock/gmock.h>
93 #include <gtest/gtest.h>
97 using namespace blink;
98 using WebCore::Document;
99 using WebCore::DocumentMarker;
100 using WebCore::Element;
101 using WebCore::FloatRect;
102 using WebCore::HitTestRequest;
103 using WebCore::Range;
104 using blink::URLTestHelpers::toKURL;
105 using blink::FrameTestHelpers::runPendingTasks;
109 const int touchPointPadding = 32;
111 #define EXPECT_EQ_RECT(a, b) \
112 EXPECT_EQ(a.x(), b.x()); \
113 EXPECT_EQ(a.y(), b.y()); \
114 EXPECT_EQ(a.width(), b.width()); \
115 EXPECT_EQ(a.height(), b.height());
117 class FakeCompositingWebViewClient : public FrameTestHelpers::TestWebViewClient {
119 virtual bool enterFullScreen() OVERRIDE { return true; }
122 class WebFrameTest : public testing::Test {
125 : m_baseURL("http://www.test.com/")
126 , m_chromeURL("chrome://")
130 virtual ~WebFrameTest()
132 Platform::current()->unitTestSupport()->unregisterAllMockedURLs();
135 void registerMockedHttpURLLoad(const std::string& fileName)
137 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8(fileName.c_str()));
140 void registerMockedChromeURLLoad(const std::string& fileName)
142 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_chromeURL.c_str()), WebString::fromUTF8(fileName.c_str()));
145 void applyViewportStyleOverride(FrameTestHelpers::WebViewHelper* webViewHelper)
147 RefPtrWillBeRawPtr<WebCore::StyleSheetContents> styleSheet = WebCore::StyleSheetContents::create(WebCore::CSSParserContext(WebCore::UASheetMode, 0));
148 styleSheet->parseString(String(WebCore::viewportAndroidUserAgentStyleSheet, sizeof(WebCore::viewportAndroidUserAgentStyleSheet)));
149 OwnPtrWillBeRawPtr<WebCore::RuleSet> ruleSet = WebCore::RuleSet::create();
150 ruleSet->addRulesFromSheet(styleSheet.get(), WebCore::MediaQueryEvaluator("screen"));
152 Document* document = webViewHelper->webViewImpl()->page()->mainFrame()->document();
153 document->ensureStyleResolver().viewportStyleResolver()->collectViewportRules(ruleSet.get(), WebCore::ViewportStyleResolver::UserAgentOrigin);
154 document->ensureStyleResolver().viewportStyleResolver()->resolve();
157 static void configueCompositingWebView(WebSettings* settings)
159 settings->setForceCompositingMode(true);
160 settings->setAcceleratedCompositingEnabled(true);
161 settings->setAcceleratedCompositingForFixedPositionEnabled(true);
162 settings->setAcceleratedCompositingForOverflowScrollEnabled(true);
163 settings->setCompositedScrollingForFramesEnabled(true);
166 void initializeTextSelectionWebView(const std::string& url, FrameTestHelpers::WebViewHelper* webViewHelper)
168 webViewHelper->initializeAndLoad(url, true);
169 webViewHelper->webView()->settings()->setDefaultFontSize(12);
170 webViewHelper->webView()->resize(WebSize(640, 480));
173 std::string m_baseURL;
174 std::string m_chromeURL;
177 class UseMockScrollbarSettings {
179 UseMockScrollbarSettings()
181 WebCore::Settings::setMockScrollbarsEnabled(true);
182 WebCore::RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(true);
183 EXPECT_TRUE(WebCore::ScrollbarTheme::theme()->usesOverlayScrollbars());
186 ~UseMockScrollbarSettings()
188 WebCore::Settings::setMockScrollbarsEnabled(false);
189 WebCore::RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(false);
193 TEST_F(WebFrameTest, ContentText)
195 registerMockedHttpURLLoad("iframes_test.html");
196 registerMockedHttpURLLoad("visible_iframe.html");
197 registerMockedHttpURLLoad("invisible_iframe.html");
198 registerMockedHttpURLLoad("zero_sized_iframe.html");
200 FrameTestHelpers::WebViewHelper webViewHelper;
201 webViewHelper.initializeAndLoad(m_baseURL + "iframes_test.html");
203 // Now retrieve the frames text and test it only includes visible elements.
204 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
205 EXPECT_NE(std::string::npos, content.find(" visible paragraph"));
206 EXPECT_NE(std::string::npos, content.find(" visible iframe"));
207 EXPECT_EQ(std::string::npos, content.find(" invisible pararaph"));
208 EXPECT_EQ(std::string::npos, content.find(" invisible iframe"));
209 EXPECT_EQ(std::string::npos, content.find("iframe with zero size"));
212 TEST_F(WebFrameTest, FrameForEnteredContext)
214 registerMockedHttpURLLoad("iframes_test.html");
215 registerMockedHttpURLLoad("visible_iframe.html");
216 registerMockedHttpURLLoad("invisible_iframe.html");
217 registerMockedHttpURLLoad("zero_sized_iframe.html");
219 FrameTestHelpers::WebViewHelper webViewHelper;
220 webViewHelper.initializeAndLoad(m_baseURL + "iframes_test.html", true);
222 v8::HandleScope scope(v8::Isolate::GetCurrent());
223 EXPECT_EQ(webViewHelper.webView()->mainFrame(), WebLocalFrame::frameForContext(webViewHelper.webView()->mainFrame()->mainWorldScriptContext()));
224 EXPECT_EQ(webViewHelper.webView()->mainFrame()->firstChild(), WebLocalFrame::frameForContext(webViewHelper.webView()->mainFrame()->firstChild()->mainWorldScriptContext()));
227 TEST_F(WebFrameTest, FormWithNullFrame)
229 registerMockedHttpURLLoad("form.html");
231 FrameTestHelpers::WebViewHelper webViewHelper;
232 webViewHelper.initializeAndLoad(m_baseURL + "form.html");
234 WebVector<WebFormElement> forms;
235 webViewHelper.webView()->mainFrame()->document().forms(forms);
236 webViewHelper.reset();
238 EXPECT_EQ(forms.size(), 1U);
240 // This test passes if this doesn't crash.
241 WebSearchableFormData searchableDataForm(forms[0]);
244 TEST_F(WebFrameTest, ChromePageJavascript)
246 registerMockedChromeURLLoad("history.html");
248 // Pass true to enable JavaScript.
249 FrameTestHelpers::WebViewHelper webViewHelper;
250 webViewHelper.initializeAndLoad(m_chromeURL + "history.html", true);
252 // Try to run JS against the chrome-style URL.
253 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.appendChild(document.createTextNode('Clobbered'))");
255 // Required to see any updates in contentAsText.
256 webViewHelper.webView()->layout();
258 // Now retrieve the frame's text and ensure it was modified by running javascript.
259 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
260 EXPECT_NE(std::string::npos, content.find("Clobbered"));
263 TEST_F(WebFrameTest, ChromePageNoJavascript)
265 registerMockedChromeURLLoad("history.html");
267 /// Pass true to enable JavaScript.
268 FrameTestHelpers::WebViewHelper webViewHelper;
269 webViewHelper.initializeAndLoad(m_chromeURL + "history.html", true);
271 // Try to run JS against the chrome-style URL after prohibiting it.
272 WebSecurityPolicy::registerURLSchemeAsNotAllowingJavascriptURLs("chrome");
273 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.appendChild(document.createTextNode('Clobbered'))");
275 // Required to see any updates in contentAsText.
276 webViewHelper.webView()->layout();
278 // Now retrieve the frame's text and ensure it wasn't modified by running javascript.
279 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
280 EXPECT_EQ(std::string::npos, content.find("Clobbered"));
283 TEST_F(WebFrameTest, LocationSetHostWithMissingPort)
285 std::string fileName = "print-location-href.html";
286 registerMockedHttpURLLoad(fileName);
287 URLTestHelpers::registerMockedURLLoad(toKURL("http://www.test.com:0/" + fileName), WebString::fromUTF8(fileName));
289 FrameTestHelpers::WebViewHelper webViewHelper;
291 /// Pass true to enable JavaScript.
292 webViewHelper.initializeAndLoad(m_baseURL + fileName, true);
294 // Setting host to "hostname:" should be treated as "hostname:0".
295 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:location.host = 'www.test.com:'; void 0;");
298 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
300 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.textContent = location.href; void 0;");
301 // Required to see any updates in contentAsText.
303 webViewHelper.webView()->layout();
305 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
306 EXPECT_EQ("http://www.test.com:0/" + fileName, content);
309 TEST_F(WebFrameTest, LocationSetEmptyPort)
311 std::string fileName = "print-location-href.html";
312 registerMockedHttpURLLoad(fileName);
313 URLTestHelpers::registerMockedURLLoad(toKURL("http://www.test.com:0/" + fileName), WebString::fromUTF8(fileName));
315 FrameTestHelpers::WebViewHelper webViewHelper;
317 /// Pass true to enable JavaScript.
318 webViewHelper.initializeAndLoad(m_baseURL + fileName, true);
320 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:location.port = ''; void 0;");
323 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
325 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.textContent = location.href; void 0;");
326 // Required to see any updates in contentAsText.
328 webViewHelper.webView()->layout();
330 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
331 EXPECT_EQ("http://www.test.com:0/" + fileName, content);
334 class CSSCallbackWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
336 CSSCallbackWebFrameClient() : m_updateCount(0) { }
337 virtual void didMatchCSS(WebLocalFrame*, const WebVector<WebString>& newlyMatchingSelectors, const WebVector<WebString>& stoppedMatchingSelectors) OVERRIDE;
339 std::map<WebLocalFrame*, std::set<std::string> > m_matchedSelectors;
343 void CSSCallbackWebFrameClient::didMatchCSS(WebLocalFrame* frame, const WebVector<WebString>& newlyMatchingSelectors, const WebVector<WebString>& stoppedMatchingSelectors)
346 std::set<std::string>& frameSelectors = m_matchedSelectors[frame];
347 for (size_t i = 0; i < newlyMatchingSelectors.size(); ++i) {
348 std::string selector = newlyMatchingSelectors[i].utf8();
349 EXPECT_EQ(0U, frameSelectors.count(selector)) << selector;
350 frameSelectors.insert(selector);
352 for (size_t i = 0; i < stoppedMatchingSelectors.size(); ++i) {
353 std::string selector = stoppedMatchingSelectors[i].utf8();
354 EXPECT_EQ(1U, frameSelectors.count(selector)) << selector;
355 frameSelectors.erase(selector);
359 class WebFrameCSSCallbackTest : public testing::Test {
361 WebFrameCSSCallbackTest()
364 m_frame = m_helper.initializeAndLoad("about:blank", true, &m_client)->mainFrame()->toWebLocalFrame();
367 ~WebFrameCSSCallbackTest()
369 EXPECT_EQ(1U, m_client.m_matchedSelectors.size());
372 WebDocument doc() const
374 return m_frame->document();
377 int updateCount() const
379 return m_client.m_updateCount;
382 const std::set<std::string>& matchedSelectors()
384 return m_client.m_matchedSelectors[m_frame];
387 void loadHTML(const WebData& html)
389 m_frame->loadHTMLString(html, toKURL("about:blank"));
393 void executeScript(const WebString& code)
395 m_frame->executeScript(WebScriptSource(code));
396 m_frame->view()->layout();
400 CSSCallbackWebFrameClient m_client;
401 FrameTestHelpers::WebViewHelper m_helper;
402 WebLocalFrame* m_frame;
405 TEST_F(WebFrameCSSCallbackTest, AuthorStyleSheet)
409 // This stylesheet checks that the internal property and value can't be
410 // set by a stylesheet, only WebDocument::watchCSSSelectors().
411 "div.initial_on { -internal-callback: none; }"
412 "div.initial_off { -internal-callback: -internal-presence; }"
414 "<div class=\"initial_on\"></div>"
415 "<div class=\"initial_off\"></div>");
417 std::vector<WebString> selectors;
418 selectors.push_back(WebString::fromUTF8("div.initial_on"));
419 m_frame->document().watchCSSSelectors(WebVector<WebString>(selectors));
420 m_frame->view()->layout();
422 EXPECT_EQ(1, updateCount());
423 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("div.initial_on"));
425 // Check that adding a watched selector calls back for already-present nodes.
426 selectors.push_back(WebString::fromUTF8("div.initial_off"));
427 doc().watchCSSSelectors(WebVector<WebString>(selectors));
428 m_frame->view()->layout();
430 EXPECT_EQ(2, updateCount());
431 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("div.initial_off", "div.initial_on"));
433 // Check that we can turn off callbacks for certain selectors.
434 doc().watchCSSSelectors(WebVector<WebString>());
435 m_frame->view()->layout();
437 EXPECT_EQ(3, updateCount());
438 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
441 TEST_F(WebFrameCSSCallbackTest, SharedRenderStyle)
443 // Check that adding an element calls back when it matches an existing rule.
444 std::vector<WebString> selectors;
445 selectors.push_back(WebString::fromUTF8("span"));
446 doc().watchCSSSelectors(WebVector<WebString>(selectors));
449 "i1 = document.createElement('span');"
450 "i1.id = 'first_span';"
451 "document.body.appendChild(i1)");
452 EXPECT_EQ(1, updateCount());
453 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
455 // Adding a second element that shares a RenderStyle shouldn't call back.
456 // We use <span>s to avoid default style rules that can set
457 // RenderStyle::unique().
459 "i2 = document.createElement('span');"
460 "i2.id = 'second_span';"
461 "i1 = document.getElementById('first_span');"
462 "i1.parentNode.insertBefore(i2, i1.nextSibling);");
463 EXPECT_EQ(1, updateCount());
464 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
466 // Removing the first element shouldn't call back.
468 "i1 = document.getElementById('first_span');"
469 "i1.parentNode.removeChild(i1);");
470 EXPECT_EQ(1, updateCount());
471 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
473 // But removing the second element *should* call back.
475 "i2 = document.getElementById('second_span');"
476 "i2.parentNode.removeChild(i2);");
477 EXPECT_EQ(2, updateCount());
478 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
481 TEST_F(WebFrameCSSCallbackTest, CatchesAttributeChange)
483 loadHTML("<span></span>");
485 std::vector<WebString> selectors;
486 selectors.push_back(WebString::fromUTF8("span[attr=\"value\"]"));
487 doc().watchCSSSelectors(WebVector<WebString>(selectors));
490 EXPECT_EQ(0, updateCount());
491 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
494 "document.querySelector('span').setAttribute('attr', 'value');");
495 EXPECT_EQ(1, updateCount());
496 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span[attr=\"value\"]"));
499 TEST_F(WebFrameCSSCallbackTest, DisplayNone)
501 loadHTML("<div style='display:none'><span></span></div>");
503 std::vector<WebString> selectors;
504 selectors.push_back(WebString::fromUTF8("span"));
505 doc().watchCSSSelectors(WebVector<WebString>(selectors));
508 EXPECT_EQ(0, updateCount()) << "Don't match elements in display:none trees.";
511 "d = document.querySelector('div');"
512 "d.style.display = 'block';");
513 EXPECT_EQ(1, updateCount()) << "Match elements when they become displayed.";
514 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
517 "d = document.querySelector('div');"
518 "d.style.display = 'none';");
519 EXPECT_EQ(2, updateCount()) << "Unmatch elements when they become undisplayed.";
520 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
523 "s = document.querySelector('span');"
524 "s.style.display = 'none';");
525 EXPECT_EQ(2, updateCount()) << "No effect from no-display'ing a span that's already undisplayed.";
528 "d = document.querySelector('div');"
529 "d.style.display = 'block';");
530 EXPECT_EQ(2, updateCount()) << "No effect from displaying a div whose span is display:none.";
533 "s = document.querySelector('span');"
534 "s.style.display = 'inline';");
535 EXPECT_EQ(3, updateCount()) << "Now the span is visible and produces a callback.";
536 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
539 "s = document.querySelector('span');"
540 "s.style.display = 'none';");
541 EXPECT_EQ(4, updateCount()) << "Undisplaying the span directly should produce another callback.";
542 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
545 TEST_F(WebFrameCSSCallbackTest, Reparenting)
548 "<div id='d1'><span></span></div>"
549 "<div id='d2'></div>");
551 std::vector<WebString> selectors;
552 selectors.push_back(WebString::fromUTF8("span"));
553 doc().watchCSSSelectors(WebVector<WebString>(selectors));
554 m_frame->view()->layout();
557 EXPECT_EQ(1, updateCount());
558 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
561 "s = document.querySelector('span');"
562 "d2 = document.getElementById('d2');"
563 "d2.appendChild(s);");
564 EXPECT_EQ(1, updateCount()) << "Just moving an element that continues to match shouldn't send a spurious callback.";
565 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
568 TEST_F(WebFrameCSSCallbackTest, MultiSelector)
570 loadHTML("<span></span>");
572 // Check that selector lists match as the whole list, not as each element
574 std::vector<WebString> selectors;
575 selectors.push_back(WebString::fromUTF8("span"));
576 selectors.push_back(WebString::fromUTF8("span,p"));
577 doc().watchCSSSelectors(WebVector<WebString>(selectors));
578 m_frame->view()->layout();
581 EXPECT_EQ(1, updateCount());
582 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span", "span, p"));
585 TEST_F(WebFrameCSSCallbackTest, InvalidSelector)
587 loadHTML("<p><span></span></p>");
589 // Build a list with one valid selector and one invalid.
590 std::vector<WebString> selectors;
591 selectors.push_back(WebString::fromUTF8("span"));
592 selectors.push_back(WebString::fromUTF8("[")); // Invalid.
593 selectors.push_back(WebString::fromUTF8("p span")); // Not compound.
594 doc().watchCSSSelectors(WebVector<WebString>(selectors));
595 m_frame->view()->layout();
598 EXPECT_EQ(1, updateCount());
599 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"))
600 << "An invalid selector shouldn't prevent other selectors from matching.";
603 TEST_F(WebFrameTest, DispatchMessageEventWithOriginCheck)
605 registerMockedHttpURLLoad("postmessage_test.html");
607 // Pass true to enable JavaScript.
608 FrameTestHelpers::WebViewHelper webViewHelper;
609 webViewHelper.initializeAndLoad(m_baseURL + "postmessage_test.html", true);
611 // Send a message with the correct origin.
612 WebSecurityOrigin correctOrigin(WebSecurityOrigin::create(toKURL(m_baseURL)));
613 WebDOMEvent event = webViewHelper.webView()->mainFrame()->document().createEvent("MessageEvent");
614 WebDOMMessageEvent message = event.to<WebDOMMessageEvent>();
615 WebSerializedScriptValue data(WebSerializedScriptValue::fromString("foo"));
616 message.initMessageEvent("message", false, false, data, "http://origin.com", 0, "");
617 webViewHelper.webView()->mainFrame()->dispatchMessageEventWithOriginCheck(correctOrigin, message);
619 // Send another message with incorrect origin.
620 WebSecurityOrigin incorrectOrigin(WebSecurityOrigin::create(toKURL(m_chromeURL)));
621 webViewHelper.webView()->mainFrame()->dispatchMessageEventWithOriginCheck(incorrectOrigin, message);
623 // Required to see any updates in contentAsText.
624 webViewHelper.webView()->layout();
626 // Verify that only the first addition is in the body of the page.
627 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
628 EXPECT_NE(std::string::npos, content.find("Message 1."));
629 EXPECT_EQ(std::string::npos, content.find("Message 2."));
632 TEST_F(WebFrameTest, PostMessageThenDetach)
634 FrameTestHelpers::WebViewHelper webViewHelper;
635 webViewHelper.initializeAndLoad("about:blank");
637 RefPtr<WebCore::LocalFrame> frame = webViewHelper.webViewImpl()->page()->mainFrame();
638 WebCore::NonThrowableExceptionState exceptionState;
639 frame->domWindow()->postMessage(WebCore::SerializedScriptValue::create("message"), 0, "*", frame->domWindow(), exceptionState);
640 webViewHelper.reset();
641 EXPECT_FALSE(exceptionState.hadException());
643 // Success is not crashing.
647 class FixedLayoutTestWebViewClient : public FrameTestHelpers::TestWebViewClient {
649 virtual WebScreenInfo screenInfo() OVERRIDE { return m_screenInfo; }
651 WebScreenInfo m_screenInfo;
654 // Viewport settings need to be set before the page gets loaded
655 static void enableViewportSettings(WebSettings* settings)
657 settings->setViewportMetaEnabled(true);
658 settings->setViewportEnabled(true);
659 settings->setMainFrameResizesAreOrientationChanges(true);
660 settings->setShrinksViewportContentToFit(true);
663 TEST_F(WebFrameTest, FrameViewNeedsLayoutOnFixedLayoutResize)
665 UseMockScrollbarSettings mockScrollbarSettings;
666 registerMockedHttpURLLoad("fixed_layout.html");
668 FixedLayoutTestWebViewClient client;
669 int viewportWidth = 640;
670 int viewportHeight = 480;
672 // Make sure we initialize to minimum scale, even if the window size
673 // only becomes available after the load begins.
674 FrameTestHelpers::WebViewHelper webViewHelper;
675 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
676 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
677 webViewHelper.webView()->layout();
679 webViewHelper.webViewImpl()->setFixedLayoutSize(WebCore::IntSize(100, 100));
680 EXPECT_TRUE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
682 int prevLayoutCount = webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount();
683 webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->setFrameRect(WebCore::IntRect(0, 0, 641, 481));
684 EXPECT_EQ(prevLayoutCount, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount());
686 webViewHelper.webViewImpl()->layout();
689 // Helper function to check or set text autosizing multipliers on a document.
690 static bool checkOrSetTextAutosizingMultiplier(Document* document, float multiplier, bool setMultiplier)
692 bool multiplierCheckedOrSetAtLeastOnce = false;
693 for (WebCore::RenderObject* renderer = document->renderer(); renderer; renderer = renderer->nextInPreOrder()) {
694 if (renderer->style()) {
696 renderer->style()->setTextAutosizingMultiplier(multiplier);
697 EXPECT_EQ(multiplier, renderer->style()->textAutosizingMultiplier());
698 multiplierCheckedOrSetAtLeastOnce = true;
701 return multiplierCheckedOrSetAtLeastOnce;
705 static bool setTextAutosizingMultiplier(Document* document, float multiplier)
707 return checkOrSetTextAutosizingMultiplier(document, multiplier, true);
710 static bool checkTextAutosizingMultiplier(Document* document, float multiplier)
712 return checkOrSetTextAutosizingMultiplier(document, multiplier, false);
715 TEST_F(WebFrameTest, ChangeInFixedLayoutResetsTextAutosizingMultipliers)
717 UseMockScrollbarSettings mockScrollbarSettings;
718 registerMockedHttpURLLoad("fixed_layout.html");
720 FixedLayoutTestWebViewClient client;
721 int viewportWidth = 640;
722 int viewportHeight = 480;
724 FrameTestHelpers::WebViewHelper webViewHelper;
725 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
727 WebCore::Document* document = webViewHelper.webViewImpl()->page()->mainFrame()->document();
728 document->settings()->setTextAutosizingEnabled(true);
729 EXPECT_TRUE(document->settings()->textAutosizingEnabled());
730 webViewHelper.webViewImpl()->resize(WebSize(viewportWidth, viewportHeight));
731 webViewHelper.webViewImpl()->layout();
733 EXPECT_TRUE(setTextAutosizingMultiplier(document, 2));
735 WebCore::ViewportDescription description = document->viewportDescription();
736 // Choose a width that's not going match the viewport width of the loaded document.
737 description.minWidth = WebCore::Length(100, WebCore::Fixed);
738 description.maxWidth = WebCore::Length(100, WebCore::Fixed);
739 webViewHelper.webViewImpl()->updatePageDefinedViewportConstraints(description);
741 EXPECT_TRUE(checkTextAutosizingMultiplier(document, 1));
744 TEST_F(WebFrameTest, SetFrameRectInvalidatesTextAutosizingMultipliers)
746 UseMockScrollbarSettings mockScrollbarSettings;
747 registerMockedHttpURLLoad("iframe_reload.html");
748 registerMockedHttpURLLoad("visible_iframe.html");
750 FixedLayoutTestWebViewClient client;
751 int viewportWidth = 640;
752 int viewportHeight = 480;
754 FrameTestHelpers::WebViewHelper webViewHelper;
755 webViewHelper.initializeAndLoad(m_baseURL + "iframe_reload.html", true, 0, &client, enableViewportSettings);
757 WebCore::LocalFrame* mainFrame = webViewHelper.webViewImpl()->page()->mainFrame();
758 WebCore::Document* document = mainFrame->document();
759 WebCore::FrameView* frameView = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
760 document->settings()->setTextAutosizingEnabled(true);
761 EXPECT_TRUE(document->settings()->textAutosizingEnabled());
762 webViewHelper.webViewImpl()->resize(WebSize(viewportWidth, viewportHeight));
763 webViewHelper.webViewImpl()->layout();
765 for (WebCore::LocalFrame* frame = mainFrame; frame; frame = frame->tree().traverseNext()) {
766 EXPECT_TRUE(setTextAutosizingMultiplier(frame->document(), 2));
767 for (WebCore::RenderObject* renderer = frame->document()->renderer(); renderer; renderer = renderer->nextInPreOrder()) {
768 if (renderer->isText())
769 EXPECT_FALSE(renderer->needsLayout());
773 frameView->setFrameRect(WebCore::IntRect(0, 0, 200, 200));
774 for (WebCore::LocalFrame* frame = mainFrame; frame; frame = frame->tree().traverseNext()) {
775 for (WebCore::RenderObject* renderer = frame->document()->renderer(); renderer; renderer = renderer->nextInPreOrder()) {
776 if (renderer->isText())
777 EXPECT_TRUE(renderer->needsLayout());
782 TEST_F(WebFrameTest, FixedLayoutSizeStopsResizeFromChangingLayoutSize)
784 UseMockScrollbarSettings mockScrollbarSettings;
785 registerMockedHttpURLLoad("fixed_layout.html");
787 int viewportWidth = 640;
788 int viewportHeight = 480;
790 int fixedLayoutWidth = viewportWidth / 2;
791 int fixedLayoutHeight = viewportHeight / 2;
793 FrameTestHelpers::WebViewHelper webViewHelper;
794 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, 0, enableViewportSettings);
795 webViewHelper.webView()->setFixedLayoutSize(WebSize(fixedLayoutWidth, fixedLayoutHeight));
796 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
797 webViewHelper.webView()->layout();
799 EXPECT_EQ(fixedLayoutWidth, webViewHelper.webViewImpl()->page()->mainFrame()->view()->layoutSize().width());
800 EXPECT_EQ(fixedLayoutHeight, webViewHelper.webViewImpl()->page()->mainFrame()->view()->layoutSize().height());
803 TEST_F(WebFrameTest, FixedLayoutSizePreventsResizeFromChangingPageScale)
805 UseMockScrollbarSettings mockScrollbarSettings;
806 registerMockedHttpURLLoad("fixed_layout.html");
808 int viewportWidth = 640;
809 int viewportHeight = 480;
811 int fixedLayoutWidth = viewportWidth / 2;
812 int fixedLayoutHeight = viewportHeight / 2;
814 FrameTestHelpers::WebViewHelper webViewHelper;
815 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, 0, enableViewportSettings);
816 webViewHelper.webView()->setFixedLayoutSize(WebSize(fixedLayoutWidth, fixedLayoutHeight));
817 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
818 webViewHelper.webView()->layout();
819 float pageScaleFactor = webViewHelper.webView()->pageScaleFactor();
821 webViewHelper.webView()->resize(WebSize(viewportWidth * 2, viewportHeight * 2));
823 EXPECT_EQ(pageScaleFactor, webViewHelper.webView()->pageScaleFactor());
826 TEST_F(WebFrameTest, FixedLayoutSizePreventsLayoutFromChangingPageScale)
828 UseMockScrollbarSettings mockScrollbarSettings;
829 registerMockedHttpURLLoad("fixed_layout.html");
831 int viewportWidth = 640;
832 int viewportHeight = 480;
834 int fixedLayoutWidth = viewportWidth * 2;
835 int fixedLayoutHeight = viewportHeight * 2;
837 FrameTestHelpers::WebViewHelper webViewHelper;
838 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, 0, enableViewportSettings);
839 webViewHelper.webView()->setFixedLayoutSize(WebSize(viewportWidth, viewportHeight));
840 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
841 webViewHelper.webView()->layout();
842 float pageScaleFactor = webViewHelper.webView()->pageScaleFactor();
844 webViewHelper.webView()->setFixedLayoutSize(WebSize(fixedLayoutWidth, fixedLayoutHeight));
845 webViewHelper.webView()->layout();
847 EXPECT_EQ(pageScaleFactor, webViewHelper.webView()->pageScaleFactor());
850 TEST_F(WebFrameTest, PreferredSizeAndContentSizeReportedCorrectlyWithZeroHeightFixedLayout)
852 UseMockScrollbarSettings mockScrollbarSettings;
853 registerMockedHttpURLLoad("200-by-300.html");
855 int windowWidth = 100;
856 int windowHeight = 100;
857 int viewportWidth = 100;
858 int viewportHeight = 0;
862 FixedLayoutTestWebViewClient client;
863 client.m_screenInfo.deviceScaleFactor = 1;
865 FrameTestHelpers::WebViewHelper webViewHelper;
866 webViewHelper.initializeAndLoad(m_baseURL + "200-by-300.html", true, 0, &client, enableViewportSettings);
867 webViewHelper.webView()->resize(WebSize(windowWidth, windowHeight));
868 webViewHelper.webView()->setFixedLayoutSize(WebSize(viewportWidth, viewportHeight));
869 webViewHelper.webView()->layout();
871 EXPECT_EQ(divWidth, webViewHelper.webView()->mainFrame()->contentsSize().width);
872 EXPECT_EQ(divHeight, webViewHelper.webView()->mainFrame()->contentsSize().height);
874 EXPECT_EQ(divWidth, webViewHelper.webView()->contentsPreferredMinimumSize().width);
875 EXPECT_EQ(divHeight, webViewHelper.webView()->contentsPreferredMinimumSize().height);
878 TEST_F(WebFrameTest, DisablingFixedLayoutSizeSetsCorrectLayoutSize)
880 UseMockScrollbarSettings mockScrollbarSettings;
881 registerMockedHttpURLLoad("no_viewport_tag.html");
883 FixedLayoutTestWebViewClient client;
884 client.m_screenInfo.deviceScaleFactor = 1;
885 int viewportWidth = 640;
886 int viewportHeight = 480;
888 FrameTestHelpers::WebViewHelper webViewHelper;
889 webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client, enableViewportSettings);
890 applyViewportStyleOverride(&webViewHelper);
891 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
892 webViewHelper.webView()->settings()->setUseWideViewport(true);
893 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
895 webViewHelper.webView()->setFixedLayoutSize(WebSize(viewportWidth, viewportHeight));
896 EXPECT_TRUE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
897 webViewHelper.webView()->layout();
898 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
900 webViewHelper.webView()->setFixedLayoutSize(WebSize(0, 0));
901 EXPECT_TRUE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
902 webViewHelper.webView()->layout();
903 EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
906 TEST_F(WebFrameTest, ZeroHeightPositiveWidthNotIgnored)
908 UseMockScrollbarSettings mockScrollbarSettings;
910 FixedLayoutTestWebViewClient client;
911 client.m_screenInfo.deviceScaleFactor = 1;
912 int viewportWidth = 1280;
913 int viewportHeight = 0;
915 FrameTestHelpers::WebViewHelper webViewHelper;
916 webViewHelper.initialize(true, 0, &client, enableViewportSettings);
917 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
919 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
920 EXPECT_EQ(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
923 TEST_F(WebFrameTest, DeviceScaleFactorUsesDefaultWithoutViewportTag)
925 UseMockScrollbarSettings mockScrollbarSettings;
926 registerMockedHttpURLLoad("no_viewport_tag.html");
928 int viewportWidth = 640;
929 int viewportHeight = 480;
931 FixedLayoutTestWebViewClient client;
932 client.m_screenInfo.deviceScaleFactor = 2;
934 FrameTestHelpers::WebViewHelper webViewHelper;
935 webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client, enableViewportSettings);
937 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
938 webViewHelper.webView()->layout();
940 EXPECT_EQ(2, webViewHelper.webView()->deviceScaleFactor());
942 // Device scale factor should be independent of page scale.
943 webViewHelper.webView()->setPageScaleFactorLimits(1, 2);
944 webViewHelper.webView()->setPageScaleFactor(0.5);
945 webViewHelper.webView()->layout();
946 EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor());
948 // Force the layout to happen before leaving the test.
949 webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
952 TEST_F(WebFrameTest, FixedLayoutInitializeAtMinimumScale)
954 UseMockScrollbarSettings mockScrollbarSettings;
956 registerMockedHttpURLLoad("fixed_layout.html");
958 FixedLayoutTestWebViewClient client;
959 client.m_screenInfo.deviceScaleFactor = 1;
960 int viewportWidth = 640;
961 int viewportHeight = 480;
963 // Make sure we initialize to minimum scale, even if the window size
964 // only becomes available after the load begins.
965 FrameTestHelpers::WebViewHelper webViewHelper;
966 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
967 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
969 int defaultFixedLayoutWidth = 980;
970 float minimumPageScaleFactor = viewportWidth / (float) defaultFixedLayoutWidth;
971 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
972 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->minimumPageScaleFactor());
974 // Assume the user has pinch zoomed to page scale factor 2.
975 float userPinchPageScaleFactor = 2;
976 webViewHelper.webView()->setPageScaleFactor(userPinchPageScaleFactor);
977 webViewHelper.webView()->layout();
979 // Make sure we don't reset to initial scale if the page continues to load.
980 webViewHelper.webViewImpl()->didCommitLoad(false, false);
981 webViewHelper.webViewImpl()->didChangeContentsSize();
982 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
984 // Make sure we don't reset to initial scale if the viewport size changes.
985 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight + 100));
986 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
989 TEST_F(WebFrameTest, WideDocumentInitializeAtMinimumScale)
991 UseMockScrollbarSettings mockScrollbarSettings;
993 registerMockedHttpURLLoad("wide_document.html");
995 FixedLayoutTestWebViewClient client;
996 client.m_screenInfo.deviceScaleFactor = 1;
997 int viewportWidth = 640;
998 int viewportHeight = 480;
1000 // Make sure we initialize to minimum scale, even if the window size
1001 // only becomes available after the load begins.
1002 FrameTestHelpers::WebViewHelper webViewHelper;
1003 webViewHelper.initializeAndLoad(m_baseURL + "wide_document.html", true, 0, &client, enableViewportSettings);
1004 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1006 int wideDocumentWidth = 1500;
1007 float minimumPageScaleFactor = viewportWidth / (float) wideDocumentWidth;
1008 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1009 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->minimumPageScaleFactor());
1011 // Assume the user has pinch zoomed to page scale factor 2.
1012 float userPinchPageScaleFactor = 2;
1013 webViewHelper.webView()->setPageScaleFactor(userPinchPageScaleFactor);
1014 webViewHelper.webView()->layout();
1016 // Make sure we don't reset to initial scale if the page continues to load.
1017 webViewHelper.webViewImpl()->didCommitLoad(false, false);
1018 webViewHelper.webViewImpl()->didChangeContentsSize();
1019 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1021 // Make sure we don't reset to initial scale if the viewport size changes.
1022 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight + 100));
1023 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1026 TEST_F(WebFrameTest, DelayedViewportInitialScale)
1028 UseMockScrollbarSettings mockScrollbarSettings;
1029 registerMockedHttpURLLoad("viewport-auto-initial-scale.html");
1031 FixedLayoutTestWebViewClient client;
1032 client.m_screenInfo.deviceScaleFactor = 1;
1033 int viewportWidth = 640;
1034 int viewportHeight = 480;
1036 FrameTestHelpers::WebViewHelper webViewHelper;
1037 webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings);
1038 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1040 EXPECT_EQ(0.25f, webViewHelper.webView()->pageScaleFactor());
1042 WebCore::Document* document = webViewHelper.webViewImpl()->page()->mainFrame()->document();
1043 WebCore::ViewportDescription description = document->viewportDescription();
1044 description.zoom = 2;
1045 document->setViewportDescription(description);
1046 webViewHelper.webView()->layout();
1047 EXPECT_EQ(2, webViewHelper.webView()->pageScaleFactor());
1050 TEST_F(WebFrameTest, setLoadWithOverviewModeToFalse)
1052 UseMockScrollbarSettings mockScrollbarSettings;
1053 registerMockedHttpURLLoad("viewport-auto-initial-scale.html");
1055 FixedLayoutTestWebViewClient client;
1056 client.m_screenInfo.deviceScaleFactor = 1;
1057 int viewportWidth = 640;
1058 int viewportHeight = 480;
1060 FrameTestHelpers::WebViewHelper webViewHelper;
1061 webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings);
1062 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1063 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1064 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1066 // The page must be displayed at 100% zoom.
1067 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
1070 TEST_F(WebFrameTest, SetLoadWithOverviewModeToFalseAndNoWideViewport)
1072 UseMockScrollbarSettings mockScrollbarSettings;
1073 registerMockedHttpURLLoad("large-div.html");
1075 FixedLayoutTestWebViewClient client;
1076 client.m_screenInfo.deviceScaleFactor = 1;
1077 int viewportWidth = 640;
1078 int viewportHeight = 480;
1080 FrameTestHelpers::WebViewHelper webViewHelper;
1081 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client, enableViewportSettings);
1082 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1083 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1084 webViewHelper.webView()->settings()->setUseWideViewport(false);
1085 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1087 // The page must be displayed at 100% zoom, despite that it hosts a wide div element.
1088 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
1091 TEST_F(WebFrameTest, NoWideViewportIgnoresPageViewportWidth)
1093 UseMockScrollbarSettings mockScrollbarSettings;
1094 registerMockedHttpURLLoad("viewport-auto-initial-scale.html");
1096 FixedLayoutTestWebViewClient client;
1097 client.m_screenInfo.deviceScaleFactor = 1;
1098 int viewportWidth = 640;
1099 int viewportHeight = 480;
1101 FrameTestHelpers::WebViewHelper webViewHelper;
1102 webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings);
1103 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1104 webViewHelper.webView()->settings()->setUseWideViewport(false);
1105 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1107 // The page sets viewport width to 3000, but with UseWideViewport == false is must be ignored.
1108 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1109 EXPECT_EQ(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
1112 TEST_F(WebFrameTest, NoWideViewportIgnoresPageViewportWidthButAccountsScale)
1114 UseMockScrollbarSettings mockScrollbarSettings;
1115 registerMockedHttpURLLoad("viewport-wide-2x-initial-scale.html");
1117 FixedLayoutTestWebViewClient client;
1118 client.m_screenInfo.deviceScaleFactor = 1;
1119 int viewportWidth = 640;
1120 int viewportHeight = 480;
1122 FrameTestHelpers::WebViewHelper webViewHelper;
1123 webViewHelper.initializeAndLoad(m_baseURL + "viewport-wide-2x-initial-scale.html", true, 0, &client, enableViewportSettings);
1124 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1125 webViewHelper.webView()->settings()->setUseWideViewport(false);
1126 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1128 // The page sets viewport width to 3000, but with UseWideViewport == false it must be ignored.
1129 // While the initial scale specified by the page must be accounted.
1130 EXPECT_EQ(viewportWidth / 2, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1131 EXPECT_EQ(viewportHeight / 2, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
1134 TEST_F(WebFrameTest, WideViewportSetsTo980WithoutViewportTag)
1136 UseMockScrollbarSettings mockScrollbarSettings;
1137 registerMockedHttpURLLoad("no_viewport_tag.html");
1139 FixedLayoutTestWebViewClient client;
1140 client.m_screenInfo.deviceScaleFactor = 1;
1141 int viewportWidth = 640;
1142 int viewportHeight = 480;
1144 FrameTestHelpers::WebViewHelper webViewHelper;
1145 webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client, enableViewportSettings);
1146 applyViewportStyleOverride(&webViewHelper);
1147 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1148 webViewHelper.webView()->settings()->setUseWideViewport(true);
1149 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1151 EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1152 EXPECT_EQ(980.0 / viewportWidth * viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
1155 TEST_F(WebFrameTest, NoWideViewportAndHeightInMeta)
1157 UseMockScrollbarSettings mockScrollbarSettings;
1158 registerMockedHttpURLLoad("viewport-height-1000.html");
1160 FixedLayoutTestWebViewClient client;
1161 client.m_screenInfo.deviceScaleFactor = 1;
1162 int viewportWidth = 640;
1163 int viewportHeight = 480;
1165 FrameTestHelpers::WebViewHelper webViewHelper;
1166 webViewHelper.initializeAndLoad(m_baseURL + "viewport-height-1000.html", true, 0, &client, enableViewportSettings);
1167 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1168 webViewHelper.webView()->settings()->setUseWideViewport(false);
1169 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1171 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1174 TEST_F(WebFrameTest, WideViewportSetsTo980WithAutoWidth)
1176 UseMockScrollbarSettings mockScrollbarSettings;
1177 registerMockedHttpURLLoad("viewport-2x-initial-scale.html");
1179 FixedLayoutTestWebViewClient client;
1180 client.m_screenInfo.deviceScaleFactor = 1;
1181 int viewportWidth = 640;
1182 int viewportHeight = 480;
1184 FrameTestHelpers::WebViewHelper webViewHelper;
1185 webViewHelper.initializeAndLoad(m_baseURL + "viewport-2x-initial-scale.html", true, 0, &client, enableViewportSettings);
1186 applyViewportStyleOverride(&webViewHelper);
1187 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1188 webViewHelper.webView()->settings()->setUseWideViewport(true);
1189 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1191 EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1192 EXPECT_EQ(980.0 / viewportWidth * viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
1195 TEST_F(WebFrameTest, PageViewportInitialScaleOverridesLoadWithOverviewMode)
1197 UseMockScrollbarSettings mockScrollbarSettings;
1198 registerMockedHttpURLLoad("viewport-wide-2x-initial-scale.html");
1200 FixedLayoutTestWebViewClient client;
1201 client.m_screenInfo.deviceScaleFactor = 1;
1202 int viewportWidth = 640;
1203 int viewportHeight = 480;
1205 FrameTestHelpers::WebViewHelper webViewHelper;
1206 webViewHelper.initializeAndLoad(m_baseURL + "viewport-wide-2x-initial-scale.html", true, 0, &client, enableViewportSettings);
1207 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1208 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1210 // The page must be displayed at 200% zoom, as specified in its viewport meta tag.
1211 EXPECT_EQ(2.0f, webViewHelper.webView()->pageScaleFactor());
1214 TEST_F(WebFrameTest, setInitialPageScaleFactorPermanently)
1216 UseMockScrollbarSettings mockScrollbarSettings;
1218 registerMockedHttpURLLoad("fixed_layout.html");
1220 FixedLayoutTestWebViewClient client;
1221 client.m_screenInfo.deviceScaleFactor = 1;
1222 float enforcedPageScaleFactor = 2.0f;
1224 FrameTestHelpers::WebViewHelper webViewHelper;
1225 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1226 applyViewportStyleOverride(&webViewHelper);
1227 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1228 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1229 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1230 webViewHelper.webView()->layout();
1232 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1234 int viewportWidth = 640;
1235 int viewportHeight = 480;
1236 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1237 webViewHelper.webView()->layout();
1239 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1241 webViewHelper.webView()->setInitialPageScaleOverride(-1);
1242 webViewHelper.webView()->layout();
1243 EXPECT_EQ(1.0, webViewHelper.webView()->pageScaleFactor());
1246 TEST_F(WebFrameTest, PermanentInitialPageScaleFactorOverridesLoadWithOverviewMode)
1248 UseMockScrollbarSettings mockScrollbarSettings;
1249 registerMockedHttpURLLoad("viewport-auto-initial-scale.html");
1251 FixedLayoutTestWebViewClient client;
1252 client.m_screenInfo.deviceScaleFactor = 1;
1253 int viewportWidth = 640;
1254 int viewportHeight = 480;
1255 float enforcedPageScaleFactor = 0.5f;
1257 FrameTestHelpers::WebViewHelper webViewHelper;
1258 webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings);
1259 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1260 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1261 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1263 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1266 TEST_F(WebFrameTest, PermanentInitialPageScaleFactorOverridesPageViewportInitialScale)
1268 UseMockScrollbarSettings mockScrollbarSettings;
1269 registerMockedHttpURLLoad("viewport-wide-2x-initial-scale.html");
1271 FixedLayoutTestWebViewClient client;
1272 client.m_screenInfo.deviceScaleFactor = 1;
1273 int viewportWidth = 640;
1274 int viewportHeight = 480;
1275 float enforcedPageScaleFactor = 0.5f;
1277 FrameTestHelpers::WebViewHelper webViewHelper;
1278 webViewHelper.initializeAndLoad(m_baseURL + "viewport-wide-2x-initial-scale.html", true, 0, &client, enableViewportSettings);
1279 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1280 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1282 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1285 TEST_F(WebFrameTest, SmallPermanentInitialPageScaleFactorIsClobbered)
1287 UseMockScrollbarSettings mockScrollbarSettings;
1288 const char* pages[] = {
1289 // These pages trigger the clobbering condition. There must be a matching item in "pageScaleFactors" array.
1290 "viewport-device-0.5x-initial-scale.html",
1291 "viewport-initial-scale-1.html",
1292 // These ones do not.
1293 "viewport-auto-initial-scale.html",
1294 "viewport-target-densitydpi-device-and-fixed-width.html"
1296 float pageScaleFactors[] = { 0.5f, 1.0f };
1297 for (size_t i = 0; i < ARRAY_SIZE(pages); ++i)
1298 registerMockedHttpURLLoad(pages[i]);
1300 FixedLayoutTestWebViewClient client;
1301 client.m_screenInfo.deviceScaleFactor = 1;
1302 int viewportWidth = 400;
1303 int viewportHeight = 300;
1304 float enforcedPageScaleFactor = 0.75f;
1306 for (size_t i = 0; i < ARRAY_SIZE(pages); ++i) {
1307 for (int quirkEnabled = 0; quirkEnabled <= 1; ++quirkEnabled) {
1308 FrameTestHelpers::WebViewHelper webViewHelper;
1309 webViewHelper.initializeAndLoad(m_baseURL + pages[i], true, 0, &client, enableViewportSettings);
1310 applyViewportStyleOverride(&webViewHelper);
1311 webViewHelper.webView()->settings()->setClobberUserAgentInitialScaleQuirk(quirkEnabled);
1312 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1313 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1315 float expectedPageScaleFactor = quirkEnabled && i < ARRAY_SIZE(pageScaleFactors) ? pageScaleFactors[i] : enforcedPageScaleFactor;
1316 EXPECT_EQ(expectedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1321 TEST_F(WebFrameTest, PermanentInitialPageScaleFactorAffectsLayoutWidth)
1323 UseMockScrollbarSettings mockScrollbarSettings;
1325 FixedLayoutTestWebViewClient client;
1326 client.m_screenInfo.deviceScaleFactor = 1;
1327 int viewportWidth = 640;
1328 int viewportHeight = 480;
1329 float enforcedPageScaleFactor = 0.5;
1331 FrameTestHelpers::WebViewHelper webViewHelper;
1332 webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings);
1333 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1334 webViewHelper.webView()->settings()->setUseWideViewport(false);
1335 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1336 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1337 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1339 EXPECT_EQ(viewportWidth / enforcedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1340 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1343 TEST_F(WebFrameTest, WideViewportInitialScaleDoesNotExpandFixedLayoutWidth)
1345 UseMockScrollbarSettings mockScrollbarSettings;
1346 registerMockedHttpURLLoad("viewport-device-0.5x-initial-scale.html");
1348 FixedLayoutTestWebViewClient client;
1349 client.m_screenInfo.deviceScaleFactor = 1;
1350 int viewportWidth = 640;
1351 int viewportHeight = 480;
1353 FrameTestHelpers::WebViewHelper webViewHelper;
1354 webViewHelper.initializeAndLoad(m_baseURL + "viewport-device-0.5x-initial-scale.html", true, 0, &client, enableViewportSettings);
1355 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1356 webViewHelper.webView()->settings()->setUseWideViewport(true);
1357 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1358 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1360 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1361 EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor());
1363 webViewHelper.webView()->setFixedLayoutSize(WebSize(2000, 1500));
1364 webViewHelper.webView()->layout();
1365 EXPECT_EQ(2000, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1366 EXPECT_EQ(0.5f, webViewHelper.webView()->pageScaleFactor());
1369 TEST_F(WebFrameTest, WideViewportAndWideContentWithInitialScale)
1371 UseMockScrollbarSettings mockScrollbarSettings;
1372 registerMockedHttpURLLoad("wide_document_width_viewport.html");
1374 FixedLayoutTestWebViewClient client;
1375 client.m_screenInfo.deviceScaleFactor = 1;
1376 int viewportWidth = 600;
1377 int viewportHeight = 800;
1379 FrameTestHelpers::WebViewHelper webViewHelper;
1380 webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings);
1381 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1382 webViewHelper.webView()->settings()->setUseWideViewport(true);
1383 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1384 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1386 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "wide_document_width_viewport.html");
1387 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
1388 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1390 int wideDocumentWidth = 800;
1391 float minimumPageScaleFactor = viewportWidth / (float) wideDocumentWidth;
1392 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1393 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->minimumPageScaleFactor());
1396 TEST_F(WebFrameTest, WideViewportQuirkClobbersHeight)
1398 UseMockScrollbarSettings mockScrollbarSettings;
1399 registerMockedHttpURLLoad("viewport-height-1000.html");
1401 FixedLayoutTestWebViewClient client;
1402 client.m_screenInfo.deviceScaleFactor = 1;
1403 int viewportWidth = 600;
1404 int viewportHeight = 800;
1406 FrameTestHelpers::WebViewHelper webViewHelper;
1407 webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings);
1408 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1409 webViewHelper.webView()->settings()->setUseWideViewport(false);
1410 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1411 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1413 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport-height-1000.html");
1414 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
1415 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1417 EXPECT_EQ(800, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1418 EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor());
1421 TEST_F(WebFrameTest, LayoutSize320Quirk)
1423 UseMockScrollbarSettings mockScrollbarSettings;
1424 registerMockedHttpURLLoad("viewport/viewport-30.html");
1426 FixedLayoutTestWebViewClient client;
1427 client.m_screenInfo.deviceScaleFactor = 1;
1428 int viewportWidth = 600;
1429 int viewportHeight = 800;
1431 FrameTestHelpers::WebViewHelper webViewHelper;
1432 webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings);
1433 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1434 webViewHelper.webView()->settings()->setUseWideViewport(true);
1435 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1436 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1438 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport/viewport-30.html");
1439 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
1440 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1442 EXPECT_EQ(600, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1443 EXPECT_EQ(800, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1444 EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor());
1446 // The magic number to snap to device-width is 320, so test that 321 is
1448 WebCore::Document* document = webViewHelper.webViewImpl()->page()->mainFrame()->document();
1449 WebCore::ViewportDescription description = document->viewportDescription();
1450 description.minWidth = WebCore::Length(321, WebCore::Fixed);
1451 description.maxWidth = WebCore::Length(321, WebCore::Fixed);
1452 document->setViewportDescription(description);
1453 webViewHelper.webView()->layout();
1454 EXPECT_EQ(321, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1456 description.minWidth = WebCore::Length(320, WebCore::Fixed);
1457 description.maxWidth = WebCore::Length(320, WebCore::Fixed);
1458 document->setViewportDescription(description);
1459 webViewHelper.webView()->layout();
1460 EXPECT_EQ(600, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1462 description = document->viewportDescription();
1463 description.maxHeight = WebCore::Length(1000, WebCore::Fixed);
1464 document->setViewportDescription(description);
1465 webViewHelper.webView()->layout();
1466 EXPECT_EQ(1000, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1468 description.maxHeight = WebCore::Length(320, WebCore::Fixed);
1469 document->setViewportDescription(description);
1470 webViewHelper.webView()->layout();
1471 EXPECT_EQ(800, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1474 TEST_F(WebFrameTest, ZeroValuesQuirk)
1476 UseMockScrollbarSettings mockScrollbarSettings;
1477 registerMockedHttpURLLoad("viewport-zero-values.html");
1479 FixedLayoutTestWebViewClient client;
1480 client.m_screenInfo.deviceScaleFactor = 1;
1481 int viewportWidth = 640;
1482 int viewportHeight = 480;
1484 FrameTestHelpers::WebViewHelper webViewHelper;
1485 webViewHelper.initialize(true, 0, &client, enableViewportSettings);
1486 webViewHelper.webView()->settings()->setViewportMetaZeroValuesQuirk(true);
1487 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1488 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1489 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport-zero-values.html");
1490 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
1491 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1493 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1494 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
1496 webViewHelper.webView()->settings()->setUseWideViewport(true);
1497 webViewHelper.webView()->layout();
1498 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1499 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
1502 TEST_F(WebFrameTest, OverflowHiddenDisablesScrolling)
1504 registerMockedHttpURLLoad("body-overflow-hidden.html");
1506 FixedLayoutTestWebViewClient client;
1507 client.m_screenInfo.deviceScaleFactor = 1;
1508 int viewportWidth = 640;
1509 int viewportHeight = 480;
1511 FrameTestHelpers::WebViewHelper webViewHelper;
1512 webViewHelper.initialize(true, 0, &client);
1513 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "body-overflow-hidden.html");
1514 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
1515 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1517 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
1518 EXPECT_FALSE(view->userInputScrollable(WebCore::VerticalScrollbar));
1521 TEST_F(WebFrameTest, IgnoreOverflowHiddenQuirk)
1523 registerMockedHttpURLLoad("body-overflow-hidden.html");
1525 FixedLayoutTestWebViewClient client;
1526 client.m_screenInfo.deviceScaleFactor = 1;
1527 int viewportWidth = 640;
1528 int viewportHeight = 480;
1530 FrameTestHelpers::WebViewHelper webViewHelper;
1531 webViewHelper.initialize(true, 0, &client);
1532 webViewHelper.webView()->settings()->setIgnoreMainFrameOverflowHiddenQuirk(true);
1533 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "body-overflow-hidden.html");
1534 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
1535 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1537 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
1538 EXPECT_TRUE(view->userInputScrollable(WebCore::VerticalScrollbar));
1541 TEST_F(WebFrameTest, NonZeroValuesNoQuirk)
1543 UseMockScrollbarSettings mockScrollbarSettings;
1544 registerMockedHttpURLLoad("viewport-nonzero-values.html");
1546 FixedLayoutTestWebViewClient client;
1547 client.m_screenInfo.deviceScaleFactor = 1;
1548 int viewportWidth = 640;
1549 int viewportHeight = 480;
1550 float expectedPageScaleFactor = 0.5f;
1552 FrameTestHelpers::WebViewHelper webViewHelper;
1553 webViewHelper.initialize(true, 0, &client, enableViewportSettings);
1554 webViewHelper.webView()->settings()->setViewportMetaZeroValuesQuirk(true);
1555 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1556 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport-nonzero-values.html");
1557 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
1558 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1560 EXPECT_EQ(viewportWidth / expectedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1561 EXPECT_EQ(expectedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1563 webViewHelper.webView()->settings()->setUseWideViewport(true);
1564 webViewHelper.webView()->layout();
1565 EXPECT_EQ(viewportWidth / expectedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1566 EXPECT_EQ(expectedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1569 TEST_F(WebFrameTest, setPageScaleFactorDoesNotLayout)
1571 UseMockScrollbarSettings mockScrollbarSettings;
1572 registerMockedHttpURLLoad("fixed_layout.html");
1574 FixedLayoutTestWebViewClient client;
1575 client.m_screenInfo.deviceScaleFactor = 1;
1576 // Small viewport to ensure there are always scrollbars.
1577 int viewportWidth = 64;
1578 int viewportHeight = 48;
1580 FrameTestHelpers::WebViewHelper webViewHelper;
1581 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1582 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1583 webViewHelper.webView()->layout();
1585 int prevLayoutCount = webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount();
1586 webViewHelper.webViewImpl()->setPageScaleFactor(3);
1587 EXPECT_FALSE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
1588 EXPECT_EQ(prevLayoutCount, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount());
1591 TEST_F(WebFrameTest, setPageScaleFactorWithOverlayScrollbarsDoesNotLayout)
1593 UseMockScrollbarSettings mockScrollbarSettings;
1595 registerMockedHttpURLLoad("fixed_layout.html");
1597 FixedLayoutTestWebViewClient client;
1598 client.m_screenInfo.deviceScaleFactor = 1;
1599 int viewportWidth = 640;
1600 int viewportHeight = 480;
1602 FrameTestHelpers::WebViewHelper webViewHelper;
1603 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1604 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1605 webViewHelper.webView()->layout();
1607 int prevLayoutCount = webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount();
1608 webViewHelper.webViewImpl()->setPageScaleFactor(30);
1609 EXPECT_FALSE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
1610 EXPECT_EQ(prevLayoutCount, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount());
1614 TEST_F(WebFrameTest, setPageScaleFactorBeforeFrameHasView)
1616 registerMockedHttpURLLoad("fixed_layout.html");
1618 float pageScaleFactor = 3;
1619 FrameTestHelpers::WebViewHelper webViewHelper;
1620 webViewHelper.initializeAndLoad("about:html", true, 0, 0);
1621 webViewHelper.webView()->setPageScaleFactor(pageScaleFactor);
1623 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "fixed_layout.html");
1624 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
1625 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
1626 EXPECT_EQ(pageScaleFactor, view->visibleContentScaleFactor());
1629 TEST_F(WebFrameTest, pageScaleFactorWrittenToHistoryItem)
1631 UseMockScrollbarSettings mockScrollbarSettings;
1632 registerMockedHttpURLLoad("fixed_layout.html");
1634 FixedLayoutTestWebViewClient client;
1635 client.m_screenInfo.deviceScaleFactor = 1;
1636 int viewportWidth = 640;
1637 int viewportHeight = 480;
1639 FrameTestHelpers::WebViewHelper webViewHelper;
1640 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1641 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1642 webViewHelper.webView()->layout();
1644 webViewHelper.webView()->setPageScaleFactor(3);
1645 EXPECT_EQ(3, webViewHelper.webViewImpl()->page()->mainFrame()->loader().currentItem()->pageScaleFactor());
1648 TEST_F(WebFrameTest, initialScaleWrittenToHistoryItem)
1650 UseMockScrollbarSettings mockScrollbarSettings;
1651 registerMockedHttpURLLoad("fixed_layout.html");
1653 FixedLayoutTestWebViewClient client;
1654 client.m_screenInfo.deviceScaleFactor = 1;
1655 int viewportWidth = 640;
1656 int viewportHeight = 480;
1658 FrameTestHelpers::WebViewHelper webViewHelper;
1659 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1660 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1661 webViewHelper.webView()->layout();
1663 int defaultFixedLayoutWidth = 980;
1664 float minimumPageScaleFactor = viewportWidth / (float) defaultFixedLayoutWidth;
1665 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webViewImpl()->page()->mainFrame()->loader().currentItem()->pageScaleFactor());
1668 TEST_F(WebFrameTest, pageScaleFactorShrinksViewport)
1670 UseMockScrollbarSettings mockScrollbarSettings;
1671 registerMockedHttpURLLoad("large-div.html");
1673 FixedLayoutTestWebViewClient client;
1674 client.m_screenInfo.deviceScaleFactor = 1;
1675 // Small viewport to ensure there are always scrollbars.
1676 int viewportWidth = 64;
1677 int viewportHeight = 48;
1679 FrameTestHelpers::WebViewHelper webViewHelper;
1680 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client, enableViewportSettings);
1681 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1682 webViewHelper.webView()->layout();
1684 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
1685 int viewportWidthMinusScrollbar = viewportWidth - (view->verticalScrollbar()->isOverlayScrollbar() ? 0 : 15);
1686 int viewportHeightMinusScrollbar = viewportHeight - (view->horizontalScrollbar()->isOverlayScrollbar() ? 0 : 15);
1688 webViewHelper.webView()->setPageScaleFactor(2);
1690 WebCore::IntSize unscaledSize = view->unscaledVisibleContentSize(WebCore::IncludeScrollbars);
1691 EXPECT_EQ(viewportWidth, unscaledSize.width());
1692 EXPECT_EQ(viewportHeight, unscaledSize.height());
1694 WebCore::IntSize unscaledSizeMinusScrollbar = view->unscaledVisibleContentSize(WebCore::ExcludeScrollbars);
1695 EXPECT_EQ(viewportWidthMinusScrollbar, unscaledSizeMinusScrollbar.width());
1696 EXPECT_EQ(viewportHeightMinusScrollbar, unscaledSizeMinusScrollbar.height());
1698 WebCore::IntSize scaledSize = view->visibleContentRect().size();
1699 EXPECT_EQ(ceil(viewportWidthMinusScrollbar / 2.0), scaledSize.width());
1700 EXPECT_EQ(ceil(viewportHeightMinusScrollbar / 2.0), scaledSize.height());
1703 TEST_F(WebFrameTest, pageScaleFactorDoesNotApplyCssTransform)
1705 UseMockScrollbarSettings mockScrollbarSettings;
1706 registerMockedHttpURLLoad("fixed_layout.html");
1708 FixedLayoutTestWebViewClient client;
1709 client.m_screenInfo.deviceScaleFactor = 1;
1710 int viewportWidth = 640;
1711 int viewportHeight = 480;
1713 FrameTestHelpers::WebViewHelper webViewHelper;
1714 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1715 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1716 webViewHelper.webView()->layout();
1718 webViewHelper.webView()->setPageScaleFactor(2);
1720 EXPECT_EQ(980, webViewHelper.webViewImpl()->page()->mainFrame()->contentRenderer()->unscaledDocumentRect().width());
1721 EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1724 TEST_F(WebFrameTest, targetDensityDpiHigh)
1726 UseMockScrollbarSettings mockScrollbarSettings;
1727 registerMockedHttpURLLoad("viewport-target-densitydpi-high.html");
1729 FixedLayoutTestWebViewClient client;
1731 float targetDpi = 240.0f;
1732 float deviceScaleFactors[] = { 1.0f, 4.0f / 3.0f, 2.0f };
1733 int viewportWidth = 640;
1734 int viewportHeight = 480;
1736 for (size_t i = 0; i < ARRAY_SIZE(deviceScaleFactors); ++i) {
1737 float deviceScaleFactor = deviceScaleFactors[i];
1738 float deviceDpi = deviceScaleFactor * 160.0f;
1739 client.m_screenInfo.deviceScaleFactor = deviceScaleFactor;
1741 FrameTestHelpers::WebViewHelper webViewHelper;
1742 webViewHelper.initializeAndLoad(m_baseURL + "viewport-target-densitydpi-high.html", true, 0, &client, enableViewportSettings);
1743 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1744 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1745 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1747 // We need to account for the fact that logical pixels are unconditionally multiplied by deviceScaleFactor to produce
1749 float densityDpiScaleRatio = deviceScaleFactor * targetDpi / deviceDpi;
1750 EXPECT_NEAR(viewportWidth * densityDpiScaleRatio, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1751 EXPECT_NEAR(viewportHeight * densityDpiScaleRatio, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1752 EXPECT_NEAR(1.0f / densityDpiScaleRatio, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1756 TEST_F(WebFrameTest, targetDensityDpiDevice)
1758 UseMockScrollbarSettings mockScrollbarSettings;
1759 registerMockedHttpURLLoad("viewport-target-densitydpi-device.html");
1761 float deviceScaleFactors[] = { 1.0f, 4.0f / 3.0f, 2.0f };
1763 FixedLayoutTestWebViewClient client;
1764 int viewportWidth = 640;
1765 int viewportHeight = 480;
1767 for (size_t i = 0; i < ARRAY_SIZE(deviceScaleFactors); ++i) {
1768 client.m_screenInfo.deviceScaleFactor = deviceScaleFactors[i];
1770 FrameTestHelpers::WebViewHelper webViewHelper;
1771 webViewHelper.initializeAndLoad(m_baseURL + "viewport-target-densitydpi-device.html", true, 0, &client, enableViewportSettings);
1772 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1773 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1774 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1776 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1777 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1778 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1782 TEST_F(WebFrameTest, targetDensityDpiDeviceAndFixedWidth)
1784 UseMockScrollbarSettings mockScrollbarSettings;
1785 registerMockedHttpURLLoad("viewport-target-densitydpi-device-and-fixed-width.html");
1787 float deviceScaleFactors[] = { 1.0f, 4.0f / 3.0f, 2.0f };
1789 FixedLayoutTestWebViewClient client;
1790 int viewportWidth = 640;
1791 int viewportHeight = 480;
1793 for (size_t i = 0; i < ARRAY_SIZE(deviceScaleFactors); ++i) {
1794 client.m_screenInfo.deviceScaleFactor = deviceScaleFactors[i];
1796 FrameTestHelpers::WebViewHelper webViewHelper;
1797 webViewHelper.initializeAndLoad(m_baseURL + "viewport-target-densitydpi-device-and-fixed-width.html", true, 0, &client, enableViewportSettings);
1798 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1799 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1800 webViewHelper.webView()->settings()->setUseWideViewport(true);
1801 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1803 EXPECT_NEAR(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1804 EXPECT_NEAR(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1805 EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1809 TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOne)
1811 UseMockScrollbarSettings mockScrollbarSettings;
1812 registerMockedHttpURLLoad("viewport-initial-scale-less-than-1.html");
1814 FixedLayoutTestWebViewClient client;
1815 client.m_screenInfo.deviceScaleFactor = 1.33f;
1816 int viewportWidth = 640;
1817 int viewportHeight = 480;
1819 FrameTestHelpers::WebViewHelper webViewHelper;
1820 webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-less-than-1.html", true, 0, &client, enableViewportSettings);
1821 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1822 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1823 webViewHelper.webView()->settings()->setUseWideViewport(false);
1824 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1825 webViewHelper.webView()->layout();
1827 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1828 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1829 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1832 TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOneWithDeviceWidth)
1834 UseMockScrollbarSettings mockScrollbarSettings;
1835 registerMockedHttpURLLoad("viewport-initial-scale-less-than-1-device-width.html");
1837 FixedLayoutTestWebViewClient client;
1838 client.m_screenInfo.deviceScaleFactor = 1.33f;
1839 int viewportWidth = 640;
1840 int viewportHeight = 480;
1842 FrameTestHelpers::WebViewHelper webViewHelper;
1843 webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-less-than-1-device-width.html", true, 0, &client, enableViewportSettings);
1844 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1845 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1846 webViewHelper.webView()->settings()->setUseWideViewport(false);
1847 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1848 webViewHelper.webView()->layout();
1850 const float pageZoom = 0.25f;
1851 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor / pageZoom, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1852 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor / pageZoom, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1853 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1856 TEST_F(WebFrameTest, NoWideViewportAndNoViewportWithInitialPageScaleOverride)
1858 UseMockScrollbarSettings mockScrollbarSettings;
1859 registerMockedHttpURLLoad("large-div.html");
1861 FixedLayoutTestWebViewClient client;
1862 int viewportWidth = 640;
1863 int viewportHeight = 480;
1864 float enforcedPageScaleFactor = 5.0f;
1866 FrameTestHelpers::WebViewHelper webViewHelper;
1867 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client, enableViewportSettings);
1868 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1869 webViewHelper.webView()->settings()->setUseWideViewport(false);
1870 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1871 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1872 webViewHelper.webView()->layout();
1874 EXPECT_NEAR(viewportWidth / enforcedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1875 EXPECT_NEAR(viewportHeight / enforcedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1876 EXPECT_NEAR(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1879 TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScale)
1881 UseMockScrollbarSettings mockScrollbarSettings;
1882 registerMockedHttpURLLoad("viewport-initial-scale-and-user-scalable-no.html");
1884 FixedLayoutTestWebViewClient client;
1885 int viewportWidth = 640;
1886 int viewportHeight = 480;
1888 FrameTestHelpers::WebViewHelper webViewHelper;
1889 webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-and-user-scalable-no.html", true, 0, &client, enableViewportSettings);
1890 webViewHelper.webView()->settings()->setViewportMetaNonUserScalableQuirk(true);
1891 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1892 webViewHelper.webView()->layout();
1894 EXPECT_NEAR(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1895 EXPECT_NEAR(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1896 EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1899 TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScaleForNonWideViewport)
1901 UseMockScrollbarSettings mockScrollbarSettings;
1902 registerMockedHttpURLLoad("viewport-initial-scale-and-user-scalable-no.html");
1904 FixedLayoutTestWebViewClient client;
1905 client.m_screenInfo.deviceScaleFactor = 1.33f;
1906 int viewportWidth = 640;
1907 int viewportHeight = 480;
1909 FrameTestHelpers::WebViewHelper webViewHelper;
1910 webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-and-user-scalable-no.html", true, 0, &client, enableViewportSettings);
1911 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1912 webViewHelper.webView()->settings()->setViewportMetaNonUserScalableQuirk(true);
1913 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1914 webViewHelper.webView()->settings()->setUseWideViewport(false);
1915 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1916 webViewHelper.webView()->layout();
1918 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1919 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1920 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1923 TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScaleForWideViewport)
1925 UseMockScrollbarSettings mockScrollbarSettings;
1926 registerMockedHttpURLLoad("viewport-2x-initial-scale-non-user-scalable.html");
1928 FixedLayoutTestWebViewClient client;
1929 int viewportWidth = 640;
1930 int viewportHeight = 480;
1932 FrameTestHelpers::WebViewHelper webViewHelper;
1933 webViewHelper.initializeAndLoad(m_baseURL + "viewport-2x-initial-scale-non-user-scalable.html", true, 0, &client, enableViewportSettings);
1934 webViewHelper.webView()->settings()->setViewportMetaNonUserScalableQuirk(true);
1935 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1936 webViewHelper.webView()->settings()->setUseWideViewport(true);
1937 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1939 EXPECT_NEAR(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1940 EXPECT_NEAR(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1941 EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1944 TEST_F(WebFrameTest, DesktopPageCanBeZoomedInWhenWideViewportIsTurnedOff)
1946 UseMockScrollbarSettings mockScrollbarSettings;
1947 registerMockedHttpURLLoad("no_viewport_tag.html");
1949 FixedLayoutTestWebViewClient client;
1950 int viewportWidth = 640;
1951 int viewportHeight = 480;
1953 FrameTestHelpers::WebViewHelper webViewHelper;
1954 webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client, enableViewportSettings);
1955 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1956 webViewHelper.webView()->settings()->setUseWideViewport(false);
1957 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1959 EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1960 EXPECT_NEAR(1.0f, webViewHelper.webView()->minimumPageScaleFactor(), 0.01f);
1961 EXPECT_NEAR(5.0f, webViewHelper.webView()->maximumPageScaleFactor(), 0.01f);
1964 class WebFrameResizeTest : public WebFrameTest {
1967 static WebCore::FloatSize computeRelativeOffset(const WebCore::IntPoint& absoluteOffset, const WebCore::LayoutRect& rect)
1969 WebCore::FloatSize relativeOffset = WebCore::FloatPoint(absoluteOffset) - rect.location();
1970 relativeOffset.scale(1.f / rect.width(), 1.f / rect.height());
1971 return relativeOffset;
1974 void testResizeYieldsCorrectScrollAndScale(const char* url,
1975 const float initialPageScaleFactor,
1976 const WebSize scrollOffset,
1977 const WebSize viewportSize,
1978 const bool shouldScaleRelativeToViewportWidth) {
1979 UseMockScrollbarSettings mockScrollbarSettings;
1980 registerMockedHttpURLLoad(url);
1982 const float aspectRatio = static_cast<float>(viewportSize.width) / viewportSize.height;
1984 FrameTestHelpers::WebViewHelper webViewHelper;
1985 webViewHelper.initializeAndLoad(m_baseURL + url, true, 0, 0, enableViewportSettings);
1987 // Origin scrollOffsets preserved under resize.
1989 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height));
1990 webViewHelper.webViewImpl()->setPageScaleFactor(initialPageScaleFactor);
1991 ASSERT_EQ(viewportSize, webViewHelper.webViewImpl()->size());
1992 ASSERT_EQ(initialPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor());
1993 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.height, viewportSize.width));
1994 float expectedPageScaleFactor = initialPageScaleFactor * (shouldScaleRelativeToViewportWidth ? 1 / aspectRatio : 1);
1995 EXPECT_NEAR(expectedPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor(), 0.05f);
1996 EXPECT_EQ(WebSize(), webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
1999 // Resizing just the height should not affect pageScaleFactor or scrollOffset.
2001 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height));
2002 webViewHelper.webViewImpl()->setPageScaleFactor(initialPageScaleFactor);
2003 webViewHelper.webViewImpl()->setMainFrameScrollOffset(WebPoint(scrollOffset.width, scrollOffset.height));
2004 webViewHelper.webViewImpl()->layout();
2005 const WebSize expectedScrollOffset = webViewHelper.webViewImpl()->mainFrame()->scrollOffset();
2006 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height * 0.8f));
2007 EXPECT_EQ(initialPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor());
2008 EXPECT_EQ(expectedScrollOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
2009 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height * 0.8f));
2010 EXPECT_EQ(initialPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor());
2011 EXPECT_EQ(expectedScrollOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
2014 // Generic resize preserves scrollOffset relative to anchor node located
2015 // the top center of the screen.
2017 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.height, viewportSize.width));
2018 float pageScaleFactor = webViewHelper.webViewImpl()->pageScaleFactor();
2019 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height));
2020 float expectedPageScaleFactor = pageScaleFactor * (shouldScaleRelativeToViewportWidth ? aspectRatio : 1);
2021 EXPECT_NEAR(expectedPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor(), 0.05f);
2022 webViewHelper.webViewImpl()->mainFrame()->setScrollOffset(scrollOffset);
2024 WebCore::IntPoint anchorPoint = WebCore::IntPoint(scrollOffset) + WebCore::IntPoint(viewportSize.width / 2, 0);
2025 RefPtr<WebCore::Node> anchorNode = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->eventHandler().hitTestResultAtPoint(anchorPoint, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent).innerNode();
2028 pageScaleFactor = webViewHelper.webViewImpl()->pageScaleFactor();
2029 const WebCore::FloatSize preResizeRelativeOffset
2030 = computeRelativeOffset(anchorPoint, anchorNode->boundingBox());
2031 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.height, viewportSize.width));
2032 WebCore::IntPoint newAnchorPoint = WebCore::IntPoint(webViewHelper.webViewImpl()->mainFrame()->scrollOffset()) + WebCore::IntPoint(viewportSize.height / 2, 0);
2033 const WebCore::FloatSize postResizeRelativeOffset
2034 = computeRelativeOffset(newAnchorPoint, anchorNode->boundingBox());
2035 EXPECT_NEAR(preResizeRelativeOffset.width(), postResizeRelativeOffset.width(), 0.15f);
2036 expectedPageScaleFactor = pageScaleFactor * (shouldScaleRelativeToViewportWidth ? 1 / aspectRatio : 1);
2037 EXPECT_NEAR(expectedPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor(), 0.05f);
2042 TEST_F(WebFrameResizeTest, ResizeYieldsCorrectScrollAndScaleForWidthEqualsDeviceWidth)
2044 // With width=device-width, pageScaleFactor is preserved across resizes as
2045 // long as the content adjusts according to the device-width.
2046 const char* url = "resize_scroll_mobile.html";
2047 const float initialPageScaleFactor = 1;
2048 const WebSize scrollOffset(0, 50);
2049 const WebSize viewportSize(120, 160);
2050 const bool shouldScaleRelativeToViewportWidth = true;
2052 testResizeYieldsCorrectScrollAndScale(
2053 url, initialPageScaleFactor, scrollOffset, viewportSize, shouldScaleRelativeToViewportWidth);
2056 TEST_F(WebFrameResizeTest, ResizeYieldsCorrectScrollAndScaleForFixedWidth)
2058 // With a fixed width, pageScaleFactor scales by the relative change in viewport width.
2059 const char* url = "resize_scroll_fixed_width.html";
2060 const float initialPageScaleFactor = 2;
2061 const WebSize scrollOffset(0, 200);
2062 const WebSize viewportSize(240, 320);
2063 const bool shouldScaleRelativeToViewportWidth = true;
2065 testResizeYieldsCorrectScrollAndScale(
2066 url, initialPageScaleFactor, scrollOffset, viewportSize, shouldScaleRelativeToViewportWidth);
2069 TEST_F(WebFrameResizeTest, ResizeYieldsCorrectScrollAndScaleForFixedLayout)
2071 // With a fixed layout, pageScaleFactor scales by the relative change in viewport width.
2072 const char* url = "resize_scroll_fixed_layout.html";
2073 const float initialPageScaleFactor = 2;
2074 const WebSize scrollOffset(200, 400);
2075 const WebSize viewportSize(320, 240);
2076 const bool shouldScaleRelativeToViewportWidth = true;
2078 testResizeYieldsCorrectScrollAndScale(
2079 url, initialPageScaleFactor, scrollOffset, viewportSize, shouldScaleRelativeToViewportWidth);
2082 TEST_F(WebFrameTest, pageScaleFactorScalesPaintClip)
2084 UseMockScrollbarSettings mockScrollbarSettings;
2085 registerMockedHttpURLLoad("large-div.html");
2087 FixedLayoutTestWebViewClient client;
2088 client.m_screenInfo.deviceScaleFactor = 1;
2089 int viewportWidth = 50;
2090 int viewportHeight = 50;
2092 FrameTestHelpers::WebViewHelper webViewHelper;
2093 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client);
2094 // FIXME: This test breaks if the viewport is enabled before loading the page due to the paint
2095 // calls below not working on composited layers. For some reason, enabling the viewport here
2096 // doesn't cause compositing
2097 webViewHelper.webView()->settings()->setViewportEnabled(true);
2098 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2099 webViewHelper.webView()->layout();
2101 // Set <1 page scale so that the clip rect should be larger than
2102 // the viewport size as passed into resize().
2103 webViewHelper.webView()->setPageScaleFactor(0.5);
2106 ASSERT_TRUE(bitmap.allocN32Pixels(200, 200));
2107 bitmap.eraseColor(0);
2108 SkCanvas canvas(bitmap);
2110 WebCore::GraphicsContext context(&canvas);
2111 context.setTrackOpaqueRegion(true);
2113 EXPECT_EQ_RECT(WebCore::IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
2115 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
2116 WebCore::IntRect paintRect(0, 0, 200, 200);
2117 view->paint(&context, paintRect);
2119 // FIXME: This test broke in release builds when changing the FixedLayoutTestWebViewClient
2120 // to return a non-null layerTreeView, which is what all our shipping configurations do,
2121 // so this is just exposing an existing bug.
2124 int viewportWidthMinusScrollbar = 50 - (view->verticalScrollbar()->isOverlayScrollbar() ? 0 : 15);
2125 int viewportHeightMinusScrollbar = 50 - (view->horizontalScrollbar()->isOverlayScrollbar() ? 0 : 15);
2126 WebCore::IntRect clippedRect(0, 0, viewportWidthMinusScrollbar * 2, viewportHeightMinusScrollbar * 2);
2127 EXPECT_EQ_RECT(clippedRect, context.opaqueRegion().asRect());
2131 TEST_F(WebFrameTest, pageScaleFactorUpdatesScrollbars)
2133 UseMockScrollbarSettings mockScrollbarSettings;
2134 registerMockedHttpURLLoad("fixed_layout.html");
2136 FixedLayoutTestWebViewClient client;
2137 client.m_screenInfo.deviceScaleFactor = 1;
2138 int viewportWidth = 640;
2139 int viewportHeight = 480;
2141 FrameTestHelpers::WebViewHelper webViewHelper;
2142 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
2143 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2144 webViewHelper.webView()->layout();
2146 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
2147 EXPECT_EQ(view->scrollSize(WebCore::HorizontalScrollbar), view->contentsSize().width() - view->visibleContentRect().width());
2148 EXPECT_EQ(view->scrollSize(WebCore::VerticalScrollbar), view->contentsSize().height() - view->visibleContentRect().height());
2150 webViewHelper.webView()->setPageScaleFactor(10);
2152 EXPECT_EQ(view->scrollSize(WebCore::HorizontalScrollbar), view->contentsSize().width() - view->visibleContentRect().width());
2153 EXPECT_EQ(view->scrollSize(WebCore::VerticalScrollbar), view->contentsSize().height() - view->visibleContentRect().height());
2156 TEST_F(WebFrameTest, CanOverrideScaleLimits)
2158 UseMockScrollbarSettings mockScrollbarSettings;
2160 registerMockedHttpURLLoad("no_scale_for_you.html");
2162 FixedLayoutTestWebViewClient client;
2163 client.m_screenInfo.deviceScaleFactor = 1;
2164 int viewportWidth = 640;
2165 int viewportHeight = 480;
2167 FrameTestHelpers::WebViewHelper webViewHelper;
2168 webViewHelper.initializeAndLoad(m_baseURL + "no_scale_for_you.html", true, 0, &client, enableViewportSettings);
2169 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2171 EXPECT_EQ(2.0f, webViewHelper.webView()->minimumPageScaleFactor());
2172 EXPECT_EQ(2.0f, webViewHelper.webView()->maximumPageScaleFactor());
2174 webViewHelper.webView()->setIgnoreViewportTagScaleLimits(true);
2175 webViewHelper.webView()->layout();
2177 EXPECT_EQ(1.0f, webViewHelper.webView()->minimumPageScaleFactor());
2178 EXPECT_EQ(5.0f, webViewHelper.webView()->maximumPageScaleFactor());
2180 webViewHelper.webView()->setIgnoreViewportTagScaleLimits(false);
2181 webViewHelper.webView()->layout();
2183 EXPECT_EQ(2.0f, webViewHelper.webView()->minimumPageScaleFactor());
2184 EXPECT_EQ(2.0f, webViewHelper.webView()->maximumPageScaleFactor());
2187 TEST_F(WebFrameTest, updateOverlayScrollbarLayers)
2189 UseMockScrollbarSettings mockScrollbarSettings;
2191 registerMockedHttpURLLoad("large-div.html");
2193 int viewWidth = 500;
2194 int viewHeight = 500;
2196 OwnPtr<FakeCompositingWebViewClient> fakeCompositingWebViewClient = adoptPtr(new FakeCompositingWebViewClient());
2197 FrameTestHelpers::WebViewHelper webViewHelper;
2198 webViewHelper.initialize(true, 0, fakeCompositingWebViewClient.get(), &configueCompositingWebView);
2200 webViewHelper.webView()->resize(WebSize(viewWidth, viewHeight));
2201 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "large-div.html");
2202 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
2203 webViewHelper.webView()->layout();
2205 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
2206 EXPECT_TRUE(view->renderView()->compositor()->layerForHorizontalScrollbar());
2207 EXPECT_TRUE(view->renderView()->compositor()->layerForVerticalScrollbar());
2209 webViewHelper.webView()->resize(WebSize(viewWidth * 10, viewHeight * 10));
2210 webViewHelper.webView()->layout();
2211 EXPECT_FALSE(view->renderView()->compositor()->layerForHorizontalScrollbar());
2212 EXPECT_FALSE(view->renderView()->compositor()->layerForVerticalScrollbar());
2215 void setScaleAndScrollAndLayout(blink::WebView* webView, WebPoint scroll, float scale)
2217 webView->setPageScaleFactor(scale);
2218 webView->setMainFrameScrollOffset(WebPoint(scroll.x, scroll.y));
2222 TEST_F(WebFrameTest, DivAutoZoomParamsTest)
2224 registerMockedHttpURLLoad("get_scale_for_auto_zoom_into_div_test.html");
2226 const float deviceScaleFactor = 2.0f;
2227 int viewportWidth = 640 / deviceScaleFactor;
2228 int viewportHeight = 1280 / deviceScaleFactor;
2229 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2230 FrameTestHelpers::WebViewHelper webViewHelper;
2231 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_for_auto_zoom_into_div_test.html");
2232 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2233 webViewHelper.webView()->setPageScaleFactorLimits(0.01f, 4);
2234 webViewHelper.webView()->setPageScaleFactor(0.5f);
2235 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2236 webViewHelper.webView()->layout();
2238 WebRect wideDiv(200, 100, 400, 150);
2239 WebRect tallDiv(200, 300, 400, 800);
2240 WebRect doubleTapPointWide(wideDiv.x + 50, wideDiv.y + 50, touchPointPadding, touchPointPadding);
2241 WebRect doubleTapPointTall(tallDiv.x + 50, tallDiv.y + 50, touchPointPadding, touchPointPadding);
2242 WebRect wideBlockBounds;
2243 WebRect tallBlockBounds;
2247 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2249 // Test double-tap zooming into wide div.
2250 wideBlockBounds = webViewHelper.webViewImpl()->computeBlockBounds(doubleTapPointWide, false);
2251 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(doubleTapPointWide.x, doubleTapPointWide.y), wideBlockBounds, touchPointPadding, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2252 // The div should horizontally fill the screen (modulo margins), and
2253 // vertically centered (modulo integer rounding).
2254 EXPECT_NEAR(viewportWidth / (float) wideDiv.width, scale, 0.1);
2255 EXPECT_NEAR(wideDiv.x, scroll.x, 20);
2256 EXPECT_EQ(0, scroll.y);
2258 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), scroll, scale);
2260 // Test zoom out back to minimum scale.
2261 wideBlockBounds = webViewHelper.webViewImpl()->computeBlockBounds(doubleTapPointWide, false);
2262 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(doubleTapPointWide.x, doubleTapPointWide.y), wideBlockBounds, touchPointPadding, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2264 scale = webViewHelper.webViewImpl()->minimumPageScaleFactor();
2265 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), scale);
2267 // Test double-tap zooming into tall div.
2268 tallBlockBounds = webViewHelper.webViewImpl()->computeBlockBounds(doubleTapPointTall, false);
2269 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(doubleTapPointTall.x, doubleTapPointTall.y), tallBlockBounds, touchPointPadding, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2270 // The div should start at the top left of the viewport.
2271 EXPECT_NEAR(viewportWidth / (float) tallDiv.width, scale, 0.1);
2272 EXPECT_NEAR(tallDiv.x, scroll.x, 20);
2273 EXPECT_NEAR(tallDiv.y, scroll.y, 20);
2275 // Test for Non-doubletap scaling
2276 // Test zooming into div.
2277 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(250, 250), webViewHelper.webViewImpl()->computeBlockBounds(WebRect(250, 250, 10, 10), true), 0, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2278 EXPECT_NEAR(viewportWidth / (float) wideDiv.width, scale, 0.1);
2281 void simulatePageScale(WebViewImpl* webViewImpl, float& scale)
2283 WebCore::IntSize scrollDelta = webViewImpl->fakePageScaleAnimationTargetPositionForTesting() - webViewImpl->mainFrameImpl()->frameView()->scrollPosition();
2284 float scaleDelta = webViewImpl->fakePageScaleAnimationPageScaleForTesting() / webViewImpl->pageScaleFactor();
2285 webViewImpl->applyScrollAndScale(scrollDelta, scaleDelta);
2286 scale = webViewImpl->pageScaleFactor();
2289 void simulateMultiTargetZoom(WebViewImpl* webViewImpl, const WebRect& rect, float& scale)
2291 if (webViewImpl->zoomToMultipleTargetsRect(rect))
2292 simulatePageScale(webViewImpl, scale);
2295 void simulateDoubleTap(WebViewImpl* webViewImpl, WebPoint& point, float& scale)
2297 webViewImpl->animateDoubleTapZoom(point);
2298 EXPECT_TRUE(webViewImpl->fakeDoubleTapAnimationPendingForTesting());
2299 simulatePageScale(webViewImpl, scale);
2302 TEST_F(WebFrameTest, DivAutoZoomWideDivTest)
2304 registerMockedHttpURLLoad("get_wide_div_for_auto_zoom_test.html");
2306 const float deviceScaleFactor = 2.0f;
2307 int viewportWidth = 640 / deviceScaleFactor;
2308 int viewportHeight = 1280 / deviceScaleFactor;
2309 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2310 FrameTestHelpers::WebViewHelper webViewHelper;
2311 webViewHelper.initializeAndLoad(m_baseURL + "get_wide_div_for_auto_zoom_test.html");
2312 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2313 webViewHelper.webView()->setPageScaleFactorLimits(1.0f, 4);
2314 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2315 webViewHelper.webView()->setPageScaleFactor(1.0f);
2316 webViewHelper.webView()->layout();
2318 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2320 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2322 WebRect div(0, 100, viewportWidth, 150);
2323 WebPoint point(div.x + 50, div.y + 50);
2325 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2327 simulateDoubleTap(webViewHelper.webViewImpl(), point, scale);
2328 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2329 simulateDoubleTap(webViewHelper.webViewImpl(), point, scale);
2330 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2333 TEST_F(WebFrameTest, DivAutoZoomVeryTallTest)
2335 // When a block is taller than the viewport and a zoom targets a lower part
2336 // of it, then we should keep the target point onscreen instead of snapping
2337 // back up the top of the block.
2338 registerMockedHttpURLLoad("very_tall_div.html");
2340 const float deviceScaleFactor = 2.0f;
2341 int viewportWidth = 640 / deviceScaleFactor;
2342 int viewportHeight = 1280 / deviceScaleFactor;
2343 FrameTestHelpers::WebViewHelper webViewHelper;
2344 webViewHelper.initializeAndLoad(m_baseURL + "very_tall_div.html", true, 0, 0, enableViewportSettings);
2345 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2346 webViewHelper.webView()->setPageScaleFactorLimits(1.0f, 4);
2347 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2348 webViewHelper.webView()->setPageScaleFactor(1.0f);
2349 webViewHelper.webView()->layout();
2351 WebRect div(200, 300, 400, 5000);
2352 WebPoint point(div.x + 50, div.y + 3000);
2356 WebRect blockBounds = webViewHelper.webViewImpl()->computeBlockBounds(WebRect(point.x, point.y, 0, 0), true);
2357 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(point, blockBounds, 0, 1.0f, scale, scroll);
2358 EXPECT_EQ(scale, 1.0f);
2359 EXPECT_EQ(scroll.y, 2660);
2362 TEST_F(WebFrameTest, DivAutoZoomMultipleDivsTest)
2364 registerMockedHttpURLLoad("get_multiple_divs_for_auto_zoom_test.html");
2366 const float deviceScaleFactor = 2.0f;
2367 int viewportWidth = 640 / deviceScaleFactor;
2368 int viewportHeight = 1280 / deviceScaleFactor;
2369 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2370 FrameTestHelpers::WebViewHelper webViewHelper;
2371 webViewHelper.initializeAndLoad(m_baseURL + "get_multiple_divs_for_auto_zoom_test.html");
2372 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2373 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2374 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2375 webViewHelper.webView()->setPageScaleFactor(0.5f);
2376 webViewHelper.webView()->layout();
2378 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2380 WebRect topDiv(200, 100, 200, 150);
2381 WebRect bottomDiv(200, 300, 200, 150);
2382 WebPoint topPoint(topDiv.x + 50, topDiv.y + 50);
2383 WebPoint bottomPoint(bottomDiv.x + 50, bottomDiv.y + 50);
2385 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2387 // Test double tap on two different divs
2388 // After first zoom, we should go back to minimum page scale with a second double tap.
2389 simulateDoubleTap(webViewHelper.webViewImpl(), topPoint, scale);
2390 EXPECT_FLOAT_EQ(1, scale);
2391 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2392 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2394 // If the user pinch zooms after double tap, a second double tap should zoom back to the div.
2395 simulateDoubleTap(webViewHelper.webViewImpl(), topPoint, scale);
2396 EXPECT_FLOAT_EQ(1, scale);
2397 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 0.6f);
2398 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2399 EXPECT_FLOAT_EQ(1, scale);
2400 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2401 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2403 // If we didn't yet get an auto-zoom update and a second double-tap arrives, should go back to minimum scale.
2404 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2405 webViewHelper.webViewImpl()->animateDoubleTapZoom(topPoint);
2406 EXPECT_TRUE(webViewHelper.webViewImpl()->fakeDoubleTapAnimationPendingForTesting());
2407 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2408 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2411 TEST_F(WebFrameTest, DivAutoZoomScaleBoundsTest)
2413 registerMockedHttpURLLoad("get_scale_bounds_check_for_auto_zoom_test.html");
2415 int viewportWidth = 320;
2416 int viewportHeight = 480;
2417 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2418 FrameTestHelpers::WebViewHelper webViewHelper;
2419 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_bounds_check_for_auto_zoom_test.html");
2420 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2421 webViewHelper.webView()->setDeviceScaleFactor(1.5f);
2422 webViewHelper.webView()->layout();
2424 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2426 WebRect div(200, 100, 200, 150);
2427 WebPoint doubleTapPoint(div.x + 50, div.y + 50);
2430 // Test double tap scale bounds.
2431 // minimumPageScale < doubleTapZoomAlreadyLegibleScale < 1
2432 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2433 webViewHelper.webView()->layout();
2434 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2435 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2436 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2437 EXPECT_FLOAT_EQ(1, scale);
2438 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2439 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2440 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2441 EXPECT_FLOAT_EQ(1, scale);
2443 // Zoom in to reset double_tap_zoom_in_effect flag.
2444 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2445 // 1 < minimumPageScale < doubleTapZoomAlreadyLegibleScale
2446 webViewHelper.webView()->setPageScaleFactorLimits(1.1f, 4);
2447 webViewHelper.webView()->layout();
2448 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2449 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2450 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2451 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2452 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2453 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2454 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2455 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2457 // Zoom in to reset double_tap_zoom_in_effect flag.
2458 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2459 // minimumPageScale < 1 < doubleTapZoomAlreadyLegibleScale
2460 webViewHelper.webView()->setPageScaleFactorLimits(0.95f, 4);
2461 webViewHelper.webView()->layout();
2462 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2463 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2464 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2465 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2466 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2467 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2468 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2469 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2472 TEST_F(WebFrameTest, DivAutoZoomScaleFontScaleFactorTest)
2474 registerMockedHttpURLLoad("get_scale_bounds_check_for_auto_zoom_test.html");
2476 int viewportWidth = 320;
2477 int viewportHeight = 480;
2478 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2479 float accessibilityFontScaleFactor = 1.13f;
2480 FrameTestHelpers::WebViewHelper webViewHelper;
2481 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_bounds_check_for_auto_zoom_test.html");
2482 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2483 webViewHelper.webView()->layout();
2485 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2486 webViewHelper.webViewImpl()->page()->settings().setTextAutosizingEnabled(true);
2487 webViewHelper.webViewImpl()->page()->settings().setAccessibilityFontScaleFactor(accessibilityFontScaleFactor);
2489 WebRect div(200, 100, 200, 150);
2490 WebPoint doubleTapPoint(div.x + 50, div.y + 50);
2493 // Test double tap scale bounds.
2494 // minimumPageScale < doubleTapZoomAlreadyLegibleScale < 1 < accessibilityFontScaleFactor
2495 float legibleScale = accessibilityFontScaleFactor;
2496 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2497 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2498 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2499 webViewHelper.webView()->layout();
2500 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2501 EXPECT_FLOAT_EQ(legibleScale, scale);
2502 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2503 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2504 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2505 EXPECT_FLOAT_EQ(legibleScale, scale);
2507 // Zoom in to reset double_tap_zoom_in_effect flag.
2508 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2509 // 1 < accessibilityFontScaleFactor < minimumPageScale < doubleTapZoomAlreadyLegibleScale
2510 webViewHelper.webView()->setPageScaleFactorLimits(1.0f, 4);
2511 webViewHelper.webView()->layout();
2512 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2513 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2514 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2515 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2516 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2517 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2518 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2519 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2521 // Zoom in to reset double_tap_zoom_in_effect flag.
2522 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2523 // minimumPageScale < 1 < accessibilityFontScaleFactor < doubleTapZoomAlreadyLegibleScale
2524 webViewHelper.webView()->setPageScaleFactorLimits(0.95f, 4);
2525 webViewHelper.webView()->layout();
2526 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2527 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2528 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2529 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2530 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2531 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2532 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2533 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2535 // Zoom in to reset double_tap_zoom_in_effect flag.
2536 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2537 // minimumPageScale < 1 < doubleTapZoomAlreadyLegibleScale < accessibilityFontScaleFactor
2538 webViewHelper.webView()->setPageScaleFactorLimits(0.9f, 4);
2539 webViewHelper.webView()->layout();
2540 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2541 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2542 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2543 EXPECT_FLOAT_EQ(legibleScale, scale);
2544 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2545 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2546 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2547 EXPECT_FLOAT_EQ(legibleScale, scale);
2550 TEST_F(WebFrameTest, DivMultipleTargetZoomMultipleDivsTest)
2552 registerMockedHttpURLLoad("get_multiple_divs_for_auto_zoom_test.html");
2554 const float deviceScaleFactor = 2.0f;
2555 int viewportWidth = 640 / deviceScaleFactor;
2556 int viewportHeight = 1280 / deviceScaleFactor;
2557 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2558 FrameTestHelpers::WebViewHelper webViewHelper;
2559 webViewHelper.initializeAndLoad(m_baseURL + "get_multiple_divs_for_auto_zoom_test.html");
2560 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2561 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2562 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2563 webViewHelper.webView()->setPageScaleFactor(0.5f);
2564 webViewHelper.webView()->layout();
2566 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2568 WebRect viewportRect(0, 0, viewportWidth, viewportHeight);
2569 WebRect topDiv(200, 100, 200, 150);
2570 WebRect bottomDiv(200, 300, 200, 150);
2572 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2574 simulateMultiTargetZoom(webViewHelper.webViewImpl(), topDiv, scale);
2575 EXPECT_FLOAT_EQ(1, scale);
2576 simulateMultiTargetZoom(webViewHelper.webViewImpl(), bottomDiv, scale);
2577 EXPECT_FLOAT_EQ(1, scale);
2578 simulateMultiTargetZoom(webViewHelper.webViewImpl(), viewportRect, scale);
2579 EXPECT_FLOAT_EQ(1, scale);
2580 webViewHelper.webViewImpl()->setPageScaleFactor(webViewHelper.webViewImpl()->minimumPageScaleFactor());
2581 simulateMultiTargetZoom(webViewHelper.webViewImpl(), topDiv, scale);
2582 EXPECT_FLOAT_EQ(1, scale);
2585 TEST_F(WebFrameTest, DivScrollIntoEditableTest)
2587 registerMockedHttpURLLoad("get_scale_for_zoom_into_editable_test.html");
2589 int viewportWidth = 450;
2590 int viewportHeight = 300;
2591 float leftBoxRatio = 0.3f;
2592 int caretPadding = 10;
2593 float minReadableCaretHeight = 18.0f;
2594 FrameTestHelpers::WebViewHelper webViewHelper;
2595 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_for_zoom_into_editable_test.html");
2596 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2597 webViewHelper.webView()->setPageScaleFactorLimits(1, 4);
2598 webViewHelper.webView()->layout();
2599 webViewHelper.webView()->setDeviceScaleFactor(1.5f);
2600 webViewHelper.webView()->settings()->setAutoZoomFocusedNodeToLegibleScale(true);
2602 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2604 WebRect editBoxWithText(200, 200, 250, 20);
2605 WebRect editBoxWithNoText(200, 250, 250, 20);
2607 // Test scrolling the focused node
2608 // The edit box is shorter and narrower than the viewport when legible.
2609 webViewHelper.webView()->advanceFocus(false);
2610 // Set the caret to the end of the input box.
2611 webViewHelper.webView()->mainFrame()->document().getElementById("EditBoxWithText").to<WebInputElement>().setSelectionRange(1000, 1000);
2612 setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), 1);
2613 WebRect rect, caret;
2614 webViewHelper.webViewImpl()->selectionBounds(caret, rect);
2617 WebCore::IntPoint scroll;
2619 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2620 EXPECT_TRUE(needAnimation);
2621 // The edit box should be left aligned with a margin for possible label.
2622 int hScroll = editBoxWithText.x - leftBoxRatio * viewportWidth / scale;
2623 EXPECT_NEAR(hScroll, scroll.x(), 1);
2624 int vScroll = editBoxWithText.y - (viewportHeight / scale - editBoxWithText.height) / 2;
2625 EXPECT_NEAR(vScroll, scroll.y(), 1);
2626 EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1);
2628 // The edit box is wider than the viewport when legible.
2629 viewportWidth = 200;
2630 viewportHeight = 150;
2631 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2632 setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), 1);
2633 webViewHelper.webViewImpl()->selectionBounds(caret, rect);
2634 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2635 EXPECT_TRUE(needAnimation);
2636 // The caret should be right aligned since the caret would be offscreen when the edit box is left aligned.
2637 hScroll = caret.x + caret.width + caretPadding - viewportWidth / scale;
2638 EXPECT_NEAR(hScroll, scroll.x(), 1);
2639 EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1);
2641 setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), 1);
2642 // Move focus to edit box with text.
2643 webViewHelper.webView()->advanceFocus(false);
2644 webViewHelper.webViewImpl()->selectionBounds(caret, rect);
2645 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2646 EXPECT_TRUE(needAnimation);
2647 // The edit box should be left aligned.
2648 hScroll = editBoxWithNoText.x;
2649 EXPECT_NEAR(hScroll, scroll.x(), 1);
2650 vScroll = editBoxWithNoText.y - (viewportHeight / scale - editBoxWithNoText.height) / 2;
2651 EXPECT_NEAR(vScroll, scroll.y(), 1);
2652 EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1);
2654 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), scroll, scale);
2656 // Move focus back to the first edit box.
2657 webViewHelper.webView()->advanceFocus(true);
2658 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2659 // The position should have stayed the same since this box was already on screen with the right scale.
2660 EXPECT_FALSE(needAnimation);
2663 class TestReloadDoesntRedirectWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
2665 virtual WebNavigationPolicy decidePolicyForNavigation(
2666 WebLocalFrame*, WebDataSource::ExtraData*, const WebURLRequest&, WebNavigationType,
2667 WebNavigationPolicy defaultPolicy, bool isRedirect) OVERRIDE
2669 EXPECT_FALSE(isRedirect);
2670 return WebNavigationPolicyCurrentTab;
2674 TEST_F(WebFrameTest, ReloadDoesntSetRedirect)
2676 // Test for case in http://crbug.com/73104. Reloading a frame very quickly
2677 // would sometimes call decidePolicyForNavigation with isRedirect=true
2678 registerMockedHttpURLLoad("form.html");
2680 TestReloadDoesntRedirectWebFrameClient webFrameClient;
2681 FrameTestHelpers::WebViewHelper webViewHelper;
2682 webViewHelper.initializeAndLoad(m_baseURL + "form.html", false, &webFrameClient);
2684 webViewHelper.webView()->mainFrame()->reload(true);
2685 // start reload before request is delivered.
2686 webViewHelper.webView()->mainFrame()->reload(true);
2687 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
2690 TEST_F(WebFrameTest, ReloadWithOverrideURLPreservesState)
2692 const std::string firstURL = "find.html";
2693 const std::string secondURL = "form.html";
2694 const std::string thirdURL = "history.html";
2695 const float pageScaleFactor = 1.1684f;
2696 const int pageWidth = 640;
2697 const int pageHeight = 480;
2699 registerMockedHttpURLLoad(firstURL);
2700 registerMockedHttpURLLoad(secondURL);
2701 registerMockedHttpURLLoad(thirdURL);
2703 FrameTestHelpers::WebViewHelper webViewHelper;
2704 webViewHelper.initializeAndLoad(m_baseURL + firstURL, true);
2705 webViewHelper.webViewImpl()->resize(WebSize(pageWidth, pageHeight));
2706 webViewHelper.webViewImpl()->mainFrame()->setScrollOffset(WebSize(pageWidth / 4, pageHeight / 4));
2707 webViewHelper.webViewImpl()->setPageScaleFactor(pageScaleFactor);
2709 WebSize previousOffset = webViewHelper.webViewImpl()->mainFrame()->scrollOffset();
2710 float previousScale = webViewHelper.webViewImpl()->pageScaleFactor();
2712 // Reload the page using the cache.
2713 webViewHelper.webViewImpl()->mainFrame()->reloadWithOverrideURL(toKURL(m_baseURL + secondURL), false);
2714 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
2715 ASSERT_EQ(previousOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
2716 ASSERT_EQ(previousScale, webViewHelper.webViewImpl()->pageScaleFactor());
2718 // Reload the page while ignoring the cache.
2719 webViewHelper.webViewImpl()->mainFrame()->reloadWithOverrideURL(toKURL(m_baseURL + thirdURL), true);
2720 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
2721 ASSERT_EQ(previousOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
2722 ASSERT_EQ(previousScale, webViewHelper.webViewImpl()->pageScaleFactor());
2725 TEST_F(WebFrameTest, ReloadWhileProvisional)
2727 // Test that reloading while the previous load is still pending does not cause the initial
2728 // request to get lost.
2729 registerMockedHttpURLLoad("fixed_layout.html");
2731 FrameTestHelpers::WebViewHelper webViewHelper;
2732 webViewHelper.initialize();
2733 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "fixed_layout.html");
2734 // start reload before first request is delivered.
2735 webViewHelper.webView()->mainFrame()->reload(true);
2737 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
2739 WebDataSource* dataSource = webViewHelper.webView()->mainFrame()->dataSource();
2740 ASSERT_TRUE(dataSource);
2741 EXPECT_EQ(toKURL(m_baseURL + "fixed_layout.html"), toKURL(dataSource->request().url().spec()));
2744 TEST_F(WebFrameTest, AppendRedirects)
2746 const std::string firstURL = "about:blank";
2747 const std::string secondURL = "http://www.test.com";
2749 FrameTestHelpers::WebViewHelper webViewHelper;
2750 webViewHelper.initializeAndLoad(firstURL, true);
2752 WebDataSource* dataSource = webViewHelper.webView()->mainFrame()->dataSource();
2753 ASSERT_TRUE(dataSource);
2754 dataSource->appendRedirect(toKURL(secondURL));
2756 WebVector<WebURL> redirects;
2757 dataSource->redirectChain(redirects);
2758 ASSERT_EQ(2U, redirects.size());
2759 EXPECT_EQ(toKURL(firstURL), toKURL(redirects[0].spec().data()));
2760 EXPECT_EQ(toKURL(secondURL), toKURL(redirects[1].spec().data()));
2763 TEST_F(WebFrameTest, IframeRedirect)
2765 registerMockedHttpURLLoad("iframe_redirect.html");
2766 registerMockedHttpURLLoad("visible_iframe.html");
2768 FrameTestHelpers::WebViewHelper webViewHelper;
2769 webViewHelper.initializeAndLoad(m_baseURL + "iframe_redirect.html", true);
2770 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); // Load the iframe.
2772 WebFrame* iframe = webViewHelper.webView()->findFrameByName(WebString::fromUTF8("ifr"));
2773 ASSERT_TRUE(iframe);
2774 WebDataSource* iframeDataSource = iframe->dataSource();
2775 ASSERT_TRUE(iframeDataSource);
2776 WebVector<WebURL> redirects;
2777 iframeDataSource->redirectChain(redirects);
2778 ASSERT_EQ(2U, redirects.size());
2779 EXPECT_EQ(toKURL("about:blank"), toKURL(redirects[0].spec().data()));
2780 EXPECT_EQ(toKURL("http://www.test.com/visible_iframe.html"), toKURL(redirects[1].spec().data()));
2783 TEST_F(WebFrameTest, ClearFocusedNodeTest)
2785 registerMockedHttpURLLoad("iframe_clear_focused_node_test.html");
2786 registerMockedHttpURLLoad("autofocus_input_field_iframe.html");
2788 FrameTestHelpers::WebViewHelper webViewHelper;
2789 webViewHelper.initializeAndLoad(m_baseURL + "iframe_clear_focused_node_test.html", true);
2791 // Clear the focused node.
2792 webViewHelper.webView()->clearFocusedElement();
2794 // Now retrieve the FocusedNode and test it should be null.
2795 EXPECT_EQ(0, webViewHelper.webViewImpl()->focusedElement());
2798 // Implementation of WebFrameClient that tracks the v8 contexts that are created
2799 // and destroyed for verification.
2800 class ContextLifetimeTestWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
2802 struct Notification {
2804 Notification(WebLocalFrame* frame, v8::Handle<v8::Context> context, int worldId)
2806 , context(context->GetIsolate(), context)
2816 bool Equals(Notification* other)
2818 return other && frame == other->frame && context == other->context && worldId == other->worldId;
2821 WebLocalFrame* frame;
2822 v8::Persistent<v8::Context> context;
2826 virtual ~ContextLifetimeTestWebFrameClient()
2833 for (size_t i = 0; i < createNotifications.size(); ++i)
2834 delete createNotifications[i];
2836 for (size_t i = 0; i < releaseNotifications.size(); ++i)
2837 delete releaseNotifications[i];
2839 createNotifications.clear();
2840 releaseNotifications.clear();
2843 std::vector<Notification*> createNotifications;
2844 std::vector<Notification*> releaseNotifications;
2847 virtual void didCreateScriptContext(WebLocalFrame* frame, v8::Handle<v8::Context> context, int extensionGroup, int worldId) OVERRIDE
2849 createNotifications.push_back(new Notification(frame, context, worldId));
2852 virtual void willReleaseScriptContext(WebLocalFrame* frame, v8::Handle<v8::Context> context, int worldId) OVERRIDE
2854 releaseNotifications.push_back(new Notification(frame, context, worldId));
2858 // TODO(aa): Deflake this test.
2859 TEST_F(WebFrameTest, FLAKY_ContextNotificationsLoadUnload)
2861 v8::HandleScope handleScope(v8::Isolate::GetCurrent());
2863 registerMockedHttpURLLoad("context_notifications_test.html");
2864 registerMockedHttpURLLoad("context_notifications_test_frame.html");
2866 // Load a frame with an iframe, make sure we get the right create notifications.
2867 ContextLifetimeTestWebFrameClient webFrameClient;
2868 FrameTestHelpers::WebViewHelper webViewHelper;
2869 webViewHelper.initializeAndLoad(m_baseURL + "context_notifications_test.html", true, &webFrameClient);
2871 WebFrame* mainFrame = webViewHelper.webView()->mainFrame();
2872 WebFrame* childFrame = mainFrame->firstChild();
2874 ASSERT_EQ(2u, webFrameClient.createNotifications.size());
2875 EXPECT_EQ(0u, webFrameClient.releaseNotifications.size());
2877 ContextLifetimeTestWebFrameClient::Notification* firstCreateNotification = webFrameClient.createNotifications[0];
2878 ContextLifetimeTestWebFrameClient::Notification* secondCreateNotification = webFrameClient.createNotifications[1];
2880 EXPECT_EQ(mainFrame, firstCreateNotification->frame);
2881 EXPECT_EQ(mainFrame->mainWorldScriptContext(), firstCreateNotification->context);
2882 EXPECT_EQ(0, firstCreateNotification->worldId);
2884 EXPECT_EQ(childFrame, secondCreateNotification->frame);
2885 EXPECT_EQ(childFrame->mainWorldScriptContext(), secondCreateNotification->context);
2886 EXPECT_EQ(0, secondCreateNotification->worldId);
2888 // Close the view. We should get two release notifications that are exactly the same as the create ones, in reverse order.
2889 webViewHelper.reset();
2891 ASSERT_EQ(2u, webFrameClient.releaseNotifications.size());
2892 ContextLifetimeTestWebFrameClient::Notification* firstReleaseNotification = webFrameClient.releaseNotifications[0];
2893 ContextLifetimeTestWebFrameClient::Notification* secondReleaseNotification = webFrameClient.releaseNotifications[1];
2895 ASSERT_TRUE(firstCreateNotification->Equals(secondReleaseNotification));
2896 ASSERT_TRUE(secondCreateNotification->Equals(firstReleaseNotification));
2899 TEST_F(WebFrameTest, ContextNotificationsReload)
2901 v8::HandleScope handleScope(v8::Isolate::GetCurrent());
2903 registerMockedHttpURLLoad("context_notifications_test.html");
2904 registerMockedHttpURLLoad("context_notifications_test_frame.html");
2906 ContextLifetimeTestWebFrameClient webFrameClient;
2907 FrameTestHelpers::WebViewHelper webViewHelper;
2908 webViewHelper.initializeAndLoad(m_baseURL + "context_notifications_test.html", true, &webFrameClient);
2910 // Refresh, we should get two release notifications and two more create notifications.
2911 webViewHelper.webView()->mainFrame()->reload(false);
2912 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
2913 ASSERT_EQ(4u, webFrameClient.createNotifications.size());
2914 ASSERT_EQ(2u, webFrameClient.releaseNotifications.size());
2916 // The two release notifications we got should be exactly the same as the first two create notifications.
2917 for (size_t i = 0; i < webFrameClient.releaseNotifications.size(); ++i) {
2918 EXPECT_TRUE(webFrameClient.releaseNotifications[i]->Equals(
2919 webFrameClient.createNotifications[webFrameClient.createNotifications.size() - 3 - i]));
2922 // The last two create notifications should be for the current frames and context.
2923 WebFrame* mainFrame = webViewHelper.webView()->mainFrame();
2924 WebFrame* childFrame = mainFrame->firstChild();
2925 ContextLifetimeTestWebFrameClient::Notification* firstRefreshNotification = webFrameClient.createNotifications[2];
2926 ContextLifetimeTestWebFrameClient::Notification* secondRefreshNotification = webFrameClient.createNotifications[3];
2928 EXPECT_EQ(mainFrame, firstRefreshNotification->frame);
2929 EXPECT_EQ(mainFrame->mainWorldScriptContext(), firstRefreshNotification->context);
2930 EXPECT_EQ(0, firstRefreshNotification->worldId);
2932 EXPECT_EQ(childFrame, secondRefreshNotification->frame);
2933 EXPECT_EQ(childFrame->mainWorldScriptContext(), secondRefreshNotification->context);
2934 EXPECT_EQ(0, secondRefreshNotification->worldId);
2937 TEST_F(WebFrameTest, ContextNotificationsIsolatedWorlds)
2939 v8::Isolate* isolate = v8::Isolate::GetCurrent();
2940 v8::HandleScope handleScope(isolate);
2942 registerMockedHttpURLLoad("context_notifications_test.html");
2943 registerMockedHttpURLLoad("context_notifications_test_frame.html");
2945 ContextLifetimeTestWebFrameClient webFrameClient;
2946 FrameTestHelpers::WebViewHelper webViewHelper;
2947 webViewHelper.initializeAndLoad(m_baseURL + "context_notifications_test.html", true, &webFrameClient);
2949 // Add an isolated world.
2950 webFrameClient.reset();
2952 int isolatedWorldId = 42;
2953 WebScriptSource scriptSource("hi!");
2955 int extensionGroup = 0;
2956 webViewHelper.webView()->mainFrame()->executeScriptInIsolatedWorld(isolatedWorldId, &scriptSource, numSources, extensionGroup);
2958 // We should now have a new create notification.
2959 ASSERT_EQ(1u, webFrameClient.createNotifications.size());
2960 ContextLifetimeTestWebFrameClient::Notification* notification = webFrameClient.createNotifications[0];
2961 ASSERT_EQ(isolatedWorldId, notification->worldId);
2962 ASSERT_EQ(webViewHelper.webView()->mainFrame(), notification->frame);
2964 // 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.
2965 ASSERT_NE(webViewHelper.webView()->mainFrame()->mainWorldScriptContext(), v8::Local<v8::Context>::New(isolate, notification->context));
2967 webViewHelper.reset();
2969 // We should have gotten three release notifications (one for each of the frames, plus one for the isolated context).
2970 ASSERT_EQ(3u, webFrameClient.releaseNotifications.size());
2972 // And one of them should be exactly the same as the create notification for the isolated context.
2974 for (size_t i = 0; i < webFrameClient.releaseNotifications.size(); ++i) {
2975 if (webFrameClient.releaseNotifications[i]->Equals(webFrameClient.createNotifications[0]))
2978 EXPECT_EQ(1, matchCount);
2981 TEST_F(WebFrameTest, FindInPage)
2983 registerMockedHttpURLLoad("find.html");
2984 FrameTestHelpers::WebViewHelper webViewHelper;
2985 webViewHelper.initializeAndLoad(m_baseURL + "find.html");
2986 WebFrame* frame = webViewHelper.webView()->mainFrame();
2987 const int findIdentifier = 12345;
2988 WebFindOptions options;
2990 // Find in a <div> element.
2991 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar1"), options, false, 0));
2992 frame->stopFinding(false);
2993 WebRange range = frame->selectionRange();
2994 EXPECT_EQ(5, range.startOffset());
2995 EXPECT_EQ(9, range.endOffset());
2996 EXPECT_TRUE(frame->document().focusedElement().isNull());
2998 // Find in an <input> value.
2999 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar2"), options, false, 0));
3000 // Confirm stopFinding(false) sets the selection on the found text.
3001 frame->stopFinding(false);
3002 range = frame->selectionRange();
3003 ASSERT_FALSE(range.isNull());
3004 EXPECT_EQ(5, range.startOffset());
3005 EXPECT_EQ(9, range.endOffset());
3006 EXPECT_EQ(WebString::fromUTF8("INPUT"), frame->document().focusedElement().tagName());
3008 // Find in a <textarea> content.
3009 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar3"), options, false, 0));
3010 // Confirm stopFinding(false) sets the selection on the found text.
3011 frame->stopFinding(false);
3012 range = frame->selectionRange();
3013 ASSERT_FALSE(range.isNull());
3014 EXPECT_EQ(5, range.startOffset());
3015 EXPECT_EQ(9, range.endOffset());
3016 EXPECT_EQ(WebString::fromUTF8("TEXTAREA"), frame->document().focusedElement().tagName());
3018 // Find in a contentEditable element.
3019 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar4"), options, false, 0));
3020 // Confirm stopFinding(false) sets the selection on the found text.
3021 frame->stopFinding(false);
3022 range = frame->selectionRange();
3023 ASSERT_FALSE(range.isNull());
3024 EXPECT_EQ(0, range.startOffset());
3025 EXPECT_EQ(4, range.endOffset());
3026 // "bar4" is surrounded by <span>, but the focusable node should be the parent <div>.
3027 EXPECT_EQ(WebString::fromUTF8("DIV"), frame->document().focusedElement().tagName());
3029 // Find in <select> content.
3030 EXPECT_FALSE(frame->find(findIdentifier, WebString::fromUTF8("bar5"), options, false, 0));
3031 // If there are any matches, stopFinding will set the selection on the found text.
3032 // However, we do not expect any matches, so check that the selection is null.
3033 frame->stopFinding(false);
3034 range = frame->selectionRange();
3035 ASSERT_TRUE(range.isNull());
3038 TEST_F(WebFrameTest, GetContentAsPlainText)
3040 FrameTestHelpers::WebViewHelper webViewHelper;
3041 webViewHelper.initializeAndLoad("about:blank", true);
3042 // We set the size because it impacts line wrapping, which changes the
3043 // resulting text value.
3044 webViewHelper.webView()->resize(WebSize(640, 480));
3045 WebFrame* frame = webViewHelper.webView()->mainFrame();
3047 // Generate a simple test case.
3048 const char simpleSource[] = "<div>Foo bar</div><div></div>baz";
3049 WebCore::KURL testURL = toKURL("about:blank");
3050 frame->loadHTMLString(simpleSource, testURL);
3053 // Make sure it comes out OK.
3054 const std::string expected("Foo bar\nbaz");
3055 WebString text = frame->contentAsText(std::numeric_limits<size_t>::max());
3056 EXPECT_EQ(expected, text.utf8());
3058 // Try reading the same one with clipping of the text.
3059 const int length = 5;
3060 text = frame->contentAsText(length);
3061 EXPECT_EQ(expected.substr(0, length), text.utf8());
3063 // Now do a new test with a subframe.
3064 const char outerFrameSource[] = "Hello<iframe></iframe> world";
3065 frame->loadHTMLString(outerFrameSource, testURL);
3068 // Load something into the subframe.
3069 WebFrame* subframe = frame->firstChild();
3070 ASSERT_TRUE(subframe);
3071 subframe->loadHTMLString("sub<p>text", testURL);
3074 text = frame->contentAsText(std::numeric_limits<size_t>::max());
3075 EXPECT_EQ("Hello world\n\nsub\ntext", text.utf8());
3077 // Get the frame text where the subframe separator falls on the boundary of
3078 // what we'll take. There used to be a crash in this case.
3079 text = frame->contentAsText(12);
3080 EXPECT_EQ("Hello world", text.utf8());
3083 TEST_F(WebFrameTest, GetFullHtmlOfPage)
3085 FrameTestHelpers::WebViewHelper webViewHelper;
3086 webViewHelper.initializeAndLoad("about:blank", true);
3087 WebFrame* frame = webViewHelper.webView()->mainFrame();
3089 // Generate a simple test case.
3090 const char simpleSource[] = "<p>Hello</p><p>World</p>";
3091 WebCore::KURL testURL = toKURL("about:blank");
3092 frame->loadHTMLString(simpleSource, testURL);
3095 WebString text = frame->contentAsText(std::numeric_limits<size_t>::max());
3096 EXPECT_EQ("Hello\n\nWorld", text.utf8());
3098 const std::string html = frame->contentAsMarkup().utf8();
3100 // Load again with the output html.
3101 frame->loadHTMLString(WebData(html.c_str(), html.length()), testURL);
3104 EXPECT_EQ(html, frame->contentAsMarkup().utf8());
3106 text = frame->contentAsText(std::numeric_limits<size_t>::max());
3107 EXPECT_EQ("Hello\n\nWorld", text.utf8());
3109 // Test selection check
3110 EXPECT_FALSE(frame->hasSelection());
3111 frame->executeCommand(WebString::fromUTF8("SelectAll"));
3112 EXPECT_TRUE(frame->hasSelection());
3113 frame->executeCommand(WebString::fromUTF8("Unselect"));
3114 EXPECT_FALSE(frame->hasSelection());
3115 WebString selectionHtml = frame->selectionAsMarkup();
3116 EXPECT_TRUE(selectionHtml.isEmpty());
3119 class TestExecuteScriptDuringDidCreateScriptContext : public FrameTestHelpers::TestWebFrameClient {
3121 virtual void didCreateScriptContext(WebLocalFrame* frame, v8::Handle<v8::Context> context, int extensionGroup, int worldId) OVERRIDE
3123 frame->executeScript(WebScriptSource("window.history = 'replaced';"));
3127 TEST_F(WebFrameTest, ExecuteScriptDuringDidCreateScriptContext)
3129 registerMockedHttpURLLoad("hello_world.html");
3131 TestExecuteScriptDuringDidCreateScriptContext webFrameClient;
3132 FrameTestHelpers::WebViewHelper webViewHelper;
3133 webViewHelper.initializeAndLoad(m_baseURL + "hello_world.html", true, &webFrameClient);
3135 webViewHelper.webView()->mainFrame()->reload();
3136 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
3139 class FindUpdateWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
3141 FindUpdateWebFrameClient()
3142 : m_findResultsAreReady(false)
3147 virtual void reportFindInPageMatchCount(int, int count, bool finalUpdate) OVERRIDE
3151 m_findResultsAreReady = true;
3154 bool findResultsAreReady() const { return m_findResultsAreReady; }
3155 int count() const { return m_count; }
3158 bool m_findResultsAreReady;
3162 // This fails on Mac https://bugs.webkit.org/show_bug.cgi?id=108574
3163 // Also failing on Android: http://crbug.com/341314
3164 #if OS(MACOSX) || OS(ANDROID)
3165 TEST_F(WebFrameTest, DISABLED_FindInPageMatchRects)
3167 TEST_F(WebFrameTest, FindInPageMatchRects)
3170 registerMockedHttpURLLoad("find_in_page.html");
3171 registerMockedHttpURLLoad("find_in_page_frame.html");
3173 FindUpdateWebFrameClient client;
3174 FrameTestHelpers::WebViewHelper webViewHelper;
3175 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3176 webViewHelper.webView()->resize(WebSize(640, 480));
3177 webViewHelper.webView()->layout();
3180 // Note that the 'result 19' in the <select> element is not expected to produce a match.
3181 static const char* kFindString = "result";
3182 static const int kFindIdentifier = 12345;
3183 static const int kNumResults = 19;
3185 WebFindOptions options;
3186 WebString searchText = WebString::fromUTF8(kFindString);
3187 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3188 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
3190 mainFrame->resetMatchCount();
3192 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3193 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3196 EXPECT_TRUE(client.findResultsAreReady());
3198 WebVector<WebFloatRect> webMatchRects;
3199 mainFrame->findMatchRects(webMatchRects);
3200 ASSERT_EQ(webMatchRects.size(), static_cast<size_t>(kNumResults));
3201 int rectsVersion = mainFrame->findMatchMarkersVersion();
3203 for (int resultIndex = 0; resultIndex < kNumResults; ++resultIndex) {
3204 FloatRect resultRect = static_cast<FloatRect>(webMatchRects[resultIndex]);
3206 // Select the match by the center of its rect.
3207 EXPECT_EQ(mainFrame->selectNearestFindMatch(resultRect.center(), 0), resultIndex + 1);
3209 // Check that the find result ordering matches with our expectations.
3210 Range* result = mainFrame->activeMatchFrame()->activeMatch();
3211 ASSERT_TRUE(result);
3212 result->setEnd(result->endContainer(), result->endOffset() + 3);
3213 EXPECT_EQ(result->text(), String::format("%s %02d", kFindString, resultIndex));
3215 // Verify that the expected match rect also matches the currently active match.
3216 // Compare the enclosing rects to prevent precision issues caused by CSS transforms.
3217 FloatRect activeMatch = mainFrame->activeFindMatchRect();
3218 EXPECT_EQ(enclosingIntRect(activeMatch), enclosingIntRect(resultRect));
3220 // The rects version should not have changed.
3221 EXPECT_EQ(mainFrame->findMatchMarkersVersion(), rectsVersion);
3224 // All results after the first two ones should be below between them in find-in-page coordinates.
3225 // This is because results 2 to 9 are inside an iframe located between results 0 and 1. This applies to the fixed div too.
3226 EXPECT_TRUE(webMatchRects[0].y < webMatchRects[1].y);
3227 for (int resultIndex = 2; resultIndex < kNumResults; ++resultIndex) {
3228 EXPECT_TRUE(webMatchRects[0].y < webMatchRects[resultIndex].y);
3229 EXPECT_TRUE(webMatchRects[1].y > webMatchRects[resultIndex].y);
3232 // Result 3 should be below both 2 and 4. This is caused by the CSS transform in the containing div.
3233 // If the transform doesn't work then 3 will be between 2 and 4.
3234 EXPECT_TRUE(webMatchRects[3].y > webMatchRects[2].y);
3235 EXPECT_TRUE(webMatchRects[3].y > webMatchRects[4].y);
3237 // Results 6, 7, 8 and 9 should be one below the other in that same order.
3238 // If overflow:scroll is not properly handled then result 8 would be below result 9 or
3239 // result 7 above result 6 depending on the scroll.
3240 EXPECT_TRUE(webMatchRects[6].y < webMatchRects[7].y);
3241 EXPECT_TRUE(webMatchRects[7].y < webMatchRects[8].y);
3242 EXPECT_TRUE(webMatchRects[8].y < webMatchRects[9].y);
3244 // Results 11, 12, 13 and 14 should be between results 10 and 15, as they are inside the table.
3245 EXPECT_TRUE(webMatchRects[11].y > webMatchRects[10].y);
3246 EXPECT_TRUE(webMatchRects[12].y > webMatchRects[10].y);
3247 EXPECT_TRUE(webMatchRects[13].y > webMatchRects[10].y);
3248 EXPECT_TRUE(webMatchRects[14].y > webMatchRects[10].y);
3249 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[15].y);
3250 EXPECT_TRUE(webMatchRects[12].y < webMatchRects[15].y);
3251 EXPECT_TRUE(webMatchRects[13].y < webMatchRects[15].y);
3252 EXPECT_TRUE(webMatchRects[14].y < webMatchRects[15].y);
3254 // Result 11 should be above 12, 13 and 14 as it's in the table header.
3255 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[12].y);
3256 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[13].y);
3257 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[14].y);
3259 // Result 11 should also be right to 12, 13 and 14 because of the colspan.
3260 EXPECT_TRUE(webMatchRects[11].x > webMatchRects[12].x);
3261 EXPECT_TRUE(webMatchRects[11].x > webMatchRects[13].x);
3262 EXPECT_TRUE(webMatchRects[11].x > webMatchRects[14].x);
3264 // Result 12 should be left to results 11, 13 and 14 in the table layout.
3265 EXPECT_TRUE(webMatchRects[12].x < webMatchRects[11].x);
3266 EXPECT_TRUE(webMatchRects[12].x < webMatchRects[13].x);
3267 EXPECT_TRUE(webMatchRects[12].x < webMatchRects[14].x);
3269 // Results 13, 12 and 14 should be one above the other in that order because of the rowspan
3270 // and vertical-align: middle by default.
3271 EXPECT_TRUE(webMatchRects[13].y < webMatchRects[12].y);
3272 EXPECT_TRUE(webMatchRects[12].y < webMatchRects[14].y);
3274 // Result 16 should be below result 15.
3275 EXPECT_TRUE(webMatchRects[15].y > webMatchRects[14].y);
3277 // Result 18 should be normalized with respect to the position:relative div, and not it's
3278 // immediate containing div. Consequently, result 18 should be above result 17.
3279 EXPECT_TRUE(webMatchRects[17].y > webMatchRects[18].y);
3281 // Resizing should update the rects version.
3282 webViewHelper.webView()->resize(WebSize(800, 600));
3284 EXPECT_TRUE(mainFrame->findMatchMarkersVersion() != rectsVersion);
3287 TEST_F(WebFrameTest, FindInPageSkipsHiddenFrames)
3289 registerMockedHttpURLLoad("find_in_hidden_frame.html");
3291 FindUpdateWebFrameClient client;
3292 FrameTestHelpers::WebViewHelper webViewHelper;
3293 webViewHelper.initializeAndLoad(m_baseURL + "find_in_hidden_frame.html", true, &client);
3294 webViewHelper.webView()->resize(WebSize(640, 480));
3295 webViewHelper.webView()->layout();
3298 static const char* kFindString = "hello";
3299 static const int kFindIdentifier = 12345;
3300 static const int kNumResults = 1;
3302 WebFindOptions options;
3303 WebString searchText = WebString::fromUTF8(kFindString);
3304 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3305 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
3307 mainFrame->resetMatchCount();
3309 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3310 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3313 EXPECT_TRUE(client.findResultsAreReady());
3314 EXPECT_EQ(kNumResults, client.count());
3317 TEST_F(WebFrameTest, FindOnDetachedFrame)
3319 registerMockedHttpURLLoad("find_in_page.html");
3320 registerMockedHttpURLLoad("find_in_page_frame.html");
3322 FindUpdateWebFrameClient client;
3323 FrameTestHelpers::WebViewHelper webViewHelper;
3324 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3325 webViewHelper.webView()->resize(WebSize(640, 480));
3326 webViewHelper.webView()->layout();
3329 static const char* kFindString = "result";
3330 static const int kFindIdentifier = 12345;
3332 WebFindOptions options;
3333 WebString searchText = WebString::fromUTF8(kFindString);
3334 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3335 RefPtr<WebLocalFrameImpl> secondFrame = toWebLocalFrameImpl(mainFrame->traverseNext(false));
3336 RefPtr<WebCore::LocalFrame> holdSecondFrame = secondFrame->frame();
3338 // Detach the frame before finding.
3339 EXPECT_TRUE(mainFrame->document().getElementById("frame").remove());
3341 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
3342 EXPECT_FALSE(secondFrame->find(kFindIdentifier, searchText, options, false, 0));
3345 EXPECT_FALSE(client.findResultsAreReady());
3347 mainFrame->resetMatchCount();
3349 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3350 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3353 EXPECT_TRUE(client.findResultsAreReady());
3355 holdSecondFrame.release();
3358 TEST_F(WebFrameTest, FindDetachFrameBeforeScopeStrings)
3360 registerMockedHttpURLLoad("find_in_page.html");
3361 registerMockedHttpURLLoad("find_in_page_frame.html");
3363 FindUpdateWebFrameClient client;
3364 FrameTestHelpers::WebViewHelper webViewHelper;
3365 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3366 webViewHelper.webView()->resize(WebSize(640, 480));
3367 webViewHelper.webView()->layout();
3370 static const char* kFindString = "result";
3371 static const int kFindIdentifier = 12345;
3373 WebFindOptions options;
3374 WebString searchText = WebString::fromUTF8(kFindString);
3375 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3376 WebLocalFrameImpl* secondFrame = toWebLocalFrameImpl(mainFrame->traverseNext(false));
3377 RefPtr<WebCore::LocalFrame> holdSecondFrame = secondFrame->frame();
3379 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3380 EXPECT_TRUE(frame->find(kFindIdentifier, searchText, options, false, 0));
3383 EXPECT_FALSE(client.findResultsAreReady());
3385 // Detach the frame between finding and scoping.
3386 EXPECT_TRUE(mainFrame->document().getElementById("frame").remove());
3388 mainFrame->resetMatchCount();
3390 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3391 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3394 EXPECT_TRUE(client.findResultsAreReady());
3396 holdSecondFrame.release();
3399 TEST_F(WebFrameTest, FindDetachFrameWhileScopingStrings)
3401 registerMockedHttpURLLoad("find_in_page.html");
3402 registerMockedHttpURLLoad("find_in_page_frame.html");
3404 FindUpdateWebFrameClient client;
3405 FrameTestHelpers::WebViewHelper webViewHelper;
3406 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3407 webViewHelper.webView()->resize(WebSize(640, 480));
3408 webViewHelper.webView()->layout();
3411 static const char* kFindString = "result";
3412 static const int kFindIdentifier = 12345;
3414 WebFindOptions options;
3415 WebString searchText = WebString::fromUTF8(kFindString);
3416 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3417 WebLocalFrameImpl* secondFrame = toWebLocalFrameImpl(mainFrame->traverseNext(false));
3418 RefPtr<WebCore::LocalFrame> holdSecondFrame = secondFrame->frame();
3420 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3421 EXPECT_TRUE(frame->find(kFindIdentifier, searchText, options, false, 0));
3424 EXPECT_FALSE(client.findResultsAreReady());
3426 mainFrame->resetMatchCount();
3428 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3429 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3431 // The first scopeStringMatches will have reset the state. Detach before it actually scopes.
3432 EXPECT_TRUE(mainFrame->document().getElementById("frame").remove());
3435 EXPECT_TRUE(client.findResultsAreReady());
3437 holdSecondFrame.release();
3440 TEST_F(WebFrameTest, SetTickmarks)
3442 registerMockedHttpURLLoad("find.html");
3444 FindUpdateWebFrameClient client;
3445 FrameTestHelpers::WebViewHelper webViewHelper;
3446 webViewHelper.initializeAndLoad(m_baseURL + "find.html", true, &client);
3447 webViewHelper.webView()->resize(WebSize(640, 480));
3448 webViewHelper.webView()->layout();
3451 static const char* kFindString = "foo";
3452 static const int kFindIdentifier = 12345;
3454 WebFindOptions options;
3455 WebString searchText = WebString::fromUTF8(kFindString);
3456 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3457 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
3459 mainFrame->resetMatchCount();
3460 mainFrame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3463 EXPECT_TRUE(client.findResultsAreReady());
3465 // Get the tickmarks for the original find request.
3466 WebCore::FrameView* frameView = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
3467 RefPtr<WebCore::Scrollbar> scrollbar = frameView->createScrollbar(WebCore::HorizontalScrollbar);
3468 Vector<WebCore::IntRect> originalTickmarks;
3469 scrollbar->getTickmarks(originalTickmarks);
3470 EXPECT_EQ(4u, originalTickmarks.size());
3472 // Override the tickmarks.
3473 Vector<WebCore::IntRect> overridingTickmarksExpected;
3474 overridingTickmarksExpected.append(WebCore::IntRect(0, 0, 100, 100));
3475 overridingTickmarksExpected.append(WebCore::IntRect(0, 20, 100, 100));
3476 overridingTickmarksExpected.append(WebCore::IntRect(0, 30, 100, 100));
3477 mainFrame->setTickmarks(overridingTickmarksExpected);
3479 // Check the tickmarks are overriden correctly.
3480 Vector<WebCore::IntRect> overridingTickmarksActual;
3481 scrollbar->getTickmarks(overridingTickmarksActual);
3482 EXPECT_EQ(overridingTickmarksExpected, overridingTickmarksActual);
3484 // Reset the tickmark behavior.
3485 Vector<WebCore::IntRect> resetTickmarks;
3486 mainFrame->setTickmarks(resetTickmarks);
3488 // Check that the original tickmarks are returned
3489 Vector<WebCore::IntRect> originalTickmarksAfterReset;
3490 scrollbar->getTickmarks(originalTickmarksAfterReset);
3491 EXPECT_EQ(originalTickmarks, originalTickmarksAfterReset);
3494 static WebPoint topLeft(const WebRect& rect)
3496 return WebPoint(rect.x, rect.y);
3499 static WebPoint bottomRightMinusOne(const WebRect& rect)
3501 // FIXME: If we don't subtract 1 from the x- and y-coordinates of the
3502 // selection bounds, selectRange() will select the *next* element. That's
3503 // strictly correct, as hit-testing checks the pixel to the lower-right of
3504 // the input coordinate, but it's a wart on the API.
3505 return WebPoint(rect.x + rect.width - 1, rect.y + rect.height - 1);
3508 static WebRect elementBounds(WebFrame* frame, const WebString& id)
3510 return frame->document().getElementById(id).boundsInViewportSpace();
3513 static std::string selectionAsString(WebFrame* frame)
3515 return frame->selectionAsText().utf8();
3518 TEST_F(WebFrameTest, SelectRange)
3521 WebRect startWebRect;
3524 registerMockedHttpURLLoad("select_range_basic.html");
3525 registerMockedHttpURLLoad("select_range_scroll.html");
3527 FrameTestHelpers::WebViewHelper webViewHelper;
3528 initializeTextSelectionWebView(m_baseURL + "select_range_basic.html", &webViewHelper);
3529 frame = webViewHelper.webView()->mainFrame();
3530 EXPECT_EQ("Some test text for testing.", selectionAsString(frame));
3531 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3532 frame->executeCommand(WebString::fromUTF8("Unselect"));
3533 EXPECT_EQ("", selectionAsString(frame));
3534 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3535 EXPECT_EQ("Some test text for testing.", selectionAsString(frame));
3537 initializeTextSelectionWebView(m_baseURL + "select_range_scroll.html", &webViewHelper);
3538 frame = webViewHelper.webView()->mainFrame();
3539 EXPECT_EQ("Some offscreen test text for testing.", selectionAsString(frame));
3540 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3541 frame->executeCommand(WebString::fromUTF8("Unselect"));
3542 EXPECT_EQ("", selectionAsString(frame));
3543 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3544 EXPECT_EQ("Some offscreen test text for testing.", selectionAsString(frame));
3547 TEST_F(WebFrameTest, SelectRangeInIframe)
3550 WebRect startWebRect;
3553 registerMockedHttpURLLoad("select_range_iframe.html");
3554 registerMockedHttpURLLoad("select_range_basic.html");
3556 FrameTestHelpers::WebViewHelper webViewHelper;
3557 initializeTextSelectionWebView(m_baseURL + "select_range_iframe.html", &webViewHelper);
3558 frame = webViewHelper.webView()->mainFrame();
3559 WebFrame* subframe = frame->firstChild();
3560 EXPECT_EQ("Some test text for testing.", selectionAsString(subframe));
3561 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3562 subframe->executeCommand(WebString::fromUTF8("Unselect"));
3563 EXPECT_EQ("", selectionAsString(subframe));
3564 subframe->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3565 EXPECT_EQ("Some test text for testing.", selectionAsString(subframe));
3568 TEST_F(WebFrameTest, SelectRangeDivContentEditable)
3571 WebRect startWebRect;
3574 registerMockedHttpURLLoad("select_range_div_editable.html");
3576 // Select the middle of an editable element, then try to extend the selection to the top of the document.
3577 // The selection range should be clipped to the bounds of the editable element.
3578 FrameTestHelpers::WebViewHelper webViewHelper;
3579 initializeTextSelectionWebView(m_baseURL + "select_range_div_editable.html", &webViewHelper);
3580 frame = webViewHelper.webView()->mainFrame();
3581 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3582 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3584 frame->selectRange(bottomRightMinusOne(endWebRect), WebPoint(0, 0));
3585 EXPECT_EQ("16-char header. This text is initially selected.", selectionAsString(frame));
3587 // As above, but extending the selection to the bottom of the document.
3588 initializeTextSelectionWebView(m_baseURL + "select_range_div_editable.html", &webViewHelper);
3589 frame = webViewHelper.webView()->mainFrame();
3591 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3592 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3593 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3594 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3596 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3597 frame->selectRange(topLeft(startWebRect), WebPoint(640, 480));
3598 EXPECT_EQ("This text is initially selected. 16-char footer.", selectionAsString(frame));
3601 // positionForPoint returns the wrong values for contenteditable spans. See
3602 // http://crbug.com/238334.
3603 TEST_F(WebFrameTest, DISABLED_SelectRangeSpanContentEditable)
3606 WebRect startWebRect;
3609 registerMockedHttpURLLoad("select_range_span_editable.html");
3611 // Select the middle of an editable element, then try to extend the selection to the top of the document.
3612 // The selection range should be clipped to the bounds of the editable element.
3613 FrameTestHelpers::WebViewHelper webViewHelper;
3614 initializeTextSelectionWebView(m_baseURL + "select_range_span_editable.html", &webViewHelper);
3615 frame = webViewHelper.webView()->mainFrame();
3616 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3617 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3619 frame->selectRange(bottomRightMinusOne(endWebRect), WebPoint(0, 0));
3620 EXPECT_EQ("16-char header. This text is initially selected.", selectionAsString(frame));
3622 // As above, but extending the selection to the bottom of the document.
3623 initializeTextSelectionWebView(m_baseURL + "select_range_span_editable.html", &webViewHelper);
3624 frame = webViewHelper.webView()->mainFrame();
3626 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3627 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3628 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3629 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3631 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3632 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3633 frame->selectRange(topLeft(startWebRect), WebPoint(640, 480));
3634 EXPECT_EQ("This text is initially selected. 16-char footer.", selectionAsString(frame));
3637 TEST_F(WebFrameTest, SelectRangeCanMoveSelectionStart)
3639 registerMockedHttpURLLoad("text_selection.html");
3640 FrameTestHelpers::WebViewHelper webViewHelper;
3641 initializeTextSelectionWebView(m_baseURL + "text_selection.html", &webViewHelper);
3642 WebFrame* frame = webViewHelper.webView()->mainFrame();
3644 // Select second span. We can move the start to include the first span.
3645 frame->executeScript(WebScriptSource("selectElement('header_2');"));
3646 EXPECT_EQ("Header 2.", selectionAsString(frame));
3647 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "header_2")), topLeft(elementBounds(frame, "header_1")));
3648 EXPECT_EQ("Header 1. Header 2.", selectionAsString(frame));
3650 // We can move the start and end together.
3651 frame->executeScript(WebScriptSource("selectElement('header_1');"));
3652 EXPECT_EQ("Header 1.", selectionAsString(frame));
3653 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "header_1")));
3654 EXPECT_EQ("", selectionAsString(frame));
3655 // Selection is a caret, not empty.
3656 EXPECT_FALSE(frame->selectionRange().isNull());
3658 // We can move the start across the end.
3659 frame->executeScript(WebScriptSource("selectElement('header_1');"));
3660 EXPECT_EQ("Header 1.", selectionAsString(frame));
3661 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "header_2")));
3662 EXPECT_EQ(" Header 2.", selectionAsString(frame));
3664 // Can't extend the selection part-way into an editable element.
3665 frame->executeScript(WebScriptSource("selectElement('footer_2');"));
3666 EXPECT_EQ("Footer 2.", selectionAsString(frame));
3667 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "footer_2")), topLeft(elementBounds(frame, "editable_2")));
3668 EXPECT_EQ(" [ Footer 1. Footer 2.", selectionAsString(frame));
3670 // Can extend the selection completely across editable elements.
3671 frame->executeScript(WebScriptSource("selectElement('footer_2');"));
3672 EXPECT_EQ("Footer 2.", selectionAsString(frame));
3673 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "footer_2")), topLeft(elementBounds(frame, "header_2")));
3674 EXPECT_EQ("Header 2. ] [ Editable 1. Editable 2. ] [ Footer 1. Footer 2.", selectionAsString(frame));
3676 // If the selection is editable text, we can't extend it into non-editable text.
3677 frame->executeScript(WebScriptSource("selectElement('editable_2');"));
3678 EXPECT_EQ("Editable 2.", selectionAsString(frame));
3679 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "editable_2")), topLeft(elementBounds(frame, "header_2")));
3680 // positionForPoint returns the wrong values for contenteditable spans. See
3681 // http://crbug.com/238334.
3682 // EXPECT_EQ("[ Editable 1. Editable 2.", selectionAsString(frame));
3685 TEST_F(WebFrameTest, SelectRangeCanMoveSelectionEnd)
3687 registerMockedHttpURLLoad("text_selection.html");
3688 FrameTestHelpers::WebViewHelper webViewHelper;
3689 initializeTextSelectionWebView(m_baseURL + "text_selection.html", &webViewHelper);
3690 WebFrame* frame = webViewHelper.webView()->mainFrame();
3692 // Select first span. We can move the end to include the second span.
3693 frame->executeScript(WebScriptSource("selectElement('header_1');"));
3694 EXPECT_EQ("Header 1.", selectionAsString(frame));
3695 frame->selectRange(topLeft(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "header_2")));
3696 EXPECT_EQ("Header 1. Header 2.", selectionAsString(frame));
3698 // We can move the start and end together.
3699 frame->executeScript(WebScriptSource("selectElement('header_2');"));
3700 EXPECT_EQ("Header 2.", selectionAsString(frame));
3701 frame->selectRange(topLeft(elementBounds(frame, "header_2")), topLeft(elementBounds(frame, "header_2")));
3702 EXPECT_EQ("", selectionAsString(frame));
3703 // Selection is a caret, not empty.
3704 EXPECT_FALSE(frame->selectionRange().isNull());
3706 // We can move the end across the start.
3707 frame->executeScript(WebScriptSource("selectElement('header_2');"));
3708 EXPECT_EQ("Header 2.", selectionAsString(frame));
3709 frame->selectRange(topLeft(elementBounds(frame, "header_2")), topLeft(elementBounds(frame, "header_1")));
3710 EXPECT_EQ("Header 1. ", selectionAsString(frame));
3712 // Can't extend the selection part-way into an editable element.
3713 frame->executeScript(WebScriptSource("selectElement('header_1');"));
3714 EXPECT_EQ("Header 1.", selectionAsString(frame));
3715 frame->selectRange(topLeft(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "editable_1")));
3716 EXPECT_EQ("Header 1. Header 2. ] ", selectionAsString(frame));
3718 // Can extend the selection completely across editable elements.
3719 frame->executeScript(WebScriptSource("selectElement('header_1');"));
3720 EXPECT_EQ("Header 1.", selectionAsString(frame));
3721 frame->selectRange(topLeft(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "footer_1")));
3722 EXPECT_EQ("Header 1. Header 2. ] [ Editable 1. Editable 2. ] [ Footer 1.", selectionAsString(frame));
3724 // If the selection is editable text, we can't extend it into non-editable text.
3725 frame->executeScript(WebScriptSource("selectElement('editable_1');"));
3726 EXPECT_EQ("Editable 1.", selectionAsString(frame));
3727 frame->selectRange(topLeft(elementBounds(frame, "editable_1")), bottomRightMinusOne(elementBounds(frame, "footer_1")));
3728 // positionForPoint returns the wrong values for contenteditable spans. See
3729 // http://crbug.com/238334.
3730 // EXPECT_EQ("Editable 1. Editable 2. ]", selectionAsString(frame));
3733 static int computeOffset(WebCore::RenderObject* renderer, int x, int y)
3735 return WebCore::VisiblePosition(renderer->positionForPoint(WebCore::LayoutPoint(x, y))).deepEquivalent().computeOffsetInContainerNode();
3738 // positionForPoint returns the wrong values for contenteditable spans. See
3739 // http://crbug.com/238334.
3740 TEST_F(WebFrameTest, DISABLED_PositionForPointTest)
3742 registerMockedHttpURLLoad("select_range_span_editable.html");
3743 FrameTestHelpers::WebViewHelper webViewHelper;
3744 initializeTextSelectionWebView(m_baseURL + "select_range_span_editable.html", &webViewHelper);
3745 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3746 WebCore::RenderObject* renderer = mainFrame->frame()->selection().rootEditableElement()->renderer();
3747 EXPECT_EQ(0, computeOffset(renderer, -1, -1));
3748 EXPECT_EQ(64, computeOffset(renderer, 1000, 1000));
3750 registerMockedHttpURLLoad("select_range_div_editable.html");
3751 initializeTextSelectionWebView(m_baseURL + "select_range_div_editable.html", &webViewHelper);
3752 mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3753 renderer = mainFrame->frame()->selection().rootEditableElement()->renderer();
3754 EXPECT_EQ(0, computeOffset(renderer, -1, -1));
3755 EXPECT_EQ(64, computeOffset(renderer, 1000, 1000));
3758 #if !OS(MACOSX) && !OS(LINUX)
3759 TEST_F(WebFrameTest, SelectRangeStaysHorizontallyAlignedWhenMoved)
3761 registerMockedHttpURLLoad("move_caret.html");
3763 FrameTestHelpers::WebViewHelper webViewHelper;
3764 initializeTextSelectionWebView(m_baseURL + "move_caret.html", &webViewHelper);
3765 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3767 WebRect initialStartRect;
3768 WebRect initialEndRect;
3772 frame->executeScript(WebScriptSource("selectRange();"));
3773 webViewHelper.webView()->selectionBounds(initialStartRect, initialEndRect);
3774 WebPoint movedStart(topLeft(initialStartRect));
3777 frame->selectRange(movedStart, bottomRightMinusOne(initialEndRect));
3778 webViewHelper.webView()->selectionBounds(startRect, endRect);
3779 EXPECT_EQ(startRect, initialStartRect);
3780 EXPECT_EQ(endRect, initialEndRect);
3783 frame->selectRange(movedStart, bottomRightMinusOne(initialEndRect));
3784 webViewHelper.webView()->selectionBounds(startRect, endRect);
3785 EXPECT_EQ(startRect, initialStartRect);
3786 EXPECT_EQ(endRect, initialEndRect);
3788 WebPoint movedEnd(bottomRightMinusOne(initialEndRect));
3791 frame->selectRange(topLeft(initialStartRect), movedEnd);
3792 webViewHelper.webView()->selectionBounds(startRect, endRect);
3793 EXPECT_EQ(startRect, initialStartRect);
3794 EXPECT_EQ(endRect, initialEndRect);
3797 frame->selectRange(topLeft(initialStartRect), movedEnd);
3798 webViewHelper.webView()->selectionBounds(startRect, endRect);
3799 EXPECT_EQ(startRect, initialStartRect);
3800 EXPECT_EQ(endRect, initialEndRect);
3803 TEST_F(WebFrameTest, MoveCaretStaysHorizontallyAlignedWhenMoved)
3805 WebLocalFrameImpl* frame;
3806 registerMockedHttpURLLoad("move_caret.html");
3808 FrameTestHelpers::WebViewHelper webViewHelper;
3809 initializeTextSelectionWebView(m_baseURL + "move_caret.html", &webViewHelper);
3810 frame = (WebLocalFrameImpl*)webViewHelper.webView()->mainFrame();
3812 WebRect initialStartRect;
3813 WebRect initialEndRect;
3817 frame->executeScript(WebScriptSource("selectCaret();"));
3818 webViewHelper.webView()->selectionBounds(initialStartRect, initialEndRect);
3819 WebPoint moveTo(topLeft(initialStartRect));
3822 frame->moveCaretSelection(moveTo);
3823 webViewHelper.webView()->selectionBounds(startRect, endRect);
3824 EXPECT_EQ(startRect, initialStartRect);
3825 EXPECT_EQ(endRect, initialEndRect);
3828 frame->moveCaretSelection(moveTo);
3829 webViewHelper.webView()->selectionBounds(startRect, endRect);
3830 EXPECT_EQ(startRect, initialStartRect);
3831 EXPECT_EQ(endRect, initialEndRect);
3835 class DisambiguationPopupTestWebViewClient : public FrameTestHelpers::TestWebViewClient {
3837 virtual bool didTapMultipleTargets(const WebGestureEvent&, const WebVector<WebRect>& targetRects) OVERRIDE
3839 EXPECT_GE(targetRects.size(), 2u);
3844 bool triggered() const { return m_triggered; }
3845 void resetTriggered() { m_triggered = false; }
3849 static WebGestureEvent fatTap(int x, int y)
3851 WebGestureEvent event;
3852 event.type = WebInputEvent::GestureTap;
3855 event.data.tap.width = 50;
3856 event.data.tap.height = 50;
3860 TEST_F(WebFrameTest, DisambiguationPopup)
3862 const std::string htmlFile = "disambiguation_popup.html";
3863 registerMockedHttpURLLoad(htmlFile);
3865 DisambiguationPopupTestWebViewClient client;
3867 // Make sure we initialize to minimum scale, even if the window size
3868 // only becomes available after the load begins.
3869 FrameTestHelpers::WebViewHelper webViewHelper;
3870 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client);
3871 webViewHelper.webView()->resize(WebSize(1000, 1000));
3872 webViewHelper.webView()->layout();
3874 client.resetTriggered();
3875 webViewHelper.webView()->handleInputEvent(fatTap(0, 0));
3876 EXPECT_FALSE(client.triggered());
3878 client.resetTriggered();
3879 webViewHelper.webView()->handleInputEvent(fatTap(200, 115));
3880 EXPECT_FALSE(client.triggered());
3882 for (int i = 0; i <= 46; i++) {
3883 client.resetTriggered();
3884 webViewHelper.webView()->handleInputEvent(fatTap(120, 230 + i * 5));
3887 if (j >= 7 && j <= 9)
3888 EXPECT_TRUE(client.triggered());
3890 EXPECT_FALSE(client.triggered());
3893 for (int i = 0; i <= 46; i++) {
3894 client.resetTriggered();
3895 webViewHelper.webView()->handleInputEvent(fatTap(10 + i * 5, 590));
3898 if (j >= 7 && j <= 9)
3899 EXPECT_TRUE(client.triggered());
3901 EXPECT_FALSE(client.triggered());
3905 TEST_F(WebFrameTest, DisambiguationPopupNoContainer)
3907 registerMockedHttpURLLoad("disambiguation_popup_no_container.html");
3909 DisambiguationPopupTestWebViewClient client;
3911 // Make sure we initialize to minimum scale, even if the window size
3912 // only becomes available after the load begins.
3913 FrameTestHelpers::WebViewHelper webViewHelper;
3914 webViewHelper.initializeAndLoad(m_baseURL + "disambiguation_popup_no_container.html", true, 0, &client);
3915 webViewHelper.webView()->resize(WebSize(1000, 1000));
3916 webViewHelper.webView()->layout();
3918 client.resetTriggered();
3919 webViewHelper.webView()->handleInputEvent(fatTap(50, 50));
3920 EXPECT_FALSE(client.triggered());
3923 TEST_F(WebFrameTest, DisambiguationPopupMobileSite)
3925 UseMockScrollbarSettings mockScrollbarSettings;
3926 const std::string htmlFile = "disambiguation_popup_mobile_site.html";
3927 registerMockedHttpURLLoad(htmlFile);
3929 DisambiguationPopupTestWebViewClient client;
3931 // Make sure we initialize to minimum scale, even if the window size
3932 // only becomes available after the load begins.
3933 FrameTestHelpers::WebViewHelper webViewHelper;
3934 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client, enableViewportSettings);
3935 webViewHelper.webView()->resize(WebSize(1000, 1000));
3936 webViewHelper.webView()->layout();
3938 client.resetTriggered();
3939 webViewHelper.webView()->handleInputEvent(fatTap(0, 0));
3940 EXPECT_FALSE(client.triggered());
3942 client.resetTriggered();
3943 webViewHelper.webView()->handleInputEvent(fatTap(200, 115));
3944 EXPECT_FALSE(client.triggered());
3946 for (int i = 0; i <= 46; i++) {
3947 client.resetTriggered();
3948 webViewHelper.webView()->handleInputEvent(fatTap(120, 230 + i * 5));
3949 EXPECT_FALSE(client.triggered());
3952 for (int i = 0; i <= 46; i++) {
3953 client.resetTriggered();
3954 webViewHelper.webView()->handleInputEvent(fatTap(10 + i * 5, 590));
3955 EXPECT_FALSE(client.triggered());
3959 TEST_F(WebFrameTest, DisambiguationPopupViewportSite)
3961 UseMockScrollbarSettings mockScrollbarSettings;
3962 const std::string htmlFile = "disambiguation_popup_viewport_site.html";
3963 registerMockedHttpURLLoad(htmlFile);
3965 DisambiguationPopupTestWebViewClient client;
3967 // Make sure we initialize to minimum scale, even if the window size
3968 // only becomes available after the load begins.
3969 FrameTestHelpers::WebViewHelper webViewHelper;
3970 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client, enableViewportSettings);
3971 webViewHelper.webView()->resize(WebSize(1000, 1000));
3972 webViewHelper.webView()->layout();
3974 client.resetTriggered();
3975 webViewHelper.webView()->handleInputEvent(fatTap(0, 0));
3976 EXPECT_FALSE(client.triggered());
3978 client.resetTriggered();
3979 webViewHelper.webView()->handleInputEvent(fatTap(200, 115));
3980 EXPECT_FALSE(client.triggered());
3982 for (int i = 0; i <= 46; i++) {
3983 client.resetTriggered();
3984 webViewHelper.webView()->handleInputEvent(fatTap(120, 230 + i * 5));
3985 EXPECT_FALSE(client.triggered());
3988 for (int i = 0; i <= 46; i++) {
3989 client.resetTriggered();
3990 webViewHelper.webView()->handleInputEvent(fatTap(10 + i * 5, 590));
3991 EXPECT_FALSE(client.triggered());
3995 TEST_F(WebFrameTest, DisambiguationPopupBlacklist)
3997 const unsigned viewportWidth = 500;
3998 const unsigned viewportHeight = 1000;
3999 const unsigned divHeight = 100;
4000 const std::string htmlFile = "disambiguation_popup_blacklist.html";
4001 registerMockedHttpURLLoad(htmlFile);
4003 DisambiguationPopupTestWebViewClient client;
4005 // Make sure we initialize to minimum scale, even if the window size
4006 // only becomes available after the load begins.
4007 FrameTestHelpers::WebViewHelper webViewHelper;
4008 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client);
4009 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
4010 webViewHelper.webView()->layout();
4012 // Click somewhere where the popup shouldn't appear.
4013 client.resetTriggered();
4014 webViewHelper.webView()->handleInputEvent(fatTap(viewportWidth / 2, 0));
4015 EXPECT_FALSE(client.triggered());
4017 // Click directly in between two container divs with click handlers, with children that don't handle clicks.
4018 client.resetTriggered();
4019 webViewHelper.webView()->handleInputEvent(fatTap(viewportWidth / 2, divHeight));
4020 EXPECT_TRUE(client.triggered());
4022 // The third div container should be blacklisted if you click on the link it contains.
4023 client.resetTriggered();
4024 webViewHelper.webView()->handleInputEvent(fatTap(viewportWidth / 2, divHeight * 3.25));
4025 EXPECT_FALSE(client.triggered());
4028 TEST_F(WebFrameTest, DisambiguationPopupPageScale)
4030 registerMockedHttpURLLoad("disambiguation_popup_page_scale.html");
4032 DisambiguationPopupTestWebViewClient client;
4034 // Make sure we initialize to minimum scale, even if the window size
4035 // only becomes available after the load begins.
4036 FrameTestHelpers::WebViewHelper webViewHelper;
4037 webViewHelper.initializeAndLoad(m_baseURL + "disambiguation_popup_page_scale.html", true, 0, &client);
4038 webViewHelper.webView()->resize(WebSize(1000, 1000));
4039 webViewHelper.webView()->layout();
4041 client.resetTriggered();
4042 webViewHelper.webView()->handleInputEvent(fatTap(80, 80));
4043 EXPECT_TRUE(client.triggered());
4045 client.resetTriggered();
4046 webViewHelper.webView()->handleInputEvent(fatTap(230, 190));
4047 EXPECT_TRUE(client.triggered());
4049 webViewHelper.webView()->setPageScaleFactor(3.0f);
4050 webViewHelper.webView()->layout();
4052 client.resetTriggered();
4053 webViewHelper.webView()->handleInputEvent(fatTap(240, 240));
4054 EXPECT_TRUE(client.triggered());
4056 client.resetTriggered();
4057 webViewHelper.webView()->handleInputEvent(fatTap(690, 570));
4058 EXPECT_FALSE(client.triggered());
4061 class TestSubstituteDataWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
4063 TestSubstituteDataWebFrameClient()
4064 : m_commitCalled(false)
4068 virtual void didFailProvisionalLoad(WebLocalFrame* frame, const WebURLError& error)
4070 frame->loadHTMLString("This should appear", toKURL("data:text/html,chromewebdata"), error.unreachableURL, true);
4074 virtual void didCommitProvisionalLoad(WebLocalFrame* frame, const WebHistoryItem&, WebHistoryCommitType)
4076 if (frame->dataSource()->response().url() != WebURL(URLTestHelpers::toKURL("about:blank")))
4077 m_commitCalled = true;
4080 bool commitCalled() const { return m_commitCalled; }
4083 bool m_commitCalled;
4086 TEST_F(WebFrameTest, ReplaceNavigationAfterHistoryNavigation)
4088 TestSubstituteDataWebFrameClient webFrameClient;
4090 FrameTestHelpers::WebViewHelper webViewHelper;
4091 webViewHelper.initializeAndLoad("about:blank", true, &webFrameClient);
4093 WebFrame* frame = webViewHelper.webView()->mainFrame();
4095 // Load a url as a history navigation that will return an error. TestSubstituteDataWebFrameClient
4096 // will start a SubstituteData load in response to the load failure, which should get fully committed.
4097 // Due to https://bugs.webkit.org/show_bug.cgi?id=91685, FrameLoader::didReceiveData() wasn't getting
4098 // called in this case, which resulted in the SubstituteData document not getting displayed.
4100 error.reason = 1337;
4101 error.domain = "WebFrameTest";
4102 std::string errorURL = "http://0.0.0.0";
4103 WebURLResponse response;
4104 response.initialize();
4105 response.setURL(URLTestHelpers::toKURL(errorURL));
4106 response.setMIMEType("text/html");
4107 response.setHTTPStatusCode(500);
4108 WebHistoryItem errorHistoryItem;
4109 errorHistoryItem.initialize();
4110 errorHistoryItem.setURLString(WebString::fromUTF8(errorURL.c_str(), errorURL.length()));
4111 Platform::current()->unitTestSupport()->registerMockedErrorURL(URLTestHelpers::toKURL(errorURL), response, error);
4112 frame->loadHistoryItem(errorHistoryItem, WebHistoryDifferentDocumentLoad, WebURLRequest::UseProtocolCachePolicy);
4113 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4115 WebString text = frame->contentAsText(std::numeric_limits<size_t>::max());
4116 EXPECT_EQ("This should appear", text.utf8());
4117 EXPECT_TRUE(webFrameClient.commitCalled());
4120 class TestWillInsertBodyWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
4122 TestWillInsertBodyWebFrameClient() : m_numBodies(0), m_didLoad(false)
4126 virtual void didCommitProvisionalLoad(WebLocalFrame*, const WebHistoryItem&, WebHistoryCommitType) OVERRIDE
4132 virtual void didCreateDocumentElement(WebLocalFrame*) OVERRIDE
4134 EXPECT_EQ(0, m_numBodies);
4137 virtual void willInsertBody(WebLocalFrame*) OVERRIDE
4146 TEST_F(WebFrameTest, HTMLDocument)
4148 registerMockedHttpURLLoad("clipped-body.html");
4150 TestWillInsertBodyWebFrameClient webFrameClient;
4151 FrameTestHelpers::WebViewHelper webViewHelper;
4152 webViewHelper.initializeAndLoad(m_baseURL + "clipped-body.html", false, &webFrameClient);
4154 EXPECT_TRUE(webFrameClient.m_didLoad);
4155 EXPECT_EQ(1, webFrameClient.m_numBodies);
4158 TEST_F(WebFrameTest, EmptyDocument)
4160 registerMockedHttpURLLoad("pageserializer/green_rectangle.svg");
4162 TestWillInsertBodyWebFrameClient webFrameClient;
4163 FrameTestHelpers::WebViewHelper webViewHelper;
4164 webViewHelper.initialize(false, &webFrameClient);
4166 EXPECT_FALSE(webFrameClient.m_didLoad);
4167 EXPECT_EQ(1, webFrameClient.m_numBodies); // The empty document that a new frame starts with triggers this.
4170 TEST_F(WebFrameTest, MoveCaretSelectionTowardsWindowPointWithNoSelection)
4172 FrameTestHelpers::WebViewHelper webViewHelper;
4173 webViewHelper.initializeAndLoad("about:blank", true);
4174 WebFrame* frame = webViewHelper.webView()->mainFrame();
4176 // This test passes if this doesn't crash.
4177 frame->moveCaretSelection(WebPoint(0, 0));
4180 class SpellCheckClient : public WebSpellCheckClient {
4182 explicit SpellCheckClient(uint32_t hash = 0) : m_numberOfTimesChecked(0), m_hash(hash) { }
4183 virtual ~SpellCheckClient() { }
4184 virtual void requestCheckingOfText(const blink::WebString&, const blink::WebVector<uint32_t>&, const blink::WebVector<unsigned>&, blink::WebTextCheckingCompletion* completion) OVERRIDE
4186 ++m_numberOfTimesChecked;
4187 Vector<WebTextCheckingResult> results;
4188 const int misspellingStartOffset = 1;
4189 const int misspellingLength = 8;
4190 results.append(WebTextCheckingResult(WebTextDecorationTypeSpelling, misspellingStartOffset, misspellingLength, WebString(), m_hash));
4191 completion->didFinishCheckingText(results);
4193 int numberOfTimesChecked() const { return m_numberOfTimesChecked; }
4195 int m_numberOfTimesChecked;
4199 TEST_F(WebFrameTest, ReplaceMisspelledRange)
4201 registerMockedHttpURLLoad("spell.html");
4202 FrameTestHelpers::WebViewHelper webViewHelper;
4203 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4204 SpellCheckClient spellcheck;
4205 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4207 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4208 Document* document = frame->frame()->document();
4209 Element* element = document->getElementById("data");
4211 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4212 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4213 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4216 document->execCommand("InsertText", false, "_wellcome_.");
4218 const int allTextBeginOffset = 0;
4219 const int allTextLength = 11;
4220 frame->selectRange(WebRange::fromDocumentRange(frame, allTextBeginOffset, allTextLength));
4221 RefPtrWillBeRawPtr<Range> selectionRange = frame->frame()->selection().toNormalizedRange();
4223 EXPECT_EQ(1, spellcheck.numberOfTimesChecked());
4224 EXPECT_EQ(1U, document->markers().markersInRange(selectionRange.get(), DocumentMarker::Spelling).size());
4226 frame->replaceMisspelledRange("welcome");
4227 EXPECT_EQ("_welcome_.", frame->contentAsText(std::numeric_limits<size_t>::max()).utf8());
4230 TEST_F(WebFrameTest, RemoveSpellingMarkers)
4232 registerMockedHttpURLLoad("spell.html");
4233 FrameTestHelpers::WebViewHelper webViewHelper;
4234 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4235 SpellCheckClient spellcheck;
4236 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4238 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4239 Document* document = frame->frame()->document();
4240 Element* element = document->getElementById("data");
4242 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4243 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4244 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4247 document->execCommand("InsertText", false, "_wellcome_.");
4249 frame->removeSpellingMarkers();
4251 const int allTextBeginOffset = 0;
4252 const int allTextLength = 11;
4253 frame->selectRange(WebRange::fromDocumentRange(frame, allTextBeginOffset, allTextLength));
4254 RefPtrWillBeRawPtr<Range> selectionRange = frame->frame()->selection().toNormalizedRange();
4256 EXPECT_EQ(0U, document->markers().markersInRange(selectionRange.get(), DocumentMarker::Spelling).size());
4259 TEST_F(WebFrameTest, MarkerHashIdentifiers) {
4260 registerMockedHttpURLLoad("spell.html");
4261 FrameTestHelpers::WebViewHelper webViewHelper;
4262 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4264 static const uint32_t kHash = 42;
4265 SpellCheckClient spellcheck(kHash);
4266 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4268 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4269 Document* document = frame->frame()->document();
4270 Element* element = document->getElementById("data");
4272 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4273 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4274 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4277 document->execCommand("InsertText", false, "wellcome.");
4279 WebVector<uint32_t> documentMarkers;
4280 webViewHelper.webView()->spellingMarkers(&documentMarkers);
4281 EXPECT_EQ(1U, documentMarkers.size());
4282 EXPECT_EQ(kHash, documentMarkers[0]);
4285 class StubbornSpellCheckClient : public WebSpellCheckClient {
4287 StubbornSpellCheckClient() : m_completion(0) { }
4288 virtual ~StubbornSpellCheckClient() { }
4290 virtual void requestCheckingOfText(
4291 const blink::WebString&,
4292 const blink::WebVector<uint32_t>&,
4293 const blink::WebVector<unsigned>&,
4294 blink::WebTextCheckingCompletion* completion) OVERRIDE
4296 m_completion = completion;
4299 void kickNoResults()
4301 kick(-1, -1, WebTextDecorationTypeSpelling);
4306 kick(1, 8, WebTextDecorationTypeSpelling);
4311 kick(1, 8, WebTextDecorationTypeGrammar);
4314 void kickInvisibleSpellcheck()
4316 kick(1, 8, WebTextDecorationTypeInvisibleSpellcheck);
4320 void kick(int misspellingStartOffset, int misspellingLength, WebTextDecorationType type)
4324 Vector<WebTextCheckingResult> results;
4325 if (misspellingStartOffset >= 0 && misspellingLength > 0)
4326 results.append(WebTextCheckingResult(type, misspellingStartOffset, misspellingLength));
4327 m_completion->didFinishCheckingText(results);
4331 blink::WebTextCheckingCompletion* m_completion;
4334 TEST_F(WebFrameTest, SlowSpellcheckMarkerPosition)
4336 registerMockedHttpURLLoad("spell.html");
4337 FrameTestHelpers::WebViewHelper webViewHelper;
4338 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4340 StubbornSpellCheckClient spellcheck;
4341 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4343 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4344 WebInputElement webInputElement = frame->document().getElementById("data").to<WebInputElement>();
4345 Document* document = frame->frame()->document();
4346 Element* element = document->getElementById("data");
4348 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4349 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4350 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4353 document->execCommand("InsertText", false, "wellcome ");
4354 webInputElement.setSelectionRange(0, 0);
4355 document->execCommand("InsertText", false, "he");
4359 WebVector<uint32_t> documentMarkers;
4360 webViewHelper.webView()->spellingMarkers(&documentMarkers);
4361 EXPECT_EQ(0U, documentMarkers.size());
4364 // This test verifies that cancelling spelling request does not cause a
4365 // write-after-free when there's no spellcheck client set.
4366 TEST_F(WebFrameTest, CancelSpellingRequestCrash)
4368 registerMockedHttpURLLoad("spell.html");
4369 FrameTestHelpers::WebViewHelper webViewHelper;
4370 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4371 webViewHelper.webView()->setSpellCheckClient(0);
4373 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4374 Document* document = frame->frame()->document();
4375 Element* element = document->getElementById("data");
4377 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4378 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4379 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4382 frame->frame()->editor().replaceSelectionWithText("A", false, false);
4383 frame->frame()->spellChecker().cancelCheck();
4386 TEST_F(WebFrameTest, SpellcheckResultErasesMarkers)
4388 registerMockedHttpURLLoad("spell.html");
4389 FrameTestHelpers::WebViewHelper webViewHelper;
4390 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4392 StubbornSpellCheckClient spellcheck;
4393 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4395 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4396 WebInputElement webInputElement = frame->document().getElementById("data").to<WebInputElement>();
4397 Document* document = frame->frame()->document();
4398 Element* element = document->getElementById("data");
4400 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4401 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4402 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4405 document->execCommand("InsertText", false, "welcome ");
4406 document->markers().addMarker(rangeOfContents(element->toNode()).get(), DocumentMarker::Spelling);
4407 document->markers().addMarker(rangeOfContents(element->toNode()).get(), DocumentMarker::Grammar);
4408 document->markers().addMarker(rangeOfContents(element->toNode()).get(), DocumentMarker::InvisibleSpellcheck);
4409 EXPECT_EQ(3U, document->markers().markers().size());
4411 spellcheck.kickNoResults();
4412 EXPECT_EQ(0U, document->markers().markers().size());
4415 TEST_F(WebFrameTest, SpellcheckResultsSavedInDocument)
4417 registerMockedHttpURLLoad("spell.html");
4418 FrameTestHelpers::WebViewHelper webViewHelper;
4419 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4421 StubbornSpellCheckClient spellcheck;
4422 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4424 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4425 WebInputElement webInputElement = frame->document().getElementById("data").to<WebInputElement>();
4426 Document* document = frame->frame()->document();
4427 Element* element = document->getElementById("data");
4429 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4430 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4431 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4434 document->execCommand("InsertText", false, "wellcome ");
4437 ASSERT_EQ(1U, document->markers().markers().size());
4438 ASSERT_NE(static_cast<DocumentMarker*>(0), document->markers().markers()[0]);
4439 EXPECT_EQ(DocumentMarker::Spelling, document->markers().markers()[0]->type());
4441 document->execCommand("InsertText", false, "wellcome ");
4443 spellcheck.kickGrammar();
4444 ASSERT_EQ(1U, document->markers().markers().size());
4445 ASSERT_NE(static_cast<DocumentMarker*>(0), document->markers().markers()[0]);
4446 EXPECT_EQ(DocumentMarker::Grammar, document->markers().markers()[0]->type());
4448 document->execCommand("InsertText", false, "wellcome ");
4450 spellcheck.kickInvisibleSpellcheck();
4451 ASSERT_EQ(1U, document->markers().markers().size());
4452 ASSERT_NE(static_cast<DocumentMarker*>(0), document->markers().markers()[0]);
4453 EXPECT_EQ(DocumentMarker::InvisibleSpellcheck, document->markers().markers()[0]->type());
4456 class TestAccessInitialDocumentWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
4458 TestAccessInitialDocumentWebFrameClient() : m_didAccessInitialDocument(false)
4462 virtual void didAccessInitialDocument(WebLocalFrame* frame)
4464 EXPECT_TRUE(!m_didAccessInitialDocument);
4465 m_didAccessInitialDocument = true;
4468 bool m_didAccessInitialDocument;
4471 TEST_F(WebFrameTest, DidAccessInitialDocumentBody)
4473 // FIXME: Why is this local webViewClient needed instead of the default
4474 // WebViewHelper one? With out it there's some mysterious crash in the
4475 // WebViewHelper destructor.
4476 FrameTestHelpers::TestWebViewClient webViewClient;
4477 TestAccessInitialDocumentWebFrameClient webFrameClient;
4478 FrameTestHelpers::WebViewHelper webViewHelper;
4479 webViewHelper.initialize(true, &webFrameClient, &webViewClient);
4481 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4483 // Create another window that will try to access it.
4484 FrameTestHelpers::WebViewHelper newWebViewHelper;
4485 WebView* newView = newWebViewHelper.initialize(true);
4486 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
4488 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4490 // Access the initial document by modifying the body.
4491 newView->mainFrame()->executeScript(
4492 WebScriptSource("window.opener.document.body.innerHTML += 'Modified';"));
4494 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4496 // Access the initial document again, to ensure we don't notify twice.
4497 newView->mainFrame()->executeScript(
4498 WebScriptSource("window.opener.document.body.innerHTML += 'Modified';"));
4500 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4503 TEST_F(WebFrameTest, DidAccessInitialDocumentNavigator)
4505 // FIXME: Why is this local webViewClient needed instead of the default
4506 // WebViewHelper one? With out it there's some mysterious crash in the
4507 // WebViewHelper destructor.
4508 FrameTestHelpers::TestWebViewClient webViewClient;
4509 TestAccessInitialDocumentWebFrameClient webFrameClient;
4510 FrameTestHelpers::WebViewHelper webViewHelper;
4511 webViewHelper.initialize(true, &webFrameClient, &webViewClient);
4513 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4515 // Create another window that will try to access it.
4516 FrameTestHelpers::WebViewHelper newWebViewHelper;
4517 WebView* newView = newWebViewHelper.initialize(true);
4518 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
4520 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4522 // Access the initial document to get to the navigator object.
4523 newView->mainFrame()->executeScript(
4524 WebScriptSource("console.log(window.opener.navigator);"));
4526 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4529 TEST_F(WebFrameTest, DidAccessInitialDocumentViaJavascriptUrl)
4531 TestAccessInitialDocumentWebFrameClient webFrameClient;
4532 FrameTestHelpers::WebViewHelper webViewHelper;
4533 webViewHelper.initialize(true, &webFrameClient);
4535 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4537 // Access the initial document from a javascript: URL.
4538 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.appendChild(document.createTextNode('Modified'))");
4540 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4543 // Fails on the WebKit XP (deps) bot. http://crbug.com/312192
4545 TEST_F(WebFrameTest, DISABLED_DidAccessInitialDocumentBodyBeforeModalDialog)
4547 TEST_F(WebFrameTest, DidAccessInitialDocumentBodyBeforeModalDialog)
4550 // FIXME: Why is this local webViewClient needed instead of the default
4551 // WebViewHelper one? With out it there's some mysterious crash in the
4552 // WebViewHelper destructor.
4553 FrameTestHelpers::TestWebViewClient webViewClient;
4554 TestAccessInitialDocumentWebFrameClient webFrameClient;
4555 FrameTestHelpers::WebViewHelper webViewHelper;
4556 webViewHelper.initialize(true, &webFrameClient, &webViewClient);
4558 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4560 // Create another window that will try to access it.
4561 FrameTestHelpers::WebViewHelper newWebViewHelper;
4562 WebView* newView = newWebViewHelper.initialize(true);
4563 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
4565 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4567 // Access the initial document by modifying the body. We normally set a
4568 // timer to notify the client.
4569 newView->mainFrame()->executeScript(
4570 WebScriptSource("window.opener.document.body.innerHTML += 'Modified';"));
4571 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4573 // Make sure that a modal dialog forces us to notify right away.
4574 newView->mainFrame()->executeScript(
4575 WebScriptSource("window.opener.confirm('Modal');"));
4576 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4578 // Ensure that we don't notify again later.
4580 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4583 // Fails on the WebKit XP (deps) bot. http://crbug.com/312192
4585 TEST_F(WebFrameTest, DISABLED_DidWriteToInitialDocumentBeforeModalDialog)
4587 TEST_F(WebFrameTest, DidWriteToInitialDocumentBeforeModalDialog)
4590 // FIXME: Why is this local webViewClient needed instead of the default
4591 // WebViewHelper one? With out it there's some mysterious crash in the
4592 // WebViewHelper destructor.
4593 FrameTestHelpers::TestWebViewClient webViewClient;
4594 TestAccessInitialDocumentWebFrameClient webFrameClient;
4595 FrameTestHelpers::WebViewHelper webViewHelper;
4596 webViewHelper.initialize(true, &webFrameClient, &webViewClient);
4598 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4600 // Create another window that will try to access it.
4601 FrameTestHelpers::WebViewHelper newWebViewHelper;
4602 WebView* newView = newWebViewHelper.initialize(true);
4603 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
4605 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4607 // Access the initial document with document.write, which moves us past the
4608 // initial empty document state of the state machine. We normally set a
4609 // timer to notify the client.
4610 newView->mainFrame()->executeScript(
4611 WebScriptSource("window.opener.document.write('Modified');"));
4612 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4614 // Make sure that a modal dialog forces us to notify right away.
4615 newView->mainFrame()->executeScript(
4616 WebScriptSource("window.opener.confirm('Modal');"));
4617 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4619 // Ensure that we don't notify again later.
4621 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4624 class TestMainFrameUserOrProgrammaticScrollFrameClient : public FrameTestHelpers::TestWebFrameClient {
4626 TestMainFrameUserOrProgrammaticScrollFrameClient() { reset(); }
4629 m_didScrollMainFrame = false;
4630 m_wasProgrammaticScroll = false;
4632 bool wasUserScroll() const { return m_didScrollMainFrame && !m_wasProgrammaticScroll; }
4633 bool wasProgrammaticScroll() const { return m_didScrollMainFrame && m_wasProgrammaticScroll; }
4636 virtual void didChangeScrollOffset(WebLocalFrame* frame) OVERRIDE
4638 if (frame->parent())
4640 EXPECT_FALSE(m_didScrollMainFrame);
4641 WebCore::FrameView* view = toWebLocalFrameImpl(frame)->frameView();
4642 // FrameView can be scrolled in FrameView::setFixedVisibleContentRect
4643 // which is called from LocalFrame::createView (before the frame is associated
4644 // with the the view).
4646 m_didScrollMainFrame = true;
4647 m_wasProgrammaticScroll = view->inProgrammaticScroll();
4651 bool m_didScrollMainFrame;
4652 bool m_wasProgrammaticScroll;
4655 TEST_F(WebFrameTest, CompositorScrollIsUserScrollLongPage)
4657 registerMockedHttpURLLoad("long_scroll.html");
4658 TestMainFrameUserOrProgrammaticScrollFrameClient client;
4660 // Make sure we initialize to minimum scale, even if the window size
4661 // only becomes available after the load begins.
4662 FrameTestHelpers::WebViewHelper webViewHelper;
4663 webViewHelper.initializeAndLoad(m_baseURL + "long_scroll.html", true, &client);
4664 webViewHelper.webView()->resize(WebSize(1000, 1000));
4665 webViewHelper.webView()->layout();
4667 EXPECT_FALSE(client.wasUserScroll());
4668 EXPECT_FALSE(client.wasProgrammaticScroll());
4670 // Do a compositor scroll, verify that this is counted as a user scroll.
4671 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(0, 1), 1.1f);
4672 EXPECT_TRUE(client.wasUserScroll());
4675 EXPECT_FALSE(client.wasUserScroll());
4676 EXPECT_FALSE(client.wasProgrammaticScroll());
4678 // The page scale 1.0f and scroll.
4679 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(0, 1), 1.0f);
4680 EXPECT_TRUE(client.wasUserScroll());
4683 // No scroll event if there is no scroll delta.
4684 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.0f);
4685 EXPECT_FALSE(client.wasUserScroll());
4686 EXPECT_FALSE(client.wasProgrammaticScroll());
4689 // Non zero page scale and scroll.
4690 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(9, 13), 0.6f);
4691 EXPECT_TRUE(client.wasUserScroll());
4694 // Programmatic scroll.
4695 WebLocalFrameImpl* frameImpl = webViewHelper.webViewImpl()->mainFrameImpl();
4696 frameImpl->executeScript(WebScriptSource("window.scrollTo(0, 20);"));
4697 EXPECT_FALSE(client.wasUserScroll());
4698 EXPECT_TRUE(client.wasProgrammaticScroll());
4701 // Programmatic scroll to same offset. No scroll event should be generated.
4702 frameImpl->executeScript(WebScriptSource("window.scrollTo(0, 20);"));
4703 EXPECT_FALSE(client.wasProgrammaticScroll());
4704 EXPECT_FALSE(client.wasUserScroll());
4708 TEST_F(WebFrameTest, CompositorScrollIsUserScrollShortPage)
4710 registerMockedHttpURLLoad("short_scroll.html");
4712 TestMainFrameUserOrProgrammaticScrollFrameClient client;
4714 // Short page tests.
4715 FrameTestHelpers::WebViewHelper webViewHelper;
4716 webViewHelper.initializeAndLoad(m_baseURL + "short_scroll.html", true, &client);
4718 webViewHelper.webView()->resize(WebSize(1000, 1000));
4719 webViewHelper.webView()->layout();
4721 EXPECT_FALSE(client.wasUserScroll());
4722 EXPECT_FALSE(client.wasProgrammaticScroll());
4724 // Non zero page scale and scroll.
4725 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(9, 13), 2.0f);
4726 EXPECT_FALSE(client.wasProgrammaticScroll());
4727 EXPECT_TRUE(client.wasUserScroll());
4731 TEST_F(WebFrameTest, FirstPartyForCookiesForRedirect)
4733 WTF::String filePath = Platform::current()->unitTestSupport()->webKitRootDir();
4734 filePath.append("/Source/web/tests/data/first_party.html");
4736 WebURL testURL(toKURL("http://www.test.com/first_party_redirect.html"));
4737 char redirect[] = "http://www.test.com/first_party.html";
4738 WebURL redirectURL(toKURL(redirect));
4739 WebURLResponse redirectResponse;
4740 redirectResponse.initialize();
4741 redirectResponse.setMIMEType("text/html");
4742 redirectResponse.setHTTPStatusCode(302);
4743 redirectResponse.setHTTPHeaderField("Location", redirect);
4744 Platform::current()->unitTestSupport()->registerMockedURL(testURL, redirectResponse, filePath);
4746 WebURLResponse finalResponse;
4747 finalResponse.initialize();
4748 finalResponse.setMIMEType("text/html");
4749 Platform::current()->unitTestSupport()->registerMockedURL(redirectURL, finalResponse, filePath);
4751 FrameTestHelpers::WebViewHelper webViewHelper;
4752 webViewHelper.initializeAndLoad(m_baseURL + "first_party_redirect.html", true);
4753 EXPECT_TRUE(webViewHelper.webView()->mainFrame()->document().firstPartyForCookies() == redirectURL);
4756 class TestNavigationPolicyWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
4759 virtual void didNavigateWithinPage(WebLocalFrame*, const WebHistoryItem&, WebHistoryCommitType) OVERRIDE
4765 TEST_F(WebFrameTest, SimulateFragmentAnchorMiddleClick)
4767 registerMockedHttpURLLoad("fragment_middle_click.html");
4768 TestNavigationPolicyWebFrameClient client;
4769 FrameTestHelpers::WebViewHelper webViewHelper;
4770 webViewHelper.initializeAndLoad(m_baseURL + "fragment_middle_click.html", true, &client);
4772 WebCore::Document* document = webViewHelper.webViewImpl()->page()->mainFrame()->document();
4773 WebCore::KURL destination = document->url();
4774 destination.setFragmentIdentifier("test");
4776 RefPtrWillBeRawPtr<WebCore::Event> event = WebCore::MouseEvent::create(WebCore::EventTypeNames::click, false, false,
4777 document->domWindow(), 0, 0, 0, 0, 0, 0, 0, false, false, false, false, 1, nullptr, nullptr);
4778 WebCore::FrameLoadRequest frameRequest(document, WebCore::ResourceRequest(destination));
4779 frameRequest.setTriggeringEvent(event);
4780 webViewHelper.webViewImpl()->page()->mainFrame()->loader().load(frameRequest);
4783 class TestNewWindowWebViewClient : public FrameTestHelpers::TestWebViewClient {
4785 virtual WebView* createView(WebLocalFrame*, const WebURLRequest&, const WebWindowFeatures&,
4786 const WebString&, WebNavigationPolicy, bool) OVERRIDE
4793 class TestNewWindowWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
4795 TestNewWindowWebFrameClient()
4796 : m_decidePolicyCallCount(0)
4800 virtual WebNavigationPolicy decidePolicyForNavigation(WebLocalFrame*, WebDataSource::ExtraData*, const WebURLRequest&,
4801 WebNavigationType, WebNavigationPolicy policy, bool) OVERRIDE
4803 m_decidePolicyCallCount++;
4807 int decidePolicyCallCount() const { return m_decidePolicyCallCount; }
4810 int m_decidePolicyCallCount;
4813 TEST_F(WebFrameTest, ModifiedClickNewWindow)
4815 registerMockedHttpURLLoad("ctrl_click.html");
4816 registerMockedHttpURLLoad("hello_world.html");
4817 TestNewWindowWebViewClient webViewClient;
4818 TestNewWindowWebFrameClient webFrameClient;
4819 FrameTestHelpers::WebViewHelper webViewHelper;
4820 webViewHelper.initializeAndLoad(m_baseURL + "ctrl_click.html", true, &webFrameClient, &webViewClient);
4822 WebCore::Document* document = webViewHelper.webViewImpl()->page()->mainFrame()->document();
4823 WebCore::KURL destination = toKURL(m_baseURL + "hello_world.html");
4826 RefPtrWillBeRawPtr<WebCore::Event> event = WebCore::MouseEvent::create(WebCore::EventTypeNames::click, false, false,
4827 document->domWindow(), 0, 0, 0, 0, 0, 0, 0, true, false, false, false, 0, nullptr, nullptr);
4828 WebCore::FrameLoadRequest frameRequest(document, WebCore::ResourceRequest(destination));
4829 frameRequest.setTriggeringEvent(event);
4830 WebCore::UserGestureIndicator gesture(WebCore::DefinitelyProcessingUserGesture);
4831 webViewHelper.webViewImpl()->page()->mainFrame()->loader().load(frameRequest);
4833 // decidePolicyForNavigation should be called both for the original request and the ctrl+click.
4834 EXPECT_EQ(2, webFrameClient.decidePolicyCallCount());
4837 TEST_F(WebFrameTest, BackToReload)
4839 registerMockedHttpURLLoad("fragment_middle_click.html");
4840 FrameTestHelpers::WebViewHelper webViewHelper;
4841 webViewHelper.initializeAndLoad(m_baseURL + "fragment_middle_click.html", true);
4842 WebFrame* frame = webViewHelper.webView()->mainFrame();
4843 const WebCore::FrameLoader& mainFrameLoader = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->loader();
4844 RefPtr<WebCore::HistoryItem> firstItem = mainFrameLoader.currentItem();
4845 EXPECT_TRUE(firstItem);
4847 registerMockedHttpURLLoad("white-1x1.png");
4848 FrameTestHelpers::loadFrame(frame, m_baseURL + "white-1x1.png");
4849 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4850 EXPECT_NE(firstItem.get(), mainFrameLoader.currentItem());
4852 frame->loadHistoryItem(WebHistoryItem(firstItem.get()), WebHistoryDifferentDocumentLoad, WebURLRequest::UseProtocolCachePolicy);
4853 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4854 EXPECT_EQ(firstItem.get(), mainFrameLoader.currentItem());
4857 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4858 EXPECT_EQ(WebURLRequest::ReloadIgnoringCacheData, frame->dataSource()->request().cachePolicy());
4861 TEST_F(WebFrameTest, BackDuringChildFrameReload)
4863 registerMockedHttpURLLoad("page_with_blank_iframe.html");
4864 FrameTestHelpers::WebViewHelper webViewHelper;
4865 webViewHelper.initializeAndLoad(m_baseURL + "page_with_blank_iframe.html", true);
4866 WebFrame* mainFrame = webViewHelper.webView()->mainFrame();
4867 const WebCore::FrameLoader& mainFrameLoader = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->loader();
4868 WebFrame* childFrame = mainFrame->firstChild();
4869 ASSERT_TRUE(childFrame);
4871 // Start a history navigation, then have a different frame commit a navigation.
4872 // In this case, reload an about:blank frame, which will commit synchronously.
4873 // After the history navigation completes, both the appropriate document url and
4874 // the current history item should reflect the history navigation.
4875 registerMockedHttpURLLoad("white-1x1.png");
4876 WebHistoryItem item;
4878 WebURL historyURL(toKURL(m_baseURL + "white-1x1.png"));
4879 item.setURLString(historyURL.string());
4880 mainFrame->loadHistoryItem(item, WebHistoryDifferentDocumentLoad, WebURLRequest::UseProtocolCachePolicy);
4882 childFrame->reload();
4883 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4884 EXPECT_EQ(item.urlString(), mainFrame->document().url().string());
4885 EXPECT_EQ(item.urlString(), WebString(mainFrameLoader.currentItem()->urlString()));
4888 TEST_F(WebFrameTest, ReloadPost)
4890 registerMockedHttpURLLoad("reload_post.html");
4891 FrameTestHelpers::WebViewHelper webViewHelper;
4892 webViewHelper.initializeAndLoad(m_baseURL + "reload_post.html", true);
4893 WebFrame* frame = webViewHelper.webView()->mainFrame();
4895 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.forms[0].submit()");
4897 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4898 EXPECT_EQ(WebString::fromUTF8("POST"), frame->dataSource()->request().httpMethod());
4901 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4902 EXPECT_EQ(WebURLRequest::ReloadIgnoringCacheData, frame->dataSource()->request().cachePolicy());
4903 EXPECT_EQ(WebNavigationTypeFormResubmitted, frame->dataSource()->navigationType());
4906 TEST_F(WebFrameTest, LoadHistoryItemReload)
4908 registerMockedHttpURLLoad("fragment_middle_click.html");
4909 FrameTestHelpers::WebViewHelper webViewHelper;
4910 webViewHelper.initializeAndLoad(m_baseURL + "fragment_middle_click.html", true);
4911 WebFrame* frame = webViewHelper.webView()->mainFrame();
4912 const WebCore::FrameLoader& mainFrameLoader = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->loader();
4913 RefPtr<WebCore::HistoryItem> firstItem = mainFrameLoader.currentItem();
4914 EXPECT_TRUE(firstItem);
4916 registerMockedHttpURLLoad("white-1x1.png");
4917 FrameTestHelpers::loadFrame(frame, m_baseURL + "white-1x1.png");
4918 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4919 EXPECT_NE(firstItem.get(), mainFrameLoader.currentItem());
4921 // Cache policy overrides should take.
4922 frame->loadHistoryItem(WebHistoryItem(firstItem), WebHistoryDifferentDocumentLoad, WebURLRequest::ReloadIgnoringCacheData);
4923 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4924 EXPECT_EQ(firstItem.get(), mainFrameLoader.currentItem());
4925 EXPECT_EQ(WebURLRequest::ReloadIgnoringCacheData, frame->dataSource()->request().cachePolicy());
4929 class TestCachePolicyWebFrameClient : public WebFrameClient {
4931 TestCachePolicyWebFrameClient()
4932 : m_policy(WebURLRequest::UseProtocolCachePolicy)
4934 , m_willSendRequestCallCount(0)
4935 , m_childFrameCreationCount(0)
4939 void setChildWebFrameClient(WebFrameClient* client) { m_client = client; }
4940 WebURLRequest::CachePolicy cachePolicy() const { return m_policy; }
4941 int willSendRequestCallCount() const { return m_willSendRequestCallCount; }
4942 int childFrameCreationCount() const { return m_childFrameCreationCount; }
4944 virtual WebFrame* createChildFrame(WebLocalFrame* parent, const WebString&)
4946 m_childFrameCreationCount++;
4947 WebFrame* frame = WebLocalFrame::create(m_client);
4948 parent->appendChild(frame);
4952 virtual void frameDetached(WebFrame* frame) OVERRIDE
4954 if (frame->parent())
4955 frame->parent()->removeChild(frame);
4959 virtual void willSendRequest(WebLocalFrame* frame, unsigned, WebURLRequest& request, const WebURLResponse&) OVERRIDE
4961 m_policy = request.cachePolicy();
4962 m_willSendRequestCallCount++;
4966 WebURLRequest::CachePolicy m_policy;
4967 WebFrameClient* m_client;
4968 int m_willSendRequestCallCount;
4969 int m_childFrameCreationCount;
4972 TEST_F(WebFrameTest, ReloadIframe)
4974 registerMockedHttpURLLoad("iframe_reload.html");
4975 registerMockedHttpURLLoad("visible_iframe.html");
4976 TestCachePolicyWebFrameClient mainClient;
4977 TestCachePolicyWebFrameClient childClient;
4978 mainClient.setChildWebFrameClient(&childClient);
4980 FrameTestHelpers::WebViewHelper webViewHelper;
4981 webViewHelper.initializeAndLoad(m_baseURL + "iframe_reload.html", true, &mainClient);
4983 WebLocalFrameImpl* mainFrame = webViewHelper.webViewImpl()->mainFrameImpl();
4984 RefPtr<WebLocalFrameImpl> childFrame = toWebLocalFrameImpl(mainFrame->firstChild());
4985 ASSERT_EQ(childFrame->client(), &childClient);
4986 EXPECT_EQ(mainClient.childFrameCreationCount(), 1);
4987 EXPECT_EQ(childClient.willSendRequestCallCount(), 1);
4988 EXPECT_EQ(childClient.cachePolicy(), WebURLRequest::UseProtocolCachePolicy);
4990 mainFrame->reload(false);
4991 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4993 // A new WebFrame should have been created, but the child WebFrameClient should be reused.
4994 ASSERT_NE(childFrame, toWebLocalFrameImpl(mainFrame->firstChild()));
4995 ASSERT_EQ(toWebLocalFrameImpl(mainFrame->firstChild())->client(), &childClient);
4997 EXPECT_EQ(mainClient.childFrameCreationCount(), 2);
4998 EXPECT_EQ(childClient.willSendRequestCallCount(), 2);
4999 EXPECT_EQ(childClient.cachePolicy(), WebURLRequest::ReloadIgnoringCacheData);
5002 class TestSameDocumentWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5004 TestSameDocumentWebFrameClient()
5005 : m_frameLoadTypeSameSeen(false)
5009 virtual void willSendRequest(WebLocalFrame* frame, unsigned, WebURLRequest&, const WebURLResponse&)
5011 if (toWebLocalFrameImpl(frame)->frame()->loader().loadType() == WebCore::FrameLoadTypeSame)
5012 m_frameLoadTypeSameSeen = true;
5015 bool frameLoadTypeSameSeen() const { return m_frameLoadTypeSameSeen; }
5018 bool m_frameLoadTypeSameSeen;
5021 TEST_F(WebFrameTest, NavigateToSame)
5023 registerMockedHttpURLLoad("navigate_to_same.html");
5024 TestSameDocumentWebFrameClient client;
5025 FrameTestHelpers::WebViewHelper webViewHelper;
5026 webViewHelper.initializeAndLoad(m_baseURL + "navigate_to_same.html", true, &client);
5027 EXPECT_FALSE(client.frameLoadTypeSameSeen());
5029 WebCore::FrameLoadRequest frameRequest(0, WebCore::ResourceRequest(webViewHelper.webViewImpl()->page()->mainFrame()->document()->url()));
5030 webViewHelper.webViewImpl()->page()->mainFrame()->loader().load(frameRequest);
5031 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
5033 EXPECT_TRUE(client.frameLoadTypeSameSeen());
5036 TEST_F(WebFrameTest, WebNodeImageContents)
5038 FrameTestHelpers::WebViewHelper webViewHelper;
5039 webViewHelper.initializeAndLoad("about:blank", true);
5040 WebFrame* frame = webViewHelper.webView()->mainFrame();
5042 static const char bluePNG[] = "<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAGElEQVQYV2NkYPj/n4EIwDiqEF8oUT94AFIQE/cCn90IAAAAAElFTkSuQmCC\">";
5044 // Load up the image and test that we can extract the contents.
5045 WebCore::KURL testURL = toKURL("about:blank");
5046 frame->loadHTMLString(bluePNG, testURL);
5049 WebNode node = frame->document().body().firstChild();
5050 EXPECT_TRUE(node.isElementNode());
5051 WebElement element = node.to<WebElement>();
5052 WebImage image = element.imageContents();
5053 ASSERT_FALSE(image.isNull());
5054 EXPECT_EQ(image.size().width, 10);
5055 EXPECT_EQ(image.size().height, 10);
5056 // FIXME: The rest of this test is disabled since the ImageDecodeCache state may be inconsistent when this test runs.
5058 // SkBitmap bitmap = image.getSkBitmap();
5059 // SkAutoLockPixels locker(bitmap);
5060 // EXPECT_EQ(bitmap.getColor(0, 0), SK_ColorBLUE);
5063 class TestStartStopCallbackWebFrameClient : public WebFrameClient {
5065 TestStartStopCallbackWebFrameClient()
5066 : m_startLoadingCount(0)
5067 , m_stopLoadingCount(0)
5068 , m_differentDocumentStartCount(0)
5072 virtual void didStartLoading(bool toDifferentDocument) OVERRIDE
5074 m_startLoadingCount++;
5075 if (toDifferentDocument)
5076 m_differentDocumentStartCount++;
5079 virtual void didStopLoading() OVERRIDE
5081 m_stopLoadingCount++;
5084 int startLoadingCount() const { return m_startLoadingCount; }
5085 int stopLoadingCount() const { return m_stopLoadingCount; }
5086 int differentDocumentStartCount() const { return m_differentDocumentStartCount; }
5089 int m_startLoadingCount;
5090 int m_stopLoadingCount;
5091 int m_differentDocumentStartCount;
5094 TEST_F(WebFrameTest, PushStateStartsAndStops)
5096 registerMockedHttpURLLoad("push_state.html");
5097 TestStartStopCallbackWebFrameClient client;
5098 FrameTestHelpers::WebViewHelper webViewHelper;
5099 webViewHelper.initializeAndLoad(m_baseURL + "push_state.html", true, &client);
5102 EXPECT_EQ(client.startLoadingCount(), 2);
5103 EXPECT_EQ(client.stopLoadingCount(), 2);
5104 EXPECT_EQ(client.differentDocumentStartCount(), 1);
5107 class TestHistoryWebFrameClient : public WebFrameClient {
5109 TestHistoryWebFrameClient()
5111 m_replacesCurrentHistoryItem = false;
5114 void didStartProvisionalLoad(WebLocalFrame* frame)
5116 WebDataSource* ds = frame->provisionalDataSource();
5117 m_replacesCurrentHistoryItem = ds->replacesCurrentHistoryItem();
5121 bool replacesCurrentHistoryItem() { return m_replacesCurrentHistoryItem; }
5122 WebFrame* frame() { return m_frame; }
5125 bool m_replacesCurrentHistoryItem;
5129 // Test which ensures that the first navigation in a subframe will always
5130 // result in history entry being replaced and not a new one added.
5131 TEST_F(WebFrameTest, DISABLED_FirstFrameNavigationReplacesHistory)
5133 registerMockedHttpURLLoad("history.html");
5134 registerMockedHttpURLLoad("find.html");
5136 FrameTestHelpers::WebViewHelper webViewHelper;
5137 TestHistoryWebFrameClient client;
5138 webViewHelper.initializeAndLoad("about:blank", true, &client);
5140 EXPECT_TRUE(client.replacesCurrentHistoryItem());
5142 WebFrame* frame = webViewHelper.webView()->mainFrame();
5144 FrameTestHelpers::loadFrame(frame,
5145 "javascript:document.body.appendChild(document.createElement('iframe'))");
5146 // Need to call runPendingTasks in order for the JavaScript above to be
5147 // evaluated and executed.
5149 WebFrame* iframe = frame->firstChild();
5150 EXPECT_EQ(client.frame(), iframe);
5151 EXPECT_TRUE(client.replacesCurrentHistoryItem());
5153 FrameTestHelpers::loadFrame(frame,
5154 "javascript:window.frames[0].location.assign('" + m_baseURL + "history.html')");
5156 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
5157 EXPECT_EQ(client.frame(), iframe);
5158 EXPECT_TRUE(client.replacesCurrentHistoryItem());
5160 FrameTestHelpers::loadFrame(frame,
5161 "javascript:window.frames[0].location.assign('" + m_baseURL + "find.html')");
5163 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
5164 EXPECT_EQ(client.frame(), iframe);
5165 EXPECT_FALSE(client.replacesCurrentHistoryItem());
5167 // Repeat the test, but start out the iframe with initial URL, which is not
5169 FrameTestHelpers::loadFrame(frame,
5170 "javascript:var f = document.createElement('iframe'); "
5171 "f.src = '" + m_baseURL + "history.html';"
5172 "document.body.appendChild(f)");
5174 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
5176 iframe = frame->firstChild()->nextSibling();
5177 EXPECT_EQ(client.frame(), iframe);
5178 EXPECT_TRUE(client.replacesCurrentHistoryItem());
5180 FrameTestHelpers::loadFrame(frame,
5181 "javascript:window.frames[1].location.assign('" + m_baseURL + "find.html')");
5183 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
5184 EXPECT_EQ(client.frame(), iframe);
5185 EXPECT_FALSE(client.replacesCurrentHistoryItem());
5188 // Test verifies that layout will change a layer's scrollable attibutes
5189 TEST_F(WebFrameTest, overflowHiddenRewrite)
5191 registerMockedHttpURLLoad("non-scrollable.html");
5192 TestMainFrameUserOrProgrammaticScrollFrameClient client;
5193 OwnPtr<FakeCompositingWebViewClient> fakeCompositingWebViewClient = adoptPtr(new FakeCompositingWebViewClient());
5194 FrameTestHelpers::WebViewHelper webViewHelper;
5195 webViewHelper.initialize(true, 0, fakeCompositingWebViewClient.get(), &configueCompositingWebView);
5197 webViewHelper.webView()->resize(WebSize(100, 100));
5198 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "non-scrollable.html");
5199 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
5200 webViewHelper.webView()->layout();
5202 WebCore::RenderLayerCompositor* compositor = webViewHelper.webViewImpl()->compositor();
5203 ASSERT_TRUE(compositor->scrollLayer());
5205 // Verify that the WebLayer is not scrollable initially.
5206 WebCore::GraphicsLayer* scrollLayer = compositor->scrollLayer();
5207 WebLayer* webScrollLayer = scrollLayer->platformLayer();
5208 ASSERT_FALSE(webScrollLayer->userScrollableHorizontal());
5209 ASSERT_FALSE(webScrollLayer->userScrollableVertical());
5211 // Call javascript to make the layer scrollable, and verify it.
5212 WebLocalFrameImpl* frame = (WebLocalFrameImpl*)webViewHelper.webView()->mainFrame();
5213 frame->executeScript(WebScriptSource("allowScroll();"));
5214 webViewHelper.webView()->layout();
5215 ASSERT_TRUE(webScrollLayer->userScrollableHorizontal());
5216 ASSERT_TRUE(webScrollLayer->userScrollableVertical());
5219 // Test that currentHistoryItem reflects the current page, not the provisional load.
5220 TEST_F(WebFrameTest, CurrentHistoryItem)
5222 registerMockedHttpURLLoad("fixed_layout.html");
5223 std::string url = m_baseURL + "fixed_layout.html";
5225 FrameTestHelpers::WebViewHelper webViewHelper;
5226 webViewHelper.initialize();
5227 WebFrame* frame = webViewHelper.webView()->mainFrame();
5228 const WebCore::FrameLoader& mainFrameLoader = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->loader();
5229 FrameTestHelpers::loadFrame(frame, url);
5231 // Before commit, there is no history item.
5232 EXPECT_FALSE(mainFrameLoader.currentItem());
5234 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
5236 // After commit, there is.
5237 WebCore::HistoryItem* item = mainFrameLoader.currentItem();
5239 EXPECT_EQ(WTF::String(url.data()), item->urlString());
5242 class FailCreateChildFrame : public WebFrameClient {
5244 FailCreateChildFrame() : m_callCount(0) { }
5246 virtual WebFrame* createChildFrame(WebLocalFrame* parent, const WebString& frameName) OVERRIDE
5252 virtual void frameDetached(WebFrame* frame) OVERRIDE
5257 int callCount() const { return m_callCount; }
5263 // Test that we don't crash if WebFrameClient::createChildFrame() fails.
5264 TEST_F(WebFrameTest, CreateChildFrameFailure)
5266 registerMockedHttpURLLoad("create_child_frame_fail.html");
5267 FailCreateChildFrame client;
5268 FrameTestHelpers::WebViewHelper webViewHelper;
5269 webViewHelper.initializeAndLoad(m_baseURL + "create_child_frame_fail.html", true, &client);
5271 EXPECT_EQ(1, client.callCount());
5274 TEST_F(WebFrameTest, fixedPositionInFixedViewport)
5276 UseMockScrollbarSettings mockScrollbarSettings;
5277 registerMockedHttpURLLoad("fixed-position-in-fixed-viewport.html");
5278 FrameTestHelpers::WebViewHelper webViewHelper;
5279 webViewHelper.initializeAndLoad(m_baseURL + "fixed-position-in-fixed-viewport.html", true, 0, 0, enableViewportSettings);
5281 WebView* webView = webViewHelper.webView();
5282 webView->resize(WebSize(100, 100));
5285 Document* document = toWebLocalFrameImpl(webView->mainFrame())->frame()->document();
5286 Element* bottomFixed = document->getElementById("bottom-fixed");
5287 Element* topBottomFixed = document->getElementById("top-bottom-fixed");
5288 Element* rightFixed = document->getElementById("right-fixed");
5289 Element* leftRightFixed = document->getElementById("left-right-fixed");
5291 webView->resize(WebSize(100, 200));
5293 EXPECT_EQ(200, bottomFixed->offsetTop() + bottomFixed->offsetHeight());
5294 EXPECT_EQ(200, topBottomFixed->offsetHeight());
5296 webView->settings()->setMainFrameResizesAreOrientationChanges(false);
5297 webView->resize(WebSize(200, 200));
5299 EXPECT_EQ(200, rightFixed->offsetLeft() + rightFixed->offsetWidth());
5300 EXPECT_EQ(200, leftRightFixed->offsetWidth());
5302 webView->settings()->setMainFrameResizesAreOrientationChanges(true);
5303 // Will scale the page by 1.5.
5304 webView->resize(WebSize(300, 330));
5306 EXPECT_EQ(220, bottomFixed->offsetTop() + bottomFixed->offsetHeight());
5307 EXPECT_EQ(220, topBottomFixed->offsetHeight());
5308 EXPECT_EQ(200, rightFixed->offsetLeft() + rightFixed->offsetWidth());
5309 EXPECT_EQ(200, leftRightFixed->offsetWidth());
5312 TEST_F(WebFrameTest, FrameViewSetFrameRect)
5314 FrameTestHelpers::WebViewHelper webViewHelper;
5315 webViewHelper.initializeAndLoad("about:blank");
5317 WebCore::FrameView* frameView = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
5318 frameView->setFrameRect(WebCore::IntRect(0, 0, 200, 200));
5319 EXPECT_EQ_RECT(WebCore::IntRect(0, 0, 200, 200), frameView->frameRect());
5320 frameView->setFrameRect(WebCore::IntRect(100, 100, 200, 200));
5321 EXPECT_EQ_RECT(WebCore::IntRect(100, 100, 200, 200), frameView->frameRect());
5324 TEST_F(WebFrameTest, FullscreenLayerNonScrollable)
5326 FakeCompositingWebViewClient client;
5327 registerMockedHttpURLLoad("fullscreen_div.html");
5328 FrameTestHelpers::WebViewHelper webViewHelper;
5329 int viewportWidth = 640;
5330 int viewportHeight = 480;
5331 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "fullscreen_div.html", true, 0, &client, &configueCompositingWebView);
5332 webViewImpl->resize(WebSize(viewportWidth, viewportHeight));
5333 webViewImpl->layout();
5335 Document* document = toWebLocalFrameImpl(webViewImpl->mainFrame())->frame()->document();
5336 WebCore::UserGestureIndicator gesture(WebCore::DefinitelyProcessingUserGesture);
5337 Element* divFullscreen = document->getElementById("div1");
5338 divFullscreen->webkitRequestFullscreen();
5339 webViewImpl->willEnterFullScreen();
5340 webViewImpl->didEnterFullScreen();
5341 webViewImpl->layout();
5343 // Verify that the main frame is not scrollable.
5344 ASSERT_TRUE(WebCore::FullscreenElementStack::isFullScreen(*document));
5345 WebLayer* webScrollLayer = webViewImpl->compositor()->scrollLayer()->platformLayer();
5346 ASSERT_FALSE(webScrollLayer->scrollable());
5348 // Verify that the main frame is scrollable upon exiting fullscreen.
5349 webViewImpl->willExitFullScreen();
5350 webViewImpl->didExitFullScreen();
5351 webViewImpl->layout();
5352 ASSERT_FALSE(WebCore::FullscreenElementStack::isFullScreen(*document));
5353 webScrollLayer = webViewImpl->compositor()->scrollLayer()->platformLayer();
5354 ASSERT_TRUE(webScrollLayer->scrollable());
5357 TEST_F(WebFrameTest, RenderBlockPercentHeightDescendants)
5359 registerMockedHttpURLLoad("percent-height-descendants.html");
5360 FrameTestHelpers::WebViewHelper webViewHelper;
5361 webViewHelper.initializeAndLoad(m_baseURL + "percent-height-descendants.html");
5363 WebView* webView = webViewHelper.webView();
5364 webView->resize(WebSize(800, 800));
5367 Document* document = toWebLocalFrameImpl(webView->mainFrame())->frame()->document();
5368 WebCore::RenderBlock* container = WebCore::toRenderBlock(document->getElementById("container")->renderer());
5369 WebCore::RenderBox* percentHeightInAnonymous = WebCore::toRenderBox(document->getElementById("percent-height-in-anonymous")->renderer());
5370 WebCore::RenderBox* percentHeightDirectChild = WebCore::toRenderBox(document->getElementById("percent-height-direct-child")->renderer());
5372 EXPECT_TRUE(WebCore::RenderBlock::hasPercentHeightDescendant(percentHeightInAnonymous));
5373 EXPECT_TRUE(WebCore::RenderBlock::hasPercentHeightDescendant(percentHeightDirectChild));
5375 ASSERT_TRUE(container->percentHeightDescendants());
5376 ASSERT_TRUE(container->hasPercentHeightDescendants());
5377 EXPECT_EQ(2U, container->percentHeightDescendants()->size());
5378 EXPECT_TRUE(container->percentHeightDescendants()->contains(percentHeightInAnonymous));
5379 EXPECT_TRUE(container->percentHeightDescendants()->contains(percentHeightDirectChild));
5381 WebCore::RenderBlock* anonymousBlock = percentHeightInAnonymous->containingBlock();
5382 EXPECT_TRUE(anonymousBlock->isAnonymous());
5383 EXPECT_FALSE(anonymousBlock->hasPercentHeightDescendants());
5386 TEST_F(WebFrameTest, HasVisibleContentOnVisibleFrames)
5388 registerMockedHttpURLLoad("visible_frames.html");
5389 FrameTestHelpers::WebViewHelper webViewHelper;
5390 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "visible_frames.html");
5391 for (WebFrame* frame = webViewImpl->mainFrameImpl()->traverseNext(false); frame; frame = frame->traverseNext(false)) {
5392 EXPECT_TRUE(frame->hasVisibleContent());
5396 TEST_F(WebFrameTest, HasVisibleContentOnHiddenFrames)
5398 registerMockedHttpURLLoad("hidden_frames.html");
5399 FrameTestHelpers::WebViewHelper webViewHelper;
5400 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "hidden_frames.html");
5401 for (WebFrame* frame = webViewImpl->mainFrameImpl()->traverseNext(false); frame; frame = frame->traverseNext(false)) {
5402 EXPECT_FALSE(frame->hasVisibleContent());
5406 class ManifestChangeWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5408 ManifestChangeWebFrameClient() : m_manifestChangeCount(0) { }
5409 virtual void didChangeManifest(WebLocalFrame*) OVERRIDE
5411 ++m_manifestChangeCount;
5414 int manifestChangeCount() { return m_manifestChangeCount; }
5417 int m_manifestChangeCount;
5420 TEST_F(WebFrameTest, NotifyManifestChange)
5422 registerMockedHttpURLLoad("link-manifest-change.html");
5424 ManifestChangeWebFrameClient webFrameClient;
5425 FrameTestHelpers::WebViewHelper webViewHelper;
5426 webViewHelper.initializeAndLoad(m_baseURL + "link-manifest-change.html", true, &webFrameClient);
5428 EXPECT_EQ(14, webFrameClient.manifestChangeCount());