2 * Copyright (C) 2010 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include "public/web/WebFrame.h"
37 #include "core/UserAgentStyleSheets.h"
38 #include "core/clipboard/Clipboard.h"
39 #include "core/css/StyleSheetContents.h"
40 #include "core/css/resolver/ViewportStyleResolver.h"
41 #include "core/dom/DocumentMarkerController.h"
42 #include "core/dom/FullscreenElementStack.h"
43 #include "core/dom/Range.h"
44 #include "core/editing/Editor.h"
45 #include "core/editing/FrameSelection.h"
46 #include "core/editing/SpellChecker.h"
47 #include "core/editing/VisiblePosition.h"
48 #include "core/events/MouseEvent.h"
49 #include "core/frame/FrameView.h"
50 #include "core/frame/LocalFrame.h"
51 #include "core/frame/Settings.h"
52 #include "core/html/HTMLFormElement.h"
53 #include "core/loader/FrameLoadRequest.h"
54 #include "core/page/EventHandler.h"
55 #include "core/rendering/HitTestResult.h"
56 #include "core/rendering/RenderView.h"
57 #include "core/rendering/TextAutosizer.h"
58 #include "core/rendering/compositing/RenderLayerCompositor.h"
59 #include "platform/DragImage.h"
60 #include "platform/RuntimeEnabledFeatures.h"
61 #include "platform/UserGestureIndicator.h"
62 #include "platform/geometry/FloatRect.h"
63 #include "platform/network/ResourceError.h"
64 #include "platform/scroll/ScrollbarTheme.h"
65 #include "public/platform/Platform.h"
66 #include "public/platform/WebFloatRect.h"
67 #include "public/platform/WebThread.h"
68 #include "public/platform/WebURL.h"
69 #include "public/platform/WebURLResponse.h"
70 #include "public/platform/WebUnitTestSupport.h"
71 #include "public/web/WebDataSource.h"
72 #include "public/web/WebDocument.h"
73 #include "public/web/WebFindOptions.h"
74 #include "public/web/WebFormElement.h"
75 #include "public/web/WebFrameClient.h"
76 #include "public/web/WebHistoryItem.h"
77 #include "public/web/WebRange.h"
78 #include "public/web/WebScriptSource.h"
79 #include "public/web/WebSearchableFormData.h"
80 #include "public/web/WebSecurityOrigin.h"
81 #include "public/web/WebSecurityPolicy.h"
82 #include "public/web/WebSettings.h"
83 #include "public/web/WebSpellCheckClient.h"
84 #include "public/web/WebTextCheckingCompletion.h"
85 #include "public/web/WebTextCheckingResult.h"
86 #include "public/web/WebViewClient.h"
87 #include "web/WebLocalFrameImpl.h"
88 #include "web/WebViewImpl.h"
89 #include "web/tests/FrameTestHelpers.h"
90 #include "web/tests/URLTestHelpers.h"
91 #include "wtf/Forward.h"
92 #include "wtf/dtoa/utils.h"
93 #include <gmock/gmock.h>
94 #include <gtest/gtest.h>
98 using namespace blink;
99 using WebCore::Document;
100 using WebCore::DocumentMarker;
101 using WebCore::Element;
102 using WebCore::FloatRect;
103 using WebCore::HitTestRequest;
104 using WebCore::Range;
105 using blink::URLTestHelpers::toKURL;
106 using blink::FrameTestHelpers::runPendingTasks;
110 const int touchPointPadding = 32;
112 #define EXPECT_EQ_RECT(a, b) \
113 EXPECT_EQ(a.x(), b.x()); \
114 EXPECT_EQ(a.y(), b.y()); \
115 EXPECT_EQ(a.width(), b.width()); \
116 EXPECT_EQ(a.height(), b.height());
118 class FakeCompositingWebViewClient : public FrameTestHelpers::TestWebViewClient {
120 virtual bool enterFullScreen() OVERRIDE { return true; }
123 class WebFrameTest : public testing::Test {
126 : m_baseURL("http://www.test.com/")
127 , m_chromeURL("chrome://")
131 virtual ~WebFrameTest()
133 Platform::current()->unitTestSupport()->unregisterAllMockedURLs();
136 void registerMockedHttpURLLoad(const std::string& fileName)
138 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8(fileName.c_str()));
141 void registerMockedChromeURLLoad(const std::string& fileName)
143 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_chromeURL.c_str()), WebString::fromUTF8(fileName.c_str()));
146 void applyViewportStyleOverride(FrameTestHelpers::WebViewHelper* webViewHelper)
148 RefPtrWillBeRawPtr<WebCore::StyleSheetContents> styleSheet = WebCore::StyleSheetContents::create(WebCore::CSSParserContext(WebCore::UASheetMode, 0));
149 styleSheet->parseString(String(WebCore::viewportAndroidUserAgentStyleSheet, sizeof(WebCore::viewportAndroidUserAgentStyleSheet)));
150 OwnPtrWillBeRawPtr<WebCore::RuleSet> ruleSet = WebCore::RuleSet::create();
151 ruleSet->addRulesFromSheet(styleSheet.get(), WebCore::MediaQueryEvaluator("screen"));
153 Document* document = toLocalFrame(webViewHelper->webViewImpl()->page()->mainFrame())->document();
154 document->ensureStyleResolver().viewportStyleResolver()->collectViewportRules(ruleSet.get(), WebCore::ViewportStyleResolver::UserAgentOrigin);
155 document->ensureStyleResolver().viewportStyleResolver()->resolve();
158 static void configueCompositingWebView(WebSettings* settings)
160 settings->setAcceleratedCompositingEnabled(true);
161 settings->setAcceleratedCompositingForFixedPositionEnabled(true);
162 settings->setAcceleratedCompositingForOverflowScrollEnabled(true);
163 settings->setCompositedScrollingForFramesEnabled(true);
166 void initializeTextSelectionWebView(const std::string& url, FrameTestHelpers::WebViewHelper* webViewHelper)
168 webViewHelper->initializeAndLoad(url, true);
169 webViewHelper->webView()->settings()->setDefaultFontSize(12);
170 webViewHelper->webView()->resize(WebSize(640, 480));
173 PassOwnPtr<WebCore::DragImage> nodeImageTestSetup(FrameTestHelpers::WebViewHelper* webViewHelper, const std::string& testcase)
175 registerMockedHttpURLLoad("nodeimage.html");
176 webViewHelper->initializeAndLoad(m_baseURL + "nodeimage.html");
177 webViewHelper->webView()->resize(WebSize(640, 480));
178 webViewHelper->webView()->layout();
179 RefPtr<WebCore::LocalFrame> frame = toLocalFrame(webViewHelper->webViewImpl()->page()->mainFrame());
180 WebCore::Element* element = frame->document()->getElementById(testcase.c_str());
181 return frame->nodeImage(*element);
184 std::string m_baseURL;
185 std::string m_chromeURL;
188 class UseMockScrollbarSettings {
190 UseMockScrollbarSettings()
192 WebCore::Settings::setMockScrollbarsEnabled(true);
193 WebCore::RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(true);
194 EXPECT_TRUE(WebCore::ScrollbarTheme::theme()->usesOverlayScrollbars());
197 ~UseMockScrollbarSettings()
199 WebCore::Settings::setMockScrollbarsEnabled(false);
200 WebCore::RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(false);
204 TEST_F(WebFrameTest, ContentText)
206 registerMockedHttpURLLoad("iframes_test.html");
207 registerMockedHttpURLLoad("visible_iframe.html");
208 registerMockedHttpURLLoad("invisible_iframe.html");
209 registerMockedHttpURLLoad("zero_sized_iframe.html");
211 FrameTestHelpers::WebViewHelper webViewHelper;
212 webViewHelper.initializeAndLoad(m_baseURL + "iframes_test.html");
214 // Now retrieve the frames text and test it only includes visible elements.
215 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
216 EXPECT_NE(std::string::npos, content.find(" visible paragraph"));
217 EXPECT_NE(std::string::npos, content.find(" visible iframe"));
218 EXPECT_EQ(std::string::npos, content.find(" invisible pararaph"));
219 EXPECT_EQ(std::string::npos, content.find(" invisible iframe"));
220 EXPECT_EQ(std::string::npos, content.find("iframe with zero size"));
223 TEST_F(WebFrameTest, FrameForEnteredContext)
225 registerMockedHttpURLLoad("iframes_test.html");
226 registerMockedHttpURLLoad("visible_iframe.html");
227 registerMockedHttpURLLoad("invisible_iframe.html");
228 registerMockedHttpURLLoad("zero_sized_iframe.html");
230 FrameTestHelpers::WebViewHelper webViewHelper;
231 webViewHelper.initializeAndLoad(m_baseURL + "iframes_test.html", true);
233 v8::HandleScope scope(v8::Isolate::GetCurrent());
234 EXPECT_EQ(webViewHelper.webView()->mainFrame(), WebLocalFrame::frameForContext(webViewHelper.webView()->mainFrame()->mainWorldScriptContext()));
235 EXPECT_EQ(webViewHelper.webView()->mainFrame()->firstChild(), WebLocalFrame::frameForContext(webViewHelper.webView()->mainFrame()->firstChild()->mainWorldScriptContext()));
238 TEST_F(WebFrameTest, FormWithNullFrame)
240 registerMockedHttpURLLoad("form.html");
242 FrameTestHelpers::WebViewHelper webViewHelper;
243 webViewHelper.initializeAndLoad(m_baseURL + "form.html");
245 WebVector<WebFormElement> forms;
246 webViewHelper.webView()->mainFrame()->document().forms(forms);
247 webViewHelper.reset();
249 EXPECT_EQ(forms.size(), 1U);
251 // This test passes if this doesn't crash.
252 WebSearchableFormData searchableDataForm(forms[0]);
255 TEST_F(WebFrameTest, ChromePageJavascript)
257 registerMockedChromeURLLoad("history.html");
259 // Pass true to enable JavaScript.
260 FrameTestHelpers::WebViewHelper webViewHelper;
261 webViewHelper.initializeAndLoad(m_chromeURL + "history.html", true);
263 // Try to run JS against the chrome-style URL.
264 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.appendChild(document.createTextNode('Clobbered'))");
266 // Required to see any updates in contentAsText.
267 webViewHelper.webView()->layout();
269 // Now retrieve the frame's text and ensure it was modified by running javascript.
270 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
271 EXPECT_NE(std::string::npos, content.find("Clobbered"));
274 TEST_F(WebFrameTest, ChromePageNoJavascript)
276 registerMockedChromeURLLoad("history.html");
278 /// Pass true to enable JavaScript.
279 FrameTestHelpers::WebViewHelper webViewHelper;
280 webViewHelper.initializeAndLoad(m_chromeURL + "history.html", true);
282 // Try to run JS against the chrome-style URL after prohibiting it.
283 WebSecurityPolicy::registerURLSchemeAsNotAllowingJavascriptURLs("chrome");
284 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.appendChild(document.createTextNode('Clobbered'))");
286 // Required to see any updates in contentAsText.
287 webViewHelper.webView()->layout();
289 // Now retrieve the frame's text and ensure it wasn't modified by running javascript.
290 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
291 EXPECT_EQ(std::string::npos, content.find("Clobbered"));
294 TEST_F(WebFrameTest, LocationSetHostWithMissingPort)
296 std::string fileName = "print-location-href.html";
297 registerMockedHttpURLLoad(fileName);
298 URLTestHelpers::registerMockedURLLoad(toKURL("http://www.test.com:0/" + fileName), WebString::fromUTF8(fileName));
300 FrameTestHelpers::WebViewHelper webViewHelper;
302 /// Pass true to enable JavaScript.
303 webViewHelper.initializeAndLoad(m_baseURL + fileName, true);
305 // Setting host to "hostname:" should be treated as "hostname:0".
306 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:location.host = 'www.test.com:'; void 0;");
308 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.textContent = location.href; void 0;");
310 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
311 EXPECT_EQ("http://www.test.com:0/" + fileName, content);
314 TEST_F(WebFrameTest, LocationSetEmptyPort)
316 std::string fileName = "print-location-href.html";
317 registerMockedHttpURLLoad(fileName);
318 URLTestHelpers::registerMockedURLLoad(toKURL("http://www.test.com:0/" + fileName), WebString::fromUTF8(fileName));
320 FrameTestHelpers::WebViewHelper webViewHelper;
322 /// Pass true to enable JavaScript.
323 webViewHelper.initializeAndLoad(m_baseURL + fileName, true);
325 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:location.port = ''; void 0;");
327 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.textContent = location.href; void 0;");
329 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
330 EXPECT_EQ("http://www.test.com:0/" + fileName, content);
333 class CSSCallbackWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
335 CSSCallbackWebFrameClient() : m_updateCount(0) { }
336 virtual void didMatchCSS(WebLocalFrame*, const WebVector<WebString>& newlyMatchingSelectors, const WebVector<WebString>& stoppedMatchingSelectors) OVERRIDE;
338 std::map<WebLocalFrame*, std::set<std::string> > m_matchedSelectors;
342 void CSSCallbackWebFrameClient::didMatchCSS(WebLocalFrame* frame, const WebVector<WebString>& newlyMatchingSelectors, const WebVector<WebString>& stoppedMatchingSelectors)
345 std::set<std::string>& frameSelectors = m_matchedSelectors[frame];
346 for (size_t i = 0; i < newlyMatchingSelectors.size(); ++i) {
347 std::string selector = newlyMatchingSelectors[i].utf8();
348 EXPECT_EQ(0U, frameSelectors.count(selector)) << selector;
349 frameSelectors.insert(selector);
351 for (size_t i = 0; i < stoppedMatchingSelectors.size(); ++i) {
352 std::string selector = stoppedMatchingSelectors[i].utf8();
353 EXPECT_EQ(1U, frameSelectors.count(selector)) << selector;
354 frameSelectors.erase(selector);
358 class WebFrameCSSCallbackTest : public testing::Test {
360 WebFrameCSSCallbackTest()
363 m_frame = m_helper.initializeAndLoad("about:blank", true, &m_client)->mainFrame()->toWebLocalFrame();
366 ~WebFrameCSSCallbackTest()
368 EXPECT_EQ(1U, m_client.m_matchedSelectors.size());
371 WebDocument doc() const
373 return m_frame->document();
376 int updateCount() const
378 return m_client.m_updateCount;
381 const std::set<std::string>& matchedSelectors()
383 return m_client.m_matchedSelectors[m_frame];
386 void loadHTML(const std::string& html)
388 FrameTestHelpers::loadHTMLString(m_frame, html, toKURL("about:blank"));
391 void executeScript(const WebString& code)
393 m_frame->executeScript(WebScriptSource(code));
394 m_frame->view()->layout();
398 CSSCallbackWebFrameClient m_client;
399 FrameTestHelpers::WebViewHelper m_helper;
400 WebLocalFrame* m_frame;
403 TEST_F(WebFrameCSSCallbackTest, AuthorStyleSheet)
407 // This stylesheet checks that the internal property and value can't be
408 // set by a stylesheet, only WebDocument::watchCSSSelectors().
409 "div.initial_on { -internal-callback: none; }"
410 "div.initial_off { -internal-callback: -internal-presence; }"
412 "<div class=\"initial_on\"></div>"
413 "<div class=\"initial_off\"></div>");
415 std::vector<WebString> selectors;
416 selectors.push_back(WebString::fromUTF8("div.initial_on"));
417 m_frame->document().watchCSSSelectors(WebVector<WebString>(selectors));
418 m_frame->view()->layout();
420 EXPECT_EQ(1, updateCount());
421 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("div.initial_on"));
423 // Check that adding a watched selector calls back for already-present nodes.
424 selectors.push_back(WebString::fromUTF8("div.initial_off"));
425 doc().watchCSSSelectors(WebVector<WebString>(selectors));
426 m_frame->view()->layout();
428 EXPECT_EQ(2, updateCount());
429 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("div.initial_off", "div.initial_on"));
431 // Check that we can turn off callbacks for certain selectors.
432 doc().watchCSSSelectors(WebVector<WebString>());
433 m_frame->view()->layout();
435 EXPECT_EQ(3, updateCount());
436 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
439 TEST_F(WebFrameCSSCallbackTest, SharedRenderStyle)
441 // Check that adding an element calls back when it matches an existing rule.
442 std::vector<WebString> selectors;
443 selectors.push_back(WebString::fromUTF8("span"));
444 doc().watchCSSSelectors(WebVector<WebString>(selectors));
447 "i1 = document.createElement('span');"
448 "i1.id = 'first_span';"
449 "document.body.appendChild(i1)");
450 EXPECT_EQ(1, updateCount());
451 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
453 // Adding a second element that shares a RenderStyle shouldn't call back.
454 // We use <span>s to avoid default style rules that can set
455 // RenderStyle::unique().
457 "i2 = document.createElement('span');"
458 "i2.id = 'second_span';"
459 "i1 = document.getElementById('first_span');"
460 "i1.parentNode.insertBefore(i2, i1.nextSibling);");
461 EXPECT_EQ(1, updateCount());
462 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
464 // Removing the first element shouldn't call back.
466 "i1 = document.getElementById('first_span');"
467 "i1.parentNode.removeChild(i1);");
468 EXPECT_EQ(1, updateCount());
469 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
471 // But removing the second element *should* call back.
473 "i2 = document.getElementById('second_span');"
474 "i2.parentNode.removeChild(i2);");
475 EXPECT_EQ(2, updateCount());
476 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
479 TEST_F(WebFrameCSSCallbackTest, CatchesAttributeChange)
481 loadHTML("<span></span>");
483 std::vector<WebString> selectors;
484 selectors.push_back(WebString::fromUTF8("span[attr=\"value\"]"));
485 doc().watchCSSSelectors(WebVector<WebString>(selectors));
488 EXPECT_EQ(0, updateCount());
489 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
492 "document.querySelector('span').setAttribute('attr', 'value');");
493 EXPECT_EQ(1, updateCount());
494 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span[attr=\"value\"]"));
497 TEST_F(WebFrameCSSCallbackTest, DisplayNone)
499 loadHTML("<div style='display:none'><span></span></div>");
501 std::vector<WebString> selectors;
502 selectors.push_back(WebString::fromUTF8("span"));
503 doc().watchCSSSelectors(WebVector<WebString>(selectors));
506 EXPECT_EQ(0, updateCount()) << "Don't match elements in display:none trees.";
509 "d = document.querySelector('div');"
510 "d.style.display = 'block';");
511 EXPECT_EQ(1, updateCount()) << "Match elements when they become displayed.";
512 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
515 "d = document.querySelector('div');"
516 "d.style.display = 'none';");
517 EXPECT_EQ(2, updateCount()) << "Unmatch elements when they become undisplayed.";
518 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
521 "s = document.querySelector('span');"
522 "s.style.display = 'none';");
523 EXPECT_EQ(2, updateCount()) << "No effect from no-display'ing a span that's already undisplayed.";
526 "d = document.querySelector('div');"
527 "d.style.display = 'block';");
528 EXPECT_EQ(2, updateCount()) << "No effect from displaying a div whose span is display:none.";
531 "s = document.querySelector('span');"
532 "s.style.display = 'inline';");
533 EXPECT_EQ(3, updateCount()) << "Now the span is visible and produces a callback.";
534 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
537 "s = document.querySelector('span');"
538 "s.style.display = 'none';");
539 EXPECT_EQ(4, updateCount()) << "Undisplaying the span directly should produce another callback.";
540 EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
543 TEST_F(WebFrameCSSCallbackTest, Reparenting)
546 "<div id='d1'><span></span></div>"
547 "<div id='d2'></div>");
549 std::vector<WebString> selectors;
550 selectors.push_back(WebString::fromUTF8("span"));
551 doc().watchCSSSelectors(WebVector<WebString>(selectors));
552 m_frame->view()->layout();
555 EXPECT_EQ(1, updateCount());
556 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
559 "s = document.querySelector('span');"
560 "d2 = document.getElementById('d2');"
561 "d2.appendChild(s);");
562 EXPECT_EQ(1, updateCount()) << "Just moving an element that continues to match shouldn't send a spurious callback.";
563 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
566 TEST_F(WebFrameCSSCallbackTest, MultiSelector)
568 loadHTML("<span></span>");
570 // Check that selector lists match as the whole list, not as each element
572 std::vector<WebString> selectors;
573 selectors.push_back(WebString::fromUTF8("span"));
574 selectors.push_back(WebString::fromUTF8("span,p"));
575 doc().watchCSSSelectors(WebVector<WebString>(selectors));
576 m_frame->view()->layout();
579 EXPECT_EQ(1, updateCount());
580 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span", "span, p"));
583 TEST_F(WebFrameCSSCallbackTest, InvalidSelector)
585 loadHTML("<p><span></span></p>");
587 // Build a list with one valid selector and one invalid.
588 std::vector<WebString> selectors;
589 selectors.push_back(WebString::fromUTF8("span"));
590 selectors.push_back(WebString::fromUTF8("[")); // Invalid.
591 selectors.push_back(WebString::fromUTF8("p span")); // Not compound.
592 doc().watchCSSSelectors(WebVector<WebString>(selectors));
593 m_frame->view()->layout();
596 EXPECT_EQ(1, updateCount());
597 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"))
598 << "An invalid selector shouldn't prevent other selectors from matching.";
601 TEST_F(WebFrameTest, DispatchMessageEventWithOriginCheck)
603 registerMockedHttpURLLoad("postmessage_test.html");
605 // Pass true to enable JavaScript.
606 FrameTestHelpers::WebViewHelper webViewHelper;
607 webViewHelper.initializeAndLoad(m_baseURL + "postmessage_test.html", true);
609 // Send a message with the correct origin.
610 WebSecurityOrigin correctOrigin(WebSecurityOrigin::create(toKURL(m_baseURL)));
611 WebDOMEvent event = webViewHelper.webView()->mainFrame()->document().createEvent("MessageEvent");
612 WebDOMMessageEvent message = event.to<WebDOMMessageEvent>();
613 WebSerializedScriptValue data(WebSerializedScriptValue::fromString("foo"));
614 message.initMessageEvent("message", false, false, data, "http://origin.com", 0, "");
615 webViewHelper.webView()->mainFrame()->dispatchMessageEventWithOriginCheck(correctOrigin, message);
617 // Send another message with incorrect origin.
618 WebSecurityOrigin incorrectOrigin(WebSecurityOrigin::create(toKURL(m_chromeURL)));
619 webViewHelper.webView()->mainFrame()->dispatchMessageEventWithOriginCheck(incorrectOrigin, message);
621 // Required to see any updates in contentAsText.
622 webViewHelper.webView()->layout();
624 // Verify that only the first addition is in the body of the page.
625 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
626 EXPECT_NE(std::string::npos, content.find("Message 1."));
627 EXPECT_EQ(std::string::npos, content.find("Message 2."));
630 TEST_F(WebFrameTest, PostMessageThenDetach)
632 FrameTestHelpers::WebViewHelper webViewHelper;
633 webViewHelper.initializeAndLoad("about:blank");
635 RefPtr<WebCore::LocalFrame> frame = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame());
636 WebCore::NonThrowableExceptionState exceptionState;
637 frame->domWindow()->postMessage(WebCore::SerializedScriptValue::create("message"), 0, "*", frame->domWindow(), exceptionState);
638 webViewHelper.reset();
639 EXPECT_FALSE(exceptionState.hadException());
641 // Success is not crashing.
645 class FixedLayoutTestWebViewClient : public FrameTestHelpers::TestWebViewClient {
647 virtual WebScreenInfo screenInfo() OVERRIDE { return m_screenInfo; }
649 WebScreenInfo m_screenInfo;
652 // Viewport settings need to be set before the page gets loaded
653 static void enableViewportSettings(WebSettings* settings)
655 settings->setViewportMetaEnabled(true);
656 settings->setViewportEnabled(true);
657 settings->setMainFrameResizesAreOrientationChanges(true);
658 settings->setShrinksViewportContentToFit(true);
661 TEST_F(WebFrameTest, FrameViewNeedsLayoutOnFixedLayoutResize)
663 UseMockScrollbarSettings mockScrollbarSettings;
664 registerMockedHttpURLLoad("fixed_layout.html");
666 FixedLayoutTestWebViewClient client;
667 int viewportWidth = 640;
668 int viewportHeight = 480;
670 // Make sure we initialize to minimum scale, even if the window size
671 // only becomes available after the load begins.
672 FrameTestHelpers::WebViewHelper webViewHelper;
673 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
674 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
675 webViewHelper.webView()->layout();
677 webViewHelper.webViewImpl()->setFixedLayoutSize(WebCore::IntSize(100, 100));
678 EXPECT_TRUE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
680 int prevLayoutCount = webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount();
681 webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->setFrameRect(WebCore::IntRect(0, 0, 641, 481));
682 EXPECT_EQ(prevLayoutCount, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount());
684 webViewHelper.webViewImpl()->layout();
687 // Helper function to check or set text autosizing multipliers on a document.
688 static bool checkOrSetTextAutosizingMultiplier(Document* document, float multiplier, bool setMultiplier)
690 bool multiplierCheckedOrSetAtLeastOnce = false;
691 for (WebCore::RenderObject* renderer = document->renderView(); renderer; renderer = renderer->nextInPreOrder()) {
692 if (renderer->style()) {
694 renderer->style()->setTextAutosizingMultiplier(multiplier);
695 EXPECT_EQ(multiplier, renderer->style()->textAutosizingMultiplier());
696 multiplierCheckedOrSetAtLeastOnce = true;
699 return multiplierCheckedOrSetAtLeastOnce;
703 static bool setTextAutosizingMultiplier(Document* document, float multiplier)
705 return checkOrSetTextAutosizingMultiplier(document, multiplier, true);
708 static bool checkTextAutosizingMultiplier(Document* document, float multiplier)
710 return checkOrSetTextAutosizingMultiplier(document, multiplier, false);
713 TEST_F(WebFrameTest, ChangeInFixedLayoutResetsTextAutosizingMultipliers)
715 UseMockScrollbarSettings mockScrollbarSettings;
716 registerMockedHttpURLLoad("fixed_layout.html");
718 FixedLayoutTestWebViewClient client;
719 int viewportWidth = 640;
720 int viewportHeight = 480;
722 FrameTestHelpers::WebViewHelper webViewHelper;
723 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
725 WebCore::Document* document = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document();
726 document->settings()->setTextAutosizingEnabled(true);
727 EXPECT_TRUE(document->settings()->textAutosizingEnabled());
728 webViewHelper.webViewImpl()->resize(WebSize(viewportWidth, viewportHeight));
729 webViewHelper.webViewImpl()->layout();
731 EXPECT_TRUE(setTextAutosizingMultiplier(document, 2));
733 WebCore::ViewportDescription description = document->viewportDescription();
734 // Choose a width that's not going match the viewport width of the loaded document.
735 description.minWidth = WebCore::Length(100, WebCore::Fixed);
736 description.maxWidth = WebCore::Length(100, WebCore::Fixed);
737 webViewHelper.webViewImpl()->updatePageDefinedViewportConstraints(description);
739 EXPECT_TRUE(checkTextAutosizingMultiplier(document, 1));
742 TEST_F(WebFrameTest, SetFrameRectInvalidatesTextAutosizingMultipliers)
744 UseMockScrollbarSettings mockScrollbarSettings;
745 registerMockedHttpURLLoad("iframe_reload.html");
746 registerMockedHttpURLLoad("visible_iframe.html");
748 FixedLayoutTestWebViewClient client;
749 int viewportWidth = 640;
750 int viewportHeight = 480;
752 FrameTestHelpers::WebViewHelper webViewHelper;
753 webViewHelper.initializeAndLoad(m_baseURL + "iframe_reload.html", true, 0, &client, enableViewportSettings);
755 WebCore::LocalFrame* mainFrame = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame());
756 WebCore::Document* document = mainFrame->document();
757 WebCore::FrameView* frameView = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
758 document->settings()->setTextAutosizingEnabled(true);
759 EXPECT_TRUE(document->settings()->textAutosizingEnabled());
760 webViewHelper.webViewImpl()->resize(WebSize(viewportWidth, viewportHeight));
761 webViewHelper.webViewImpl()->layout();
763 for (WebCore::Frame* frame = mainFrame; frame; frame = frame->tree().traverseNext()) {
764 if (!frame->isLocalFrame())
766 EXPECT_TRUE(setTextAutosizingMultiplier(toLocalFrame(frame)->document(), 2));
767 for (WebCore::RenderObject* renderer = toLocalFrame(frame)->document()->renderView(); renderer; renderer = renderer->nextInPreOrder()) {
768 if (renderer->isText())
769 EXPECT_FALSE(renderer->needsLayout());
773 frameView->setFrameRect(WebCore::IntRect(0, 0, 200, 200));
774 for (WebCore::Frame* frame = mainFrame; frame; frame = frame->tree().traverseNext()) {
775 if (!frame->isLocalFrame())
777 for (WebCore::RenderObject* renderer = toLocalFrame(frame)->document()->renderView(); renderer; renderer = renderer->nextInPreOrder()) {
778 if (renderer->isText())
779 EXPECT_TRUE(renderer->needsLayout());
784 TEST_F(WebFrameTest, FixedLayoutSizeStopsResizeFromChangingLayoutSize)
786 UseMockScrollbarSettings mockScrollbarSettings;
787 registerMockedHttpURLLoad("fixed_layout.html");
789 int viewportWidth = 640;
790 int viewportHeight = 480;
792 int fixedLayoutWidth = viewportWidth / 2;
793 int fixedLayoutHeight = viewportHeight / 2;
795 FrameTestHelpers::WebViewHelper webViewHelper;
796 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, 0, enableViewportSettings);
797 webViewHelper.webView()->setFixedLayoutSize(WebSize(fixedLayoutWidth, fixedLayoutHeight));
798 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
799 webViewHelper.webView()->layout();
801 EXPECT_EQ(fixedLayoutWidth, toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->view()->layoutSize().width());
802 EXPECT_EQ(fixedLayoutHeight, toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->view()->layoutSize().height());
805 TEST_F(WebFrameTest, FixedLayoutSizePreventsResizeFromChangingPageScale)
807 UseMockScrollbarSettings mockScrollbarSettings;
808 registerMockedHttpURLLoad("fixed_layout.html");
810 int viewportWidth = 640;
811 int viewportHeight = 480;
813 int fixedLayoutWidth = viewportWidth / 2;
814 int fixedLayoutHeight = viewportHeight / 2;
816 FrameTestHelpers::WebViewHelper webViewHelper;
817 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, 0, enableViewportSettings);
818 webViewHelper.webView()->setFixedLayoutSize(WebSize(fixedLayoutWidth, fixedLayoutHeight));
819 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
820 webViewHelper.webView()->layout();
821 float pageScaleFactor = webViewHelper.webView()->pageScaleFactor();
823 webViewHelper.webView()->resize(WebSize(viewportWidth * 2, viewportHeight * 2));
825 EXPECT_EQ(pageScaleFactor, webViewHelper.webView()->pageScaleFactor());
828 TEST_F(WebFrameTest, FixedLayoutSizePreventsLayoutFromChangingPageScale)
830 UseMockScrollbarSettings mockScrollbarSettings;
831 registerMockedHttpURLLoad("fixed_layout.html");
833 int viewportWidth = 640;
834 int viewportHeight = 480;
836 int fixedLayoutWidth = viewportWidth * 2;
837 int fixedLayoutHeight = viewportHeight * 2;
839 FrameTestHelpers::WebViewHelper webViewHelper;
840 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, 0, enableViewportSettings);
841 webViewHelper.webView()->setFixedLayoutSize(WebSize(viewportWidth, viewportHeight));
842 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
843 webViewHelper.webView()->layout();
844 float pageScaleFactor = webViewHelper.webView()->pageScaleFactor();
846 webViewHelper.webView()->setFixedLayoutSize(WebSize(fixedLayoutWidth, fixedLayoutHeight));
847 webViewHelper.webView()->layout();
849 EXPECT_EQ(pageScaleFactor, webViewHelper.webView()->pageScaleFactor());
852 TEST_F(WebFrameTest, PreferredSizeAndContentSizeReportedCorrectlyWithZeroHeightFixedLayout)
854 UseMockScrollbarSettings mockScrollbarSettings;
855 registerMockedHttpURLLoad("200-by-300.html");
857 int windowWidth = 100;
858 int windowHeight = 100;
859 int viewportWidth = 100;
860 int viewportHeight = 0;
864 FixedLayoutTestWebViewClient client;
865 client.m_screenInfo.deviceScaleFactor = 1;
867 FrameTestHelpers::WebViewHelper webViewHelper;
868 webViewHelper.initializeAndLoad(m_baseURL + "200-by-300.html", true, 0, &client, enableViewportSettings);
869 webViewHelper.webView()->resize(WebSize(windowWidth, windowHeight));
870 webViewHelper.webView()->setFixedLayoutSize(WebSize(viewportWidth, viewportHeight));
871 webViewHelper.webView()->layout();
873 EXPECT_EQ(divWidth, webViewHelper.webView()->mainFrame()->contentsSize().width);
874 EXPECT_EQ(divHeight, webViewHelper.webView()->mainFrame()->contentsSize().height);
876 EXPECT_EQ(divWidth, webViewHelper.webView()->contentsPreferredMinimumSize().width);
877 EXPECT_EQ(divHeight, webViewHelper.webView()->contentsPreferredMinimumSize().height);
880 TEST_F(WebFrameTest, DisablingFixedLayoutSizeSetsCorrectLayoutSize)
882 UseMockScrollbarSettings mockScrollbarSettings;
883 registerMockedHttpURLLoad("no_viewport_tag.html");
885 FixedLayoutTestWebViewClient client;
886 client.m_screenInfo.deviceScaleFactor = 1;
887 int viewportWidth = 640;
888 int viewportHeight = 480;
890 FrameTestHelpers::WebViewHelper webViewHelper;
891 webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client, enableViewportSettings);
892 applyViewportStyleOverride(&webViewHelper);
893 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
894 webViewHelper.webView()->settings()->setUseWideViewport(true);
895 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
897 webViewHelper.webView()->setFixedLayoutSize(WebSize(viewportWidth, viewportHeight));
898 EXPECT_TRUE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
899 webViewHelper.webView()->layout();
900 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
902 webViewHelper.webView()->setFixedLayoutSize(WebSize(0, 0));
903 EXPECT_TRUE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
904 webViewHelper.webView()->layout();
905 EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
908 TEST_F(WebFrameTest, ZeroHeightPositiveWidthNotIgnored)
910 UseMockScrollbarSettings mockScrollbarSettings;
912 FixedLayoutTestWebViewClient client;
913 client.m_screenInfo.deviceScaleFactor = 1;
914 int viewportWidth = 1280;
915 int viewportHeight = 0;
917 FrameTestHelpers::WebViewHelper webViewHelper;
918 webViewHelper.initialize(true, 0, &client, enableViewportSettings);
919 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
921 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
922 EXPECT_EQ(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
925 TEST_F(WebFrameTest, DeviceScaleFactorUsesDefaultWithoutViewportTag)
927 UseMockScrollbarSettings mockScrollbarSettings;
928 registerMockedHttpURLLoad("no_viewport_tag.html");
930 int viewportWidth = 640;
931 int viewportHeight = 480;
933 FixedLayoutTestWebViewClient client;
934 client.m_screenInfo.deviceScaleFactor = 2;
936 FrameTestHelpers::WebViewHelper webViewHelper;
937 webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client, enableViewportSettings);
939 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
940 webViewHelper.webView()->layout();
942 EXPECT_EQ(2, webViewHelper.webView()->deviceScaleFactor());
944 // Device scale factor should be independent of page scale.
945 webViewHelper.webView()->setPageScaleFactorLimits(1, 2);
946 webViewHelper.webView()->setPageScaleFactor(0.5);
947 webViewHelper.webView()->layout();
948 EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor());
950 // Force the layout to happen before leaving the test.
951 webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
954 TEST_F(WebFrameTest, FixedLayoutInitializeAtMinimumScale)
956 UseMockScrollbarSettings mockScrollbarSettings;
958 registerMockedHttpURLLoad("fixed_layout.html");
960 FixedLayoutTestWebViewClient client;
961 client.m_screenInfo.deviceScaleFactor = 1;
962 int viewportWidth = 640;
963 int viewportHeight = 480;
965 // Make sure we initialize to minimum scale, even if the window size
966 // only becomes available after the load begins.
967 FrameTestHelpers::WebViewHelper webViewHelper;
968 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
969 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
971 int defaultFixedLayoutWidth = 980;
972 float minimumPageScaleFactor = viewportWidth / (float) defaultFixedLayoutWidth;
973 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
974 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->minimumPageScaleFactor());
976 // Assume the user has pinch zoomed to page scale factor 2.
977 float userPinchPageScaleFactor = 2;
978 webViewHelper.webView()->setPageScaleFactor(userPinchPageScaleFactor);
979 webViewHelper.webView()->layout();
981 // Make sure we don't reset to initial scale if the page continues to load.
982 webViewHelper.webViewImpl()->didCommitLoad(false, false);
983 webViewHelper.webViewImpl()->didChangeContentsSize();
984 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
986 // Make sure we don't reset to initial scale if the viewport size changes.
987 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight + 100));
988 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
991 TEST_F(WebFrameTest, WideDocumentInitializeAtMinimumScale)
993 UseMockScrollbarSettings mockScrollbarSettings;
995 registerMockedHttpURLLoad("wide_document.html");
997 FixedLayoutTestWebViewClient client;
998 client.m_screenInfo.deviceScaleFactor = 1;
999 int viewportWidth = 640;
1000 int viewportHeight = 480;
1002 // Make sure we initialize to minimum scale, even if the window size
1003 // only becomes available after the load begins.
1004 FrameTestHelpers::WebViewHelper webViewHelper;
1005 webViewHelper.initializeAndLoad(m_baseURL + "wide_document.html", true, 0, &client, enableViewportSettings);
1006 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1008 int wideDocumentWidth = 1500;
1009 float minimumPageScaleFactor = viewportWidth / (float) wideDocumentWidth;
1010 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1011 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->minimumPageScaleFactor());
1013 // Assume the user has pinch zoomed to page scale factor 2.
1014 float userPinchPageScaleFactor = 2;
1015 webViewHelper.webView()->setPageScaleFactor(userPinchPageScaleFactor);
1016 webViewHelper.webView()->layout();
1018 // Make sure we don't reset to initial scale if the page continues to load.
1019 webViewHelper.webViewImpl()->didCommitLoad(false, false);
1020 webViewHelper.webViewImpl()->didChangeContentsSize();
1021 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1023 // Make sure we don't reset to initial scale if the viewport size changes.
1024 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight + 100));
1025 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1028 TEST_F(WebFrameTest, DelayedViewportInitialScale)
1030 UseMockScrollbarSettings mockScrollbarSettings;
1031 registerMockedHttpURLLoad("viewport-auto-initial-scale.html");
1033 FixedLayoutTestWebViewClient client;
1034 client.m_screenInfo.deviceScaleFactor = 1;
1035 int viewportWidth = 640;
1036 int viewportHeight = 480;
1038 FrameTestHelpers::WebViewHelper webViewHelper;
1039 webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings);
1040 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1042 EXPECT_EQ(0.25f, webViewHelper.webView()->pageScaleFactor());
1044 WebCore::Document* document = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document();
1045 WebCore::ViewportDescription description = document->viewportDescription();
1046 description.zoom = 2;
1047 document->setViewportDescription(description);
1048 webViewHelper.webView()->layout();
1049 EXPECT_EQ(2, webViewHelper.webView()->pageScaleFactor());
1052 TEST_F(WebFrameTest, setLoadWithOverviewModeToFalse)
1054 UseMockScrollbarSettings mockScrollbarSettings;
1055 registerMockedHttpURLLoad("viewport-auto-initial-scale.html");
1057 FixedLayoutTestWebViewClient client;
1058 client.m_screenInfo.deviceScaleFactor = 1;
1059 int viewportWidth = 640;
1060 int viewportHeight = 480;
1062 FrameTestHelpers::WebViewHelper webViewHelper;
1063 webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings);
1064 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1065 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1066 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1068 // The page must be displayed at 100% zoom.
1069 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
1072 TEST_F(WebFrameTest, SetLoadWithOverviewModeToFalseAndNoWideViewport)
1074 UseMockScrollbarSettings mockScrollbarSettings;
1075 registerMockedHttpURLLoad("large-div.html");
1077 FixedLayoutTestWebViewClient client;
1078 client.m_screenInfo.deviceScaleFactor = 1;
1079 int viewportWidth = 640;
1080 int viewportHeight = 480;
1082 FrameTestHelpers::WebViewHelper webViewHelper;
1083 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client, enableViewportSettings);
1084 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1085 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1086 webViewHelper.webView()->settings()->setUseWideViewport(false);
1087 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1089 // The page must be displayed at 100% zoom, despite that it hosts a wide div element.
1090 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
1093 TEST_F(WebFrameTest, NoWideViewportIgnoresPageViewportWidth)
1095 UseMockScrollbarSettings mockScrollbarSettings;
1096 registerMockedHttpURLLoad("viewport-auto-initial-scale.html");
1098 FixedLayoutTestWebViewClient client;
1099 client.m_screenInfo.deviceScaleFactor = 1;
1100 int viewportWidth = 640;
1101 int viewportHeight = 480;
1103 FrameTestHelpers::WebViewHelper webViewHelper;
1104 webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings);
1105 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1106 webViewHelper.webView()->settings()->setUseWideViewport(false);
1107 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1109 // The page sets viewport width to 3000, but with UseWideViewport == false is must be ignored.
1110 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1111 EXPECT_EQ(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
1114 TEST_F(WebFrameTest, NoWideViewportIgnoresPageViewportWidthButAccountsScale)
1116 UseMockScrollbarSettings mockScrollbarSettings;
1117 registerMockedHttpURLLoad("viewport-wide-2x-initial-scale.html");
1119 FixedLayoutTestWebViewClient client;
1120 client.m_screenInfo.deviceScaleFactor = 1;
1121 int viewportWidth = 640;
1122 int viewportHeight = 480;
1124 FrameTestHelpers::WebViewHelper webViewHelper;
1125 webViewHelper.initializeAndLoad(m_baseURL + "viewport-wide-2x-initial-scale.html", true, 0, &client, enableViewportSettings);
1126 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1127 webViewHelper.webView()->settings()->setUseWideViewport(false);
1128 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1130 // The page sets viewport width to 3000, but with UseWideViewport == false it must be ignored.
1131 // While the initial scale specified by the page must be accounted.
1132 EXPECT_EQ(viewportWidth / 2, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1133 EXPECT_EQ(viewportHeight / 2, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
1136 TEST_F(WebFrameTest, WideViewportSetsTo980WithoutViewportTag)
1138 UseMockScrollbarSettings mockScrollbarSettings;
1139 registerMockedHttpURLLoad("no_viewport_tag.html");
1141 FixedLayoutTestWebViewClient client;
1142 client.m_screenInfo.deviceScaleFactor = 1;
1143 int viewportWidth = 640;
1144 int viewportHeight = 480;
1146 FrameTestHelpers::WebViewHelper webViewHelper;
1147 webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client, enableViewportSettings);
1148 applyViewportStyleOverride(&webViewHelper);
1149 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1150 webViewHelper.webView()->settings()->setUseWideViewport(true);
1151 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1153 EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1154 EXPECT_EQ(980.0 / viewportWidth * viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
1157 TEST_F(WebFrameTest, NoWideViewportAndHeightInMeta)
1159 UseMockScrollbarSettings mockScrollbarSettings;
1160 registerMockedHttpURLLoad("viewport-height-1000.html");
1162 FixedLayoutTestWebViewClient client;
1163 client.m_screenInfo.deviceScaleFactor = 1;
1164 int viewportWidth = 640;
1165 int viewportHeight = 480;
1167 FrameTestHelpers::WebViewHelper webViewHelper;
1168 webViewHelper.initializeAndLoad(m_baseURL + "viewport-height-1000.html", true, 0, &client, enableViewportSettings);
1169 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1170 webViewHelper.webView()->settings()->setUseWideViewport(false);
1171 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1173 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1176 TEST_F(WebFrameTest, WideViewportSetsTo980WithAutoWidth)
1178 UseMockScrollbarSettings mockScrollbarSettings;
1179 registerMockedHttpURLLoad("viewport-2x-initial-scale.html");
1181 FixedLayoutTestWebViewClient client;
1182 client.m_screenInfo.deviceScaleFactor = 1;
1183 int viewportWidth = 640;
1184 int viewportHeight = 480;
1186 FrameTestHelpers::WebViewHelper webViewHelper;
1187 webViewHelper.initializeAndLoad(m_baseURL + "viewport-2x-initial-scale.html", true, 0, &client, enableViewportSettings);
1188 applyViewportStyleOverride(&webViewHelper);
1189 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1190 webViewHelper.webView()->settings()->setUseWideViewport(true);
1191 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1193 EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1194 EXPECT_EQ(980.0 / viewportWidth * viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
1197 TEST_F(WebFrameTest, PageViewportInitialScaleOverridesLoadWithOverviewMode)
1199 UseMockScrollbarSettings mockScrollbarSettings;
1200 registerMockedHttpURLLoad("viewport-wide-2x-initial-scale.html");
1202 FixedLayoutTestWebViewClient client;
1203 client.m_screenInfo.deviceScaleFactor = 1;
1204 int viewportWidth = 640;
1205 int viewportHeight = 480;
1207 FrameTestHelpers::WebViewHelper webViewHelper;
1208 webViewHelper.initializeAndLoad(m_baseURL + "viewport-wide-2x-initial-scale.html", true, 0, &client, enableViewportSettings);
1209 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1210 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1212 // The page must be displayed at 200% zoom, as specified in its viewport meta tag.
1213 EXPECT_EQ(2.0f, webViewHelper.webView()->pageScaleFactor());
1216 TEST_F(WebFrameTest, setInitialPageScaleFactorPermanently)
1218 UseMockScrollbarSettings mockScrollbarSettings;
1220 registerMockedHttpURLLoad("fixed_layout.html");
1222 FixedLayoutTestWebViewClient client;
1223 client.m_screenInfo.deviceScaleFactor = 1;
1224 float enforcedPageScaleFactor = 2.0f;
1226 FrameTestHelpers::WebViewHelper webViewHelper;
1227 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1228 applyViewportStyleOverride(&webViewHelper);
1229 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1230 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1231 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1232 webViewHelper.webView()->layout();
1234 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1236 int viewportWidth = 640;
1237 int viewportHeight = 480;
1238 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1239 webViewHelper.webView()->layout();
1241 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1243 webViewHelper.webView()->setInitialPageScaleOverride(-1);
1244 webViewHelper.webView()->layout();
1245 EXPECT_EQ(1.0, webViewHelper.webView()->pageScaleFactor());
1248 TEST_F(WebFrameTest, PermanentInitialPageScaleFactorOverridesLoadWithOverviewMode)
1250 UseMockScrollbarSettings mockScrollbarSettings;
1251 registerMockedHttpURLLoad("viewport-auto-initial-scale.html");
1253 FixedLayoutTestWebViewClient client;
1254 client.m_screenInfo.deviceScaleFactor = 1;
1255 int viewportWidth = 640;
1256 int viewportHeight = 480;
1257 float enforcedPageScaleFactor = 0.5f;
1259 FrameTestHelpers::WebViewHelper webViewHelper;
1260 webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings);
1261 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1262 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1263 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1265 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1268 TEST_F(WebFrameTest, PermanentInitialPageScaleFactorOverridesPageViewportInitialScale)
1270 UseMockScrollbarSettings mockScrollbarSettings;
1271 registerMockedHttpURLLoad("viewport-wide-2x-initial-scale.html");
1273 FixedLayoutTestWebViewClient client;
1274 client.m_screenInfo.deviceScaleFactor = 1;
1275 int viewportWidth = 640;
1276 int viewportHeight = 480;
1277 float enforcedPageScaleFactor = 0.5f;
1279 FrameTestHelpers::WebViewHelper webViewHelper;
1280 webViewHelper.initializeAndLoad(m_baseURL + "viewport-wide-2x-initial-scale.html", true, 0, &client, enableViewportSettings);
1281 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1282 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1284 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1287 TEST_F(WebFrameTest, SmallPermanentInitialPageScaleFactorIsClobbered)
1289 UseMockScrollbarSettings mockScrollbarSettings;
1290 const char* pages[] = {
1291 // These pages trigger the clobbering condition. There must be a matching item in "pageScaleFactors" array.
1292 "viewport-device-0.5x-initial-scale.html",
1293 "viewport-initial-scale-1.html",
1294 // These ones do not.
1295 "viewport-auto-initial-scale.html",
1296 "viewport-target-densitydpi-device-and-fixed-width.html"
1298 float pageScaleFactors[] = { 0.5f, 1.0f };
1299 for (size_t i = 0; i < ARRAY_SIZE(pages); ++i)
1300 registerMockedHttpURLLoad(pages[i]);
1302 FixedLayoutTestWebViewClient client;
1303 client.m_screenInfo.deviceScaleFactor = 1;
1304 int viewportWidth = 400;
1305 int viewportHeight = 300;
1306 float enforcedPageScaleFactor = 0.75f;
1308 for (size_t i = 0; i < ARRAY_SIZE(pages); ++i) {
1309 for (int quirkEnabled = 0; quirkEnabled <= 1; ++quirkEnabled) {
1310 FrameTestHelpers::WebViewHelper webViewHelper;
1311 webViewHelper.initializeAndLoad(m_baseURL + pages[i], true, 0, &client, enableViewportSettings);
1312 applyViewportStyleOverride(&webViewHelper);
1313 webViewHelper.webView()->settings()->setClobberUserAgentInitialScaleQuirk(quirkEnabled);
1314 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1315 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1317 float expectedPageScaleFactor = quirkEnabled && i < ARRAY_SIZE(pageScaleFactors) ? pageScaleFactors[i] : enforcedPageScaleFactor;
1318 EXPECT_EQ(expectedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1323 TEST_F(WebFrameTest, PermanentInitialPageScaleFactorAffectsLayoutWidth)
1325 UseMockScrollbarSettings mockScrollbarSettings;
1327 FixedLayoutTestWebViewClient client;
1328 client.m_screenInfo.deviceScaleFactor = 1;
1329 int viewportWidth = 640;
1330 int viewportHeight = 480;
1331 float enforcedPageScaleFactor = 0.5;
1333 FrameTestHelpers::WebViewHelper webViewHelper;
1334 webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings);
1335 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1336 webViewHelper.webView()->settings()->setUseWideViewport(false);
1337 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1338 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1339 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1341 EXPECT_EQ(viewportWidth / enforcedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1342 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1345 TEST_F(WebFrameTest, WideViewportInitialScaleDoesNotExpandFixedLayoutWidth)
1347 UseMockScrollbarSettings mockScrollbarSettings;
1348 registerMockedHttpURLLoad("viewport-device-0.5x-initial-scale.html");
1350 FixedLayoutTestWebViewClient client;
1351 client.m_screenInfo.deviceScaleFactor = 1;
1352 int viewportWidth = 640;
1353 int viewportHeight = 480;
1355 FrameTestHelpers::WebViewHelper webViewHelper;
1356 webViewHelper.initializeAndLoad(m_baseURL + "viewport-device-0.5x-initial-scale.html", true, 0, &client, enableViewportSettings);
1357 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1358 webViewHelper.webView()->settings()->setUseWideViewport(true);
1359 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1360 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1362 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1363 EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor());
1365 webViewHelper.webView()->setFixedLayoutSize(WebSize(2000, 1500));
1366 webViewHelper.webView()->layout();
1367 EXPECT_EQ(2000, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1368 EXPECT_EQ(0.5f, webViewHelper.webView()->pageScaleFactor());
1371 TEST_F(WebFrameTest, WideViewportAndWideContentWithInitialScale)
1373 UseMockScrollbarSettings mockScrollbarSettings;
1374 registerMockedHttpURLLoad("wide_document_width_viewport.html");
1376 FixedLayoutTestWebViewClient client;
1377 client.m_screenInfo.deviceScaleFactor = 1;
1378 int viewportWidth = 600;
1379 int viewportHeight = 800;
1381 FrameTestHelpers::WebViewHelper webViewHelper;
1382 webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings);
1383 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1384 webViewHelper.webView()->settings()->setUseWideViewport(true);
1385 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1386 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1388 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "wide_document_width_viewport.html");
1389 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1391 int wideDocumentWidth = 800;
1392 float minimumPageScaleFactor = viewportWidth / (float) wideDocumentWidth;
1393 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1394 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->minimumPageScaleFactor());
1397 TEST_F(WebFrameTest, WideViewportQuirkClobbersHeight)
1399 UseMockScrollbarSettings mockScrollbarSettings;
1400 registerMockedHttpURLLoad("viewport-height-1000.html");
1402 FixedLayoutTestWebViewClient client;
1403 client.m_screenInfo.deviceScaleFactor = 1;
1404 int viewportWidth = 600;
1405 int viewportHeight = 800;
1407 FrameTestHelpers::WebViewHelper webViewHelper;
1408 webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings);
1409 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1410 webViewHelper.webView()->settings()->setUseWideViewport(false);
1411 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1412 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1414 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport-height-1000.html");
1415 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1417 EXPECT_EQ(800, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1418 EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor());
1421 TEST_F(WebFrameTest, LayoutSize320Quirk)
1423 UseMockScrollbarSettings mockScrollbarSettings;
1424 registerMockedHttpURLLoad("viewport/viewport-30.html");
1426 FixedLayoutTestWebViewClient client;
1427 client.m_screenInfo.deviceScaleFactor = 1;
1428 int viewportWidth = 600;
1429 int viewportHeight = 800;
1431 FrameTestHelpers::WebViewHelper webViewHelper;
1432 webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings);
1433 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1434 webViewHelper.webView()->settings()->setUseWideViewport(true);
1435 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1436 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1438 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport/viewport-30.html");
1439 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1441 EXPECT_EQ(600, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1442 EXPECT_EQ(800, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1443 EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor());
1445 // The magic number to snap to device-width is 320, so test that 321 is
1447 WebCore::Document* document = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document();
1448 WebCore::ViewportDescription description = document->viewportDescription();
1449 description.minWidth = WebCore::Length(321, WebCore::Fixed);
1450 description.maxWidth = WebCore::Length(321, WebCore::Fixed);
1451 document->setViewportDescription(description);
1452 webViewHelper.webView()->layout();
1453 EXPECT_EQ(321, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1455 description.minWidth = WebCore::Length(320, WebCore::Fixed);
1456 description.maxWidth = WebCore::Length(320, WebCore::Fixed);
1457 document->setViewportDescription(description);
1458 webViewHelper.webView()->layout();
1459 EXPECT_EQ(600, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1461 description = document->viewportDescription();
1462 description.maxHeight = WebCore::Length(1000, WebCore::Fixed);
1463 document->setViewportDescription(description);
1464 webViewHelper.webView()->layout();
1465 EXPECT_EQ(1000, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1467 description.maxHeight = WebCore::Length(320, WebCore::Fixed);
1468 document->setViewportDescription(description);
1469 webViewHelper.webView()->layout();
1470 EXPECT_EQ(800, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1473 TEST_F(WebFrameTest, ZeroValuesQuirk)
1475 UseMockScrollbarSettings mockScrollbarSettings;
1476 registerMockedHttpURLLoad("viewport-zero-values.html");
1478 FixedLayoutTestWebViewClient client;
1479 client.m_screenInfo.deviceScaleFactor = 1;
1480 int viewportWidth = 640;
1481 int viewportHeight = 480;
1483 FrameTestHelpers::WebViewHelper webViewHelper;
1484 webViewHelper.initialize(true, 0, &client, enableViewportSettings);
1485 webViewHelper.webView()->settings()->setViewportMetaZeroValuesQuirk(true);
1486 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1487 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1488 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport-zero-values.html");
1489 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1491 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1492 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
1494 webViewHelper.webView()->settings()->setUseWideViewport(true);
1495 webViewHelper.webView()->layout();
1496 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1497 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
1500 TEST_F(WebFrameTest, OverflowHiddenDisablesScrolling)
1502 registerMockedHttpURLLoad("body-overflow-hidden.html");
1504 FixedLayoutTestWebViewClient client;
1505 client.m_screenInfo.deviceScaleFactor = 1;
1506 int viewportWidth = 640;
1507 int viewportHeight = 480;
1509 FrameTestHelpers::WebViewHelper webViewHelper;
1510 webViewHelper.initialize(true, 0, &client);
1511 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "body-overflow-hidden.html");
1512 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1514 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
1515 EXPECT_FALSE(view->userInputScrollable(WebCore::VerticalScrollbar));
1518 TEST_F(WebFrameTest, IgnoreOverflowHiddenQuirk)
1520 registerMockedHttpURLLoad("body-overflow-hidden.html");
1522 FixedLayoutTestWebViewClient client;
1523 client.m_screenInfo.deviceScaleFactor = 1;
1524 int viewportWidth = 640;
1525 int viewportHeight = 480;
1527 FrameTestHelpers::WebViewHelper webViewHelper;
1528 webViewHelper.initialize(true, 0, &client);
1529 webViewHelper.webView()->settings()->setIgnoreMainFrameOverflowHiddenQuirk(true);
1530 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "body-overflow-hidden.html");
1531 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1533 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
1534 EXPECT_TRUE(view->userInputScrollable(WebCore::VerticalScrollbar));
1537 TEST_F(WebFrameTest, NonZeroValuesNoQuirk)
1539 UseMockScrollbarSettings mockScrollbarSettings;
1540 registerMockedHttpURLLoad("viewport-nonzero-values.html");
1542 FixedLayoutTestWebViewClient client;
1543 client.m_screenInfo.deviceScaleFactor = 1;
1544 int viewportWidth = 640;
1545 int viewportHeight = 480;
1546 float expectedPageScaleFactor = 0.5f;
1548 FrameTestHelpers::WebViewHelper webViewHelper;
1549 webViewHelper.initialize(true, 0, &client, enableViewportSettings);
1550 webViewHelper.webView()->settings()->setViewportMetaZeroValuesQuirk(true);
1551 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1552 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport-nonzero-values.html");
1553 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1555 EXPECT_EQ(viewportWidth / expectedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1556 EXPECT_EQ(expectedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1558 webViewHelper.webView()->settings()->setUseWideViewport(true);
1559 webViewHelper.webView()->layout();
1560 EXPECT_EQ(viewportWidth / expectedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1561 EXPECT_EQ(expectedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1564 TEST_F(WebFrameTest, setPageScaleFactorDoesNotLayout)
1566 UseMockScrollbarSettings mockScrollbarSettings;
1567 registerMockedHttpURLLoad("fixed_layout.html");
1569 FixedLayoutTestWebViewClient client;
1570 client.m_screenInfo.deviceScaleFactor = 1;
1571 // Small viewport to ensure there are always scrollbars.
1572 int viewportWidth = 64;
1573 int viewportHeight = 48;
1575 FrameTestHelpers::WebViewHelper webViewHelper;
1576 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1577 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1578 webViewHelper.webView()->layout();
1580 int prevLayoutCount = webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount();
1581 webViewHelper.webViewImpl()->setPageScaleFactor(3);
1582 EXPECT_FALSE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
1583 EXPECT_EQ(prevLayoutCount, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount());
1586 TEST_F(WebFrameTest, setPageScaleFactorWithOverlayScrollbarsDoesNotLayout)
1588 UseMockScrollbarSettings mockScrollbarSettings;
1590 registerMockedHttpURLLoad("fixed_layout.html");
1592 FixedLayoutTestWebViewClient client;
1593 client.m_screenInfo.deviceScaleFactor = 1;
1594 int viewportWidth = 640;
1595 int viewportHeight = 480;
1597 FrameTestHelpers::WebViewHelper webViewHelper;
1598 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1599 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1600 webViewHelper.webView()->layout();
1602 int prevLayoutCount = webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount();
1603 webViewHelper.webViewImpl()->setPageScaleFactor(30);
1604 EXPECT_FALSE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
1605 EXPECT_EQ(prevLayoutCount, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount());
1609 TEST_F(WebFrameTest, pageScaleFactorWrittenToHistoryItem)
1611 UseMockScrollbarSettings mockScrollbarSettings;
1612 registerMockedHttpURLLoad("fixed_layout.html");
1614 FixedLayoutTestWebViewClient client;
1615 client.m_screenInfo.deviceScaleFactor = 1;
1616 int viewportWidth = 640;
1617 int viewportHeight = 480;
1619 FrameTestHelpers::WebViewHelper webViewHelper;
1620 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1621 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1622 webViewHelper.webView()->layout();
1624 webViewHelper.webView()->setPageScaleFactor(3);
1625 EXPECT_EQ(3, toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->loader().currentItem()->pageScaleFactor());
1628 TEST_F(WebFrameTest, initialScaleWrittenToHistoryItem)
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 int defaultFixedLayoutWidth = 980;
1644 float minimumPageScaleFactor = viewportWidth / (float) defaultFixedLayoutWidth;
1645 EXPECT_EQ(minimumPageScaleFactor, toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->loader().currentItem()->pageScaleFactor());
1648 TEST_F(WebFrameTest, pageScaleFactorShrinksViewport)
1650 UseMockScrollbarSettings mockScrollbarSettings;
1651 registerMockedHttpURLLoad("large-div.html");
1653 FixedLayoutTestWebViewClient client;
1654 client.m_screenInfo.deviceScaleFactor = 1;
1655 // Small viewport to ensure there are always scrollbars.
1656 int viewportWidth = 64;
1657 int viewportHeight = 48;
1659 FrameTestHelpers::WebViewHelper webViewHelper;
1660 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client, enableViewportSettings);
1661 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1662 webViewHelper.webView()->layout();
1664 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
1665 int viewportWidthMinusScrollbar = viewportWidth - (view->verticalScrollbar()->isOverlayScrollbar() ? 0 : 15);
1666 int viewportHeightMinusScrollbar = viewportHeight - (view->horizontalScrollbar()->isOverlayScrollbar() ? 0 : 15);
1668 webViewHelper.webView()->setPageScaleFactor(2);
1670 WebCore::IntSize unscaledSize = view->unscaledVisibleContentSize(WebCore::IncludeScrollbars);
1671 EXPECT_EQ(viewportWidth, unscaledSize.width());
1672 EXPECT_EQ(viewportHeight, unscaledSize.height());
1674 WebCore::IntSize unscaledSizeMinusScrollbar = view->unscaledVisibleContentSize(WebCore::ExcludeScrollbars);
1675 EXPECT_EQ(viewportWidthMinusScrollbar, unscaledSizeMinusScrollbar.width());
1676 EXPECT_EQ(viewportHeightMinusScrollbar, unscaledSizeMinusScrollbar.height());
1678 WebCore::IntSize scaledSize = view->visibleContentRect().size();
1679 EXPECT_EQ(ceil(viewportWidthMinusScrollbar / 2.0), scaledSize.width());
1680 EXPECT_EQ(ceil(viewportHeightMinusScrollbar / 2.0), scaledSize.height());
1683 TEST_F(WebFrameTest, pageScaleFactorDoesNotApplyCssTransform)
1685 UseMockScrollbarSettings mockScrollbarSettings;
1686 registerMockedHttpURLLoad("fixed_layout.html");
1688 FixedLayoutTestWebViewClient client;
1689 client.m_screenInfo.deviceScaleFactor = 1;
1690 int viewportWidth = 640;
1691 int viewportHeight = 480;
1693 FrameTestHelpers::WebViewHelper webViewHelper;
1694 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1695 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1696 webViewHelper.webView()->layout();
1698 webViewHelper.webView()->setPageScaleFactor(2);
1700 EXPECT_EQ(980, toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->contentRenderer()->unscaledDocumentRect().width());
1701 EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1704 TEST_F(WebFrameTest, targetDensityDpiHigh)
1706 UseMockScrollbarSettings mockScrollbarSettings;
1707 registerMockedHttpURLLoad("viewport-target-densitydpi-high.html");
1709 FixedLayoutTestWebViewClient client;
1711 float targetDpi = 240.0f;
1712 float deviceScaleFactors[] = { 1.0f, 4.0f / 3.0f, 2.0f };
1713 int viewportWidth = 640;
1714 int viewportHeight = 480;
1716 for (size_t i = 0; i < ARRAY_SIZE(deviceScaleFactors); ++i) {
1717 float deviceScaleFactor = deviceScaleFactors[i];
1718 float deviceDpi = deviceScaleFactor * 160.0f;
1719 client.m_screenInfo.deviceScaleFactor = deviceScaleFactor;
1721 FrameTestHelpers::WebViewHelper webViewHelper;
1722 webViewHelper.initializeAndLoad(m_baseURL + "viewport-target-densitydpi-high.html", true, 0, &client, enableViewportSettings);
1723 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1724 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1725 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1727 // We need to account for the fact that logical pixels are unconditionally multiplied by deviceScaleFactor to produce
1729 float densityDpiScaleRatio = deviceScaleFactor * targetDpi / deviceDpi;
1730 EXPECT_NEAR(viewportWidth * densityDpiScaleRatio, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1731 EXPECT_NEAR(viewportHeight * densityDpiScaleRatio, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1732 EXPECT_NEAR(1.0f / densityDpiScaleRatio, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1736 TEST_F(WebFrameTest, targetDensityDpiDevice)
1738 UseMockScrollbarSettings mockScrollbarSettings;
1739 registerMockedHttpURLLoad("viewport-target-densitydpi-device.html");
1741 float deviceScaleFactors[] = { 1.0f, 4.0f / 3.0f, 2.0f };
1743 FixedLayoutTestWebViewClient client;
1744 int viewportWidth = 640;
1745 int viewportHeight = 480;
1747 for (size_t i = 0; i < ARRAY_SIZE(deviceScaleFactors); ++i) {
1748 client.m_screenInfo.deviceScaleFactor = deviceScaleFactors[i];
1750 FrameTestHelpers::WebViewHelper webViewHelper;
1751 webViewHelper.initializeAndLoad(m_baseURL + "viewport-target-densitydpi-device.html", true, 0, &client, enableViewportSettings);
1752 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1753 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1754 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1756 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1757 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1758 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1762 TEST_F(WebFrameTest, targetDensityDpiDeviceAndFixedWidth)
1764 UseMockScrollbarSettings mockScrollbarSettings;
1765 registerMockedHttpURLLoad("viewport-target-densitydpi-device-and-fixed-width.html");
1767 float deviceScaleFactors[] = { 1.0f, 4.0f / 3.0f, 2.0f };
1769 FixedLayoutTestWebViewClient client;
1770 int viewportWidth = 640;
1771 int viewportHeight = 480;
1773 for (size_t i = 0; i < ARRAY_SIZE(deviceScaleFactors); ++i) {
1774 client.m_screenInfo.deviceScaleFactor = deviceScaleFactors[i];
1776 FrameTestHelpers::WebViewHelper webViewHelper;
1777 webViewHelper.initializeAndLoad(m_baseURL + "viewport-target-densitydpi-device-and-fixed-width.html", true, 0, &client, enableViewportSettings);
1778 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1779 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1780 webViewHelper.webView()->settings()->setUseWideViewport(true);
1781 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1783 EXPECT_NEAR(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1784 EXPECT_NEAR(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1785 EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1789 TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOne)
1791 UseMockScrollbarSettings mockScrollbarSettings;
1792 registerMockedHttpURLLoad("viewport-initial-scale-less-than-1.html");
1794 FixedLayoutTestWebViewClient client;
1795 client.m_screenInfo.deviceScaleFactor = 1.33f;
1796 int viewportWidth = 640;
1797 int viewportHeight = 480;
1799 FrameTestHelpers::WebViewHelper webViewHelper;
1800 webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-less-than-1.html", true, 0, &client, enableViewportSettings);
1801 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1802 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1803 webViewHelper.webView()->settings()->setUseWideViewport(false);
1804 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1805 webViewHelper.webView()->layout();
1807 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1808 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1809 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1812 TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOneWithDeviceWidth)
1814 UseMockScrollbarSettings mockScrollbarSettings;
1815 registerMockedHttpURLLoad("viewport-initial-scale-less-than-1-device-width.html");
1817 FixedLayoutTestWebViewClient client;
1818 client.m_screenInfo.deviceScaleFactor = 1.33f;
1819 int viewportWidth = 640;
1820 int viewportHeight = 480;
1822 FrameTestHelpers::WebViewHelper webViewHelper;
1823 webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-less-than-1-device-width.html", true, 0, &client, enableViewportSettings);
1824 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1825 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1826 webViewHelper.webView()->settings()->setUseWideViewport(false);
1827 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1828 webViewHelper.webView()->layout();
1830 const float pageZoom = 0.25f;
1831 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor / pageZoom, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1832 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor / pageZoom, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1833 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1836 TEST_F(WebFrameTest, NoWideViewportAndNoViewportWithInitialPageScaleOverride)
1838 UseMockScrollbarSettings mockScrollbarSettings;
1839 registerMockedHttpURLLoad("large-div.html");
1841 FixedLayoutTestWebViewClient client;
1842 int viewportWidth = 640;
1843 int viewportHeight = 480;
1844 float enforcedPageScaleFactor = 5.0f;
1846 FrameTestHelpers::WebViewHelper webViewHelper;
1847 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client, enableViewportSettings);
1848 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1849 webViewHelper.webView()->settings()->setUseWideViewport(false);
1850 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1851 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1852 webViewHelper.webView()->layout();
1854 EXPECT_NEAR(viewportWidth / enforcedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1855 EXPECT_NEAR(viewportHeight / enforcedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1856 EXPECT_NEAR(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1859 TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScale)
1861 UseMockScrollbarSettings mockScrollbarSettings;
1862 registerMockedHttpURLLoad("viewport-initial-scale-and-user-scalable-no.html");
1864 FixedLayoutTestWebViewClient client;
1865 int viewportWidth = 640;
1866 int viewportHeight = 480;
1868 FrameTestHelpers::WebViewHelper webViewHelper;
1869 webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-and-user-scalable-no.html", true, 0, &client, enableViewportSettings);
1870 webViewHelper.webView()->settings()->setViewportMetaNonUserScalableQuirk(true);
1871 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1872 webViewHelper.webView()->layout();
1874 EXPECT_NEAR(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1875 EXPECT_NEAR(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1876 EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1879 TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScaleForNonWideViewport)
1881 UseMockScrollbarSettings mockScrollbarSettings;
1882 registerMockedHttpURLLoad("viewport-initial-scale-and-user-scalable-no.html");
1884 FixedLayoutTestWebViewClient client;
1885 client.m_screenInfo.deviceScaleFactor = 1.33f;
1886 int viewportWidth = 640;
1887 int viewportHeight = 480;
1889 FrameTestHelpers::WebViewHelper webViewHelper;
1890 webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-and-user-scalable-no.html", true, 0, &client, enableViewportSettings);
1891 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1892 webViewHelper.webView()->settings()->setViewportMetaNonUserScalableQuirk(true);
1893 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1894 webViewHelper.webView()->settings()->setUseWideViewport(false);
1895 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1896 webViewHelper.webView()->layout();
1898 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1899 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1900 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1903 TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScaleForWideViewport)
1905 UseMockScrollbarSettings mockScrollbarSettings;
1906 registerMockedHttpURLLoad("viewport-2x-initial-scale-non-user-scalable.html");
1908 FixedLayoutTestWebViewClient client;
1909 int viewportWidth = 640;
1910 int viewportHeight = 480;
1912 FrameTestHelpers::WebViewHelper webViewHelper;
1913 webViewHelper.initializeAndLoad(m_baseURL + "viewport-2x-initial-scale-non-user-scalable.html", true, 0, &client, enableViewportSettings);
1914 webViewHelper.webView()->settings()->setViewportMetaNonUserScalableQuirk(true);
1915 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1916 webViewHelper.webView()->settings()->setUseWideViewport(true);
1917 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1919 EXPECT_NEAR(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1920 EXPECT_NEAR(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1921 EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1924 TEST_F(WebFrameTest, DesktopPageCanBeZoomedInWhenWideViewportIsTurnedOff)
1926 UseMockScrollbarSettings mockScrollbarSettings;
1927 registerMockedHttpURLLoad("no_viewport_tag.html");
1929 FixedLayoutTestWebViewClient client;
1930 int viewportWidth = 640;
1931 int viewportHeight = 480;
1933 FrameTestHelpers::WebViewHelper webViewHelper;
1934 webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client, enableViewportSettings);
1935 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1936 webViewHelper.webView()->settings()->setUseWideViewport(false);
1937 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1939 EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1940 EXPECT_NEAR(1.0f, webViewHelper.webView()->minimumPageScaleFactor(), 0.01f);
1941 EXPECT_NEAR(5.0f, webViewHelper.webView()->maximumPageScaleFactor(), 0.01f);
1944 class WebFrameResizeTest : public WebFrameTest {
1947 static WebCore::FloatSize computeRelativeOffset(const WebCore::IntPoint& absoluteOffset, const WebCore::LayoutRect& rect)
1949 WebCore::FloatSize relativeOffset = WebCore::FloatPoint(absoluteOffset) - rect.location();
1950 relativeOffset.scale(1.f / rect.width(), 1.f / rect.height());
1951 return relativeOffset;
1954 void testResizeYieldsCorrectScrollAndScale(const char* url,
1955 const float initialPageScaleFactor,
1956 const WebSize scrollOffset,
1957 const WebSize viewportSize,
1958 const bool shouldScaleRelativeToViewportWidth) {
1959 UseMockScrollbarSettings mockScrollbarSettings;
1960 registerMockedHttpURLLoad(url);
1962 const float aspectRatio = static_cast<float>(viewportSize.width) / viewportSize.height;
1964 FrameTestHelpers::WebViewHelper webViewHelper;
1965 webViewHelper.initializeAndLoad(m_baseURL + url, true, 0, 0, enableViewportSettings);
1967 // Origin scrollOffsets preserved under resize.
1969 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height));
1970 webViewHelper.webViewImpl()->setPageScaleFactor(initialPageScaleFactor);
1971 ASSERT_EQ(viewportSize, webViewHelper.webViewImpl()->size());
1972 ASSERT_EQ(initialPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor());
1973 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.height, viewportSize.width));
1974 float expectedPageScaleFactor = initialPageScaleFactor * (shouldScaleRelativeToViewportWidth ? 1 / aspectRatio : 1);
1975 EXPECT_NEAR(expectedPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor(), 0.05f);
1976 EXPECT_EQ(WebSize(), webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
1979 // Resizing just the height should not affect pageScaleFactor or scrollOffset.
1981 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height));
1982 webViewHelper.webViewImpl()->setPageScaleFactor(initialPageScaleFactor);
1983 webViewHelper.webViewImpl()->setMainFrameScrollOffset(WebPoint(scrollOffset.width, scrollOffset.height));
1984 webViewHelper.webViewImpl()->layout();
1985 const WebSize expectedScrollOffset = webViewHelper.webViewImpl()->mainFrame()->scrollOffset();
1986 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height * 0.8f));
1987 EXPECT_EQ(initialPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor());
1988 EXPECT_EQ(expectedScrollOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
1989 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height * 0.8f));
1990 EXPECT_EQ(initialPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor());
1991 EXPECT_EQ(expectedScrollOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
1994 // Generic resize preserves scrollOffset relative to anchor node located
1995 // the top center of the screen.
1997 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.height, viewportSize.width));
1998 float pageScaleFactor = webViewHelper.webViewImpl()->pageScaleFactor();
1999 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height));
2000 float expectedPageScaleFactor = pageScaleFactor * (shouldScaleRelativeToViewportWidth ? aspectRatio : 1);
2001 EXPECT_NEAR(expectedPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor(), 0.05f);
2002 webViewHelper.webViewImpl()->mainFrame()->setScrollOffset(scrollOffset);
2004 WebCore::IntPoint anchorPoint = WebCore::IntPoint(scrollOffset) + WebCore::IntPoint(viewportSize.width / 2, 0);
2005 RefPtrWillBeRawPtr<WebCore::Node> anchorNode = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->eventHandler().hitTestResultAtPoint(anchorPoint, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent).innerNode();
2008 pageScaleFactor = webViewHelper.webViewImpl()->pageScaleFactor();
2009 const WebCore::FloatSize preResizeRelativeOffset
2010 = computeRelativeOffset(anchorPoint, anchorNode->boundingBox());
2011 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.height, viewportSize.width));
2012 WebCore::IntPoint newAnchorPoint = WebCore::IntPoint(webViewHelper.webViewImpl()->mainFrame()->scrollOffset()) + WebCore::IntPoint(viewportSize.height / 2, 0);
2013 const WebCore::FloatSize postResizeRelativeOffset
2014 = computeRelativeOffset(newAnchorPoint, anchorNode->boundingBox());
2015 EXPECT_NEAR(preResizeRelativeOffset.width(), postResizeRelativeOffset.width(), 0.15f);
2016 expectedPageScaleFactor = pageScaleFactor * (shouldScaleRelativeToViewportWidth ? 1 / aspectRatio : 1);
2017 EXPECT_NEAR(expectedPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor(), 0.05f);
2022 TEST_F(WebFrameResizeTest, ResizeYieldsCorrectScrollAndScaleForWidthEqualsDeviceWidth)
2024 // With width=device-width, pageScaleFactor is preserved across resizes as
2025 // long as the content adjusts according to the device-width.
2026 const char* url = "resize_scroll_mobile.html";
2027 const float initialPageScaleFactor = 1;
2028 const WebSize scrollOffset(0, 50);
2029 const WebSize viewportSize(120, 160);
2030 const bool shouldScaleRelativeToViewportWidth = true;
2032 testResizeYieldsCorrectScrollAndScale(
2033 url, initialPageScaleFactor, scrollOffset, viewportSize, shouldScaleRelativeToViewportWidth);
2036 TEST_F(WebFrameResizeTest, ResizeYieldsCorrectScrollAndScaleForFixedWidth)
2038 // With a fixed width, pageScaleFactor scales by the relative change in viewport width.
2039 const char* url = "resize_scroll_fixed_width.html";
2040 const float initialPageScaleFactor = 2;
2041 const WebSize scrollOffset(0, 200);
2042 const WebSize viewportSize(240, 320);
2043 const bool shouldScaleRelativeToViewportWidth = true;
2045 testResizeYieldsCorrectScrollAndScale(
2046 url, initialPageScaleFactor, scrollOffset, viewportSize, shouldScaleRelativeToViewportWidth);
2049 TEST_F(WebFrameResizeTest, ResizeYieldsCorrectScrollAndScaleForFixedLayout)
2051 // With a fixed layout, pageScaleFactor scales by the relative change in viewport width.
2052 const char* url = "resize_scroll_fixed_layout.html";
2053 const float initialPageScaleFactor = 2;
2054 const WebSize scrollOffset(200, 400);
2055 const WebSize viewportSize(320, 240);
2056 const bool shouldScaleRelativeToViewportWidth = true;
2058 testResizeYieldsCorrectScrollAndScale(
2059 url, initialPageScaleFactor, scrollOffset, viewportSize, shouldScaleRelativeToViewportWidth);
2062 TEST_F(WebFrameTest, pageScaleFactorScalesPaintClip)
2064 UseMockScrollbarSettings mockScrollbarSettings;
2065 registerMockedHttpURLLoad("large-div.html");
2067 FixedLayoutTestWebViewClient client;
2068 client.m_screenInfo.deviceScaleFactor = 1;
2069 int viewportWidth = 50;
2070 int viewportHeight = 50;
2072 FrameTestHelpers::WebViewHelper webViewHelper;
2073 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client);
2074 // FIXME: This test breaks if the viewport is enabled before loading the page due to the paint
2075 // calls below not working on composited layers. For some reason, enabling the viewport here
2076 // doesn't cause compositing
2077 webViewHelper.webView()->settings()->setViewportEnabled(true);
2078 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2079 webViewHelper.webView()->layout();
2081 // Set <1 page scale so that the clip rect should be larger than
2082 // the viewport size as passed into resize().
2083 webViewHelper.webView()->setPageScaleFactor(0.5);
2086 ASSERT_TRUE(bitmap.allocN32Pixels(200, 200));
2087 bitmap.eraseColor(0);
2088 SkCanvas canvas(bitmap);
2090 WebCore::GraphicsContext context(&canvas);
2091 context.setTrackOpaqueRegion(true);
2093 EXPECT_EQ_RECT(WebCore::IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
2095 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
2096 WebCore::IntRect paintRect(0, 0, 200, 200);
2097 view->paint(&context, paintRect);
2099 // FIXME: This test broke in release builds when changing the FixedLayoutTestWebViewClient
2100 // to return a non-null layerTreeView, which is what all our shipping configurations do,
2101 // so this is just exposing an existing bug.
2104 int viewportWidthMinusScrollbar = 50 - (view->verticalScrollbar()->isOverlayScrollbar() ? 0 : 15);
2105 int viewportHeightMinusScrollbar = 50 - (view->horizontalScrollbar()->isOverlayScrollbar() ? 0 : 15);
2106 WebCore::IntRect clippedRect(0, 0, viewportWidthMinusScrollbar * 2, viewportHeightMinusScrollbar * 2);
2107 EXPECT_EQ_RECT(clippedRect, context.opaqueRegion().asRect());
2111 TEST_F(WebFrameTest, pageScaleFactorUpdatesScrollbars)
2113 UseMockScrollbarSettings mockScrollbarSettings;
2114 registerMockedHttpURLLoad("fixed_layout.html");
2116 FixedLayoutTestWebViewClient client;
2117 client.m_screenInfo.deviceScaleFactor = 1;
2118 int viewportWidth = 640;
2119 int viewportHeight = 480;
2121 FrameTestHelpers::WebViewHelper webViewHelper;
2122 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
2123 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2124 webViewHelper.webView()->layout();
2126 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
2127 EXPECT_EQ(view->scrollSize(WebCore::HorizontalScrollbar), view->contentsSize().width() - view->visibleContentRect().width());
2128 EXPECT_EQ(view->scrollSize(WebCore::VerticalScrollbar), view->contentsSize().height() - view->visibleContentRect().height());
2130 webViewHelper.webView()->setPageScaleFactor(10);
2132 EXPECT_EQ(view->scrollSize(WebCore::HorizontalScrollbar), view->contentsSize().width() - view->visibleContentRect().width());
2133 EXPECT_EQ(view->scrollSize(WebCore::VerticalScrollbar), view->contentsSize().height() - view->visibleContentRect().height());
2136 TEST_F(WebFrameTest, CanOverrideScaleLimits)
2138 UseMockScrollbarSettings mockScrollbarSettings;
2140 registerMockedHttpURLLoad("no_scale_for_you.html");
2142 FixedLayoutTestWebViewClient client;
2143 client.m_screenInfo.deviceScaleFactor = 1;
2144 int viewportWidth = 640;
2145 int viewportHeight = 480;
2147 FrameTestHelpers::WebViewHelper webViewHelper;
2148 webViewHelper.initializeAndLoad(m_baseURL + "no_scale_for_you.html", true, 0, &client, enableViewportSettings);
2149 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2151 EXPECT_EQ(2.0f, webViewHelper.webView()->minimumPageScaleFactor());
2152 EXPECT_EQ(2.0f, webViewHelper.webView()->maximumPageScaleFactor());
2154 webViewHelper.webView()->setIgnoreViewportTagScaleLimits(true);
2155 webViewHelper.webView()->layout();
2157 EXPECT_EQ(1.0f, webViewHelper.webView()->minimumPageScaleFactor());
2158 EXPECT_EQ(5.0f, webViewHelper.webView()->maximumPageScaleFactor());
2160 webViewHelper.webView()->setIgnoreViewportTagScaleLimits(false);
2161 webViewHelper.webView()->layout();
2163 EXPECT_EQ(2.0f, webViewHelper.webView()->minimumPageScaleFactor());
2164 EXPECT_EQ(2.0f, webViewHelper.webView()->maximumPageScaleFactor());
2167 TEST_F(WebFrameTest, updateOverlayScrollbarLayers)
2169 UseMockScrollbarSettings mockScrollbarSettings;
2171 registerMockedHttpURLLoad("large-div.html");
2173 int viewWidth = 500;
2174 int viewHeight = 500;
2176 OwnPtr<FakeCompositingWebViewClient> fakeCompositingWebViewClient = adoptPtr(new FakeCompositingWebViewClient());
2177 FrameTestHelpers::WebViewHelper webViewHelper;
2178 webViewHelper.initialize(true, 0, fakeCompositingWebViewClient.get(), &configueCompositingWebView);
2180 webViewHelper.webView()->setPageScaleFactorLimits(1, 1);
2181 webViewHelper.webView()->resize(WebSize(viewWidth, viewHeight));
2182 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "large-div.html");
2184 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
2185 EXPECT_TRUE(view->renderView()->compositor()->layerForHorizontalScrollbar());
2186 EXPECT_TRUE(view->renderView()->compositor()->layerForVerticalScrollbar());
2188 webViewHelper.webView()->resize(WebSize(viewWidth * 10, viewHeight * 10));
2189 webViewHelper.webView()->layout();
2190 EXPECT_FALSE(view->renderView()->compositor()->layerForHorizontalScrollbar());
2191 EXPECT_FALSE(view->renderView()->compositor()->layerForVerticalScrollbar());
2194 void setScaleAndScrollAndLayout(blink::WebView* webView, WebPoint scroll, float scale)
2196 webView->setPageScaleFactor(scale);
2197 webView->setMainFrameScrollOffset(WebPoint(scroll.x, scroll.y));
2201 TEST_F(WebFrameTest, DivAutoZoomParamsTest)
2203 registerMockedHttpURLLoad("get_scale_for_auto_zoom_into_div_test.html");
2205 const float deviceScaleFactor = 2.0f;
2206 int viewportWidth = 640 / deviceScaleFactor;
2207 int viewportHeight = 1280 / deviceScaleFactor;
2208 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2209 FrameTestHelpers::WebViewHelper webViewHelper;
2210 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_for_auto_zoom_into_div_test.html");
2211 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2212 webViewHelper.webView()->setPageScaleFactorLimits(0.01f, 4);
2213 webViewHelper.webView()->setPageScaleFactor(0.5f);
2214 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2215 webViewHelper.webView()->layout();
2217 WebRect wideDiv(200, 100, 400, 150);
2218 WebRect tallDiv(200, 300, 400, 800);
2219 WebRect doubleTapPointWide(wideDiv.x + 50, wideDiv.y + 50, touchPointPadding, touchPointPadding);
2220 WebRect doubleTapPointTall(tallDiv.x + 50, tallDiv.y + 50, touchPointPadding, touchPointPadding);
2221 WebRect wideBlockBounds;
2222 WebRect tallBlockBounds;
2226 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2228 // Test double-tap zooming into wide div.
2229 wideBlockBounds = webViewHelper.webViewImpl()->computeBlockBounds(doubleTapPointWide, false);
2230 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(doubleTapPointWide.x, doubleTapPointWide.y), wideBlockBounds, touchPointPadding, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2231 // The div should horizontally fill the screen (modulo margins), and
2232 // vertically centered (modulo integer rounding).
2233 EXPECT_NEAR(viewportWidth / (float) wideDiv.width, scale, 0.1);
2234 EXPECT_NEAR(wideDiv.x, scroll.x, 20);
2235 EXPECT_EQ(0, scroll.y);
2237 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), scroll, scale);
2239 // Test zoom out back to minimum scale.
2240 wideBlockBounds = webViewHelper.webViewImpl()->computeBlockBounds(doubleTapPointWide, false);
2241 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(doubleTapPointWide.x, doubleTapPointWide.y), wideBlockBounds, touchPointPadding, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2243 scale = webViewHelper.webViewImpl()->minimumPageScaleFactor();
2244 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), scale);
2246 // Test double-tap zooming into tall div.
2247 tallBlockBounds = webViewHelper.webViewImpl()->computeBlockBounds(doubleTapPointTall, false);
2248 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(doubleTapPointTall.x, doubleTapPointTall.y), tallBlockBounds, touchPointPadding, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2249 // The div should start at the top left of the viewport.
2250 EXPECT_NEAR(viewportWidth / (float) tallDiv.width, scale, 0.1);
2251 EXPECT_NEAR(tallDiv.x, scroll.x, 20);
2252 EXPECT_NEAR(tallDiv.y, scroll.y, 20);
2254 // Test for Non-doubletap scaling
2255 // Test zooming into div.
2256 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(250, 250), webViewHelper.webViewImpl()->computeBlockBounds(WebRect(250, 250, 10, 10), true), 0, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2257 EXPECT_NEAR(viewportWidth / (float) wideDiv.width, scale, 0.1);
2260 void simulatePageScale(WebViewImpl* webViewImpl, float& scale)
2262 WebCore::IntSize scrollDelta = webViewImpl->fakePageScaleAnimationTargetPositionForTesting() - webViewImpl->mainFrameImpl()->frameView()->scrollPosition();
2263 float scaleDelta = webViewImpl->fakePageScaleAnimationPageScaleForTesting() / webViewImpl->pageScaleFactor();
2264 webViewImpl->applyScrollAndScale(scrollDelta, scaleDelta);
2265 scale = webViewImpl->pageScaleFactor();
2268 void simulateMultiTargetZoom(WebViewImpl* webViewImpl, const WebRect& rect, float& scale)
2270 if (webViewImpl->zoomToMultipleTargetsRect(rect))
2271 simulatePageScale(webViewImpl, scale);
2274 void simulateDoubleTap(WebViewImpl* webViewImpl, WebPoint& point, float& scale)
2276 webViewImpl->animateDoubleTapZoom(point);
2277 EXPECT_TRUE(webViewImpl->fakeDoubleTapAnimationPendingForTesting());
2278 simulatePageScale(webViewImpl, scale);
2281 TEST_F(WebFrameTest, DivAutoZoomWideDivTest)
2283 registerMockedHttpURLLoad("get_wide_div_for_auto_zoom_test.html");
2285 const float deviceScaleFactor = 2.0f;
2286 int viewportWidth = 640 / deviceScaleFactor;
2287 int viewportHeight = 1280 / deviceScaleFactor;
2288 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2289 FrameTestHelpers::WebViewHelper webViewHelper;
2290 webViewHelper.initializeAndLoad(m_baseURL + "get_wide_div_for_auto_zoom_test.html");
2291 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2292 webViewHelper.webView()->setPageScaleFactorLimits(1.0f, 4);
2293 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2294 webViewHelper.webView()->setPageScaleFactor(1.0f);
2295 webViewHelper.webView()->layout();
2297 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2299 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2301 WebRect div(0, 100, viewportWidth, 150);
2302 WebPoint point(div.x + 50, div.y + 50);
2304 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2306 simulateDoubleTap(webViewHelper.webViewImpl(), point, scale);
2307 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2308 simulateDoubleTap(webViewHelper.webViewImpl(), point, scale);
2309 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2312 TEST_F(WebFrameTest, DivAutoZoomVeryTallTest)
2314 // When a block is taller than the viewport and a zoom targets a lower part
2315 // of it, then we should keep the target point onscreen instead of snapping
2316 // back up the top of the block.
2317 registerMockedHttpURLLoad("very_tall_div.html");
2319 const float deviceScaleFactor = 2.0f;
2320 int viewportWidth = 640 / deviceScaleFactor;
2321 int viewportHeight = 1280 / deviceScaleFactor;
2322 FrameTestHelpers::WebViewHelper webViewHelper;
2323 webViewHelper.initializeAndLoad(m_baseURL + "very_tall_div.html", true, 0, 0, enableViewportSettings);
2324 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2325 webViewHelper.webView()->setPageScaleFactorLimits(1.0f, 4);
2326 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2327 webViewHelper.webView()->setPageScaleFactor(1.0f);
2328 webViewHelper.webView()->layout();
2330 WebRect div(200, 300, 400, 5000);
2331 WebPoint point(div.x + 50, div.y + 3000);
2335 WebRect blockBounds = webViewHelper.webViewImpl()->computeBlockBounds(WebRect(point.x, point.y, 0, 0), true);
2336 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(point, blockBounds, 0, 1.0f, scale, scroll);
2337 EXPECT_EQ(scale, 1.0f);
2338 EXPECT_EQ(scroll.y, 2660);
2341 TEST_F(WebFrameTest, DivAutoZoomMultipleDivsTest)
2343 registerMockedHttpURLLoad("get_multiple_divs_for_auto_zoom_test.html");
2345 const float deviceScaleFactor = 2.0f;
2346 int viewportWidth = 640 / deviceScaleFactor;
2347 int viewportHeight = 1280 / deviceScaleFactor;
2348 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2349 FrameTestHelpers::WebViewHelper webViewHelper;
2350 webViewHelper.initializeAndLoad(m_baseURL + "get_multiple_divs_for_auto_zoom_test.html");
2351 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2352 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2353 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2354 webViewHelper.webView()->setPageScaleFactor(0.5f);
2355 webViewHelper.webView()->layout();
2357 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2359 WebRect topDiv(200, 100, 200, 150);
2360 WebRect bottomDiv(200, 300, 200, 150);
2361 WebPoint topPoint(topDiv.x + 50, topDiv.y + 50);
2362 WebPoint bottomPoint(bottomDiv.x + 50, bottomDiv.y + 50);
2364 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2366 // Test double tap on two different divs
2367 // After first zoom, we should go back to minimum page scale with a second double tap.
2368 simulateDoubleTap(webViewHelper.webViewImpl(), topPoint, scale);
2369 EXPECT_FLOAT_EQ(1, scale);
2370 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2371 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2373 // If the user pinch zooms after double tap, a second double tap should zoom back to the div.
2374 simulateDoubleTap(webViewHelper.webViewImpl(), topPoint, scale);
2375 EXPECT_FLOAT_EQ(1, scale);
2376 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 0.6f);
2377 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2378 EXPECT_FLOAT_EQ(1, scale);
2379 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2380 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2382 // If we didn't yet get an auto-zoom update and a second double-tap arrives, should go back to minimum scale.
2383 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2384 webViewHelper.webViewImpl()->animateDoubleTapZoom(topPoint);
2385 EXPECT_TRUE(webViewHelper.webViewImpl()->fakeDoubleTapAnimationPendingForTesting());
2386 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2387 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2390 TEST_F(WebFrameTest, DivAutoZoomScaleBoundsTest)
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 FrameTestHelpers::WebViewHelper webViewHelper;
2398 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_bounds_check_for_auto_zoom_test.html");
2399 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2400 webViewHelper.webView()->setDeviceScaleFactor(1.5f);
2401 webViewHelper.webView()->layout();
2403 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2405 WebRect div(200, 100, 200, 150);
2406 WebPoint doubleTapPoint(div.x + 50, div.y + 50);
2409 // Test double tap scale bounds.
2410 // minimumPageScale < doubleTapZoomAlreadyLegibleScale < 1
2411 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2412 webViewHelper.webView()->layout();
2413 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2414 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2415 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2416 EXPECT_FLOAT_EQ(1, scale);
2417 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2418 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2419 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2420 EXPECT_FLOAT_EQ(1, scale);
2422 // Zoom in to reset double_tap_zoom_in_effect flag.
2423 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2424 // 1 < minimumPageScale < doubleTapZoomAlreadyLegibleScale
2425 webViewHelper.webView()->setPageScaleFactorLimits(1.1f, 4);
2426 webViewHelper.webView()->layout();
2427 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2428 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2429 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2430 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2431 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2432 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2433 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2434 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2436 // Zoom in to reset double_tap_zoom_in_effect flag.
2437 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2438 // minimumPageScale < 1 < doubleTapZoomAlreadyLegibleScale
2439 webViewHelper.webView()->setPageScaleFactorLimits(0.95f, 4);
2440 webViewHelper.webView()->layout();
2441 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2442 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2443 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2444 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2445 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2446 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2447 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2448 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2451 TEST_F(WebFrameTest, DivAutoZoomScaleFontScaleFactorTest)
2453 registerMockedHttpURLLoad("get_scale_bounds_check_for_auto_zoom_test.html");
2455 int viewportWidth = 320;
2456 int viewportHeight = 480;
2457 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2458 float accessibilityFontScaleFactor = 1.13f;
2459 FrameTestHelpers::WebViewHelper webViewHelper;
2460 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_bounds_check_for_auto_zoom_test.html");
2461 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2462 webViewHelper.webView()->layout();
2464 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2465 webViewHelper.webViewImpl()->page()->settings().setTextAutosizingEnabled(true);
2466 webViewHelper.webViewImpl()->page()->settings().setAccessibilityFontScaleFactor(accessibilityFontScaleFactor);
2468 WebRect div(200, 100, 200, 150);
2469 WebPoint doubleTapPoint(div.x + 50, div.y + 50);
2472 // Test double tap scale bounds.
2473 // minimumPageScale < doubleTapZoomAlreadyLegibleScale < 1 < accessibilityFontScaleFactor
2474 float legibleScale = accessibilityFontScaleFactor;
2475 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2476 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2477 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2478 webViewHelper.webView()->layout();
2479 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2480 EXPECT_FLOAT_EQ(legibleScale, scale);
2481 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2482 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2483 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2484 EXPECT_FLOAT_EQ(legibleScale, scale);
2486 // Zoom in to reset double_tap_zoom_in_effect flag.
2487 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2488 // 1 < accessibilityFontScaleFactor < minimumPageScale < doubleTapZoomAlreadyLegibleScale
2489 webViewHelper.webView()->setPageScaleFactorLimits(1.0f, 4);
2490 webViewHelper.webView()->layout();
2491 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2492 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2493 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2494 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2495 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2496 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2497 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2498 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2500 // Zoom in to reset double_tap_zoom_in_effect flag.
2501 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2502 // minimumPageScale < 1 < accessibilityFontScaleFactor < doubleTapZoomAlreadyLegibleScale
2503 webViewHelper.webView()->setPageScaleFactorLimits(0.95f, 4);
2504 webViewHelper.webView()->layout();
2505 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2506 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2507 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2508 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2509 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2510 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2511 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2512 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2514 // Zoom in to reset double_tap_zoom_in_effect flag.
2515 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2516 // minimumPageScale < 1 < doubleTapZoomAlreadyLegibleScale < accessibilityFontScaleFactor
2517 webViewHelper.webView()->setPageScaleFactorLimits(0.9f, 4);
2518 webViewHelper.webView()->layout();
2519 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2520 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2521 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2522 EXPECT_FLOAT_EQ(legibleScale, scale);
2523 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2524 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2525 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2526 EXPECT_FLOAT_EQ(legibleScale, scale);
2529 TEST_F(WebFrameTest, DivMultipleTargetZoomMultipleDivsTest)
2531 registerMockedHttpURLLoad("get_multiple_divs_for_auto_zoom_test.html");
2533 const float deviceScaleFactor = 2.0f;
2534 int viewportWidth = 640 / deviceScaleFactor;
2535 int viewportHeight = 1280 / deviceScaleFactor;
2536 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2537 FrameTestHelpers::WebViewHelper webViewHelper;
2538 webViewHelper.initializeAndLoad(m_baseURL + "get_multiple_divs_for_auto_zoom_test.html");
2539 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2540 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2541 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2542 webViewHelper.webView()->setPageScaleFactor(0.5f);
2543 webViewHelper.webView()->layout();
2545 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2547 WebRect viewportRect(0, 0, viewportWidth, viewportHeight);
2548 WebRect topDiv(200, 100, 200, 150);
2549 WebRect bottomDiv(200, 300, 200, 150);
2551 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2553 simulateMultiTargetZoom(webViewHelper.webViewImpl(), topDiv, scale);
2554 EXPECT_FLOAT_EQ(1, scale);
2555 simulateMultiTargetZoom(webViewHelper.webViewImpl(), bottomDiv, scale);
2556 EXPECT_FLOAT_EQ(1, scale);
2557 simulateMultiTargetZoom(webViewHelper.webViewImpl(), viewportRect, scale);
2558 EXPECT_FLOAT_EQ(1, scale);
2559 webViewHelper.webViewImpl()->setPageScaleFactor(webViewHelper.webViewImpl()->minimumPageScaleFactor());
2560 simulateMultiTargetZoom(webViewHelper.webViewImpl(), topDiv, scale);
2561 EXPECT_FLOAT_EQ(1, scale);
2564 TEST_F(WebFrameTest, DivScrollIntoEditableTest)
2566 registerMockedHttpURLLoad("get_scale_for_zoom_into_editable_test.html");
2568 int viewportWidth = 450;
2569 int viewportHeight = 300;
2570 float leftBoxRatio = 0.3f;
2571 int caretPadding = 10;
2572 float minReadableCaretHeight = 18.0f;
2573 FrameTestHelpers::WebViewHelper webViewHelper;
2574 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_for_zoom_into_editable_test.html");
2575 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2576 webViewHelper.webView()->setPageScaleFactorLimits(1, 4);
2577 webViewHelper.webView()->layout();
2578 webViewHelper.webView()->setDeviceScaleFactor(1.5f);
2579 webViewHelper.webView()->settings()->setAutoZoomFocusedNodeToLegibleScale(true);
2581 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2583 WebRect editBoxWithText(200, 200, 250, 20);
2584 WebRect editBoxWithNoText(200, 250, 250, 20);
2586 // Test scrolling the focused node
2587 // The edit box is shorter and narrower than the viewport when legible.
2588 webViewHelper.webView()->advanceFocus(false);
2589 // Set the caret to the end of the input box.
2590 webViewHelper.webView()->mainFrame()->document().getElementById("EditBoxWithText").to<WebInputElement>().setSelectionRange(1000, 1000);
2591 setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), 1);
2592 WebRect rect, caret;
2593 webViewHelper.webViewImpl()->selectionBounds(caret, rect);
2596 WebCore::IntPoint scroll;
2598 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2599 EXPECT_TRUE(needAnimation);
2600 // The edit box should be left aligned with a margin for possible label.
2601 int hScroll = editBoxWithText.x - leftBoxRatio * viewportWidth / scale;
2602 EXPECT_NEAR(hScroll, scroll.x(), 1);
2603 int vScroll = editBoxWithText.y - (viewportHeight / scale - editBoxWithText.height) / 2;
2604 EXPECT_NEAR(vScroll, scroll.y(), 1);
2605 EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1);
2607 // The edit box is wider than the viewport when legible.
2608 viewportWidth = 200;
2609 viewportHeight = 150;
2610 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2611 setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), 1);
2612 webViewHelper.webViewImpl()->selectionBounds(caret, rect);
2613 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2614 EXPECT_TRUE(needAnimation);
2615 // The caret should be right aligned since the caret would be offscreen when the edit box is left aligned.
2616 hScroll = caret.x + caret.width + caretPadding - viewportWidth / scale;
2617 EXPECT_NEAR(hScroll, scroll.x(), 1);
2618 EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1);
2620 setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), 1);
2621 // Move focus to edit box with text.
2622 webViewHelper.webView()->advanceFocus(false);
2623 webViewHelper.webViewImpl()->selectionBounds(caret, rect);
2624 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2625 EXPECT_TRUE(needAnimation);
2626 // The edit box should be left aligned.
2627 hScroll = editBoxWithNoText.x;
2628 EXPECT_NEAR(hScroll, scroll.x(), 1);
2629 vScroll = editBoxWithNoText.y - (viewportHeight / scale - editBoxWithNoText.height) / 2;
2630 EXPECT_NEAR(vScroll, scroll.y(), 1);
2631 EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1);
2633 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), scroll, scale);
2635 // Move focus back to the first edit box.
2636 webViewHelper.webView()->advanceFocus(true);
2637 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2638 // The position should have stayed the same since this box was already on screen with the right scale.
2639 EXPECT_FALSE(needAnimation);
2642 class TestReloadDoesntRedirectWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
2644 virtual WebNavigationPolicy decidePolicyForNavigation(
2645 WebLocalFrame*, WebDataSource::ExtraData*, const WebURLRequest&, WebNavigationType,
2646 WebNavigationPolicy defaultPolicy, bool isRedirect) OVERRIDE
2648 EXPECT_FALSE(isRedirect);
2649 return WebNavigationPolicyCurrentTab;
2653 TEST_F(WebFrameTest, ReloadDoesntSetRedirect)
2655 // Test for case in http://crbug.com/73104. Reloading a frame very quickly
2656 // would sometimes call decidePolicyForNavigation with isRedirect=true
2657 registerMockedHttpURLLoad("form.html");
2659 TestReloadDoesntRedirectWebFrameClient webFrameClient;
2660 FrameTestHelpers::WebViewHelper webViewHelper;
2661 webViewHelper.initializeAndLoad(m_baseURL + "form.html", false, &webFrameClient);
2663 webViewHelper.webView()->mainFrame()->reload(true);
2664 // start another reload before request is delivered.
2665 FrameTestHelpers::reloadFrameIgnoringCache(webViewHelper.webView()->mainFrame());
2668 class ReloadWithOverrideURLTask : public WebThread::Task {
2670 ReloadWithOverrideURLTask(WebFrame* frame, const WebCore::KURL& url, bool ignoreCache)
2671 : m_frame(frame), m_url(url), m_ignoreCache(ignoreCache)
2675 virtual void run() OVERRIDE
2677 m_frame->reloadWithOverrideURL(m_url, m_ignoreCache);
2681 WebFrame* const m_frame;
2682 const WebCore::KURL m_url;
2683 const bool m_ignoreCache;
2686 TEST_F(WebFrameTest, ReloadWithOverrideURLPreservesState)
2688 const std::string firstURL = "find.html";
2689 const std::string secondURL = "form.html";
2690 const std::string thirdURL = "history.html";
2691 const float pageScaleFactor = 1.1684f;
2692 const int pageWidth = 640;
2693 const int pageHeight = 480;
2695 registerMockedHttpURLLoad(firstURL);
2696 registerMockedHttpURLLoad(secondURL);
2697 registerMockedHttpURLLoad(thirdURL);
2699 FrameTestHelpers::WebViewHelper webViewHelper;
2700 webViewHelper.initializeAndLoad(m_baseURL + firstURL, true);
2701 webViewHelper.webViewImpl()->resize(WebSize(pageWidth, pageHeight));
2702 webViewHelper.webViewImpl()->mainFrame()->setScrollOffset(WebSize(pageWidth / 4, pageHeight / 4));
2703 webViewHelper.webViewImpl()->setPageScaleFactor(pageScaleFactor);
2705 WebSize previousOffset = webViewHelper.webViewImpl()->mainFrame()->scrollOffset();
2706 float previousScale = webViewHelper.webViewImpl()->pageScaleFactor();
2708 // Reload the page using the cache.
2709 Platform::current()->currentThread()->postTask(
2710 new ReloadWithOverrideURLTask(webViewHelper.webViewImpl()->mainFrame(), toKURL(m_baseURL + secondURL), false));
2711 FrameTestHelpers::pumpPendingRequestsDoNotUse(webViewHelper.webViewImpl()->mainFrame());
2712 ASSERT_EQ(previousOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
2713 ASSERT_EQ(previousScale, webViewHelper.webViewImpl()->pageScaleFactor());
2715 // Reload the page while ignoring the cache.
2716 Platform::current()->currentThread()->postTask(
2717 new ReloadWithOverrideURLTask(webViewHelper.webViewImpl()->mainFrame(), toKURL(m_baseURL + thirdURL), true));
2718 FrameTestHelpers::pumpPendingRequestsDoNotUse(webViewHelper.webViewImpl()->mainFrame());
2719 ASSERT_EQ(previousOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
2720 ASSERT_EQ(previousScale, webViewHelper.webViewImpl()->pageScaleFactor());
2723 TEST_F(WebFrameTest, ReloadWhileProvisional)
2725 // Test that reloading while the previous load is still pending does not cause the initial
2726 // request to get lost.
2727 registerMockedHttpURLLoad("fixed_layout.html");
2729 FrameTestHelpers::WebViewHelper webViewHelper;
2730 webViewHelper.initialize();
2731 WebURLRequest request;
2732 request.initialize();
2733 request.setURL(toKURL(m_baseURL + "fixed_layout.html"));
2734 webViewHelper.webView()->mainFrame()->loadRequest(request);
2735 // start reload before first request is delivered.
2736 FrameTestHelpers::reloadFrameIgnoringCache(webViewHelper.webView()->mainFrame());
2738 WebDataSource* dataSource = webViewHelper.webView()->mainFrame()->dataSource();
2739 ASSERT_TRUE(dataSource);
2740 EXPECT_EQ(toKURL(m_baseURL + "fixed_layout.html"), toKURL(dataSource->request().url().spec()));
2743 TEST_F(WebFrameTest, AppendRedirects)
2745 const std::string firstURL = "about:blank";
2746 const std::string secondURL = "http://www.test.com";
2748 FrameTestHelpers::WebViewHelper webViewHelper;
2749 webViewHelper.initializeAndLoad(firstURL, true);
2751 WebDataSource* dataSource = webViewHelper.webView()->mainFrame()->dataSource();
2752 ASSERT_TRUE(dataSource);
2753 dataSource->appendRedirect(toKURL(secondURL));
2755 WebVector<WebURL> redirects;
2756 dataSource->redirectChain(redirects);
2757 ASSERT_EQ(2U, redirects.size());
2758 EXPECT_EQ(toKURL(firstURL), toKURL(redirects[0].spec().data()));
2759 EXPECT_EQ(toKURL(secondURL), toKURL(redirects[1].spec().data()));
2762 TEST_F(WebFrameTest, IframeRedirect)
2764 registerMockedHttpURLLoad("iframe_redirect.html");
2765 registerMockedHttpURLLoad("visible_iframe.html");
2767 FrameTestHelpers::WebViewHelper webViewHelper;
2768 webViewHelper.initializeAndLoad(m_baseURL + "iframe_redirect.html", true);
2769 // Pump pending requests one more time. The test page loads script that navigates.
2770 FrameTestHelpers::pumpPendingRequestsDoNotUse(webViewHelper.webView()->mainFrame());
2772 WebFrame* iframe = webViewHelper.webView()->findFrameByName(WebString::fromUTF8("ifr"));
2773 ASSERT_TRUE(iframe);
2774 WebDataSource* iframeDataSource = iframe->dataSource();
2775 ASSERT_TRUE(iframeDataSource);
2776 WebVector<WebURL> redirects;
2777 iframeDataSource->redirectChain(redirects);
2778 ASSERT_EQ(2U, redirects.size());
2779 EXPECT_EQ(toKURL("about:blank"), toKURL(redirects[0].spec().data()));
2780 EXPECT_EQ(toKURL("http://www.test.com/visible_iframe.html"), toKURL(redirects[1].spec().data()));
2783 TEST_F(WebFrameTest, ClearFocusedNodeTest)
2785 registerMockedHttpURLLoad("iframe_clear_focused_node_test.html");
2786 registerMockedHttpURLLoad("autofocus_input_field_iframe.html");
2788 FrameTestHelpers::WebViewHelper webViewHelper;
2789 webViewHelper.initializeAndLoad(m_baseURL + "iframe_clear_focused_node_test.html", true);
2791 // Clear the focused node.
2792 webViewHelper.webView()->clearFocusedElement();
2794 // Now retrieve the FocusedNode and test it should be null.
2795 EXPECT_EQ(0, webViewHelper.webViewImpl()->focusedElement());
2798 // Implementation of WebFrameClient that tracks the v8 contexts that are created
2799 // and destroyed for verification.
2800 class ContextLifetimeTestWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
2802 struct Notification {
2804 Notification(WebLocalFrame* frame, v8::Handle<v8::Context> context, int worldId)
2806 , context(context->GetIsolate(), context)
2816 bool Equals(Notification* other)
2818 return other && frame == other->frame && context == other->context && worldId == other->worldId;
2821 WebLocalFrame* frame;
2822 v8::Persistent<v8::Context> context;
2826 virtual ~ContextLifetimeTestWebFrameClient()
2833 for (size_t i = 0; i < createNotifications.size(); ++i)
2834 delete createNotifications[i];
2836 for (size_t i = 0; i < releaseNotifications.size(); ++i)
2837 delete releaseNotifications[i];
2839 createNotifications.clear();
2840 releaseNotifications.clear();
2843 std::vector<Notification*> createNotifications;
2844 std::vector<Notification*> releaseNotifications;
2847 virtual void didCreateScriptContext(WebLocalFrame* frame, v8::Handle<v8::Context> context, int extensionGroup, int worldId) OVERRIDE
2849 createNotifications.push_back(new Notification(frame, context, worldId));
2852 virtual void willReleaseScriptContext(WebLocalFrame* frame, v8::Handle<v8::Context> context, int worldId) OVERRIDE
2854 releaseNotifications.push_back(new Notification(frame, context, worldId));
2858 // TODO(aa): Deflake this test.
2859 TEST_F(WebFrameTest, FLAKY_ContextNotificationsLoadUnload)
2861 v8::HandleScope handleScope(v8::Isolate::GetCurrent());
2863 registerMockedHttpURLLoad("context_notifications_test.html");
2864 registerMockedHttpURLLoad("context_notifications_test_frame.html");
2866 // Load a frame with an iframe, make sure we get the right create notifications.
2867 ContextLifetimeTestWebFrameClient webFrameClient;
2868 FrameTestHelpers::WebViewHelper webViewHelper;
2869 webViewHelper.initializeAndLoad(m_baseURL + "context_notifications_test.html", true, &webFrameClient);
2871 WebFrame* mainFrame = webViewHelper.webView()->mainFrame();
2872 WebFrame* childFrame = mainFrame->firstChild();
2874 ASSERT_EQ(2u, webFrameClient.createNotifications.size());
2875 EXPECT_EQ(0u, webFrameClient.releaseNotifications.size());
2877 ContextLifetimeTestWebFrameClient::Notification* firstCreateNotification = webFrameClient.createNotifications[0];
2878 ContextLifetimeTestWebFrameClient::Notification* secondCreateNotification = webFrameClient.createNotifications[1];
2880 EXPECT_EQ(mainFrame, firstCreateNotification->frame);
2881 EXPECT_EQ(mainFrame->mainWorldScriptContext(), firstCreateNotification->context);
2882 EXPECT_EQ(0, firstCreateNotification->worldId);
2884 EXPECT_EQ(childFrame, secondCreateNotification->frame);
2885 EXPECT_EQ(childFrame->mainWorldScriptContext(), secondCreateNotification->context);
2886 EXPECT_EQ(0, secondCreateNotification->worldId);
2888 // Close the view. We should get two release notifications that are exactly the same as the create ones, in reverse order.
2889 webViewHelper.reset();
2891 ASSERT_EQ(2u, webFrameClient.releaseNotifications.size());
2892 ContextLifetimeTestWebFrameClient::Notification* firstReleaseNotification = webFrameClient.releaseNotifications[0];
2893 ContextLifetimeTestWebFrameClient::Notification* secondReleaseNotification = webFrameClient.releaseNotifications[1];
2895 ASSERT_TRUE(firstCreateNotification->Equals(secondReleaseNotification));
2896 ASSERT_TRUE(secondCreateNotification->Equals(firstReleaseNotification));
2899 TEST_F(WebFrameTest, ContextNotificationsReload)
2901 v8::HandleScope handleScope(v8::Isolate::GetCurrent());
2903 registerMockedHttpURLLoad("context_notifications_test.html");
2904 registerMockedHttpURLLoad("context_notifications_test_frame.html");
2906 ContextLifetimeTestWebFrameClient webFrameClient;
2907 FrameTestHelpers::WebViewHelper webViewHelper;
2908 webViewHelper.initializeAndLoad(m_baseURL + "context_notifications_test.html", true, &webFrameClient);
2910 // Refresh, we should get two release notifications and two more create notifications.
2911 FrameTestHelpers::reloadFrame(webViewHelper.webView()->mainFrame());
2912 ASSERT_EQ(4u, webFrameClient.createNotifications.size());
2913 ASSERT_EQ(2u, webFrameClient.releaseNotifications.size());
2915 // The two release notifications we got should be exactly the same as the first two create notifications.
2916 for (size_t i = 0; i < webFrameClient.releaseNotifications.size(); ++i) {
2917 EXPECT_TRUE(webFrameClient.releaseNotifications[i]->Equals(
2918 webFrameClient.createNotifications[webFrameClient.createNotifications.size() - 3 - i]));
2921 // The last two create notifications should be for the current frames and context.
2922 WebFrame* mainFrame = webViewHelper.webView()->mainFrame();
2923 WebFrame* childFrame = mainFrame->firstChild();
2924 ContextLifetimeTestWebFrameClient::Notification* firstRefreshNotification = webFrameClient.createNotifications[2];
2925 ContextLifetimeTestWebFrameClient::Notification* secondRefreshNotification = webFrameClient.createNotifications[3];
2927 EXPECT_EQ(mainFrame, firstRefreshNotification->frame);
2928 EXPECT_EQ(mainFrame->mainWorldScriptContext(), firstRefreshNotification->context);
2929 EXPECT_EQ(0, firstRefreshNotification->worldId);
2931 EXPECT_EQ(childFrame, secondRefreshNotification->frame);
2932 EXPECT_EQ(childFrame->mainWorldScriptContext(), secondRefreshNotification->context);
2933 EXPECT_EQ(0, secondRefreshNotification->worldId);
2936 TEST_F(WebFrameTest, ContextNotificationsIsolatedWorlds)
2938 v8::Isolate* isolate = v8::Isolate::GetCurrent();
2939 v8::HandleScope handleScope(isolate);
2941 registerMockedHttpURLLoad("context_notifications_test.html");
2942 registerMockedHttpURLLoad("context_notifications_test_frame.html");
2944 ContextLifetimeTestWebFrameClient webFrameClient;
2945 FrameTestHelpers::WebViewHelper webViewHelper;
2946 webViewHelper.initializeAndLoad(m_baseURL + "context_notifications_test.html", true, &webFrameClient);
2948 // Add an isolated world.
2949 webFrameClient.reset();
2951 int isolatedWorldId = 42;
2952 WebScriptSource scriptSource("hi!");
2954 int extensionGroup = 0;
2955 webViewHelper.webView()->mainFrame()->executeScriptInIsolatedWorld(isolatedWorldId, &scriptSource, numSources, extensionGroup);
2957 // We should now have a new create notification.
2958 ASSERT_EQ(1u, webFrameClient.createNotifications.size());
2959 ContextLifetimeTestWebFrameClient::Notification* notification = webFrameClient.createNotifications[0];
2960 ASSERT_EQ(isolatedWorldId, notification->worldId);
2961 ASSERT_EQ(webViewHelper.webView()->mainFrame(), notification->frame);
2963 // 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.
2964 ASSERT_NE(webViewHelper.webView()->mainFrame()->mainWorldScriptContext(), v8::Local<v8::Context>::New(isolate, notification->context));
2966 webViewHelper.reset();
2968 // We should have gotten three release notifications (one for each of the frames, plus one for the isolated context).
2969 ASSERT_EQ(3u, webFrameClient.releaseNotifications.size());
2971 // And one of them should be exactly the same as the create notification for the isolated context.
2973 for (size_t i = 0; i < webFrameClient.releaseNotifications.size(); ++i) {
2974 if (webFrameClient.releaseNotifications[i]->Equals(webFrameClient.createNotifications[0]))
2977 EXPECT_EQ(1, matchCount);
2980 TEST_F(WebFrameTest, FindInPage)
2982 registerMockedHttpURLLoad("find.html");
2983 FrameTestHelpers::WebViewHelper webViewHelper;
2984 webViewHelper.initializeAndLoad(m_baseURL + "find.html");
2985 WebFrame* frame = webViewHelper.webView()->mainFrame();
2986 const int findIdentifier = 12345;
2987 WebFindOptions options;
2989 // Find in a <div> element.
2990 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar1"), options, false, 0));
2991 frame->stopFinding(false);
2992 WebRange range = frame->selectionRange();
2993 EXPECT_EQ(5, range.startOffset());
2994 EXPECT_EQ(9, range.endOffset());
2995 EXPECT_TRUE(frame->document().focusedElement().isNull());
2997 // Find in an <input> value.
2998 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar2"), options, false, 0));
2999 // Confirm stopFinding(false) sets the selection on the found text.
3000 frame->stopFinding(false);
3001 range = frame->selectionRange();
3002 ASSERT_FALSE(range.isNull());
3003 EXPECT_EQ(5, range.startOffset());
3004 EXPECT_EQ(9, range.endOffset());
3005 EXPECT_EQ(WebString::fromUTF8("INPUT"), frame->document().focusedElement().tagName());
3007 // Find in a <textarea> content.
3008 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar3"), options, false, 0));
3009 // Confirm stopFinding(false) sets the selection on the found text.
3010 frame->stopFinding(false);
3011 range = frame->selectionRange();
3012 ASSERT_FALSE(range.isNull());
3013 EXPECT_EQ(5, range.startOffset());
3014 EXPECT_EQ(9, range.endOffset());
3015 EXPECT_EQ(WebString::fromUTF8("TEXTAREA"), frame->document().focusedElement().tagName());
3017 // Find in a contentEditable element.
3018 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar4"), options, false, 0));
3019 // Confirm stopFinding(false) sets the selection on the found text.
3020 frame->stopFinding(false);
3021 range = frame->selectionRange();
3022 ASSERT_FALSE(range.isNull());
3023 EXPECT_EQ(0, range.startOffset());
3024 EXPECT_EQ(4, range.endOffset());
3025 // "bar4" is surrounded by <span>, but the focusable node should be the parent <div>.
3026 EXPECT_EQ(WebString::fromUTF8("DIV"), frame->document().focusedElement().tagName());
3028 // Find in <select> content.
3029 EXPECT_FALSE(frame->find(findIdentifier, WebString::fromUTF8("bar5"), options, false, 0));
3030 // If there are any matches, stopFinding will set the selection on the found text.
3031 // However, we do not expect any matches, so check that the selection is null.
3032 frame->stopFinding(false);
3033 range = frame->selectionRange();
3034 ASSERT_TRUE(range.isNull());
3037 TEST_F(WebFrameTest, GetContentAsPlainText)
3039 FrameTestHelpers::WebViewHelper webViewHelper;
3040 webViewHelper.initializeAndLoad("about:blank", true);
3041 // We set the size because it impacts line wrapping, which changes the
3042 // resulting text value.
3043 webViewHelper.webView()->resize(WebSize(640, 480));
3044 WebFrame* frame = webViewHelper.webView()->mainFrame();
3046 // Generate a simple test case.
3047 const char simpleSource[] = "<div>Foo bar</div><div></div>baz";
3048 WebCore::KURL testURL = toKURL("about:blank");
3049 FrameTestHelpers::loadHTMLString(frame, simpleSource, testURL);
3051 // Make sure it comes out OK.
3052 const std::string expected("Foo bar\nbaz");
3053 WebString text = frame->contentAsText(std::numeric_limits<size_t>::max());
3054 EXPECT_EQ(expected, text.utf8());
3056 // Try reading the same one with clipping of the text.
3057 const int length = 5;
3058 text = frame->contentAsText(length);
3059 EXPECT_EQ(expected.substr(0, length), text.utf8());
3061 // Now do a new test with a subframe.
3062 const char outerFrameSource[] = "Hello<iframe></iframe> world";
3063 FrameTestHelpers::loadHTMLString(frame, outerFrameSource, testURL);
3065 // Load something into the subframe.
3066 WebFrame* subframe = frame->firstChild();
3067 ASSERT_TRUE(subframe);
3068 FrameTestHelpers::loadHTMLString(subframe, "sub<p>text", testURL);
3070 text = frame->contentAsText(std::numeric_limits<size_t>::max());
3071 EXPECT_EQ("Hello world\n\nsub\ntext", text.utf8());
3073 // Get the frame text where the subframe separator falls on the boundary of
3074 // what we'll take. There used to be a crash in this case.
3075 text = frame->contentAsText(12);
3076 EXPECT_EQ("Hello world", text.utf8());
3079 TEST_F(WebFrameTest, GetFullHtmlOfPage)
3081 FrameTestHelpers::WebViewHelper webViewHelper;
3082 webViewHelper.initializeAndLoad("about:blank", true);
3083 WebFrame* frame = webViewHelper.webView()->mainFrame();
3085 // Generate a simple test case.
3086 const char simpleSource[] = "<p>Hello</p><p>World</p>";
3087 WebCore::KURL testURL = toKURL("about:blank");
3088 FrameTestHelpers::loadHTMLString(frame, simpleSource, testURL);
3090 WebString text = frame->contentAsText(std::numeric_limits<size_t>::max());
3091 EXPECT_EQ("Hello\n\nWorld", text.utf8());
3093 const std::string html = frame->contentAsMarkup().utf8();
3095 // Load again with the output html.
3096 FrameTestHelpers::loadHTMLString(frame, html, testURL);
3098 EXPECT_EQ(html, frame->contentAsMarkup().utf8());
3100 text = frame->contentAsText(std::numeric_limits<size_t>::max());
3101 EXPECT_EQ("Hello\n\nWorld", text.utf8());
3103 // Test selection check
3104 EXPECT_FALSE(frame->hasSelection());
3105 frame->executeCommand(WebString::fromUTF8("SelectAll"));
3106 EXPECT_TRUE(frame->hasSelection());
3107 frame->executeCommand(WebString::fromUTF8("Unselect"));
3108 EXPECT_FALSE(frame->hasSelection());
3109 WebString selectionHtml = frame->selectionAsMarkup();
3110 EXPECT_TRUE(selectionHtml.isEmpty());
3113 class TestExecuteScriptDuringDidCreateScriptContext : public FrameTestHelpers::TestWebFrameClient {
3115 virtual void didCreateScriptContext(WebLocalFrame* frame, v8::Handle<v8::Context> context, int extensionGroup, int worldId) OVERRIDE
3117 frame->executeScript(WebScriptSource("window.history = 'replaced';"));
3121 TEST_F(WebFrameTest, ExecuteScriptDuringDidCreateScriptContext)
3123 registerMockedHttpURLLoad("hello_world.html");
3125 TestExecuteScriptDuringDidCreateScriptContext webFrameClient;
3126 FrameTestHelpers::WebViewHelper webViewHelper;
3127 webViewHelper.initializeAndLoad(m_baseURL + "hello_world.html", true, &webFrameClient);
3129 FrameTestHelpers::reloadFrame(webViewHelper.webView()->mainFrame());
3132 class FindUpdateWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
3134 FindUpdateWebFrameClient()
3135 : m_findResultsAreReady(false)
3140 virtual void reportFindInPageMatchCount(int, int count, bool finalUpdate) OVERRIDE
3144 m_findResultsAreReady = true;
3147 bool findResultsAreReady() const { return m_findResultsAreReady; }
3148 int count() const { return m_count; }
3151 bool m_findResultsAreReady;
3155 // This fails on Mac https://bugs.webkit.org/show_bug.cgi?id=108574
3156 // Also failing on Android: http://crbug.com/341314
3157 #if OS(MACOSX) || OS(ANDROID)
3158 TEST_F(WebFrameTest, DISABLED_FindInPageMatchRects)
3160 TEST_F(WebFrameTest, FindInPageMatchRects)
3163 registerMockedHttpURLLoad("find_in_page.html");
3164 registerMockedHttpURLLoad("find_in_page_frame.html");
3166 FindUpdateWebFrameClient client;
3167 FrameTestHelpers::WebViewHelper webViewHelper;
3168 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3169 webViewHelper.webView()->resize(WebSize(640, 480));
3170 webViewHelper.webView()->layout();
3173 // Note that the 'result 19' in the <select> element is not expected to produce a match.
3174 static const char* kFindString = "result";
3175 static const int kFindIdentifier = 12345;
3176 static const int kNumResults = 19;
3178 WebFindOptions options;
3179 WebString searchText = WebString::fromUTF8(kFindString);
3180 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3181 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
3183 mainFrame->resetMatchCount();
3185 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3186 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3189 EXPECT_TRUE(client.findResultsAreReady());
3191 WebVector<WebFloatRect> webMatchRects;
3192 mainFrame->findMatchRects(webMatchRects);
3193 ASSERT_EQ(webMatchRects.size(), static_cast<size_t>(kNumResults));
3194 int rectsVersion = mainFrame->findMatchMarkersVersion();
3196 for (int resultIndex = 0; resultIndex < kNumResults; ++resultIndex) {
3197 FloatRect resultRect = static_cast<FloatRect>(webMatchRects[resultIndex]);
3199 // Select the match by the center of its rect.
3200 EXPECT_EQ(mainFrame->selectNearestFindMatch(resultRect.center(), 0), resultIndex + 1);
3202 // Check that the find result ordering matches with our expectations.
3203 Range* result = mainFrame->activeMatchFrame()->activeMatch();
3204 ASSERT_TRUE(result);
3205 result->setEnd(result->endContainer(), result->endOffset() + 3);
3206 EXPECT_EQ(result->text(), String::format("%s %02d", kFindString, resultIndex));
3208 // Verify that the expected match rect also matches the currently active match.
3209 // Compare the enclosing rects to prevent precision issues caused by CSS transforms.
3210 FloatRect activeMatch = mainFrame->activeFindMatchRect();
3211 EXPECT_EQ(enclosingIntRect(activeMatch), enclosingIntRect(resultRect));
3213 // The rects version should not have changed.
3214 EXPECT_EQ(mainFrame->findMatchMarkersVersion(), rectsVersion);
3217 // All results after the first two ones should be below between them in find-in-page coordinates.
3218 // This is because results 2 to 9 are inside an iframe located between results 0 and 1. This applies to the fixed div too.
3219 EXPECT_TRUE(webMatchRects[0].y < webMatchRects[1].y);
3220 for (int resultIndex = 2; resultIndex < kNumResults; ++resultIndex) {
3221 EXPECT_TRUE(webMatchRects[0].y < webMatchRects[resultIndex].y);
3222 EXPECT_TRUE(webMatchRects[1].y > webMatchRects[resultIndex].y);
3225 // Result 3 should be below both 2 and 4. This is caused by the CSS transform in the containing div.
3226 // If the transform doesn't work then 3 will be between 2 and 4.
3227 EXPECT_TRUE(webMatchRects[3].y > webMatchRects[2].y);
3228 EXPECT_TRUE(webMatchRects[3].y > webMatchRects[4].y);
3230 // Results 6, 7, 8 and 9 should be one below the other in that same order.
3231 // If overflow:scroll is not properly handled then result 8 would be below result 9 or
3232 // result 7 above result 6 depending on the scroll.
3233 EXPECT_TRUE(webMatchRects[6].y < webMatchRects[7].y);
3234 EXPECT_TRUE(webMatchRects[7].y < webMatchRects[8].y);
3235 EXPECT_TRUE(webMatchRects[8].y < webMatchRects[9].y);
3237 // Results 11, 12, 13 and 14 should be between results 10 and 15, as they are inside the table.
3238 EXPECT_TRUE(webMatchRects[11].y > webMatchRects[10].y);
3239 EXPECT_TRUE(webMatchRects[12].y > webMatchRects[10].y);
3240 EXPECT_TRUE(webMatchRects[13].y > webMatchRects[10].y);
3241 EXPECT_TRUE(webMatchRects[14].y > webMatchRects[10].y);
3242 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[15].y);
3243 EXPECT_TRUE(webMatchRects[12].y < webMatchRects[15].y);
3244 EXPECT_TRUE(webMatchRects[13].y < webMatchRects[15].y);
3245 EXPECT_TRUE(webMatchRects[14].y < webMatchRects[15].y);
3247 // Result 11 should be above 12, 13 and 14 as it's in the table header.
3248 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[12].y);
3249 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[13].y);
3250 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[14].y);
3252 // Result 11 should also be right to 12, 13 and 14 because of the colspan.
3253 EXPECT_TRUE(webMatchRects[11].x > webMatchRects[12].x);
3254 EXPECT_TRUE(webMatchRects[11].x > webMatchRects[13].x);
3255 EXPECT_TRUE(webMatchRects[11].x > webMatchRects[14].x);
3257 // Result 12 should be left to results 11, 13 and 14 in the table layout.
3258 EXPECT_TRUE(webMatchRects[12].x < webMatchRects[11].x);
3259 EXPECT_TRUE(webMatchRects[12].x < webMatchRects[13].x);
3260 EXPECT_TRUE(webMatchRects[12].x < webMatchRects[14].x);
3262 // Results 13, 12 and 14 should be one above the other in that order because of the rowspan
3263 // and vertical-align: middle by default.
3264 EXPECT_TRUE(webMatchRects[13].y < webMatchRects[12].y);
3265 EXPECT_TRUE(webMatchRects[12].y < webMatchRects[14].y);
3267 // Result 16 should be below result 15.
3268 EXPECT_TRUE(webMatchRects[15].y > webMatchRects[14].y);
3270 // Result 18 should be normalized with respect to the position:relative div, and not it's
3271 // immediate containing div. Consequently, result 18 should be above result 17.
3272 EXPECT_TRUE(webMatchRects[17].y > webMatchRects[18].y);
3274 // Resizing should update the rects version.
3275 webViewHelper.webView()->resize(WebSize(800, 600));
3277 EXPECT_TRUE(mainFrame->findMatchMarkersVersion() != rectsVersion);
3280 TEST_F(WebFrameTest, FindInPageSkipsHiddenFrames)
3282 registerMockedHttpURLLoad("find_in_hidden_frame.html");
3284 FindUpdateWebFrameClient client;
3285 FrameTestHelpers::WebViewHelper webViewHelper;
3286 webViewHelper.initializeAndLoad(m_baseURL + "find_in_hidden_frame.html", true, &client);
3287 webViewHelper.webView()->resize(WebSize(640, 480));
3288 webViewHelper.webView()->layout();
3291 static const char* kFindString = "hello";
3292 static const int kFindIdentifier = 12345;
3293 static const int kNumResults = 1;
3295 WebFindOptions options;
3296 WebString searchText = WebString::fromUTF8(kFindString);
3297 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3298 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
3300 mainFrame->resetMatchCount();
3302 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3303 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3306 EXPECT_TRUE(client.findResultsAreReady());
3307 EXPECT_EQ(kNumResults, client.count());
3310 TEST_F(WebFrameTest, FindOnDetachedFrame)
3312 registerMockedHttpURLLoad("find_in_page.html");
3313 registerMockedHttpURLLoad("find_in_page_frame.html");
3315 FindUpdateWebFrameClient client;
3316 FrameTestHelpers::WebViewHelper webViewHelper;
3317 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3318 webViewHelper.webView()->resize(WebSize(640, 480));
3319 webViewHelper.webView()->layout();
3322 static const char* kFindString = "result";
3323 static const int kFindIdentifier = 12345;
3325 WebFindOptions options;
3326 WebString searchText = WebString::fromUTF8(kFindString);
3327 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3328 RefPtr<WebLocalFrameImpl> secondFrame = toWebLocalFrameImpl(mainFrame->traverseNext(false));
3329 RefPtr<WebCore::LocalFrame> holdSecondFrame = secondFrame->frame();
3331 // Detach the frame before finding.
3332 EXPECT_TRUE(mainFrame->document().getElementById("frame").remove());
3334 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
3335 EXPECT_FALSE(secondFrame->find(kFindIdentifier, searchText, options, false, 0));
3338 EXPECT_FALSE(client.findResultsAreReady());
3340 mainFrame->resetMatchCount();
3342 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3343 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3346 EXPECT_TRUE(client.findResultsAreReady());
3348 holdSecondFrame.release();
3351 TEST_F(WebFrameTest, FindDetachFrameBeforeScopeStrings)
3353 registerMockedHttpURLLoad("find_in_page.html");
3354 registerMockedHttpURLLoad("find_in_page_frame.html");
3356 FindUpdateWebFrameClient client;
3357 FrameTestHelpers::WebViewHelper webViewHelper;
3358 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3359 webViewHelper.webView()->resize(WebSize(640, 480));
3360 webViewHelper.webView()->layout();
3363 static const char* kFindString = "result";
3364 static const int kFindIdentifier = 12345;
3366 WebFindOptions options;
3367 WebString searchText = WebString::fromUTF8(kFindString);
3368 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3369 WebLocalFrameImpl* secondFrame = toWebLocalFrameImpl(mainFrame->traverseNext(false));
3370 RefPtr<WebCore::LocalFrame> holdSecondFrame = secondFrame->frame();
3372 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3373 EXPECT_TRUE(frame->find(kFindIdentifier, searchText, options, false, 0));
3376 EXPECT_FALSE(client.findResultsAreReady());
3378 // Detach the frame between finding and scoping.
3379 EXPECT_TRUE(mainFrame->document().getElementById("frame").remove());
3381 mainFrame->resetMatchCount();
3383 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3384 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3387 EXPECT_TRUE(client.findResultsAreReady());
3389 holdSecondFrame.release();
3392 TEST_F(WebFrameTest, FindDetachFrameWhileScopingStrings)
3394 registerMockedHttpURLLoad("find_in_page.html");
3395 registerMockedHttpURLLoad("find_in_page_frame.html");
3397 FindUpdateWebFrameClient client;
3398 FrameTestHelpers::WebViewHelper webViewHelper;
3399 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3400 webViewHelper.webView()->resize(WebSize(640, 480));
3401 webViewHelper.webView()->layout();
3404 static const char* kFindString = "result";
3405 static const int kFindIdentifier = 12345;
3407 WebFindOptions options;
3408 WebString searchText = WebString::fromUTF8(kFindString);
3409 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3410 WebLocalFrameImpl* secondFrame = toWebLocalFrameImpl(mainFrame->traverseNext(false));
3411 RefPtr<WebCore::LocalFrame> holdSecondFrame = secondFrame->frame();
3413 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3414 EXPECT_TRUE(frame->find(kFindIdentifier, searchText, options, false, 0));
3417 EXPECT_FALSE(client.findResultsAreReady());
3419 mainFrame->resetMatchCount();
3421 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3422 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3424 // The first scopeStringMatches will have reset the state. Detach before it actually scopes.
3425 EXPECT_TRUE(mainFrame->document().getElementById("frame").remove());
3428 EXPECT_TRUE(client.findResultsAreReady());
3430 holdSecondFrame.release();
3433 TEST_F(WebFrameTest, ResetMatchCount)
3435 registerMockedHttpURLLoad("find_in_generated_frame.html");
3437 FindUpdateWebFrameClient client;
3438 FrameTestHelpers::WebViewHelper webViewHelper;
3439 webViewHelper.initializeAndLoad(m_baseURL + "find_in_generated_frame.html", true, &client);
3440 webViewHelper.webView()->resize(WebSize(640, 480));
3441 webViewHelper.webView()->layout();
3444 static const char* kFindString = "result";
3445 static const int kFindIdentifier = 12345;
3447 WebFindOptions options;
3448 WebString searchText = WebString::fromUTF8(kFindString);
3449 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3451 // Check that child frame exists.
3452 EXPECT_TRUE(!!mainFrame->traverseNext(false));
3454 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false)) {
3455 EXPECT_FALSE(frame->find(kFindIdentifier, searchText, options, false, 0));
3459 EXPECT_FALSE(client.findResultsAreReady());
3461 mainFrame->resetMatchCount();
3464 TEST_F(WebFrameTest, SetTickmarks)
3466 registerMockedHttpURLLoad("find.html");
3468 FindUpdateWebFrameClient client;
3469 FrameTestHelpers::WebViewHelper webViewHelper;
3470 webViewHelper.initializeAndLoad(m_baseURL + "find.html", true, &client);
3471 webViewHelper.webView()->resize(WebSize(640, 480));
3472 webViewHelper.webView()->layout();
3475 static const char* kFindString = "foo";
3476 static const int kFindIdentifier = 12345;
3478 WebFindOptions options;
3479 WebString searchText = WebString::fromUTF8(kFindString);
3480 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3481 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
3483 mainFrame->resetMatchCount();
3484 mainFrame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3487 EXPECT_TRUE(client.findResultsAreReady());
3489 // Get the tickmarks for the original find request.
3490 WebCore::FrameView* frameView = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
3491 RefPtr<WebCore::Scrollbar> scrollbar = frameView->createScrollbar(WebCore::HorizontalScrollbar);
3492 Vector<WebCore::IntRect> originalTickmarks;
3493 scrollbar->getTickmarks(originalTickmarks);
3494 EXPECT_EQ(4u, originalTickmarks.size());
3496 // Override the tickmarks.
3497 Vector<WebCore::IntRect> overridingTickmarksExpected;
3498 overridingTickmarksExpected.append(WebCore::IntRect(0, 0, 100, 100));
3499 overridingTickmarksExpected.append(WebCore::IntRect(0, 20, 100, 100));
3500 overridingTickmarksExpected.append(WebCore::IntRect(0, 30, 100, 100));
3501 mainFrame->setTickmarks(overridingTickmarksExpected);
3503 // Check the tickmarks are overriden correctly.
3504 Vector<WebCore::IntRect> overridingTickmarksActual;
3505 scrollbar->getTickmarks(overridingTickmarksActual);
3506 EXPECT_EQ(overridingTickmarksExpected, overridingTickmarksActual);
3508 // Reset the tickmark behavior.
3509 Vector<WebCore::IntRect> resetTickmarks;
3510 mainFrame->setTickmarks(resetTickmarks);
3512 // Check that the original tickmarks are returned
3513 Vector<WebCore::IntRect> originalTickmarksAfterReset;
3514 scrollbar->getTickmarks(originalTickmarksAfterReset);
3515 EXPECT_EQ(originalTickmarks, originalTickmarksAfterReset);
3518 static WebPoint topLeft(const WebRect& rect)
3520 return WebPoint(rect.x, rect.y);
3523 static WebPoint bottomRightMinusOne(const WebRect& rect)
3525 // FIXME: If we don't subtract 1 from the x- and y-coordinates of the
3526 // selection bounds, selectRange() will select the *next* element. That's
3527 // strictly correct, as hit-testing checks the pixel to the lower-right of
3528 // the input coordinate, but it's a wart on the API.
3529 return WebPoint(rect.x + rect.width - 1, rect.y + rect.height - 1);
3532 static WebRect elementBounds(WebFrame* frame, const WebString& id)
3534 return frame->document().getElementById(id).boundsInViewportSpace();
3537 static std::string selectionAsString(WebFrame* frame)
3539 return frame->selectionAsText().utf8();
3542 TEST_F(WebFrameTest, SelectRange)
3545 WebRect startWebRect;
3548 registerMockedHttpURLLoad("select_range_basic.html");
3549 registerMockedHttpURLLoad("select_range_scroll.html");
3551 FrameTestHelpers::WebViewHelper webViewHelper;
3552 initializeTextSelectionWebView(m_baseURL + "select_range_basic.html", &webViewHelper);
3553 frame = webViewHelper.webView()->mainFrame();
3554 EXPECT_EQ("Some test text for testing.", selectionAsString(frame));
3555 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3556 frame->executeCommand(WebString::fromUTF8("Unselect"));
3557 EXPECT_EQ("", selectionAsString(frame));
3558 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3559 EXPECT_EQ("Some test text for testing.", selectionAsString(frame));
3561 initializeTextSelectionWebView(m_baseURL + "select_range_scroll.html", &webViewHelper);
3562 frame = webViewHelper.webView()->mainFrame();
3563 EXPECT_EQ("Some offscreen test text for testing.", selectionAsString(frame));
3564 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3565 frame->executeCommand(WebString::fromUTF8("Unselect"));
3566 EXPECT_EQ("", selectionAsString(frame));
3567 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3568 EXPECT_EQ("Some offscreen test text for testing.", selectionAsString(frame));
3571 TEST_F(WebFrameTest, SelectRangeInIframe)
3574 WebRect startWebRect;
3577 registerMockedHttpURLLoad("select_range_iframe.html");
3578 registerMockedHttpURLLoad("select_range_basic.html");
3580 FrameTestHelpers::WebViewHelper webViewHelper;
3581 initializeTextSelectionWebView(m_baseURL + "select_range_iframe.html", &webViewHelper);
3582 frame = webViewHelper.webView()->mainFrame();
3583 WebFrame* subframe = frame->firstChild();
3584 EXPECT_EQ("Some test text for testing.", selectionAsString(subframe));
3585 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3586 subframe->executeCommand(WebString::fromUTF8("Unselect"));
3587 EXPECT_EQ("", selectionAsString(subframe));
3588 subframe->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3589 EXPECT_EQ("Some test text for testing.", selectionAsString(subframe));
3592 TEST_F(WebFrameTest, SelectRangeDivContentEditable)
3595 WebRect startWebRect;
3598 registerMockedHttpURLLoad("select_range_div_editable.html");
3600 // Select the middle of an editable element, then try to extend the selection to the top of the document.
3601 // The selection range should be clipped to the bounds of the editable element.
3602 FrameTestHelpers::WebViewHelper webViewHelper;
3603 initializeTextSelectionWebView(m_baseURL + "select_range_div_editable.html", &webViewHelper);
3604 frame = webViewHelper.webView()->mainFrame();
3605 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3606 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3608 frame->selectRange(bottomRightMinusOne(endWebRect), WebPoint(0, 0));
3609 EXPECT_EQ("16-char header. This text is initially selected.", selectionAsString(frame));
3611 // As above, but extending the selection to the bottom of the document.
3612 initializeTextSelectionWebView(m_baseURL + "select_range_div_editable.html", &webViewHelper);
3613 frame = webViewHelper.webView()->mainFrame();
3615 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3616 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3617 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3618 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3620 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3621 frame->selectRange(topLeft(startWebRect), WebPoint(640, 480));
3622 EXPECT_EQ("This text is initially selected. 16-char footer.", selectionAsString(frame));
3625 // positionForPoint returns the wrong values for contenteditable spans. See
3626 // http://crbug.com/238334.
3627 TEST_F(WebFrameTest, DISABLED_SelectRangeSpanContentEditable)
3630 WebRect startWebRect;
3633 registerMockedHttpURLLoad("select_range_span_editable.html");
3635 // Select the middle of an editable element, then try to extend the selection to the top of the document.
3636 // The selection range should be clipped to the bounds of the editable element.
3637 FrameTestHelpers::WebViewHelper webViewHelper;
3638 initializeTextSelectionWebView(m_baseURL + "select_range_span_editable.html", &webViewHelper);
3639 frame = webViewHelper.webView()->mainFrame();
3640 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3641 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3643 frame->selectRange(bottomRightMinusOne(endWebRect), WebPoint(0, 0));
3644 EXPECT_EQ("16-char header. This text is initially selected.", selectionAsString(frame));
3646 // As above, but extending the selection to the bottom of the document.
3647 initializeTextSelectionWebView(m_baseURL + "select_range_span_editable.html", &webViewHelper);
3648 frame = webViewHelper.webView()->mainFrame();
3650 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3651 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3652 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3653 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3655 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3656 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3657 frame->selectRange(topLeft(startWebRect), WebPoint(640, 480));
3658 EXPECT_EQ("This text is initially selected. 16-char footer.", selectionAsString(frame));
3661 TEST_F(WebFrameTest, SelectRangeCanMoveSelectionStart)
3663 registerMockedHttpURLLoad("text_selection.html");
3664 FrameTestHelpers::WebViewHelper webViewHelper;
3665 initializeTextSelectionWebView(m_baseURL + "text_selection.html", &webViewHelper);
3666 WebFrame* frame = webViewHelper.webView()->mainFrame();
3668 // Select second span. We can move the start to include the first span.
3669 frame->executeScript(WebScriptSource("selectElement('header_2');"));
3670 EXPECT_EQ("Header 2.", selectionAsString(frame));
3671 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "header_2")), topLeft(elementBounds(frame, "header_1")));
3672 EXPECT_EQ("Header 1. Header 2.", selectionAsString(frame));
3674 // We can move the start and end together.
3675 frame->executeScript(WebScriptSource("selectElement('header_1');"));
3676 EXPECT_EQ("Header 1.", selectionAsString(frame));
3677 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "header_1")));
3678 EXPECT_EQ("", selectionAsString(frame));
3679 // Selection is a caret, not empty.
3680 EXPECT_FALSE(frame->selectionRange().isNull());
3682 // We can move the start across the end.
3683 frame->executeScript(WebScriptSource("selectElement('header_1');"));
3684 EXPECT_EQ("Header 1.", selectionAsString(frame));
3685 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "header_2")));
3686 EXPECT_EQ(" Header 2.", selectionAsString(frame));
3688 // Can't extend the selection part-way into an editable element.
3689 frame->executeScript(WebScriptSource("selectElement('footer_2');"));
3690 EXPECT_EQ("Footer 2.", selectionAsString(frame));
3691 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "footer_2")), topLeft(elementBounds(frame, "editable_2")));
3692 EXPECT_EQ(" [ Footer 1. Footer 2.", selectionAsString(frame));
3694 // Can extend the selection completely across editable elements.
3695 frame->executeScript(WebScriptSource("selectElement('footer_2');"));
3696 EXPECT_EQ("Footer 2.", selectionAsString(frame));
3697 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "footer_2")), topLeft(elementBounds(frame, "header_2")));
3698 EXPECT_EQ("Header 2. ] [ Editable 1. Editable 2. ] [ Footer 1. Footer 2.", selectionAsString(frame));
3700 // If the selection is editable text, we can't extend it into non-editable text.
3701 frame->executeScript(WebScriptSource("selectElement('editable_2');"));
3702 EXPECT_EQ("Editable 2.", selectionAsString(frame));
3703 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "editable_2")), topLeft(elementBounds(frame, "header_2")));
3704 // positionForPoint returns the wrong values for contenteditable spans. See
3705 // http://crbug.com/238334.
3706 // EXPECT_EQ("[ Editable 1. Editable 2.", selectionAsString(frame));
3709 TEST_F(WebFrameTest, SelectRangeCanMoveSelectionEnd)
3711 registerMockedHttpURLLoad("text_selection.html");
3712 FrameTestHelpers::WebViewHelper webViewHelper;
3713 initializeTextSelectionWebView(m_baseURL + "text_selection.html", &webViewHelper);
3714 WebFrame* frame = webViewHelper.webView()->mainFrame();
3716 // Select first span. We can move the end to include the second span.
3717 frame->executeScript(WebScriptSource("selectElement('header_1');"));
3718 EXPECT_EQ("Header 1.", selectionAsString(frame));
3719 frame->selectRange(topLeft(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "header_2")));
3720 EXPECT_EQ("Header 1. Header 2.", selectionAsString(frame));
3722 // We can move the start and end together.
3723 frame->executeScript(WebScriptSource("selectElement('header_2');"));
3724 EXPECT_EQ("Header 2.", selectionAsString(frame));
3725 frame->selectRange(topLeft(elementBounds(frame, "header_2")), topLeft(elementBounds(frame, "header_2")));
3726 EXPECT_EQ("", selectionAsString(frame));
3727 // Selection is a caret, not empty.
3728 EXPECT_FALSE(frame->selectionRange().isNull());
3730 // We can move the end across the start.
3731 frame->executeScript(WebScriptSource("selectElement('header_2');"));
3732 EXPECT_EQ("Header 2.", selectionAsString(frame));
3733 frame->selectRange(topLeft(elementBounds(frame, "header_2")), topLeft(elementBounds(frame, "header_1")));
3734 EXPECT_EQ("Header 1. ", selectionAsString(frame));
3736 // Can't extend the selection part-way into an editable element.
3737 frame->executeScript(WebScriptSource("selectElement('header_1');"));
3738 EXPECT_EQ("Header 1.", selectionAsString(frame));
3739 frame->selectRange(topLeft(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "editable_1")));
3740 EXPECT_EQ("Header 1. Header 2. ] ", selectionAsString(frame));
3742 // Can extend the selection completely across editable elements.
3743 frame->executeScript(WebScriptSource("selectElement('header_1');"));
3744 EXPECT_EQ("Header 1.", selectionAsString(frame));
3745 frame->selectRange(topLeft(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "footer_1")));
3746 EXPECT_EQ("Header 1. Header 2. ] [ Editable 1. Editable 2. ] [ Footer 1.", selectionAsString(frame));
3748 // If the selection is editable text, we can't extend it into non-editable text.
3749 frame->executeScript(WebScriptSource("selectElement('editable_1');"));
3750 EXPECT_EQ("Editable 1.", selectionAsString(frame));
3751 frame->selectRange(topLeft(elementBounds(frame, "editable_1")), bottomRightMinusOne(elementBounds(frame, "footer_1")));
3752 // positionForPoint returns the wrong values for contenteditable spans. See
3753 // http://crbug.com/238334.
3754 // EXPECT_EQ("Editable 1. Editable 2. ]", selectionAsString(frame));
3757 static int computeOffset(WebCore::RenderObject* renderer, int x, int y)
3759 return WebCore::VisiblePosition(renderer->positionForPoint(WebCore::LayoutPoint(x, y))).deepEquivalent().computeOffsetInContainerNode();
3762 // positionForPoint returns the wrong values for contenteditable spans. See
3763 // http://crbug.com/238334.
3764 TEST_F(WebFrameTest, DISABLED_PositionForPointTest)
3766 registerMockedHttpURLLoad("select_range_span_editable.html");
3767 FrameTestHelpers::WebViewHelper webViewHelper;
3768 initializeTextSelectionWebView(m_baseURL + "select_range_span_editable.html", &webViewHelper);
3769 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3770 WebCore::RenderObject* renderer = mainFrame->frame()->selection().rootEditableElement()->renderer();
3771 EXPECT_EQ(0, computeOffset(renderer, -1, -1));
3772 EXPECT_EQ(64, computeOffset(renderer, 1000, 1000));
3774 registerMockedHttpURLLoad("select_range_div_editable.html");
3775 initializeTextSelectionWebView(m_baseURL + "select_range_div_editable.html", &webViewHelper);
3776 mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3777 renderer = mainFrame->frame()->selection().rootEditableElement()->renderer();
3778 EXPECT_EQ(0, computeOffset(renderer, -1, -1));
3779 EXPECT_EQ(64, computeOffset(renderer, 1000, 1000));
3782 #if !OS(MACOSX) && !OS(LINUX)
3783 TEST_F(WebFrameTest, SelectRangeStaysHorizontallyAlignedWhenMoved)
3785 registerMockedHttpURLLoad("move_caret.html");
3787 FrameTestHelpers::WebViewHelper webViewHelper;
3788 initializeTextSelectionWebView(m_baseURL + "move_caret.html", &webViewHelper);
3789 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3791 WebRect initialStartRect;
3792 WebRect initialEndRect;
3796 frame->executeScript(WebScriptSource("selectRange();"));
3797 webViewHelper.webView()->selectionBounds(initialStartRect, initialEndRect);
3798 WebPoint movedStart(topLeft(initialStartRect));
3801 frame->selectRange(movedStart, bottomRightMinusOne(initialEndRect));
3802 webViewHelper.webView()->selectionBounds(startRect, endRect);
3803 EXPECT_EQ(startRect, initialStartRect);
3804 EXPECT_EQ(endRect, initialEndRect);
3807 frame->selectRange(movedStart, bottomRightMinusOne(initialEndRect));
3808 webViewHelper.webView()->selectionBounds(startRect, endRect);
3809 EXPECT_EQ(startRect, initialStartRect);
3810 EXPECT_EQ(endRect, initialEndRect);
3812 WebPoint movedEnd(bottomRightMinusOne(initialEndRect));
3815 frame->selectRange(topLeft(initialStartRect), movedEnd);
3816 webViewHelper.webView()->selectionBounds(startRect, endRect);
3817 EXPECT_EQ(startRect, initialStartRect);
3818 EXPECT_EQ(endRect, initialEndRect);
3821 frame->selectRange(topLeft(initialStartRect), movedEnd);
3822 webViewHelper.webView()->selectionBounds(startRect, endRect);
3823 EXPECT_EQ(startRect, initialStartRect);
3824 EXPECT_EQ(endRect, initialEndRect);
3827 TEST_F(WebFrameTest, MoveCaretStaysHorizontallyAlignedWhenMoved)
3829 WebLocalFrameImpl* frame;
3830 registerMockedHttpURLLoad("move_caret.html");
3832 FrameTestHelpers::WebViewHelper webViewHelper;
3833 initializeTextSelectionWebView(m_baseURL + "move_caret.html", &webViewHelper);
3834 frame = (WebLocalFrameImpl*)webViewHelper.webView()->mainFrame();
3836 WebRect initialStartRect;
3837 WebRect initialEndRect;
3841 frame->executeScript(WebScriptSource("selectCaret();"));
3842 webViewHelper.webView()->selectionBounds(initialStartRect, initialEndRect);
3843 WebPoint moveTo(topLeft(initialStartRect));
3846 frame->moveCaretSelection(moveTo);
3847 webViewHelper.webView()->selectionBounds(startRect, endRect);
3848 EXPECT_EQ(startRect, initialStartRect);
3849 EXPECT_EQ(endRect, initialEndRect);
3852 frame->moveCaretSelection(moveTo);
3853 webViewHelper.webView()->selectionBounds(startRect, endRect);
3854 EXPECT_EQ(startRect, initialStartRect);
3855 EXPECT_EQ(endRect, initialEndRect);
3859 class DisambiguationPopupTestWebViewClient : public FrameTestHelpers::TestWebViewClient {
3861 virtual bool didTapMultipleTargets(const WebGestureEvent&, const WebVector<WebRect>& targetRects) OVERRIDE
3863 EXPECT_GE(targetRects.size(), 2u);
3868 bool triggered() const { return m_triggered; }
3869 void resetTriggered() { m_triggered = false; }
3873 static WebGestureEvent fatTap(int x, int y)
3875 WebGestureEvent event;
3876 event.type = WebInputEvent::GestureTap;
3879 event.data.tap.width = 50;
3880 event.data.tap.height = 50;
3884 TEST_F(WebFrameTest, DisambiguationPopup)
3886 const std::string htmlFile = "disambiguation_popup.html";
3887 registerMockedHttpURLLoad(htmlFile);
3889 DisambiguationPopupTestWebViewClient client;
3891 // Make sure we initialize to minimum scale, even if the window size
3892 // only becomes available after the load begins.
3893 FrameTestHelpers::WebViewHelper webViewHelper;
3894 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client);
3895 webViewHelper.webView()->resize(WebSize(1000, 1000));
3896 webViewHelper.webView()->layout();
3898 client.resetTriggered();
3899 webViewHelper.webView()->handleInputEvent(fatTap(0, 0));
3900 EXPECT_FALSE(client.triggered());
3902 client.resetTriggered();
3903 webViewHelper.webView()->handleInputEvent(fatTap(200, 115));
3904 EXPECT_FALSE(client.triggered());
3906 for (int i = 0; i <= 46; i++) {
3907 client.resetTriggered();
3908 webViewHelper.webView()->handleInputEvent(fatTap(120, 230 + i * 5));
3911 if (j >= 7 && j <= 9)
3912 EXPECT_TRUE(client.triggered());
3914 EXPECT_FALSE(client.triggered());
3917 for (int i = 0; i <= 46; i++) {
3918 client.resetTriggered();
3919 webViewHelper.webView()->handleInputEvent(fatTap(10 + i * 5, 590));
3922 if (j >= 7 && j <= 9)
3923 EXPECT_TRUE(client.triggered());
3925 EXPECT_FALSE(client.triggered());
3929 TEST_F(WebFrameTest, DisambiguationPopupNoContainer)
3931 registerMockedHttpURLLoad("disambiguation_popup_no_container.html");
3933 DisambiguationPopupTestWebViewClient client;
3935 // Make sure we initialize to minimum scale, even if the window size
3936 // only becomes available after the load begins.
3937 FrameTestHelpers::WebViewHelper webViewHelper;
3938 webViewHelper.initializeAndLoad(m_baseURL + "disambiguation_popup_no_container.html", true, 0, &client);
3939 webViewHelper.webView()->resize(WebSize(1000, 1000));
3940 webViewHelper.webView()->layout();
3942 client.resetTriggered();
3943 webViewHelper.webView()->handleInputEvent(fatTap(50, 50));
3944 EXPECT_FALSE(client.triggered());
3947 TEST_F(WebFrameTest, DisambiguationPopupMobileSite)
3949 UseMockScrollbarSettings mockScrollbarSettings;
3950 const std::string htmlFile = "disambiguation_popup_mobile_site.html";
3951 registerMockedHttpURLLoad(htmlFile);
3953 DisambiguationPopupTestWebViewClient client;
3955 // Make sure we initialize to minimum scale, even if the window size
3956 // only becomes available after the load begins.
3957 FrameTestHelpers::WebViewHelper webViewHelper;
3958 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client, enableViewportSettings);
3959 webViewHelper.webView()->resize(WebSize(1000, 1000));
3960 webViewHelper.webView()->layout();
3962 client.resetTriggered();
3963 webViewHelper.webView()->handleInputEvent(fatTap(0, 0));
3964 EXPECT_FALSE(client.triggered());
3966 client.resetTriggered();
3967 webViewHelper.webView()->handleInputEvent(fatTap(200, 115));
3968 EXPECT_FALSE(client.triggered());
3970 for (int i = 0; i <= 46; i++) {
3971 client.resetTriggered();
3972 webViewHelper.webView()->handleInputEvent(fatTap(120, 230 + i * 5));
3973 EXPECT_FALSE(client.triggered());
3976 for (int i = 0; i <= 46; i++) {
3977 client.resetTriggered();
3978 webViewHelper.webView()->handleInputEvent(fatTap(10 + i * 5, 590));
3979 EXPECT_FALSE(client.triggered());
3983 TEST_F(WebFrameTest, DisambiguationPopupViewportSite)
3985 UseMockScrollbarSettings mockScrollbarSettings;
3986 const std::string htmlFile = "disambiguation_popup_viewport_site.html";
3987 registerMockedHttpURLLoad(htmlFile);
3989 DisambiguationPopupTestWebViewClient client;
3991 // Make sure we initialize to minimum scale, even if the window size
3992 // only becomes available after the load begins.
3993 FrameTestHelpers::WebViewHelper webViewHelper;
3994 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client, enableViewportSettings);
3995 webViewHelper.webView()->resize(WebSize(1000, 1000));
3996 webViewHelper.webView()->layout();
3998 client.resetTriggered();
3999 webViewHelper.webView()->handleInputEvent(fatTap(0, 0));
4000 EXPECT_FALSE(client.triggered());
4002 client.resetTriggered();
4003 webViewHelper.webView()->handleInputEvent(fatTap(200, 115));
4004 EXPECT_FALSE(client.triggered());
4006 for (int i = 0; i <= 46; i++) {
4007 client.resetTriggered();
4008 webViewHelper.webView()->handleInputEvent(fatTap(120, 230 + i * 5));
4009 EXPECT_FALSE(client.triggered());
4012 for (int i = 0; i <= 46; i++) {
4013 client.resetTriggered();
4014 webViewHelper.webView()->handleInputEvent(fatTap(10 + i * 5, 590));
4015 EXPECT_FALSE(client.triggered());
4019 TEST_F(WebFrameTest, DisambiguationPopupBlacklist)
4021 const unsigned viewportWidth = 500;
4022 const unsigned viewportHeight = 1000;
4023 const unsigned divHeight = 100;
4024 const std::string htmlFile = "disambiguation_popup_blacklist.html";
4025 registerMockedHttpURLLoad(htmlFile);
4027 DisambiguationPopupTestWebViewClient client;
4029 // Make sure we initialize to minimum scale, even if the window size
4030 // only becomes available after the load begins.
4031 FrameTestHelpers::WebViewHelper webViewHelper;
4032 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client);
4033 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
4034 webViewHelper.webView()->layout();
4036 // Click somewhere where the popup shouldn't appear.
4037 client.resetTriggered();
4038 webViewHelper.webView()->handleInputEvent(fatTap(viewportWidth / 2, 0));
4039 EXPECT_FALSE(client.triggered());
4041 // Click directly in between two container divs with click handlers, with children that don't handle clicks.
4042 client.resetTriggered();
4043 webViewHelper.webView()->handleInputEvent(fatTap(viewportWidth / 2, divHeight));
4044 EXPECT_TRUE(client.triggered());
4046 // The third div container should be blacklisted if you click on the link it contains.
4047 client.resetTriggered();
4048 webViewHelper.webView()->handleInputEvent(fatTap(viewportWidth / 2, divHeight * 3.25));
4049 EXPECT_FALSE(client.triggered());
4052 TEST_F(WebFrameTest, DisambiguationPopupPageScale)
4054 registerMockedHttpURLLoad("disambiguation_popup_page_scale.html");
4056 DisambiguationPopupTestWebViewClient client;
4058 // Make sure we initialize to minimum scale, even if the window size
4059 // only becomes available after the load begins.
4060 FrameTestHelpers::WebViewHelper webViewHelper;
4061 webViewHelper.initializeAndLoad(m_baseURL + "disambiguation_popup_page_scale.html", true, 0, &client);
4062 webViewHelper.webView()->resize(WebSize(1000, 1000));
4063 webViewHelper.webView()->layout();
4065 client.resetTriggered();
4066 webViewHelper.webView()->handleInputEvent(fatTap(80, 80));
4067 EXPECT_TRUE(client.triggered());
4069 client.resetTriggered();
4070 webViewHelper.webView()->handleInputEvent(fatTap(230, 190));
4071 EXPECT_TRUE(client.triggered());
4073 webViewHelper.webView()->setPageScaleFactor(3.0f);
4074 webViewHelper.webView()->layout();
4076 client.resetTriggered();
4077 webViewHelper.webView()->handleInputEvent(fatTap(240, 240));
4078 EXPECT_TRUE(client.triggered());
4080 client.resetTriggered();
4081 webViewHelper.webView()->handleInputEvent(fatTap(690, 570));
4082 EXPECT_FALSE(client.triggered());
4085 class TestSubstituteDataWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
4087 TestSubstituteDataWebFrameClient()
4088 : m_commitCalled(false)
4092 virtual void didFailProvisionalLoad(WebLocalFrame* frame, const WebURLError& error)
4094 frame->loadHTMLString("This should appear", toKURL("data:text/html,chromewebdata"), error.unreachableURL, true);
4097 virtual void didCommitProvisionalLoad(WebLocalFrame* frame, const WebHistoryItem&, WebHistoryCommitType)
4099 if (frame->dataSource()->response().url() != WebURL(URLTestHelpers::toKURL("about:blank")))
4100 m_commitCalled = true;
4103 bool commitCalled() const { return m_commitCalled; }
4106 bool m_commitCalled;
4109 TEST_F(WebFrameTest, ReplaceNavigationAfterHistoryNavigation)
4111 TestSubstituteDataWebFrameClient webFrameClient;
4113 FrameTestHelpers::WebViewHelper webViewHelper;
4114 webViewHelper.initializeAndLoad("about:blank", true, &webFrameClient);
4115 WebFrame* frame = webViewHelper.webView()->mainFrame();
4117 // Load a url as a history navigation that will return an error. TestSubstituteDataWebFrameClient
4118 // will start a SubstituteData load in response to the load failure, which should get fully committed.
4119 // Due to https://bugs.webkit.org/show_bug.cgi?id=91685, FrameLoader::didReceiveData() wasn't getting
4120 // called in this case, which resulted in the SubstituteData document not getting displayed.
4122 error.reason = 1337;
4123 error.domain = "WebFrameTest";
4124 std::string errorURL = "http://0.0.0.0";
4125 WebURLResponse response;
4126 response.initialize();
4127 response.setURL(URLTestHelpers::toKURL(errorURL));
4128 response.setMIMEType("text/html");
4129 response.setHTTPStatusCode(500);
4130 WebHistoryItem errorHistoryItem;
4131 errorHistoryItem.initialize();
4132 errorHistoryItem.setURLString(WebString::fromUTF8(errorURL.c_str(), errorURL.length()));
4133 Platform::current()->unitTestSupport()->registerMockedErrorURL(URLTestHelpers::toKURL(errorURL), response, error);
4134 FrameTestHelpers::loadHistoryItem(frame, errorHistoryItem, WebHistoryDifferentDocumentLoad, WebURLRequest::UseProtocolCachePolicy);
4136 WebString text = frame->contentAsText(std::numeric_limits<size_t>::max());
4137 EXPECT_EQ("This should appear", text.utf8());
4138 EXPECT_TRUE(webFrameClient.commitCalled());
4141 class TestWillInsertBodyWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
4143 TestWillInsertBodyWebFrameClient() : m_numBodies(0), m_didLoad(false)
4147 virtual void didCommitProvisionalLoad(WebLocalFrame*, const WebHistoryItem&, WebHistoryCommitType) OVERRIDE
4153 virtual void didCreateDocumentElement(WebLocalFrame*) OVERRIDE
4155 EXPECT_EQ(0, m_numBodies);
4158 virtual void willInsertBody(WebLocalFrame*) OVERRIDE
4167 TEST_F(WebFrameTest, HTMLDocument)
4169 registerMockedHttpURLLoad("clipped-body.html");
4171 TestWillInsertBodyWebFrameClient webFrameClient;
4172 FrameTestHelpers::WebViewHelper webViewHelper;
4173 webViewHelper.initializeAndLoad(m_baseURL + "clipped-body.html", false, &webFrameClient);
4175 EXPECT_TRUE(webFrameClient.m_didLoad);
4176 EXPECT_EQ(1, webFrameClient.m_numBodies);
4179 TEST_F(WebFrameTest, EmptyDocument)
4181 registerMockedHttpURLLoad("pageserializer/green_rectangle.svg");
4183 TestWillInsertBodyWebFrameClient webFrameClient;
4184 FrameTestHelpers::WebViewHelper webViewHelper;
4185 webViewHelper.initialize(false, &webFrameClient);
4187 EXPECT_FALSE(webFrameClient.m_didLoad);
4188 EXPECT_EQ(1, webFrameClient.m_numBodies); // The empty document that a new frame starts with triggers this.
4191 TEST_F(WebFrameTest, MoveCaretSelectionTowardsWindowPointWithNoSelection)
4193 FrameTestHelpers::WebViewHelper webViewHelper;
4194 webViewHelper.initializeAndLoad("about:blank", true);
4195 WebFrame* frame = webViewHelper.webView()->mainFrame();
4197 // This test passes if this doesn't crash.
4198 frame->moveCaretSelection(WebPoint(0, 0));
4201 class SpellCheckClient : public WebSpellCheckClient {
4203 explicit SpellCheckClient(uint32_t hash = 0) : m_numberOfTimesChecked(0), m_hash(hash) { }
4204 virtual ~SpellCheckClient() { }
4205 virtual void requestCheckingOfText(const blink::WebString&, const blink::WebVector<uint32_t>&, const blink::WebVector<unsigned>&, blink::WebTextCheckingCompletion* completion) OVERRIDE
4207 ++m_numberOfTimesChecked;
4208 Vector<WebTextCheckingResult> results;
4209 const int misspellingStartOffset = 1;
4210 const int misspellingLength = 8;
4211 results.append(WebTextCheckingResult(WebTextDecorationTypeSpelling, misspellingStartOffset, misspellingLength, WebString(), m_hash));
4212 completion->didFinishCheckingText(results);
4214 int numberOfTimesChecked() const { return m_numberOfTimesChecked; }
4216 int m_numberOfTimesChecked;
4220 TEST_F(WebFrameTest, ReplaceMisspelledRange)
4222 registerMockedHttpURLLoad("spell.html");
4223 FrameTestHelpers::WebViewHelper webViewHelper;
4224 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4225 SpellCheckClient spellcheck;
4226 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4228 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4229 Document* document = frame->frame()->document();
4230 Element* element = document->getElementById("data");
4232 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4233 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4234 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4237 document->execCommand("InsertText", false, "_wellcome_.");
4239 const int allTextBeginOffset = 0;
4240 const int allTextLength = 11;
4241 frame->selectRange(WebRange::fromDocumentRange(frame, allTextBeginOffset, allTextLength));
4242 RefPtrWillBeRawPtr<Range> selectionRange = frame->frame()->selection().toNormalizedRange();
4244 EXPECT_EQ(1, spellcheck.numberOfTimesChecked());
4245 EXPECT_EQ(1U, document->markers().markersInRange(selectionRange.get(), DocumentMarker::Spelling).size());
4247 frame->replaceMisspelledRange("welcome");
4248 EXPECT_EQ("_welcome_.", frame->contentAsText(std::numeric_limits<size_t>::max()).utf8());
4251 TEST_F(WebFrameTest, RemoveSpellingMarkers)
4253 registerMockedHttpURLLoad("spell.html");
4254 FrameTestHelpers::WebViewHelper webViewHelper;
4255 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4256 SpellCheckClient spellcheck;
4257 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4259 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4260 Document* document = frame->frame()->document();
4261 Element* element = document->getElementById("data");
4263 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4264 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4265 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4268 document->execCommand("InsertText", false, "_wellcome_.");
4270 frame->removeSpellingMarkers();
4272 const int allTextBeginOffset = 0;
4273 const int allTextLength = 11;
4274 frame->selectRange(WebRange::fromDocumentRange(frame, allTextBeginOffset, allTextLength));
4275 RefPtrWillBeRawPtr<Range> selectionRange = frame->frame()->selection().toNormalizedRange();
4277 EXPECT_EQ(0U, document->markers().markersInRange(selectionRange.get(), DocumentMarker::Spelling).size());
4280 TEST_F(WebFrameTest, MarkerHashIdentifiers) {
4281 registerMockedHttpURLLoad("spell.html");
4282 FrameTestHelpers::WebViewHelper webViewHelper;
4283 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4285 static const uint32_t kHash = 42;
4286 SpellCheckClient spellcheck(kHash);
4287 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4289 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4290 Document* document = frame->frame()->document();
4291 Element* element = document->getElementById("data");
4293 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4294 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4295 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4298 document->execCommand("InsertText", false, "wellcome.");
4300 WebVector<uint32_t> documentMarkers;
4301 webViewHelper.webView()->spellingMarkers(&documentMarkers);
4302 EXPECT_EQ(1U, documentMarkers.size());
4303 EXPECT_EQ(kHash, documentMarkers[0]);
4306 class StubbornSpellCheckClient : public WebSpellCheckClient {
4308 StubbornSpellCheckClient() : m_completion(0) { }
4309 virtual ~StubbornSpellCheckClient() { }
4311 virtual void requestCheckingOfText(
4312 const blink::WebString&,
4313 const blink::WebVector<uint32_t>&,
4314 const blink::WebVector<unsigned>&,
4315 blink::WebTextCheckingCompletion* completion) OVERRIDE
4317 m_completion = completion;
4320 void kickNoResults()
4322 kick(-1, -1, WebTextDecorationTypeSpelling);
4327 kick(1, 8, WebTextDecorationTypeSpelling);
4332 kick(1, 8, WebTextDecorationTypeGrammar);
4335 void kickInvisibleSpellcheck()
4337 kick(1, 8, WebTextDecorationTypeInvisibleSpellcheck);
4341 void kick(int misspellingStartOffset, int misspellingLength, WebTextDecorationType type)
4345 Vector<WebTextCheckingResult> results;
4346 if (misspellingStartOffset >= 0 && misspellingLength > 0)
4347 results.append(WebTextCheckingResult(type, misspellingStartOffset, misspellingLength));
4348 m_completion->didFinishCheckingText(results);
4352 blink::WebTextCheckingCompletion* m_completion;
4355 TEST_F(WebFrameTest, SlowSpellcheckMarkerPosition)
4357 registerMockedHttpURLLoad("spell.html");
4358 FrameTestHelpers::WebViewHelper webViewHelper;
4359 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4361 StubbornSpellCheckClient spellcheck;
4362 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4364 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4365 WebInputElement webInputElement = frame->document().getElementById("data").to<WebInputElement>();
4366 Document* document = frame->frame()->document();
4367 Element* element = document->getElementById("data");
4369 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4370 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4371 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4374 document->execCommand("InsertText", false, "wellcome ");
4375 webInputElement.setSelectionRange(0, 0);
4376 document->execCommand("InsertText", false, "he");
4380 WebVector<uint32_t> documentMarkers;
4381 webViewHelper.webView()->spellingMarkers(&documentMarkers);
4382 EXPECT_EQ(0U, documentMarkers.size());
4385 // This test verifies that cancelling spelling request does not cause a
4386 // write-after-free when there's no spellcheck client set.
4387 TEST_F(WebFrameTest, CancelSpellingRequestCrash)
4389 registerMockedHttpURLLoad("spell.html");
4390 FrameTestHelpers::WebViewHelper webViewHelper;
4391 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4392 webViewHelper.webView()->setSpellCheckClient(0);
4394 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4395 Document* document = frame->frame()->document();
4396 Element* element = document->getElementById("data");
4398 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4399 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4400 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4403 frame->frame()->editor().replaceSelectionWithText("A", false, false);
4404 frame->frame()->spellChecker().cancelCheck();
4407 TEST_F(WebFrameTest, SpellcheckResultErasesMarkers)
4409 registerMockedHttpURLLoad("spell.html");
4410 FrameTestHelpers::WebViewHelper webViewHelper;
4411 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4413 StubbornSpellCheckClient spellcheck;
4414 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4416 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4417 WebInputElement webInputElement = frame->document().getElementById("data").to<WebInputElement>();
4418 Document* document = frame->frame()->document();
4419 Element* element = document->getElementById("data");
4421 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4422 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4423 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4426 document->execCommand("InsertText", false, "welcome ");
4427 document->markers().addMarker(rangeOfContents(element->toNode()).get(), DocumentMarker::Spelling);
4428 document->markers().addMarker(rangeOfContents(element->toNode()).get(), DocumentMarker::Grammar);
4429 document->markers().addMarker(rangeOfContents(element->toNode()).get(), DocumentMarker::InvisibleSpellcheck);
4430 EXPECT_EQ(3U, document->markers().markers().size());
4432 spellcheck.kickNoResults();
4433 EXPECT_EQ(0U, document->markers().markers().size());
4436 TEST_F(WebFrameTest, SpellcheckResultsSavedInDocument)
4438 registerMockedHttpURLLoad("spell.html");
4439 FrameTestHelpers::WebViewHelper webViewHelper;
4440 webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4442 StubbornSpellCheckClient spellcheck;
4443 webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4445 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4446 WebInputElement webInputElement = frame->document().getElementById("data").to<WebInputElement>();
4447 Document* document = frame->frame()->document();
4448 Element* element = document->getElementById("data");
4450 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4451 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4452 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4455 document->execCommand("InsertText", false, "wellcome ");
4458 ASSERT_EQ(1U, document->markers().markers().size());
4459 ASSERT_NE(static_cast<DocumentMarker*>(0), document->markers().markers()[0]);
4460 EXPECT_EQ(DocumentMarker::Spelling, document->markers().markers()[0]->type());
4462 document->execCommand("InsertText", false, "wellcome ");
4464 spellcheck.kickGrammar();
4465 ASSERT_EQ(1U, document->markers().markers().size());
4466 ASSERT_NE(static_cast<DocumentMarker*>(0), document->markers().markers()[0]);
4467 EXPECT_EQ(DocumentMarker::Grammar, document->markers().markers()[0]->type());
4469 document->execCommand("InsertText", false, "wellcome ");
4471 spellcheck.kickInvisibleSpellcheck();
4472 ASSERT_EQ(1U, document->markers().markers().size());
4473 ASSERT_NE(static_cast<DocumentMarker*>(0), document->markers().markers()[0]);
4474 EXPECT_EQ(DocumentMarker::InvisibleSpellcheck, document->markers().markers()[0]->type());
4477 class TestAccessInitialDocumentWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
4479 TestAccessInitialDocumentWebFrameClient() : m_didAccessInitialDocument(false)
4483 virtual void didAccessInitialDocument(WebLocalFrame* frame)
4485 EXPECT_TRUE(!m_didAccessInitialDocument);
4486 m_didAccessInitialDocument = true;
4489 bool m_didAccessInitialDocument;
4492 TEST_F(WebFrameTest, DidAccessInitialDocumentBody)
4494 // FIXME: Why is this local webViewClient needed instead of the default
4495 // WebViewHelper one? With out it there's some mysterious crash in the
4496 // WebViewHelper destructor.
4497 FrameTestHelpers::TestWebViewClient webViewClient;
4498 TestAccessInitialDocumentWebFrameClient webFrameClient;
4499 FrameTestHelpers::WebViewHelper webViewHelper;
4500 webViewHelper.initialize(true, &webFrameClient, &webViewClient);
4502 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4504 // Create another window that will try to access it.
4505 FrameTestHelpers::WebViewHelper newWebViewHelper;
4506 WebView* newView = newWebViewHelper.initialize(true);
4507 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
4509 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4511 // Access the initial document by modifying the body.
4512 newView->mainFrame()->executeScript(
4513 WebScriptSource("window.opener.document.body.innerHTML += 'Modified';"));
4515 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4517 // Access the initial document again, to ensure we don't notify twice.
4518 newView->mainFrame()->executeScript(
4519 WebScriptSource("window.opener.document.body.innerHTML += 'Modified';"));
4521 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4524 TEST_F(WebFrameTest, DidAccessInitialDocumentNavigator)
4526 // FIXME: Why is this local webViewClient needed instead of the default
4527 // WebViewHelper one? With out it there's some mysterious crash in the
4528 // WebViewHelper destructor.
4529 FrameTestHelpers::TestWebViewClient webViewClient;
4530 TestAccessInitialDocumentWebFrameClient webFrameClient;
4531 FrameTestHelpers::WebViewHelper webViewHelper;
4532 webViewHelper.initialize(true, &webFrameClient, &webViewClient);
4534 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4536 // Create another window that will try to access it.
4537 FrameTestHelpers::WebViewHelper newWebViewHelper;
4538 WebView* newView = newWebViewHelper.initialize(true);
4539 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
4541 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4543 // Access the initial document to get to the navigator object.
4544 newView->mainFrame()->executeScript(
4545 WebScriptSource("console.log(window.opener.navigator);"));
4547 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4550 TEST_F(WebFrameTest, DidAccessInitialDocumentViaJavascriptUrl)
4552 TestAccessInitialDocumentWebFrameClient webFrameClient;
4553 FrameTestHelpers::WebViewHelper webViewHelper;
4554 webViewHelper.initialize(true, &webFrameClient);
4556 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4558 // Access the initial document from a javascript: URL.
4559 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.appendChild(document.createTextNode('Modified'))");
4560 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4563 // Fails on the WebKit XP (deps) bot. http://crbug.com/312192
4565 TEST_F(WebFrameTest, DISABLED_DidAccessInitialDocumentBodyBeforeModalDialog)
4567 TEST_F(WebFrameTest, DidAccessInitialDocumentBodyBeforeModalDialog)
4570 // FIXME: Why is this local webViewClient needed instead of the default
4571 // WebViewHelper one? With out it there's some mysterious crash in the
4572 // WebViewHelper destructor.
4573 FrameTestHelpers::TestWebViewClient webViewClient;
4574 TestAccessInitialDocumentWebFrameClient webFrameClient;
4575 FrameTestHelpers::WebViewHelper webViewHelper;
4576 webViewHelper.initialize(true, &webFrameClient, &webViewClient);
4578 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4580 // Create another window that will try to access it.
4581 FrameTestHelpers::WebViewHelper newWebViewHelper;
4582 WebView* newView = newWebViewHelper.initialize(true);
4583 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
4585 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4587 // Access the initial document by modifying the body. We normally set a
4588 // timer to notify the client.
4589 newView->mainFrame()->executeScript(
4590 WebScriptSource("window.opener.document.body.innerHTML += 'Modified';"));
4591 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4593 // Make sure that a modal dialog forces us to notify right away.
4594 newView->mainFrame()->executeScript(
4595 WebScriptSource("window.opener.confirm('Modal');"));
4596 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4598 // Ensure that we don't notify again later.
4600 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4603 // Fails on the WebKit XP (deps) bot. http://crbug.com/312192
4605 TEST_F(WebFrameTest, DISABLED_DidWriteToInitialDocumentBeforeModalDialog)
4607 TEST_F(WebFrameTest, DidWriteToInitialDocumentBeforeModalDialog)
4610 // FIXME: Why is this local webViewClient needed instead of the default
4611 // WebViewHelper one? With out it there's some mysterious crash in the
4612 // WebViewHelper destructor.
4613 FrameTestHelpers::TestWebViewClient webViewClient;
4614 TestAccessInitialDocumentWebFrameClient webFrameClient;
4615 FrameTestHelpers::WebViewHelper webViewHelper;
4616 webViewHelper.initialize(true, &webFrameClient, &webViewClient);
4618 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4620 // Create another window that will try to access it.
4621 FrameTestHelpers::WebViewHelper newWebViewHelper;
4622 WebView* newView = newWebViewHelper.initialize(true);
4623 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
4625 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4627 // Access the initial document with document.write, which moves us past the
4628 // initial empty document state of the state machine. We normally set a
4629 // timer to notify the client.
4630 newView->mainFrame()->executeScript(
4631 WebScriptSource("window.opener.document.write('Modified');"));
4632 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4634 // Make sure that a modal dialog forces us to notify right away.
4635 newView->mainFrame()->executeScript(
4636 WebScriptSource("window.opener.confirm('Modal');"));
4637 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4639 // Ensure that we don't notify again later.
4641 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4644 class TestMainFrameUserOrProgrammaticScrollFrameClient : public FrameTestHelpers::TestWebFrameClient {
4646 TestMainFrameUserOrProgrammaticScrollFrameClient() { reset(); }
4649 m_didScrollMainFrame = false;
4650 m_wasProgrammaticScroll = false;
4652 bool wasUserScroll() const { return m_didScrollMainFrame && !m_wasProgrammaticScroll; }
4653 bool wasProgrammaticScroll() const { return m_didScrollMainFrame && m_wasProgrammaticScroll; }
4656 virtual void didChangeScrollOffset(WebLocalFrame* frame) OVERRIDE
4658 if (frame->parent())
4660 EXPECT_FALSE(m_didScrollMainFrame);
4661 WebCore::FrameView* view = toWebLocalFrameImpl(frame)->frameView();
4662 // FrameView can be scrolled in FrameView::setFixedVisibleContentRect
4663 // which is called from LocalFrame::createView (before the frame is associated
4664 // with the the view).
4666 m_didScrollMainFrame = true;
4667 m_wasProgrammaticScroll = view->inProgrammaticScroll();
4671 bool m_didScrollMainFrame;
4672 bool m_wasProgrammaticScroll;
4675 TEST_F(WebFrameTest, CompositorScrollIsUserScrollLongPage)
4677 registerMockedHttpURLLoad("long_scroll.html");
4678 TestMainFrameUserOrProgrammaticScrollFrameClient client;
4680 // Make sure we initialize to minimum scale, even if the window size
4681 // only becomes available after the load begins.
4682 FrameTestHelpers::WebViewHelper webViewHelper;
4683 webViewHelper.initializeAndLoad(m_baseURL + "long_scroll.html", true, &client);
4684 webViewHelper.webView()->resize(WebSize(1000, 1000));
4685 webViewHelper.webView()->layout();
4687 EXPECT_FALSE(client.wasUserScroll());
4688 EXPECT_FALSE(client.wasProgrammaticScroll());
4690 // Do a compositor scroll, verify that this is counted as a user scroll.
4691 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(0, 1), 1.1f);
4692 EXPECT_TRUE(client.wasUserScroll());
4695 EXPECT_FALSE(client.wasUserScroll());
4696 EXPECT_FALSE(client.wasProgrammaticScroll());
4698 // The page scale 1.0f and scroll.
4699 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(0, 1), 1.0f);
4700 EXPECT_TRUE(client.wasUserScroll());
4703 // No scroll event if there is no scroll delta.
4704 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.0f);
4705 EXPECT_FALSE(client.wasUserScroll());
4706 EXPECT_FALSE(client.wasProgrammaticScroll());
4709 // Non zero page scale and scroll.
4710 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(9, 13), 0.6f);
4711 EXPECT_TRUE(client.wasUserScroll());
4714 // Programmatic scroll.
4715 WebLocalFrameImpl* frameImpl = webViewHelper.webViewImpl()->mainFrameImpl();
4716 frameImpl->executeScript(WebScriptSource("window.scrollTo(0, 20);"));
4717 EXPECT_FALSE(client.wasUserScroll());
4718 EXPECT_TRUE(client.wasProgrammaticScroll());
4721 // Programmatic scroll to same offset. No scroll event should be generated.
4722 frameImpl->executeScript(WebScriptSource("window.scrollTo(0, 20);"));
4723 EXPECT_FALSE(client.wasProgrammaticScroll());
4724 EXPECT_FALSE(client.wasUserScroll());
4728 TEST_F(WebFrameTest, CompositorScrollIsUserScrollShortPage)
4730 registerMockedHttpURLLoad("short_scroll.html");
4732 TestMainFrameUserOrProgrammaticScrollFrameClient client;
4734 // Short page tests.
4735 FrameTestHelpers::WebViewHelper webViewHelper;
4736 webViewHelper.initializeAndLoad(m_baseURL + "short_scroll.html", true, &client);
4738 webViewHelper.webView()->resize(WebSize(1000, 1000));
4739 webViewHelper.webView()->layout();
4741 EXPECT_FALSE(client.wasUserScroll());
4742 EXPECT_FALSE(client.wasProgrammaticScroll());
4744 // Non zero page scale and scroll.
4745 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(9, 13), 2.0f);
4746 EXPECT_FALSE(client.wasProgrammaticScroll());
4747 EXPECT_TRUE(client.wasUserScroll());
4751 TEST_F(WebFrameTest, FirstPartyForCookiesForRedirect)
4753 WTF::String filePath = Platform::current()->unitTestSupport()->webKitRootDir();
4754 filePath.append("/Source/web/tests/data/first_party.html");
4756 WebURL testURL(toKURL("http://www.test.com/first_party_redirect.html"));
4757 char redirect[] = "http://www.test.com/first_party.html";
4758 WebURL redirectURL(toKURL(redirect));
4759 WebURLResponse redirectResponse;
4760 redirectResponse.initialize();
4761 redirectResponse.setMIMEType("text/html");
4762 redirectResponse.setHTTPStatusCode(302);
4763 redirectResponse.setHTTPHeaderField("Location", redirect);
4764 Platform::current()->unitTestSupport()->registerMockedURL(testURL, redirectResponse, filePath);
4766 WebURLResponse finalResponse;
4767 finalResponse.initialize();
4768 finalResponse.setMIMEType("text/html");
4769 Platform::current()->unitTestSupport()->registerMockedURL(redirectURL, finalResponse, filePath);
4771 FrameTestHelpers::WebViewHelper webViewHelper;
4772 webViewHelper.initializeAndLoad(m_baseURL + "first_party_redirect.html", true);
4773 EXPECT_TRUE(webViewHelper.webView()->mainFrame()->document().firstPartyForCookies() == redirectURL);
4776 class TestNavigationPolicyWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
4779 virtual void didNavigateWithinPage(WebLocalFrame*, const WebHistoryItem&, WebHistoryCommitType) OVERRIDE
4785 TEST_F(WebFrameTest, SimulateFragmentAnchorMiddleClick)
4787 registerMockedHttpURLLoad("fragment_middle_click.html");
4788 TestNavigationPolicyWebFrameClient client;
4789 FrameTestHelpers::WebViewHelper webViewHelper;
4790 webViewHelper.initializeAndLoad(m_baseURL + "fragment_middle_click.html", true, &client);
4792 WebCore::Document* document = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document();
4793 WebCore::KURL destination = document->url();
4794 destination.setFragmentIdentifier("test");
4796 RefPtrWillBeRawPtr<WebCore::Event> event = WebCore::MouseEvent::create(WebCore::EventTypeNames::click, false, false,
4797 document->domWindow(), 0, 0, 0, 0, 0, 0, 0, false, false, false, false, 1, nullptr, nullptr);
4798 WebCore::FrameLoadRequest frameRequest(document, WebCore::ResourceRequest(destination));
4799 frameRequest.setTriggeringEvent(event);
4800 toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->loader().load(frameRequest);
4803 class TestNewWindowWebViewClient : public FrameTestHelpers::TestWebViewClient {
4805 virtual WebView* createView(WebLocalFrame*, const WebURLRequest&, const WebWindowFeatures&,
4806 const WebString&, WebNavigationPolicy, bool) OVERRIDE
4813 class TestNewWindowWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
4815 TestNewWindowWebFrameClient()
4816 : m_decidePolicyCallCount(0)
4820 virtual WebNavigationPolicy decidePolicyForNavigation(WebLocalFrame*, WebDataSource::ExtraData*, const WebURLRequest&,
4821 WebNavigationType, WebNavigationPolicy policy, bool) OVERRIDE
4823 m_decidePolicyCallCount++;
4827 int decidePolicyCallCount() const { return m_decidePolicyCallCount; }
4830 int m_decidePolicyCallCount;
4833 TEST_F(WebFrameTest, ModifiedClickNewWindow)
4835 registerMockedHttpURLLoad("ctrl_click.html");
4836 registerMockedHttpURLLoad("hello_world.html");
4837 TestNewWindowWebViewClient webViewClient;
4838 TestNewWindowWebFrameClient webFrameClient;
4839 FrameTestHelpers::WebViewHelper webViewHelper;
4840 webViewHelper.initializeAndLoad(m_baseURL + "ctrl_click.html", true, &webFrameClient, &webViewClient);
4842 WebCore::Document* document = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document();
4843 WebCore::KURL destination = toKURL(m_baseURL + "hello_world.html");
4846 RefPtrWillBeRawPtr<WebCore::Event> event = WebCore::MouseEvent::create(WebCore::EventTypeNames::click, false, false,
4847 document->domWindow(), 0, 0, 0, 0, 0, 0, 0, true, false, false, false, 0, nullptr, nullptr);
4848 WebCore::FrameLoadRequest frameRequest(document, WebCore::ResourceRequest(destination));
4849 frameRequest.setTriggeringEvent(event);
4850 WebCore::UserGestureIndicator gesture(WebCore::DefinitelyProcessingUserGesture);
4851 toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->loader().load(frameRequest);
4852 FrameTestHelpers::pumpPendingRequestsDoNotUse(webViewHelper.webView()->mainFrame());
4854 // decidePolicyForNavigation should be called both for the original request and the ctrl+click.
4855 EXPECT_EQ(2, webFrameClient.decidePolicyCallCount());
4858 TEST_F(WebFrameTest, BackToReload)
4860 registerMockedHttpURLLoad("fragment_middle_click.html");
4861 FrameTestHelpers::WebViewHelper webViewHelper;
4862 webViewHelper.initializeAndLoad(m_baseURL + "fragment_middle_click.html", true);
4863 WebFrame* frame = webViewHelper.webView()->mainFrame();
4864 const WebCore::FrameLoader& mainFrameLoader = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->loader();
4865 RefPtr<WebCore::HistoryItem> firstItem = mainFrameLoader.currentItem();
4866 EXPECT_TRUE(firstItem);
4868 registerMockedHttpURLLoad("white-1x1.png");
4869 FrameTestHelpers::loadFrame(frame, m_baseURL + "white-1x1.png");
4870 EXPECT_NE(firstItem.get(), mainFrameLoader.currentItem());
4872 FrameTestHelpers::loadHistoryItem(frame, WebHistoryItem(firstItem.get()), WebHistoryDifferentDocumentLoad, WebURLRequest::UseProtocolCachePolicy);
4873 EXPECT_EQ(firstItem.get(), mainFrameLoader.currentItem());
4875 FrameTestHelpers::reloadFrame(frame);
4876 EXPECT_EQ(WebURLRequest::ReloadIgnoringCacheData, frame->dataSource()->request().cachePolicy());
4879 TEST_F(WebFrameTest, BackDuringChildFrameReload)
4881 registerMockedHttpURLLoad("page_with_blank_iframe.html");
4882 FrameTestHelpers::WebViewHelper webViewHelper;
4883 webViewHelper.initializeAndLoad(m_baseURL + "page_with_blank_iframe.html", true);
4884 WebFrame* mainFrame = webViewHelper.webView()->mainFrame();
4885 const WebCore::FrameLoader& mainFrameLoader = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->loader();
4886 WebFrame* childFrame = mainFrame->firstChild();
4887 ASSERT_TRUE(childFrame);
4889 // Start a history navigation, then have a different frame commit a navigation.
4890 // In this case, reload an about:blank frame, which will commit synchronously.
4891 // After the history navigation completes, both the appropriate document url and
4892 // the current history item should reflect the history navigation.
4893 registerMockedHttpURLLoad("white-1x1.png");
4894 WebHistoryItem item;
4896 WebURL historyURL(toKURL(m_baseURL + "white-1x1.png"));
4897 item.setURLString(historyURL.string());
4898 mainFrame->loadHistoryItem(item, WebHistoryDifferentDocumentLoad, WebURLRequest::UseProtocolCachePolicy);
4900 FrameTestHelpers::reloadFrame(childFrame);
4901 EXPECT_EQ(item.urlString(), mainFrame->document().url().string());
4902 EXPECT_EQ(item.urlString(), WebString(mainFrameLoader.currentItem()->urlString()));
4905 TEST_F(WebFrameTest, ReloadPost)
4907 registerMockedHttpURLLoad("reload_post.html");
4908 FrameTestHelpers::WebViewHelper webViewHelper;
4909 webViewHelper.initializeAndLoad(m_baseURL + "reload_post.html", true);
4910 WebFrame* frame = webViewHelper.webView()->mainFrame();
4912 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.forms[0].submit()");
4913 // Pump requests one more time after the javascript URL has executed to
4914 // trigger the actual POST load request.
4915 FrameTestHelpers::pumpPendingRequestsDoNotUse(webViewHelper.webView()->mainFrame());
4916 EXPECT_EQ(WebString::fromUTF8("POST"), frame->dataSource()->request().httpMethod());
4918 FrameTestHelpers::reloadFrame(frame);
4919 EXPECT_EQ(WebURLRequest::ReloadIgnoringCacheData, frame->dataSource()->request().cachePolicy());
4920 EXPECT_EQ(WebNavigationTypeFormResubmitted, frame->dataSource()->navigationType());
4923 TEST_F(WebFrameTest, LoadHistoryItemReload)
4925 registerMockedHttpURLLoad("fragment_middle_click.html");
4926 FrameTestHelpers::WebViewHelper webViewHelper;
4927 webViewHelper.initializeAndLoad(m_baseURL + "fragment_middle_click.html", true);
4928 WebFrame* frame = webViewHelper.webView()->mainFrame();
4929 const WebCore::FrameLoader& mainFrameLoader = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->loader();
4930 RefPtr<WebCore::HistoryItem> firstItem = mainFrameLoader.currentItem();
4931 EXPECT_TRUE(firstItem);
4933 registerMockedHttpURLLoad("white-1x1.png");
4934 FrameTestHelpers::loadFrame(frame, m_baseURL + "white-1x1.png");
4935 EXPECT_NE(firstItem.get(), mainFrameLoader.currentItem());
4937 // Cache policy overrides should take.
4938 FrameTestHelpers::loadHistoryItem(frame, WebHistoryItem(firstItem), WebHistoryDifferentDocumentLoad, WebURLRequest::ReloadIgnoringCacheData);
4939 EXPECT_EQ(firstItem.get(), mainFrameLoader.currentItem());
4940 EXPECT_EQ(WebURLRequest::ReloadIgnoringCacheData, frame->dataSource()->request().cachePolicy());
4944 class TestCachePolicyWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
4946 explicit TestCachePolicyWebFrameClient(TestCachePolicyWebFrameClient* parentClient)
4947 : m_parentClient(parentClient)
4948 , m_policy(WebURLRequest::UseProtocolCachePolicy)
4950 , m_willSendRequestCallCount(0)
4951 , m_childFrameCreationCount(0)
4955 void setChildWebFrameClient(TestCachePolicyWebFrameClient* client) { m_childClient = client; }
4956 WebURLRequest::CachePolicy cachePolicy() const { return m_policy; }
4957 int willSendRequestCallCount() const { return m_willSendRequestCallCount; }
4958 int childFrameCreationCount() const { return m_childFrameCreationCount; }
4960 virtual WebFrame* createChildFrame(WebLocalFrame* parent, const WebString&)
4962 ASSERT(m_childClient);
4963 m_childFrameCreationCount++;
4964 WebFrame* frame = WebLocalFrame::create(m_childClient);
4965 parent->appendChild(frame);
4969 virtual void didStartLoading(bool toDifferentDocument)
4971 if (m_parentClient) {
4972 m_parentClient->didStartLoading(toDifferentDocument);
4975 TestWebFrameClient::didStartLoading(toDifferentDocument);
4978 virtual void didStopLoading()
4980 if (m_parentClient) {
4981 m_parentClient->didStopLoading();
4984 TestWebFrameClient::didStopLoading();
4987 virtual void willSendRequest(WebLocalFrame* frame, unsigned, WebURLRequest& request, const WebURLResponse&) OVERRIDE
4989 m_policy = request.cachePolicy();
4990 m_willSendRequestCallCount++;
4994 TestCachePolicyWebFrameClient* m_parentClient;
4996 WebURLRequest::CachePolicy m_policy;
4997 TestCachePolicyWebFrameClient* m_childClient;
4998 int m_willSendRequestCallCount;
4999 int m_childFrameCreationCount;
5002 TEST_F(WebFrameTest, ReloadIframe)
5004 registerMockedHttpURLLoad("iframe_reload.html");
5005 registerMockedHttpURLLoad("visible_iframe.html");
5006 TestCachePolicyWebFrameClient mainClient(0);
5007 TestCachePolicyWebFrameClient childClient(&mainClient);
5008 mainClient.setChildWebFrameClient(&childClient);
5010 FrameTestHelpers::WebViewHelper webViewHelper;
5011 webViewHelper.initializeAndLoad(m_baseURL + "iframe_reload.html", true, &mainClient);
5013 WebLocalFrameImpl* mainFrame = webViewHelper.webViewImpl()->mainFrameImpl();
5014 RefPtr<WebLocalFrameImpl> childFrame = toWebLocalFrameImpl(mainFrame->firstChild());
5015 ASSERT_EQ(childFrame->client(), &childClient);
5016 EXPECT_EQ(mainClient.childFrameCreationCount(), 1);
5017 EXPECT_EQ(childClient.willSendRequestCallCount(), 1);
5018 EXPECT_EQ(childClient.cachePolicy(), WebURLRequest::UseProtocolCachePolicy);
5020 FrameTestHelpers::reloadFrame(mainFrame);
5022 // A new WebFrame should have been created, but the child WebFrameClient should be reused.
5023 ASSERT_NE(childFrame, toWebLocalFrameImpl(mainFrame->firstChild()));
5024 ASSERT_EQ(toWebLocalFrameImpl(mainFrame->firstChild())->client(), &childClient);
5026 EXPECT_EQ(mainClient.childFrameCreationCount(), 2);
5027 EXPECT_EQ(childClient.willSendRequestCallCount(), 2);
5028 EXPECT_EQ(childClient.cachePolicy(), WebURLRequest::ReloadIgnoringCacheData);
5031 class TestSameDocumentWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5033 TestSameDocumentWebFrameClient()
5034 : m_frameLoadTypeSameSeen(false)
5038 virtual void willSendRequest(WebLocalFrame* frame, unsigned, WebURLRequest&, const WebURLResponse&)
5040 if (toWebLocalFrameImpl(frame)->frame()->loader().loadType() == WebCore::FrameLoadTypeSame)
5041 m_frameLoadTypeSameSeen = true;
5044 bool frameLoadTypeSameSeen() const { return m_frameLoadTypeSameSeen; }
5047 bool m_frameLoadTypeSameSeen;
5050 TEST_F(WebFrameTest, NavigateToSame)
5052 registerMockedHttpURLLoad("navigate_to_same.html");
5053 TestSameDocumentWebFrameClient client;
5054 FrameTestHelpers::WebViewHelper webViewHelper;
5055 webViewHelper.initializeAndLoad(m_baseURL + "navigate_to_same.html", true, &client);
5056 EXPECT_FALSE(client.frameLoadTypeSameSeen());
5058 WebCore::FrameLoadRequest frameRequest(0, WebCore::ResourceRequest(toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document()->url()));
5059 toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->loader().load(frameRequest);
5060 FrameTestHelpers::pumpPendingRequestsDoNotUse(webViewHelper.webView()->mainFrame());
5062 EXPECT_TRUE(client.frameLoadTypeSameSeen());
5065 TEST_F(WebFrameTest, WebNodeImageContents)
5067 FrameTestHelpers::WebViewHelper webViewHelper;
5068 webViewHelper.initializeAndLoad("about:blank", true);
5069 WebFrame* frame = webViewHelper.webView()->mainFrame();
5071 static const char bluePNG[] = "<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAGElEQVQYV2NkYPj/n4EIwDiqEF8oUT94AFIQE/cCn90IAAAAAElFTkSuQmCC\">";
5073 // Load up the image and test that we can extract the contents.
5074 WebCore::KURL testURL = toKURL("about:blank");
5075 FrameTestHelpers::loadHTMLString(frame, bluePNG, testURL);
5077 WebNode node = frame->document().body().firstChild();
5078 EXPECT_TRUE(node.isElementNode());
5079 WebElement element = node.to<WebElement>();
5080 WebImage image = element.imageContents();
5081 ASSERT_FALSE(image.isNull());
5082 EXPECT_EQ(image.size().width, 10);
5083 EXPECT_EQ(image.size().height, 10);
5084 // FIXME: The rest of this test is disabled since the ImageDecodeCache state may be inconsistent when this test runs.
5086 // SkBitmap bitmap = image.getSkBitmap();
5087 // SkAutoLockPixels locker(bitmap);
5088 // EXPECT_EQ(bitmap.getColor(0, 0), SK_ColorBLUE);
5091 class TestStartStopCallbackWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5093 TestStartStopCallbackWebFrameClient()
5094 : m_startLoadingCount(0)
5095 , m_stopLoadingCount(0)
5096 , m_differentDocumentStartCount(0)
5100 virtual void didStartLoading(bool toDifferentDocument) OVERRIDE
5102 TestWebFrameClient::didStartLoading(toDifferentDocument);
5103 m_startLoadingCount++;
5104 if (toDifferentDocument)
5105 m_differentDocumentStartCount++;
5108 virtual void didStopLoading() OVERRIDE
5110 TestWebFrameClient::didStopLoading();
5111 m_stopLoadingCount++;
5114 int startLoadingCount() const { return m_startLoadingCount; }
5115 int stopLoadingCount() const { return m_stopLoadingCount; }
5116 int differentDocumentStartCount() const { return m_differentDocumentStartCount; }
5119 int m_startLoadingCount;
5120 int m_stopLoadingCount;
5121 int m_differentDocumentStartCount;
5124 TEST_F(WebFrameTest, PushStateStartsAndStops)
5126 registerMockedHttpURLLoad("push_state.html");
5127 TestStartStopCallbackWebFrameClient client;
5128 FrameTestHelpers::WebViewHelper webViewHelper;
5129 webViewHelper.initializeAndLoad(m_baseURL + "push_state.html", true, &client);
5131 EXPECT_EQ(client.startLoadingCount(), 2);
5132 EXPECT_EQ(client.stopLoadingCount(), 2);
5133 EXPECT_EQ(client.differentDocumentStartCount(), 1);
5136 class TestDidNavigateCommitTypeWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5138 TestDidNavigateCommitTypeWebFrameClient()
5139 : m_lastCommitType(WebHistoryInertCommit)
5143 virtual void didNavigateWithinPage(WebLocalFrame*, const WebHistoryItem&, WebHistoryCommitType type) OVERRIDE
5145 m_lastCommitType = type;
5148 WebHistoryCommitType lastCommitType() const { return m_lastCommitType; }
5151 WebHistoryCommitType m_lastCommitType;
5154 TEST_F(WebFrameTest, SameDocumentHistoryNavigationCommitType)
5156 registerMockedHttpURLLoad("push_state.html");
5157 TestDidNavigateCommitTypeWebFrameClient client;
5158 FrameTestHelpers::WebViewHelper webViewHelper;
5159 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "push_state.html", true, &client);
5160 RefPtr<WebCore::HistoryItem> item = toLocalFrame(webViewImpl->page()->mainFrame())->loader().currentItem();
5163 toLocalFrame(webViewImpl->page()->mainFrame())->loader().loadHistoryItem(item.get(), WebCore::HistorySameDocumentLoad);
5164 EXPECT_EQ(WebBackForwardCommit, client.lastCommitType());
5167 class TestHistoryWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5169 TestHistoryWebFrameClient()
5171 m_replacesCurrentHistoryItem = false;
5174 void didStartProvisionalLoad(WebLocalFrame* frame)
5176 WebDataSource* ds = frame->provisionalDataSource();
5177 m_replacesCurrentHistoryItem = ds->replacesCurrentHistoryItem();
5181 bool replacesCurrentHistoryItem() { return m_replacesCurrentHistoryItem; }
5182 WebFrame* frame() { return m_frame; }
5185 bool m_replacesCurrentHistoryItem;
5189 // Test which ensures that the first navigation in a subframe will always
5190 // result in history entry being replaced and not a new one added.
5191 TEST_F(WebFrameTest, DISABLED_FirstFrameNavigationReplacesHistory)
5193 registerMockedHttpURLLoad("history.html");
5194 registerMockedHttpURLLoad("find.html");
5196 FrameTestHelpers::WebViewHelper webViewHelper;
5197 TestHistoryWebFrameClient client;
5198 webViewHelper.initializeAndLoad("about:blank", true, &client);
5199 EXPECT_TRUE(client.replacesCurrentHistoryItem());
5201 WebFrame* frame = webViewHelper.webView()->mainFrame();
5203 FrameTestHelpers::loadFrame(frame,
5204 "javascript:document.body.appendChild(document.createElement('iframe'))");
5205 WebFrame* iframe = frame->firstChild();
5206 EXPECT_EQ(client.frame(), iframe);
5207 EXPECT_TRUE(client.replacesCurrentHistoryItem());
5209 FrameTestHelpers::loadFrame(frame,
5210 "javascript:window.frames[0].location.assign('" + m_baseURL + "history.html')");
5211 EXPECT_EQ(client.frame(), iframe);
5212 EXPECT_TRUE(client.replacesCurrentHistoryItem());
5214 FrameTestHelpers::loadFrame(frame,
5215 "javascript:window.frames[0].location.assign('" + m_baseURL + "find.html')");
5216 EXPECT_EQ(client.frame(), iframe);
5217 EXPECT_FALSE(client.replacesCurrentHistoryItem());
5219 // Repeat the test, but start out the iframe with initial URL, which is not
5221 FrameTestHelpers::loadFrame(frame,
5222 "javascript:var f = document.createElement('iframe'); "
5223 "f.src = '" + m_baseURL + "history.html';"
5224 "document.body.appendChild(f)");
5226 iframe = frame->firstChild()->nextSibling();
5227 EXPECT_EQ(client.frame(), iframe);
5228 EXPECT_TRUE(client.replacesCurrentHistoryItem());
5230 FrameTestHelpers::loadFrame(frame,
5231 "javascript:window.frames[1].location.assign('" + m_baseURL + "find.html')");
5232 EXPECT_EQ(client.frame(), iframe);
5233 EXPECT_FALSE(client.replacesCurrentHistoryItem());
5236 // Test verifies that layout will change a layer's scrollable attibutes
5237 TEST_F(WebFrameTest, overflowHiddenRewrite)
5239 registerMockedHttpURLLoad("non-scrollable.html");
5240 TestMainFrameUserOrProgrammaticScrollFrameClient client;
5241 OwnPtr<FakeCompositingWebViewClient> fakeCompositingWebViewClient = adoptPtr(new FakeCompositingWebViewClient());
5242 FrameTestHelpers::WebViewHelper webViewHelper;
5243 webViewHelper.initialize(true, 0, fakeCompositingWebViewClient.get(), &configueCompositingWebView);
5245 webViewHelper.webView()->resize(WebSize(100, 100));
5246 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "non-scrollable.html");
5248 WebCore::RenderLayerCompositor* compositor = webViewHelper.webViewImpl()->compositor();
5249 ASSERT_TRUE(compositor->scrollLayer());
5251 // Verify that the WebLayer is not scrollable initially.
5252 WebCore::GraphicsLayer* scrollLayer = compositor->scrollLayer();
5253 WebLayer* webScrollLayer = scrollLayer->platformLayer();
5254 ASSERT_FALSE(webScrollLayer->userScrollableHorizontal());
5255 ASSERT_FALSE(webScrollLayer->userScrollableVertical());
5257 // Call javascript to make the layer scrollable, and verify it.
5258 WebLocalFrameImpl* frame = (WebLocalFrameImpl*)webViewHelper.webView()->mainFrame();
5259 frame->executeScript(WebScriptSource("allowScroll();"));
5260 webViewHelper.webView()->layout();
5261 ASSERT_TRUE(webScrollLayer->userScrollableHorizontal());
5262 ASSERT_TRUE(webScrollLayer->userScrollableVertical());
5265 // Test that currentHistoryItem reflects the current page, not the provisional load.
5266 TEST_F(WebFrameTest, CurrentHistoryItem)
5268 registerMockedHttpURLLoad("fixed_layout.html");
5269 std::string url = m_baseURL + "fixed_layout.html";
5271 FrameTestHelpers::WebViewHelper webViewHelper;
5272 webViewHelper.initialize();
5273 WebFrame* frame = webViewHelper.webView()->mainFrame();
5274 const WebCore::FrameLoader& mainFrameLoader = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->loader();
5275 WebURLRequest request;
5276 request.initialize();
5277 request.setURL(toKURL(url));
5278 frame->loadRequest(request);
5280 // Before commit, there is no history item.
5281 EXPECT_FALSE(mainFrameLoader.currentItem());
5283 FrameTestHelpers::pumpPendingRequestsDoNotUse(frame);
5285 // After commit, there is.
5286 WebCore::HistoryItem* item = mainFrameLoader.currentItem();
5288 EXPECT_EQ(WTF::String(url.data()), item->urlString());
5291 class FailCreateChildFrame : public FrameTestHelpers::TestWebFrameClient {
5293 FailCreateChildFrame() : m_callCount(0) { }
5295 virtual WebFrame* createChildFrame(WebLocalFrame* parent, const WebString& frameName) OVERRIDE
5301 int callCount() const { return m_callCount; }
5307 // Test that we don't crash if WebFrameClient::createChildFrame() fails.
5308 TEST_F(WebFrameTest, CreateChildFrameFailure)
5310 registerMockedHttpURLLoad("create_child_frame_fail.html");
5311 FailCreateChildFrame client;
5312 FrameTestHelpers::WebViewHelper webViewHelper;
5313 webViewHelper.initializeAndLoad(m_baseURL + "create_child_frame_fail.html", true, &client);
5315 EXPECT_EQ(1, client.callCount());
5318 TEST_F(WebFrameTest, fixedPositionInFixedViewport)
5320 UseMockScrollbarSettings mockScrollbarSettings;
5321 registerMockedHttpURLLoad("fixed-position-in-fixed-viewport.html");
5322 FrameTestHelpers::WebViewHelper webViewHelper;
5323 webViewHelper.initializeAndLoad(m_baseURL + "fixed-position-in-fixed-viewport.html", true, 0, 0, enableViewportSettings);
5325 WebView* webView = webViewHelper.webView();
5326 webView->resize(WebSize(100, 100));
5329 Document* document = toWebLocalFrameImpl(webView->mainFrame())->frame()->document();
5330 Element* bottomFixed = document->getElementById("bottom-fixed");
5331 Element* topBottomFixed = document->getElementById("top-bottom-fixed");
5332 Element* rightFixed = document->getElementById("right-fixed");
5333 Element* leftRightFixed = document->getElementById("left-right-fixed");
5335 webView->resize(WebSize(100, 200));
5337 EXPECT_EQ(200, bottomFixed->offsetTop() + bottomFixed->offsetHeight());
5338 EXPECT_EQ(200, topBottomFixed->offsetHeight());
5340 webView->settings()->setMainFrameResizesAreOrientationChanges(false);
5341 webView->resize(WebSize(200, 200));
5343 EXPECT_EQ(200, rightFixed->offsetLeft() + rightFixed->offsetWidth());
5344 EXPECT_EQ(200, leftRightFixed->offsetWidth());
5346 webView->settings()->setMainFrameResizesAreOrientationChanges(true);
5347 // Will scale the page by 1.5.
5348 webView->resize(WebSize(300, 330));
5350 EXPECT_EQ(220, bottomFixed->offsetTop() + bottomFixed->offsetHeight());
5351 EXPECT_EQ(220, topBottomFixed->offsetHeight());
5352 EXPECT_EQ(200, rightFixed->offsetLeft() + rightFixed->offsetWidth());
5353 EXPECT_EQ(200, leftRightFixed->offsetWidth());
5356 TEST_F(WebFrameTest, FrameViewSetFrameRect)
5358 FrameTestHelpers::WebViewHelper webViewHelper;
5359 webViewHelper.initializeAndLoad("about:blank");
5361 WebCore::FrameView* frameView = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
5362 frameView->setFrameRect(WebCore::IntRect(0, 0, 200, 200));
5363 EXPECT_EQ_RECT(WebCore::IntRect(0, 0, 200, 200), frameView->frameRect());
5364 frameView->setFrameRect(WebCore::IntRect(100, 100, 200, 200));
5365 EXPECT_EQ_RECT(WebCore::IntRect(100, 100, 200, 200), frameView->frameRect());
5368 TEST_F(WebFrameTest, FullscreenLayerNonScrollable)
5370 FakeCompositingWebViewClient client;
5371 registerMockedHttpURLLoad("fullscreen_div.html");
5372 FrameTestHelpers::WebViewHelper webViewHelper;
5373 int viewportWidth = 640;
5374 int viewportHeight = 480;
5375 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "fullscreen_div.html", true, 0, &client, &configueCompositingWebView);
5376 webViewImpl->resize(WebSize(viewportWidth, viewportHeight));
5377 webViewImpl->layout();
5379 Document* document = toWebLocalFrameImpl(webViewImpl->mainFrame())->frame()->document();
5380 WebCore::UserGestureIndicator gesture(WebCore::DefinitelyProcessingUserGesture);
5381 Element* divFullscreen = document->getElementById("div1");
5382 divFullscreen->webkitRequestFullscreen();
5383 webViewImpl->willEnterFullScreen();
5384 webViewImpl->didEnterFullScreen();
5385 webViewImpl->layout();
5387 // Verify that the main frame is not scrollable.
5388 ASSERT_TRUE(WebCore::FullscreenElementStack::isFullScreen(*document));
5389 WebLayer* webScrollLayer = webViewImpl->compositor()->scrollLayer()->platformLayer();
5390 ASSERT_FALSE(webScrollLayer->scrollable());
5392 // Verify that the main frame is scrollable upon exiting fullscreen.
5393 webViewImpl->willExitFullScreen();
5394 webViewImpl->didExitFullScreen();
5395 webViewImpl->layout();
5396 ASSERT_FALSE(WebCore::FullscreenElementStack::isFullScreen(*document));
5397 webScrollLayer = webViewImpl->compositor()->scrollLayer()->platformLayer();
5398 ASSERT_TRUE(webScrollLayer->scrollable());
5401 TEST_F(WebFrameTest, FullscreenMainFrameScrollable)
5403 FakeCompositingWebViewClient client;
5404 registerMockedHttpURLLoad("fullscreen_div.html");
5405 FrameTestHelpers::WebViewHelper webViewHelper;
5406 int viewportWidth = 640;
5407 int viewportHeight = 480;
5408 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "fullscreen_div.html", true, 0, &client, &configueCompositingWebView);
5409 webViewImpl->resize(WebSize(viewportWidth, viewportHeight));
5410 webViewImpl->layout();
5412 Document* document = toWebLocalFrameImpl(webViewImpl->mainFrame())->frame()->document();
5413 WebCore::UserGestureIndicator gesture(WebCore::DefinitelyProcessingUserGesture);
5414 document->documentElement()->webkitRequestFullscreen();
5415 webViewImpl->willEnterFullScreen();
5416 webViewImpl->didEnterFullScreen();
5417 webViewImpl->layout();
5419 // Verify that the main frame is still scrollable.
5420 ASSERT_TRUE(WebCore::FullscreenElementStack::isFullScreen(*document));
5421 WebLayer* webScrollLayer = webViewImpl->compositor()->scrollLayer()->platformLayer();
5422 ASSERT_TRUE(webScrollLayer->scrollable());
5425 TEST_F(WebFrameTest, RenderBlockPercentHeightDescendants)
5427 registerMockedHttpURLLoad("percent-height-descendants.html");
5428 FrameTestHelpers::WebViewHelper webViewHelper;
5429 webViewHelper.initializeAndLoad(m_baseURL + "percent-height-descendants.html");
5431 WebView* webView = webViewHelper.webView();
5432 webView->resize(WebSize(800, 800));
5435 Document* document = toWebLocalFrameImpl(webView->mainFrame())->frame()->document();
5436 WebCore::RenderBlock* container = WebCore::toRenderBlock(document->getElementById("container")->renderer());
5437 WebCore::RenderBox* percentHeightInAnonymous = WebCore::toRenderBox(document->getElementById("percent-height-in-anonymous")->renderer());
5438 WebCore::RenderBox* percentHeightDirectChild = WebCore::toRenderBox(document->getElementById("percent-height-direct-child")->renderer());
5440 EXPECT_TRUE(WebCore::RenderBlock::hasPercentHeightDescendant(percentHeightInAnonymous));
5441 EXPECT_TRUE(WebCore::RenderBlock::hasPercentHeightDescendant(percentHeightDirectChild));
5443 ASSERT_TRUE(container->percentHeightDescendants());
5444 ASSERT_TRUE(container->hasPercentHeightDescendants());
5445 EXPECT_EQ(2U, container->percentHeightDescendants()->size());
5446 EXPECT_TRUE(container->percentHeightDescendants()->contains(percentHeightInAnonymous));
5447 EXPECT_TRUE(container->percentHeightDescendants()->contains(percentHeightDirectChild));
5449 WebCore::RenderBlock* anonymousBlock = percentHeightInAnonymous->containingBlock();
5450 EXPECT_TRUE(anonymousBlock->isAnonymous());
5451 EXPECT_FALSE(anonymousBlock->hasPercentHeightDescendants());
5454 TEST_F(WebFrameTest, HasVisibleContentOnVisibleFrames)
5456 registerMockedHttpURLLoad("visible_frames.html");
5457 FrameTestHelpers::WebViewHelper webViewHelper;
5458 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "visible_frames.html");
5459 for (WebFrame* frame = webViewImpl->mainFrameImpl()->traverseNext(false); frame; frame = frame->traverseNext(false)) {
5460 EXPECT_TRUE(frame->hasVisibleContent());
5464 TEST_F(WebFrameTest, HasVisibleContentOnHiddenFrames)
5466 registerMockedHttpURLLoad("hidden_frames.html");
5467 FrameTestHelpers::WebViewHelper webViewHelper;
5468 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "hidden_frames.html");
5469 for (WebFrame* frame = webViewImpl->mainFrameImpl()->traverseNext(false); frame; frame = frame->traverseNext(false)) {
5470 EXPECT_FALSE(frame->hasVisibleContent());
5474 class ManifestChangeWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5476 ManifestChangeWebFrameClient() : m_manifestChangeCount(0) { }
5477 virtual void didChangeManifest(WebLocalFrame*) OVERRIDE
5479 ++m_manifestChangeCount;
5482 int manifestChangeCount() { return m_manifestChangeCount; }
5485 int m_manifestChangeCount;
5488 TEST_F(WebFrameTest, NotifyManifestChange)
5490 registerMockedHttpURLLoad("link-manifest-change.html");
5492 ManifestChangeWebFrameClient webFrameClient;
5493 FrameTestHelpers::WebViewHelper webViewHelper;
5494 webViewHelper.initializeAndLoad(m_baseURL + "link-manifest-change.html", true, &webFrameClient);
5496 EXPECT_EQ(14, webFrameClient.manifestChangeCount());
5499 TEST_F(WebFrameTest, ReloadBypassingCache)
5501 // Check that a reload ignoring cache on a frame will result in the cache
5502 // policy of the request being set to ReloadBypassingCache.
5503 registerMockedHttpURLLoad("foo.html");
5504 FrameTestHelpers::WebViewHelper webViewHelper;
5505 webViewHelper.initializeAndLoad(m_baseURL + "foo.html", true);
5506 WebFrame* frame = webViewHelper.webView()->mainFrame();
5507 FrameTestHelpers::reloadFrameIgnoringCache(frame);
5508 EXPECT_EQ(WebURLRequest::ReloadBypassingCache, frame->dataSource()->request().cachePolicy());
5511 TEST_F(WebFrameTest, NodeImageTestCSSTransform)
5513 FrameTestHelpers::WebViewHelper webViewHelper;
5514 OwnPtr<WebCore::DragImage> dragImage = nodeImageTestSetup(&webViewHelper, std::string("case-css-transform"));
5515 EXPECT_TRUE(dragImage);
5518 ASSERT_TRUE(bitmap.allocN32Pixels(40, 40));
5519 SkCanvas canvas(bitmap);
5520 canvas.drawColor(SK_ColorGREEN);
5522 EXPECT_EQ(40, dragImage->size().width());
5523 EXPECT_EQ(40, dragImage->size().height());
5524 const SkBitmap& dragBitmap = dragImage->bitmap();
5525 SkAutoLockPixels lockPixel(dragBitmap);
5526 EXPECT_EQ(0, memcmp(bitmap.getPixels(), dragBitmap.getPixels(), bitmap.getSize()));
5529 TEST_F(WebFrameTest, NodeImageTestCSS3DTransform)
5531 FrameTestHelpers::WebViewHelper webViewHelper;
5532 OwnPtr<WebCore::DragImage> dragImage = nodeImageTestSetup(&webViewHelper, std::string("case-css-3dtransform"));
5533 EXPECT_TRUE(dragImage);
5536 ASSERT_TRUE(bitmap.allocN32Pixels(20, 40));
5537 SkCanvas canvas(bitmap);
5538 canvas.drawColor(SK_ColorGREEN);
5540 EXPECT_EQ(20, dragImage->size().width());
5541 EXPECT_EQ(40, dragImage->size().height());
5542 const SkBitmap& dragBitmap = dragImage->bitmap();
5543 SkAutoLockPixels lockPixel(dragBitmap);
5544 EXPECT_EQ(0, memcmp(bitmap.getPixels(), dragBitmap.getPixels(), bitmap.getSize()));
5547 class BrandColorTestWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5549 BrandColorTestWebFrameClient()
5550 : m_didNotify(false)
5556 m_didNotify = false;
5559 bool didNotify() const
5565 virtual void didChangeBrandColor()
5573 TEST_F(WebFrameTest, BrandColor)
5575 registerMockedHttpURLLoad("brand_color_test.html");
5576 FrameTestHelpers::WebViewHelper webViewHelper;
5577 BrandColorTestWebFrameClient client;
5578 webViewHelper.initializeAndLoad(m_baseURL + "brand_color_test.html", true, &client);
5579 EXPECT_TRUE(client.didNotify());
5580 WebLocalFrameImpl* frame = webViewHelper.webViewImpl()->mainFrameImpl();
5581 EXPECT_EQ(0xff0000ff, frame->document().brandColor());
5582 // Change color by rgb.
5584 frame->executeScript(WebScriptSource("document.getElementById('bc1').setAttribute('content', 'rgb(0, 0, 0)');"));
5585 EXPECT_TRUE(client.didNotify());
5586 EXPECT_EQ(0xff000000, frame->document().brandColor());
5587 // Change color by hsl.
5589 frame->executeScript(WebScriptSource("document.getElementById('bc1').setAttribute('content', 'hsl(240,100%, 50%)');"));
5590 EXPECT_TRUE(client.didNotify());
5591 EXPECT_EQ(0xff0000ff, frame->document().brandColor());
5592 // Change of second brand-color meta tag will not change frame's brand
5595 frame->executeScript(WebScriptSource("document.getElementById('bc2').setAttribute('content', '#00FF00');"));
5596 EXPECT_TRUE(client.didNotify());
5597 EXPECT_EQ(0xff0000ff, frame->document().brandColor());