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/FetchRequest.h"
53 #include "core/fetch/MemoryCache.h"
54 #include "core/fetch/ResourceFetcher.h"
55 #include "core/frame/FrameHost.h"
56 #include "core/frame/FrameView.h"
57 #include "core/frame/LocalFrame.h"
58 #include "core/frame/PinchViewport.h"
59 #include "core/frame/Settings.h"
60 #include "core/html/HTMLDocument.h"
61 #include "core/html/HTMLFormElement.h"
62 #include "core/html/HTMLMediaElement.h"
63 #include "core/loader/DocumentThreadableLoader.h"
64 #include "core/loader/DocumentThreadableLoaderClient.h"
65 #include "core/loader/FrameLoadRequest.h"
66 #include "core/loader/ThreadableLoader.h"
67 #include "core/page/EventHandler.h"
68 #include "core/page/Page.h"
69 #include "core/rendering/HitTestResult.h"
70 #include "core/rendering/RenderFullScreen.h"
71 #include "core/rendering/RenderView.h"
72 #include "core/rendering/compositing/RenderLayerCompositor.h"
73 #include "core/testing/NullExecutionContext.h"
74 #include "core/testing/URLTestHelpers.h"
75 #include "modules/mediastream/MediaStream.h"
76 #include "modules/mediastream/MediaStreamRegistry.h"
77 #include "platform/DragImage.h"
78 #include "platform/RuntimeEnabledFeatures.h"
79 #include "platform/UserGestureIndicator.h"
80 #include "platform/geometry/FloatRect.h"
81 #include "platform/network/ResourceError.h"
82 #include "platform/scroll/ScrollbarTheme.h"
83 #include "platform/weborigin/SchemeRegistry.h"
84 #include "public/platform/Platform.h"
85 #include "public/platform/WebFloatRect.h"
86 #include "public/platform/WebSelectionBound.h"
87 #include "public/platform/WebThread.h"
88 #include "public/platform/WebURL.h"
89 #include "public/platform/WebURLResponse.h"
90 #include "public/platform/WebUnitTestSupport.h"
91 #include "public/web/WebCache.h"
92 #include "public/web/WebDataSource.h"
93 #include "public/web/WebDocument.h"
94 #include "public/web/WebFindOptions.h"
95 #include "public/web/WebFormElement.h"
96 #include "public/web/WebFrameClient.h"
97 #include "public/web/WebHistoryItem.h"
98 #include "public/web/WebPrintParams.h"
99 #include "public/web/WebRange.h"
100 #include "public/web/WebRemoteFrame.h"
101 #include "public/web/WebScriptSource.h"
102 #include "public/web/WebSearchableFormData.h"
103 #include "public/web/WebSecurityOrigin.h"
104 #include "public/web/WebSecurityPolicy.h"
105 #include "public/web/WebSettings.h"
106 #include "public/web/WebSpellCheckClient.h"
107 #include "public/web/WebTextCheckingCompletion.h"
108 #include "public/web/WebTextCheckingResult.h"
109 #include "public/web/WebViewClient.h"
110 #include "web/WebLocalFrameImpl.h"
111 #include "web/WebRemoteFrameImpl.h"
112 #include "web/WebViewImpl.h"
113 #include "web/tests/FrameTestHelpers.h"
114 #include "wtf/Forward.h"
115 #include "wtf/dtoa/utils.h"
116 #include <gmock/gmock.h>
117 #include <gtest/gtest.h>
123 using blink::URLTestHelpers::toKURL;
124 using blink::FrameTestHelpers::runPendingTasks;
125 using blink::FrameTestHelpers::UseMockScrollbarSettings;
126 using namespace blink;
128 const int touchPointPadding = 32;
130 #define EXPECT_RECT_EQ(a, b) \
132 EXPECT_EQ(a.x(), b.x()); \
133 EXPECT_EQ(a.y(), b.y()); \
134 EXPECT_EQ(a.width(), b.width()); \
135 EXPECT_EQ(a.height(), b.height()); \
138 #define EXPECT_POINT_EQ(expected, actual) \
140 EXPECT_EQ((expected).x(), (actual).x()); \
141 EXPECT_EQ((expected).y(), (actual).y()); \
144 #define EXPECT_FLOAT_POINT_EQ(expected, actual) \
146 EXPECT_FLOAT_EQ((expected).x(), (actual).x()); \
147 EXPECT_FLOAT_EQ((expected).y(), (actual).y()); \
151 class WebFrameTest : public testing::Test {
154 : m_baseURL("http://internal.test/")
155 , m_notBaseURL("http://external.test/")
156 , m_chromeURL("chrome://")
160 virtual ~WebFrameTest()
162 Platform::current()->unitTestSupport()->unregisterAllMockedURLs();
165 void registerMockedHttpURLLoad(const std::string& fileName)
167 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8(fileName.c_str()));
170 void registerMockedChromeURLLoad(const std::string& fileName)
172 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_chromeURL.c_str()), WebString::fromUTF8(fileName.c_str()));
176 void registerMockedHttpURLLoadWithCSP(const std::string& fileName, const std::string& csp, bool reportOnly = false)
178 WebURLResponse response;
179 response.initialize();
180 response.setMIMEType("text/html");
181 response.addHTTPHeaderField(reportOnly ? WebString("Content-Security-Policy-Report-Only") : WebString("Content-Security-Policy"), WebString::fromUTF8(csp));
182 std::string fullString = m_baseURL + fileName;
183 URLTestHelpers::registerMockedURLLoadWithCustomResponse(toKURL(fullString.c_str()), WebString::fromUTF8(fileName.c_str()), WebString::fromUTF8(""), response);
186 void applyViewportStyleOverride(FrameTestHelpers::WebViewHelper* webViewHelper)
188 RefPtrWillBeRawPtr<StyleSheetContents> styleSheet = StyleSheetContents::create(CSSParserContext(UASheetMode, 0));
189 styleSheet->parseString(String(blink::viewportAndroidCss, sizeof(blink::viewportAndroidCss)));
190 OwnPtrWillBeRawPtr<RuleSet> ruleSet = RuleSet::create();
191 ruleSet->addRulesFromSheet(styleSheet.get(), MediaQueryEvaluator("screen"));
193 Document* document = toLocalFrame(webViewHelper->webViewImpl()->page()->mainFrame())->document();
194 document->ensureStyleResolver().viewportStyleResolver()->collectViewportRules(ruleSet.get(), ViewportStyleResolver::UserAgentOrigin);
195 document->ensureStyleResolver().viewportStyleResolver()->resolve();
198 static void configueCompositingWebView(WebSettings* settings)
200 settings->setAcceleratedCompositingEnabled(true);
201 settings->setPreferCompositingToLCDTextEnabled(true);
204 static void configurePinchVirtualViewport(WebSettings* settings)
206 settings->setPinchVirtualViewportEnabled(true);
207 settings->setViewportMetaEnabled(true);
208 settings->setViewportEnabled(true);
209 settings->setMainFrameResizesAreOrientationChanges(true);
210 settings->setShrinksViewportContentToFit(true);
213 static void configureLoadsImagesAutomatically(WebSettings* settings)
215 settings->setLoadsImagesAutomatically(true);
218 void initializeTextSelectionWebView(const std::string& url, FrameTestHelpers::WebViewHelper* webViewHelper)
220 webViewHelper->initializeAndLoad(url, true);
221 webViewHelper->webView()->settings()->setDefaultFontSize(12);
222 webViewHelper->webView()->resize(WebSize(640, 480));
225 PassOwnPtr<DragImage> nodeImageTestSetup(FrameTestHelpers::WebViewHelper* webViewHelper, const std::string& testcase)
227 registerMockedHttpURLLoad("nodeimage.html");
228 webViewHelper->initializeAndLoad(m_baseURL + "nodeimage.html");
229 webViewHelper->webView()->resize(WebSize(640, 480));
230 webViewHelper->webView()->layout();
231 RefPtrWillBeRawPtr<LocalFrame> frame = toLocalFrame(webViewHelper->webViewImpl()->page()->mainFrame());
233 Element* element = frame->document()->getElementById(testcase.c_str());
234 return frame->nodeImage(*element);
237 std::string m_baseURL;
238 std::string m_notBaseURL;
239 std::string m_chromeURL;
242 TEST_F(WebFrameTest, ContentText)
244 registerMockedHttpURLLoad("iframes_test.html");
245 registerMockedHttpURLLoad("visible_iframe.html");
246 registerMockedHttpURLLoad("invisible_iframe.html");
247 registerMockedHttpURLLoad("zero_sized_iframe.html");
249 FrameTestHelpers::WebViewHelper webViewHelper;
250 webViewHelper.initializeAndLoad(m_baseURL + "iframes_test.html");
252 // Now retrieve the frames text and test it only includes visible elements.
253 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
254 EXPECT_NE(std::string::npos, content.find(" visible paragraph"));
255 EXPECT_NE(std::string::npos, content.find(" visible iframe"));
256 EXPECT_EQ(std::string::npos, content.find(" invisible pararaph"));
257 EXPECT_EQ(std::string::npos, content.find(" invisible iframe"));
258 EXPECT_EQ(std::string::npos, content.find("iframe with zero size"));
261 TEST_F(WebFrameTest, FrameForEnteredContext)
263 registerMockedHttpURLLoad("iframes_test.html");
264 registerMockedHttpURLLoad("visible_iframe.html");
265 registerMockedHttpURLLoad("invisible_iframe.html");
266 registerMockedHttpURLLoad("zero_sized_iframe.html");
268 FrameTestHelpers::WebViewHelper webViewHelper;
269 webViewHelper.initializeAndLoad(m_baseURL + "iframes_test.html", true);
271 v8::HandleScope scope(v8::Isolate::GetCurrent());
272 EXPECT_EQ(webViewHelper.webView()->mainFrame(), WebLocalFrame::frameForContext(webViewHelper.webView()->mainFrame()->mainWorldScriptContext()));
273 EXPECT_EQ(webViewHelper.webView()->mainFrame()->firstChild(), WebLocalFrame::frameForContext(webViewHelper.webView()->mainFrame()->firstChild()->mainWorldScriptContext()));
276 TEST_F(WebFrameTest, FormWithNullFrame)
278 registerMockedHttpURLLoad("form.html");
280 FrameTestHelpers::WebViewHelper webViewHelper;
281 webViewHelper.initializeAndLoad(m_baseURL + "form.html");
283 WebVector<WebFormElement> forms;
284 webViewHelper.webView()->mainFrame()->document().forms(forms);
285 webViewHelper.reset();
287 EXPECT_EQ(forms.size(), 1U);
289 // This test passes if this doesn't crash.
290 WebSearchableFormData searchableDataForm(forms[0]);
293 TEST_F(WebFrameTest, ChromePageJavascript)
295 registerMockedChromeURLLoad("history.html");
297 // Pass true to enable JavaScript.
298 FrameTestHelpers::WebViewHelper webViewHelper;
299 webViewHelper.initializeAndLoad(m_chromeURL + "history.html", true);
301 // Try to run JS against the chrome-style URL.
302 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.appendChild(document.createTextNode('Clobbered'))");
304 // Required to see any updates in contentAsText.
305 webViewHelper.webView()->layout();
307 // Now retrieve the frame's text and ensure it was modified by running javascript.
308 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
309 EXPECT_NE(std::string::npos, content.find("Clobbered"));
312 TEST_F(WebFrameTest, ChromePageNoJavascript)
314 registerMockedChromeURLLoad("history.html");
316 /// Pass true to enable JavaScript.
317 FrameTestHelpers::WebViewHelper webViewHelper;
318 webViewHelper.initializeAndLoad(m_chromeURL + "history.html", true);
320 // Try to run JS against the chrome-style URL after prohibiting it.
321 WebSecurityPolicy::registerURLSchemeAsNotAllowingJavascriptURLs("chrome");
322 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.appendChild(document.createTextNode('Clobbered'))");
324 // Required to see any updates in contentAsText.
325 webViewHelper.webView()->layout();
327 // Now retrieve the frame's text and ensure it wasn't modified by running javascript.
328 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
329 EXPECT_EQ(std::string::npos, content.find("Clobbered"));
332 TEST_F(WebFrameTest, LocationSetHostWithMissingPort)
334 std::string fileName = "print-location-href.html";
335 registerMockedHttpURLLoad(fileName);
336 URLTestHelpers::registerMockedURLLoad(toKURL("http://internal.test:0/" + fileName), WebString::fromUTF8(fileName));
338 FrameTestHelpers::WebViewHelper webViewHelper;
340 /// Pass true to enable JavaScript.
341 webViewHelper.initializeAndLoad(m_baseURL + fileName, true);
343 // Setting host to "hostname:" should be treated as "hostname:0".
344 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:location.host = 'internal.test:'; void 0;");
346 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.textContent = location.href; void 0;");
348 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
349 EXPECT_EQ("http://internal.test:0/" + fileName, content);
352 TEST_F(WebFrameTest, LocationSetEmptyPort)
354 std::string fileName = "print-location-href.html";
355 registerMockedHttpURLLoad(fileName);
356 URLTestHelpers::registerMockedURLLoad(toKURL("http://internal.test:0/" + fileName), WebString::fromUTF8(fileName));
358 FrameTestHelpers::WebViewHelper webViewHelper;
360 /// Pass true to enable JavaScript.
361 webViewHelper.initializeAndLoad(m_baseURL + fileName, true);
363 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:location.port = ''; void 0;");
365 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.textContent = location.href; void 0;");
367 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
368 EXPECT_EQ("http://internal.test:0/" + fileName, content);
371 class CSSCallbackWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
373 CSSCallbackWebFrameClient() : m_updateCount(0) { }
374 virtual void didMatchCSS(WebLocalFrame*, const WebVector<WebString>& newlyMatchingSelectors, const WebVector<WebString>& stoppedMatchingSelectors) override;
376 std::map<WebLocalFrame*, std::set<std::string> > m_matchedSelectors;
380 void CSSCallbackWebFrameClient::didMatchCSS(WebLocalFrame* frame, const WebVector<WebString>& newlyMatchingSelectors, const WebVector<WebString>& stoppedMatchingSelectors)
383 std::set<std::string>& frameSelectors = m_matchedSelectors[frame];
384 for (size_t i = 0; i < newlyMatchingSelectors.size(); ++i) {
385 std::string selector = newlyMatchingSelectors[i].utf8();
386 EXPECT_EQ(0U, frameSelectors.count(selector)) << selector;
387 frameSelectors.insert(selector);
389 for (size_t i = 0; i < stoppedMatchingSelectors.size(); ++i) {
390 std::string selector = stoppedMatchingSelectors[i].utf8();
391 EXPECT_EQ(1U, frameSelectors.count(selector)) << selector;
392 frameSelectors.erase(selector);
396 class WebFrameCSSCallbackTest : public testing::Test {
398 WebFrameCSSCallbackTest()
401 m_frame = m_helper.initializeAndLoad("about:blank", true, &m_client)->mainFrame()->toWebLocalFrame();
404 ~WebFrameCSSCallbackTest()
406 EXPECT_EQ(1U, m_client.m_matchedSelectors.size());
409 WebDocument doc() const
411 return m_frame->document();
414 int updateCount() const
416 return m_client.m_updateCount;
419 const std::set<std::string>& matchedSelectors()
421 return m_client.m_matchedSelectors[m_frame];
424 void loadHTML(const std::string& html)
426 FrameTestHelpers::loadHTMLString(m_frame, html, toKURL("about:blank"));
429 void executeScript(const WebString& code)
431 m_frame->executeScript(WebScriptSource(code));
432 m_frame->view()->layout();
436 CSSCallbackWebFrameClient m_client;
437 FrameTestHelpers::WebViewHelper m_helper;
438 WebLocalFrame* m_frame;
441 TEST_F(WebFrameCSSCallbackTest, AuthorStyleSheet)
445 // This stylesheet checks that the internal property and value can't be
446 // set by a stylesheet, only WebDocument::watchCSSSelectors().
447 "div.initial_on { -internal-callback: none; }"
448 "div.initial_off { -internal-callback: -internal-presence; }"
450 "<div class=\"initial_on\"></div>"
451 "<div class=\"initial_off\"></div>");
453 std::vector<WebString> selectors;
454 selectors.push_back(WebString::fromUTF8("div.initial_on"));
455 m_frame->document().watchCSSSelectors(WebVector<WebString>(selectors));
456 m_frame->view()->layout();
458 EXPECT_EQ(1, updateCount());
459 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("div.initial_on"));
461 // Check that adding a watched selector calls back for already-present nodes.
462 selectors.push_back(WebString::fromUTF8("div.initial_off"));
463 doc().watchCSSSelectors(WebVector<WebString>(selectors));
464 m_frame->view()->layout();
466 EXPECT_EQ(2, updateCount());
467 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("div.initial_off", "div.initial_on"));
469 // Check that we can turn off callbacks for certain selectors.
470 doc().watchCSSSelectors(WebVector<WebString>());
471 m_frame->view()->layout();
473 EXPECT_EQ(3, updateCount());
474 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
477 TEST_F(WebFrameCSSCallbackTest, SharedRenderStyle)
479 // Check that adding an element calls back when it matches an existing rule.
480 std::vector<WebString> selectors;
481 selectors.push_back(WebString::fromUTF8("span"));
482 doc().watchCSSSelectors(WebVector<WebString>(selectors));
485 "i1 = document.createElement('span');"
486 "i1.id = 'first_span';"
487 "document.body.appendChild(i1)");
488 EXPECT_EQ(1, updateCount());
489 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
491 // Adding a second element that shares a RenderStyle shouldn't call back.
492 // We use <span>s to avoid default style rules that can set
493 // RenderStyle::unique().
495 "i2 = document.createElement('span');"
496 "i2.id = 'second_span';"
497 "i1 = document.getElementById('first_span');"
498 "i1.parentNode.insertBefore(i2, i1.nextSibling);");
499 EXPECT_EQ(1, updateCount());
500 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
502 // Removing the first element shouldn't call back.
504 "i1 = document.getElementById('first_span');"
505 "i1.parentNode.removeChild(i1);");
506 EXPECT_EQ(1, updateCount());
507 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
509 // But removing the second element *should* call back.
511 "i2 = document.getElementById('second_span');"
512 "i2.parentNode.removeChild(i2);");
513 EXPECT_EQ(2, updateCount());
514 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
517 TEST_F(WebFrameCSSCallbackTest, CatchesAttributeChange)
519 loadHTML("<span></span>");
521 std::vector<WebString> selectors;
522 selectors.push_back(WebString::fromUTF8("span[attr=\"value\"]"));
523 doc().watchCSSSelectors(WebVector<WebString>(selectors));
526 EXPECT_EQ(0, updateCount());
527 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
530 "document.querySelector('span').setAttribute('attr', 'value');");
531 EXPECT_EQ(1, updateCount());
532 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span[attr=\"value\"]"));
535 TEST_F(WebFrameCSSCallbackTest, DisplayNone)
537 loadHTML("<div style='display:none'><span></span></div>");
539 std::vector<WebString> selectors;
540 selectors.push_back(WebString::fromUTF8("span"));
541 doc().watchCSSSelectors(WebVector<WebString>(selectors));
544 EXPECT_EQ(0, updateCount()) << "Don't match elements in display:none trees.";
547 "d = document.querySelector('div');"
548 "d.style.display = 'block';");
549 EXPECT_EQ(1, updateCount()) << "Match elements when they become displayed.";
550 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
553 "d = document.querySelector('div');"
554 "d.style.display = 'none';");
555 EXPECT_EQ(2, updateCount()) << "Unmatch elements when they become undisplayed.";
556 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
559 "s = document.querySelector('span');"
560 "s.style.display = 'none';");
561 EXPECT_EQ(2, updateCount()) << "No effect from no-display'ing a span that's already undisplayed.";
564 "d = document.querySelector('div');"
565 "d.style.display = 'block';");
566 EXPECT_EQ(2, updateCount()) << "No effect from displaying a div whose span is display:none.";
569 "s = document.querySelector('span');"
570 "s.style.display = 'inline';");
571 EXPECT_EQ(3, updateCount()) << "Now the span is visible and produces a callback.";
572 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
575 "s = document.querySelector('span');"
576 "s.style.display = 'none';");
577 EXPECT_EQ(4, updateCount()) << "Undisplaying the span directly should produce another callback.";
578 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
581 TEST_F(WebFrameCSSCallbackTest, Reparenting)
584 "<div id='d1'><span></span></div>"
585 "<div id='d2'></div>");
587 std::vector<WebString> selectors;
588 selectors.push_back(WebString::fromUTF8("span"));
589 doc().watchCSSSelectors(WebVector<WebString>(selectors));
590 m_frame->view()->layout();
593 EXPECT_EQ(1, updateCount());
594 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
597 "s = document.querySelector('span');"
598 "d2 = document.getElementById('d2');"
599 "d2.appendChild(s);");
600 EXPECT_EQ(1, updateCount()) << "Just moving an element that continues to match shouldn't send a spurious callback.";
601 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
604 TEST_F(WebFrameCSSCallbackTest, MultiSelector)
606 loadHTML("<span></span>");
608 // Check that selector lists match as the whole list, not as each element
610 std::vector<WebString> selectors;
611 selectors.push_back(WebString::fromUTF8("span"));
612 selectors.push_back(WebString::fromUTF8("span,p"));
613 doc().watchCSSSelectors(WebVector<WebString>(selectors));
614 m_frame->view()->layout();
617 EXPECT_EQ(1, updateCount());
618 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span", "span, p"));
621 TEST_F(WebFrameCSSCallbackTest, InvalidSelector)
623 loadHTML("<p><span></span></p>");
625 // Build a list with one valid selector and one invalid.
626 std::vector<WebString> selectors;
627 selectors.push_back(WebString::fromUTF8("span"));
628 selectors.push_back(WebString::fromUTF8("[")); // Invalid.
629 selectors.push_back(WebString::fromUTF8("p span")); // Not compound.
630 doc().watchCSSSelectors(WebVector<WebString>(selectors));
631 m_frame->view()->layout();
634 EXPECT_EQ(1, updateCount());
635 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"))
636 << "An invalid selector shouldn't prevent other selectors from matching.";
639 TEST_F(WebFrameTest, DispatchMessageEventWithOriginCheck)
641 registerMockedHttpURLLoad("postmessage_test.html");
643 // Pass true to enable JavaScript.
644 FrameTestHelpers::WebViewHelper webViewHelper;
645 webViewHelper.initializeAndLoad(m_baseURL + "postmessage_test.html", true);
647 // Send a message with the correct origin.
648 WebSecurityOrigin correctOrigin(WebSecurityOrigin::create(toKURL(m_baseURL)));
649 WebDOMEvent event = webViewHelper.webView()->mainFrame()->document().createEvent("MessageEvent");
650 WebDOMMessageEvent message = event.to<WebDOMMessageEvent>();
651 WebSerializedScriptValue data(WebSerializedScriptValue::fromString("foo"));
652 message.initMessageEvent("message", false, false, data, "http://origin.com", 0, "");
653 webViewHelper.webView()->mainFrame()->dispatchMessageEventWithOriginCheck(correctOrigin, message);
655 // Send another message with incorrect origin.
656 WebSecurityOrigin incorrectOrigin(WebSecurityOrigin::create(toKURL(m_chromeURL)));
657 webViewHelper.webView()->mainFrame()->dispatchMessageEventWithOriginCheck(incorrectOrigin, message);
659 // Required to see any updates in contentAsText.
660 webViewHelper.webView()->layout();
662 // Verify that only the first addition is in the body of the page.
663 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
664 EXPECT_NE(std::string::npos, content.find("Message 1."));
665 EXPECT_EQ(std::string::npos, content.find("Message 2."));
668 TEST_F(WebFrameTest, PostMessageThenDetach)
670 FrameTestHelpers::WebViewHelper webViewHelper;
671 webViewHelper.initializeAndLoad("about:blank");
673 RefPtrWillBeRawPtr<LocalFrame> frame = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame());
674 NonThrowableExceptionState exceptionState;
675 frame->domWindow()->postMessage(SerializedScriptValue::create("message"), 0, "*", frame->domWindow(), exceptionState);
676 webViewHelper.reset();
677 EXPECT_FALSE(exceptionState.hadException());
679 // Success is not crashing.
683 class FixedLayoutTestWebViewClient : public FrameTestHelpers::TestWebViewClient {
685 virtual WebScreenInfo screenInfo() override { return m_screenInfo; }
687 WebScreenInfo m_screenInfo;
690 class FakeCompositingWebViewClient : public FixedLayoutTestWebViewClient {
692 virtual bool enterFullScreen() override { return true; }
695 // Viewport settings need to be set before the page gets loaded
696 static void enableViewportSettings(WebSettings* settings)
698 settings->setViewportMetaEnabled(true);
699 settings->setViewportEnabled(true);
700 settings->setMainFrameResizesAreOrientationChanges(true);
701 settings->setShrinksViewportContentToFit(true);
704 // Helper function to set autosizing multipliers on a document.
705 static bool setTextAutosizingMultiplier(Document* document, float multiplier)
707 bool multiplierSet = false;
708 for (RenderObject* renderer = document->renderView(); renderer; renderer = renderer->nextInPreOrder()) {
709 if (renderer->style()) {
710 renderer->style()->setTextAutosizingMultiplier(multiplier);
712 EXPECT_EQ(multiplier, renderer->style()->textAutosizingMultiplier());
713 multiplierSet = true;
716 return multiplierSet;
719 // Helper function to check autosizing multipliers on a document.
720 static bool checkTextAutosizingMultiplier(Document* document, float multiplier)
722 bool multiplierChecked = false;
723 for (RenderObject* renderer = document->renderView(); renderer; renderer = renderer->nextInPreOrder()) {
724 if (renderer->style() && renderer->isText()) {
725 EXPECT_EQ(multiplier, renderer->style()->textAutosizingMultiplier());
726 multiplierChecked = true;
729 return multiplierChecked;
732 TEST_F(WebFrameTest, ChangeInFixedLayoutResetsTextAutosizingMultipliers)
734 UseMockScrollbarSettings mockScrollbarSettings;
735 registerMockedHttpURLLoad("fixed_layout.html");
737 FixedLayoutTestWebViewClient client;
738 int viewportWidth = 640;
739 int viewportHeight = 480;
741 FrameTestHelpers::WebViewHelper webViewHelper;
742 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
744 Document* document = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document();
745 document->settings()->setTextAutosizingEnabled(true);
746 EXPECT_TRUE(document->settings()->textAutosizingEnabled());
747 webViewHelper.webViewImpl()->resize(WebSize(viewportWidth, viewportHeight));
748 webViewHelper.webViewImpl()->layout();
750 EXPECT_TRUE(setTextAutosizingMultiplier(document, 2));
752 ViewportDescription description = document->viewportDescription();
753 // Choose a width that's not going match the viewport width of the loaded document.
754 description.minWidth = Length(100, blink::Fixed);
755 description.maxWidth = Length(100, blink::Fixed);
756 webViewHelper.webViewImpl()->updatePageDefinedViewportConstraints(description);
758 EXPECT_TRUE(checkTextAutosizingMultiplier(document, 1));
761 TEST_F(WebFrameTest, WorkingTextAutosizingMultipliers_VirtualViewport)
763 UseMockScrollbarSettings mockScrollbarSettings;
764 const std::string htmlFile = "fixed_layout.html";
765 registerMockedHttpURLLoad(htmlFile);
767 FixedLayoutTestWebViewClient client;
769 FrameTestHelpers::WebViewHelper webViewHelper;
770 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client, configurePinchVirtualViewport);
772 Document* document = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document();
773 document->settings()->setTextAutosizingEnabled(true);
774 EXPECT_TRUE(document->settings()->textAutosizingEnabled());
776 webViewHelper.webView()->resize(WebSize(490, 800));
778 // Multiplier: 980 / 490 = 2.0
779 EXPECT_TRUE(checkTextAutosizingMultiplier(document, 2.0));
782 TEST_F(WebFrameTest, SetFrameRectInvalidatesTextAutosizingMultipliers)
784 UseMockScrollbarSettings mockScrollbarSettings;
785 registerMockedHttpURLLoad("iframe_reload.html");
786 registerMockedHttpURLLoad("visible_iframe.html");
788 FixedLayoutTestWebViewClient client;
789 int viewportWidth = 640;
790 int viewportHeight = 480;
792 FrameTestHelpers::WebViewHelper webViewHelper;
793 webViewHelper.initializeAndLoad(m_baseURL + "iframe_reload.html", true, 0, &client, enableViewportSettings);
795 LocalFrame* mainFrame = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame());
796 Document* document = mainFrame->document();
797 FrameView* frameView = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
798 document->settings()->setTextAutosizingEnabled(true);
799 EXPECT_TRUE(document->settings()->textAutosizingEnabled());
800 webViewHelper.webViewImpl()->resize(WebSize(viewportWidth, viewportHeight));
801 webViewHelper.webViewImpl()->layout();
803 for (Frame* frame = mainFrame; frame; frame = frame->tree().traverseNext()) {
804 if (!frame->isLocalFrame())
806 EXPECT_TRUE(setTextAutosizingMultiplier(toLocalFrame(frame)->document(), 2));
807 for (RenderObject* renderer = toLocalFrame(frame)->document()->renderView(); renderer; renderer = renderer->nextInPreOrder()) {
808 if (renderer->isText())
809 EXPECT_FALSE(renderer->needsLayout());
813 frameView->setFrameRect(IntRect(0, 0, 200, 200));
814 for (Frame* frame = mainFrame; frame; frame = frame->tree().traverseNext()) {
815 if (!frame->isLocalFrame())
817 for (RenderObject* renderer = toLocalFrame(frame)->document()->renderView(); renderer; renderer = renderer->nextInPreOrder()) {
818 if (renderer->isText())
819 EXPECT_TRUE(renderer->needsLayout());
824 TEST_F(WebFrameTest, ZeroHeightPositiveWidthNotIgnored)
826 UseMockScrollbarSettings mockScrollbarSettings;
828 FixedLayoutTestWebViewClient client;
829 client.m_screenInfo.deviceScaleFactor = 1;
830 int viewportWidth = 1280;
831 int viewportHeight = 0;
833 FrameTestHelpers::WebViewHelper webViewHelper;
834 webViewHelper.initialize(true, 0, &client, enableViewportSettings);
835 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
837 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
838 EXPECT_EQ(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
841 TEST_F(WebFrameTest, DeviceScaleFactorUsesDefaultWithoutViewportTag)
843 UseMockScrollbarSettings mockScrollbarSettings;
844 registerMockedHttpURLLoad("no_viewport_tag.html");
846 int viewportWidth = 640;
847 int viewportHeight = 480;
849 FixedLayoutTestWebViewClient client;
850 client.m_screenInfo.deviceScaleFactor = 2;
852 FrameTestHelpers::WebViewHelper webViewHelper;
853 webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client, enableViewportSettings);
855 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
856 webViewHelper.webView()->layout();
858 EXPECT_EQ(2, webViewHelper.webView()->deviceScaleFactor());
860 // Device scale factor should be independent of page scale.
861 webViewHelper.webView()->setPageScaleFactorLimits(1, 2);
862 webViewHelper.webView()->setPageScaleFactor(0.5);
863 webViewHelper.webView()->layout();
864 EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor());
866 // Force the layout to happen before leaving the test.
867 webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
870 TEST_F(WebFrameTest, FixedLayoutInitializeAtMinimumScale)
872 UseMockScrollbarSettings mockScrollbarSettings;
874 registerMockedHttpURLLoad("fixed_layout.html");
876 FixedLayoutTestWebViewClient client;
877 client.m_screenInfo.deviceScaleFactor = 1;
878 int viewportWidth = 640;
879 int viewportHeight = 480;
881 // Make sure we initialize to minimum scale, even if the window size
882 // only becomes available after the load begins.
883 FrameTestHelpers::WebViewHelper webViewHelper;
884 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
885 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
887 int defaultFixedLayoutWidth = 980;
888 float minimumPageScaleFactor = viewportWidth / (float) defaultFixedLayoutWidth;
889 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
890 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->minimumPageScaleFactor());
892 // Assume the user has pinch zoomed to page scale factor 2.
893 float userPinchPageScaleFactor = 2;
894 webViewHelper.webView()->setPageScaleFactor(userPinchPageScaleFactor);
895 webViewHelper.webView()->layout();
897 // Make sure we don't reset to initial scale if the page continues to load.
898 webViewHelper.webViewImpl()->didCommitLoad(false, false);
899 webViewHelper.webViewImpl()->didChangeContentsSize();
900 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
902 // Make sure we don't reset to initial scale if the viewport size changes.
903 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight + 100));
904 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
907 TEST_F(WebFrameTest, WideDocumentInitializeAtMinimumScale)
909 UseMockScrollbarSettings mockScrollbarSettings;
911 registerMockedHttpURLLoad("wide_document.html");
913 FixedLayoutTestWebViewClient client;
914 client.m_screenInfo.deviceScaleFactor = 1;
915 int viewportWidth = 640;
916 int viewportHeight = 480;
918 // Make sure we initialize to minimum scale, even if the window size
919 // only becomes available after the load begins.
920 FrameTestHelpers::WebViewHelper webViewHelper;
921 webViewHelper.initializeAndLoad(m_baseURL + "wide_document.html", true, 0, &client, enableViewportSettings);
922 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
924 int wideDocumentWidth = 1500;
925 float minimumPageScaleFactor = viewportWidth / (float) wideDocumentWidth;
926 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
927 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->minimumPageScaleFactor());
929 // Assume the user has pinch zoomed to page scale factor 2.
930 float userPinchPageScaleFactor = 2;
931 webViewHelper.webView()->setPageScaleFactor(userPinchPageScaleFactor);
932 webViewHelper.webView()->layout();
934 // Make sure we don't reset to initial scale if the page continues to load.
935 webViewHelper.webViewImpl()->didCommitLoad(false, false);
936 webViewHelper.webViewImpl()->didChangeContentsSize();
937 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
939 // Make sure we don't reset to initial scale if the viewport size changes.
940 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight + 100));
941 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
944 TEST_F(WebFrameTest, DelayedViewportInitialScale)
946 UseMockScrollbarSettings mockScrollbarSettings;
947 registerMockedHttpURLLoad("viewport-auto-initial-scale.html");
949 FixedLayoutTestWebViewClient client;
950 client.m_screenInfo.deviceScaleFactor = 1;
951 int viewportWidth = 640;
952 int viewportHeight = 480;
954 FrameTestHelpers::WebViewHelper webViewHelper;
955 webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings);
956 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
958 EXPECT_EQ(0.25f, webViewHelper.webView()->pageScaleFactor());
960 Document* document = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document();
961 ViewportDescription description = document->viewportDescription();
962 description.zoom = 2;
963 document->setViewportDescription(description);
964 webViewHelper.webView()->layout();
965 EXPECT_EQ(2, webViewHelper.webView()->pageScaleFactor());
968 TEST_F(WebFrameTest, setLoadWithOverviewModeToFalse)
970 UseMockScrollbarSettings mockScrollbarSettings;
971 registerMockedHttpURLLoad("viewport-auto-initial-scale.html");
973 FixedLayoutTestWebViewClient client;
974 client.m_screenInfo.deviceScaleFactor = 1;
975 int viewportWidth = 640;
976 int viewportHeight = 480;
978 FrameTestHelpers::WebViewHelper webViewHelper;
979 webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings);
980 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
981 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
982 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
984 // The page must be displayed at 100% zoom.
985 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
988 TEST_F(WebFrameTest, SetLoadWithOverviewModeToFalseAndNoWideViewport)
990 UseMockScrollbarSettings mockScrollbarSettings;
991 registerMockedHttpURLLoad("large-div.html");
993 FixedLayoutTestWebViewClient client;
994 client.m_screenInfo.deviceScaleFactor = 1;
995 int viewportWidth = 640;
996 int viewportHeight = 480;
998 FrameTestHelpers::WebViewHelper webViewHelper;
999 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client, enableViewportSettings);
1000 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1001 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1002 webViewHelper.webView()->settings()->setUseWideViewport(false);
1003 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1005 // The page must be displayed at 100% zoom, despite that it hosts a wide div element.
1006 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
1009 TEST_F(WebFrameTest, NoWideViewportIgnoresPageViewportWidth)
1011 UseMockScrollbarSettings mockScrollbarSettings;
1012 registerMockedHttpURLLoad("viewport-auto-initial-scale.html");
1014 FixedLayoutTestWebViewClient client;
1015 client.m_screenInfo.deviceScaleFactor = 1;
1016 int viewportWidth = 640;
1017 int viewportHeight = 480;
1019 FrameTestHelpers::WebViewHelper webViewHelper;
1020 webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings);
1021 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1022 webViewHelper.webView()->settings()->setUseWideViewport(false);
1023 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1025 // The page sets viewport width to 3000, but with UseWideViewport == false is must be ignored.
1026 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1027 EXPECT_EQ(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
1030 TEST_F(WebFrameTest, NoWideViewportIgnoresPageViewportWidthButAccountsScale)
1032 UseMockScrollbarSettings mockScrollbarSettings;
1033 registerMockedHttpURLLoad("viewport-wide-2x-initial-scale.html");
1035 FixedLayoutTestWebViewClient client;
1036 client.m_screenInfo.deviceScaleFactor = 1;
1037 int viewportWidth = 640;
1038 int viewportHeight = 480;
1040 FrameTestHelpers::WebViewHelper webViewHelper;
1041 webViewHelper.initializeAndLoad(m_baseURL + "viewport-wide-2x-initial-scale.html", true, 0, &client, enableViewportSettings);
1042 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1043 webViewHelper.webView()->settings()->setUseWideViewport(false);
1044 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1046 // The page sets viewport width to 3000, but with UseWideViewport == false it must be ignored.
1047 // While the initial scale specified by the page must be accounted.
1048 EXPECT_EQ(viewportWidth / 2, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1049 EXPECT_EQ(viewportHeight / 2, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
1052 TEST_F(WebFrameTest, WideViewportSetsTo980WithoutViewportTag)
1054 UseMockScrollbarSettings mockScrollbarSettings;
1055 registerMockedHttpURLLoad("no_viewport_tag.html");
1057 FixedLayoutTestWebViewClient client;
1058 client.m_screenInfo.deviceScaleFactor = 1;
1059 int viewportWidth = 640;
1060 int viewportHeight = 480;
1062 FrameTestHelpers::WebViewHelper webViewHelper;
1063 webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client, enableViewportSettings);
1064 applyViewportStyleOverride(&webViewHelper);
1065 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1066 webViewHelper.webView()->settings()->setUseWideViewport(true);
1067 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1069 EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1070 EXPECT_EQ(980.0 / viewportWidth * viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
1073 TEST_F(WebFrameTest, NoWideViewportAndHeightInMeta)
1075 UseMockScrollbarSettings mockScrollbarSettings;
1076 registerMockedHttpURLLoad("viewport-height-1000.html");
1078 FixedLayoutTestWebViewClient client;
1079 client.m_screenInfo.deviceScaleFactor = 1;
1080 int viewportWidth = 640;
1081 int viewportHeight = 480;
1083 FrameTestHelpers::WebViewHelper webViewHelper;
1084 webViewHelper.initializeAndLoad(m_baseURL + "viewport-height-1000.html", true, 0, &client, enableViewportSettings);
1085 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1086 webViewHelper.webView()->settings()->setUseWideViewport(false);
1087 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1089 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1092 TEST_F(WebFrameTest, WideViewportSetsTo980WithAutoWidth)
1094 UseMockScrollbarSettings mockScrollbarSettings;
1095 registerMockedHttpURLLoad("viewport-2x-initial-scale.html");
1097 FixedLayoutTestWebViewClient client;
1098 client.m_screenInfo.deviceScaleFactor = 1;
1099 int viewportWidth = 640;
1100 int viewportHeight = 480;
1102 FrameTestHelpers::WebViewHelper webViewHelper;
1103 webViewHelper.initializeAndLoad(m_baseURL + "viewport-2x-initial-scale.html", true, 0, &client, enableViewportSettings);
1104 applyViewportStyleOverride(&webViewHelper);
1105 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1106 webViewHelper.webView()->settings()->setUseWideViewport(true);
1107 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1109 EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1110 EXPECT_EQ(980.0 / viewportWidth * viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
1113 TEST_F(WebFrameTest, PageViewportInitialScaleOverridesLoadWithOverviewMode)
1115 UseMockScrollbarSettings mockScrollbarSettings;
1116 registerMockedHttpURLLoad("viewport-wide-2x-initial-scale.html");
1118 FixedLayoutTestWebViewClient client;
1119 client.m_screenInfo.deviceScaleFactor = 1;
1120 int viewportWidth = 640;
1121 int viewportHeight = 480;
1123 FrameTestHelpers::WebViewHelper webViewHelper;
1124 webViewHelper.initializeAndLoad(m_baseURL + "viewport-wide-2x-initial-scale.html", true, 0, &client, enableViewportSettings);
1125 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1126 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1128 // The page must be displayed at 200% zoom, as specified in its viewport meta tag.
1129 EXPECT_EQ(2.0f, webViewHelper.webView()->pageScaleFactor());
1132 TEST_F(WebFrameTest, setInitialPageScaleFactorPermanently)
1134 UseMockScrollbarSettings mockScrollbarSettings;
1136 registerMockedHttpURLLoad("fixed_layout.html");
1138 FixedLayoutTestWebViewClient client;
1139 client.m_screenInfo.deviceScaleFactor = 1;
1140 float enforcedPageScaleFactor = 2.0f;
1142 FrameTestHelpers::WebViewHelper webViewHelper;
1143 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1144 applyViewportStyleOverride(&webViewHelper);
1145 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1146 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1147 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1148 webViewHelper.webView()->layout();
1150 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1152 int viewportWidth = 640;
1153 int viewportHeight = 480;
1154 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1155 webViewHelper.webView()->layout();
1157 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1159 webViewHelper.webView()->setInitialPageScaleOverride(-1);
1160 webViewHelper.webView()->layout();
1161 EXPECT_EQ(1.0, webViewHelper.webView()->pageScaleFactor());
1164 TEST_F(WebFrameTest, PermanentInitialPageScaleFactorOverridesLoadWithOverviewMode)
1166 UseMockScrollbarSettings mockScrollbarSettings;
1167 registerMockedHttpURLLoad("viewport-auto-initial-scale.html");
1169 FixedLayoutTestWebViewClient client;
1170 client.m_screenInfo.deviceScaleFactor = 1;
1171 int viewportWidth = 640;
1172 int viewportHeight = 480;
1173 float enforcedPageScaleFactor = 0.5f;
1175 FrameTestHelpers::WebViewHelper webViewHelper;
1176 webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings);
1177 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1178 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1179 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1181 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1184 TEST_F(WebFrameTest, PermanentInitialPageScaleFactorOverridesPageViewportInitialScale)
1186 UseMockScrollbarSettings mockScrollbarSettings;
1187 registerMockedHttpURLLoad("viewport-wide-2x-initial-scale.html");
1189 FixedLayoutTestWebViewClient client;
1190 client.m_screenInfo.deviceScaleFactor = 1;
1191 int viewportWidth = 640;
1192 int viewportHeight = 480;
1193 float enforcedPageScaleFactor = 0.5f;
1195 FrameTestHelpers::WebViewHelper webViewHelper;
1196 webViewHelper.initializeAndLoad(m_baseURL + "viewport-wide-2x-initial-scale.html", true, 0, &client, enableViewportSettings);
1197 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1198 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1200 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1203 TEST_F(WebFrameTest, SmallPermanentInitialPageScaleFactorIsClobbered)
1205 UseMockScrollbarSettings mockScrollbarSettings;
1206 const char* pages[] = {
1207 // These pages trigger the clobbering condition. There must be a matching item in "pageScaleFactors" array.
1208 "viewport-device-0.5x-initial-scale.html",
1209 "viewport-initial-scale-1.html",
1210 // These ones do not.
1211 "viewport-auto-initial-scale.html",
1212 "viewport-target-densitydpi-device-and-fixed-width.html"
1214 float pageScaleFactors[] = { 0.5f, 1.0f };
1215 for (size_t i = 0; i < ARRAY_SIZE(pages); ++i)
1216 registerMockedHttpURLLoad(pages[i]);
1218 FixedLayoutTestWebViewClient client;
1219 client.m_screenInfo.deviceScaleFactor = 1;
1220 int viewportWidth = 400;
1221 int viewportHeight = 300;
1222 float enforcedPageScaleFactor = 0.75f;
1224 for (size_t i = 0; i < ARRAY_SIZE(pages); ++i) {
1225 for (int quirkEnabled = 0; quirkEnabled <= 1; ++quirkEnabled) {
1226 FrameTestHelpers::WebViewHelper webViewHelper;
1227 webViewHelper.initializeAndLoad(m_baseURL + pages[i], true, 0, &client, enableViewportSettings);
1228 applyViewportStyleOverride(&webViewHelper);
1229 webViewHelper.webView()->settings()->setClobberUserAgentInitialScaleQuirk(quirkEnabled);
1230 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1231 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1233 float expectedPageScaleFactor = quirkEnabled && i < ARRAY_SIZE(pageScaleFactors) ? pageScaleFactors[i] : enforcedPageScaleFactor;
1234 EXPECT_EQ(expectedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1239 TEST_F(WebFrameTest, PermanentInitialPageScaleFactorAffectsLayoutWidth)
1241 UseMockScrollbarSettings mockScrollbarSettings;
1243 FixedLayoutTestWebViewClient client;
1244 client.m_screenInfo.deviceScaleFactor = 1;
1245 int viewportWidth = 640;
1246 int viewportHeight = 480;
1247 float enforcedPageScaleFactor = 0.5;
1249 FrameTestHelpers::WebViewHelper webViewHelper;
1250 webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings);
1251 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1252 webViewHelper.webView()->settings()->setUseWideViewport(false);
1253 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1254 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1255 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1257 EXPECT_EQ(viewportWidth / enforcedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1258 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1261 TEST_F(WebFrameTest, SetForceZeroLayoutHeight)
1263 UseMockScrollbarSettings mockScrollbarSettings;
1264 registerMockedHttpURLLoad("200-by-300.html");
1266 FixedLayoutTestWebViewClient client;
1267 client.m_screenInfo.deviceScaleFactor = 1;
1268 int viewportWidth = 640;
1269 int viewportHeight = 480;
1271 FrameTestHelpers::WebViewHelper webViewHelper;
1273 webViewHelper.initializeAndLoad(m_baseURL + "200-by-300.html", true, 0, &client, enableViewportSettings);
1274 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1275 webViewHelper.webView()->layout();
1277 EXPECT_LE(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1278 webViewHelper.webView()->settings()->setForceZeroLayoutHeight(true);
1279 EXPECT_TRUE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
1281 EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1283 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight * 2));
1284 EXPECT_FALSE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
1285 EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1287 webViewHelper.webView()->resize(WebSize(viewportWidth * 2, viewportHeight));
1288 webViewHelper.webView()->layout();
1289 EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1291 webViewHelper.webView()->settings()->setForceZeroLayoutHeight(false);
1292 EXPECT_LE(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1295 TEST_F(WebFrameTest, SetForceZeroLayoutHeightWorksAcrossNavigations)
1297 UseMockScrollbarSettings mockScrollbarSettings;
1298 registerMockedHttpURLLoad("200-by-300.html");
1299 registerMockedHttpURLLoad("large-div.html");
1301 FixedLayoutTestWebViewClient client;
1302 client.m_screenInfo.deviceScaleFactor = 1;
1303 int viewportWidth = 640;
1304 int viewportHeight = 480;
1306 FrameTestHelpers::WebViewHelper webViewHelper;
1308 webViewHelper.initializeAndLoad(m_baseURL + "200-by-300.html", true, 0, &client, enableViewportSettings);
1309 webViewHelper.webView()->settings()->setForceZeroLayoutHeight(true);
1310 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1311 webViewHelper.webView()->layout();
1313 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "large-div.html");
1314 webViewHelper.webView()->layout();
1316 EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1319 TEST_F(WebFrameTest, SetForceZeroLayoutHeightWithWideViewportQuirk)
1321 UseMockScrollbarSettings mockScrollbarSettings;
1322 registerMockedHttpURLLoad("200-by-300.html");
1324 FixedLayoutTestWebViewClient client;
1325 client.m_screenInfo.deviceScaleFactor = 1;
1326 int viewportWidth = 640;
1327 int viewportHeight = 480;
1329 FrameTestHelpers::WebViewHelper webViewHelper;
1331 webViewHelper.initializeAndLoad(m_baseURL + "200-by-300.html", true, 0, &client, enableViewportSettings);
1332 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1333 webViewHelper.webView()->settings()->setUseWideViewport(true);
1334 webViewHelper.webView()->settings()->setForceZeroLayoutHeight(true);
1335 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1336 webViewHelper.webView()->layout();
1338 EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1341 TEST_F(WebFrameTest, WideViewportAndWideContentWithInitialScale)
1343 UseMockScrollbarSettings mockScrollbarSettings;
1344 registerMockedHttpURLLoad("wide_document_width_viewport.html");
1346 FixedLayoutTestWebViewClient client;
1347 client.m_screenInfo.deviceScaleFactor = 1;
1348 int viewportWidth = 600;
1349 int viewportHeight = 800;
1351 FrameTestHelpers::WebViewHelper webViewHelper;
1352 webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings);
1353 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1354 webViewHelper.webView()->settings()->setUseWideViewport(true);
1355 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1356 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1358 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "wide_document_width_viewport.html");
1359 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1361 int wideDocumentWidth = 800;
1362 float minimumPageScaleFactor = viewportWidth / (float) wideDocumentWidth;
1363 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1364 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->minimumPageScaleFactor());
1367 TEST_F(WebFrameTest, WideViewportQuirkClobbersHeight)
1369 UseMockScrollbarSettings mockScrollbarSettings;
1370 registerMockedHttpURLLoad("viewport-height-1000.html");
1372 FixedLayoutTestWebViewClient client;
1373 client.m_screenInfo.deviceScaleFactor = 1;
1374 int viewportWidth = 600;
1375 int viewportHeight = 800;
1377 FrameTestHelpers::WebViewHelper webViewHelper;
1378 webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings);
1379 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1380 webViewHelper.webView()->settings()->setUseWideViewport(false);
1381 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1382 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1384 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport-height-1000.html");
1385 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1387 EXPECT_EQ(800, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1388 EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor());
1391 TEST_F(WebFrameTest, LayoutSize320Quirk)
1393 UseMockScrollbarSettings mockScrollbarSettings;
1394 registerMockedHttpURLLoad("viewport/viewport-30.html");
1396 FixedLayoutTestWebViewClient client;
1397 client.m_screenInfo.deviceScaleFactor = 1;
1398 int viewportWidth = 600;
1399 int viewportHeight = 800;
1401 FrameTestHelpers::WebViewHelper webViewHelper;
1402 webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings);
1403 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1404 webViewHelper.webView()->settings()->setUseWideViewport(true);
1405 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1406 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1408 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport/viewport-30.html");
1409 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1411 EXPECT_EQ(600, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1412 EXPECT_EQ(800, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1413 EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor());
1415 // The magic number to snap to device-width is 320, so test that 321 is
1417 Document* document = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document();
1418 ViewportDescription description = document->viewportDescription();
1419 description.minWidth = Length(321, blink::Fixed);
1420 description.maxWidth = Length(321, blink::Fixed);
1421 document->setViewportDescription(description);
1422 webViewHelper.webView()->layout();
1423 EXPECT_EQ(321, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1425 description.minWidth = Length(320, blink::Fixed);
1426 description.maxWidth = Length(320, blink::Fixed);
1427 document->setViewportDescription(description);
1428 webViewHelper.webView()->layout();
1429 EXPECT_EQ(600, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1431 description = document->viewportDescription();
1432 description.maxHeight = Length(1000, blink::Fixed);
1433 document->setViewportDescription(description);
1434 webViewHelper.webView()->layout();
1435 EXPECT_EQ(1000, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1437 description.maxHeight = Length(320, blink::Fixed);
1438 document->setViewportDescription(description);
1439 webViewHelper.webView()->layout();
1440 EXPECT_EQ(800, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1443 TEST_F(WebFrameTest, ZeroValuesQuirk)
1445 UseMockScrollbarSettings mockScrollbarSettings;
1446 registerMockedHttpURLLoad("viewport-zero-values.html");
1448 FixedLayoutTestWebViewClient client;
1449 client.m_screenInfo.deviceScaleFactor = 1;
1450 int viewportWidth = 640;
1451 int viewportHeight = 480;
1453 FrameTestHelpers::WebViewHelper webViewHelper;
1454 webViewHelper.initialize(true, 0, &client, enableViewportSettings);
1455 webViewHelper.webView()->settings()->setViewportMetaZeroValuesQuirk(true);
1456 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1457 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1458 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport-zero-values.html");
1459 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1461 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1462 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
1464 webViewHelper.webView()->settings()->setUseWideViewport(true);
1465 webViewHelper.webView()->layout();
1466 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1467 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
1470 TEST_F(WebFrameTest, OverflowHiddenDisablesScrolling)
1472 registerMockedHttpURLLoad("body-overflow-hidden.html");
1474 FixedLayoutTestWebViewClient client;
1475 client.m_screenInfo.deviceScaleFactor = 1;
1476 int viewportWidth = 640;
1477 int viewportHeight = 480;
1479 FrameTestHelpers::WebViewHelper webViewHelper;
1480 webViewHelper.initialize(true, 0, &client);
1481 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "body-overflow-hidden.html");
1482 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1484 FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
1485 EXPECT_FALSE(view->userInputScrollable(VerticalScrollbar));
1488 TEST_F(WebFrameTest, IgnoreOverflowHiddenQuirk)
1490 registerMockedHttpURLLoad("body-overflow-hidden.html");
1492 FixedLayoutTestWebViewClient client;
1493 client.m_screenInfo.deviceScaleFactor = 1;
1494 int viewportWidth = 640;
1495 int viewportHeight = 480;
1497 FrameTestHelpers::WebViewHelper webViewHelper;
1498 webViewHelper.initialize(true, 0, &client);
1499 webViewHelper.webView()->settings()->setIgnoreMainFrameOverflowHiddenQuirk(true);
1500 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "body-overflow-hidden.html");
1501 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1503 FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
1504 EXPECT_TRUE(view->userInputScrollable(VerticalScrollbar));
1507 TEST_F(WebFrameTest, NonZeroValuesNoQuirk)
1509 UseMockScrollbarSettings mockScrollbarSettings;
1510 registerMockedHttpURLLoad("viewport-nonzero-values.html");
1512 FixedLayoutTestWebViewClient client;
1513 client.m_screenInfo.deviceScaleFactor = 1;
1514 int viewportWidth = 640;
1515 int viewportHeight = 480;
1516 float expectedPageScaleFactor = 0.5f;
1518 FrameTestHelpers::WebViewHelper webViewHelper;
1519 webViewHelper.initialize(true, 0, &client, enableViewportSettings);
1520 webViewHelper.webView()->settings()->setViewportMetaZeroValuesQuirk(true);
1521 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1522 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport-nonzero-values.html");
1523 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1525 EXPECT_EQ(viewportWidth / expectedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1526 EXPECT_EQ(expectedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1528 webViewHelper.webView()->settings()->setUseWideViewport(true);
1529 webViewHelper.webView()->layout();
1530 EXPECT_EQ(viewportWidth / expectedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1531 EXPECT_EQ(expectedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1534 TEST_F(WebFrameTest, setPageScaleFactorDoesNotLayout)
1536 UseMockScrollbarSettings mockScrollbarSettings;
1537 registerMockedHttpURLLoad("fixed_layout.html");
1539 FixedLayoutTestWebViewClient client;
1540 client.m_screenInfo.deviceScaleFactor = 1;
1541 // Small viewport to ensure there are always scrollbars.
1542 int viewportWidth = 64;
1543 int viewportHeight = 48;
1545 FrameTestHelpers::WebViewHelper webViewHelper;
1546 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1547 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1548 webViewHelper.webView()->layout();
1550 int prevLayoutCount = webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount();
1551 webViewHelper.webViewImpl()->setPageScaleFactor(3);
1552 EXPECT_FALSE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
1553 EXPECT_EQ(prevLayoutCount, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount());
1556 TEST_F(WebFrameTest, setPageScaleFactorWithOverlayScrollbarsDoesNotLayout)
1558 UseMockScrollbarSettings mockScrollbarSettings;
1560 registerMockedHttpURLLoad("fixed_layout.html");
1562 FixedLayoutTestWebViewClient client;
1563 client.m_screenInfo.deviceScaleFactor = 1;
1564 int viewportWidth = 640;
1565 int viewportHeight = 480;
1567 FrameTestHelpers::WebViewHelper webViewHelper;
1568 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1569 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1570 webViewHelper.webView()->layout();
1572 int prevLayoutCount = webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount();
1573 webViewHelper.webViewImpl()->setPageScaleFactor(30);
1574 EXPECT_FALSE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
1575 EXPECT_EQ(prevLayoutCount, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount());
1579 TEST_F(WebFrameTest, pageScaleFactorWrittenToHistoryItem)
1581 UseMockScrollbarSettings mockScrollbarSettings;
1582 registerMockedHttpURLLoad("fixed_layout.html");
1584 FixedLayoutTestWebViewClient client;
1585 client.m_screenInfo.deviceScaleFactor = 1;
1586 int viewportWidth = 640;
1587 int viewportHeight = 480;
1589 FrameTestHelpers::WebViewHelper webViewHelper;
1590 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1591 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1592 webViewHelper.webView()->layout();
1594 webViewHelper.webView()->setPageScaleFactor(3);
1595 EXPECT_EQ(3, toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->loader().currentItem()->pageScaleFactor());
1598 TEST_F(WebFrameTest, initialScaleWrittenToHistoryItem)
1600 UseMockScrollbarSettings mockScrollbarSettings;
1601 registerMockedHttpURLLoad("fixed_layout.html");
1603 FixedLayoutTestWebViewClient client;
1604 client.m_screenInfo.deviceScaleFactor = 1;
1605 int viewportWidth = 640;
1606 int viewportHeight = 480;
1608 FrameTestHelpers::WebViewHelper webViewHelper;
1609 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1610 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1611 webViewHelper.webView()->layout();
1613 int defaultFixedLayoutWidth = 980;
1614 float minimumPageScaleFactor = viewportWidth / (float) defaultFixedLayoutWidth;
1615 EXPECT_EQ(minimumPageScaleFactor, toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->loader().currentItem()->pageScaleFactor());
1618 TEST_F(WebFrameTest, pageScaleFactorShrinksViewport)
1620 UseMockScrollbarSettings mockScrollbarSettings;
1621 registerMockedHttpURLLoad("large-div.html");
1623 FixedLayoutTestWebViewClient client;
1624 client.m_screenInfo.deviceScaleFactor = 1;
1625 // Small viewport to ensure there are always scrollbars.
1626 int viewportWidth = 64;
1627 int viewportHeight = 48;
1629 FrameTestHelpers::WebViewHelper webViewHelper;
1630 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client, enableViewportSettings);
1631 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1632 webViewHelper.webView()->layout();
1634 FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
1635 int viewportWidthMinusScrollbar = viewportWidth - (view->verticalScrollbar()->isOverlayScrollbar() ? 0 : 15);
1636 int viewportHeightMinusScrollbar = viewportHeight - (view->horizontalScrollbar()->isOverlayScrollbar() ? 0 : 15);
1638 webViewHelper.webView()->setPageScaleFactor(2);
1640 IntSize unscaledSize = view->unscaledVisibleContentSize(IncludeScrollbars);
1641 EXPECT_EQ(viewportWidth, unscaledSize.width());
1642 EXPECT_EQ(viewportHeight, unscaledSize.height());
1644 IntSize unscaledSizeMinusScrollbar = view->unscaledVisibleContentSize(ExcludeScrollbars);
1645 EXPECT_EQ(viewportWidthMinusScrollbar, unscaledSizeMinusScrollbar.width());
1646 EXPECT_EQ(viewportHeightMinusScrollbar, unscaledSizeMinusScrollbar.height());
1648 IntSize scaledSize = view->visibleContentRect().size();
1649 EXPECT_EQ(ceil(viewportWidthMinusScrollbar / 2.0), scaledSize.width());
1650 EXPECT_EQ(ceil(viewportHeightMinusScrollbar / 2.0), scaledSize.height());
1653 TEST_F(WebFrameTest, pageScaleFactorDoesNotApplyCssTransform)
1655 UseMockScrollbarSettings mockScrollbarSettings;
1656 registerMockedHttpURLLoad("fixed_layout.html");
1658 FixedLayoutTestWebViewClient client;
1659 client.m_screenInfo.deviceScaleFactor = 1;
1660 int viewportWidth = 640;
1661 int viewportHeight = 480;
1663 FrameTestHelpers::WebViewHelper webViewHelper;
1664 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1665 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1666 webViewHelper.webView()->layout();
1668 webViewHelper.webView()->setPageScaleFactor(2);
1670 EXPECT_EQ(980, toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->contentRenderer()->unscaledDocumentRect().width());
1671 EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1674 TEST_F(WebFrameTest, targetDensityDpiHigh)
1676 UseMockScrollbarSettings mockScrollbarSettings;
1677 registerMockedHttpURLLoad("viewport-target-densitydpi-high.html");
1679 FixedLayoutTestWebViewClient client;
1681 float targetDpi = 240.0f;
1682 float deviceScaleFactors[] = { 1.0f, 4.0f / 3.0f, 2.0f };
1683 int viewportWidth = 640;
1684 int viewportHeight = 480;
1686 for (size_t i = 0; i < ARRAY_SIZE(deviceScaleFactors); ++i) {
1687 float deviceScaleFactor = deviceScaleFactors[i];
1688 float deviceDpi = deviceScaleFactor * 160.0f;
1689 client.m_screenInfo.deviceScaleFactor = deviceScaleFactor;
1691 FrameTestHelpers::WebViewHelper webViewHelper;
1692 webViewHelper.initializeAndLoad(m_baseURL + "viewport-target-densitydpi-high.html", true, 0, &client, enableViewportSettings);
1693 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1694 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1695 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1697 // We need to account for the fact that logical pixels are unconditionally multiplied by deviceScaleFactor to produce
1699 float densityDpiScaleRatio = deviceScaleFactor * targetDpi / deviceDpi;
1700 EXPECT_NEAR(viewportWidth * densityDpiScaleRatio, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1701 EXPECT_NEAR(viewportHeight * densityDpiScaleRatio, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1702 EXPECT_NEAR(1.0f / densityDpiScaleRatio, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1706 TEST_F(WebFrameTest, targetDensityDpiDevice)
1708 UseMockScrollbarSettings mockScrollbarSettings;
1709 registerMockedHttpURLLoad("viewport-target-densitydpi-device.html");
1711 float deviceScaleFactors[] = { 1.0f, 4.0f / 3.0f, 2.0f };
1713 FixedLayoutTestWebViewClient client;
1714 int viewportWidth = 640;
1715 int viewportHeight = 480;
1717 for (size_t i = 0; i < ARRAY_SIZE(deviceScaleFactors); ++i) {
1718 client.m_screenInfo.deviceScaleFactor = deviceScaleFactors[i];
1720 FrameTestHelpers::WebViewHelper webViewHelper;
1721 webViewHelper.initializeAndLoad(m_baseURL + "viewport-target-densitydpi-device.html", true, 0, &client, enableViewportSettings);
1722 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1723 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1724 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1726 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1727 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1728 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1732 TEST_F(WebFrameTest, targetDensityDpiDeviceAndFixedWidth)
1734 UseMockScrollbarSettings mockScrollbarSettings;
1735 registerMockedHttpURLLoad("viewport-target-densitydpi-device-and-fixed-width.html");
1737 float deviceScaleFactors[] = { 1.0f, 4.0f / 3.0f, 2.0f };
1739 FixedLayoutTestWebViewClient client;
1740 int viewportWidth = 640;
1741 int viewportHeight = 480;
1743 for (size_t i = 0; i < ARRAY_SIZE(deviceScaleFactors); ++i) {
1744 client.m_screenInfo.deviceScaleFactor = deviceScaleFactors[i];
1746 FrameTestHelpers::WebViewHelper webViewHelper;
1747 webViewHelper.initializeAndLoad(m_baseURL + "viewport-target-densitydpi-device-and-fixed-width.html", true, 0, &client, enableViewportSettings);
1748 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1749 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1750 webViewHelper.webView()->settings()->setUseWideViewport(true);
1751 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1753 EXPECT_NEAR(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1754 EXPECT_NEAR(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1755 EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1759 TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOne)
1761 UseMockScrollbarSettings mockScrollbarSettings;
1762 registerMockedHttpURLLoad("viewport-initial-scale-less-than-1.html");
1764 FixedLayoutTestWebViewClient client;
1765 client.m_screenInfo.deviceScaleFactor = 1.33f;
1766 int viewportWidth = 640;
1767 int viewportHeight = 480;
1769 FrameTestHelpers::WebViewHelper webViewHelper;
1770 webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-less-than-1.html", true, 0, &client, enableViewportSettings);
1771 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1772 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1773 webViewHelper.webView()->settings()->setUseWideViewport(false);
1774 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1775 webViewHelper.webView()->layout();
1777 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1778 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1779 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1782 TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOneWithDeviceWidth)
1784 UseMockScrollbarSettings mockScrollbarSettings;
1785 registerMockedHttpURLLoad("viewport-initial-scale-less-than-1-device-width.html");
1787 FixedLayoutTestWebViewClient client;
1788 client.m_screenInfo.deviceScaleFactor = 1.33f;
1789 int viewportWidth = 640;
1790 int viewportHeight = 480;
1792 FrameTestHelpers::WebViewHelper webViewHelper;
1793 webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-less-than-1-device-width.html", true, 0, &client, enableViewportSettings);
1794 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1795 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1796 webViewHelper.webView()->settings()->setUseWideViewport(false);
1797 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1798 webViewHelper.webView()->layout();
1800 const float pageZoom = 0.25f;
1801 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor / pageZoom, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1802 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor / pageZoom, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1803 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1806 TEST_F(WebFrameTest, NoWideViewportAndNoViewportWithInitialPageScaleOverride)
1808 UseMockScrollbarSettings mockScrollbarSettings;
1809 registerMockedHttpURLLoad("large-div.html");
1811 FixedLayoutTestWebViewClient client;
1812 int viewportWidth = 640;
1813 int viewportHeight = 480;
1814 float enforcedPageScaleFactor = 5.0f;
1816 FrameTestHelpers::WebViewHelper webViewHelper;
1817 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client, enableViewportSettings);
1818 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1819 webViewHelper.webView()->settings()->setUseWideViewport(false);
1820 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1821 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1822 webViewHelper.webView()->layout();
1824 EXPECT_NEAR(viewportWidth / enforcedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1825 EXPECT_NEAR(viewportHeight / enforcedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1826 EXPECT_NEAR(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1829 TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScale)
1831 UseMockScrollbarSettings mockScrollbarSettings;
1832 registerMockedHttpURLLoad("viewport-initial-scale-and-user-scalable-no.html");
1834 FixedLayoutTestWebViewClient client;
1835 int viewportWidth = 640;
1836 int viewportHeight = 480;
1838 FrameTestHelpers::WebViewHelper webViewHelper;
1839 webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-and-user-scalable-no.html", true, 0, &client, enableViewportSettings);
1840 webViewHelper.webView()->settings()->setViewportMetaNonUserScalableQuirk(true);
1841 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1842 webViewHelper.webView()->layout();
1844 EXPECT_NEAR(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1845 EXPECT_NEAR(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1846 EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1849 TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScaleForNonWideViewport)
1851 UseMockScrollbarSettings mockScrollbarSettings;
1852 registerMockedHttpURLLoad("viewport-initial-scale-and-user-scalable-no.html");
1854 FixedLayoutTestWebViewClient client;
1855 client.m_screenInfo.deviceScaleFactor = 1.33f;
1856 int viewportWidth = 640;
1857 int viewportHeight = 480;
1859 FrameTestHelpers::WebViewHelper webViewHelper;
1860 webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-and-user-scalable-no.html", true, 0, &client, enableViewportSettings);
1861 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1862 webViewHelper.webView()->settings()->setViewportMetaNonUserScalableQuirk(true);
1863 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1864 webViewHelper.webView()->settings()->setUseWideViewport(false);
1865 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1866 webViewHelper.webView()->layout();
1868 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1869 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1870 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1873 TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScaleForWideViewport)
1875 UseMockScrollbarSettings mockScrollbarSettings;
1876 registerMockedHttpURLLoad("viewport-2x-initial-scale-non-user-scalable.html");
1878 FixedLayoutTestWebViewClient client;
1879 int viewportWidth = 640;
1880 int viewportHeight = 480;
1882 FrameTestHelpers::WebViewHelper webViewHelper;
1883 webViewHelper.initializeAndLoad(m_baseURL + "viewport-2x-initial-scale-non-user-scalable.html", true, 0, &client, enableViewportSettings);
1884 webViewHelper.webView()->settings()->setViewportMetaNonUserScalableQuirk(true);
1885 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1886 webViewHelper.webView()->settings()->setUseWideViewport(true);
1887 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1889 EXPECT_NEAR(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1890 EXPECT_NEAR(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1891 EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1894 TEST_F(WebFrameTest, DesktopPageCanBeZoomedInWhenWideViewportIsTurnedOff)
1896 UseMockScrollbarSettings mockScrollbarSettings;
1897 registerMockedHttpURLLoad("no_viewport_tag.html");
1899 FixedLayoutTestWebViewClient client;
1900 int viewportWidth = 640;
1901 int viewportHeight = 480;
1903 FrameTestHelpers::WebViewHelper webViewHelper;
1904 webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client, enableViewportSettings);
1905 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1906 webViewHelper.webView()->settings()->setUseWideViewport(false);
1907 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1909 EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1910 EXPECT_NEAR(1.0f, webViewHelper.webView()->minimumPageScaleFactor(), 0.01f);
1911 EXPECT_NEAR(5.0f, webViewHelper.webView()->maximumPageScaleFactor(), 0.01f);
1914 class WebFrameResizeTest : public WebFrameTest {
1917 static FloatSize computeRelativeOffset(const IntPoint& absoluteOffset, const LayoutRect& rect)
1919 FloatSize relativeOffset = FloatPoint(absoluteOffset) - rect.location();
1920 relativeOffset.scale(1.f / rect.width(), 1.f / rect.height());
1921 return relativeOffset;
1924 void testResizeYieldsCorrectScrollAndScale(const char* url,
1925 const float initialPageScaleFactor,
1926 const WebSize scrollOffset,
1927 const WebSize viewportSize,
1928 const bool shouldScaleRelativeToViewportWidth) {
1929 UseMockScrollbarSettings mockScrollbarSettings;
1930 registerMockedHttpURLLoad(url);
1932 const float aspectRatio = static_cast<float>(viewportSize.width) / viewportSize.height;
1934 FrameTestHelpers::WebViewHelper webViewHelper;
1935 webViewHelper.initializeAndLoad(m_baseURL + url, true, 0, 0, enableViewportSettings);
1937 // Origin scrollOffsets preserved under resize.
1939 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height));
1940 webViewHelper.webViewImpl()->setPageScaleFactor(initialPageScaleFactor);
1941 ASSERT_EQ(viewportSize, webViewHelper.webViewImpl()->size());
1942 ASSERT_EQ(initialPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor());
1943 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.height, viewportSize.width));
1944 float expectedPageScaleFactor = initialPageScaleFactor * (shouldScaleRelativeToViewportWidth ? 1 / aspectRatio : 1);
1945 EXPECT_NEAR(expectedPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor(), 0.05f);
1946 EXPECT_EQ(WebSize(), webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
1949 // Resizing just the height should not affect pageScaleFactor or scrollOffset.
1951 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height));
1952 webViewHelper.webViewImpl()->setPageScaleFactor(initialPageScaleFactor);
1953 webViewHelper.webViewImpl()->setMainFrameScrollOffset(WebPoint(scrollOffset.width, scrollOffset.height));
1954 webViewHelper.webViewImpl()->layout();
1955 const WebSize expectedScrollOffset = webViewHelper.webViewImpl()->mainFrame()->scrollOffset();
1956 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height * 0.8f));
1957 EXPECT_EQ(initialPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor());
1958 EXPECT_EQ(expectedScrollOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
1959 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height * 0.8f));
1960 EXPECT_EQ(initialPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor());
1961 EXPECT_EQ(expectedScrollOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
1964 // Generic resize preserves scrollOffset relative to anchor node located
1965 // the top center of the screen.
1967 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.height, viewportSize.width));
1968 float pageScaleFactor = webViewHelper.webViewImpl()->pageScaleFactor();
1969 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height));
1970 float expectedPageScaleFactor = pageScaleFactor * (shouldScaleRelativeToViewportWidth ? aspectRatio : 1);
1971 EXPECT_NEAR(expectedPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor(), 0.05f);
1972 webViewHelper.webViewImpl()->mainFrame()->setScrollOffset(scrollOffset);
1974 IntPoint anchorPoint = IntPoint(scrollOffset) + IntPoint(viewportSize.width / 2, 0);
1975 RefPtrWillBeRawPtr<Node> anchorNode = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->eventHandler().hitTestResultAtPoint(anchorPoint, HitTestRequest::ReadOnly | HitTestRequest::Active).innerNode();
1978 pageScaleFactor = webViewHelper.webViewImpl()->pageScaleFactor();
1979 const FloatSize preResizeRelativeOffset
1980 = computeRelativeOffset(anchorPoint, anchorNode->boundingBox());
1981 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.height, viewportSize.width));
1982 IntPoint newAnchorPoint = IntPoint(webViewHelper.webViewImpl()->mainFrame()->scrollOffset()) + IntPoint(viewportSize.height / 2, 0);
1983 const FloatSize postResizeRelativeOffset
1984 = computeRelativeOffset(newAnchorPoint, anchorNode->boundingBox());
1985 EXPECT_NEAR(preResizeRelativeOffset.width(), postResizeRelativeOffset.width(), 0.15f);
1986 expectedPageScaleFactor = pageScaleFactor * (shouldScaleRelativeToViewportWidth ? 1 / aspectRatio : 1);
1987 EXPECT_NEAR(expectedPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor(), 0.05f);
1992 TEST_F(WebFrameResizeTest, ResizeYieldsCorrectScrollAndScaleForWidthEqualsDeviceWidth)
1994 // With width=device-width, pageScaleFactor is preserved across resizes as
1995 // long as the content adjusts according to the device-width.
1996 const char* url = "resize_scroll_mobile.html";
1997 const float initialPageScaleFactor = 1;
1998 const WebSize scrollOffset(0, 50);
1999 const WebSize viewportSize(120, 160);
2000 const bool shouldScaleRelativeToViewportWidth = true;
2002 testResizeYieldsCorrectScrollAndScale(
2003 url, initialPageScaleFactor, scrollOffset, viewportSize, shouldScaleRelativeToViewportWidth);
2006 TEST_F(WebFrameResizeTest, ResizeYieldsCorrectScrollAndScaleForMinimumScale)
2008 // This tests a scenario where minimum-scale is set to 1.0, but some element
2009 // on the page is slightly larger than the portrait width, so our "natural"
2010 // minimum-scale would be lower. In that case, we should stick to 1.0 scale
2011 // on rotation and not do anything strange.
2012 const char* url = "resize_scroll_minimum_scale.html";
2013 const float initialPageScaleFactor = 1;
2014 const WebSize scrollOffset(0, 0);
2015 const WebSize viewportSize(240, 320);
2016 const bool shouldScaleRelativeToViewportWidth = false;
2018 testResizeYieldsCorrectScrollAndScale(
2019 url, initialPageScaleFactor, scrollOffset, viewportSize, shouldScaleRelativeToViewportWidth);
2022 TEST_F(WebFrameResizeTest, ResizeYieldsCorrectScrollAndScaleForFixedWidth)
2024 // With a fixed width, pageScaleFactor scales by the relative change in viewport width.
2025 const char* url = "resize_scroll_fixed_width.html";
2026 const float initialPageScaleFactor = 2;
2027 const WebSize scrollOffset(0, 200);
2028 const WebSize viewportSize(240, 320);
2029 const bool shouldScaleRelativeToViewportWidth = true;
2031 testResizeYieldsCorrectScrollAndScale(
2032 url, initialPageScaleFactor, scrollOffset, viewportSize, shouldScaleRelativeToViewportWidth);
2035 TEST_F(WebFrameResizeTest, ResizeYieldsCorrectScrollAndScaleForFixedLayout)
2037 // With a fixed layout, pageScaleFactor scales by the relative change in viewport width.
2038 const char* url = "resize_scroll_fixed_layout.html";
2039 const float initialPageScaleFactor = 2;
2040 const WebSize scrollOffset(200, 400);
2041 const WebSize viewportSize(320, 240);
2042 const bool shouldScaleRelativeToViewportWidth = true;
2044 testResizeYieldsCorrectScrollAndScale(
2045 url, initialPageScaleFactor, scrollOffset, viewportSize, shouldScaleRelativeToViewportWidth);
2048 TEST_F(WebFrameTest, pageScaleFactorScalesPaintClip)
2050 UseMockScrollbarSettings mockScrollbarSettings;
2051 registerMockedHttpURLLoad("large-div.html");
2053 FixedLayoutTestWebViewClient client;
2054 client.m_screenInfo.deviceScaleFactor = 1;
2055 int viewportWidth = 50;
2056 int viewportHeight = 50;
2058 FrameTestHelpers::WebViewHelper webViewHelper;
2059 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client);
2060 // FIXME: This test breaks if the viewport is enabled before loading the page due to the paint
2061 // calls below not working on composited layers. For some reason, enabling the viewport here
2062 // doesn't cause compositing
2063 webViewHelper.webView()->settings()->setViewportEnabled(true);
2064 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2065 webViewHelper.webView()->layout();
2067 // Set <1 page scale so that the clip rect should be larger than
2068 // the viewport size as passed into resize().
2069 webViewHelper.webView()->setPageScaleFactor(0.5);
2072 bitmap.allocN32Pixels(200, 200);
2073 bitmap.eraseColor(0);
2074 SkCanvas canvas(bitmap);
2076 GraphicsContext context(&canvas);
2077 context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
2079 EXPECT_RECT_EQ(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
2081 FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
2082 IntRect paintRect(0, 0, 200, 200);
2083 view->paint(&context, paintRect);
2085 // FIXME: This test broke in release builds when changing the FixedLayoutTestWebViewClient
2086 // to return a non-null layerTreeView, which is what all our shipping configurations do,
2087 // so this is just exposing an existing bug.
2090 int viewportWidthMinusScrollbar = 50 - (view->verticalScrollbar()->isOverlayScrollbar() ? 0 : 15);
2091 int viewportHeightMinusScrollbar = 50 - (view->horizontalScrollbar()->isOverlayScrollbar() ? 0 : 15);
2092 IntRect clippedRect(0, 0, viewportWidthMinusScrollbar * 2, viewportHeightMinusScrollbar * 2);
2093 EXPECT_RECT_EQ(clippedRect, context.opaqueRegion().asRect());
2097 TEST_F(WebFrameTest, pageScaleFactorUpdatesScrollbars)
2099 UseMockScrollbarSettings mockScrollbarSettings;
2100 registerMockedHttpURLLoad("fixed_layout.html");
2102 FixedLayoutTestWebViewClient client;
2103 client.m_screenInfo.deviceScaleFactor = 1;
2104 int viewportWidth = 640;
2105 int viewportHeight = 480;
2107 FrameTestHelpers::WebViewHelper webViewHelper;
2108 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
2109 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2110 webViewHelper.webView()->layout();
2112 FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
2113 EXPECT_EQ(view->scrollSize(HorizontalScrollbar), view->contentsSize().width() - view->visibleContentRect().width());
2114 EXPECT_EQ(view->scrollSize(VerticalScrollbar), view->contentsSize().height() - view->visibleContentRect().height());
2116 webViewHelper.webView()->setPageScaleFactor(10);
2118 EXPECT_EQ(view->scrollSize(HorizontalScrollbar), view->contentsSize().width() - view->visibleContentRect().width());
2119 EXPECT_EQ(view->scrollSize(VerticalScrollbar), view->contentsSize().height() - view->visibleContentRect().height());
2122 TEST_F(WebFrameTest, CanOverrideScaleLimits)
2124 UseMockScrollbarSettings mockScrollbarSettings;
2126 registerMockedHttpURLLoad("no_scale_for_you.html");
2128 FixedLayoutTestWebViewClient client;
2129 client.m_screenInfo.deviceScaleFactor = 1;
2130 int viewportWidth = 640;
2131 int viewportHeight = 480;
2133 FrameTestHelpers::WebViewHelper webViewHelper;
2134 webViewHelper.initializeAndLoad(m_baseURL + "no_scale_for_you.html", true, 0, &client, enableViewportSettings);
2135 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2137 EXPECT_EQ(2.0f, webViewHelper.webView()->minimumPageScaleFactor());
2138 EXPECT_EQ(2.0f, webViewHelper.webView()->maximumPageScaleFactor());
2140 webViewHelper.webView()->setIgnoreViewportTagScaleLimits(true);
2141 webViewHelper.webView()->layout();
2143 EXPECT_EQ(1.0f, webViewHelper.webView()->minimumPageScaleFactor());
2144 EXPECT_EQ(5.0f, webViewHelper.webView()->maximumPageScaleFactor());
2146 webViewHelper.webView()->setIgnoreViewportTagScaleLimits(false);
2147 webViewHelper.webView()->layout();
2149 EXPECT_EQ(2.0f, webViewHelper.webView()->minimumPageScaleFactor());
2150 EXPECT_EQ(2.0f, webViewHelper.webView()->maximumPageScaleFactor());
2153 TEST_F(WebFrameTest, updateOverlayScrollbarLayers)
2155 UseMockScrollbarSettings mockScrollbarSettings;
2157 registerMockedHttpURLLoad("large-div.html");
2159 int viewWidth = 500;
2160 int viewHeight = 500;
2162 OwnPtr<FakeCompositingWebViewClient> fakeCompositingWebViewClient = adoptPtr(new FakeCompositingWebViewClient());
2163 FrameTestHelpers::WebViewHelper webViewHelper;
2164 webViewHelper.initialize(true, 0, fakeCompositingWebViewClient.get(), &configueCompositingWebView);
2166 webViewHelper.webView()->setPageScaleFactorLimits(1, 1);
2167 webViewHelper.webView()->resize(WebSize(viewWidth, viewHeight));
2168 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "large-div.html");
2170 FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
2171 EXPECT_TRUE(view->renderView()->compositor()->layerForHorizontalScrollbar());
2172 EXPECT_TRUE(view->renderView()->compositor()->layerForVerticalScrollbar());
2174 webViewHelper.webView()->resize(WebSize(viewWidth * 10, viewHeight * 10));
2175 webViewHelper.webView()->layout();
2176 EXPECT_FALSE(view->renderView()->compositor()->layerForHorizontalScrollbar());
2177 EXPECT_FALSE(view->renderView()->compositor()->layerForVerticalScrollbar());
2180 void setScaleAndScrollAndLayout(WebView* webView, WebPoint scroll, float scale)
2182 webView->setPageScaleFactor(scale);
2183 webView->setMainFrameScrollOffset(WebPoint(scroll.x, scroll.y));
2187 void simulatePageScale(WebViewImpl* webViewImpl, float& scale)
2189 IntSize scrollDelta = webViewImpl->fakePageScaleAnimationTargetPositionForTesting() - webViewImpl->mainFrameImpl()->frameView()->scrollPosition();
2190 float scaleDelta = webViewImpl->fakePageScaleAnimationPageScaleForTesting() / webViewImpl->pageScaleFactor();
2191 webViewImpl->applyViewportDeltas(scrollDelta, scaleDelta, 0);
2192 scale = webViewImpl->pageScaleFactor();
2195 void simulateMultiTargetZoom(WebViewImpl* webViewImpl, const WebRect& rect, float& scale)
2197 if (webViewImpl->zoomToMultipleTargetsRect(rect))
2198 simulatePageScale(webViewImpl, scale);
2201 void simulateDoubleTap(WebViewImpl* webViewImpl, WebPoint& point, float& scale)
2203 webViewImpl->animateDoubleTapZoom(point);
2204 EXPECT_TRUE(webViewImpl->fakeDoubleTapAnimationPendingForTesting());
2205 simulatePageScale(webViewImpl, scale);
2210 TEST_F(WebFrameTest, DivAutoZoomParamsTest_VirtualViewport)
2212 registerMockedHttpURLLoad("get_scale_for_auto_zoom_into_div_test.html");
2214 const float deviceScaleFactor = 2.0f;
2215 int viewportWidth = 640 / deviceScaleFactor;
2216 int viewportHeight = 1280 / deviceScaleFactor;
2217 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2218 FrameTestHelpers::WebViewHelper webViewHelper;
2219 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_for_auto_zoom_into_div_test.html", false, 0, 0, configurePinchVirtualViewport);
2220 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2221 webViewHelper.webView()->setPageScaleFactorLimits(0.01f, 4);
2222 webViewHelper.webView()->setPageScaleFactor(0.5f);
2223 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2224 webViewHelper.webView()->layout();
2226 WebRect wideDiv(200, 100, 400, 150);
2227 WebRect tallDiv(200, 300, 400, 800);
2228 WebRect doubleTapPointWide(wideDiv.x + 50, wideDiv.y + 50, touchPointPadding, touchPointPadding);
2229 WebRect doubleTapPointTall(tallDiv.x + 50, tallDiv.y + 50, touchPointPadding, touchPointPadding);
2230 WebRect wideBlockBounds;
2231 WebRect tallBlockBounds;
2235 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2237 // Test double-tap zooming into wide div.
2238 wideBlockBounds = webViewHelper.webViewImpl()->computeBlockBounds(doubleTapPointWide, false);
2239 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(doubleTapPointWide.x, doubleTapPointWide.y), wideBlockBounds, touchPointPadding, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2240 // The div should horizontally fill the screen (modulo margins), and
2241 // vertically centered (modulo integer rounding).
2242 EXPECT_NEAR(viewportWidth / (float) wideDiv.width, scale, 0.1);
2243 EXPECT_NEAR(wideDiv.x, scroll.x, 20);
2244 EXPECT_EQ(0, scroll.y);
2246 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), scroll, scale);
2248 // Test zoom out back to minimum scale.
2249 wideBlockBounds = webViewHelper.webViewImpl()->computeBlockBounds(doubleTapPointWide, false);
2250 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(doubleTapPointWide.x, doubleTapPointWide.y), wideBlockBounds, touchPointPadding, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2252 scale = webViewHelper.webViewImpl()->minimumPageScaleFactor();
2253 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), scale);
2255 // Test double-tap zooming into tall div.
2256 tallBlockBounds = webViewHelper.webViewImpl()->computeBlockBounds(doubleTapPointTall, false);
2257 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(doubleTapPointTall.x, doubleTapPointTall.y), tallBlockBounds, touchPointPadding, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2258 // The div should start at the top left of the viewport.
2259 EXPECT_NEAR(viewportWidth / (float) tallDiv.width, scale, 0.1);
2260 EXPECT_NEAR(tallDiv.x, scroll.x, 20);
2261 EXPECT_NEAR(tallDiv.y, scroll.y, 20);
2263 // Test for Non-doubletap scaling
2264 // Test zooming into div.
2265 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(250, 250), webViewHelper.webViewImpl()->computeBlockBounds(WebRect(250, 250, 10, 10), true), 0, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2266 EXPECT_NEAR(viewportWidth / (float) wideDiv.width, scale, 0.1);
2269 TEST_F(WebFrameTest, DivAutoZoomWideDivTest_VirtualViewport)
2271 registerMockedHttpURLLoad("get_wide_div_for_auto_zoom_test.html");
2273 const float deviceScaleFactor = 2.0f;
2274 int viewportWidth = 640 / deviceScaleFactor;
2275 int viewportHeight = 1280 / deviceScaleFactor;
2276 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2277 FrameTestHelpers::WebViewHelper webViewHelper;
2278 webViewHelper.initializeAndLoad(m_baseURL + "get_wide_div_for_auto_zoom_test.html", false, 0, 0, configurePinchVirtualViewport);
2279 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2280 webViewHelper.webView()->setPageScaleFactorLimits(1.0f, 4);
2281 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2282 webViewHelper.webView()->setPageScaleFactor(1.0f);
2283 webViewHelper.webView()->layout();
2285 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2287 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2289 WebRect div(0, 100, viewportWidth, 150);
2290 WebPoint point(div.x + 50, div.y + 50);
2292 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2294 simulateDoubleTap(webViewHelper.webViewImpl(), point, scale);
2295 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2296 simulateDoubleTap(webViewHelper.webViewImpl(), point, scale);
2297 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2300 TEST_F(WebFrameTest, DivAutoZoomVeryTallTest_VirtualViewport)
2302 // When a block is taller than the viewport and a zoom targets a lower part
2303 // of it, then we should keep the target point onscreen instead of snapping
2304 // back up the top of the block.
2305 registerMockedHttpURLLoad("very_tall_div.html");
2307 const float deviceScaleFactor = 2.0f;
2308 int viewportWidth = 640 / deviceScaleFactor;
2309 int viewportHeight = 1280 / deviceScaleFactor;
2310 FrameTestHelpers::WebViewHelper webViewHelper;
2311 webViewHelper.initializeAndLoad(m_baseURL + "very_tall_div.html", true, 0, 0, configurePinchVirtualViewport);
2312 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2313 webViewHelper.webView()->setPageScaleFactorLimits(1.0f, 4);
2314 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2315 webViewHelper.webView()->setPageScaleFactor(1.0f);
2316 webViewHelper.webView()->layout();
2318 WebRect div(200, 300, 400, 5000);
2319 WebPoint point(div.x + 50, div.y + 3000);
2323 WebRect blockBounds = webViewHelper.webViewImpl()->computeBlockBounds(WebRect(point.x, point.y, 0, 0), true);
2324 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(point, blockBounds, 0, 1.0f, scale, scroll);
2325 EXPECT_EQ(scale, 1.0f);
2326 EXPECT_EQ(scroll.y, 2660);
2329 TEST_F(WebFrameTest, DivAutoZoomMultipleDivsTest_VirtualViewport)
2331 registerMockedHttpURLLoad("get_multiple_divs_for_auto_zoom_test.html");
2333 const float deviceScaleFactor = 2.0f;
2334 int viewportWidth = 640 / deviceScaleFactor;
2335 int viewportHeight = 1280 / deviceScaleFactor;
2336 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2337 FrameTestHelpers::WebViewHelper webViewHelper;
2338 webViewHelper.initializeAndLoad(m_baseURL + "get_multiple_divs_for_auto_zoom_test.html", false, 0, 0, configurePinchVirtualViewport);
2339 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2340 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2341 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2342 webViewHelper.webView()->setPageScaleFactor(0.5f);
2343 webViewHelper.webView()->layout();
2345 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2347 WebRect topDiv(200, 100, 200, 150);
2348 WebRect bottomDiv(200, 300, 200, 150);
2349 WebPoint topPoint(topDiv.x + 50, topDiv.y + 50);
2350 WebPoint bottomPoint(bottomDiv.x + 50, bottomDiv.y + 50);
2352 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2354 // Test double tap on two different divs
2355 // After first zoom, we should go back to minimum page scale with a second double tap.
2356 simulateDoubleTap(webViewHelper.webViewImpl(), topPoint, scale);
2357 EXPECT_FLOAT_EQ(1, scale);
2358 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2359 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2361 // If the user pinch zooms after double tap, a second double tap should zoom back to the div.
2362 simulateDoubleTap(webViewHelper.webViewImpl(), topPoint, scale);
2363 EXPECT_FLOAT_EQ(1, scale);
2364 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(), 0.6f, 0);
2365 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2366 EXPECT_FLOAT_EQ(1, scale);
2367 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2368 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2370 // If we didn't yet get an auto-zoom update and a second double-tap arrives, should go back to minimum scale.
2371 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(), 1.1f, 0);
2372 webViewHelper.webViewImpl()->animateDoubleTapZoom(topPoint);
2373 EXPECT_TRUE(webViewHelper.webViewImpl()->fakeDoubleTapAnimationPendingForTesting());
2374 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2375 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2378 TEST_F(WebFrameTest, DivAutoZoomScaleBoundsTest_VirtualViewport)
2380 registerMockedHttpURLLoad("get_scale_bounds_check_for_auto_zoom_test.html");
2382 int viewportWidth = 320;
2383 int viewportHeight = 480;
2384 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2385 FrameTestHelpers::WebViewHelper webViewHelper;
2386 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_bounds_check_for_auto_zoom_test.html", false, 0, 0, configurePinchVirtualViewport);
2387 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2388 webViewHelper.webView()->setDeviceScaleFactor(1.5f);
2389 webViewHelper.webView()->layout();
2391 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2393 WebRect div(200, 100, 200, 150);
2394 WebPoint doubleTapPoint(div.x + 50, div.y + 50);
2397 // Test double tap scale bounds.
2398 // minimumPageScale < doubleTapZoomAlreadyLegibleScale < 1
2399 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2400 webViewHelper.webView()->layout();
2401 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2402 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2403 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2404 EXPECT_FLOAT_EQ(1, scale);
2405 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2406 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2407 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2408 EXPECT_FLOAT_EQ(1, scale);
2410 // Zoom in to reset double_tap_zoom_in_effect flag.
2411 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(), 1.1f, 0);
2412 // 1 < minimumPageScale < doubleTapZoomAlreadyLegibleScale
2413 webViewHelper.webView()->setPageScaleFactorLimits(1.1f, 4);
2414 webViewHelper.webView()->layout();
2415 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2416 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2417 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2418 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2419 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2420 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2421 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2422 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2424 // Zoom in to reset double_tap_zoom_in_effect flag.
2425 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(), 1.1f, 0);
2426 // minimumPageScale < 1 < doubleTapZoomAlreadyLegibleScale
2427 webViewHelper.webView()->setPageScaleFactorLimits(0.95f, 4);
2428 webViewHelper.webView()->layout();
2429 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2430 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2431 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2432 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, 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(doubleTapZoomAlreadyLegibleScale, scale);
2439 TEST_F(WebFrameTest, DivAutoZoomScaleFontScaleFactorTest_VirtualViewport)
2441 registerMockedHttpURLLoad("get_scale_bounds_check_for_auto_zoom_test.html");
2443 int viewportWidth = 320;
2444 int viewportHeight = 480;
2445 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2446 float accessibilityFontScaleFactor = 1.13f;
2447 FrameTestHelpers::WebViewHelper webViewHelper;
2448 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_bounds_check_for_auto_zoom_test.html", false, 0, 0, configurePinchVirtualViewport);
2449 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2450 webViewHelper.webView()->layout();
2452 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2453 webViewHelper.webViewImpl()->page()->settings().setTextAutosizingEnabled(true);
2454 webViewHelper.webViewImpl()->page()->settings().setAccessibilityFontScaleFactor(accessibilityFontScaleFactor);
2456 WebRect div(200, 100, 200, 150);
2457 WebPoint doubleTapPoint(div.x + 50, div.y + 50);
2460 // Test double tap scale bounds.
2461 // minimumPageScale < doubleTapZoomAlreadyLegibleScale < 1 < accessibilityFontScaleFactor
2462 float legibleScale = accessibilityFontScaleFactor;
2463 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2464 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2465 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2466 webViewHelper.webView()->layout();
2467 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2468 EXPECT_FLOAT_EQ(legibleScale, scale);
2469 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2470 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2471 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2472 EXPECT_FLOAT_EQ(legibleScale, scale);
2474 // Zoom in to reset double_tap_zoom_in_effect flag.
2475 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(), 1.1f, 0);
2476 // 1 < accessibilityFontScaleFactor < minimumPageScale < doubleTapZoomAlreadyLegibleScale
2477 webViewHelper.webView()->setPageScaleFactorLimits(1.0f, 4);
2478 webViewHelper.webView()->layout();
2479 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2480 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2481 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2482 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2483 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2484 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2485 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2486 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2488 // Zoom in to reset double_tap_zoom_in_effect flag.
2489 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(), 1.1f, 0);
2490 // minimumPageScale < 1 < accessibilityFontScaleFactor < doubleTapZoomAlreadyLegibleScale
2491 webViewHelper.webView()->setPageScaleFactorLimits(0.95f, 4);
2492 webViewHelper.webView()->layout();
2493 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2494 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2495 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2496 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2497 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2498 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2499 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2500 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2502 // Zoom in to reset double_tap_zoom_in_effect flag.
2503 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(), 1.1f, 0);
2504 // minimumPageScale < 1 < doubleTapZoomAlreadyLegibleScale < accessibilityFontScaleFactor
2505 webViewHelper.webView()->setPageScaleFactorLimits(0.9f, 4);
2506 webViewHelper.webView()->layout();
2507 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2508 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2509 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2510 EXPECT_FLOAT_EQ(legibleScale, scale);
2511 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2512 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2513 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2514 EXPECT_FLOAT_EQ(legibleScale, scale);
2517 // FIXME(bokan): The following tests marked with _OldPinch test AutoZoom
2518 // without the pinch virtual viewport mode enabled. As this becomes the default
2519 // and the old path is deprecated, these tests can be removed; they've been
2520 // cloned above to use the new virtual viewport path.
2522 TEST_F(WebFrameTest, DivAutoZoomParamsTest_OldPinch)
2524 registerMockedHttpURLLoad("get_scale_for_auto_zoom_into_div_test.html");
2526 const float deviceScaleFactor = 2.0f;
2527 int viewportWidth = 640 / deviceScaleFactor;
2528 int viewportHeight = 1280 / deviceScaleFactor;
2529 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2530 FrameTestHelpers::WebViewHelper webViewHelper;
2531 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_for_auto_zoom_into_div_test.html");
2532 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2533 webViewHelper.webView()->setPageScaleFactorLimits(0.01f, 4);
2534 webViewHelper.webView()->setPageScaleFactor(0.5f);
2535 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2536 webViewHelper.webView()->layout();
2538 WebRect wideDiv(200, 100, 400, 150);
2539 WebRect tallDiv(200, 300, 400, 800);
2540 WebRect doubleTapPointWide(wideDiv.x + 50, wideDiv.y + 50, touchPointPadding, touchPointPadding);
2541 WebRect doubleTapPointTall(tallDiv.x + 50, tallDiv.y + 50, touchPointPadding, touchPointPadding);
2542 WebRect wideBlockBounds;
2543 WebRect tallBlockBounds;
2547 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2549 // Test double-tap zooming into wide div.
2550 wideBlockBounds = webViewHelper.webViewImpl()->computeBlockBounds(doubleTapPointWide, false);
2551 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(doubleTapPointWide.x, doubleTapPointWide.y), wideBlockBounds, touchPointPadding, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2552 // The div should horizontally fill the screen (modulo margins), and
2553 // vertically centered (modulo integer rounding).
2554 EXPECT_NEAR(viewportWidth / (float) wideDiv.width, scale, 0.1);
2555 EXPECT_NEAR(wideDiv.x, scroll.x, 20);
2556 EXPECT_EQ(0, scroll.y);
2558 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), scroll, scale);
2560 // Test zoom out back to minimum scale.
2561 wideBlockBounds = webViewHelper.webViewImpl()->computeBlockBounds(doubleTapPointWide, false);
2562 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(doubleTapPointWide.x, doubleTapPointWide.y), wideBlockBounds, touchPointPadding, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2564 scale = webViewHelper.webViewImpl()->minimumPageScaleFactor();
2565 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), scale);
2567 // Test double-tap zooming into tall div.
2568 tallBlockBounds = webViewHelper.webViewImpl()->computeBlockBounds(doubleTapPointTall, false);
2569 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(doubleTapPointTall.x, doubleTapPointTall.y), tallBlockBounds, touchPointPadding, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2570 // The div should start at the top left of the viewport.
2571 EXPECT_NEAR(viewportWidth / (float) tallDiv.width, scale, 0.1);
2572 EXPECT_NEAR(tallDiv.x, scroll.x, 20);
2573 EXPECT_NEAR(tallDiv.y, scroll.y, 20);
2575 // Test for Non-doubletap scaling
2576 // Test zooming into div.
2577 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(250, 250), webViewHelper.webViewImpl()->computeBlockBounds(WebRect(250, 250, 10, 10), true), 0, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2578 EXPECT_NEAR(viewportWidth / (float) wideDiv.width, scale, 0.1);
2581 TEST_F(WebFrameTest, DivAutoZoomWideDivTest_OldPinch)
2583 registerMockedHttpURLLoad("get_wide_div_for_auto_zoom_test.html");
2585 const float deviceScaleFactor = 2.0f;
2586 int viewportWidth = 640 / deviceScaleFactor;
2587 int viewportHeight = 1280 / deviceScaleFactor;
2588 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2589 FrameTestHelpers::WebViewHelper webViewHelper;
2590 webViewHelper.initializeAndLoad(m_baseURL + "get_wide_div_for_auto_zoom_test.html");
2591 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2592 webViewHelper.webView()->setPageScaleFactorLimits(1.0f, 4);
2593 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2594 webViewHelper.webView()->setPageScaleFactor(1.0f);
2595 webViewHelper.webView()->layout();
2597 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2599 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2601 WebRect div(0, 100, viewportWidth, 150);
2602 WebPoint point(div.x + 50, div.y + 50);
2604 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2606 simulateDoubleTap(webViewHelper.webViewImpl(), point, scale);
2607 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2608 simulateDoubleTap(webViewHelper.webViewImpl(), point, scale);
2609 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2612 TEST_F(WebFrameTest, DivAutoZoomVeryTallTest_OldPinch)
2614 // When a block is taller than the viewport and a zoom targets a lower part
2615 // of it, then we should keep the target point onscreen instead of snapping
2616 // back up the top of the block.
2617 registerMockedHttpURLLoad("very_tall_div.html");
2619 const float deviceScaleFactor = 2.0f;
2620 int viewportWidth = 640 / deviceScaleFactor;
2621 int viewportHeight = 1280 / deviceScaleFactor;
2622 FrameTestHelpers::WebViewHelper webViewHelper;
2623 webViewHelper.initializeAndLoad(m_baseURL + "very_tall_div.html", true, 0, 0, enableViewportSettings);
2624 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2625 webViewHelper.webView()->setPageScaleFactorLimits(1.0f, 4);
2626 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2627 webViewHelper.webView()->setPageScaleFactor(1.0f);
2628 webViewHelper.webView()->layout();
2630 WebRect div(200, 300, 400, 5000);
2631 WebPoint point(div.x + 50, div.y + 3000);
2635 WebRect blockBounds = webViewHelper.webViewImpl()->computeBlockBounds(WebRect(point.x, point.y, 0, 0), true);
2636 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(point, blockBounds, 0, 1.0f, scale, scroll);
2637 EXPECT_EQ(scale, 1.0f);
2638 EXPECT_EQ(scroll.y, 2660);
2641 TEST_F(WebFrameTest, DivAutoZoomMultipleDivsTest_OldPinch)
2643 registerMockedHttpURLLoad("get_multiple_divs_for_auto_zoom_test.html");
2645 const float deviceScaleFactor = 2.0f;
2646 int viewportWidth = 640 / deviceScaleFactor;
2647 int viewportHeight = 1280 / deviceScaleFactor;
2648 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2649 FrameTestHelpers::WebViewHelper webViewHelper;
2650 webViewHelper.initializeAndLoad(m_baseURL + "get_multiple_divs_for_auto_zoom_test.html");
2651 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2652 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2653 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2654 webViewHelper.webView()->setPageScaleFactor(0.5f);
2655 webViewHelper.webView()->layout();
2657 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2659 WebRect topDiv(200, 100, 200, 150);
2660 WebRect bottomDiv(200, 300, 200, 150);
2661 WebPoint topPoint(topDiv.x + 50, topDiv.y + 50);
2662 WebPoint bottomPoint(bottomDiv.x + 50, bottomDiv.y + 50);
2664 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2666 // Test double tap on two different divs
2667 // After first zoom, we should go back to minimum page scale with a second double tap.
2668 simulateDoubleTap(webViewHelper.webViewImpl(), topPoint, scale);
2669 EXPECT_FLOAT_EQ(1, scale);
2670 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2671 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2673 // If the user pinch zooms after double tap, a second double tap should zoom back to the div.
2674 simulateDoubleTap(webViewHelper.webViewImpl(), topPoint, scale);
2675 EXPECT_FLOAT_EQ(1, scale);
2676 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(), 0.6f, 0);
2677 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2678 EXPECT_FLOAT_EQ(1, scale);
2679 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2680 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2682 // If we didn't yet get an auto-zoom update and a second double-tap arrives, should go back to minimum scale.
2683 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(), 1.1f, 0);
2684 webViewHelper.webViewImpl()->animateDoubleTapZoom(topPoint);
2685 EXPECT_TRUE(webViewHelper.webViewImpl()->fakeDoubleTapAnimationPendingForTesting());
2686 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2687 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2690 TEST_F(WebFrameTest, DivAutoZoomScaleBoundsTest_OldPinch)
2692 registerMockedHttpURLLoad("get_scale_bounds_check_for_auto_zoom_test.html");
2694 int viewportWidth = 320;
2695 int viewportHeight = 480;
2696 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2697 FrameTestHelpers::WebViewHelper webViewHelper;
2698 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_bounds_check_for_auto_zoom_test.html");
2699 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2700 webViewHelper.webView()->setDeviceScaleFactor(1.5f);
2701 webViewHelper.webView()->layout();
2703 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2705 WebRect div(200, 100, 200, 150);
2706 WebPoint doubleTapPoint(div.x + 50, div.y + 50);
2709 // Test double tap scale bounds.
2710 // minimumPageScale < doubleTapZoomAlreadyLegibleScale < 1
2711 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2712 webViewHelper.webView()->layout();
2713 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2714 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2715 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2716 EXPECT_FLOAT_EQ(1, scale);
2717 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2718 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2719 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2720 EXPECT_FLOAT_EQ(1, scale);
2722 // Zoom in to reset double_tap_zoom_in_effect flag.
2723 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(), 1.1f, 0);
2724 // 1 < minimumPageScale < doubleTapZoomAlreadyLegibleScale
2725 webViewHelper.webView()->setPageScaleFactorLimits(1.1f, 4);
2726 webViewHelper.webView()->layout();
2727 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2728 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2729 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2730 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2731 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2732 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2733 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2734 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2736 // Zoom in to reset double_tap_zoom_in_effect flag.
2737 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(), 1.1f, 0);
2738 // minimumPageScale < 1 < doubleTapZoomAlreadyLegibleScale
2739 webViewHelper.webView()->setPageScaleFactorLimits(0.95f, 4);
2740 webViewHelper.webView()->layout();
2741 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2742 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2743 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2744 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2745 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2746 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2747 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2748 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2751 TEST_F(WebFrameTest, DivAutoZoomScaleFontScaleFactorTest_OldPinch)
2753 registerMockedHttpURLLoad("get_scale_bounds_check_for_auto_zoom_test.html");
2755 int viewportWidth = 320;
2756 int viewportHeight = 480;
2757 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2758 float accessibilityFontScaleFactor = 1.13f;
2759 FrameTestHelpers::WebViewHelper webViewHelper;
2760 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_bounds_check_for_auto_zoom_test.html");
2761 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2762 webViewHelper.webView()->layout();
2764 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2765 webViewHelper.webViewImpl()->page()->settings().setTextAutosizingEnabled(true);
2766 webViewHelper.webViewImpl()->page()->settings().setAccessibilityFontScaleFactor(accessibilityFontScaleFactor);
2768 WebRect div(200, 100, 200, 150);
2769 WebPoint doubleTapPoint(div.x + 50, div.y + 50);
2772 // Test double tap scale bounds.
2773 // minimumPageScale < doubleTapZoomAlreadyLegibleScale < 1 < accessibilityFontScaleFactor
2774 float legibleScale = accessibilityFontScaleFactor;
2775 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2776 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2777 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2778 webViewHelper.webView()->layout();
2779 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2780 EXPECT_FLOAT_EQ(legibleScale, scale);
2781 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2782 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2783 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2784 EXPECT_FLOAT_EQ(legibleScale, scale);
2786 // Zoom in to reset double_tap_zoom_in_effect flag.
2787 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(), 1.1f, 0);
2788 // 1 < accessibilityFontScaleFactor < minimumPageScale < doubleTapZoomAlreadyLegibleScale
2789 webViewHelper.webView()->setPageScaleFactorLimits(1.0f, 4);
2790 webViewHelper.webView()->layout();
2791 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2792 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2793 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2794 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2795 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2796 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2797 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2798 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2800 // Zoom in to reset double_tap_zoom_in_effect flag.
2801 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(), 1.1f, 0);
2802 // minimumPageScale < 1 < accessibilityFontScaleFactor < doubleTapZoomAlreadyLegibleScale
2803 webViewHelper.webView()->setPageScaleFactorLimits(0.95f, 4);
2804 webViewHelper.webView()->layout();
2805 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2806 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2807 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2808 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2809 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2810 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2811 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2812 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2814 // Zoom in to reset double_tap_zoom_in_effect flag.
2815 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(), 1.1f, 0);
2816 // minimumPageScale < 1 < doubleTapZoomAlreadyLegibleScale < accessibilityFontScaleFactor
2817 webViewHelper.webView()->setPageScaleFactorLimits(0.9f, 4);
2818 webViewHelper.webView()->layout();
2819 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2820 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2821 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2822 EXPECT_FLOAT_EQ(legibleScale, scale);
2823 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2824 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2825 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2826 EXPECT_FLOAT_EQ(legibleScale, scale);
2829 // ================= End Old-Style Pinch tests to be removed ===================
2831 TEST_F(WebFrameTest, DivMultipleTargetZoomMultipleDivsTest)
2833 registerMockedHttpURLLoad("get_multiple_divs_for_auto_zoom_test.html");
2835 const float deviceScaleFactor = 2.0f;
2836 int viewportWidth = 640 / deviceScaleFactor;
2837 int viewportHeight = 1280 / deviceScaleFactor;
2838 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2839 FrameTestHelpers::WebViewHelper webViewHelper;
2840 webViewHelper.initializeAndLoad(m_baseURL + "get_multiple_divs_for_auto_zoom_test.html");
2841 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2842 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2843 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2844 webViewHelper.webView()->setPageScaleFactor(0.5f);
2845 webViewHelper.webView()->layout();
2847 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2849 WebRect viewportRect(0, 0, viewportWidth, viewportHeight);
2850 WebRect topDiv(200, 100, 200, 150);
2851 WebRect bottomDiv(200, 300, 200, 150);
2853 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2855 simulateMultiTargetZoom(webViewHelper.webViewImpl(), topDiv, scale);
2856 EXPECT_FLOAT_EQ(1, scale);
2857 simulateMultiTargetZoom(webViewHelper.webViewImpl(), bottomDiv, scale);
2858 EXPECT_FLOAT_EQ(1, scale);
2859 simulateMultiTargetZoom(webViewHelper.webViewImpl(), viewportRect, scale);
2860 EXPECT_FLOAT_EQ(1, scale);
2861 webViewHelper.webViewImpl()->setPageScaleFactor(webViewHelper.webViewImpl()->minimumPageScaleFactor());
2862 simulateMultiTargetZoom(webViewHelper.webViewImpl(), topDiv, scale);
2863 EXPECT_FLOAT_EQ(1, scale);
2866 TEST_F(WebFrameTest, DivScrollIntoEditableTest)
2868 registerMockedHttpURLLoad("get_scale_for_zoom_into_editable_test.html");
2870 int viewportWidth = 450;
2871 int viewportHeight = 300;
2872 float leftBoxRatio = 0.3f;
2873 int caretPadding = 10;
2874 float minReadableCaretHeight = 18.0f;
2875 FrameTestHelpers::WebViewHelper webViewHelper;
2876 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_for_zoom_into_editable_test.html");
2877 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2878 webViewHelper.webView()->setPageScaleFactorLimits(1, 4);
2879 webViewHelper.webView()->layout();
2880 webViewHelper.webView()->setDeviceScaleFactor(1.5f);
2881 webViewHelper.webView()->settings()->setAutoZoomFocusedNodeToLegibleScale(true);
2883 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2885 WebRect editBoxWithText(200, 200, 250, 20);
2886 WebRect editBoxWithNoText(200, 250, 250, 20);
2888 // Test scrolling the focused node
2889 // The edit box is shorter and narrower than the viewport when legible.
2890 webViewHelper.webView()->advanceFocus(false);
2891 // Set the caret to the end of the input box.
2892 webViewHelper.webView()->mainFrame()->document().getElementById("EditBoxWithText").to<WebInputElement>().setSelectionRange(1000, 1000);
2893 setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), 1);
2894 WebRect rect, caret;
2895 webViewHelper.webViewImpl()->selectionBounds(caret, rect);
2900 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2901 EXPECT_TRUE(needAnimation);
2902 // The edit box should be left aligned with a margin for possible label.
2903 int hScroll = editBoxWithText.x - leftBoxRatio * viewportWidth / scale;
2904 EXPECT_NEAR(hScroll, scroll.x(), 5);
2905 int vScroll = editBoxWithText.y - (viewportHeight / scale - editBoxWithText.height) / 2;
2906 EXPECT_NEAR(vScroll, scroll.y(), 1);
2907 EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1);
2909 // The edit box is wider than the viewport when legible.
2910 viewportWidth = 200;
2911 viewportHeight = 150;
2912 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2913 setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), 1);
2914 webViewHelper.webViewImpl()->selectionBounds(caret, rect);
2915 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2916 EXPECT_TRUE(needAnimation);
2917 // The caret should be right aligned since the caret would be offscreen when the edit box is left aligned.
2918 hScroll = caret.x + caret.width + caretPadding - viewportWidth / scale;
2919 EXPECT_NEAR(hScroll, scroll.x(), 1);
2920 EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1);
2922 setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), 1);
2923 // Move focus to edit box with text.
2924 webViewHelper.webView()->advanceFocus(false);
2925 webViewHelper.webViewImpl()->selectionBounds(caret, rect);
2926 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2927 EXPECT_TRUE(needAnimation);
2928 // The edit box should be left aligned.
2929 hScroll = editBoxWithNoText.x;
2930 EXPECT_NEAR(hScroll, scroll.x(), 1);
2931 vScroll = editBoxWithNoText.y - (viewportHeight / scale - editBoxWithNoText.height) / 2;
2932 EXPECT_NEAR(vScroll, scroll.y(), 1);
2933 EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1);
2935 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), scroll, scale);
2937 // Move focus back to the first edit box.
2938 webViewHelper.webView()->advanceFocus(true);
2939 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2940 // The position should have stayed the same since this box was already on screen with the right scale.
2941 EXPECT_FALSE(needAnimation);
2944 TEST_F(WebFrameTest, DivScrollIntoEditablePreservePageScaleTest)
2946 registerMockedHttpURLLoad("get_scale_for_zoom_into_editable_test.html");
2948 const int viewportWidth = 450;
2949 const int viewportHeight = 300;
2950 const float minReadableCaretHeight = 18.0f;
2951 FrameTestHelpers::WebViewHelper webViewHelper;
2952 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_for_zoom_into_editable_test.html");
2953 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2954 webViewHelper.webView()->setPageScaleFactorLimits(1, 4);
2955 webViewHelper.webView()->layout();
2956 webViewHelper.webView()->setDeviceScaleFactor(1.5f);
2957 webViewHelper.webView()->settings()->setAutoZoomFocusedNodeToLegibleScale(true);
2958 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2960 const WebRect editBoxWithText(200, 200, 250, 20);
2962 webViewHelper.webView()->advanceFocus(false);
2963 // Set the caret to the begining of the input box.
2964 webViewHelper.webView()->mainFrame()->document().getElementById("EditBoxWithText").to<WebInputElement>().setSelectionRange(0, 0);
2965 setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), 1);
2966 WebRect rect, caret;
2967 webViewHelper.webViewImpl()->selectionBounds(caret, rect);
2969 // Set page scale twice larger then minimal readable scale
2970 float newScale = minReadableCaretHeight / caret.height * 2.0;
2971 setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), newScale);
2976 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2977 EXPECT_TRUE(needAnimation);
2978 // Edit box and caret should be left alinged
2979 int hScroll = editBoxWithText.x;
2980 EXPECT_NEAR(hScroll, scroll.x(), 1);
2981 int vScroll = editBoxWithText.y - (viewportHeight / scale - editBoxWithText.height) / 2;
2982 EXPECT_NEAR(vScroll, scroll.y(), 1);
2983 // Page scale have to be unchanged
2984 EXPECT_EQ(newScale, scale);
2986 // Set page scale and scroll such that edit box will be under the screen
2989 setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(hScroll, 0), newScale);
2990 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2991 EXPECT_TRUE(needAnimation);
2992 // Horizontal scroll have to be the same
2993 EXPECT_NEAR(hScroll, scroll.x(), 1);
2994 vScroll = editBoxWithText.y - (viewportHeight / scale - editBoxWithText.height) / 2;
2995 EXPECT_NEAR(vScroll, scroll.y(), 1);
2996 // Page scale have to be unchanged
2997 EXPECT_EQ(newScale, scale);
3000 class TestReloadDoesntRedirectWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
3002 virtual WebNavigationPolicy decidePolicyForNavigation(const NavigationPolicyInfo& info) override
3004 EXPECT_FALSE(info.isRedirect);
3005 return WebNavigationPolicyCurrentTab;
3009 TEST_F(WebFrameTest, ReloadDoesntSetRedirect)
3011 // Test for case in http://crbug.com/73104. Reloading a frame very quickly
3012 // would sometimes call decidePolicyForNavigation with isRedirect=true
3013 registerMockedHttpURLLoad("form.html");
3015 TestReloadDoesntRedirectWebFrameClient webFrameClient;
3016 FrameTestHelpers::WebViewHelper webViewHelper;
3017 webViewHelper.initializeAndLoad(m_baseURL + "form.html", false, &webFrameClient);
3019 webViewHelper.webView()->mainFrame()->reload(true);
3020 // start another reload before request is delivered.
3021 FrameTestHelpers::reloadFrameIgnoringCache(webViewHelper.webView()->mainFrame());
3024 class ReloadWithOverrideURLTask : public WebThread::Task {
3026 ReloadWithOverrideURLTask(WebFrame* frame, const KURL& url, bool ignoreCache)
3027 : m_frame(frame), m_url(url), m_ignoreCache(ignoreCache)
3031 virtual void run() override
3033 m_frame->reloadWithOverrideURL(m_url, m_ignoreCache);
3037 WebFrame* const m_frame;
3039 const bool m_ignoreCache;
3042 TEST_F(WebFrameTest, ReloadWithOverrideURLPreservesState)
3044 const std::string firstURL = "find.html";
3045 const std::string secondURL = "form.html";
3046 const std::string thirdURL = "history.html";
3047 const float pageScaleFactor = 1.1684f;
3048 const int pageWidth = 640;
3049 const int pageHeight = 480;
3051 registerMockedHttpURLLoad(firstURL);
3052 registerMockedHttpURLLoad(secondURL);
3053 registerMockedHttpURLLoad(thirdURL);
3055 FrameTestHelpers::WebViewHelper webViewHelper;
3056 webViewHelper.initializeAndLoad(m_baseURL + firstURL, true);
3057 webViewHelper.webViewImpl()->resize(WebSize(pageWidth, pageHeight));
3058 webViewHelper.webViewImpl()->mainFrame()->setScrollOffset(WebSize(pageWidth / 4, pageHeight / 4));
3059 webViewHelper.webViewImpl()->setPageScaleFactor(pageScaleFactor);
3061 WebSize previousOffset = webViewHelper.webViewImpl()->mainFrame()->scrollOffset();
3062 float previousScale = webViewHelper.webViewImpl()->pageScaleFactor();
3064 // Reload the page using the cache.
3065 Platform::current()->currentThread()->postTask(
3066 new ReloadWithOverrideURLTask(webViewHelper.webViewImpl()->mainFrame(), toKURL(m_baseURL + secondURL), false));
3067 FrameTestHelpers::pumpPendingRequestsDoNotUse(webViewHelper.webViewImpl()->mainFrame());
3068 ASSERT_EQ(previousOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
3069 ASSERT_EQ(previousScale, webViewHelper.webViewImpl()->pageScaleFactor());
3071 // Reload the page while ignoring the cache.
3072 Platform::current()->currentThread()->postTask(
3073 new ReloadWithOverrideURLTask(webViewHelper.webViewImpl()->mainFrame(), toKURL(m_baseURL + thirdURL), true));
3074 FrameTestHelpers::pumpPendingRequestsDoNotUse(webViewHelper.webViewImpl()->mainFrame());
3075 ASSERT_EQ(previousOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
3076 ASSERT_EQ(previousScale, webViewHelper.webViewImpl()->pageScaleFactor());
3079 TEST_F(WebFrameTest, ReloadWhileProvisional)
3081 // Test that reloading while the previous load is still pending does not cause the initial
3082 // request to get lost.
3083 registerMockedHttpURLLoad("fixed_layout.html");
3085 FrameTestHelpers::WebViewHelper webViewHelper;
3086 webViewHelper.initialize();
3087 WebURLRequest request;
3088 request.initialize();
3089 request.setURL(toKURL(m_baseURL + "fixed_layout.html"));
3090 webViewHelper.webView()->mainFrame()->loadRequest(request);
3091 // start reload before first request is delivered.
3092 FrameTestHelpers::reloadFrameIgnoringCache(webViewHelper.webView()->mainFrame());
3094 WebDataSource* dataSource = webViewHelper.webView()->mainFrame()->dataSource();
3095 ASSERT_TRUE(dataSource);
3096 EXPECT_EQ(toKURL(m_baseURL + "fixed_layout.html"), toKURL(dataSource->request().url().spec()));
3099 TEST_F(WebFrameTest, AppendRedirects)
3101 const std::string firstURL = "about:blank";
3102 const std::string secondURL = "http://internal.test";
3104 FrameTestHelpers::WebViewHelper webViewHelper;
3105 webViewHelper.initializeAndLoad(firstURL, true);
3107 WebDataSource* dataSource = webViewHelper.webView()->mainFrame()->dataSource();
3108 ASSERT_TRUE(dataSource);
3109 dataSource->appendRedirect(toKURL(secondURL));
3111 WebVector<WebURL> redirects;
3112 dataSource->redirectChain(redirects);
3113 ASSERT_EQ(2U, redirects.size());
3114 EXPECT_EQ(toKURL(firstURL), toKURL(redirects[0].spec().data()));
3115 EXPECT_EQ(toKURL(secondURL), toKURL(redirects[1].spec().data()));
3118 TEST_F(WebFrameTest, IframeRedirect)
3120 registerMockedHttpURLLoad("iframe_redirect.html");
3121 registerMockedHttpURLLoad("visible_iframe.html");
3123 FrameTestHelpers::WebViewHelper webViewHelper;
3124 webViewHelper.initializeAndLoad(m_baseURL + "iframe_redirect.html", true);
3125 // Pump pending requests one more time. The test page loads script that navigates.
3126 FrameTestHelpers::pumpPendingRequestsDoNotUse(webViewHelper.webView()->mainFrame());
3128 WebFrame* iframe = webViewHelper.webView()->findFrameByName(WebString::fromUTF8("ifr"));
3129 ASSERT_TRUE(iframe);
3130 WebDataSource* iframeDataSource = iframe->dataSource();
3131 ASSERT_TRUE(iframeDataSource);
3132 WebVector<WebURL> redirects;
3133 iframeDataSource->redirectChain(redirects);
3134 ASSERT_EQ(2U, redirects.size());
3135 EXPECT_EQ(toKURL("about:blank"), toKURL(redirects[0].spec().data()));
3136 EXPECT_EQ(toKURL("http://internal.test/visible_iframe.html"), toKURL(redirects[1].spec().data()));
3139 TEST_F(WebFrameTest, ClearFocusedNodeTest)
3141 registerMockedHttpURLLoad("iframe_clear_focused_node_test.html");
3142 registerMockedHttpURLLoad("autofocus_input_field_iframe.html");
3144 FrameTestHelpers::WebViewHelper webViewHelper;
3145 webViewHelper.initializeAndLoad(m_baseURL + "iframe_clear_focused_node_test.html", true);
3147 // Clear the focused node.
3148 webViewHelper.webView()->clearFocusedElement();
3150 // Now retrieve the FocusedNode and test it should be null.
3151 EXPECT_EQ(0, webViewHelper.webViewImpl()->focusedElement());
3154 // Implementation of WebFrameClient that tracks the v8 contexts that are created
3155 // and destroyed for verification.
3156 class ContextLifetimeTestWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
3158 struct Notification {
3160 Notification(WebLocalFrame* frame, v8::Handle<v8::Context> context, int worldId)
3162 , context(context->GetIsolate(), context)
3172 bool Equals(Notification* other)
3174 return other && frame == other->frame && context == other->context && worldId == other->worldId;
3177 WebLocalFrame* frame;
3178 v8::Persistent<v8::Context> context;
3182 virtual ~ContextLifetimeTestWebFrameClient()
3189 for (size_t i = 0; i < createNotifications.size(); ++i)
3190 delete createNotifications[i];
3192 for (size_t i = 0; i < releaseNotifications.size(); ++i)
3193 delete releaseNotifications[i];
3195 createNotifications.clear();
3196 releaseNotifications.clear();
3199 std::vector<Notification*> createNotifications;
3200 std::vector<Notification*> releaseNotifications;
3203 virtual void didCreateScriptContext(WebLocalFrame* frame, v8::Handle<v8::Context> context, int extensionGroup, int worldId) override
3205 createNotifications.push_back(new Notification(frame, context, worldId));
3208 virtual void willReleaseScriptContext(WebLocalFrame* frame, v8::Handle<v8::Context> context, int worldId) override
3210 releaseNotifications.push_back(new Notification(frame, context, worldId));
3214 // TODO(aa): Deflake this test.
3215 TEST_F(WebFrameTest, FLAKY_ContextNotificationsLoadUnload)
3217 v8::HandleScope handleScope(v8::Isolate::GetCurrent());
3219 registerMockedHttpURLLoad("context_notifications_test.html");
3220 registerMockedHttpURLLoad("context_notifications_test_frame.html");
3222 // Load a frame with an iframe, make sure we get the right create notifications.
3223 ContextLifetimeTestWebFrameClient webFrameClient;
3224 FrameTestHelpers::WebViewHelper webViewHelper;
3225 webViewHelper.initializeAndLoad(m_baseURL + "context_notifications_test.html", true, &webFrameClient);
3227 WebFrame* mainFrame = webViewHelper.webView()->mainFrame();
3228 WebFrame* childFrame = mainFrame->firstChild();
3230 ASSERT_EQ(2u, webFrameClient.createNotifications.size());
3231 EXPECT_EQ(0u, webFrameClient.releaseNotifications.size());
3233 ContextLifetimeTestWebFrameClient::Notification* firstCreateNotification = webFrameClient.createNotifications[0];
3234 ContextLifetimeTestWebFrameClient::Notification* secondCreateNotification = webFrameClient.createNotifications[1];
3236 EXPECT_EQ(mainFrame, firstCreateNotification->frame);
3237 EXPECT_EQ(mainFrame->mainWorldScriptContext(), firstCreateNotification->context);
3238 EXPECT_EQ(0, firstCreateNotification->worldId);
3240 EXPECT_EQ(childFrame, secondCreateNotification->frame);
3241 EXPECT_EQ(childFrame->mainWorldScriptContext(), secondCreateNotification->context);
3242 EXPECT_EQ(0, secondCreateNotification->worldId);
3244 // Close the view. We should get two release notifications that are exactly the same as the create ones, in reverse order.
3245 webViewHelper.reset();
3247 ASSERT_EQ(2u, webFrameClient.releaseNotifications.size());
3248 ContextLifetimeTestWebFrameClient::Notification* firstReleaseNotification = webFrameClient.releaseNotifications[0];
3249 ContextLifetimeTestWebFrameClient::Notification* secondReleaseNotification = webFrameClient.releaseNotifications[1];
3251 ASSERT_TRUE(firstCreateNotification->Equals(secondReleaseNotification));
3252 ASSERT_TRUE(secondCreateNotification->Equals(firstReleaseNotification));
3255 TEST_F(WebFrameTest, ContextNotificationsReload)
3257 v8::HandleScope handleScope(v8::Isolate::GetCurrent());
3259 registerMockedHttpURLLoad("context_notifications_test.html");
3260 registerMockedHttpURLLoad("context_notifications_test_frame.html");
3262 ContextLifetimeTestWebFrameClient webFrameClient;
3263 FrameTestHelpers::WebViewHelper webViewHelper;
3264 webViewHelper.initializeAndLoad(m_baseURL + "context_notifications_test.html", true, &webFrameClient);
3266 // Refresh, we should get two release notifications and two more create notifications.
3267 FrameTestHelpers::reloadFrame(webViewHelper.webView()->mainFrame());
3268 ASSERT_EQ(4u, webFrameClient.createNotifications.size());
3269 ASSERT_EQ(2u, webFrameClient.releaseNotifications.size());
3271 // The two release notifications we got should be exactly the same as the first two create notifications.
3272 for (size_t i = 0; i < webFrameClient.releaseNotifications.size(); ++i) {
3273 EXPECT_TRUE(webFrameClient.releaseNotifications[i]->Equals(
3274 webFrameClient.createNotifications[webFrameClient.createNotifications.size() - 3 - i]));
3277 // The last two create notifications should be for the current frames and context.
3278 WebFrame* mainFrame = webViewHelper.webView()->mainFrame();
3279 WebFrame* childFrame = mainFrame->firstChild();
3280 ContextLifetimeTestWebFrameClient::Notification* firstRefreshNotification = webFrameClient.createNotifications[2];
3281 ContextLifetimeTestWebFrameClient::Notification* secondRefreshNotification = webFrameClient.createNotifications[3];
3283 EXPECT_EQ(mainFrame, firstRefreshNotification->frame);
3284 EXPECT_EQ(mainFrame->mainWorldScriptContext(), firstRefreshNotification->context);
3285 EXPECT_EQ(0, firstRefreshNotification->worldId);
3287 EXPECT_EQ(childFrame, secondRefreshNotification->frame);
3288 EXPECT_EQ(childFrame->mainWorldScriptContext(), secondRefreshNotification->context);
3289 EXPECT_EQ(0, secondRefreshNotification->worldId);
3292 TEST_F(WebFrameTest, ContextNotificationsIsolatedWorlds)
3294 v8::Isolate* isolate = v8::Isolate::GetCurrent();
3295 v8::HandleScope handleScope(isolate);
3297 registerMockedHttpURLLoad("context_notifications_test.html");
3298 registerMockedHttpURLLoad("context_notifications_test_frame.html");
3300 ContextLifetimeTestWebFrameClient webFrameClient;
3301 FrameTestHelpers::WebViewHelper webViewHelper;
3302 webViewHelper.initializeAndLoad(m_baseURL + "context_notifications_test.html", true, &webFrameClient);
3304 // Add an isolated world.
3305 webFrameClient.reset();
3307 int isolatedWorldId = 42;
3308 WebScriptSource scriptSource("hi!");
3310 int extensionGroup = 0;
3311 webViewHelper.webView()->mainFrame()->executeScriptInIsolatedWorld(isolatedWorldId, &scriptSource, numSources, extensionGroup);
3313 // We should now have a new create notification.
3314 ASSERT_EQ(1u, webFrameClient.createNotifications.size());
3315 ContextLifetimeTestWebFrameClient::Notification* notification = webFrameClient.createNotifications[0];
3316 ASSERT_EQ(isolatedWorldId, notification->worldId);
3317 ASSERT_EQ(webViewHelper.webView()->mainFrame(), notification->frame);
3319 // 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.
3320 ASSERT_NE(webViewHelper.webView()->mainFrame()->mainWorldScriptContext(), v8::Local<v8::Context>::New(isolate, notification->context));
3322 webViewHelper.reset();
3324 // We should have gotten three release notifications (one for each of the frames, plus one for the isolated context).
3325 ASSERT_EQ(3u, webFrameClient.releaseNotifications.size());
3327 // And one of them should be exactly the same as the create notification for the isolated context.
3329 for (size_t i = 0; i < webFrameClient.releaseNotifications.size(); ++i) {
3330 if (webFrameClient.releaseNotifications[i]->Equals(webFrameClient.createNotifications[0]))
3333 EXPECT_EQ(1, matchCount);
3336 TEST_F(WebFrameTest, FindInPage)
3338 registerMockedHttpURLLoad("find.html");
3339 FrameTestHelpers::WebViewHelper webViewHelper;
3340 webViewHelper.initializeAndLoad(m_baseURL + "find.html");
3341 WebFrame* frame = webViewHelper.webView()->mainFrame();
3342 const int findIdentifier = 12345;
3343 WebFindOptions options;
3345 // Find in a <div> element.
3346 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar1"), options, false, 0));
3347 frame->stopFinding(false);
3348 WebRange range = frame->selectionRange();
3349 EXPECT_EQ(5, range.startOffset());
3350 EXPECT_EQ(9, range.endOffset());
3351 EXPECT_TRUE(frame->document().focusedElement().isNull());
3353 // Find in an <input> value.
3354 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar2"), options, false, 0));
3355 // Confirm stopFinding(false) sets the selection on the found text.
3356 frame->stopFinding(false);
3357 range = frame->selectionRange();
3358 ASSERT_FALSE(range.isNull());
3359 EXPECT_EQ(5, range.startOffset());
3360 EXPECT_EQ(9, range.endOffset());
3361 EXPECT_EQ(WebString::fromUTF8("INPUT"), frame->document().focusedElement().tagName());
3363 // Find in a <textarea> content.
3364 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar3"), options, false, 0));
3365 // Confirm stopFinding(false) sets the selection on the found text.
3366 frame->stopFinding(false);
3367 range = frame->selectionRange();
3368 ASSERT_FALSE(range.isNull());
3369 EXPECT_EQ(5, range.startOffset());
3370 EXPECT_EQ(9, range.endOffset());
3371 EXPECT_EQ(WebString::fromUTF8("TEXTAREA"), frame->document().focusedElement().tagName());
3373 // Find in a contentEditable element.
3374 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar4"), options, false, 0));
3375 // Confirm stopFinding(false) sets the selection on the found text.
3376 frame->stopFinding(false);
3377 range = frame->selectionRange();
3378 ASSERT_FALSE(range.isNull());
3379 EXPECT_EQ(0, range.startOffset());
3380 EXPECT_EQ(4, range.endOffset());
3381 // "bar4" is surrounded by <span>, but the focusable node should be the parent <div>.
3382 EXPECT_EQ(WebString::fromUTF8("DIV"), frame->document().focusedElement().tagName());
3384 // Find in <select> content.
3385 EXPECT_FALSE(frame->find(findIdentifier, WebString::fromUTF8("bar5"), options, false, 0));
3386 // If there are any matches, stopFinding will set the selection on the found text.
3387 // However, we do not expect any matches, so check that the selection is null.
3388 frame->stopFinding(false);
3389 range = frame->selectionRange();
3390 ASSERT_TRUE(range.isNull());
3393 TEST_F(WebFrameTest, GetContentAsPlainText)
3395 FrameTestHelpers::WebViewHelper webViewHelper;
3396 webViewHelper.initializeAndLoad("about:blank", true);
3397 // We set the size because it impacts line wrapping, which changes the
3398 // resulting text value.
3399 webViewHelper.webView()->resize(WebSize(640, 480));
3400 WebFrame* frame = webViewHelper.webView()->mainFrame();
3402 // Generate a simple test case.
3403 const char simpleSource[] = "<div>Foo bar</div><div></div>baz";
3404 KURL testURL = toKURL("about:blank");
3405 FrameTestHelpers::loadHTMLString(frame, simpleSource, testURL);
3407 // Make sure it comes out OK.
3408 const std::string expected("Foo bar\nbaz");
3409 WebString text = frame->contentAsText(std::numeric_limits<size_t>::max());
3410 EXPECT_EQ(expected, text.utf8());
3412 // Try reading the same one with clipping of the text.
3413 const int length = 5;
3414 text = frame->contentAsText(length);
3415 EXPECT_EQ(expected.substr(0, length), text.utf8());
3417 // Now do a new test with a subframe.
3418 const char outerFrameSource[] = "Hello<iframe></iframe> world";
3419 FrameTestHelpers::loadHTMLString(frame, outerFrameSource, testURL);
3421 // Load something into the subframe.
3422 WebFrame* subframe = frame->firstChild();
3423 ASSERT_TRUE(subframe);
3424 FrameTestHelpers::loadHTMLString(subframe, "sub<p>text", testURL);
3426 text = frame->contentAsText(std::numeric_limits<size_t>::max());
3427 EXPECT_EQ("Hello world\n\nsub\ntext", text.utf8());
3429 // Get the frame text where the subframe separator falls on the boundary of
3430 // what we'll take. There used to be a crash in this case.
3431 text = frame->contentAsText(12);
3432 EXPECT_EQ("Hello world", text.utf8());
3435 TEST_F(WebFrameTest, GetFullHtmlOfPage)
3437 FrameTestHelpers::WebViewHelper webViewHelper;
3438 webViewHelper.initializeAndLoad("about:blank", true);
3439 WebFrame* frame = webViewHelper.webView()->mainFrame();
3441 // Generate a simple test case.
3442 const char simpleSource[] = "<p>Hello</p><p>World</p>";
3443 KURL testURL = toKURL("about:blank");
3444 FrameTestHelpers::loadHTMLString(frame, simpleSource, testURL);
3446 WebString text = frame->contentAsText(std::numeric_limits<size_t>::max());
3447 EXPECT_EQ("Hello\n\nWorld", text.utf8());
3449 const std::string html = frame->contentAsMarkup().utf8();
3451 // Load again with the output html.
3452 FrameTestHelpers::loadHTMLString(frame, html, testURL);
3454 EXPECT_EQ(html, frame->contentAsMarkup().utf8());
3456 text = frame->contentAsText(std::numeric_limits<size_t>::max());
3457 EXPECT_EQ("Hello\n\nWorld", text.utf8());
3459 // Test selection check
3460 EXPECT_FALSE(frame->hasSelection());
3461 frame->executeCommand(WebString::fromUTF8("SelectAll"));
3462 EXPECT_TRUE(frame->hasSelection());
3463 frame->executeCommand(WebString::fromUTF8("Unselect"));
3464 EXPECT_FALSE(frame->hasSelection());
3465 WebString selectionHtml = frame->selectionAsMarkup();
3466 EXPECT_TRUE(selectionHtml.isEmpty());
3469 class TestExecuteScriptDuringDidCreateScriptContext : public FrameTestHelpers::TestWebFrameClient {
3471 virtual void didCreateScriptContext(WebLocalFrame* frame, v8::Handle<v8::Context> context, int extensionGroup, int worldId) override
3473 frame->executeScript(WebScriptSource("window.history = 'replaced';"));
3477 TEST_F(WebFrameTest, ExecuteScriptDuringDidCreateScriptContext)
3479 registerMockedHttpURLLoad("hello_world.html");
3481 TestExecuteScriptDuringDidCreateScriptContext webFrameClient;
3482 FrameTestHelpers::WebViewHelper webViewHelper;
3483 webViewHelper.initializeAndLoad(m_baseURL + "hello_world.html", true, &webFrameClient);
3485 FrameTestHelpers::reloadFrame(webViewHelper.webView()->mainFrame());
3488 class FindUpdateWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
3490 FindUpdateWebFrameClient()
3491 : m_findResultsAreReady(false)
3496 virtual void reportFindInPageMatchCount(int, int count, bool finalUpdate) override
3500 m_findResultsAreReady = true;
3503 bool findResultsAreReady() const { return m_findResultsAreReady; }
3504 int count() const { return m_count; }
3507 bool m_findResultsAreReady;
3511 // This fails on Mac https://bugs.webkit.org/show_bug.cgi?id=108574
3512 // Also failing on Android: http://crbug.com/341314
3513 #if OS(MACOSX) || OS(ANDROID)
3514 TEST_F(WebFrameTest, DISABLED_FindInPageMatchRects)
3516 TEST_F(WebFrameTest, FindInPageMatchRects)
3519 registerMockedHttpURLLoad("find_in_page.html");
3520 registerMockedHttpURLLoad("find_in_page_frame.html");
3522 FindUpdateWebFrameClient client;
3523 FrameTestHelpers::WebViewHelper webViewHelper;
3524 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3525 webViewHelper.webView()->resize(WebSize(640, 480));
3526 webViewHelper.webView()->layout();
3529 // Note that the 'result 19' in the <select> element is not expected to produce a match.
3530 static const char* kFindString = "result";
3531 static const int kFindIdentifier = 12345;
3532 static const int kNumResults = 19;
3534 WebFindOptions options;
3535 WebString searchText = WebString::fromUTF8(kFindString);
3536 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3537 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
3539 mainFrame->resetMatchCount();
3541 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3542 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3545 EXPECT_TRUE(client.findResultsAreReady());
3547 WebVector<WebFloatRect> webMatchRects;
3548 mainFrame->findMatchRects(webMatchRects);
3549 ASSERT_EQ(webMatchRects.size(), static_cast<size_t>(kNumResults));
3550 int rectsVersion = mainFrame->findMatchMarkersVersion();
3552 for (int resultIndex = 0; resultIndex < kNumResults; ++resultIndex) {
3553 FloatRect resultRect = static_cast<FloatRect>(webMatchRects[resultIndex]);
3555 // Select the match by the center of its rect.
3556 EXPECT_EQ(mainFrame->selectNearestFindMatch(resultRect.center(), 0), resultIndex + 1);
3558 // Check that the find result ordering matches with our expectations.
3559 Range* result = mainFrame->activeMatchFrame()->activeMatch();
3560 ASSERT_TRUE(result);
3561 result->setEnd(result->endContainer(), result->endOffset() + 3);
3562 EXPECT_EQ(result->text(), String::format("%s %02d", kFindString, resultIndex));
3564 // Verify that the expected match rect also matches the currently active match.
3565 // Compare the enclosing rects to prevent precision issues caused by CSS transforms.
3566 FloatRect activeMatch = mainFrame->activeFindMatchRect();
3567 EXPECT_EQ(enclosingIntRect(activeMatch), enclosingIntRect(resultRect));
3569 // The rects version should not have changed.
3570 EXPECT_EQ(mainFrame->findMatchMarkersVersion(), rectsVersion);
3573 // All results after the first two ones should be below between them in find-in-page coordinates.
3574 // This is because results 2 to 9 are inside an iframe located between results 0 and 1. This applies to the fixed div too.
3575 EXPECT_TRUE(webMatchRects[0].y < webMatchRects[1].y);
3576 for (int resultIndex = 2; resultIndex < kNumResults; ++resultIndex) {
3577 EXPECT_TRUE(webMatchRects[0].y < webMatchRects[resultIndex].y);
3578 EXPECT_TRUE(webMatchRects[1].y > webMatchRects[resultIndex].y);
3581 // Result 3 should be below both 2 and 4. This is caused by the CSS transform in the containing div.
3582 // If the transform doesn't work then 3 will be between 2 and 4.
3583 EXPECT_TRUE(webMatchRects[3].y > webMatchRects[2].y);
3584 EXPECT_TRUE(webMatchRects[3].y > webMatchRects[4].y);
3586 // Results 6, 7, 8 and 9 should be one below the other in that same order.
3587 // If overflow:scroll is not properly handled then result 8 would be below result 9 or
3588 // result 7 above result 6 depending on the scroll.
3589 EXPECT_TRUE(webMatchRects[6].y < webMatchRects[7].y);
3590 EXPECT_TRUE(webMatchRects[7].y < webMatchRects[8].y);
3591 EXPECT_TRUE(webMatchRects[8].y < webMatchRects[9].y);
3593 // Results 11, 12, 13 and 14 should be between results 10 and 15, as they are inside the table.
3594 EXPECT_TRUE(webMatchRects[11].y > webMatchRects[10].y);
3595 EXPECT_TRUE(webMatchRects[12].y > webMatchRects[10].y);
3596 EXPECT_TRUE(webMatchRects[13].y > webMatchRects[10].y);
3597 EXPECT_TRUE(webMatchRects[14].y > webMatchRects[10].y);
3598 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[15].y);
3599 EXPECT_TRUE(webMatchRects[12].y < webMatchRects[15].y);
3600 EXPECT_TRUE(webMatchRects[13].y < webMatchRects[15].y);
3601 EXPECT_TRUE(webMatchRects[14].y < webMatchRects[15].y);
3603 // Result 11 should be above 12, 13 and 14 as it's in the table header.
3604 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[12].y);
3605 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[13].y);
3606 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[14].y);
3608 // Result 11 should also be right to 12, 13 and 14 because of the colspan.
3609 EXPECT_TRUE(webMatchRects[11].x > webMatchRects[12].x);
3610 EXPECT_TRUE(webMatchRects[11].x > webMatchRects[13].x);
3611 EXPECT_TRUE(webMatchRects[11].x > webMatchRects[14].x);
3613 // Result 12 should be left to results 11, 13 and 14 in the table layout.
3614 EXPECT_TRUE(webMatchRects[12].x < webMatchRects[11].x);
3615 EXPECT_TRUE(webMatchRects[12].x < webMatchRects[13].x);
3616 EXPECT_TRUE(webMatchRects[12].x < webMatchRects[14].x);
3618 // Results 13, 12 and 14 should be one above the other in that order because of the rowspan
3619 // and vertical-align: middle by default.
3620 EXPECT_TRUE(webMatchRects[13].y < webMatchRects[12].y);
3621 EXPECT_TRUE(webMatchRects[12].y < webMatchRects[14].y);
3623 // Result 16 should be below result 15.
3624 EXPECT_TRUE(webMatchRects[15].y > webMatchRects[14].y);
3626 // Result 18 should be normalized with respect to the position:relative div, and not it's
3627 // immediate containing div. Consequently, result 18 should be above result 17.
3628 EXPECT_TRUE(webMatchRects[17].y > webMatchRects[18].y);
3630 // Resizing should update the rects version.
3631 webViewHelper.webView()->resize(WebSize(800, 600));
3633 EXPECT_TRUE(mainFrame->findMatchMarkersVersion() != rectsVersion);
3636 TEST_F(WebFrameTest, FindInPageSkipsHiddenFrames)
3638 registerMockedHttpURLLoad("find_in_hidden_frame.html");
3640 FindUpdateWebFrameClient client;
3641 FrameTestHelpers::WebViewHelper webViewHelper;
3642 webViewHelper.initializeAndLoad(m_baseURL + "find_in_hidden_frame.html", true, &client);
3643 webViewHelper.webView()->resize(WebSize(640, 480));
3644 webViewHelper.webView()->layout();
3647 static const char* kFindString = "hello";
3648 static const int kFindIdentifier = 12345;
3649 static const int kNumResults = 1;
3651 WebFindOptions options;
3652 WebString searchText = WebString::fromUTF8(kFindString);
3653 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3654 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
3656 mainFrame->resetMatchCount();
3658 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3659 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3662 EXPECT_TRUE(client.findResultsAreReady());
3663 EXPECT_EQ(kNumResults, client.count());
3666 TEST_F(WebFrameTest, FindOnDetachedFrame)
3668 registerMockedHttpURLLoad("find_in_page.html");
3669 registerMockedHttpURLLoad("find_in_page_frame.html");
3671 FindUpdateWebFrameClient client;
3672 FrameTestHelpers::WebViewHelper webViewHelper;
3673 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3674 webViewHelper.webView()->resize(WebSize(640, 480));
3675 webViewHelper.webView()->layout();
3678 static const char* kFindString = "result";
3679 static const int kFindIdentifier = 12345;
3681 WebFindOptions options;
3682 WebString searchText = WebString::fromUTF8(kFindString);
3683 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3684 RefPtrWillBeRawPtr<WebLocalFrameImpl> secondFrame = toWebLocalFrameImpl(mainFrame->traverseNext(false));
3685 RefPtrWillBeRawPtr<LocalFrame> holdSecondFrame(secondFrame->frame());
3687 // Detach the frame before finding.
3688 EXPECT_TRUE(mainFrame->document().getElementById("frame").remove());
3690 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
3691 EXPECT_FALSE(secondFrame->find(kFindIdentifier, searchText, options, false, 0));
3694 EXPECT_FALSE(client.findResultsAreReady());
3696 mainFrame->resetMatchCount();
3698 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3699 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3702 EXPECT_TRUE(client.findResultsAreReady());
3705 TEST_F(WebFrameTest, FindDetachFrameBeforeScopeStrings)
3707 registerMockedHttpURLLoad("find_in_page.html");
3708 registerMockedHttpURLLoad("find_in_page_frame.html");
3710 FindUpdateWebFrameClient client;
3711 FrameTestHelpers::WebViewHelper webViewHelper;
3712 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3713 webViewHelper.webView()->resize(WebSize(640, 480));
3714 webViewHelper.webView()->layout();
3717 static const char* kFindString = "result";
3718 static const int kFindIdentifier = 12345;
3720 WebFindOptions options;
3721 WebString searchText = WebString::fromUTF8(kFindString);
3722 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3723 WebLocalFrameImpl* secondFrame = toWebLocalFrameImpl(mainFrame->traverseNext(false));
3724 RefPtrWillBeRawPtr<LocalFrame> holdSecondFrame(secondFrame->frame());
3726 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3727 EXPECT_TRUE(frame->find(kFindIdentifier, searchText, options, false, 0));
3730 EXPECT_FALSE(client.findResultsAreReady());
3732 // Detach the frame between finding and scoping.
3733 EXPECT_TRUE(mainFrame->document().getElementById("frame").remove());
3735 mainFrame->resetMatchCount();
3737 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3738 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3741 EXPECT_TRUE(client.findResultsAreReady());
3744 TEST_F(WebFrameTest, FindDetachFrameWhileScopingStrings)
3746 registerMockedHttpURLLoad("find_in_page.html");
3747 registerMockedHttpURLLoad("find_in_page_frame.html");
3749 FindUpdateWebFrameClient client;
3750 FrameTestHelpers::WebViewHelper webViewHelper;
3751 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3752 webViewHelper.webView()->resize(WebSize(640, 480));
3753 webViewHelper.webView()->layout();
3756 static const char* kFindString = "result";
3757 static const int kFindIdentifier = 12345;
3759 WebFindOptions options;
3760 WebString searchText = WebString::fromUTF8(kFindString);
3761 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3762 WebLocalFrameImpl* secondFrame = toWebLocalFrameImpl(mainFrame->traverseNext(false));
3763 RefPtrWillBeRawPtr<LocalFrame> holdSecondFrame(secondFrame->frame());
3765 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3766 EXPECT_TRUE(frame->find(kFindIdentifier, searchText, options, false, 0));
3769 EXPECT_FALSE(client.findResultsAreReady());
3771 mainFrame->resetMatchCount();
3773 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3774 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3776 // The first scopeStringMatches will have reset the state. Detach before it actually scopes.
3777 EXPECT_TRUE(mainFrame->document().getElementById("frame").remove());
3780 EXPECT_TRUE(client.findResultsAreReady());
3783 TEST_F(WebFrameTest, ResetMatchCount)
3785 registerMockedHttpURLLoad("find_in_generated_frame.html");
3787 FindUpdateWebFrameClient client;
3788 FrameTestHelpers::WebViewHelper webViewHelper;
3789 webViewHelper.initializeAndLoad(m_baseURL + "find_in_generated_frame.html", true, &client);
3790 webViewHelper.webView()->resize(WebSize(640, 480));
3791 webViewHelper.webView()->layout();
3794 static const char* kFindString = "result";
3795 static const int kFindIdentifier = 12345;
3797 WebFindOptions options;
3798 WebString searchText = WebString::fromUTF8(kFindString);
3799 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3801 // Check that child frame exists.
3802 EXPECT_TRUE(!!mainFrame->traverseNext(false));
3804 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false)) {
3805 EXPECT_FALSE(frame->find(kFindIdentifier, searchText, options, false, 0));
3809 EXPECT_FALSE(client.findResultsAreReady());
3811 mainFrame->resetMatchCount();
3814 TEST_F(WebFrameTest, SetTickmarks)
3816 registerMockedHttpURLLoad("find.html");
3818 FindUpdateWebFrameClient client;
3819 FrameTestHelpers::WebViewHelper webViewHelper;
3820 webViewHelper.initializeAndLoad(m_baseURL + "find.html", true, &client);
3821 webViewHelper.webView()->resize(WebSize(640, 480));
3822 webViewHelper.webView()->layout();
3825 static const char* kFindString = "foo";
3826 static const int kFindIdentifier = 12345;
3828 WebFindOptions options;
3829 WebString searchText = WebString::fromUTF8(kFindString);
3830 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3831 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
3833 mainFrame->resetMatchCount();
3834 mainFrame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3837 EXPECT_TRUE(client.findResultsAreReady());
3839 // Get the tickmarks for the original find request.
3840 FrameView* frameView = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
3841 RefPtrWillBeRawPtr<Scrollbar> scrollbar = frameView->createScrollbar(HorizontalScrollbar);
3842 Vector<IntRect> originalTickmarks;
3843 scrollbar->getTickmarks(originalTickmarks);
3844 EXPECT_EQ(4u, originalTickmarks.size());
3846 // Override the tickmarks.
3847 Vector<IntRect> overridingTickmarksExpected;
3848 overridingTickmarksExpected.append(IntRect(0, 0, 100, 100));
3849 overridingTickmarksExpected.append(IntRect(0, 20, 100, 100));
3850 overridingTickmarksExpected.append(IntRect(0, 30, 100, 100));
3851 mainFrame->setTickmarks(overridingTickmarksExpected);
3853 // Check the tickmarks are overriden correctly.
3854 Vector<IntRect> overridingTickmarksActual;
3855 scrollbar->getTickmarks(overridingTickmarksActual);
3856 EXPECT_EQ(overridingTickmarksExpected, overridingTickmarksActual);
3858 // Reset the tickmark behavior.
3859 Vector<IntRect> resetTickmarks;
3860 mainFrame->setTickmarks(resetTickmarks);
3862 // Check that the original tickmarks are returned
3863 Vector<IntRect> originalTickmarksAfterReset;
3864 scrollbar->getTickmarks(originalTickmarksAfterReset);
3865 EXPECT_EQ(originalTickmarks, originalTickmarksAfterReset);
3868 static WebPoint topLeft(const WebRect& rect)
3870 return WebPoint(rect.x, rect.y);
3873 static WebPoint bottomRightMinusOne(const WebRect& rect)
3875 // FIXME: If we don't subtract 1 from the x- and y-coordinates of the
3876 // selection bounds, selectRange() will select the *next* element. That's
3877 // strictly correct, as hit-testing checks the pixel to the lower-right of
3878 // the input coordinate, but it's a wart on the API.
3879 return WebPoint(rect.x + rect.width - 1, rect.y + rect.height - 1);
3882 static WebRect elementBounds(WebFrame* frame, const WebString& id)
3884 return frame->document().getElementById(id).boundsInViewportSpace();
3887 static std::string selectionAsString(WebFrame* frame)
3889 return frame->selectionAsText().utf8();
3892 TEST_F(WebFrameTest, SelectRange)
3895 WebRect startWebRect;
3898 registerMockedHttpURLLoad("select_range_basic.html");
3899 registerMockedHttpURLLoad("select_range_scroll.html");
3901 FrameTestHelpers::WebViewHelper webViewHelper;
3902 initializeTextSelectionWebView(m_baseURL + "select_range_basic.html", &webViewHelper);
3903 frame = webViewHelper.webView()->mainFrame();
3904 EXPECT_EQ("Some test text for testing.", selectionAsString(frame));
3905 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3906 frame->executeCommand(WebString::fromUTF8("Unselect"));
3907 EXPECT_EQ("", selectionAsString(frame));
3908 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3909 EXPECT_EQ("Some test text for testing.", selectionAsString(frame));
3911 initializeTextSelectionWebView(m_baseURL + "select_range_scroll.html", &webViewHelper);
3912 frame = webViewHelper.webView()->mainFrame();
3913 EXPECT_EQ("Some offscreen test text for testing.", selectionAsString(frame));
3914 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3915 frame->executeCommand(WebString::fromUTF8("Unselect"));
3916 EXPECT_EQ("", selectionAsString(frame));
3917 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3918 EXPECT_EQ("Some offscreen test text for testing.", selectionAsString(frame));
3921 TEST_F(WebFrameTest, SelectRangeInIframe)
3924 WebRect startWebRect;
3927 registerMockedHttpURLLoad("select_range_iframe.html");
3928 registerMockedHttpURLLoad("select_range_basic.html");
3930 FrameTestHelpers::WebViewHelper webViewHelper;
3931 initializeTextSelectionWebView(m_baseURL + "select_range_iframe.html", &webViewHelper);
3932 frame = webViewHelper.webView()->mainFrame();
3933 WebFrame* subframe = frame->firstChild();
3934 EXPECT_EQ("Some test text for testing.", selectionAsString(subframe));
3935 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3936 subframe->executeCommand(WebString::fromUTF8("Unselect"));
3937 EXPECT_EQ("", selectionAsString(subframe));
3938 subframe->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3939 EXPECT_EQ("Some test text for testing.", selectionAsString(subframe));
3942 TEST_F(WebFrameTest, SelectRangeDivContentEditable)
3945 WebRect startWebRect;
3948 registerMockedHttpURLLoad("select_range_div_editable.html");
3950 // Select the middle of an editable element, then try to extend the selection to the top of the document.
3951 // The selection range should be clipped to the bounds of the editable element.
3952 FrameTestHelpers::WebViewHelper webViewHelper;
3953 initializeTextSelectionWebView(m_baseURL + "select_range_div_editable.html", &webViewHelper);
3954 frame = webViewHelper.webView()->mainFrame();
3955 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3956 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3958 frame->selectRange(bottomRightMinusOne(endWebRect), WebPoint(0, 0));
3959 EXPECT_EQ("16-char header. This text is initially selected.", selectionAsString(frame));
3961 // As above, but extending the selection to the bottom of the document.
3962 initializeTextSelectionWebView(m_baseURL + "select_range_div_editable.html", &webViewHelper);
3963 frame = webViewHelper.webView()->mainFrame();
3965 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3966 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3967 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3968 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3970 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3971 frame->selectRange(topLeft(startWebRect), WebPoint(640, 480));
3972 EXPECT_EQ("This text is initially selected. 16-char footer.", selectionAsString(frame));
3975 // positionForPoint returns the wrong values for contenteditable spans. See
3976 // http://crbug.com/238334.
3977 TEST_F(WebFrameTest, DISABLED_SelectRangeSpanContentEditable)
3980 WebRect startWebRect;
3983 registerMockedHttpURLLoad("select_range_span_editable.html");
3985 // Select the middle of an editable element, then try to extend the selection to the top of the document.
3986 // The selection range should be clipped to the bounds of the editable element.
3987 FrameTestHelpers::WebViewHelper webViewHelper;
3988 initializeTextSelectionWebView(m_baseURL + "select_range_span_editable.html", &webViewHelper);
3989 frame = webViewHelper.webView()->mainFrame();
3990 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3991 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3993 frame->selectRange(bottomRightMinusOne(endWebRect), WebPoint(0, 0));
3994 EXPECT_EQ("16-char header. This text is initially selected.", selectionAsString(frame));
3996 // As above, but extending the selection to the bottom of the document.
3997 initializeTextSelectionWebView(m_baseURL + "select_range_span_editable.html", &webViewHelper);
3998 frame = webViewHelper.webView()->mainFrame();
4000 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
4001 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
4002 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
4003 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
4005 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
4006 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
4007 frame->selectRange(topLeft(startWebRect), WebPoint(640, 480));
4008 EXPECT_EQ("This text is initially selected. 16-char footer.", selectionAsString(frame));
4011 TEST_F(WebFrameTest, SelectRangeCanMoveSelectionStart)
4013 registerMockedHttpURLLoad("text_selection.html");
4014 FrameTestHelpers::WebViewHelper webViewHelper;
4015 initializeTextSelectionWebView(m_baseURL + "text_selection.html", &webViewHelper);
4016 WebFrame* frame = webViewHelper.webView()->mainFrame();
4018 // Select second span. We can move the start to include the first span.
4019 frame->executeScript(WebScriptSource("selectElement('header_2');"));
4020 EXPECT_EQ("Header 2.", selectionAsString(frame));
4021 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "header_2")), topLeft(elementBounds(frame, "header_1")));
4022 EXPECT_EQ("Header 1. Header 2.", selectionAsString(frame));
4024 // We can move the start and end together.
4025 frame->executeScript(WebScriptSource("selectElement('header_1');"));
4026 EXPECT_EQ("Header 1.", selectionAsString(frame));
4027 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "header_1")));
4028 EXPECT_EQ("", selectionAsString(frame));
4029 // Selection is a caret, not empty.
4030 EXPECT_FALSE(frame->selectionRange().isNull());
4032 // We can move the start across the end.
4033 frame->executeScript(WebScriptSource("selectElement('header_1');"));
4034 EXPECT_EQ("Header 1.", selectionAsString(frame));
4035 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "header_2")));
4036 EXPECT_EQ(" Header 2.", selectionAsString(frame));
4038 // Can't extend the selection part-way into an editable element.
4039 frame->executeScript(WebScriptSource("selectElement('footer_2');"));
4040 EXPECT_EQ("Footer 2.", selectionAsString(frame));
4041 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "footer_2")), topLeft(elementBounds(frame, "editable_2")));
4042 EXPECT_EQ(" [ Footer 1. Footer 2.", selectionAsString(frame));
4044 // Can extend the selection completely across editable elements.
4045 frame->executeScript(WebScriptSource("selectElement('footer_2');"));
4046 EXPECT_EQ("Footer 2.", selectionAsString(frame));
4047 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "footer_2")), topLeft(elementBounds(frame, "header_2")));
4048 EXPECT_EQ("Header 2. ] [ Editable 1. Editable 2. ] [ Footer 1. Footer 2.", selectionAsString(frame));
4050 // If the selection is editable text, we can't extend it into non-editable text.
4051 frame->executeScript(WebScriptSource("selectElement('editable_2');"));
4052 EXPECT_EQ("Editable 2.", selectionAsString(frame));
4053 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "editable_2")), topLeft(elementBounds(frame, "header_2")));
4054 // positionForPoint returns the wrong values for contenteditable spans. See
4055 // http://crbug.com/238334.
4056 // EXPECT_EQ("[ Editable 1. Editable 2.", selectionAsString(frame));
4059 TEST_F(WebFrameTest, SelectRangeCanMoveSelectionEnd)
4061 registerMockedHttpURLLoad("text_selection.html");
4062 FrameTestHelpers::WebViewHelper webViewHelper;
4063 initializeTextSelectionWebView(m_baseURL + "text_selection.html", &webViewHelper);
4064 WebFrame* frame = webViewHelper.webView()->mainFrame();
4066 // Select first span. We can move the end to include the second span.
4067 frame->executeScript(WebScriptSource("selectElement('header_1');"));
4068 EXPECT_EQ("Header 1.", selectionAsString(frame));
4069 frame->selectRange(topLeft(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "header_2")));
4070 EXPECT_EQ("Header 1. Header 2.", selectionAsString(frame));
4072 // We can move the start and end together.
4073 frame->executeScript(WebScriptSource("selectElement('header_2');"));
4074 EXPECT_EQ("Header 2.", selectionAsString(frame));
4075 frame->selectRange(topLeft(elementBounds(frame, "header_2")), topLeft(elementBounds(frame, "header_2")));
4076 EXPECT_EQ("", selectionAsString(frame));
4077 // Selection is a caret, not empty.
4078 EXPECT_FALSE(frame->selectionRange().isNull());
4080 // We can move the end across the start.
4081 frame->executeScript(WebScriptSource("selectElement('header_2');"));
4082 EXPECT_EQ("Header 2.", selectionAsString(frame));
4083 frame->selectRange(topLeft(elementBounds(frame, "header_2")), topLeft(elementBounds(frame, "header_1")));
4084 EXPECT_EQ("Header 1. ", selectionAsString(frame));
4086 // Can't extend the selection part-way into an editable element.
4087 frame->executeScript(WebScriptSource("selectElement('header_1');"));
4088 EXPECT_EQ("Header 1.", selectionAsString(frame));
4089 frame->selectRange(topLeft(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "editable_1")));
4090 EXPECT_EQ("Header 1. Header 2. ] ", selectionAsString(frame));
4092 // Can extend the selection completely across editable elements.
4093 frame->executeScript(WebScriptSource("selectElement('header_1');"));
4094 EXPECT_EQ("Header 1.", selectionAsString(frame));
4095 frame->selectRange(topLeft(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "footer_1")));
4096 EXPECT_EQ("Header 1. Header 2. ] [ Editable 1. Editable 2. ] [ Footer 1.", selectionAsString(frame));
4098 // If the selection is editable text, we can't extend it into non-editable text.
4099 frame->executeScript(WebScriptSource("selectElement('editable_1');"));
4100 EXPECT_EQ("Editable 1.", selectionAsString(frame));
4101 frame->selectRange(topLeft(elementBounds(frame, "editable_1")), bottomRightMinusOne(elementBounds(frame, "footer_1")));
4102 // positionForPoint returns the wrong values for contenteditable spans. See
4103 // http://crbug.com/238334.
4104 // EXPECT_EQ("Editable 1. Editable 2. ]", selectionAsString(frame));
4107 TEST_F(WebFrameTest, MoveRangeSelectionExtent)
4109 WebLocalFrameImpl* frame;
4110 WebRect startWebRect;
4113 registerMockedHttpURLLoad("move_range_selection_extent.html");
4115 FrameTestHelpers::WebViewHelper webViewHelper;
4116 initializeTextSelectionWebView(m_baseURL + "move_range_selection_extent.html", &webViewHelper);
4117 frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4118 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
4119 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
4121 frame->moveRangeSelectionExtent(WebPoint(640, 480));
4122 EXPECT_EQ("This text is initially selected. 16-char footer.", selectionAsString(frame));
4124 frame->moveRangeSelectionExtent(WebPoint(0, 0));
4125 EXPECT_EQ("16-char header. ", selectionAsString(frame));
4127 // Reset with swapped base and extent.
4128 frame->selectRange(topLeft(endWebRect), bottomRightMinusOne(startWebRect));
4129 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
4131 frame->moveRangeSelectionExtent(WebPoint(640, 480));
4132 EXPECT_EQ(" 16-char footer.", selectionAsString(frame));
4134 frame->moveRangeSelectionExtent(WebPoint(0, 0));
4135 EXPECT_EQ("16-char header. This text is initially selected.", selectionAsString(frame));
4137 frame->executeCommand(WebString::fromUTF8("Unselect"));
4138 EXPECT_EQ("", selectionAsString(frame));
4141 TEST_F(WebFrameTest, MoveRangeSelectionExtentCannotCollapse)
4143 WebLocalFrameImpl* frame;
4144 WebRect startWebRect;
4147 registerMockedHttpURLLoad("move_range_selection_extent.html");
4149 FrameTestHelpers::WebViewHelper webViewHelper;
4150 initializeTextSelectionWebView(m_baseURL + "move_range_selection_extent.html", &webViewHelper);
4151 frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4152 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
4153 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
4155 frame->moveRangeSelectionExtent(bottomRightMinusOne(startWebRect));
4156 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
4158 // Reset with swapped base and extent.
4159 frame->selectRange(topLeft(endWebRect), bottomRightMinusOne(startWebRect));
4160 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
4162 frame->moveRangeSelectionExtent(bottomRightMinusOne(endWebRect));
4163 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
4166 static int computeOffset(RenderObject* renderer, int x, int y)
4168 return VisiblePosition(renderer->positionForPoint(LayoutPoint(x, y))).deepEquivalent().computeOffsetInContainerNode();
4171 // positionForPoint returns the wrong values for contenteditable spans. See
4172 // http://crbug.com/238334.
4173 TEST_F(WebFrameTest, DISABLED_PositionForPointTest)
4175 registerMockedHttpURLLoad("select_range_span_editable.html");
4176 FrameTestHelpers::WebViewHelper webViewHelper;
4177 initializeTextSelectionWebView(m_baseURL + "select_range_span_editable.html", &webViewHelper);
4178 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4179 RenderObject* renderer = mainFrame->frame()->selection().rootEditableElement()->renderer();
4180 EXPECT_EQ(0, computeOffset(renderer, -1, -1));
4181 EXPECT_EQ(64, computeOffset(renderer, 1000, 1000));
4183 registerMockedHttpURLLoad("select_range_div_editable.html");
4184 initializeTextSelectionWebView(m_baseURL + "select_range_div_editable.html", &webViewHelper);
4185 mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4186 renderer = mainFrame->frame()->selection().rootEditableElement()->renderer();
4187 EXPECT_EQ(0, computeOffset(renderer, -1, -1));
4188 EXPECT_EQ(64, computeOffset(renderer, 1000, 1000));
4191 #if !OS(MACOSX) && !OS(LINUX)
4192 TEST_F(WebFrameTest, SelectRangeStaysHorizontallyAlignedWhenMoved)
4194 registerMockedHttpURLLoad("move_caret.html");
4196 FrameTestHelpers::WebViewHelper webViewHelper;
4197 initializeTextSelectionWebView(m_baseURL + "move_caret.html", &webViewHelper);
4198 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4200 WebRect initialStartRect;
4201 WebRect initialEndRect;
4205 frame->executeScript(WebScriptSource("selectRange();"));
4206 webViewHelper.webView()->selectionBounds(initialStartRect, initialEndRect);
4207 WebPoint movedStart(topLeft(initialStartRect));
4210 frame->selectRange(movedStart, bottomRightMinusOne(initialEndRect));
4211 webViewHelper.webView()->selectionBounds(startRect, endRect);
4212 EXPECT_EQ(startRect, initialStartRect);
4213 EXPECT_EQ(endRect, initialEndRect);
4216 frame->selectRange(movedStart, bottomRightMinusOne(initialEndRect));
4217 webViewHelper.webView()->selectionBounds(startRect, endRect);
4218 EXPECT_EQ(startRect, initialStartRect);
4219 EXPECT_EQ(endRect, initialEndRect);
4221 WebPoint movedEnd(bottomRightMinusOne(initialEndRect));
4224 frame->selectRange(topLeft(initialStartRect), movedEnd);
4225 webViewHelper.webView()->selectionBounds(startRect, endRect);
4226 EXPECT_EQ(startRect, initialStartRect);
4227 EXPECT_EQ(endRect, initialEndRect);
4230 frame->selectRange(topLeft(initialStartRect), movedEnd);
4231 webViewHelper.webView()->selectionBounds(startRect, endRect);
4232 EXPECT_EQ(startRect, initialStartRect);
4233 EXPECT_EQ(endRect, initialEndRect);
4236 TEST_F(WebFrameTest, MoveCaretStaysHorizontallyAlignedWhenMoved)
4238 WebLocalFrameImpl* frame;
4239 registerMockedHttpURLLoad("move_caret.html");
4241 FrameTestHelpers::WebViewHelper webViewHelper;
4242 initializeTextSelectionWebView(m_baseURL + "move_caret.html", &webViewHelper);
4243 frame = (WebLocalFrameImpl*)webViewHelper.webView()->mainFrame();
4245 WebRect initialStartRect;
4246 WebRect initialEndRect;
4250 frame->executeScript(WebScriptSource("selectCaret();"));
4251 webViewHelper.webView()->selectionBounds(initialStartRect, initialEndRect);
4252 WebPoint moveTo(topLeft(initialStartRect));
4255 frame->moveCaretSelection(moveTo);
4256 webViewHelper.webView()->selectionBounds(startRect, endRect);
4257 EXPECT_EQ(startRect, initialStartRect);
4258 EXPECT_EQ(endRect, initialEndRect);
4261 frame->moveCaretSelection(moveTo);
4262 webViewHelper.webView()->selectionBounds(startRect, endRect);
4263 EXPECT_EQ(startRect, initialStartRect);
4264 EXPECT_EQ(endRect, initialEndRect);
4268 class CompositedSelectionBoundsTestLayerTreeView : public WebLayerTreeView {
4270 CompositedSelectionBoundsTestLayerTreeView() : m_selectionCleared(false) { }
4271 virtual ~CompositedSelectionBoundsTestLayerTreeView() { }
4273 virtual void setSurfaceReady() override { }
4274 virtual void setRootLayer(const WebLayer&) override { }
4275 virtual void clearRootLayer() override { }
4276 virtual void setViewportSize(const WebSize& deviceViewportSize) override { }
4277 virtual WebSize deviceViewportSize() const override { return WebSize(); }
4278 virtual void setDeviceScaleFactor(float) override { }
4279 virtual float deviceScaleFactor() const override { return 1.f; }
4280 virtual void setBackgroundColor(WebColor) override { }
4281 virtual void setHasTransparentBackground(bool) override { }
4282 virtual void setVisible(bool) override { }
4283 virtual void setPageScaleFactorAndLimits(float pageScaleFactor, float minimum, float maximum) override { }
4284 virtual void startPageScaleAnimation(const WebPoint& destination, bool useAnchor, float newPageScale, double durationSec) override { }
4285 virtual void setNeedsAnimate() override { }
4286 virtual bool commitRequested() const override { return false; }
4287 virtual void finishAllRendering() override { }
4288 virtual void registerSelection(const WebSelectionBound& start, const WebSelectionBound& end) override
4290 m_start = adoptPtr(new WebSelectionBound(start));
4291 m_end = adoptPtr(new WebSelectionBound(end));
4293 virtual void clearSelection() override
4295 m_selectionCleared = true;
4300 bool getAndResetSelectionCleared()
4302 bool selectionCleared = m_selectionCleared;
4303 m_selectionCleared = false;
4304 return selectionCleared;
4307 const WebSelectionBound* start() const { return m_start.get(); }
4308 const WebSelectionBound* end() const { return m_end.get(); }
4311 bool m_selectionCleared;
4312 OwnPtr<WebSelectionBound> m_start;
4313 OwnPtr<WebSelectionBound> m_end;
4316 class CompositedSelectionBoundsTestWebViewClient : public FrameTestHelpers::TestWebViewClient {
4318 virtual ~CompositedSelectionBoundsTestWebViewClient() { }
4319 virtual WebLayerTreeView* layerTreeView() override { return &m_testLayerTreeView; }
4321 CompositedSelectionBoundsTestLayerTreeView& selectionLayerTreeView() { return m_testLayerTreeView; }
4324 CompositedSelectionBoundsTestLayerTreeView m_testLayerTreeView;
4327 class CompositedSelectionBoundsTest : public WebFrameTest {
4329 CompositedSelectionBoundsTest()
4330 : m_fakeSelectionLayerTreeView(m_fakeSelectionWebViewClient.selectionLayerTreeView())
4332 blink::RuntimeEnabledFeatures::setCompositedSelectionUpdateEnabled(true);
4333 registerMockedHttpURLLoad("Ahem.ttf");
4335 m_webViewHelper.initialize(true, 0, &m_fakeSelectionWebViewClient);
4336 m_webViewHelper.webView()->settings()->setDefaultFontSize(12);
4337 m_webViewHelper.webView()->setPageScaleFactorLimits(1, 1);
4338 m_webViewHelper.webView()->resize(WebSize(640, 480));
4341 void runTest(const char* testFile)
4343 registerMockedHttpURLLoad(testFile);
4344 FrameTestHelpers::loadFrame(m_webViewHelper.webView()->mainFrame(), m_baseURL + testFile);
4345 m_webViewHelper.webView()->layout();
4347 const WebSelectionBound* selectStart = m_fakeSelectionLayerTreeView.start();
4348 const WebSelectionBound* selectEnd = m_fakeSelectionLayerTreeView.end();
4350 v8::HandleScope handleScope(v8::Isolate::GetCurrent());
4351 v8::Handle<v8::Value> result = m_webViewHelper.webView()->mainFrame()->toWebLocalFrame()->executeScriptAndReturnValueForTests(WebScriptSource("expectedResult"));
4352 if (result.IsEmpty() || (*result)->IsUndefined()) {
4353 EXPECT_FALSE(selectStart);
4354 EXPECT_FALSE(selectEnd);
4358 ASSERT_TRUE(selectStart);
4359 ASSERT_TRUE(selectEnd);
4361 ASSERT_TRUE((*result)->IsArray());
4362 v8::Array& expectedResult = *v8::Array::Cast(*result);
4363 ASSERT_EQ(10u, expectedResult.Length());
4365 blink::Node* layerOwnerNodeForStart = blink::V8Node::toImplWithTypeCheck(v8::Isolate::GetCurrent(), expectedResult.Get(0));
4366 ASSERT_TRUE(layerOwnerNodeForStart);
4367 EXPECT_EQ(layerOwnerNodeForStart->renderer()->enclosingLayer()->enclosingLayerForPaintInvalidation()->graphicsLayerBacking()->platformLayer()->id(), selectStart->layerId);
4368 EXPECT_EQ(expectedResult.Get(1)->Int32Value(), selectStart->edgeTopInLayer.x);
4369 EXPECT_EQ(expectedResult.Get(2)->Int32Value(), selectStart->edgeTopInLayer.y);
4370 EXPECT_EQ(expectedResult.Get(3)->Int32Value(), selectStart->edgeBottomInLayer.x);
4371 EXPECT_EQ(expectedResult.Get(4)->Int32Value(), selectStart->edgeBottomInLayer.y);
4373 blink::Node* layerOwnerNodeForEnd = blink::V8Node::toImplWithTypeCheck(v8::Isolate::GetCurrent(), expectedResult.Get(5));
4374 ASSERT_TRUE(layerOwnerNodeForEnd);
4375 EXPECT_EQ(layerOwnerNodeForEnd->renderer()->enclosingLayer()->enclosingLayerForPaintInvalidation()->graphicsLayerBacking()->platformLayer()->id(), selectEnd->layerId);
4376 EXPECT_EQ(expectedResult.Get(6)->Int32Value(), selectEnd->edgeTopInLayer.x);
4377 EXPECT_EQ(expectedResult.Get(7)->Int32Value(), selectEnd->edgeTopInLayer.y);
4378 EXPECT_EQ(expectedResult.Get(8)->Int32Value(), selectEnd->edgeBottomInLayer.x);
4379 EXPECT_EQ(expectedResult.Get(9)->Int32Value(), selectEnd->edgeBottomInLayer.y);
4382 void runTestWithMultipleFiles(const char* testFile, ...)
4385 va_start(auxFiles, testFile);
4386 while (const char* auxFile = va_arg(auxFiles, const char*))
4387 registerMockedHttpURLLoad(auxFile);
4393 CompositedSelectionBoundsTestWebViewClient m_fakeSelectionWebViewClient;
4394 CompositedSelectionBoundsTestLayerTreeView& m_fakeSelectionLayerTreeView;
4395 FrameTestHelpers::WebViewHelper m_webViewHelper;
4398 TEST_F(CompositedSelectionBoundsTest, None) { runTest("composited_selection_bounds_none.html"); }
4399 TEST_F(CompositedSelectionBoundsTest, Basic) { runTest("composited_selection_bounds_basic.html"); }
4400 TEST_F(CompositedSelectionBoundsTest, Transformed) { runTest("composited_selection_bounds_transformed.html"); }
4401 TEST_F(CompositedSelectionBoundsTest, SplitLayer) { runTest("composited_selection_bounds_split_layer.html"); }
4402 TEST_F(CompositedSelectionBoundsTest, EmptyLayer) { runTest("composited_selection_bounds_empty_layer.html"); }
4403 TEST_F(CompositedSelectionBoundsTest, Iframe) { runTestWithMultipleFiles("composited_selection_bounds_iframe.html", "composited_selection_bounds_basic.html", nullptr); }
4405 TEST_F(WebFrameTest, CompositedSelectionBoundsCleared)
4407 RuntimeEnabledFeatures::setCompositedSelectionUpdateEnabled(true);
4409 registerMockedHttpURLLoad("select_range_basic.html");
4410 registerMockedHttpURLLoad("select_range_scroll.html");
4412 int viewWidth = 500;
4413 int viewHeight = 500;
4415 CompositedSelectionBoundsTestWebViewClient fakeSelectionWebViewClient;
4416 CompositedSelectionBoundsTestLayerTreeView& fakeSelectionLayerTreeView = fakeSelectionWebViewClient.selectionLayerTreeView();
4418 FrameTestHelpers::WebViewHelper webViewHelper;
4419 webViewHelper.initialize(true, 0, &fakeSelectionWebViewClient);
4420 webViewHelper.webView()->settings()->setDefaultFontSize(12);
4421 webViewHelper.webView()->setPageScaleFactorLimits(1, 1);
4422 webViewHelper.webView()->resize(WebSize(viewWidth, viewHeight));
4423 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "select_range_basic.html");
4425 // The frame starts with a non-empty selection.
4426 WebFrame* frame = webViewHelper.webView()->mainFrame();
4427 ASSERT_TRUE(frame->hasSelection());
4428 EXPECT_FALSE(fakeSelectionLayerTreeView.getAndResetSelectionCleared());
4430 // The selection cleared notification should be triggered upon layout.
4431 frame->executeCommand(WebString::fromUTF8("Unselect"));
4432 ASSERT_FALSE(frame->hasSelection());
4433 EXPECT_FALSE(fakeSelectionLayerTreeView.getAndResetSelectionCleared());
4434 webViewHelper.webView()->layout();
4435 EXPECT_TRUE(fakeSelectionLayerTreeView.getAndResetSelectionCleared());
4437 frame->executeCommand(WebString::fromUTF8("SelectAll"));
4438 webViewHelper.webView()->layout();
4439 ASSERT_TRUE(frame->hasSelection());
4440 EXPECT_FALSE(fakeSelectionLayerTreeView.getAndResetSelectionCleared());
4442 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "select_range_scroll.html");
4443 ASSERT_TRUE(frame->hasSelection());
4444 EXPECT_FALSE(fakeSelectionLayerTreeView.getAndResetSelectionCleared());
4446 // Transitions between non-empty selections should not trigger a clearing.
4447 WebRect startWebRect;
4449 webViewHelper.webViewImpl()->selectionBounds(startWebRect, endWebRect);
4450 WebPoint movedEnd(bottomRightMinusOne(endWebRect));
4452 frame->selectRange(topLeft(startWebRect), movedEnd);
4453 webViewHelper.webView()->layout();
4454 ASSERT_TRUE(frame->hasSelection());
4455 EXPECT_FALSE(fakeSelectionLayerTreeView.getAndResetSelectionCleared());
4457 frame = webViewHelper.webView()->mainFrame();
4458 frame->executeCommand(WebString::fromUTF8("Unselect"));
4459 webViewHelper.webView()->layout();
4460 ASSERT_FALSE(frame->hasSelection());
4461 EXPECT_TRUE(fakeSelectionLayerTreeView.getAndResetSelectionCleared());
4464 class DisambiguationPopupTestWebViewClient : public FrameTestHelpers::TestWebViewClient {
4466 virtual bool didTapMultipleTargets(const WebSize&, const WebRect&, const WebVector<WebRect>& targetRects) override
4468 EXPECT_GE(targetRects.size(), 2u);
4473 bool triggered() const { return m_triggered; }
4474 void resetTriggered() { m_triggered = false; }
4478 static WebGestureEvent fatTap(int x, int y)
4480 WebGestureEvent event;
4481 event.type = WebInputEvent::GestureTap;
4484 event.data.tap.width = 50;
4485 event.data.tap.height = 50;
4489 TEST_F(WebFrameTest, DisambiguationPopup)
4491 const std::string htmlFile = "disambiguation_popup.html";
4492 registerMockedHttpURLLoad(htmlFile);
4494 DisambiguationPopupTestWebViewClient client;
4496 // Make sure we initialize to minimum scale, even if the window size
4497 // only becomes available after the load begins.
4498 FrameTestHelpers::WebViewHelper webViewHelper;
4499 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client);
4500 webViewHelper.webView()->resize(WebSize(1000, 1000));
4501 webViewHelper.webView()->layout();
4503 client.resetTriggered();
4504 webViewHelper.webView()->handleInputEvent(fatTap(0, 0));
4505 EXPECT_FALSE(client.triggered());
4507 client.resetTriggered();
4508 webViewHelper.webView()->handleInputEvent(fatTap(200, 115));
4509 EXPECT_FALSE(client.triggered());
4511 for (int i = 0; i <= 46; i++) {
4512 client.resetTriggered();
4513 webViewHelper.webView()->handleInputEvent(fatTap(120, 230 + i * 5));
4516 if (j >= 7 && j <= 9)
4517 EXPECT_TRUE(client.triggered());
4519 EXPECT_FALSE(client.triggered());
4522 for (int i = 0; i <= 46; i++) {
4523 client.resetTriggered();
4524 webViewHelper.webView()->handleInputEvent(fatTap(10 + i * 5, 590));
4527 if (j >= 7 && j <= 9)
4528 EXPECT_TRUE(client.triggered());
4530 EXPECT_FALSE(client.triggered());
4534 TEST_F(WebFrameTest, DisambiguationPopupNoContainer)
4536 registerMockedHttpURLLoad("disambiguation_popup_no_container.html");
4538 DisambiguationPopupTestWebViewClient client;
4540 // Make sure we initialize to minimum scale, even if the window size
4541 // only becomes available after the load begins.
4542 FrameTestHelpers::WebViewHelper webViewHelper;
4543 webViewHelper.initializeAndLoad(m_baseURL + "disambiguation_popup_no_container.html", true, 0, &client);
4544 webViewHelper.webView()->resize(WebSize(1000, 1000));
4545 webViewHelper.webView()->layout();
4547 client.resetTriggered();
4548 webViewHelper.webView()->handleInputEvent(fatTap(50, 50));
4549 EXPECT_FALSE(client.triggered());
4552 TEST_F(WebFrameTest, DisambiguationPopupMobileSite)
4554 UseMockScrollbarSettings mockScrollbarSettings;
4555 const std::string htmlFile = "disambiguation_popup_mobile_site.html";
4556 registerMockedHttpURLLoad(htmlFile);
4558 DisambiguationPopupTestWebViewClient client;
4560 // Make sure we initialize to minimum scale, even if the window size
4561 // only becomes available after the load begins.
4562 FrameTestHelpers::WebViewHelper webViewHelper;
4563 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client, enableViewportSettings);
4564 webViewHelper.webView()->resize(WebSize(1000, 1000));
4565 webViewHelper.webView()->layout();
4567 client.resetTriggered();
4568 webViewHelper.webView()->handleInputEvent(fatTap(0, 0));
4569 EXPECT_FALSE(client.triggered());
4571 client.resetTriggered();
4572 webViewHelper.webView()->handleInputEvent(fatTap(200, 115));
4573 EXPECT_FALSE(client.triggered());
4575 for (int i = 0; i <= 46; i++) {
4576 client.resetTriggered();
4577 webViewHelper.webView()->handleInputEvent(fatTap(120, 230 + i * 5));
4578 EXPECT_FALSE(client.triggered());
4581 for (int i = 0; i <= 46; i++) {
4582 client.resetTriggered();
4583 webViewHelper.webView()->handleInputEvent(fatTap(10 + i * 5, 590));
4584 EXPECT_FALSE(client.triggered());
4588 TEST_F(WebFrameTest, DisambiguationPopupViewportSite)
4590 UseMockScrollbarSettings mockScrollbarSettings;
4591 const std::string htmlFile = "disambiguation_popup_viewport_site.html";
4592 registerMockedHttpURLLoad(htmlFile);
4594 DisambiguationPopupTestWebViewClient client;
4596 // Make sure we initialize to minimum scale, even if the window size
4597 // only becomes available after the load begins.
4598 FrameTestHelpers::WebViewHelper webViewHelper;
4599 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client, enableViewportSettings);
4600 webViewHelper.webView()->resize(WebSize(1000, 1000));
4601 webViewHelper.webView()->layout();
4603 client.resetTriggered();
4604 webViewHelper.webView()->handleInputEvent(fatTap(0, 0));
4605 EXPECT_FALSE(client.triggered());
4607 client.resetTriggered();
4608 webViewHelper.webView()->handleInputEvent(fatTap(200, 115));
4609 EXPECT_FALSE(client.triggered());
4611 for (int i = 0; i <= 46; i++) {
4612 client.resetTriggered();
4613 webViewHelper.webView()->handleInputEvent(fatTap(120, 230 + i * 5));
4614 EXPECT_FALSE(client.triggered());
4617 for (int i = 0; i <= 46; i++) {
4618 client.resetTriggered();
4619 webViewHelper.webView()->handleInputEvent(fatTap(10 + i * 5, 590));
4620 EXPECT_FALSE(client.triggered());
4624 TEST_F(WebFrameTest, DisambiguationPopupPinchViewport)
4626 UseMockScrollbarSettings mockScrollbarSettings;
4627 const std::string htmlFile = "disambiguation_popup_200_by_800.html";
4628 registerMockedHttpURLLoad(htmlFile);
4630 DisambiguationPopupTestWebViewClient client;
4632 FrameTestHelpers::WebViewHelper webViewHelper;
4633 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client, configurePinchVirtualViewport);
4635 WebViewImpl* webViewImpl = webViewHelper.webViewImpl();
4636 ASSERT_TRUE(webViewImpl);
4637 LocalFrame* frame = webViewImpl->mainFrameImpl()->frame();
4640 webViewHelper.webView()->resize(WebSize(100, 200));
4642 // Scroll main frame to the bottom of the document
4643 webViewImpl->setMainFrameScrollOffset(WebPoint(0, 400));
4644 EXPECT_POINT_EQ(IntPoint(0, 400), frame->view()->scrollPosition());
4646 webViewImpl->setPageScaleFactor(2.0);
4648 // Scroll pinch viewport to the top of the main frame.
4649 PinchViewport& pinchViewport = frame->page()->frameHost().pinchViewport();
4650 pinchViewport.setLocation(FloatPoint(0, 0));
4651 EXPECT_FLOAT_POINT_EQ(FloatPoint(0, 0), pinchViewport.location());
4653 // Tap at the top: there is nothing there.
4654 client.resetTriggered();
4655 webViewHelper.webView()->handleInputEvent(fatTap(10, 60));
4656 EXPECT_FALSE(client.triggered());
4658 // Scroll pinch viewport to the bottom of the main frame.
4659 pinchViewport.setLocation(FloatPoint(0, 200));
4660 EXPECT_FLOAT_POINT_EQ(FloatPoint(0, 200), pinchViewport.location());
4662 // Now the tap with the same coordinates should hit two elements.
4663 client.resetTriggered();
4664 webViewHelper.webView()->handleInputEvent(fatTap(10, 60));
4665 EXPECT_TRUE(client.triggered());
4668 TEST_F(WebFrameTest, DisambiguationPopupBlacklist)
4670 const unsigned viewportWidth = 500;
4671 const unsigned viewportHeight = 1000;
4672 const unsigned divHeight = 100;
4673 const std::string htmlFile = "disambiguation_popup_blacklist.html";
4674 registerMockedHttpURLLoad(htmlFile);
4676 DisambiguationPopupTestWebViewClient client;
4678 // Make sure we initialize to minimum scale, even if the window size
4679 // only becomes available after the load begins.
4680 FrameTestHelpers::WebViewHelper webViewHelper;
4681 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client);
4682 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
4683 webViewHelper.webView()->layout();
4685 // Click somewhere where the popup shouldn't appear.
4686 client.resetTriggered();
4687 webViewHelper.webView()->handleInputEvent(fatTap(viewportWidth / 2, 0));
4688 EXPECT_FALSE(client.triggered());
4690 // Click directly in between two container divs with click handlers, with children that don't handle clicks.
4691 client.resetTriggered();
4692 webViewHelper.webView()->handleInputEvent(fatTap(viewportWidth / 2, divHeight));
4693 EXPECT_TRUE(client.triggered());
4695 // The third div container should be blacklisted if you click on the link it contains.
4696 client.resetTriggered();
4697 webViewHelper.webView()->handleInputEvent(fatTap(viewportWidth / 2, divHeight * 3.25));
4698 EXPECT_FALSE(client.triggered());
4701 TEST_F(WebFrameTest, DisambiguationPopupPageScale)
4703 registerMockedHttpURLLoad("disambiguation_popup_page_scale.html");
4705 DisambiguationPopupTestWebViewClient client;
4707 // Make sure we initialize to minimum scale, even if the window size
4708 // only becomes available after the load begins.
4709 FrameTestHelpers::WebViewHelper webViewHelper;
4710 webViewHelper.initializeAndLoad(m_baseURL + "disambiguation_popup_page_scale.html", true, 0, &client);
4711 webViewHelper.webView()->resize(WebSize(1000, 1000));
4712 webViewHelper.webView()->layout();
4714 client.resetTriggered();
4715 webViewHelper.webView()->handleInputEvent(fatTap(80, 80));
4716 EXPECT_TRUE(client.triggered());
4718 client.resetTriggered();
4719 webViewHelper.webView()->handleInputEvent(fatTap(230, 190));
4720 EXPECT_TRUE(client.triggered());
4722 webViewHelper.webView()->setPageScaleFactor(3.0f);
4723 webViewHelper.webView()->layout();
4725 client.resetTriggered();
4726 webViewHelper.webView()->handleInputEvent(fatTap(240, 240));
4727 EXPECT_TRUE(client.triggered());
4729 client.resetTriggered();
4730 webViewHelper.webView()->handleInputEvent(fatTap(690, 570));
4731 EXPECT_FALSE(client.triggered());
4734 class TestSubstituteDataWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
4736 TestSubstituteDataWebFrameClient()
4737 : m_commitCalled(false)
4741 virtual void didFailProvisionalLoad(WebLocalFrame* frame, const WebURLError& error)
4743 frame->loadHTMLString("This should appear", toKURL("data:text/html,chromewebdata"), error.unreachableURL, true);
4746 virtual void didCommitProvisionalLoad(WebLocalFrame* frame, const WebHistoryItem&, WebHistoryCommitType)
4748 if (frame->dataSource()->response().url() != WebURL(URLTestHelpers::toKURL("about:blank")))
4749 m_commitCalled = true;
4752 bool commitCalled() const { return m_commitCalled; }
4755 bool m_commitCalled;
4758 TEST_F(WebFrameTest, ReplaceNavigationAfterHistoryNavigation)
4760 TestSubstituteDataWebFrameClient webFrameClient;
4762 FrameTestHelpers::WebViewHelper webViewHelper;
4763 webViewHelper.initializeAndLoad("about:blank", true, &webFrameClient);
4764 WebFrame* frame = webViewHelper.webView()->mainFrame();
4766 // Load a url as a history navigation that will return an error. TestSubstituteDataWebFrameClient
4767 // will start a SubstituteData load in response to the load failure, which should get fully committed.
4768 // Due to https://bugs.webkit.org/show_bug.cgi?id=91685, FrameLoader::didReceiveData() wasn't getting
4769 // called in this case, which resulted in the SubstituteData document not getting displayed.
4771 error.reason = 1337;
4772 error.domain = "WebFrameTest";
4773 std::string errorURL = "http://0.0.0.0";
4774 WebURLResponse response;
4775 response.initialize();
4776 response.setURL(URLTestHelpers::toKURL(errorURL));
4777 response.setMIMEType("text/html");
4778 response.setHTTPStatusCode(500);
4779 WebHistoryItem errorHistoryItem;
4780 errorHistoryItem.initialize();
4781 errorHistoryItem.setURLString(WebString::fromUTF8(errorURL.c_str(), errorURL.length()));
4782 Platform::current()->unitTestSupport()->registerMockedErrorURL(URLTestHelpers::toKURL(errorURL), response, error);
4783 FrameTestHelpers::loadHistoryItem(frame, errorHistoryItem, WebHistoryDifferentDocumentLoad, WebURLRequest::UseProtocolCachePolicy);
4785 WebString text = frame->contentAsText(std::numeric_limits<size_t>::max());
4786 EXPECT_EQ("This should appear", text.utf8());
4787 EXPECT_TRUE(webFrameClient.commitCalled());
4790 class TestWillInsertBodyWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
4792 TestWillInsertBodyWebFrameClient() : m_numBodies(0), m_didLoad(false)
4796 virtual void didCommitProvisionalLoad(WebLocalFrame*, const WebHistoryItem&, WebHistoryCommitType) override
4802 virtual void didCreateDocumentElement(WebLocalFrame*) override
4804 EXPECT_EQ(0, m_numBodies);
4807 virtual void willInsertBody(WebLocalFrame*) override
4816 TEST_F(WebFrameTest, HTMLDocument)
4818 registerMockedHttpURLLoad("clipped-body.html");
4820 TestWillInsertBodyWebFrameClient webFrameClient;
4821 FrameTestHelpers::WebViewHelper webViewHelper;
4822 webViewHelper.initializeAndLoad(m_baseURL + "clipped-body.html", false, &webFrameClient);
4824 EXPECT_TRUE(webFrameClient.m_didLoad);
4825 EXPECT_EQ(1, webFrameClient.m_numBodies);
4828 TEST_F(WebFrameTest, EmptyDocument)
4830 registerMockedHttpURLLoad("pageserializer/green_rectangle.svg");
4832 TestWillInsertBodyWebFrameClient webFrameClient;
4833 FrameTestHelpers::WebViewHelper webViewHelper;
4834 webViewHelper.initialize(false, &webFrameClient);
4836 EXPECT_FALSE(webFrameClient.m_didLoad);
4837 EXPECT_EQ(1, webFrameClient.m_numBodies); // The empty document that a new frame starts with triggers this.
4840 TEST_F(WebFrameTest, MoveCaretSelectionTowardsWindowPointWithNoSelection)
4842 FrameTestHelpers::WebViewHelper webViewHelper;
4843 webViewHelper.initializeAndLoad("about:blank", true);
4844 WebFrame* frame = webViewHelper.webView()->mainFrame();
4846 // This test passes if this doesn't crash.
4847 frame->moveCaretSelection(WebPoint(0, 0));
4850 TEST_F(WebFrameTest, NavigateToSandboxedMarkup)
4852 FrameTestHelpers::TestWebFrameClient webFrameClient;
4853 FrameTestHelpers::WebViewHelper webViewHelper;
4854 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad("about:blank", true, &webFrameClient);
4855 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4857 frame->document().setIsTransitionDocument();
4859 std::string markup("<div id='foo'></div><script>document.getElementById('foo').setAttribute('dir', 'rtl')</script>");
4860 frame->navigateToSandboxedMarkup(WebData(markup.data(), markup.length()));
4862 webFrameClient.waitForLoadToComplete();
4864 WebDocument document = webViewImpl->mainFrame()->document();
4865 WebElement transitionElement = document.getElementById("foo");
4866 // Check that the markup got navigated to successfully.
4867 EXPECT_FALSE(transitionElement.isNull());
4869 // Check that the inline script was not executed.
4870 EXPECT_FALSE(transitionElement.hasAttribute("dir"));
4873 class SpellCheckClient : public WebSpellCheckClient {
4875 explicit SpellCheckClient(uint32_t hash = 0) : m_numberOfTimesChecked(0), m_hash(hash) { }
4876 virtual ~SpellCheckClient() { }
4877 virtual void requestCheckingOfText(const WebString&, const WebVector<uint32_t>&, const WebVector<unsigned>&, WebTextCheckingCompletion* completion) override
4879 ++m_numberOfTimesChecked;
4880 Vector<WebTextCheckingResult> results;
4881 const int misspellingStartOffset = 1;
4882 const int misspellingLength = 8;
4883 results.append(WebTextCheckingResult(WebTextDecorationTypeSpelling, misspellingStartOffset, misspellingLength, WebString(), m_hash));
4884 completion->didFinishCheckingText(results);
4886 int numberOfTimesChecked() const { return m_numberOfTimesChecked; }
4888 int m_numberOfTimesChecked;
4892 TEST_F(WebFrameTest, ReplaceMisspelledRange)
4894 registerMockedHttpURLLoad("spell.html");
4895 FrameTestHelpers::WebViewHelper webViewHelper;
4896 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4897 SpellCheckClient spellcheck;
4898 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4900 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4901 Document* document = frame->frame()->document();
4902 Element* element = document->getElementById("data");
4904 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4905 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4906 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4909 document->execCommand("InsertText", false, "_wellcome_.");
4911 const int allTextBeginOffset = 0;
4912 const int allTextLength = 11;
4913 frame->selectRange(WebRange::fromDocumentRange(frame, allTextBeginOffset, allTextLength));
4914 RefPtrWillBeRawPtr<Range> selectionRange = frame->frame()->selection().toNormalizedRange();
4916 EXPECT_EQ(1, spellcheck.numberOfTimesChecked());
4917 EXPECT_EQ(1U, document->markers().markersInRange(selectionRange.get(), DocumentMarker::Spelling).size());
4919 frame->replaceMisspelledRange("welcome");
4920 EXPECT_EQ("_welcome_.", frame->contentAsText(std::numeric_limits<size_t>::max()).utf8());
4923 TEST_F(WebFrameTest, RemoveSpellingMarkers)
4925 registerMockedHttpURLLoad("spell.html");
4926 FrameTestHelpers::WebViewHelper webViewHelper;
4927 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4928 SpellCheckClient spellcheck;
4929 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4931 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4932 Document* document = frame->frame()->document();
4933 Element* element = document->getElementById("data");
4935 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4936 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4937 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4940 document->execCommand("InsertText", false, "_wellcome_.");
4942 frame->removeSpellingMarkers();
4944 const int allTextBeginOffset = 0;
4945 const int allTextLength = 11;
4946 frame->selectRange(WebRange::fromDocumentRange(frame, allTextBeginOffset, allTextLength));
4947 RefPtrWillBeRawPtr<Range> selectionRange = frame->frame()->selection().toNormalizedRange();
4949 EXPECT_EQ(0U, document->markers().markersInRange(selectionRange.get(), DocumentMarker::Spelling).size());
4952 TEST_F(WebFrameTest, RemoveSpellingMarkersUnderWords)
4954 registerMockedHttpURLLoad("spell.html");
4955 FrameTestHelpers::WebViewHelper webViewHelper;
4956 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4957 SpellCheckClient spellcheck;
4958 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4960 LocalFrame* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame())->frame();
4961 Document* document = frame->document();
4962 Element* element = document->getElementById("data");
4964 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4965 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4966 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4969 document->execCommand("InsertText", false, " wellcome ");
4971 WebVector<uint32_t> documentMarkers1;
4972 webViewHelper.webView()->spellingMarkers(&documentMarkers1);
4973 EXPECT_EQ(1U, documentMarkers1.size());
4975 Vector<String> words;
4976 words.append("wellcome");
4977 frame->removeSpellingMarkersUnderWords(words);
4979 WebVector<uint32_t> documentMarkers2;
4980 webViewHelper.webView()->spellingMarkers(&documentMarkers2);
4981 EXPECT_EQ(0U, documentMarkers2.size());
4984 TEST_F(WebFrameTest, MarkerHashIdentifiers) {
4985 registerMockedHttpURLLoad("spell.html");
4986 FrameTestHelpers::WebViewHelper webViewHelper;
4987 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4989 static const uint32_t kHash = 42;
4990 SpellCheckClient spellcheck(kHash);
4991 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4993 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4994 Document* document = frame->frame()->document();
4995 Element* element = document->getElementById("data");
4997 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4998 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4999 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
5002 document->execCommand("InsertText", false, "wellcome.");
5004 WebVector<uint32_t> documentMarkers;
5005 webViewHelper.webView()->spellingMarkers(&documentMarkers);
5006 EXPECT_EQ(1U, documentMarkers.size());
5007 EXPECT_EQ(kHash, documentMarkers[0]);
5010 class StubbornSpellCheckClient : public WebSpellCheckClient {
5012 StubbornSpellCheckClient() : m_completion(0) { }
5013 virtual ~StubbornSpellCheckClient() { }
5015 virtual void requestCheckingOfText(
5017 const WebVector<uint32_t>&,
5018 const WebVector<unsigned>&,
5019 WebTextCheckingCompletion* completion) override
5021 m_completion = completion;
5024 void kickNoResults()
5026 kick(-1, -1, WebTextDecorationTypeSpelling);
5031 kick(1, 8, WebTextDecorationTypeSpelling);
5036 kick(1, 8, WebTextDecorationTypeGrammar);
5039 void kickInvisibleSpellcheck()
5041 kick(1, 8, WebTextDecorationTypeInvisibleSpellcheck);
5045 void kick(int misspellingStartOffset, int misspellingLength, WebTextDecorationType type)
5049 Vector<WebTextCheckingResult> results;
5050 if (misspellingStartOffset >= 0 && misspellingLength > 0)
5051 results.append(WebTextCheckingResult(type, misspellingStartOffset, misspellingLength));
5052 m_completion->didFinishCheckingText(results);
5056 WebTextCheckingCompletion* m_completion;
5059 TEST_F(WebFrameTest, SlowSpellcheckMarkerPosition)
5061 registerMockedHttpURLLoad("spell.html");
5062 FrameTestHelpers::WebViewHelper webViewHelper;
5063 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
5065 StubbornSpellCheckClient spellcheck;
5066 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
5068 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
5069 WebInputElement webInputElement = frame->document().getElementById("data").to<WebInputElement>();
5070 Document* document = frame->frame()->document();
5071 Element* element = document->getElementById("data");
5073 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
5074 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
5075 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
5078 document->execCommand("InsertText", false, "wellcome ");
5079 webInputElement.setSelectionRange(0, 0);
5080 document->execCommand("InsertText", false, "he");
5084 WebVector<uint32_t> documentMarkers;
5085 webViewHelper.webView()->spellingMarkers(&documentMarkers);
5086 EXPECT_EQ(0U, documentMarkers.size());
5089 // This test verifies that cancelling spelling request does not cause a
5090 // write-after-free when there's no spellcheck client set.
5091 TEST_F(WebFrameTest, CancelSpellingRequestCrash)
5093 registerMockedHttpURLLoad("spell.html");
5094 FrameTestHelpers::WebViewHelper webViewHelper;
5095 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
5096 webViewHelper.webView()->setSpellCheckClient(0);
5098 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
5099 Document* document = frame->frame()->document();
5100 Element* element = document->getElementById("data");
5102 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
5103 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
5104 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
5107 frame->frame()->editor().replaceSelectionWithText("A", false, false);
5108 frame->frame()->spellChecker().cancelCheck();
5111 TEST_F(WebFrameTest, SpellcheckResultErasesMarkers)
5113 registerMockedHttpURLLoad("spell.html");
5114 FrameTestHelpers::WebViewHelper webViewHelper;
5115 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
5117 StubbornSpellCheckClient spellcheck;
5118 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
5120 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
5121 WebInputElement webInputElement = frame->document().getElementById("data").to<WebInputElement>();
5122 Document* document = frame->frame()->document();
5123 Element* element = document->getElementById("data");
5125 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
5126 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
5127 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
5130 document->execCommand("InsertText", false, "welcome ");
5131 document->markers().addMarker(rangeOfContents(element->toNode()).get(), DocumentMarker::Spelling);
5132 document->markers().addMarker(rangeOfContents(element->toNode()).get(), DocumentMarker::Grammar);
5133 document->markers().addMarker(rangeOfContents(element->toNode()).get(), DocumentMarker::InvisibleSpellcheck);
5134 EXPECT_EQ(3U, document->markers().markers().size());
5136 spellcheck.kickNoResults();
5137 EXPECT_EQ(0U, document->markers().markers().size());
5140 TEST_F(WebFrameTest, SpellcheckResultsSavedInDocument)
5142 registerMockedHttpURLLoad("spell.html");
5143 FrameTestHelpers::WebViewHelper webViewHelper;
5144 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
5146 StubbornSpellCheckClient spellcheck;
5147 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
5149 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
5150 WebInputElement webInputElement = frame->document().getElementById("data").to<WebInputElement>();
5151 Document* document = frame->frame()->document();
5152 Element* element = document->getElementById("data");
5154 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
5155 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
5156 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
5159 document->execCommand("InsertText", false, "wellcome ");
5162 ASSERT_EQ(1U, document->markers().markers().size());
5163 ASSERT_NE(static_cast<DocumentMarker*>(0), document->markers().markers()[0]);
5164 EXPECT_EQ(DocumentMarker::Spelling, document->markers().markers()[0]->type());
5166 document->execCommand("InsertText", false, "wellcome ");
5168 spellcheck.kickGrammar();
5169 ASSERT_EQ(1U, document->markers().markers().size());
5170 ASSERT_NE(static_cast<DocumentMarker*>(0), document->markers().markers()[0]);
5171 EXPECT_EQ(DocumentMarker::Grammar, document->markers().markers()[0]->type());
5173 document->execCommand("InsertText", false, "wellcome ");
5175 spellcheck.kickInvisibleSpellcheck();
5176 ASSERT_EQ(1U, document->markers().markers().size());
5177 ASSERT_NE(static_cast<DocumentMarker*>(0), document->markers().markers()[0]);
5178 EXPECT_EQ(DocumentMarker::InvisibleSpellcheck, document->markers().markers()[0]->type());
5181 class TestAccessInitialDocumentWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5183 TestAccessInitialDocumentWebFrameClient() : m_didAccessInitialDocument(false)
5187 virtual void didAccessInitialDocument(WebLocalFrame* frame)
5189 EXPECT_TRUE(!m_didAccessInitialDocument);
5190 m_didAccessInitialDocument = true;
5193 bool m_didAccessInitialDocument;
5196 TEST_F(WebFrameTest, DidAccessInitialDocumentBody)
5198 // FIXME: Why is this local webViewClient needed instead of the default
5199 // WebViewHelper one? With out it there's some mysterious crash in the
5200 // WebViewHelper destructor.
5201 FrameTestHelpers::TestWebViewClient webViewClient;
5202 TestAccessInitialDocumentWebFrameClient webFrameClient;
5203 FrameTestHelpers::WebViewHelper webViewHelper;
5204 webViewHelper.initialize(true, &webFrameClient, &webViewClient);
5206 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
5208 // Create another window that will try to access it.
5209 FrameTestHelpers::WebViewHelper newWebViewHelper;
5210 WebView* newView = newWebViewHelper.initialize(true);
5211 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
5213 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
5215 // Access the initial document by modifying the body.
5216 newView->mainFrame()->executeScript(
5217 WebScriptSource("window.opener.document.body.innerHTML += 'Modified';"));
5219 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
5221 // Access the initial document again, to ensure we don't notify twice.
5222 newView->mainFrame()->executeScript(
5223 WebScriptSource("window.opener.document.body.innerHTML += 'Modified';"));
5225 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
5228 TEST_F(WebFrameTest, DidAccessInitialDocumentNavigator)
5230 // FIXME: Why is this local webViewClient needed instead of the default
5231 // WebViewHelper one? With out it there's some mysterious crash in the
5232 // WebViewHelper destructor.
5233 FrameTestHelpers::TestWebViewClient webViewClient;
5234 TestAccessInitialDocumentWebFrameClient webFrameClient;
5235 FrameTestHelpers::WebViewHelper webViewHelper;
5236 webViewHelper.initialize(true, &webFrameClient, &webViewClient);
5238 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
5240 // Create another window that will try to access it.
5241 FrameTestHelpers::WebViewHelper newWebViewHelper;
5242 WebView* newView = newWebViewHelper.initialize(true);
5243 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
5245 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
5247 // Access the initial document to get to the navigator object.
5248 newView->mainFrame()->executeScript(
5249 WebScriptSource("console.log(window.opener.navigator);"));
5251 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
5254 TEST_F(WebFrameTest, DidAccessInitialDocumentViaJavascriptUrl)
5256 TestAccessInitialDocumentWebFrameClient webFrameClient;
5257 FrameTestHelpers::WebViewHelper webViewHelper;
5258 webViewHelper.initialize(true, &webFrameClient);
5260 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
5262 // Access the initial document from a javascript: URL.
5263 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.appendChild(document.createTextNode('Modified'))");
5264 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
5267 // Fails on the WebKit XP (deps) bot. http://crbug.com/312192
5269 TEST_F(WebFrameTest, DISABLED_DidAccessInitialDocumentBodyBeforeModalDialog)
5271 TEST_F(WebFrameTest, DidAccessInitialDocumentBodyBeforeModalDialog)
5274 // FIXME: Why is this local webViewClient needed instead of the default
5275 // WebViewHelper one? With out it there's some mysterious crash in the
5276 // WebViewHelper destructor.
5277 FrameTestHelpers::TestWebViewClient webViewClient;
5278 TestAccessInitialDocumentWebFrameClient webFrameClient;
5279 FrameTestHelpers::WebViewHelper webViewHelper;
5280 webViewHelper.initialize(true, &webFrameClient, &webViewClient);
5282 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
5284 // Create another window that will try to access it.
5285 FrameTestHelpers::WebViewHelper newWebViewHelper;
5286 WebView* newView = newWebViewHelper.initialize(true);
5287 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
5289 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
5291 // Access the initial document by modifying the body. We normally set a
5292 // timer to notify the client.
5293 newView->mainFrame()->executeScript(
5294 WebScriptSource("window.opener.document.body.innerHTML += 'Modified';"));
5295 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
5297 // Make sure that a modal dialog forces us to notify right away.
5298 newView->mainFrame()->executeScript(
5299 WebScriptSource("window.opener.confirm('Modal');"));
5300 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
5302 // Ensure that we don't notify again later.
5304 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
5307 // Fails on the WebKit XP (deps) bot. http://crbug.com/312192
5309 TEST_F(WebFrameTest, DISABLED_DidWriteToInitialDocumentBeforeModalDialog)
5311 TEST_F(WebFrameTest, DidWriteToInitialDocumentBeforeModalDialog)
5314 // FIXME: Why is this local webViewClient needed instead of the default
5315 // WebViewHelper one? With out it there's some mysterious crash in the
5316 // WebViewHelper destructor.
5317 FrameTestHelpers::TestWebViewClient webViewClient;
5318 TestAccessInitialDocumentWebFrameClient webFrameClient;
5319 FrameTestHelpers::WebViewHelper webViewHelper;
5320 webViewHelper.initialize(true, &webFrameClient, &webViewClient);
5322 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
5324 // Create another window that will try to access it.
5325 FrameTestHelpers::WebViewHelper newWebViewHelper;
5326 WebView* newView = newWebViewHelper.initialize(true);
5327 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
5329 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
5331 // Access the initial document with document.write, which moves us past the
5332 // initial empty document state of the state machine. We normally set a
5333 // timer to notify the client.
5334 newView->mainFrame()->executeScript(
5335 WebScriptSource("window.opener.document.write('Modified'); window.opener.document.close();"));
5336 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
5338 // Make sure that a modal dialog forces us to notify right away.
5339 newView->mainFrame()->executeScript(
5340 WebScriptSource("window.opener.confirm('Modal');"));
5341 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
5343 // Ensure that we don't notify again later.
5345 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
5348 class TestMainFrameUserOrProgrammaticScrollFrameClient : public FrameTestHelpers::TestWebFrameClient {
5350 TestMainFrameUserOrProgrammaticScrollFrameClient() { reset(); }
5353 m_didScrollMainFrame = false;
5354 m_wasProgrammaticScroll = false;
5356 bool wasUserScroll() const { return m_didScrollMainFrame && !m_wasProgrammaticScroll; }
5357 bool wasProgrammaticScroll() const { return m_didScrollMainFrame && m_wasProgrammaticScroll; }
5360 virtual void didChangeScrollOffset(WebLocalFrame* frame) override
5362 if (frame->parent())
5364 EXPECT_FALSE(m_didScrollMainFrame);
5365 FrameView* view = toWebLocalFrameImpl(frame)->frameView();
5366 // FrameView can be scrolled in FrameView::setFixedVisibleContentRect
5367 // which is called from LocalFrame::createView (before the frame is associated
5368 // with the the view).
5370 m_didScrollMainFrame = true;
5371 m_wasProgrammaticScroll = view->inProgrammaticScroll();
5375 bool m_didScrollMainFrame;
5376 bool m_wasProgrammaticScroll;
5379 TEST_F(WebFrameTest, CompositorScrollIsUserScrollLongPage)
5381 registerMockedHttpURLLoad("long_scroll.html");
5382 TestMainFrameUserOrProgrammaticScrollFrameClient client;
5384 // Make sure we initialize to minimum scale, even if the window size
5385 // only becomes available after the load begins.
5386 FrameTestHelpers::WebViewHelper webViewHelper;
5387 webViewHelper.initializeAndLoad(m_baseURL + "long_scroll.html", true, &client);
5388 webViewHelper.webView()->resize(WebSize(1000, 1000));
5389 webViewHelper.webView()->layout();
5391 EXPECT_FALSE(client.wasUserScroll());
5392 EXPECT_FALSE(client.wasProgrammaticScroll());
5394 // Do a compositor scroll, verify that this is counted as a user scroll.
5395 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(0, 1), 1.1f, 0);
5396 EXPECT_TRUE(client.wasUserScroll());
5399 EXPECT_FALSE(client.wasUserScroll());
5400 EXPECT_FALSE(client.wasProgrammaticScroll());
5402 // The page scale 1.0f and scroll.
5403 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(0, 1), 1.0f, 0);
5404 EXPECT_TRUE(client.wasUserScroll());
5407 // No scroll event if there is no scroll delta.
5408 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(), 1.0f, 0);
5409 EXPECT_FALSE(client.wasUserScroll());
5410 EXPECT_FALSE(client.wasProgrammaticScroll());
5413 // Non zero page scale and scroll.
5414 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(9, 13), 0.6f, 0);
5415 EXPECT_TRUE(client.wasUserScroll());
5418 // Programmatic scroll.
5419 WebLocalFrameImpl* frameImpl = webViewHelper.webViewImpl()->mainFrameImpl();
5420 frameImpl->executeScript(WebScriptSource("window.scrollTo(0, 20);"));
5421 EXPECT_FALSE(client.wasUserScroll());
5422 EXPECT_TRUE(client.wasProgrammaticScroll());
5425 // Programmatic scroll to same offset. No scroll event should be generated.
5426 frameImpl->executeScript(WebScriptSource("window.scrollTo(0, 20);"));
5427 EXPECT_FALSE(client.wasProgrammaticScroll());
5428 EXPECT_FALSE(client.wasUserScroll());
5432 TEST_F(WebFrameTest, CompositorScrollIsUserScrollShortPage)
5434 registerMockedHttpURLLoad("short_scroll.html");
5436 TestMainFrameUserOrProgrammaticScrollFrameClient client;
5438 // Short page tests.
5439 FrameTestHelpers::WebViewHelper webViewHelper;
5440 webViewHelper.initializeAndLoad(m_baseURL + "short_scroll.html", true, &client);
5442 webViewHelper.webView()->resize(WebSize(1000, 1000));
5443 webViewHelper.webView()->layout();
5445 EXPECT_FALSE(client.wasUserScroll());
5446 EXPECT_FALSE(client.wasProgrammaticScroll());
5448 // Non zero page scale and scroll.
5449 webViewHelper.webViewImpl()->applyViewportDeltas(WebSize(9, 13), 2.0f, 0);
5450 EXPECT_FALSE(client.wasProgrammaticScroll());
5451 EXPECT_TRUE(client.wasUserScroll());
5455 TEST_F(WebFrameTest, FirstPartyForCookiesForRedirect)
5457 WTF::String filePath = Platform::current()->unitTestSupport()->webKitRootDir();
5458 filePath.append("/Source/web/tests/data/first_party.html");
5460 WebURL testURL(toKURL("http://internal.test/first_party_redirect.html"));
5461 char redirect[] = "http://internal.test/first_party.html";
5462 WebURL redirectURL(toKURL(redirect));
5463 WebURLResponse redirectResponse;
5464 redirectResponse.initialize();
5465 redirectResponse.setMIMEType("text/html");
5466 redirectResponse.setHTTPStatusCode(302);
5467 redirectResponse.setHTTPHeaderField("Location", redirect);
5468 Platform::current()->unitTestSupport()->registerMockedURL(testURL, redirectResponse, filePath);
5470 WebURLResponse finalResponse;
5471 finalResponse.initialize();
5472 finalResponse.setMIMEType("text/html");
5473 Platform::current()->unitTestSupport()->registerMockedURL(redirectURL, finalResponse, filePath);
5475 FrameTestHelpers::WebViewHelper webViewHelper;
5476 webViewHelper.initializeAndLoad(m_baseURL + "first_party_redirect.html", true);
5477 EXPECT_TRUE(webViewHelper.webView()->mainFrame()->document().firstPartyForCookies() == redirectURL);
5480 class TestNavigationPolicyWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5483 virtual void didNavigateWithinPage(WebLocalFrame*, const WebHistoryItem&, WebHistoryCommitType) override
5489 TEST_F(WebFrameTest, SimulateFragmentAnchorMiddleClick)
5491 registerMockedHttpURLLoad("fragment_middle_click.html");
5492 TestNavigationPolicyWebFrameClient client;
5493 FrameTestHelpers::WebViewHelper webViewHelper;
5494 webViewHelper.initializeAndLoad(m_baseURL + "fragment_middle_click.html", true, &client);
5496 Document* document = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document();
5497 KURL destination = document->url();
5498 destination.setFragmentIdentifier("test");
5500 RefPtrWillBeRawPtr<Event> event = MouseEvent::create(EventTypeNames::click, false, false,
5501 document->domWindow(), 0, 0, 0, 0, 0, 0, 0, false, false, false, false, 1, nullptr, nullptr);
5502 FrameLoadRequest frameRequest(document, ResourceRequest(destination));
5503 frameRequest.setTriggeringEvent(event);
5504 toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->loader().load(frameRequest);
5507 class TestNewWindowWebViewClient : public FrameTestHelpers::TestWebViewClient {
5509 virtual WebView* createView(WebLocalFrame*, const WebURLRequest&, const WebWindowFeatures&,
5510 const WebString&, WebNavigationPolicy, bool) override
5517 class TestNewWindowWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5519 TestNewWindowWebFrameClient()
5520 : m_decidePolicyCallCount(0)
5524 virtual WebNavigationPolicy decidePolicyForNavigation(const NavigationPolicyInfo& info) override
5526 m_decidePolicyCallCount++;
5527 return info.defaultPolicy;
5530 int decidePolicyCallCount() const { return m_decidePolicyCallCount; }
5533 int m_decidePolicyCallCount;
5536 TEST_F(WebFrameTest, ModifiedClickNewWindow)
5538 registerMockedHttpURLLoad("ctrl_click.html");
5539 registerMockedHttpURLLoad("hello_world.html");
5540 TestNewWindowWebViewClient webViewClient;
5541 TestNewWindowWebFrameClient webFrameClient;
5542 FrameTestHelpers::WebViewHelper webViewHelper;
5543 webViewHelper.initializeAndLoad(m_baseURL + "ctrl_click.html", true, &webFrameClient, &webViewClient);
5545 Document* document = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document();
5546 KURL destination = toKURL(m_baseURL + "hello_world.html");
5549 RefPtrWillBeRawPtr<Event> event = MouseEvent::create(EventTypeNames::click, false, false,
5550 document->domWindow(), 0, 0, 0, 0, 0, 0, 0, true, false, false, false, 0, nullptr, nullptr);
5551 FrameLoadRequest frameRequest(document, ResourceRequest(destination));
5552 frameRequest.setTriggeringEvent(event);
5553 UserGestureIndicator gesture(DefinitelyProcessingUserGesture);
5554 toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->loader().load(frameRequest);
5555 FrameTestHelpers::pumpPendingRequestsDoNotUse(webViewHelper.webView()->mainFrame());
5557 // decidePolicyForNavigation should be called both for the original request and the ctrl+click.
5558 EXPECT_EQ(2, webFrameClient.decidePolicyCallCount());
5561 TEST_F(WebFrameTest, BackToReload)
5563 registerMockedHttpURLLoad("fragment_middle_click.html");
5564 FrameTestHelpers::WebViewHelper webViewHelper;
5565 webViewHelper.initializeAndLoad(m_baseURL + "fragment_middle_click.html", true);
5566 WebFrame* frame = webViewHelper.webView()->mainFrame();
5567 const FrameLoader& mainFrameLoader = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->loader();
5568 RefPtrWillBePersistent<HistoryItem> firstItem = mainFrameLoader.currentItem();
5569 EXPECT_TRUE(firstItem);
5571 registerMockedHttpURLLoad("white-1x1.png");
5572 FrameTestHelpers::loadFrame(frame, m_baseURL + "white-1x1.png");
5573 EXPECT_NE(firstItem.get(), mainFrameLoader.currentItem());
5575 FrameTestHelpers::loadHistoryItem(frame, WebHistoryItem(firstItem.get()), WebHistoryDifferentDocumentLoad, WebURLRequest::UseProtocolCachePolicy);
5576 EXPECT_EQ(firstItem.get(), mainFrameLoader.currentItem());
5578 FrameTestHelpers::reloadFrame(frame);
5579 EXPECT_EQ(WebURLRequest::ReloadIgnoringCacheData, frame->dataSource()->request().cachePolicy());
5582 TEST_F(WebFrameTest, BackDuringChildFrameReload)
5584 registerMockedHttpURLLoad("page_with_blank_iframe.html");
5585 FrameTestHelpers::WebViewHelper webViewHelper;
5586 webViewHelper.initializeAndLoad(m_baseURL + "page_with_blank_iframe.html", true);
5587 WebFrame* mainFrame = webViewHelper.webView()->mainFrame();
5588 const FrameLoader& mainFrameLoader = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->loader();
5589 WebFrame* childFrame = mainFrame->firstChild();
5590 ASSERT_TRUE(childFrame);
5592 // Start a history navigation, then have a different frame commit a navigation.
5593 // In this case, reload an about:blank frame, which will commit synchronously.
5594 // After the history navigation completes, both the appropriate document url and
5595 // the current history item should reflect the history navigation.
5596 registerMockedHttpURLLoad("white-1x1.png");
5597 WebHistoryItem item;
5599 WebURL historyURL(toKURL(m_baseURL + "white-1x1.png"));
5600 item.setURLString(historyURL.string());
5601 mainFrame->loadHistoryItem(item, WebHistoryDifferentDocumentLoad, WebURLRequest::UseProtocolCachePolicy);
5603 FrameTestHelpers::reloadFrame(childFrame);
5604 EXPECT_EQ(item.urlString(), mainFrame->document().url().string());
5605 EXPECT_EQ(item.urlString(), WebString(mainFrameLoader.currentItem()->urlString()));
5608 TEST_F(WebFrameTest, ReloadPost)
5610 registerMockedHttpURLLoad("reload_post.html");
5611 FrameTestHelpers::WebViewHelper webViewHelper;
5612 webViewHelper.initializeAndLoad(m_baseURL + "reload_post.html", true);
5613 WebFrame* frame = webViewHelper.webView()->mainFrame();
5615 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.forms[0].submit()");
5616 // Pump requests one more time after the javascript URL has executed to
5617 // trigger the actual POST load request.
5618 FrameTestHelpers::pumpPendingRequestsDoNotUse(webViewHelper.webView()->mainFrame());
5619 EXPECT_EQ(WebString::fromUTF8("POST"), frame->dataSource()->request().httpMethod());
5621 FrameTestHelpers::reloadFrame(frame);
5622 EXPECT_EQ(WebURLRequest::ReloadIgnoringCacheData, frame->dataSource()->request().cachePolicy());
5623 EXPECT_EQ(WebNavigationTypeFormResubmitted, frame->dataSource()->navigationType());
5626 TEST_F(WebFrameTest, LoadHistoryItemReload)
5628 registerMockedHttpURLLoad("fragment_middle_click.html");
5629 FrameTestHelpers::WebViewHelper webViewHelper;
5630 webViewHelper.initializeAndLoad(m_baseURL + "fragment_middle_click.html", true);
5631 WebFrame* frame = webViewHelper.webView()->mainFrame();
5632 const FrameLoader& mainFrameLoader = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->loader();
5633 RefPtrWillBePersistent<HistoryItem> firstItem = mainFrameLoader.currentItem();
5634 EXPECT_TRUE(firstItem);
5636 registerMockedHttpURLLoad("white-1x1.png");
5637 FrameTestHelpers::loadFrame(frame, m_baseURL + "white-1x1.png");
5638 EXPECT_NE(firstItem.get(), mainFrameLoader.currentItem());
5640 // Cache policy overrides should take.
5641 FrameTestHelpers::loadHistoryItem(frame, WebHistoryItem(firstItem), WebHistoryDifferentDocumentLoad, WebURLRequest::ReloadIgnoringCacheData);
5642 EXPECT_EQ(firstItem.get(), mainFrameLoader.currentItem());
5643 EXPECT_EQ(WebURLRequest::ReloadIgnoringCacheData, frame->dataSource()->request().cachePolicy());
5647 class TestCachePolicyWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5649 explicit TestCachePolicyWebFrameClient(TestCachePolicyWebFrameClient* parentClient)
5650 : m_parentClient(parentClient)
5651 , m_policy(WebURLRequest::UseProtocolCachePolicy)
5653 , m_willSendRequestCallCount(0)
5654 , m_childFrameCreationCount(0)
5658 void setChildWebFrameClient(TestCachePolicyWebFrameClient* client) { m_childClient = client; }
5659 WebURLRequest::CachePolicy cachePolicy() const { return m_policy; }
5660 int willSendRequestCallCount() const { return m_willSendRequestCallCount; }
5661 int childFrameCreationCount() const { return m_childFrameCreationCount; }
5663 virtual WebFrame* createChildFrame(WebLocalFrame* parent, const WebString&)
5665 ASSERT(m_childClient);
5666 m_childFrameCreationCount++;
5667 WebFrame* frame = WebLocalFrame::create(m_childClient);
5668 parent->appendChild(frame);
5672 virtual void didStartLoading(bool toDifferentDocument)
5674 if (m_parentClient) {
5675 m_parentClient->didStartLoading(toDifferentDocument);
5678 TestWebFrameClient::didStartLoading(toDifferentDocument);
5681 virtual void didStopLoading()
5683 if (m_parentClient) {
5684 m_parentClient->didStopLoading();
5687 TestWebFrameClient::didStopLoading();
5690 virtual void willSendRequest(WebLocalFrame* frame, unsigned, WebURLRequest& request, const WebURLResponse&) override
5692 m_policy = request.cachePolicy();
5693 m_willSendRequestCallCount++;
5697 TestCachePolicyWebFrameClient* m_parentClient;
5699 WebURLRequest::CachePolicy m_policy;
5700 TestCachePolicyWebFrameClient* m_childClient;
5701 int m_willSendRequestCallCount;
5702 int m_childFrameCreationCount;
5705 TEST_F(WebFrameTest, ReloadIframe)
5707 registerMockedHttpURLLoad("iframe_reload.html");
5708 registerMockedHttpURLLoad("visible_iframe.html");
5709 TestCachePolicyWebFrameClient mainClient(0);
5710 TestCachePolicyWebFrameClient childClient(&mainClient);
5711 mainClient.setChildWebFrameClient(&childClient);
5713 FrameTestHelpers::WebViewHelper webViewHelper;
5714 webViewHelper.initializeAndLoad(m_baseURL + "iframe_reload.html", true, &mainClient);
5716 WebLocalFrameImpl* mainFrame = webViewHelper.webViewImpl()->mainFrameImpl();
5717 RefPtrWillBeRawPtr<WebLocalFrameImpl> childFrame = toWebLocalFrameImpl(mainFrame->firstChild());
5718 ASSERT_EQ(childFrame->client(), &childClient);
5719 EXPECT_EQ(mainClient.childFrameCreationCount(), 1);
5720 EXPECT_EQ(childClient.willSendRequestCallCount(), 1);
5721 EXPECT_EQ(childClient.cachePolicy(), WebURLRequest::UseProtocolCachePolicy);
5723 FrameTestHelpers::reloadFrame(mainFrame);
5725 // A new WebFrame should have been created, but the child WebFrameClient should be reused.
5726 ASSERT_NE(childFrame, toWebLocalFrameImpl(mainFrame->firstChild()));
5727 ASSERT_EQ(toWebLocalFrameImpl(mainFrame->firstChild())->client(), &childClient);
5729 EXPECT_EQ(mainClient.childFrameCreationCount(), 2);
5730 EXPECT_EQ(childClient.willSendRequestCallCount(), 2);
5731 EXPECT_EQ(childClient.cachePolicy(), WebURLRequest::ReloadIgnoringCacheData);
5734 class TestSameDocumentWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5736 TestSameDocumentWebFrameClient()
5737 : m_frameLoadTypeSameSeen(false)
5741 virtual void willSendRequest(WebLocalFrame* frame, unsigned, WebURLRequest&, const WebURLResponse&)
5743 if (toWebLocalFrameImpl(frame)->frame()->loader().loadType() == FrameLoadTypeSame)
5744 m_frameLoadTypeSameSeen = true;
5747 bool frameLoadTypeSameSeen() const { return m_frameLoadTypeSameSeen; }
5750 bool m_frameLoadTypeSameSeen;
5753 TEST_F(WebFrameTest, NavigateToSame)
5755 registerMockedHttpURLLoad("navigate_to_same.html");
5756 TestSameDocumentWebFrameClient client;
5757 FrameTestHelpers::WebViewHelper webViewHelper;
5758 webViewHelper.initializeAndLoad(m_baseURL + "navigate_to_same.html", true, &client);
5759 EXPECT_FALSE(client.frameLoadTypeSameSeen());
5761 FrameLoadRequest frameRequest(0, ResourceRequest(toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document()->url()));
5762 toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->loader().load(frameRequest);
5763 FrameTestHelpers::pumpPendingRequestsDoNotUse(webViewHelper.webView()->mainFrame());
5765 EXPECT_TRUE(client.frameLoadTypeSameSeen());
5768 class TestSameDocumentWithImageWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5770 TestSameDocumentWithImageWebFrameClient()
5771 : m_numOfImageRequests(0)
5775 virtual void willSendRequest(WebLocalFrame* frame, unsigned, WebURLRequest& request, const WebURLResponse&)
5777 if (request.requestContext() == WebURLRequest::RequestContextImage) {
5778 m_numOfImageRequests++;
5779 EXPECT_EQ(WebURLRequest::UseProtocolCachePolicy, request.cachePolicy());
5783 int numOfImageRequests() const { return m_numOfImageRequests; }
5786 int m_numOfImageRequests;
5789 TEST_F(WebFrameTest, NavigateToSameNoConditionalRequestForSubresource)
5791 registerMockedHttpURLLoad("foo_with_image.html");
5792 registerMockedHttpURLLoad("white-1x1.png");
5793 TestSameDocumentWithImageWebFrameClient client;
5794 FrameTestHelpers::WebViewHelper webViewHelper;
5795 webViewHelper.initializeAndLoad(m_baseURL + "foo_with_image.html", true, &client, 0, &configureLoadsImagesAutomatically);
5798 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "foo_with_image.html");
5800 EXPECT_EQ(client.numOfImageRequests(), 2);
5803 TEST_F(WebFrameTest, WebNodeImageContents)
5805 FrameTestHelpers::WebViewHelper webViewHelper;
5806 webViewHelper.initializeAndLoad("about:blank", true);
5807 WebFrame* frame = webViewHelper.webView()->mainFrame();
5809 static const char bluePNG[] = "<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAGElEQVQYV2NkYPj/n4EIwDiqEF8oUT94AFIQE/cCn90IAAAAAElFTkSuQmCC\">";
5811 // Load up the image and test that we can extract the contents.
5812 KURL testURL = toKURL("about:blank");
5813 FrameTestHelpers::loadHTMLString(frame, bluePNG, testURL);
5815 WebNode node = frame->document().body().firstChild();
5816 EXPECT_TRUE(node.isElementNode());
5817 WebElement element = node.to<WebElement>();
5818 WebImage image = element.imageContents();
5819 ASSERT_FALSE(image.isNull());
5820 EXPECT_EQ(image.size().width, 10);
5821 EXPECT_EQ(image.size().height, 10);
5822 // FIXME: The rest of this test is disabled since the ImageDecodeCache state may be inconsistent when this test runs.
5824 // SkBitmap bitmap = image.getSkBitmap();
5825 // SkAutoLockPixels locker(bitmap);
5826 // EXPECT_EQ(bitmap.getColor(0, 0), SK_ColorBLUE);
5829 class TestStartStopCallbackWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5831 TestStartStopCallbackWebFrameClient()
5832 : m_startLoadingCount(0)
5833 , m_stopLoadingCount(0)
5834 , m_differentDocumentStartCount(0)
5838 virtual void didStartLoading(bool toDifferentDocument) override
5840 TestWebFrameClient::didStartLoading(toDifferentDocument);
5841 m_startLoadingCount++;
5842 if (toDifferentDocument)
5843 m_differentDocumentStartCount++;
5846 virtual void didStopLoading() override
5848 TestWebFrameClient::didStopLoading();
5849 m_stopLoadingCount++;
5852 int startLoadingCount() const { return m_startLoadingCount; }
5853 int stopLoadingCount() const { return m_stopLoadingCount; }
5854 int differentDocumentStartCount() const { return m_differentDocumentStartCount; }
5857 int m_startLoadingCount;
5858 int m_stopLoadingCount;
5859 int m_differentDocumentStartCount;
5862 TEST_F(WebFrameTest, PushStateStartsAndStops)
5864 registerMockedHttpURLLoad("push_state.html");
5865 TestStartStopCallbackWebFrameClient client;
5866 FrameTestHelpers::WebViewHelper webViewHelper;
5867 webViewHelper.initializeAndLoad(m_baseURL + "push_state.html", true, &client);
5869 EXPECT_EQ(client.startLoadingCount(), 2);
5870 EXPECT_EQ(client.stopLoadingCount(), 2);
5871 EXPECT_EQ(client.differentDocumentStartCount(), 1);
5874 class TestDidNavigateCommitTypeWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5876 TestDidNavigateCommitTypeWebFrameClient()
5877 : m_lastCommitType(WebHistoryInertCommit)
5881 virtual void didNavigateWithinPage(WebLocalFrame*, const WebHistoryItem&, WebHistoryCommitType type) override
5883 m_lastCommitType = type;
5886 WebHistoryCommitType lastCommitType() const { return m_lastCommitType; }
5889 WebHistoryCommitType m_lastCommitType;
5892 TEST_F(WebFrameTest, SameDocumentHistoryNavigationCommitType)
5894 registerMockedHttpURLLoad("push_state.html");
5895 TestDidNavigateCommitTypeWebFrameClient client;
5896 FrameTestHelpers::WebViewHelper webViewHelper;
5897 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "push_state.html", true, &client);
5898 RefPtrWillBePersistent<HistoryItem> item = toLocalFrame(webViewImpl->page()->mainFrame())->loader().currentItem();
5901 toLocalFrame(webViewImpl->page()->mainFrame())->loader().loadHistoryItem(item.get(), FrameLoadTypeBackForward, HistorySameDocumentLoad);
5902 EXPECT_EQ(WebBackForwardCommit, client.lastCommitType());
5905 class TestHistoryWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5907 TestHistoryWebFrameClient()
5909 m_replacesCurrentHistoryItem = false;
5913 void didStartProvisionalLoad(WebLocalFrame* frame, bool isTransitionNavigation)
5915 WebDataSource* ds = frame->provisionalDataSource();
5916 m_replacesCurrentHistoryItem = ds->replacesCurrentHistoryItem();
5920 bool replacesCurrentHistoryItem() { return m_replacesCurrentHistoryItem; }
5921 WebFrame* frame() { return m_frame; }
5924 bool m_replacesCurrentHistoryItem;
5928 // Test which ensures that the first navigation in a subframe will always
5929 // result in history entry being replaced and not a new one added.
5930 TEST_F(WebFrameTest, DISABLED_FirstFrameNavigationReplacesHistory)
5932 registerMockedHttpURLLoad("history.html");
5933 registerMockedHttpURLLoad("find.html");
5935 FrameTestHelpers::WebViewHelper webViewHelper;
5936 TestHistoryWebFrameClient client;
5937 webViewHelper.initializeAndLoad("about:blank", true, &client);
5938 EXPECT_TRUE(client.replacesCurrentHistoryItem());
5940 WebFrame* frame = webViewHelper.webView()->mainFrame();
5942 FrameTestHelpers::loadFrame(frame,
5943 "javascript:document.body.appendChild(document.createElement('iframe'))");
5944 WebFrame* iframe = frame->firstChild();
5945 EXPECT_EQ(client.frame(), iframe);
5946 EXPECT_TRUE(client.replacesCurrentHistoryItem());
5948 FrameTestHelpers::loadFrame(frame,
5949 "javascript:window.frames[0].location.assign('" + m_baseURL + "history.html')");
5950 EXPECT_EQ(client.frame(), iframe);
5951 EXPECT_TRUE(client.replacesCurrentHistoryItem());
5953 FrameTestHelpers::loadFrame(frame,
5954 "javascript:window.frames[0].location.assign('" + m_baseURL + "find.html')");
5955 EXPECT_EQ(client.frame(), iframe);
5956 EXPECT_FALSE(client.replacesCurrentHistoryItem());
5958 // Repeat the test, but start out the iframe with initial URL, which is not
5960 FrameTestHelpers::loadFrame(frame,
5961 "javascript:var f = document.createElement('iframe'); "
5962 "f.src = '" + m_baseURL + "history.html';"
5963 "document.body.appendChild(f)");
5965 iframe = frame->firstChild()->nextSibling();
5966 EXPECT_EQ(client.frame(), iframe);
5967 EXPECT_TRUE(client.replacesCurrentHistoryItem());
5969 FrameTestHelpers::loadFrame(frame,
5970 "javascript:window.frames[1].location.assign('" + m_baseURL + "find.html')");
5971 EXPECT_EQ(client.frame(), iframe);
5972 EXPECT_FALSE(client.replacesCurrentHistoryItem());
5975 // Test verifies that layout will change a layer's scrollable attibutes
5976 TEST_F(WebFrameTest, overflowHiddenRewrite)
5978 registerMockedHttpURLLoad("non-scrollable.html");
5979 TestMainFrameUserOrProgrammaticScrollFrameClient client;
5980 OwnPtr<FakeCompositingWebViewClient> fakeCompositingWebViewClient = adoptPtr(new FakeCompositingWebViewClient());
5981 FrameTestHelpers::WebViewHelper webViewHelper;
5982 webViewHelper.initialize(true, 0, fakeCompositingWebViewClient.get(), &configueCompositingWebView);
5984 webViewHelper.webView()->resize(WebSize(100, 100));
5985 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "non-scrollable.html");
5987 RenderLayerCompositor* compositor = webViewHelper.webViewImpl()->compositor();
5988 ASSERT_TRUE(compositor->scrollLayer());
5990 // Verify that the WebLayer is not scrollable initially.
5991 GraphicsLayer* scrollLayer = compositor->scrollLayer();
5992 WebLayer* webScrollLayer = scrollLayer->platformLayer();
5993 ASSERT_FALSE(webScrollLayer->userScrollableHorizontal());
5994 ASSERT_FALSE(webScrollLayer->userScrollableVertical());
5996 // Call javascript to make the layer scrollable, and verify it.
5997 WebLocalFrameImpl* frame = (WebLocalFrameImpl*)webViewHelper.webView()->mainFrame();
5998 frame->executeScript(WebScriptSource("allowScroll();"));
5999 webViewHelper.webView()->layout();
6000 ASSERT_TRUE(webScrollLayer->userScrollableHorizontal());
6001 ASSERT_TRUE(webScrollLayer->userScrollableVertical());
6004 // Test that currentHistoryItem reflects the current page, not the provisional load.
6005 TEST_F(WebFrameTest, CurrentHistoryItem)
6007 registerMockedHttpURLLoad("fixed_layout.html");
6008 std::string url = m_baseURL + "fixed_layout.html";
6010 FrameTestHelpers::WebViewHelper webViewHelper;
6011 webViewHelper.initialize();
6012 WebFrame* frame = webViewHelper.webView()->mainFrame();
6013 const FrameLoader& mainFrameLoader = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->loader();
6014 WebURLRequest request;
6015 request.initialize();
6016 request.setURL(toKURL(url));
6017 frame->loadRequest(request);
6019 // Before commit, there is no history item.
6020 EXPECT_FALSE(mainFrameLoader.currentItem());
6022 FrameTestHelpers::pumpPendingRequestsDoNotUse(frame);
6024 // After commit, there is.
6025 HistoryItem* item = mainFrameLoader.currentItem();
6027 EXPECT_EQ(WTF::String(url.data()), item->urlString());
6030 class FailCreateChildFrame : public FrameTestHelpers::TestWebFrameClient {
6032 FailCreateChildFrame() : m_callCount(0) { }
6034 virtual WebFrame* createChildFrame(WebLocalFrame* parent, const WebString& frameName) override
6040 int callCount() const { return m_callCount; }
6046 // Test that we don't crash if WebFrameClient::createChildFrame() fails.
6047 TEST_F(WebFrameTest, CreateChildFrameFailure)
6049 registerMockedHttpURLLoad("create_child_frame_fail.html");
6050 FailCreateChildFrame client;
6051 FrameTestHelpers::WebViewHelper webViewHelper;
6052 webViewHelper.initializeAndLoad(m_baseURL + "create_child_frame_fail.html", true, &client);
6054 EXPECT_EQ(1, client.callCount());
6057 TEST_F(WebFrameTest, fixedPositionInFixedViewport)
6059 UseMockScrollbarSettings mockScrollbarSettings;
6060 registerMockedHttpURLLoad("fixed-position-in-fixed-viewport.html");
6061 FrameTestHelpers::WebViewHelper webViewHelper;
6062 webViewHelper.initializeAndLoad(m_baseURL + "fixed-position-in-fixed-viewport.html", true, 0, 0, enableViewportSettings);
6064 WebView* webView = webViewHelper.webView();
6065 webView->resize(WebSize(100, 100));
6068 Document* document = toWebLocalFrameImpl(webView->mainFrame())->frame()->document();
6069 Element* bottomFixed = document->getElementById("bottom-fixed");
6070 Element* topBottomFixed = document->getElementById("top-bottom-fixed");
6071 Element* rightFixed = document->getElementById("right-fixed");
6072 Element* leftRightFixed = document->getElementById("left-right-fixed");
6074 webView->resize(WebSize(100, 200));
6076 EXPECT_EQ(200, bottomFixed->offsetTop() + bottomFixed->offsetHeight());
6077 EXPECT_EQ(200, topBottomFixed->offsetHeight());
6079 webView->settings()->setMainFrameResizesAreOrientationChanges(false);
6080 webView->resize(WebSize(200, 200));
6082 EXPECT_EQ(200, rightFixed->offsetLeft() + rightFixed->offsetWidth());
6083 EXPECT_EQ(200, leftRightFixed->offsetWidth());
6085 webView->settings()->setMainFrameResizesAreOrientationChanges(true);
6086 // Will scale the page by 1.5.
6087 webView->resize(WebSize(300, 330));
6089 EXPECT_EQ(220, bottomFixed->offsetTop() + bottomFixed->offsetHeight());
6090 EXPECT_EQ(220, topBottomFixed->offsetHeight());
6091 EXPECT_EQ(200, rightFixed->offsetLeft() + rightFixed->offsetWidth());
6092 EXPECT_EQ(200, leftRightFixed->offsetWidth());
6095 TEST_F(WebFrameTest, FrameViewSetFrameRect)
6097 FrameTestHelpers::WebViewHelper webViewHelper;
6098 webViewHelper.initializeAndLoad("about:blank");
6100 FrameView* frameView = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
6101 frameView->setFrameRect(IntRect(0, 0, 200, 200));
6102 EXPECT_RECT_EQ(IntRect(0, 0, 200, 200), frameView->frameRect());
6103 frameView->setFrameRect(IntRect(100, 100, 200, 200));
6104 EXPECT_RECT_EQ(IntRect(100, 100, 200, 200), frameView->frameRect());
6107 // FIXME(bokan) Renable once Chromium-side of patch lands
6108 TEST_F(WebFrameTest, DISABLED_FrameViewScrollAccountsForTopControls)
6110 FrameTestHelpers::WebViewHelper webViewHelper;
6111 webViewHelper.initializeAndLoad("about:blank");
6113 WebViewImpl* webView = webViewHelper.webViewImpl();
6114 FrameView* frameView = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
6116 webView->setTopControlsLayoutHeight(0);
6117 webView->resize(WebSize(100, 100));
6118 webView->setPageScaleFactor(2.0f);
6121 webView->setMainFrameScrollOffset(WebPoint(20, 100));
6122 EXPECT_POINT_EQ(IntPoint(20, 50), IntPoint(frameView->scrollOffset()));
6124 // Simulate the top controls showing by 20px, thus shrinking the viewport
6125 // and allowing it to scroll an additional 10px (since we're 2X zoomed).
6126 webView->applyViewportDeltas(WebSize(0, 0), 1.0f, 20.0f);
6127 EXPECT_POINT_EQ(IntPoint(50, 60), frameView->maximumScrollPosition());
6129 // Show more, make sure the scroll actually gets clamped. Horizontal
6130 // direction shouldn't be affected.
6131 webView->applyViewportDeltas(WebSize(0, 0), 1.0f, 20.0f);
6132 webView->setMainFrameScrollOffset(WebPoint(100, 100));
6133 EXPECT_POINT_EQ(IntPoint(50, 70), IntPoint(frameView->scrollOffset()));
6135 // Hide until there's 10px showing.
6136 webView->applyViewportDeltas(WebSize(0, 0), 1.0f, -30.0f);
6137 EXPECT_POINT_EQ(IntPoint(50, 55), frameView->maximumScrollPosition());
6139 // Simulate a RenderPart::resize. The frame is resized to accomodate
6140 // the top controls and Blink's view of the top controls matches that of
6142 webView->setTopControlsLayoutHeight(10.0f);
6143 webView->resize(WebSize(100, 90));
6145 EXPECT_POINT_EQ(IntPoint(50, 45), frameView->maximumScrollPosition());
6147 // Now simulate hiding.
6148 webView->applyViewportDeltas(WebSize(0, 0), 1.0f, -10.0f);
6149 EXPECT_POINT_EQ(IntPoint(50, 40), frameView->maximumScrollPosition());
6151 // Reset to original state: 100px widget height, top controls fully hidden.
6152 webView->setTopControlsLayoutHeight(0.0f);
6153 webView->resize(WebSize(100, 100));
6155 EXPECT_POINT_EQ(IntPoint(50, 50), frameView->maximumScrollPosition());
6157 // Show the top controls by just 1px, since we're zoomed in to 2X, that
6158 // should allow an extra 0.5px of scrolling, but since we quantize to ints
6159 // it should clamp such that we don't show anything outside bounds.
6160 webView->applyViewportDeltas(WebSize(0, 0), 1.0f, 1.0f);
6161 EXPECT_POINT_EQ(IntPoint(50, 50), frameView->maximumScrollPosition());
6163 webView->applyViewportDeltas(WebSize(0, 0), 1.0f, 2.0f);
6164 EXPECT_POINT_EQ(IntPoint(50, 51), frameView->maximumScrollPosition());
6167 TEST_F(WebFrameTest, FullscreenLayerSize)
6169 FakeCompositingWebViewClient client;
6170 registerMockedHttpURLLoad("fullscreen_div.html");
6171 FrameTestHelpers::WebViewHelper webViewHelper;
6172 int viewportWidth = 640;
6173 int viewportHeight = 480;
6174 client.m_screenInfo.rect.width = viewportWidth;
6175 client.m_screenInfo.rect.height = viewportHeight;
6176 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "fullscreen_div.html", true, 0, &client, configurePinchVirtualViewport);
6177 webViewImpl->resize(WebSize(viewportWidth, viewportHeight));
6178 webViewImpl->layout();
6180 Document* document = toWebLocalFrameImpl(webViewImpl->mainFrame())->frame()->document();
6181 UserGestureIndicator gesture(DefinitelyProcessingUserGesture);
6182 Element* divFullscreen = document->getElementById("div1");
6183 Fullscreen::from(*document).requestFullscreen(*divFullscreen, Fullscreen::PrefixedRequest);
6184 webViewImpl->didEnterFullScreen();
6185 webViewImpl->layout();
6186 ASSERT_TRUE(Fullscreen::isFullScreen(*document));
6188 // Verify that the element is sized to the viewport.
6189 RenderFullScreen* fullscreenRenderer = Fullscreen::from(*document).fullScreenRenderer();
6190 EXPECT_EQ(viewportWidth, fullscreenRenderer->logicalWidth().toInt());
6191 EXPECT_EQ(viewportHeight, fullscreenRenderer->logicalHeight().toInt());
6193 // Verify it's updated after a device rotation.
6194 client.m_screenInfo.rect.width = viewportHeight;
6195 client.m_screenInfo.rect.height = viewportWidth;
6196 webViewImpl->resize(WebSize(viewportHeight, viewportWidth));
6197 webViewImpl->layout();
6198 EXPECT_EQ(viewportHeight, fullscreenRenderer->logicalWidth().toInt());
6199 EXPECT_EQ(viewportWidth, fullscreenRenderer->logicalHeight().toInt());
6202 TEST_F(WebFrameTest, FullscreenLayerNonScrollable)
6204 FakeCompositingWebViewClient client;
6205 registerMockedHttpURLLoad("fullscreen_div.html");
6206 FrameTestHelpers::WebViewHelper webViewHelper;
6207 int viewportWidth = 640;
6208 int viewportHeight = 480;
6209 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "fullscreen_div.html", true, 0, &client, configurePinchVirtualViewport);
6210 webViewImpl->resize(WebSize(viewportWidth, viewportHeight));
6211 webViewImpl->layout();
6213 Document* document = toWebLocalFrameImpl(webViewImpl->mainFrame())->frame()->document();
6214 UserGestureIndicator gesture(DefinitelyProcessingUserGesture);
6215 Element* divFullscreen = document->getElementById("div1");
6216 Fullscreen::from(*document).requestFullscreen(*divFullscreen, Fullscreen::PrefixedRequest);
6217 webViewImpl->didEnterFullScreen();
6218 webViewImpl->layout();
6220 // Verify that the main frame is nonscrollable.
6221 ASSERT_TRUE(Fullscreen::isFullScreen(*document));
6222 WebLayer* webScrollLayer = webViewImpl->compositor()->scrollLayer()->platformLayer();
6223 ASSERT_FALSE(webScrollLayer->userScrollableHorizontal());
6224 ASSERT_FALSE(webScrollLayer->userScrollableVertical());
6226 // Verify that the main frame is scrollable upon exiting fullscreen.
6227 webViewImpl->didExitFullScreen();
6228 webViewImpl->layout();
6229 ASSERT_FALSE(Fullscreen::isFullScreen(*document));
6230 webScrollLayer = webViewImpl->compositor()->scrollLayer()->platformLayer();
6231 ASSERT_TRUE(webScrollLayer->userScrollableHorizontal());
6232 ASSERT_TRUE(webScrollLayer->userScrollableVertical());
6235 TEST_F(WebFrameTest, FullscreenMainFrame)
6237 FakeCompositingWebViewClient client;
6238 registerMockedHttpURLLoad("fullscreen_div.html");
6239 FrameTestHelpers::WebViewHelper webViewHelper;
6240 int viewportWidth = 640;
6241 int viewportHeight = 480;
6242 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "fullscreen_div.html", true, 0, &client, configurePinchVirtualViewport);
6243 webViewImpl->resize(WebSize(viewportWidth, viewportHeight));
6244 webViewImpl->layout();
6246 Document* document = toWebLocalFrameImpl(webViewImpl->mainFrame())->frame()->document();
6247 UserGestureIndicator gesture(DefinitelyProcessingUserGesture);
6248 Fullscreen::from(*document).requestFullscreen(*document->documentElement(), Fullscreen::PrefixedRequest);
6249 webViewImpl->didEnterFullScreen();
6250 webViewImpl->layout();
6252 // Verify that the main frame is still scrollable.
6253 ASSERT_TRUE(Fullscreen::isFullScreen(*document));
6254 WebLayer* webScrollLayer = webViewImpl->compositor()->scrollLayer()->platformLayer();
6255 ASSERT_TRUE(webScrollLayer->scrollable());
6256 ASSERT_TRUE(webScrollLayer->userScrollableHorizontal());
6257 ASSERT_TRUE(webScrollLayer->userScrollableVertical());
6259 // Verify the main frame still behaves correctly after a resize.
6260 webViewImpl->resize(WebSize(viewportHeight, viewportWidth));
6261 ASSERT_TRUE(webScrollLayer->scrollable());
6262 ASSERT_TRUE(webScrollLayer->userScrollableHorizontal());
6263 ASSERT_TRUE(webScrollLayer->userScrollableVertical());
6266 TEST_F(WebFrameTest, FullscreenSubframe)
6268 FakeCompositingWebViewClient client;
6269 registerMockedHttpURLLoad("fullscreen_iframe.html");
6270 registerMockedHttpURLLoad("fullscreen_div.html");
6271 FrameTestHelpers::WebViewHelper webViewHelper;
6272 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "fullscreen_iframe.html", true, 0, &client, configurePinchVirtualViewport);
6273 int viewportWidth = 640;
6274 int viewportHeight = 480;
6275 client.m_screenInfo.rect.width = viewportWidth;
6276 client.m_screenInfo.rect.height = viewportHeight;
6277 webViewImpl->resize(WebSize(viewportWidth, viewportHeight));
6278 webViewImpl->layout();
6280 Document* document = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame()->firstChild())->frame()->document();
6281 UserGestureIndicator gesture(DefinitelyProcessingUserGesture);
6282 Element* divFullscreen = document->getElementById("div1");
6283 Fullscreen::from(*document).requestFullscreen(*divFullscreen, Fullscreen::PrefixedRequest);
6284 webViewImpl->didEnterFullScreen();
6285 webViewImpl->layout();
6287 // Verify that the element is sized to the viewport.
6288 RenderFullScreen* fullscreenRenderer = Fullscreen::from(*document).fullScreenRenderer();
6289 EXPECT_EQ(viewportWidth, fullscreenRenderer->logicalWidth().toInt());
6290 EXPECT_EQ(viewportHeight, fullscreenRenderer->logicalHeight().toInt());
6292 // Verify it's updated after a device rotation.
6293 client.m_screenInfo.rect.width = viewportHeight;
6294 client.m_screenInfo.rect.height = viewportWidth;
6295 webViewImpl->resize(WebSize(viewportHeight, viewportWidth));
6296 webViewImpl->layout();
6297 EXPECT_EQ(viewportHeight, fullscreenRenderer->logicalWidth().toInt());
6298 EXPECT_EQ(viewportWidth, fullscreenRenderer->logicalHeight().toInt());
6301 TEST_F(WebFrameTest, FullscreenMediaStreamVideo)
6303 RuntimeEnabledFeatures::setOverlayFullscreenVideoEnabled(true);
6304 FakeCompositingWebViewClient client;
6305 registerMockedHttpURLLoad("fullscreen_video.html");
6306 FrameTestHelpers::WebViewHelper webViewHelper;
6307 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "fullscreen_video.html", true, 0, &client, configurePinchVirtualViewport);
6308 int viewportWidth = 640;
6309 int viewportHeight = 480;
6310 client.m_screenInfo.rect.width = viewportWidth;
6311 client.m_screenInfo.rect.height = viewportHeight;
6312 webViewImpl->resize(WebSize(viewportWidth, viewportHeight));
6313 webViewImpl->layout();
6315 // Fake the video element as MediaStream
6316 RefPtrWillBeRawPtr<NullExecutionContext> context = adoptRefWillBeNoop(new NullExecutionContext());
6317 MediaStreamRegistry::registry().registerURL(0, toKURL(m_baseURL + "test.webm"), MediaStream::create(context.get()));
6318 Document* document = toWebLocalFrameImpl(webViewImpl->mainFrame())->frame()->document();
6319 UserGestureIndicator gesture(DefinitelyProcessingUserGesture);
6320 Element* videoFullscreen = document->getElementById("video");
6321 Fullscreen::from(*document).requestFullscreen(*videoFullscreen, Fullscreen::PrefixedRequest);
6322 webViewImpl->didEnterFullScreen();
6323 webViewImpl->layout();
6325 // Verify that the video layer is visible in fullscreen.
6326 RenderLayer* renderLayer = videoFullscreen->renderer()->enclosingLayer();
6327 GraphicsLayer* graphicsLayer = renderLayer->graphicsLayerBacking();
6328 EXPECT_TRUE(graphicsLayer->contentsAreVisible());
6331 TEST_F(WebFrameTest, RenderBlockPercentHeightDescendants)
6333 registerMockedHttpURLLoad("percent-height-descendants.html");
6334 FrameTestHelpers::WebViewHelper webViewHelper;
6335 webViewHelper.initializeAndLoad(m_baseURL + "percent-height-descendants.html");
6337 WebView* webView = webViewHelper.webView();
6338 webView->resize(WebSize(800, 800));
6341 Document* document = toWebLocalFrameImpl(webView->mainFrame())->frame()->document();
6342 RenderBlock* container = toRenderBlock(document->getElementById("container")->renderer());
6343 RenderBox* percentHeightInAnonymous = toRenderBox(document->getElementById("percent-height-in-anonymous")->renderer());
6344 RenderBox* percentHeightDirectChild = toRenderBox(document->getElementById("percent-height-direct-child")->renderer());
6346 EXPECT_TRUE(RenderBlock::hasPercentHeightDescendant(percentHeightInAnonymous));
6347 EXPECT_TRUE(RenderBlock::hasPercentHeightDescendant(percentHeightDirectChild));
6349 ASSERT_TRUE(container->percentHeightDescendants());
6350 ASSERT_TRUE(container->hasPercentHeightDescendants());
6351 EXPECT_EQ(2U, container->percentHeightDescendants()->size());
6352 EXPECT_TRUE(container->percentHeightDescendants()->contains(percentHeightInAnonymous));
6353 EXPECT_TRUE(container->percentHeightDescendants()->contains(percentHeightDirectChild));
6355 RenderBlock* anonymousBlock = percentHeightInAnonymous->containingBlock();
6356 EXPECT_TRUE(anonymousBlock->isAnonymous());
6357 EXPECT_FALSE(anonymousBlock->hasPercentHeightDescendants());
6360 TEST_F(WebFrameTest, HasVisibleContentOnVisibleFrames)
6362 registerMockedHttpURLLoad("visible_frames.html");
6363 FrameTestHelpers::WebViewHelper webViewHelper;
6364 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "visible_frames.html");
6365 for (WebFrame* frame = webViewImpl->mainFrameImpl()->traverseNext(false); frame; frame = frame->traverseNext(false)) {
6366 EXPECT_TRUE(frame->hasVisibleContent());
6370 TEST_F(WebFrameTest, HasVisibleContentOnHiddenFrames)
6372 registerMockedHttpURLLoad("hidden_frames.html");
6373 FrameTestHelpers::WebViewHelper webViewHelper;
6374 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "hidden_frames.html");
6375 for (WebFrame* frame = webViewImpl->mainFrameImpl()->traverseNext(false); frame; frame = frame->traverseNext(false)) {
6376 EXPECT_FALSE(frame->hasVisibleContent());
6380 class ManifestChangeWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
6382 ManifestChangeWebFrameClient() : m_manifestChangeCount(0) { }
6383 virtual void didChangeManifest(WebLocalFrame*) override
6385 ++m_manifestChangeCount;
6388 int manifestChangeCount() { return m_manifestChangeCount; }
6391 int m_manifestChangeCount;
6394 TEST_F(WebFrameTest, NotifyManifestChange)
6396 registerMockedHttpURLLoad("link-manifest-change.html");
6398 ManifestChangeWebFrameClient webFrameClient;
6399 FrameTestHelpers::WebViewHelper webViewHelper;
6400 webViewHelper.initializeAndLoad(m_baseURL + "link-manifest-change.html", true, &webFrameClient);
6402 EXPECT_EQ(14, webFrameClient.manifestChangeCount());
6405 static ResourcePtr<Resource> fetchManifest(Document* document, const KURL& url)
6407 FetchRequest fetchRequest = FetchRequest(ResourceRequest(url), FetchInitiatorInfo());
6408 fetchRequest.mutableResourceRequest().setRequestContext(WebURLRequest::RequestContextManifest);
6410 return document->fetcher()->fetchSynchronously(fetchRequest);
6413 TEST_F(WebFrameTest, ManifestFetch)
6415 registerMockedHttpURLLoad("foo.html");
6416 registerMockedHttpURLLoad("link-manifest-fetch.json");
6418 FrameTestHelpers::WebViewHelper webViewHelper;
6419 webViewHelper.initializeAndLoad(m_baseURL + "foo.html");
6420 Document* document = toWebLocalFrameImpl(webViewHelper.webViewImpl()->mainFrame())->frame()->document();
6422 ResourcePtr<Resource> resource = fetchManifest(document, toKURL(m_baseURL + "link-manifest-fetch.json"));
6424 EXPECT_TRUE(resource->isLoaded());
6427 TEST_F(WebFrameTest, ManifestCSPFetchAllow)
6429 URLTestHelpers::registerMockedURLLoad(toKURL(m_notBaseURL + "link-manifest-fetch.json"), "link-manifest-fetch.json");
6430 registerMockedHttpURLLoadWithCSP("foo.html", "manifest-src *");
6432 FrameTestHelpers::WebViewHelper webViewHelper;
6433 webViewHelper.initializeAndLoad(m_baseURL + "foo.html");
6434 Document* document = toWebLocalFrameImpl(webViewHelper.webViewImpl()->mainFrame())->frame()->document();
6436 ResourcePtr<Resource> resource = fetchManifest(document, toKURL(m_notBaseURL + "link-manifest-fetch.json"));
6438 EXPECT_TRUE(resource->isLoaded());
6441 TEST_F(WebFrameTest, ManifestCSPFetchSelf)
6443 URLTestHelpers::registerMockedURLLoad(toKURL(m_notBaseURL + "link-manifest-fetch.json"), "link-manifest-fetch.json");
6444 registerMockedHttpURLLoadWithCSP("foo.html", "manifest-src 'self'");
6446 FrameTestHelpers::WebViewHelper webViewHelper;
6447 webViewHelper.initializeAndLoad(m_baseURL + "foo.html");
6448 Document* document = toWebLocalFrameImpl(webViewHelper.webViewImpl()->mainFrame())->frame()->document();
6450 ResourcePtr<Resource> resource = fetchManifest(document, toKURL(m_notBaseURL + "link-manifest-fetch.json"));
6452 EXPECT_EQ(0, resource.get()); // Fetching resource wasn't allowed.
6455 TEST_F(WebFrameTest, ManifestCSPFetchSelfReportOnly)
6457 URLTestHelpers::registerMockedURLLoad(toKURL(m_notBaseURL + "link-manifest-fetch.json"), "link-manifest-fetch.json");
6458 registerMockedHttpURLLoadWithCSP("foo.html", "manifest-src 'self'", /* report only */ true);
6460 FrameTestHelpers::WebViewHelper webViewHelper;
6461 webViewHelper.initializeAndLoad(m_baseURL + "foo.html");
6462 Document* document = toWebLocalFrameImpl(webViewHelper.webViewImpl()->mainFrame())->frame()->document();
6464 ResourcePtr<Resource> resource = fetchManifest(document, toKURL(m_notBaseURL + "link-manifest-fetch.json"));
6466 EXPECT_TRUE(resource->isLoaded());
6470 TEST_F(WebFrameTest, ReloadBypassingCache)
6472 // Check that a reload ignoring cache on a frame will result in the cache
6473 // policy of the request being set to ReloadBypassingCache.
6474 registerMockedHttpURLLoad("foo.html");
6475 FrameTestHelpers::WebViewHelper webViewHelper;
6476 webViewHelper.initializeAndLoad(m_baseURL + "foo.html", true);
6477 WebFrame* frame = webViewHelper.webView()->mainFrame();
6478 FrameTestHelpers::reloadFrameIgnoringCache(frame);
6479 EXPECT_EQ(WebURLRequest::ReloadBypassingCache, frame->dataSource()->request().cachePolicy());
6482 static void nodeImageTestValidation(const IntSize& referenceBitmapSize, DragImage* dragImage)
6484 // Prepare the reference bitmap.
6486 bitmap.allocN32Pixels(referenceBitmapSize.width(), referenceBitmapSize.height());
6487 SkCanvas canvas(bitmap);
6488 canvas.drawColor(SK_ColorGREEN);
6490 EXPECT_EQ(referenceBitmapSize.width(), dragImage->size().width());
6491 EXPECT_EQ(referenceBitmapSize.height(), dragImage->size().height());
6492 const SkBitmap& dragBitmap = dragImage->bitmap();
6493 SkAutoLockPixels lockPixel(dragBitmap);
6494 EXPECT_EQ(0, memcmp(bitmap.getPixels(), dragBitmap.getPixels(), bitmap.getSize()));
6497 TEST_F(WebFrameTest, NodeImageTestCSSTransform)
6499 FrameTestHelpers::WebViewHelper webViewHelper;
6500 OwnPtr<DragImage> dragImage = nodeImageTestSetup(&webViewHelper, std::string("case-css-transform"));
6501 EXPECT_TRUE(dragImage);
6503 nodeImageTestValidation(IntSize(40, 40), dragImage.get());
6506 TEST_F(WebFrameTest, NodeImageTestCSS3DTransform)
6508 FrameTestHelpers::WebViewHelper webViewHelper;
6509 OwnPtr<DragImage> dragImage = nodeImageTestSetup(&webViewHelper, std::string("case-css-3dtransform"));
6510 EXPECT_TRUE(dragImage);
6512 nodeImageTestValidation(IntSize(20, 40), dragImage.get());
6515 TEST_F(WebFrameTest, NodeImageTestInlineBlock)
6517 FrameTestHelpers::WebViewHelper webViewHelper;
6518 OwnPtr<DragImage> dragImage = nodeImageTestSetup(&webViewHelper, std::string("case-inlineblock"));
6519 EXPECT_TRUE(dragImage);
6521 nodeImageTestValidation(IntSize(40, 40), dragImage.get());
6524 TEST_F(WebFrameTest, NodeImageTestFloatLeft)
6526 FrameTestHelpers::WebViewHelper webViewHelper;
6527 OwnPtr<DragImage> dragImage = nodeImageTestSetup(&webViewHelper, std::string("case-float-left-overflow-hidden"));
6528 EXPECT_TRUE(dragImage);
6530 nodeImageTestValidation(IntSize(40, 40), dragImage.get());
6533 // Crashes on Android: http://crbug.com/403804
6535 TEST_F(WebFrameTest, DISABLED_PrintingBasic)
6537 TEST_F(WebFrameTest, PrintingBasic)
6540 FrameTestHelpers::WebViewHelper webViewHelper;
6541 webViewHelper.initializeAndLoad("data:text/html,Hello, world.");
6543 WebFrame* frame = webViewHelper.webView()->mainFrame();
6545 WebPrintParams printParams;
6546 printParams.printContentArea.width = 500;
6547 printParams.printContentArea.height = 500;
6549 int pageCount = frame->printBegin(printParams);
6550 EXPECT_EQ(1, pageCount);
6554 class ThemeColorTestWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
6556 ThemeColorTestWebFrameClient()
6557 : m_didNotify(false)
6563 m_didNotify = false;
6566 bool didNotify() const
6572 virtual void didChangeThemeColor()
6580 TEST_F(WebFrameTest, ThemeColor)
6582 registerMockedHttpURLLoad("theme_color_test.html");
6583 FrameTestHelpers::WebViewHelper webViewHelper;
6584 ThemeColorTestWebFrameClient client;
6585 webViewHelper.initializeAndLoad(m_baseURL + "theme_color_test.html", true, &client);
6586 EXPECT_TRUE(client.didNotify());
6587 WebLocalFrameImpl* frame = webViewHelper.webViewImpl()->mainFrameImpl();
6588 EXPECT_EQ(0xff0000ff, frame->document().themeColor());
6589 // Change color by rgb.
6591 frame->executeScript(WebScriptSource("document.getElementById('tc1').setAttribute('content', 'rgb(0, 0, 0)');"));
6592 EXPECT_TRUE(client.didNotify());
6593 EXPECT_EQ(0xff000000, frame->document().themeColor());
6594 // Change color by hsl.
6596 frame->executeScript(WebScriptSource("document.getElementById('tc1').setAttribute('content', 'hsl(240,100%, 50%)');"));
6597 EXPECT_TRUE(client.didNotify());
6598 EXPECT_EQ(0xff0000ff, frame->document().themeColor());
6599 // Change of second theme-color meta tag will not change frame's theme
6602 frame->executeScript(WebScriptSource("document.getElementById('tc2').setAttribute('content', '#00FF00');"));
6603 EXPECT_TRUE(client.didNotify());
6604 EXPECT_EQ(0xff0000ff, frame->document().themeColor());
6607 // Make sure that an embedder-triggered detach with a remote frame parent
6608 // doesn't leave behind dangling pointers.
6609 TEST_F(WebFrameTest, EmbedderTriggeredDetachWithRemoteMainFrame)
6611 // FIXME: Refactor some of this logic into WebViewHelper to make it easier to
6612 // write tests with a top-level remote frame.
6613 FrameTestHelpers::TestWebViewClient viewClient;
6614 FrameTestHelpers::TestWebRemoteFrameClient remoteClient;
6615 WebView* view = WebView::create(&viewClient);
6616 view->setMainFrame(WebRemoteFrame::create(&remoteClient));
6617 FrameTestHelpers::TestWebFrameClient childFrameClient;
6618 WebLocalFrame* childFrame = view->mainFrame()->toWebRemoteFrame()->createLocalChild("", &childFrameClient);
6620 // Purposely keep the LocalFrame alive so it's the last thing to be destroyed.
6621 RefPtrWillBePersistent<Frame> childCoreFrame = toCoreFrame(childFrame);
6623 childCoreFrame.clear();
6626 class WebFrameSwapTest : public WebFrameTest {
6630 registerMockedHttpURLLoad("frame-a-b-c.html");
6631 registerMockedHttpURLLoad("subframe-a.html");
6632 registerMockedHttpURLLoad("subframe-b.html");
6633 registerMockedHttpURLLoad("subframe-c.html");
6634 registerMockedHttpURLLoad("subframe-hello.html");
6636 m_webViewHelper.initializeAndLoad(m_baseURL + "frame-a-b-c.html");
6639 void reset() { m_webViewHelper.reset(); }
6640 WebFrame* mainFrame() const { return m_webViewHelper.webView()->mainFrame(); }
6643 FrameTestHelpers::WebViewHelper m_webViewHelper;
6646 TEST_F(WebFrameSwapTest, SwapMainFrame)
6648 WebFrame* remoteFrame = WebRemoteFrame::create(0);
6649 mainFrame()->swap(remoteFrame);
6651 FrameTestHelpers::TestWebFrameClient client;
6652 WebFrame* localFrame = WebLocalFrame::create(&client);
6653 remoteFrame->swap(localFrame);
6655 // Finally, make sure an embedder triggered load in the local frame swapped
6657 FrameTestHelpers::loadFrame(localFrame, m_baseURL + "subframe-hello.html");
6658 std::string content = localFrame->contentAsText(1024).utf8();
6659 EXPECT_EQ("hello", content);
6661 // Manually reset to break WebViewHelper's dependency on the stack allocated
6662 // TestWebFrameClient.
6664 remoteFrame->close();
6667 void swapAndVerifyFirstChildConsistency(const char* const message, WebFrame* parent, WebFrame* newChild)
6669 SCOPED_TRACE(message);
6670 parent->firstChild()->swap(newChild);
6672 EXPECT_EQ(newChild, parent->firstChild());
6673 EXPECT_EQ(newChild->parent(), parent);
6674 EXPECT_EQ(newChild, parent->lastChild()->previousSibling()->previousSibling());
6675 EXPECT_EQ(newChild->nextSibling(), parent->lastChild()->previousSibling());
6678 TEST_F(WebFrameSwapTest, SwapFirstChild)
6680 WebFrame* remoteFrame = WebRemoteFrame::create(0);
6681 swapAndVerifyFirstChildConsistency("local->remote", mainFrame(), remoteFrame);
6683 FrameTestHelpers::TestWebFrameClient client;
6684 WebFrame* localFrame = WebLocalFrame::create(&client);
6685 swapAndVerifyFirstChildConsistency("remote->local", mainFrame(), localFrame);
6687 // FIXME: This almost certainly fires more load events on the iframe element
6689 // Finally, make sure an embedder triggered load in the local frame swapped
6691 FrameTestHelpers::loadFrame(localFrame, m_baseURL + "subframe-hello.html");
6692 std::string content = localFrame->contentAsText(1024).utf8();
6693 EXPECT_EQ("hello", content);
6695 // Manually reset to break WebViewHelper's dependency on the stack allocated
6696 // TestWebFrameClient.
6698 remoteFrame->close();
6701 void swapAndVerifyMiddleChildConsistency(const char* const message, WebFrame* parent, WebFrame* newChild)
6703 SCOPED_TRACE(message);
6704 parent->firstChild()->nextSibling()->swap(newChild);
6706 EXPECT_EQ(newChild, parent->firstChild()->nextSibling());
6707 EXPECT_EQ(newChild, parent->lastChild()->previousSibling());
6708 EXPECT_EQ(newChild->parent(), parent);
6709 EXPECT_EQ(newChild, parent->firstChild()->nextSibling());
6710 EXPECT_EQ(newChild->previousSibling(), parent->firstChild());
6711 EXPECT_EQ(newChild, parent->lastChild()->previousSibling());
6712 EXPECT_EQ(newChild->nextSibling(), parent->lastChild());
6715 TEST_F(WebFrameSwapTest, SwapMiddleChild)
6717 WebFrame* remoteFrame = WebRemoteFrame::create(0);
6718 swapAndVerifyMiddleChildConsistency("local->remote", mainFrame(), remoteFrame);
6720 FrameTestHelpers::TestWebFrameClient client;
6721 WebFrame* localFrame = WebLocalFrame::create(&client);
6722 swapAndVerifyMiddleChildConsistency("remote->local", mainFrame(), localFrame);
6724 // FIXME: This almost certainly fires more load events on the iframe element
6726 // Finally, make sure an embedder triggered load in the local frame swapped
6728 FrameTestHelpers::loadFrame(localFrame, m_baseURL + "subframe-hello.html");
6729 std::string content = localFrame->contentAsText(1024).utf8();
6730 EXPECT_EQ("hello", content);
6732 // Manually reset to break WebViewHelper's dependency on the stack allocated
6733 // TestWebFrameClient.
6735 remoteFrame->close();
6738 void swapAndVerifyLastChildConsistency(const char* const message, WebFrame* parent, WebFrame* newChild)
6740 SCOPED_TRACE(message);
6741 parent->lastChild()->swap(newChild);
6743 EXPECT_EQ(newChild, parent->lastChild());
6744 EXPECT_EQ(newChild->parent(), parent);
6745 EXPECT_EQ(newChild, parent->firstChild()->nextSibling()->nextSibling());
6746 EXPECT_EQ(newChild->previousSibling(), parent->firstChild()->nextSibling());
6749 TEST_F(WebFrameSwapTest, SwapLastChild)
6751 WebFrame* remoteFrame = WebRemoteFrame::create(0);
6752 swapAndVerifyLastChildConsistency("local->remote", mainFrame(), remoteFrame);
6754 FrameTestHelpers::TestWebFrameClient client;
6755 WebFrame* localFrame = WebLocalFrame::create(&client);
6756 swapAndVerifyLastChildConsistency("remote->local", mainFrame(), localFrame);
6758 // FIXME: This almost certainly fires more load events on the iframe element
6760 // Finally, make sure an embedder triggered load in the local frame swapped
6762 FrameTestHelpers::loadFrame(localFrame, m_baseURL + "subframe-hello.html");
6763 std::string content = localFrame->contentAsText(1024).utf8();
6764 EXPECT_EQ("hello", content);
6766 // Manually reset to break WebViewHelper's dependency on the stack allocated
6767 // TestWebFrameClient.
6769 remoteFrame->close();
6772 void swapAndVerifySubframeConsistency(const char* const message, WebFrame* oldFrame, WebFrame* newFrame)
6774 SCOPED_TRACE(message);
6776 EXPECT_TRUE(oldFrame->firstChild());
6777 oldFrame->swap(newFrame);
6779 EXPECT_FALSE(newFrame->firstChild());
6780 EXPECT_FALSE(newFrame->lastChild());
6783 TEST_F(WebFrameSwapTest, SwapParentShouldDetachChildren)
6785 WebRemoteFrame* remoteFrame = WebRemoteFrame::create(0);
6786 WebFrame* targetFrame = mainFrame()->firstChild()->nextSibling();
6787 EXPECT_TRUE(targetFrame);
6788 swapAndVerifySubframeConsistency("local->remote", targetFrame, remoteFrame);
6790 targetFrame = mainFrame()->firstChild()->nextSibling();
6791 EXPECT_TRUE(targetFrame);
6793 // Create child frames in the target frame before testing the swap.
6794 FrameTestHelpers::TestWebRemoteFrameClient remoteFrameClient;
6795 remoteFrame->createRemoteChild("", &remoteFrameClient);
6797 FrameTestHelpers::TestWebFrameClient client;
6798 WebFrame* localFrame = WebLocalFrame::create(&client);
6799 swapAndVerifySubframeConsistency("remote->local", targetFrame, localFrame);
6801 // FIXME: This almost certainly fires more load events on the iframe element
6803 // Finally, make sure an embedder triggered load in the local frame swapped
6805 FrameTestHelpers::loadFrame(localFrame, m_baseURL + "subframe-hello.html");
6806 std::string content = localFrame->contentAsText(1024).utf8();
6807 EXPECT_EQ("hello", content);
6809 // Manually reset to break WebViewHelper's dependency on the stack allocated
6810 // TestWebFrameClient.
6812 remoteFrame->close();
6815 class MockDocumentThreadableLoaderClient : public DocumentThreadableLoaderClient {
6817 MockDocumentThreadableLoaderClient() : m_failed(false) { }
6818 virtual void didFail(const ResourceError&) override { m_failed = true;}
6820 void reset() { m_failed = false; }
6821 bool failed() { return m_failed; }
6826 // FIXME: This would be better as a unittest on DocumentThreadableLoader but it
6827 // requires spin-up of a frame. It may be possible to remove that requirement
6828 // and convert it to a unittest.
6829 TEST_F(WebFrameTest, LoaderOriginAccess)
6831 FrameTestHelpers::WebViewHelper webViewHelper;
6832 webViewHelper.initializeAndLoad("about:blank");
6834 SchemeRegistry::registerURLSchemeAsDisplayIsolated("chrome");
6836 // Cross-origin request.
6837 KURL resourceUrl(ParsedURLString, "chrome://test.pdf");
6838 registerMockedChromeURLLoad("test.pdf");
6840 RefPtrWillBeRawPtr<LocalFrame> frame(toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame()));
6842 MockDocumentThreadableLoaderClient client;
6843 ThreadableLoaderOptions options;
6845 // First try to load the request with regular access. Should fail.
6846 options.crossOriginRequestPolicy = UseAccessControl;
6847 ResourceLoaderOptions resourceLoaderOptions;
6848 DocumentThreadableLoader::loadResourceSynchronously(
6849 *frame->document(), ResourceRequest(resourceUrl), client, options, resourceLoaderOptions);
6850 EXPECT_TRUE(client.failed());
6853 // Try to load the request with cross origin access. Should succeed.
6854 options.crossOriginRequestPolicy = AllowCrossOriginRequests;
6855 DocumentThreadableLoader::loadResourceSynchronously(
6856 *frame->document(), ResourceRequest(resourceUrl), client, options, resourceLoaderOptions);
6857 EXPECT_FALSE(client.failed());
6860 class NavigationTransitionCallbackWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
6862 NavigationTransitionCallbackWebFrameClient()
6863 : m_navigationalDataReceivedCount(0)
6864 , m_provisionalLoadCount(0)
6865 , m_wasLastProvisionalLoadATransition(false) { }
6867 virtual void addNavigationTransitionData(const WebString& allowedDestinationOrigin, const WebString& selector, const WebString& markup) override
6869 m_navigationalDataReceivedCount++;
6872 virtual void didStartProvisionalLoad(WebLocalFrame* localFrame, bool isTransitionNavigation) override
6874 m_provisionalLoadCount++;
6875 m_wasLastProvisionalLoadATransition = isTransitionNavigation;
6878 unsigned navigationalDataReceivedCount() const { return m_navigationalDataReceivedCount; }
6879 unsigned provisionalLoadCount() const { return m_provisionalLoadCount; }
6880 bool wasLastProvisionalLoadATransition() const { return m_wasLastProvisionalLoadATransition; }
6883 unsigned m_navigationalDataReceivedCount;
6884 unsigned m_provisionalLoadCount;
6885 bool m_wasLastProvisionalLoadATransition;
6888 TEST_F(WebFrameTest, NavigationTransitionCallbacks)
6890 RuntimeEnabledFeatures::setNavigationTransitionsEnabled(true);
6891 FrameTestHelpers::WebViewHelper viewHelper;
6892 NavigationTransitionCallbackWebFrameClient frameClient;
6893 WebLocalFrame* localFrame = viewHelper.initialize(true, &frameClient)->mainFrame()->toWebLocalFrame();
6895 const char* transitionHTMLString =
6897 "<meta name='transition-elements' content='#foo;*'>"
6900 // Initial document load should not be a transition.
6901 FrameTestHelpers::loadHTMLString(localFrame, transitionHTMLString, toKURL("http://internal.test"));
6902 EXPECT_EQ(1u, frameClient.provisionalLoadCount());
6903 EXPECT_FALSE(frameClient.wasLastProvisionalLoadATransition());
6904 EXPECT_EQ(0u, frameClient.navigationalDataReceivedCount());
6906 // Going from internal.test containing transition elements to about:blank, should be a transition.
6907 FrameTestHelpers::loadHTMLString(localFrame, transitionHTMLString, toKURL("about:blank"));
6908 EXPECT_EQ(2u, frameClient.provisionalLoadCount());
6909 EXPECT_TRUE(frameClient.wasLastProvisionalLoadATransition());
6910 EXPECT_EQ(1u, frameClient.navigationalDataReceivedCount());
6912 // Navigating to the URL of the current page shouldn't be a transition.
6913 FrameTestHelpers::loadHTMLString(localFrame, transitionHTMLString, toKURL("about:blank"));
6914 EXPECT_EQ(3u, frameClient.provisionalLoadCount());
6915 EXPECT_FALSE(frameClient.wasLastProvisionalLoadATransition());
6916 EXPECT_EQ(1u, frameClient.navigationalDataReceivedCount());
6918 // Neither should a page reload.
6919 localFrame->reload();
6920 EXPECT_EQ(4u, frameClient.provisionalLoadCount());
6921 EXPECT_FALSE(frameClient.wasLastProvisionalLoadATransition());
6922 EXPECT_EQ(1u, frameClient.navigationalDataReceivedCount());