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/clipboard/Clipboard.h"
61 #include "core/dom/DocumentMarkerController.h"
62 #include "core/dom/Range.h"
63 #include "core/editing/Editor.h"
64 #include "core/editing/FrameSelection.h"
65 #include "core/editing/SpellChecker.h"
66 #include "core/editing/VisiblePosition.h"
67 #include "core/events/MouseEvent.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/frame/Settings.h"
74 #include "core/rendering/HitTestResult.h"
75 #include "core/rendering/RenderLayerCompositor.h"
76 #include "core/rendering/RenderView.h"
77 #include "core/rendering/TextAutosizer.h"
78 #include "platform/geometry/FloatRect.h"
79 #include "platform/network/ResourceError.h"
80 #include "platform/scroll/ScrollbarTheme.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 blink;
93 using WebCore::Document;
94 using WebCore::DocumentMarker;
95 using WebCore::Element;
96 using WebCore::FloatRect;
97 using WebCore::HitTestRequest;
99 using blink::URLTestHelpers::toKURL;
100 using blink::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 FakeCompositingWebViewClient : public WebViewClient {
114 virtual ~FakeCompositingWebViewClient()
118 virtual void initializeLayerTreeView() OVERRIDE
120 m_layerTreeView = adoptPtr(Platform::current()->unitTestSupport()->createLayerTreeViewForTesting(WebUnitTestSupport::TestViewTypeUnitTest));
121 ASSERT(m_layerTreeView);
124 virtual WebLayerTreeView* layerTreeView() OVERRIDE
126 return m_layerTreeView.get();
130 OwnPtr<WebLayerTreeView> m_layerTreeView;
133 class WebFrameTest : public testing::Test {
136 : m_baseURL("http://www.test.com/")
137 , m_chromeURL("chrome://")
141 virtual ~WebFrameTest()
143 Platform::current()->unitTestSupport()->unregisterAllMockedURLs();
146 void registerMockedHttpURLLoad(const std::string& fileName)
148 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8(fileName.c_str()));
151 void registerMockedChromeURLLoad(const std::string& fileName)
153 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_chromeURL.c_str()), WebString::fromUTF8(fileName.c_str()));
156 static void configueCompositingWebView(WebSettings* settings)
158 settings->setForceCompositingMode(true);
159 settings->setAcceleratedCompositingEnabled(true);
160 settings->setAcceleratedCompositingForFixedPositionEnabled(true);
161 settings->setAcceleratedCompositingForOverflowScrollEnabled(true);
162 settings->setAcceleratedCompositingForScrollableFramesEnabled(true);
163 settings->setCompositedScrollingForFramesEnabled(true);
164 settings->setFixedPositionCreatesStackingContext(true);
167 void initializeTextSelectionWebView(const std::string& url, FrameTestHelpers::WebViewHelper* webViewHelper)
169 webViewHelper->initializeAndLoad(url, true);
170 webViewHelper->webView()->settings()->setDefaultFontSize(12);
171 webViewHelper->webView()->resize(WebSize(640, 480));
174 std::string m_baseURL;
175 std::string m_chromeURL;
178 class UseMockScrollbarSettings {
180 UseMockScrollbarSettings()
182 WebCore::Settings::setMockScrollbarsEnabled(true);
183 WebCore::RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(true);
184 EXPECT_TRUE(WebCore::ScrollbarTheme::theme()->usesOverlayScrollbars());
187 ~UseMockScrollbarSettings()
189 WebCore::Settings::setMockScrollbarsEnabled(false);
190 WebCore::RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(false);
194 TEST_F(WebFrameTest, ContentText)
196 registerMockedHttpURLLoad("iframes_test.html");
197 registerMockedHttpURLLoad("visible_iframe.html");
198 registerMockedHttpURLLoad("invisible_iframe.html");
199 registerMockedHttpURLLoad("zero_sized_iframe.html");
201 FrameTestHelpers::WebViewHelper webViewHelper;
202 webViewHelper.initializeAndLoad(m_baseURL + "iframes_test.html");
204 // Now retrieve the frames text and test it only includes visible elements.
205 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
206 EXPECT_NE(std::string::npos, content.find(" visible paragraph"));
207 EXPECT_NE(std::string::npos, content.find(" visible iframe"));
208 EXPECT_EQ(std::string::npos, content.find(" invisible pararaph"));
209 EXPECT_EQ(std::string::npos, content.find(" invisible iframe"));
210 EXPECT_EQ(std::string::npos, content.find("iframe with zero size"));
213 TEST_F(WebFrameTest, FrameForEnteredContext)
215 registerMockedHttpURLLoad("iframes_test.html");
216 registerMockedHttpURLLoad("visible_iframe.html");
217 registerMockedHttpURLLoad("invisible_iframe.html");
218 registerMockedHttpURLLoad("zero_sized_iframe.html");
220 FrameTestHelpers::WebViewHelper webViewHelper;
221 webViewHelper.initializeAndLoad(m_baseURL + "iframes_test.html", true);
223 v8::HandleScope scope(v8::Isolate::GetCurrent());
224 EXPECT_EQ(webViewHelper.webView()->mainFrame(), WebFrame::frameForContext(webViewHelper.webView()->mainFrame()->mainWorldScriptContext()));
225 EXPECT_EQ(webViewHelper.webView()->mainFrame()->firstChild(), WebFrame::frameForContext(webViewHelper.webView()->mainFrame()->firstChild()->mainWorldScriptContext()));
228 TEST_F(WebFrameTest, FormWithNullFrame)
230 registerMockedHttpURLLoad("form.html");
232 FrameTestHelpers::WebViewHelper webViewHelper;
233 webViewHelper.initializeAndLoad(m_baseURL + "form.html");
235 WebVector<WebFormElement> forms;
236 webViewHelper.webView()->mainFrame()->document().forms(forms);
237 webViewHelper.reset();
239 EXPECT_EQ(forms.size(), 1U);
241 // This test passes if this doesn't crash.
242 WebSearchableFormData searchableDataForm(forms[0]);
245 TEST_F(WebFrameTest, ChromePageJavascript)
247 registerMockedChromeURLLoad("history.html");
249 // Pass true to enable JavaScript.
250 FrameTestHelpers::WebViewHelper webViewHelper;
251 webViewHelper.initializeAndLoad(m_chromeURL + "history.html", true);
253 // Try to run JS against the chrome-style URL.
254 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.appendChild(document.createTextNode('Clobbered'))");
256 // Required to see any updates in contentAsText.
257 webViewHelper.webView()->layout();
259 // Now retrieve the frame's text and ensure it was modified by running javascript.
260 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
261 EXPECT_NE(std::string::npos, content.find("Clobbered"));
264 TEST_F(WebFrameTest, ChromePageNoJavascript)
266 registerMockedChromeURLLoad("history.html");
268 /// Pass true to enable JavaScript.
269 FrameTestHelpers::WebViewHelper webViewHelper;
270 webViewHelper.initializeAndLoad(m_chromeURL + "history.html", true);
272 // Try to run JS against the chrome-style URL after prohibiting it.
273 WebSecurityPolicy::registerURLSchemeAsNotAllowingJavascriptURLs("chrome");
274 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.appendChild(document.createTextNode('Clobbered'))");
276 // Required to see any updates in contentAsText.
277 webViewHelper.webView()->layout();
279 // Now retrieve the frame's text and ensure it wasn't modified by running javascript.
280 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
281 EXPECT_EQ(std::string::npos, content.find("Clobbered"));
284 TEST_F(WebFrameTest, LocationSetHostWithMissingPort)
286 std::string fileName = "print-location-href.html";
287 registerMockedHttpURLLoad(fileName);
288 URLTestHelpers::registerMockedURLLoad(toKURL("http://www.test.com:0/" + fileName), WebString::fromUTF8(fileName));
290 FrameTestHelpers::WebViewHelper webViewHelper;
292 /// Pass true to enable JavaScript.
293 webViewHelper.initializeAndLoad(m_baseURL + fileName, true);
295 // Setting host to "hostname:" should be treated as "hostname:0".
296 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:location.host = 'www.test.com:'; void 0;");
299 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
301 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.textContent = location.href; void 0;");
302 // Required to see any updates in contentAsText.
304 webViewHelper.webView()->layout();
306 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
307 EXPECT_EQ("http://www.test.com:0/" + fileName, content);
310 TEST_F(WebFrameTest, LocationSetEmptyPort)
312 std::string fileName = "print-location-href.html";
313 registerMockedHttpURLLoad(fileName);
314 URLTestHelpers::registerMockedURLLoad(toKURL("http://www.test.com:0/" + fileName), WebString::fromUTF8(fileName));
316 FrameTestHelpers::WebViewHelper webViewHelper;
318 /// Pass true to enable JavaScript.
319 webViewHelper.initializeAndLoad(m_baseURL + fileName, true);
321 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:location.port = ''; void 0;");
324 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
326 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.textContent = location.href; void 0;");
327 // Required to see any updates in contentAsText.
329 webViewHelper.webView()->layout();
331 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
332 EXPECT_EQ("http://www.test.com:0/" + fileName, content);
335 class CSSCallbackWebFrameClient : public WebFrameClient {
337 CSSCallbackWebFrameClient() : m_updateCount(0) { }
338 virtual void didMatchCSS(WebFrame*, const WebVector<WebString>& newlyMatchingSelectors, const WebVector<WebString>& stoppedMatchingSelectors) OVERRIDE;
340 std::map<WebFrame*, std::set<std::string> > m_matchedSelectors;
344 void CSSCallbackWebFrameClient::didMatchCSS(WebFrame* frame, const WebVector<WebString>& newlyMatchingSelectors, const WebVector<WebString>& stoppedMatchingSelectors)
347 std::set<std::string>& frameSelectors = m_matchedSelectors[frame];
348 for (size_t i = 0; i < newlyMatchingSelectors.size(); ++i) {
349 std::string selector = newlyMatchingSelectors[i].utf8();
350 EXPECT_EQ(0U, frameSelectors.count(selector)) << selector;
351 frameSelectors.insert(selector);
353 for (size_t i = 0; i < stoppedMatchingSelectors.size(); ++i) {
354 std::string selector = stoppedMatchingSelectors[i].utf8();
355 EXPECT_EQ(1U, frameSelectors.count(selector)) << selector;
356 frameSelectors.erase(selector);
360 class WebFrameCSSCallbackTest : public testing::Test {
362 WebFrameCSSCallbackTest()
365 m_frame = m_helper.initializeAndLoad("about:blank", true, &m_client)->mainFrame();
368 ~WebFrameCSSCallbackTest()
370 EXPECT_EQ(1U, m_client.m_matchedSelectors.size());
373 WebDocument doc() const
375 return m_frame->document();
378 int updateCount() const
380 return m_client.m_updateCount;
383 const std::set<std::string>& matchedSelectors()
385 return m_client.m_matchedSelectors[m_frame];
388 void loadHTML(const WebData& html)
390 m_frame->loadHTMLString(html, toKURL("about:blank"));
394 void executeScript(const WebString& code)
396 m_frame->executeScript(WebScriptSource(code));
397 m_frame->view()->layout();
401 CSSCallbackWebFrameClient m_client;
402 FrameTestHelpers::WebViewHelper m_helper;
406 TEST_F(WebFrameCSSCallbackTest, AuthorStyleSheet)
410 // This stylesheet checks that the internal property and value can't be
411 // set by a stylesheet, only WebDocument::watchCSSSelectors().
412 "div.initial_on { -internal-callback: none; }"
413 "div.initial_off { -internal-callback: -internal-presence; }"
415 "<div class=\"initial_on\"></div>"
416 "<div class=\"initial_off\"></div>");
418 std::vector<WebString> selectors;
419 selectors.push_back(WebString::fromUTF8("div.initial_on"));
420 m_frame->document().watchCSSSelectors(WebVector<WebString>(selectors));
421 m_frame->view()->layout();
423 EXPECT_EQ(1, updateCount());
424 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("div.initial_on"));
426 // Check that adding a watched selector calls back for already-present nodes.
427 selectors.push_back(WebString::fromUTF8("div.initial_off"));
428 doc().watchCSSSelectors(WebVector<WebString>(selectors));
429 m_frame->view()->layout();
431 EXPECT_EQ(2, updateCount());
432 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("div.initial_off", "div.initial_on"));
434 // Check that we can turn off callbacks for certain selectors.
435 doc().watchCSSSelectors(WebVector<WebString>());
436 m_frame->view()->layout();
438 EXPECT_EQ(3, updateCount());
439 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
442 TEST_F(WebFrameCSSCallbackTest, SharedRenderStyle)
444 // Check that adding an element calls back when it matches an existing rule.
445 std::vector<WebString> selectors;
446 selectors.push_back(WebString::fromUTF8("span"));
447 doc().watchCSSSelectors(WebVector<WebString>(selectors));
450 "i1 = document.createElement('span');"
451 "i1.id = 'first_span';"
452 "document.body.appendChild(i1)");
453 EXPECT_EQ(1, updateCount());
454 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
456 // Adding a second element that shares a RenderStyle shouldn't call back.
457 // We use <span>s to avoid default style rules that can set
458 // RenderStyle::unique().
460 "i2 = document.createElement('span');"
461 "i2.id = 'second_span';"
462 "i1 = document.getElementById('first_span');"
463 "i1.parentNode.insertBefore(i2, i1.nextSibling);");
464 EXPECT_EQ(1, updateCount());
465 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
467 // Removing the first element shouldn't call back.
469 "i1 = document.getElementById('first_span');"
470 "i1.parentNode.removeChild(i1);");
471 EXPECT_EQ(1, updateCount());
472 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
474 // But removing the second element *should* call back.
476 "i2 = document.getElementById('second_span');"
477 "i2.parentNode.removeChild(i2);");
478 EXPECT_EQ(2, updateCount());
479 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
482 TEST_F(WebFrameCSSCallbackTest, CatchesAttributeChange)
484 loadHTML("<span></span>");
486 std::vector<WebString> selectors;
487 selectors.push_back(WebString::fromUTF8("span[attr=\"value\"]"));
488 doc().watchCSSSelectors(WebVector<WebString>(selectors));
491 EXPECT_EQ(0, updateCount());
492 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
495 "document.querySelector('span').setAttribute('attr', 'value');");
496 EXPECT_EQ(1, updateCount());
497 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span[attr=\"value\"]"));
500 TEST_F(WebFrameCSSCallbackTest, DisplayNone)
502 loadHTML("<div style='display:none'><span></span></div>");
504 std::vector<WebString> selectors;
505 selectors.push_back(WebString::fromUTF8("span"));
506 doc().watchCSSSelectors(WebVector<WebString>(selectors));
509 EXPECT_EQ(0, updateCount()) << "Don't match elements in display:none trees.";
512 "d = document.querySelector('div');"
513 "d.style.display = 'block';");
514 EXPECT_EQ(1, updateCount()) << "Match elements when they become displayed.";
515 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
518 "d = document.querySelector('div');"
519 "d.style.display = 'none';");
520 EXPECT_EQ(2, updateCount()) << "Unmatch elements when they become undisplayed.";
521 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
524 "s = document.querySelector('span');"
525 "s.style.display = 'none';");
526 EXPECT_EQ(2, updateCount()) << "No effect from no-display'ing a span that's already undisplayed.";
529 "d = document.querySelector('div');"
530 "d.style.display = 'block';");
531 EXPECT_EQ(2, updateCount()) << "No effect from displaying a div whose span is display:none.";
534 "s = document.querySelector('span');"
535 "s.style.display = 'inline';");
536 EXPECT_EQ(3, updateCount()) << "Now the span is visible and produces a callback.";
537 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
540 "s = document.querySelector('span');"
541 "s.style.display = 'none';");
542 EXPECT_EQ(4, updateCount()) << "Undisplaying the span directly should produce another callback.";
543 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
546 TEST_F(WebFrameCSSCallbackTest, Reparenting)
549 "<div id='d1'><span></span></div>"
550 "<div id='d2'></div>");
552 std::vector<WebString> selectors;
553 selectors.push_back(WebString::fromUTF8("span"));
554 doc().watchCSSSelectors(WebVector<WebString>(selectors));
555 m_frame->view()->layout();
558 EXPECT_EQ(1, updateCount());
559 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
562 "s = document.querySelector('span');"
563 "d2 = document.getElementById('d2');"
564 "d2.appendChild(s);");
565 EXPECT_EQ(1, updateCount()) << "Just moving an element that continues to match shouldn't send a spurious callback.";
566 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
569 TEST_F(WebFrameCSSCallbackTest, MultiSelector)
571 loadHTML("<span></span>");
573 // Check that selector lists match as the whole list, not as each element
575 std::vector<WebString> selectors;
576 selectors.push_back(WebString::fromUTF8("span"));
577 selectors.push_back(WebString::fromUTF8("span,p"));
578 doc().watchCSSSelectors(WebVector<WebString>(selectors));
579 m_frame->view()->layout();
582 EXPECT_EQ(1, updateCount());
583 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span", "span, p"));
586 TEST_F(WebFrameCSSCallbackTest, InvalidSelector)
588 loadHTML("<p><span></span></p>");
590 // Build a list with one valid selector and one invalid.
591 std::vector<WebString> selectors;
592 selectors.push_back(WebString::fromUTF8("span"));
593 selectors.push_back(WebString::fromUTF8("[")); // Invalid.
594 selectors.push_back(WebString::fromUTF8("p span")); // Not compound.
595 doc().watchCSSSelectors(WebVector<WebString>(selectors));
596 m_frame->view()->layout();
599 EXPECT_EQ(1, updateCount());
600 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"))
601 << "An invalid selector shouldn't prevent other selectors from matching.";
604 TEST_F(WebFrameTest, DispatchMessageEventWithOriginCheck)
606 registerMockedHttpURLLoad("postmessage_test.html");
608 // Pass true to enable JavaScript.
609 FrameTestHelpers::WebViewHelper webViewHelper;
610 webViewHelper.initializeAndLoad(m_baseURL + "postmessage_test.html", true);
612 // Send a message with the correct origin.
613 WebSecurityOrigin correctOrigin(WebSecurityOrigin::create(toKURL(m_baseURL)));
614 WebDOMEvent event = webViewHelper.webView()->mainFrame()->document().createEvent("MessageEvent");
615 WebDOMMessageEvent message = event.to<WebDOMMessageEvent>();
616 WebSerializedScriptValue data(WebSerializedScriptValue::fromString("foo"));
617 message.initMessageEvent("message", false, false, data, "http://origin.com", 0, "");
618 webViewHelper.webView()->mainFrame()->dispatchMessageEventWithOriginCheck(correctOrigin, message);
620 // Send another message with incorrect origin.
621 WebSecurityOrigin incorrectOrigin(WebSecurityOrigin::create(toKURL(m_chromeURL)));
622 webViewHelper.webView()->mainFrame()->dispatchMessageEventWithOriginCheck(incorrectOrigin, message);
624 // Required to see any updates in contentAsText.
625 webViewHelper.webView()->layout();
627 // Verify that only the first addition is in the body of the page.
628 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
629 EXPECT_NE(std::string::npos, content.find("Message 1."));
630 EXPECT_EQ(std::string::npos, content.find("Message 2."));
633 TEST_F(WebFrameTest, PostMessageThenDetach)
635 FrameTestHelpers::WebViewHelper webViewHelper;
636 webViewHelper.initializeAndLoad("about:blank");
638 RefPtr<WebCore::Frame> frame = webViewHelper.webViewImpl()->page()->mainFrame();
639 WebCore::NonThrowableExceptionState exceptionState;
640 frame->domWindow()->postMessage(WebCore::SerializedScriptValue::create("message"), 0, "*", frame->domWindow(), exceptionState);
641 webViewHelper.reset();
642 EXPECT_FALSE(exceptionState.hadException());
644 // Success is not crashing.
648 class FixedLayoutTestWebViewClient : public WebViewClient {
650 virtual WebScreenInfo screenInfo() OVERRIDE { return m_screenInfo; }
652 WebScreenInfo m_screenInfo;
655 // Viewport settings need to be set before the page gets loaded
656 static void enableViewportSettings(WebSettings* settings)
658 settings->setViewportMetaEnabled(true);
659 settings->setViewportEnabled(true);
660 settings->setMainFrameResizesAreOrientationChanges(true);
663 TEST_F(WebFrameTest, FrameViewNeedsLayoutOnFixedLayoutResize)
665 UseMockScrollbarSettings mockScrollbarSettings;
666 registerMockedHttpURLLoad("fixed_layout.html");
668 FixedLayoutTestWebViewClient client;
669 int viewportWidth = 640;
670 int viewportHeight = 480;
672 // Make sure we initialize to minimum scale, even if the window size
673 // only becomes available after the load begins.
674 FrameTestHelpers::WebViewHelper webViewHelper;
675 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
676 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
677 webViewHelper.webView()->layout();
679 webViewHelper.webViewImpl()->setFixedLayoutSize(WebCore::IntSize(100, 100));
680 EXPECT_TRUE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
682 int prevLayoutCount = webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount();
683 webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->setFrameRect(WebCore::IntRect(0, 0, 641, 481));
684 EXPECT_EQ(prevLayoutCount, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount());
686 webViewHelper.webViewImpl()->layout();
689 TEST_F(WebFrameTest, ChangeInFixedLayoutTriggersTextAutosizingRecalculate)
691 UseMockScrollbarSettings mockScrollbarSettings;
692 registerMockedHttpURLLoad("fixed_layout.html");
694 FixedLayoutTestWebViewClient client;
695 int viewportWidth = 640;
696 int viewportHeight = 480;
698 // Make sure we initialize to minimum scale, even if the window size
699 // only becomes available after the load begins.
700 FrameTestHelpers::WebViewHelper webViewHelper;
701 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
703 WebCore::Document* document = webViewHelper.webViewImpl()->page()->mainFrame()->document();
704 document->settings()->setTextAutosizingEnabled(true);
705 EXPECT_TRUE(document->settings()->textAutosizingEnabled());
706 webViewHelper.webViewImpl()->resize(WebSize(viewportWidth, viewportHeight));
707 webViewHelper.webViewImpl()->layout();
709 WebCore::RenderObject* renderer = document->renderer();
710 bool multiplierSetAtLeastOnce = false;
712 if (renderer->style()) {
713 renderer->style()->setTextAutosizingMultiplier(2);
714 EXPECT_EQ(2, renderer->style()->textAutosizingMultiplier());
715 multiplierSetAtLeastOnce = true;
717 renderer = renderer->nextInPreOrder();
719 EXPECT_TRUE(multiplierSetAtLeastOnce);
721 WebCore::ViewportDescription description = document->viewportDescription();
722 // Choose a width that's not going match the viewport width of the loaded document.
723 description.minWidth = WebCore::Length(100, WebCore::Fixed);
724 description.maxWidth = WebCore::Length(100, WebCore::Fixed);
725 webViewHelper.webViewImpl()->updatePageDefinedViewportConstraints(description);
727 bool multiplierCheckedAtLeastOnce = false;
728 renderer = document->renderer();
730 if (renderer->style()) {
731 EXPECT_EQ(1, renderer->style()->textAutosizingMultiplier());
732 multiplierCheckedAtLeastOnce = true;
734 renderer = renderer->nextInPreOrder();
736 EXPECT_TRUE(multiplierCheckedAtLeastOnce);
739 TEST_F(WebFrameTest, FixedLayoutSizeStopsResizeFromChangingLayoutSize)
741 UseMockScrollbarSettings mockScrollbarSettings;
742 registerMockedHttpURLLoad("fixed_layout.html");
744 int viewportWidth = 640;
745 int viewportHeight = 480;
747 int fixedLayoutWidth = viewportWidth / 2;
748 int fixedLayoutHeight = viewportHeight / 2;
750 FrameTestHelpers::WebViewHelper webViewHelper;
751 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, 0, enableViewportSettings);
752 webViewHelper.webView()->setFixedLayoutSize(WebSize(fixedLayoutWidth, fixedLayoutHeight));
753 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
754 webViewHelper.webView()->layout();
756 EXPECT_EQ(fixedLayoutWidth, webViewHelper.webViewImpl()->page()->mainFrame()->view()->layoutSize().width());
757 EXPECT_EQ(fixedLayoutHeight, webViewHelper.webViewImpl()->page()->mainFrame()->view()->layoutSize().height());
760 TEST_F(WebFrameTest, FixedLayoutSizePreventsResizeFromChangingPageScale)
762 UseMockScrollbarSettings mockScrollbarSettings;
763 registerMockedHttpURLLoad("fixed_layout.html");
765 int viewportWidth = 640;
766 int viewportHeight = 480;
768 int fixedLayoutWidth = viewportWidth / 2;
769 int fixedLayoutHeight = viewportHeight / 2;
771 FrameTestHelpers::WebViewHelper webViewHelper;
772 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, 0, enableViewportSettings);
773 webViewHelper.webView()->setFixedLayoutSize(WebSize(fixedLayoutWidth, fixedLayoutHeight));
774 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
775 webViewHelper.webView()->layout();
776 float pageScaleFactor = webViewHelper.webView()->pageScaleFactor();
778 webViewHelper.webView()->resize(WebSize(viewportWidth * 2, viewportHeight * 2));
780 EXPECT_EQ(pageScaleFactor, webViewHelper.webView()->pageScaleFactor());
783 TEST_F(WebFrameTest, FixedLayoutSizePreventsLayoutFromChangingPageScale)
785 UseMockScrollbarSettings mockScrollbarSettings;
786 registerMockedHttpURLLoad("fixed_layout.html");
788 int viewportWidth = 640;
789 int viewportHeight = 480;
791 int fixedLayoutWidth = viewportWidth * 2;
792 int fixedLayoutHeight = viewportHeight * 2;
794 FrameTestHelpers::WebViewHelper webViewHelper;
795 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, 0, enableViewportSettings);
796 webViewHelper.webView()->setFixedLayoutSize(WebSize(viewportWidth, viewportHeight));
797 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
798 webViewHelper.webView()->layout();
799 float pageScaleFactor = webViewHelper.webView()->pageScaleFactor();
801 webViewHelper.webView()->setFixedLayoutSize(WebSize(fixedLayoutWidth, fixedLayoutHeight));
802 webViewHelper.webView()->layout();
804 EXPECT_EQ(pageScaleFactor, webViewHelper.webView()->pageScaleFactor());
807 TEST_F(WebFrameTest, PreferredSizeAndContentSizeReportedCorrectlyWithZeroHeightFixedLayout)
809 UseMockScrollbarSettings mockScrollbarSettings;
810 registerMockedHttpURLLoad("200-by-300.html");
812 int windowWidth = 100;
813 int windowHeight = 100;
814 int viewportWidth = 100;
815 int viewportHeight = 0;
819 FixedLayoutTestWebViewClient client;
820 client.m_screenInfo.deviceScaleFactor = 1;
822 FrameTestHelpers::WebViewHelper webViewHelper;
823 webViewHelper.initializeAndLoad(m_baseURL + "200-by-300.html", true, 0, &client, enableViewportSettings);
824 webViewHelper.webView()->resize(WebSize(windowWidth, windowHeight));
825 webViewHelper.webView()->setFixedLayoutSize(WebSize(viewportWidth, viewportHeight));
826 webViewHelper.webView()->layout();
828 EXPECT_EQ(divWidth, webViewHelper.webView()->mainFrame()->contentsSize().width);
829 EXPECT_EQ(divHeight, webViewHelper.webView()->mainFrame()->contentsSize().height);
831 EXPECT_EQ(divWidth, webViewHelper.webView()->contentsPreferredMinimumSize().width);
832 EXPECT_EQ(divHeight, webViewHelper.webView()->contentsPreferredMinimumSize().height);
835 TEST_F(WebFrameTest, DisablingFixedLayoutSizeSetsCorrectLayoutSize)
837 UseMockScrollbarSettings mockScrollbarSettings;
838 registerMockedHttpURLLoad("no_viewport_tag.html");
840 FixedLayoutTestWebViewClient client;
841 client.m_screenInfo.deviceScaleFactor = 1;
842 int viewportWidth = 640;
843 int viewportHeight = 480;
845 FrameTestHelpers::WebViewHelper webViewHelper;
846 webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client, enableViewportSettings);
847 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
848 webViewHelper.webView()->settings()->setUseWideViewport(true);
849 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
851 webViewHelper.webView()->setFixedLayoutSize(WebSize(viewportWidth, viewportHeight));
852 EXPECT_TRUE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
853 webViewHelper.webView()->layout();
854 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
856 webViewHelper.webView()->setFixedLayoutSize(WebSize(0, 0));
857 EXPECT_TRUE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
858 webViewHelper.webView()->layout();
859 EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
862 TEST_F(WebFrameTest, ZeroHeightPositiveWidthNotIgnored)
864 UseMockScrollbarSettings mockScrollbarSettings;
866 FixedLayoutTestWebViewClient client;
867 client.m_screenInfo.deviceScaleFactor = 1;
868 int viewportWidth = 1280;
869 int viewportHeight = 0;
871 FrameTestHelpers::WebViewHelper webViewHelper;
872 webViewHelper.initialize(true, 0, &client, enableViewportSettings);
873 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
875 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
876 EXPECT_EQ(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
879 TEST_F(WebFrameTest, DeviceScaleFactorUsesDefaultWithoutViewportTag)
881 UseMockScrollbarSettings mockScrollbarSettings;
882 registerMockedHttpURLLoad("no_viewport_tag.html");
884 int viewportWidth = 640;
885 int viewportHeight = 480;
887 FixedLayoutTestWebViewClient client;
888 client.m_screenInfo.deviceScaleFactor = 2;
890 FrameTestHelpers::WebViewHelper webViewHelper;
891 webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client, enableViewportSettings);
893 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
894 webViewHelper.webView()->layout();
896 EXPECT_EQ(2, webViewHelper.webView()->deviceScaleFactor());
898 // Device scale factor should be independent of page scale.
899 webViewHelper.webView()->setPageScaleFactorLimits(1, 2);
900 webViewHelper.webView()->setPageScaleFactorPreservingScrollOffset(0.5);
901 webViewHelper.webView()->layout();
902 EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor());
904 // Force the layout to happen before leaving the test.
905 webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
908 TEST_F(WebFrameTest, FixedLayoutInitializeAtMinimumScale)
910 UseMockScrollbarSettings mockScrollbarSettings;
912 registerMockedHttpURLLoad("fixed_layout.html");
914 FixedLayoutTestWebViewClient client;
915 client.m_screenInfo.deviceScaleFactor = 1;
916 int viewportWidth = 640;
917 int viewportHeight = 480;
919 // Make sure we initialize to minimum scale, even if the window size
920 // only becomes available after the load begins.
921 FrameTestHelpers::WebViewHelper webViewHelper;
922 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
923 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
925 int defaultFixedLayoutWidth = 980;
926 float minimumPageScaleFactor = viewportWidth / (float) defaultFixedLayoutWidth;
927 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
928 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->minimumPageScaleFactor());
930 // Assume the user has pinch zoomed to page scale factor 2.
931 float userPinchPageScaleFactor = 2;
932 webViewHelper.webView()->setPageScaleFactorPreservingScrollOffset(userPinchPageScaleFactor);
933 webViewHelper.webView()->layout();
935 // Make sure we don't reset to initial scale if the page continues to load.
936 webViewHelper.webViewImpl()->didCommitLoad(false, false);
937 webViewHelper.webViewImpl()->didChangeContentsSize();
938 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
940 // Make sure we don't reset to initial scale if the viewport size changes.
941 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight + 100));
942 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
945 TEST_F(WebFrameTest, WideDocumentInitializeAtMinimumScale)
947 UseMockScrollbarSettings mockScrollbarSettings;
949 registerMockedHttpURLLoad("wide_document.html");
951 FixedLayoutTestWebViewClient client;
952 client.m_screenInfo.deviceScaleFactor = 1;
953 int viewportWidth = 640;
954 int viewportHeight = 480;
956 // Make sure we initialize to minimum scale, even if the window size
957 // only becomes available after the load begins.
958 FrameTestHelpers::WebViewHelper webViewHelper;
959 webViewHelper.initializeAndLoad(m_baseURL + "wide_document.html", true, 0, &client, enableViewportSettings);
960 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
962 int wideDocumentWidth = 1500;
963 float minimumPageScaleFactor = viewportWidth / (float) wideDocumentWidth;
964 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
965 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->minimumPageScaleFactor());
967 // Assume the user has pinch zoomed to page scale factor 2.
968 float userPinchPageScaleFactor = 2;
969 webViewHelper.webView()->setPageScaleFactorPreservingScrollOffset(userPinchPageScaleFactor);
970 webViewHelper.webView()->layout();
972 // Make sure we don't reset to initial scale if the page continues to load.
973 webViewHelper.webViewImpl()->didCommitLoad(false, false);
974 webViewHelper.webViewImpl()->didChangeContentsSize();
975 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
977 // Make sure we don't reset to initial scale if the viewport size changes.
978 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight + 100));
979 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
982 TEST_F(WebFrameTest, DelayedViewportInitialScale)
984 UseMockScrollbarSettings mockScrollbarSettings;
985 registerMockedHttpURLLoad("viewport-auto-initial-scale.html");
987 FixedLayoutTestWebViewClient client;
988 client.m_screenInfo.deviceScaleFactor = 1;
989 int viewportWidth = 640;
990 int viewportHeight = 480;
992 FrameTestHelpers::WebViewHelper webViewHelper;
993 webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings);
994 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
996 EXPECT_EQ(0.25f, webViewHelper.webView()->pageScaleFactor());
998 WebCore::Document* document = webViewHelper.webViewImpl()->page()->mainFrame()->document();
999 WebCore::ViewportDescription description = document->viewportDescription();
1000 description.zoom = 2;
1001 document->setViewportDescription(description);
1002 webViewHelper.webView()->layout();
1003 EXPECT_EQ(2, webViewHelper.webView()->pageScaleFactor());
1006 TEST_F(WebFrameTest, setLoadWithOverviewModeToFalse)
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, enableViewportSettings);
1018 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1019 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1020 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1022 // The page must be displayed at 100% zoom.
1023 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
1026 TEST_F(WebFrameTest, SetLoadWithOverviewModeToFalseAndNoWideViewport)
1028 UseMockScrollbarSettings mockScrollbarSettings;
1029 registerMockedHttpURLLoad("large-div.html");
1031 FixedLayoutTestWebViewClient client;
1032 client.m_screenInfo.deviceScaleFactor = 1;
1033 int viewportWidth = 640;
1034 int viewportHeight = 480;
1036 FrameTestHelpers::WebViewHelper webViewHelper;
1037 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client, enableViewportSettings);
1038 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1039 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1040 webViewHelper.webView()->settings()->setUseWideViewport(false);
1041 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1043 // The page must be displayed at 100% zoom, despite that it hosts a wide div element.
1044 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
1047 TEST_F(WebFrameTest, NoWideViewportIgnoresPageViewportWidth)
1049 UseMockScrollbarSettings mockScrollbarSettings;
1050 registerMockedHttpURLLoad("viewport-auto-initial-scale.html");
1052 FixedLayoutTestWebViewClient client;
1053 client.m_screenInfo.deviceScaleFactor = 1;
1054 int viewportWidth = 640;
1055 int viewportHeight = 480;
1057 FrameTestHelpers::WebViewHelper webViewHelper;
1058 webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings);
1059 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1060 webViewHelper.webView()->settings()->setUseWideViewport(false);
1061 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1063 // The page sets viewport width to 3000, but with UseWideViewport == false is must be ignored.
1064 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1065 EXPECT_EQ(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
1068 TEST_F(WebFrameTest, NoWideViewportIgnoresPageViewportWidthButAccountsScale)
1070 UseMockScrollbarSettings mockScrollbarSettings;
1071 registerMockedHttpURLLoad("viewport-wide-2x-initial-scale.html");
1073 FixedLayoutTestWebViewClient client;
1074 client.m_screenInfo.deviceScaleFactor = 1;
1075 int viewportWidth = 640;
1076 int viewportHeight = 480;
1078 FrameTestHelpers::WebViewHelper webViewHelper;
1079 webViewHelper.initializeAndLoad(m_baseURL + "viewport-wide-2x-initial-scale.html", true, 0, &client, enableViewportSettings);
1080 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1081 webViewHelper.webView()->settings()->setUseWideViewport(false);
1082 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1084 // The page sets viewport width to 3000, but with UseWideViewport == false it must be ignored.
1085 // While the initial scale specified by the page must be accounted.
1086 EXPECT_EQ(viewportWidth / 2, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1087 EXPECT_EQ(viewportHeight / 2, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
1090 TEST_F(WebFrameTest, WideViewportSetsTo980WithoutViewportTag)
1092 UseMockScrollbarSettings mockScrollbarSettings;
1093 registerMockedHttpURLLoad("no_viewport_tag.html");
1095 FixedLayoutTestWebViewClient client;
1096 client.m_screenInfo.deviceScaleFactor = 1;
1097 int viewportWidth = 640;
1098 int viewportHeight = 480;
1100 FrameTestHelpers::WebViewHelper webViewHelper;
1101 webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client, enableViewportSettings);
1102 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1103 webViewHelper.webView()->settings()->setUseWideViewport(true);
1104 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1106 EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1107 EXPECT_EQ(980.0 / viewportWidth * viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
1110 TEST_F(WebFrameTest, NoWideViewportAndHeightInMeta)
1112 UseMockScrollbarSettings mockScrollbarSettings;
1113 registerMockedHttpURLLoad("viewport-height-1000.html");
1115 FixedLayoutTestWebViewClient client;
1116 client.m_screenInfo.deviceScaleFactor = 1;
1117 int viewportWidth = 640;
1118 int viewportHeight = 480;
1120 FrameTestHelpers::WebViewHelper webViewHelper;
1121 webViewHelper.initializeAndLoad(m_baseURL + "viewport-height-1000.html", true, 0, &client, enableViewportSettings);
1122 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1123 webViewHelper.webView()->settings()->setUseWideViewport(false);
1124 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1126 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1129 TEST_F(WebFrameTest, WideViewportSetsTo980WithAutoWidth)
1131 UseMockScrollbarSettings mockScrollbarSettings;
1132 registerMockedHttpURLLoad("viewport-2x-initial-scale.html");
1134 FixedLayoutTestWebViewClient client;
1135 client.m_screenInfo.deviceScaleFactor = 1;
1136 int viewportWidth = 640;
1137 int viewportHeight = 480;
1139 FrameTestHelpers::WebViewHelper webViewHelper;
1140 webViewHelper.initializeAndLoad(m_baseURL + "viewport-2x-initial-scale.html", true, 0, &client, enableViewportSettings);
1141 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1142 webViewHelper.webView()->settings()->setUseWideViewport(true);
1143 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1145 EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1146 EXPECT_EQ(980.0 / viewportWidth * viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
1149 TEST_F(WebFrameTest, PageViewportInitialScaleOverridesLoadWithOverviewMode)
1151 UseMockScrollbarSettings mockScrollbarSettings;
1152 registerMockedHttpURLLoad("viewport-wide-2x-initial-scale.html");
1154 FixedLayoutTestWebViewClient client;
1155 client.m_screenInfo.deviceScaleFactor = 1;
1156 int viewportWidth = 640;
1157 int viewportHeight = 480;
1159 FrameTestHelpers::WebViewHelper webViewHelper;
1160 webViewHelper.initializeAndLoad(m_baseURL + "viewport-wide-2x-initial-scale.html", true, 0, &client, enableViewportSettings);
1161 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1162 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1164 // The page must be displayed at 200% zoom, as specified in its viewport meta tag.
1165 EXPECT_EQ(2.0f, webViewHelper.webView()->pageScaleFactor());
1168 TEST_F(WebFrameTest, setInitialPageScaleFactorPermanently)
1170 UseMockScrollbarSettings mockScrollbarSettings;
1172 registerMockedHttpURLLoad("fixed_layout.html");
1174 FixedLayoutTestWebViewClient client;
1175 client.m_screenInfo.deviceScaleFactor = 1;
1176 float enforcedPageScaleFactor = 2.0f;
1178 FrameTestHelpers::WebViewHelper webViewHelper;
1179 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1180 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1181 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1182 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1183 webViewHelper.webView()->layout();
1185 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1187 int viewportWidth = 640;
1188 int viewportHeight = 480;
1189 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1190 webViewHelper.webView()->layout();
1192 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1194 webViewHelper.webView()->setInitialPageScaleOverride(-1);
1195 webViewHelper.webView()->layout();
1196 EXPECT_EQ(1.0, webViewHelper.webView()->pageScaleFactor());
1199 TEST_F(WebFrameTest, PermanentInitialPageScaleFactorOverridesLoadWithOverviewMode)
1201 UseMockScrollbarSettings mockScrollbarSettings;
1202 registerMockedHttpURLLoad("viewport-auto-initial-scale.html");
1204 FixedLayoutTestWebViewClient client;
1205 client.m_screenInfo.deviceScaleFactor = 1;
1206 int viewportWidth = 640;
1207 int viewportHeight = 480;
1208 float enforcedPageScaleFactor = 0.5f;
1210 FrameTestHelpers::WebViewHelper webViewHelper;
1211 webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings);
1212 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1213 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1214 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1216 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1219 TEST_F(WebFrameTest, PermanentInitialPageScaleFactorOverridesPageViewportInitialScale)
1221 UseMockScrollbarSettings mockScrollbarSettings;
1222 registerMockedHttpURLLoad("viewport-wide-2x-initial-scale.html");
1224 FixedLayoutTestWebViewClient client;
1225 client.m_screenInfo.deviceScaleFactor = 1;
1226 int viewportWidth = 640;
1227 int viewportHeight = 480;
1228 float enforcedPageScaleFactor = 0.5f;
1230 FrameTestHelpers::WebViewHelper webViewHelper;
1231 webViewHelper.initializeAndLoad(m_baseURL + "viewport-wide-2x-initial-scale.html", true, 0, &client, enableViewportSettings);
1232 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1233 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1235 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1238 TEST_F(WebFrameTest, SmallPermanentInitialPageScaleFactorIsClobbered)
1240 UseMockScrollbarSettings mockScrollbarSettings;
1241 const char* pages[] = {
1242 // These pages trigger the clobbering condition. There must be a matching item in "pageScaleFactors" array.
1243 "viewport-device-0.5x-initial-scale.html",
1244 "viewport-initial-scale-1.html",
1245 // These ones do not.
1246 "viewport-auto-initial-scale.html",
1247 "viewport-target-densitydpi-device-and-fixed-width.html"
1249 float pageScaleFactors[] = { 0.5f, 1.0f };
1250 for (size_t i = 0; i < ARRAY_SIZE(pages); ++i)
1251 registerMockedHttpURLLoad(pages[i]);
1253 FixedLayoutTestWebViewClient client;
1254 client.m_screenInfo.deviceScaleFactor = 1;
1255 int viewportWidth = 400;
1256 int viewportHeight = 300;
1257 float enforcedPageScaleFactor = 0.75f;
1259 for (size_t i = 0; i < ARRAY_SIZE(pages); ++i) {
1260 for (int quirkEnabled = 0; quirkEnabled <= 1; ++quirkEnabled) {
1261 FrameTestHelpers::WebViewHelper webViewHelper;
1262 webViewHelper.initializeAndLoad(m_baseURL + pages[i], true, 0, &client, enableViewportSettings);
1263 webViewHelper.webView()->settings()->setClobberUserAgentInitialScaleQuirk(quirkEnabled);
1264 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1265 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1267 float expectedPageScaleFactor = quirkEnabled && i < ARRAY_SIZE(pageScaleFactors) ? pageScaleFactors[i] : enforcedPageScaleFactor;
1268 EXPECT_EQ(expectedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1273 TEST_F(WebFrameTest, PermanentInitialPageScaleFactorAffectsLayoutWidth)
1275 UseMockScrollbarSettings mockScrollbarSettings;
1277 FixedLayoutTestWebViewClient client;
1278 client.m_screenInfo.deviceScaleFactor = 1;
1279 int viewportWidth = 640;
1280 int viewportHeight = 480;
1281 float enforcedPageScaleFactor = 0.5;
1283 FrameTestHelpers::WebViewHelper webViewHelper;
1284 webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings);
1285 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1286 webViewHelper.webView()->settings()->setUseWideViewport(false);
1287 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1288 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1289 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1291 EXPECT_EQ(viewportWidth / enforcedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1292 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1295 TEST_F(WebFrameTest, WideViewportInitialScaleDoesNotExpandFixedLayoutWidth)
1297 UseMockScrollbarSettings mockScrollbarSettings;
1298 registerMockedHttpURLLoad("viewport-device-0.5x-initial-scale.html");
1300 FixedLayoutTestWebViewClient client;
1301 client.m_screenInfo.deviceScaleFactor = 1;
1302 int viewportWidth = 640;
1303 int viewportHeight = 480;
1305 FrameTestHelpers::WebViewHelper webViewHelper;
1306 webViewHelper.initializeAndLoad(m_baseURL + "viewport-device-0.5x-initial-scale.html", true, 0, &client, enableViewportSettings);
1307 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1308 webViewHelper.webView()->settings()->setUseWideViewport(true);
1309 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1310 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1312 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1313 EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor());
1315 webViewHelper.webView()->setFixedLayoutSize(WebSize(2000, 1500));
1316 webViewHelper.webView()->layout();
1317 EXPECT_EQ(2000, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1318 EXPECT_EQ(0.5f, webViewHelper.webView()->pageScaleFactor());
1321 TEST_F(WebFrameTest, WideViewportAndWideContentWithInitialScale)
1323 UseMockScrollbarSettings mockScrollbarSettings;
1324 registerMockedHttpURLLoad("wide_document_width_viewport.html");
1326 FixedLayoutTestWebViewClient client;
1327 client.m_screenInfo.deviceScaleFactor = 1;
1328 int viewportWidth = 600;
1329 int viewportHeight = 800;
1331 FrameTestHelpers::WebViewHelper webViewHelper;
1332 webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings);
1333 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1334 webViewHelper.webView()->settings()->setUseWideViewport(true);
1335 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1336 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1338 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "wide_document_width_viewport.html");
1339 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
1340 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1342 int wideDocumentWidth = 800;
1343 float minimumPageScaleFactor = viewportWidth / (float) wideDocumentWidth;
1344 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1345 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->minimumPageScaleFactor());
1348 TEST_F(WebFrameTest, WideViewportQuirkClobbersHeight)
1350 UseMockScrollbarSettings mockScrollbarSettings;
1351 registerMockedHttpURLLoad("viewport-height-1000.html");
1353 FixedLayoutTestWebViewClient client;
1354 client.m_screenInfo.deviceScaleFactor = 1;
1355 int viewportWidth = 600;
1356 int viewportHeight = 800;
1358 FrameTestHelpers::WebViewHelper webViewHelper;
1359 webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings);
1360 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1361 webViewHelper.webView()->settings()->setUseWideViewport(false);
1362 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1363 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1365 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport-height-1000.html");
1366 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
1367 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1369 EXPECT_EQ(800, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1370 EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor());
1373 TEST_F(WebFrameTest, LayoutSize320Quirk)
1375 UseMockScrollbarSettings mockScrollbarSettings;
1376 registerMockedHttpURLLoad("viewport/viewport-30.html");
1378 FixedLayoutTestWebViewClient client;
1379 client.m_screenInfo.deviceScaleFactor = 1;
1380 int viewportWidth = 600;
1381 int viewportHeight = 800;
1383 FrameTestHelpers::WebViewHelper webViewHelper;
1384 webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings);
1385 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1386 webViewHelper.webView()->settings()->setUseWideViewport(true);
1387 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1388 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1390 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport/viewport-30.html");
1391 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
1392 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1394 EXPECT_EQ(600, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1395 EXPECT_EQ(800, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1396 EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor());
1398 // The magic number to snap to device-width is 320, so test that 321 is
1400 WebCore::Document* document = webViewHelper.webViewImpl()->page()->mainFrame()->document();
1401 WebCore::ViewportDescription description = document->viewportDescription();
1402 description.minWidth = WebCore::Length(321, WebCore::Fixed);
1403 description.maxWidth = WebCore::Length(321, WebCore::Fixed);
1404 document->setViewportDescription(description);
1405 webViewHelper.webView()->layout();
1406 EXPECT_EQ(321, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1408 description.minWidth = WebCore::Length(320, WebCore::Fixed);
1409 description.maxWidth = WebCore::Length(320, WebCore::Fixed);
1410 document->setViewportDescription(description);
1411 webViewHelper.webView()->layout();
1412 EXPECT_EQ(600, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1415 TEST_F(WebFrameTest, ZeroValuesQuirk)
1417 UseMockScrollbarSettings mockScrollbarSettings;
1418 registerMockedHttpURLLoad("viewport-zero-values.html");
1420 FixedLayoutTestWebViewClient client;
1421 client.m_screenInfo.deviceScaleFactor = 1;
1422 int viewportWidth = 640;
1423 int viewportHeight = 480;
1425 FrameTestHelpers::WebViewHelper webViewHelper;
1426 webViewHelper.initialize(true, 0, &client, enableViewportSettings);
1427 webViewHelper.webView()->settings()->setViewportMetaZeroValuesQuirk(true);
1428 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1429 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1430 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport-zero-values.html");
1431 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
1432 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1434 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1435 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
1437 webViewHelper.webView()->settings()->setUseWideViewport(true);
1438 webViewHelper.webView()->layout();
1439 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1440 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
1443 TEST_F(WebFrameTest, OverflowHiddenDisablesScrolling)
1445 registerMockedHttpURLLoad("body-overflow-hidden.html");
1447 FixedLayoutTestWebViewClient client;
1448 client.m_screenInfo.deviceScaleFactor = 1;
1449 int viewportWidth = 640;
1450 int viewportHeight = 480;
1452 FrameTestHelpers::WebViewHelper webViewHelper;
1453 webViewHelper.initialize(true, 0, &client);
1454 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "body-overflow-hidden.html");
1455 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
1456 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1458 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
1459 EXPECT_FALSE(view->userInputScrollable(WebCore::VerticalScrollbar));
1462 TEST_F(WebFrameTest, IgnoreOverflowHiddenQuirk)
1464 registerMockedHttpURLLoad("body-overflow-hidden.html");
1466 FixedLayoutTestWebViewClient client;
1467 client.m_screenInfo.deviceScaleFactor = 1;
1468 int viewportWidth = 640;
1469 int viewportHeight = 480;
1471 FrameTestHelpers::WebViewHelper webViewHelper;
1472 webViewHelper.initialize(true, 0, &client);
1473 webViewHelper.webView()->settings()->setIgnoreMainFrameOverflowHiddenQuirk(true);
1474 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "body-overflow-hidden.html");
1475 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
1476 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1478 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
1479 EXPECT_TRUE(view->userInputScrollable(WebCore::VerticalScrollbar));
1482 TEST_F(WebFrameTest, NonZeroValuesNoQuirk)
1484 UseMockScrollbarSettings mockScrollbarSettings;
1485 registerMockedHttpURLLoad("viewport-nonzero-values.html");
1487 FixedLayoutTestWebViewClient client;
1488 client.m_screenInfo.deviceScaleFactor = 1;
1489 int viewportWidth = 640;
1490 int viewportHeight = 480;
1491 float expectedPageScaleFactor = 0.5f;
1493 FrameTestHelpers::WebViewHelper webViewHelper;
1494 webViewHelper.initialize(true, 0, &client, enableViewportSettings);
1495 webViewHelper.webView()->settings()->setViewportMetaZeroValuesQuirk(true);
1496 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1497 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport-nonzero-values.html");
1498 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
1499 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1501 EXPECT_EQ(viewportWidth / expectedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1502 EXPECT_EQ(expectedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1504 webViewHelper.webView()->settings()->setUseWideViewport(true);
1505 webViewHelper.webView()->layout();
1506 EXPECT_EQ(viewportWidth / expectedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1507 EXPECT_EQ(expectedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1510 TEST_F(WebFrameTest, setPageScaleFactorDoesNotLayout)
1512 UseMockScrollbarSettings mockScrollbarSettings;
1513 registerMockedHttpURLLoad("fixed_layout.html");
1515 FixedLayoutTestWebViewClient client;
1516 client.m_screenInfo.deviceScaleFactor = 1;
1517 // Small viewport to ensure there are always scrollbars.
1518 int viewportWidth = 64;
1519 int viewportHeight = 48;
1521 FrameTestHelpers::WebViewHelper webViewHelper;
1522 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1523 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1524 webViewHelper.webView()->layout();
1526 int prevLayoutCount = webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount();
1527 webViewHelper.webViewImpl()->setPageScaleFactor(3, WebPoint());
1528 EXPECT_FALSE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
1529 EXPECT_EQ(prevLayoutCount, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount());
1532 TEST_F(WebFrameTest, setPageScaleFactorWithOverlayScrollbarsDoesNotLayout)
1534 UseMockScrollbarSettings mockScrollbarSettings;
1536 registerMockedHttpURLLoad("fixed_layout.html");
1538 FixedLayoutTestWebViewClient client;
1539 client.m_screenInfo.deviceScaleFactor = 1;
1540 int viewportWidth = 640;
1541 int viewportHeight = 480;
1543 FrameTestHelpers::WebViewHelper webViewHelper;
1544 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1545 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1546 webViewHelper.webView()->layout();
1548 int prevLayoutCount = webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount();
1549 webViewHelper.webViewImpl()->setPageScaleFactor(30, WebPoint());
1550 EXPECT_FALSE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
1551 EXPECT_EQ(prevLayoutCount, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount());
1555 TEST_F(WebFrameTest, setPageScaleFactorBeforeFrameHasView)
1557 registerMockedHttpURLLoad("fixed_layout.html");
1559 float pageScaleFactor = 3;
1560 FrameTestHelpers::WebViewHelper webViewHelper;
1561 webViewHelper.initializeAndLoad("about:html", true, 0, 0);
1562 webViewHelper.webView()->setPageScaleFactor(pageScaleFactor, WebPoint());
1564 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "fixed_layout.html");
1565 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
1566 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
1567 EXPECT_EQ(pageScaleFactor, view->visibleContentScaleFactor());
1570 TEST_F(WebFrameTest, pageScaleFactorWrittenToHistoryItem)
1572 UseMockScrollbarSettings mockScrollbarSettings;
1573 registerMockedHttpURLLoad("fixed_layout.html");
1575 FixedLayoutTestWebViewClient client;
1576 client.m_screenInfo.deviceScaleFactor = 1;
1577 int viewportWidth = 640;
1578 int viewportHeight = 480;
1580 FrameTestHelpers::WebViewHelper webViewHelper;
1581 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1582 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1583 webViewHelper.webView()->layout();
1585 webViewHelper.webView()->setPageScaleFactor(3, WebPoint());
1586 webViewHelper.webViewImpl()->page()->mainFrame()->loader().saveDocumentAndScrollState();
1587 webViewHelper.webView()->setPageScaleFactor(1, WebPoint());
1588 webViewHelper.webViewImpl()->page()->mainFrame()->loader().setLoadType(WebCore::FrameLoadTypeBackForward);
1589 webViewHelper.webViewImpl()->page()->mainFrame()->loader().restoreScrollPositionAndViewState();
1590 EXPECT_EQ(3, webViewHelper.webView()->pageScaleFactor());
1593 TEST_F(WebFrameTest, pageScaleFactorShrinksViewport)
1595 UseMockScrollbarSettings mockScrollbarSettings;
1596 registerMockedHttpURLLoad("large-div.html");
1598 FixedLayoutTestWebViewClient client;
1599 client.m_screenInfo.deviceScaleFactor = 1;
1600 // Small viewport to ensure there are always scrollbars.
1601 int viewportWidth = 64;
1602 int viewportHeight = 48;
1604 FrameTestHelpers::WebViewHelper webViewHelper;
1605 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client, enableViewportSettings);
1606 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1607 webViewHelper.webView()->layout();
1609 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
1610 int viewportWidthMinusScrollbar = viewportWidth - (view->verticalScrollbar()->isOverlayScrollbar() ? 0 : 15);
1611 int viewportHeightMinusScrollbar = viewportHeight - (view->horizontalScrollbar()->isOverlayScrollbar() ? 0 : 15);
1613 webViewHelper.webView()->setPageScaleFactor(2, WebPoint());
1615 WebCore::IntSize unscaledSize = view->unscaledVisibleContentSize(WebCore::ScrollableArea::IncludeScrollbars);
1616 EXPECT_EQ(viewportWidth, unscaledSize.width());
1617 EXPECT_EQ(viewportHeight, unscaledSize.height());
1619 WebCore::IntSize unscaledSizeMinusScrollbar = view->unscaledVisibleContentSize(WebCore::ScrollableArea::ExcludeScrollbars);
1620 EXPECT_EQ(viewportWidthMinusScrollbar, unscaledSizeMinusScrollbar.width());
1621 EXPECT_EQ(viewportHeightMinusScrollbar, unscaledSizeMinusScrollbar.height());
1623 WebCore::IntSize scaledSize = view->visibleContentRect().size();
1624 EXPECT_EQ(ceil(viewportWidthMinusScrollbar / 2.0), scaledSize.width());
1625 EXPECT_EQ(ceil(viewportHeightMinusScrollbar / 2.0), scaledSize.height());
1628 TEST_F(WebFrameTest, pageScaleFactorDoesNotApplyCssTransform)
1630 UseMockScrollbarSettings mockScrollbarSettings;
1631 registerMockedHttpURLLoad("fixed_layout.html");
1633 FixedLayoutTestWebViewClient client;
1634 client.m_screenInfo.deviceScaleFactor = 1;
1635 int viewportWidth = 640;
1636 int viewportHeight = 480;
1638 FrameTestHelpers::WebViewHelper webViewHelper;
1639 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1640 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1641 webViewHelper.webView()->layout();
1643 webViewHelper.webView()->setPageScaleFactor(2, WebPoint());
1645 EXPECT_EQ(980, webViewHelper.webViewImpl()->page()->mainFrame()->contentRenderer()->unscaledDocumentRect().width());
1646 EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1649 TEST_F(WebFrameTest, targetDensityDpiHigh)
1651 UseMockScrollbarSettings mockScrollbarSettings;
1652 registerMockedHttpURLLoad("viewport-target-densitydpi-high.html");
1654 FixedLayoutTestWebViewClient client;
1656 float targetDpi = 240.0f;
1657 float deviceScaleFactors[] = { 1.0f, 4.0f / 3.0f, 2.0f };
1658 int viewportWidth = 640;
1659 int viewportHeight = 480;
1661 for (size_t i = 0; i < ARRAY_SIZE(deviceScaleFactors); ++i) {
1662 float deviceScaleFactor = deviceScaleFactors[i];
1663 float deviceDpi = deviceScaleFactor * 160.0f;
1664 client.m_screenInfo.deviceScaleFactor = deviceScaleFactor;
1666 FrameTestHelpers::WebViewHelper webViewHelper;
1667 webViewHelper.initializeAndLoad(m_baseURL + "viewport-target-densitydpi-high.html", true, 0, &client, enableViewportSettings);
1668 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1669 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1670 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1672 // We need to account for the fact that logical pixels are unconditionally multiplied by deviceScaleFactor to produce
1674 float densityDpiScaleRatio = deviceScaleFactor * targetDpi / deviceDpi;
1675 EXPECT_NEAR(viewportWidth * densityDpiScaleRatio, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1676 EXPECT_NEAR(viewportHeight * densityDpiScaleRatio, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1677 EXPECT_NEAR(1.0f / densityDpiScaleRatio, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1681 TEST_F(WebFrameTest, targetDensityDpiDevice)
1683 UseMockScrollbarSettings mockScrollbarSettings;
1684 registerMockedHttpURLLoad("viewport-target-densitydpi-device.html");
1686 float deviceScaleFactors[] = { 1.0f, 4.0f / 3.0f, 2.0f };
1688 FixedLayoutTestWebViewClient client;
1689 int viewportWidth = 640;
1690 int viewportHeight = 480;
1692 for (size_t i = 0; i < ARRAY_SIZE(deviceScaleFactors); ++i) {
1693 client.m_screenInfo.deviceScaleFactor = deviceScaleFactors[i];
1695 FrameTestHelpers::WebViewHelper webViewHelper;
1696 webViewHelper.initializeAndLoad(m_baseURL + "viewport-target-densitydpi-device.html", true, 0, &client, enableViewportSettings);
1697 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1698 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1699 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1701 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1702 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1703 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1707 TEST_F(WebFrameTest, targetDensityDpiDeviceAndFixedWidth)
1709 UseMockScrollbarSettings mockScrollbarSettings;
1710 registerMockedHttpURLLoad("viewport-target-densitydpi-device-and-fixed-width.html");
1712 float deviceScaleFactors[] = { 1.0f, 4.0f / 3.0f, 2.0f };
1714 FixedLayoutTestWebViewClient client;
1715 int viewportWidth = 640;
1716 int viewportHeight = 480;
1718 for (size_t i = 0; i < ARRAY_SIZE(deviceScaleFactors); ++i) {
1719 client.m_screenInfo.deviceScaleFactor = deviceScaleFactors[i];
1721 FrameTestHelpers::WebViewHelper webViewHelper;
1722 webViewHelper.initializeAndLoad(m_baseURL + "viewport-target-densitydpi-device-and-fixed-width.html", true, 0, &client, enableViewportSettings);
1723 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1724 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1725 webViewHelper.webView()->settings()->setUseWideViewport(true);
1726 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1728 EXPECT_NEAR(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1729 EXPECT_NEAR(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1730 EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1734 TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOne)
1736 UseMockScrollbarSettings mockScrollbarSettings;
1737 registerMockedHttpURLLoad("viewport-initial-scale-less-than-1.html");
1739 FixedLayoutTestWebViewClient client;
1740 client.m_screenInfo.deviceScaleFactor = 1.33f;
1741 int viewportWidth = 640;
1742 int viewportHeight = 480;
1744 FrameTestHelpers::WebViewHelper webViewHelper;
1745 webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-less-than-1.html", true, 0, &client, enableViewportSettings);
1746 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1747 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1748 webViewHelper.webView()->settings()->setUseWideViewport(false);
1749 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1750 webViewHelper.webView()->layout();
1752 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1753 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1754 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1757 TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOneWithDeviceWidth)
1759 UseMockScrollbarSettings mockScrollbarSettings;
1760 registerMockedHttpURLLoad("viewport-initial-scale-less-than-1-device-width.html");
1762 FixedLayoutTestWebViewClient client;
1763 client.m_screenInfo.deviceScaleFactor = 1.33f;
1764 int viewportWidth = 640;
1765 int viewportHeight = 480;
1767 FrameTestHelpers::WebViewHelper webViewHelper;
1768 webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-less-than-1-device-width.html", true, 0, &client, enableViewportSettings);
1769 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1770 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1771 webViewHelper.webView()->settings()->setUseWideViewport(false);
1772 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1773 webViewHelper.webView()->layout();
1775 const float pageZoom = 0.25f;
1776 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor / pageZoom, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1777 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor / pageZoom, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1778 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1781 TEST_F(WebFrameTest, NoWideViewportAndNoViewportWithInitialPageScaleOverride)
1783 UseMockScrollbarSettings mockScrollbarSettings;
1784 registerMockedHttpURLLoad("large-div.html");
1786 FixedLayoutTestWebViewClient client;
1787 int viewportWidth = 640;
1788 int viewportHeight = 480;
1789 float enforcedPageScaleFactor = 5.0f;
1791 FrameTestHelpers::WebViewHelper webViewHelper;
1792 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client, enableViewportSettings);
1793 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1794 webViewHelper.webView()->settings()->setUseWideViewport(false);
1795 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1796 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1797 webViewHelper.webView()->layout();
1799 EXPECT_NEAR(viewportWidth / enforcedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1800 EXPECT_NEAR(viewportHeight / enforcedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1801 EXPECT_NEAR(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1804 TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScale)
1806 UseMockScrollbarSettings mockScrollbarSettings;
1807 registerMockedHttpURLLoad("viewport-initial-scale-and-user-scalable-no.html");
1809 FixedLayoutTestWebViewClient client;
1810 int viewportWidth = 640;
1811 int viewportHeight = 480;
1813 FrameTestHelpers::WebViewHelper webViewHelper;
1814 webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-and-user-scalable-no.html", true, 0, &client, enableViewportSettings);
1815 webViewHelper.webView()->settings()->setViewportMetaNonUserScalableQuirk(true);
1816 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1817 webViewHelper.webView()->layout();
1819 EXPECT_NEAR(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1820 EXPECT_NEAR(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1821 EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1824 TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScaleForNonWideViewport)
1826 UseMockScrollbarSettings mockScrollbarSettings;
1827 registerMockedHttpURLLoad("viewport-initial-scale-and-user-scalable-no.html");
1829 FixedLayoutTestWebViewClient client;
1830 client.m_screenInfo.deviceScaleFactor = 1.33f;
1831 int viewportWidth = 640;
1832 int viewportHeight = 480;
1834 FrameTestHelpers::WebViewHelper webViewHelper;
1835 webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-and-user-scalable-no.html", true, 0, &client, enableViewportSettings);
1836 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1837 webViewHelper.webView()->settings()->setViewportMetaNonUserScalableQuirk(true);
1838 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1839 webViewHelper.webView()->settings()->setUseWideViewport(false);
1840 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1841 webViewHelper.webView()->layout();
1843 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1844 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1845 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1848 TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScaleForWideViewport)
1850 UseMockScrollbarSettings mockScrollbarSettings;
1851 registerMockedHttpURLLoad("viewport-2x-initial-scale-non-user-scalable.html");
1853 FixedLayoutTestWebViewClient client;
1854 int viewportWidth = 640;
1855 int viewportHeight = 480;
1857 FrameTestHelpers::WebViewHelper webViewHelper;
1858 webViewHelper.initializeAndLoad(m_baseURL + "viewport-2x-initial-scale-non-user-scalable.html", true, 0, &client, enableViewportSettings);
1859 webViewHelper.webView()->settings()->setViewportMetaNonUserScalableQuirk(true);
1860 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1861 webViewHelper.webView()->settings()->setUseWideViewport(true);
1862 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1864 EXPECT_NEAR(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1865 EXPECT_NEAR(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1866 EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1869 TEST_F(WebFrameTest, DesktopPageCanBeZoomedInWhenWideViewportIsTurnedOff)
1871 UseMockScrollbarSettings mockScrollbarSettings;
1872 registerMockedHttpURLLoad("no_viewport_tag.html");
1874 FixedLayoutTestWebViewClient client;
1875 int viewportWidth = 640;
1876 int viewportHeight = 480;
1878 FrameTestHelpers::WebViewHelper webViewHelper;
1879 webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client, enableViewportSettings);
1880 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1881 webViewHelper.webView()->settings()->setUseWideViewport(false);
1882 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1884 EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1885 EXPECT_NEAR(1.0f, webViewHelper.webView()->minimumPageScaleFactor(), 0.01f);
1886 EXPECT_NEAR(5.0f, webViewHelper.webView()->maximumPageScaleFactor(), 0.01f);
1889 class WebFrameResizeTest : public WebFrameTest {
1892 static WebCore::FloatSize computeRelativeOffset(const WebCore::IntPoint& absoluteOffset, const WebCore::LayoutRect& rect)
1894 WebCore::FloatSize relativeOffset = WebCore::FloatPoint(absoluteOffset) - rect.location();
1895 relativeOffset.scale(1.f / rect.width(), 1.f / rect.height());
1896 return relativeOffset;
1899 void testResizeYieldsCorrectScrollAndScale(const char* url,
1900 const float initialPageScaleFactor,
1901 const WebSize scrollOffset,
1902 const WebSize viewportSize,
1903 const bool shouldScaleRelativeToViewportWidth) {
1904 UseMockScrollbarSettings mockScrollbarSettings;
1905 registerMockedHttpURLLoad(url);
1907 const float aspectRatio = static_cast<float>(viewportSize.width) / viewportSize.height;
1909 FrameTestHelpers::WebViewHelper webViewHelper;
1910 webViewHelper.initializeAndLoad(m_baseURL + url, true, 0, 0, enableViewportSettings);
1912 // Origin scrollOffsets preserved under resize.
1914 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height));
1915 webViewHelper.webViewImpl()->setPageScaleFactor(initialPageScaleFactor, WebPoint());
1916 ASSERT_EQ(viewportSize, webViewHelper.webViewImpl()->size());
1917 ASSERT_EQ(initialPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor());
1918 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.height, viewportSize.width));
1919 float expectedPageScaleFactor = initialPageScaleFactor * (shouldScaleRelativeToViewportWidth ? 1 / aspectRatio : 1);
1920 EXPECT_NEAR(expectedPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor(), 0.05f);
1921 EXPECT_EQ(WebSize(), webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
1924 // Resizing just the height should not affect pageScaleFactor or scrollOffset.
1926 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height));
1927 webViewHelper.webViewImpl()->setPageScaleFactor(initialPageScaleFactor, WebPoint(scrollOffset.width, scrollOffset.height));
1928 webViewHelper.webViewImpl()->layout();
1929 const WebSize expectedScrollOffset = webViewHelper.webViewImpl()->mainFrame()->scrollOffset();
1930 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height * 0.8f));
1931 EXPECT_EQ(initialPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor());
1932 EXPECT_EQ(expectedScrollOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
1933 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height * 0.8f));
1934 EXPECT_EQ(initialPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor());
1935 EXPECT_EQ(expectedScrollOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
1938 // Generic resize preserves scrollOffset relative to anchor node located
1939 // the top center of the screen.
1941 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.height, viewportSize.width));
1942 float pageScaleFactor = webViewHelper.webViewImpl()->pageScaleFactor();
1943 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height));
1944 float expectedPageScaleFactor = pageScaleFactor * (shouldScaleRelativeToViewportWidth ? aspectRatio : 1);
1945 EXPECT_NEAR(expectedPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor(), 0.05f);
1946 webViewHelper.webViewImpl()->mainFrame()->setScrollOffset(scrollOffset);
1948 WebCore::IntPoint anchorPoint = WebCore::IntPoint(scrollOffset) + WebCore::IntPoint(viewportSize.width / 2, 0);
1949 RefPtr<WebCore::Node> anchorNode = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->eventHandler().hitTestResultAtPoint(anchorPoint, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent).innerNode();
1952 pageScaleFactor = webViewHelper.webViewImpl()->pageScaleFactor();
1953 const WebCore::FloatSize preResizeRelativeOffset
1954 = computeRelativeOffset(anchorPoint, anchorNode->boundingBox());
1955 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.height, viewportSize.width));
1956 WebCore::IntPoint newAnchorPoint = WebCore::IntPoint(webViewHelper.webViewImpl()->mainFrame()->scrollOffset()) + WebCore::IntPoint(viewportSize.height / 2, 0);
1957 const WebCore::FloatSize postResizeRelativeOffset
1958 = computeRelativeOffset(newAnchorPoint, anchorNode->boundingBox());
1959 EXPECT_NEAR(preResizeRelativeOffset.width(), postResizeRelativeOffset.width(), 0.15f);
1960 expectedPageScaleFactor = pageScaleFactor * (shouldScaleRelativeToViewportWidth ? 1 / aspectRatio : 1);
1961 EXPECT_NEAR(expectedPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor(), 0.05f);
1966 TEST_F(WebFrameResizeTest, ResizeYieldsCorrectScrollAndScaleForWidthEqualsDeviceWidth)
1968 // With width=device-width, pageScaleFactor is preserved across resizes as
1969 // long as the content adjusts according to the device-width.
1970 const char* url = "resize_scroll_mobile.html";
1971 const float initialPageScaleFactor = 1;
1972 const WebSize scrollOffset(0, 50);
1973 const WebSize viewportSize(120, 160);
1974 const bool shouldScaleRelativeToViewportWidth = true;
1976 testResizeYieldsCorrectScrollAndScale(
1977 url, initialPageScaleFactor, scrollOffset, viewportSize, shouldScaleRelativeToViewportWidth);
1980 TEST_F(WebFrameResizeTest, ResizeYieldsCorrectScrollAndScaleForFixedWidth)
1982 // With a fixed width, pageScaleFactor scales by the relative change in viewport width.
1983 const char* url = "resize_scroll_fixed_width.html";
1984 const float initialPageScaleFactor = 2;
1985 const WebSize scrollOffset(0, 200);
1986 const WebSize viewportSize(240, 320);
1987 const bool shouldScaleRelativeToViewportWidth = true;
1989 testResizeYieldsCorrectScrollAndScale(
1990 url, initialPageScaleFactor, scrollOffset, viewportSize, shouldScaleRelativeToViewportWidth);
1993 TEST_F(WebFrameResizeTest, ResizeYieldsCorrectScrollAndScaleForFixedLayout)
1995 // With a fixed layout, pageScaleFactor scales by the relative change in viewport width.
1996 const char* url = "resize_scroll_fixed_layout.html";
1997 const float initialPageScaleFactor = 2;
1998 const WebSize scrollOffset(200, 400);
1999 const WebSize viewportSize(320, 240);
2000 const bool shouldScaleRelativeToViewportWidth = true;
2002 testResizeYieldsCorrectScrollAndScale(
2003 url, initialPageScaleFactor, scrollOffset, viewportSize, shouldScaleRelativeToViewportWidth);
2006 TEST_F(WebFrameTest, pageScaleFactorScalesPaintClip)
2008 UseMockScrollbarSettings mockScrollbarSettings;
2009 registerMockedHttpURLLoad("large-div.html");
2011 FixedLayoutTestWebViewClient client;
2012 client.m_screenInfo.deviceScaleFactor = 1;
2013 int viewportWidth = 50;
2014 int viewportHeight = 50;
2016 FrameTestHelpers::WebViewHelper webViewHelper;
2017 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client);
2018 // FIXME: This test breaks if the viewport is enabled before loading the page due to the paint
2019 // calls below not working on composited layers. For some reason, enabling the viewport here
2020 // doesn't cause compositing
2021 webViewHelper.webView()->settings()->setViewportEnabled(true);
2022 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2023 webViewHelper.webView()->layout();
2025 // Set <1 page scale so that the clip rect should be larger than
2026 // the viewport size as passed into resize().
2027 webViewHelper.webView()->setPageScaleFactor(0.5, WebPoint());
2030 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 200, 200);
2031 bitmap.allocPixels();
2032 bitmap.eraseColor(0);
2033 SkCanvas canvas(bitmap);
2035 WebCore::GraphicsContext context(&canvas);
2036 context.setTrackOpaqueRegion(true);
2038 EXPECT_EQ_RECT(WebCore::IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
2040 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
2041 WebCore::IntRect paintRect(0, 0, 200, 200);
2042 view->paint(&context, paintRect);
2044 int viewportWidthMinusScrollbar = 50 - (view->verticalScrollbar()->isOverlayScrollbar() ? 0 : 15);
2045 int viewportHeightMinusScrollbar = 50 - (view->horizontalScrollbar()->isOverlayScrollbar() ? 0 : 15);
2046 WebCore::IntRect clippedRect(0, 0, viewportWidthMinusScrollbar * 2, viewportHeightMinusScrollbar * 2);
2047 EXPECT_EQ_RECT(clippedRect, context.opaqueRegion().asRect());
2050 TEST_F(WebFrameTest, pageScaleFactorUpdatesScrollbars)
2052 UseMockScrollbarSettings mockScrollbarSettings;
2053 registerMockedHttpURLLoad("fixed_layout.html");
2055 FixedLayoutTestWebViewClient client;
2056 client.m_screenInfo.deviceScaleFactor = 1;
2057 int viewportWidth = 640;
2058 int viewportHeight = 480;
2060 FrameTestHelpers::WebViewHelper webViewHelper;
2061 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
2062 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2063 webViewHelper.webView()->layout();
2065 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
2066 EXPECT_EQ(view->scrollSize(WebCore::HorizontalScrollbar), view->contentsSize().width() - view->visibleContentRect().width());
2067 EXPECT_EQ(view->scrollSize(WebCore::VerticalScrollbar), view->contentsSize().height() - view->visibleContentRect().height());
2069 webViewHelper.webView()->setPageScaleFactor(10, WebPoint());
2071 EXPECT_EQ(view->scrollSize(WebCore::HorizontalScrollbar), view->contentsSize().width() - view->visibleContentRect().width());
2072 EXPECT_EQ(view->scrollSize(WebCore::VerticalScrollbar), view->contentsSize().height() - view->visibleContentRect().height());
2075 TEST_F(WebFrameTest, CanOverrideScaleLimits)
2077 UseMockScrollbarSettings mockScrollbarSettings;
2079 registerMockedHttpURLLoad("no_scale_for_you.html");
2081 FixedLayoutTestWebViewClient client;
2082 client.m_screenInfo.deviceScaleFactor = 1;
2083 int viewportWidth = 640;
2084 int viewportHeight = 480;
2086 FrameTestHelpers::WebViewHelper webViewHelper;
2087 webViewHelper.initializeAndLoad(m_baseURL + "no_scale_for_you.html", true, 0, &client, enableViewportSettings);
2088 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2090 EXPECT_EQ(2.0f, webViewHelper.webView()->minimumPageScaleFactor());
2091 EXPECT_EQ(2.0f, webViewHelper.webView()->maximumPageScaleFactor());
2093 webViewHelper.webView()->setIgnoreViewportTagScaleLimits(true);
2094 webViewHelper.webView()->layout();
2096 EXPECT_EQ(1.0f, webViewHelper.webView()->minimumPageScaleFactor());
2097 EXPECT_EQ(5.0f, webViewHelper.webView()->maximumPageScaleFactor());
2099 webViewHelper.webView()->setIgnoreViewportTagScaleLimits(false);
2100 webViewHelper.webView()->layout();
2102 EXPECT_EQ(2.0f, webViewHelper.webView()->minimumPageScaleFactor());
2103 EXPECT_EQ(2.0f, webViewHelper.webView()->maximumPageScaleFactor());
2106 TEST_F(WebFrameTest, updateOverlayScrollbarLayers)
2108 UseMockScrollbarSettings mockScrollbarSettings;
2110 registerMockedHttpURLLoad("large-div.html");
2112 int viewWidth = 500;
2113 int viewHeight = 500;
2115 OwnPtr<FakeCompositingWebViewClient> fakeCompositingWebViewClient = adoptPtr(new FakeCompositingWebViewClient());
2116 FrameTestHelpers::WebViewHelper webViewHelper;
2117 webViewHelper.initialize(true, 0, fakeCompositingWebViewClient.get(), &configueCompositingWebView);
2119 webViewHelper.webView()->resize(WebSize(viewWidth, viewHeight));
2120 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "large-div.html");
2121 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
2122 webViewHelper.webView()->layout();
2124 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
2125 EXPECT_TRUE(view->renderView()->compositor()->layerForHorizontalScrollbar());
2126 EXPECT_TRUE(view->renderView()->compositor()->layerForVerticalScrollbar());
2128 webViewHelper.webView()->resize(WebSize(viewWidth * 10, viewHeight * 10));
2129 webViewHelper.webView()->layout();
2130 EXPECT_FALSE(view->renderView()->compositor()->layerForHorizontalScrollbar());
2131 EXPECT_FALSE(view->renderView()->compositor()->layerForVerticalScrollbar());
2134 void setScaleAndScrollAndLayout(blink::WebView* webView, WebPoint scroll, float scale)
2136 webView->setPageScaleFactor(scale, WebPoint(scroll.x, scroll.y));
2140 TEST_F(WebFrameTest, DivAutoZoomParamsTest)
2142 registerMockedHttpURLLoad("get_scale_for_auto_zoom_into_div_test.html");
2144 const float deviceScaleFactor = 2.0f;
2145 int viewportWidth = 640 / deviceScaleFactor;
2146 int viewportHeight = 1280 / deviceScaleFactor;
2147 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2148 FrameTestHelpers::WebViewHelper webViewHelper;
2149 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_for_auto_zoom_into_div_test.html");
2150 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2151 webViewHelper.webView()->setPageScaleFactorLimits(0.01f, 4);
2152 webViewHelper.webView()->setPageScaleFactor(0.5f, WebPoint(0, 0));
2153 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2154 webViewHelper.webView()->layout();
2156 WebRect wideDiv(200, 100, 400, 150);
2157 WebRect tallDiv(200, 300, 400, 800);
2158 WebRect doubleTapPointWide(wideDiv.x + 50, wideDiv.y + 50, touchPointPadding, touchPointPadding);
2159 WebRect doubleTapPointTall(tallDiv.x + 50, tallDiv.y + 50, touchPointPadding, touchPointPadding);
2160 WebRect wideBlockBounds;
2161 WebRect tallBlockBounds;
2165 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2167 // Test double-tap zooming into wide div.
2168 wideBlockBounds = webViewHelper.webViewImpl()->computeBlockBounds(doubleTapPointWide, false);
2169 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(doubleTapPointWide.x, doubleTapPointWide.y), wideBlockBounds, touchPointPadding, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2170 // The div should horizontally fill the screen (modulo margins), and
2171 // vertically centered (modulo integer rounding).
2172 EXPECT_NEAR(viewportWidth / (float) wideDiv.width, scale, 0.1);
2173 EXPECT_NEAR(wideDiv.x, scroll.x, 20);
2174 EXPECT_EQ(0, scroll.y);
2176 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), scroll, scale);
2178 // Test zoom out back to minimum scale.
2179 wideBlockBounds = webViewHelper.webViewImpl()->computeBlockBounds(doubleTapPointWide, false);
2180 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(doubleTapPointWide.x, doubleTapPointWide.y), wideBlockBounds, touchPointPadding, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2182 scale = webViewHelper.webViewImpl()->minimumPageScaleFactor();
2183 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), scale);
2185 // Test double-tap zooming into tall div.
2186 tallBlockBounds = webViewHelper.webViewImpl()->computeBlockBounds(doubleTapPointTall, false);
2187 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(doubleTapPointTall.x, doubleTapPointTall.y), tallBlockBounds, touchPointPadding, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2188 // The div should start at the top left of the viewport.
2189 EXPECT_NEAR(viewportWidth / (float) tallDiv.width, scale, 0.1);
2190 EXPECT_NEAR(tallDiv.x, scroll.x, 20);
2191 EXPECT_NEAR(tallDiv.y, scroll.y, 20);
2193 // Test for Non-doubletap scaling
2194 // Test zooming into div.
2195 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(250, 250), webViewHelper.webViewImpl()->computeBlockBounds(WebRect(250, 250, 10, 10), true), 0, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2196 EXPECT_NEAR(viewportWidth / (float) wideDiv.width, scale, 0.1);
2199 void simulatePageScale(WebViewImpl* webViewImpl, float& scale)
2201 WebCore::IntSize scrollDelta = webViewImpl->fakePageScaleAnimationTargetPositionForTesting() - webViewImpl->mainFrameImpl()->frameView()->scrollPosition();
2202 float scaleDelta = webViewImpl->fakePageScaleAnimationPageScaleForTesting() / webViewImpl->pageScaleFactor();
2203 webViewImpl->applyScrollAndScale(scrollDelta, scaleDelta);
2204 scale = webViewImpl->pageScaleFactor();
2207 void simulateMultiTargetZoom(WebViewImpl* webViewImpl, const WebRect& rect, float& scale)
2209 if (webViewImpl->zoomToMultipleTargetsRect(rect))
2210 simulatePageScale(webViewImpl, scale);
2213 void simulateDoubleTap(WebViewImpl* webViewImpl, WebPoint& point, float& scale)
2215 webViewImpl->animateDoubleTapZoom(point);
2216 EXPECT_TRUE(webViewImpl->fakeDoubleTapAnimationPendingForTesting());
2217 simulatePageScale(webViewImpl, scale);
2220 TEST_F(WebFrameTest, DivAutoZoomWideDivTest)
2222 registerMockedHttpURLLoad("get_wide_div_for_auto_zoom_test.html");
2224 const float deviceScaleFactor = 2.0f;
2225 int viewportWidth = 640 / deviceScaleFactor;
2226 int viewportHeight = 1280 / deviceScaleFactor;
2227 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2228 FrameTestHelpers::WebViewHelper webViewHelper;
2229 webViewHelper.initializeAndLoad(m_baseURL + "get_wide_div_for_auto_zoom_test.html");
2230 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2231 webViewHelper.webView()->setPageScaleFactorLimits(1.0f, 4);
2232 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2233 webViewHelper.webView()->setPageScaleFactor(1.0f, WebPoint(0, 0));
2234 webViewHelper.webView()->layout();
2236 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2238 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2240 WebRect div(0, 100, viewportWidth, 150);
2241 WebPoint point(div.x + 50, div.y + 50);
2243 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2245 simulateDoubleTap(webViewHelper.webViewImpl(), point, scale);
2246 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2247 simulateDoubleTap(webViewHelper.webViewImpl(), point, scale);
2248 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2251 TEST_F(WebFrameTest, DivAutoZoomVeryTallTest)
2253 // When a block is taller than the viewport and a zoom targets a lower part
2254 // of it, then we should keep the target point onscreen instead of snapping
2255 // back up the top of the block.
2256 registerMockedHttpURLLoad("very_tall_div.html");
2258 const float deviceScaleFactor = 2.0f;
2259 int viewportWidth = 640 / deviceScaleFactor;
2260 int viewportHeight = 1280 / deviceScaleFactor;
2261 FrameTestHelpers::WebViewHelper webViewHelper;
2262 webViewHelper.initializeAndLoad(m_baseURL + "very_tall_div.html", true, 0, 0, enableViewportSettings);
2263 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2264 webViewHelper.webView()->setPageScaleFactorLimits(1.0f, 4);
2265 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2266 webViewHelper.webView()->setPageScaleFactor(1.0f, WebPoint(0, 0));
2267 webViewHelper.webView()->layout();
2269 WebRect div(200, 300, 400, 5000);
2270 WebPoint point(div.x + 50, div.y + 3000);
2274 WebRect blockBounds = webViewHelper.webViewImpl()->computeBlockBounds(WebRect(point.x, point.y, 0, 0), true);
2275 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(point, blockBounds, 0, 1.0f, scale, scroll);
2276 EXPECT_EQ(scale, 1.0f);
2277 EXPECT_EQ(scroll.y, 2660);
2280 TEST_F(WebFrameTest, DivAutoZoomMultipleDivsTest)
2282 registerMockedHttpURLLoad("get_multiple_divs_for_auto_zoom_test.html");
2284 const float deviceScaleFactor = 2.0f;
2285 int viewportWidth = 640 / deviceScaleFactor;
2286 int viewportHeight = 1280 / deviceScaleFactor;
2287 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2288 FrameTestHelpers::WebViewHelper webViewHelper;
2289 webViewHelper.initializeAndLoad(m_baseURL + "get_multiple_divs_for_auto_zoom_test.html");
2290 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2291 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2292 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2293 webViewHelper.webView()->setPageScaleFactor(0.5f, WebPoint(0, 0));
2294 webViewHelper.webView()->layout();
2296 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2298 WebRect topDiv(200, 100, 200, 150);
2299 WebRect bottomDiv(200, 300, 200, 150);
2300 WebPoint topPoint(topDiv.x + 50, topDiv.y + 50);
2301 WebPoint bottomPoint(bottomDiv.x + 50, bottomDiv.y + 50);
2303 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2305 // Test double tap on two different divs
2306 // After first zoom, we should go back to minimum page scale with a second double tap.
2307 simulateDoubleTap(webViewHelper.webViewImpl(), topPoint, scale);
2308 EXPECT_FLOAT_EQ(1, scale);
2309 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2310 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2312 // If the user pinch zooms after double tap, a second double tap should zoom back to the div.
2313 simulateDoubleTap(webViewHelper.webViewImpl(), topPoint, scale);
2314 EXPECT_FLOAT_EQ(1, scale);
2315 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 0.6f);
2316 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2317 EXPECT_FLOAT_EQ(1, scale);
2318 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2319 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2321 // If we didn't yet get an auto-zoom update and a second double-tap arrives, should go back to minimum scale.
2322 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2323 webViewHelper.webViewImpl()->animateDoubleTapZoom(topPoint);
2324 EXPECT_TRUE(webViewHelper.webViewImpl()->fakeDoubleTapAnimationPendingForTesting());
2325 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2326 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2329 TEST_F(WebFrameTest, DivAutoZoomScaleBoundsTest)
2331 registerMockedHttpURLLoad("get_scale_bounds_check_for_auto_zoom_test.html");
2333 int viewportWidth = 320;
2334 int viewportHeight = 480;
2335 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2336 FrameTestHelpers::WebViewHelper webViewHelper;
2337 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_bounds_check_for_auto_zoom_test.html");
2338 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2339 webViewHelper.webView()->setDeviceScaleFactor(1.5f);
2340 webViewHelper.webView()->layout();
2342 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2344 WebRect div(200, 100, 200, 150);
2345 WebPoint doubleTapPoint(div.x + 50, div.y + 50);
2348 // Test double tap scale bounds.
2349 // minimumPageScale < doubleTapZoomAlreadyLegibleScale < 1
2350 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2351 webViewHelper.webView()->layout();
2352 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2353 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2354 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2355 EXPECT_FLOAT_EQ(1, scale);
2356 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2357 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2358 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2359 EXPECT_FLOAT_EQ(1, scale);
2361 // Zoom in to reset double_tap_zoom_in_effect flag.
2362 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2363 // 1 < minimumPageScale < doubleTapZoomAlreadyLegibleScale
2364 webViewHelper.webView()->setPageScaleFactorLimits(1.1f, 4);
2365 webViewHelper.webView()->layout();
2366 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2367 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2368 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2369 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2370 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2371 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2372 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2373 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2375 // Zoom in to reset double_tap_zoom_in_effect flag.
2376 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2377 // minimumPageScale < 1 < doubleTapZoomAlreadyLegibleScale
2378 webViewHelper.webView()->setPageScaleFactorLimits(0.95f, 4);
2379 webViewHelper.webView()->layout();
2380 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2381 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2382 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2383 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2384 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2385 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2386 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2387 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2390 TEST_F(WebFrameTest, DivAutoZoomScaleFontScaleFactorTest)
2392 registerMockedHttpURLLoad("get_scale_bounds_check_for_auto_zoom_test.html");
2394 int viewportWidth = 320;
2395 int viewportHeight = 480;
2396 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2397 float accessibilityFontScaleFactor = 1.13f;
2398 FrameTestHelpers::WebViewHelper webViewHelper;
2399 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_bounds_check_for_auto_zoom_test.html");
2400 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2401 webViewHelper.webView()->layout();
2403 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2404 webViewHelper.webViewImpl()->page()->settings().setTextAutosizingEnabled(true);
2405 webViewHelper.webViewImpl()->page()->settings().setAccessibilityFontScaleFactor(accessibilityFontScaleFactor);
2407 WebRect div(200, 100, 200, 150);
2408 WebPoint doubleTapPoint(div.x + 50, div.y + 50);
2411 // Test double tap scale bounds.
2412 // minimumPageScale < doubleTapZoomAlreadyLegibleScale < 1 < accessibilityFontScaleFactor
2413 float legibleScale = accessibilityFontScaleFactor;
2414 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2415 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2416 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2417 webViewHelper.webView()->layout();
2418 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2419 EXPECT_FLOAT_EQ(legibleScale, scale);
2420 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2421 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2422 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2423 EXPECT_FLOAT_EQ(legibleScale, scale);
2425 // Zoom in to reset double_tap_zoom_in_effect flag.
2426 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2427 // 1 < accessibilityFontScaleFactor < minimumPageScale < doubleTapZoomAlreadyLegibleScale
2428 webViewHelper.webView()->setPageScaleFactorLimits(1.0f, 4);
2429 webViewHelper.webView()->layout();
2430 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2431 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2432 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2433 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2434 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2435 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2436 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2437 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2439 // Zoom in to reset double_tap_zoom_in_effect flag.
2440 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2441 // minimumPageScale < 1 < accessibilityFontScaleFactor < doubleTapZoomAlreadyLegibleScale
2442 webViewHelper.webView()->setPageScaleFactorLimits(0.95f, 4);
2443 webViewHelper.webView()->layout();
2444 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2445 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2446 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2447 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2448 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2449 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2450 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2451 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2453 // Zoom in to reset double_tap_zoom_in_effect flag.
2454 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2455 // minimumPageScale < 1 < doubleTapZoomAlreadyLegibleScale < accessibilityFontScaleFactor
2456 webViewHelper.webView()->setPageScaleFactorLimits(0.9f, 4);
2457 webViewHelper.webView()->layout();
2458 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2459 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2460 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2461 EXPECT_FLOAT_EQ(legibleScale, scale);
2462 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2463 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2464 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2465 EXPECT_FLOAT_EQ(legibleScale, scale);
2468 TEST_F(WebFrameTest, DivMultipleTargetZoomMultipleDivsTest)
2470 registerMockedHttpURLLoad("get_multiple_divs_for_auto_zoom_test.html");
2472 const float deviceScaleFactor = 2.0f;
2473 int viewportWidth = 640 / deviceScaleFactor;
2474 int viewportHeight = 1280 / deviceScaleFactor;
2475 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2476 FrameTestHelpers::WebViewHelper webViewHelper;
2477 webViewHelper.initializeAndLoad(m_baseURL + "get_multiple_divs_for_auto_zoom_test.html");
2478 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2479 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2480 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2481 webViewHelper.webView()->setPageScaleFactor(0.5f, WebPoint(0, 0));
2482 webViewHelper.webView()->layout();
2484 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2486 WebRect viewportRect(0, 0, viewportWidth, viewportHeight);
2487 WebRect topDiv(200, 100, 200, 150);
2488 WebRect bottomDiv(200, 300, 200, 150);
2490 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2492 simulateMultiTargetZoom(webViewHelper.webViewImpl(), topDiv, scale);
2493 EXPECT_FLOAT_EQ(1, scale);
2494 simulateMultiTargetZoom(webViewHelper.webViewImpl(), bottomDiv, scale);
2495 EXPECT_FLOAT_EQ(1, scale);
2496 simulateMultiTargetZoom(webViewHelper.webViewImpl(), viewportRect, scale);
2497 EXPECT_FLOAT_EQ(1, scale);
2498 webViewHelper.webViewImpl()->setPageScaleFactor(webViewHelper.webViewImpl()->minimumPageScaleFactor(), WebPoint(0, 0));
2499 simulateMultiTargetZoom(webViewHelper.webViewImpl(), topDiv, scale);
2500 EXPECT_FLOAT_EQ(1, scale);
2503 TEST_F(WebFrameTest, DivScrollIntoEditableTest)
2505 registerMockedHttpURLLoad("get_scale_for_zoom_into_editable_test.html");
2507 int viewportWidth = 450;
2508 int viewportHeight = 300;
2509 float leftBoxRatio = 0.3f;
2510 int caretPadding = 10;
2511 float minReadableCaretHeight = 18.0f;
2512 FrameTestHelpers::WebViewHelper webViewHelper;
2513 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_for_zoom_into_editable_test.html");
2514 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2515 webViewHelper.webView()->setPageScaleFactorLimits(1, 4);
2516 webViewHelper.webView()->layout();
2517 webViewHelper.webView()->setDeviceScaleFactor(1.5f);
2518 webViewHelper.webView()->settings()->setAutoZoomFocusedNodeToLegibleScale(true);
2520 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2522 WebRect editBoxWithText(200, 200, 250, 20);
2523 WebRect editBoxWithNoText(200, 250, 250, 20);
2525 // Test scrolling the focused node
2526 // The edit box is shorter and narrower than the viewport when legible.
2527 webViewHelper.webView()->advanceFocus(false);
2528 // Set the caret to the end of the input box.
2529 webViewHelper.webView()->mainFrame()->document().getElementById("EditBoxWithText").to<WebInputElement>().setSelectionRange(1000, 1000);
2530 setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), 1);
2531 WebRect rect, caret;
2532 webViewHelper.webViewImpl()->selectionBounds(caret, rect);
2535 WebCore::IntPoint scroll;
2537 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2538 EXPECT_TRUE(needAnimation);
2539 // The edit box should be left aligned with a margin for possible label.
2540 int hScroll = editBoxWithText.x - leftBoxRatio * viewportWidth / scale;
2541 EXPECT_NEAR(hScroll, scroll.x(), 1);
2542 int vScroll = editBoxWithText.y - (viewportHeight / scale - editBoxWithText.height) / 2;
2543 EXPECT_NEAR(vScroll, scroll.y(), 1);
2544 EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1);
2546 // The edit box is wider than the viewport when legible.
2547 viewportWidth = 200;
2548 viewportHeight = 150;
2549 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2550 setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), 1);
2551 webViewHelper.webViewImpl()->selectionBounds(caret, rect);
2552 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2553 EXPECT_TRUE(needAnimation);
2554 // The caret should be right aligned since the caret would be offscreen when the edit box is left aligned.
2555 hScroll = caret.x + caret.width + caretPadding - viewportWidth / scale;
2556 EXPECT_NEAR(hScroll, scroll.x(), 1);
2557 EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1);
2559 setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), 1);
2560 // Move focus to edit box with text.
2561 webViewHelper.webView()->advanceFocus(false);
2562 webViewHelper.webViewImpl()->selectionBounds(caret, rect);
2563 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2564 EXPECT_TRUE(needAnimation);
2565 // The edit box should be left aligned.
2566 hScroll = editBoxWithNoText.x;
2567 EXPECT_NEAR(hScroll, scroll.x(), 1);
2568 vScroll = editBoxWithNoText.y - (viewportHeight / scale - editBoxWithNoText.height) / 2;
2569 EXPECT_NEAR(vScroll, scroll.y(), 1);
2570 EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1);
2572 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), scroll, scale);
2574 // Move focus back to the first edit box.
2575 webViewHelper.webView()->advanceFocus(true);
2576 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2577 // The position should have stayed the same since this box was already on screen with the right scale.
2578 EXPECT_FALSE(needAnimation);
2581 class TestReloadDoesntRedirectWebFrameClient : public WebFrameClient {
2583 virtual WebNavigationPolicy decidePolicyForNavigation(
2584 WebFrame*, WebDataSource::ExtraData*, const WebURLRequest&, WebNavigationType,
2585 WebNavigationPolicy defaultPolicy, bool isRedirect) OVERRIDE
2587 EXPECT_FALSE(isRedirect);
2588 return WebNavigationPolicyCurrentTab;
2592 TEST_F(WebFrameTest, ReloadDoesntSetRedirect)
2594 // Test for case in http://crbug.com/73104. Reloading a frame very quickly
2595 // would sometimes call decidePolicyForNavigation with isRedirect=true
2596 registerMockedHttpURLLoad("form.html");
2598 TestReloadDoesntRedirectWebFrameClient webFrameClient;
2599 FrameTestHelpers::WebViewHelper webViewHelper;
2600 webViewHelper.initializeAndLoad(m_baseURL + "form.html", false, &webFrameClient);
2602 webViewHelper.webView()->mainFrame()->reload(true);
2603 // start reload before request is delivered.
2604 webViewHelper.webView()->mainFrame()->reload(true);
2605 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
2608 TEST_F(WebFrameTest, ReloadWithOverrideURLPreservesState)
2610 const std::string firstURL = "find.html";
2611 const std::string secondURL = "form.html";
2612 const std::string thirdURL = "history.html";
2613 const float pageScaleFactor = 1.1684f;
2614 const int pageWidth = 640;
2615 const int pageHeight = 480;
2617 registerMockedHttpURLLoad(firstURL);
2618 registerMockedHttpURLLoad(secondURL);
2619 registerMockedHttpURLLoad(thirdURL);
2621 FrameTestHelpers::WebViewHelper webViewHelper;
2622 webViewHelper.initializeAndLoad(m_baseURL + firstURL, true);
2623 webViewHelper.webViewImpl()->resize(WebSize(pageWidth, pageHeight));
2624 webViewHelper.webViewImpl()->mainFrame()->setScrollOffset(WebSize(pageWidth / 4, pageHeight / 4));
2625 webViewHelper.webViewImpl()->setPageScaleFactorPreservingScrollOffset(pageScaleFactor);
2627 WebSize previousOffset = webViewHelper.webViewImpl()->mainFrame()->scrollOffset();
2628 float previousScale = webViewHelper.webViewImpl()->pageScaleFactor();
2630 // Reload the page using the cache.
2631 webViewHelper.webViewImpl()->mainFrame()->reloadWithOverrideURL(toKURL(m_baseURL + secondURL), false);
2632 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
2633 ASSERT_EQ(previousOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
2634 ASSERT_EQ(previousScale, webViewHelper.webViewImpl()->pageScaleFactor());
2636 // Reload the page while ignoring the cache.
2637 webViewHelper.webViewImpl()->mainFrame()->reloadWithOverrideURL(toKURL(m_baseURL + thirdURL), true);
2638 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
2639 ASSERT_EQ(previousOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
2640 ASSERT_EQ(previousScale, webViewHelper.webViewImpl()->pageScaleFactor());
2643 TEST_F(WebFrameTest, ReloadWhileProvisional)
2645 // Test that reloading while the previous load is still pending does not cause the initial
2646 // request to get lost.
2647 registerMockedHttpURLLoad("fixed_layout.html");
2649 FrameTestHelpers::WebViewHelper webViewHelper;
2650 webViewHelper.initialize();
2651 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "fixed_layout.html");
2652 // start reload before first request is delivered.
2653 webViewHelper.webView()->mainFrame()->reload(true);
2655 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
2657 WebDataSource* dataSource = webViewHelper.webView()->mainFrame()->dataSource();
2658 ASSERT_TRUE(dataSource);
2659 EXPECT_EQ(toKURL(m_baseURL + "fixed_layout.html"), toKURL(dataSource->request().url().spec()));
2662 TEST_F(WebFrameTest, AppendRedirects)
2664 const std::string firstURL = "about:blank";
2665 const std::string secondURL = "http://www.test.com";
2667 FrameTestHelpers::WebViewHelper webViewHelper;
2668 webViewHelper.initializeAndLoad(firstURL, true);
2670 WebDataSource* dataSource = webViewHelper.webView()->mainFrame()->dataSource();
2671 ASSERT_TRUE(dataSource);
2672 dataSource->appendRedirect(toKURL(secondURL));
2674 WebVector<WebURL> redirects;
2675 dataSource->redirectChain(redirects);
2676 ASSERT_EQ(2U, redirects.size());
2677 EXPECT_EQ(toKURL(firstURL), toKURL(redirects[0].spec().data()));
2678 EXPECT_EQ(toKURL(secondURL), toKURL(redirects[1].spec().data()));
2681 TEST_F(WebFrameTest, IframeRedirect)
2683 registerMockedHttpURLLoad("iframe_redirect.html");
2684 registerMockedHttpURLLoad("visible_iframe.html");
2686 FrameTestHelpers::WebViewHelper webViewHelper;
2687 webViewHelper.initializeAndLoad(m_baseURL + "iframe_redirect.html", true);
2688 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); // Load the iframe.
2690 WebFrame* iframe = webViewHelper.webView()->findFrameByName(WebString::fromUTF8("ifr"));
2691 ASSERT_TRUE(iframe);
2692 WebDataSource* iframeDataSource = iframe->dataSource();
2693 ASSERT_TRUE(iframeDataSource);
2694 WebVector<WebURL> redirects;
2695 iframeDataSource->redirectChain(redirects);
2696 ASSERT_EQ(2U, redirects.size());
2697 EXPECT_EQ(toKURL("about:blank"), toKURL(redirects[0].spec().data()));
2698 EXPECT_EQ(toKURL("http://www.test.com/visible_iframe.html"), toKURL(redirects[1].spec().data()));
2701 TEST_F(WebFrameTest, ClearFocusedNodeTest)
2703 registerMockedHttpURLLoad("iframe_clear_focused_node_test.html");
2704 registerMockedHttpURLLoad("autofocus_input_field_iframe.html");
2706 FrameTestHelpers::WebViewHelper webViewHelper;
2707 webViewHelper.initializeAndLoad(m_baseURL + "iframe_clear_focused_node_test.html", true);
2709 // Clear the focused node.
2710 webViewHelper.webView()->clearFocusedNode();
2712 // Now retrieve the FocusedNode and test it should be null.
2713 EXPECT_EQ(0, webViewHelper.webViewImpl()->focusedElement());
2716 // Implementation of WebFrameClient that tracks the v8 contexts that are created
2717 // and destroyed for verification.
2718 class ContextLifetimeTestWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
2720 struct Notification {
2722 Notification(WebFrame* frame, v8::Handle<v8::Context> context, int worldId)
2724 , context(context->GetIsolate(), context)
2734 bool Equals(Notification* other)
2736 return other && frame == other->frame && context == other->context && worldId == other->worldId;
2740 v8::Persistent<v8::Context> context;
2744 virtual ~ContextLifetimeTestWebFrameClient()
2751 for (size_t i = 0; i < createNotifications.size(); ++i)
2752 delete createNotifications[i];
2754 for (size_t i = 0; i < releaseNotifications.size(); ++i)
2755 delete releaseNotifications[i];
2757 createNotifications.clear();
2758 releaseNotifications.clear();
2761 std::vector<Notification*> createNotifications;
2762 std::vector<Notification*> releaseNotifications;
2765 virtual void didCreateScriptContext(WebFrame* frame, v8::Handle<v8::Context> context, int extensionGroup, int worldId) OVERRIDE
2767 createNotifications.push_back(new Notification(frame, context, worldId));
2770 virtual void willReleaseScriptContext(WebFrame* frame, v8::Handle<v8::Context> context, int worldId) OVERRIDE
2772 releaseNotifications.push_back(new Notification(frame, context, worldId));
2776 // TODO(aa): Deflake this test.
2777 TEST_F(WebFrameTest, FLAKY_ContextNotificationsLoadUnload)
2779 v8::HandleScope handleScope(v8::Isolate::GetCurrent());
2781 registerMockedHttpURLLoad("context_notifications_test.html");
2782 registerMockedHttpURLLoad("context_notifications_test_frame.html");
2784 // Load a frame with an iframe, make sure we get the right create notifications.
2785 ContextLifetimeTestWebFrameClient webFrameClient;
2786 FrameTestHelpers::WebViewHelper webViewHelper;
2787 webViewHelper.initializeAndLoad(m_baseURL + "context_notifications_test.html", true, &webFrameClient);
2789 WebFrame* mainFrame = webViewHelper.webView()->mainFrame();
2790 WebFrame* childFrame = mainFrame->firstChild();
2792 ASSERT_EQ(2u, webFrameClient.createNotifications.size());
2793 EXPECT_EQ(0u, webFrameClient.releaseNotifications.size());
2795 ContextLifetimeTestWebFrameClient::Notification* firstCreateNotification = webFrameClient.createNotifications[0];
2796 ContextLifetimeTestWebFrameClient::Notification* secondCreateNotification = webFrameClient.createNotifications[1];
2798 EXPECT_EQ(mainFrame, firstCreateNotification->frame);
2799 EXPECT_EQ(mainFrame->mainWorldScriptContext(), firstCreateNotification->context);
2800 EXPECT_EQ(0, firstCreateNotification->worldId);
2802 EXPECT_EQ(childFrame, secondCreateNotification->frame);
2803 EXPECT_EQ(childFrame->mainWorldScriptContext(), secondCreateNotification->context);
2804 EXPECT_EQ(0, secondCreateNotification->worldId);
2806 // Close the view. We should get two release notifications that are exactly the same as the create ones, in reverse order.
2807 webViewHelper.reset();
2809 ASSERT_EQ(2u, webFrameClient.releaseNotifications.size());
2810 ContextLifetimeTestWebFrameClient::Notification* firstReleaseNotification = webFrameClient.releaseNotifications[0];
2811 ContextLifetimeTestWebFrameClient::Notification* secondReleaseNotification = webFrameClient.releaseNotifications[1];
2813 ASSERT_TRUE(firstCreateNotification->Equals(secondReleaseNotification));
2814 ASSERT_TRUE(secondCreateNotification->Equals(firstReleaseNotification));
2817 TEST_F(WebFrameTest, ContextNotificationsReload)
2819 v8::HandleScope handleScope(v8::Isolate::GetCurrent());
2821 registerMockedHttpURLLoad("context_notifications_test.html");
2822 registerMockedHttpURLLoad("context_notifications_test_frame.html");
2824 ContextLifetimeTestWebFrameClient webFrameClient;
2825 FrameTestHelpers::WebViewHelper webViewHelper;
2826 webViewHelper.initializeAndLoad(m_baseURL + "context_notifications_test.html", true, &webFrameClient);
2828 // Refresh, we should get two release notifications and two more create notifications.
2829 webViewHelper.webView()->mainFrame()->reload(false);
2830 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
2831 ASSERT_EQ(4u, webFrameClient.createNotifications.size());
2832 ASSERT_EQ(2u, webFrameClient.releaseNotifications.size());
2834 // The two release notifications we got should be exactly the same as the first two create notifications.
2835 for (size_t i = 0; i < webFrameClient.releaseNotifications.size(); ++i) {
2836 EXPECT_TRUE(webFrameClient.releaseNotifications[i]->Equals(
2837 webFrameClient.createNotifications[webFrameClient.createNotifications.size() - 3 - i]));
2840 // The last two create notifications should be for the current frames and context.
2841 WebFrame* mainFrame = webViewHelper.webView()->mainFrame();
2842 WebFrame* childFrame = mainFrame->firstChild();
2843 ContextLifetimeTestWebFrameClient::Notification* firstRefreshNotification = webFrameClient.createNotifications[2];
2844 ContextLifetimeTestWebFrameClient::Notification* secondRefreshNotification = webFrameClient.createNotifications[3];
2846 EXPECT_EQ(mainFrame, firstRefreshNotification->frame);
2847 EXPECT_EQ(mainFrame->mainWorldScriptContext(), firstRefreshNotification->context);
2848 EXPECT_EQ(0, firstRefreshNotification->worldId);
2850 EXPECT_EQ(childFrame, secondRefreshNotification->frame);
2851 EXPECT_EQ(childFrame->mainWorldScriptContext(), secondRefreshNotification->context);
2852 EXPECT_EQ(0, secondRefreshNotification->worldId);
2855 TEST_F(WebFrameTest, ContextNotificationsIsolatedWorlds)
2857 v8::Isolate* isolate = v8::Isolate::GetCurrent();
2858 v8::HandleScope handleScope(isolate);
2860 registerMockedHttpURLLoad("context_notifications_test.html");
2861 registerMockedHttpURLLoad("context_notifications_test_frame.html");
2863 ContextLifetimeTestWebFrameClient webFrameClient;
2864 FrameTestHelpers::WebViewHelper webViewHelper;
2865 webViewHelper.initializeAndLoad(m_baseURL + "context_notifications_test.html", true, &webFrameClient);
2867 // Add an isolated world.
2868 webFrameClient.reset();
2870 int isolatedWorldId = 42;
2871 WebScriptSource scriptSource("hi!");
2873 int extensionGroup = 0;
2874 webViewHelper.webView()->mainFrame()->executeScriptInIsolatedWorld(isolatedWorldId, &scriptSource, numSources, extensionGroup);
2876 // We should now have a new create notification.
2877 ASSERT_EQ(1u, webFrameClient.createNotifications.size());
2878 ContextLifetimeTestWebFrameClient::Notification* notification = webFrameClient.createNotifications[0];
2879 ASSERT_EQ(isolatedWorldId, notification->worldId);
2880 ASSERT_EQ(webViewHelper.webView()->mainFrame(), notification->frame);
2882 // 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.
2883 ASSERT_NE(webViewHelper.webView()->mainFrame()->mainWorldScriptContext(), v8::Local<v8::Context>::New(isolate, notification->context));
2885 webViewHelper.reset();
2887 // We should have gotten three release notifications (one for each of the frames, plus one for the isolated context).
2888 ASSERT_EQ(3u, webFrameClient.releaseNotifications.size());
2890 // And one of them should be exactly the same as the create notification for the isolated context.
2892 for (size_t i = 0; i < webFrameClient.releaseNotifications.size(); ++i) {
2893 if (webFrameClient.releaseNotifications[i]->Equals(webFrameClient.createNotifications[0]))
2896 EXPECT_EQ(1, matchCount);
2899 TEST_F(WebFrameTest, FindInPage)
2901 registerMockedHttpURLLoad("find.html");
2902 FrameTestHelpers::WebViewHelper webViewHelper;
2903 webViewHelper.initializeAndLoad(m_baseURL + "find.html");
2904 WebFrame* frame = webViewHelper.webView()->mainFrame();
2905 const int findIdentifier = 12345;
2906 WebFindOptions options;
2908 // Find in a <div> element.
2909 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar1"), options, false, 0));
2910 frame->stopFinding(false);
2911 WebRange range = frame->selectionRange();
2912 EXPECT_EQ(5, range.startOffset());
2913 EXPECT_EQ(9, range.endOffset());
2914 EXPECT_TRUE(frame->document().focusedNode().isNull());
2916 // Find in an <input> value.
2917 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar2"), options, false, 0));
2918 // Confirm stopFinding(false) sets the selection on the found text.
2919 frame->stopFinding(false);
2920 range = frame->selectionRange();
2921 ASSERT_FALSE(range.isNull());
2922 EXPECT_EQ(5, range.startOffset());
2923 EXPECT_EQ(9, range.endOffset());
2924 EXPECT_EQ(WebString::fromUTF8("INPUT"), frame->document().focusedNode().nodeName());
2926 // Find in a <textarea> content.
2927 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar3"), options, false, 0));
2928 // Confirm stopFinding(false) sets the selection on the found text.
2929 frame->stopFinding(false);
2930 range = frame->selectionRange();
2931 ASSERT_FALSE(range.isNull());
2932 EXPECT_EQ(5, range.startOffset());
2933 EXPECT_EQ(9, range.endOffset());
2934 EXPECT_EQ(WebString::fromUTF8("TEXTAREA"), frame->document().focusedNode().nodeName());
2936 // Find in a contentEditable element.
2937 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar4"), options, false, 0));
2938 // Confirm stopFinding(false) sets the selection on the found text.
2939 frame->stopFinding(false);
2940 range = frame->selectionRange();
2941 ASSERT_FALSE(range.isNull());
2942 EXPECT_EQ(0, range.startOffset());
2943 EXPECT_EQ(4, range.endOffset());
2944 // "bar4" is surrounded by <span>, but the focusable node should be the parent <div>.
2945 EXPECT_EQ(WebString::fromUTF8("DIV"), frame->document().focusedNode().nodeName());
2947 // Find in <select> content.
2948 EXPECT_FALSE(frame->find(findIdentifier, WebString::fromUTF8("bar5"), options, false, 0));
2949 // If there are any matches, stopFinding will set the selection on the found text.
2950 // However, we do not expect any matches, so check that the selection is null.
2951 frame->stopFinding(false);
2952 range = frame->selectionRange();
2953 ASSERT_TRUE(range.isNull());
2956 TEST_F(WebFrameTest, GetContentAsPlainText)
2958 FrameTestHelpers::WebViewHelper webViewHelper;
2959 webViewHelper.initializeAndLoad("about:blank", true);
2960 // We set the size because it impacts line wrapping, which changes the
2961 // resulting text value.
2962 webViewHelper.webView()->resize(WebSize(640, 480));
2963 WebFrame* frame = webViewHelper.webView()->mainFrame();
2965 // Generate a simple test case.
2966 const char simpleSource[] = "<div>Foo bar</div><div></div>baz";
2967 WebCore::KURL testURL = toKURL("about:blank");
2968 frame->loadHTMLString(simpleSource, testURL);
2971 // Make sure it comes out OK.
2972 const std::string expected("Foo bar\nbaz");
2973 WebString text = frame->contentAsText(std::numeric_limits<size_t>::max());
2974 EXPECT_EQ(expected, text.utf8());
2976 // Try reading the same one with clipping of the text.
2977 const int length = 5;
2978 text = frame->contentAsText(length);
2979 EXPECT_EQ(expected.substr(0, length), text.utf8());
2981 // Now do a new test with a subframe.
2982 const char outerFrameSource[] = "Hello<iframe></iframe> world";
2983 frame->loadHTMLString(outerFrameSource, testURL);
2986 // Load something into the subframe.
2987 WebFrame* subframe = frame->findChildByExpression(WebString::fromUTF8("/html/body/iframe"));
2988 ASSERT_TRUE(subframe);
2989 subframe->loadHTMLString("sub<p>text", testURL);
2992 text = frame->contentAsText(std::numeric_limits<size_t>::max());
2993 EXPECT_EQ("Hello world\n\nsub\ntext", text.utf8());
2995 // Get the frame text where the subframe separator falls on the boundary of
2996 // what we'll take. There used to be a crash in this case.
2997 text = frame->contentAsText(12);
2998 EXPECT_EQ("Hello world", text.utf8());
3001 TEST_F(WebFrameTest, GetFullHtmlOfPage)
3003 FrameTestHelpers::WebViewHelper webViewHelper;
3004 webViewHelper.initializeAndLoad("about:blank", true);
3005 WebFrame* frame = webViewHelper.webView()->mainFrame();
3007 // Generate a simple test case.
3008 const char simpleSource[] = "<p>Hello</p><p>World</p>";
3009 WebCore::KURL testURL = toKURL("about:blank");
3010 frame->loadHTMLString(simpleSource, testURL);
3013 WebString text = frame->contentAsText(std::numeric_limits<size_t>::max());
3014 EXPECT_EQ("Hello\n\nWorld", text.utf8());
3016 const std::string html = frame->contentAsMarkup().utf8();
3018 // Load again with the output html.
3019 frame->loadHTMLString(WebData(html.c_str(), html.length()), testURL);
3022 EXPECT_EQ(html, frame->contentAsMarkup().utf8());
3024 text = frame->contentAsText(std::numeric_limits<size_t>::max());
3025 EXPECT_EQ("Hello\n\nWorld", text.utf8());
3027 // Test selection check
3028 EXPECT_FALSE(frame->hasSelection());
3029 frame->executeCommand(WebString::fromUTF8("SelectAll"));
3030 EXPECT_TRUE(frame->hasSelection());
3031 frame->executeCommand(WebString::fromUTF8("Unselect"));
3032 EXPECT_FALSE(frame->hasSelection());
3033 WebString selectionHtml = frame->selectionAsMarkup();
3034 EXPECT_TRUE(selectionHtml.isEmpty());
3037 class TestExecuteScriptDuringDidCreateScriptContext : public WebFrameClient {
3039 virtual void didCreateScriptContext(WebFrame* frame, v8::Handle<v8::Context> context, int extensionGroup, int worldId) OVERRIDE
3041 frame->executeScript(WebScriptSource("window.history = 'replaced';"));
3045 TEST_F(WebFrameTest, ExecuteScriptDuringDidCreateScriptContext)
3047 registerMockedHttpURLLoad("hello_world.html");
3049 TestExecuteScriptDuringDidCreateScriptContext webFrameClient;
3050 FrameTestHelpers::WebViewHelper webViewHelper;
3051 webViewHelper.initializeAndLoad(m_baseURL + "hello_world.html", true, &webFrameClient);
3053 webViewHelper.webView()->mainFrame()->reload();
3054 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
3057 class FindUpdateWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
3059 FindUpdateWebFrameClient()
3060 : m_findResultsAreReady(false)
3065 virtual void reportFindInPageMatchCount(int, int count, bool finalUpdate) OVERRIDE
3069 m_findResultsAreReady = true;
3072 bool findResultsAreReady() const { return m_findResultsAreReady; }
3073 int count() const { return m_count; }
3076 bool m_findResultsAreReady;
3080 // This fails on Mac https://bugs.webkit.org/show_bug.cgi?id=108574
3081 // Also failing on Android: http://crbug.com/341314
3082 #if OS(MACOSX) || OS(ANDROID)
3083 TEST_F(WebFrameTest, DISABLED_FindInPageMatchRects)
3085 TEST_F(WebFrameTest, FindInPageMatchRects)
3088 registerMockedHttpURLLoad("find_in_page.html");
3089 registerMockedHttpURLLoad("find_in_page_frame.html");
3091 FindUpdateWebFrameClient client;
3092 FrameTestHelpers::WebViewHelper webViewHelper;
3093 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3094 webViewHelper.webView()->resize(WebSize(640, 480));
3095 webViewHelper.webView()->layout();
3098 // Note that the 'result 19' in the <select> element is not expected to produce a match.
3099 static const char* kFindString = "result";
3100 static const int kFindIdentifier = 12345;
3101 static const int kNumResults = 19;
3103 WebFindOptions options;
3104 WebString searchText = WebString::fromUTF8(kFindString);
3105 WebFrameImpl* mainFrame = toWebFrameImpl(webViewHelper.webView()->mainFrame());
3106 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
3108 mainFrame->resetMatchCount();
3110 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3111 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3114 EXPECT_TRUE(client.findResultsAreReady());
3116 WebVector<WebFloatRect> webMatchRects;
3117 mainFrame->findMatchRects(webMatchRects);
3118 ASSERT_EQ(webMatchRects.size(), static_cast<size_t>(kNumResults));
3119 int rectsVersion = mainFrame->findMatchMarkersVersion();
3121 for (int resultIndex = 0; resultIndex < kNumResults; ++resultIndex) {
3122 FloatRect resultRect = static_cast<FloatRect>(webMatchRects[resultIndex]);
3124 // Select the match by the center of its rect.
3125 EXPECT_EQ(mainFrame->selectNearestFindMatch(resultRect.center(), 0), resultIndex + 1);
3127 // Check that the find result ordering matches with our expectations.
3128 Range* result = mainFrame->activeMatchFrame()->activeMatch();
3129 ASSERT_TRUE(result);
3130 result->setEnd(result->endContainer(), result->endOffset() + 3);
3131 EXPECT_EQ(result->text(), String::format("%s %02d", kFindString, resultIndex));
3133 // Verify that the expected match rect also matches the currently active match.
3134 // Compare the enclosing rects to prevent precision issues caused by CSS transforms.
3135 FloatRect activeMatch = mainFrame->activeFindMatchRect();
3136 EXPECT_EQ(enclosingIntRect(activeMatch), enclosingIntRect(resultRect));
3138 // The rects version should not have changed.
3139 EXPECT_EQ(mainFrame->findMatchMarkersVersion(), rectsVersion);
3142 // All results after the first two ones should be below between them in find-in-page coordinates.
3143 // This is because results 2 to 9 are inside an iframe located between results 0 and 1. This applies to the fixed div too.
3144 EXPECT_TRUE(webMatchRects[0].y < webMatchRects[1].y);
3145 for (int resultIndex = 2; resultIndex < kNumResults; ++resultIndex) {
3146 EXPECT_TRUE(webMatchRects[0].y < webMatchRects[resultIndex].y);
3147 EXPECT_TRUE(webMatchRects[1].y > webMatchRects[resultIndex].y);
3150 // Result 3 should be below both 2 and 4. This is caused by the CSS transform in the containing div.
3151 // If the transform doesn't work then 3 will be between 2 and 4.
3152 EXPECT_TRUE(webMatchRects[3].y > webMatchRects[2].y);
3153 EXPECT_TRUE(webMatchRects[3].y > webMatchRects[4].y);
3155 // Results 6, 7, 8 and 9 should be one below the other in that same order.
3156 // If overflow:scroll is not properly handled then result 8 would be below result 9 or
3157 // result 7 above result 6 depending on the scroll.
3158 EXPECT_TRUE(webMatchRects[6].y < webMatchRects[7].y);
3159 EXPECT_TRUE(webMatchRects[7].y < webMatchRects[8].y);
3160 EXPECT_TRUE(webMatchRects[8].y < webMatchRects[9].y);
3162 // Results 11, 12, 13 and 14 should be between results 10 and 15, as they are inside the table.
3163 EXPECT_TRUE(webMatchRects[11].y > webMatchRects[10].y);
3164 EXPECT_TRUE(webMatchRects[12].y > webMatchRects[10].y);
3165 EXPECT_TRUE(webMatchRects[13].y > webMatchRects[10].y);
3166 EXPECT_TRUE(webMatchRects[14].y > webMatchRects[10].y);
3167 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[15].y);
3168 EXPECT_TRUE(webMatchRects[12].y < webMatchRects[15].y);
3169 EXPECT_TRUE(webMatchRects[13].y < webMatchRects[15].y);
3170 EXPECT_TRUE(webMatchRects[14].y < webMatchRects[15].y);
3172 // Result 11 should be above 12, 13 and 14 as it's in the table header.
3173 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[12].y);
3174 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[13].y);
3175 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[14].y);
3177 // Result 11 should also be right to 12, 13 and 14 because of the colspan.
3178 EXPECT_TRUE(webMatchRects[11].x > webMatchRects[12].x);
3179 EXPECT_TRUE(webMatchRects[11].x > webMatchRects[13].x);
3180 EXPECT_TRUE(webMatchRects[11].x > webMatchRects[14].x);
3182 // Result 12 should be left to results 11, 13 and 14 in the table layout.
3183 EXPECT_TRUE(webMatchRects[12].x < webMatchRects[11].x);
3184 EXPECT_TRUE(webMatchRects[12].x < webMatchRects[13].x);
3185 EXPECT_TRUE(webMatchRects[12].x < webMatchRects[14].x);
3187 // Results 13, 12 and 14 should be one above the other in that order because of the rowspan
3188 // and vertical-align: middle by default.
3189 EXPECT_TRUE(webMatchRects[13].y < webMatchRects[12].y);
3190 EXPECT_TRUE(webMatchRects[12].y < webMatchRects[14].y);
3192 // Result 16 should be below result 15.
3193 EXPECT_TRUE(webMatchRects[15].y > webMatchRects[14].y);
3195 // Result 18 should be normalized with respect to the position:relative div, and not it's
3196 // immediate containing div. Consequently, result 18 should be above result 17.
3197 EXPECT_TRUE(webMatchRects[17].y > webMatchRects[18].y);
3199 // Resizing should update the rects version.
3200 webViewHelper.webView()->resize(WebSize(800, 600));
3202 EXPECT_TRUE(mainFrame->findMatchMarkersVersion() != rectsVersion);
3205 TEST_F(WebFrameTest, FindInPageSkipsHiddenFrames)
3207 registerMockedHttpURLLoad("find_in_hidden_frame.html");
3209 FindUpdateWebFrameClient client;
3210 FrameTestHelpers::WebViewHelper webViewHelper;
3211 webViewHelper.initializeAndLoad(m_baseURL + "find_in_hidden_frame.html", true, &client);
3212 webViewHelper.webView()->resize(WebSize(640, 480));
3213 webViewHelper.webView()->layout();
3216 static const char* kFindString = "hello";
3217 static const int kFindIdentifier = 12345;
3218 static const int kNumResults = 1;
3220 WebFindOptions options;
3221 WebString searchText = WebString::fromUTF8(kFindString);
3222 WebFrameImpl* mainFrame = toWebFrameImpl(webViewHelper.webView()->mainFrame());
3223 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
3225 mainFrame->resetMatchCount();
3227 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3228 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3231 EXPECT_TRUE(client.findResultsAreReady());
3232 EXPECT_EQ(kNumResults, client.count());
3235 TEST_F(WebFrameTest, FindOnDetachedFrame)
3237 registerMockedHttpURLLoad("find_in_page.html");
3238 registerMockedHttpURLLoad("find_in_page_frame.html");
3240 FindUpdateWebFrameClient client;
3241 FrameTestHelpers::WebViewHelper webViewHelper;
3242 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3243 webViewHelper.webView()->resize(WebSize(640, 480));
3244 webViewHelper.webView()->layout();
3247 static const char* kFindString = "result";
3248 static const int kFindIdentifier = 12345;
3250 WebFindOptions options;
3251 WebString searchText = WebString::fromUTF8(kFindString);
3252 WebFrameImpl* mainFrame = toWebFrameImpl(webViewHelper.webView()->mainFrame());
3253 RefPtr<WebFrameImpl> secondFrame = toWebFrameImpl(mainFrame->traverseNext(false));
3254 RefPtr<WebCore::Frame> holdSecondFrame = secondFrame->frame();
3256 // Detach the frame before finding.
3257 EXPECT_TRUE(mainFrame->document().getElementById("frame").remove());
3259 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
3260 EXPECT_FALSE(secondFrame->find(kFindIdentifier, searchText, options, false, 0));
3263 EXPECT_FALSE(client.findResultsAreReady());
3265 mainFrame->resetMatchCount();
3267 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3268 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3271 EXPECT_TRUE(client.findResultsAreReady());
3273 holdSecondFrame.release();
3276 TEST_F(WebFrameTest, FindDetachFrameBeforeScopeStrings)
3278 registerMockedHttpURLLoad("find_in_page.html");
3279 registerMockedHttpURLLoad("find_in_page_frame.html");
3281 FindUpdateWebFrameClient client;
3282 FrameTestHelpers::WebViewHelper webViewHelper;
3283 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3284 webViewHelper.webView()->resize(WebSize(640, 480));
3285 webViewHelper.webView()->layout();
3288 static const char* kFindString = "result";
3289 static const int kFindIdentifier = 12345;
3291 WebFindOptions options;
3292 WebString searchText = WebString::fromUTF8(kFindString);
3293 WebFrameImpl* mainFrame = toWebFrameImpl(webViewHelper.webView()->mainFrame());
3294 WebFrameImpl* secondFrame = toWebFrameImpl(mainFrame->traverseNext(false));
3295 RefPtr<WebCore::Frame> holdSecondFrame = secondFrame->frame();
3297 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3298 EXPECT_TRUE(frame->find(kFindIdentifier, searchText, options, false, 0));
3301 EXPECT_FALSE(client.findResultsAreReady());
3303 // Detach the frame between finding and scoping.
3304 EXPECT_TRUE(mainFrame->document().getElementById("frame").remove());
3306 mainFrame->resetMatchCount();
3308 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3309 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3312 EXPECT_TRUE(client.findResultsAreReady());
3314 holdSecondFrame.release();
3317 TEST_F(WebFrameTest, FindDetachFrameWhileScopingStrings)
3319 registerMockedHttpURLLoad("find_in_page.html");
3320 registerMockedHttpURLLoad("find_in_page_frame.html");
3322 FindUpdateWebFrameClient client;
3323 FrameTestHelpers::WebViewHelper webViewHelper;
3324 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3325 webViewHelper.webView()->resize(WebSize(640, 480));
3326 webViewHelper.webView()->layout();
3329 static const char* kFindString = "result";
3330 static const int kFindIdentifier = 12345;
3332 WebFindOptions options;
3333 WebString searchText = WebString::fromUTF8(kFindString);
3334 WebFrameImpl* mainFrame = toWebFrameImpl(webViewHelper.webView()->mainFrame());
3335 WebFrameImpl* secondFrame = toWebFrameImpl(mainFrame->traverseNext(false));
3336 RefPtr<WebCore::Frame> holdSecondFrame = secondFrame->frame();
3338 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3339 EXPECT_TRUE(frame->find(kFindIdentifier, searchText, options, false, 0));
3342 EXPECT_FALSE(client.findResultsAreReady());
3344 mainFrame->resetMatchCount();
3346 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3347 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3349 // The first scopeStringMatches will have reset the state. Detach before it actually scopes.
3350 EXPECT_TRUE(mainFrame->document().getElementById("frame").remove());
3353 EXPECT_TRUE(client.findResultsAreReady());
3355 holdSecondFrame.release();
3358 static WebPoint topLeft(const WebRect& rect)
3360 return WebPoint(rect.x, rect.y);
3363 static WebPoint bottomRightMinusOne(const WebRect& rect)
3365 // FIXME: If we don't subtract 1 from the x- and y-coordinates of the
3366 // selection bounds, selectRange() will select the *next* element. That's
3367 // strictly correct, as hit-testing checks the pixel to the lower-right of
3368 // the input coordinate, but it's a wart on the API.
3369 return WebPoint(rect.x + rect.width - 1, rect.y + rect.height - 1);
3372 static WebRect elementBounds(WebFrame* frame, const WebString& id)
3374 return frame->document().getElementById(id).boundsInViewportSpace();
3377 static std::string selectionAsString(WebFrame* frame)
3379 return frame->selectionAsText().utf8();
3382 TEST_F(WebFrameTest, SelectRange)
3385 WebRect startWebRect;
3388 registerMockedHttpURLLoad("select_range_basic.html");
3389 registerMockedHttpURLLoad("select_range_scroll.html");
3391 FrameTestHelpers::WebViewHelper webViewHelper;
3392 initializeTextSelectionWebView(m_baseURL + "select_range_basic.html", &webViewHelper);
3393 frame = webViewHelper.webView()->mainFrame();
3394 EXPECT_EQ("Some test text for testing.", selectionAsString(frame));
3395 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3396 frame->executeCommand(WebString::fromUTF8("Unselect"));
3397 EXPECT_EQ("", selectionAsString(frame));
3398 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3399 EXPECT_EQ("Some test text for testing.", selectionAsString(frame));
3401 initializeTextSelectionWebView(m_baseURL + "select_range_scroll.html", &webViewHelper);
3402 frame = webViewHelper.webView()->mainFrame();
3403 EXPECT_EQ("Some offscreen test text for testing.", selectionAsString(frame));
3404 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3405 frame->executeCommand(WebString::fromUTF8("Unselect"));
3406 EXPECT_EQ("", selectionAsString(frame));
3407 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3408 EXPECT_EQ("Some offscreen test text for testing.", selectionAsString(frame));
3411 TEST_F(WebFrameTest, SelectRangeInIframe)
3414 WebRect startWebRect;
3417 registerMockedHttpURLLoad("select_range_iframe.html");
3418 registerMockedHttpURLLoad("select_range_basic.html");
3420 FrameTestHelpers::WebViewHelper webViewHelper;
3421 initializeTextSelectionWebView(m_baseURL + "select_range_iframe.html", &webViewHelper);
3422 frame = webViewHelper.webView()->mainFrame();
3423 WebFrame* subframe = frame->findChildByExpression(WebString::fromUTF8("/html/body/iframe"));
3424 EXPECT_EQ("Some test text for testing.", selectionAsString(subframe));
3425 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3426 subframe->executeCommand(WebString::fromUTF8("Unselect"));
3427 EXPECT_EQ("", selectionAsString(subframe));
3428 subframe->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3429 EXPECT_EQ("Some test text for testing.", selectionAsString(subframe));
3432 TEST_F(WebFrameTest, SelectRangeDivContentEditable)
3435 WebRect startWebRect;
3438 registerMockedHttpURLLoad("select_range_div_editable.html");
3440 // Select the middle of an editable element, then try to extend the selection to the top of the document.
3441 // The selection range should be clipped to the bounds of the editable element.
3442 FrameTestHelpers::WebViewHelper webViewHelper;
3443 initializeTextSelectionWebView(m_baseURL + "select_range_div_editable.html", &webViewHelper);
3444 frame = webViewHelper.webView()->mainFrame();
3445 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3446 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3448 frame->selectRange(bottomRightMinusOne(endWebRect), WebPoint(0, 0));
3449 EXPECT_EQ("16-char header. This text is initially selected.", selectionAsString(frame));
3451 // As above, but extending the selection to the bottom of the document.
3452 initializeTextSelectionWebView(m_baseURL + "select_range_div_editable.html", &webViewHelper);
3453 frame = webViewHelper.webView()->mainFrame();
3455 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3456 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3457 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3458 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3460 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3461 frame->selectRange(topLeft(startWebRect), WebPoint(640, 480));
3462 EXPECT_EQ("This text is initially selected. 16-char footer.", selectionAsString(frame));
3465 // positionForPoint returns the wrong values for contenteditable spans. See
3466 // http://crbug.com/238334.
3467 TEST_F(WebFrameTest, DISABLED_SelectRangeSpanContentEditable)
3470 WebRect startWebRect;
3473 registerMockedHttpURLLoad("select_range_span_editable.html");
3475 // Select the middle of an editable element, then try to extend the selection to the top of the document.
3476 // The selection range should be clipped to the bounds of the editable element.
3477 FrameTestHelpers::WebViewHelper webViewHelper;
3478 initializeTextSelectionWebView(m_baseURL + "select_range_span_editable.html", &webViewHelper);
3479 frame = webViewHelper.webView()->mainFrame();
3480 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3481 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3483 frame->selectRange(bottomRightMinusOne(endWebRect), WebPoint(0, 0));
3484 EXPECT_EQ("16-char header. This text is initially selected.", selectionAsString(frame));
3486 // As above, but extending the selection to the bottom of the document.
3487 initializeTextSelectionWebView(m_baseURL + "select_range_span_editable.html", &webViewHelper);
3488 frame = webViewHelper.webView()->mainFrame();
3490 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3491 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3492 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3493 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3495 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3496 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3497 frame->selectRange(topLeft(startWebRect), WebPoint(640, 480));
3498 EXPECT_EQ("This text is initially selected. 16-char footer.", selectionAsString(frame));
3501 TEST_F(WebFrameTest, SelectRangeCanMoveSelectionStart)
3503 registerMockedHttpURLLoad("text_selection.html");
3504 FrameTestHelpers::WebViewHelper webViewHelper;
3505 initializeTextSelectionWebView(m_baseURL + "text_selection.html", &webViewHelper);
3506 WebFrame* frame = webViewHelper.webView()->mainFrame();
3508 // Select second span. We can move the start to include the first span.
3509 frame->executeScript(WebScriptSource("selectElement('header_2');"));
3510 EXPECT_EQ("Header 2.", selectionAsString(frame));
3511 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "header_2")), topLeft(elementBounds(frame, "header_1")));
3512 EXPECT_EQ("Header 1. Header 2.", selectionAsString(frame));
3514 // We can move the start and end together.
3515 frame->executeScript(WebScriptSource("selectElement('header_1');"));
3516 EXPECT_EQ("Header 1.", selectionAsString(frame));
3517 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "header_1")));
3518 EXPECT_EQ("", selectionAsString(frame));
3519 // Selection is a caret, not empty.
3520 EXPECT_FALSE(frame->selectionRange().isNull());
3522 // We can move the start across the end.
3523 frame->executeScript(WebScriptSource("selectElement('header_1');"));
3524 EXPECT_EQ("Header 1.", selectionAsString(frame));
3525 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "header_2")));
3526 EXPECT_EQ(" Header 2.", selectionAsString(frame));
3528 // Can't extend the selection part-way into an editable element.
3529 frame->executeScript(WebScriptSource("selectElement('footer_2');"));
3530 EXPECT_EQ("Footer 2.", selectionAsString(frame));
3531 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "footer_2")), topLeft(elementBounds(frame, "editable_2")));
3532 EXPECT_EQ(" [ Footer 1. Footer 2.", selectionAsString(frame));
3534 // Can extend the selection completely across editable elements.
3535 frame->executeScript(WebScriptSource("selectElement('footer_2');"));
3536 EXPECT_EQ("Footer 2.", selectionAsString(frame));
3537 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "footer_2")), topLeft(elementBounds(frame, "header_2")));
3538 EXPECT_EQ("Header 2. ] [ Editable 1. Editable 2. ] [ Footer 1. Footer 2.", selectionAsString(frame));
3540 // If the selection is editable text, we can't extend it into non-editable text.
3541 frame->executeScript(WebScriptSource("selectElement('editable_2');"));
3542 EXPECT_EQ("Editable 2.", selectionAsString(frame));
3543 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "editable_2")), topLeft(elementBounds(frame, "header_2")));
3544 // positionForPoint returns the wrong values for contenteditable spans. See
3545 // http://crbug.com/238334.
3546 // EXPECT_EQ("[ Editable 1. Editable 2.", selectionAsString(frame));
3549 TEST_F(WebFrameTest, SelectRangeCanMoveSelectionEnd)
3551 registerMockedHttpURLLoad("text_selection.html");
3552 FrameTestHelpers::WebViewHelper webViewHelper;
3553 initializeTextSelectionWebView(m_baseURL + "text_selection.html", &webViewHelper);
3554 WebFrame* frame = webViewHelper.webView()->mainFrame();
3556 // Select first span. We can move the end to include the second span.
3557 frame->executeScript(WebScriptSource("selectElement('header_1');"));
3558 EXPECT_EQ("Header 1.", selectionAsString(frame));
3559 frame->selectRange(topLeft(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "header_2")));
3560 EXPECT_EQ("Header 1. Header 2.", selectionAsString(frame));
3562 // We can move the start and end together.
3563 frame->executeScript(WebScriptSource("selectElement('header_2');"));
3564 EXPECT_EQ("Header 2.", selectionAsString(frame));
3565 frame->selectRange(topLeft(elementBounds(frame, "header_2")), topLeft(elementBounds(frame, "header_2")));
3566 EXPECT_EQ("", selectionAsString(frame));
3567 // Selection is a caret, not empty.
3568 EXPECT_FALSE(frame->selectionRange().isNull());
3570 // We can move the end across the start.
3571 frame->executeScript(WebScriptSource("selectElement('header_2');"));
3572 EXPECT_EQ("Header 2.", selectionAsString(frame));
3573 frame->selectRange(topLeft(elementBounds(frame, "header_2")), topLeft(elementBounds(frame, "header_1")));
3574 EXPECT_EQ("Header 1. ", selectionAsString(frame));
3576 // Can't extend the selection part-way into an editable element.
3577 frame->executeScript(WebScriptSource("selectElement('header_1');"));
3578 EXPECT_EQ("Header 1.", selectionAsString(frame));
3579 frame->selectRange(topLeft(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "editable_1")));
3580 EXPECT_EQ("Header 1. Header 2. ] ", selectionAsString(frame));
3582 // Can extend the selection completely across editable elements.
3583 frame->executeScript(WebScriptSource("selectElement('header_1');"));
3584 EXPECT_EQ("Header 1.", selectionAsString(frame));
3585 frame->selectRange(topLeft(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "footer_1")));
3586 EXPECT_EQ("Header 1. Header 2. ] [ Editable 1. Editable 2. ] [ Footer 1.", selectionAsString(frame));
3588 // If the selection is editable text, we can't extend it into non-editable text.
3589 frame->executeScript(WebScriptSource("selectElement('editable_1');"));
3590 EXPECT_EQ("Editable 1.", selectionAsString(frame));
3591 frame->selectRange(topLeft(elementBounds(frame, "editable_1")), bottomRightMinusOne(elementBounds(frame, "footer_1")));
3592 // positionForPoint returns the wrong values for contenteditable spans. See
3593 // http://crbug.com/238334.
3594 // EXPECT_EQ("Editable 1. Editable 2. ]", selectionAsString(frame));
3597 static int computeOffset(WebCore::RenderObject* renderer, int x, int y)
3599 return WebCore::VisiblePosition(renderer->positionForPoint(WebCore::LayoutPoint(x, y))).deepEquivalent().computeOffsetInContainerNode();
3602 // positionForPoint returns the wrong values for contenteditable spans. See
3603 // http://crbug.com/238334.
3604 TEST_F(WebFrameTest, DISABLED_PositionForPointTest)
3606 registerMockedHttpURLLoad("select_range_span_editable.html");
3607 FrameTestHelpers::WebViewHelper webViewHelper;
3608 initializeTextSelectionWebView(m_baseURL + "select_range_span_editable.html", &webViewHelper);
3609 WebFrameImpl* mainFrame = toWebFrameImpl(webViewHelper.webView()->mainFrame());
3610 WebCore::RenderObject* renderer = mainFrame->frame()->selection().rootEditableElement()->renderer();
3611 EXPECT_EQ(0, computeOffset(renderer, -1, -1));
3612 EXPECT_EQ(64, computeOffset(renderer, 1000, 1000));
3614 registerMockedHttpURLLoad("select_range_div_editable.html");
3615 initializeTextSelectionWebView(m_baseURL + "select_range_div_editable.html", &webViewHelper);
3616 mainFrame = toWebFrameImpl(webViewHelper.webView()->mainFrame());
3617 renderer = mainFrame->frame()->selection().rootEditableElement()->renderer();
3618 EXPECT_EQ(0, computeOffset(renderer, -1, -1));
3619 EXPECT_EQ(64, computeOffset(renderer, 1000, 1000));
3623 TEST_F(WebFrameTest, SelectRangeStaysHorizontallyAlignedWhenMoved)
3625 registerMockedHttpURLLoad("move_caret.html");
3627 FrameTestHelpers::WebViewHelper webViewHelper;
3628 initializeTextSelectionWebView(m_baseURL + "move_caret.html", &webViewHelper);
3629 WebFrameImpl* frame = toWebFrameImpl(webViewHelper.webView()->mainFrame());
3631 WebRect initialStartRect;
3632 WebRect initialEndRect;
3636 frame->executeScript(WebScriptSource("selectRange();"));
3637 webViewHelper.webView()->selectionBounds(initialStartRect, initialEndRect);
3638 WebPoint movedStart(topLeft(initialStartRect));
3641 frame->selectRange(movedStart, bottomRightMinusOne(initialEndRect));
3642 webViewHelper.webView()->selectionBounds(startRect, endRect);
3643 EXPECT_EQ(startRect, initialStartRect);
3644 EXPECT_EQ(endRect, initialEndRect);
3647 frame->selectRange(movedStart, bottomRightMinusOne(initialEndRect));
3648 webViewHelper.webView()->selectionBounds(startRect, endRect);
3649 EXPECT_EQ(startRect, initialStartRect);
3650 EXPECT_EQ(endRect, initialEndRect);
3652 WebPoint movedEnd(bottomRightMinusOne(initialEndRect));
3655 frame->selectRange(topLeft(initialStartRect), movedEnd);
3656 webViewHelper.webView()->selectionBounds(startRect, endRect);
3657 EXPECT_EQ(startRect, initialStartRect);
3658 EXPECT_EQ(endRect, initialEndRect);
3661 frame->selectRange(topLeft(initialStartRect), movedEnd);
3662 webViewHelper.webView()->selectionBounds(startRect, endRect);
3663 EXPECT_EQ(startRect, initialStartRect);
3664 EXPECT_EQ(endRect, initialEndRect);
3667 TEST_F(WebFrameTest, MoveCaretStaysHorizontallyAlignedWhenMoved)
3669 WebFrameImpl* frame;
3670 registerMockedHttpURLLoad("move_caret.html");
3672 FrameTestHelpers::WebViewHelper webViewHelper;
3673 initializeTextSelectionWebView(m_baseURL + "move_caret.html", &webViewHelper);
3674 frame = (WebFrameImpl*)webViewHelper.webView()->mainFrame();
3676 WebRect initialStartRect;
3677 WebRect initialEndRect;
3681 frame->executeScript(WebScriptSource("selectCaret();"));
3682 webViewHelper.webView()->selectionBounds(initialStartRect, initialEndRect);
3683 WebPoint moveTo(topLeft(initialStartRect));
3686 frame->moveCaretSelection(moveTo);
3687 webViewHelper.webView()->selectionBounds(startRect, endRect);
3688 EXPECT_EQ(startRect, initialStartRect);
3689 EXPECT_EQ(endRect, initialEndRect);
3692 frame->moveCaretSelection(moveTo);
3693 webViewHelper.webView()->selectionBounds(startRect, endRect);
3694 EXPECT_EQ(startRect, initialStartRect);
3695 EXPECT_EQ(endRect, initialEndRect);
3699 class DisambiguationPopupTestWebViewClient : public WebViewClient {
3701 virtual bool didTapMultipleTargets(const WebGestureEvent&, const WebVector<WebRect>& targetRects) OVERRIDE
3703 EXPECT_GE(targetRects.size(), 2u);
3708 bool triggered() const { return m_triggered; }
3709 void resetTriggered() { m_triggered = false; }
3713 static WebGestureEvent fatTap(int x, int y)
3715 WebGestureEvent event;
3716 event.type = WebInputEvent::GestureTap;
3719 event.data.tap.width = 50;
3720 event.data.tap.height = 50;
3724 TEST_F(WebFrameTest, DisambiguationPopup)
3726 const std::string htmlFile = "disambiguation_popup.html";
3727 registerMockedHttpURLLoad(htmlFile);
3729 DisambiguationPopupTestWebViewClient client;
3731 // Make sure we initialize to minimum scale, even if the window size
3732 // only becomes available after the load begins.
3733 FrameTestHelpers::WebViewHelper webViewHelper;
3734 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client);
3735 webViewHelper.webView()->resize(WebSize(1000, 1000));
3736 webViewHelper.webView()->layout();
3738 client.resetTriggered();
3739 webViewHelper.webView()->handleInputEvent(fatTap(0, 0));
3740 EXPECT_FALSE(client.triggered());
3742 client.resetTriggered();
3743 webViewHelper.webView()->handleInputEvent(fatTap(200, 115));
3744 EXPECT_FALSE(client.triggered());
3746 for (int i = 0; i <= 46; i++) {
3747 client.resetTriggered();
3748 webViewHelper.webView()->handleInputEvent(fatTap(120, 230 + i * 5));
3751 if (j >= 7 && j <= 9)
3752 EXPECT_TRUE(client.triggered());
3754 EXPECT_FALSE(client.triggered());
3757 for (int i = 0; i <= 46; i++) {
3758 client.resetTriggered();
3759 webViewHelper.webView()->handleInputEvent(fatTap(10 + i * 5, 590));
3762 if (j >= 7 && j <= 9)
3763 EXPECT_TRUE(client.triggered());
3765 EXPECT_FALSE(client.triggered());
3769 TEST_F(WebFrameTest, DisambiguationPopupNoContainer)
3771 registerMockedHttpURLLoad("disambiguation_popup_no_container.html");
3773 DisambiguationPopupTestWebViewClient client;
3775 // Make sure we initialize to minimum scale, even if the window size
3776 // only becomes available after the load begins.
3777 FrameTestHelpers::WebViewHelper webViewHelper;
3778 webViewHelper.initializeAndLoad(m_baseURL + "disambiguation_popup_no_container.html", true, 0, &client);
3779 webViewHelper.webView()->resize(WebSize(1000, 1000));
3780 webViewHelper.webView()->layout();
3782 client.resetTriggered();
3783 webViewHelper.webView()->handleInputEvent(fatTap(50, 50));
3784 EXPECT_FALSE(client.triggered());
3787 TEST_F(WebFrameTest, DisambiguationPopupMobileSite)
3789 UseMockScrollbarSettings mockScrollbarSettings;
3790 const std::string htmlFile = "disambiguation_popup_mobile_site.html";
3791 registerMockedHttpURLLoad(htmlFile);
3793 DisambiguationPopupTestWebViewClient client;
3795 // Make sure we initialize to minimum scale, even if the window size
3796 // only becomes available after the load begins.
3797 FrameTestHelpers::WebViewHelper webViewHelper;
3798 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client, enableViewportSettings);
3799 webViewHelper.webView()->resize(WebSize(1000, 1000));
3800 webViewHelper.webView()->layout();
3802 client.resetTriggered();
3803 webViewHelper.webView()->handleInputEvent(fatTap(0, 0));
3804 EXPECT_FALSE(client.triggered());
3806 client.resetTriggered();
3807 webViewHelper.webView()->handleInputEvent(fatTap(200, 115));
3808 EXPECT_FALSE(client.triggered());
3810 for (int i = 0; i <= 46; i++) {
3811 client.resetTriggered();
3812 webViewHelper.webView()->handleInputEvent(fatTap(120, 230 + i * 5));
3813 EXPECT_FALSE(client.triggered());
3816 for (int i = 0; i <= 46; i++) {
3817 client.resetTriggered();
3818 webViewHelper.webView()->handleInputEvent(fatTap(10 + i * 5, 590));
3819 EXPECT_FALSE(client.triggered());
3823 TEST_F(WebFrameTest, DisambiguationPopupViewportSite)
3825 UseMockScrollbarSettings mockScrollbarSettings;
3826 const std::string htmlFile = "disambiguation_popup_viewport_site.html";
3827 registerMockedHttpURLLoad(htmlFile);
3829 DisambiguationPopupTestWebViewClient client;
3831 // Make sure we initialize to minimum scale, even if the window size
3832 // only becomes available after the load begins.
3833 FrameTestHelpers::WebViewHelper webViewHelper;
3834 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client, enableViewportSettings);
3835 webViewHelper.webView()->resize(WebSize(1000, 1000));
3836 webViewHelper.webView()->layout();
3838 client.resetTriggered();
3839 webViewHelper.webView()->handleInputEvent(fatTap(0, 0));
3840 EXPECT_FALSE(client.triggered());
3842 client.resetTriggered();
3843 webViewHelper.webView()->handleInputEvent(fatTap(200, 115));
3844 EXPECT_FALSE(client.triggered());
3846 for (int i = 0; i <= 46; i++) {
3847 client.resetTriggered();
3848 webViewHelper.webView()->handleInputEvent(fatTap(120, 230 + i * 5));
3849 EXPECT_FALSE(client.triggered());
3852 for (int i = 0; i <= 46; i++) {
3853 client.resetTriggered();
3854 webViewHelper.webView()->handleInputEvent(fatTap(10 + i * 5, 590));
3855 EXPECT_FALSE(client.triggered());
3859 TEST_F(WebFrameTest, DisambiguationPopupBlacklist)
3861 const unsigned viewportWidth = 500;
3862 const unsigned viewportHeight = 1000;
3863 const unsigned divHeight = 100;
3864 const std::string htmlFile = "disambiguation_popup_blacklist.html";
3865 registerMockedHttpURLLoad(htmlFile);
3867 DisambiguationPopupTestWebViewClient client;
3869 // Make sure we initialize to minimum scale, even if the window size
3870 // only becomes available after the load begins.
3871 FrameTestHelpers::WebViewHelper webViewHelper;
3872 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client);
3873 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
3874 webViewHelper.webView()->layout();
3876 // Click somewhere where the popup shouldn't appear.
3877 client.resetTriggered();
3878 webViewHelper.webView()->handleInputEvent(fatTap(viewportWidth / 2, 0));
3879 EXPECT_FALSE(client.triggered());
3881 // Click directly in between two container divs with click handlers, with children that don't handle clicks.
3882 client.resetTriggered();
3883 webViewHelper.webView()->handleInputEvent(fatTap(viewportWidth / 2, divHeight));
3884 EXPECT_TRUE(client.triggered());
3886 // The third div container should be blacklisted if you click on the link it contains.
3887 client.resetTriggered();
3888 webViewHelper.webView()->handleInputEvent(fatTap(viewportWidth / 2, divHeight * 3.25));
3889 EXPECT_FALSE(client.triggered());
3892 TEST_F(WebFrameTest, DisambiguationPopupPageScale)
3894 registerMockedHttpURLLoad("disambiguation_popup_page_scale.html");
3896 DisambiguationPopupTestWebViewClient client;
3898 // Make sure we initialize to minimum scale, even if the window size
3899 // only becomes available after the load begins.
3900 FrameTestHelpers::WebViewHelper webViewHelper;
3901 webViewHelper.initializeAndLoad(m_baseURL + "disambiguation_popup_page_scale.html", true, 0, &client);
3902 webViewHelper.webView()->resize(WebSize(1000, 1000));
3903 webViewHelper.webView()->layout();
3905 client.resetTriggered();
3906 webViewHelper.webView()->handleInputEvent(fatTap(80, 80));
3907 EXPECT_TRUE(client.triggered());
3909 client.resetTriggered();
3910 webViewHelper.webView()->handleInputEvent(fatTap(230, 190));
3911 EXPECT_TRUE(client.triggered());
3913 webViewHelper.webView()->setPageScaleFactor(3.0f, WebPoint(0, 0));
3914 webViewHelper.webView()->layout();
3916 client.resetTriggered();
3917 webViewHelper.webView()->handleInputEvent(fatTap(240, 240));
3918 EXPECT_TRUE(client.triggered());
3920 client.resetTriggered();
3921 webViewHelper.webView()->handleInputEvent(fatTap(690, 570));
3922 EXPECT_FALSE(client.triggered());
3925 class TestSubstituteDataWebFrameClient : public WebFrameClient {
3927 TestSubstituteDataWebFrameClient()
3928 : m_commitCalled(false)
3932 virtual void didFailProvisionalLoad(WebFrame* frame, const WebURLError& error)
3934 frame->loadHTMLString("This should appear", toKURL("data:text/html,chromewebdata"), error.unreachableURL, true);
3938 virtual void didCommitProvisionalLoad(WebFrame* frame, bool)
3940 if (frame->dataSource()->response().url() != WebURL(URLTestHelpers::toKURL("about:blank")))
3941 m_commitCalled = true;
3944 bool commitCalled() const { return m_commitCalled; }
3947 bool m_commitCalled;
3950 TEST_F(WebFrameTest, ReplaceNavigationAfterHistoryNavigation)
3952 TestSubstituteDataWebFrameClient webFrameClient;
3954 FrameTestHelpers::WebViewHelper webViewHelper;
3955 webViewHelper.initializeAndLoad("about:blank", true, &webFrameClient);
3957 WebFrame* frame = webViewHelper.webView()->mainFrame();
3959 // Load a url as a history navigation that will return an error. TestSubstituteDataWebFrameClient
3960 // will start a SubstituteData load in response to the load failure, which should get fully committed.
3961 // Due to https://bugs.webkit.org/show_bug.cgi?id=91685, FrameLoader::didReceiveData() wasn't getting
3962 // called in this case, which resulted in the SubstituteData document not getting displayed.
3964 error.reason = 1337;
3965 error.domain = "WebFrameTest";
3966 std::string errorURL = "http://0.0.0.0";
3967 WebURLResponse response;
3968 response.initialize();
3969 response.setURL(URLTestHelpers::toKURL(errorURL));
3970 response.setMIMEType("text/html");
3971 response.setHTTPStatusCode(500);
3972 WebHistoryItem errorHistoryItem;
3973 errorHistoryItem.initialize();
3974 errorHistoryItem.setURLString(WebString::fromUTF8(errorURL.c_str(), errorURL.length()));
3975 errorHistoryItem.setOriginalURLString(WebString::fromUTF8(errorURL.c_str(), errorURL.length()));
3976 Platform::current()->unitTestSupport()->registerMockedErrorURL(URLTestHelpers::toKURL(errorURL), response, error);
3977 frame->loadHistoryItem(errorHistoryItem);
3978 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
3980 WebString text = frame->contentAsText(std::numeric_limits<size_t>::max());
3981 EXPECT_EQ("This should appear", text.utf8());
3982 EXPECT_TRUE(webFrameClient.commitCalled());
3985 class TestWillInsertBodyWebFrameClient : public WebFrameClient {
3987 TestWillInsertBodyWebFrameClient() : m_numBodies(0), m_didLoad(false)
3991 virtual void didCommitProvisionalLoad(WebFrame*, bool) OVERRIDE
3997 virtual void didCreateDocumentElement(WebFrame*) OVERRIDE
3999 EXPECT_EQ(0, m_numBodies);
4002 virtual void willInsertBody(WebFrame*) OVERRIDE
4011 TEST_F(WebFrameTest, HTMLDocument)
4013 registerMockedHttpURLLoad("clipped-body.html");
4015 TestWillInsertBodyWebFrameClient webFrameClient;
4016 FrameTestHelpers::WebViewHelper webViewHelper;
4017 webViewHelper.initializeAndLoad(m_baseURL + "clipped-body.html", false, &webFrameClient);
4019 EXPECT_TRUE(webFrameClient.m_didLoad);
4020 EXPECT_EQ(1, webFrameClient.m_numBodies);
4023 TEST_F(WebFrameTest, EmptyDocument)
4025 registerMockedHttpURLLoad("pageserializer/green_rectangle.svg");
4027 TestWillInsertBodyWebFrameClient webFrameClient;
4028 FrameTestHelpers::WebViewHelper webViewHelper;
4029 webViewHelper.initialize(false, &webFrameClient);
4031 EXPECT_FALSE(webFrameClient.m_didLoad);
4032 EXPECT_EQ(1, webFrameClient.m_numBodies); // The empty document that a new frame starts with triggers this.
4035 TEST_F(WebFrameTest, MoveCaretSelectionTowardsWindowPointWithNoSelection)
4037 FrameTestHelpers::WebViewHelper webViewHelper;
4038 webViewHelper.initializeAndLoad("about:blank", true);
4039 WebFrame* frame = webViewHelper.webView()->mainFrame();
4041 // This test passes if this doesn't crash.
4042 frame->moveCaretSelection(WebPoint(0, 0));
4045 class SpellCheckClient : public WebSpellCheckClient {
4047 explicit SpellCheckClient(uint32_t hash = 0) : m_numberOfTimesChecked(0), m_hash(hash) { }
4048 virtual ~SpellCheckClient() { }
4049 virtual void requestCheckingOfText(const blink::WebString&, const blink::WebVector<uint32_t>&, const blink::WebVector<unsigned>&, blink::WebTextCheckingCompletion* completion) OVERRIDE
4051 ++m_numberOfTimesChecked;
4052 Vector<WebTextCheckingResult> results;
4053 const int misspellingStartOffset = 1;
4054 const int misspellingLength = 8;
4055 results.append(WebTextCheckingResult(WebTextDecorationTypeSpelling, misspellingStartOffset, misspellingLength, WebString(), m_hash));
4056 completion->didFinishCheckingText(results);
4058 int numberOfTimesChecked() const { return m_numberOfTimesChecked; }
4060 int m_numberOfTimesChecked;
4064 TEST_F(WebFrameTest, ReplaceMisspelledRange)
4066 registerMockedHttpURLLoad("spell.html");
4067 FrameTestHelpers::WebViewHelper webViewHelper;
4068 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4069 SpellCheckClient spellcheck;
4070 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4072 WebFrameImpl* frame = toWebFrameImpl(webViewHelper.webView()->mainFrame());
4073 Document* document = frame->frame()->document();
4074 Element* element = document->getElementById("data");
4076 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4077 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4078 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4081 document->execCommand("InsertText", false, "_wellcome_.");
4083 const int allTextBeginOffset = 0;
4084 const int allTextLength = 11;
4085 frame->selectRange(WebRange::fromDocumentRange(frame, allTextBeginOffset, allTextLength));
4086 RefPtr<Range> selectionRange = frame->frame()->selection().toNormalizedRange();
4088 EXPECT_EQ(1, spellcheck.numberOfTimesChecked());
4089 EXPECT_EQ(1U, document->markers()->markersInRange(selectionRange.get(), DocumentMarker::Spelling).size());
4091 frame->replaceMisspelledRange("welcome");
4092 EXPECT_EQ("_welcome_.", frame->contentAsText(std::numeric_limits<size_t>::max()).utf8());
4095 TEST_F(WebFrameTest, RemoveSpellingMarkers)
4097 registerMockedHttpURLLoad("spell.html");
4098 FrameTestHelpers::WebViewHelper webViewHelper;
4099 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4100 SpellCheckClient spellcheck;
4101 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4103 WebFrameImpl* frame = toWebFrameImpl(webViewHelper.webView()->mainFrame());
4104 Document* document = frame->frame()->document();
4105 Element* element = document->getElementById("data");
4107 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4108 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4109 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4112 document->execCommand("InsertText", false, "_wellcome_.");
4114 frame->removeSpellingMarkers();
4116 const int allTextBeginOffset = 0;
4117 const int allTextLength = 11;
4118 frame->selectRange(WebRange::fromDocumentRange(frame, allTextBeginOffset, allTextLength));
4119 RefPtr<Range> selectionRange = frame->frame()->selection().toNormalizedRange();
4121 EXPECT_EQ(0U, document->markers()->markersInRange(selectionRange.get(), DocumentMarker::Spelling).size());
4124 TEST_F(WebFrameTest, MarkerHashIdentifiers) {
4125 registerMockedHttpURLLoad("spell.html");
4126 FrameTestHelpers::WebViewHelper webViewHelper;
4127 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4129 static const uint32_t kHash = 42;
4130 SpellCheckClient spellcheck(kHash);
4131 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4133 WebFrameImpl* frame = toWebFrameImpl(webViewHelper.webView()->mainFrame());
4134 Document* document = frame->frame()->document();
4135 Element* element = document->getElementById("data");
4137 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4138 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4139 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4142 document->execCommand("InsertText", false, "wellcome.");
4144 WebVector<uint32_t> documentMarkers;
4145 webViewHelper.webView()->spellingMarkers(&documentMarkers);
4146 EXPECT_EQ(1U, documentMarkers.size());
4147 EXPECT_EQ(kHash, documentMarkers[0]);
4150 class StubbornSpellCheckClient : public WebSpellCheckClient {
4152 StubbornSpellCheckClient() : m_completion(0) { }
4153 virtual ~StubbornSpellCheckClient() { }
4155 virtual void requestCheckingOfText(
4156 const blink::WebString&,
4157 const blink::WebVector<uint32_t>&,
4158 const blink::WebVector<unsigned>&,
4159 blink::WebTextCheckingCompletion* completion) OVERRIDE
4161 m_completion = completion;
4164 void kickNoResults()
4166 kick(-1, -1, WebTextDecorationTypeSpelling);
4171 kick(1, 8, WebTextDecorationTypeSpelling);
4176 kick(1, 8, WebTextDecorationTypeGrammar);
4179 void kickInvisibleSpellcheck()
4181 kick(1, 8, WebTextDecorationTypeInvisibleSpellcheck);
4185 void kick(int misspellingStartOffset, int misspellingLength, WebTextDecorationType type)
4189 Vector<WebTextCheckingResult> results;
4190 if (misspellingStartOffset >= 0 && misspellingLength > 0)
4191 results.append(WebTextCheckingResult(type, misspellingStartOffset, misspellingLength));
4192 m_completion->didFinishCheckingText(results);
4196 blink::WebTextCheckingCompletion* m_completion;
4199 TEST_F(WebFrameTest, SlowSpellcheckMarkerPosition)
4201 registerMockedHttpURLLoad("spell.html");
4202 FrameTestHelpers::WebViewHelper webViewHelper;
4203 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4205 StubbornSpellCheckClient spellcheck;
4206 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4208 WebFrameImpl* frame = toWebFrameImpl(webViewHelper.webView()->mainFrame());
4209 WebInputElement webInputElement = frame->document().getElementById("data").to<WebInputElement>();
4210 Document* document = frame->frame()->document();
4211 Element* element = document->getElementById("data");
4213 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4214 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4215 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4218 document->execCommand("InsertText", false, "wellcome ");
4219 webInputElement.setSelectionRange(0, 0);
4220 document->execCommand("InsertText", false, "he");
4224 WebVector<uint32_t> documentMarkers;
4225 webViewHelper.webView()->spellingMarkers(&documentMarkers);
4226 EXPECT_EQ(0U, documentMarkers.size());
4229 // This test verifies that cancelling spelling request does not cause a
4230 // write-after-free when there's no spellcheck client set.
4231 TEST_F(WebFrameTest, CancelSpellingRequestCrash)
4233 registerMockedHttpURLLoad("spell.html");
4234 FrameTestHelpers::WebViewHelper webViewHelper;
4235 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4236 webViewHelper.webView()->setSpellCheckClient(0);
4238 WebFrameImpl* frame = toWebFrameImpl(webViewHelper.webView()->mainFrame());
4239 Document* document = frame->frame()->document();
4240 Element* element = document->getElementById("data");
4242 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4243 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4244 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4247 frame->frame()->editor().replaceSelectionWithText("A", false, false);
4248 frame->frame()->spellChecker().cancelCheck();
4251 TEST_F(WebFrameTest, SpellcheckResultErasesMarkers)
4253 registerMockedHttpURLLoad("spell.html");
4254 FrameTestHelpers::WebViewHelper webViewHelper;
4255 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4257 StubbornSpellCheckClient spellcheck;
4258 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4260 WebFrameImpl* frame = toWebFrameImpl(webViewHelper.webView()->mainFrame());
4261 WebInputElement webInputElement = frame->document().getElementById("data").to<WebInputElement>();
4262 Document* document = frame->frame()->document();
4263 Element* element = document->getElementById("data");
4265 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4266 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4267 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4270 document->execCommand("InsertText", false, "welcome ");
4271 document->markers()->addMarker(rangeOfContents(element->toNode()).get(), DocumentMarker::Spelling);
4272 document->markers()->addMarker(rangeOfContents(element->toNode()).get(), DocumentMarker::Grammar);
4273 document->markers()->addMarker(rangeOfContents(element->toNode()).get(), DocumentMarker::InvisibleSpellcheck);
4274 EXPECT_EQ(3U, document->markers()->markers().size());
4276 spellcheck.kickNoResults();
4277 EXPECT_EQ(0U, document->markers()->markers().size());
4280 TEST_F(WebFrameTest, SpellcheckResultsSavedInDocument)
4282 registerMockedHttpURLLoad("spell.html");
4283 FrameTestHelpers::WebViewHelper webViewHelper;
4284 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4286 StubbornSpellCheckClient spellcheck;
4287 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4289 WebFrameImpl* frame = toWebFrameImpl(webViewHelper.webView()->mainFrame());
4290 WebInputElement webInputElement = frame->document().getElementById("data").to<WebInputElement>();
4291 Document* document = frame->frame()->document();
4292 Element* element = document->getElementById("data");
4294 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4295 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4296 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4299 document->execCommand("InsertText", false, "wellcome ");
4302 ASSERT_EQ(1U, document->markers()->markers().size());
4303 ASSERT_NE(static_cast<DocumentMarker*>(0), document->markers()->markers()[0]);
4304 EXPECT_EQ(DocumentMarker::Spelling, document->markers()->markers()[0]->type());
4306 document->execCommand("InsertText", false, "wellcome ");
4308 spellcheck.kickGrammar();
4309 ASSERT_EQ(1U, document->markers()->markers().size());
4310 ASSERT_NE(static_cast<DocumentMarker*>(0), document->markers()->markers()[0]);
4311 EXPECT_EQ(DocumentMarker::Grammar, document->markers()->markers()[0]->type());
4313 document->execCommand("InsertText", false, "wellcome ");
4315 spellcheck.kickInvisibleSpellcheck();
4316 ASSERT_EQ(1U, document->markers()->markers().size());
4317 ASSERT_NE(static_cast<DocumentMarker*>(0), document->markers()->markers()[0]);
4318 EXPECT_EQ(DocumentMarker::InvisibleSpellcheck, document->markers()->markers()[0]->type());
4321 class TestAccessInitialDocumentWebFrameClient : public WebFrameClient {
4323 TestAccessInitialDocumentWebFrameClient() : m_didAccessInitialDocument(false)
4327 virtual void didAccessInitialDocument(WebFrame* frame)
4329 EXPECT_TRUE(!m_didAccessInitialDocument);
4330 m_didAccessInitialDocument = true;
4333 bool m_didAccessInitialDocument;
4336 TEST_F(WebFrameTest, DidAccessInitialDocumentBody)
4338 TestAccessInitialDocumentWebFrameClient webFrameClient;
4339 FrameTestHelpers::WebViewHelper webViewHelper;
4340 webViewHelper.initialize(true, &webFrameClient);
4342 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4344 // Create another window that will try to access it.
4345 FrameTestHelpers::WebViewHelper newWebViewHelper;
4346 WebView* newView = newWebViewHelper.initialize(true);
4347 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
4349 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4351 // Access the initial document by modifying the body.
4352 newView->mainFrame()->executeScript(
4353 WebScriptSource("window.opener.document.body.innerHTML += 'Modified';"));
4355 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4357 // Access the initial document again, to ensure we don't notify twice.
4358 newView->mainFrame()->executeScript(
4359 WebScriptSource("window.opener.document.body.innerHTML += 'Modified';"));
4361 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4364 TEST_F(WebFrameTest, DidAccessInitialDocumentNavigator)
4366 TestAccessInitialDocumentWebFrameClient webFrameClient;
4367 FrameTestHelpers::WebViewHelper webViewHelper;
4368 webViewHelper.initialize(true, &webFrameClient);
4370 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4372 // Create another window that will try to access it.
4373 FrameTestHelpers::WebViewHelper newWebViewHelper;
4374 WebView* newView = newWebViewHelper.initialize(true);
4375 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
4377 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4379 // Access the initial document to get to the navigator object.
4380 newView->mainFrame()->executeScript(
4381 WebScriptSource("console.log(window.opener.navigator);"));
4383 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4386 TEST_F(WebFrameTest, DidAccessInitialDocumentViaJavascriptUrl)
4388 TestAccessInitialDocumentWebFrameClient webFrameClient;
4389 FrameTestHelpers::WebViewHelper webViewHelper;
4390 webViewHelper.initialize(true, &webFrameClient);
4392 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4394 // Access the initial document from a javascript: URL.
4395 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.appendChild(document.createTextNode('Modified'))");
4397 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4400 // Fails on the WebKit XP (deps) bot. http://crbug.com/312192
4402 TEST_F(WebFrameTest, DISABLED_DidAccessInitialDocumentBodyBeforeModalDialog)
4404 TEST_F(WebFrameTest, DidAccessInitialDocumentBodyBeforeModalDialog)
4407 TestAccessInitialDocumentWebFrameClient webFrameClient;
4408 FrameTestHelpers::WebViewHelper webViewHelper;
4409 webViewHelper.initialize(true, &webFrameClient);
4411 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4413 // Create another window that will try to access it.
4414 FrameTestHelpers::WebViewHelper newWebViewHelper;
4415 WebView* newView = newWebViewHelper.initialize(true);
4416 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
4418 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4420 // Access the initial document by modifying the body. We normally set a
4421 // timer to notify the client.
4422 newView->mainFrame()->executeScript(
4423 WebScriptSource("window.opener.document.body.innerHTML += 'Modified';"));
4424 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4426 // Make sure that a modal dialog forces us to notify right away.
4427 newView->mainFrame()->executeScript(
4428 WebScriptSource("window.opener.confirm('Modal');"));
4429 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4431 // Ensure that we don't notify again later.
4433 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4436 // Fails on the WebKit XP (deps) bot. http://crbug.com/312192
4438 TEST_F(WebFrameTest, DISABLED_DidWriteToInitialDocumentBeforeModalDialog)
4440 TEST_F(WebFrameTest, DidWriteToInitialDocumentBeforeModalDialog)
4443 TestAccessInitialDocumentWebFrameClient webFrameClient;
4444 FrameTestHelpers::WebViewHelper webViewHelper;
4445 webViewHelper.initialize(true, &webFrameClient);
4447 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4449 // Create another window that will try to access it.
4450 FrameTestHelpers::WebViewHelper newWebViewHelper;
4451 WebView* newView = newWebViewHelper.initialize(true);
4452 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
4454 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4456 // Access the initial document with document.write, which moves us past the
4457 // initial empty document state of the state machine. We normally set a
4458 // timer to notify the client.
4459 newView->mainFrame()->executeScript(
4460 WebScriptSource("window.opener.document.write('Modified');"));
4461 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4463 // Make sure that a modal dialog forces us to notify right away.
4464 newView->mainFrame()->executeScript(
4465 WebScriptSource("window.opener.confirm('Modal');"));
4466 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4468 // Ensure that we don't notify again later.
4470 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4473 class TestMainFrameUserOrProgrammaticScrollFrameClient : public WebFrameClient {
4475 TestMainFrameUserOrProgrammaticScrollFrameClient() { reset(); }
4478 m_didScrollMainFrame = false;
4479 m_wasProgrammaticScroll = false;
4481 bool wasUserScroll() const { return m_didScrollMainFrame && !m_wasProgrammaticScroll; }
4482 bool wasProgrammaticScroll() const { return m_didScrollMainFrame && m_wasProgrammaticScroll; }
4485 virtual void didChangeScrollOffset(WebFrame* frame) OVERRIDE
4487 if (frame->parent())
4489 EXPECT_FALSE(m_didScrollMainFrame);
4490 WebCore::FrameView* view = toWebFrameImpl(frame)->frameView();
4491 // FrameView can be scrolled in FrameView::setFixedVisibleContentRect
4492 // which is called from Frame::createView (before the frame is associated
4493 // with the the view).
4495 m_didScrollMainFrame = true;
4496 m_wasProgrammaticScroll = view->inProgrammaticScroll();
4500 bool m_didScrollMainFrame;
4501 bool m_wasProgrammaticScroll;
4504 TEST_F(WebFrameTest, CompositorScrollIsUserScrollLongPage)
4506 registerMockedHttpURLLoad("long_scroll.html");
4507 TestMainFrameUserOrProgrammaticScrollFrameClient client;
4509 // Make sure we initialize to minimum scale, even if the window size
4510 // only becomes available after the load begins.
4511 FrameTestHelpers::WebViewHelper webViewHelper;
4512 webViewHelper.initializeAndLoad(m_baseURL + "long_scroll.html", true, &client);
4513 webViewHelper.webView()->resize(WebSize(1000, 1000));
4514 webViewHelper.webView()->layout();
4516 EXPECT_FALSE(client.wasUserScroll());
4517 EXPECT_FALSE(client.wasProgrammaticScroll());
4519 // Do a compositor scroll, verify that this is counted as a user scroll.
4520 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(0, 1), 1.1f);
4521 EXPECT_TRUE(client.wasUserScroll());
4524 EXPECT_FALSE(client.wasUserScroll());
4525 EXPECT_FALSE(client.wasProgrammaticScroll());
4527 // The page scale 1.0f and scroll.
4528 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(0, 1), 1.0f);
4529 EXPECT_TRUE(client.wasUserScroll());
4532 // No scroll event if there is no scroll delta.
4533 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.0f);
4534 EXPECT_FALSE(client.wasUserScroll());
4535 EXPECT_FALSE(client.wasProgrammaticScroll());
4538 // Non zero page scale and scroll.
4539 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(9, 13), 0.6f);
4540 EXPECT_TRUE(client.wasUserScroll());
4543 // Programmatic scroll.
4544 WebFrameImpl* frameImpl = webViewHelper.webViewImpl()->mainFrameImpl();
4545 frameImpl->executeScript(WebScriptSource("window.scrollTo(0, 20);"));
4546 EXPECT_FALSE(client.wasUserScroll());
4547 EXPECT_TRUE(client.wasProgrammaticScroll());
4550 // Programmatic scroll to same offset. No scroll event should be generated.
4551 frameImpl->executeScript(WebScriptSource("window.scrollTo(0, 20);"));
4552 EXPECT_FALSE(client.wasProgrammaticScroll());
4553 EXPECT_FALSE(client.wasUserScroll());
4557 TEST_F(WebFrameTest, CompositorScrollIsUserScrollShortPage)
4559 registerMockedHttpURLLoad("short_scroll.html");
4561 TestMainFrameUserOrProgrammaticScrollFrameClient client;
4563 // Short page tests.
4564 FrameTestHelpers::WebViewHelper webViewHelper;
4565 webViewHelper.initializeAndLoad(m_baseURL + "short_scroll.html", true, &client);
4567 webViewHelper.webView()->resize(WebSize(1000, 1000));
4568 webViewHelper.webView()->layout();
4570 EXPECT_FALSE(client.wasUserScroll());
4571 EXPECT_FALSE(client.wasProgrammaticScroll());
4573 // Non zero page scale and scroll.
4574 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(9, 13), 2.0f);
4575 EXPECT_FALSE(client.wasProgrammaticScroll());
4576 EXPECT_TRUE(client.wasUserScroll());
4580 TEST_F(WebFrameTest, FirstPartyForCookiesForRedirect)
4582 WTF::String filePath = Platform::current()->unitTestSupport()->webKitRootDir();
4583 filePath.append("/Source/web/tests/data/first_party.html");
4585 WebURL testURL(toKURL("http://www.test.com/first_party_redirect.html"));
4586 char redirect[] = "http://www.test.com/first_party.html";
4587 WebURL redirectURL(toKURL(redirect));
4588 WebURLResponse redirectResponse;
4589 redirectResponse.initialize();
4590 redirectResponse.setMIMEType("text/html");
4591 redirectResponse.setHTTPStatusCode(302);
4592 redirectResponse.setHTTPHeaderField("Location", redirect);
4593 Platform::current()->unitTestSupport()->registerMockedURL(testURL, redirectResponse, filePath);
4595 WebURLResponse finalResponse;
4596 finalResponse.initialize();
4597 finalResponse.setMIMEType("text/html");
4598 Platform::current()->unitTestSupport()->registerMockedURL(redirectURL, finalResponse, filePath);
4600 FrameTestHelpers::WebViewHelper webViewHelper;
4601 webViewHelper.initializeAndLoad(m_baseURL + "first_party_redirect.html", true);
4602 EXPECT_TRUE(webViewHelper.webView()->mainFrame()->document().firstPartyForCookies() == redirectURL);
4605 class TestNavigationPolicyWebFrameClient : public WebFrameClient {
4608 virtual void didNavigateWithinPage(WebFrame*, bool)
4614 TEST_F(WebFrameTest, SimulateFragmentAnchorMiddleClick)
4616 registerMockedHttpURLLoad("fragment_middle_click.html");
4617 TestNavigationPolicyWebFrameClient client;
4618 FrameTestHelpers::WebViewHelper webViewHelper;
4619 webViewHelper.initializeAndLoad(m_baseURL + "fragment_middle_click.html", true, &client);
4621 WebCore::Document* document = webViewHelper.webViewImpl()->page()->mainFrame()->document();
4622 WebCore::KURL destination = document->url();
4623 destination.setFragmentIdentifier("test");
4625 RefPtr<WebCore::Event> event = WebCore::MouseEvent::create(WebCore::EventTypeNames::click, false, false,
4626 document->domWindow(), 0, 0, 0, 0, 0, 0, 0, false, false, false, false, 1, 0, 0);
4627 WebCore::FrameLoadRequest frameRequest(document, WebCore::ResourceRequest(destination));
4628 frameRequest.setTriggeringEvent(event);
4629 webViewHelper.webViewImpl()->page()->mainFrame()->loader().load(frameRequest);
4632 TEST_F(WebFrameTest, BackToReload)
4634 registerMockedHttpURLLoad("fragment_middle_click.html");
4635 FrameTestHelpers::WebViewHelper webViewHelper;
4636 webViewHelper.initializeAndLoad(m_baseURL + "fragment_middle_click.html", true);
4637 WebFrame* frame = webViewHelper.webView()->mainFrame();
4638 WebHistoryItem firstItem = frame->currentHistoryItem();
4639 EXPECT_FALSE(firstItem.isNull());
4641 registerMockedHttpURLLoad("white-1x1.png");
4642 FrameTestHelpers::loadFrame(frame, m_baseURL + "white-1x1.png");
4643 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4644 EXPECT_FALSE(frame->previousHistoryItem().isNull());
4645 EXPECT_EQ(firstItem.urlString(), frame->previousHistoryItem().urlString());
4647 frame->loadHistoryItem(frame->previousHistoryItem());
4648 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4649 EXPECT_EQ(firstItem.urlString(), frame->currentHistoryItem().urlString());
4652 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4653 EXPECT_EQ(WebURLRequest::ReloadIgnoringCacheData, frame->dataSource()->request().cachePolicy());
4656 TEST_F(WebFrameTest, BackDuringChildFrameReload)
4658 registerMockedHttpURLLoad("page_with_blank_iframe.html");
4659 FrameTestHelpers::WebViewHelper webViewHelper;
4660 webViewHelper.initializeAndLoad(m_baseURL + "page_with_blank_iframe.html", true);
4661 WebFrame* mainFrame = webViewHelper.webView()->mainFrame();
4662 WebFrame* childFrame = mainFrame->firstChild();
4663 ASSERT_TRUE(childFrame);
4665 // Start a history navigation, then have a different frame commit a navigation.
4666 // In this case, reload an about:blank frame, which will commit synchronously.
4667 // After the history navigation completes, both the appropriate document url and
4668 // the current history item should reflect the history navigation.
4669 registerMockedHttpURLLoad("white-1x1.png");
4670 WebHistoryItem item;
4672 WebURL historyURL(toKURL(m_baseURL + "white-1x1.png"));
4673 item.setURLString(historyURL.string());
4674 mainFrame->loadHistoryItem(item);
4676 childFrame->reload();
4677 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4678 EXPECT_EQ(item.urlString(), mainFrame->document().url().string());
4679 EXPECT_EQ(item.urlString(), mainFrame->currentHistoryItem().urlString());
4682 TEST_F(WebFrameTest, ReloadPost)
4684 registerMockedHttpURLLoad("reload_post.html");
4685 FrameTestHelpers::WebViewHelper webViewHelper;
4686 webViewHelper.initializeAndLoad(m_baseURL + "reload_post.html", true);
4687 WebFrame* frame = webViewHelper.webView()->mainFrame();
4689 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.forms[0].submit()");
4691 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4692 EXPECT_FALSE(frame->previousHistoryItem().isNull());
4693 EXPECT_EQ(WebString::fromUTF8("POST"), frame->dataSource()->request().httpMethod());
4696 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4697 EXPECT_EQ(WebURLRequest::ReloadIgnoringCacheData, frame->dataSource()->request().cachePolicy());
4698 EXPECT_EQ(WebNavigationTypeFormResubmitted, frame->dataSource()->navigationType());
4701 TEST_F(WebFrameTest, LoadHistoryItemReload)
4703 registerMockedHttpURLLoad("fragment_middle_click.html");
4704 FrameTestHelpers::WebViewHelper webViewHelper;
4705 webViewHelper.initializeAndLoad(m_baseURL + "fragment_middle_click.html", true);
4706 WebFrame* frame = webViewHelper.webView()->mainFrame();
4707 WebHistoryItem firstItem = frame->currentHistoryItem();
4708 EXPECT_FALSE(firstItem.isNull());
4710 registerMockedHttpURLLoad("white-1x1.png");
4711 FrameTestHelpers::loadFrame(frame, m_baseURL + "white-1x1.png");
4712 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4713 EXPECT_FALSE(frame->previousHistoryItem().isNull());
4714 EXPECT_EQ(firstItem.urlString(), frame->previousHistoryItem().urlString());
4716 // Cache policy overrides should take.
4717 frame->loadHistoryItem(frame->previousHistoryItem(), WebURLRequest::ReloadIgnoringCacheData);
4718 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4719 EXPECT_EQ(firstItem.urlString(), frame->currentHistoryItem().urlString());
4720 EXPECT_EQ(WebURLRequest::ReloadIgnoringCacheData, frame->dataSource()->request().cachePolicy());
4724 class TestCachePolicyWebFrameClient : public WebFrameClient {
4726 TestCachePolicyWebFrameClient()
4727 : m_policy(WebURLRequest::UseProtocolCachePolicy)
4729 , m_willSendRequestCallCount(0)
4730 , m_childFrameCreationCount(0)
4734 void setChildWebFrameClient(WebFrameClient* client) { m_client = client; }
4735 WebURLRequest::CachePolicy cachePolicy() const { return m_policy; }
4736 int willSendRequestCallCount() const { return m_willSendRequestCallCount; }
4737 int childFrameCreationCount() const { return m_childFrameCreationCount; }
4739 virtual WebFrame* createChildFrame(WebFrame* parent, const WebString&)
4741 m_childFrameCreationCount++;
4742 WebFrame* frame = WebFrame::create(m_client);
4743 parent->appendChild(frame);
4747 virtual void frameDetached(WebFrame* frame) OVERRIDE
4749 if (frame->parent())
4750 frame->parent()->removeChild(frame);
4754 virtual void willSendRequest(WebFrame* frame, unsigned, WebURLRequest& request, const WebURLResponse&) OVERRIDE
4756 m_policy = request.cachePolicy();
4757 m_willSendRequestCallCount++;
4761 WebURLRequest::CachePolicy m_policy;
4762 WebFrameClient* m_client;
4763 int m_willSendRequestCallCount;
4764 int m_childFrameCreationCount;
4767 TEST_F(WebFrameTest, ReloadIframe)
4769 registerMockedHttpURLLoad("iframe_reload.html");
4770 registerMockedHttpURLLoad("visible_iframe.html");
4771 TestCachePolicyWebFrameClient mainClient;
4772 TestCachePolicyWebFrameClient childClient;
4773 mainClient.setChildWebFrameClient(&childClient);
4775 FrameTestHelpers::WebViewHelper webViewHelper;
4776 webViewHelper.initializeAndLoad(m_baseURL + "iframe_reload.html", true, &mainClient);
4778 WebFrameImpl* mainFrame = webViewHelper.webViewImpl()->mainFrameImpl();
4779 RefPtr<WebFrameImpl> childFrame = toWebFrameImpl(mainFrame->firstChild());
4780 ASSERT_EQ(childFrame->client(), &childClient);
4781 EXPECT_EQ(mainClient.childFrameCreationCount(), 1);
4782 EXPECT_EQ(childClient.willSendRequestCallCount(), 1);
4783 EXPECT_EQ(childClient.cachePolicy(), WebURLRequest::UseProtocolCachePolicy);
4785 mainFrame->reload(false);
4786 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4788 // A new WebFrame should have been created, but the child WebFrameClient should be reused.
4789 ASSERT_NE(childFrame, toWebFrameImpl(mainFrame->firstChild()));
4790 ASSERT_EQ(toWebFrameImpl(mainFrame->firstChild())->client(), &childClient);
4792 EXPECT_EQ(mainClient.childFrameCreationCount(), 2);
4793 EXPECT_EQ(childClient.willSendRequestCallCount(), 2);
4794 EXPECT_EQ(childClient.cachePolicy(), WebURLRequest::ReloadIgnoringCacheData);
4797 TEST_F(WebFrameTest, ExportHistoryItemFromChildFrame)
4799 registerMockedHttpURLLoad("iframe_reload.html");
4800 registerMockedHttpURLLoad("visible_iframe.html");
4801 TestCachePolicyWebFrameClient mainClient;
4802 TestCachePolicyWebFrameClient childClient;
4803 mainClient.setChildWebFrameClient(&childClient);
4805 FrameTestHelpers::WebViewHelper webViewHelper;
4806 webViewHelper.initializeAndLoad(m_baseURL + "iframe_reload.html", true, &mainClient);
4808 WebFrame* childFrame = webViewHelper.webViewImpl()->mainFrameImpl()->firstChild();
4809 WebHistoryItem item = childFrame->currentHistoryItem();
4810 EXPECT_EQ(item.urlString().utf8(), m_baseURL + "iframe_reload.html");
4813 class TestSameDocumentWebFrameClient : public WebFrameClient {
4815 TestSameDocumentWebFrameClient()
4816 : m_frameLoadTypeSameSeen(false)
4820 virtual void willSendRequest(WebFrame* frame, unsigned, WebURLRequest&, const WebURLResponse&)
4822 if (toWebFrameImpl(frame)->frame()->loader().loadType() == WebCore::FrameLoadTypeSame)
4823 m_frameLoadTypeSameSeen = true;
4826 bool frameLoadTypeSameSeen() const { return m_frameLoadTypeSameSeen; }
4829 bool m_frameLoadTypeSameSeen;
4832 TEST_F(WebFrameTest, NavigateToSame)
4834 registerMockedHttpURLLoad("navigate_to_same.html");
4835 TestSameDocumentWebFrameClient client;
4836 FrameTestHelpers::WebViewHelper webViewHelper;
4837 webViewHelper.initializeAndLoad(m_baseURL + "navigate_to_same.html", true, &client);
4838 EXPECT_FALSE(client.frameLoadTypeSameSeen());
4840 WebCore::FrameLoadRequest frameRequest(0, WebCore::ResourceRequest(webViewHelper.webViewImpl()->page()->mainFrame()->document()->url()));
4841 webViewHelper.webViewImpl()->page()->mainFrame()->loader().load(frameRequest);
4842 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4844 EXPECT_TRUE(client.frameLoadTypeSameSeen());
4847 TEST_F(WebFrameTest, WebNodeImageContents)
4849 FrameTestHelpers::WebViewHelper webViewHelper;
4850 webViewHelper.initializeAndLoad("about:blank", true);
4851 WebFrame* frame = webViewHelper.webView()->mainFrame();
4853 static const char bluePNG[] = "<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAGElEQVQYV2NkYPj/n4EIwDiqEF8oUT94AFIQE/cCn90IAAAAAElFTkSuQmCC\">";
4855 // Load up the image and test that we can extract the contents.
4856 WebCore::KURL testURL = toKURL("about:blank");
4857 frame->loadHTMLString(bluePNG, testURL);
4860 WebNode node = frame->document().body().firstChild();
4861 EXPECT_TRUE(node.isElementNode());
4862 WebElement element = node.to<WebElement>();
4863 WebImage image = element.imageContents();
4864 ASSERT_FALSE(image.isNull());
4865 EXPECT_EQ(image.size().width, 10);
4866 EXPECT_EQ(image.size().height, 10);
4867 // FIXME: The rest of this test is disabled since the ImageDecodeCache state may be inconsistent when this test runs.
4869 // SkBitmap bitmap = image.getSkBitmap();
4870 // SkAutoLockPixels locker(bitmap);
4871 // EXPECT_EQ(bitmap.getColor(0, 0), SK_ColorBLUE);
4874 class TestStartStopCallbackWebViewClient : public WebViewClient {
4876 TestStartStopCallbackWebViewClient()
4877 : m_startLoadingCount(0)
4878 , m_stopLoadingCount(0)
4879 , m_differentDocumentStartCount(0)
4883 virtual void didStartLoading(bool toDifferentDocument) OVERRIDE
4885 m_startLoadingCount++;
4886 if (toDifferentDocument)
4887 m_differentDocumentStartCount++;
4890 virtual void didStopLoading() OVERRIDE
4892 m_stopLoadingCount++;
4895 int startLoadingCount() const { return m_startLoadingCount; }
4896 int stopLoadingCount() const { return m_stopLoadingCount; }
4897 int differentDocumentStartCount() const { return m_differentDocumentStartCount; }
4900 int m_startLoadingCount;
4901 int m_stopLoadingCount;
4902 int m_differentDocumentStartCount;
4905 TEST_F(WebFrameTest, PushStateStartsAndStops)
4907 registerMockedHttpURLLoad("push_state.html");
4908 TestStartStopCallbackWebViewClient client;
4909 FrameTestHelpers::WebViewHelper webViewHelper;
4910 webViewHelper.initializeAndLoad(m_baseURL + "push_state.html", true, 0, &client);
4913 EXPECT_EQ(client.startLoadingCount(), 2);
4914 EXPECT_EQ(client.stopLoadingCount(), 2);
4915 EXPECT_EQ(client.differentDocumentStartCount(), 1);
4918 class TestHistoryWebFrameClient : public WebFrameClient {
4920 TestHistoryWebFrameClient()
4922 m_replacesCurrentHistoryItem = false;
4925 void didStartProvisionalLoad(WebFrame* frame)
4927 WebDataSource* ds = frame->provisionalDataSource();
4928 m_replacesCurrentHistoryItem = ds->replacesCurrentHistoryItem();
4932 bool replacesCurrentHistoryItem() { return m_replacesCurrentHistoryItem; }
4933 WebFrame* frame() { return m_frame; }
4936 bool m_replacesCurrentHistoryItem;
4940 // Test which ensures that the first navigation in a subframe will always
4941 // result in history entry being replaced and not a new one added.
4942 TEST_F(WebFrameTest, DISABLED_FirstFrameNavigationReplacesHistory)
4944 registerMockedHttpURLLoad("history.html");
4945 registerMockedHttpURLLoad("find.html");
4947 FrameTestHelpers::WebViewHelper webViewHelper;
4948 TestHistoryWebFrameClient client;
4949 webViewHelper.initializeAndLoad("about:blank", true, &client);
4951 EXPECT_TRUE(client.replacesCurrentHistoryItem());
4953 WebFrame* frame = webViewHelper.webView()->mainFrame();
4955 FrameTestHelpers::loadFrame(frame,
4956 "javascript:document.body.appendChild(document.createElement('iframe'))");
4957 // Need to call runPendingTasks in order for the JavaScript above to be
4958 // evaluated and executed.
4960 WebFrame* iframe = frame->firstChild();
4961 EXPECT_EQ(client.frame(), iframe);
4962 EXPECT_TRUE(client.replacesCurrentHistoryItem());
4964 FrameTestHelpers::loadFrame(frame,
4965 "javascript:window.frames[0].location.assign('" + m_baseURL + "history.html')");
4967 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4968 EXPECT_EQ(client.frame(), iframe);
4969 EXPECT_TRUE(client.replacesCurrentHistoryItem());
4971 FrameTestHelpers::loadFrame(frame,
4972 "javascript:window.frames[0].location.assign('" + m_baseURL + "find.html')");
4974 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4975 EXPECT_EQ(client.frame(), iframe);
4976 EXPECT_FALSE(client.replacesCurrentHistoryItem());
4978 // Repeat the test, but start out the iframe with initial URL, which is not
4980 FrameTestHelpers::loadFrame(frame,
4981 "javascript:var f = document.createElement('iframe'); "
4982 "f.src = '" + m_baseURL + "history.html';"
4983 "document.body.appendChild(f)");
4985 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4987 iframe = frame->firstChild()->nextSibling();
4988 EXPECT_EQ(client.frame(), iframe);
4989 EXPECT_TRUE(client.replacesCurrentHistoryItem());
4991 FrameTestHelpers::loadFrame(frame,
4992 "javascript:window.frames[1].location.assign('" + m_baseURL + "find.html')");
4994 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
4995 EXPECT_EQ(client.frame(), iframe);
4996 EXPECT_FALSE(client.replacesCurrentHistoryItem());
4999 // This tests the restore case where the first load in a page is
5000 // via loadHistoryItem(). If multiple pages are in the same process
5001 // and are restoring around the same time, they may not restore in
5002 // the order they were created and may end up with different names
5003 // than they were given when they were saved. If the initial item
5004 // has a child with url "about:blank", we should still navigate the
5005 // main frame to the parent, rather than incorrectly matching the
5006 // blank child to the main frame.
5007 TEST_F(WebFrameTest, firstNavigationIsHistoryWithBlankChild)
5009 registerMockedHttpURLLoad("history.html");
5010 FrameTestHelpers::WebViewHelper webViewHelper;
5011 WebViewImpl* webView = webViewHelper.initialize();
5012 ASSERT_TRUE(webView->mainFrame()->currentHistoryItem().isNull());
5014 WebHistoryItem item;
5016 WebURL destinationURL(toKURL(m_baseURL + "history.html"));
5017 item.setURLString(destinationURL.string());
5018 item.setTarget(WebString::fromUTF8("expectedButMissingMainFrameName"));
5020 WebHistoryItem childItem;
5021 childItem.initialize();
5022 childItem.setURLString("about:blank");
5023 item.appendToChildren(childItem);
5025 webView->mainFrame()->loadHistoryItem(item);
5026 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
5027 EXPECT_EQ(destinationURL, webView->mainFrame()->document().url());
5030 // Test verifies that layout will change a layer's scrollable attibutes
5031 TEST_F(WebFrameTest, overflowHiddenRewrite)
5033 registerMockedHttpURLLoad("non-scrollable.html");
5034 TestMainFrameUserOrProgrammaticScrollFrameClient client;
5035 OwnPtr<FakeCompositingWebViewClient> fakeCompositingWebViewClient = adoptPtr(new FakeCompositingWebViewClient());
5036 FrameTestHelpers::WebViewHelper webViewHelper;
5037 webViewHelper.initialize(true, 0, fakeCompositingWebViewClient.get(), &configueCompositingWebView);
5039 webViewHelper.webView()->resize(WebSize(100, 100));
5040 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "non-scrollable.html");
5041 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
5042 webViewHelper.webView()->layout();
5044 WebCore::RenderLayerCompositor* compositor = webViewHelper.webViewImpl()->compositor();
5045 ASSERT_TRUE(compositor->scrollLayer());
5047 // Verify that the WebLayer is not scrollable initially.
5048 WebCore::GraphicsLayer* scrollLayer = compositor->scrollLayer();
5049 WebLayer* webScrollLayer = scrollLayer->platformLayer();
5050 ASSERT_FALSE(webScrollLayer->userScrollableHorizontal());
5051 ASSERT_FALSE(webScrollLayer->userScrollableVertical());
5053 // Call javascript to make the layer scrollable, and verify it.
5054 WebFrameImpl* frame = (WebFrameImpl*)webViewHelper.webView()->mainFrame();
5055 frame->executeScript(WebScriptSource("allowScroll();"));
5056 webViewHelper.webView()->layout();
5057 ASSERT_TRUE(webScrollLayer->userScrollableHorizontal());
5058 ASSERT_TRUE(webScrollLayer->userScrollableVertical());
5061 // Test that currentHistoryItem reflects the current page, not the provisional load.
5062 TEST_F(WebFrameTest, CurrentHistoryItem)
5064 registerMockedHttpURLLoad("fixed_layout.html");
5065 std::string url = m_baseURL + "fixed_layout.html";
5067 FrameTestHelpers::WebViewHelper webViewHelper;
5068 webViewHelper.initialize();
5069 WebFrame* frame = webViewHelper.webView()->mainFrame();
5070 FrameTestHelpers::loadFrame(frame, url);
5072 // Before commit, there is no history item.
5073 EXPECT_TRUE(frame->currentHistoryItem().isNull());
5075 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
5077 // After commit, there is.
5078 WebHistoryItem item = frame->currentHistoryItem();
5079 ASSERT_FALSE(item.isNull());
5080 EXPECT_EQ(url, item.urlString().utf8());
5083 class FailCreateChildFrame : public WebFrameClient {
5085 FailCreateChildFrame() : m_callCount(0) { }
5087 WebFrame* createChildFrame(WebFrame* parent, const WebString& frameName)
5093 int callCount() const { return m_callCount; }
5099 // Test that we don't crash if WebFrameClient::createChildFrame() fails.
5100 TEST_F(WebFrameTest, CreateChildFrameFailure)
5102 registerMockedHttpURLLoad("create_child_frame_fail.html");
5103 FailCreateChildFrame client;
5104 FrameTestHelpers::WebViewHelper webViewHelper;
5105 webViewHelper.initializeAndLoad(m_baseURL + "create_child_frame_fail.html", true, &client);
5107 EXPECT_EQ(1, client.callCount());
5110 TEST_F(WebFrameTest, fixedPositionInFixedViewport)
5112 UseMockScrollbarSettings mockScrollbarSettings;
5113 registerMockedHttpURLLoad("fixed-position-in-fixed-viewport.html");
5114 FrameTestHelpers::WebViewHelper webViewHelper;
5115 webViewHelper.initializeAndLoad(m_baseURL + "fixed-position-in-fixed-viewport.html", true, 0, 0, enableViewportSettings);
5117 WebView* webView = webViewHelper.webView();
5118 webView->resize(WebSize(100, 100));
5121 Document* document = toWebFrameImpl(webView->mainFrame())->frame()->document();
5122 Element* bottomFixed = document->getElementById("bottom-fixed");
5123 Element* topBottomFixed = document->getElementById("top-bottom-fixed");
5124 Element* rightFixed = document->getElementById("right-fixed");
5125 Element* leftRightFixed = document->getElementById("left-right-fixed");
5127 webView->resize(WebSize(100, 200));
5129 EXPECT_EQ(200, bottomFixed->offsetTop() + bottomFixed->offsetHeight());
5130 EXPECT_EQ(200, topBottomFixed->offsetHeight());
5132 webView->settings()->setMainFrameResizesAreOrientationChanges(false);
5133 webView->resize(WebSize(200, 200));
5135 EXPECT_EQ(200, rightFixed->offsetLeft() + rightFixed->offsetWidth());
5136 EXPECT_EQ(200, leftRightFixed->offsetWidth());
5138 webView->settings()->setMainFrameResizesAreOrientationChanges(true);
5139 // Will scale the page by 1.5.
5140 webView->resize(WebSize(300, 330));
5142 EXPECT_EQ(220, bottomFixed->offsetTop() + bottomFixed->offsetHeight());
5143 EXPECT_EQ(220, topBottomFixed->offsetHeight());
5144 EXPECT_EQ(200, rightFixed->offsetLeft() + rightFixed->offsetWidth());
5145 EXPECT_EQ(200, leftRightFixed->offsetWidth());
5148 TEST_F(WebFrameTest, FrameViewSetFrameRect)
5150 FrameTestHelpers::WebViewHelper webViewHelper;
5151 webViewHelper.initializeAndLoad("about:blank");
5153 WebCore::FrameView* frameView = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
5154 frameView->setFrameRect(WebCore::IntRect(0, 0, 200, 200));
5155 EXPECT_EQ_RECT(WebCore::IntRect(0, 0, 200, 200), frameView->frameRect());
5156 frameView->setFrameRect(WebCore::IntRect(100, 100, 200, 200));
5157 EXPECT_EQ_RECT(WebCore::IntRect(100, 100, 200, 200), frameView->frameRect());