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"
37 #include "bindings/core/v8/V8Node.h"
38 #include "core/UserAgentStyleSheets.h"
39 #include "core/clipboard/DataTransfer.h"
40 #include "core/css/StyleSheetContents.h"
41 #include "core/css/resolver/StyleResolver.h"
42 #include "core/css/resolver/ViewportStyleResolver.h"
43 #include "core/dom/DocumentMarkerController.h"
44 #include "core/dom/Fullscreen.h"
45 #include "core/dom/NodeRenderStyle.h"
46 #include "core/dom/Range.h"
47 #include "core/editing/Editor.h"
48 #include "core/editing/FrameSelection.h"
49 #include "core/editing/SpellChecker.h"
50 #include "core/editing/VisiblePosition.h"
51 #include "core/events/MouseEvent.h"
52 #include "core/fetch/MemoryCache.h"
53 #include "core/frame/FrameHost.h"
54 #include "core/frame/FrameView.h"
55 #include "core/frame/LocalFrame.h"
56 #include "core/frame/PinchViewport.h"
57 #include "core/frame/Settings.h"
58 #include "core/html/HTMLDocument.h"
59 #include "core/html/HTMLFormElement.h"
60 #include "core/loader/DocumentThreadableLoader.h"
61 #include "core/loader/DocumentThreadableLoaderClient.h"
62 #include "core/loader/FrameLoadRequest.h"
63 #include "core/loader/ThreadableLoader.h"
64 #include "core/page/EventHandler.h"
65 #include "core/page/Page.h"
66 #include "core/rendering/HitTestResult.h"
67 #include "core/rendering/RenderView.h"
68 #include "core/rendering/compositing/RenderLayerCompositor.h"
69 #include "core/testing/URLTestHelpers.h"
70 #include "platform/DragImage.h"
71 #include "platform/RuntimeEnabledFeatures.h"
72 #include "platform/UserGestureIndicator.h"
73 #include "platform/geometry/FloatRect.h"
74 #include "platform/network/ResourceError.h"
75 #include "platform/scroll/ScrollbarTheme.h"
76 #include "platform/weborigin/SchemeRegistry.h"
77 #include "public/platform/Platform.h"
78 #include "public/platform/WebFloatRect.h"
79 #include "public/platform/WebSelectionBound.h"
80 #include "public/platform/WebThread.h"
81 #include "public/platform/WebURL.h"
82 #include "public/platform/WebURLResponse.h"
83 #include "public/platform/WebUnitTestSupport.h"
84 #include "public/web/WebCache.h"
85 #include "public/web/WebDataSource.h"
86 #include "public/web/WebDocument.h"
87 #include "public/web/WebFindOptions.h"
88 #include "public/web/WebFormElement.h"
89 #include "public/web/WebFrameClient.h"
90 #include "public/web/WebHistoryItem.h"
91 #include "public/web/WebPrintParams.h"
92 #include "public/web/WebRange.h"
93 #include "public/web/WebRemoteFrame.h"
94 #include "public/web/WebScriptSource.h"
95 #include "public/web/WebSearchableFormData.h"
96 #include "public/web/WebSecurityOrigin.h"
97 #include "public/web/WebSecurityPolicy.h"
98 #include "public/web/WebSettings.h"
99 #include "public/web/WebSpellCheckClient.h"
100 #include "public/web/WebTextCheckingCompletion.h"
101 #include "public/web/WebTextCheckingResult.h"
102 #include "public/web/WebViewClient.h"
103 #include "web/WebLocalFrameImpl.h"
104 #include "web/WebRemoteFrameImpl.h"
105 #include "web/WebViewImpl.h"
106 #include "web/tests/FrameTestHelpers.h"
107 #include "wtf/Forward.h"
108 #include "wtf/dtoa/utils.h"
109 #include <gmock/gmock.h>
110 #include <gtest/gtest.h>
116 using blink::URLTestHelpers::toKURL;
117 using blink::FrameTestHelpers::runPendingTasks;
118 using namespace blink;
120 const int touchPointPadding = 32;
122 #define EXPECT_RECT_EQ(a, b) \
124 EXPECT_EQ(a.x(), b.x()); \
125 EXPECT_EQ(a.y(), b.y()); \
126 EXPECT_EQ(a.width(), b.width()); \
127 EXPECT_EQ(a.height(), b.height()); \
130 #define EXPECT_POINT_EQ(expected, actual) \
132 EXPECT_EQ((expected).x(), (actual).x()); \
133 EXPECT_EQ((expected).y(), (actual).y()); \
136 #define EXPECT_FLOAT_POINT_EQ(expected, actual) \
138 EXPECT_FLOAT_EQ((expected).x(), (actual).x()); \
139 EXPECT_FLOAT_EQ((expected).y(), (actual).y()); \
142 #define EXPECT_EQ_POINT(a, b) \
143 EXPECT_EQ(a.x(), b.x()); \
144 EXPECT_EQ(a.y(), b.y());
146 class FakeCompositingWebViewClient : public FrameTestHelpers::TestWebViewClient {
148 virtual bool enterFullScreen() OVERRIDE { return true; }
151 class WebFrameTest : public testing::Test {
154 : m_baseURL("http://www.test.com/")
155 , m_chromeURL("chrome://")
159 virtual ~WebFrameTest()
161 Platform::current()->unitTestSupport()->unregisterAllMockedURLs();
164 void registerMockedHttpURLLoad(const std::string& fileName)
166 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8(fileName.c_str()));
169 void registerMockedChromeURLLoad(const std::string& fileName)
171 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_chromeURL.c_str()), WebString::fromUTF8(fileName.c_str()));
174 void applyViewportStyleOverride(FrameTestHelpers::WebViewHelper* webViewHelper)
176 RefPtrWillBeRawPtr<StyleSheetContents> styleSheet = StyleSheetContents::create(CSSParserContext(UASheetMode, 0));
177 styleSheet->parseString(String(blink::viewportAndroidCss, sizeof(blink::viewportAndroidCss)));
178 OwnPtrWillBeRawPtr<RuleSet> ruleSet = RuleSet::create();
179 ruleSet->addRulesFromSheet(styleSheet.get(), MediaQueryEvaluator("screen"));
181 Document* document = toLocalFrame(webViewHelper->webViewImpl()->page()->mainFrame())->document();
182 document->ensureStyleResolver().viewportStyleResolver()->collectViewportRules(ruleSet.get(), ViewportStyleResolver::UserAgentOrigin);
183 document->ensureStyleResolver().viewportStyleResolver()->resolve();
186 static void configueCompositingWebView(WebSettings* settings)
188 settings->setAcceleratedCompositingEnabled(true);
189 settings->setPreferCompositingToLCDTextEnabled(true);
192 static void configureLoadsImagesAutomatically(WebSettings* settings)
194 settings->setLoadsImagesAutomatically(true);
197 void initializeTextSelectionWebView(const std::string& url, FrameTestHelpers::WebViewHelper* webViewHelper)
199 webViewHelper->initializeAndLoad(url, true);
200 webViewHelper->webView()->settings()->setDefaultFontSize(12);
201 webViewHelper->webView()->resize(WebSize(640, 480));
204 PassOwnPtr<DragImage> nodeImageTestSetup(FrameTestHelpers::WebViewHelper* webViewHelper, const std::string& testcase)
206 registerMockedHttpURLLoad("nodeimage.html");
207 webViewHelper->initializeAndLoad(m_baseURL + "nodeimage.html");
208 webViewHelper->webView()->resize(WebSize(640, 480));
209 webViewHelper->webView()->layout();
210 RefPtrWillBeRawPtr<LocalFrame> frame = toLocalFrame(webViewHelper->webViewImpl()->page()->mainFrame());
212 Element* element = frame->document()->getElementById(testcase.c_str());
213 return frame->nodeImage(*element);
216 std::string m_baseURL;
217 std::string m_chromeURL;
220 class UseMockScrollbarSettings {
222 UseMockScrollbarSettings()
224 Settings::setMockScrollbarsEnabled(true);
225 RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(true);
226 EXPECT_TRUE(ScrollbarTheme::theme()->usesOverlayScrollbars());
229 ~UseMockScrollbarSettings()
231 Settings::setMockScrollbarsEnabled(false);
232 RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(false);
236 TEST_F(WebFrameTest, ContentText)
238 registerMockedHttpURLLoad("iframes_test.html");
239 registerMockedHttpURLLoad("visible_iframe.html");
240 registerMockedHttpURLLoad("invisible_iframe.html");
241 registerMockedHttpURLLoad("zero_sized_iframe.html");
243 FrameTestHelpers::WebViewHelper webViewHelper;
244 webViewHelper.initializeAndLoad(m_baseURL + "iframes_test.html");
246 // Now retrieve the frames text and test it only includes visible elements.
247 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
248 EXPECT_NE(std::string::npos, content.find(" visible paragraph"));
249 EXPECT_NE(std::string::npos, content.find(" visible iframe"));
250 EXPECT_EQ(std::string::npos, content.find(" invisible pararaph"));
251 EXPECT_EQ(std::string::npos, content.find(" invisible iframe"));
252 EXPECT_EQ(std::string::npos, content.find("iframe with zero size"));
255 TEST_F(WebFrameTest, FrameForEnteredContext)
257 registerMockedHttpURLLoad("iframes_test.html");
258 registerMockedHttpURLLoad("visible_iframe.html");
259 registerMockedHttpURLLoad("invisible_iframe.html");
260 registerMockedHttpURLLoad("zero_sized_iframe.html");
262 FrameTestHelpers::WebViewHelper webViewHelper;
263 webViewHelper.initializeAndLoad(m_baseURL + "iframes_test.html", true);
265 v8::HandleScope scope(v8::Isolate::GetCurrent());
266 EXPECT_EQ(webViewHelper.webView()->mainFrame(), WebLocalFrame::frameForContext(webViewHelper.webView()->mainFrame()->mainWorldScriptContext()));
267 EXPECT_EQ(webViewHelper.webView()->mainFrame()->firstChild(), WebLocalFrame::frameForContext(webViewHelper.webView()->mainFrame()->firstChild()->mainWorldScriptContext()));
270 TEST_F(WebFrameTest, FormWithNullFrame)
272 registerMockedHttpURLLoad("form.html");
274 FrameTestHelpers::WebViewHelper webViewHelper;
275 webViewHelper.initializeAndLoad(m_baseURL + "form.html");
277 WebVector<WebFormElement> forms;
278 webViewHelper.webView()->mainFrame()->document().forms(forms);
279 webViewHelper.reset();
281 EXPECT_EQ(forms.size(), 1U);
283 // This test passes if this doesn't crash.
284 WebSearchableFormData searchableDataForm(forms[0]);
287 TEST_F(WebFrameTest, ChromePageJavascript)
289 registerMockedChromeURLLoad("history.html");
291 // Pass true to enable JavaScript.
292 FrameTestHelpers::WebViewHelper webViewHelper;
293 webViewHelper.initializeAndLoad(m_chromeURL + "history.html", true);
295 // Try to run JS against the chrome-style URL.
296 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.appendChild(document.createTextNode('Clobbered'))");
298 // Required to see any updates in contentAsText.
299 webViewHelper.webView()->layout();
301 // Now retrieve the frame's text and ensure it was modified by running javascript.
302 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
303 EXPECT_NE(std::string::npos, content.find("Clobbered"));
306 TEST_F(WebFrameTest, ChromePageNoJavascript)
308 registerMockedChromeURLLoad("history.html");
310 /// Pass true to enable JavaScript.
311 FrameTestHelpers::WebViewHelper webViewHelper;
312 webViewHelper.initializeAndLoad(m_chromeURL + "history.html", true);
314 // Try to run JS against the chrome-style URL after prohibiting it.
315 WebSecurityPolicy::registerURLSchemeAsNotAllowingJavascriptURLs("chrome");
316 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.appendChild(document.createTextNode('Clobbered'))");
318 // Required to see any updates in contentAsText.
319 webViewHelper.webView()->layout();
321 // Now retrieve the frame's text and ensure it wasn't modified by running javascript.
322 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
323 EXPECT_EQ(std::string::npos, content.find("Clobbered"));
326 TEST_F(WebFrameTest, LocationSetHostWithMissingPort)
328 std::string fileName = "print-location-href.html";
329 registerMockedHttpURLLoad(fileName);
330 URLTestHelpers::registerMockedURLLoad(toKURL("http://www.test.com:0/" + fileName), WebString::fromUTF8(fileName));
332 FrameTestHelpers::WebViewHelper webViewHelper;
334 /// Pass true to enable JavaScript.
335 webViewHelper.initializeAndLoad(m_baseURL + fileName, true);
337 // Setting host to "hostname:" should be treated as "hostname:0".
338 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:location.host = 'www.test.com:'; void 0;");
340 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.textContent = location.href; void 0;");
342 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
343 EXPECT_EQ("http://www.test.com:0/" + fileName, content);
346 TEST_F(WebFrameTest, LocationSetEmptyPort)
348 std::string fileName = "print-location-href.html";
349 registerMockedHttpURLLoad(fileName);
350 URLTestHelpers::registerMockedURLLoad(toKURL("http://www.test.com:0/" + fileName), WebString::fromUTF8(fileName));
352 FrameTestHelpers::WebViewHelper webViewHelper;
354 /// Pass true to enable JavaScript.
355 webViewHelper.initializeAndLoad(m_baseURL + fileName, true);
357 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:location.port = ''; void 0;");
359 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.textContent = location.href; void 0;");
361 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
362 EXPECT_EQ("http://www.test.com:0/" + fileName, content);
365 class CSSCallbackWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
367 CSSCallbackWebFrameClient() : m_updateCount(0) { }
368 virtual void didMatchCSS(WebLocalFrame*, const WebVector<WebString>& newlyMatchingSelectors, const WebVector<WebString>& stoppedMatchingSelectors) OVERRIDE;
370 std::map<WebLocalFrame*, std::set<std::string> > m_matchedSelectors;
374 void CSSCallbackWebFrameClient::didMatchCSS(WebLocalFrame* frame, const WebVector<WebString>& newlyMatchingSelectors, const WebVector<WebString>& stoppedMatchingSelectors)
377 std::set<std::string>& frameSelectors = m_matchedSelectors[frame];
378 for (size_t i = 0; i < newlyMatchingSelectors.size(); ++i) {
379 std::string selector = newlyMatchingSelectors[i].utf8();
380 EXPECT_EQ(0U, frameSelectors.count(selector)) << selector;
381 frameSelectors.insert(selector);
383 for (size_t i = 0; i < stoppedMatchingSelectors.size(); ++i) {
384 std::string selector = stoppedMatchingSelectors[i].utf8();
385 EXPECT_EQ(1U, frameSelectors.count(selector)) << selector;
386 frameSelectors.erase(selector);
390 class WebFrameCSSCallbackTest : public testing::Test {
392 WebFrameCSSCallbackTest()
395 m_frame = m_helper.initializeAndLoad("about:blank", true, &m_client)->mainFrame()->toWebLocalFrame();
398 ~WebFrameCSSCallbackTest()
400 EXPECT_EQ(1U, m_client.m_matchedSelectors.size());
403 WebDocument doc() const
405 return m_frame->document();
408 int updateCount() const
410 return m_client.m_updateCount;
413 const std::set<std::string>& matchedSelectors()
415 return m_client.m_matchedSelectors[m_frame];
418 void loadHTML(const std::string& html)
420 FrameTestHelpers::loadHTMLString(m_frame, html, toKURL("about:blank"));
423 void executeScript(const WebString& code)
425 m_frame->executeScript(WebScriptSource(code));
426 m_frame->view()->layout();
430 CSSCallbackWebFrameClient m_client;
431 FrameTestHelpers::WebViewHelper m_helper;
432 WebLocalFrame* m_frame;
435 TEST_F(WebFrameCSSCallbackTest, AuthorStyleSheet)
439 // This stylesheet checks that the internal property and value can't be
440 // set by a stylesheet, only WebDocument::watchCSSSelectors().
441 "div.initial_on { -internal-callback: none; }"
442 "div.initial_off { -internal-callback: -internal-presence; }"
444 "<div class=\"initial_on\"></div>"
445 "<div class=\"initial_off\"></div>");
447 std::vector<WebString> selectors;
448 selectors.push_back(WebString::fromUTF8("div.initial_on"));
449 m_frame->document().watchCSSSelectors(WebVector<WebString>(selectors));
450 m_frame->view()->layout();
452 EXPECT_EQ(1, updateCount());
453 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("div.initial_on"));
455 // Check that adding a watched selector calls back for already-present nodes.
456 selectors.push_back(WebString::fromUTF8("div.initial_off"));
457 doc().watchCSSSelectors(WebVector<WebString>(selectors));
458 m_frame->view()->layout();
460 EXPECT_EQ(2, updateCount());
461 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("div.initial_off", "div.initial_on"));
463 // Check that we can turn off callbacks for certain selectors.
464 doc().watchCSSSelectors(WebVector<WebString>());
465 m_frame->view()->layout();
467 EXPECT_EQ(3, updateCount());
468 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
471 TEST_F(WebFrameCSSCallbackTest, SharedRenderStyle)
473 // Check that adding an element calls back when it matches an existing rule.
474 std::vector<WebString> selectors;
475 selectors.push_back(WebString::fromUTF8("span"));
476 doc().watchCSSSelectors(WebVector<WebString>(selectors));
479 "i1 = document.createElement('span');"
480 "i1.id = 'first_span';"
481 "document.body.appendChild(i1)");
482 EXPECT_EQ(1, updateCount());
483 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
485 // Adding a second element that shares a RenderStyle shouldn't call back.
486 // We use <span>s to avoid default style rules that can set
487 // RenderStyle::unique().
489 "i2 = document.createElement('span');"
490 "i2.id = 'second_span';"
491 "i1 = document.getElementById('first_span');"
492 "i1.parentNode.insertBefore(i2, i1.nextSibling);");
493 EXPECT_EQ(1, updateCount());
494 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
496 // Removing the first element shouldn't call back.
498 "i1 = document.getElementById('first_span');"
499 "i1.parentNode.removeChild(i1);");
500 EXPECT_EQ(1, updateCount());
501 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
503 // But removing the second element *should* call back.
505 "i2 = document.getElementById('second_span');"
506 "i2.parentNode.removeChild(i2);");
507 EXPECT_EQ(2, updateCount());
508 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
511 TEST_F(WebFrameCSSCallbackTest, CatchesAttributeChange)
513 loadHTML("<span></span>");
515 std::vector<WebString> selectors;
516 selectors.push_back(WebString::fromUTF8("span[attr=\"value\"]"));
517 doc().watchCSSSelectors(WebVector<WebString>(selectors));
520 EXPECT_EQ(0, updateCount());
521 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
524 "document.querySelector('span').setAttribute('attr', 'value');");
525 EXPECT_EQ(1, updateCount());
526 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span[attr=\"value\"]"));
529 TEST_F(WebFrameCSSCallbackTest, DisplayNone)
531 loadHTML("<div style='display:none'><span></span></div>");
533 std::vector<WebString> selectors;
534 selectors.push_back(WebString::fromUTF8("span"));
535 doc().watchCSSSelectors(WebVector<WebString>(selectors));
538 EXPECT_EQ(0, updateCount()) << "Don't match elements in display:none trees.";
541 "d = document.querySelector('div');"
542 "d.style.display = 'block';");
543 EXPECT_EQ(1, updateCount()) << "Match elements when they become displayed.";
544 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
547 "d = document.querySelector('div');"
548 "d.style.display = 'none';");
549 EXPECT_EQ(2, updateCount()) << "Unmatch elements when they become undisplayed.";
550 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
553 "s = document.querySelector('span');"
554 "s.style.display = 'none';");
555 EXPECT_EQ(2, updateCount()) << "No effect from no-display'ing a span that's already undisplayed.";
558 "d = document.querySelector('div');"
559 "d.style.display = 'block';");
560 EXPECT_EQ(2, updateCount()) << "No effect from displaying a div whose span is display:none.";
563 "s = document.querySelector('span');"
564 "s.style.display = 'inline';");
565 EXPECT_EQ(3, updateCount()) << "Now the span is visible and produces a callback.";
566 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
569 "s = document.querySelector('span');"
570 "s.style.display = 'none';");
571 EXPECT_EQ(4, updateCount()) << "Undisplaying the span directly should produce another callback.";
572 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
575 TEST_F(WebFrameCSSCallbackTest, Reparenting)
578 "<div id='d1'><span></span></div>"
579 "<div id='d2'></div>");
581 std::vector<WebString> selectors;
582 selectors.push_back(WebString::fromUTF8("span"));
583 doc().watchCSSSelectors(WebVector<WebString>(selectors));
584 m_frame->view()->layout();
587 EXPECT_EQ(1, updateCount());
588 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
591 "s = document.querySelector('span');"
592 "d2 = document.getElementById('d2');"
593 "d2.appendChild(s);");
594 EXPECT_EQ(1, updateCount()) << "Just moving an element that continues to match shouldn't send a spurious callback.";
595 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
598 TEST_F(WebFrameCSSCallbackTest, MultiSelector)
600 loadHTML("<span></span>");
602 // Check that selector lists match as the whole list, not as each element
604 std::vector<WebString> selectors;
605 selectors.push_back(WebString::fromUTF8("span"));
606 selectors.push_back(WebString::fromUTF8("span,p"));
607 doc().watchCSSSelectors(WebVector<WebString>(selectors));
608 m_frame->view()->layout();
611 EXPECT_EQ(1, updateCount());
612 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span", "span, p"));
615 TEST_F(WebFrameCSSCallbackTest, InvalidSelector)
617 loadHTML("<p><span></span></p>");
619 // Build a list with one valid selector and one invalid.
620 std::vector<WebString> selectors;
621 selectors.push_back(WebString::fromUTF8("span"));
622 selectors.push_back(WebString::fromUTF8("[")); // Invalid.
623 selectors.push_back(WebString::fromUTF8("p span")); // Not compound.
624 doc().watchCSSSelectors(WebVector<WebString>(selectors));
625 m_frame->view()->layout();
628 EXPECT_EQ(1, updateCount());
629 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"))
630 << "An invalid selector shouldn't prevent other selectors from matching.";
633 TEST_F(WebFrameTest, DispatchMessageEventWithOriginCheck)
635 registerMockedHttpURLLoad("postmessage_test.html");
637 // Pass true to enable JavaScript.
638 FrameTestHelpers::WebViewHelper webViewHelper;
639 webViewHelper.initializeAndLoad(m_baseURL + "postmessage_test.html", true);
641 // Send a message with the correct origin.
642 WebSecurityOrigin correctOrigin(WebSecurityOrigin::create(toKURL(m_baseURL)));
643 WebDOMEvent event = webViewHelper.webView()->mainFrame()->document().createEvent("MessageEvent");
644 WebDOMMessageEvent message = event.to<WebDOMMessageEvent>();
645 WebSerializedScriptValue data(WebSerializedScriptValue::fromString("foo"));
646 message.initMessageEvent("message", false, false, data, "http://origin.com", 0, "");
647 webViewHelper.webView()->mainFrame()->dispatchMessageEventWithOriginCheck(correctOrigin, message);
649 // Send another message with incorrect origin.
650 WebSecurityOrigin incorrectOrigin(WebSecurityOrigin::create(toKURL(m_chromeURL)));
651 webViewHelper.webView()->mainFrame()->dispatchMessageEventWithOriginCheck(incorrectOrigin, message);
653 // Required to see any updates in contentAsText.
654 webViewHelper.webView()->layout();
656 // Verify that only the first addition is in the body of the page.
657 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
658 EXPECT_NE(std::string::npos, content.find("Message 1."));
659 EXPECT_EQ(std::string::npos, content.find("Message 2."));
662 TEST_F(WebFrameTest, PostMessageThenDetach)
664 FrameTestHelpers::WebViewHelper webViewHelper;
665 webViewHelper.initializeAndLoad("about:blank");
667 RefPtrWillBeRawPtr<LocalFrame> frame = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame());
668 NonThrowableExceptionState exceptionState;
669 frame->domWindow()->postMessage(SerializedScriptValue::create("message"), 0, "*", frame->domWindow(), exceptionState);
670 webViewHelper.reset();
671 EXPECT_FALSE(exceptionState.hadException());
673 // Success is not crashing.
677 class FixedLayoutTestWebViewClient : public FrameTestHelpers::TestWebViewClient {
679 virtual WebScreenInfo screenInfo() OVERRIDE { return m_screenInfo; }
681 WebScreenInfo m_screenInfo;
684 // Viewport settings need to be set before the page gets loaded
685 static void enableViewportSettings(WebSettings* settings)
687 settings->setViewportMetaEnabled(true);
688 settings->setViewportEnabled(true);
689 settings->setMainFrameResizesAreOrientationChanges(true);
690 settings->setShrinksViewportContentToFit(true);
693 // Helper function to check or set text autosizing multipliers on a document.
694 static bool checkOrSetTextAutosizingMultiplier(Document* document, float multiplier, bool setMultiplier)
696 bool multiplierCheckedOrSetAtLeastOnce = false;
697 for (RenderObject* renderer = document->renderView(); renderer; renderer = renderer->nextInPreOrder()) {
698 if (renderer->style()) {
700 renderer->style()->setTextAutosizingMultiplier(multiplier);
701 EXPECT_EQ(multiplier, renderer->style()->textAutosizingMultiplier());
702 multiplierCheckedOrSetAtLeastOnce = true;
705 return multiplierCheckedOrSetAtLeastOnce;
709 static bool setTextAutosizingMultiplier(Document* document, float multiplier)
711 return checkOrSetTextAutosizingMultiplier(document, multiplier, true);
714 static bool checkTextAutosizingMultiplier(Document* document, float multiplier)
716 return checkOrSetTextAutosizingMultiplier(document, multiplier, false);
719 TEST_F(WebFrameTest, ChangeInFixedLayoutResetsTextAutosizingMultipliers)
721 UseMockScrollbarSettings mockScrollbarSettings;
722 registerMockedHttpURLLoad("fixed_layout.html");
724 FixedLayoutTestWebViewClient client;
725 int viewportWidth = 640;
726 int viewportHeight = 480;
728 FrameTestHelpers::WebViewHelper webViewHelper;
729 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
731 Document* document = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document();
732 document->settings()->setTextAutosizingEnabled(true);
733 EXPECT_TRUE(document->settings()->textAutosizingEnabled());
734 webViewHelper.webViewImpl()->resize(WebSize(viewportWidth, viewportHeight));
735 webViewHelper.webViewImpl()->layout();
737 EXPECT_TRUE(setTextAutosizingMultiplier(document, 2));
739 ViewportDescription description = document->viewportDescription();
740 // Choose a width that's not going match the viewport width of the loaded document.
741 description.minWidth = Length(100, blink::Fixed);
742 description.maxWidth = Length(100, blink::Fixed);
743 webViewHelper.webViewImpl()->updatePageDefinedViewportConstraints(description);
745 EXPECT_TRUE(checkTextAutosizingMultiplier(document, 1));
748 TEST_F(WebFrameTest, SetFrameRectInvalidatesTextAutosizingMultipliers)
750 UseMockScrollbarSettings mockScrollbarSettings;
751 registerMockedHttpURLLoad("iframe_reload.html");
752 registerMockedHttpURLLoad("visible_iframe.html");
754 FixedLayoutTestWebViewClient client;
755 int viewportWidth = 640;
756 int viewportHeight = 480;
758 FrameTestHelpers::WebViewHelper webViewHelper;
759 webViewHelper.initializeAndLoad(m_baseURL + "iframe_reload.html", true, 0, &client, enableViewportSettings);
761 LocalFrame* mainFrame = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame());
762 Document* document = mainFrame->document();
763 FrameView* frameView = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
764 document->settings()->setTextAutosizingEnabled(true);
765 EXPECT_TRUE(document->settings()->textAutosizingEnabled());
766 webViewHelper.webViewImpl()->resize(WebSize(viewportWidth, viewportHeight));
767 webViewHelper.webViewImpl()->layout();
769 for (Frame* frame = mainFrame; frame; frame = frame->tree().traverseNext()) {
770 if (!frame->isLocalFrame())
772 EXPECT_TRUE(setTextAutosizingMultiplier(toLocalFrame(frame)->document(), 2));
773 for (RenderObject* renderer = toLocalFrame(frame)->document()->renderView(); renderer; renderer = renderer->nextInPreOrder()) {
774 if (renderer->isText())
775 EXPECT_FALSE(renderer->needsLayout());
779 frameView->setFrameRect(IntRect(0, 0, 200, 200));
780 for (Frame* frame = mainFrame; frame; frame = frame->tree().traverseNext()) {
781 if (!frame->isLocalFrame())
783 for (RenderObject* renderer = toLocalFrame(frame)->document()->renderView(); renderer; renderer = renderer->nextInPreOrder()) {
784 if (renderer->isText())
785 EXPECT_TRUE(renderer->needsLayout());
790 TEST_F(WebFrameTest, ZeroHeightPositiveWidthNotIgnored)
792 UseMockScrollbarSettings mockScrollbarSettings;
794 FixedLayoutTestWebViewClient client;
795 client.m_screenInfo.deviceScaleFactor = 1;
796 int viewportWidth = 1280;
797 int viewportHeight = 0;
799 FrameTestHelpers::WebViewHelper webViewHelper;
800 webViewHelper.initialize(true, 0, &client, enableViewportSettings);
801 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
803 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
804 EXPECT_EQ(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
807 TEST_F(WebFrameTest, DeviceScaleFactorUsesDefaultWithoutViewportTag)
809 UseMockScrollbarSettings mockScrollbarSettings;
810 registerMockedHttpURLLoad("no_viewport_tag.html");
812 int viewportWidth = 640;
813 int viewportHeight = 480;
815 FixedLayoutTestWebViewClient client;
816 client.m_screenInfo.deviceScaleFactor = 2;
818 FrameTestHelpers::WebViewHelper webViewHelper;
819 webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client, enableViewportSettings);
821 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
822 webViewHelper.webView()->layout();
824 EXPECT_EQ(2, webViewHelper.webView()->deviceScaleFactor());
826 // Device scale factor should be independent of page scale.
827 webViewHelper.webView()->setPageScaleFactorLimits(1, 2);
828 webViewHelper.webView()->setPageScaleFactor(0.5);
829 webViewHelper.webView()->layout();
830 EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor());
832 // Force the layout to happen before leaving the test.
833 webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
836 TEST_F(WebFrameTest, FixedLayoutInitializeAtMinimumScale)
838 UseMockScrollbarSettings mockScrollbarSettings;
840 registerMockedHttpURLLoad("fixed_layout.html");
842 FixedLayoutTestWebViewClient client;
843 client.m_screenInfo.deviceScaleFactor = 1;
844 int viewportWidth = 640;
845 int viewportHeight = 480;
847 // Make sure we initialize to minimum scale, even if the window size
848 // only becomes available after the load begins.
849 FrameTestHelpers::WebViewHelper webViewHelper;
850 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
851 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
853 int defaultFixedLayoutWidth = 980;
854 float minimumPageScaleFactor = viewportWidth / (float) defaultFixedLayoutWidth;
855 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
856 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->minimumPageScaleFactor());
858 // Assume the user has pinch zoomed to page scale factor 2.
859 float userPinchPageScaleFactor = 2;
860 webViewHelper.webView()->setPageScaleFactor(userPinchPageScaleFactor);
861 webViewHelper.webView()->layout();
863 // Make sure we don't reset to initial scale if the page continues to load.
864 webViewHelper.webViewImpl()->didCommitLoad(false, false);
865 webViewHelper.webViewImpl()->didChangeContentsSize();
866 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
868 // Make sure we don't reset to initial scale if the viewport size changes.
869 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight + 100));
870 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
873 TEST_F(WebFrameTest, WideDocumentInitializeAtMinimumScale)
875 UseMockScrollbarSettings mockScrollbarSettings;
877 registerMockedHttpURLLoad("wide_document.html");
879 FixedLayoutTestWebViewClient client;
880 client.m_screenInfo.deviceScaleFactor = 1;
881 int viewportWidth = 640;
882 int viewportHeight = 480;
884 // Make sure we initialize to minimum scale, even if the window size
885 // only becomes available after the load begins.
886 FrameTestHelpers::WebViewHelper webViewHelper;
887 webViewHelper.initializeAndLoad(m_baseURL + "wide_document.html", true, 0, &client, enableViewportSettings);
888 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
890 int wideDocumentWidth = 1500;
891 float minimumPageScaleFactor = viewportWidth / (float) wideDocumentWidth;
892 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
893 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->minimumPageScaleFactor());
895 // Assume the user has pinch zoomed to page scale factor 2.
896 float userPinchPageScaleFactor = 2;
897 webViewHelper.webView()->setPageScaleFactor(userPinchPageScaleFactor);
898 webViewHelper.webView()->layout();
900 // Make sure we don't reset to initial scale if the page continues to load.
901 webViewHelper.webViewImpl()->didCommitLoad(false, false);
902 webViewHelper.webViewImpl()->didChangeContentsSize();
903 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
905 // Make sure we don't reset to initial scale if the viewport size changes.
906 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight + 100));
907 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
910 TEST_F(WebFrameTest, DelayedViewportInitialScale)
912 UseMockScrollbarSettings mockScrollbarSettings;
913 registerMockedHttpURLLoad("viewport-auto-initial-scale.html");
915 FixedLayoutTestWebViewClient client;
916 client.m_screenInfo.deviceScaleFactor = 1;
917 int viewportWidth = 640;
918 int viewportHeight = 480;
920 FrameTestHelpers::WebViewHelper webViewHelper;
921 webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings);
922 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
924 EXPECT_EQ(0.25f, webViewHelper.webView()->pageScaleFactor());
926 Document* document = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document();
927 ViewportDescription description = document->viewportDescription();
928 description.zoom = 2;
929 document->setViewportDescription(description);
930 webViewHelper.webView()->layout();
931 EXPECT_EQ(2, webViewHelper.webView()->pageScaleFactor());
934 TEST_F(WebFrameTest, setLoadWithOverviewModeToFalse)
936 UseMockScrollbarSettings mockScrollbarSettings;
937 registerMockedHttpURLLoad("viewport-auto-initial-scale.html");
939 FixedLayoutTestWebViewClient client;
940 client.m_screenInfo.deviceScaleFactor = 1;
941 int viewportWidth = 640;
942 int viewportHeight = 480;
944 FrameTestHelpers::WebViewHelper webViewHelper;
945 webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings);
946 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
947 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
948 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
950 // The page must be displayed at 100% zoom.
951 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
954 TEST_F(WebFrameTest, SetLoadWithOverviewModeToFalseAndNoWideViewport)
956 UseMockScrollbarSettings mockScrollbarSettings;
957 registerMockedHttpURLLoad("large-div.html");
959 FixedLayoutTestWebViewClient client;
960 client.m_screenInfo.deviceScaleFactor = 1;
961 int viewportWidth = 640;
962 int viewportHeight = 480;
964 FrameTestHelpers::WebViewHelper webViewHelper;
965 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client, enableViewportSettings);
966 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
967 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
968 webViewHelper.webView()->settings()->setUseWideViewport(false);
969 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
971 // The page must be displayed at 100% zoom, despite that it hosts a wide div element.
972 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
975 TEST_F(WebFrameTest, NoWideViewportIgnoresPageViewportWidth)
977 UseMockScrollbarSettings mockScrollbarSettings;
978 registerMockedHttpURLLoad("viewport-auto-initial-scale.html");
980 FixedLayoutTestWebViewClient client;
981 client.m_screenInfo.deviceScaleFactor = 1;
982 int viewportWidth = 640;
983 int viewportHeight = 480;
985 FrameTestHelpers::WebViewHelper webViewHelper;
986 webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings);
987 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
988 webViewHelper.webView()->settings()->setUseWideViewport(false);
989 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
991 // The page sets viewport width to 3000, but with UseWideViewport == false is must be ignored.
992 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
993 EXPECT_EQ(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
996 TEST_F(WebFrameTest, NoWideViewportIgnoresPageViewportWidthButAccountsScale)
998 UseMockScrollbarSettings mockScrollbarSettings;
999 registerMockedHttpURLLoad("viewport-wide-2x-initial-scale.html");
1001 FixedLayoutTestWebViewClient client;
1002 client.m_screenInfo.deviceScaleFactor = 1;
1003 int viewportWidth = 640;
1004 int viewportHeight = 480;
1006 FrameTestHelpers::WebViewHelper webViewHelper;
1007 webViewHelper.initializeAndLoad(m_baseURL + "viewport-wide-2x-initial-scale.html", true, 0, &client, enableViewportSettings);
1008 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1009 webViewHelper.webView()->settings()->setUseWideViewport(false);
1010 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1012 // The page sets viewport width to 3000, but with UseWideViewport == false it must be ignored.
1013 // While the initial scale specified by the page must be accounted.
1014 EXPECT_EQ(viewportWidth / 2, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1015 EXPECT_EQ(viewportHeight / 2, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
1018 TEST_F(WebFrameTest, WideViewportSetsTo980WithoutViewportTag)
1020 UseMockScrollbarSettings mockScrollbarSettings;
1021 registerMockedHttpURLLoad("no_viewport_tag.html");
1023 FixedLayoutTestWebViewClient client;
1024 client.m_screenInfo.deviceScaleFactor = 1;
1025 int viewportWidth = 640;
1026 int viewportHeight = 480;
1028 FrameTestHelpers::WebViewHelper webViewHelper;
1029 webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client, enableViewportSettings);
1030 applyViewportStyleOverride(&webViewHelper);
1031 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1032 webViewHelper.webView()->settings()->setUseWideViewport(true);
1033 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1035 EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1036 EXPECT_EQ(980.0 / viewportWidth * viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
1039 TEST_F(WebFrameTest, NoWideViewportAndHeightInMeta)
1041 UseMockScrollbarSettings mockScrollbarSettings;
1042 registerMockedHttpURLLoad("viewport-height-1000.html");
1044 FixedLayoutTestWebViewClient client;
1045 client.m_screenInfo.deviceScaleFactor = 1;
1046 int viewportWidth = 640;
1047 int viewportHeight = 480;
1049 FrameTestHelpers::WebViewHelper webViewHelper;
1050 webViewHelper.initializeAndLoad(m_baseURL + "viewport-height-1000.html", true, 0, &client, enableViewportSettings);
1051 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1052 webViewHelper.webView()->settings()->setUseWideViewport(false);
1053 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1055 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1058 TEST_F(WebFrameTest, WideViewportSetsTo980WithAutoWidth)
1060 UseMockScrollbarSettings mockScrollbarSettings;
1061 registerMockedHttpURLLoad("viewport-2x-initial-scale.html");
1063 FixedLayoutTestWebViewClient client;
1064 client.m_screenInfo.deviceScaleFactor = 1;
1065 int viewportWidth = 640;
1066 int viewportHeight = 480;
1068 FrameTestHelpers::WebViewHelper webViewHelper;
1069 webViewHelper.initializeAndLoad(m_baseURL + "viewport-2x-initial-scale.html", true, 0, &client, enableViewportSettings);
1070 applyViewportStyleOverride(&webViewHelper);
1071 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1072 webViewHelper.webView()->settings()->setUseWideViewport(true);
1073 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1075 EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1076 EXPECT_EQ(980.0 / viewportWidth * viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
1079 TEST_F(WebFrameTest, PageViewportInitialScaleOverridesLoadWithOverviewMode)
1081 UseMockScrollbarSettings mockScrollbarSettings;
1082 registerMockedHttpURLLoad("viewport-wide-2x-initial-scale.html");
1084 FixedLayoutTestWebViewClient client;
1085 client.m_screenInfo.deviceScaleFactor = 1;
1086 int viewportWidth = 640;
1087 int viewportHeight = 480;
1089 FrameTestHelpers::WebViewHelper webViewHelper;
1090 webViewHelper.initializeAndLoad(m_baseURL + "viewport-wide-2x-initial-scale.html", true, 0, &client, enableViewportSettings);
1091 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1092 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1094 // The page must be displayed at 200% zoom, as specified in its viewport meta tag.
1095 EXPECT_EQ(2.0f, webViewHelper.webView()->pageScaleFactor());
1098 TEST_F(WebFrameTest, setInitialPageScaleFactorPermanently)
1100 UseMockScrollbarSettings mockScrollbarSettings;
1102 registerMockedHttpURLLoad("fixed_layout.html");
1104 FixedLayoutTestWebViewClient client;
1105 client.m_screenInfo.deviceScaleFactor = 1;
1106 float enforcedPageScaleFactor = 2.0f;
1108 FrameTestHelpers::WebViewHelper webViewHelper;
1109 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1110 applyViewportStyleOverride(&webViewHelper);
1111 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1112 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1113 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1114 webViewHelper.webView()->layout();
1116 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1118 int viewportWidth = 640;
1119 int viewportHeight = 480;
1120 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1121 webViewHelper.webView()->layout();
1123 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1125 webViewHelper.webView()->setInitialPageScaleOverride(-1);
1126 webViewHelper.webView()->layout();
1127 EXPECT_EQ(1.0, webViewHelper.webView()->pageScaleFactor());
1130 TEST_F(WebFrameTest, PermanentInitialPageScaleFactorOverridesLoadWithOverviewMode)
1132 UseMockScrollbarSettings mockScrollbarSettings;
1133 registerMockedHttpURLLoad("viewport-auto-initial-scale.html");
1135 FixedLayoutTestWebViewClient client;
1136 client.m_screenInfo.deviceScaleFactor = 1;
1137 int viewportWidth = 640;
1138 int viewportHeight = 480;
1139 float enforcedPageScaleFactor = 0.5f;
1141 FrameTestHelpers::WebViewHelper webViewHelper;
1142 webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings);
1143 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1144 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1145 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1147 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1150 TEST_F(WebFrameTest, PermanentInitialPageScaleFactorOverridesPageViewportInitialScale)
1152 UseMockScrollbarSettings mockScrollbarSettings;
1153 registerMockedHttpURLLoad("viewport-wide-2x-initial-scale.html");
1155 FixedLayoutTestWebViewClient client;
1156 client.m_screenInfo.deviceScaleFactor = 1;
1157 int viewportWidth = 640;
1158 int viewportHeight = 480;
1159 float enforcedPageScaleFactor = 0.5f;
1161 FrameTestHelpers::WebViewHelper webViewHelper;
1162 webViewHelper.initializeAndLoad(m_baseURL + "viewport-wide-2x-initial-scale.html", true, 0, &client, enableViewportSettings);
1163 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1164 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1166 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1169 TEST_F(WebFrameTest, SmallPermanentInitialPageScaleFactorIsClobbered)
1171 UseMockScrollbarSettings mockScrollbarSettings;
1172 const char* pages[] = {
1173 // These pages trigger the clobbering condition. There must be a matching item in "pageScaleFactors" array.
1174 "viewport-device-0.5x-initial-scale.html",
1175 "viewport-initial-scale-1.html",
1176 // These ones do not.
1177 "viewport-auto-initial-scale.html",
1178 "viewport-target-densitydpi-device-and-fixed-width.html"
1180 float pageScaleFactors[] = { 0.5f, 1.0f };
1181 for (size_t i = 0; i < ARRAY_SIZE(pages); ++i)
1182 registerMockedHttpURLLoad(pages[i]);
1184 FixedLayoutTestWebViewClient client;
1185 client.m_screenInfo.deviceScaleFactor = 1;
1186 int viewportWidth = 400;
1187 int viewportHeight = 300;
1188 float enforcedPageScaleFactor = 0.75f;
1190 for (size_t i = 0; i < ARRAY_SIZE(pages); ++i) {
1191 for (int quirkEnabled = 0; quirkEnabled <= 1; ++quirkEnabled) {
1192 FrameTestHelpers::WebViewHelper webViewHelper;
1193 webViewHelper.initializeAndLoad(m_baseURL + pages[i], true, 0, &client, enableViewportSettings);
1194 applyViewportStyleOverride(&webViewHelper);
1195 webViewHelper.webView()->settings()->setClobberUserAgentInitialScaleQuirk(quirkEnabled);
1196 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1197 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1199 float expectedPageScaleFactor = quirkEnabled && i < ARRAY_SIZE(pageScaleFactors) ? pageScaleFactors[i] : enforcedPageScaleFactor;
1200 EXPECT_EQ(expectedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1205 TEST_F(WebFrameTest, PermanentInitialPageScaleFactorAffectsLayoutWidth)
1207 UseMockScrollbarSettings mockScrollbarSettings;
1209 FixedLayoutTestWebViewClient client;
1210 client.m_screenInfo.deviceScaleFactor = 1;
1211 int viewportWidth = 640;
1212 int viewportHeight = 480;
1213 float enforcedPageScaleFactor = 0.5;
1215 FrameTestHelpers::WebViewHelper webViewHelper;
1216 webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings);
1217 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1218 webViewHelper.webView()->settings()->setUseWideViewport(false);
1219 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1220 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1221 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1223 EXPECT_EQ(viewportWidth / enforcedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1224 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1227 TEST_F(WebFrameTest, SetForceZeroLayoutHeight)
1229 UseMockScrollbarSettings mockScrollbarSettings;
1230 registerMockedHttpURLLoad("200-by-300.html");
1232 FixedLayoutTestWebViewClient client;
1233 client.m_screenInfo.deviceScaleFactor = 1;
1234 int viewportWidth = 640;
1235 int viewportHeight = 480;
1237 FrameTestHelpers::WebViewHelper webViewHelper;
1239 webViewHelper.initializeAndLoad(m_baseURL + "200-by-300.html", true, 0, &client, enableViewportSettings);
1240 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1241 webViewHelper.webView()->layout();
1243 EXPECT_LE(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1244 webViewHelper.webView()->settings()->setForceZeroLayoutHeight(true);
1245 EXPECT_TRUE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
1247 EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1249 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight * 2));
1250 EXPECT_FALSE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
1251 EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1253 webViewHelper.webView()->resize(WebSize(viewportWidth * 2, viewportHeight));
1254 webViewHelper.webView()->layout();
1255 EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1257 webViewHelper.webView()->settings()->setForceZeroLayoutHeight(false);
1258 EXPECT_LE(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1261 TEST_F(WebFrameTest, SetForceZeroLayoutHeightWorksAcrossNavigations)
1263 UseMockScrollbarSettings mockScrollbarSettings;
1264 registerMockedHttpURLLoad("200-by-300.html");
1265 registerMockedHttpURLLoad("large-div.html");
1267 FixedLayoutTestWebViewClient client;
1268 client.m_screenInfo.deviceScaleFactor = 1;
1269 int viewportWidth = 640;
1270 int viewportHeight = 480;
1272 FrameTestHelpers::WebViewHelper webViewHelper;
1274 webViewHelper.initializeAndLoad(m_baseURL + "200-by-300.html", true, 0, &client, enableViewportSettings);
1275 webViewHelper.webView()->settings()->setForceZeroLayoutHeight(true);
1276 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1277 webViewHelper.webView()->layout();
1279 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "large-div.html");
1280 webViewHelper.webView()->layout();
1282 EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1285 TEST_F(WebFrameTest, SetForceZeroLayoutHeightWithWideViewportQuirk)
1287 UseMockScrollbarSettings mockScrollbarSettings;
1288 registerMockedHttpURLLoad("200-by-300.html");
1290 FixedLayoutTestWebViewClient client;
1291 client.m_screenInfo.deviceScaleFactor = 1;
1292 int viewportWidth = 640;
1293 int viewportHeight = 480;
1295 FrameTestHelpers::WebViewHelper webViewHelper;
1297 webViewHelper.initializeAndLoad(m_baseURL + "200-by-300.html", true, 0, &client, enableViewportSettings);
1298 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1299 webViewHelper.webView()->settings()->setUseWideViewport(true);
1300 webViewHelper.webView()->settings()->setForceZeroLayoutHeight(true);
1301 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1302 webViewHelper.webView()->layout();
1304 EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1307 TEST_F(WebFrameTest, WideViewportAndWideContentWithInitialScale)
1309 UseMockScrollbarSettings mockScrollbarSettings;
1310 registerMockedHttpURLLoad("wide_document_width_viewport.html");
1312 FixedLayoutTestWebViewClient client;
1313 client.m_screenInfo.deviceScaleFactor = 1;
1314 int viewportWidth = 600;
1315 int viewportHeight = 800;
1317 FrameTestHelpers::WebViewHelper webViewHelper;
1318 webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings);
1319 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1320 webViewHelper.webView()->settings()->setUseWideViewport(true);
1321 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1322 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1324 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "wide_document_width_viewport.html");
1325 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1327 int wideDocumentWidth = 800;
1328 float minimumPageScaleFactor = viewportWidth / (float) wideDocumentWidth;
1329 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1330 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->minimumPageScaleFactor());
1333 TEST_F(WebFrameTest, WideViewportQuirkClobbersHeight)
1335 UseMockScrollbarSettings mockScrollbarSettings;
1336 registerMockedHttpURLLoad("viewport-height-1000.html");
1338 FixedLayoutTestWebViewClient client;
1339 client.m_screenInfo.deviceScaleFactor = 1;
1340 int viewportWidth = 600;
1341 int viewportHeight = 800;
1343 FrameTestHelpers::WebViewHelper webViewHelper;
1344 webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings);
1345 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1346 webViewHelper.webView()->settings()->setUseWideViewport(false);
1347 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1348 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1350 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport-height-1000.html");
1351 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1353 EXPECT_EQ(800, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1354 EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor());
1357 TEST_F(WebFrameTest, LayoutSize320Quirk)
1359 UseMockScrollbarSettings mockScrollbarSettings;
1360 registerMockedHttpURLLoad("viewport/viewport-30.html");
1362 FixedLayoutTestWebViewClient client;
1363 client.m_screenInfo.deviceScaleFactor = 1;
1364 int viewportWidth = 600;
1365 int viewportHeight = 800;
1367 FrameTestHelpers::WebViewHelper webViewHelper;
1368 webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings);
1369 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1370 webViewHelper.webView()->settings()->setUseWideViewport(true);
1371 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1372 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1374 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport/viewport-30.html");
1375 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1377 EXPECT_EQ(600, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1378 EXPECT_EQ(800, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1379 EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor());
1381 // The magic number to snap to device-width is 320, so test that 321 is
1383 Document* document = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document();
1384 ViewportDescription description = document->viewportDescription();
1385 description.minWidth = Length(321, blink::Fixed);
1386 description.maxWidth = Length(321, blink::Fixed);
1387 document->setViewportDescription(description);
1388 webViewHelper.webView()->layout();
1389 EXPECT_EQ(321, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1391 description.minWidth = Length(320, blink::Fixed);
1392 description.maxWidth = Length(320, blink::Fixed);
1393 document->setViewportDescription(description);
1394 webViewHelper.webView()->layout();
1395 EXPECT_EQ(600, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1397 description = document->viewportDescription();
1398 description.maxHeight = Length(1000, blink::Fixed);
1399 document->setViewportDescription(description);
1400 webViewHelper.webView()->layout();
1401 EXPECT_EQ(1000, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1403 description.maxHeight = Length(320, blink::Fixed);
1404 document->setViewportDescription(description);
1405 webViewHelper.webView()->layout();
1406 EXPECT_EQ(800, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1409 TEST_F(WebFrameTest, ZeroValuesQuirk)
1411 UseMockScrollbarSettings mockScrollbarSettings;
1412 registerMockedHttpURLLoad("viewport-zero-values.html");
1414 FixedLayoutTestWebViewClient client;
1415 client.m_screenInfo.deviceScaleFactor = 1;
1416 int viewportWidth = 640;
1417 int viewportHeight = 480;
1419 FrameTestHelpers::WebViewHelper webViewHelper;
1420 webViewHelper.initialize(true, 0, &client, enableViewportSettings);
1421 webViewHelper.webView()->settings()->setViewportMetaZeroValuesQuirk(true);
1422 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1423 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1424 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport-zero-values.html");
1425 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1427 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1428 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
1430 webViewHelper.webView()->settings()->setUseWideViewport(true);
1431 webViewHelper.webView()->layout();
1432 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1433 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
1436 TEST_F(WebFrameTest, OverflowHiddenDisablesScrolling)
1438 registerMockedHttpURLLoad("body-overflow-hidden.html");
1440 FixedLayoutTestWebViewClient client;
1441 client.m_screenInfo.deviceScaleFactor = 1;
1442 int viewportWidth = 640;
1443 int viewportHeight = 480;
1445 FrameTestHelpers::WebViewHelper webViewHelper;
1446 webViewHelper.initialize(true, 0, &client);
1447 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "body-overflow-hidden.html");
1448 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1450 FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
1451 EXPECT_FALSE(view->userInputScrollable(VerticalScrollbar));
1454 TEST_F(WebFrameTest, IgnoreOverflowHiddenQuirk)
1456 registerMockedHttpURLLoad("body-overflow-hidden.html");
1458 FixedLayoutTestWebViewClient client;
1459 client.m_screenInfo.deviceScaleFactor = 1;
1460 int viewportWidth = 640;
1461 int viewportHeight = 480;
1463 FrameTestHelpers::WebViewHelper webViewHelper;
1464 webViewHelper.initialize(true, 0, &client);
1465 webViewHelper.webView()->settings()->setIgnoreMainFrameOverflowHiddenQuirk(true);
1466 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "body-overflow-hidden.html");
1467 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1469 FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
1470 EXPECT_TRUE(view->userInputScrollable(VerticalScrollbar));
1473 TEST_F(WebFrameTest, NonZeroValuesNoQuirk)
1475 UseMockScrollbarSettings mockScrollbarSettings;
1476 registerMockedHttpURLLoad("viewport-nonzero-values.html");
1478 FixedLayoutTestWebViewClient client;
1479 client.m_screenInfo.deviceScaleFactor = 1;
1480 int viewportWidth = 640;
1481 int viewportHeight = 480;
1482 float expectedPageScaleFactor = 0.5f;
1484 FrameTestHelpers::WebViewHelper webViewHelper;
1485 webViewHelper.initialize(true, 0, &client, enableViewportSettings);
1486 webViewHelper.webView()->settings()->setViewportMetaZeroValuesQuirk(true);
1487 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1488 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport-nonzero-values.html");
1489 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1491 EXPECT_EQ(viewportWidth / expectedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1492 EXPECT_EQ(expectedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1494 webViewHelper.webView()->settings()->setUseWideViewport(true);
1495 webViewHelper.webView()->layout();
1496 EXPECT_EQ(viewportWidth / expectedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1497 EXPECT_EQ(expectedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1500 TEST_F(WebFrameTest, setPageScaleFactorDoesNotLayout)
1502 UseMockScrollbarSettings mockScrollbarSettings;
1503 registerMockedHttpURLLoad("fixed_layout.html");
1505 FixedLayoutTestWebViewClient client;
1506 client.m_screenInfo.deviceScaleFactor = 1;
1507 // Small viewport to ensure there are always scrollbars.
1508 int viewportWidth = 64;
1509 int viewportHeight = 48;
1511 FrameTestHelpers::WebViewHelper webViewHelper;
1512 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1513 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1514 webViewHelper.webView()->layout();
1516 int prevLayoutCount = webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount();
1517 webViewHelper.webViewImpl()->setPageScaleFactor(3);
1518 EXPECT_FALSE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
1519 EXPECT_EQ(prevLayoutCount, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount());
1522 TEST_F(WebFrameTest, setPageScaleFactorWithOverlayScrollbarsDoesNotLayout)
1524 UseMockScrollbarSettings mockScrollbarSettings;
1526 registerMockedHttpURLLoad("fixed_layout.html");
1528 FixedLayoutTestWebViewClient client;
1529 client.m_screenInfo.deviceScaleFactor = 1;
1530 int viewportWidth = 640;
1531 int viewportHeight = 480;
1533 FrameTestHelpers::WebViewHelper webViewHelper;
1534 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1535 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1536 webViewHelper.webView()->layout();
1538 int prevLayoutCount = webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount();
1539 webViewHelper.webViewImpl()->setPageScaleFactor(30);
1540 EXPECT_FALSE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
1541 EXPECT_EQ(prevLayoutCount, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount());
1545 TEST_F(WebFrameTest, pageScaleFactorWrittenToHistoryItem)
1547 UseMockScrollbarSettings mockScrollbarSettings;
1548 registerMockedHttpURLLoad("fixed_layout.html");
1550 FixedLayoutTestWebViewClient client;
1551 client.m_screenInfo.deviceScaleFactor = 1;
1552 int viewportWidth = 640;
1553 int viewportHeight = 480;
1555 FrameTestHelpers::WebViewHelper webViewHelper;
1556 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1557 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1558 webViewHelper.webView()->layout();
1560 webViewHelper.webView()->setPageScaleFactor(3);
1561 EXPECT_EQ(3, toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->loader().currentItem()->pageScaleFactor());
1564 TEST_F(WebFrameTest, initialScaleWrittenToHistoryItem)
1566 UseMockScrollbarSettings mockScrollbarSettings;
1567 registerMockedHttpURLLoad("fixed_layout.html");
1569 FixedLayoutTestWebViewClient client;
1570 client.m_screenInfo.deviceScaleFactor = 1;
1571 int viewportWidth = 640;
1572 int viewportHeight = 480;
1574 FrameTestHelpers::WebViewHelper webViewHelper;
1575 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1576 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1577 webViewHelper.webView()->layout();
1579 int defaultFixedLayoutWidth = 980;
1580 float minimumPageScaleFactor = viewportWidth / (float) defaultFixedLayoutWidth;
1581 EXPECT_EQ(minimumPageScaleFactor, toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->loader().currentItem()->pageScaleFactor());
1584 TEST_F(WebFrameTest, pageScaleFactorShrinksViewport)
1586 UseMockScrollbarSettings mockScrollbarSettings;
1587 registerMockedHttpURLLoad("large-div.html");
1589 FixedLayoutTestWebViewClient client;
1590 client.m_screenInfo.deviceScaleFactor = 1;
1591 // Small viewport to ensure there are always scrollbars.
1592 int viewportWidth = 64;
1593 int viewportHeight = 48;
1595 FrameTestHelpers::WebViewHelper webViewHelper;
1596 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client, enableViewportSettings);
1597 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1598 webViewHelper.webView()->layout();
1600 FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
1601 int viewportWidthMinusScrollbar = viewportWidth - (view->verticalScrollbar()->isOverlayScrollbar() ? 0 : 15);
1602 int viewportHeightMinusScrollbar = viewportHeight - (view->horizontalScrollbar()->isOverlayScrollbar() ? 0 : 15);
1604 webViewHelper.webView()->setPageScaleFactor(2);
1606 IntSize unscaledSize = view->unscaledVisibleContentSize(IncludeScrollbars);
1607 EXPECT_EQ(viewportWidth, unscaledSize.width());
1608 EXPECT_EQ(viewportHeight, unscaledSize.height());
1610 IntSize unscaledSizeMinusScrollbar = view->unscaledVisibleContentSize(ExcludeScrollbars);
1611 EXPECT_EQ(viewportWidthMinusScrollbar, unscaledSizeMinusScrollbar.width());
1612 EXPECT_EQ(viewportHeightMinusScrollbar, unscaledSizeMinusScrollbar.height());
1614 IntSize scaledSize = view->visibleContentRect().size();
1615 EXPECT_EQ(ceil(viewportWidthMinusScrollbar / 2.0), scaledSize.width());
1616 EXPECT_EQ(ceil(viewportHeightMinusScrollbar / 2.0), scaledSize.height());
1619 TEST_F(WebFrameTest, pageScaleFactorDoesNotApplyCssTransform)
1621 UseMockScrollbarSettings mockScrollbarSettings;
1622 registerMockedHttpURLLoad("fixed_layout.html");
1624 FixedLayoutTestWebViewClient client;
1625 client.m_screenInfo.deviceScaleFactor = 1;
1626 int viewportWidth = 640;
1627 int viewportHeight = 480;
1629 FrameTestHelpers::WebViewHelper webViewHelper;
1630 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1631 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1632 webViewHelper.webView()->layout();
1634 webViewHelper.webView()->setPageScaleFactor(2);
1636 EXPECT_EQ(980, toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->contentRenderer()->unscaledDocumentRect().width());
1637 EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1640 TEST_F(WebFrameTest, targetDensityDpiHigh)
1642 UseMockScrollbarSettings mockScrollbarSettings;
1643 registerMockedHttpURLLoad("viewport-target-densitydpi-high.html");
1645 FixedLayoutTestWebViewClient client;
1647 float targetDpi = 240.0f;
1648 float deviceScaleFactors[] = { 1.0f, 4.0f / 3.0f, 2.0f };
1649 int viewportWidth = 640;
1650 int viewportHeight = 480;
1652 for (size_t i = 0; i < ARRAY_SIZE(deviceScaleFactors); ++i) {
1653 float deviceScaleFactor = deviceScaleFactors[i];
1654 float deviceDpi = deviceScaleFactor * 160.0f;
1655 client.m_screenInfo.deviceScaleFactor = deviceScaleFactor;
1657 FrameTestHelpers::WebViewHelper webViewHelper;
1658 webViewHelper.initializeAndLoad(m_baseURL + "viewport-target-densitydpi-high.html", true, 0, &client, enableViewportSettings);
1659 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1660 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1661 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1663 // We need to account for the fact that logical pixels are unconditionally multiplied by deviceScaleFactor to produce
1665 float densityDpiScaleRatio = deviceScaleFactor * targetDpi / deviceDpi;
1666 EXPECT_NEAR(viewportWidth * densityDpiScaleRatio, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1667 EXPECT_NEAR(viewportHeight * densityDpiScaleRatio, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1668 EXPECT_NEAR(1.0f / densityDpiScaleRatio, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1672 TEST_F(WebFrameTest, targetDensityDpiDevice)
1674 UseMockScrollbarSettings mockScrollbarSettings;
1675 registerMockedHttpURLLoad("viewport-target-densitydpi-device.html");
1677 float deviceScaleFactors[] = { 1.0f, 4.0f / 3.0f, 2.0f };
1679 FixedLayoutTestWebViewClient client;
1680 int viewportWidth = 640;
1681 int viewportHeight = 480;
1683 for (size_t i = 0; i < ARRAY_SIZE(deviceScaleFactors); ++i) {
1684 client.m_screenInfo.deviceScaleFactor = deviceScaleFactors[i];
1686 FrameTestHelpers::WebViewHelper webViewHelper;
1687 webViewHelper.initializeAndLoad(m_baseURL + "viewport-target-densitydpi-device.html", true, 0, &client, enableViewportSettings);
1688 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1689 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1690 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1692 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1693 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1694 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1698 TEST_F(WebFrameTest, targetDensityDpiDeviceAndFixedWidth)
1700 UseMockScrollbarSettings mockScrollbarSettings;
1701 registerMockedHttpURLLoad("viewport-target-densitydpi-device-and-fixed-width.html");
1703 float deviceScaleFactors[] = { 1.0f, 4.0f / 3.0f, 2.0f };
1705 FixedLayoutTestWebViewClient client;
1706 int viewportWidth = 640;
1707 int viewportHeight = 480;
1709 for (size_t i = 0; i < ARRAY_SIZE(deviceScaleFactors); ++i) {
1710 client.m_screenInfo.deviceScaleFactor = deviceScaleFactors[i];
1712 FrameTestHelpers::WebViewHelper webViewHelper;
1713 webViewHelper.initializeAndLoad(m_baseURL + "viewport-target-densitydpi-device-and-fixed-width.html", true, 0, &client, enableViewportSettings);
1714 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1715 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1716 webViewHelper.webView()->settings()->setUseWideViewport(true);
1717 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1719 EXPECT_NEAR(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1720 EXPECT_NEAR(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1721 EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1725 TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOne)
1727 UseMockScrollbarSettings mockScrollbarSettings;
1728 registerMockedHttpURLLoad("viewport-initial-scale-less-than-1.html");
1730 FixedLayoutTestWebViewClient client;
1731 client.m_screenInfo.deviceScaleFactor = 1.33f;
1732 int viewportWidth = 640;
1733 int viewportHeight = 480;
1735 FrameTestHelpers::WebViewHelper webViewHelper;
1736 webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-less-than-1.html", true, 0, &client, enableViewportSettings);
1737 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1738 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1739 webViewHelper.webView()->settings()->setUseWideViewport(false);
1740 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1741 webViewHelper.webView()->layout();
1743 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1744 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1745 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1748 TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOneWithDeviceWidth)
1750 UseMockScrollbarSettings mockScrollbarSettings;
1751 registerMockedHttpURLLoad("viewport-initial-scale-less-than-1-device-width.html");
1753 FixedLayoutTestWebViewClient client;
1754 client.m_screenInfo.deviceScaleFactor = 1.33f;
1755 int viewportWidth = 640;
1756 int viewportHeight = 480;
1758 FrameTestHelpers::WebViewHelper webViewHelper;
1759 webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-less-than-1-device-width.html", true, 0, &client, enableViewportSettings);
1760 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1761 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1762 webViewHelper.webView()->settings()->setUseWideViewport(false);
1763 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1764 webViewHelper.webView()->layout();
1766 const float pageZoom = 0.25f;
1767 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor / pageZoom, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1768 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor / pageZoom, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1769 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1772 TEST_F(WebFrameTest, NoWideViewportAndNoViewportWithInitialPageScaleOverride)
1774 UseMockScrollbarSettings mockScrollbarSettings;
1775 registerMockedHttpURLLoad("large-div.html");
1777 FixedLayoutTestWebViewClient client;
1778 int viewportWidth = 640;
1779 int viewportHeight = 480;
1780 float enforcedPageScaleFactor = 5.0f;
1782 FrameTestHelpers::WebViewHelper webViewHelper;
1783 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client, enableViewportSettings);
1784 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1785 webViewHelper.webView()->settings()->setUseWideViewport(false);
1786 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1787 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1788 webViewHelper.webView()->layout();
1790 EXPECT_NEAR(viewportWidth / enforcedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1791 EXPECT_NEAR(viewportHeight / enforcedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1792 EXPECT_NEAR(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1795 TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScale)
1797 UseMockScrollbarSettings mockScrollbarSettings;
1798 registerMockedHttpURLLoad("viewport-initial-scale-and-user-scalable-no.html");
1800 FixedLayoutTestWebViewClient client;
1801 int viewportWidth = 640;
1802 int viewportHeight = 480;
1804 FrameTestHelpers::WebViewHelper webViewHelper;
1805 webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-and-user-scalable-no.html", true, 0, &client, enableViewportSettings);
1806 webViewHelper.webView()->settings()->setViewportMetaNonUserScalableQuirk(true);
1807 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1808 webViewHelper.webView()->layout();
1810 EXPECT_NEAR(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1811 EXPECT_NEAR(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1812 EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1815 TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScaleForNonWideViewport)
1817 UseMockScrollbarSettings mockScrollbarSettings;
1818 registerMockedHttpURLLoad("viewport-initial-scale-and-user-scalable-no.html");
1820 FixedLayoutTestWebViewClient client;
1821 client.m_screenInfo.deviceScaleFactor = 1.33f;
1822 int viewportWidth = 640;
1823 int viewportHeight = 480;
1825 FrameTestHelpers::WebViewHelper webViewHelper;
1826 webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-and-user-scalable-no.html", true, 0, &client, enableViewportSettings);
1827 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1828 webViewHelper.webView()->settings()->setViewportMetaNonUserScalableQuirk(true);
1829 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1830 webViewHelper.webView()->settings()->setUseWideViewport(false);
1831 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1832 webViewHelper.webView()->layout();
1834 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1835 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1836 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1839 TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScaleForWideViewport)
1841 UseMockScrollbarSettings mockScrollbarSettings;
1842 registerMockedHttpURLLoad("viewport-2x-initial-scale-non-user-scalable.html");
1844 FixedLayoutTestWebViewClient client;
1845 int viewportWidth = 640;
1846 int viewportHeight = 480;
1848 FrameTestHelpers::WebViewHelper webViewHelper;
1849 webViewHelper.initializeAndLoad(m_baseURL + "viewport-2x-initial-scale-non-user-scalable.html", true, 0, &client, enableViewportSettings);
1850 webViewHelper.webView()->settings()->setViewportMetaNonUserScalableQuirk(true);
1851 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1852 webViewHelper.webView()->settings()->setUseWideViewport(true);
1853 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1855 EXPECT_NEAR(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1856 EXPECT_NEAR(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1857 EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1860 TEST_F(WebFrameTest, DesktopPageCanBeZoomedInWhenWideViewportIsTurnedOff)
1862 UseMockScrollbarSettings mockScrollbarSettings;
1863 registerMockedHttpURLLoad("no_viewport_tag.html");
1865 FixedLayoutTestWebViewClient client;
1866 int viewportWidth = 640;
1867 int viewportHeight = 480;
1869 FrameTestHelpers::WebViewHelper webViewHelper;
1870 webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client, enableViewportSettings);
1871 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1872 webViewHelper.webView()->settings()->setUseWideViewport(false);
1873 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1875 EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1876 EXPECT_NEAR(1.0f, webViewHelper.webView()->minimumPageScaleFactor(), 0.01f);
1877 EXPECT_NEAR(5.0f, webViewHelper.webView()->maximumPageScaleFactor(), 0.01f);
1880 class WebFrameResizeTest : public WebFrameTest {
1883 static FloatSize computeRelativeOffset(const IntPoint& absoluteOffset, const LayoutRect& rect)
1885 FloatSize relativeOffset = FloatPoint(absoluteOffset) - rect.location();
1886 relativeOffset.scale(1.f / rect.width(), 1.f / rect.height());
1887 return relativeOffset;
1890 void testResizeYieldsCorrectScrollAndScale(const char* url,
1891 const float initialPageScaleFactor,
1892 const WebSize scrollOffset,
1893 const WebSize viewportSize,
1894 const bool shouldScaleRelativeToViewportWidth) {
1895 UseMockScrollbarSettings mockScrollbarSettings;
1896 registerMockedHttpURLLoad(url);
1898 const float aspectRatio = static_cast<float>(viewportSize.width) / viewportSize.height;
1900 FrameTestHelpers::WebViewHelper webViewHelper;
1901 webViewHelper.initializeAndLoad(m_baseURL + url, true, 0, 0, enableViewportSettings);
1903 // Origin scrollOffsets preserved under resize.
1905 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height));
1906 webViewHelper.webViewImpl()->setPageScaleFactor(initialPageScaleFactor);
1907 ASSERT_EQ(viewportSize, webViewHelper.webViewImpl()->size());
1908 ASSERT_EQ(initialPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor());
1909 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.height, viewportSize.width));
1910 float expectedPageScaleFactor = initialPageScaleFactor * (shouldScaleRelativeToViewportWidth ? 1 / aspectRatio : 1);
1911 EXPECT_NEAR(expectedPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor(), 0.05f);
1912 EXPECT_EQ(WebSize(), webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
1915 // Resizing just the height should not affect pageScaleFactor or scrollOffset.
1917 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height));
1918 webViewHelper.webViewImpl()->setPageScaleFactor(initialPageScaleFactor);
1919 webViewHelper.webViewImpl()->setMainFrameScrollOffset(WebPoint(scrollOffset.width, scrollOffset.height));
1920 webViewHelper.webViewImpl()->layout();
1921 const WebSize expectedScrollOffset = webViewHelper.webViewImpl()->mainFrame()->scrollOffset();
1922 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height * 0.8f));
1923 EXPECT_EQ(initialPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor());
1924 EXPECT_EQ(expectedScrollOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
1925 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height * 0.8f));
1926 EXPECT_EQ(initialPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor());
1927 EXPECT_EQ(expectedScrollOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
1930 // Generic resize preserves scrollOffset relative to anchor node located
1931 // the top center of the screen.
1933 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.height, viewportSize.width));
1934 float pageScaleFactor = webViewHelper.webViewImpl()->pageScaleFactor();
1935 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height));
1936 float expectedPageScaleFactor = pageScaleFactor * (shouldScaleRelativeToViewportWidth ? aspectRatio : 1);
1937 EXPECT_NEAR(expectedPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor(), 0.05f);
1938 webViewHelper.webViewImpl()->mainFrame()->setScrollOffset(scrollOffset);
1940 IntPoint anchorPoint = IntPoint(scrollOffset) + IntPoint(viewportSize.width / 2, 0);
1941 RefPtrWillBeRawPtr<Node> anchorNode = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->eventHandler().hitTestResultAtPoint(anchorPoint, HitTestRequest::ReadOnly | HitTestRequest::Active).innerNode();
1944 pageScaleFactor = webViewHelper.webViewImpl()->pageScaleFactor();
1945 const FloatSize preResizeRelativeOffset
1946 = computeRelativeOffset(anchorPoint, anchorNode->boundingBox());
1947 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.height, viewportSize.width));
1948 IntPoint newAnchorPoint = IntPoint(webViewHelper.webViewImpl()->mainFrame()->scrollOffset()) + IntPoint(viewportSize.height / 2, 0);
1949 const FloatSize postResizeRelativeOffset
1950 = computeRelativeOffset(newAnchorPoint, anchorNode->boundingBox());
1951 EXPECT_NEAR(preResizeRelativeOffset.width(), postResizeRelativeOffset.width(), 0.15f);
1952 expectedPageScaleFactor = pageScaleFactor * (shouldScaleRelativeToViewportWidth ? 1 / aspectRatio : 1);
1953 EXPECT_NEAR(expectedPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor(), 0.05f);
1958 TEST_F(WebFrameResizeTest, ResizeYieldsCorrectScrollAndScaleForWidthEqualsDeviceWidth)
1960 // With width=device-width, pageScaleFactor is preserved across resizes as
1961 // long as the content adjusts according to the device-width.
1962 const char* url = "resize_scroll_mobile.html";
1963 const float initialPageScaleFactor = 1;
1964 const WebSize scrollOffset(0, 50);
1965 const WebSize viewportSize(120, 160);
1966 const bool shouldScaleRelativeToViewportWidth = true;
1968 testResizeYieldsCorrectScrollAndScale(
1969 url, initialPageScaleFactor, scrollOffset, viewportSize, shouldScaleRelativeToViewportWidth);
1972 TEST_F(WebFrameResizeTest, ResizeYieldsCorrectScrollAndScaleForMinimumScale)
1974 // This tests a scenario where minimum-scale is set to 1.0, but some element
1975 // on the page is slightly larger than the portrait width, so our "natural"
1976 // minimum-scale would be lower. In that case, we should stick to 1.0 scale
1977 // on rotation and not do anything strange.
1978 const char* url = "resize_scroll_minimum_scale.html";
1979 const float initialPageScaleFactor = 1;
1980 const WebSize scrollOffset(0, 0);
1981 const WebSize viewportSize(240, 320);
1982 const bool shouldScaleRelativeToViewportWidth = false;
1984 testResizeYieldsCorrectScrollAndScale(
1985 url, initialPageScaleFactor, scrollOffset, viewportSize, shouldScaleRelativeToViewportWidth);
1988 TEST_F(WebFrameResizeTest, ResizeYieldsCorrectScrollAndScaleForFixedWidth)
1990 // With a fixed width, pageScaleFactor scales by the relative change in viewport width.
1991 const char* url = "resize_scroll_fixed_width.html";
1992 const float initialPageScaleFactor = 2;
1993 const WebSize scrollOffset(0, 200);
1994 const WebSize viewportSize(240, 320);
1995 const bool shouldScaleRelativeToViewportWidth = true;
1997 testResizeYieldsCorrectScrollAndScale(
1998 url, initialPageScaleFactor, scrollOffset, viewportSize, shouldScaleRelativeToViewportWidth);
2001 TEST_F(WebFrameResizeTest, ResizeYieldsCorrectScrollAndScaleForFixedLayout)
2003 // With a fixed layout, pageScaleFactor scales by the relative change in viewport width.
2004 const char* url = "resize_scroll_fixed_layout.html";
2005 const float initialPageScaleFactor = 2;
2006 const WebSize scrollOffset(200, 400);
2007 const WebSize viewportSize(320, 240);
2008 const bool shouldScaleRelativeToViewportWidth = true;
2010 testResizeYieldsCorrectScrollAndScale(
2011 url, initialPageScaleFactor, scrollOffset, viewportSize, shouldScaleRelativeToViewportWidth);
2014 TEST_F(WebFrameTest, pageScaleFactorScalesPaintClip)
2016 UseMockScrollbarSettings mockScrollbarSettings;
2017 registerMockedHttpURLLoad("large-div.html");
2019 FixedLayoutTestWebViewClient client;
2020 client.m_screenInfo.deviceScaleFactor = 1;
2021 int viewportWidth = 50;
2022 int viewportHeight = 50;
2024 FrameTestHelpers::WebViewHelper webViewHelper;
2025 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client);
2026 // FIXME: This test breaks if the viewport is enabled before loading the page due to the paint
2027 // calls below not working on composited layers. For some reason, enabling the viewport here
2028 // doesn't cause compositing
2029 webViewHelper.webView()->settings()->setViewportEnabled(true);
2030 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2031 webViewHelper.webView()->layout();
2033 // Set <1 page scale so that the clip rect should be larger than
2034 // the viewport size as passed into resize().
2035 webViewHelper.webView()->setPageScaleFactor(0.5);
2038 bitmap.allocN32Pixels(200, 200);
2039 bitmap.eraseColor(0);
2040 SkCanvas canvas(bitmap);
2042 GraphicsContext context(&canvas);
2043 context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
2045 EXPECT_RECT_EQ(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
2047 FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
2048 IntRect paintRect(0, 0, 200, 200);
2049 view->paint(&context, paintRect);
2051 // FIXME: This test broke in release builds when changing the FixedLayoutTestWebViewClient
2052 // to return a non-null layerTreeView, which is what all our shipping configurations do,
2053 // so this is just exposing an existing bug.
2056 int viewportWidthMinusScrollbar = 50 - (view->verticalScrollbar()->isOverlayScrollbar() ? 0 : 15);
2057 int viewportHeightMinusScrollbar = 50 - (view->horizontalScrollbar()->isOverlayScrollbar() ? 0 : 15);
2058 IntRect clippedRect(0, 0, viewportWidthMinusScrollbar * 2, viewportHeightMinusScrollbar * 2);
2059 EXPECT_RECT_EQ(clippedRect, context.opaqueRegion().asRect());
2063 TEST_F(WebFrameTest, pageScaleFactorUpdatesScrollbars)
2065 UseMockScrollbarSettings mockScrollbarSettings;
2066 registerMockedHttpURLLoad("fixed_layout.html");
2068 FixedLayoutTestWebViewClient client;
2069 client.m_screenInfo.deviceScaleFactor = 1;
2070 int viewportWidth = 640;
2071 int viewportHeight = 480;
2073 FrameTestHelpers::WebViewHelper webViewHelper;
2074 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
2075 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2076 webViewHelper.webView()->layout();
2078 FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
2079 EXPECT_EQ(view->scrollSize(HorizontalScrollbar), view->contentsSize().width() - view->visibleContentRect().width());
2080 EXPECT_EQ(view->scrollSize(VerticalScrollbar), view->contentsSize().height() - view->visibleContentRect().height());
2082 webViewHelper.webView()->setPageScaleFactor(10);
2084 EXPECT_EQ(view->scrollSize(HorizontalScrollbar), view->contentsSize().width() - view->visibleContentRect().width());
2085 EXPECT_EQ(view->scrollSize(VerticalScrollbar), view->contentsSize().height() - view->visibleContentRect().height());
2088 TEST_F(WebFrameTest, CanOverrideScaleLimits)
2090 UseMockScrollbarSettings mockScrollbarSettings;
2092 registerMockedHttpURLLoad("no_scale_for_you.html");
2094 FixedLayoutTestWebViewClient client;
2095 client.m_screenInfo.deviceScaleFactor = 1;
2096 int viewportWidth = 640;
2097 int viewportHeight = 480;
2099 FrameTestHelpers::WebViewHelper webViewHelper;
2100 webViewHelper.initializeAndLoad(m_baseURL + "no_scale_for_you.html", true, 0, &client, enableViewportSettings);
2101 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2103 EXPECT_EQ(2.0f, webViewHelper.webView()->minimumPageScaleFactor());
2104 EXPECT_EQ(2.0f, webViewHelper.webView()->maximumPageScaleFactor());
2106 webViewHelper.webView()->setIgnoreViewportTagScaleLimits(true);
2107 webViewHelper.webView()->layout();
2109 EXPECT_EQ(1.0f, webViewHelper.webView()->minimumPageScaleFactor());
2110 EXPECT_EQ(5.0f, webViewHelper.webView()->maximumPageScaleFactor());
2112 webViewHelper.webView()->setIgnoreViewportTagScaleLimits(false);
2113 webViewHelper.webView()->layout();
2115 EXPECT_EQ(2.0f, webViewHelper.webView()->minimumPageScaleFactor());
2116 EXPECT_EQ(2.0f, webViewHelper.webView()->maximumPageScaleFactor());
2119 TEST_F(WebFrameTest, updateOverlayScrollbarLayers)
2121 UseMockScrollbarSettings mockScrollbarSettings;
2123 registerMockedHttpURLLoad("large-div.html");
2125 int viewWidth = 500;
2126 int viewHeight = 500;
2128 OwnPtr<FakeCompositingWebViewClient> fakeCompositingWebViewClient = adoptPtr(new FakeCompositingWebViewClient());
2129 FrameTestHelpers::WebViewHelper webViewHelper;
2130 webViewHelper.initialize(true, 0, fakeCompositingWebViewClient.get(), &configueCompositingWebView);
2132 webViewHelper.webView()->setPageScaleFactorLimits(1, 1);
2133 webViewHelper.webView()->resize(WebSize(viewWidth, viewHeight));
2134 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "large-div.html");
2136 FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
2137 EXPECT_TRUE(view->renderView()->compositor()->layerForHorizontalScrollbar());
2138 EXPECT_TRUE(view->renderView()->compositor()->layerForVerticalScrollbar());
2140 webViewHelper.webView()->resize(WebSize(viewWidth * 10, viewHeight * 10));
2141 webViewHelper.webView()->layout();
2142 EXPECT_FALSE(view->renderView()->compositor()->layerForHorizontalScrollbar());
2143 EXPECT_FALSE(view->renderView()->compositor()->layerForVerticalScrollbar());
2146 void setScaleAndScrollAndLayout(WebView* webView, WebPoint scroll, float scale)
2148 webView->setPageScaleFactor(scale);
2149 webView->setMainFrameScrollOffset(WebPoint(scroll.x, scroll.y));
2153 TEST_F(WebFrameTest, DivAutoZoomParamsTest)
2155 registerMockedHttpURLLoad("get_scale_for_auto_zoom_into_div_test.html");
2157 const float deviceScaleFactor = 2.0f;
2158 int viewportWidth = 640 / deviceScaleFactor;
2159 int viewportHeight = 1280 / deviceScaleFactor;
2160 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2161 FrameTestHelpers::WebViewHelper webViewHelper;
2162 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_for_auto_zoom_into_div_test.html");
2163 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2164 webViewHelper.webView()->setPageScaleFactorLimits(0.01f, 4);
2165 webViewHelper.webView()->setPageScaleFactor(0.5f);
2166 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2167 webViewHelper.webView()->layout();
2169 WebRect wideDiv(200, 100, 400, 150);
2170 WebRect tallDiv(200, 300, 400, 800);
2171 WebRect doubleTapPointWide(wideDiv.x + 50, wideDiv.y + 50, touchPointPadding, touchPointPadding);
2172 WebRect doubleTapPointTall(tallDiv.x + 50, tallDiv.y + 50, touchPointPadding, touchPointPadding);
2173 WebRect wideBlockBounds;
2174 WebRect tallBlockBounds;
2178 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2180 // Test double-tap zooming into wide div.
2181 wideBlockBounds = webViewHelper.webViewImpl()->computeBlockBounds(doubleTapPointWide, false);
2182 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(doubleTapPointWide.x, doubleTapPointWide.y), wideBlockBounds, touchPointPadding, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2183 // The div should horizontally fill the screen (modulo margins), and
2184 // vertically centered (modulo integer rounding).
2185 EXPECT_NEAR(viewportWidth / (float) wideDiv.width, scale, 0.1);
2186 EXPECT_NEAR(wideDiv.x, scroll.x, 20);
2187 EXPECT_EQ(0, scroll.y);
2189 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), scroll, scale);
2191 // Test zoom out back to minimum scale.
2192 wideBlockBounds = webViewHelper.webViewImpl()->computeBlockBounds(doubleTapPointWide, false);
2193 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(doubleTapPointWide.x, doubleTapPointWide.y), wideBlockBounds, touchPointPadding, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2195 scale = webViewHelper.webViewImpl()->minimumPageScaleFactor();
2196 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), scale);
2198 // Test double-tap zooming into tall div.
2199 tallBlockBounds = webViewHelper.webViewImpl()->computeBlockBounds(doubleTapPointTall, false);
2200 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(doubleTapPointTall.x, doubleTapPointTall.y), tallBlockBounds, touchPointPadding, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2201 // The div should start at the top left of the viewport.
2202 EXPECT_NEAR(viewportWidth / (float) tallDiv.width, scale, 0.1);
2203 EXPECT_NEAR(tallDiv.x, scroll.x, 20);
2204 EXPECT_NEAR(tallDiv.y, scroll.y, 20);
2206 // Test for Non-doubletap scaling
2207 // Test zooming into div.
2208 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(250, 250), webViewHelper.webViewImpl()->computeBlockBounds(WebRect(250, 250, 10, 10), true), 0, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2209 EXPECT_NEAR(viewportWidth / (float) wideDiv.width, scale, 0.1);
2212 void simulatePageScale(WebViewImpl* webViewImpl, float& scale)
2214 IntSize scrollDelta = webViewImpl->fakePageScaleAnimationTargetPositionForTesting() - webViewImpl->mainFrameImpl()->frameView()->scrollPosition();
2215 float scaleDelta = webViewImpl->fakePageScaleAnimationPageScaleForTesting() / webViewImpl->pageScaleFactor();
2216 webViewImpl->applyViewportDeltas(scrollDelta, scaleDelta, 0);
2217 scale = webViewImpl->pageScaleFactor();
2220 void simulateMultiTargetZoom(WebViewImpl* webViewImpl, const WebRect& rect, float& scale)
2222 if (webViewImpl->zoomToMultipleTargetsRect(rect))
2223 simulatePageScale(webViewImpl, scale);
2226 void simulateDoubleTap(WebViewImpl* webViewImpl, WebPoint& point, float& scale)
2228 webViewImpl->animateDoubleTapZoom(point);
2229 EXPECT_TRUE(webViewImpl->fakeDoubleTapAnimationPendingForTesting());
2230 simulatePageScale(webViewImpl, scale);
2233 TEST_F(WebFrameTest, DivAutoZoomWideDivTest)
2235 registerMockedHttpURLLoad("get_wide_div_for_auto_zoom_test.html");
2237 const float deviceScaleFactor = 2.0f;
2238 int viewportWidth = 640 / deviceScaleFactor;
2239 int viewportHeight = 1280 / deviceScaleFactor;
2240 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2241 FrameTestHelpers::WebViewHelper webViewHelper;
2242 webViewHelper.initializeAndLoad(m_baseURL + "get_wide_div_for_auto_zoom_test.html");
2243 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2244 webViewHelper.webView()->setPageScaleFactorLimits(1.0f, 4);
2245 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2246 webViewHelper.webView()->setPageScaleFactor(1.0f);
2247 webViewHelper.webView()->layout();
2249 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2251 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2253 WebRect div(0, 100, viewportWidth, 150);
2254 WebPoint point(div.x + 50, div.y + 50);
2256 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2258 simulateDoubleTap(webViewHelper.webViewImpl(), point, scale);
2259 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2260 simulateDoubleTap(webViewHelper.webViewImpl(), point, scale);
2261 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2264 TEST_F(WebFrameTest, DivAutoZoomVeryTallTest)
2266 // When a block is taller than the viewport and a zoom targets a lower part
2267 // of it, then we should keep the target point onscreen instead of snapping
2268 // back up the top of the block.
2269 registerMockedHttpURLLoad("very_tall_div.html");
2271 const float deviceScaleFactor = 2.0f;
2272 int viewportWidth = 640 / deviceScaleFactor;
2273 int viewportHeight = 1280 / deviceScaleFactor;
2274 FrameTestHelpers::WebViewHelper webViewHelper;
2275 webViewHelper.initializeAndLoad(m_baseURL + "very_tall_div.html", true, 0, 0, enableViewportSettings);
2276 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2277 webViewHelper.webView()->setPageScaleFactorLimits(1.0f, 4);
2278 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2279 webViewHelper.webView()->setPageScaleFactor(1.0f);
2280 webViewHelper.webView()->layout();
2282 WebRect div(200, 300, 400, 5000);
2283 WebPoint point(div.x + 50, div.y + 3000);
2287 WebRect blockBounds = webViewHelper.webViewImpl()->computeBlockBounds(WebRect(point.x, point.y, 0, 0), true);
2288 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(point, blockBounds, 0, 1.0f, scale, scroll);
2289 EXPECT_EQ(scale, 1.0f);
2290 EXPECT_EQ(scroll.y, 2660);
2293 TEST_F(WebFrameTest, DivAutoZoomMultipleDivsTest)
2295 registerMockedHttpURLLoad("get_multiple_divs_for_auto_zoom_test.html");
2297 const float deviceScaleFactor = 2.0f;
2298 int viewportWidth = 640 / deviceScaleFactor;
2299 int viewportHeight = 1280 / deviceScaleFactor;
2300 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2301 FrameTestHelpers::WebViewHelper webViewHelper;
2302 webViewHelper.initializeAndLoad(m_baseURL + "get_multiple_divs_for_auto_zoom_test.html");
2303 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2304 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2305 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2306 webViewHelper.webView()->setPageScaleFactor(0.5f);
2307 webViewHelper.webView()->layout();
2309 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2311 WebRect topDiv(200, 100, 200, 150);
2312 WebRect bottomDiv(200, 300, 200, 150);
2313 WebPoint topPoint(topDiv.x + 50, topDiv.y + 50);
2314 WebPoint bottomPoint(bottomDiv.x + 50, bottomDiv.y + 50);
2316 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2318 // Test double tap on two different divs
2319 // After first zoom, we should go back to minimum page scale with a second double tap.
2320 simulateDoubleTap(webViewHelper.webViewImpl(), topPoint, scale);
2321 EXPECT_FLOAT_EQ(1, scale);
2322 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2323 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2325 // If the user pinch zooms after double tap, a second double tap should zoom back to the div.
2326 simulateDoubleTap(webViewHelper.webViewImpl(), topPoint, scale);
2327 EXPECT_FLOAT_EQ(1, scale);
2328 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(), 0.6f, 0);
2329 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2330 EXPECT_FLOAT_EQ(1, scale);
2331 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2332 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2334 // If we didn't yet get an auto-zoom update and a second double-tap arrives, should go back to minimum scale.
2335 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(), 1.1f, 0);
2336 webViewHelper.webViewImpl()->animateDoubleTapZoom(topPoint);
2337 EXPECT_TRUE(webViewHelper.webViewImpl()->fakeDoubleTapAnimationPendingForTesting());
2338 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2339 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2342 TEST_F(WebFrameTest, DivAutoZoomScaleBoundsTest)
2344 registerMockedHttpURLLoad("get_scale_bounds_check_for_auto_zoom_test.html");
2346 int viewportWidth = 320;
2347 int viewportHeight = 480;
2348 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2349 FrameTestHelpers::WebViewHelper webViewHelper;
2350 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_bounds_check_for_auto_zoom_test.html");
2351 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2352 webViewHelper.webView()->setDeviceScaleFactor(1.5f);
2353 webViewHelper.webView()->layout();
2355 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2357 WebRect div(200, 100, 200, 150);
2358 WebPoint doubleTapPoint(div.x + 50, div.y + 50);
2361 // Test double tap scale bounds.
2362 // minimumPageScale < doubleTapZoomAlreadyLegibleScale < 1
2363 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2364 webViewHelper.webView()->layout();
2365 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2366 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2367 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2368 EXPECT_FLOAT_EQ(1, scale);
2369 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2370 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2371 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2372 EXPECT_FLOAT_EQ(1, scale);
2374 // Zoom in to reset double_tap_zoom_in_effect flag.
2375 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(), 1.1f, 0);
2376 // 1 < minimumPageScale < doubleTapZoomAlreadyLegibleScale
2377 webViewHelper.webView()->setPageScaleFactorLimits(1.1f, 4);
2378 webViewHelper.webView()->layout();
2379 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2380 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2381 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2382 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2383 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2384 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2385 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2386 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2388 // Zoom in to reset double_tap_zoom_in_effect flag.
2389 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(), 1.1f, 0);
2390 // minimumPageScale < 1 < doubleTapZoomAlreadyLegibleScale
2391 webViewHelper.webView()->setPageScaleFactorLimits(0.95f, 4);
2392 webViewHelper.webView()->layout();
2393 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2394 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2395 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2396 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2397 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2398 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2399 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2400 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2403 TEST_F(WebFrameTest, DivAutoZoomScaleFontScaleFactorTest)
2405 registerMockedHttpURLLoad("get_scale_bounds_check_for_auto_zoom_test.html");
2407 int viewportWidth = 320;
2408 int viewportHeight = 480;
2409 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2410 float accessibilityFontScaleFactor = 1.13f;
2411 FrameTestHelpers::WebViewHelper webViewHelper;
2412 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_bounds_check_for_auto_zoom_test.html");
2413 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2414 webViewHelper.webView()->layout();
2416 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2417 webViewHelper.webViewImpl()->page()->settings().setTextAutosizingEnabled(true);
2418 webViewHelper.webViewImpl()->page()->settings().setAccessibilityFontScaleFactor(accessibilityFontScaleFactor);
2420 WebRect div(200, 100, 200, 150);
2421 WebPoint doubleTapPoint(div.x + 50, div.y + 50);
2424 // Test double tap scale bounds.
2425 // minimumPageScale < doubleTapZoomAlreadyLegibleScale < 1 < accessibilityFontScaleFactor
2426 float legibleScale = accessibilityFontScaleFactor;
2427 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2428 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2429 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2430 webViewHelper.webView()->layout();
2431 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2432 EXPECT_FLOAT_EQ(legibleScale, scale);
2433 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2434 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2435 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2436 EXPECT_FLOAT_EQ(legibleScale, scale);
2438 // Zoom in to reset double_tap_zoom_in_effect flag.
2439 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(), 1.1f, 0);
2440 // 1 < accessibilityFontScaleFactor < minimumPageScale < doubleTapZoomAlreadyLegibleScale
2441 webViewHelper.webView()->setPageScaleFactorLimits(1.0f, 4);
2442 webViewHelper.webView()->layout();
2443 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2444 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2445 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2446 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2447 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2448 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2449 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2450 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2452 // Zoom in to reset double_tap_zoom_in_effect flag.
2453 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(), 1.1f, 0);
2454 // minimumPageScale < 1 < accessibilityFontScaleFactor < doubleTapZoomAlreadyLegibleScale
2455 webViewHelper.webView()->setPageScaleFactorLimits(0.95f, 4);
2456 webViewHelper.webView()->layout();
2457 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2458 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2459 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2460 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2461 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2462 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2463 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2464 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2466 // Zoom in to reset double_tap_zoom_in_effect flag.
2467 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(), 1.1f, 0);
2468 // minimumPageScale < 1 < doubleTapZoomAlreadyLegibleScale < accessibilityFontScaleFactor
2469 webViewHelper.webView()->setPageScaleFactorLimits(0.9f, 4);
2470 webViewHelper.webView()->layout();
2471 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2472 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2473 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2474 EXPECT_FLOAT_EQ(legibleScale, scale);
2475 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2476 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2477 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2478 EXPECT_FLOAT_EQ(legibleScale, scale);
2481 TEST_F(WebFrameTest, DivMultipleTargetZoomMultipleDivsTest)
2483 registerMockedHttpURLLoad("get_multiple_divs_for_auto_zoom_test.html");
2485 const float deviceScaleFactor = 2.0f;
2486 int viewportWidth = 640 / deviceScaleFactor;
2487 int viewportHeight = 1280 / deviceScaleFactor;
2488 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2489 FrameTestHelpers::WebViewHelper webViewHelper;
2490 webViewHelper.initializeAndLoad(m_baseURL + "get_multiple_divs_for_auto_zoom_test.html");
2491 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2492 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2493 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2494 webViewHelper.webView()->setPageScaleFactor(0.5f);
2495 webViewHelper.webView()->layout();
2497 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2499 WebRect viewportRect(0, 0, viewportWidth, viewportHeight);
2500 WebRect topDiv(200, 100, 200, 150);
2501 WebRect bottomDiv(200, 300, 200, 150);
2503 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2505 simulateMultiTargetZoom(webViewHelper.webViewImpl(), topDiv, scale);
2506 EXPECT_FLOAT_EQ(1, scale);
2507 simulateMultiTargetZoom(webViewHelper.webViewImpl(), bottomDiv, scale);
2508 EXPECT_FLOAT_EQ(1, scale);
2509 simulateMultiTargetZoom(webViewHelper.webViewImpl(), viewportRect, scale);
2510 EXPECT_FLOAT_EQ(1, scale);
2511 webViewHelper.webViewImpl()->setPageScaleFactor(webViewHelper.webViewImpl()->minimumPageScaleFactor());
2512 simulateMultiTargetZoom(webViewHelper.webViewImpl(), topDiv, scale);
2513 EXPECT_FLOAT_EQ(1, scale);
2516 TEST_F(WebFrameTest, DivScrollIntoEditableTest)
2518 registerMockedHttpURLLoad("get_scale_for_zoom_into_editable_test.html");
2520 int viewportWidth = 450;
2521 int viewportHeight = 300;
2522 float leftBoxRatio = 0.3f;
2523 int caretPadding = 10;
2524 float minReadableCaretHeight = 18.0f;
2525 FrameTestHelpers::WebViewHelper webViewHelper;
2526 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_for_zoom_into_editable_test.html");
2527 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2528 webViewHelper.webView()->setPageScaleFactorLimits(1, 4);
2529 webViewHelper.webView()->layout();
2530 webViewHelper.webView()->setDeviceScaleFactor(1.5f);
2531 webViewHelper.webView()->settings()->setAutoZoomFocusedNodeToLegibleScale(true);
2533 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2535 WebRect editBoxWithText(200, 200, 250, 20);
2536 WebRect editBoxWithNoText(200, 250, 250, 20);
2538 // Test scrolling the focused node
2539 // The edit box is shorter and narrower than the viewport when legible.
2540 webViewHelper.webView()->advanceFocus(false);
2541 // Set the caret to the end of the input box.
2542 webViewHelper.webView()->mainFrame()->document().getElementById("EditBoxWithText").to<WebInputElement>().setSelectionRange(1000, 1000);
2543 setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), 1);
2544 WebRect rect, caret;
2545 webViewHelper.webViewImpl()->selectionBounds(caret, rect);
2550 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2551 EXPECT_TRUE(needAnimation);
2552 // The edit box should be left aligned with a margin for possible label.
2553 int hScroll = editBoxWithText.x - leftBoxRatio * viewportWidth / scale;
2554 EXPECT_NEAR(hScroll, scroll.x(), 1);
2555 int vScroll = editBoxWithText.y - (viewportHeight / scale - editBoxWithText.height) / 2;
2556 EXPECT_NEAR(vScroll, scroll.y(), 1);
2557 EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1);
2559 // The edit box is wider than the viewport when legible.
2560 viewportWidth = 200;
2561 viewportHeight = 150;
2562 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2563 setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), 1);
2564 webViewHelper.webViewImpl()->selectionBounds(caret, rect);
2565 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2566 EXPECT_TRUE(needAnimation);
2567 // The caret should be right aligned since the caret would be offscreen when the edit box is left aligned.
2568 hScroll = caret.x + caret.width + caretPadding - viewportWidth / scale;
2569 EXPECT_NEAR(hScroll, scroll.x(), 1);
2570 EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1);
2572 setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), 1);
2573 // Move focus to edit box with text.
2574 webViewHelper.webView()->advanceFocus(false);
2575 webViewHelper.webViewImpl()->selectionBounds(caret, rect);
2576 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2577 EXPECT_TRUE(needAnimation);
2578 // The edit box should be left aligned.
2579 hScroll = editBoxWithNoText.x;
2580 EXPECT_NEAR(hScroll, scroll.x(), 1);
2581 vScroll = editBoxWithNoText.y - (viewportHeight / scale - editBoxWithNoText.height) / 2;
2582 EXPECT_NEAR(vScroll, scroll.y(), 1);
2583 EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1);
2585 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), scroll, scale);
2587 // Move focus back to the first edit box.
2588 webViewHelper.webView()->advanceFocus(true);
2589 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2590 // The position should have stayed the same since this box was already on screen with the right scale.
2591 EXPECT_FALSE(needAnimation);
2594 TEST_F(WebFrameTest, DivScrollIntoEditablePreservePageScaleTest)
2596 registerMockedHttpURLLoad("get_scale_for_zoom_into_editable_test.html");
2598 const int viewportWidth = 450;
2599 const int viewportHeight = 300;
2600 const float minReadableCaretHeight = 18.0f;
2601 FrameTestHelpers::WebViewHelper webViewHelper;
2602 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_for_zoom_into_editable_test.html");
2603 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2604 webViewHelper.webView()->setPageScaleFactorLimits(1, 4);
2605 webViewHelper.webView()->layout();
2606 webViewHelper.webView()->setDeviceScaleFactor(1.5f);
2607 webViewHelper.webView()->settings()->setAutoZoomFocusedNodeToLegibleScale(true);
2608 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2610 const WebRect editBoxWithText(200, 200, 250, 20);
2612 webViewHelper.webView()->advanceFocus(false);
2613 // Set the caret to the begining of the input box.
2614 webViewHelper.webView()->mainFrame()->document().getElementById("EditBoxWithText").to<WebInputElement>().setSelectionRange(0, 0);
2615 setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), 1);
2616 WebRect rect, caret;
2617 webViewHelper.webViewImpl()->selectionBounds(caret, rect);
2619 // Set page scale twice larger then minimal readable scale
2620 float newScale = minReadableCaretHeight / caret.height * 2.0;
2621 setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), newScale);
2626 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2627 EXPECT_TRUE(needAnimation);
2628 // Edit box and caret should be left alinged
2629 int hScroll = editBoxWithText.x;
2630 EXPECT_NEAR(hScroll, scroll.x(), 1);
2631 int vScroll = editBoxWithText.y - (viewportHeight / scale - editBoxWithText.height) / 2;
2632 EXPECT_NEAR(vScroll, scroll.y(), 1);
2633 // Page scale have to be unchanged
2634 EXPECT_EQ(newScale, scale);
2636 // Set page scale and scroll such that edit box will be under the screen
2639 setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(hScroll, 0), newScale);
2640 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2641 EXPECT_TRUE(needAnimation);
2642 // Horizontal scroll have to be the same
2643 EXPECT_NEAR(hScroll, scroll.x(), 1);
2644 vScroll = editBoxWithText.y - (viewportHeight / scale - editBoxWithText.height) / 2;
2645 EXPECT_NEAR(vScroll, scroll.y(), 1);
2646 // Page scale have to be unchanged
2647 EXPECT_EQ(newScale, scale);
2650 class TestReloadDoesntRedirectWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
2652 virtual WebNavigationPolicy decidePolicyForNavigation(const NavigationPolicyInfo& info) OVERRIDE
2654 EXPECT_FALSE(info.isRedirect);
2655 return WebNavigationPolicyCurrentTab;
2659 TEST_F(WebFrameTest, ReloadDoesntSetRedirect)
2661 // Test for case in http://crbug.com/73104. Reloading a frame very quickly
2662 // would sometimes call decidePolicyForNavigation with isRedirect=true
2663 registerMockedHttpURLLoad("form.html");
2665 TestReloadDoesntRedirectWebFrameClient webFrameClient;
2666 FrameTestHelpers::WebViewHelper webViewHelper;
2667 webViewHelper.initializeAndLoad(m_baseURL + "form.html", false, &webFrameClient);
2669 webViewHelper.webView()->mainFrame()->reload(true);
2670 // start another reload before request is delivered.
2671 FrameTestHelpers::reloadFrameIgnoringCache(webViewHelper.webView()->mainFrame());
2674 class ReloadWithOverrideURLTask : public WebThread::Task {
2676 ReloadWithOverrideURLTask(WebFrame* frame, const KURL& url, bool ignoreCache)
2677 : m_frame(frame), m_url(url), m_ignoreCache(ignoreCache)
2681 virtual void run() OVERRIDE
2683 m_frame->reloadWithOverrideURL(m_url, m_ignoreCache);
2687 WebFrame* const m_frame;
2689 const bool m_ignoreCache;
2692 TEST_F(WebFrameTest, ReloadWithOverrideURLPreservesState)
2694 const std::string firstURL = "find.html";
2695 const std::string secondURL = "form.html";
2696 const std::string thirdURL = "history.html";
2697 const float pageScaleFactor = 1.1684f;
2698 const int pageWidth = 640;
2699 const int pageHeight = 480;
2701 registerMockedHttpURLLoad(firstURL);
2702 registerMockedHttpURLLoad(secondURL);
2703 registerMockedHttpURLLoad(thirdURL);
2705 FrameTestHelpers::WebViewHelper webViewHelper;
2706 webViewHelper.initializeAndLoad(m_baseURL + firstURL, true);
2707 webViewHelper.webViewImpl()->resize(WebSize(pageWidth, pageHeight));
2708 webViewHelper.webViewImpl()->mainFrame()->setScrollOffset(WebSize(pageWidth / 4, pageHeight / 4));
2709 webViewHelper.webViewImpl()->setPageScaleFactor(pageScaleFactor);
2711 WebSize previousOffset = webViewHelper.webViewImpl()->mainFrame()->scrollOffset();
2712 float previousScale = webViewHelper.webViewImpl()->pageScaleFactor();
2714 // Reload the page using the cache.
2715 Platform::current()->currentThread()->postTask(
2716 new ReloadWithOverrideURLTask(webViewHelper.webViewImpl()->mainFrame(), toKURL(m_baseURL + secondURL), false));
2717 FrameTestHelpers::pumpPendingRequestsDoNotUse(webViewHelper.webViewImpl()->mainFrame());
2718 ASSERT_EQ(previousOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
2719 ASSERT_EQ(previousScale, webViewHelper.webViewImpl()->pageScaleFactor());
2721 // Reload the page while ignoring the cache.
2722 Platform::current()->currentThread()->postTask(
2723 new ReloadWithOverrideURLTask(webViewHelper.webViewImpl()->mainFrame(), toKURL(m_baseURL + thirdURL), true));
2724 FrameTestHelpers::pumpPendingRequestsDoNotUse(webViewHelper.webViewImpl()->mainFrame());
2725 ASSERT_EQ(previousOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
2726 ASSERT_EQ(previousScale, webViewHelper.webViewImpl()->pageScaleFactor());
2729 TEST_F(WebFrameTest, ReloadWhileProvisional)
2731 // Test that reloading while the previous load is still pending does not cause the initial
2732 // request to get lost.
2733 registerMockedHttpURLLoad("fixed_layout.html");
2735 FrameTestHelpers::WebViewHelper webViewHelper;
2736 webViewHelper.initialize();
2737 WebURLRequest request;
2738 request.initialize();
2739 request.setURL(toKURL(m_baseURL + "fixed_layout.html"));
2740 webViewHelper.webView()->mainFrame()->loadRequest(request);
2741 // start reload before first request is delivered.
2742 FrameTestHelpers::reloadFrameIgnoringCache(webViewHelper.webView()->mainFrame());
2744 WebDataSource* dataSource = webViewHelper.webView()->mainFrame()->dataSource();
2745 ASSERT_TRUE(dataSource);
2746 EXPECT_EQ(toKURL(m_baseURL + "fixed_layout.html"), toKURL(dataSource->request().url().spec()));
2749 TEST_F(WebFrameTest, AppendRedirects)
2751 const std::string firstURL = "about:blank";
2752 const std::string secondURL = "http://www.test.com";
2754 FrameTestHelpers::WebViewHelper webViewHelper;
2755 webViewHelper.initializeAndLoad(firstURL, true);
2757 WebDataSource* dataSource = webViewHelper.webView()->mainFrame()->dataSource();
2758 ASSERT_TRUE(dataSource);
2759 dataSource->appendRedirect(toKURL(secondURL));
2761 WebVector<WebURL> redirects;
2762 dataSource->redirectChain(redirects);
2763 ASSERT_EQ(2U, redirects.size());
2764 EXPECT_EQ(toKURL(firstURL), toKURL(redirects[0].spec().data()));
2765 EXPECT_EQ(toKURL(secondURL), toKURL(redirects[1].spec().data()));
2768 TEST_F(WebFrameTest, IframeRedirect)
2770 registerMockedHttpURLLoad("iframe_redirect.html");
2771 registerMockedHttpURLLoad("visible_iframe.html");
2773 FrameTestHelpers::WebViewHelper webViewHelper;
2774 webViewHelper.initializeAndLoad(m_baseURL + "iframe_redirect.html", true);
2775 // Pump pending requests one more time. The test page loads script that navigates.
2776 FrameTestHelpers::pumpPendingRequestsDoNotUse(webViewHelper.webView()->mainFrame());
2778 WebFrame* iframe = webViewHelper.webView()->findFrameByName(WebString::fromUTF8("ifr"));
2779 ASSERT_TRUE(iframe);
2780 WebDataSource* iframeDataSource = iframe->dataSource();
2781 ASSERT_TRUE(iframeDataSource);
2782 WebVector<WebURL> redirects;
2783 iframeDataSource->redirectChain(redirects);
2784 ASSERT_EQ(2U, redirects.size());
2785 EXPECT_EQ(toKURL("about:blank"), toKURL(redirects[0].spec().data()));
2786 EXPECT_EQ(toKURL("http://www.test.com/visible_iframe.html"), toKURL(redirects[1].spec().data()));
2789 TEST_F(WebFrameTest, ClearFocusedNodeTest)
2791 registerMockedHttpURLLoad("iframe_clear_focused_node_test.html");
2792 registerMockedHttpURLLoad("autofocus_input_field_iframe.html");
2794 FrameTestHelpers::WebViewHelper webViewHelper;
2795 webViewHelper.initializeAndLoad(m_baseURL + "iframe_clear_focused_node_test.html", true);
2797 // Clear the focused node.
2798 webViewHelper.webView()->clearFocusedElement();
2800 // Now retrieve the FocusedNode and test it should be null.
2801 EXPECT_EQ(0, webViewHelper.webViewImpl()->focusedElement());
2804 // Implementation of WebFrameClient that tracks the v8 contexts that are created
2805 // and destroyed for verification.
2806 class ContextLifetimeTestWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
2808 struct Notification {
2810 Notification(WebLocalFrame* frame, v8::Handle<v8::Context> context, int worldId)
2812 , context(context->GetIsolate(), context)
2822 bool Equals(Notification* other)
2824 return other && frame == other->frame && context == other->context && worldId == other->worldId;
2827 WebLocalFrame* frame;
2828 v8::Persistent<v8::Context> context;
2832 virtual ~ContextLifetimeTestWebFrameClient()
2839 for (size_t i = 0; i < createNotifications.size(); ++i)
2840 delete createNotifications[i];
2842 for (size_t i = 0; i < releaseNotifications.size(); ++i)
2843 delete releaseNotifications[i];
2845 createNotifications.clear();
2846 releaseNotifications.clear();
2849 std::vector<Notification*> createNotifications;
2850 std::vector<Notification*> releaseNotifications;
2853 virtual void didCreateScriptContext(WebLocalFrame* frame, v8::Handle<v8::Context> context, int extensionGroup, int worldId) OVERRIDE
2855 createNotifications.push_back(new Notification(frame, context, worldId));
2858 virtual void willReleaseScriptContext(WebLocalFrame* frame, v8::Handle<v8::Context> context, int worldId) OVERRIDE
2860 releaseNotifications.push_back(new Notification(frame, context, worldId));
2864 // TODO(aa): Deflake this test.
2865 TEST_F(WebFrameTest, FLAKY_ContextNotificationsLoadUnload)
2867 v8::HandleScope handleScope(v8::Isolate::GetCurrent());
2869 registerMockedHttpURLLoad("context_notifications_test.html");
2870 registerMockedHttpURLLoad("context_notifications_test_frame.html");
2872 // Load a frame with an iframe, make sure we get the right create notifications.
2873 ContextLifetimeTestWebFrameClient webFrameClient;
2874 FrameTestHelpers::WebViewHelper webViewHelper;
2875 webViewHelper.initializeAndLoad(m_baseURL + "context_notifications_test.html", true, &webFrameClient);
2877 WebFrame* mainFrame = webViewHelper.webView()->mainFrame();
2878 WebFrame* childFrame = mainFrame->firstChild();
2880 ASSERT_EQ(2u, webFrameClient.createNotifications.size());
2881 EXPECT_EQ(0u, webFrameClient.releaseNotifications.size());
2883 ContextLifetimeTestWebFrameClient::Notification* firstCreateNotification = webFrameClient.createNotifications[0];
2884 ContextLifetimeTestWebFrameClient::Notification* secondCreateNotification = webFrameClient.createNotifications[1];
2886 EXPECT_EQ(mainFrame, firstCreateNotification->frame);
2887 EXPECT_EQ(mainFrame->mainWorldScriptContext(), firstCreateNotification->context);
2888 EXPECT_EQ(0, firstCreateNotification->worldId);
2890 EXPECT_EQ(childFrame, secondCreateNotification->frame);
2891 EXPECT_EQ(childFrame->mainWorldScriptContext(), secondCreateNotification->context);
2892 EXPECT_EQ(0, secondCreateNotification->worldId);
2894 // Close the view. We should get two release notifications that are exactly the same as the create ones, in reverse order.
2895 webViewHelper.reset();
2897 ASSERT_EQ(2u, webFrameClient.releaseNotifications.size());
2898 ContextLifetimeTestWebFrameClient::Notification* firstReleaseNotification = webFrameClient.releaseNotifications[0];
2899 ContextLifetimeTestWebFrameClient::Notification* secondReleaseNotification = webFrameClient.releaseNotifications[1];
2901 ASSERT_TRUE(firstCreateNotification->Equals(secondReleaseNotification));
2902 ASSERT_TRUE(secondCreateNotification->Equals(firstReleaseNotification));
2905 TEST_F(WebFrameTest, ContextNotificationsReload)
2907 v8::HandleScope handleScope(v8::Isolate::GetCurrent());
2909 registerMockedHttpURLLoad("context_notifications_test.html");
2910 registerMockedHttpURLLoad("context_notifications_test_frame.html");
2912 ContextLifetimeTestWebFrameClient webFrameClient;
2913 FrameTestHelpers::WebViewHelper webViewHelper;
2914 webViewHelper.initializeAndLoad(m_baseURL + "context_notifications_test.html", true, &webFrameClient);
2916 // Refresh, we should get two release notifications and two more create notifications.
2917 FrameTestHelpers::reloadFrame(webViewHelper.webView()->mainFrame());
2918 ASSERT_EQ(4u, webFrameClient.createNotifications.size());
2919 ASSERT_EQ(2u, webFrameClient.releaseNotifications.size());
2921 // The two release notifications we got should be exactly the same as the first two create notifications.
2922 for (size_t i = 0; i < webFrameClient.releaseNotifications.size(); ++i) {
2923 EXPECT_TRUE(webFrameClient.releaseNotifications[i]->Equals(
2924 webFrameClient.createNotifications[webFrameClient.createNotifications.size() - 3 - i]));
2927 // The last two create notifications should be for the current frames and context.
2928 WebFrame* mainFrame = webViewHelper.webView()->mainFrame();
2929 WebFrame* childFrame = mainFrame->firstChild();
2930 ContextLifetimeTestWebFrameClient::Notification* firstRefreshNotification = webFrameClient.createNotifications[2];
2931 ContextLifetimeTestWebFrameClient::Notification* secondRefreshNotification = webFrameClient.createNotifications[3];
2933 EXPECT_EQ(mainFrame, firstRefreshNotification->frame);
2934 EXPECT_EQ(mainFrame->mainWorldScriptContext(), firstRefreshNotification->context);
2935 EXPECT_EQ(0, firstRefreshNotification->worldId);
2937 EXPECT_EQ(childFrame, secondRefreshNotification->frame);
2938 EXPECT_EQ(childFrame->mainWorldScriptContext(), secondRefreshNotification->context);
2939 EXPECT_EQ(0, secondRefreshNotification->worldId);
2942 TEST_F(WebFrameTest, ContextNotificationsIsolatedWorlds)
2944 v8::Isolate* isolate = v8::Isolate::GetCurrent();
2945 v8::HandleScope handleScope(isolate);
2947 registerMockedHttpURLLoad("context_notifications_test.html");
2948 registerMockedHttpURLLoad("context_notifications_test_frame.html");
2950 ContextLifetimeTestWebFrameClient webFrameClient;
2951 FrameTestHelpers::WebViewHelper webViewHelper;
2952 webViewHelper.initializeAndLoad(m_baseURL + "context_notifications_test.html", true, &webFrameClient);
2954 // Add an isolated world.
2955 webFrameClient.reset();
2957 int isolatedWorldId = 42;
2958 WebScriptSource scriptSource("hi!");
2960 int extensionGroup = 0;
2961 webViewHelper.webView()->mainFrame()->executeScriptInIsolatedWorld(isolatedWorldId, &scriptSource, numSources, extensionGroup);
2963 // We should now have a new create notification.
2964 ASSERT_EQ(1u, webFrameClient.createNotifications.size());
2965 ContextLifetimeTestWebFrameClient::Notification* notification = webFrameClient.createNotifications[0];
2966 ASSERT_EQ(isolatedWorldId, notification->worldId);
2967 ASSERT_EQ(webViewHelper.webView()->mainFrame(), notification->frame);
2969 // 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.
2970 ASSERT_NE(webViewHelper.webView()->mainFrame()->mainWorldScriptContext(), v8::Local<v8::Context>::New(isolate, notification->context));
2972 webViewHelper.reset();
2974 // We should have gotten three release notifications (one for each of the frames, plus one for the isolated context).
2975 ASSERT_EQ(3u, webFrameClient.releaseNotifications.size());
2977 // And one of them should be exactly the same as the create notification for the isolated context.
2979 for (size_t i = 0; i < webFrameClient.releaseNotifications.size(); ++i) {
2980 if (webFrameClient.releaseNotifications[i]->Equals(webFrameClient.createNotifications[0]))
2983 EXPECT_EQ(1, matchCount);
2986 TEST_F(WebFrameTest, FindInPage)
2988 registerMockedHttpURLLoad("find.html");
2989 FrameTestHelpers::WebViewHelper webViewHelper;
2990 webViewHelper.initializeAndLoad(m_baseURL + "find.html");
2991 WebFrame* frame = webViewHelper.webView()->mainFrame();
2992 const int findIdentifier = 12345;
2993 WebFindOptions options;
2995 // Find in a <div> element.
2996 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar1"), options, false, 0));
2997 frame->stopFinding(false);
2998 WebRange range = frame->selectionRange();
2999 EXPECT_EQ(5, range.startOffset());
3000 EXPECT_EQ(9, range.endOffset());
3001 EXPECT_TRUE(frame->document().focusedElement().isNull());
3003 // Find in an <input> value.
3004 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar2"), options, false, 0));
3005 // Confirm stopFinding(false) sets the selection on the found text.
3006 frame->stopFinding(false);
3007 range = frame->selectionRange();
3008 ASSERT_FALSE(range.isNull());
3009 EXPECT_EQ(5, range.startOffset());
3010 EXPECT_EQ(9, range.endOffset());
3011 EXPECT_EQ(WebString::fromUTF8("INPUT"), frame->document().focusedElement().tagName());
3013 // Find in a <textarea> content.
3014 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar3"), options, false, 0));
3015 // Confirm stopFinding(false) sets the selection on the found text.
3016 frame->stopFinding(false);
3017 range = frame->selectionRange();
3018 ASSERT_FALSE(range.isNull());
3019 EXPECT_EQ(5, range.startOffset());
3020 EXPECT_EQ(9, range.endOffset());
3021 EXPECT_EQ(WebString::fromUTF8("TEXTAREA"), frame->document().focusedElement().tagName());
3023 // Find in a contentEditable element.
3024 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar4"), options, false, 0));
3025 // Confirm stopFinding(false) sets the selection on the found text.
3026 frame->stopFinding(false);
3027 range = frame->selectionRange();
3028 ASSERT_FALSE(range.isNull());
3029 EXPECT_EQ(0, range.startOffset());
3030 EXPECT_EQ(4, range.endOffset());
3031 // "bar4" is surrounded by <span>, but the focusable node should be the parent <div>.
3032 EXPECT_EQ(WebString::fromUTF8("DIV"), frame->document().focusedElement().tagName());
3034 // Find in <select> content.
3035 EXPECT_FALSE(frame->find(findIdentifier, WebString::fromUTF8("bar5"), options, false, 0));
3036 // If there are any matches, stopFinding will set the selection on the found text.
3037 // However, we do not expect any matches, so check that the selection is null.
3038 frame->stopFinding(false);
3039 range = frame->selectionRange();
3040 ASSERT_TRUE(range.isNull());
3043 TEST_F(WebFrameTest, GetContentAsPlainText)
3045 FrameTestHelpers::WebViewHelper webViewHelper;
3046 webViewHelper.initializeAndLoad("about:blank", true);
3047 // We set the size because it impacts line wrapping, which changes the
3048 // resulting text value.
3049 webViewHelper.webView()->resize(WebSize(640, 480));
3050 WebFrame* frame = webViewHelper.webView()->mainFrame();
3052 // Generate a simple test case.
3053 const char simpleSource[] = "<div>Foo bar</div><div></div>baz";
3054 KURL testURL = toKURL("about:blank");
3055 FrameTestHelpers::loadHTMLString(frame, simpleSource, testURL);
3057 // Make sure it comes out OK.
3058 const std::string expected("Foo bar\nbaz");
3059 WebString text = frame->contentAsText(std::numeric_limits<size_t>::max());
3060 EXPECT_EQ(expected, text.utf8());
3062 // Try reading the same one with clipping of the text.
3063 const int length = 5;
3064 text = frame->contentAsText(length);
3065 EXPECT_EQ(expected.substr(0, length), text.utf8());
3067 // Now do a new test with a subframe.
3068 const char outerFrameSource[] = "Hello<iframe></iframe> world";
3069 FrameTestHelpers::loadHTMLString(frame, outerFrameSource, testURL);
3071 // Load something into the subframe.
3072 WebFrame* subframe = frame->firstChild();
3073 ASSERT_TRUE(subframe);
3074 FrameTestHelpers::loadHTMLString(subframe, "sub<p>text", testURL);
3076 text = frame->contentAsText(std::numeric_limits<size_t>::max());
3077 EXPECT_EQ("Hello world\n\nsub\ntext", text.utf8());
3079 // Get the frame text where the subframe separator falls on the boundary of
3080 // what we'll take. There used to be a crash in this case.
3081 text = frame->contentAsText(12);
3082 EXPECT_EQ("Hello world", text.utf8());
3085 TEST_F(WebFrameTest, GetFullHtmlOfPage)
3087 FrameTestHelpers::WebViewHelper webViewHelper;
3088 webViewHelper.initializeAndLoad("about:blank", true);
3089 WebFrame* frame = webViewHelper.webView()->mainFrame();
3091 // Generate a simple test case.
3092 const char simpleSource[] = "<p>Hello</p><p>World</p>";
3093 KURL testURL = toKURL("about:blank");
3094 FrameTestHelpers::loadHTMLString(frame, simpleSource, testURL);
3096 WebString text = frame->contentAsText(std::numeric_limits<size_t>::max());
3097 EXPECT_EQ("Hello\n\nWorld", text.utf8());
3099 const std::string html = frame->contentAsMarkup().utf8();
3101 // Load again with the output html.
3102 FrameTestHelpers::loadHTMLString(frame, html, 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 FrameTestHelpers::reloadFrame(webViewHelper.webView()->mainFrame());
3138 class FindUpdateWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
3140 FindUpdateWebFrameClient()
3141 : m_findResultsAreReady(false)
3146 virtual void reportFindInPageMatchCount(int, int count, bool finalUpdate) OVERRIDE
3150 m_findResultsAreReady = true;
3153 bool findResultsAreReady() const { return m_findResultsAreReady; }
3154 int count() const { return m_count; }
3157 bool m_findResultsAreReady;
3161 // This fails on Mac https://bugs.webkit.org/show_bug.cgi?id=108574
3162 // Also failing on Android: http://crbug.com/341314
3163 #if OS(MACOSX) || OS(ANDROID)
3164 TEST_F(WebFrameTest, DISABLED_FindInPageMatchRects)
3166 TEST_F(WebFrameTest, FindInPageMatchRects)
3169 registerMockedHttpURLLoad("find_in_page.html");
3170 registerMockedHttpURLLoad("find_in_page_frame.html");
3172 FindUpdateWebFrameClient client;
3173 FrameTestHelpers::WebViewHelper webViewHelper;
3174 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3175 webViewHelper.webView()->resize(WebSize(640, 480));
3176 webViewHelper.webView()->layout();
3179 // Note that the 'result 19' in the <select> element is not expected to produce a match.
3180 static const char* kFindString = "result";
3181 static const int kFindIdentifier = 12345;
3182 static const int kNumResults = 19;
3184 WebFindOptions options;
3185 WebString searchText = WebString::fromUTF8(kFindString);
3186 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3187 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
3189 mainFrame->resetMatchCount();
3191 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3192 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3195 EXPECT_TRUE(client.findResultsAreReady());
3197 WebVector<WebFloatRect> webMatchRects;
3198 mainFrame->findMatchRects(webMatchRects);
3199 ASSERT_EQ(webMatchRects.size(), static_cast<size_t>(kNumResults));
3200 int rectsVersion = mainFrame->findMatchMarkersVersion();
3202 for (int resultIndex = 0; resultIndex < kNumResults; ++resultIndex) {
3203 FloatRect resultRect = static_cast<FloatRect>(webMatchRects[resultIndex]);
3205 // Select the match by the center of its rect.
3206 EXPECT_EQ(mainFrame->selectNearestFindMatch(resultRect.center(), 0), resultIndex + 1);
3208 // Check that the find result ordering matches with our expectations.
3209 Range* result = mainFrame->activeMatchFrame()->activeMatch();
3210 ASSERT_TRUE(result);
3211 result->setEnd(result->endContainer(), result->endOffset() + 3);
3212 EXPECT_EQ(result->text(), String::format("%s %02d", kFindString, resultIndex));
3214 // Verify that the expected match rect also matches the currently active match.
3215 // Compare the enclosing rects to prevent precision issues caused by CSS transforms.
3216 FloatRect activeMatch = mainFrame->activeFindMatchRect();
3217 EXPECT_EQ(enclosingIntRect(activeMatch), enclosingIntRect(resultRect));
3219 // The rects version should not have changed.
3220 EXPECT_EQ(mainFrame->findMatchMarkersVersion(), rectsVersion);
3223 // All results after the first two ones should be below between them in find-in-page coordinates.
3224 // This is because results 2 to 9 are inside an iframe located between results 0 and 1. This applies to the fixed div too.
3225 EXPECT_TRUE(webMatchRects[0].y < webMatchRects[1].y);
3226 for (int resultIndex = 2; resultIndex < kNumResults; ++resultIndex) {
3227 EXPECT_TRUE(webMatchRects[0].y < webMatchRects[resultIndex].y);
3228 EXPECT_TRUE(webMatchRects[1].y > webMatchRects[resultIndex].y);
3231 // Result 3 should be below both 2 and 4. This is caused by the CSS transform in the containing div.
3232 // If the transform doesn't work then 3 will be between 2 and 4.
3233 EXPECT_TRUE(webMatchRects[3].y > webMatchRects[2].y);
3234 EXPECT_TRUE(webMatchRects[3].y > webMatchRects[4].y);
3236 // Results 6, 7, 8 and 9 should be one below the other in that same order.
3237 // If overflow:scroll is not properly handled then result 8 would be below result 9 or
3238 // result 7 above result 6 depending on the scroll.
3239 EXPECT_TRUE(webMatchRects[6].y < webMatchRects[7].y);
3240 EXPECT_TRUE(webMatchRects[7].y < webMatchRects[8].y);
3241 EXPECT_TRUE(webMatchRects[8].y < webMatchRects[9].y);
3243 // Results 11, 12, 13 and 14 should be between results 10 and 15, as they are inside the table.
3244 EXPECT_TRUE(webMatchRects[11].y > webMatchRects[10].y);
3245 EXPECT_TRUE(webMatchRects[12].y > webMatchRects[10].y);
3246 EXPECT_TRUE(webMatchRects[13].y > webMatchRects[10].y);
3247 EXPECT_TRUE(webMatchRects[14].y > webMatchRects[10].y);
3248 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[15].y);
3249 EXPECT_TRUE(webMatchRects[12].y < webMatchRects[15].y);
3250 EXPECT_TRUE(webMatchRects[13].y < webMatchRects[15].y);
3251 EXPECT_TRUE(webMatchRects[14].y < webMatchRects[15].y);
3253 // Result 11 should be above 12, 13 and 14 as it's in the table header.
3254 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[12].y);
3255 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[13].y);
3256 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[14].y);
3258 // Result 11 should also be right to 12, 13 and 14 because of the colspan.
3259 EXPECT_TRUE(webMatchRects[11].x > webMatchRects[12].x);
3260 EXPECT_TRUE(webMatchRects[11].x > webMatchRects[13].x);
3261 EXPECT_TRUE(webMatchRects[11].x > webMatchRects[14].x);
3263 // Result 12 should be left to results 11, 13 and 14 in the table layout.
3264 EXPECT_TRUE(webMatchRects[12].x < webMatchRects[11].x);
3265 EXPECT_TRUE(webMatchRects[12].x < webMatchRects[13].x);
3266 EXPECT_TRUE(webMatchRects[12].x < webMatchRects[14].x);
3268 // Results 13, 12 and 14 should be one above the other in that order because of the rowspan
3269 // and vertical-align: middle by default.
3270 EXPECT_TRUE(webMatchRects[13].y < webMatchRects[12].y);
3271 EXPECT_TRUE(webMatchRects[12].y < webMatchRects[14].y);
3273 // Result 16 should be below result 15.
3274 EXPECT_TRUE(webMatchRects[15].y > webMatchRects[14].y);
3276 // Result 18 should be normalized with respect to the position:relative div, and not it's
3277 // immediate containing div. Consequently, result 18 should be above result 17.
3278 EXPECT_TRUE(webMatchRects[17].y > webMatchRects[18].y);
3280 // Resizing should update the rects version.
3281 webViewHelper.webView()->resize(WebSize(800, 600));
3283 EXPECT_TRUE(mainFrame->findMatchMarkersVersion() != rectsVersion);
3286 TEST_F(WebFrameTest, FindInPageSkipsHiddenFrames)
3288 registerMockedHttpURLLoad("find_in_hidden_frame.html");
3290 FindUpdateWebFrameClient client;
3291 FrameTestHelpers::WebViewHelper webViewHelper;
3292 webViewHelper.initializeAndLoad(m_baseURL + "find_in_hidden_frame.html", true, &client);
3293 webViewHelper.webView()->resize(WebSize(640, 480));
3294 webViewHelper.webView()->layout();
3297 static const char* kFindString = "hello";
3298 static const int kFindIdentifier = 12345;
3299 static const int kNumResults = 1;
3301 WebFindOptions options;
3302 WebString searchText = WebString::fromUTF8(kFindString);
3303 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3304 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
3306 mainFrame->resetMatchCount();
3308 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3309 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3312 EXPECT_TRUE(client.findResultsAreReady());
3313 EXPECT_EQ(kNumResults, client.count());
3316 TEST_F(WebFrameTest, FindOnDetachedFrame)
3318 registerMockedHttpURLLoad("find_in_page.html");
3319 registerMockedHttpURLLoad("find_in_page_frame.html");
3321 FindUpdateWebFrameClient client;
3322 FrameTestHelpers::WebViewHelper webViewHelper;
3323 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3324 webViewHelper.webView()->resize(WebSize(640, 480));
3325 webViewHelper.webView()->layout();
3328 static const char* kFindString = "result";
3329 static const int kFindIdentifier = 12345;
3331 WebFindOptions options;
3332 WebString searchText = WebString::fromUTF8(kFindString);
3333 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3334 RefPtrWillBeRawPtr<WebLocalFrameImpl> secondFrame = toWebLocalFrameImpl(mainFrame->traverseNext(false));
3335 RefPtrWillBeRawPtr<LocalFrame> holdSecondFrame(secondFrame->frame());
3337 // Detach the frame before finding.
3338 EXPECT_TRUE(mainFrame->document().getElementById("frame").remove());
3340 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
3341 EXPECT_FALSE(secondFrame->find(kFindIdentifier, searchText, options, false, 0));
3344 EXPECT_FALSE(client.findResultsAreReady());
3346 mainFrame->resetMatchCount();
3348 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3349 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3352 EXPECT_TRUE(client.findResultsAreReady());
3355 TEST_F(WebFrameTest, FindDetachFrameBeforeScopeStrings)
3357 registerMockedHttpURLLoad("find_in_page.html");
3358 registerMockedHttpURLLoad("find_in_page_frame.html");
3360 FindUpdateWebFrameClient client;
3361 FrameTestHelpers::WebViewHelper webViewHelper;
3362 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3363 webViewHelper.webView()->resize(WebSize(640, 480));
3364 webViewHelper.webView()->layout();
3367 static const char* kFindString = "result";
3368 static const int kFindIdentifier = 12345;
3370 WebFindOptions options;
3371 WebString searchText = WebString::fromUTF8(kFindString);
3372 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3373 WebLocalFrameImpl* secondFrame = toWebLocalFrameImpl(mainFrame->traverseNext(false));
3374 RefPtrWillBeRawPtr<LocalFrame> holdSecondFrame(secondFrame->frame());
3376 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3377 EXPECT_TRUE(frame->find(kFindIdentifier, searchText, options, false, 0));
3380 EXPECT_FALSE(client.findResultsAreReady());
3382 // Detach the frame between finding and scoping.
3383 EXPECT_TRUE(mainFrame->document().getElementById("frame").remove());
3385 mainFrame->resetMatchCount();
3387 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3388 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3391 EXPECT_TRUE(client.findResultsAreReady());
3394 TEST_F(WebFrameTest, FindDetachFrameWhileScopingStrings)
3396 registerMockedHttpURLLoad("find_in_page.html");
3397 registerMockedHttpURLLoad("find_in_page_frame.html");
3399 FindUpdateWebFrameClient client;
3400 FrameTestHelpers::WebViewHelper webViewHelper;
3401 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3402 webViewHelper.webView()->resize(WebSize(640, 480));
3403 webViewHelper.webView()->layout();
3406 static const char* kFindString = "result";
3407 static const int kFindIdentifier = 12345;
3409 WebFindOptions options;
3410 WebString searchText = WebString::fromUTF8(kFindString);
3411 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3412 WebLocalFrameImpl* secondFrame = toWebLocalFrameImpl(mainFrame->traverseNext(false));
3413 RefPtrWillBeRawPtr<LocalFrame> holdSecondFrame(secondFrame->frame());
3415 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3416 EXPECT_TRUE(frame->find(kFindIdentifier, searchText, options, false, 0));
3419 EXPECT_FALSE(client.findResultsAreReady());
3421 mainFrame->resetMatchCount();
3423 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3424 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3426 // The first scopeStringMatches will have reset the state. Detach before it actually scopes.
3427 EXPECT_TRUE(mainFrame->document().getElementById("frame").remove());
3430 EXPECT_TRUE(client.findResultsAreReady());
3433 TEST_F(WebFrameTest, ResetMatchCount)
3435 registerMockedHttpURLLoad("find_in_generated_frame.html");
3437 FindUpdateWebFrameClient client;
3438 FrameTestHelpers::WebViewHelper webViewHelper;
3439 webViewHelper.initializeAndLoad(m_baseURL + "find_in_generated_frame.html", true, &client);
3440 webViewHelper.webView()->resize(WebSize(640, 480));
3441 webViewHelper.webView()->layout();
3444 static const char* kFindString = "result";
3445 static const int kFindIdentifier = 12345;
3447 WebFindOptions options;
3448 WebString searchText = WebString::fromUTF8(kFindString);
3449 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3451 // Check that child frame exists.
3452 EXPECT_TRUE(!!mainFrame->traverseNext(false));
3454 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false)) {
3455 EXPECT_FALSE(frame->find(kFindIdentifier, searchText, options, false, 0));
3459 EXPECT_FALSE(client.findResultsAreReady());
3461 mainFrame->resetMatchCount();
3464 TEST_F(WebFrameTest, SetTickmarks)
3466 registerMockedHttpURLLoad("find.html");
3468 FindUpdateWebFrameClient client;
3469 FrameTestHelpers::WebViewHelper webViewHelper;
3470 webViewHelper.initializeAndLoad(m_baseURL + "find.html", true, &client);
3471 webViewHelper.webView()->resize(WebSize(640, 480));
3472 webViewHelper.webView()->layout();
3475 static const char* kFindString = "foo";
3476 static const int kFindIdentifier = 12345;
3478 WebFindOptions options;
3479 WebString searchText = WebString::fromUTF8(kFindString);
3480 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3481 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
3483 mainFrame->resetMatchCount();
3484 mainFrame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3487 EXPECT_TRUE(client.findResultsAreReady());
3489 // Get the tickmarks for the original find request.
3490 FrameView* frameView = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
3491 RefPtr<Scrollbar> scrollbar = frameView->createScrollbar(HorizontalScrollbar);
3492 Vector<IntRect> originalTickmarks;
3493 scrollbar->getTickmarks(originalTickmarks);
3494 EXPECT_EQ(4u, originalTickmarks.size());
3496 // Override the tickmarks.
3497 Vector<IntRect> overridingTickmarksExpected;
3498 overridingTickmarksExpected.append(IntRect(0, 0, 100, 100));
3499 overridingTickmarksExpected.append(IntRect(0, 20, 100, 100));
3500 overridingTickmarksExpected.append(IntRect(0, 30, 100, 100));
3501 mainFrame->setTickmarks(overridingTickmarksExpected);
3503 // Check the tickmarks are overriden correctly.
3504 Vector<IntRect> overridingTickmarksActual;
3505 scrollbar->getTickmarks(overridingTickmarksActual);
3506 EXPECT_EQ(overridingTickmarksExpected, overridingTickmarksActual);
3508 // Reset the tickmark behavior.
3509 Vector<IntRect> resetTickmarks;
3510 mainFrame->setTickmarks(resetTickmarks);
3512 // Check that the original tickmarks are returned
3513 Vector<IntRect> originalTickmarksAfterReset;
3514 scrollbar->getTickmarks(originalTickmarksAfterReset);
3515 EXPECT_EQ(originalTickmarks, originalTickmarksAfterReset);
3518 static WebPoint topLeft(const WebRect& rect)
3520 return WebPoint(rect.x, rect.y);
3523 static WebPoint bottomRightMinusOne(const WebRect& rect)
3525 // FIXME: If we don't subtract 1 from the x- and y-coordinates of the
3526 // selection bounds, selectRange() will select the *next* element. That's
3527 // strictly correct, as hit-testing checks the pixel to the lower-right of
3528 // the input coordinate, but it's a wart on the API.
3529 return WebPoint(rect.x + rect.width - 1, rect.y + rect.height - 1);
3532 static WebRect elementBounds(WebFrame* frame, const WebString& id)
3534 return frame->document().getElementById(id).boundsInViewportSpace();
3537 static std::string selectionAsString(WebFrame* frame)
3539 return frame->selectionAsText().utf8();
3542 TEST_F(WebFrameTest, SelectRange)
3545 WebRect startWebRect;
3548 registerMockedHttpURLLoad("select_range_basic.html");
3549 registerMockedHttpURLLoad("select_range_scroll.html");
3551 FrameTestHelpers::WebViewHelper webViewHelper;
3552 initializeTextSelectionWebView(m_baseURL + "select_range_basic.html", &webViewHelper);
3553 frame = webViewHelper.webView()->mainFrame();
3554 EXPECT_EQ("Some test text for testing.", selectionAsString(frame));
3555 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3556 frame->executeCommand(WebString::fromUTF8("Unselect"));
3557 EXPECT_EQ("", selectionAsString(frame));
3558 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3559 EXPECT_EQ("Some test text for testing.", selectionAsString(frame));
3561 initializeTextSelectionWebView(m_baseURL + "select_range_scroll.html", &webViewHelper);
3562 frame = webViewHelper.webView()->mainFrame();
3563 EXPECT_EQ("Some offscreen test text for testing.", selectionAsString(frame));
3564 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3565 frame->executeCommand(WebString::fromUTF8("Unselect"));
3566 EXPECT_EQ("", selectionAsString(frame));
3567 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3568 EXPECT_EQ("Some offscreen test text for testing.", selectionAsString(frame));
3571 TEST_F(WebFrameTest, SelectRangeInIframe)
3574 WebRect startWebRect;
3577 registerMockedHttpURLLoad("select_range_iframe.html");
3578 registerMockedHttpURLLoad("select_range_basic.html");
3580 FrameTestHelpers::WebViewHelper webViewHelper;
3581 initializeTextSelectionWebView(m_baseURL + "select_range_iframe.html", &webViewHelper);
3582 frame = webViewHelper.webView()->mainFrame();
3583 WebFrame* subframe = frame->firstChild();
3584 EXPECT_EQ("Some test text for testing.", selectionAsString(subframe));
3585 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3586 subframe->executeCommand(WebString::fromUTF8("Unselect"));
3587 EXPECT_EQ("", selectionAsString(subframe));
3588 subframe->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3589 EXPECT_EQ("Some test text for testing.", selectionAsString(subframe));
3592 TEST_F(WebFrameTest, SelectRangeDivContentEditable)
3595 WebRect startWebRect;
3598 registerMockedHttpURLLoad("select_range_div_editable.html");
3600 // Select the middle of an editable element, then try to extend the selection to the top of the document.
3601 // The selection range should be clipped to the bounds of the editable element.
3602 FrameTestHelpers::WebViewHelper webViewHelper;
3603 initializeTextSelectionWebView(m_baseURL + "select_range_div_editable.html", &webViewHelper);
3604 frame = webViewHelper.webView()->mainFrame();
3605 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3606 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3608 frame->selectRange(bottomRightMinusOne(endWebRect), WebPoint(0, 0));
3609 EXPECT_EQ("16-char header. This text is initially selected.", selectionAsString(frame));
3611 // As above, but extending the selection to the bottom of the document.
3612 initializeTextSelectionWebView(m_baseURL + "select_range_div_editable.html", &webViewHelper);
3613 frame = webViewHelper.webView()->mainFrame();
3615 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3616 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3617 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3618 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3620 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3621 frame->selectRange(topLeft(startWebRect), WebPoint(640, 480));
3622 EXPECT_EQ("This text is initially selected. 16-char footer.", selectionAsString(frame));
3625 // positionForPoint returns the wrong values for contenteditable spans. See
3626 // http://crbug.com/238334.
3627 TEST_F(WebFrameTest, DISABLED_SelectRangeSpanContentEditable)
3630 WebRect startWebRect;
3633 registerMockedHttpURLLoad("select_range_span_editable.html");
3635 // Select the middle of an editable element, then try to extend the selection to the top of the document.
3636 // The selection range should be clipped to the bounds of the editable element.
3637 FrameTestHelpers::WebViewHelper webViewHelper;
3638 initializeTextSelectionWebView(m_baseURL + "select_range_span_editable.html", &webViewHelper);
3639 frame = webViewHelper.webView()->mainFrame();
3640 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3641 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3643 frame->selectRange(bottomRightMinusOne(endWebRect), WebPoint(0, 0));
3644 EXPECT_EQ("16-char header. This text is initially selected.", selectionAsString(frame));
3646 // As above, but extending the selection to the bottom of the document.
3647 initializeTextSelectionWebView(m_baseURL + "select_range_span_editable.html", &webViewHelper);
3648 frame = webViewHelper.webView()->mainFrame();
3650 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3651 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3652 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3653 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3655 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3656 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3657 frame->selectRange(topLeft(startWebRect), WebPoint(640, 480));
3658 EXPECT_EQ("This text is initially selected. 16-char footer.", selectionAsString(frame));
3661 TEST_F(WebFrameTest, SelectRangeCanMoveSelectionStart)
3663 registerMockedHttpURLLoad("text_selection.html");
3664 FrameTestHelpers::WebViewHelper webViewHelper;
3665 initializeTextSelectionWebView(m_baseURL + "text_selection.html", &webViewHelper);
3666 WebFrame* frame = webViewHelper.webView()->mainFrame();
3668 // Select second span. We can move the start to include the first span.
3669 frame->executeScript(WebScriptSource("selectElement('header_2');"));
3670 EXPECT_EQ("Header 2.", selectionAsString(frame));
3671 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "header_2")), topLeft(elementBounds(frame, "header_1")));
3672 EXPECT_EQ("Header 1. Header 2.", selectionAsString(frame));
3674 // We can move the start and end together.
3675 frame->executeScript(WebScriptSource("selectElement('header_1');"));
3676 EXPECT_EQ("Header 1.", selectionAsString(frame));
3677 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "header_1")));
3678 EXPECT_EQ("", selectionAsString(frame));
3679 // Selection is a caret, not empty.
3680 EXPECT_FALSE(frame->selectionRange().isNull());
3682 // We can move the start across the end.
3683 frame->executeScript(WebScriptSource("selectElement('header_1');"));
3684 EXPECT_EQ("Header 1.", selectionAsString(frame));
3685 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "header_2")));
3686 EXPECT_EQ(" Header 2.", selectionAsString(frame));
3688 // Can't extend the selection part-way into an editable element.
3689 frame->executeScript(WebScriptSource("selectElement('footer_2');"));
3690 EXPECT_EQ("Footer 2.", selectionAsString(frame));
3691 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "footer_2")), topLeft(elementBounds(frame, "editable_2")));
3692 EXPECT_EQ(" [ Footer 1. Footer 2.", selectionAsString(frame));
3694 // Can extend the selection completely across editable elements.
3695 frame->executeScript(WebScriptSource("selectElement('footer_2');"));
3696 EXPECT_EQ("Footer 2.", selectionAsString(frame));
3697 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "footer_2")), topLeft(elementBounds(frame, "header_2")));
3698 EXPECT_EQ("Header 2. ] [ Editable 1. Editable 2. ] [ Footer 1. Footer 2.", selectionAsString(frame));
3700 // If the selection is editable text, we can't extend it into non-editable text.
3701 frame->executeScript(WebScriptSource("selectElement('editable_2');"));
3702 EXPECT_EQ("Editable 2.", selectionAsString(frame));
3703 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "editable_2")), topLeft(elementBounds(frame, "header_2")));
3704 // positionForPoint returns the wrong values for contenteditable spans. See
3705 // http://crbug.com/238334.
3706 // EXPECT_EQ("[ Editable 1. Editable 2.", selectionAsString(frame));
3709 TEST_F(WebFrameTest, SelectRangeCanMoveSelectionEnd)
3711 registerMockedHttpURLLoad("text_selection.html");
3712 FrameTestHelpers::WebViewHelper webViewHelper;
3713 initializeTextSelectionWebView(m_baseURL + "text_selection.html", &webViewHelper);
3714 WebFrame* frame = webViewHelper.webView()->mainFrame();
3716 // Select first span. We can move the end to include the second span.
3717 frame->executeScript(WebScriptSource("selectElement('header_1');"));
3718 EXPECT_EQ("Header 1.", selectionAsString(frame));
3719 frame->selectRange(topLeft(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "header_2")));
3720 EXPECT_EQ("Header 1. Header 2.", selectionAsString(frame));
3722 // We can move the start and end together.
3723 frame->executeScript(WebScriptSource("selectElement('header_2');"));
3724 EXPECT_EQ("Header 2.", selectionAsString(frame));
3725 frame->selectRange(topLeft(elementBounds(frame, "header_2")), topLeft(elementBounds(frame, "header_2")));
3726 EXPECT_EQ("", selectionAsString(frame));
3727 // Selection is a caret, not empty.
3728 EXPECT_FALSE(frame->selectionRange().isNull());
3730 // We can move the end across the start.
3731 frame->executeScript(WebScriptSource("selectElement('header_2');"));
3732 EXPECT_EQ("Header 2.", selectionAsString(frame));
3733 frame->selectRange(topLeft(elementBounds(frame, "header_2")), topLeft(elementBounds(frame, "header_1")));
3734 EXPECT_EQ("Header 1. ", selectionAsString(frame));
3736 // Can't extend the selection part-way into an editable element.
3737 frame->executeScript(WebScriptSource("selectElement('header_1');"));
3738 EXPECT_EQ("Header 1.", selectionAsString(frame));
3739 frame->selectRange(topLeft(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "editable_1")));
3740 EXPECT_EQ("Header 1. Header 2. ] ", selectionAsString(frame));
3742 // Can extend the selection completely across editable elements.
3743 frame->executeScript(WebScriptSource("selectElement('header_1');"));
3744 EXPECT_EQ("Header 1.", selectionAsString(frame));
3745 frame->selectRange(topLeft(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "footer_1")));
3746 EXPECT_EQ("Header 1. Header 2. ] [ Editable 1. Editable 2. ] [ Footer 1.", selectionAsString(frame));
3748 // If the selection is editable text, we can't extend it into non-editable text.
3749 frame->executeScript(WebScriptSource("selectElement('editable_1');"));
3750 EXPECT_EQ("Editable 1.", selectionAsString(frame));
3751 frame->selectRange(topLeft(elementBounds(frame, "editable_1")), bottomRightMinusOne(elementBounds(frame, "footer_1")));
3752 // positionForPoint returns the wrong values for contenteditable spans. See
3753 // http://crbug.com/238334.
3754 // EXPECT_EQ("Editable 1. Editable 2. ]", selectionAsString(frame));
3757 static int computeOffset(RenderObject* renderer, int x, int y)
3759 return VisiblePosition(renderer->positionForPoint(LayoutPoint(x, y))).deepEquivalent().computeOffsetInContainerNode();
3762 // positionForPoint returns the wrong values for contenteditable spans. See
3763 // http://crbug.com/238334.
3764 TEST_F(WebFrameTest, DISABLED_PositionForPointTest)
3766 registerMockedHttpURLLoad("select_range_span_editable.html");
3767 FrameTestHelpers::WebViewHelper webViewHelper;
3768 initializeTextSelectionWebView(m_baseURL + "select_range_span_editable.html", &webViewHelper);
3769 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3770 RenderObject* renderer = mainFrame->frame()->selection().rootEditableElement()->renderer();
3771 EXPECT_EQ(0, computeOffset(renderer, -1, -1));
3772 EXPECT_EQ(64, computeOffset(renderer, 1000, 1000));
3774 registerMockedHttpURLLoad("select_range_div_editable.html");
3775 initializeTextSelectionWebView(m_baseURL + "select_range_div_editable.html", &webViewHelper);
3776 mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3777 renderer = mainFrame->frame()->selection().rootEditableElement()->renderer();
3778 EXPECT_EQ(0, computeOffset(renderer, -1, -1));
3779 EXPECT_EQ(64, computeOffset(renderer, 1000, 1000));
3782 #if !OS(MACOSX) && !OS(LINUX)
3783 TEST_F(WebFrameTest, SelectRangeStaysHorizontallyAlignedWhenMoved)
3785 registerMockedHttpURLLoad("move_caret.html");
3787 FrameTestHelpers::WebViewHelper webViewHelper;
3788 initializeTextSelectionWebView(m_baseURL + "move_caret.html", &webViewHelper);
3789 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3791 WebRect initialStartRect;
3792 WebRect initialEndRect;
3796 frame->executeScript(WebScriptSource("selectRange();"));
3797 webViewHelper.webView()->selectionBounds(initialStartRect, initialEndRect);
3798 WebPoint movedStart(topLeft(initialStartRect));
3801 frame->selectRange(movedStart, bottomRightMinusOne(initialEndRect));
3802 webViewHelper.webView()->selectionBounds(startRect, endRect);
3803 EXPECT_EQ(startRect, initialStartRect);
3804 EXPECT_EQ(endRect, initialEndRect);
3807 frame->selectRange(movedStart, bottomRightMinusOne(initialEndRect));
3808 webViewHelper.webView()->selectionBounds(startRect, endRect);
3809 EXPECT_EQ(startRect, initialStartRect);
3810 EXPECT_EQ(endRect, initialEndRect);
3812 WebPoint movedEnd(bottomRightMinusOne(initialEndRect));
3815 frame->selectRange(topLeft(initialStartRect), movedEnd);
3816 webViewHelper.webView()->selectionBounds(startRect, endRect);
3817 EXPECT_EQ(startRect, initialStartRect);
3818 EXPECT_EQ(endRect, initialEndRect);
3821 frame->selectRange(topLeft(initialStartRect), movedEnd);
3822 webViewHelper.webView()->selectionBounds(startRect, endRect);
3823 EXPECT_EQ(startRect, initialStartRect);
3824 EXPECT_EQ(endRect, initialEndRect);
3827 TEST_F(WebFrameTest, MoveCaretStaysHorizontallyAlignedWhenMoved)
3829 WebLocalFrameImpl* frame;
3830 registerMockedHttpURLLoad("move_caret.html");
3832 FrameTestHelpers::WebViewHelper webViewHelper;
3833 initializeTextSelectionWebView(m_baseURL + "move_caret.html", &webViewHelper);
3834 frame = (WebLocalFrameImpl*)webViewHelper.webView()->mainFrame();
3836 WebRect initialStartRect;
3837 WebRect initialEndRect;
3841 frame->executeScript(WebScriptSource("selectCaret();"));
3842 webViewHelper.webView()->selectionBounds(initialStartRect, initialEndRect);
3843 WebPoint moveTo(topLeft(initialStartRect));
3846 frame->moveCaretSelection(moveTo);
3847 webViewHelper.webView()->selectionBounds(startRect, endRect);
3848 EXPECT_EQ(startRect, initialStartRect);
3849 EXPECT_EQ(endRect, initialEndRect);
3852 frame->moveCaretSelection(moveTo);
3853 webViewHelper.webView()->selectionBounds(startRect, endRect);
3854 EXPECT_EQ(startRect, initialStartRect);
3855 EXPECT_EQ(endRect, initialEndRect);
3859 class CompositedSelectionBoundsTestLayerTreeView : public WebLayerTreeView {
3861 CompositedSelectionBoundsTestLayerTreeView() : m_selectionCleared(false) { }
3862 virtual ~CompositedSelectionBoundsTestLayerTreeView() { }
3864 virtual void setSurfaceReady() OVERRIDE { }
3865 virtual void setRootLayer(const WebLayer&) OVERRIDE { }
3866 virtual void clearRootLayer() OVERRIDE { }
3867 virtual void setViewportSize(const WebSize& deviceViewportSize) OVERRIDE { }
3868 virtual WebSize deviceViewportSize() const OVERRIDE { return WebSize(); }
3869 virtual void setDeviceScaleFactor(float) OVERRIDE { }
3870 virtual float deviceScaleFactor() const OVERRIDE { return 1.f; }
3871 virtual void setBackgroundColor(WebColor) OVERRIDE { }
3872 virtual void setHasTransparentBackground(bool) OVERRIDE { }
3873 virtual void setVisible(bool) OVERRIDE { }
3874 virtual void setPageScaleFactorAndLimits(float pageScaleFactor, float minimum, float maximum) OVERRIDE { }
3875 virtual void startPageScaleAnimation(const WebPoint& destination, bool useAnchor, float newPageScale, double durationSec) OVERRIDE { }
3876 virtual void setNeedsAnimate() OVERRIDE { }
3877 virtual bool commitRequested() const OVERRIDE { return false; }
3878 virtual void finishAllRendering() OVERRIDE { }
3879 virtual void registerSelection(const WebSelectionBound& start, const WebSelectionBound& end) OVERRIDE
3881 m_start = adoptPtr(new WebSelectionBound(start));
3882 m_end = adoptPtr(new WebSelectionBound(end));
3884 virtual void clearSelection() OVERRIDE
3886 m_selectionCleared = true;
3891 bool getAndResetSelectionCleared()
3893 bool selectionCleared = m_selectionCleared;
3894 m_selectionCleared = false;
3895 return selectionCleared;
3898 const WebSelectionBound* start() const { return m_start.get(); }
3899 const WebSelectionBound* end() const { return m_end.get(); }
3902 bool m_selectionCleared;
3903 OwnPtr<WebSelectionBound> m_start;
3904 OwnPtr<WebSelectionBound> m_end;
3907 class CompositedSelectionBoundsTestWebViewClient : public FrameTestHelpers::TestWebViewClient {
3909 virtual ~CompositedSelectionBoundsTestWebViewClient() { }
3910 virtual WebLayerTreeView* layerTreeView() OVERRIDE { return &m_testLayerTreeView; }
3912 CompositedSelectionBoundsTestLayerTreeView& selectionLayerTreeView() { return m_testLayerTreeView; }
3915 CompositedSelectionBoundsTestLayerTreeView m_testLayerTreeView;
3918 class CompositedSelectionBoundsTest : public WebFrameTest {
3920 CompositedSelectionBoundsTest()
3921 : m_fakeSelectionLayerTreeView(m_fakeSelectionWebViewClient.selectionLayerTreeView())
3923 blink::RuntimeEnabledFeatures::setCompositedSelectionUpdateEnabled(true);
3924 registerMockedHttpURLLoad("Ahem.ttf");
3926 m_webViewHelper.initialize(true, 0, &m_fakeSelectionWebViewClient);
3927 m_webViewHelper.webView()->settings()->setDefaultFontSize(12);
3928 m_webViewHelper.webView()->setPageScaleFactorLimits(1, 1);
3929 m_webViewHelper.webView()->resize(WebSize(640, 480));
3932 void runTest(const char* testFile)
3934 registerMockedHttpURLLoad(testFile);
3935 FrameTestHelpers::loadFrame(m_webViewHelper.webView()->mainFrame(), m_baseURL + testFile);
3936 m_webViewHelper.webView()->layout();
3938 const WebSelectionBound* selectStart = m_fakeSelectionLayerTreeView.start();
3939 const WebSelectionBound* selectEnd = m_fakeSelectionLayerTreeView.end();
3941 v8::HandleScope handleScope(v8::Isolate::GetCurrent());
3942 v8::Handle<v8::Value> result = m_webViewHelper.webView()->mainFrame()->toWebLocalFrame()->executeScriptAndReturnValueForTests(WebScriptSource("expectedResult"));
3943 if (result.IsEmpty() || (*result)->IsUndefined()) {
3944 EXPECT_FALSE(selectStart);
3945 EXPECT_FALSE(selectEnd);
3949 ASSERT_TRUE(selectStart);
3950 ASSERT_TRUE(selectEnd);
3952 ASSERT_TRUE((*result)->IsArray());
3953 v8::Array& expectedResult = *v8::Array::Cast(*result);
3954 ASSERT_EQ(10u, expectedResult.Length());
3956 blink::Node* layerOwnerNodeForStart = blink::V8Node::toImplWithTypeCheck(v8::Isolate::GetCurrent(), expectedResult.Get(0));
3957 ASSERT_TRUE(layerOwnerNodeForStart);
3958 EXPECT_EQ(layerOwnerNodeForStart->renderer()->enclosingLayer()->enclosingLayerForPaintInvalidation()->graphicsLayerBacking()->platformLayer()->id(), selectStart->layerId);
3959 EXPECT_EQ(expectedResult.Get(1)->Int32Value(), selectStart->edgeTopInLayer.x);
3960 EXPECT_EQ(expectedResult.Get(2)->Int32Value(), selectStart->edgeTopInLayer.y);
3961 EXPECT_EQ(expectedResult.Get(3)->Int32Value(), selectStart->edgeBottomInLayer.x);
3962 EXPECT_EQ(expectedResult.Get(4)->Int32Value(), selectStart->edgeBottomInLayer.y);
3964 blink::Node* layerOwnerNodeForEnd = blink::V8Node::toImplWithTypeCheck(v8::Isolate::GetCurrent(), expectedResult.Get(5));
3965 ASSERT_TRUE(layerOwnerNodeForEnd);
3966 EXPECT_EQ(layerOwnerNodeForEnd->renderer()->enclosingLayer()->enclosingLayerForPaintInvalidation()->graphicsLayerBacking()->platformLayer()->id(), selectEnd->layerId);
3967 EXPECT_EQ(expectedResult.Get(6)->Int32Value(), selectEnd->edgeTopInLayer.x);
3968 EXPECT_EQ(expectedResult.Get(7)->Int32Value(), selectEnd->edgeTopInLayer.y);
3969 EXPECT_EQ(expectedResult.Get(8)->Int32Value(), selectEnd->edgeBottomInLayer.x);
3970 EXPECT_EQ(expectedResult.Get(9)->Int32Value(), selectEnd->edgeBottomInLayer.y);
3973 void runTestWithMultipleFiles(const char* testFile, ...)
3976 va_start(auxFiles, testFile);
3977 while (const char* auxFile = va_arg(auxFiles, const char*))
3978 registerMockedHttpURLLoad(auxFile);
3984 CompositedSelectionBoundsTestWebViewClient m_fakeSelectionWebViewClient;
3985 CompositedSelectionBoundsTestLayerTreeView& m_fakeSelectionLayerTreeView;
3986 FrameTestHelpers::WebViewHelper m_webViewHelper;
3989 TEST_F(CompositedSelectionBoundsTest, None) { runTest("composited_selection_bounds_none.html"); }
3990 TEST_F(CompositedSelectionBoundsTest, Basic) { runTest("composited_selection_bounds_basic.html"); }
3991 TEST_F(CompositedSelectionBoundsTest, Transformed) { runTest("composited_selection_bounds_transformed.html"); }
3992 TEST_F(CompositedSelectionBoundsTest, SplitLayer) { runTest("composited_selection_bounds_split_layer.html"); }
3993 TEST_F(CompositedSelectionBoundsTest, Iframe) { runTestWithMultipleFiles("composited_selection_bounds_iframe.html", "composited_selection_bounds_basic.html", nullptr); }
3995 TEST_F(WebFrameTest, CompositedSelectionBoundsCleared)
3997 RuntimeEnabledFeatures::setCompositedSelectionUpdateEnabled(true);
3999 registerMockedHttpURLLoad("select_range_basic.html");
4000 registerMockedHttpURLLoad("select_range_scroll.html");
4002 int viewWidth = 500;
4003 int viewHeight = 500;
4005 CompositedSelectionBoundsTestWebViewClient fakeSelectionWebViewClient;
4006 CompositedSelectionBoundsTestLayerTreeView& fakeSelectionLayerTreeView = fakeSelectionWebViewClient.selectionLayerTreeView();
4008 FrameTestHelpers::WebViewHelper webViewHelper;
4009 webViewHelper.initialize(true, 0, &fakeSelectionWebViewClient);
4010 webViewHelper.webView()->settings()->setDefaultFontSize(12);
4011 webViewHelper.webView()->setPageScaleFactorLimits(1, 1);
4012 webViewHelper.webView()->resize(WebSize(viewWidth, viewHeight));
4013 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "select_range_basic.html");
4015 // The frame starts with a non-empty selection.
4016 WebFrame* frame = webViewHelper.webView()->mainFrame();
4017 ASSERT_TRUE(frame->hasSelection());
4018 EXPECT_FALSE(fakeSelectionLayerTreeView.getAndResetSelectionCleared());
4020 // The selection cleared notification should be triggered upon layout.
4021 frame->executeCommand(WebString::fromUTF8("Unselect"));
4022 ASSERT_FALSE(frame->hasSelection());
4023 EXPECT_FALSE(fakeSelectionLayerTreeView.getAndResetSelectionCleared());
4024 webViewHelper.webView()->layout();
4025 EXPECT_TRUE(fakeSelectionLayerTreeView.getAndResetSelectionCleared());
4027 frame->executeCommand(WebString::fromUTF8("SelectAll"));
4028 webViewHelper.webView()->layout();
4029 ASSERT_TRUE(frame->hasSelection());
4030 EXPECT_FALSE(fakeSelectionLayerTreeView.getAndResetSelectionCleared());
4032 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "select_range_scroll.html");
4033 ASSERT_TRUE(frame->hasSelection());
4034 EXPECT_FALSE(fakeSelectionLayerTreeView.getAndResetSelectionCleared());
4036 // Transitions between non-empty selections should not trigger a clearing.
4037 WebRect startWebRect;
4039 webViewHelper.webViewImpl()->selectionBounds(startWebRect, endWebRect);
4040 WebPoint movedEnd(bottomRightMinusOne(endWebRect));
4042 frame->selectRange(topLeft(startWebRect), movedEnd);
4043 webViewHelper.webView()->layout();
4044 ASSERT_TRUE(frame->hasSelection());
4045 EXPECT_FALSE(fakeSelectionLayerTreeView.getAndResetSelectionCleared());
4047 frame = webViewHelper.webView()->mainFrame();
4048 frame->executeCommand(WebString::fromUTF8("Unselect"));
4049 webViewHelper.webView()->layout();
4050 ASSERT_FALSE(frame->hasSelection());
4051 EXPECT_TRUE(fakeSelectionLayerTreeView.getAndResetSelectionCleared());
4054 class DisambiguationPopupTestWebViewClient : public FrameTestHelpers::TestWebViewClient {
4056 virtual bool didTapMultipleTargets(const WebSize&, const WebRect&, const WebVector<WebRect>& targetRects) OVERRIDE
4058 EXPECT_GE(targetRects.size(), 2u);
4063 bool triggered() const { return m_triggered; }
4064 void resetTriggered() { m_triggered = false; }
4068 static WebGestureEvent fatTap(int x, int y)
4070 WebGestureEvent event;
4071 event.type = WebInputEvent::GestureTap;
4074 event.data.tap.width = 50;
4075 event.data.tap.height = 50;
4079 TEST_F(WebFrameTest, DisambiguationPopup)
4081 const std::string htmlFile = "disambiguation_popup.html";
4082 registerMockedHttpURLLoad(htmlFile);
4084 DisambiguationPopupTestWebViewClient client;
4086 // Make sure we initialize to minimum scale, even if the window size
4087 // only becomes available after the load begins.
4088 FrameTestHelpers::WebViewHelper webViewHelper;
4089 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client);
4090 webViewHelper.webView()->resize(WebSize(1000, 1000));
4091 webViewHelper.webView()->layout();
4093 client.resetTriggered();
4094 webViewHelper.webView()->handleInputEvent(fatTap(0, 0));
4095 EXPECT_FALSE(client.triggered());
4097 client.resetTriggered();
4098 webViewHelper.webView()->handleInputEvent(fatTap(200, 115));
4099 EXPECT_FALSE(client.triggered());
4101 for (int i = 0; i <= 46; i++) {
4102 client.resetTriggered();
4103 webViewHelper.webView()->handleInputEvent(fatTap(120, 230 + i * 5));
4106 if (j >= 7 && j <= 9)
4107 EXPECT_TRUE(client.triggered());
4109 EXPECT_FALSE(client.triggered());
4112 for (int i = 0; i <= 46; i++) {
4113 client.resetTriggered();
4114 webViewHelper.webView()->handleInputEvent(fatTap(10 + i * 5, 590));
4117 if (j >= 7 && j <= 9)
4118 EXPECT_TRUE(client.triggered());
4120 EXPECT_FALSE(client.triggered());
4124 TEST_F(WebFrameTest, DisambiguationPopupNoContainer)
4126 registerMockedHttpURLLoad("disambiguation_popup_no_container.html");
4128 DisambiguationPopupTestWebViewClient client;
4130 // Make sure we initialize to minimum scale, even if the window size
4131 // only becomes available after the load begins.
4132 FrameTestHelpers::WebViewHelper webViewHelper;
4133 webViewHelper.initializeAndLoad(m_baseURL + "disambiguation_popup_no_container.html", true, 0, &client);
4134 webViewHelper.webView()->resize(WebSize(1000, 1000));
4135 webViewHelper.webView()->layout();
4137 client.resetTriggered();
4138 webViewHelper.webView()->handleInputEvent(fatTap(50, 50));
4139 EXPECT_FALSE(client.triggered());
4142 TEST_F(WebFrameTest, DisambiguationPopupMobileSite)
4144 UseMockScrollbarSettings mockScrollbarSettings;
4145 const std::string htmlFile = "disambiguation_popup_mobile_site.html";
4146 registerMockedHttpURLLoad(htmlFile);
4148 DisambiguationPopupTestWebViewClient client;
4150 // Make sure we initialize to minimum scale, even if the window size
4151 // only becomes available after the load begins.
4152 FrameTestHelpers::WebViewHelper webViewHelper;
4153 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client, enableViewportSettings);
4154 webViewHelper.webView()->resize(WebSize(1000, 1000));
4155 webViewHelper.webView()->layout();
4157 client.resetTriggered();
4158 webViewHelper.webView()->handleInputEvent(fatTap(0, 0));
4159 EXPECT_FALSE(client.triggered());
4161 client.resetTriggered();
4162 webViewHelper.webView()->handleInputEvent(fatTap(200, 115));
4163 EXPECT_FALSE(client.triggered());
4165 for (int i = 0; i <= 46; i++) {
4166 client.resetTriggered();
4167 webViewHelper.webView()->handleInputEvent(fatTap(120, 230 + i * 5));
4168 EXPECT_FALSE(client.triggered());
4171 for (int i = 0; i <= 46; i++) {
4172 client.resetTriggered();
4173 webViewHelper.webView()->handleInputEvent(fatTap(10 + i * 5, 590));
4174 EXPECT_FALSE(client.triggered());
4178 TEST_F(WebFrameTest, DisambiguationPopupViewportSite)
4180 UseMockScrollbarSettings mockScrollbarSettings;
4181 const std::string htmlFile = "disambiguation_popup_viewport_site.html";
4182 registerMockedHttpURLLoad(htmlFile);
4184 DisambiguationPopupTestWebViewClient client;
4186 // Make sure we initialize to minimum scale, even if the window size
4187 // only becomes available after the load begins.
4188 FrameTestHelpers::WebViewHelper webViewHelper;
4189 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client, enableViewportSettings);
4190 webViewHelper.webView()->resize(WebSize(1000, 1000));
4191 webViewHelper.webView()->layout();
4193 client.resetTriggered();
4194 webViewHelper.webView()->handleInputEvent(fatTap(0, 0));
4195 EXPECT_FALSE(client.triggered());
4197 client.resetTriggered();
4198 webViewHelper.webView()->handleInputEvent(fatTap(200, 115));
4199 EXPECT_FALSE(client.triggered());
4201 for (int i = 0; i <= 46; i++) {
4202 client.resetTriggered();
4203 webViewHelper.webView()->handleInputEvent(fatTap(120, 230 + i * 5));
4204 EXPECT_FALSE(client.triggered());
4207 for (int i = 0; i <= 46; i++) {
4208 client.resetTriggered();
4209 webViewHelper.webView()->handleInputEvent(fatTap(10 + i * 5, 590));
4210 EXPECT_FALSE(client.triggered());
4214 static void enableVirtualViewport(WebSettings* settings)
4216 settings->setPinchVirtualViewportEnabled(true);
4217 settings->setViewportEnabled(true);
4218 settings->setViewportMetaEnabled(true);
4219 settings->setShrinksViewportContentToFit(true);
4222 TEST_F(WebFrameTest, DisambiguationPopupPinchViewport)
4224 UseMockScrollbarSettings mockScrollbarSettings;
4225 const std::string htmlFile = "disambiguation_popup_200_by_800.html";
4226 registerMockedHttpURLLoad(htmlFile);
4228 DisambiguationPopupTestWebViewClient client;
4230 FrameTestHelpers::WebViewHelper webViewHelper;
4231 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client, enableVirtualViewport);
4233 WebViewImpl* webViewImpl = webViewHelper.webViewImpl();
4234 ASSERT_TRUE(webViewImpl);
4235 LocalFrame* frame = webViewImpl->mainFrameImpl()->frame();
4238 webViewHelper.webView()->resize(WebSize(100, 200));
4240 // Scroll main frame to the bottom of the document
4241 webViewImpl->setMainFrameScrollOffset(WebPoint(0, 400));
4242 EXPECT_POINT_EQ(IntPoint(0, 400), frame->view()->scrollPosition());
4244 webViewImpl->setPageScaleFactor(2.0);
4246 // Scroll pinch viewport to the top of the main frame.
4247 PinchViewport& pinchViewport = frame->page()->frameHost().pinchViewport();
4248 pinchViewport.setLocation(FloatPoint(0, 0));
4249 EXPECT_FLOAT_POINT_EQ(FloatPoint(0, 0), pinchViewport.location());
4251 // Tap at the top: there is nothing there.
4252 client.resetTriggered();
4253 webViewHelper.webView()->handleInputEvent(fatTap(10, 60));
4254 EXPECT_FALSE(client.triggered());
4256 // Scroll pinch viewport to the bottom of the main frame.
4257 pinchViewport.setLocation(FloatPoint(0, 200));
4258 EXPECT_FLOAT_POINT_EQ(FloatPoint(0, 200), pinchViewport.location());
4260 // Now the tap with the same coordinates should hit two elements.
4261 client.resetTriggered();
4262 webViewHelper.webView()->handleInputEvent(fatTap(10, 60));
4263 EXPECT_TRUE(client.triggered());
4266 TEST_F(WebFrameTest, DisambiguationPopupBlacklist)
4268 const unsigned viewportWidth = 500;
4269 const unsigned viewportHeight = 1000;
4270 const unsigned divHeight = 100;
4271 const std::string htmlFile = "disambiguation_popup_blacklist.html";
4272 registerMockedHttpURLLoad(htmlFile);
4274 DisambiguationPopupTestWebViewClient client;
4276 // Make sure we initialize to minimum scale, even if the window size
4277 // only becomes available after the load begins.
4278 FrameTestHelpers::WebViewHelper webViewHelper;
4279 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client);
4280 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
4281 webViewHelper.webView()->layout();
4283 // Click somewhere where the popup shouldn't appear.
4284 client.resetTriggered();
4285 webViewHelper.webView()->handleInputEvent(fatTap(viewportWidth / 2, 0));
4286 EXPECT_FALSE(client.triggered());
4288 // Click directly in between two container divs with click handlers, with children that don't handle clicks.
4289 client.resetTriggered();
4290 webViewHelper.webView()->handleInputEvent(fatTap(viewportWidth / 2, divHeight));
4291 EXPECT_TRUE(client.triggered());
4293 // The third div container should be blacklisted if you click on the link it contains.
4294 client.resetTriggered();
4295 webViewHelper.webView()->handleInputEvent(fatTap(viewportWidth / 2, divHeight * 3.25));
4296 EXPECT_FALSE(client.triggered());
4299 TEST_F(WebFrameTest, DisambiguationPopupPageScale)
4301 registerMockedHttpURLLoad("disambiguation_popup_page_scale.html");
4303 DisambiguationPopupTestWebViewClient client;
4305 // Make sure we initialize to minimum scale, even if the window size
4306 // only becomes available after the load begins.
4307 FrameTestHelpers::WebViewHelper webViewHelper;
4308 webViewHelper.initializeAndLoad(m_baseURL + "disambiguation_popup_page_scale.html", true, 0, &client);
4309 webViewHelper.webView()->resize(WebSize(1000, 1000));
4310 webViewHelper.webView()->layout();
4312 client.resetTriggered();
4313 webViewHelper.webView()->handleInputEvent(fatTap(80, 80));
4314 EXPECT_TRUE(client.triggered());
4316 client.resetTriggered();
4317 webViewHelper.webView()->handleInputEvent(fatTap(230, 190));
4318 EXPECT_TRUE(client.triggered());
4320 webViewHelper.webView()->setPageScaleFactor(3.0f);
4321 webViewHelper.webView()->layout();
4323 client.resetTriggered();
4324 webViewHelper.webView()->handleInputEvent(fatTap(240, 240));
4325 EXPECT_TRUE(client.triggered());
4327 client.resetTriggered();
4328 webViewHelper.webView()->handleInputEvent(fatTap(690, 570));
4329 EXPECT_FALSE(client.triggered());
4332 class TestSubstituteDataWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
4334 TestSubstituteDataWebFrameClient()
4335 : m_commitCalled(false)
4339 virtual void didFailProvisionalLoad(WebLocalFrame* frame, const WebURLError& error)
4341 frame->loadHTMLString("This should appear", toKURL("data:text/html,chromewebdata"), error.unreachableURL, true);
4344 virtual void didCommitProvisionalLoad(WebLocalFrame* frame, const WebHistoryItem&, WebHistoryCommitType)
4346 if (frame->dataSource()->response().url() != WebURL(URLTestHelpers::toKURL("about:blank")))
4347 m_commitCalled = true;
4350 bool commitCalled() const { return m_commitCalled; }
4353 bool m_commitCalled;
4356 TEST_F(WebFrameTest, ReplaceNavigationAfterHistoryNavigation)
4358 TestSubstituteDataWebFrameClient webFrameClient;
4360 FrameTestHelpers::WebViewHelper webViewHelper;
4361 webViewHelper.initializeAndLoad("about:blank", true, &webFrameClient);
4362 WebFrame* frame = webViewHelper.webView()->mainFrame();
4364 // Load a url as a history navigation that will return an error. TestSubstituteDataWebFrameClient
4365 // will start a SubstituteData load in response to the load failure, which should get fully committed.
4366 // Due to https://bugs.webkit.org/show_bug.cgi?id=91685, FrameLoader::didReceiveData() wasn't getting
4367 // called in this case, which resulted in the SubstituteData document not getting displayed.
4369 error.reason = 1337;
4370 error.domain = "WebFrameTest";
4371 std::string errorURL = "http://0.0.0.0";
4372 WebURLResponse response;
4373 response.initialize();
4374 response.setURL(URLTestHelpers::toKURL(errorURL));
4375 response.setMIMEType("text/html");
4376 response.setHTTPStatusCode(500);
4377 WebHistoryItem errorHistoryItem;
4378 errorHistoryItem.initialize();
4379 errorHistoryItem.setURLString(WebString::fromUTF8(errorURL.c_str(), errorURL.length()));
4380 Platform::current()->unitTestSupport()->registerMockedErrorURL(URLTestHelpers::toKURL(errorURL), response, error);
4381 FrameTestHelpers::loadHistoryItem(frame, errorHistoryItem, WebHistoryDifferentDocumentLoad, WebURLRequest::UseProtocolCachePolicy);
4383 WebString text = frame->contentAsText(std::numeric_limits<size_t>::max());
4384 EXPECT_EQ("This should appear", text.utf8());
4385 EXPECT_TRUE(webFrameClient.commitCalled());
4388 class TestWillInsertBodyWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
4390 TestWillInsertBodyWebFrameClient() : m_numBodies(0), m_didLoad(false)
4394 virtual void didCommitProvisionalLoad(WebLocalFrame*, const WebHistoryItem&, WebHistoryCommitType) OVERRIDE
4400 virtual void didCreateDocumentElement(WebLocalFrame*) OVERRIDE
4402 EXPECT_EQ(0, m_numBodies);
4405 virtual void willInsertBody(WebLocalFrame*) OVERRIDE
4414 TEST_F(WebFrameTest, HTMLDocument)
4416 registerMockedHttpURLLoad("clipped-body.html");
4418 TestWillInsertBodyWebFrameClient webFrameClient;
4419 FrameTestHelpers::WebViewHelper webViewHelper;
4420 webViewHelper.initializeAndLoad(m_baseURL + "clipped-body.html", false, &webFrameClient);
4422 EXPECT_TRUE(webFrameClient.m_didLoad);
4423 EXPECT_EQ(1, webFrameClient.m_numBodies);
4426 TEST_F(WebFrameTest, EmptyDocument)
4428 registerMockedHttpURLLoad("pageserializer/green_rectangle.svg");
4430 TestWillInsertBodyWebFrameClient webFrameClient;
4431 FrameTestHelpers::WebViewHelper webViewHelper;
4432 webViewHelper.initialize(false, &webFrameClient);
4434 EXPECT_FALSE(webFrameClient.m_didLoad);
4435 EXPECT_EQ(1, webFrameClient.m_numBodies); // The empty document that a new frame starts with triggers this.
4438 TEST_F(WebFrameTest, MoveCaretSelectionTowardsWindowPointWithNoSelection)
4440 FrameTestHelpers::WebViewHelper webViewHelper;
4441 webViewHelper.initializeAndLoad("about:blank", true);
4442 WebFrame* frame = webViewHelper.webView()->mainFrame();
4444 // This test passes if this doesn't crash.
4445 frame->moveCaretSelection(WebPoint(0, 0));
4448 TEST_F(WebFrameTest, NavigateToSandboxedMarkup)
4450 FrameTestHelpers::WebViewHelper webViewHelper;
4451 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad("about:blank", true);
4452 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4454 frame->document().setIsTransitionDocument();
4456 std::string markup("<div id='foo'></div><script>document.getElementById('foo').setAttribute('dir', 'rtl')</script>");
4457 frame->navigateToSandboxedMarkup(WebData(markup.data(), markup.length()));
4458 FrameTestHelpers::runPendingTasks();
4460 WebDocument document = webViewImpl->mainFrame()->document();
4461 WebElement transitionElement = document.getElementById("foo");
4462 // Check that the markup got navigated to successfully.
4463 EXPECT_FALSE(transitionElement.isNull());
4465 // Check that the inline script was not executed.
4466 EXPECT_FALSE(transitionElement.hasAttribute("dir"));
4469 class SpellCheckClient : public WebSpellCheckClient {
4471 explicit SpellCheckClient(uint32_t hash = 0) : m_numberOfTimesChecked(0), m_hash(hash) { }
4472 virtual ~SpellCheckClient() { }
4473 virtual void requestCheckingOfText(const WebString&, const WebVector<uint32_t>&, const WebVector<unsigned>&, WebTextCheckingCompletion* completion) OVERRIDE
4475 ++m_numberOfTimesChecked;
4476 Vector<WebTextCheckingResult> results;
4477 const int misspellingStartOffset = 1;
4478 const int misspellingLength = 8;
4479 results.append(WebTextCheckingResult(WebTextDecorationTypeSpelling, misspellingStartOffset, misspellingLength, WebString(), m_hash));
4480 completion->didFinishCheckingText(results);
4482 int numberOfTimesChecked() const { return m_numberOfTimesChecked; }
4484 int m_numberOfTimesChecked;
4488 TEST_F(WebFrameTest, ReplaceMisspelledRange)
4490 registerMockedHttpURLLoad("spell.html");
4491 FrameTestHelpers::WebViewHelper webViewHelper;
4492 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4493 SpellCheckClient spellcheck;
4494 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4496 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4497 Document* document = frame->frame()->document();
4498 Element* element = document->getElementById("data");
4500 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4501 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4502 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4505 document->execCommand("InsertText", false, "_wellcome_.");
4507 const int allTextBeginOffset = 0;
4508 const int allTextLength = 11;
4509 frame->selectRange(WebRange::fromDocumentRange(frame, allTextBeginOffset, allTextLength));
4510 RefPtrWillBeRawPtr<Range> selectionRange = frame->frame()->selection().toNormalizedRange();
4512 EXPECT_EQ(1, spellcheck.numberOfTimesChecked());
4513 EXPECT_EQ(1U, document->markers().markersInRange(selectionRange.get(), DocumentMarker::Spelling).size());
4515 frame->replaceMisspelledRange("welcome");
4516 EXPECT_EQ("_welcome_.", frame->contentAsText(std::numeric_limits<size_t>::max()).utf8());
4519 TEST_F(WebFrameTest, RemoveSpellingMarkers)
4521 registerMockedHttpURLLoad("spell.html");
4522 FrameTestHelpers::WebViewHelper webViewHelper;
4523 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4524 SpellCheckClient spellcheck;
4525 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4527 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4528 Document* document = frame->frame()->document();
4529 Element* element = document->getElementById("data");
4531 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4532 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4533 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4536 document->execCommand("InsertText", false, "_wellcome_.");
4538 frame->removeSpellingMarkers();
4540 const int allTextBeginOffset = 0;
4541 const int allTextLength = 11;
4542 frame->selectRange(WebRange::fromDocumentRange(frame, allTextBeginOffset, allTextLength));
4543 RefPtrWillBeRawPtr<Range> selectionRange = frame->frame()->selection().toNormalizedRange();
4545 EXPECT_EQ(0U, document->markers().markersInRange(selectionRange.get(), DocumentMarker::Spelling).size());
4548 TEST_F(WebFrameTest, RemoveSpellingMarkersUnderWords)
4550 registerMockedHttpURLLoad("spell.html");
4551 FrameTestHelpers::WebViewHelper webViewHelper;
4552 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4553 SpellCheckClient spellcheck;
4554 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4556 LocalFrame* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame())->frame();
4557 Document* document = frame->document();
4558 Element* element = document->getElementById("data");
4560 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4561 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4562 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4565 document->execCommand("InsertText", false, " wellcome ");
4567 WebVector<uint32_t> documentMarkers1;
4568 webViewHelper.webView()->spellingMarkers(&documentMarkers1);
4569 EXPECT_EQ(1U, documentMarkers1.size());
4571 Vector<String> words;
4572 words.append("wellcome");
4573 frame->removeSpellingMarkersUnderWords(words);
4575 WebVector<uint32_t> documentMarkers2;
4576 webViewHelper.webView()->spellingMarkers(&documentMarkers2);
4577 EXPECT_EQ(0U, documentMarkers2.size());
4580 TEST_F(WebFrameTest, MarkerHashIdentifiers) {
4581 registerMockedHttpURLLoad("spell.html");
4582 FrameTestHelpers::WebViewHelper webViewHelper;
4583 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4585 static const uint32_t kHash = 42;
4586 SpellCheckClient spellcheck(kHash);
4587 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4589 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4590 Document* document = frame->frame()->document();
4591 Element* element = document->getElementById("data");
4593 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4594 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4595 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4598 document->execCommand("InsertText", false, "wellcome.");
4600 WebVector<uint32_t> documentMarkers;
4601 webViewHelper.webView()->spellingMarkers(&documentMarkers);
4602 EXPECT_EQ(1U, documentMarkers.size());
4603 EXPECT_EQ(kHash, documentMarkers[0]);
4606 class StubbornSpellCheckClient : public WebSpellCheckClient {
4608 StubbornSpellCheckClient() : m_completion(0) { }
4609 virtual ~StubbornSpellCheckClient() { }
4611 virtual void requestCheckingOfText(
4613 const WebVector<uint32_t>&,
4614 const WebVector<unsigned>&,
4615 WebTextCheckingCompletion* completion) OVERRIDE
4617 m_completion = completion;
4620 void kickNoResults()
4622 kick(-1, -1, WebTextDecorationTypeSpelling);
4627 kick(1, 8, WebTextDecorationTypeSpelling);
4632 kick(1, 8, WebTextDecorationTypeGrammar);
4635 void kickInvisibleSpellcheck()
4637 kick(1, 8, WebTextDecorationTypeInvisibleSpellcheck);
4641 void kick(int misspellingStartOffset, int misspellingLength, WebTextDecorationType type)
4645 Vector<WebTextCheckingResult> results;
4646 if (misspellingStartOffset >= 0 && misspellingLength > 0)
4647 results.append(WebTextCheckingResult(type, misspellingStartOffset, misspellingLength));
4648 m_completion->didFinishCheckingText(results);
4652 WebTextCheckingCompletion* m_completion;
4655 TEST_F(WebFrameTest, SlowSpellcheckMarkerPosition)
4657 registerMockedHttpURLLoad("spell.html");
4658 FrameTestHelpers::WebViewHelper webViewHelper;
4659 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4661 StubbornSpellCheckClient spellcheck;
4662 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4664 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4665 WebInputElement webInputElement = frame->document().getElementById("data").to<WebInputElement>();
4666 Document* document = frame->frame()->document();
4667 Element* element = document->getElementById("data");
4669 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4670 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4671 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4674 document->execCommand("InsertText", false, "wellcome ");
4675 webInputElement.setSelectionRange(0, 0);
4676 document->execCommand("InsertText", false, "he");
4680 WebVector<uint32_t> documentMarkers;
4681 webViewHelper.webView()->spellingMarkers(&documentMarkers);
4682 EXPECT_EQ(0U, documentMarkers.size());
4685 // This test verifies that cancelling spelling request does not cause a
4686 // write-after-free when there's no spellcheck client set.
4687 TEST_F(WebFrameTest, CancelSpellingRequestCrash)
4689 registerMockedHttpURLLoad("spell.html");
4690 FrameTestHelpers::WebViewHelper webViewHelper;
4691 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4692 webViewHelper.webView()->setSpellCheckClient(0);
4694 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4695 Document* document = frame->frame()->document();
4696 Element* element = document->getElementById("data");
4698 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4699 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4700 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4703 frame->frame()->editor().replaceSelectionWithText("A", false, false);
4704 frame->frame()->spellChecker().cancelCheck();
4707 TEST_F(WebFrameTest, SpellcheckResultErasesMarkers)
4709 registerMockedHttpURLLoad("spell.html");
4710 FrameTestHelpers::WebViewHelper webViewHelper;
4711 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4713 StubbornSpellCheckClient spellcheck;
4714 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4716 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4717 WebInputElement webInputElement = frame->document().getElementById("data").to<WebInputElement>();
4718 Document* document = frame->frame()->document();
4719 Element* element = document->getElementById("data");
4721 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4722 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4723 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4726 document->execCommand("InsertText", false, "welcome ");
4727 document->markers().addMarker(rangeOfContents(element->toNode()).get(), DocumentMarker::Spelling);
4728 document->markers().addMarker(rangeOfContents(element->toNode()).get(), DocumentMarker::Grammar);
4729 document->markers().addMarker(rangeOfContents(element->toNode()).get(), DocumentMarker::InvisibleSpellcheck);
4730 EXPECT_EQ(3U, document->markers().markers().size());
4732 spellcheck.kickNoResults();
4733 EXPECT_EQ(0U, document->markers().markers().size());
4736 TEST_F(WebFrameTest, SpellcheckResultsSavedInDocument)
4738 registerMockedHttpURLLoad("spell.html");
4739 FrameTestHelpers::WebViewHelper webViewHelper;
4740 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4742 StubbornSpellCheckClient spellcheck;
4743 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4745 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4746 WebInputElement webInputElement = frame->document().getElementById("data").to<WebInputElement>();
4747 Document* document = frame->frame()->document();
4748 Element* element = document->getElementById("data");
4750 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4751 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4752 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4755 document->execCommand("InsertText", false, "wellcome ");
4758 ASSERT_EQ(1U, document->markers().markers().size());
4759 ASSERT_NE(static_cast<DocumentMarker*>(0), document->markers().markers()[0]);
4760 EXPECT_EQ(DocumentMarker::Spelling, document->markers().markers()[0]->type());
4762 document->execCommand("InsertText", false, "wellcome ");
4764 spellcheck.kickGrammar();
4765 ASSERT_EQ(1U, document->markers().markers().size());
4766 ASSERT_NE(static_cast<DocumentMarker*>(0), document->markers().markers()[0]);
4767 EXPECT_EQ(DocumentMarker::Grammar, document->markers().markers()[0]->type());
4769 document->execCommand("InsertText", false, "wellcome ");
4771 spellcheck.kickInvisibleSpellcheck();
4772 ASSERT_EQ(1U, document->markers().markers().size());
4773 ASSERT_NE(static_cast<DocumentMarker*>(0), document->markers().markers()[0]);
4774 EXPECT_EQ(DocumentMarker::InvisibleSpellcheck, document->markers().markers()[0]->type());
4777 class TestAccessInitialDocumentWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
4779 TestAccessInitialDocumentWebFrameClient() : m_didAccessInitialDocument(false)
4783 virtual void didAccessInitialDocument(WebLocalFrame* frame)
4785 EXPECT_TRUE(!m_didAccessInitialDocument);
4786 m_didAccessInitialDocument = true;
4789 bool m_didAccessInitialDocument;
4792 TEST_F(WebFrameTest, DidAccessInitialDocumentBody)
4794 // FIXME: Why is this local webViewClient needed instead of the default
4795 // WebViewHelper one? With out it there's some mysterious crash in the
4796 // WebViewHelper destructor.
4797 FrameTestHelpers::TestWebViewClient webViewClient;
4798 TestAccessInitialDocumentWebFrameClient webFrameClient;
4799 FrameTestHelpers::WebViewHelper webViewHelper;
4800 webViewHelper.initialize(true, &webFrameClient, &webViewClient);
4802 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4804 // Create another window that will try to access it.
4805 FrameTestHelpers::WebViewHelper newWebViewHelper;
4806 WebView* newView = newWebViewHelper.initialize(true);
4807 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
4809 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4811 // Access the initial document by modifying the body.
4812 newView->mainFrame()->executeScript(
4813 WebScriptSource("window.opener.document.body.innerHTML += 'Modified';"));
4815 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4817 // Access the initial document again, to ensure we don't notify twice.
4818 newView->mainFrame()->executeScript(
4819 WebScriptSource("window.opener.document.body.innerHTML += 'Modified';"));
4821 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4824 TEST_F(WebFrameTest, DidAccessInitialDocumentNavigator)
4826 // FIXME: Why is this local webViewClient needed instead of the default
4827 // WebViewHelper one? With out it there's some mysterious crash in the
4828 // WebViewHelper destructor.
4829 FrameTestHelpers::TestWebViewClient webViewClient;
4830 TestAccessInitialDocumentWebFrameClient webFrameClient;
4831 FrameTestHelpers::WebViewHelper webViewHelper;
4832 webViewHelper.initialize(true, &webFrameClient, &webViewClient);
4834 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4836 // Create another window that will try to access it.
4837 FrameTestHelpers::WebViewHelper newWebViewHelper;
4838 WebView* newView = newWebViewHelper.initialize(true);
4839 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
4841 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4843 // Access the initial document to get to the navigator object.
4844 newView->mainFrame()->executeScript(
4845 WebScriptSource("console.log(window.opener.navigator);"));
4847 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4850 TEST_F(WebFrameTest, DidAccessInitialDocumentViaJavascriptUrl)
4852 TestAccessInitialDocumentWebFrameClient webFrameClient;
4853 FrameTestHelpers::WebViewHelper webViewHelper;
4854 webViewHelper.initialize(true, &webFrameClient);
4856 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4858 // Access the initial document from a javascript: URL.
4859 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.appendChild(document.createTextNode('Modified'))");
4860 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4863 // Fails on the WebKit XP (deps) bot. http://crbug.com/312192
4865 TEST_F(WebFrameTest, DISABLED_DidAccessInitialDocumentBodyBeforeModalDialog)
4867 TEST_F(WebFrameTest, DidAccessInitialDocumentBodyBeforeModalDialog)
4870 // FIXME: Why is this local webViewClient needed instead of the default
4871 // WebViewHelper one? With out it there's some mysterious crash in the
4872 // WebViewHelper destructor.
4873 FrameTestHelpers::TestWebViewClient webViewClient;
4874 TestAccessInitialDocumentWebFrameClient webFrameClient;
4875 FrameTestHelpers::WebViewHelper webViewHelper;
4876 webViewHelper.initialize(true, &webFrameClient, &webViewClient);
4878 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4880 // Create another window that will try to access it.
4881 FrameTestHelpers::WebViewHelper newWebViewHelper;
4882 WebView* newView = newWebViewHelper.initialize(true);
4883 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
4885 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4887 // Access the initial document by modifying the body. We normally set a
4888 // timer to notify the client.
4889 newView->mainFrame()->executeScript(
4890 WebScriptSource("window.opener.document.body.innerHTML += 'Modified';"));
4891 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4893 // Make sure that a modal dialog forces us to notify right away.
4894 newView->mainFrame()->executeScript(
4895 WebScriptSource("window.opener.confirm('Modal');"));
4896 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4898 // Ensure that we don't notify again later.
4900 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4903 // Fails on the WebKit XP (deps) bot. http://crbug.com/312192
4905 TEST_F(WebFrameTest, DISABLED_DidWriteToInitialDocumentBeforeModalDialog)
4907 TEST_F(WebFrameTest, DidWriteToInitialDocumentBeforeModalDialog)
4910 // FIXME: Why is this local webViewClient needed instead of the default
4911 // WebViewHelper one? With out it there's some mysterious crash in the
4912 // WebViewHelper destructor.
4913 FrameTestHelpers::TestWebViewClient webViewClient;
4914 TestAccessInitialDocumentWebFrameClient webFrameClient;
4915 FrameTestHelpers::WebViewHelper webViewHelper;
4916 webViewHelper.initialize(true, &webFrameClient, &webViewClient);
4918 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4920 // Create another window that will try to access it.
4921 FrameTestHelpers::WebViewHelper newWebViewHelper;
4922 WebView* newView = newWebViewHelper.initialize(true);
4923 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
4925 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4927 // Access the initial document with document.write, which moves us past the
4928 // initial empty document state of the state machine. We normally set a
4929 // timer to notify the client.
4930 newView->mainFrame()->executeScript(
4931 WebScriptSource("window.opener.document.write('Modified');"));
4932 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4934 // Make sure that a modal dialog forces us to notify right away.
4935 newView->mainFrame()->executeScript(
4936 WebScriptSource("window.opener.confirm('Modal');"));
4937 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4939 // Ensure that we don't notify again later.
4941 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4944 class TestMainFrameUserOrProgrammaticScrollFrameClient : public FrameTestHelpers::TestWebFrameClient {
4946 TestMainFrameUserOrProgrammaticScrollFrameClient() { reset(); }
4949 m_didScrollMainFrame = false;
4950 m_wasProgrammaticScroll = false;
4952 bool wasUserScroll() const { return m_didScrollMainFrame && !m_wasProgrammaticScroll; }
4953 bool wasProgrammaticScroll() const { return m_didScrollMainFrame && m_wasProgrammaticScroll; }
4956 virtual void didChangeScrollOffset(WebLocalFrame* frame) OVERRIDE
4958 if (frame->parent())
4960 EXPECT_FALSE(m_didScrollMainFrame);
4961 FrameView* view = toWebLocalFrameImpl(frame)->frameView();
4962 // FrameView can be scrolled in FrameView::setFixedVisibleContentRect
4963 // which is called from LocalFrame::createView (before the frame is associated
4964 // with the the view).
4966 m_didScrollMainFrame = true;
4967 m_wasProgrammaticScroll = view->inProgrammaticScroll();
4971 bool m_didScrollMainFrame;
4972 bool m_wasProgrammaticScroll;
4975 TEST_F(WebFrameTest, CompositorScrollIsUserScrollLongPage)
4977 registerMockedHttpURLLoad("long_scroll.html");
4978 TestMainFrameUserOrProgrammaticScrollFrameClient client;
4980 // Make sure we initialize to minimum scale, even if the window size
4981 // only becomes available after the load begins.
4982 FrameTestHelpers::WebViewHelper webViewHelper;
4983 webViewHelper.initializeAndLoad(m_baseURL + "long_scroll.html", true, &client);
4984 webViewHelper.webView()->resize(WebSize(1000, 1000));
4985 webViewHelper.webView()->layout();
4987 EXPECT_FALSE(client.wasUserScroll());
4988 EXPECT_FALSE(client.wasProgrammaticScroll());
4990 // Do a compositor scroll, verify that this is counted as a user scroll.
4991 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(0, 1), 1.1f, 0);
4992 EXPECT_TRUE(client.wasUserScroll());
4995 EXPECT_FALSE(client.wasUserScroll());
4996 EXPECT_FALSE(client.wasProgrammaticScroll());
4998 // The page scale 1.0f and scroll.
4999 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(0, 1), 1.0f, 0);
5000 EXPECT_TRUE(client.wasUserScroll());
5003 // No scroll event if there is no scroll delta.
5004 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(), 1.0f, 0);
5005 EXPECT_FALSE(client.wasUserScroll());
5006 EXPECT_FALSE(client.wasProgrammaticScroll());
5009 // Non zero page scale and scroll.
5010 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(9, 13), 0.6f, 0);
5011 EXPECT_TRUE(client.wasUserScroll());
5014 // Programmatic scroll.
5015 WebLocalFrameImpl* frameImpl = webViewHelper.webViewImpl()->mainFrameImpl();
5016 frameImpl->executeScript(WebScriptSource("window.scrollTo(0, 20);"));
5017 EXPECT_FALSE(client.wasUserScroll());
5018 EXPECT_TRUE(client.wasProgrammaticScroll());
5021 // Programmatic scroll to same offset. No scroll event should be generated.
5022 frameImpl->executeScript(WebScriptSource("window.scrollTo(0, 20);"));
5023 EXPECT_FALSE(client.wasProgrammaticScroll());
5024 EXPECT_FALSE(client.wasUserScroll());
5028 TEST_F(WebFrameTest, CompositorScrollIsUserScrollShortPage)
5030 registerMockedHttpURLLoad("short_scroll.html");
5032 TestMainFrameUserOrProgrammaticScrollFrameClient client;
5034 // Short page tests.
5035 FrameTestHelpers::WebViewHelper webViewHelper;
5036 webViewHelper.initializeAndLoad(m_baseURL + "short_scroll.html", true, &client);
5038 webViewHelper.webView()->resize(WebSize(1000, 1000));
5039 webViewHelper.webView()->layout();
5041 EXPECT_FALSE(client.wasUserScroll());
5042 EXPECT_FALSE(client.wasProgrammaticScroll());
5044 // Non zero page scale and scroll.
5045 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(9, 13), 2.0f, 0);
5046 EXPECT_FALSE(client.wasProgrammaticScroll());
5047 EXPECT_TRUE(client.wasUserScroll());
5051 TEST_F(WebFrameTest, FirstPartyForCookiesForRedirect)
5053 WTF::String filePath = Platform::current()->unitTestSupport()->webKitRootDir();
5054 filePath.append("/Source/web/tests/data/first_party.html");
5056 WebURL testURL(toKURL("http://www.test.com/first_party_redirect.html"));
5057 char redirect[] = "http://www.test.com/first_party.html";
5058 WebURL redirectURL(toKURL(redirect));
5059 WebURLResponse redirectResponse;
5060 redirectResponse.initialize();
5061 redirectResponse.setMIMEType("text/html");
5062 redirectResponse.setHTTPStatusCode(302);
5063 redirectResponse.setHTTPHeaderField("Location", redirect);
5064 Platform::current()->unitTestSupport()->registerMockedURL(testURL, redirectResponse, filePath);
5066 WebURLResponse finalResponse;
5067 finalResponse.initialize();
5068 finalResponse.setMIMEType("text/html");
5069 Platform::current()->unitTestSupport()->registerMockedURL(redirectURL, finalResponse, filePath);
5071 FrameTestHelpers::WebViewHelper webViewHelper;
5072 webViewHelper.initializeAndLoad(m_baseURL + "first_party_redirect.html", true);
5073 EXPECT_TRUE(webViewHelper.webView()->mainFrame()->document().firstPartyForCookies() == redirectURL);
5076 class TestNavigationPolicyWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5079 virtual void didNavigateWithinPage(WebLocalFrame*, const WebHistoryItem&, WebHistoryCommitType) OVERRIDE
5085 TEST_F(WebFrameTest, SimulateFragmentAnchorMiddleClick)
5087 registerMockedHttpURLLoad("fragment_middle_click.html");
5088 TestNavigationPolicyWebFrameClient client;
5089 FrameTestHelpers::WebViewHelper webViewHelper;
5090 webViewHelper.initializeAndLoad(m_baseURL + "fragment_middle_click.html", true, &client);
5092 Document* document = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document();
5093 KURL destination = document->url();
5094 destination.setFragmentIdentifier("test");
5096 RefPtrWillBeRawPtr<Event> event = MouseEvent::create(EventTypeNames::click, false, false,
5097 document->domWindow(), 0, 0, 0, 0, 0, 0, 0, false, false, false, false, 1, nullptr, nullptr);
5098 FrameLoadRequest frameRequest(document, ResourceRequest(destination));
5099 frameRequest.setTriggeringEvent(event);
5100 toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->loader().load(frameRequest);
5103 class TestNewWindowWebViewClient : public FrameTestHelpers::TestWebViewClient {
5105 virtual WebView* createView(WebLocalFrame*, const WebURLRequest&, const WebWindowFeatures&,
5106 const WebString&, WebNavigationPolicy, bool) OVERRIDE
5113 class TestNewWindowWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5115 TestNewWindowWebFrameClient()
5116 : m_decidePolicyCallCount(0)
5120 virtual WebNavigationPolicy decidePolicyForNavigation(const NavigationPolicyInfo& info) OVERRIDE
5122 m_decidePolicyCallCount++;
5123 return info.defaultPolicy;
5126 int decidePolicyCallCount() const { return m_decidePolicyCallCount; }
5129 int m_decidePolicyCallCount;
5132 TEST_F(WebFrameTest, ModifiedClickNewWindow)
5134 registerMockedHttpURLLoad("ctrl_click.html");
5135 registerMockedHttpURLLoad("hello_world.html");
5136 TestNewWindowWebViewClient webViewClient;
5137 TestNewWindowWebFrameClient webFrameClient;
5138 FrameTestHelpers::WebViewHelper webViewHelper;
5139 webViewHelper.initializeAndLoad(m_baseURL + "ctrl_click.html", true, &webFrameClient, &webViewClient);
5141 Document* document = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document();
5142 KURL destination = toKURL(m_baseURL + "hello_world.html");
5145 RefPtrWillBeRawPtr<Event> event = MouseEvent::create(EventTypeNames::click, false, false,
5146 document->domWindow(), 0, 0, 0, 0, 0, 0, 0, true, false, false, false, 0, nullptr, nullptr);
5147 FrameLoadRequest frameRequest(document, ResourceRequest(destination));
5148 frameRequest.setTriggeringEvent(event);
5149 UserGestureIndicator gesture(DefinitelyProcessingUserGesture);
5150 toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->loader().load(frameRequest);
5151 FrameTestHelpers::pumpPendingRequestsDoNotUse(webViewHelper.webView()->mainFrame());
5153 // decidePolicyForNavigation should be called both for the original request and the ctrl+click.
5154 EXPECT_EQ(2, webFrameClient.decidePolicyCallCount());
5157 TEST_F(WebFrameTest, BackToReload)
5159 registerMockedHttpURLLoad("fragment_middle_click.html");
5160 FrameTestHelpers::WebViewHelper webViewHelper;
5161 webViewHelper.initializeAndLoad(m_baseURL + "fragment_middle_click.html", true);
5162 WebFrame* frame = webViewHelper.webView()->mainFrame();
5163 const FrameLoader& mainFrameLoader = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->loader();
5164 RefPtr<HistoryItem> firstItem = mainFrameLoader.currentItem();
5165 EXPECT_TRUE(firstItem);
5167 registerMockedHttpURLLoad("white-1x1.png");
5168 FrameTestHelpers::loadFrame(frame, m_baseURL + "white-1x1.png");
5169 EXPECT_NE(firstItem.get(), mainFrameLoader.currentItem());
5171 FrameTestHelpers::loadHistoryItem(frame, WebHistoryItem(firstItem.get()), WebHistoryDifferentDocumentLoad, WebURLRequest::UseProtocolCachePolicy);
5172 EXPECT_EQ(firstItem.get(), mainFrameLoader.currentItem());
5174 FrameTestHelpers::reloadFrame(frame);
5175 EXPECT_EQ(WebURLRequest::ReloadIgnoringCacheData, frame->dataSource()->request().cachePolicy());
5178 TEST_F(WebFrameTest, BackDuringChildFrameReload)
5180 registerMockedHttpURLLoad("page_with_blank_iframe.html");
5181 FrameTestHelpers::WebViewHelper webViewHelper;
5182 webViewHelper.initializeAndLoad(m_baseURL + "page_with_blank_iframe.html", true);
5183 WebFrame* mainFrame = webViewHelper.webView()->mainFrame();
5184 const FrameLoader& mainFrameLoader = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->loader();
5185 WebFrame* childFrame = mainFrame->firstChild();
5186 ASSERT_TRUE(childFrame);
5188 // Start a history navigation, then have a different frame commit a navigation.
5189 // In this case, reload an about:blank frame, which will commit synchronously.
5190 // After the history navigation completes, both the appropriate document url and
5191 // the current history item should reflect the history navigation.
5192 registerMockedHttpURLLoad("white-1x1.png");
5193 WebHistoryItem item;
5195 WebURL historyURL(toKURL(m_baseURL + "white-1x1.png"));
5196 item.setURLString(historyURL.string());
5197 mainFrame->loadHistoryItem(item, WebHistoryDifferentDocumentLoad, WebURLRequest::UseProtocolCachePolicy);
5199 FrameTestHelpers::reloadFrame(childFrame);
5200 EXPECT_EQ(item.urlString(), mainFrame->document().url().string());
5201 EXPECT_EQ(item.urlString(), WebString(mainFrameLoader.currentItem()->urlString()));
5204 TEST_F(WebFrameTest, ReloadPost)
5206 registerMockedHttpURLLoad("reload_post.html");
5207 FrameTestHelpers::WebViewHelper webViewHelper;
5208 webViewHelper.initializeAndLoad(m_baseURL + "reload_post.html", true);
5209 WebFrame* frame = webViewHelper.webView()->mainFrame();
5211 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.forms[0].submit()");
5212 // Pump requests one more time after the javascript URL has executed to
5213 // trigger the actual POST load request.
5214 FrameTestHelpers::pumpPendingRequestsDoNotUse(webViewHelper.webView()->mainFrame());
5215 EXPECT_EQ(WebString::fromUTF8("POST"), frame->dataSource()->request().httpMethod());
5217 FrameTestHelpers::reloadFrame(frame);
5218 EXPECT_EQ(WebURLRequest::ReloadIgnoringCacheData, frame->dataSource()->request().cachePolicy());
5219 EXPECT_EQ(WebNavigationTypeFormResubmitted, frame->dataSource()->navigationType());
5222 TEST_F(WebFrameTest, LoadHistoryItemReload)
5224 registerMockedHttpURLLoad("fragment_middle_click.html");
5225 FrameTestHelpers::WebViewHelper webViewHelper;
5226 webViewHelper.initializeAndLoad(m_baseURL + "fragment_middle_click.html", true);
5227 WebFrame* frame = webViewHelper.webView()->mainFrame();
5228 const FrameLoader& mainFrameLoader = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->loader();
5229 RefPtr<HistoryItem> firstItem = mainFrameLoader.currentItem();
5230 EXPECT_TRUE(firstItem);
5232 registerMockedHttpURLLoad("white-1x1.png");
5233 FrameTestHelpers::loadFrame(frame, m_baseURL + "white-1x1.png");
5234 EXPECT_NE(firstItem.get(), mainFrameLoader.currentItem());
5236 // Cache policy overrides should take.
5237 FrameTestHelpers::loadHistoryItem(frame, WebHistoryItem(firstItem), WebHistoryDifferentDocumentLoad, WebURLRequest::ReloadIgnoringCacheData);
5238 EXPECT_EQ(firstItem.get(), mainFrameLoader.currentItem());
5239 EXPECT_EQ(WebURLRequest::ReloadIgnoringCacheData, frame->dataSource()->request().cachePolicy());
5243 class TestCachePolicyWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5245 explicit TestCachePolicyWebFrameClient(TestCachePolicyWebFrameClient* parentClient)
5246 : m_parentClient(parentClient)
5247 , m_policy(WebURLRequest::UseProtocolCachePolicy)
5249 , m_willSendRequestCallCount(0)
5250 , m_childFrameCreationCount(0)
5254 void setChildWebFrameClient(TestCachePolicyWebFrameClient* client) { m_childClient = client; }
5255 WebURLRequest::CachePolicy cachePolicy() const { return m_policy; }
5256 int willSendRequestCallCount() const { return m_willSendRequestCallCount; }
5257 int childFrameCreationCount() const { return m_childFrameCreationCount; }
5259 virtual WebFrame* createChildFrame(WebLocalFrame* parent, const WebString&)
5261 ASSERT(m_childClient);
5262 m_childFrameCreationCount++;
5263 WebFrame* frame = WebLocalFrame::create(m_childClient);
5264 parent->appendChild(frame);
5268 virtual void didStartLoading(bool toDifferentDocument)
5270 if (m_parentClient) {
5271 m_parentClient->didStartLoading(toDifferentDocument);
5274 TestWebFrameClient::didStartLoading(toDifferentDocument);
5277 virtual void didStopLoading()
5279 if (m_parentClient) {
5280 m_parentClient->didStopLoading();
5283 TestWebFrameClient::didStopLoading();
5286 virtual void willSendRequest(WebLocalFrame* frame, unsigned, WebURLRequest& request, const WebURLResponse&) OVERRIDE
5288 m_policy = request.cachePolicy();
5289 m_willSendRequestCallCount++;
5293 TestCachePolicyWebFrameClient* m_parentClient;
5295 WebURLRequest::CachePolicy m_policy;
5296 TestCachePolicyWebFrameClient* m_childClient;
5297 int m_willSendRequestCallCount;
5298 int m_childFrameCreationCount;
5301 TEST_F(WebFrameTest, ReloadIframe)
5303 registerMockedHttpURLLoad("iframe_reload.html");
5304 registerMockedHttpURLLoad("visible_iframe.html");
5305 TestCachePolicyWebFrameClient mainClient(0);
5306 TestCachePolicyWebFrameClient childClient(&mainClient);
5307 mainClient.setChildWebFrameClient(&childClient);
5309 FrameTestHelpers::WebViewHelper webViewHelper;
5310 webViewHelper.initializeAndLoad(m_baseURL + "iframe_reload.html", true, &mainClient);
5312 WebLocalFrameImpl* mainFrame = webViewHelper.webViewImpl()->mainFrameImpl();
5313 RefPtrWillBeRawPtr<WebLocalFrameImpl> childFrame = toWebLocalFrameImpl(mainFrame->firstChild());
5314 ASSERT_EQ(childFrame->client(), &childClient);
5315 EXPECT_EQ(mainClient.childFrameCreationCount(), 1);
5316 EXPECT_EQ(childClient.willSendRequestCallCount(), 1);
5317 EXPECT_EQ(childClient.cachePolicy(), WebURLRequest::UseProtocolCachePolicy);
5319 FrameTestHelpers::reloadFrame(mainFrame);
5321 // A new WebFrame should have been created, but the child WebFrameClient should be reused.
5322 ASSERT_NE(childFrame, toWebLocalFrameImpl(mainFrame->firstChild()));
5323 ASSERT_EQ(toWebLocalFrameImpl(mainFrame->firstChild())->client(), &childClient);
5325 EXPECT_EQ(mainClient.childFrameCreationCount(), 2);
5326 EXPECT_EQ(childClient.willSendRequestCallCount(), 2);
5327 EXPECT_EQ(childClient.cachePolicy(), WebURLRequest::ReloadIgnoringCacheData);
5330 class TestSameDocumentWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5332 TestSameDocumentWebFrameClient()
5333 : m_frameLoadTypeSameSeen(false)
5337 virtual void willSendRequest(WebLocalFrame* frame, unsigned, WebURLRequest&, const WebURLResponse&)
5339 if (toWebLocalFrameImpl(frame)->frame()->loader().loadType() == FrameLoadTypeSame)
5340 m_frameLoadTypeSameSeen = true;
5343 bool frameLoadTypeSameSeen() const { return m_frameLoadTypeSameSeen; }
5346 bool m_frameLoadTypeSameSeen;
5349 TEST_F(WebFrameTest, NavigateToSame)
5351 registerMockedHttpURLLoad("navigate_to_same.html");
5352 TestSameDocumentWebFrameClient client;
5353 FrameTestHelpers::WebViewHelper webViewHelper;
5354 webViewHelper.initializeAndLoad(m_baseURL + "navigate_to_same.html", true, &client);
5355 EXPECT_FALSE(client.frameLoadTypeSameSeen());
5357 FrameLoadRequest frameRequest(0, ResourceRequest(toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document()->url()));
5358 toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->loader().load(frameRequest);
5359 FrameTestHelpers::pumpPendingRequestsDoNotUse(webViewHelper.webView()->mainFrame());
5361 EXPECT_TRUE(client.frameLoadTypeSameSeen());
5364 class TestSameDocumentWithImageWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5366 TestSameDocumentWithImageWebFrameClient()
5367 : m_numOfImageRequests(0)
5371 virtual void willSendRequest(WebLocalFrame* frame, unsigned, WebURLRequest& request, const WebURLResponse&)
5373 if (request.requestContext() == WebURLRequest::RequestContextImage) {
5374 m_numOfImageRequests++;
5375 EXPECT_EQ(WebURLRequest::UseProtocolCachePolicy, request.cachePolicy());
5379 int numOfImageRequests() const { return m_numOfImageRequests; }
5382 int m_numOfImageRequests;
5385 TEST_F(WebFrameTest, NavigateToSameNoConditionalRequestForSubresource)
5387 registerMockedHttpURLLoad("foo_with_image.html");
5388 registerMockedHttpURLLoad("white-1x1.png");
5389 TestSameDocumentWithImageWebFrameClient client;
5390 FrameTestHelpers::WebViewHelper webViewHelper;
5391 webViewHelper.initializeAndLoad(m_baseURL + "foo_with_image.html", true, &client, 0, &configureLoadsImagesAutomatically);
5394 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "foo_with_image.html");
5396 EXPECT_EQ(client.numOfImageRequests(), 2);
5399 TEST_F(WebFrameTest, WebNodeImageContents)
5401 FrameTestHelpers::WebViewHelper webViewHelper;
5402 webViewHelper.initializeAndLoad("about:blank", true);
5403 WebFrame* frame = webViewHelper.webView()->mainFrame();
5405 static const char bluePNG[] = "<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAGElEQVQYV2NkYPj/n4EIwDiqEF8oUT94AFIQE/cCn90IAAAAAElFTkSuQmCC\">";
5407 // Load up the image and test that we can extract the contents.
5408 KURL testURL = toKURL("about:blank");
5409 FrameTestHelpers::loadHTMLString(frame, bluePNG, testURL);
5411 WebNode node = frame->document().body().firstChild();
5412 EXPECT_TRUE(node.isElementNode());
5413 WebElement element = node.to<WebElement>();
5414 WebImage image = element.imageContents();
5415 ASSERT_FALSE(image.isNull());
5416 EXPECT_EQ(image.size().width, 10);
5417 EXPECT_EQ(image.size().height, 10);
5418 // FIXME: The rest of this test is disabled since the ImageDecodeCache state may be inconsistent when this test runs.
5420 // SkBitmap bitmap = image.getSkBitmap();
5421 // SkAutoLockPixels locker(bitmap);
5422 // EXPECT_EQ(bitmap.getColor(0, 0), SK_ColorBLUE);
5425 class TestStartStopCallbackWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5427 TestStartStopCallbackWebFrameClient()
5428 : m_startLoadingCount(0)
5429 , m_stopLoadingCount(0)
5430 , m_differentDocumentStartCount(0)
5434 virtual void didStartLoading(bool toDifferentDocument) OVERRIDE
5436 TestWebFrameClient::didStartLoading(toDifferentDocument);
5437 m_startLoadingCount++;
5438 if (toDifferentDocument)
5439 m_differentDocumentStartCount++;
5442 virtual void didStopLoading() OVERRIDE
5444 TestWebFrameClient::didStopLoading();
5445 m_stopLoadingCount++;
5448 int startLoadingCount() const { return m_startLoadingCount; }
5449 int stopLoadingCount() const { return m_stopLoadingCount; }
5450 int differentDocumentStartCount() const { return m_differentDocumentStartCount; }
5453 int m_startLoadingCount;
5454 int m_stopLoadingCount;
5455 int m_differentDocumentStartCount;
5458 TEST_F(WebFrameTest, PushStateStartsAndStops)
5460 registerMockedHttpURLLoad("push_state.html");
5461 TestStartStopCallbackWebFrameClient client;
5462 FrameTestHelpers::WebViewHelper webViewHelper;
5463 webViewHelper.initializeAndLoad(m_baseURL + "push_state.html", true, &client);
5465 EXPECT_EQ(client.startLoadingCount(), 2);
5466 EXPECT_EQ(client.stopLoadingCount(), 2);
5467 EXPECT_EQ(client.differentDocumentStartCount(), 1);
5470 class TestDidNavigateCommitTypeWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5472 TestDidNavigateCommitTypeWebFrameClient()
5473 : m_lastCommitType(WebHistoryInertCommit)
5477 virtual void didNavigateWithinPage(WebLocalFrame*, const WebHistoryItem&, WebHistoryCommitType type) OVERRIDE
5479 m_lastCommitType = type;
5482 WebHistoryCommitType lastCommitType() const { return m_lastCommitType; }
5485 WebHistoryCommitType m_lastCommitType;
5488 TEST_F(WebFrameTest, SameDocumentHistoryNavigationCommitType)
5490 registerMockedHttpURLLoad("push_state.html");
5491 TestDidNavigateCommitTypeWebFrameClient client;
5492 FrameTestHelpers::WebViewHelper webViewHelper;
5493 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "push_state.html", true, &client);
5494 RefPtr<HistoryItem> item = toLocalFrame(webViewImpl->page()->mainFrame())->loader().currentItem();
5497 toLocalFrame(webViewImpl->page()->mainFrame())->loader().loadHistoryItem(item.get(), HistorySameDocumentLoad);
5498 EXPECT_EQ(WebBackForwardCommit, client.lastCommitType());
5501 class TestHistoryWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5503 TestHistoryWebFrameClient()
5505 m_replacesCurrentHistoryItem = false;
5509 void didStartProvisionalLoad(WebLocalFrame* frame, bool isTransitionNavigation)
5511 WebDataSource* ds = frame->provisionalDataSource();
5512 m_replacesCurrentHistoryItem = ds->replacesCurrentHistoryItem();
5516 bool replacesCurrentHistoryItem() { return m_replacesCurrentHistoryItem; }
5517 WebFrame* frame() { return m_frame; }
5520 bool m_replacesCurrentHistoryItem;
5524 // Test which ensures that the first navigation in a subframe will always
5525 // result in history entry being replaced and not a new one added.
5526 TEST_F(WebFrameTest, DISABLED_FirstFrameNavigationReplacesHistory)
5528 registerMockedHttpURLLoad("history.html");
5529 registerMockedHttpURLLoad("find.html");
5531 FrameTestHelpers::WebViewHelper webViewHelper;
5532 TestHistoryWebFrameClient client;
5533 webViewHelper.initializeAndLoad("about:blank", true, &client);
5534 EXPECT_TRUE(client.replacesCurrentHistoryItem());
5536 WebFrame* frame = webViewHelper.webView()->mainFrame();
5538 FrameTestHelpers::loadFrame(frame,
5539 "javascript:document.body.appendChild(document.createElement('iframe'))");
5540 WebFrame* iframe = frame->firstChild();
5541 EXPECT_EQ(client.frame(), iframe);
5542 EXPECT_TRUE(client.replacesCurrentHistoryItem());
5544 FrameTestHelpers::loadFrame(frame,
5545 "javascript:window.frames[0].location.assign('" + m_baseURL + "history.html')");
5546 EXPECT_EQ(client.frame(), iframe);
5547 EXPECT_TRUE(client.replacesCurrentHistoryItem());
5549 FrameTestHelpers::loadFrame(frame,
5550 "javascript:window.frames[0].location.assign('" + m_baseURL + "find.html')");
5551 EXPECT_EQ(client.frame(), iframe);
5552 EXPECT_FALSE(client.replacesCurrentHistoryItem());
5554 // Repeat the test, but start out the iframe with initial URL, which is not
5556 FrameTestHelpers::loadFrame(frame,
5557 "javascript:var f = document.createElement('iframe'); "
5558 "f.src = '" + m_baseURL + "history.html';"
5559 "document.body.appendChild(f)");
5561 iframe = frame->firstChild()->nextSibling();
5562 EXPECT_EQ(client.frame(), iframe);
5563 EXPECT_TRUE(client.replacesCurrentHistoryItem());
5565 FrameTestHelpers::loadFrame(frame,
5566 "javascript:window.frames[1].location.assign('" + m_baseURL + "find.html')");
5567 EXPECT_EQ(client.frame(), iframe);
5568 EXPECT_FALSE(client.replacesCurrentHistoryItem());
5571 // Test verifies that layout will change a layer's scrollable attibutes
5572 TEST_F(WebFrameTest, overflowHiddenRewrite)
5574 registerMockedHttpURLLoad("non-scrollable.html");
5575 TestMainFrameUserOrProgrammaticScrollFrameClient client;
5576 OwnPtr<FakeCompositingWebViewClient> fakeCompositingWebViewClient = adoptPtr(new FakeCompositingWebViewClient());
5577 FrameTestHelpers::WebViewHelper webViewHelper;
5578 webViewHelper.initialize(true, 0, fakeCompositingWebViewClient.get(), &configueCompositingWebView);
5580 webViewHelper.webView()->resize(WebSize(100, 100));
5581 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "non-scrollable.html");
5583 RenderLayerCompositor* compositor = webViewHelper.webViewImpl()->compositor();
5584 ASSERT_TRUE(compositor->scrollLayer());
5586 // Verify that the WebLayer is not scrollable initially.
5587 GraphicsLayer* scrollLayer = compositor->scrollLayer();
5588 WebLayer* webScrollLayer = scrollLayer->platformLayer();
5589 ASSERT_FALSE(webScrollLayer->userScrollableHorizontal());
5590 ASSERT_FALSE(webScrollLayer->userScrollableVertical());
5592 // Call javascript to make the layer scrollable, and verify it.
5593 WebLocalFrameImpl* frame = (WebLocalFrameImpl*)webViewHelper.webView()->mainFrame();
5594 frame->executeScript(WebScriptSource("allowScroll();"));
5595 webViewHelper.webView()->layout();
5596 ASSERT_TRUE(webScrollLayer->userScrollableHorizontal());
5597 ASSERT_TRUE(webScrollLayer->userScrollableVertical());
5600 // Test that currentHistoryItem reflects the current page, not the provisional load.
5601 TEST_F(WebFrameTest, CurrentHistoryItem)
5603 registerMockedHttpURLLoad("fixed_layout.html");
5604 std::string url = m_baseURL + "fixed_layout.html";
5606 FrameTestHelpers::WebViewHelper webViewHelper;
5607 webViewHelper.initialize();
5608 WebFrame* frame = webViewHelper.webView()->mainFrame();
5609 const FrameLoader& mainFrameLoader = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->loader();
5610 WebURLRequest request;
5611 request.initialize();
5612 request.setURL(toKURL(url));
5613 frame->loadRequest(request);
5615 // Before commit, there is no history item.
5616 EXPECT_FALSE(mainFrameLoader.currentItem());
5618 FrameTestHelpers::pumpPendingRequestsDoNotUse(frame);
5620 // After commit, there is.
5621 HistoryItem* item = mainFrameLoader.currentItem();
5623 EXPECT_EQ(WTF::String(url.data()), item->urlString());
5626 class FailCreateChildFrame : public FrameTestHelpers::TestWebFrameClient {
5628 FailCreateChildFrame() : m_callCount(0) { }
5630 virtual WebFrame* createChildFrame(WebLocalFrame* parent, const WebString& frameName) OVERRIDE
5636 int callCount() const { return m_callCount; }
5642 // Test that we don't crash if WebFrameClient::createChildFrame() fails.
5643 TEST_F(WebFrameTest, CreateChildFrameFailure)
5645 registerMockedHttpURLLoad("create_child_frame_fail.html");
5646 FailCreateChildFrame client;
5647 FrameTestHelpers::WebViewHelper webViewHelper;
5648 webViewHelper.initializeAndLoad(m_baseURL + "create_child_frame_fail.html", true, &client);
5650 EXPECT_EQ(1, client.callCount());
5653 TEST_F(WebFrameTest, fixedPositionInFixedViewport)
5655 UseMockScrollbarSettings mockScrollbarSettings;
5656 registerMockedHttpURLLoad("fixed-position-in-fixed-viewport.html");
5657 FrameTestHelpers::WebViewHelper webViewHelper;
5658 webViewHelper.initializeAndLoad(m_baseURL + "fixed-position-in-fixed-viewport.html", true, 0, 0, enableViewportSettings);
5660 WebView* webView = webViewHelper.webView();
5661 webView->resize(WebSize(100, 100));
5664 Document* document = toWebLocalFrameImpl(webView->mainFrame())->frame()->document();
5665 Element* bottomFixed = document->getElementById("bottom-fixed");
5666 Element* topBottomFixed = document->getElementById("top-bottom-fixed");
5667 Element* rightFixed = document->getElementById("right-fixed");
5668 Element* leftRightFixed = document->getElementById("left-right-fixed");
5670 webView->resize(WebSize(100, 200));
5672 EXPECT_EQ(200, bottomFixed->offsetTop() + bottomFixed->offsetHeight());
5673 EXPECT_EQ(200, topBottomFixed->offsetHeight());
5675 webView->settings()->setMainFrameResizesAreOrientationChanges(false);
5676 webView->resize(WebSize(200, 200));
5678 EXPECT_EQ(200, rightFixed->offsetLeft() + rightFixed->offsetWidth());
5679 EXPECT_EQ(200, leftRightFixed->offsetWidth());
5681 webView->settings()->setMainFrameResizesAreOrientationChanges(true);
5682 // Will scale the page by 1.5.
5683 webView->resize(WebSize(300, 330));
5685 EXPECT_EQ(220, bottomFixed->offsetTop() + bottomFixed->offsetHeight());
5686 EXPECT_EQ(220, topBottomFixed->offsetHeight());
5687 EXPECT_EQ(200, rightFixed->offsetLeft() + rightFixed->offsetWidth());
5688 EXPECT_EQ(200, leftRightFixed->offsetWidth());
5691 TEST_F(WebFrameTest, FrameViewSetFrameRect)
5693 FrameTestHelpers::WebViewHelper webViewHelper;
5694 webViewHelper.initializeAndLoad("about:blank");
5696 FrameView* frameView = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
5697 frameView->setFrameRect(IntRect(0, 0, 200, 200));
5698 EXPECT_RECT_EQ(IntRect(0, 0, 200, 200), frameView->frameRect());
5699 frameView->setFrameRect(IntRect(100, 100, 200, 200));
5700 EXPECT_RECT_EQ(IntRect(100, 100, 200, 200), frameView->frameRect());
5703 // FIXME(bokan) Renable once Chromium-side of patch lands
5704 TEST_F(WebFrameTest, DISABLED_FrameViewScrollAccountsForTopControls)
5706 FrameTestHelpers::WebViewHelper webViewHelper;
5707 webViewHelper.initializeAndLoad("about:blank");
5709 WebViewImpl* webView = webViewHelper.webViewImpl();
5710 FrameView* frameView = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
5712 webView->setTopControlsLayoutHeight(0);
5713 webView->resize(WebSize(100, 100));
5714 webView->setPageScaleFactor(2.0f);
5717 webView->setMainFrameScrollOffset(WebPoint(20, 100));
5718 EXPECT_EQ_POINT(IntPoint(20, 50), IntPoint(frameView->scrollOffset()));
5720 // Simulate the top controls showing by 20px, thus shrinking the viewport
5721 // and allowing it to scroll an additional 10px (since we're 2X zoomed).
5722 webView->applyViewportDeltas(WebSize(0, 0), 1.0f, 20.0f);
5723 EXPECT_EQ_POINT(IntPoint(50, 60), frameView->maximumScrollPosition());
5725 // Show more, make sure the scroll actually gets clamped. Horizontal
5726 // direction shouldn't be affected.
5727 webView->applyViewportDeltas(WebSize(0, 0), 1.0f, 20.0f);
5728 webView->setMainFrameScrollOffset(WebPoint(100, 100));
5729 EXPECT_EQ_POINT(IntPoint(50, 70), IntPoint(frameView->scrollOffset()));
5731 // Hide until there's 10px showing.
5732 webView->applyViewportDeltas(WebSize(0, 0), 1.0f, -30.0f);
5733 EXPECT_EQ_POINT(IntPoint(50, 55), frameView->maximumScrollPosition());
5735 // Simulate a RenderWidget::resize. The frame is resized to accomodate
5736 // the top controls and Blink's view of the top controls matches that of
5738 webView->setTopControlsLayoutHeight(10.0f);
5739 webView->resize(WebSize(100, 90));
5741 EXPECT_EQ_POINT(IntPoint(50, 45), frameView->maximumScrollPosition());
5743 // Now simulate hiding.
5744 webView->applyViewportDeltas(WebSize(0, 0), 1.0f, -10.0f);
5745 EXPECT_EQ_POINT(IntPoint(50, 40), frameView->maximumScrollPosition());
5747 // Reset to original state: 100px widget height, top controls fully hidden.
5748 webView->setTopControlsLayoutHeight(0.0f);
5749 webView->resize(WebSize(100, 100));
5751 EXPECT_EQ_POINT(IntPoint(50, 50), frameView->maximumScrollPosition());
5753 // Show the top controls by just 1px, since we're zoomed in to 2X, that
5754 // should allow an extra 0.5px of scrolling, but since we quantize to ints
5755 // it should clamp such that we don't show anything outside bounds.
5756 webView->applyViewportDeltas(WebSize(0, 0), 1.0f, 1.0f);
5757 EXPECT_EQ_POINT(IntPoint(50, 50), frameView->maximumScrollPosition());
5759 webView->applyViewportDeltas(WebSize(0, 0), 1.0f, 2.0f);
5760 EXPECT_EQ_POINT(IntPoint(50, 51), frameView->maximumScrollPosition());
5765 TEST_F(WebFrameTest, FullscreenLayerNonScrollable)
5767 FakeCompositingWebViewClient client;
5768 registerMockedHttpURLLoad("fullscreen_div.html");
5769 FrameTestHelpers::WebViewHelper webViewHelper;
5770 int viewportWidth = 640;
5771 int viewportHeight = 480;
5772 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "fullscreen_div.html", true, 0, &client, &configueCompositingWebView);
5773 webViewImpl->resize(WebSize(viewportWidth, viewportHeight));
5774 webViewImpl->layout();
5776 Document* document = toWebLocalFrameImpl(webViewImpl->mainFrame())->frame()->document();
5777 UserGestureIndicator gesture(DefinitelyProcessingUserGesture);
5778 Element* divFullscreen = document->getElementById("div1");
5779 Fullscreen::from(*document).requestFullscreen(*divFullscreen, Fullscreen::PrefixedRequest);
5780 webViewImpl->didEnterFullScreen();
5781 webViewImpl->layout();
5783 // Verify that the main frame bounds are empty.
5784 ASSERT_TRUE(Fullscreen::isFullScreen(*document));
5785 WebLayer* webScrollLayer = webViewImpl->compositor()->scrollLayer()->platformLayer();
5786 ASSERT_EQ(WebSize(), webScrollLayer->bounds());
5788 // Verify that the main frame is scrollable upon exiting fullscreen.
5789 webViewImpl->didExitFullScreen();
5790 webViewImpl->layout();
5791 ASSERT_FALSE(Fullscreen::isFullScreen(*document));
5792 webScrollLayer = webViewImpl->compositor()->scrollLayer()->platformLayer();
5793 ASSERT_NE(WebSize(), webScrollLayer->bounds());
5796 TEST_F(WebFrameTest, FullscreenMainFrameScrollable)
5798 FakeCompositingWebViewClient client;
5799 registerMockedHttpURLLoad("fullscreen_div.html");
5800 FrameTestHelpers::WebViewHelper webViewHelper;
5801 int viewportWidth = 640;
5802 int viewportHeight = 480;
5803 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "fullscreen_div.html", true, 0, &client, &configueCompositingWebView);
5804 webViewImpl->resize(WebSize(viewportWidth, viewportHeight));
5805 webViewImpl->layout();
5807 Document* document = toWebLocalFrameImpl(webViewImpl->mainFrame())->frame()->document();
5808 UserGestureIndicator gesture(DefinitelyProcessingUserGesture);
5809 Fullscreen::from(*document).requestFullscreen(*document->documentElement(), Fullscreen::PrefixedRequest);
5810 webViewImpl->didEnterFullScreen();
5811 webViewImpl->layout();
5813 // Verify that the main frame is still scrollable.
5814 ASSERT_TRUE(Fullscreen::isFullScreen(*document));
5815 WebLayer* webScrollLayer = webViewImpl->compositor()->scrollLayer()->platformLayer();
5816 ASSERT_TRUE(webScrollLayer->scrollable());
5819 TEST_F(WebFrameTest, RenderBlockPercentHeightDescendants)
5821 registerMockedHttpURLLoad("percent-height-descendants.html");
5822 FrameTestHelpers::WebViewHelper webViewHelper;
5823 webViewHelper.initializeAndLoad(m_baseURL + "percent-height-descendants.html");
5825 WebView* webView = webViewHelper.webView();
5826 webView->resize(WebSize(800, 800));
5829 Document* document = toWebLocalFrameImpl(webView->mainFrame())->frame()->document();
5830 RenderBlock* container = toRenderBlock(document->getElementById("container")->renderer());
5831 RenderBox* percentHeightInAnonymous = toRenderBox(document->getElementById("percent-height-in-anonymous")->renderer());
5832 RenderBox* percentHeightDirectChild = toRenderBox(document->getElementById("percent-height-direct-child")->renderer());
5834 EXPECT_TRUE(RenderBlock::hasPercentHeightDescendant(percentHeightInAnonymous));
5835 EXPECT_TRUE(RenderBlock::hasPercentHeightDescendant(percentHeightDirectChild));
5837 ASSERT_TRUE(container->percentHeightDescendants());
5838 ASSERT_TRUE(container->hasPercentHeightDescendants());
5839 EXPECT_EQ(2U, container->percentHeightDescendants()->size());
5840 EXPECT_TRUE(container->percentHeightDescendants()->contains(percentHeightInAnonymous));
5841 EXPECT_TRUE(container->percentHeightDescendants()->contains(percentHeightDirectChild));
5843 RenderBlock* anonymousBlock = percentHeightInAnonymous->containingBlock();
5844 EXPECT_TRUE(anonymousBlock->isAnonymous());
5845 EXPECT_FALSE(anonymousBlock->hasPercentHeightDescendants());
5848 TEST_F(WebFrameTest, HasVisibleContentOnVisibleFrames)
5850 registerMockedHttpURLLoad("visible_frames.html");
5851 FrameTestHelpers::WebViewHelper webViewHelper;
5852 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "visible_frames.html");
5853 for (WebFrame* frame = webViewImpl->mainFrameImpl()->traverseNext(false); frame; frame = frame->traverseNext(false)) {
5854 EXPECT_TRUE(frame->hasVisibleContent());
5858 TEST_F(WebFrameTest, HasVisibleContentOnHiddenFrames)
5860 registerMockedHttpURLLoad("hidden_frames.html");
5861 FrameTestHelpers::WebViewHelper webViewHelper;
5862 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "hidden_frames.html");
5863 for (WebFrame* frame = webViewImpl->mainFrameImpl()->traverseNext(false); frame; frame = frame->traverseNext(false)) {
5864 EXPECT_FALSE(frame->hasVisibleContent());
5868 class ManifestChangeWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5870 ManifestChangeWebFrameClient() : m_manifestChangeCount(0) { }
5871 virtual void didChangeManifest(WebLocalFrame*) OVERRIDE
5873 ++m_manifestChangeCount;
5876 int manifestChangeCount() { return m_manifestChangeCount; }
5879 int m_manifestChangeCount;
5882 TEST_F(WebFrameTest, NotifyManifestChange)
5884 registerMockedHttpURLLoad("link-manifest-change.html");
5886 ManifestChangeWebFrameClient webFrameClient;
5887 FrameTestHelpers::WebViewHelper webViewHelper;
5888 webViewHelper.initializeAndLoad(m_baseURL + "link-manifest-change.html", true, &webFrameClient);
5890 EXPECT_EQ(14, webFrameClient.manifestChangeCount());
5893 TEST_F(WebFrameTest, ReloadBypassingCache)
5895 // Check that a reload ignoring cache on a frame will result in the cache
5896 // policy of the request being set to ReloadBypassingCache.
5897 registerMockedHttpURLLoad("foo.html");
5898 FrameTestHelpers::WebViewHelper webViewHelper;
5899 webViewHelper.initializeAndLoad(m_baseURL + "foo.html", true);
5900 WebFrame* frame = webViewHelper.webView()->mainFrame();
5901 FrameTestHelpers::reloadFrameIgnoringCache(frame);
5902 EXPECT_EQ(WebURLRequest::ReloadBypassingCache, frame->dataSource()->request().cachePolicy());
5905 static void nodeImageTestValidation(const IntSize& referenceBitmapSize, DragImage* dragImage)
5907 // Prepare the reference bitmap.
5909 bitmap.allocN32Pixels(referenceBitmapSize.width(), referenceBitmapSize.height());
5910 SkCanvas canvas(bitmap);
5911 canvas.drawColor(SK_ColorGREEN);
5913 EXPECT_EQ(referenceBitmapSize.width(), dragImage->size().width());
5914 EXPECT_EQ(referenceBitmapSize.height(), dragImage->size().height());
5915 const SkBitmap& dragBitmap = dragImage->bitmap();
5916 SkAutoLockPixels lockPixel(dragBitmap);
5917 EXPECT_EQ(0, memcmp(bitmap.getPixels(), dragBitmap.getPixels(), bitmap.getSize()));
5920 TEST_F(WebFrameTest, NodeImageTestCSSTransform)
5922 FrameTestHelpers::WebViewHelper webViewHelper;
5923 OwnPtr<DragImage> dragImage = nodeImageTestSetup(&webViewHelper, std::string("case-css-transform"));
5924 EXPECT_TRUE(dragImage);
5926 nodeImageTestValidation(IntSize(40, 40), dragImage.get());
5929 TEST_F(WebFrameTest, NodeImageTestCSS3DTransform)
5931 FrameTestHelpers::WebViewHelper webViewHelper;
5932 OwnPtr<DragImage> dragImage = nodeImageTestSetup(&webViewHelper, std::string("case-css-3dtransform"));
5933 EXPECT_TRUE(dragImage);
5935 nodeImageTestValidation(IntSize(20, 40), dragImage.get());
5938 TEST_F(WebFrameTest, NodeImageTestInlineBlock)
5940 FrameTestHelpers::WebViewHelper webViewHelper;
5941 OwnPtr<DragImage> dragImage = nodeImageTestSetup(&webViewHelper, std::string("case-inlineblock"));
5942 EXPECT_TRUE(dragImage);
5944 nodeImageTestValidation(IntSize(40, 40), dragImage.get());
5947 TEST_F(WebFrameTest, NodeImageTestFloatLeft)
5949 FrameTestHelpers::WebViewHelper webViewHelper;
5950 OwnPtr<DragImage> dragImage = nodeImageTestSetup(&webViewHelper, std::string("case-float-left-overflow-hidden"));
5951 EXPECT_TRUE(dragImage);
5953 nodeImageTestValidation(IntSize(40, 40), dragImage.get());
5956 // Crashes on Android: http://crbug.com/403804
5958 TEST_F(WebFrameTest, DISABLED_PrintingBasic)
5960 TEST_F(WebFrameTest, PrintingBasic)
5963 FrameTestHelpers::WebViewHelper webViewHelper;
5964 webViewHelper.initializeAndLoad("data:text/html,Hello, world.");
5966 WebFrame* frame = webViewHelper.webView()->mainFrame();
5968 WebPrintParams printParams;
5969 printParams.printContentArea.width = 500;
5970 printParams.printContentArea.height = 500;
5972 int pageCount = frame->printBegin(printParams);
5973 EXPECT_EQ(1, pageCount);
5977 class ThemeColorTestWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5979 ThemeColorTestWebFrameClient()
5980 : m_didNotify(false)
5986 m_didNotify = false;
5989 bool didNotify() const
5995 virtual void didChangeThemeColor()
6003 TEST_F(WebFrameTest, ThemeColor)
6005 registerMockedHttpURLLoad("theme_color_test.html");
6006 FrameTestHelpers::WebViewHelper webViewHelper;
6007 ThemeColorTestWebFrameClient client;
6008 webViewHelper.initializeAndLoad(m_baseURL + "theme_color_test.html", true, &client);
6009 EXPECT_TRUE(client.didNotify());
6010 WebLocalFrameImpl* frame = webViewHelper.webViewImpl()->mainFrameImpl();
6011 EXPECT_EQ(0xff0000ff, frame->document().themeColor());
6012 // Change color by rgb.
6014 frame->executeScript(WebScriptSource("document.getElementById('tc1').setAttribute('content', 'rgb(0, 0, 0)');"));
6015 EXPECT_TRUE(client.didNotify());
6016 EXPECT_EQ(0xff000000, frame->document().themeColor());
6017 // Change color by hsl.
6019 frame->executeScript(WebScriptSource("document.getElementById('tc1').setAttribute('content', 'hsl(240,100%, 50%)');"));
6020 EXPECT_TRUE(client.didNotify());
6021 EXPECT_EQ(0xff0000ff, frame->document().themeColor());
6022 // Change of second theme-color meta tag will not change frame's theme
6025 frame->executeScript(WebScriptSource("document.getElementById('tc2').setAttribute('content', '#00FF00');"));
6026 EXPECT_TRUE(client.didNotify());
6027 EXPECT_EQ(0xff0000ff, frame->document().themeColor());
6030 class WebFrameSwapTest : public WebFrameTest {
6034 registerMockedHttpURLLoad("frame-a-b-c.html");
6035 registerMockedHttpURLLoad("subframe-a.html");
6036 registerMockedHttpURLLoad("subframe-b.html");
6037 registerMockedHttpURLLoad("subframe-c.html");
6038 registerMockedHttpURLLoad("subframe-hello.html");
6040 m_webViewHelper.initializeAndLoad(m_baseURL + "frame-a-b-c.html");
6043 void reset() { m_webViewHelper.reset(); }
6044 WebFrame* mainFrame() const { return m_webViewHelper.webView()->mainFrame(); }
6047 FrameTestHelpers::WebViewHelper m_webViewHelper;
6050 // FIXME: We should have tests for main frame swaps, but it interacts poorly
6051 // with the geolocation inspector agent, since the lifetime of the inspector
6052 // agent is tied to the Page, but the inspector agent is created by the
6053 // instantiation of the main frame.
6055 void swapAndVerifyFirstChildConsistency(const char* const message, WebFrame* parent, WebFrame* newChild)
6057 SCOPED_TRACE(message);
6058 parent->firstChild()->swap(newChild);
6060 EXPECT_EQ(newChild, parent->firstChild());
6061 EXPECT_EQ(newChild->parent(), parent);
6062 EXPECT_EQ(newChild, parent->lastChild()->previousSibling()->previousSibling());
6063 EXPECT_EQ(newChild->nextSibling(), parent->lastChild()->previousSibling());
6066 TEST_F(WebFrameSwapTest, SwapFirstChild)
6068 WebFrame* remoteFrame = WebRemoteFrame::create(0);
6069 swapAndVerifyFirstChildConsistency("local->remote", mainFrame(), remoteFrame);
6071 FrameTestHelpers::TestWebFrameClient client;
6072 WebFrame* localFrame = WebLocalFrame::create(&client);
6073 swapAndVerifyFirstChildConsistency("remote->local", mainFrame(), localFrame);
6075 // FIXME: This almost certainly fires more load events on the iframe element
6077 // Finally, make sure an embedder triggered load in the local frame swapped
6079 FrameTestHelpers::loadFrame(localFrame, m_baseURL + "subframe-hello.html");
6080 std::string content = localFrame->contentAsText(1024).utf8();
6081 EXPECT_EQ("hello", content);
6083 // Manually reset to break WebViewHelper's dependency on the stack allocated
6084 // TestWebFrameClient.
6086 remoteFrame->close();
6089 void swapAndVerifyMiddleChildConsistency(const char* const message, WebFrame* parent, WebFrame* newChild)
6091 SCOPED_TRACE(message);
6092 parent->firstChild()->nextSibling()->swap(newChild);
6094 EXPECT_EQ(newChild, parent->firstChild()->nextSibling());
6095 EXPECT_EQ(newChild, parent->lastChild()->previousSibling());
6096 EXPECT_EQ(newChild->parent(), parent);
6097 EXPECT_EQ(newChild, parent->firstChild()->nextSibling());
6098 EXPECT_EQ(newChild->previousSibling(), parent->firstChild());
6099 EXPECT_EQ(newChild, parent->lastChild()->previousSibling());
6100 EXPECT_EQ(newChild->nextSibling(), parent->lastChild());
6103 TEST_F(WebFrameSwapTest, SwapMiddleChild)
6105 WebFrame* remoteFrame = WebRemoteFrame::create(0);
6106 swapAndVerifyMiddleChildConsistency("local->remote", mainFrame(), remoteFrame);
6108 FrameTestHelpers::TestWebFrameClient client;
6109 WebFrame* localFrame = WebLocalFrame::create(&client);
6110 swapAndVerifyMiddleChildConsistency("remote->local", mainFrame(), localFrame);
6112 // FIXME: This almost certainly fires more load events on the iframe element
6114 // Finally, make sure an embedder triggered load in the local frame swapped
6116 FrameTestHelpers::loadFrame(localFrame, m_baseURL + "subframe-hello.html");
6117 std::string content = localFrame->contentAsText(1024).utf8();
6118 EXPECT_EQ("hello", content);
6120 // Manually reset to break WebViewHelper's dependency on the stack allocated
6121 // TestWebFrameClient.
6123 remoteFrame->close();
6126 void swapAndVerifyLastChildConsistency(const char* const message, WebFrame* parent, WebFrame* newChild)
6128 SCOPED_TRACE(message);
6129 parent->lastChild()->swap(newChild);
6131 EXPECT_EQ(newChild, parent->lastChild());
6132 EXPECT_EQ(newChild->parent(), parent);
6133 EXPECT_EQ(newChild, parent->firstChild()->nextSibling()->nextSibling());
6134 EXPECT_EQ(newChild->previousSibling(), parent->firstChild()->nextSibling());
6137 TEST_F(WebFrameSwapTest, SwapLastChild)
6139 WebFrame* remoteFrame = WebRemoteFrame::create(0);
6140 swapAndVerifyLastChildConsistency("local->remote", mainFrame(), remoteFrame);
6142 FrameTestHelpers::TestWebFrameClient client;
6143 WebFrame* localFrame = WebLocalFrame::create(&client);
6144 swapAndVerifyLastChildConsistency("remote->local", mainFrame(), localFrame);
6146 // FIXME: This almost certainly fires more load events on the iframe element
6148 // Finally, make sure an embedder triggered load in the local frame swapped
6150 FrameTestHelpers::loadFrame(localFrame, m_baseURL + "subframe-hello.html");
6151 std::string content = localFrame->contentAsText(1024).utf8();
6152 EXPECT_EQ("hello", content);
6154 // Manually reset to break WebViewHelper's dependency on the stack allocated
6155 // TestWebFrameClient.
6157 remoteFrame->close();
6160 void swapAndVerifySubframeConsistency(const char* const message, WebFrame* oldFrame, WebFrame* newFrame)
6162 SCOPED_TRACE(message);
6164 EXPECT_TRUE(oldFrame->firstChild());
6165 oldFrame->swap(newFrame);
6167 EXPECT_FALSE(newFrame->firstChild());
6168 EXPECT_FALSE(newFrame->lastChild());
6171 TEST_F(WebFrameSwapTest, SwapParentShouldDetachChildren)
6173 WebRemoteFrame* remoteFrame = WebRemoteFrame::create(0);
6174 WebFrame* targetFrame = mainFrame()->firstChild()->nextSibling();
6175 EXPECT_TRUE(targetFrame);
6176 swapAndVerifySubframeConsistency("local->remote", targetFrame, remoteFrame);
6178 targetFrame = mainFrame()->firstChild()->nextSibling();
6179 EXPECT_TRUE(targetFrame);
6181 // Create child frames in the target frame before testing the swap.
6182 FrameTestHelpers::TestWebRemoteFrameClient remoteFrameClient;
6183 remoteFrame->createRemoteChild("", &remoteFrameClient);
6185 FrameTestHelpers::TestWebFrameClient client;
6186 WebFrame* localFrame = WebLocalFrame::create(&client);
6187 swapAndVerifySubframeConsistency("remote->local", targetFrame, localFrame);
6189 // FIXME: This almost certainly fires more load events on the iframe element
6191 // Finally, make sure an embedder triggered load in the local frame swapped
6193 FrameTestHelpers::loadFrame(localFrame, m_baseURL + "subframe-hello.html");
6194 std::string content = localFrame->contentAsText(1024).utf8();
6195 EXPECT_EQ("hello", content);
6197 // Manually reset to break WebViewHelper's dependency on the stack allocated
6198 // TestWebFrameClient.
6200 remoteFrame->close();
6203 class MockDocumentThreadableLoaderClient : public DocumentThreadableLoaderClient {
6205 MockDocumentThreadableLoaderClient() : m_failed(false) { }
6206 virtual void didFail(const ResourceError&) OVERRIDE { m_failed = true;}
6208 void reset() { m_failed = false; }
6209 bool failed() { return m_failed; }
6214 // FIXME: This would be better as a unittest on DocumentThreadableLoader but it
6215 // requires spin-up of a frame. It may be possible to remove that requirement
6216 // and convert it to a unittest.
6217 TEST_F(WebFrameTest, LoaderOriginAccess)
6219 FrameTestHelpers::WebViewHelper webViewHelper;
6220 webViewHelper.initializeAndLoad("about:blank");
6222 SchemeRegistry::registerURLSchemeAsDisplayIsolated("chrome");
6224 // Cross-origin request.
6225 KURL resourceUrl(ParsedURLString, "chrome://test.pdf");
6226 registerMockedChromeURLLoad("test.pdf");
6228 RefPtrWillBeRawPtr<LocalFrame> frame(toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame()));
6230 MockDocumentThreadableLoaderClient client;
6231 ThreadableLoaderOptions options;
6233 // First try to load the request with regular access. Should fail.
6234 options.crossOriginRequestPolicy = UseAccessControl;
6235 ResourceLoaderOptions resourceLoaderOptions;
6236 DocumentThreadableLoader::loadResourceSynchronously(
6237 *frame->document(), ResourceRequest(resourceUrl), client, options, resourceLoaderOptions);
6238 EXPECT_TRUE(client.failed());
6241 // Try to load the request with cross origin access. Should succeed.
6242 options.crossOriginRequestPolicy = AllowCrossOriginRequests;
6243 DocumentThreadableLoader::loadResourceSynchronously(
6244 *frame->document(), ResourceRequest(resourceUrl), client, options, resourceLoaderOptions);
6245 EXPECT_FALSE(client.failed());
6248 class NavigationTransitionCallbackWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
6250 NavigationTransitionCallbackWebFrameClient()
6251 : m_navigationalDataReceivedCount(0)
6252 , m_provisionalLoadCount(0)
6253 , m_wasLastProvisionalLoadATransition(false) { }
6255 virtual void addNavigationTransitionData(const WebString& allowedDestinationOrigin, const WebString& selector, const WebString& markup) OVERRIDE
6257 m_navigationalDataReceivedCount++;
6260 virtual void didStartProvisionalLoad(WebLocalFrame* localFrame, bool isTransitionNavigation) OVERRIDE
6262 m_provisionalLoadCount++;
6263 m_wasLastProvisionalLoadATransition = isTransitionNavigation;
6266 unsigned navigationalDataReceivedCount() const { return m_navigationalDataReceivedCount; }
6267 unsigned provisionalLoadCount() const { return m_provisionalLoadCount; }
6268 bool wasLastProvisionalLoadATransition() const { return m_wasLastProvisionalLoadATransition; }
6271 unsigned m_navigationalDataReceivedCount;
6272 unsigned m_provisionalLoadCount;
6273 bool m_wasLastProvisionalLoadATransition;
6276 TEST_F(WebFrameTest, NavigationTransitionCallbacks)
6278 RuntimeEnabledFeatures::setNavigationTransitionsEnabled(true);
6279 FrameTestHelpers::WebViewHelper viewHelper;
6280 NavigationTransitionCallbackWebFrameClient frameClient;
6281 WebLocalFrame* localFrame = viewHelper.initialize(true, &frameClient)->mainFrame()->toWebLocalFrame();
6283 const char* transitionHTMLString =
6285 "<meta name='transition-elements' content='#foo;*'>"
6288 // Initial document load should not be a transition.
6289 FrameTestHelpers::loadHTMLString(localFrame, transitionHTMLString, toKURL("http://www.test.com"));
6290 EXPECT_EQ(1u, frameClient.provisionalLoadCount());
6291 EXPECT_FALSE(frameClient.wasLastProvisionalLoadATransition());
6292 EXPECT_EQ(0u, frameClient.navigationalDataReceivedCount());
6294 // Going from www.test.com containing transition elements to about:blank, should be a transition.
6295 FrameTestHelpers::loadHTMLString(localFrame, transitionHTMLString, toKURL("about:blank"));
6296 EXPECT_EQ(2u, frameClient.provisionalLoadCount());
6297 EXPECT_TRUE(frameClient.wasLastProvisionalLoadATransition());
6298 EXPECT_EQ(1u, frameClient.navigationalDataReceivedCount());
6300 // Navigating to the URL of the current page shouldn't be a transition.
6301 FrameTestHelpers::loadHTMLString(localFrame, transitionHTMLString, toKURL("about:blank"));
6302 EXPECT_EQ(3u, frameClient.provisionalLoadCount());
6303 EXPECT_FALSE(frameClient.wasLastProvisionalLoadATransition());
6304 EXPECT_EQ(1u, frameClient.navigationalDataReceivedCount());
6306 // Neither should a page reload.
6307 localFrame->reload();
6308 EXPECT_EQ(4u, frameClient.provisionalLoadCount());
6309 EXPECT_FALSE(frameClient.wasLastProvisionalLoadATransition());
6310 EXPECT_EQ(1u, frameClient.navigationalDataReceivedCount());