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.
35 #include <gmock/gmock.h>
36 #include <gtest/gtest.h>
37 #include "FrameTestHelpers.h"
38 #include "RuntimeEnabledFeatures.h"
41 #include "URLTestHelpers.h"
42 #include "WebDataSource.h"
43 #include "WebDocument.h"
44 #include "WebFindOptions.h"
45 #include "WebFormElement.h"
46 #include "WebFrameClient.h"
47 #include "WebFrameImpl.h"
48 #include "WebHistoryItem.h"
50 #include "WebScriptSource.h"
51 #include "WebSearchableFormData.h"
52 #include "WebSecurityOrigin.h"
53 #include "WebSecurityPolicy.h"
54 #include "WebSettings.h"
55 #include "WebSpellCheckClient.h"
56 #include "WebTextCheckingCompletion.h"
57 #include "WebTextCheckingResult.h"
58 #include "WebViewClient.h"
59 #include "WebViewImpl.h"
60 #include "core/dom/Clipboard.h"
61 #include "core/dom/DocumentMarkerController.h"
62 #include "core/events/MouseEvent.h"
63 #include "core/dom/Range.h"
64 #include "core/editing/Editor.h"
65 #include "core/editing/FrameSelection.h"
66 #include "core/editing/SpellChecker.h"
67 #include "core/editing/VisiblePosition.h"
68 #include "core/html/HTMLFormElement.h"
69 #include "core/loader/FrameLoadRequest.h"
70 #include "core/page/EventHandler.h"
71 #include "core/frame/Frame.h"
72 #include "core/frame/FrameView.h"
73 #include "core/page/Settings.h"
74 #include "core/platform/ScrollbarTheme.h"
75 #include "core/rendering/HitTestResult.h"
76 #include "core/rendering/RenderLayerCompositor.h"
77 #include "core/rendering/RenderView.h"
78 #include "core/rendering/TextAutosizer.h"
79 #include "platform/geometry/FloatRect.h"
80 #include "platform/network/ResourceError.h"
82 #include "public/platform/Platform.h"
83 #include "public/platform/WebFloatRect.h"
84 #include "public/platform/WebThread.h"
85 #include "public/platform/WebURL.h"
86 #include "public/platform/WebURLResponse.h"
87 #include "public/platform/WebUnitTestSupport.h"
88 #include "wtf/dtoa/utils.h"
89 #include "wtf/Forward.h"
92 using namespace WebKit;
93 using WebCore::Document;
94 using WebCore::DocumentMarker;
95 using WebCore::Element;
96 using WebCore::FloatRect;
97 using WebCore::HitTestRequest;
99 using WebKit::URLTestHelpers::toKURL;
100 using WebKit::FrameTestHelpers::runPendingTasks;
104 const int touchPointPadding = 32;
106 #define EXPECT_EQ_RECT(a, b) \
107 EXPECT_EQ(a.x(), b.x()); \
108 EXPECT_EQ(a.y(), b.y()); \
109 EXPECT_EQ(a.width(), b.width()); \
110 EXPECT_EQ(a.height(), b.height());
112 class FakeWebFrameClient : public WebFrameClient {
113 // To make the destructor public.
116 class FakeCompositingWebViewClient : public WebViewClient {
118 virtual ~FakeCompositingWebViewClient()
122 virtual void initializeLayerTreeView() OVERRIDE
124 m_layerTreeView = adoptPtr(Platform::current()->unitTestSupport()->createLayerTreeViewForTesting(WebUnitTestSupport::TestViewTypeUnitTest));
125 ASSERT(m_layerTreeView);
128 virtual WebLayerTreeView* layerTreeView() OVERRIDE
130 return m_layerTreeView.get();
133 FakeWebFrameClient m_fakeWebFrameClient;
136 OwnPtr<WebLayerTreeView> m_layerTreeView;
139 class WebFrameTest : public testing::Test {
142 : m_baseURL("http://www.test.com/")
143 , m_chromeURL("chrome://")
147 virtual ~WebFrameTest()
149 Platform::current()->unitTestSupport()->unregisterAllMockedURLs();
152 void registerMockedHttpURLLoad(const std::string& fileName)
154 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8(fileName.c_str()));
157 void registerMockedChromeURLLoad(const std::string& fileName)
159 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_chromeURL.c_str()), WebString::fromUTF8(fileName.c_str()));
162 static void configueCompositingWebView(WebSettings* settings)
164 settings->setForceCompositingMode(true);
165 settings->setAcceleratedCompositingEnabled(true);
166 settings->setAcceleratedCompositingForFixedPositionEnabled(true);
167 settings->setAcceleratedCompositingForOverflowScrollEnabled(true);
168 settings->setAcceleratedCompositingForScrollableFramesEnabled(true);
169 settings->setCompositedScrollingForFramesEnabled(true);
170 settings->setFixedPositionCreatesStackingContext(true);
173 void initializeTextSelectionWebView(const std::string& url, FrameTestHelpers::WebViewHelper* webViewHelper)
175 webViewHelper->initializeAndLoad(url, true);
176 webViewHelper->webView()->settings()->setDefaultFontSize(12);
177 webViewHelper->webView()->resize(WebSize(640, 480));
180 std::string m_baseURL;
181 std::string m_chromeURL;
184 class UseMockScrollbarSettings {
186 UseMockScrollbarSettings()
188 WebCore::Settings::setMockScrollbarsEnabled(true);
189 WebCore::RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(true);
190 EXPECT_TRUE(WebCore::ScrollbarTheme::theme()->usesOverlayScrollbars());
193 ~UseMockScrollbarSettings()
195 WebCore::Settings::setMockScrollbarsEnabled(false);
196 WebCore::RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(false);
200 TEST_F(WebFrameTest, ContentText)
202 registerMockedHttpURLLoad("iframes_test.html");
203 registerMockedHttpURLLoad("visible_iframe.html");
204 registerMockedHttpURLLoad("invisible_iframe.html");
205 registerMockedHttpURLLoad("zero_sized_iframe.html");
207 FrameTestHelpers::WebViewHelper webViewHelper;
208 webViewHelper.initializeAndLoad(m_baseURL + "iframes_test.html");
210 // Now retrieve the frames text and test it only includes visible elements.
211 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
212 EXPECT_NE(std::string::npos, content.find(" visible paragraph"));
213 EXPECT_NE(std::string::npos, content.find(" visible iframe"));
214 EXPECT_EQ(std::string::npos, content.find(" invisible pararaph"));
215 EXPECT_EQ(std::string::npos, content.find(" invisible iframe"));
216 EXPECT_EQ(std::string::npos, content.find("iframe with zero size"));
219 TEST_F(WebFrameTest, FrameForEnteredContext)
221 registerMockedHttpURLLoad("iframes_test.html");
222 registerMockedHttpURLLoad("visible_iframe.html");
223 registerMockedHttpURLLoad("invisible_iframe.html");
224 registerMockedHttpURLLoad("zero_sized_iframe.html");
226 FrameTestHelpers::WebViewHelper webViewHelper;
227 webViewHelper.initializeAndLoad(m_baseURL + "iframes_test.html", true);
229 v8::HandleScope scope(v8::Isolate::GetCurrent());
230 EXPECT_EQ(webViewHelper.webView()->mainFrame(), WebFrame::frameForContext(webViewHelper.webView()->mainFrame()->mainWorldScriptContext()));
231 EXPECT_EQ(webViewHelper.webView()->mainFrame()->firstChild(), WebFrame::frameForContext(webViewHelper.webView()->mainFrame()->firstChild()->mainWorldScriptContext()));
234 TEST_F(WebFrameTest, FormWithNullFrame)
236 registerMockedHttpURLLoad("form.html");
238 FrameTestHelpers::WebViewHelper webViewHelper;
239 webViewHelper.initializeAndLoad(m_baseURL + "form.html");
241 WebVector<WebFormElement> forms;
242 webViewHelper.webView()->mainFrame()->document().forms(forms);
243 webViewHelper.reset();
245 EXPECT_EQ(forms.size(), 1U);
247 // This test passes if this doesn't crash.
248 WebSearchableFormData searchableDataForm(forms[0]);
251 TEST_F(WebFrameTest, ChromePageJavascript)
253 registerMockedChromeURLLoad("history.html");
255 // Pass true to enable JavaScript.
256 FrameTestHelpers::WebViewHelper webViewHelper;
257 webViewHelper.initializeAndLoad(m_chromeURL + "history.html", true);
259 // Try to run JS against the chrome-style URL.
260 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.appendChild(document.createTextNode('Clobbered'))");
262 // Required to see any updates in contentAsText.
263 webViewHelper.webView()->layout();
265 // Now retrieve the frame's text and ensure it was modified by running javascript.
266 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
267 EXPECT_NE(std::string::npos, content.find("Clobbered"));
270 TEST_F(WebFrameTest, ChromePageNoJavascript)
272 registerMockedChromeURLLoad("history.html");
274 /// Pass true to enable JavaScript.
275 FrameTestHelpers::WebViewHelper webViewHelper;
276 webViewHelper.initializeAndLoad(m_chromeURL + "history.html", true);
278 // Try to run JS against the chrome-style URL after prohibiting it.
279 WebSecurityPolicy::registerURLSchemeAsNotAllowingJavascriptURLs("chrome");
280 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.appendChild(document.createTextNode('Clobbered'))");
282 // Required to see any updates in contentAsText.
283 webViewHelper.webView()->layout();
285 // Now retrieve the frame's text and ensure it wasn't modified by running javascript.
286 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
287 EXPECT_EQ(std::string::npos, content.find("Clobbered"));
290 TEST_F(WebFrameTest, LocationSetHostWithMissingPort)
292 std::string fileName = "print-location-href.html";
293 registerMockedHttpURLLoad(fileName);
294 URLTestHelpers::registerMockedURLLoad(toKURL("http://www.test.com:0/" + fileName), WebString::fromUTF8(fileName));
296 FrameTestHelpers::WebViewHelper webViewHelper;
298 /// Pass true to enable JavaScript.
299 webViewHelper.initializeAndLoad(m_baseURL + fileName, true);
301 // Setting host to "hostname:" should be treated as "hostname:0".
302 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:location.host = 'www.test.com:'; void 0;");
305 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
307 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.textContent = location.href; void 0;");
308 // Required to see any updates in contentAsText.
310 webViewHelper.webView()->layout();
312 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
313 EXPECT_EQ("http://www.test.com:0/" + fileName, content);
316 TEST_F(WebFrameTest, LocationSetEmptyPort)
318 std::string fileName = "print-location-href.html";
319 registerMockedHttpURLLoad(fileName);
320 URLTestHelpers::registerMockedURLLoad(toKURL("http://www.test.com:0/" + fileName), WebString::fromUTF8(fileName));
322 FrameTestHelpers::WebViewHelper webViewHelper;
324 /// Pass true to enable JavaScript.
325 webViewHelper.initializeAndLoad(m_baseURL + fileName, true);
327 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:location.port = ''; void 0;");
330 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
332 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.textContent = location.href; void 0;");
333 // Required to see any updates in contentAsText.
335 webViewHelper.webView()->layout();
337 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
338 EXPECT_EQ("http://www.test.com:0/" + fileName, content);
341 class CSSCallbackWebFrameClient : public WebFrameClient {
343 CSSCallbackWebFrameClient() : m_updateCount(0) { }
344 virtual void didMatchCSS(WebFrame*, const WebVector<WebString>& newlyMatchingSelectors, const WebVector<WebString>& stoppedMatchingSelectors) OVERRIDE;
346 std::map<WebFrame*, std::set<std::string> > m_matchedSelectors;
350 void CSSCallbackWebFrameClient::didMatchCSS(WebFrame* frame, const WebVector<WebString>& newlyMatchingSelectors, const WebVector<WebString>& stoppedMatchingSelectors)
353 std::set<std::string>& frameSelectors = m_matchedSelectors[frame];
354 for (size_t i = 0; i < newlyMatchingSelectors.size(); ++i) {
355 std::string selector = newlyMatchingSelectors[i].utf8();
356 EXPECT_EQ(0U, frameSelectors.count(selector)) << selector;
357 frameSelectors.insert(selector);
359 for (size_t i = 0; i < stoppedMatchingSelectors.size(); ++i) {
360 std::string selector = stoppedMatchingSelectors[i].utf8();
361 EXPECT_EQ(1U, frameSelectors.count(selector)) << selector;
362 frameSelectors.erase(selector);
366 class WebFrameCSSCallbackTest : public testing::Test {
368 WebFrameCSSCallbackTest()
371 m_frame = m_helper.initializeAndLoad("about:blank", true, &m_client)->mainFrame();
374 ~WebFrameCSSCallbackTest()
376 EXPECT_EQ(1U, m_client.m_matchedSelectors.size());
379 WebDocument doc() const
381 return m_frame->document();
384 int updateCount() const
386 return m_client.m_updateCount;
389 const std::set<std::string>& matchedSelectors()
391 return m_client.m_matchedSelectors[m_frame];
394 void loadHTML(const WebData& html)
396 m_frame->loadHTMLString(html, toKURL("about:blank"));
400 void executeScript(const WebString& code)
402 m_frame->executeScript(WebScriptSource(code));
406 CSSCallbackWebFrameClient m_client;
407 FrameTestHelpers::WebViewHelper m_helper;
412 TEST_F(WebFrameCSSCallbackTest, DISABLED_AuthorStyleSheet)
416 // This stylesheet checks that the internal property and value can't be
417 // set by a stylesheet, only WebDocument::watchCSSSelectors().
418 "div.initial_on { -internal-callback: none; }"
419 "div.initial_off { -internal-callback: -internal-presence; }"
421 "<div class=\"initial_on\"></div>"
422 "<div class=\"initial_off\"></div>");
424 std::vector<WebString> selectors;
425 selectors.push_back(WebString::fromUTF8("div.initial_on"));
426 m_frame->document().watchCSSSelectors(WebVector<WebString>(selectors));
428 EXPECT_EQ(1, updateCount());
429 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("div.initial_on"));
431 // Check that adding a watched selector calls back for already-present nodes.
432 selectors.push_back(WebString::fromUTF8("div.initial_off"));
433 doc().watchCSSSelectors(WebVector<WebString>(selectors));
435 EXPECT_EQ(2, updateCount());
436 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("div.initial_off", "div.initial_on"));
438 // Check that we can turn off callbacks for certain selectors.
439 doc().watchCSSSelectors(WebVector<WebString>());
441 EXPECT_EQ(3, updateCount());
442 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
445 TEST_F(WebFrameCSSCallbackTest, SharedRenderStyle)
447 // Check that adding an element calls back when it matches an existing rule.
448 std::vector<WebString> selectors;
449 selectors.push_back(WebString::fromUTF8("span"));
450 doc().watchCSSSelectors(WebVector<WebString>(selectors));
453 "i1 = document.createElement('span');"
454 "i1.id = 'first_span';"
455 "document.body.appendChild(i1)");
456 EXPECT_EQ(1, updateCount());
457 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
459 // Adding a second element that shares a RenderStyle shouldn't call back.
460 // We use <span>s to avoid default style rules that can set
461 // RenderStyle::unique().
463 "i2 = document.createElement('span');"
464 "i2.id = 'second_span';"
465 "i1 = document.getElementById('first_span');"
466 "i1.parentNode.insertBefore(i2, i1.nextSibling);");
467 EXPECT_EQ(1, updateCount());
468 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
470 // Removing the first element shouldn't call back.
472 "i1 = document.getElementById('first_span');"
473 "i1.parentNode.removeChild(i1);");
474 EXPECT_EQ(1, updateCount());
475 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
477 // But removing the second element *should* call back.
479 "i2 = document.getElementById('second_span');"
480 "i2.parentNode.removeChild(i2);");
481 EXPECT_EQ(2, updateCount());
482 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
485 TEST_F(WebFrameCSSCallbackTest, DISABLED_CatchesAttributeChange)
487 loadHTML("<span></span>");
489 std::vector<WebString> selectors;
490 selectors.push_back(WebString::fromUTF8("span[attr=\"value\"]"));
491 doc().watchCSSSelectors(WebVector<WebString>(selectors));
494 EXPECT_EQ(0, updateCount());
495 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
498 "document.querySelector('span').setAttribute('attr', 'value');");
499 EXPECT_EQ(1, updateCount());
500 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span[attr=\"value\"]"));
503 TEST_F(WebFrameCSSCallbackTest, DISABLED_DisplayNone)
505 loadHTML("<div style='display:none'><span></span></div>");
507 std::vector<WebString> selectors;
508 selectors.push_back(WebString::fromUTF8("span"));
509 doc().watchCSSSelectors(WebVector<WebString>(selectors));
512 EXPECT_EQ(0, updateCount()) << "Don't match elements in display:none trees.";
515 "d = document.querySelector('div');"
516 "d.style.display = 'block';");
517 EXPECT_EQ(1, updateCount()) << "Match elements when they become displayed.";
518 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
521 "d = document.querySelector('div');"
522 "d.style.display = 'none';");
523 EXPECT_EQ(2, updateCount()) << "Unmatch elements when they become undisplayed.";
524 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
527 "s = document.querySelector('span');"
528 "s.style.display = 'none';");
529 EXPECT_EQ(2, updateCount()) << "No effect from no-display'ing a span that's already undisplayed.";
532 "d = document.querySelector('div');"
533 "d.style.display = 'block';");
534 EXPECT_EQ(2, updateCount()) << "No effect from displaying a div whose span is display:none.";
537 "s = document.querySelector('span');"
538 "s.style.display = 'inline';");
539 EXPECT_EQ(3, updateCount()) << "Now the span is visible and produces a callback.";
540 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
543 "s = document.querySelector('span');"
544 "s.style.display = 'none';");
545 EXPECT_EQ(4, updateCount()) << "Undisplaying the span directly should produce another callback.";
546 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
549 // Flaky on Win7 and Mac dbg: crbug.com/314554
550 #if (OS(MACOSX) || OS(WIN)) && !defined(NDEBUG)
551 TEST_F(WebFrameCSSCallbackTest, FLAKY_Reparenting)
553 TEST_F(WebFrameCSSCallbackTest, Reparenting)
557 "<div id='d1'><span></span></div>"
558 "<div id='d2'></div>");
560 std::vector<WebString> selectors;
561 selectors.push_back(WebString::fromUTF8("span"));
562 doc().watchCSSSelectors(WebVector<WebString>(selectors));
565 EXPECT_EQ(1, updateCount());
566 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
569 "s = document.querySelector('span');"
570 "d2 = document.getElementById('d2');"
571 "d2.appendChild(s);");
572 EXPECT_EQ(1, updateCount()) << "Just moving an element that continues to match shouldn't send a spurious callback.";
573 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
576 // Flaky: crbug.com/310440
577 TEST_F(WebFrameCSSCallbackTest, DISABLED_MultiSelector)
579 loadHTML("<span></span>");
581 // Check that selector lists match as the whole list, not as each element
583 std::vector<WebString> selectors;
584 selectors.push_back(WebString::fromUTF8("span"));
585 selectors.push_back(WebString::fromUTF8("span,p"));
586 doc().watchCSSSelectors(WebVector<WebString>(selectors));
589 EXPECT_EQ(1, updateCount());
590 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span", "span, p"));
593 // Flaky on MacOS https://code.google.com/p/chromium/issues/detail?id=310361
595 TEST_F(WebFrameCSSCallbackTest, DISABLED_InvalidSelector)
597 TEST_F(WebFrameCSSCallbackTest, InvalidSelector)
600 loadHTML("<p><span></span></p>");
602 // Build a list with one valid selector and one invalid.
603 std::vector<WebString> selectors;
604 selectors.push_back(WebString::fromUTF8("span"));
605 selectors.push_back(WebString::fromUTF8("[")); // Invalid.
606 selectors.push_back(WebString::fromUTF8("p span")); // Not compound.
607 doc().watchCSSSelectors(WebVector<WebString>(selectors));
610 EXPECT_EQ(1, updateCount());
611 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"))
612 << "An invalid selector shouldn't prevent other selectors from matching.";
615 TEST_F(WebFrameTest, DispatchMessageEventWithOriginCheck)
617 registerMockedHttpURLLoad("postmessage_test.html");
619 // Pass true to enable JavaScript.
620 FrameTestHelpers::WebViewHelper webViewHelper;
621 webViewHelper.initializeAndLoad(m_baseURL + "postmessage_test.html", true);
623 // Send a message with the correct origin.
624 WebSecurityOrigin correctOrigin(WebSecurityOrigin::create(toKURL(m_baseURL)));
625 WebDOMEvent event = webViewHelper.webView()->mainFrame()->document().createEvent("MessageEvent");
626 WebDOMMessageEvent message = event.to<WebDOMMessageEvent>();
627 WebSerializedScriptValue data(WebSerializedScriptValue::fromString("foo"));
628 message.initMessageEvent("message", false, false, data, "http://origin.com", 0, "");
629 webViewHelper.webView()->mainFrame()->dispatchMessageEventWithOriginCheck(correctOrigin, message);
631 // Send another message with incorrect origin.
632 WebSecurityOrigin incorrectOrigin(WebSecurityOrigin::create(toKURL(m_chromeURL)));
633 webViewHelper.webView()->mainFrame()->dispatchMessageEventWithOriginCheck(incorrectOrigin, message);
635 // Required to see any updates in contentAsText.
636 webViewHelper.webView()->layout();
638 // Verify that only the first addition is in the body of the page.
639 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
640 EXPECT_NE(std::string::npos, content.find("Message 1."));
641 EXPECT_EQ(std::string::npos, content.find("Message 2."));
644 class FixedLayoutTestWebViewClient : public WebViewClient {
646 virtual WebScreenInfo screenInfo() OVERRIDE { return m_screenInfo; }
648 WebScreenInfo m_screenInfo;
651 TEST_F(WebFrameTest, FrameViewNeedsLayoutOnFixedLayoutResize)
653 UseMockScrollbarSettings mockScrollbarSettings;
654 registerMockedHttpURLLoad("fixed_layout.html");
656 FixedLayoutTestWebViewClient client;
657 int viewportWidth = 640;
658 int viewportHeight = 480;
660 // Make sure we initialize to minimum scale, even if the window size
661 // only becomes available after the load begins.
662 FrameTestHelpers::WebViewHelper webViewHelper;
663 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client);
664 webViewHelper.webView()->settings()->setViewportEnabled(true);
665 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
666 webViewHelper.webView()->layout();
668 webViewHelper.webViewImpl()->setFixedLayoutSize(WebCore::IntSize(100, 100));
669 EXPECT_TRUE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
671 int prevLayoutCount = webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount();
672 webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->setFrameRect(WebCore::IntRect(0, 0, 641, 481));
673 EXPECT_EQ(prevLayoutCount, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount());
675 webViewHelper.webViewImpl()->layout();
678 TEST_F(WebFrameTest, ChangeInFixedLayoutTriggersTextAutosizingRecalculate)
680 UseMockScrollbarSettings mockScrollbarSettings;
681 registerMockedHttpURLLoad("fixed_layout.html");
683 FixedLayoutTestWebViewClient client;
684 int viewportWidth = 640;
685 int viewportHeight = 480;
687 // Make sure we initialize to minimum scale, even if the window size
688 // only becomes available after the load begins.
689 FrameTestHelpers::WebViewHelper webViewHelper;
690 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client);
691 webViewHelper.webView()->settings()->setViewportEnabled(true);
693 WebCore::Document* document = webViewHelper.webViewImpl()->page()->mainFrame()->document();
694 document->settings()->setTextAutosizingEnabled(true);
695 EXPECT_TRUE(document->settings()->textAutosizingEnabled());
696 webViewHelper.webViewImpl()->resize(WebSize(viewportWidth, viewportHeight));
697 webViewHelper.webViewImpl()->layout();
699 WebCore::RenderObject* renderer = document->renderer();
700 bool multiplierSetAtLeastOnce = false;
702 if (renderer->style()) {
703 renderer->style()->setTextAutosizingMultiplier(2);
704 EXPECT_EQ(2, renderer->style()->textAutosizingMultiplier());
705 multiplierSetAtLeastOnce = true;
707 renderer = renderer->nextInPreOrder();
709 EXPECT_TRUE(multiplierSetAtLeastOnce);
711 WebCore::ViewportDescription description = document->viewportDescription();
712 // Choose a width that's not going match the viewport width of the loaded document.
713 description.minWidth = WebCore::Length(100, WebCore::Fixed);
714 description.maxWidth = WebCore::Length(100, WebCore::Fixed);
715 webViewHelper.webViewImpl()->updatePageDefinedViewportConstraints(description);
717 bool multiplierCheckedAtLeastOnce = false;
718 renderer = document->renderer();
720 if (renderer->style()) {
721 EXPECT_EQ(1, renderer->style()->textAutosizingMultiplier());
722 multiplierCheckedAtLeastOnce = true;
724 renderer = renderer->nextInPreOrder();
726 EXPECT_TRUE(multiplierCheckedAtLeastOnce);
729 TEST_F(WebFrameTest, FixedLayoutSizeStopsResizeFromChangingLayoutSize)
731 UseMockScrollbarSettings mockScrollbarSettings;
732 registerMockedHttpURLLoad("fixed_layout.html");
734 int viewportWidth = 640;
735 int viewportHeight = 480;
737 int fixedLayoutWidth = viewportWidth / 2;
738 int fixedLayoutHeight = viewportHeight / 2;
740 FrameTestHelpers::WebViewHelper webViewHelper;
741 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html");
742 webViewHelper.webView()->settings()->setViewportEnabled(true);
743 webViewHelper.webView()->setFixedLayoutSize(WebSize(fixedLayoutWidth, fixedLayoutHeight));
744 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
745 webViewHelper.webView()->layout();
747 EXPECT_EQ(fixedLayoutWidth, webViewHelper.webViewImpl()->page()->mainFrame()->view()->layoutSize().width());
748 EXPECT_EQ(fixedLayoutHeight, webViewHelper.webViewImpl()->page()->mainFrame()->view()->layoutSize().height());
751 TEST_F(WebFrameTest, FixedLayoutSizePreventsResizeFromChangingPageScale)
753 UseMockScrollbarSettings mockScrollbarSettings;
754 registerMockedHttpURLLoad("fixed_layout.html");
756 int viewportWidth = 640;
757 int viewportHeight = 480;
759 int fixedLayoutWidth = viewportWidth / 2;
760 int fixedLayoutHeight = viewportHeight / 2;
762 FrameTestHelpers::WebViewHelper webViewHelper;
763 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html");
764 webViewHelper.webView()->settings()->setViewportEnabled(true);
765 webViewHelper.webView()->setFixedLayoutSize(WebSize(fixedLayoutWidth, fixedLayoutHeight));
766 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
767 webViewHelper.webView()->layout();
768 float pageScaleFactor = webViewHelper.webView()->pageScaleFactor();
770 webViewHelper.webView()->resize(WebSize(viewportWidth * 2, viewportHeight * 2));
772 EXPECT_EQ(pageScaleFactor, webViewHelper.webView()->pageScaleFactor());
775 TEST_F(WebFrameTest, FixedLayoutSizePreventsLayoutFromChangingPageScale)
777 UseMockScrollbarSettings mockScrollbarSettings;
778 registerMockedHttpURLLoad("fixed_layout.html");
780 int viewportWidth = 640;
781 int viewportHeight = 480;
783 int fixedLayoutWidth = viewportWidth * 2;
784 int fixedLayoutHeight = viewportHeight * 2;
786 FrameTestHelpers::WebViewHelper webViewHelper;
787 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html");
788 webViewHelper.webView()->settings()->setViewportEnabled(true);
789 webViewHelper.webView()->setFixedLayoutSize(WebSize(viewportWidth, viewportHeight));
790 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
791 webViewHelper.webView()->layout();
792 float pageScaleFactor = webViewHelper.webView()->pageScaleFactor();
794 webViewHelper.webView()->setFixedLayoutSize(WebSize(fixedLayoutWidth, fixedLayoutHeight));
795 webViewHelper.webView()->layout();
797 EXPECT_EQ(pageScaleFactor, webViewHelper.webView()->pageScaleFactor());
800 TEST_F(WebFrameTest, PreferredSizeAndContentSizeReportedCorrectlyWithZeroHeightFixedLayout)
802 UseMockScrollbarSettings mockScrollbarSettings;
803 registerMockedHttpURLLoad("200-by-300.html");
805 int windowWidth = 100;
806 int windowHeight = 100;
807 int viewportWidth = 100;
808 int viewportHeight = 0;
812 FixedLayoutTestWebViewClient client;
813 client.m_screenInfo.deviceScaleFactor = 1;
815 FrameTestHelpers::WebViewHelper webViewHelper;
816 webViewHelper.initializeAndLoad(m_baseURL + "200-by-300.html", true, 0, &client);
817 webViewHelper.webView()->settings()->setViewportEnabled(true);
818 webViewHelper.webView()->resize(WebSize(windowWidth, windowHeight));
819 webViewHelper.webView()->setFixedLayoutSize(WebSize(viewportWidth, viewportHeight));
820 webViewHelper.webView()->layout();
822 EXPECT_EQ(divWidth, webViewHelper.webView()->mainFrame()->contentsSize().width);
823 EXPECT_EQ(divHeight, webViewHelper.webView()->mainFrame()->contentsSize().height);
825 EXPECT_EQ(divWidth, webViewHelper.webView()->contentsPreferredMinimumSize().width);
826 EXPECT_EQ(divHeight, webViewHelper.webView()->contentsPreferredMinimumSize().height);
829 TEST_F(WebFrameTest, DisablingFixedLayoutSizeSetsCorrectLayoutSize)
831 UseMockScrollbarSettings mockScrollbarSettings;
832 registerMockedHttpURLLoad("no_viewport_tag.html");
834 FixedLayoutTestWebViewClient client;
835 client.m_screenInfo.deviceScaleFactor = 1;
836 int viewportWidth = 640;
837 int viewportHeight = 480;
839 FrameTestHelpers::WebViewHelper webViewHelper;
840 webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client);
841 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
842 webViewHelper.webView()->settings()->setUseWideViewport(true);
843 webViewHelper.webView()->settings()->setViewportEnabled(true);
844 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
846 webViewHelper.webView()->setFixedLayoutSize(WebSize(viewportWidth, viewportHeight));
847 EXPECT_TRUE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
848 webViewHelper.webView()->layout();
849 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
851 webViewHelper.webView()->setFixedLayoutSize(WebSize(0, 0));
852 EXPECT_TRUE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
853 webViewHelper.webView()->layout();
854 EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
857 TEST_F(WebFrameTest, DeviceScaleFactorUsesDefaultWithoutViewportTag)
859 UseMockScrollbarSettings mockScrollbarSettings;
860 registerMockedHttpURLLoad("no_viewport_tag.html");
862 int viewportWidth = 640;
863 int viewportHeight = 480;
865 FixedLayoutTestWebViewClient client;
866 client.m_screenInfo.deviceScaleFactor = 2;
868 FrameTestHelpers::WebViewHelper webViewHelper;
869 webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client);
871 webViewHelper.webView()->settings()->setViewportEnabled(true);
872 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
873 webViewHelper.webView()->layout();
875 EXPECT_EQ(2, webViewHelper.webView()->deviceScaleFactor());
877 // Device scale factor should be independent of page scale.
878 webViewHelper.webView()->setPageScaleFactorLimits(1, 2);
879 webViewHelper.webView()->setPageScaleFactorPreservingScrollOffset(0.5);
880 webViewHelper.webView()->layout();
881 EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor());
883 // Force the layout to happen before leaving the test.
884 webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
887 TEST_F(WebFrameTest, FixedLayoutInitializeAtMinimumScale)
889 UseMockScrollbarSettings mockScrollbarSettings;
891 registerMockedHttpURLLoad("fixed_layout.html");
893 FixedLayoutTestWebViewClient client;
894 client.m_screenInfo.deviceScaleFactor = 1;
895 int viewportWidth = 640;
896 int viewportHeight = 480;
898 // Make sure we initialize to minimum scale, even if the window size
899 // only becomes available after the load begins.
900 FrameTestHelpers::WebViewHelper webViewHelper;
901 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client);
902 webViewHelper.webView()->settings()->setViewportEnabled(true);
903 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
905 int defaultFixedLayoutWidth = 980;
906 float minimumPageScaleFactor = viewportWidth / (float) defaultFixedLayoutWidth;
907 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
908 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->minimumPageScaleFactor());
910 // Assume the user has pinch zoomed to page scale factor 2.
911 float userPinchPageScaleFactor = 2;
912 webViewHelper.webView()->setPageScaleFactorPreservingScrollOffset(userPinchPageScaleFactor);
913 webViewHelper.webView()->layout();
915 // Make sure we don't reset to initial scale if the page continues to load.
916 webViewHelper.webViewImpl()->didCommitLoad(false, false);
917 webViewHelper.webViewImpl()->didChangeContentsSize();
918 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
920 // Make sure we don't reset to initial scale if the viewport size changes.
921 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight + 100));
922 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
925 TEST_F(WebFrameTest, WideDocumentInitializeAtMinimumScale)
927 UseMockScrollbarSettings mockScrollbarSettings;
929 registerMockedHttpURLLoad("wide_document.html");
931 FixedLayoutTestWebViewClient client;
932 client.m_screenInfo.deviceScaleFactor = 1;
933 int viewportWidth = 640;
934 int viewportHeight = 480;
936 // Make sure we initialize to minimum scale, even if the window size
937 // only becomes available after the load begins.
938 FrameTestHelpers::WebViewHelper webViewHelper;
939 webViewHelper.initializeAndLoad(m_baseURL + "wide_document.html", true, 0, &client);
940 webViewHelper.webView()->settings()->setViewportEnabled(true);
941 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
943 int wideDocumentWidth = 1500;
944 float minimumPageScaleFactor = viewportWidth / (float) wideDocumentWidth;
945 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
946 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->minimumPageScaleFactor());
948 // Assume the user has pinch zoomed to page scale factor 2.
949 float userPinchPageScaleFactor = 2;
950 webViewHelper.webView()->setPageScaleFactorPreservingScrollOffset(userPinchPageScaleFactor);
951 webViewHelper.webView()->layout();
953 // Make sure we don't reset to initial scale if the page continues to load.
954 webViewHelper.webViewImpl()->didCommitLoad(false, false);
955 webViewHelper.webViewImpl()->didChangeContentsSize();
956 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
958 // Make sure we don't reset to initial scale if the viewport size changes.
959 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight + 100));
960 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
963 TEST_F(WebFrameTest, setLoadWithOverviewModeToFalse)
965 UseMockScrollbarSettings mockScrollbarSettings;
966 registerMockedHttpURLLoad("viewport-auto-initial-scale.html");
968 FixedLayoutTestWebViewClient client;
969 client.m_screenInfo.deviceScaleFactor = 1;
970 int viewportWidth = 640;
971 int viewportHeight = 480;
973 FrameTestHelpers::WebViewHelper webViewHelper;
974 webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client);
975 webViewHelper.webView()->settings()->setViewportEnabled(true);
976 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
977 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
978 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
980 // The page must be displayed at 100% zoom.
981 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
984 TEST_F(WebFrameTest, SetLoadWithOverviewModeToFalseAndNoWideViewport)
986 UseMockScrollbarSettings mockScrollbarSettings;
987 registerMockedHttpURLLoad("large-div.html");
989 FixedLayoutTestWebViewClient client;
990 client.m_screenInfo.deviceScaleFactor = 1;
991 int viewportWidth = 640;
992 int viewportHeight = 480;
994 FrameTestHelpers::WebViewHelper webViewHelper;
995 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client);
996 webViewHelper.webView()->settings()->setViewportEnabled(true);
997 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
998 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
999 webViewHelper.webView()->settings()->setUseWideViewport(false);
1000 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1002 // The page must be displayed at 100% zoom, despite that it hosts a wide div element.
1003 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
1006 TEST_F(WebFrameTest, NoWideViewportIgnoresPageViewportWidth)
1008 UseMockScrollbarSettings mockScrollbarSettings;
1009 registerMockedHttpURLLoad("viewport-auto-initial-scale.html");
1011 FixedLayoutTestWebViewClient client;
1012 client.m_screenInfo.deviceScaleFactor = 1;
1013 int viewportWidth = 640;
1014 int viewportHeight = 480;
1016 FrameTestHelpers::WebViewHelper webViewHelper;
1017 webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client);
1018 webViewHelper.webView()->settings()->setViewportEnabled(true);
1019 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1020 webViewHelper.webView()->settings()->setUseWideViewport(false);
1021 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1023 // The page sets viewport width to 3000, but with UseWideViewport == false is must be ignored.
1024 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1025 EXPECT_EQ(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
1028 TEST_F(WebFrameTest, NoWideViewportIgnoresPageViewportWidthButAccountsScale)
1030 UseMockScrollbarSettings mockScrollbarSettings;
1031 registerMockedHttpURLLoad("viewport-wide-2x-initial-scale.html");
1033 FixedLayoutTestWebViewClient client;
1034 client.m_screenInfo.deviceScaleFactor = 1;
1035 int viewportWidth = 640;
1036 int viewportHeight = 480;
1038 FrameTestHelpers::WebViewHelper webViewHelper;
1039 webViewHelper.initializeAndLoad(m_baseURL + "viewport-wide-2x-initial-scale.html", true, 0, &client);
1040 webViewHelper.webView()->settings()->setViewportEnabled(true);
1041 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1042 webViewHelper.webView()->settings()->setUseWideViewport(false);
1043 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1045 // The page sets viewport width to 3000, but with UseWideViewport == false it must be ignored.
1046 // While the initial scale specified by the page must be accounted.
1047 EXPECT_EQ(viewportWidth / 2, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1048 EXPECT_EQ(viewportHeight / 2, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
1051 TEST_F(WebFrameTest, WideViewportSetsTo980WithoutViewportTag)
1053 UseMockScrollbarSettings mockScrollbarSettings;
1054 registerMockedHttpURLLoad("no_viewport_tag.html");
1056 FixedLayoutTestWebViewClient client;
1057 client.m_screenInfo.deviceScaleFactor = 1;
1058 int viewportWidth = 640;
1059 int viewportHeight = 480;
1061 FrameTestHelpers::WebViewHelper webViewHelper;
1062 webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client);
1063 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1064 webViewHelper.webView()->settings()->setUseWideViewport(true);
1065 webViewHelper.webView()->settings()->setViewportEnabled(true);
1066 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1068 EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1069 EXPECT_EQ(980.0 / viewportWidth * viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
1072 TEST_F(WebFrameTest, NoWideViewportAndHeightInMeta)
1074 UseMockScrollbarSettings mockScrollbarSettings;
1075 registerMockedHttpURLLoad("viewport-height-1000.html");
1077 FixedLayoutTestWebViewClient client;
1078 client.m_screenInfo.deviceScaleFactor = 1;
1079 int viewportWidth = 640;
1080 int viewportHeight = 480;
1082 FrameTestHelpers::WebViewHelper webViewHelper;
1083 webViewHelper.initializeAndLoad(m_baseURL + "viewport-height-1000.html", true, 0, &client);
1084 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1085 webViewHelper.webView()->settings()->setUseWideViewport(false);
1086 webViewHelper.webView()->settings()->setViewportEnabled(true);
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);
1104 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1105 webViewHelper.webView()->settings()->setUseWideViewport(true);
1106 webViewHelper.webView()->settings()->setViewportEnabled(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);
1125 webViewHelper.webView()->settings()->setViewportEnabled(true);
1126 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1127 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1129 // The page must be displayed at 200% zoom, as specified in its viewport meta tag.
1130 EXPECT_EQ(2.0f, webViewHelper.webView()->pageScaleFactor());
1133 TEST_F(WebFrameTest, setInitialPageScaleFactorPermanently)
1135 UseMockScrollbarSettings mockScrollbarSettings;
1137 registerMockedHttpURLLoad("fixed_layout.html");
1139 FixedLayoutTestWebViewClient client;
1140 client.m_screenInfo.deviceScaleFactor = 1;
1141 float enforcedPageScaleFactor = 2.0f;
1143 FrameTestHelpers::WebViewHelper webViewHelper;
1144 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client);
1145 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1146 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1147 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1148 webViewHelper.webView()->settings()->setViewportEnabled(true);
1149 webViewHelper.webView()->layout();
1151 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1153 int viewportWidth = 640;
1154 int viewportHeight = 480;
1155 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1156 webViewHelper.webView()->layout();
1158 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1160 webViewHelper.webView()->setInitialPageScaleOverride(-1);
1161 webViewHelper.webView()->layout();
1162 EXPECT_EQ(1.0, webViewHelper.webView()->pageScaleFactor());
1165 TEST_F(WebFrameTest, PermanentInitialPageScaleFactorOverridesLoadWithOverviewMode)
1167 UseMockScrollbarSettings mockScrollbarSettings;
1168 registerMockedHttpURLLoad("viewport-auto-initial-scale.html");
1170 FixedLayoutTestWebViewClient client;
1171 client.m_screenInfo.deviceScaleFactor = 1;
1172 int viewportWidth = 640;
1173 int viewportHeight = 480;
1174 float enforcedPageScalePactor = 0.5f;
1176 FrameTestHelpers::WebViewHelper webViewHelper;
1177 webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client);
1178 webViewHelper.webView()->settings()->setViewportEnabled(true);
1179 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1180 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScalePactor);
1181 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1183 EXPECT_EQ(enforcedPageScalePactor, webViewHelper.webView()->pageScaleFactor());
1186 TEST_F(WebFrameTest, PermanentInitialPageScaleFactorOverridesPageViewportInitialScale)
1188 UseMockScrollbarSettings mockScrollbarSettings;
1189 registerMockedHttpURLLoad("viewport-wide-2x-initial-scale.html");
1191 FixedLayoutTestWebViewClient client;
1192 client.m_screenInfo.deviceScaleFactor = 1;
1193 int viewportWidth = 640;
1194 int viewportHeight = 480;
1195 float enforcedPageScalePactor = 0.5f;
1197 FrameTestHelpers::WebViewHelper webViewHelper;
1198 webViewHelper.initializeAndLoad(m_baseURL + "viewport-wide-2x-initial-scale.html", true, 0, &client);
1199 webViewHelper.webView()->settings()->setViewportEnabled(true);
1200 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScalePactor);
1201 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1203 EXPECT_EQ(enforcedPageScalePactor, webViewHelper.webView()->pageScaleFactor());
1206 TEST_F(WebFrameTest, WideViewportInitialScaleDoesNotExpandFixedLayoutWidth)
1208 UseMockScrollbarSettings mockScrollbarSettings;
1209 registerMockedHttpURLLoad("viewport-device-0.5x-initial-scale.html");
1211 FixedLayoutTestWebViewClient client;
1212 client.m_screenInfo.deviceScaleFactor = 1;
1213 int viewportWidth = 640;
1214 int viewportHeight = 480;
1216 FrameTestHelpers::WebViewHelper webViewHelper;
1217 webViewHelper.initializeAndLoad(m_baseURL + "viewport-device-0.5x-initial-scale.html", true, 0, &client);
1218 webViewHelper.webView()->settings()->setViewportEnabled(true);
1219 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1220 webViewHelper.webView()->settings()->setUseWideViewport(true);
1221 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1222 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1224 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1227 TEST_F(WebFrameTest, WideViewportAndWideContentWithInitialScale)
1229 UseMockScrollbarSettings mockScrollbarSettings;
1230 registerMockedHttpURLLoad("wide_document_width_viewport.html");
1232 FixedLayoutTestWebViewClient client;
1233 client.m_screenInfo.deviceScaleFactor = 1;
1234 int viewportWidth = 600;
1235 int viewportHeight = 800;
1237 FrameTestHelpers::WebViewHelper webViewHelper;
1238 webViewHelper.initializeAndLoad("about:blank", true, 0, &client);
1239 webViewHelper.webView()->settings()->setViewportEnabled(true);
1240 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1241 webViewHelper.webView()->settings()->setUseWideViewport(true);
1242 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1243 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1245 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "wide_document_width_viewport.html");
1246 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
1247 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1249 int wideDocumentWidth = 800;
1250 float minimumPageScaleFactor = viewportWidth / (float) wideDocumentWidth;
1251 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1252 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->minimumPageScaleFactor());
1255 TEST_F(WebFrameTest, ZeroValuesQuirk)
1257 UseMockScrollbarSettings mockScrollbarSettings;
1258 registerMockedHttpURLLoad("viewport-zero-values.html");
1260 FixedLayoutTestWebViewClient client;
1261 client.m_screenInfo.deviceScaleFactor = 1;
1262 int viewportWidth = 640;
1263 int viewportHeight = 480;
1265 FrameTestHelpers::WebViewHelper webViewHelper;
1266 webViewHelper.initialize(true, 0, &client);
1267 webViewHelper.webView()->settings()->setViewportEnabled(true);
1268 webViewHelper.webView()->settings()->setViewportMetaZeroValuesQuirk(true);
1269 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1270 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport-zero-values.html");
1271 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
1272 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1274 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1275 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
1277 webViewHelper.webView()->settings()->setUseWideViewport(true);
1278 webViewHelper.webView()->layout();
1279 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1280 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
1283 TEST_F(WebFrameTest, OverflowHiddenDisablesScrolling)
1285 registerMockedHttpURLLoad("body-overflow-hidden.html");
1287 FixedLayoutTestWebViewClient client;
1288 client.m_screenInfo.deviceScaleFactor = 1;
1289 int viewportWidth = 640;
1290 int viewportHeight = 480;
1292 FrameTestHelpers::WebViewHelper webViewHelper;
1293 webViewHelper.initialize(true, 0, &client);
1294 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "body-overflow-hidden.html");
1295 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
1296 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1298 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
1299 EXPECT_FALSE(view->userInputScrollable(WebCore::VerticalScrollbar));
1302 TEST_F(WebFrameTest, IgnoreOverflowHiddenQuirk)
1304 registerMockedHttpURLLoad("body-overflow-hidden.html");
1306 FixedLayoutTestWebViewClient client;
1307 client.m_screenInfo.deviceScaleFactor = 1;
1308 int viewportWidth = 640;
1309 int viewportHeight = 480;
1311 FrameTestHelpers::WebViewHelper webViewHelper;
1312 webViewHelper.initialize(true, 0, &client);
1313 webViewHelper.webView()->settings()->setIgnoreMainFrameOverflowHiddenQuirk(true);
1314 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "body-overflow-hidden.html");
1315 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
1316 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1318 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
1319 EXPECT_TRUE(view->userInputScrollable(WebCore::VerticalScrollbar));
1322 TEST_F(WebFrameTest, NonZeroValuesNoQuirk)
1324 UseMockScrollbarSettings mockScrollbarSettings;
1325 registerMockedHttpURLLoad("viewport-nonzero-values.html");
1327 FixedLayoutTestWebViewClient client;
1328 client.m_screenInfo.deviceScaleFactor = 1;
1329 int viewportWidth = 640;
1330 int viewportHeight = 480;
1331 float expectedPageScaleFactor = 0.5f;
1333 FrameTestHelpers::WebViewHelper webViewHelper;
1334 webViewHelper.initialize(true, 0, &client);
1335 webViewHelper.webView()->settings()->setViewportEnabled(true);
1336 webViewHelper.webView()->settings()->setViewportMetaZeroValuesQuirk(true);
1337 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1338 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport-nonzero-values.html");
1339 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
1340 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1342 EXPECT_EQ(viewportWidth / expectedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1343 EXPECT_EQ(expectedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1345 webViewHelper.webView()->settings()->setUseWideViewport(true);
1346 webViewHelper.webView()->layout();
1347 EXPECT_EQ(viewportWidth / expectedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1348 EXPECT_EQ(expectedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1351 TEST_F(WebFrameTest, ScaleFactorShouldNotOscillate)
1353 UseMockScrollbarSettings mockScrollbarSettings;
1354 registerMockedHttpURLLoad("scale_oscillate.html");
1356 FixedLayoutTestWebViewClient client;
1357 client.m_screenInfo.deviceScaleFactor = static_cast<float>(1.325);
1358 int viewportWidth = 800;
1359 int viewportHeight = 1057;
1361 FrameTestHelpers::WebViewHelper webViewHelper;
1362 webViewHelper.initializeAndLoad(m_baseURL + "scale_oscillate.html", true, 0, &client);
1363 webViewHelper.webView()->settings()->setViewportEnabled(true);
1364 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1365 webViewHelper.webView()->layout();
1368 TEST_F(WebFrameTest, setPageScaleFactorDoesNotLayout)
1370 UseMockScrollbarSettings mockScrollbarSettings;
1371 registerMockedHttpURLLoad("fixed_layout.html");
1373 FixedLayoutTestWebViewClient client;
1374 client.m_screenInfo.deviceScaleFactor = 1;
1375 // Small viewport to ensure there are always scrollbars.
1376 int viewportWidth = 64;
1377 int viewportHeight = 48;
1379 FrameTestHelpers::WebViewHelper webViewHelper;
1380 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client);
1381 webViewHelper.webView()->settings()->setViewportEnabled(true);
1382 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1383 webViewHelper.webView()->layout();
1385 int prevLayoutCount = webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount();
1386 webViewHelper.webViewImpl()->setPageScaleFactor(3, WebPoint());
1387 EXPECT_FALSE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
1388 EXPECT_EQ(prevLayoutCount, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount());
1391 TEST_F(WebFrameTest, setPageScaleFactorWithOverlayScrollbarsDoesNotLayout)
1393 UseMockScrollbarSettings mockScrollbarSettings;
1395 registerMockedHttpURLLoad("fixed_layout.html");
1397 FixedLayoutTestWebViewClient client;
1398 client.m_screenInfo.deviceScaleFactor = 1;
1399 int viewportWidth = 640;
1400 int viewportHeight = 480;
1402 FrameTestHelpers::WebViewHelper webViewHelper;
1403 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client);
1404 webViewHelper.webView()->settings()->setViewportEnabled(true);
1405 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1406 webViewHelper.webView()->layout();
1408 int prevLayoutCount = webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount();
1409 webViewHelper.webViewImpl()->setPageScaleFactor(30, WebPoint());
1410 EXPECT_FALSE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
1411 EXPECT_EQ(prevLayoutCount, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount());
1415 TEST_F(WebFrameTest, setPageScaleFactorBeforeFrameHasView)
1417 registerMockedHttpURLLoad("fixed_layout.html");
1419 float pageScaleFactor = 3;
1420 FrameTestHelpers::WebViewHelper webViewHelper;
1421 webViewHelper.initializeAndLoad("about:html", true, 0, 0);
1422 webViewHelper.webView()->setPageScaleFactor(pageScaleFactor, WebPoint());
1424 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "fixed_layout.html");
1425 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
1426 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
1427 EXPECT_EQ(pageScaleFactor, view->visibleContentScaleFactor());
1430 TEST_F(WebFrameTest, pageScaleFactorWrittenToHistoryItem)
1432 UseMockScrollbarSettings mockScrollbarSettings;
1433 registerMockedHttpURLLoad("fixed_layout.html");
1435 FixedLayoutTestWebViewClient client;
1436 client.m_screenInfo.deviceScaleFactor = 1;
1437 int viewportWidth = 640;
1438 int viewportHeight = 480;
1440 FrameTestHelpers::WebViewHelper webViewHelper;
1441 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client);
1442 webViewHelper.webView()->settings()->setViewportEnabled(true);
1443 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1444 webViewHelper.webView()->layout();
1446 webViewHelper.webView()->setPageScaleFactor(3, WebPoint());
1447 webViewHelper.webViewImpl()->page()->mainFrame()->loader().history()->saveDocumentAndScrollState();
1448 webViewHelper.webView()->setPageScaleFactor(1, WebPoint());
1449 webViewHelper.webViewImpl()->page()->mainFrame()->loader().history()->restoreScrollPositionAndViewState();
1450 EXPECT_EQ(3, webViewHelper.webView()->pageScaleFactor());
1453 TEST_F(WebFrameTest, pageScaleFactorShrinksViewport)
1455 UseMockScrollbarSettings mockScrollbarSettings;
1456 registerMockedHttpURLLoad("large-div.html");
1458 FixedLayoutTestWebViewClient client;
1459 client.m_screenInfo.deviceScaleFactor = 1;
1460 // Small viewport to ensure there are always scrollbars.
1461 int viewportWidth = 64;
1462 int viewportHeight = 48;
1464 FrameTestHelpers::WebViewHelper webViewHelper;
1465 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client);
1466 webViewHelper.webView()->settings()->setViewportEnabled(true);
1467 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1468 webViewHelper.webView()->layout();
1470 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
1471 int viewportWidthMinusScrollbar = viewportWidth - (view->verticalScrollbar()->isOverlayScrollbar() ? 0 : 15);
1472 int viewportHeightMinusScrollbar = viewportHeight - (view->horizontalScrollbar()->isOverlayScrollbar() ? 0 : 15);
1474 webViewHelper.webView()->setPageScaleFactor(2, WebPoint());
1476 WebCore::IntSize unscaledSize = view->unscaledVisibleContentSize(WebCore::ScrollableArea::IncludeScrollbars);
1477 EXPECT_EQ(viewportWidth, unscaledSize.width());
1478 EXPECT_EQ(viewportHeight, unscaledSize.height());
1480 WebCore::IntSize unscaledSizeMinusScrollbar = view->unscaledVisibleContentSize(WebCore::ScrollableArea::ExcludeScrollbars);
1481 EXPECT_EQ(viewportWidthMinusScrollbar, unscaledSizeMinusScrollbar.width());
1482 EXPECT_EQ(viewportHeightMinusScrollbar, unscaledSizeMinusScrollbar.height());
1484 WebCore::IntSize scaledSize = view->visibleContentRect().size();
1485 EXPECT_EQ(ceil(viewportWidthMinusScrollbar / 2.0), scaledSize.width());
1486 EXPECT_EQ(ceil(viewportHeightMinusScrollbar / 2.0), scaledSize.height());
1489 TEST_F(WebFrameTest, pageScaleFactorDoesNotApplyCssTransform)
1491 UseMockScrollbarSettings mockScrollbarSettings;
1492 registerMockedHttpURLLoad("fixed_layout.html");
1494 FixedLayoutTestWebViewClient client;
1495 client.m_screenInfo.deviceScaleFactor = 1;
1496 int viewportWidth = 640;
1497 int viewportHeight = 480;
1499 FrameTestHelpers::WebViewHelper webViewHelper;
1500 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client);
1501 webViewHelper.webView()->settings()->setViewportEnabled(true);
1502 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1503 webViewHelper.webView()->layout();
1505 webViewHelper.webView()->setPageScaleFactor(2, WebPoint());
1507 EXPECT_EQ(980, webViewHelper.webViewImpl()->page()->mainFrame()->contentRenderer()->unscaledDocumentRect().width());
1508 EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1511 TEST_F(WebFrameTest, targetDensityDpiHigh)
1513 UseMockScrollbarSettings mockScrollbarSettings;
1514 registerMockedHttpURLLoad("viewport-target-densitydpi-high.html");
1516 FixedLayoutTestWebViewClient client;
1518 float targetDpi = 240.0f;
1519 float deviceScaleFactors[] = { 1.0f, 4.0f / 3.0f, 2.0f };
1520 int viewportWidth = 640;
1521 int viewportHeight = 480;
1523 for (size_t i = 0; i < ARRAY_SIZE(deviceScaleFactors); ++i) {
1524 float deviceScaleFactor = deviceScaleFactors[i];
1525 float deviceDpi = deviceScaleFactor * 160.0f;
1526 client.m_screenInfo.deviceScaleFactor = deviceScaleFactor;
1528 FrameTestHelpers::WebViewHelper webViewHelper;
1529 webViewHelper.initializeAndLoad(m_baseURL + "viewport-target-densitydpi-high.html", true, 0, &client);
1530 webViewHelper.webView()->settings()->setViewportEnabled(true);
1531 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1532 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1533 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1535 // We need to account for the fact that logical pixels are unconditionally multiplied by deviceScaleFactor to produce
1537 float densityDpiScaleRatio = deviceScaleFactor * targetDpi / deviceDpi;
1538 EXPECT_NEAR(viewportWidth * densityDpiScaleRatio, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1539 EXPECT_NEAR(viewportHeight * densityDpiScaleRatio, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1540 EXPECT_NEAR(1.0f / densityDpiScaleRatio, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1544 TEST_F(WebFrameTest, targetDensityDpiDevice)
1546 UseMockScrollbarSettings mockScrollbarSettings;
1547 registerMockedHttpURLLoad("viewport-target-densitydpi-device.html");
1549 float deviceScaleFactors[] = { 1.0f, 4.0f / 3.0f, 2.0f };
1551 FixedLayoutTestWebViewClient client;
1552 int viewportWidth = 640;
1553 int viewportHeight = 480;
1555 for (size_t i = 0; i < ARRAY_SIZE(deviceScaleFactors); ++i) {
1556 client.m_screenInfo.deviceScaleFactor = deviceScaleFactors[i];
1558 FrameTestHelpers::WebViewHelper webViewHelper;
1559 webViewHelper.initializeAndLoad(m_baseURL + "viewport-target-densitydpi-device.html", true, 0, &client);
1560 webViewHelper.webView()->settings()->setViewportEnabled(true);
1561 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1562 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1563 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1565 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1566 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1567 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1571 TEST_F(WebFrameTest, targetDensityDpiDeviceAndFixedWidth)
1573 UseMockScrollbarSettings mockScrollbarSettings;
1574 registerMockedHttpURLLoad("viewport-target-densitydpi-device-and-fixed-width.html");
1576 float deviceScaleFactors[] = { 1.0f, 4.0f / 3.0f, 2.0f };
1578 FixedLayoutTestWebViewClient client;
1579 int viewportWidth = 640;
1580 int viewportHeight = 480;
1582 for (size_t i = 0; i < ARRAY_SIZE(deviceScaleFactors); ++i) {
1583 client.m_screenInfo.deviceScaleFactor = deviceScaleFactors[i];
1585 FrameTestHelpers::WebViewHelper webViewHelper;
1586 webViewHelper.initializeAndLoad(m_baseURL + "viewport-target-densitydpi-device-and-fixed-width.html", true, 0, &client);
1587 webViewHelper.webView()->settings()->setViewportEnabled(true);
1588 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1589 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1590 webViewHelper.webView()->settings()->setUseWideViewport(true);
1591 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1593 EXPECT_NEAR(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1594 EXPECT_NEAR(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1595 EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1599 TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOne)
1601 UseMockScrollbarSettings mockScrollbarSettings;
1602 registerMockedHttpURLLoad("viewport-initial-scale-less-than-1.html");
1604 FixedLayoutTestWebViewClient client;
1605 client.m_screenInfo.deviceScaleFactor = 1.33f;
1606 int viewportWidth = 640;
1607 int viewportHeight = 480;
1609 FrameTestHelpers::WebViewHelper webViewHelper;
1610 webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-less-than-1.html", true, 0, &client);
1611 webViewHelper.webView()->settings()->setViewportEnabled(true);
1612 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1613 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1614 webViewHelper.webView()->settings()->setUseWideViewport(false);
1615 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1616 webViewHelper.webView()->layout();
1618 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1619 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1620 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1623 TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOneWithDeviceWidth)
1625 UseMockScrollbarSettings mockScrollbarSettings;
1626 registerMockedHttpURLLoad("viewport-initial-scale-less-than-1-device-width.html");
1628 FixedLayoutTestWebViewClient client;
1629 client.m_screenInfo.deviceScaleFactor = 1.33f;
1630 int viewportWidth = 640;
1631 int viewportHeight = 480;
1633 FrameTestHelpers::WebViewHelper webViewHelper;
1634 webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-less-than-1-device-width.html", true, 0, &client);
1635 webViewHelper.webView()->settings()->setViewportEnabled(true);
1636 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1637 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1638 webViewHelper.webView()->settings()->setUseWideViewport(false);
1639 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1640 webViewHelper.webView()->layout();
1642 const float pageZoom = 0.25f;
1643 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor / pageZoom, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1644 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor / pageZoom, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1645 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1648 class WebFrameResizeTest : public WebFrameTest {
1651 static WebCore::FloatSize computeRelativeOffset(const WebCore::IntPoint& absoluteOffset, const WebCore::LayoutRect& rect)
1653 WebCore::FloatSize relativeOffset = WebCore::FloatPoint(absoluteOffset) - rect.location();
1654 relativeOffset.scale(1.f / rect.width(), 1.f / rect.height());
1655 return relativeOffset;
1658 void testResizeYieldsCorrectScrollAndScale(const char* url,
1659 const float initialPageScaleFactor,
1660 const WebSize scrollOffset,
1661 const WebSize viewportSize,
1662 const bool shouldScaleRelativeToViewportWidth) {
1663 UseMockScrollbarSettings mockScrollbarSettings;
1664 registerMockedHttpURLLoad(url);
1666 const float aspectRatio = static_cast<float>(viewportSize.width) / viewportSize.height;
1668 FrameTestHelpers::WebViewHelper webViewHelper;
1669 webViewHelper.initializeAndLoad(m_baseURL + url, true);
1670 webViewHelper.webView()->settings()->setViewportEnabled(true);
1672 // Origin scrollOffsets preserved under resize.
1674 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height));
1675 webViewHelper.webViewImpl()->setPageScaleFactor(initialPageScaleFactor, WebPoint());
1676 ASSERT_EQ(viewportSize, webViewHelper.webViewImpl()->size());
1677 ASSERT_EQ(initialPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor());
1678 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.height, viewportSize.width));
1679 float expectedPageScaleFactor = initialPageScaleFactor * (shouldScaleRelativeToViewportWidth ? 1 / aspectRatio : 1);
1680 EXPECT_NEAR(expectedPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor(), 0.05f);
1681 EXPECT_EQ(WebSize(), webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
1684 // Resizing just the height should not affect pageScaleFactor or scrollOffset.
1686 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height));
1687 webViewHelper.webViewImpl()->setPageScaleFactor(initialPageScaleFactor, WebPoint(scrollOffset.width, scrollOffset.height));
1688 webViewHelper.webViewImpl()->layout();
1689 const WebSize expectedScrollOffset = webViewHelper.webViewImpl()->mainFrame()->scrollOffset();
1690 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height * 0.8f));
1691 EXPECT_EQ(initialPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor());
1692 EXPECT_EQ(expectedScrollOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
1693 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height * 0.8f));
1694 EXPECT_EQ(initialPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor());
1695 EXPECT_EQ(expectedScrollOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
1698 // Generic resize preserves scrollOffset relative to anchor node located
1699 // the top center of the screen.
1701 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.height, viewportSize.width));
1702 float pageScaleFactor = webViewHelper.webViewImpl()->pageScaleFactor();
1703 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height));
1704 float expectedPageScaleFactor = pageScaleFactor * (shouldScaleRelativeToViewportWidth ? aspectRatio : 1);
1705 EXPECT_NEAR(expectedPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor(), 0.05f);
1706 webViewHelper.webViewImpl()->mainFrame()->setScrollOffset(scrollOffset);
1708 WebCore::IntPoint anchorPoint = WebCore::IntPoint(scrollOffset) + WebCore::IntPoint(viewportSize.width / 2, 0);
1709 RefPtr<WebCore::Node> anchorNode = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->eventHandler().hitTestResultAtPoint(anchorPoint, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent).innerNode();
1712 pageScaleFactor = webViewHelper.webViewImpl()->pageScaleFactor();
1713 const WebCore::FloatSize preResizeRelativeOffset
1714 = computeRelativeOffset(anchorPoint, anchorNode->boundingBox());
1715 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.height, viewportSize.width));
1716 WebCore::IntPoint newAnchorPoint = WebCore::IntPoint(webViewHelper.webViewImpl()->mainFrame()->scrollOffset()) + WebCore::IntPoint(viewportSize.height / 2, 0);
1717 const WebCore::FloatSize postResizeRelativeOffset
1718 = computeRelativeOffset(newAnchorPoint, anchorNode->boundingBox());
1719 EXPECT_NEAR(preResizeRelativeOffset.width(), postResizeRelativeOffset.width(), 0.15f);
1720 expectedPageScaleFactor = pageScaleFactor * (shouldScaleRelativeToViewportWidth ? 1 / aspectRatio : 1);
1721 EXPECT_NEAR(expectedPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor(), 0.05f);
1726 TEST_F(WebFrameResizeTest, ResizeYieldsCorrectScrollAndScaleForWidthEqualsDeviceWidth)
1728 // With width=device-width, pageScaleFactor is preserved across resizes as
1729 // long as the content adjusts according to the device-width.
1730 const char* url = "resize_scroll_mobile.html";
1731 const float initialPageScaleFactor = 1;
1732 const WebSize scrollOffset(0, 50);
1733 const WebSize viewportSize(120, 160);
1734 const bool shouldScaleRelativeToViewportWidth = true;
1736 testResizeYieldsCorrectScrollAndScale(
1737 url, initialPageScaleFactor, scrollOffset, viewportSize, shouldScaleRelativeToViewportWidth);
1740 TEST_F(WebFrameResizeTest, ResizeYieldsCorrectScrollAndScaleForFixedWidth)
1742 // With a fixed width, pageScaleFactor scales by the relative change in viewport width.
1743 const char* url = "resize_scroll_fixed_width.html";
1744 const float initialPageScaleFactor = 2;
1745 const WebSize scrollOffset(0, 200);
1746 const WebSize viewportSize(240, 320);
1747 const bool shouldScaleRelativeToViewportWidth = true;
1749 testResizeYieldsCorrectScrollAndScale(
1750 url, initialPageScaleFactor, scrollOffset, viewportSize, shouldScaleRelativeToViewportWidth);
1753 TEST_F(WebFrameResizeTest, ResizeYieldsCorrectScrollAndScaleForFixedLayout)
1755 // With a fixed layout, pageScaleFactor scales by the relative change in viewport width.
1756 const char* url = "resize_scroll_fixed_layout.html";
1757 const float initialPageScaleFactor = 2;
1758 const WebSize scrollOffset(200, 400);
1759 const WebSize viewportSize(320, 240);
1760 const bool shouldScaleRelativeToViewportWidth = true;
1762 testResizeYieldsCorrectScrollAndScale(
1763 url, initialPageScaleFactor, scrollOffset, viewportSize, shouldScaleRelativeToViewportWidth);
1766 TEST_F(WebFrameTest, pageScaleFactorScalesPaintClip)
1768 UseMockScrollbarSettings mockScrollbarSettings;
1769 registerMockedHttpURLLoad("large-div.html");
1771 FixedLayoutTestWebViewClient client;
1772 client.m_screenInfo.deviceScaleFactor = 1;
1773 int viewportWidth = 50;
1774 int viewportHeight = 50;
1776 FrameTestHelpers::WebViewHelper webViewHelper;
1777 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client);
1778 webViewHelper.webView()->settings()->setViewportEnabled(true);
1779 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1780 webViewHelper.webView()->layout();
1782 // Set <1 page scale so that the clip rect should be larger than
1783 // the viewport size as passed into resize().
1784 webViewHelper.webView()->setPageScaleFactor(0.5, WebPoint());
1787 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 200, 200);
1788 bitmap.allocPixels();
1789 bitmap.eraseColor(0);
1790 SkCanvas canvas(bitmap);
1792 WebCore::GraphicsContext context(&canvas);
1793 context.setTrackOpaqueRegion(true);
1795 EXPECT_EQ_RECT(WebCore::IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
1797 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
1798 WebCore::IntRect paintRect(0, 0, 200, 200);
1799 view->paint(&context, paintRect);
1801 int viewportWidthMinusScrollbar = 50 - (view->verticalScrollbar()->isOverlayScrollbar() ? 0 : 15);
1802 int viewportHeightMinusScrollbar = 50 - (view->horizontalScrollbar()->isOverlayScrollbar() ? 0 : 15);
1803 WebCore::IntRect clippedRect(0, 0, viewportWidthMinusScrollbar * 2, viewportHeightMinusScrollbar * 2);
1804 EXPECT_EQ_RECT(clippedRect, context.opaqueRegion().asRect());
1807 TEST_F(WebFrameTest, pageScaleFactorUpdatesScrollbars)
1809 UseMockScrollbarSettings mockScrollbarSettings;
1810 registerMockedHttpURLLoad("fixed_layout.html");
1812 FixedLayoutTestWebViewClient client;
1813 client.m_screenInfo.deviceScaleFactor = 1;
1814 int viewportWidth = 640;
1815 int viewportHeight = 480;
1817 FrameTestHelpers::WebViewHelper webViewHelper;
1818 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client);
1819 webViewHelper.webView()->settings()->setViewportEnabled(true);
1820 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1821 webViewHelper.webView()->layout();
1823 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
1824 EXPECT_EQ(view->scrollSize(WebCore::HorizontalScrollbar), view->contentsSize().width() - view->visibleContentRect().width());
1825 EXPECT_EQ(view->scrollSize(WebCore::VerticalScrollbar), view->contentsSize().height() - view->visibleContentRect().height());
1827 webViewHelper.webView()->setPageScaleFactor(10, WebPoint());
1829 EXPECT_EQ(view->scrollSize(WebCore::HorizontalScrollbar), view->contentsSize().width() - view->visibleContentRect().width());
1830 EXPECT_EQ(view->scrollSize(WebCore::VerticalScrollbar), view->contentsSize().height() - view->visibleContentRect().height());
1833 TEST_F(WebFrameTest, CanOverrideScaleLimits)
1835 UseMockScrollbarSettings mockScrollbarSettings;
1837 registerMockedHttpURLLoad("no_scale_for_you.html");
1839 FixedLayoutTestWebViewClient client;
1840 client.m_screenInfo.deviceScaleFactor = 1;
1841 int viewportWidth = 640;
1842 int viewportHeight = 480;
1844 FrameTestHelpers::WebViewHelper webViewHelper;
1845 webViewHelper.initializeAndLoad(m_baseURL + "no_scale_for_you.html", true, 0, &client);
1846 webViewHelper.webView()->settings()->setViewportEnabled(true);
1847 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1849 EXPECT_EQ(2.0f, webViewHelper.webView()->minimumPageScaleFactor());
1850 EXPECT_EQ(2.0f, webViewHelper.webView()->maximumPageScaleFactor());
1852 webViewHelper.webView()->setIgnoreViewportTagScaleLimits(true);
1853 webViewHelper.webView()->layout();
1855 EXPECT_EQ(1.0f, webViewHelper.webView()->minimumPageScaleFactor());
1856 EXPECT_EQ(5.0f, webViewHelper.webView()->maximumPageScaleFactor());
1858 webViewHelper.webView()->setIgnoreViewportTagScaleLimits(false);
1859 webViewHelper.webView()->layout();
1861 EXPECT_EQ(2.0f, webViewHelper.webView()->minimumPageScaleFactor());
1862 EXPECT_EQ(2.0f, webViewHelper.webView()->maximumPageScaleFactor());
1865 TEST_F(WebFrameTest, updateOverlayScrollbarLayers)
1867 UseMockScrollbarSettings mockScrollbarSettings;
1869 registerMockedHttpURLLoad("large-div.html");
1871 int viewWidth = 500;
1872 int viewHeight = 500;
1874 OwnPtr<FakeCompositingWebViewClient> fakeCompositingWebViewClient = adoptPtr(new FakeCompositingWebViewClient());
1875 FrameTestHelpers::WebViewHelper webViewHelper;
1876 webViewHelper.initialize(true, &fakeCompositingWebViewClient->m_fakeWebFrameClient, fakeCompositingWebViewClient.get(), &configueCompositingWebView);
1878 webViewHelper.webView()->resize(WebSize(viewWidth, viewHeight));
1879 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "large-div.html");
1880 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
1881 webViewHelper.webView()->layout();
1883 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
1884 EXPECT_TRUE(view->renderView()->compositor()->layerForHorizontalScrollbar());
1885 EXPECT_TRUE(view->renderView()->compositor()->layerForVerticalScrollbar());
1887 webViewHelper.webView()->resize(WebSize(viewWidth * 10, viewHeight * 10));
1888 webViewHelper.webView()->layout();
1889 EXPECT_FALSE(view->renderView()->compositor()->layerForHorizontalScrollbar());
1890 EXPECT_FALSE(view->renderView()->compositor()->layerForVerticalScrollbar());
1893 void setScaleAndScrollAndLayout(WebKit::WebView* webView, WebPoint scroll, float scale)
1895 webView->setPageScaleFactor(scale, WebPoint(scroll.x, scroll.y));
1899 TEST_F(WebFrameTest, DivAutoZoomParamsTest)
1901 registerMockedHttpURLLoad("get_scale_for_auto_zoom_into_div_test.html");
1903 const float deviceScaleFactor = 2.0f;
1904 int viewportWidth = 640 / deviceScaleFactor;
1905 int viewportHeight = 1280 / deviceScaleFactor;
1906 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
1907 FrameTestHelpers::WebViewHelper webViewHelper;
1908 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_for_auto_zoom_into_div_test.html");
1909 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
1910 webViewHelper.webView()->setPageScaleFactorLimits(0.01f, 4);
1911 webViewHelper.webView()->setPageScaleFactor(0.5f, WebPoint(0, 0));
1912 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1913 webViewHelper.webView()->layout();
1915 WebRect wideDiv(200, 100, 400, 150);
1916 WebRect tallDiv(200, 300, 400, 800);
1917 WebRect doubleTapPointWide(wideDiv.x + 50, wideDiv.y + 50, touchPointPadding, touchPointPadding);
1918 WebRect doubleTapPointTall(tallDiv.x + 50, tallDiv.y + 50, touchPointPadding, touchPointPadding);
1919 WebRect wideBlockBounds;
1920 WebRect tallBlockBounds;
1924 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
1926 // Test double-tap zooming into wide div.
1927 wideBlockBounds = webViewHelper.webViewImpl()->computeBlockBounds(doubleTapPointWide, false);
1928 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(doubleTapPointWide.x, doubleTapPointWide.y), wideBlockBounds, touchPointPadding, doubleTapZoomAlreadyLegibleScale, scale, scroll);
1929 // The div should horizontally fill the screen (modulo margins), and
1930 // vertically centered (modulo integer rounding).
1931 EXPECT_NEAR(viewportWidth / (float) wideDiv.width, scale, 0.1);
1932 EXPECT_NEAR(wideDiv.x, scroll.x, 20);
1933 EXPECT_EQ(0, scroll.y);
1935 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), scroll, scale);
1937 // Test zoom out back to minimum scale.
1938 wideBlockBounds = webViewHelper.webViewImpl()->computeBlockBounds(doubleTapPointWide, false);
1939 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(doubleTapPointWide.x, doubleTapPointWide.y), wideBlockBounds, touchPointPadding, doubleTapZoomAlreadyLegibleScale, scale, scroll);
1941 scale = webViewHelper.webViewImpl()->minimumPageScaleFactor();
1942 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), scale);
1944 // Test double-tap zooming into tall div.
1945 tallBlockBounds = webViewHelper.webViewImpl()->computeBlockBounds(doubleTapPointTall, false);
1946 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(doubleTapPointTall.x, doubleTapPointTall.y), tallBlockBounds, touchPointPadding, doubleTapZoomAlreadyLegibleScale, scale, scroll);
1947 // The div should start at the top left of the viewport.
1948 EXPECT_NEAR(viewportWidth / (float) tallDiv.width, scale, 0.1);
1949 EXPECT_NEAR(tallDiv.x, scroll.x, 20);
1950 EXPECT_NEAR(tallDiv.y, scroll.y, 20);
1952 // Test for Non-doubletap scaling
1953 // Test zooming into div.
1954 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(250, 250), webViewHelper.webViewImpl()->computeBlockBounds(WebRect(250, 250, 10, 10), true), 0, doubleTapZoomAlreadyLegibleScale, scale, scroll);
1955 EXPECT_NEAR(viewportWidth / (float) wideDiv.width, scale, 0.1);
1958 void simulatePageScale(WebViewImpl* webViewImpl, float& scale)
1960 WebCore::IntSize scrollDelta = webViewImpl->fakePageScaleAnimationTargetPositionForTesting() - webViewImpl->mainFrameImpl()->frameView()->scrollPosition();
1961 float scaleDelta = webViewImpl->fakePageScaleAnimationPageScaleForTesting() / webViewImpl->pageScaleFactor();
1962 webViewImpl->applyScrollAndScale(scrollDelta, scaleDelta);
1963 scale = webViewImpl->pageScaleFactor();
1966 void simulateMultiTargetZoom(WebViewImpl* webViewImpl, const WebRect& rect, float& scale)
1968 if (webViewImpl->zoomToMultipleTargetsRect(rect))
1969 simulatePageScale(webViewImpl, scale);
1972 void simulateDoubleTap(WebViewImpl* webViewImpl, WebPoint& point, float& scale)
1974 webViewImpl->animateDoubleTapZoom(point);
1975 EXPECT_TRUE(webViewImpl->fakeDoubleTapAnimationPendingForTesting());
1976 simulatePageScale(webViewImpl, scale);
1979 TEST_F(WebFrameTest, DivAutoZoomWideDivTest)
1981 registerMockedHttpURLLoad("get_wide_div_for_auto_zoom_test.html");
1983 const float deviceScaleFactor = 2.0f;
1984 int viewportWidth = 640 / deviceScaleFactor;
1985 int viewportHeight = 1280 / deviceScaleFactor;
1986 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
1987 FrameTestHelpers::WebViewHelper webViewHelper;
1988 webViewHelper.initializeAndLoad(m_baseURL + "get_wide_div_for_auto_zoom_test.html");
1989 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1990 webViewHelper.webView()->setPageScaleFactorLimits(1.0f, 4);
1991 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
1992 webViewHelper.webView()->setPageScaleFactor(1.0f, WebPoint(0, 0));
1993 webViewHelper.webView()->layout();
1995 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
1997 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
1999 WebRect div(0, 100, viewportWidth, 150);
2000 WebPoint point(div.x + 50, div.y + 50);
2002 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2004 simulateDoubleTap(webViewHelper.webViewImpl(), point, scale);
2005 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2006 simulateDoubleTap(webViewHelper.webViewImpl(), point, scale);
2007 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2010 TEST_F(WebFrameTest, DivAutoZoomVeryTallTest)
2012 // When a block is taller than the viewport and a zoom targets a lower part
2013 // of it, then we should keep the target point onscreen instead of snapping
2014 // back up the top of the block.
2015 registerMockedHttpURLLoad("very_tall_div.html");
2017 const float deviceScaleFactor = 2.0f;
2018 int viewportWidth = 640 / deviceScaleFactor;
2019 int viewportHeight = 1280 / deviceScaleFactor;
2020 FrameTestHelpers::WebViewHelper webViewHelper;
2021 webViewHelper.initializeAndLoad(m_baseURL + "very_tall_div.html");
2022 webViewHelper.webView()->settings()->setViewportEnabled(true);
2023 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2024 webViewHelper.webView()->setPageScaleFactorLimits(1.0f, 4);
2025 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2026 webViewHelper.webView()->setPageScaleFactor(1.0f, WebPoint(0, 0));
2027 webViewHelper.webView()->layout();
2029 WebRect div(200, 300, 400, 5000);
2030 WebPoint point(div.x + 50, div.y + 3000);
2034 WebRect blockBounds = webViewHelper.webViewImpl()->computeBlockBounds(WebRect(point.x, point.y, 0, 0), true);
2035 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(point, blockBounds, 0, 1.0f, scale, scroll);
2036 EXPECT_EQ(scale, 1.0f);
2037 EXPECT_EQ(scroll.y, 2660);
2040 TEST_F(WebFrameTest, DivAutoZoomMultipleDivsTest)
2042 registerMockedHttpURLLoad("get_multiple_divs_for_auto_zoom_test.html");
2044 const float deviceScaleFactor = 2.0f;
2045 int viewportWidth = 640 / deviceScaleFactor;
2046 int viewportHeight = 1280 / deviceScaleFactor;
2047 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2048 FrameTestHelpers::WebViewHelper webViewHelper;
2049 webViewHelper.initializeAndLoad(m_baseURL + "get_multiple_divs_for_auto_zoom_test.html");
2050 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2051 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2052 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2053 webViewHelper.webView()->setPageScaleFactor(0.5f, WebPoint(0, 0));
2054 webViewHelper.webView()->layout();
2056 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2058 WebRect topDiv(200, 100, 200, 150);
2059 WebRect bottomDiv(200, 300, 200, 150);
2060 WebPoint topPoint(topDiv.x + 50, topDiv.y + 50);
2061 WebPoint bottomPoint(bottomDiv.x + 50, bottomDiv.y + 50);
2063 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2065 // Test double tap on two different divs
2066 // After first zoom, we should go back to minimum page scale with a second double tap.
2067 simulateDoubleTap(webViewHelper.webViewImpl(), topPoint, scale);
2068 EXPECT_FLOAT_EQ(1, scale);
2069 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2070 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2072 // If the user pinch zooms after double tap, a second double tap should zoom back to the div.
2073 simulateDoubleTap(webViewHelper.webViewImpl(), topPoint, scale);
2074 EXPECT_FLOAT_EQ(1, scale);
2075 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 0.6f);
2076 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2077 EXPECT_FLOAT_EQ(1, scale);
2078 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2079 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2081 // If we didn't yet get an auto-zoom update and a second double-tap arrives, should go back to minimum scale.
2082 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2083 webViewHelper.webViewImpl()->animateDoubleTapZoom(topPoint);
2084 EXPECT_TRUE(webViewHelper.webViewImpl()->fakeDoubleTapAnimationPendingForTesting());
2085 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2086 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2089 TEST_F(WebFrameTest, DivAutoZoomScaleBoundsTest)
2091 registerMockedHttpURLLoad("get_scale_bounds_check_for_auto_zoom_test.html");
2093 int viewportWidth = 320;
2094 int viewportHeight = 480;
2095 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2096 FrameTestHelpers::WebViewHelper webViewHelper;
2097 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_bounds_check_for_auto_zoom_test.html");
2098 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2099 webViewHelper.webView()->setDeviceScaleFactor(1.5f);
2100 webViewHelper.webView()->layout();
2102 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2104 WebRect div(200, 100, 200, 150);
2105 WebPoint doubleTapPoint(div.x + 50, div.y + 50);
2108 // Test double tap scale bounds.
2109 // minimumPageScale < doubleTapZoomAlreadyLegibleScale < 1
2110 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2111 webViewHelper.webView()->layout();
2112 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2113 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2114 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2115 EXPECT_FLOAT_EQ(1, scale);
2116 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2117 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2118 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2119 EXPECT_FLOAT_EQ(1, scale);
2121 // Zoom in to reset double_tap_zoom_in_effect flag.
2122 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2123 // 1 < minimumPageScale < doubleTapZoomAlreadyLegibleScale
2124 webViewHelper.webView()->setPageScaleFactorLimits(1.1f, 4);
2125 webViewHelper.webView()->layout();
2126 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2127 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2128 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2129 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2130 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2131 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2132 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2133 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2135 // Zoom in to reset double_tap_zoom_in_effect flag.
2136 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2137 // minimumPageScale < 1 < doubleTapZoomAlreadyLegibleScale
2138 webViewHelper.webView()->setPageScaleFactorLimits(0.95f, 4);
2139 webViewHelper.webView()->layout();
2140 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2141 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2142 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2143 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2144 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2145 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2146 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2147 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2150 TEST_F(WebFrameTest, DivAutoZoomScaleFontScaleFactorTest)
2152 registerMockedHttpURLLoad("get_scale_bounds_check_for_auto_zoom_test.html");
2154 int viewportWidth = 320;
2155 int viewportHeight = 480;
2156 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2157 float textAutosizingFontScaleFactor = 1.13f;
2158 FrameTestHelpers::WebViewHelper webViewHelper;
2159 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_bounds_check_for_auto_zoom_test.html");
2160 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2161 webViewHelper.webView()->layout();
2163 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2164 webViewHelper.webViewImpl()->page()->settings().setTextAutosizingEnabled(true);
2165 webViewHelper.webViewImpl()->page()->settings().setTextAutosizingFontScaleFactor(textAutosizingFontScaleFactor);
2167 WebRect div(200, 100, 200, 150);
2168 WebPoint doubleTapPoint(div.x + 50, div.y + 50);
2171 // Test double tap scale bounds.
2172 // minimumPageScale < doubleTapZoomAlreadyLegibleScale < 1 < textAutosizingFontScaleFactor
2173 float legibleScale = textAutosizingFontScaleFactor;
2174 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2175 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2176 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2177 webViewHelper.webView()->layout();
2178 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2179 EXPECT_FLOAT_EQ(legibleScale, scale);
2180 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2181 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2182 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2183 EXPECT_FLOAT_EQ(legibleScale, scale);
2185 // Zoom in to reset double_tap_zoom_in_effect flag.
2186 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2187 // 1 < textAutosizingFontScaleFactor < minimumPageScale < doubleTapZoomAlreadyLegibleScale
2188 webViewHelper.webView()->setPageScaleFactorLimits(1.0f, 4);
2189 webViewHelper.webView()->layout();
2190 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2191 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2192 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2193 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2194 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2195 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2196 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2197 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2199 // Zoom in to reset double_tap_zoom_in_effect flag.
2200 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2201 // minimumPageScale < 1 < textAutosizingFontScaleFactor < doubleTapZoomAlreadyLegibleScale
2202 webViewHelper.webView()->setPageScaleFactorLimits(0.95f, 4);
2203 webViewHelper.webView()->layout();
2204 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2205 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2206 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2207 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2208 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2209 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2210 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2211 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2213 // Zoom in to reset double_tap_zoom_in_effect flag.
2214 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2215 // minimumPageScale < 1 < doubleTapZoomAlreadyLegibleScale < textAutosizingFontScaleFactor
2216 webViewHelper.webView()->setPageScaleFactorLimits(0.9f, 4);
2217 webViewHelper.webView()->layout();
2218 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2219 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2220 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2221 EXPECT_FLOAT_EQ(legibleScale, scale);
2222 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2223 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2224 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2225 EXPECT_FLOAT_EQ(legibleScale, scale);
2228 TEST_F(WebFrameTest, DivMultipleTargetZoomMultipleDivsTest)
2230 registerMockedHttpURLLoad("get_multiple_divs_for_auto_zoom_test.html");
2232 const float deviceScaleFactor = 2.0f;
2233 int viewportWidth = 640 / deviceScaleFactor;
2234 int viewportHeight = 1280 / deviceScaleFactor;
2235 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2236 FrameTestHelpers::WebViewHelper webViewHelper;
2237 webViewHelper.initializeAndLoad(m_baseURL + "get_multiple_divs_for_auto_zoom_test.html");
2238 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2239 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2240 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2241 webViewHelper.webView()->setPageScaleFactor(0.5f, WebPoint(0, 0));
2242 webViewHelper.webView()->layout();
2244 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2246 WebRect viewportRect(0, 0, viewportWidth, viewportHeight);
2247 WebRect topDiv(200, 100, 200, 150);
2248 WebRect bottomDiv(200, 300, 200, 150);
2250 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2252 simulateMultiTargetZoom(webViewHelper.webViewImpl(), topDiv, scale);
2253 EXPECT_FLOAT_EQ(1, scale);
2254 simulateMultiTargetZoom(webViewHelper.webViewImpl(), bottomDiv, scale);
2255 EXPECT_FLOAT_EQ(1, scale);
2256 simulateMultiTargetZoom(webViewHelper.webViewImpl(), viewportRect, scale);
2257 EXPECT_FLOAT_EQ(1, scale);
2258 webViewHelper.webViewImpl()->setPageScaleFactor(webViewHelper.webViewImpl()->minimumPageScaleFactor(), WebPoint(0, 0));
2259 simulateMultiTargetZoom(webViewHelper.webViewImpl(), topDiv, scale);
2260 EXPECT_FLOAT_EQ(1, scale);
2263 TEST_F(WebFrameTest, DivScrollIntoEditableTest)
2265 registerMockedHttpURLLoad("get_scale_for_zoom_into_editable_test.html");
2267 int viewportWidth = 450;
2268 int viewportHeight = 300;
2269 float leftBoxRatio = 0.3f;
2270 int caretPadding = 10;
2271 float minReadableCaretHeight = 18.0f;
2272 FrameTestHelpers::WebViewHelper webViewHelper;
2273 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_for_zoom_into_editable_test.html");
2274 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2275 webViewHelper.webView()->setPageScaleFactorLimits(1, 4);
2276 webViewHelper.webView()->layout();
2277 webViewHelper.webView()->setDeviceScaleFactor(1.5f);
2278 webViewHelper.webView()->settings()->setAutoZoomFocusedNodeToLegibleScale(true);
2280 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2282 WebRect editBoxWithText(200, 200, 250, 20);
2283 WebRect editBoxWithNoText(200, 250, 250, 20);
2285 // Test scrolling the focused node
2286 // The edit box is shorter and narrower than the viewport when legible.
2287 webViewHelper.webView()->advanceFocus(false);
2288 // Set the caret to the end of the input box.
2289 webViewHelper.webView()->mainFrame()->document().getElementById("EditBoxWithText").to<WebInputElement>().setSelectionRange(1000, 1000);
2290 setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), 1);
2291 WebRect rect, caret;
2292 webViewHelper.webViewImpl()->selectionBounds(caret, rect);
2295 WebCore::IntPoint scroll;
2297 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2298 EXPECT_TRUE(needAnimation);
2299 // The edit box should be left aligned with a margin for possible label.
2300 int hScroll = editBoxWithText.x - leftBoxRatio * viewportWidth / scale;
2301 EXPECT_NEAR(hScroll, scroll.x(), 1);
2302 int vScroll = editBoxWithText.y - (viewportHeight / scale - editBoxWithText.height) / 2;
2303 EXPECT_NEAR(vScroll, scroll.y(), 1);
2304 EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1);
2306 // The edit box is wider than the viewport when legible.
2307 viewportWidth = 200;
2308 viewportHeight = 150;
2309 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2310 setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), 1);
2311 webViewHelper.webViewImpl()->selectionBounds(caret, rect);
2312 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2313 EXPECT_TRUE(needAnimation);
2314 // The caret should be right aligned since the caret would be offscreen when the edit box is left aligned.
2315 hScroll = caret.x + caret.width + caretPadding - viewportWidth / scale;
2316 EXPECT_NEAR(hScroll, scroll.x(), 1);
2317 EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1);
2319 setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), 1);
2320 // Move focus to edit box with text.
2321 webViewHelper.webView()->advanceFocus(false);
2322 webViewHelper.webViewImpl()->selectionBounds(caret, rect);
2323 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2324 EXPECT_TRUE(needAnimation);
2325 // The edit box should be left aligned.
2326 hScroll = editBoxWithNoText.x;
2327 EXPECT_NEAR(hScroll, scroll.x(), 1);
2328 vScroll = editBoxWithNoText.y - (viewportHeight / scale - editBoxWithNoText.height) / 2;
2329 EXPECT_NEAR(vScroll, scroll.y(), 1);
2330 EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1);
2332 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), scroll, scale);
2334 // Move focus back to the first edit box.
2335 webViewHelper.webView()->advanceFocus(true);
2336 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2337 // The position should have stayed the same since this box was already on screen with the right scale.
2338 EXPECT_FALSE(needAnimation);
2341 class TestReloadDoesntRedirectWebFrameClient : public WebFrameClient {
2343 virtual WebNavigationPolicy decidePolicyForNavigation(
2344 WebFrame*, WebDataSource::ExtraData*, const WebURLRequest&, WebNavigationType,
2345 WebNavigationPolicy defaultPolicy, bool isRedirect) OVERRIDE
2347 EXPECT_FALSE(isRedirect);
2348 return WebNavigationPolicyCurrentTab;
2352 TEST_F(WebFrameTest, ReloadDoesntSetRedirect)
2354 // Test for case in http://crbug.com/73104. Reloading a frame very quickly
2355 // would sometimes call decidePolicyForNavigation with isRedirect=true
2356 registerMockedHttpURLLoad("form.html");
2358 TestReloadDoesntRedirectWebFrameClient webFrameClient;
2359 FrameTestHelpers::WebViewHelper webViewHelper;
2360 webViewHelper.initializeAndLoad(m_baseURL + "form.html", false, &webFrameClient);
2362 webViewHelper.webView()->mainFrame()->reload(true);
2363 // start reload before request is delivered.
2364 webViewHelper.webView()->mainFrame()->reload(true);
2365 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
2368 TEST_F(WebFrameTest, ReloadWithOverrideURLPreservesState)
2370 const std::string firstURL = "find.html";
2371 const std::string secondURL = "form.html";
2372 const std::string thirdURL = "history.html";
2373 const float pageScaleFactor = 1.1684f;
2374 const int pageWidth = 640;
2375 const int pageHeight = 480;
2377 registerMockedHttpURLLoad(firstURL);
2378 registerMockedHttpURLLoad(secondURL);
2379 registerMockedHttpURLLoad(thirdURL);
2381 FrameTestHelpers::WebViewHelper webViewHelper;
2382 webViewHelper.initializeAndLoad(m_baseURL + firstURL, true);
2383 webViewHelper.webViewImpl()->resize(WebSize(pageWidth, pageHeight));
2384 webViewHelper.webViewImpl()->mainFrame()->setScrollOffset(WebSize(pageWidth / 4, pageHeight / 4));
2385 webViewHelper.webViewImpl()->setPageScaleFactorPreservingScrollOffset(pageScaleFactor);
2387 WebSize previousOffset = webViewHelper.webViewImpl()->mainFrame()->scrollOffset();
2388 float previousScale = webViewHelper.webViewImpl()->pageScaleFactor();
2390 // Reload the page using the cache.
2391 webViewHelper.webViewImpl()->mainFrame()->reloadWithOverrideURL(toKURL(m_baseURL + secondURL), false);
2392 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
2393 ASSERT_EQ(previousOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
2394 ASSERT_EQ(previousScale, webViewHelper.webViewImpl()->pageScaleFactor());
2396 // Reload the page while ignoring the cache.
2397 webViewHelper.webViewImpl()->mainFrame()->reloadWithOverrideURL(toKURL(m_baseURL + thirdURL), true);
2398 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
2399 ASSERT_EQ(previousOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
2400 ASSERT_EQ(previousScale, webViewHelper.webViewImpl()->pageScaleFactor());
2403 class TestReloadWhileProvisionalFrameClient : public WebFrameClient {
2406 TEST_F(WebFrameTest, ReloadWhileProvisional)
2408 // Test that reloading while the previous load is still pending does not cause the initial
2409 // request to get lost.
2410 registerMockedHttpURLLoad("fixed_layout.html");
2412 TestReloadWhileProvisionalFrameClient webFrameClient;
2413 FrameTestHelpers::WebViewHelper webViewHelper;
2414 webViewHelper.initialize(false, &webFrameClient);
2415 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "fixed_layout.html");
2416 // start reload before first request is delivered.
2417 webViewHelper.webView()->mainFrame()->reload(true);
2418 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
2419 ASSERT_EQ(WebURL(toKURL(m_baseURL + "fixed_layout.html")),
2420 webViewHelper.webView()->mainFrame()->dataSource()->request().url());
2423 TEST_F(WebFrameTest, AppendRedirects)
2425 const std::string firstURL = "about:blank";
2426 const std::string secondURL = "http://www.test.com";
2428 FrameTestHelpers::WebViewHelper webViewHelper;
2429 webViewHelper.initializeAndLoad(firstURL, true);
2431 WebDataSource* dataSource = webViewHelper.webView()->mainFrame()->dataSource();
2432 ASSERT_TRUE(dataSource);
2433 dataSource->appendRedirect(toKURL(secondURL));
2435 WebVector<WebURL> redirects;
2436 dataSource->redirectChain(redirects);
2437 ASSERT_EQ(2U, redirects.size());
2438 EXPECT_EQ(toKURL(firstURL), toKURL(redirects[0].spec().data()));
2439 EXPECT_EQ(toKURL(secondURL), toKURL(redirects[1].spec().data()));
2442 TEST_F(WebFrameTest, IframeRedirect)
2444 registerMockedHttpURLLoad("iframe_redirect.html");
2445 registerMockedHttpURLLoad("visible_iframe.html");
2447 FrameTestHelpers::WebViewHelper webViewHelper;
2448 webViewHelper.initializeAndLoad(m_baseURL + "iframe_redirect.html", true);
2449 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); // Load the iframe.
2451 WebFrame* iframe = webViewHelper.webView()->findFrameByName(WebString::fromUTF8("ifr"));
2452 ASSERT_TRUE(iframe);
2453 WebDataSource* iframeDataSource = iframe->dataSource();
2454 ASSERT_TRUE(iframeDataSource);
2455 WebVector<WebURL> redirects;
2456 iframeDataSource->redirectChain(redirects);
2457 ASSERT_EQ(2U, redirects.size());
2458 EXPECT_EQ(toKURL("about:blank"), toKURL(redirects[0].spec().data()));
2459 EXPECT_EQ(toKURL("http://www.test.com/visible_iframe.html"), toKURL(redirects[1].spec().data()));
2462 TEST_F(WebFrameTest, ClearFocusedNodeTest)
2464 registerMockedHttpURLLoad("iframe_clear_focused_node_test.html");
2465 registerMockedHttpURLLoad("autofocus_input_field_iframe.html");
2467 FrameTestHelpers::WebViewHelper webViewHelper;
2468 webViewHelper.initializeAndLoad(m_baseURL + "iframe_clear_focused_node_test.html", true);
2470 // Clear the focused node.
2471 webViewHelper.webView()->clearFocusedNode();
2473 // Now retrieve the FocusedNode and test it should be null.
2474 EXPECT_EQ(0, webViewHelper.webViewImpl()->focusedElement());
2477 // Implementation of WebFrameClient that tracks the v8 contexts that are created
2478 // and destroyed for verification.
2479 class ContextLifetimeTestWebFrameClient : public WebFrameClient {
2481 struct Notification {
2483 Notification(WebFrame* frame, v8::Handle<v8::Context> context, int worldId)
2485 , context(context->GetIsolate(), context)
2495 bool Equals(Notification* other)
2497 return other && frame == other->frame && context == other->context && worldId == other->worldId;
2501 v8::Persistent<v8::Context> context;
2505 virtual ~ContextLifetimeTestWebFrameClient()
2512 for (size_t i = 0; i < createNotifications.size(); ++i)
2513 delete createNotifications[i];
2515 for (size_t i = 0; i < releaseNotifications.size(); ++i)
2516 delete releaseNotifications[i];
2518 createNotifications.clear();
2519 releaseNotifications.clear();
2522 std::vector<Notification*> createNotifications;
2523 std::vector<Notification*> releaseNotifications;
2526 virtual void didCreateScriptContext(WebFrame* frame, v8::Handle<v8::Context> context, int extensionGroup, int worldId) OVERRIDE
2528 createNotifications.push_back(new Notification(frame, context, worldId));
2531 virtual void willReleaseScriptContext(WebFrame* frame, v8::Handle<v8::Context> context, int worldId) OVERRIDE
2533 releaseNotifications.push_back(new Notification(frame, context, worldId));
2537 // TODO(aa): Deflake this test.
2538 TEST_F(WebFrameTest, FLAKY_ContextNotificationsLoadUnload)
2540 v8::HandleScope handleScope(v8::Isolate::GetCurrent());
2542 registerMockedHttpURLLoad("context_notifications_test.html");
2543 registerMockedHttpURLLoad("context_notifications_test_frame.html");
2545 // Load a frame with an iframe, make sure we get the right create notifications.
2546 ContextLifetimeTestWebFrameClient webFrameClient;
2547 FrameTestHelpers::WebViewHelper webViewHelper;
2548 webViewHelper.initializeAndLoad(m_baseURL + "context_notifications_test.html", true, &webFrameClient);
2550 WebFrame* mainFrame = webViewHelper.webView()->mainFrame();
2551 WebFrame* childFrame = mainFrame->firstChild();
2553 ASSERT_EQ(2u, webFrameClient.createNotifications.size());
2554 EXPECT_EQ(0u, webFrameClient.releaseNotifications.size());
2556 ContextLifetimeTestWebFrameClient::Notification* firstCreateNotification = webFrameClient.createNotifications[0];
2557 ContextLifetimeTestWebFrameClient::Notification* secondCreateNotification = webFrameClient.createNotifications[1];
2559 EXPECT_EQ(mainFrame, firstCreateNotification->frame);
2560 EXPECT_EQ(mainFrame->mainWorldScriptContext(), firstCreateNotification->context);
2561 EXPECT_EQ(0, firstCreateNotification->worldId);
2563 EXPECT_EQ(childFrame, secondCreateNotification->frame);
2564 EXPECT_EQ(childFrame->mainWorldScriptContext(), secondCreateNotification->context);
2565 EXPECT_EQ(0, secondCreateNotification->worldId);
2567 // Close the view. We should get two release notifications that are exactly the same as the create ones, in reverse order.
2568 webViewHelper.reset();
2570 ASSERT_EQ(2u, webFrameClient.releaseNotifications.size());
2571 ContextLifetimeTestWebFrameClient::Notification* firstReleaseNotification = webFrameClient.releaseNotifications[0];
2572 ContextLifetimeTestWebFrameClient::Notification* secondReleaseNotification = webFrameClient.releaseNotifications[1];
2574 ASSERT_TRUE(firstCreateNotification->Equals(secondReleaseNotification));
2575 ASSERT_TRUE(secondCreateNotification->Equals(firstReleaseNotification));
2578 TEST_F(WebFrameTest, ContextNotificationsReload)
2580 v8::HandleScope handleScope(v8::Isolate::GetCurrent());
2582 registerMockedHttpURLLoad("context_notifications_test.html");
2583 registerMockedHttpURLLoad("context_notifications_test_frame.html");
2585 ContextLifetimeTestWebFrameClient webFrameClient;
2586 FrameTestHelpers::WebViewHelper webViewHelper;
2587 webViewHelper.initializeAndLoad(m_baseURL + "context_notifications_test.html", true, &webFrameClient);
2589 // Refresh, we should get two release notifications and two more create notifications.
2590 webViewHelper.webView()->mainFrame()->reload(false);
2591 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
2592 ASSERT_EQ(4u, webFrameClient.createNotifications.size());
2593 ASSERT_EQ(2u, webFrameClient.releaseNotifications.size());
2595 // The two release notifications we got should be exactly the same as the first two create notifications.
2596 for (size_t i = 0; i < webFrameClient.releaseNotifications.size(); ++i) {
2597 EXPECT_TRUE(webFrameClient.releaseNotifications[i]->Equals(
2598 webFrameClient.createNotifications[webFrameClient.createNotifications.size() - 3 - i]));
2601 // The last two create notifications should be for the current frames and context.
2602 WebFrame* mainFrame = webViewHelper.webView()->mainFrame();
2603 WebFrame* childFrame = mainFrame->firstChild();
2604 ContextLifetimeTestWebFrameClient::Notification* firstRefreshNotification = webFrameClient.createNotifications[2];
2605 ContextLifetimeTestWebFrameClient::Notification* secondRefreshNotification = webFrameClient.createNotifications[3];
2607 EXPECT_EQ(mainFrame, firstRefreshNotification->frame);
2608 EXPECT_EQ(mainFrame->mainWorldScriptContext(), firstRefreshNotification->context);
2609 EXPECT_EQ(0, firstRefreshNotification->worldId);
2611 EXPECT_EQ(childFrame, secondRefreshNotification->frame);
2612 EXPECT_EQ(childFrame->mainWorldScriptContext(), secondRefreshNotification->context);
2613 EXPECT_EQ(0, secondRefreshNotification->worldId);
2616 TEST_F(WebFrameTest, ContextNotificationsIsolatedWorlds)
2618 v8::Isolate* isolate = v8::Isolate::GetCurrent();
2619 v8::HandleScope handleScope(isolate);
2621 registerMockedHttpURLLoad("context_notifications_test.html");
2622 registerMockedHttpURLLoad("context_notifications_test_frame.html");
2624 ContextLifetimeTestWebFrameClient webFrameClient;
2625 FrameTestHelpers::WebViewHelper webViewHelper;
2626 webViewHelper.initializeAndLoad(m_baseURL + "context_notifications_test.html", true, &webFrameClient);
2628 // Add an isolated world.
2629 webFrameClient.reset();
2631 int isolatedWorldId = 42;
2632 WebScriptSource scriptSource("hi!");
2634 int extensionGroup = 0;
2635 webViewHelper.webView()->mainFrame()->executeScriptInIsolatedWorld(isolatedWorldId, &scriptSource, numSources, extensionGroup);
2637 // We should now have a new create notification.
2638 ASSERT_EQ(1u, webFrameClient.createNotifications.size());
2639 ContextLifetimeTestWebFrameClient::Notification* notification = webFrameClient.createNotifications[0];
2640 ASSERT_EQ(isolatedWorldId, notification->worldId);
2641 ASSERT_EQ(webViewHelper.webView()->mainFrame(), notification->frame);
2643 // 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.
2644 ASSERT_NE(webViewHelper.webView()->mainFrame()->mainWorldScriptContext(), v8::Local<v8::Context>::New(isolate, notification->context));
2646 webViewHelper.reset();
2648 // We should have gotten three release notifications (one for each of the frames, plus one for the isolated context).
2649 ASSERT_EQ(3u, webFrameClient.releaseNotifications.size());
2651 // And one of them should be exactly the same as the create notification for the isolated context.
2653 for (size_t i = 0; i < webFrameClient.releaseNotifications.size(); ++i) {
2654 if (webFrameClient.releaseNotifications[i]->Equals(webFrameClient.createNotifications[0]))
2657 EXPECT_EQ(1, matchCount);
2660 TEST_F(WebFrameTest, FindInPage)
2662 registerMockedHttpURLLoad("find.html");
2663 FrameTestHelpers::WebViewHelper webViewHelper;
2664 webViewHelper.initializeAndLoad(m_baseURL + "find.html");
2665 WebFrame* frame = webViewHelper.webView()->mainFrame();
2666 const int findIdentifier = 12345;
2667 WebFindOptions options;
2669 // Find in a <div> element.
2670 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar1"), options, false, 0));
2671 frame->stopFinding(false);
2672 WebRange range = frame->selectionRange();
2673 EXPECT_EQ(5, range.startOffset());
2674 EXPECT_EQ(9, range.endOffset());
2675 EXPECT_TRUE(frame->document().focusedNode().isNull());
2677 // Find in an <input> value.
2678 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar2"), options, false, 0));
2679 // Confirm stopFinding(false) sets the selection on the found text.
2680 frame->stopFinding(false);
2681 range = frame->selectionRange();
2682 ASSERT_FALSE(range.isNull());
2683 EXPECT_EQ(5, range.startOffset());
2684 EXPECT_EQ(9, range.endOffset());
2685 EXPECT_EQ(WebString::fromUTF8("INPUT"), frame->document().focusedNode().nodeName());
2687 // Find in a <textarea> content.
2688 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar3"), options, false, 0));
2689 // Confirm stopFinding(false) sets the selection on the found text.
2690 frame->stopFinding(false);
2691 range = frame->selectionRange();
2692 ASSERT_FALSE(range.isNull());
2693 EXPECT_EQ(5, range.startOffset());
2694 EXPECT_EQ(9, range.endOffset());
2695 EXPECT_EQ(WebString::fromUTF8("TEXTAREA"), frame->document().focusedNode().nodeName());
2697 // Find in a contentEditable element.
2698 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar4"), options, false, 0));
2699 // Confirm stopFinding(false) sets the selection on the found text.
2700 frame->stopFinding(false);
2701 range = frame->selectionRange();
2702 ASSERT_FALSE(range.isNull());
2703 EXPECT_EQ(0, range.startOffset());
2704 EXPECT_EQ(4, range.endOffset());
2705 // "bar4" is surrounded by <span>, but the focusable node should be the parent <div>.
2706 EXPECT_EQ(WebString::fromUTF8("DIV"), frame->document().focusedNode().nodeName());
2708 // Find in <select> content.
2709 EXPECT_FALSE(frame->find(findIdentifier, WebString::fromUTF8("bar5"), options, false, 0));
2710 // If there are any matches, stopFinding will set the selection on the found text.
2711 // However, we do not expect any matches, so check that the selection is null.
2712 frame->stopFinding(false);
2713 range = frame->selectionRange();
2714 ASSERT_TRUE(range.isNull());
2717 TEST_F(WebFrameTest, GetContentAsPlainText)
2719 FrameTestHelpers::WebViewHelper webViewHelper;
2720 webViewHelper.initializeAndLoad("about:blank", true);
2721 // We set the size because it impacts line wrapping, which changes the
2722 // resulting text value.
2723 webViewHelper.webView()->resize(WebSize(640, 480));
2724 WebFrame* frame = webViewHelper.webView()->mainFrame();
2726 // Generate a simple test case.
2727 const char simpleSource[] = "<div>Foo bar</div><div></div>baz";
2728 WebCore::KURL testURL = toKURL("about:blank");
2729 frame->loadHTMLString(simpleSource, testURL);
2732 // Make sure it comes out OK.
2733 const std::string expected("Foo bar\nbaz");
2734 WebString text = frame->contentAsText(std::numeric_limits<size_t>::max());
2735 EXPECT_EQ(expected, text.utf8());
2737 // Try reading the same one with clipping of the text.
2738 const int length = 5;
2739 text = frame->contentAsText(length);
2740 EXPECT_EQ(expected.substr(0, length), text.utf8());
2742 // Now do a new test with a subframe.
2743 const char outerFrameSource[] = "Hello<iframe></iframe> world";
2744 frame->loadHTMLString(outerFrameSource, testURL);
2747 // Load something into the subframe.
2748 WebFrame* subframe = frame->findChildByExpression(WebString::fromUTF8("/html/body/iframe"));
2749 ASSERT_TRUE(subframe);
2750 subframe->loadHTMLString("sub<p>text", testURL);
2753 text = frame->contentAsText(std::numeric_limits<size_t>::max());
2754 EXPECT_EQ("Hello world\n\nsub\ntext", text.utf8());
2756 // Get the frame text where the subframe separator falls on the boundary of
2757 // what we'll take. There used to be a crash in this case.
2758 text = frame->contentAsText(12);
2759 EXPECT_EQ("Hello world", text.utf8());
2762 TEST_F(WebFrameTest, GetFullHtmlOfPage)
2764 FrameTestHelpers::WebViewHelper webViewHelper;
2765 webViewHelper.initializeAndLoad("about:blank", true);
2766 WebFrame* frame = webViewHelper.webView()->mainFrame();
2768 // Generate a simple test case.
2769 const char simpleSource[] = "<p>Hello</p><p>World</p>";
2770 WebCore::KURL testURL = toKURL("about:blank");
2771 frame->loadHTMLString(simpleSource, testURL);
2774 WebString text = frame->contentAsText(std::numeric_limits<size_t>::max());
2775 EXPECT_EQ("Hello\n\nWorld", text.utf8());
2777 const std::string html = frame->contentAsMarkup().utf8();
2779 // Load again with the output html.
2780 frame->loadHTMLString(WebData(html.c_str(), html.length()), testURL);
2783 EXPECT_EQ(html, frame->contentAsMarkup().utf8());
2785 text = frame->contentAsText(std::numeric_limits<size_t>::max());
2786 EXPECT_EQ("Hello\n\nWorld", text.utf8());
2788 // Test selection check
2789 EXPECT_FALSE(frame->hasSelection());
2790 frame->executeCommand(WebString::fromUTF8("SelectAll"));
2791 EXPECT_TRUE(frame->hasSelection());
2792 frame->executeCommand(WebString::fromUTF8("Unselect"));
2793 EXPECT_FALSE(frame->hasSelection());
2794 WebString selectionHtml = frame->selectionAsMarkup();
2795 EXPECT_TRUE(selectionHtml.isEmpty());
2798 class TestExecuteScriptDuringDidCreateScriptContext : public WebFrameClient {
2800 virtual void didCreateScriptContext(WebFrame* frame, v8::Handle<v8::Context> context, int extensionGroup, int worldId) OVERRIDE
2802 frame->executeScript(WebScriptSource("window.history = 'replaced';"));
2806 TEST_F(WebFrameTest, ExecuteScriptDuringDidCreateScriptContext)
2808 registerMockedHttpURLLoad("hello_world.html");
2810 TestExecuteScriptDuringDidCreateScriptContext webFrameClient;
2811 FrameTestHelpers::WebViewHelper webViewHelper;
2812 webViewHelper.initializeAndLoad(m_baseURL + "hello_world.html", true, &webFrameClient);
2814 webViewHelper.webView()->mainFrame()->reload();
2815 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
2818 class TestDidCreateFrameWebFrameClient : public WebFrameClient {
2820 TestDidCreateFrameWebFrameClient() : m_frameCount(0), m_parent(0)
2824 virtual void didCreateFrame(WebFrame* parent, WebFrame* child)
2835 TEST_F(WebFrameTest, DidCreateFrame)
2837 registerMockedHttpURLLoad("iframes_test.html");
2838 registerMockedHttpURLLoad("visible_iframe.html");
2839 registerMockedHttpURLLoad("invisible_iframe.html");
2840 registerMockedHttpURLLoad("zero_sized_iframe.html");
2842 TestDidCreateFrameWebFrameClient webFrameClient;
2843 FrameTestHelpers::WebViewHelper webViewHelper;
2844 webViewHelper.initializeAndLoad(m_baseURL + "iframes_test.html", false, &webFrameClient);
2846 EXPECT_EQ(webFrameClient.m_frameCount, 3);
2847 EXPECT_EQ(webFrameClient.m_parent, webViewHelper.webView()->mainFrame());
2850 class FindUpdateWebFrameClient : public WebFrameClient {
2852 FindUpdateWebFrameClient()
2853 : m_findResultsAreReady(false)
2858 virtual void reportFindInPageMatchCount(int, int count, bool finalUpdate) OVERRIDE
2862 m_findResultsAreReady = true;
2865 bool findResultsAreReady() const { return m_findResultsAreReady; }
2866 int count() const { return m_count; }
2869 bool m_findResultsAreReady;
2873 // This fails on Mac https://bugs.webkit.org/show_bug.cgi?id=108574
2875 TEST_F(WebFrameTest, DISABLED_FindInPageMatchRects)
2877 TEST_F(WebFrameTest, FindInPageMatchRects)
2880 registerMockedHttpURLLoad("find_in_page.html");
2881 registerMockedHttpURLLoad("find_in_page_frame.html");
2883 FindUpdateWebFrameClient client;
2884 FrameTestHelpers::WebViewHelper webViewHelper;
2885 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
2886 webViewHelper.webView()->resize(WebSize(640, 480));
2887 webViewHelper.webView()->layout();
2890 // Note that the 'result 19' in the <select> element is not expected to produce a match.
2891 static const char* kFindString = "result";
2892 static const int kFindIdentifier = 12345;
2893 static const int kNumResults = 19;
2895 WebFindOptions options;
2896 WebString searchText = WebString::fromUTF8(kFindString);
2897 WebFrameImpl* mainFrame = toWebFrameImpl(webViewHelper.webView()->mainFrame());
2898 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
2900 mainFrame->resetMatchCount();
2902 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
2903 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
2906 EXPECT_TRUE(client.findResultsAreReady());
2908 WebVector<WebFloatRect> webMatchRects;
2909 mainFrame->findMatchRects(webMatchRects);
2910 ASSERT_EQ(webMatchRects.size(), static_cast<size_t>(kNumResults));
2911 int rectsVersion = mainFrame->findMatchMarkersVersion();
2913 for (int resultIndex = 0; resultIndex < kNumResults; ++resultIndex) {
2914 FloatRect resultRect = static_cast<FloatRect>(webMatchRects[resultIndex]);
2916 // Select the match by the center of its rect.
2917 EXPECT_EQ(mainFrame->selectNearestFindMatch(resultRect.center(), 0), resultIndex + 1);
2919 // Check that the find result ordering matches with our expectations.
2920 Range* result = mainFrame->activeMatchFrame()->activeMatch();
2921 ASSERT_TRUE(result);
2922 result->setEnd(result->endContainer(), result->endOffset() + 3);
2923 EXPECT_EQ(result->text(), String::format("%s %02d", kFindString, resultIndex));
2925 // Verify that the expected match rect also matches the currently active match.
2926 // Compare the enclosing rects to prevent precision issues caused by CSS transforms.
2927 FloatRect activeMatch = mainFrame->activeFindMatchRect();
2928 EXPECT_EQ(enclosingIntRect(activeMatch), enclosingIntRect(resultRect));
2930 // The rects version should not have changed.
2931 EXPECT_EQ(mainFrame->findMatchMarkersVersion(), rectsVersion);
2934 // All results after the first two ones should be below between them in find-in-page coordinates.
2935 // This is because results 2 to 9 are inside an iframe located between results 0 and 1. This applies to the fixed div too.
2936 EXPECT_TRUE(webMatchRects[0].y < webMatchRects[1].y);
2937 for (int resultIndex = 2; resultIndex < kNumResults; ++resultIndex) {
2938 EXPECT_TRUE(webMatchRects[0].y < webMatchRects[resultIndex].y);
2939 EXPECT_TRUE(webMatchRects[1].y > webMatchRects[resultIndex].y);
2942 // Result 3 should be below both 2 and 4. This is caused by the CSS transform in the containing div.
2943 // If the transform doesn't work then 3 will be between 2 and 4.
2944 EXPECT_TRUE(webMatchRects[3].y > webMatchRects[2].y);
2945 EXPECT_TRUE(webMatchRects[3].y > webMatchRects[4].y);
2947 // Results 6, 7, 8 and 9 should be one below the other in that same order.
2948 // If overflow:scroll is not properly handled then result 8 would be below result 9 or
2949 // result 7 above result 6 depending on the scroll.
2950 EXPECT_TRUE(webMatchRects[6].y < webMatchRects[7].y);
2951 EXPECT_TRUE(webMatchRects[7].y < webMatchRects[8].y);
2952 EXPECT_TRUE(webMatchRects[8].y < webMatchRects[9].y);
2954 // Results 11, 12, 13 and 14 should be between results 10 and 15, as they are inside the table.
2955 EXPECT_TRUE(webMatchRects[11].y > webMatchRects[10].y);
2956 EXPECT_TRUE(webMatchRects[12].y > webMatchRects[10].y);
2957 EXPECT_TRUE(webMatchRects[13].y > webMatchRects[10].y);
2958 EXPECT_TRUE(webMatchRects[14].y > webMatchRects[10].y);
2959 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[15].y);
2960 EXPECT_TRUE(webMatchRects[12].y < webMatchRects[15].y);
2961 EXPECT_TRUE(webMatchRects[13].y < webMatchRects[15].y);
2962 EXPECT_TRUE(webMatchRects[14].y < webMatchRects[15].y);
2964 // Result 11 should be above 12, 13 and 14 as it's in the table header.
2965 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[12].y);
2966 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[13].y);
2967 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[14].y);
2969 // Result 11 should also be right to 12, 13 and 14 because of the colspan.
2970 EXPECT_TRUE(webMatchRects[11].x > webMatchRects[12].x);
2971 EXPECT_TRUE(webMatchRects[11].x > webMatchRects[13].x);
2972 EXPECT_TRUE(webMatchRects[11].x > webMatchRects[14].x);
2974 // Result 12 should be left to results 11, 13 and 14 in the table layout.
2975 EXPECT_TRUE(webMatchRects[12].x < webMatchRects[11].x);
2976 EXPECT_TRUE(webMatchRects[12].x < webMatchRects[13].x);
2977 EXPECT_TRUE(webMatchRects[12].x < webMatchRects[14].x);
2979 // Results 13, 12 and 14 should be one above the other in that order because of the rowspan
2980 // and vertical-align: middle by default.
2981 EXPECT_TRUE(webMatchRects[13].y < webMatchRects[12].y);
2982 EXPECT_TRUE(webMatchRects[12].y < webMatchRects[14].y);
2984 // Result 16 should be below result 15.
2985 EXPECT_TRUE(webMatchRects[15].y > webMatchRects[14].y);
2987 // Result 18 should be normalized with respect to the position:relative div, and not it's
2988 // immediate containing div. Consequently, result 18 should be above result 17.
2989 EXPECT_TRUE(webMatchRects[17].y > webMatchRects[18].y);
2991 // Resizing should update the rects version.
2992 webViewHelper.webView()->resize(WebSize(800, 600));
2994 EXPECT_TRUE(mainFrame->findMatchMarkersVersion() != rectsVersion);
2997 TEST_F(WebFrameTest, FindInPageSkipsHiddenFrames)
2999 registerMockedHttpURLLoad("find_in_hidden_frame.html");
3001 FindUpdateWebFrameClient client;
3002 FrameTestHelpers::WebViewHelper webViewHelper;
3003 webViewHelper.initializeAndLoad(m_baseURL + "find_in_hidden_frame.html", true, &client);
3004 webViewHelper.webView()->resize(WebSize(640, 480));
3005 webViewHelper.webView()->layout();
3008 static const char* kFindString = "hello";
3009 static const int kFindIdentifier = 12345;
3010 static const int kNumResults = 1;
3012 WebFindOptions options;
3013 WebString searchText = WebString::fromUTF8(kFindString);
3014 WebFrameImpl* mainFrame = toWebFrameImpl(webViewHelper.webView()->mainFrame());
3015 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
3017 mainFrame->resetMatchCount();
3019 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3020 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3023 EXPECT_TRUE(client.findResultsAreReady());
3024 EXPECT_EQ(kNumResults, client.count());
3027 TEST_F(WebFrameTest, FindOnDetachedFrame)
3029 registerMockedHttpURLLoad("find_in_page.html");
3030 registerMockedHttpURLLoad("find_in_page_frame.html");
3032 FindUpdateWebFrameClient client;
3033 FrameTestHelpers::WebViewHelper webViewHelper;
3034 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3035 webViewHelper.webView()->resize(WebSize(640, 480));
3036 webViewHelper.webView()->layout();
3039 static const char* kFindString = "result";
3040 static const int kFindIdentifier = 12345;
3042 WebFindOptions options;
3043 WebString searchText = WebString::fromUTF8(kFindString);
3044 WebFrameImpl* mainFrame = toWebFrameImpl(webViewHelper.webView()->mainFrame());
3045 WebFrameImpl* secondFrame = toWebFrameImpl(mainFrame->traverseNext(false));
3046 RefPtr<WebCore::Frame> holdSecondFrame = secondFrame->frame();
3048 // Detach the frame before finding.
3049 EXPECT_TRUE(mainFrame->document().getElementById("frame").remove());
3051 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
3052 EXPECT_FALSE(secondFrame->find(kFindIdentifier, searchText, options, false, 0));
3055 EXPECT_FALSE(client.findResultsAreReady());
3057 mainFrame->resetMatchCount();
3059 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3060 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3063 EXPECT_TRUE(client.findResultsAreReady());
3065 holdSecondFrame.release();
3068 TEST_F(WebFrameTest, FindDetachFrameBeforeScopeStrings)
3070 registerMockedHttpURLLoad("find_in_page.html");
3071 registerMockedHttpURLLoad("find_in_page_frame.html");
3073 FindUpdateWebFrameClient client;
3074 FrameTestHelpers::WebViewHelper webViewHelper;
3075 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3076 webViewHelper.webView()->resize(WebSize(640, 480));
3077 webViewHelper.webView()->layout();
3080 static const char* kFindString = "result";
3081 static const int kFindIdentifier = 12345;
3083 WebFindOptions options;
3084 WebString searchText = WebString::fromUTF8(kFindString);
3085 WebFrameImpl* mainFrame = toWebFrameImpl(webViewHelper.webView()->mainFrame());
3086 WebFrameImpl* secondFrame = toWebFrameImpl(mainFrame->traverseNext(false));
3087 RefPtr<WebCore::Frame> holdSecondFrame = secondFrame->frame();
3089 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3090 EXPECT_TRUE(frame->find(kFindIdentifier, searchText, options, false, 0));
3093 EXPECT_FALSE(client.findResultsAreReady());
3095 // Detach the frame between finding and scoping.
3096 EXPECT_TRUE(mainFrame->document().getElementById("frame").remove());
3098 mainFrame->resetMatchCount();
3100 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3101 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3104 EXPECT_TRUE(client.findResultsAreReady());
3106 holdSecondFrame.release();
3109 TEST_F(WebFrameTest, FindDetachFrameWhileScopingStrings)
3111 registerMockedHttpURLLoad("find_in_page.html");
3112 registerMockedHttpURLLoad("find_in_page_frame.html");
3114 FindUpdateWebFrameClient client;
3115 FrameTestHelpers::WebViewHelper webViewHelper;
3116 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3117 webViewHelper.webView()->resize(WebSize(640, 480));
3118 webViewHelper.webView()->layout();
3121 static const char* kFindString = "result";
3122 static const int kFindIdentifier = 12345;
3124 WebFindOptions options;
3125 WebString searchText = WebString::fromUTF8(kFindString);
3126 WebFrameImpl* mainFrame = toWebFrameImpl(webViewHelper.webView()->mainFrame());
3127 WebFrameImpl* secondFrame = toWebFrameImpl(mainFrame->traverseNext(false));
3128 RefPtr<WebCore::Frame> holdSecondFrame = secondFrame->frame();
3130 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3131 EXPECT_TRUE(frame->find(kFindIdentifier, searchText, options, false, 0));
3134 EXPECT_FALSE(client.findResultsAreReady());
3136 mainFrame->resetMatchCount();
3138 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3139 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3141 // The first scopeStringMatches will have reset the state. Detach before it actually scopes.
3142 EXPECT_TRUE(mainFrame->document().getElementById("frame").remove());
3145 EXPECT_TRUE(client.findResultsAreReady());
3147 holdSecondFrame.release();
3150 static WebPoint topLeft(const WebRect& rect)
3152 return WebPoint(rect.x, rect.y);
3155 static WebPoint bottomRightMinusOne(const WebRect& rect)
3157 // FIXME: If we don't subtract 1 from the x- and y-coordinates of the
3158 // selection bounds, selectRange() will select the *next* element. That's
3159 // strictly correct, as hit-testing checks the pixel to the lower-right of
3160 // the input coordinate, but it's a wart on the API.
3161 return WebPoint(rect.x + rect.width - 1, rect.y + rect.height - 1);
3164 static WebRect elementBounds(WebFrame* frame, const WebString& id)
3166 return frame->document().getElementById(id).boundsInViewportSpace();
3169 static std::string selectionAsString(WebFrame* frame)
3171 return frame->selectionAsText().utf8();
3174 TEST_F(WebFrameTest, SelectRange)
3177 WebRect startWebRect;
3180 registerMockedHttpURLLoad("select_range_basic.html");
3181 registerMockedHttpURLLoad("select_range_scroll.html");
3183 FrameTestHelpers::WebViewHelper webViewHelper;
3184 initializeTextSelectionWebView(m_baseURL + "select_range_basic.html", &webViewHelper);
3185 frame = webViewHelper.webView()->mainFrame();
3186 EXPECT_EQ("Some test text for testing.", selectionAsString(frame));
3187 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3188 frame->executeCommand(WebString::fromUTF8("Unselect"));
3189 EXPECT_EQ("", selectionAsString(frame));
3190 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3191 EXPECT_EQ("Some test text for testing.", selectionAsString(frame));
3193 initializeTextSelectionWebView(m_baseURL + "select_range_scroll.html", &webViewHelper);
3194 frame = webViewHelper.webView()->mainFrame();
3195 EXPECT_EQ("Some offscreen test text for testing.", selectionAsString(frame));
3196 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3197 frame->executeCommand(WebString::fromUTF8("Unselect"));
3198 EXPECT_EQ("", selectionAsString(frame));
3199 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3200 EXPECT_EQ("Some offscreen test text for testing.", selectionAsString(frame));
3203 TEST_F(WebFrameTest, SelectRangeInIframe)
3206 WebRect startWebRect;
3209 registerMockedHttpURLLoad("select_range_iframe.html");
3210 registerMockedHttpURLLoad("select_range_basic.html");
3212 FrameTestHelpers::WebViewHelper webViewHelper;
3213 initializeTextSelectionWebView(m_baseURL + "select_range_iframe.html", &webViewHelper);
3214 frame = webViewHelper.webView()->mainFrame();
3215 WebFrame* subframe = frame->findChildByExpression(WebString::fromUTF8("/html/body/iframe"));
3216 EXPECT_EQ("Some test text for testing.", selectionAsString(subframe));
3217 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3218 subframe->executeCommand(WebString::fromUTF8("Unselect"));
3219 EXPECT_EQ("", selectionAsString(subframe));
3220 subframe->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3221 EXPECT_EQ("Some test text for testing.", selectionAsString(subframe));
3224 TEST_F(WebFrameTest, SelectRangeDivContentEditable)
3227 WebRect startWebRect;
3230 registerMockedHttpURLLoad("select_range_div_editable.html");
3232 // Select the middle of an editable element, then try to extend the selection to the top of the document.
3233 // The selection range should be clipped to the bounds of the editable element.
3234 FrameTestHelpers::WebViewHelper webViewHelper;
3235 initializeTextSelectionWebView(m_baseURL + "select_range_div_editable.html", &webViewHelper);
3236 frame = webViewHelper.webView()->mainFrame();
3237 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3238 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3240 frame->selectRange(bottomRightMinusOne(endWebRect), WebPoint(0, 0));
3241 EXPECT_EQ("16-char header. This text is initially selected.", selectionAsString(frame));
3243 // As above, but extending the selection to the bottom of the document.
3244 initializeTextSelectionWebView(m_baseURL + "select_range_div_editable.html", &webViewHelper);
3245 frame = webViewHelper.webView()->mainFrame();
3247 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3248 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3249 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3250 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3252 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3253 frame->selectRange(topLeft(startWebRect), WebPoint(640, 480));
3254 EXPECT_EQ("This text is initially selected. 16-char footer.", selectionAsString(frame));
3257 // positionForPoint returns the wrong values for contenteditable spans. See
3258 // http://crbug.com/238334.
3259 TEST_F(WebFrameTest, DISABLED_SelectRangeSpanContentEditable)
3262 WebRect startWebRect;
3265 registerMockedHttpURLLoad("select_range_span_editable.html");
3267 // Select the middle of an editable element, then try to extend the selection to the top of the document.
3268 // The selection range should be clipped to the bounds of the editable element.
3269 FrameTestHelpers::WebViewHelper webViewHelper;
3270 initializeTextSelectionWebView(m_baseURL + "select_range_span_editable.html", &webViewHelper);
3271 frame = webViewHelper.webView()->mainFrame();
3272 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3273 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3275 frame->selectRange(bottomRightMinusOne(endWebRect), WebPoint(0, 0));
3276 EXPECT_EQ("16-char header. This text is initially selected.", selectionAsString(frame));
3278 // As above, but extending the selection to the bottom of the document.
3279 initializeTextSelectionWebView(m_baseURL + "select_range_span_editable.html", &webViewHelper);
3280 frame = webViewHelper.webView()->mainFrame();
3282 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3283 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3284 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3285 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3287 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3288 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3289 frame->selectRange(topLeft(startWebRect), WebPoint(640, 480));
3290 EXPECT_EQ("This text is initially selected. 16-char footer.", selectionAsString(frame));
3293 TEST_F(WebFrameTest, SelectRangeCanMoveSelectionStart)
3295 registerMockedHttpURLLoad("text_selection.html");
3296 FrameTestHelpers::WebViewHelper webViewHelper;
3297 initializeTextSelectionWebView(m_baseURL + "text_selection.html", &webViewHelper);
3298 WebFrame* frame = webViewHelper.webView()->mainFrame();
3300 // Select second span. We can move the start to include the first span.
3301 frame->executeScript(WebScriptSource("selectElement('header_2');"));
3302 EXPECT_EQ("Header 2.", selectionAsString(frame));
3303 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "header_2")), topLeft(elementBounds(frame, "header_1")));
3304 EXPECT_EQ("Header 1. Header 2.", selectionAsString(frame));
3306 // We can move the start and end together.
3307 frame->executeScript(WebScriptSource("selectElement('header_1');"));
3308 EXPECT_EQ("Header 1.", selectionAsString(frame));
3309 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "header_1")));
3310 EXPECT_EQ("", selectionAsString(frame));
3311 // Selection is a caret, not empty.
3312 EXPECT_FALSE(frame->selectionRange().isNull());
3314 // We can move the start across the end.
3315 frame->executeScript(WebScriptSource("selectElement('header_1');"));
3316 EXPECT_EQ("Header 1.", selectionAsString(frame));
3317 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "header_2")));
3318 EXPECT_EQ(" Header 2.", selectionAsString(frame));
3320 // Can't extend the selection part-way into an editable element.
3321 frame->executeScript(WebScriptSource("selectElement('footer_2');"));
3322 EXPECT_EQ("Footer 2.", selectionAsString(frame));
3323 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "footer_2")), topLeft(elementBounds(frame, "editable_2")));
3324 EXPECT_EQ(" [ Footer 1. Footer 2.", selectionAsString(frame));
3326 // Can extend the selection completely across editable elements.
3327 frame->executeScript(WebScriptSource("selectElement('footer_2');"));
3328 EXPECT_EQ("Footer 2.", selectionAsString(frame));
3329 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "footer_2")), topLeft(elementBounds(frame, "header_2")));
3330 EXPECT_EQ("Header 2. ] [ Editable 1. Editable 2. ] [ Footer 1. Footer 2.", selectionAsString(frame));
3332 // If the selection is editable text, we can't extend it into non-editable text.
3333 frame->executeScript(WebScriptSource("selectElement('editable_2');"));
3334 EXPECT_EQ("Editable 2.", selectionAsString(frame));
3335 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "editable_2")), topLeft(elementBounds(frame, "header_2")));
3336 // positionForPoint returns the wrong values for contenteditable spans. See
3337 // http://crbug.com/238334.
3338 // EXPECT_EQ("[ Editable 1. Editable 2.", selectionAsString(frame));
3341 TEST_F(WebFrameTest, SelectRangeCanMoveSelectionEnd)
3343 registerMockedHttpURLLoad("text_selection.html");
3344 FrameTestHelpers::WebViewHelper webViewHelper;
3345 initializeTextSelectionWebView(m_baseURL + "text_selection.html", &webViewHelper);
3346 WebFrame* frame = webViewHelper.webView()->mainFrame();
3348 // Select first span. We can move the end to include the second span.
3349 frame->executeScript(WebScriptSource("selectElement('header_1');"));
3350 EXPECT_EQ("Header 1.", selectionAsString(frame));
3351 frame->selectRange(topLeft(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "header_2")));
3352 EXPECT_EQ("Header 1. Header 2.", selectionAsString(frame));
3354 // We can move the start and end together.
3355 frame->executeScript(WebScriptSource("selectElement('header_2');"));
3356 EXPECT_EQ("Header 2.", selectionAsString(frame));
3357 frame->selectRange(topLeft(elementBounds(frame, "header_2")), topLeft(elementBounds(frame, "header_2")));
3358 EXPECT_EQ("", selectionAsString(frame));
3359 // Selection is a caret, not empty.
3360 EXPECT_FALSE(frame->selectionRange().isNull());
3362 // We can move the end across the start.
3363 frame->executeScript(WebScriptSource("selectElement('header_2');"));
3364 EXPECT_EQ("Header 2.", selectionAsString(frame));
3365 frame->selectRange(topLeft(elementBounds(frame, "header_2")), topLeft(elementBounds(frame, "header_1")));
3366 EXPECT_EQ("Header 1. ", selectionAsString(frame));
3368 // Can't extend the selection part-way into an editable element.
3369 frame->executeScript(WebScriptSource("selectElement('header_1');"));
3370 EXPECT_EQ("Header 1.", selectionAsString(frame));
3371 frame->selectRange(topLeft(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "editable_1")));
3372 EXPECT_EQ("Header 1. Header 2. ] ", selectionAsString(frame));
3374 // Can extend the selection completely across editable elements.
3375 frame->executeScript(WebScriptSource("selectElement('header_1');"));
3376 EXPECT_EQ("Header 1.", selectionAsString(frame));
3377 frame->selectRange(topLeft(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "footer_1")));
3378 EXPECT_EQ("Header 1. Header 2. ] [ Editable 1. Editable 2. ] [ Footer 1.", selectionAsString(frame));
3380 // If the selection is editable text, we can't extend it into non-editable text.
3381 frame->executeScript(WebScriptSource("selectElement('editable_1');"));
3382 EXPECT_EQ("Editable 1.", selectionAsString(frame));
3383 frame->selectRange(topLeft(elementBounds(frame, "editable_1")), bottomRightMinusOne(elementBounds(frame, "footer_1")));
3384 // positionForPoint returns the wrong values for contenteditable spans. See
3385 // http://crbug.com/238334.
3386 // EXPECT_EQ("Editable 1. Editable 2. ]", selectionAsString(frame));
3389 static int computeOffset(WebCore::RenderObject* renderer, int x, int y)
3391 return WebCore::VisiblePosition(renderer->positionForPoint(WebCore::LayoutPoint(x, y))).deepEquivalent().computeOffsetInContainerNode();
3394 // positionForPoint returns the wrong values for contenteditable spans. See
3395 // http://crbug.com/238334.
3396 TEST_F(WebFrameTest, DISABLED_PositionForPointTest)
3398 registerMockedHttpURLLoad("select_range_span_editable.html");
3399 FrameTestHelpers::WebViewHelper webViewHelper;
3400 initializeTextSelectionWebView(m_baseURL + "select_range_span_editable.html", &webViewHelper);
3401 WebFrameImpl* mainFrame = toWebFrameImpl(webViewHelper.webView()->mainFrame());
3402 WebCore::RenderObject* renderer = mainFrame->frame()->selection().rootEditableElement()->renderer();
3403 EXPECT_EQ(0, computeOffset(renderer, -1, -1));
3404 EXPECT_EQ(64, computeOffset(renderer, 1000, 1000));
3406 registerMockedHttpURLLoad("select_range_div_editable.html");
3407 initializeTextSelectionWebView(m_baseURL + "select_range_div_editable.html", &webViewHelper);
3408 mainFrame = toWebFrameImpl(webViewHelper.webView()->mainFrame());
3409 renderer = mainFrame->frame()->selection().rootEditableElement()->renderer();
3410 EXPECT_EQ(0, computeOffset(renderer, -1, -1));
3411 EXPECT_EQ(64, computeOffset(renderer, 1000, 1000));
3415 TEST_F(WebFrameTest, SelectRangeStaysHorizontallyAlignedWhenMoved)
3417 registerMockedHttpURLLoad("move_caret.html");
3419 FrameTestHelpers::WebViewHelper webViewHelper;
3420 initializeTextSelectionWebView(m_baseURL + "move_caret.html", &webViewHelper);
3421 WebFrameImpl* frame = toWebFrameImpl(webViewHelper.webView()->mainFrame());
3423 WebRect initialStartRect;
3424 WebRect initialEndRect;
3428 frame->executeScript(WebScriptSource("selectRange();"));
3429 webViewHelper.webView()->selectionBounds(initialStartRect, initialEndRect);
3430 WebPoint movedStart(topLeft(initialStartRect));
3433 frame->selectRange(movedStart, bottomRightMinusOne(initialEndRect));
3434 webViewHelper.webView()->selectionBounds(startRect, endRect);
3435 EXPECT_EQ(startRect, initialStartRect);
3436 EXPECT_EQ(endRect, initialEndRect);
3439 frame->selectRange(movedStart, bottomRightMinusOne(initialEndRect));
3440 webViewHelper.webView()->selectionBounds(startRect, endRect);
3441 EXPECT_EQ(startRect, initialStartRect);
3442 EXPECT_EQ(endRect, initialEndRect);
3444 WebPoint movedEnd(bottomRightMinusOne(initialEndRect));
3447 frame->selectRange(topLeft(initialStartRect), movedEnd);
3448 webViewHelper.webView()->selectionBounds(startRect, endRect);
3449 EXPECT_EQ(startRect, initialStartRect);
3450 EXPECT_EQ(endRect, initialEndRect);
3453 frame->selectRange(topLeft(initialStartRect), movedEnd);
3454 webViewHelper.webView()->selectionBounds(startRect, endRect);
3455 EXPECT_EQ(startRect, initialStartRect);
3456 EXPECT_EQ(endRect, initialEndRect);
3459 TEST_F(WebFrameTest, MoveCaretStaysHorizontallyAlignedWhenMoved)
3461 WebFrameImpl* frame;
3462 registerMockedHttpURLLoad("move_caret.html");
3464 FrameTestHelpers::WebViewHelper webViewHelper;
3465 initializeTextSelectionWebView(m_baseURL + "move_caret.html", &webViewHelper);
3466 frame = (WebFrameImpl*)webViewHelper.webView()->mainFrame();
3468 WebRect initialStartRect;
3469 WebRect initialEndRect;
3473 frame->executeScript(WebScriptSource("selectCaret();"));
3474 webViewHelper.webView()->selectionBounds(initialStartRect, initialEndRect);
3475 WebPoint moveTo(topLeft(initialStartRect));
3478 frame->moveCaretSelectionTowardsWindowPoint(moveTo);
3479 webViewHelper.webView()->selectionBounds(startRect, endRect);
3480 EXPECT_EQ(startRect, initialStartRect);
3481 EXPECT_EQ(endRect, initialEndRect);
3484 frame->moveCaretSelectionTowardsWindowPoint(moveTo);
3485 webViewHelper.webView()->selectionBounds(startRect, endRect);
3486 EXPECT_EQ(startRect, initialStartRect);
3487 EXPECT_EQ(endRect, initialEndRect);
3491 class DisambiguationPopupTestWebViewClient : public WebViewClient {
3493 virtual bool didTapMultipleTargets(const WebGestureEvent&, const WebVector<WebRect>& targetRects) OVERRIDE
3495 EXPECT_GE(targetRects.size(), 2u);
3500 bool triggered() const { return m_triggered; }
3501 void resetTriggered() { m_triggered = false; }
3505 static WebGestureEvent fatTap(int x, int y)
3507 WebGestureEvent event;
3508 event.type = WebInputEvent::GestureTap;
3511 event.data.tap.width = 50;
3512 event.data.tap.height = 50;
3516 TEST_F(WebFrameTest, DisambiguationPopup)
3518 const std::string htmlFile = "disambiguation_popup.html";
3519 registerMockedHttpURLLoad(htmlFile);
3521 DisambiguationPopupTestWebViewClient client;
3523 // Make sure we initialize to minimum scale, even if the window size
3524 // only becomes available after the load begins.
3525 FrameTestHelpers::WebViewHelper webViewHelper;
3526 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client);
3527 webViewHelper.webView()->resize(WebSize(1000, 1000));
3528 webViewHelper.webView()->layout();
3530 client.resetTriggered();
3531 webViewHelper.webView()->handleInputEvent(fatTap(0, 0));
3532 EXPECT_FALSE(client.triggered());
3534 client.resetTriggered();
3535 webViewHelper.webView()->handleInputEvent(fatTap(200, 115));
3536 EXPECT_FALSE(client.triggered());
3538 for (int i = 0; i <= 46; i++) {
3539 client.resetTriggered();
3540 webViewHelper.webView()->handleInputEvent(fatTap(120, 230 + i * 5));
3543 if (j >= 7 && j <= 9)
3544 EXPECT_TRUE(client.triggered());
3546 EXPECT_FALSE(client.triggered());
3549 for (int i = 0; i <= 46; i++) {
3550 client.resetTriggered();
3551 webViewHelper.webView()->handleInputEvent(fatTap(10 + i * 5, 590));
3554 if (j >= 7 && j <= 9)
3555 EXPECT_TRUE(client.triggered());
3557 EXPECT_FALSE(client.triggered());
3561 TEST_F(WebFrameTest, DisambiguationPopupNoContainer)
3563 registerMockedHttpURLLoad("disambiguation_popup_no_container.html");
3565 DisambiguationPopupTestWebViewClient client;
3567 // Make sure we initialize to minimum scale, even if the window size
3568 // only becomes available after the load begins.
3569 FrameTestHelpers::WebViewHelper webViewHelper;
3570 webViewHelper.initializeAndLoad(m_baseURL + "disambiguation_popup_no_container.html", true, 0, &client);
3571 webViewHelper.webView()->resize(WebSize(1000, 1000));
3572 webViewHelper.webView()->layout();
3574 client.resetTriggered();
3575 webViewHelper.webView()->handleInputEvent(fatTap(50, 50));
3576 EXPECT_FALSE(client.triggered());
3579 TEST_F(WebFrameTest, DisambiguationPopupMobileSite)
3581 UseMockScrollbarSettings mockScrollbarSettings;
3582 const std::string htmlFile = "disambiguation_popup_mobile_site.html";
3583 registerMockedHttpURLLoad(htmlFile);
3585 DisambiguationPopupTestWebViewClient client;
3587 // Make sure we initialize to minimum scale, even if the window size
3588 // only becomes available after the load begins.
3589 FrameTestHelpers::WebViewHelper webViewHelper;
3590 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client);
3591 webViewHelper.webView()->settings()->setViewportEnabled(true);
3592 webViewHelper.webView()->resize(WebSize(1000, 1000));
3593 webViewHelper.webView()->layout();
3595 client.resetTriggered();
3596 webViewHelper.webView()->handleInputEvent(fatTap(0, 0));
3597 EXPECT_FALSE(client.triggered());
3599 client.resetTriggered();
3600 webViewHelper.webView()->handleInputEvent(fatTap(200, 115));
3601 EXPECT_FALSE(client.triggered());
3603 for (int i = 0; i <= 46; i++) {
3604 client.resetTriggered();
3605 webViewHelper.webView()->handleInputEvent(fatTap(120, 230 + i * 5));
3606 EXPECT_FALSE(client.triggered());
3609 for (int i = 0; i <= 46; i++) {
3610 client.resetTriggered();
3611 webViewHelper.webView()->handleInputEvent(fatTap(10 + i * 5, 590));
3612 EXPECT_FALSE(client.triggered());
3616 TEST_F(WebFrameTest, DisambiguationPopupViewportSite)
3618 UseMockScrollbarSettings mockScrollbarSettings;
3619 const std::string htmlFile = "disambiguation_popup_viewport_site.html";
3620 registerMockedHttpURLLoad(htmlFile);
3622 DisambiguationPopupTestWebViewClient client;
3624 // Make sure we initialize to minimum scale, even if the window size
3625 // only becomes available after the load begins.
3626 FrameTestHelpers::WebViewHelper webViewHelper;
3627 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client);
3628 webViewHelper.webView()->settings()->setViewportEnabled(true);
3629 webViewHelper.webView()->resize(WebSize(1000, 1000));
3630 webViewHelper.webView()->layout();
3632 client.resetTriggered();
3633 webViewHelper.webView()->handleInputEvent(fatTap(0, 0));
3634 EXPECT_FALSE(client.triggered());
3636 client.resetTriggered();
3637 webViewHelper.webView()->handleInputEvent(fatTap(200, 115));
3638 EXPECT_FALSE(client.triggered());
3640 for (int i = 0; i <= 46; i++) {
3641 client.resetTriggered();
3642 webViewHelper.webView()->handleInputEvent(fatTap(120, 230 + i * 5));
3643 EXPECT_FALSE(client.triggered());
3646 for (int i = 0; i <= 46; i++) {
3647 client.resetTriggered();
3648 webViewHelper.webView()->handleInputEvent(fatTap(10 + i * 5, 590));
3649 EXPECT_FALSE(client.triggered());
3653 TEST_F(WebFrameTest, DisambiguationPopupBlacklist)
3655 const unsigned viewportWidth = 500;
3656 const unsigned viewportHeight = 1000;
3657 const unsigned divHeight = 100;
3658 const std::string htmlFile = "disambiguation_popup_blacklist.html";
3659 registerMockedHttpURLLoad(htmlFile);
3661 DisambiguationPopupTestWebViewClient client;
3663 // Make sure we initialize to minimum scale, even if the window size
3664 // only becomes available after the load begins.
3665 FrameTestHelpers::WebViewHelper webViewHelper;
3666 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client);
3667 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
3668 webViewHelper.webView()->layout();
3670 // Click somewhere where the popup shouldn't appear.
3671 client.resetTriggered();
3672 webViewHelper.webView()->handleInputEvent(fatTap(viewportWidth / 2, 0));
3673 EXPECT_FALSE(client.triggered());
3675 // Click directly in between two container divs with click handlers, with children that don't handle clicks.
3676 client.resetTriggered();
3677 webViewHelper.webView()->handleInputEvent(fatTap(viewportWidth / 2, divHeight));
3678 EXPECT_TRUE(client.triggered());
3680 // The third div container should be blacklisted if you click on the link it contains.
3681 client.resetTriggered();
3682 webViewHelper.webView()->handleInputEvent(fatTap(viewportWidth / 2, divHeight * 3.25));
3683 EXPECT_FALSE(client.triggered());
3686 TEST_F(WebFrameTest, DisambiguationPopupPageScale)
3688 registerMockedHttpURLLoad("disambiguation_popup_page_scale.html");
3690 DisambiguationPopupTestWebViewClient client;
3692 // Make sure we initialize to minimum scale, even if the window size
3693 // only becomes available after the load begins.
3694 FrameTestHelpers::WebViewHelper webViewHelper;
3695 webViewHelper.initializeAndLoad(m_baseURL + "disambiguation_popup_page_scale.html", true, 0, &client);
3696 webViewHelper.webView()->resize(WebSize(1000, 1000));
3697 webViewHelper.webView()->layout();
3699 client.resetTriggered();
3700 webViewHelper.webView()->handleInputEvent(fatTap(80, 80));
3701 EXPECT_TRUE(client.triggered());
3703 client.resetTriggered();
3704 webViewHelper.webView()->handleInputEvent(fatTap(230, 190));
3705 EXPECT_TRUE(client.triggered());
3707 webViewHelper.webView()->setPageScaleFactor(3.0f, WebPoint(0, 0));
3708 webViewHelper.webView()->layout();
3710 client.resetTriggered();
3711 webViewHelper.webView()->handleInputEvent(fatTap(240, 240));
3712 EXPECT_TRUE(client.triggered());
3714 client.resetTriggered();
3715 webViewHelper.webView()->handleInputEvent(fatTap(690, 570));
3716 EXPECT_FALSE(client.triggered());
3719 class TestSubstituteDataWebFrameClient : public WebFrameClient {
3721 TestSubstituteDataWebFrameClient()
3722 : m_commitCalled(false)
3726 virtual void didFailProvisionalLoad(WebFrame* frame, const WebURLError& error)
3728 frame->loadHTMLString("This should appear", toKURL("data:text/html,chromewebdata"), error.unreachableURL, true);
3732 virtual void didCommitProvisionalLoad(WebFrame* frame, bool)
3734 if (frame->dataSource()->response().url() != WebURL(URLTestHelpers::toKURL("about:blank")))
3735 m_commitCalled = true;
3738 bool commitCalled() const { return m_commitCalled; }
3741 bool m_commitCalled;
3744 TEST_F(WebFrameTest, ReplaceNavigationAfterHistoryNavigation)
3746 TestSubstituteDataWebFrameClient webFrameClient;
3748 FrameTestHelpers::WebViewHelper webViewHelper;
3749 webViewHelper.initializeAndLoad("about:blank", true, &webFrameClient);
3751 WebFrame* frame = webViewHelper.webView()->mainFrame();
3753 // Load a url as a history navigation that will return an error. TestSubstituteDataWebFrameClient
3754 // will start a SubstituteData load in response to the load failure, which should get fully committed.
3755 // Due to https://bugs.webkit.org/show_bug.cgi?id=91685, FrameLoader::didReceiveData() wasn't getting
3756 // called in this case, which resulted in the SubstituteData document not getting displayed.
3758 error.reason = 1337;
3759 error.domain = "WebFrameTest";
3760 std::string errorURL = "http://0.0.0.0";
3761 WebURLResponse response;
3762 response.initialize();
3763 response.setURL(URLTestHelpers::toKURL(errorURL));
3764 response.setMIMEType("text/html");
3765 response.setHTTPStatusCode(500);
3766 WebHistoryItem errorHistoryItem;
3767 errorHistoryItem.initialize();
3768 errorHistoryItem.setURLString(WebString::fromUTF8(errorURL.c_str(), errorURL.length()));
3769 errorHistoryItem.setOriginalURLString(WebString::fromUTF8(errorURL.c_str(), errorURL.length()));
3770 Platform::current()->unitTestSupport()->registerMockedErrorURL(URLTestHelpers::toKURL(errorURL), response, error);
3771 frame->loadHistoryItem(errorHistoryItem);
3772 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
3774 WebString text = frame->contentAsText(std::numeric_limits<size_t>::max());
3775 EXPECT_EQ("This should appear", text.utf8());
3776 EXPECT_TRUE(webFrameClient.commitCalled());
3779 class TestWillInsertBodyWebFrameClient : public WebFrameClient {
3781 TestWillInsertBodyWebFrameClient() : m_numBodies(0), m_didLoad(false)
3785 virtual void didCommitProvisionalLoad(WebFrame*, bool) OVERRIDE
3791 virtual void didCreateDocumentElement(WebFrame*) OVERRIDE
3793 EXPECT_EQ(0, m_numBodies);
3796 virtual void willInsertBody(WebFrame*) OVERRIDE
3805 TEST_F(WebFrameTest, HTMLDocument)
3807 registerMockedHttpURLLoad("clipped-body.html");
3809 TestWillInsertBodyWebFrameClient webFrameClient;
3810 FrameTestHelpers::WebViewHelper webViewHelper;
3811 webViewHelper.initializeAndLoad(m_baseURL + "clipped-body.html", false, &webFrameClient);
3813 EXPECT_TRUE(webFrameClient.m_didLoad);
3814 EXPECT_EQ(1, webFrameClient.m_numBodies);
3817 TEST_F(WebFrameTest, EmptyDocument)
3819 registerMockedHttpURLLoad("pageserializer/green_rectangle.svg");
3821 TestWillInsertBodyWebFrameClient webFrameClient;
3822 FrameTestHelpers::WebViewHelper webViewHelper;
3823 webViewHelper.initialize(false, &webFrameClient);
3825 EXPECT_FALSE(webFrameClient.m_didLoad);
3826 EXPECT_EQ(1, webFrameClient.m_numBodies); // The empty document that a new frame starts with triggers this.
3829 TEST_F(WebFrameTest, MoveCaretSelectionTowardsWindowPointWithNoSelection)
3831 FrameTestHelpers::WebViewHelper webViewHelper;
3832 webViewHelper.initializeAndLoad("about:blank", true);
3833 WebFrame* frame = webViewHelper.webView()->mainFrame();
3835 // This test passes if this doesn't crash.
3836 frame->moveCaretSelectionTowardsWindowPoint(WebPoint(0, 0));
3839 class SpellCheckClient : public WebSpellCheckClient {
3841 explicit SpellCheckClient(uint32_t hash = 0) : m_numberOfTimesChecked(0), m_hash(hash) { }
3842 virtual ~SpellCheckClient() { }
3843 virtual void requestCheckingOfText(const WebKit::WebString&, const WebKit::WebVector<uint32_t>&, const WebKit::WebVector<unsigned>&, WebKit::WebTextCheckingCompletion* completion) OVERRIDE
3845 ++m_numberOfTimesChecked;
3846 Vector<WebTextCheckingResult> results;
3847 const int misspellingStartOffset = 1;
3848 const int misspellingLength = 8;
3849 results.append(WebTextCheckingResult(WebTextDecorationTypeSpelling, misspellingStartOffset, misspellingLength, WebString(), m_hash));
3850 completion->didFinishCheckingText(results);
3852 int numberOfTimesChecked() const { return m_numberOfTimesChecked; }
3854 int m_numberOfTimesChecked;
3858 TEST_F(WebFrameTest, ReplaceMisspelledRange)
3860 registerMockedHttpURLLoad("spell.html");
3861 FrameTestHelpers::WebViewHelper webViewHelper;
3862 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
3863 SpellCheckClient spellcheck;
3864 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
3866 WebFrameImpl* frame = toWebFrameImpl(webViewHelper.webView()->mainFrame());
3867 Document* document = frame->frame()->document();
3868 Element* element = document->getElementById("data");
3870 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
3871 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
3872 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
3875 document->execCommand("InsertText", false, "_wellcome_.");
3877 const int allTextBeginOffset = 0;
3878 const int allTextLength = 11;
3879 frame->selectRange(WebRange::fromDocumentRange(frame, allTextBeginOffset, allTextLength));
3880 RefPtr<Range> selectionRange = frame->frame()->selection().toNormalizedRange();
3882 EXPECT_EQ(1, spellcheck.numberOfTimesChecked());
3883 EXPECT_EQ(1U, document->markers()->markersInRange(selectionRange.get(), DocumentMarker::Spelling).size());
3885 frame->replaceMisspelledRange("welcome");
3886 EXPECT_EQ("_welcome_.", frame->contentAsText(std::numeric_limits<size_t>::max()).utf8());
3889 TEST_F(WebFrameTest, RemoveSpellingMarkers)
3891 registerMockedHttpURLLoad("spell.html");
3892 FrameTestHelpers::WebViewHelper webViewHelper;
3893 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
3894 SpellCheckClient spellcheck;
3895 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
3897 WebFrameImpl* frame = toWebFrameImpl(webViewHelper.webView()->mainFrame());
3898 Document* document = frame->frame()->document();
3899 Element* element = document->getElementById("data");
3901 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
3902 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
3903 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
3906 document->execCommand("InsertText", false, "_wellcome_.");
3908 frame->removeSpellingMarkers();
3910 const int allTextBeginOffset = 0;
3911 const int allTextLength = 11;
3912 frame->selectRange(WebRange::fromDocumentRange(frame, allTextBeginOffset, allTextLength));
3913 RefPtr<Range> selectionRange = frame->frame()->selection().toNormalizedRange();
3915 EXPECT_EQ(0U, document->markers()->markersInRange(selectionRange.get(), DocumentMarker::Spelling).size());
3918 TEST_F(WebFrameTest, MarkerHashIdentifiers) {
3919 registerMockedHttpURLLoad("spell.html");
3920 FrameTestHelpers::WebViewHelper webViewHelper;
3921 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
3923 static const uint32_t kHash = 42;
3924 SpellCheckClient spellcheck(kHash);
3925 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
3927 WebFrameImpl* frame = toWebFrameImpl(webViewHelper.webView()->mainFrame());
3928 Document* document = frame->frame()->document();
3929 Element* element = document->getElementById("data");
3931 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
3932 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
3933 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
3936 document->execCommand("InsertText", false, "wellcome.");
3938 WebVector<uint32_t> documentMarkers;
3939 webViewHelper.webView()->spellingMarkers(&documentMarkers);
3940 EXPECT_EQ(1U, documentMarkers.size());
3941 EXPECT_EQ(kHash, documentMarkers[0]);
3944 class StubbornSpellCheckClient : public WebSpellCheckClient {
3946 StubbornSpellCheckClient() : m_completion(0) { }
3947 virtual ~StubbornSpellCheckClient() { }
3949 virtual void requestCheckingOfText(
3950 const WebKit::WebString&,
3951 const WebKit::WebVector<uint32_t>&,
3952 const WebKit::WebVector<unsigned>&,
3953 WebKit::WebTextCheckingCompletion* completion) OVERRIDE
3955 m_completion = completion;
3958 void kickNoResults()
3960 kick(-1, -1, WebTextDecorationTypeSpelling);
3965 kick(1, 8, WebTextDecorationTypeSpelling);
3970 kick(1, 8, WebTextDecorationTypeGrammar);
3973 void kickInvisibleSpellcheck()
3975 kick(1, 8, WebTextDecorationTypeInvisibleSpellcheck);
3979 void kick(int misspellingStartOffset, int misspellingLength, WebTextDecorationType type)
3983 Vector<WebTextCheckingResult> results;
3984 if (misspellingStartOffset >= 0 && misspellingLength > 0)
3985 results.append(WebTextCheckingResult(type, misspellingStartOffset, misspellingLength));
3986 m_completion->didFinishCheckingText(results);
3990 WebKit::WebTextCheckingCompletion* m_completion;
3993 TEST_F(WebFrameTest, SlowSpellcheckMarkerPosition)
3995 registerMockedHttpURLLoad("spell.html");
3996 FrameTestHelpers::WebViewHelper webViewHelper;
3997 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
3999 StubbornSpellCheckClient spellcheck;
4000 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4002 WebFrameImpl* frame = toWebFrameImpl(webViewHelper.webView()->mainFrame());
4003 WebInputElement webInputElement = frame->document().getElementById("data").to<WebInputElement>();
4004 Document* document = frame->frame()->document();
4005 Element* element = document->getElementById("data");
4007 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4008 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4009 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4012 document->execCommand("InsertText", false, "wellcome ");
4013 webInputElement.setSelectionRange(0, 0);
4014 document->execCommand("InsertText", false, "he");
4018 WebVector<uint32_t> documentMarkers;
4019 webViewHelper.webView()->spellingMarkers(&documentMarkers);
4020 EXPECT_EQ(0U, documentMarkers.size());
4023 // This test verifies that cancelling spelling request does not cause a
4024 // write-after-free when there's no spellcheck client set.
4025 TEST_F(WebFrameTest, CancelSpellingRequestCrash)
4027 registerMockedHttpURLLoad("spell.html");
4028 FrameTestHelpers::WebViewHelper webViewHelper;
4029 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4030 webViewHelper.webView()->setSpellCheckClient(0);
4032 WebFrameImpl* frame = toWebFrameImpl(webViewHelper.webView()->mainFrame());
4033 Document* document = frame->frame()->document();
4034 Element* element = document->getElementById("data");
4036 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4037 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4038 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4041 frame->frame()->editor().replaceSelectionWithText("A", false, false);
4042 frame->frame()->spellChecker().cancelCheck();
4045 TEST_F(WebFrameTest, SpellcheckResultErasesMarkers)
4047 registerMockedHttpURLLoad("spell.html");
4048 FrameTestHelpers::WebViewHelper webViewHelper;
4049 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4051 StubbornSpellCheckClient spellcheck;
4052 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4054 WebFrameImpl* frame = toWebFrameImpl(webViewHelper.webView()->mainFrame());
4055 WebInputElement webInputElement = frame->document().getElementById("data").to<WebInputElement>();
4056 Document* document = frame->frame()->document();
4057 Element* element = document->getElementById("data");
4059 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4060 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4061 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4064 document->execCommand("InsertText", false, "welcome ");
4065 document->markers()->addMarker(rangeOfContents(element->toNode()).get(), DocumentMarker::Spelling);
4066 document->markers()->addMarker(rangeOfContents(element->toNode()).get(), DocumentMarker::Grammar);
4067 document->markers()->addMarker(rangeOfContents(element->toNode()).get(), DocumentMarker::InvisibleSpellcheck);
4068 EXPECT_EQ(3U, document->markers()->markers().size());
4070 spellcheck.kickNoResults();
4071 EXPECT_EQ(0U, document->markers()->markers().size());
4074 TEST_F(WebFrameTest, SpellcheckResultsSavedInDocument)
4076 registerMockedHttpURLLoad("spell.html");
4077 FrameTestHelpers::WebViewHelper webViewHelper;
4078 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4080 StubbornSpellCheckClient spellcheck;
4081 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4083 WebFrameImpl* frame = toWebFrameImpl(webViewHelper.webView()->mainFrame());
4084 WebInputElement webInputElement = frame->document().getElementById("data").to<WebInputElement>();
4085 Document* document = frame->frame()->document();
4086 Element* element = document->getElementById("data");
4088 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4089 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4090 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4093 document->execCommand("InsertText", false, "wellcome ");
4096 ASSERT_EQ(1U, document->markers()->markers().size());
4097 ASSERT_NE(static_cast<DocumentMarker*>(0), document->markers()->markers()[0]);
4098 EXPECT_EQ(DocumentMarker::Spelling, document->markers()->markers()[0]->type());
4100 document->execCommand("InsertText", false, "wellcome ");
4102 spellcheck.kickGrammar();
4103 ASSERT_EQ(1U, document->markers()->markers().size());
4104 ASSERT_NE(static_cast<DocumentMarker*>(0), document->markers()->markers()[0]);
4105 EXPECT_EQ(DocumentMarker::Grammar, document->markers()->markers()[0]->type());
4107 document->execCommand("InsertText", false, "wellcome ");
4109 spellcheck.kickInvisibleSpellcheck();
4110 ASSERT_EQ(1U, document->markers()->markers().size());
4111 ASSERT_NE(static_cast<DocumentMarker*>(0), document->markers()->markers()[0]);
4112 EXPECT_EQ(DocumentMarker::InvisibleSpellcheck, document->markers()->markers()[0]->type());
4115 class TestAccessInitialDocumentWebFrameClient : public WebFrameClient {
4117 TestAccessInitialDocumentWebFrameClient() : m_didAccessInitialDocument(false)
4121 virtual void didAccessInitialDocument(WebFrame* frame)
4123 EXPECT_TRUE(!m_didAccessInitialDocument);
4124 m_didAccessInitialDocument = true;
4127 bool m_didAccessInitialDocument;
4130 TEST_F(WebFrameTest, DidAccessInitialDocumentBody)
4132 TestAccessInitialDocumentWebFrameClient webFrameClient;
4133 FrameTestHelpers::WebViewHelper webViewHelper;
4134 webViewHelper.initialize(true, &webFrameClient);
4136 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4138 // Create another window that will try to access it.
4139 FrameTestHelpers::WebViewHelper newWebViewHelper;
4140 WebView* newView = newWebViewHelper.initialize(true);
4141 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
4143 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4145 // Access the initial document by modifying the body.
4146 newView->mainFrame()->executeScript(
4147 WebScriptSource("window.opener.document.body.innerHTML += 'Modified';"));
4149 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4151 // Access the initial document again, to ensure we don't notify twice.
4152 newView->mainFrame()->executeScript(
4153 WebScriptSource("window.opener.document.body.innerHTML += 'Modified';"));
4155 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4158 TEST_F(WebFrameTest, DidAccessInitialDocumentNavigator)
4160 TestAccessInitialDocumentWebFrameClient webFrameClient;
4161 FrameTestHelpers::WebViewHelper webViewHelper;
4162 webViewHelper.initialize(true, &webFrameClient);
4164 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4166 // Create another window that will try to access it.
4167 FrameTestHelpers::WebViewHelper newWebViewHelper;
4168 WebView* newView = newWebViewHelper.initialize(true);
4169 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
4171 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4173 // Access the initial document to get to the navigator object.
4174 newView->mainFrame()->executeScript(
4175 WebScriptSource("console.log(window.opener.navigator);"));
4177 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4180 TEST_F(WebFrameTest, DidAccessInitialDocumentViaJavascriptUrl)
4182 TestAccessInitialDocumentWebFrameClient webFrameClient;
4183 FrameTestHelpers::WebViewHelper webViewHelper;
4184 webViewHelper.initialize(true, &webFrameClient);
4186 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4188 // Access the initial document from a javascript: URL.
4189 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.appendChild(document.createTextNode('Modified'))");
4191 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4194 // Fails on the WebKit XP (deps) bot. http://crbug.com/312192
4196 TEST_F(WebFrameTest, DISABLED_DidAccessInitialDocumentBodyBeforeModalDialog)
4198 TEST_F(WebFrameTest, DidAccessInitialDocumentBodyBeforeModalDialog)
4201 TestAccessInitialDocumentWebFrameClient webFrameClient;
4202 FrameTestHelpers::WebViewHelper webViewHelper;
4203 webViewHelper.initialize(true, &webFrameClient);
4205 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4207 // Create another window that will try to access it.
4208 FrameTestHelpers::WebViewHelper newWebViewHelper;
4209 WebView* newView = newWebViewHelper.initialize(true);
4210 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
4212 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4214 // Access the initial document by modifying the body. We normally set a
4215 // timer to notify the client.
4216 newView->mainFrame()->executeScript(
4217 WebScriptSource("window.opener.document.body.innerHTML += 'Modified';"));
4218 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4220 // Make sure that a modal dialog forces us to notify right away.
4221 newView->mainFrame()->executeScript(
4222 WebScriptSource("window.opener.confirm('Modal');"));
4223 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4225 // Ensure that we don't notify again later.
4227 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4230 class TestMainFrameUserOrProgrammaticScrollFrameClient : public WebFrameClient {
4232 TestMainFrameUserOrProgrammaticScrollFrameClient() { reset(); }
4235 m_didScrollMainFrame = false;
4236 m_wasProgrammaticScroll = false;
4238 bool wasUserScroll() const { return m_didScrollMainFrame && !m_wasProgrammaticScroll; }
4239 bool wasProgrammaticScroll() const { return m_didScrollMainFrame && m_wasProgrammaticScroll; }
4242 virtual void didChangeScrollOffset(WebFrame* frame) OVERRIDE
4244 if (frame->parent())
4246 EXPECT_FALSE(m_didScrollMainFrame);
4247 WebCore::FrameView* view = toWebFrameImpl(frame)->frameView();
4248 // FrameView can be scrolled in FrameView::setFixedVisibleContentRect
4249 // which is called from Frame::createView (before the frame is associated
4250 // with the the view).
4252 m_didScrollMainFrame = true;
4253 m_wasProgrammaticScroll = view->inProgrammaticScroll();
4257 bool m_didScrollMainFrame;
4258 bool m_wasProgrammaticScroll;
4261 TEST_F(WebFrameTest, CompositorScrollIsUserScrollLongPage)
4263 registerMockedHttpURLLoad("long_scroll.html");
4264 TestMainFrameUserOrProgrammaticScrollFrameClient client;
4266 // Make sure we initialize to minimum scale, even if the window size
4267 // only becomes available after the load begins.
4268 FrameTestHelpers::WebViewHelper webViewHelper;
4269 webViewHelper.initializeAndLoad(m_baseURL + "long_scroll.html", true, &client);
4270 webViewHelper.webView()->resize(WebSize(1000, 1000));
4271 webViewHelper.webView()->layout();
4273 EXPECT_FALSE(client.wasUserScroll());
4274 EXPECT_FALSE(client.wasProgrammaticScroll());
4276 // Do a compositor scroll, verify that this is counted as a user scroll.
4277 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(0, 1), 1.1f);
4278 EXPECT_TRUE(client.wasUserScroll());
4281 EXPECT_FALSE(client.wasUserScroll());
4282 EXPECT_FALSE(client.wasProgrammaticScroll());
4284 // The page scale 1.0f and scroll.
4285 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(0, 1), 1.0f);
4286 EXPECT_TRUE(client.wasUserScroll());
4289 // No scroll event if there is no scroll delta.
4290 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.0f);
4291 EXPECT_FALSE(client.wasUserScroll());
4292 EXPECT_FALSE(client.wasProgrammaticScroll());
4295 // Non zero page scale and scroll.
4296 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(9, 13), 0.6f);
4297 EXPECT_TRUE(client.wasUserScroll());
4300 // Programmatic scroll.
4301 WebFrameImpl* frameImpl = webViewHelper.webViewImpl()->mainFrameImpl();
4302 frameImpl->executeScript(WebScriptSource("window.scrollTo(0, 20);"));
4303 EXPECT_FALSE(client.wasUserScroll());
4304 EXPECT_TRUE(client.wasProgrammaticScroll());
4307 // Programmatic scroll to same offset. No scroll event should be generated.
4308 frameImpl->executeScript(WebScriptSource("window.scrollTo(0, 20);"));
4309 EXPECT_FALSE(client.wasProgrammaticScroll());
4310 EXPECT_FALSE(client.wasUserScroll());
4314 TEST_F(WebFrameTest, CompositorScrollIsUserScrollShortPage)
4316 registerMockedHttpURLLoad("short_scroll.html");
4318 TestMainFrameUserOrProgrammaticScrollFrameClient client;
4320 // Short page tests.
4321 FrameTestHelpers::WebViewHelper webViewHelper;
4322 webViewHelper.initializeAndLoad(m_baseURL + "short_scroll.html", true, &client);
4324 webViewHelper.webView()->resize(WebSize(1000, 1000));
4325 webViewHelper.webView()->layout();
4327 EXPECT_FALSE(client.wasUserScroll());
4328 EXPECT_FALSE(client.wasProgrammaticScroll());
4330 // Non zero page scale and scroll.
4331 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(9, 13), 2.0f);
4332 EXPECT_FALSE(client.wasProgrammaticScroll());
4333 EXPECT_TRUE(client.wasUserScroll());
4337 TEST_F(WebFrameTest, FirstPartyForCookiesForRedirect)
4339 WTF::String filePath = Platform::current()->unitTestSupport()->webKitRootDir();
4340 filePath.append("/Source/web/tests/data/first_party.html");
4342 WebURL testURL(toKURL("http://www.test.com/first_party_redirect.html"));
4343 char redirect[] = "http://www.test.com/first_party.html";
4344 WebURL redirectURL(toKURL(redirect));
4345 WebURLResponse redirectResponse;
4346 redirectResponse.initialize();
4347 redirectResponse.setMIMEType("text/html");
4348 redirectResponse.setHTTPStatusCode(302);
4349 redirectResponse.setHTTPHeaderField("Location", redirect);
4350 Platform::current()->unitTestSupport()->registerMockedURL(testURL, redirectResponse, filePath);
4352 WebURLResponse finalResponse;
4353 finalResponse.initialize();
4354 finalResponse.setMIMEType("text/html");
4355 Platform::current()->unitTestSupport()->registerMockedURL(redirectURL, finalResponse, filePath);
4357 FrameTestHelpers::WebViewHelper webViewHelper;
4358 webViewHelper.initializeAndLoad(m_baseURL + "first_party_redirect.html", true);
4359 EXPECT_TRUE(webViewHelper.webView()->mainFrame()->document().firstPartyForCookies() == redirectURL);
4362 class TestNavigationPolicyWebFrameClient : public WebFrameClient {
4365 virtual void didNavigateWithinPage(WebFrame*, bool)
4371 TEST_F(WebFrameTest, SimulateFragmentAnchorMiddleClick)
4373 registerMockedHttpURLLoad("fragment_middle_click.html");
4374 TestNavigationPolicyWebFrameClient client;
4375 FrameTestHelpers::WebViewHelper webViewHelper;
4376 webViewHelper.initializeAndLoad(m_baseURL + "fragment_middle_click.html", true, &client);
4378 WebCore::Document* document = webViewHelper.webViewImpl()->page()->mainFrame()->document();
4379 WebCore::KURL destination = document->url();
4380 destination.setFragmentIdentifier("test");
4382 RefPtr<WebCore::Event> event = WebCore::MouseEvent::create(WebCore::EventTypeNames::click, false, false,
4383 document->domWindow(), 0, 0, 0, 0, 0, 0, 0, false, false, false, false, 1, 0, 0);
4384 WebCore::FrameLoadRequest frameRequest(document->securityOrigin(), WebCore::ResourceRequest(destination));
4385 frameRequest.setTriggeringEvent(event);
4386 webViewHelper.webViewImpl()->page()->mainFrame()->loader().load(frameRequest);
4389 TEST_F(WebFrameTest, BackToReload)
4391 registerMockedHttpURLLoad("fragment_middle_click.html");
4392 FrameTestHelpers::WebViewHelper webViewHelper;
4393 webViewHelper.initializeAndLoad(m_baseURL + "fragment_middle_click.html", true);
4394 WebFrame* frame = webViewHelper.webView()->mainFrame();
4395 WebHistoryItem firstItem = frame->currentHistoryItem();
4396 EXPECT_FALSE(firstItem.isNull());
4398 registerMockedHttpURLLoad("white-1x1.png");
4399 FrameTestHelpers::loadFrame(frame, m_baseURL + "white-1x1.png");
4400 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4401 EXPECT_FALSE(frame->previousHistoryItem().isNull());
4402 EXPECT_EQ(firstItem.urlString(), frame->previousHistoryItem().urlString());
4404 frame->loadHistoryItem(frame->previousHistoryItem());
4405 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4406 EXPECT_EQ(firstItem.urlString(), frame->currentHistoryItem().urlString());
4409 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4410 EXPECT_EQ(WebURLRequest::ReloadIgnoringCacheData, frame->dataSource()->request().cachePolicy());
4413 TEST_F(WebFrameTest, ReloadPost)
4415 registerMockedHttpURLLoad("reload_post.html");
4416 FrameTestHelpers::WebViewHelper webViewHelper;
4417 webViewHelper.initializeAndLoad(m_baseURL + "reload_post.html", true);
4418 WebFrame* frame = webViewHelper.webView()->mainFrame();
4420 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.forms[0].submit()");
4422 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4423 EXPECT_FALSE(frame->previousHistoryItem().isNull());
4424 EXPECT_EQ(WebString::fromUTF8("POST"), frame->dataSource()->request().httpMethod());
4427 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4428 EXPECT_EQ(WebURLRequest::ReloadIgnoringCacheData, frame->dataSource()->request().cachePolicy());
4429 EXPECT_EQ(WebNavigationTypeFormResubmitted, frame->dataSource()->navigationType());
4433 class TestCachePolicyWebFrameClient : public WebFrameClient {
4435 TestCachePolicyWebFrameClient()
4436 : m_policy(WebURLRequest::UseProtocolCachePolicy)
4438 , m_willSendRequestCallCount(0)
4439 , m_childFrameCreationCount(0)
4443 void setChildWebFrameClient(WebFrameClient* client) { m_client = client; }
4444 WebURLRequest::CachePolicy cachePolicy() const { return m_policy; }
4445 int willSendRequestCallCount() const { return m_willSendRequestCallCount; }
4446 int childFrameCreationCount() const { return m_childFrameCreationCount; }
4448 virtual WebFrame* createChildFrame(WebFrame*, const WebString&)
4450 m_childFrameCreationCount++;
4451 return WebFrame::create(m_client);
4454 virtual void willSendRequest(WebFrame* frame, unsigned, WebURLRequest& request, const WebURLResponse&)
4456 m_policy = request.cachePolicy();
4457 m_willSendRequestCallCount++;
4461 WebURLRequest::CachePolicy m_policy;
4462 WebFrameClient* m_client;
4463 int m_willSendRequestCallCount;
4464 int m_childFrameCreationCount;
4467 TEST_F(WebFrameTest, ReloadIframe)
4469 registerMockedHttpURLLoad("iframe_reload.html");
4470 registerMockedHttpURLLoad("visible_iframe.html");
4471 TestCachePolicyWebFrameClient mainClient;
4472 TestCachePolicyWebFrameClient childClient;
4473 mainClient.setChildWebFrameClient(&childClient);
4475 FrameTestHelpers::WebViewHelper webViewHelper;
4476 webViewHelper.initializeAndLoad(m_baseURL + "iframe_reload.html", true, &mainClient);
4478 WebFrameImpl* mainFrame = webViewHelper.webViewImpl()->mainFrameImpl();
4479 WebFrameImpl* childFrame = toWebFrameImpl(mainFrame->firstChild());
4480 ASSERT_EQ(childFrame->client(), &childClient);
4481 EXPECT_EQ(mainClient.childFrameCreationCount(), 1);
4482 EXPECT_EQ(childClient.willSendRequestCallCount(), 1);
4483 EXPECT_EQ(childClient.cachePolicy(), WebURLRequest::UseProtocolCachePolicy);
4485 mainFrame->reload(false);
4486 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4488 // A new WebFrame should have been created, but the child WebFrameClient should be reused.
4489 ASSERT_FALSE(childFrame == toWebFrameImpl(mainFrame->firstChild()));
4490 ASSERT_EQ(toWebFrameImpl(mainFrame->firstChild())->client(), &childClient);
4492 EXPECT_EQ(mainClient.childFrameCreationCount(), 2);
4493 EXPECT_EQ(childClient.willSendRequestCallCount(), 2);
4494 EXPECT_EQ(childClient.cachePolicy(), WebURLRequest::ReloadIgnoringCacheData);
4497 class TestSameDocumentWebFrameClient : public WebFrameClient {
4499 TestSameDocumentWebFrameClient()
4500 : m_frameLoadTypeSameSeen(false)
4504 virtual void willSendRequest(WebFrame* frame, unsigned, WebURLRequest&, const WebURLResponse&)
4506 if (toWebFrameImpl(frame)->frame()->loader().loadType() == WebCore::FrameLoadTypeSame)
4507 m_frameLoadTypeSameSeen = true;
4510 bool frameLoadTypeSameSeen() const { return m_frameLoadTypeSameSeen; }
4513 bool m_frameLoadTypeSameSeen;
4516 TEST_F(WebFrameTest, NavigateToSame)
4518 registerMockedHttpURLLoad("navigate_to_same.html");
4519 TestSameDocumentWebFrameClient client;
4520 FrameTestHelpers::WebViewHelper webViewHelper;
4521 webViewHelper.initializeAndLoad(m_baseURL + "navigate_to_same.html", true, &client);
4522 EXPECT_FALSE(client.frameLoadTypeSameSeen());
4524 WebCore::FrameLoadRequest frameRequest(0, WebCore::ResourceRequest(webViewHelper.webViewImpl()->page()->mainFrame()->document()->url()));
4525 webViewHelper.webViewImpl()->page()->mainFrame()->loader().load(frameRequest);
4526 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4528 EXPECT_TRUE(client.frameLoadTypeSameSeen());
4531 TEST_F(WebFrameTest, WebNodeImageContents)
4533 FrameTestHelpers::WebViewHelper webViewHelper;
4534 webViewHelper.initializeAndLoad("about:blank", true);
4535 WebFrame* frame = webViewHelper.webView()->mainFrame();
4537 static const char bluePNG[] = "<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAGElEQVQYV2NkYPj/n4EIwDiqEF8oUT94AFIQE/cCn90IAAAAAElFTkSuQmCC\">";
4539 // Load up the image and test that we can extract the contents.
4540 WebCore::KURL testURL = toKURL("about:blank");
4541 frame->loadHTMLString(bluePNG, testURL);
4544 WebNode node = frame->document().body().firstChild();
4545 EXPECT_TRUE(node.isElementNode());
4546 WebElement element = node.to<WebElement>();
4547 WebImage image = element.imageContents();
4548 ASSERT_FALSE(image.isNull());
4549 EXPECT_EQ(image.size().width, 10);
4550 EXPECT_EQ(image.size().height, 10);
4551 // FIXME: The rest of this test is disabled since the ImageDecodeCache state may be inconsistent when this test runs.
4553 // SkBitmap bitmap = image.getSkBitmap();
4554 // SkAutoLockPixels locker(bitmap);
4555 // EXPECT_EQ(bitmap.getColor(0, 0), SK_ColorBLUE);
4558 class TestStartStopCallbackWebViewClient : public WebViewClient {
4560 TestStartStopCallbackWebViewClient()
4561 : m_startLoadingCount(0)
4562 , m_stopLoadingCount(0)
4566 virtual void didStartLoading()
4568 m_startLoadingCount++;
4571 virtual void didStopLoading()
4573 m_stopLoadingCount++;
4576 int startLoadingCount() const { return m_startLoadingCount; }
4577 int stopLoadingCount() const { return m_stopLoadingCount; }
4580 int m_startLoadingCount;
4581 int m_stopLoadingCount;
4584 TEST_F(WebFrameTest, PushStateStartsAndStops)
4586 registerMockedHttpURLLoad("push_state.html");
4587 TestStartStopCallbackWebViewClient client;
4588 FrameTestHelpers::WebViewHelper webViewHelper;
4589 webViewHelper.initializeAndLoad(m_baseURL + "push_state.html", true, 0, &client);
4592 EXPECT_EQ(client.startLoadingCount(), 2);
4593 EXPECT_EQ(client.stopLoadingCount(), 2);
4596 class TestHistoryWebFrameClient : public WebFrameClient {
4598 TestHistoryWebFrameClient()
4600 m_replacesCurrentHistoryItem = false;
4603 void didStartProvisionalLoad(WebFrame* frame)
4605 WebDataSource* ds = frame->provisionalDataSource();
4606 m_replacesCurrentHistoryItem = ds->replacesCurrentHistoryItem();
4610 bool replacesCurrentHistoryItem() { return m_replacesCurrentHistoryItem; }
4611 WebFrame* frame() { return m_frame; }
4614 bool m_replacesCurrentHistoryItem;
4618 // Test which ensures that the first navigation in a subframe will always
4619 // result in history entry being replaced and not a new one added.
4620 TEST_F(WebFrameTest, DISABLED_FirstFrameNavigationReplacesHistory)
4622 registerMockedHttpURLLoad("history.html");
4623 registerMockedHttpURLLoad("find.html");
4625 FrameTestHelpers::WebViewHelper webViewHelper;
4626 TestHistoryWebFrameClient client;
4627 webViewHelper.initializeAndLoad("about:blank", true, &client);
4629 EXPECT_TRUE(client.replacesCurrentHistoryItem());
4631 WebFrame* frame = webViewHelper.webView()->mainFrame();
4633 FrameTestHelpers::loadFrame(frame,
4634 "javascript:document.body.appendChild(document.createElement('iframe'))");
4635 // Need to call runPendingTasks in order for the JavaScript above to be
4636 // evaluated and executed.
4638 WebFrame* iframe = frame->firstChild();
4639 EXPECT_EQ(client.frame(), iframe);
4640 EXPECT_TRUE(client.replacesCurrentHistoryItem());
4642 FrameTestHelpers::loadFrame(frame,
4643 "javascript:window.frames[0].location.assign('" + m_baseURL + "history.html')");
4645 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4646 EXPECT_EQ(client.frame(), iframe);
4647 EXPECT_TRUE(client.replacesCurrentHistoryItem());
4649 FrameTestHelpers::loadFrame(frame,
4650 "javascript:window.frames[0].location.assign('" + m_baseURL + "find.html')");
4652 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4653 EXPECT_EQ(client.frame(), iframe);
4654 EXPECT_FALSE(client.replacesCurrentHistoryItem());
4656 // Repeat the test, but start out the iframe with initial URL, which is not
4658 FrameTestHelpers::loadFrame(frame,
4659 "javascript:var f = document.createElement('iframe'); "
4660 "f.src = '" + m_baseURL + "history.html';"
4661 "document.body.appendChild(f)");
4663 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4665 iframe = frame->firstChild()->nextSibling();
4666 EXPECT_EQ(client.frame(), iframe);
4667 EXPECT_TRUE(client.replacesCurrentHistoryItem());
4669 FrameTestHelpers::loadFrame(frame,
4670 "javascript:window.frames[1].location.assign('" + m_baseURL + "find.html')");
4672 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4673 EXPECT_EQ(client.frame(), iframe);
4674 EXPECT_FALSE(client.replacesCurrentHistoryItem());