2 * Copyright (C) 2010 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include "FloatRect.h"
37 #include "FrameTestHelpers.h"
38 #include "FrameView.h"
39 #include "PlatformContextSkia.h"
41 #include "RenderView.h"
42 #include "ResourceError.h"
46 #include "URLTestHelpers.h"
47 #include "WebDataSource.h"
48 #include "WebDocument.h"
49 #include "WebFindOptions.h"
50 #include "WebFormElement.h"
51 #include "WebFrameClient.h"
52 #include "WebFrameImpl.h"
53 #include "WebHistoryItem.h"
55 #include "WebScriptSource.h"
56 #include "WebSearchableFormData.h"
57 #include "WebSecurityOrigin.h"
58 #include "WebSecurityPolicy.h"
59 #include "WebSettings.h"
60 #include "WebViewClient.h"
61 #include "WebViewImpl.h"
63 #include <gtest/gtest.h>
64 #include <public/Platform.h>
65 #include <public/WebFloatRect.h>
66 #include <public/WebThread.h>
67 #include <public/WebURLResponse.h>
68 #include <public/WebUnitTestSupport.h>
69 #include <wtf/Forward.h>
71 using namespace WebKit;
72 using WebCore::FloatRect;
74 using WebKit::URLTestHelpers::toKURL;
75 using WebKit::FrameTestHelpers::runPendingTasks;
79 #define EXPECT_EQ_RECT(a, b) \
80 EXPECT_EQ(a.x(), b.x()); \
81 EXPECT_EQ(a.y(), b.y()); \
82 EXPECT_EQ(a.width(), b.width()); \
83 EXPECT_EQ(a.height(), b.height());
85 class WebFrameTest : public testing::Test {
88 : m_baseURL("http://www.test.com/")
89 , m_chromeURL("chrome://")
94 virtual ~WebFrameTest()
100 virtual void TearDown()
102 Platform::current()->unitTestSupport()->unregisterAllMockedURLs();
105 void registerMockedHttpURLLoad(const std::string& fileName)
107 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8(fileName.c_str()));
110 void registerMockedChromeURLLoad(const std::string& fileName)
112 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_chromeURL.c_str()), WebString::fromUTF8(fileName.c_str()));
116 std::string m_baseURL;
117 std::string m_chromeURL;
122 TEST_F(WebFrameTest, ContentText)
124 registerMockedHttpURLLoad("iframes_test.html");
125 registerMockedHttpURLLoad("visible_iframe.html");
126 registerMockedHttpURLLoad("invisible_iframe.html");
127 registerMockedHttpURLLoad("zero_sized_iframe.html");
129 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "iframes_test.html");
131 // Now retrieve the frames text and test it only includes visible elements.
132 std::string content = std::string(m_webView->mainFrame()->contentAsText(1024).utf8().data());
133 EXPECT_NE(std::string::npos, content.find(" visible paragraph"));
134 EXPECT_NE(std::string::npos, content.find(" visible iframe"));
135 EXPECT_EQ(std::string::npos, content.find(" invisible pararaph"));
136 EXPECT_EQ(std::string::npos, content.find(" invisible iframe"));
137 EXPECT_EQ(std::string::npos, content.find("iframe with zero size"));
140 TEST_F(WebFrameTest, FrameForEnteredContext)
142 registerMockedHttpURLLoad("iframes_test.html");
143 registerMockedHttpURLLoad("visible_iframe.html");
144 registerMockedHttpURLLoad("invisible_iframe.html");
145 registerMockedHttpURLLoad("zero_sized_iframe.html");
147 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "iframes_test.html", true);
149 v8::HandleScope scope;
150 EXPECT_EQ(m_webView->mainFrame(),
151 WebFrame::frameForContext(
152 m_webView->mainFrame()->mainWorldScriptContext()));
153 EXPECT_EQ(m_webView->mainFrame()->firstChild(),
154 WebFrame::frameForContext(
155 m_webView->mainFrame()->firstChild()->mainWorldScriptContext()));
158 TEST_F(WebFrameTest, FormWithNullFrame)
160 registerMockedHttpURLLoad("form.html");
162 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "form.html");
164 WebVector<WebFormElement> forms;
165 m_webView->mainFrame()->document().forms(forms);
169 EXPECT_EQ(forms.size(), 1U);
171 // This test passes if this doesn't crash.
172 WebSearchableFormData searchableDataForm(forms[0]);
175 TEST_F(WebFrameTest, ChromePageJavascript)
177 registerMockedChromeURLLoad("history.html");
179 // Pass true to enable JavaScript.
180 m_webView = FrameTestHelpers::createWebViewAndLoad(m_chromeURL + "history.html", true);
182 // Try to run JS against the chrome-style URL.
183 FrameTestHelpers::loadFrame(m_webView->mainFrame(), "javascript:document.body.appendChild(document.createTextNode('Clobbered'))");
185 // Required to see any updates in contentAsText.
188 // Now retrieve the frame's text and ensure it was modified by running javascript.
189 std::string content = std::string(m_webView->mainFrame()->contentAsText(1024).utf8().data());
190 EXPECT_NE(std::string::npos, content.find("Clobbered"));
193 TEST_F(WebFrameTest, ChromePageNoJavascript)
195 registerMockedChromeURLLoad("history.html");
197 /// Pass true to enable JavaScript.
198 m_webView = FrameTestHelpers::createWebViewAndLoad(m_chromeURL + "history.html", true);
200 // Try to run JS against the chrome-style URL after prohibiting it.
201 WebSecurityPolicy::registerURLSchemeAsNotAllowingJavascriptURLs("chrome");
202 FrameTestHelpers::loadFrame(m_webView->mainFrame(), "javascript:document.body.appendChild(document.createTextNode('Clobbered'))");
204 // Required to see any updates in contentAsText.
207 // Now retrieve the frame's text and ensure it wasn't modified by running javascript.
208 std::string content = std::string(m_webView->mainFrame()->contentAsText(1024).utf8().data());
209 EXPECT_EQ(std::string::npos, content.find("Clobbered"));
212 TEST_F(WebFrameTest, DispatchMessageEventWithOriginCheck)
214 registerMockedHttpURLLoad("postmessage_test.html");
216 // Pass true to enable JavaScript.
217 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "postmessage_test.html", true);
219 // Send a message with the correct origin.
220 WebSecurityOrigin correctOrigin(WebSecurityOrigin::create(toKURL(m_baseURL)));
221 WebDOMEvent event = m_webView->mainFrame()->document().createEvent("MessageEvent");
222 WebDOMMessageEvent message = event.to<WebDOMMessageEvent>();
223 WebSerializedScriptValue data(WebSerializedScriptValue::fromString("foo"));
224 message.initMessageEvent("message", false, false, data, "http://origin.com", 0, "");
225 m_webView->mainFrame()->dispatchMessageEventWithOriginCheck(correctOrigin, message);
227 // Send another message with incorrect origin.
228 WebSecurityOrigin incorrectOrigin(WebSecurityOrigin::create(toKURL(m_chromeURL)));
229 m_webView->mainFrame()->dispatchMessageEventWithOriginCheck(incorrectOrigin, message);
231 // Required to see any updates in contentAsText.
234 // Verify that only the first addition is in the body of the page.
235 std::string content = std::string(m_webView->mainFrame()->contentAsText(1024).utf8().data());
236 EXPECT_NE(std::string::npos, content.find("Message 1."));
237 EXPECT_EQ(std::string::npos, content.find("Message 2."));
242 class FixedLayoutTestWebViewClient : public WebViewClient {
244 virtual WebScreenInfo screenInfo() OVERRIDE { return m_screenInfo; }
246 WebScreenInfo m_screenInfo;
249 TEST_F(WebFrameTest, FrameViewNeedsLayoutOnFixedLayoutResize)
251 registerMockedHttpURLLoad("fixed_layout.html");
253 FixedLayoutTestWebViewClient client;
254 int viewportWidth = 640;
255 int viewportHeight = 480;
257 // Make sure we initialize to minimum scale, even if the window size
258 // only becomes available after the load begins.
259 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client);
260 m_webView->settings()->setApplyDeviceScaleFactorInCompositor(true);
261 m_webView->settings()->setApplyPageScaleFactorInCompositor(true);
262 m_webView->enableFixedLayoutMode(true);
263 m_webView->settings()->setViewportEnabled(true);
264 m_webView->resize(WebSize(viewportWidth, viewportHeight));
267 WebViewImpl* webViewImpl = static_cast<WebViewImpl*>(m_webView);
268 webViewImpl->mainFrameImpl()->frameView()->setFixedLayoutSize(WebCore::IntSize(100, 100));
269 EXPECT_TRUE(webViewImpl->mainFrameImpl()->frameView()->needsLayout());
271 int prevLayoutCount = webViewImpl->mainFrameImpl()->frameView()->layoutCount();
272 webViewImpl->mainFrameImpl()->frameView()->setFrameRect(WebCore::IntRect(0, 0, 641, 481));
273 EXPECT_EQ(prevLayoutCount, webViewImpl->mainFrameImpl()->frameView()->layoutCount());
275 webViewImpl->layout();
278 TEST_F(WebFrameTest, DeviceScaleFactorUsesDefaultWithoutViewportTag)
280 registerMockedHttpURLLoad("no_viewport_tag.html");
282 int viewportWidth = 640;
283 int viewportHeight = 480;
285 FixedLayoutTestWebViewClient client;
286 client.m_screenInfo.deviceScaleFactor = 2;
288 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client);
290 m_webView->settings()->setApplyDeviceScaleFactorInCompositor(true);
291 m_webView->settings()->setApplyPageScaleFactorInCompositor(true);
292 m_webView->settings()->setViewportEnabled(true);
293 m_webView->enableFixedLayoutMode(true);
294 m_webView->resize(WebSize(viewportWidth, viewportHeight));
297 EXPECT_EQ(2, m_webView->deviceScaleFactor());
299 // Device scale factor should be independent of page scale.
300 m_webView->setPageScaleFactorLimits(1, 2);
301 m_webView->setPageScaleFactorPreservingScrollOffset(0.5);
303 EXPECT_EQ(1, m_webView->pageScaleFactor());
305 // Force the layout to happen before leaving the test.
306 m_webView->mainFrame()->contentAsText(1024).utf8();
309 TEST_F(WebFrameTest, FixedLayoutInitializeAtMinimumPageScale)
311 registerMockedHttpURLLoad("fixed_layout.html");
313 FixedLayoutTestWebViewClient client;
314 client.m_screenInfo.deviceScaleFactor = 1;
315 int viewportWidth = 640;
316 int viewportHeight = 480;
318 // Make sure we initialize to minimum scale, even if the window size
319 // only becomes available after the load begins.
320 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client);
321 m_webView->settings()->setApplyDeviceScaleFactorInCompositor(true);
322 m_webView->settings()->setApplyPageScaleFactorInCompositor(true);
323 m_webView->enableFixedLayoutMode(true);
324 m_webView->settings()->setViewportEnabled(true);
325 m_webView->resize(WebSize(viewportWidth, viewportHeight));
327 int defaultFixedLayoutWidth = 980;
328 float minimumPageScaleFactor = viewportWidth / (float) defaultFixedLayoutWidth;
329 EXPECT_EQ(minimumPageScaleFactor, m_webView->pageScaleFactor());
331 // Assume the user has pinch zoomed to page scale factor 2.
332 float userPinchPageScaleFactor = 2;
333 m_webView->setPageScaleFactorPreservingScrollOffset(userPinchPageScaleFactor);
336 // Make sure we don't reset to initial scale if the page continues to load.
337 bool isNewNavigation;
338 WebViewImpl* webViewImpl = static_cast<WebViewImpl*>(m_webView);
339 webViewImpl ->didCommitLoad(&isNewNavigation, false);
340 webViewImpl ->didChangeContentsSize();
341 EXPECT_EQ(userPinchPageScaleFactor, m_webView->pageScaleFactor());
343 // Make sure we don't reset to initial scale if the viewport size changes.
344 m_webView->resize(WebSize(viewportWidth, viewportHeight + 100));
345 EXPECT_EQ(userPinchPageScaleFactor, m_webView->pageScaleFactor());
348 TEST_F(WebFrameTest, ScaleFactorShouldNotOscillate)
350 registerMockedHttpURLLoad("scale_oscillate.html");
352 FixedLayoutTestWebViewClient client;
353 client.m_screenInfo.deviceScaleFactor = static_cast<float>(1.325);
354 int viewportWidth = 800;
355 int viewportHeight = 1057;
357 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "scale_oscillate.html", true, 0, &client);
358 m_webView->enableFixedLayoutMode(true);
359 m_webView->settings()->setViewportEnabled(true);
360 m_webView->resize(WebSize(viewportWidth, viewportHeight));
364 TEST_F(WebFrameTest, setPageScaleFactorDoesNotLayout)
366 registerMockedHttpURLLoad("fixed_layout.html");
368 FixedLayoutTestWebViewClient client;
369 client.m_screenInfo.deviceScaleFactor = 1;
370 int viewportWidth = 640;
371 int viewportHeight = 480;
373 m_webView = static_cast<WebViewImpl*>(FrameTestHelpers::createWebViewAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client));
374 m_webView->settings()->setApplyDeviceScaleFactorInCompositor(true);
375 m_webView->settings()->setApplyPageScaleFactorInCompositor(true);
376 m_webView->enableFixedLayoutMode(true);
377 m_webView->settings()->setViewportEnabled(true);
378 m_webView->resize(WebSize(viewportWidth, viewportHeight));
381 WebViewImpl* webViewImpl = static_cast<WebViewImpl*>(m_webView);
382 int prevLayoutCount = webViewImpl->mainFrameImpl()->frameView()->layoutCount();
383 webViewImpl->setPageScaleFactor(3, WebPoint());
384 EXPECT_FALSE(webViewImpl->mainFrameImpl()->frameView()->needsLayout());
385 EXPECT_EQ(prevLayoutCount, webViewImpl->mainFrameImpl()->frameView()->layoutCount());
388 TEST_F(WebFrameTest, pageScaleFactorWrittenToHistoryItem)
390 registerMockedHttpURLLoad("fixed_layout.html");
392 FixedLayoutTestWebViewClient client;
393 client.m_screenInfo.deviceScaleFactor = 1;
394 int viewportWidth = 640;
395 int viewportHeight = 480;
397 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client);
398 m_webView->settings()->setApplyDeviceScaleFactorInCompositor(true);
399 m_webView->settings()->setApplyPageScaleFactorInCompositor(true);
400 m_webView->enableFixedLayoutMode(true);
401 m_webView->settings()->setViewportEnabled(true);
402 m_webView->resize(WebSize(viewportWidth, viewportHeight));
405 WebViewImpl* webViewImpl = static_cast<WebViewImpl*>(m_webView);
406 m_webView->setPageScaleFactor(3, WebPoint());
407 webViewImpl->page()->mainFrame()->loader()->history()->saveDocumentAndScrollState();
408 m_webView->setPageScaleFactor(1, WebPoint());
409 webViewImpl->page()->mainFrame()->loader()->history()->restoreScrollPositionAndViewState();
410 EXPECT_EQ(3, m_webView->pageScaleFactor());
413 TEST_F(WebFrameTest, pageScaleFactorShrinksViewport)
415 registerMockedHttpURLLoad("fixed_layout.html");
417 FixedLayoutTestWebViewClient client;
418 client.m_screenInfo.deviceScaleFactor = 1;
419 int viewportWidth = 640;
420 int viewportHeight = 480;
422 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client);
423 m_webView->settings()->setApplyDeviceScaleFactorInCompositor(true);
424 m_webView->settings()->setApplyPageScaleFactorInCompositor(true);
425 m_webView->enableFixedLayoutMode(true);
426 m_webView->settings()->setViewportEnabled(true);
427 m_webView->resize(WebSize(viewportWidth, viewportHeight));
430 WebCore::FrameView* view = static_cast<WebViewImpl*>(m_webView)->mainFrameImpl()->frameView();
431 int viewportWidthMinusScrollbar = 640 - (view->verticalScrollbar()->isOverlayScrollbar() ? 0 : 15);
432 int viewportHeightMinusScrollbar = 480 - (view->horizontalScrollbar()->isOverlayScrollbar() ? 0 : 15);
434 m_webView->setPageScaleFactor(2, WebPoint());
436 WebCore::IntSize unscaledSize = view->unscaledVisibleContentSize(true);
437 EXPECT_EQ(viewportWidth, unscaledSize.width());
438 EXPECT_EQ(viewportHeight, unscaledSize.height());
440 WebCore::IntSize unscaledSizeMinusScrollbar = view->unscaledVisibleContentSize(false);
441 EXPECT_EQ(viewportWidthMinusScrollbar, unscaledSizeMinusScrollbar.width());
442 EXPECT_EQ(viewportHeightMinusScrollbar, unscaledSizeMinusScrollbar.height());
444 WebCore::IntSize scaledSize = view->visibleContentRect().size();
445 EXPECT_EQ(ceil(viewportWidthMinusScrollbar / 2.0), scaledSize.width());
446 EXPECT_EQ(ceil(viewportHeightMinusScrollbar / 2.0), scaledSize.height());
449 TEST_F(WebFrameTest, pageScaleFactorDoesNotApplyCssTransform)
451 registerMockedHttpURLLoad("fixed_layout.html");
453 FixedLayoutTestWebViewClient client;
454 client.m_screenInfo.deviceScaleFactor = 1;
455 int viewportWidth = 640;
456 int viewportHeight = 480;
458 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client);
459 m_webView->settings()->setApplyDeviceScaleFactorInCompositor(true);
460 m_webView->settings()->setApplyPageScaleFactorInCompositor(true);
461 m_webView->enableFixedLayoutMode(true);
462 m_webView->settings()->setViewportEnabled(true);
463 m_webView->resize(WebSize(viewportWidth, viewportHeight));
466 m_webView->setPageScaleFactor(2, WebPoint());
468 WebViewImpl* webViewImpl = static_cast<WebViewImpl*>(m_webView);
469 EXPECT_EQ(1, webViewImpl->page()->mainFrame()->frameScaleFactor());
470 EXPECT_EQ(980, webViewImpl->page()->mainFrame()->contentRenderer()->unscaledDocumentRect().width());
471 EXPECT_EQ(980, webViewImpl->mainFrameImpl()->frameView()->contentsSize().width());
475 TEST_F(WebFrameTest, pageScaleFactorScalesPaintClip)
477 registerMockedHttpURLLoad("fixed_layout.html");
479 FixedLayoutTestWebViewClient client;
480 client.m_screenInfo.deviceScaleFactor = 1;
481 int viewportWidth = 50;
482 int viewportHeight = 50;
484 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client);
485 m_webView->settings()->setApplyDeviceScaleFactorInCompositor(true);
486 m_webView->settings()->setApplyPageScaleFactorInCompositor(true);
487 m_webView->enableFixedLayoutMode(true);
488 m_webView->settings()->setViewportEnabled(true);
489 m_webView->resize(WebSize(viewportWidth, viewportHeight));
492 // Set <1 page scale so that the clip rect should be larger than
493 // the viewport size as passed into resize().
494 m_webView->setPageScaleFactor(0.5, WebPoint());
497 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 200, 200);
498 bitmap.allocPixels();
499 bitmap.eraseColor(0);
500 SkCanvas canvas(bitmap);
502 WebCore::PlatformContextSkia platformContext(&canvas);
503 platformContext.setTrackOpaqueRegion(true);
504 WebCore::GraphicsContext context(&platformContext);
506 EXPECT_EQ_RECT(WebCore::IntRect(0, 0, 0, 0), platformContext.opaqueRegion().asRect());
508 WebCore::FrameView* view = static_cast<WebViewImpl*>(m_webView)->mainFrameImpl()->frameView();
509 WebCore::IntRect paintRect(0, 0, 200, 200);
510 view->paint(&context, paintRect);
512 int viewportWidthMinusScrollbar = 50 - (view->verticalScrollbar()->isOverlayScrollbar() ? 0 : 15);
513 int viewportHeightMinusScrollbar = 50 - (view->horizontalScrollbar()->isOverlayScrollbar() ? 0 : 15);
514 WebCore::IntRect clippedRect(0, 0, viewportWidthMinusScrollbar * 2, viewportHeightMinusScrollbar * 2);
515 EXPECT_EQ_RECT(clippedRect, platformContext.opaqueRegion().asRect());
518 TEST_F(WebFrameTest, CanOverrideMaximumScaleFactor)
520 registerMockedHttpURLLoad("no_scale_for_you.html");
522 FixedLayoutTestWebViewClient client;
523 client.m_screenInfo.deviceScaleFactor = 1;
524 int viewportWidth = 640;
525 int viewportHeight = 480;
527 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "no_scale_for_you.html", true, 0, &client);
528 m_webView->settings()->setApplyDeviceScaleFactorInCompositor(true);
529 m_webView->settings()->setApplyPageScaleFactorInCompositor(true);
530 m_webView->enableFixedLayoutMode(true);
531 m_webView->settings()->setViewportEnabled(true);
532 m_webView->resize(WebSize(viewportWidth, viewportHeight));
534 EXPECT_EQ(1.0f, m_webView->maximumPageScaleFactor());
536 m_webView->setIgnoreViewportTagMaximumScale(true);
539 EXPECT_EQ(4.0f, m_webView->maximumPageScaleFactor());
542 #if ENABLE(GESTURE_EVENTS)
543 void setScaleAndScrollAndLayout(WebKit::WebView* webView, WebPoint scroll, float scale)
545 webView->setPageScaleFactor(scale, WebPoint(scroll.x, scroll.y));
549 TEST_F(WebFrameTest, DivAutoZoomParamsTestCompositorScaling)
551 registerMockedHttpURLLoad("get_scale_for_auto_zoom_into_div_test.html");
553 const float deviceScaleFactor = 2.0f;
554 int viewportWidth = 640 / deviceScaleFactor;
555 int viewportHeight = 1280 / deviceScaleFactor;
556 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "get_scale_for_auto_zoom_into_div_test.html"); //
557 m_webView->settings()->setApplyDeviceScaleFactorInCompositor(true);
558 m_webView->settings()->setApplyPageScaleFactorInCompositor(true);
559 m_webView->setDeviceScaleFactor(deviceScaleFactor);
560 m_webView->setPageScaleFactorLimits(0.01f, 4);
561 m_webView->setPageScaleFactor(0.5f, WebPoint(0, 0));
562 m_webView->resize(WebSize(viewportWidth, viewportHeight));
563 m_webView->enableFixedLayoutMode(true);
566 WebRect wideDiv(200, 100, 400, 150);
567 WebRect tallDiv(200, 300, 400, 800);
568 WebRect doubleTapPointWide(wideDiv.x + 50, wideDiv.y + 50, 0, 0);
569 WebRect doubleTapPointTall(tallDiv.x + 50, tallDiv.y + 50, 0, 0);
574 WebViewImpl* webViewImpl = static_cast<WebViewImpl*>(m_webView);
575 // Test double-tap zooming into wide div.
576 webViewImpl->computeScaleAndScrollForHitRect(doubleTapPointWide, WebViewImpl::DoubleTap, scale, scroll, isAnchor);
577 // The div should horizontally fill the screen (modulo margins), and
578 // vertically centered (modulo integer rounding).
579 EXPECT_NEAR(viewportWidth / (float) wideDiv.width, scale, 0.1);
580 EXPECT_NEAR(wideDiv.x, scroll.x, 20);
581 EXPECT_EQ(0, scroll.y);
582 EXPECT_FALSE(isAnchor);
584 setScaleAndScrollAndLayout(webViewImpl, scroll, scale);
586 // Test zoom out back to minimum scale.
587 webViewImpl->computeScaleAndScrollForHitRect(doubleTapPointWide, WebViewImpl::DoubleTap, scale, scroll, isAnchor);
588 EXPECT_FLOAT_EQ(webViewImpl->minimumPageScaleFactor(), scale);
589 EXPECT_TRUE(isAnchor);
591 setScaleAndScrollAndLayout(webViewImpl, WebPoint(0, 0), scale);
593 // Test double-tap zooming into tall div.
594 webViewImpl->computeScaleAndScrollForHitRect(doubleTapPointTall, WebViewImpl::DoubleTap, scale, scroll, isAnchor);
595 // The div should start at the top left of the viewport.
596 EXPECT_NEAR(viewportWidth / (float) tallDiv.width, scale, 0.1);
597 EXPECT_NEAR(tallDiv.x, scroll.x, 20);
598 EXPECT_NEAR(tallDiv.y, scroll.y, 20);
599 EXPECT_FALSE(isAnchor);
601 // Test for Non-doubletap scaling
602 // Test zooming into div.
603 webViewImpl->computeScaleAndScrollForHitRect(WebRect(250, 250, 10, 10), WebViewImpl::FindInPage, scale, scroll, isAnchor);
604 EXPECT_NEAR(viewportWidth / (float) wideDiv.width, scale, 0.1);
607 void simulateDoubleTap(WebViewImpl* webViewImpl, WebPoint& point, float& scale)
609 webViewImpl->animateZoomAroundPoint(point, WebViewImpl::DoubleTap);
610 webViewImpl->mainFrameImpl()->frameView()->layout();
611 scale = webViewImpl->pageScaleFactor();
614 TEST_F(WebFrameTest, DivAutoZoomMultipleDivsTestCompositorScaling)
616 registerMockedHttpURLLoad("get_multiple_divs_for_auto_zoom_test.html");
618 const float deviceScaleFactor = 2.0f;
619 int viewportWidth = 640 / deviceScaleFactor;
620 int viewportHeight = 1280 / deviceScaleFactor;
621 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
622 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "get_multiple_divs_for_auto_zoom_test.html");
623 m_webView->settings()->setApplyDeviceScaleFactorInCompositor(true);
624 m_webView->settings()->setApplyPageScaleFactorInCompositor(true);
625 m_webView->enableFixedLayoutMode(true);
626 m_webView->resize(WebSize(viewportWidth, viewportHeight));
627 m_webView->setPageScaleFactorLimits(0.5f, 4);
628 m_webView->setDeviceScaleFactor(deviceScaleFactor);
629 m_webView->setPageScaleFactor(0.5f, WebPoint(0, 0));
632 WebViewImpl* webViewImpl = static_cast<WebViewImpl*>(m_webView);
633 webViewImpl->shouldUseAnimateDoubleTapTimeZeroForTesting(true);
635 WebRect topDiv(200, 100, 200, 150);
636 WebRect bottomDiv(200, 300, 200, 150);
637 WebPoint topPoint(topDiv.x + 50, topDiv.y + 50);
638 WebPoint bottomPoint(bottomDiv.x + 50, bottomDiv.y + 50);
640 setScaleAndScrollAndLayout(webViewImpl, WebPoint(0, 0), (webViewImpl->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
642 // Test double tap on two different divs
643 // After first zoom, we should go back to minimum page scale with a second double tap.
644 simulateDoubleTap(webViewImpl, topPoint, scale);
645 EXPECT_FLOAT_EQ(1, scale);
646 simulateDoubleTap(webViewImpl, bottomPoint, scale);
647 EXPECT_FLOAT_EQ(webViewImpl->minimumPageScaleFactor(), scale);
649 // If the user pinch zooms after double tap, a second double tap should zoom back to the div.
650 simulateDoubleTap(webViewImpl, topPoint, scale);
651 EXPECT_FLOAT_EQ(1, scale);
652 webViewImpl->applyScrollAndScale(WebSize(), 0.6f);
653 simulateDoubleTap(webViewImpl, bottomPoint, scale);
654 EXPECT_FLOAT_EQ(1, scale);
657 TEST_F(WebFrameTest, DivAutoZoomScaleBoundsTestCompositorScaling)
659 registerMockedHttpURLLoad("get_scale_bounds_check_for_auto_zoom_test.html");
661 int viewportWidth = 320;
662 int viewportHeight = 480;
663 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
664 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "get_scale_bounds_check_for_auto_zoom_test.html");
665 m_webView->settings()->setApplyDeviceScaleFactorInCompositor(true);
666 m_webView->settings()->setApplyPageScaleFactorInCompositor(true);
667 m_webView->enableFixedLayoutMode(true);
668 m_webView->resize(WebSize(viewportWidth, viewportHeight));
669 m_webView->setDeviceScaleFactor(1.5f);
672 WebViewImpl* webViewImpl = static_cast<WebViewImpl*>(m_webView);
673 webViewImpl->shouldUseAnimateDoubleTapTimeZeroForTesting(true);
675 WebRect div(200, 100, 200, 150);
676 WebPoint doubleTapPoint(div.x + 50, div.y + 50);
679 // Test double tap scale bounds.
680 // minimumPageScale < doubleTapZoomAlreadyLegibleScale < 1
681 m_webView->setPageScaleFactorLimits(0.5f, 4);
683 float doubleTapZoomAlreadyLegibleScale = webViewImpl->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
684 setScaleAndScrollAndLayout(webViewImpl, WebPoint(0, 0), (webViewImpl->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
685 simulateDoubleTap(webViewImpl, doubleTapPoint, scale);
686 EXPECT_FLOAT_EQ(1, scale);
687 simulateDoubleTap(webViewImpl, doubleTapPoint, scale);
688 EXPECT_FLOAT_EQ(webViewImpl->minimumPageScaleFactor(), scale);
689 simulateDoubleTap(webViewImpl, doubleTapPoint, scale);
690 EXPECT_FLOAT_EQ(1, scale);
692 // Zoom in to reset double_tap_zoom_in_effect flag.
693 webViewImpl->applyScrollAndScale(WebSize(), 1.1f);
694 // 1 < minimumPageScale < doubleTapZoomAlreadyLegibleScale
695 m_webView->setPageScaleFactorLimits(1.1f, 4);
697 doubleTapZoomAlreadyLegibleScale = webViewImpl->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
698 setScaleAndScrollAndLayout(webViewImpl, WebPoint(0, 0), (webViewImpl->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
699 simulateDoubleTap(webViewImpl, doubleTapPoint, scale);
700 EXPECT_FLOAT_EQ(webViewImpl->minimumPageScaleFactor(), scale);
701 simulateDoubleTap(webViewImpl, doubleTapPoint, scale);
702 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
703 simulateDoubleTap(webViewImpl, doubleTapPoint, scale);
704 EXPECT_FLOAT_EQ(webViewImpl->minimumPageScaleFactor(), scale);
706 // Zoom in to reset double_tap_zoom_in_effect flag.
707 webViewImpl->applyScrollAndScale(WebSize(), 1.1f);
708 // minimumPageScale < 1 < doubleTapZoomAlreadyLegibleScale
709 m_webView->setPageScaleFactorLimits(0.95f, 4);
711 doubleTapZoomAlreadyLegibleScale = webViewImpl->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
712 setScaleAndScrollAndLayout(webViewImpl, WebPoint(0, 0), (webViewImpl->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
713 simulateDoubleTap(webViewImpl, doubleTapPoint, scale);
714 EXPECT_FLOAT_EQ(webViewImpl->minimumPageScaleFactor(), scale);
715 simulateDoubleTap(webViewImpl, doubleTapPoint, scale);
716 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
717 simulateDoubleTap(webViewImpl, doubleTapPoint, scale);
718 EXPECT_FLOAT_EQ(webViewImpl->minimumPageScaleFactor(), scale);
721 #if ENABLE(TEXT_AUTOSIZING)
722 TEST_F(WebFrameTest, DivAutoZoomScaleFontScaleFactorTestCompositorScaling)
724 registerMockedHttpURLLoad("get_scale_bounds_check_for_auto_zoom_test.html");
726 int viewportWidth = 320;
727 int viewportHeight = 480;
728 float doubleTapZoomAlreadyLegibleRatio = 1.2f;
729 float textAutosizingFontScaleFactor = 1.13f;
730 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "get_scale_bounds_check_for_auto_zoom_test.html");
731 m_webView->settings()->setApplyDeviceScaleFactorInCompositor(true);
732 m_webView->settings()->setApplyPageScaleFactorInCompositor(true);
733 m_webView->enableFixedLayoutMode(true);
734 m_webView->resize(WebSize(viewportWidth, viewportHeight));
737 WebViewImpl* webViewImpl = static_cast<WebViewImpl*>(m_webView);
738 webViewImpl->shouldUseAnimateDoubleTapTimeZeroForTesting(true);
739 webViewImpl->page()->settings()->setTextAutosizingFontScaleFactor(textAutosizingFontScaleFactor);
741 WebRect div(200, 100, 200, 150);
742 WebPoint doubleTapPoint(div.x + 50, div.y + 50);
745 // Test double tap scale bounds.
746 // minimumPageScale < doubleTapZoomAlreadyLegibleScale < 1 < textAutosizingFontScaleFactor
747 float legibleScale = textAutosizingFontScaleFactor;
748 setScaleAndScrollAndLayout(webViewImpl, WebPoint(0, 0), (webViewImpl->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
749 float doubleTapZoomAlreadyLegibleScale = webViewImpl->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
750 m_webView->setPageScaleFactorLimits(0.5f, 4);
752 simulateDoubleTap(webViewImpl, doubleTapPoint, scale);
753 EXPECT_FLOAT_EQ(legibleScale, scale);
754 simulateDoubleTap(webViewImpl, doubleTapPoint, scale);
755 EXPECT_FLOAT_EQ(webViewImpl->minimumPageScaleFactor(), scale);
756 simulateDoubleTap(webViewImpl, doubleTapPoint, scale);
757 EXPECT_FLOAT_EQ(legibleScale, scale);
759 // Zoom in to reset double_tap_zoom_in_effect flag.
760 webViewImpl->applyScrollAndScale(WebSize(), 1.1f);
761 // 1 < textAutosizingFontScaleFactor < minimumPageScale < doubleTapZoomAlreadyLegibleScale
762 m_webView->setPageScaleFactorLimits(1.0f, 4);
764 doubleTapZoomAlreadyLegibleScale = webViewImpl->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
765 setScaleAndScrollAndLayout(webViewImpl, WebPoint(0, 0), (webViewImpl->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
766 simulateDoubleTap(webViewImpl, doubleTapPoint, scale);
767 EXPECT_FLOAT_EQ(webViewImpl->minimumPageScaleFactor(), scale);
768 simulateDoubleTap(webViewImpl, doubleTapPoint, scale);
769 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
770 simulateDoubleTap(webViewImpl, doubleTapPoint, scale);
771 EXPECT_FLOAT_EQ(webViewImpl->minimumPageScaleFactor(), scale);
773 // Zoom in to reset double_tap_zoom_in_effect flag.
774 webViewImpl->applyScrollAndScale(WebSize(), 1.1f);
775 // minimumPageScale < 1 < textAutosizingFontScaleFactor < doubleTapZoomAlreadyLegibleScale
776 m_webView->setPageScaleFactorLimits(0.95f, 4);
778 doubleTapZoomAlreadyLegibleScale = webViewImpl->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
779 setScaleAndScrollAndLayout(webViewImpl, WebPoint(0, 0), (webViewImpl->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
780 simulateDoubleTap(webViewImpl, doubleTapPoint, scale);
781 EXPECT_FLOAT_EQ(webViewImpl->minimumPageScaleFactor(), scale);
782 simulateDoubleTap(webViewImpl, doubleTapPoint, scale);
783 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
784 simulateDoubleTap(webViewImpl, doubleTapPoint, scale);
785 EXPECT_FLOAT_EQ(webViewImpl->minimumPageScaleFactor(), scale);
787 // Zoom in to reset double_tap_zoom_in_effect flag.
788 webViewImpl->applyScrollAndScale(WebSize(), 1.1f);
789 // minimumPageScale < 1 < doubleTapZoomAlreadyLegibleScale < textAutosizingFontScaleFactor
790 m_webView->setPageScaleFactorLimits(0.9f, 4);
792 doubleTapZoomAlreadyLegibleScale = webViewImpl->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
793 setScaleAndScrollAndLayout(webViewImpl, WebPoint(0, 0), (webViewImpl->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
794 simulateDoubleTap(webViewImpl, doubleTapPoint, scale);
795 EXPECT_FLOAT_EQ(legibleScale, scale);
796 simulateDoubleTap(webViewImpl, doubleTapPoint, scale);
797 EXPECT_FLOAT_EQ(webViewImpl->minimumPageScaleFactor(), scale);
798 simulateDoubleTap(webViewImpl, doubleTapPoint, scale);
799 EXPECT_FLOAT_EQ(legibleScale, scale);
803 TEST_F(WebFrameTest, DivScrollIntoEditableTest)
805 registerMockedHttpURLLoad("get_scale_for_zoom_into_editable_test.html");
807 int viewportWidth = 450;
808 int viewportHeight = 300;
809 float leftBoxRatio = 0.3f;
810 int caretPadding = 10;
811 float minReadableCaretHeight = 18.0f;
812 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "get_scale_for_zoom_into_editable_test.html");
813 m_webView->settings()->setApplyDeviceScaleFactorInCompositor(true);
814 m_webView->settings()->setApplyPageScaleFactorInCompositor(true);
815 m_webView->enableFixedLayoutMode(true);
816 m_webView->resize(WebSize(viewportWidth, viewportHeight));
817 m_webView->setPageScaleFactorLimits(1, 4);
819 m_webView->setDeviceScaleFactor(1.5f);
820 m_webView->settings()->setAutoZoomFocusedNodeToLegibleScale(true);
822 WebViewImpl* webViewImpl = static_cast<WebViewImpl*>(m_webView);
823 webViewImpl->shouldUseAnimateDoubleTapTimeZeroForTesting(true);
825 WebRect editBoxWithText(200, 200, 250, 20);
826 WebRect editBoxWithNoText(200, 250, 250, 20);
828 // Test scrolling the focused node
829 // The edit box is shorter and narrower than the viewport when legible.
830 m_webView->advanceFocus(false);
831 // Set the caret to the end of the input box.
832 m_webView->mainFrame()->document().getElementById("EditBoxWithText").to<WebInputElement>().setSelectionRange(1000, 1000);
833 setScaleAndScrollAndLayout(m_webView, WebPoint(0, 0), 1);
835 webViewImpl->selectionBounds(caret, rect);
838 WebCore::IntPoint scroll;
840 webViewImpl->computeScaleAndScrollForFocusedNode(webViewImpl->focusedWebCoreNode(), scale, scroll, needAnimation);
841 EXPECT_TRUE(needAnimation);
842 // The edit box should be left aligned with a margin for possible label.
843 int hScroll = editBoxWithText.x - leftBoxRatio * viewportWidth / scale;
844 EXPECT_NEAR(hScroll, scroll.x(), 1);
845 int vScroll = editBoxWithText.y - (viewportHeight / scale - editBoxWithText.height) / 2;
846 EXPECT_NEAR(vScroll, scroll.y(), 1);
847 EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1);
849 // The edit box is wider than the viewport when legible.
851 viewportHeight = 150;
852 m_webView->resize(WebSize(viewportWidth, viewportHeight));
853 setScaleAndScrollAndLayout(m_webView, WebPoint(0, 0), 1);
854 webViewImpl->selectionBounds(caret, rect);
855 webViewImpl->computeScaleAndScrollForFocusedNode(webViewImpl->focusedWebCoreNode(), scale, scroll, needAnimation);
856 EXPECT_TRUE(needAnimation);
857 // The caret should be right aligned since the caret would be offscreen when the edit box is left aligned.
858 hScroll = caret.x + caret.width + caretPadding - viewportWidth / scale;
859 EXPECT_NEAR(hScroll, scroll.x(), 1);
860 EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1);
862 setScaleAndScrollAndLayout(m_webView, WebPoint(0, 0), 1);
863 // Move focus to edit box with text.
864 m_webView->advanceFocus(false);
865 webViewImpl->selectionBounds(caret, rect);
866 webViewImpl->computeScaleAndScrollForFocusedNode(webViewImpl->focusedWebCoreNode(), scale, scroll, needAnimation);
867 EXPECT_TRUE(needAnimation);
868 // The edit box should be left aligned.
869 hScroll = editBoxWithNoText.x;
870 EXPECT_NEAR(hScroll, scroll.x(), 1);
871 vScroll = editBoxWithNoText.y - (viewportHeight / scale - editBoxWithNoText.height) / 2;
872 EXPECT_NEAR(vScroll, scroll.y(), 1);
873 EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1);
875 setScaleAndScrollAndLayout(webViewImpl, scroll, scale);
877 // Move focus back to the first edit box.
878 m_webView->advanceFocus(true);
879 webViewImpl->computeScaleAndScrollForFocusedNode(webViewImpl->focusedWebCoreNode(), scale, scroll, needAnimation);
880 // The position should have stayed the same since this box was already on screen with the right scale.
881 EXPECT_FALSE(needAnimation);
886 class TestReloadDoesntRedirectWebFrameClient : public WebFrameClient {
888 virtual WebNavigationPolicy decidePolicyForNavigation(
889 WebFrame*, const WebURLRequest&, WebNavigationType,
890 const WebNode& originatingNode,
891 WebNavigationPolicy defaultPolicy, bool isRedirect)
893 EXPECT_FALSE(isRedirect);
894 return WebNavigationPolicyCurrentTab;
897 virtual WebURLError cancelledError(WebFrame*, const WebURLRequest& request)
899 // Return a dummy error so the DocumentLoader doesn't assert when
900 // the reload cancels it.
901 WebURLError webURLError;
902 webURLError.domain = "";
903 webURLError.reason = 1;
904 webURLError.isCancellation = true;
905 webURLError.unreachableURL = WebURL();
910 TEST_F(WebFrameTest, ReloadDoesntSetRedirect)
912 // Test for case in http://crbug.com/73104. Reloading a frame very quickly
913 // would sometimes call decidePolicyForNavigation with isRedirect=true
914 registerMockedHttpURLLoad("form.html");
916 TestReloadDoesntRedirectWebFrameClient webFrameClient;
917 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "form.html", false, &webFrameClient);
919 m_webView->mainFrame()->reload(true);
920 // start reload before request is delivered.
921 m_webView->mainFrame()->reload(true);
922 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
928 TEST_F(WebFrameTest, ReloadWithOverrideURLPreservesState)
930 const std::string firstURL = "find.html";
931 const std::string secondURL = "form.html";
932 const std::string thirdURL = "history.html";
933 const float pageScaleFactor = 1.1684f;
934 const int pageWidth = 640;
935 const int pageHeight = 480;
937 registerMockedHttpURLLoad(firstURL);
938 registerMockedHttpURLLoad(secondURL);
939 registerMockedHttpURLLoad(thirdURL);
941 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + firstURL, true);
942 WebViewImpl* webViewImpl = static_cast<WebViewImpl*>(m_webView);
943 webViewImpl->resize(WebSize(pageWidth, pageHeight));
944 webViewImpl->mainFrame()->setScrollOffset(WebSize(pageWidth / 4, pageHeight / 4));
945 webViewImpl->setPageScaleFactorPreservingScrollOffset(pageScaleFactor);
947 WebSize previousOffset = webViewImpl->mainFrame()->scrollOffset();
948 float previousScale = webViewImpl->pageScaleFactor();
950 // Reload the page using the cache.
951 webViewImpl->mainFrame()->reloadWithOverrideURL(toKURL(m_baseURL + secondURL), false);
952 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
953 ASSERT_EQ(previousOffset, webViewImpl->mainFrame()->scrollOffset());
954 ASSERT_EQ(previousScale, webViewImpl->pageScaleFactor());
956 // Reload the page while ignoring the cache.
957 webViewImpl->mainFrame()->reloadWithOverrideURL(toKURL(m_baseURL + thirdURL), true);
958 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
959 ASSERT_EQ(previousOffset, webViewImpl->mainFrame()->scrollOffset());
960 ASSERT_EQ(previousScale, webViewImpl->pageScaleFactor());
963 TEST_F(WebFrameTest, IframeRedirect)
965 registerMockedHttpURLLoad("iframe_redirect.html");
966 registerMockedHttpURLLoad("visible_iframe.html");
968 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "iframe_redirect.html", true);
969 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); // Load the iframe.
971 WebFrame* iframe = m_webView->findFrameByName(WebString::fromUTF8("ifr"));
973 WebDataSource* iframeDataSource = iframe->dataSource();
974 ASSERT_TRUE(iframeDataSource);
975 WebVector<WebURL> redirects;
976 iframeDataSource->redirectChain(redirects);
977 ASSERT_EQ(2U, redirects.size());
978 EXPECT_EQ(toKURL("about:blank"), toKURL(redirects[0].spec().data()));
979 EXPECT_EQ(toKURL("http://www.test.com/visible_iframe.html"), toKURL(redirects[1].spec().data()));
982 TEST_F(WebFrameTest, ClearFocusedNodeTest)
984 registerMockedHttpURLLoad("iframe_clear_focused_node_test.html");
985 registerMockedHttpURLLoad("autofocus_input_field_iframe.html");
987 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "iframe_clear_focused_node_test.html", true);
989 // Clear the focused node.
990 m_webView->clearFocusedNode();
992 // Now retrieve the FocusedNode and test it should be null.
993 EXPECT_EQ(0, static_cast<WebViewImpl*>(m_webView)->focusedWebCoreNode());
996 // Implementation of WebFrameClient that tracks the v8 contexts that are created
997 // and destroyed for verification.
998 class ContextLifetimeTestWebFrameClient : public WebFrameClient {
1000 struct Notification {
1002 Notification(WebFrame* frame, v8::Handle<v8::Context> context, int worldId)
1004 , context(v8::Persistent<v8::Context>::New(context->GetIsolate(), context))
1011 context.Dispose(context->GetIsolate());
1014 bool Equals(Notification* other)
1016 return other && frame == other->frame && context == other->context && worldId == other->worldId;
1020 v8::Persistent<v8::Context> context;
1024 virtual ~ContextLifetimeTestWebFrameClient()
1031 for (size_t i = 0; i < createNotifications.size(); ++i)
1032 delete createNotifications[i];
1034 for (size_t i = 0; i < releaseNotifications.size(); ++i)
1035 delete releaseNotifications[i];
1037 createNotifications.clear();
1038 releaseNotifications.clear();
1041 std::vector<Notification*> createNotifications;
1042 std::vector<Notification*> releaseNotifications;
1045 virtual void didCreateScriptContext(WebFrame* frame, v8::Handle<v8::Context> context, int extensionGroup, int worldId) OVERRIDE
1047 createNotifications.push_back(new Notification(frame, context, worldId));
1050 virtual void willReleaseScriptContext(WebFrame* frame, v8::Handle<v8::Context> context, int worldId) OVERRIDE
1052 releaseNotifications.push_back(new Notification(frame, context, worldId));
1056 TEST_F(WebFrameTest, ContextNotificationsLoadUnload)
1058 v8::HandleScope handleScope;
1060 registerMockedHttpURLLoad("context_notifications_test.html");
1061 registerMockedHttpURLLoad("context_notifications_test_frame.html");
1063 // Load a frame with an iframe, make sure we get the right create notifications.
1064 ContextLifetimeTestWebFrameClient webFrameClient;
1065 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "context_notifications_test.html", true, &webFrameClient);
1067 WebFrame* mainFrame = m_webView->mainFrame();
1068 WebFrame* childFrame = mainFrame->firstChild();
1070 ASSERT_EQ(2u, webFrameClient.createNotifications.size());
1071 EXPECT_EQ(0u, webFrameClient.releaseNotifications.size());
1073 ContextLifetimeTestWebFrameClient::Notification* firstCreateNotification = webFrameClient.createNotifications[0];
1074 ContextLifetimeTestWebFrameClient::Notification* secondCreateNotification = webFrameClient.createNotifications[1];
1076 EXPECT_EQ(mainFrame, firstCreateNotification->frame);
1077 EXPECT_EQ(mainFrame->mainWorldScriptContext(), firstCreateNotification->context);
1078 EXPECT_EQ(0, firstCreateNotification->worldId);
1080 EXPECT_EQ(childFrame, secondCreateNotification->frame);
1081 EXPECT_EQ(childFrame->mainWorldScriptContext(), secondCreateNotification->context);
1082 EXPECT_EQ(0, secondCreateNotification->worldId);
1084 // Close the view. We should get two release notifications that are exactly the same as the create ones, in reverse order.
1088 ASSERT_EQ(2u, webFrameClient.releaseNotifications.size());
1089 ContextLifetimeTestWebFrameClient::Notification* firstReleaseNotification = webFrameClient.releaseNotifications[0];
1090 ContextLifetimeTestWebFrameClient::Notification* secondReleaseNotification = webFrameClient.releaseNotifications[1];
1092 ASSERT_TRUE(firstCreateNotification->Equals(secondReleaseNotification));
1093 ASSERT_TRUE(secondCreateNotification->Equals(firstReleaseNotification));
1096 TEST_F(WebFrameTest, ContextNotificationsReload)
1098 v8::HandleScope handleScope;
1100 registerMockedHttpURLLoad("context_notifications_test.html");
1101 registerMockedHttpURLLoad("context_notifications_test_frame.html");
1103 ContextLifetimeTestWebFrameClient webFrameClient;
1104 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "context_notifications_test.html", true, &webFrameClient);
1106 // Refresh, we should get two release notifications and two more create notifications.
1107 m_webView->mainFrame()->reload(false);
1108 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
1109 ASSERT_EQ(4u, webFrameClient.createNotifications.size());
1110 ASSERT_EQ(2u, webFrameClient.releaseNotifications.size());
1112 // The two release notifications we got should be exactly the same as the first two create notifications.
1113 for (size_t i = 0; i < webFrameClient.releaseNotifications.size(); ++i) {
1114 EXPECT_TRUE(webFrameClient.releaseNotifications[i]->Equals(
1115 webFrameClient.createNotifications[webFrameClient.createNotifications.size() - 3 - i]));
1118 // The last two create notifications should be for the current frames and context.
1119 WebFrame* mainFrame = m_webView->mainFrame();
1120 WebFrame* childFrame = mainFrame->firstChild();
1121 ContextLifetimeTestWebFrameClient::Notification* firstRefreshNotification = webFrameClient.createNotifications[2];
1122 ContextLifetimeTestWebFrameClient::Notification* secondRefreshNotification = webFrameClient.createNotifications[3];
1124 EXPECT_EQ(mainFrame, firstRefreshNotification->frame);
1125 EXPECT_EQ(mainFrame->mainWorldScriptContext(), firstRefreshNotification->context);
1126 EXPECT_EQ(0, firstRefreshNotification->worldId);
1128 EXPECT_EQ(childFrame, secondRefreshNotification->frame);
1129 EXPECT_EQ(childFrame->mainWorldScriptContext(), secondRefreshNotification->context);
1130 EXPECT_EQ(0, secondRefreshNotification->worldId);
1136 TEST_F(WebFrameTest, ContextNotificationsIsolatedWorlds)
1138 v8::HandleScope handleScope;
1140 registerMockedHttpURLLoad("context_notifications_test.html");
1141 registerMockedHttpURLLoad("context_notifications_test_frame.html");
1143 ContextLifetimeTestWebFrameClient webFrameClient;
1144 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "context_notifications_test.html", true, &webFrameClient);
1146 // Add an isolated world.
1147 webFrameClient.reset();
1149 int isolatedWorldId = 42;
1150 WebScriptSource scriptSource("hi!");
1152 int extensionGroup = 0;
1153 m_webView->mainFrame()->executeScriptInIsolatedWorld(isolatedWorldId, &scriptSource, numSources, extensionGroup);
1155 // We should now have a new create notification.
1156 ASSERT_EQ(1u, webFrameClient.createNotifications.size());
1157 ContextLifetimeTestWebFrameClient::Notification* notification = webFrameClient.createNotifications[0];
1158 ASSERT_EQ(isolatedWorldId, notification->worldId);
1159 ASSERT_EQ(m_webView->mainFrame(), notification->frame);
1161 // 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.
1162 ASSERT_NE(m_webView->mainFrame()->mainWorldScriptContext(), notification->context);
1167 // We should have gotten three release notifications (one for each of the frames, plus one for the isolated context).
1168 ASSERT_EQ(3u, webFrameClient.releaseNotifications.size());
1170 // And one of them should be exactly the same as the create notification for the isolated context.
1172 for (size_t i = 0; i < webFrameClient.releaseNotifications.size(); ++i) {
1173 if (webFrameClient.releaseNotifications[i]->Equals(webFrameClient.createNotifications[0]))
1176 EXPECT_EQ(1, matchCount);
1179 TEST_F(WebFrameTest, FindInPage)
1181 registerMockedHttpURLLoad("find.html");
1182 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "find.html");
1183 WebFrame* frame = m_webView->mainFrame();
1184 const int findIdentifier = 12345;
1185 WebFindOptions options;
1187 // Find in a <div> element.
1188 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar1"), options, false, 0));
1189 frame->stopFinding(false);
1190 WebRange range = frame->selectionRange();
1191 EXPECT_EQ(5, range.startOffset());
1192 EXPECT_EQ(9, range.endOffset());
1193 EXPECT_TRUE(frame->document().focusedNode().isNull());
1195 // Find in an <input> value.
1196 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar2"), options, false, 0));
1197 // Confirm stopFinding(false) sets the selection on the found text.
1198 frame->stopFinding(false);
1199 range = frame->selectionRange();
1200 ASSERT_FALSE(range.isNull());
1201 EXPECT_EQ(5, range.startOffset());
1202 EXPECT_EQ(9, range.endOffset());
1203 EXPECT_EQ(WebString::fromUTF8("INPUT"), frame->document().focusedNode().nodeName());
1205 // Find in a <textarea> content.
1206 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar3"), options, false, 0));
1207 // Confirm stopFinding(false) sets the selection on the found text.
1208 frame->stopFinding(false);
1209 range = frame->selectionRange();
1210 ASSERT_FALSE(range.isNull());
1211 EXPECT_EQ(5, range.startOffset());
1212 EXPECT_EQ(9, range.endOffset());
1213 EXPECT_EQ(WebString::fromUTF8("TEXTAREA"), frame->document().focusedNode().nodeName());
1215 // Find in a contentEditable element.
1216 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar4"), options, false, 0));
1217 // Confirm stopFinding(false) sets the selection on the found text.
1218 frame->stopFinding(false);
1219 range = frame->selectionRange();
1220 ASSERT_FALSE(range.isNull());
1221 EXPECT_EQ(0, range.startOffset());
1222 EXPECT_EQ(4, range.endOffset());
1223 // "bar4" is surrounded by <span>, but the focusable node should be the parent <div>.
1224 EXPECT_EQ(WebString::fromUTF8("DIV"), frame->document().focusedNode().nodeName());
1226 // Find in <select> content.
1227 EXPECT_FALSE(frame->find(findIdentifier, WebString::fromUTF8("bar5"), options, false, 0));
1228 // If there are any matches, stopFinding will set the selection on the found text.
1229 // However, we do not expect any matches, so check that the selection is null.
1230 frame->stopFinding(false);
1231 range = frame->selectionRange();
1232 ASSERT_TRUE(range.isNull());
1235 TEST_F(WebFrameTest, GetContentAsPlainText)
1237 m_webView = FrameTestHelpers::createWebViewAndLoad("about:blank", true);
1238 // We set the size because it impacts line wrapping, which changes the
1239 // resulting text value.
1240 m_webView->resize(WebSize(640, 480));
1241 WebFrame* frame = m_webView->mainFrame();
1243 // Generate a simple test case.
1244 const char simpleSource[] = "<div>Foo bar</div><div></div>baz";
1245 WebCore::KURL testURL = toKURL("about:blank");
1246 frame->loadHTMLString(simpleSource, testURL);
1249 // Make sure it comes out OK.
1250 const std::string expected("Foo bar\nbaz");
1251 WebString text = frame->contentAsText(std::numeric_limits<size_t>::max());
1252 EXPECT_EQ(expected, std::string(text.utf8().data()));
1254 // Try reading the same one with clipping of the text.
1255 const int length = 5;
1256 text = frame->contentAsText(length);
1257 EXPECT_EQ(expected.substr(0, length), std::string(text.utf8().data()));
1259 // Now do a new test with a subframe.
1260 const char outerFrameSource[] = "Hello<iframe></iframe> world";
1261 frame->loadHTMLString(outerFrameSource, testURL);
1264 // Load something into the subframe.
1265 WebFrame* subframe = frame->findChildByExpression(WebString::fromUTF8("/html/body/iframe"));
1266 ASSERT_TRUE(subframe);
1267 subframe->loadHTMLString("sub<p>text", testURL);
1270 text = frame->contentAsText(std::numeric_limits<size_t>::max());
1271 EXPECT_EQ("Hello world\n\nsub\ntext", std::string(text.utf8().data()));
1273 // Get the frame text where the subframe separator falls on the boundary of
1274 // what we'll take. There used to be a crash in this case.
1275 text = frame->contentAsText(12);
1276 EXPECT_EQ("Hello world", std::string(text.utf8().data()));
1279 TEST_F(WebFrameTest, GetFullHtmlOfPage)
1281 m_webView = FrameTestHelpers::createWebViewAndLoad("about:blank", true);
1282 WebFrame* frame = m_webView->mainFrame();
1284 // Generate a simple test case.
1285 const char simpleSource[] = "<p>Hello</p><p>World</p>";
1286 WebCore::KURL testURL = toKURL("about:blank");
1287 frame->loadHTMLString(simpleSource, testURL);
1290 WebString text = frame->contentAsText(std::numeric_limits<size_t>::max());
1291 EXPECT_EQ("Hello\n\nWorld", std::string(text.utf8().data()));
1293 const std::string html = std::string(frame->contentAsMarkup().utf8().data());
1295 // Load again with the output html.
1296 frame->loadHTMLString(WebData(html.c_str(), html.length()), testURL);
1299 EXPECT_EQ(html, std::string(frame->contentAsMarkup().utf8().data()));
1301 text = frame->contentAsText(std::numeric_limits<size_t>::max());
1302 EXPECT_EQ("Hello\n\nWorld", std::string(text.utf8().data()));
1304 // Test selection check
1305 EXPECT_FALSE(frame->hasSelection());
1306 frame->executeCommand(WebString::fromUTF8("SelectAll"));
1307 EXPECT_TRUE(frame->hasSelection());
1308 frame->executeCommand(WebString::fromUTF8("Unselect"));
1309 EXPECT_FALSE(frame->hasSelection());
1310 WebString selectionHtml = frame->selectionAsMarkup();
1311 EXPECT_TRUE(selectionHtml.isEmpty());
1314 class TestExecuteScriptDuringDidCreateScriptContext : public WebFrameClient {
1316 virtual void didCreateScriptContext(WebFrame* frame, v8::Handle<v8::Context> context, int extensionGroup, int worldId) OVERRIDE
1318 frame->executeScript(WebScriptSource("window.history = 'replaced';"));
1322 TEST_F(WebFrameTest, ExecuteScriptDuringDidCreateScriptContext)
1324 registerMockedHttpURLLoad("hello_world.html");
1326 TestExecuteScriptDuringDidCreateScriptContext webFrameClient;
1327 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "hello_world.html", true, &webFrameClient);
1329 m_webView->mainFrame()->reload();
1330 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
1336 class TestDidCreateFrameWebFrameClient : public WebFrameClient {
1338 TestDidCreateFrameWebFrameClient() : m_frameCount(0), m_parent(0)
1342 virtual void didCreateFrame(WebFrame* parent, WebFrame* child)
1353 TEST_F(WebFrameTest, DidCreateFrame)
1355 registerMockedHttpURLLoad("iframes_test.html");
1356 registerMockedHttpURLLoad("visible_iframe.html");
1357 registerMockedHttpURLLoad("invisible_iframe.html");
1358 registerMockedHttpURLLoad("zero_sized_iframe.html");
1360 TestDidCreateFrameWebFrameClient webFrameClient;
1361 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "iframes_test.html", false, &webFrameClient);
1363 EXPECT_EQ(webFrameClient.m_frameCount, 3);
1364 EXPECT_EQ(webFrameClient.m_parent, m_webView->mainFrame());
1370 class FindUpdateWebFrameClient : public WebFrameClient {
1372 FindUpdateWebFrameClient()
1373 : m_findResultsAreReady(false)
1378 virtual void reportFindInPageMatchCount(int, int count, bool finalUpdate) OVERRIDE
1382 m_findResultsAreReady = true;
1385 bool findResultsAreReady() const { return m_findResultsAreReady; }
1386 int count() const { return m_count; }
1389 bool m_findResultsAreReady;
1393 // This fails on Mac https://bugs.webkit.org/show_bug.cgi?id=108574
1395 TEST_F(WebFrameTest, DISABLED_FindInPageMatchRects)
1397 TEST_F(WebFrameTest, FindInPageMatchRects)
1400 registerMockedHttpURLLoad("find_in_page.html");
1401 registerMockedHttpURLLoad("find_in_page_frame.html");
1403 FindUpdateWebFrameClient client;
1404 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "find_in_page.html", true, &client);
1405 m_webView->resize(WebSize(640, 480));
1406 m_webView->layout();
1409 // Note that the 'result 19' in the <select> element is not expected to produce a match.
1410 static const char* kFindString = "result";
1411 static const int kFindIdentifier = 12345;
1412 static const int kNumResults = 19;
1414 WebFindOptions options;
1415 WebString searchText = WebString::fromUTF8(kFindString);
1416 WebFrameImpl* mainFrame = static_cast<WebFrameImpl*>(m_webView->mainFrame());
1417 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
1419 mainFrame->resetMatchCount();
1421 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
1422 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
1425 EXPECT_TRUE(client.findResultsAreReady());
1427 WebVector<WebFloatRect> webMatchRects;
1428 mainFrame->findMatchRects(webMatchRects);
1429 ASSERT_EQ(webMatchRects.size(), static_cast<size_t>(kNumResults));
1430 int rectsVersion = mainFrame->findMatchMarkersVersion();
1432 for (int resultIndex = 0; resultIndex < kNumResults; ++resultIndex) {
1433 FloatRect resultRect = static_cast<FloatRect>(webMatchRects[resultIndex]);
1435 // Select the match by the center of its rect.
1436 EXPECT_EQ(mainFrame->selectNearestFindMatch(resultRect.center(), 0), resultIndex + 1);
1438 // Check that the find result ordering matches with our expectations.
1439 Range* result = mainFrame->activeMatchFrame()->activeMatch();
1440 ASSERT_TRUE(result);
1441 result->setEnd(result->endContainer(), result->endOffset() + 3);
1442 EXPECT_EQ(result->text(), String::format("%s %02d", kFindString, resultIndex));
1444 // Verify that the expected match rect also matches the currently active match.
1445 // Compare the enclosing rects to prevent precision issues caused by CSS transforms.
1446 FloatRect activeMatch = mainFrame->activeFindMatchRect();
1447 EXPECT_EQ(enclosingIntRect(activeMatch), enclosingIntRect(resultRect));
1449 // The rects version should not have changed.
1450 EXPECT_EQ(mainFrame->findMatchMarkersVersion(), rectsVersion);
1453 // All results after the first two ones should be below between them in find-in-page coordinates.
1454 // This is because results 2 to 9 are inside an iframe located between results 0 and 1. This applies to the fixed div too.
1455 EXPECT_TRUE(webMatchRects[0].y < webMatchRects[1].y);
1456 for (int resultIndex = 2; resultIndex < kNumResults; ++resultIndex) {
1457 EXPECT_TRUE(webMatchRects[0].y < webMatchRects[resultIndex].y);
1458 EXPECT_TRUE(webMatchRects[1].y > webMatchRects[resultIndex].y);
1461 // Result 3 should be below both 2 and 4. This is caused by the CSS transform in the containing div.
1462 // If the transform doesn't work then 3 will be between 2 and 4.
1463 EXPECT_TRUE(webMatchRects[3].y > webMatchRects[2].y);
1464 EXPECT_TRUE(webMatchRects[3].y > webMatchRects[4].y);
1466 // Results 6, 7, 8 and 9 should be one below the other in that same order.
1467 // If overflow:scroll is not properly handled then result 8 would be below result 9 or
1468 // result 7 above result 6 depending on the scroll.
1469 EXPECT_TRUE(webMatchRects[6].y < webMatchRects[7].y);
1470 EXPECT_TRUE(webMatchRects[7].y < webMatchRects[8].y);
1471 EXPECT_TRUE(webMatchRects[8].y < webMatchRects[9].y);
1473 // Results 11, 12, 13 and 14 should be between results 10 and 15, as they are inside the table.
1474 EXPECT_TRUE(webMatchRects[11].y > webMatchRects[10].y);
1475 EXPECT_TRUE(webMatchRects[12].y > webMatchRects[10].y);
1476 EXPECT_TRUE(webMatchRects[13].y > webMatchRects[10].y);
1477 EXPECT_TRUE(webMatchRects[14].y > webMatchRects[10].y);
1478 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[15].y);
1479 EXPECT_TRUE(webMatchRects[12].y < webMatchRects[15].y);
1480 EXPECT_TRUE(webMatchRects[13].y < webMatchRects[15].y);
1481 EXPECT_TRUE(webMatchRects[14].y < webMatchRects[15].y);
1483 // Result 11 should be above 12, 13 and 14 as it's in the table header.
1484 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[12].y);
1485 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[13].y);
1486 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[14].y);
1488 // Result 11 should also be right to 12, 13 and 14 because of the colspan.
1489 EXPECT_TRUE(webMatchRects[11].x > webMatchRects[12].x);
1490 EXPECT_TRUE(webMatchRects[11].x > webMatchRects[13].x);
1491 EXPECT_TRUE(webMatchRects[11].x > webMatchRects[14].x);
1493 // Result 12 should be left to results 11, 13 and 14 in the table layout.
1494 EXPECT_TRUE(webMatchRects[12].x < webMatchRects[11].x);
1495 EXPECT_TRUE(webMatchRects[12].x < webMatchRects[13].x);
1496 EXPECT_TRUE(webMatchRects[12].x < webMatchRects[14].x);
1498 // Results 13, 12 and 14 should be one above the other in that order because of the rowspan
1499 // and vertical-align: middle by default.
1500 EXPECT_TRUE(webMatchRects[13].y < webMatchRects[12].y);
1501 EXPECT_TRUE(webMatchRects[12].y < webMatchRects[14].y);
1503 // Result 16 should be below result 15.
1504 EXPECT_TRUE(webMatchRects[15].y > webMatchRects[14].y);
1506 // Result 18 should be normalized with respect to the position:relative div, and not it's
1507 // immediate containing div. Consequently, result 18 should be above result 17.
1508 EXPECT_TRUE(webMatchRects[17].y > webMatchRects[18].y);
1510 // Resizing should update the rects version.
1511 m_webView->resize(WebSize(800, 600));
1513 EXPECT_TRUE(mainFrame->findMatchMarkersVersion() != rectsVersion);
1519 TEST_F(WebFrameTest, FindInPageSkipsHiddenFrames)
1521 registerMockedHttpURLLoad("find_in_hidden_frame.html");
1523 FindUpdateWebFrameClient client;
1524 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "find_in_hidden_frame.html", true, &client);
1525 m_webView->resize(WebSize(640, 480));
1526 m_webView->layout();
1529 static const char* kFindString = "hello";
1530 static const int kFindIdentifier = 12345;
1531 static const int kNumResults = 1;
1533 WebFindOptions options;
1534 WebString searchText = WebString::fromUTF8(kFindString);
1535 WebFrameImpl* mainFrame = static_cast<WebFrameImpl*>(m_webView->mainFrame());
1536 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
1538 mainFrame->resetMatchCount();
1540 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
1541 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
1544 EXPECT_TRUE(client.findResultsAreReady());
1545 EXPECT_EQ(kNumResults, client.count());
1551 TEST_F(WebFrameTest, FindOnDetachedFrame)
1553 registerMockedHttpURLLoad("find_in_page.html");
1554 registerMockedHttpURLLoad("find_in_page_frame.html");
1556 FindUpdateWebFrameClient client;
1557 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "find_in_page.html", true, &client);
1558 m_webView->resize(WebSize(640, 480));
1559 m_webView->layout();
1562 static const char* kFindString = "result";
1563 static const int kFindIdentifier = 12345;
1565 WebFindOptions options;
1566 WebString searchText = WebString::fromUTF8(kFindString);
1567 WebFrameImpl* mainFrame = static_cast<WebFrameImpl*>(m_webView->mainFrame());
1568 WebFrameImpl* secondFrame = static_cast<WebFrameImpl*>(mainFrame->traverseNext(false));
1569 RefPtr<WebCore::Frame> holdSecondFrame = secondFrame->frame();
1571 // Detach the frame before finding.
1572 EXPECT_TRUE(mainFrame->document().getElementById("frame").remove());
1574 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
1575 EXPECT_FALSE(secondFrame->find(kFindIdentifier, searchText, options, false, 0));
1578 EXPECT_FALSE(client.findResultsAreReady());
1580 mainFrame->resetMatchCount();
1582 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
1583 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
1586 EXPECT_TRUE(client.findResultsAreReady());
1588 holdSecondFrame.release();
1594 TEST_F(WebFrameTest, FindDetachFrameBeforeScopeStrings)
1596 registerMockedHttpURLLoad("find_in_page.html");
1597 registerMockedHttpURLLoad("find_in_page_frame.html");
1599 FindUpdateWebFrameClient client;
1600 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "find_in_page.html", true, &client);
1601 m_webView->resize(WebSize(640, 480));
1602 m_webView->layout();
1605 static const char* kFindString = "result";
1606 static const int kFindIdentifier = 12345;
1608 WebFindOptions options;
1609 WebString searchText = WebString::fromUTF8(kFindString);
1610 WebFrameImpl* mainFrame = static_cast<WebFrameImpl*>(m_webView->mainFrame());
1611 WebFrameImpl* secondFrame = static_cast<WebFrameImpl*>(mainFrame->traverseNext(false));
1612 RefPtr<WebCore::Frame> holdSecondFrame = secondFrame->frame();
1614 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
1615 EXPECT_TRUE(frame->find(kFindIdentifier, searchText, options, false, 0));
1618 EXPECT_FALSE(client.findResultsAreReady());
1620 // Detach the frame between finding and scoping.
1621 EXPECT_TRUE(mainFrame->document().getElementById("frame").remove());
1623 mainFrame->resetMatchCount();
1625 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
1626 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
1629 EXPECT_TRUE(client.findResultsAreReady());
1631 holdSecondFrame.release();
1637 TEST_F(WebFrameTest, FindDetachFrameWhileScopingStrings)
1639 registerMockedHttpURLLoad("find_in_page.html");
1640 registerMockedHttpURLLoad("find_in_page_frame.html");
1642 FindUpdateWebFrameClient client;
1643 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "find_in_page.html", true, &client);
1644 m_webView->resize(WebSize(640, 480));
1645 m_webView->layout();
1648 static const char* kFindString = "result";
1649 static const int kFindIdentifier = 12345;
1651 WebFindOptions options;
1652 WebString searchText = WebString::fromUTF8(kFindString);
1653 WebFrameImpl* mainFrame = static_cast<WebFrameImpl*>(m_webView->mainFrame());
1654 WebFrameImpl* secondFrame = static_cast<WebFrameImpl*>(mainFrame->traverseNext(false));
1655 RefPtr<WebCore::Frame> holdSecondFrame = secondFrame->frame();
1657 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
1658 EXPECT_TRUE(frame->find(kFindIdentifier, searchText, options, false, 0));
1661 EXPECT_FALSE(client.findResultsAreReady());
1663 mainFrame->resetMatchCount();
1665 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
1666 frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
1668 // The first scopeStringMatches will have reset the state. Detach before it actually scopes.
1669 EXPECT_TRUE(mainFrame->document().getElementById("frame").remove());
1672 EXPECT_TRUE(client.findResultsAreReady());
1674 holdSecondFrame.release();
1680 static WebView* createWebViewForTextSelection(const std::string& url)
1682 WebView* webView = FrameTestHelpers::createWebViewAndLoad(url, true);
1683 webView->settings()->setDefaultFontSize(12);
1684 webView->enableFixedLayoutMode(false);
1685 webView->resize(WebSize(640, 480));
1689 static WebPoint topLeft(const WebRect& rect)
1691 return WebPoint(rect.x, rect.y);
1694 static WebPoint bottomRightMinusOne(const WebRect& rect)
1696 // FIXME: If we don't subtract 1 from the x- and y-coordinates of the
1697 // selection bounds, selectRange() will select the *next* element. That's
1698 // strictly correct, as hit-testing checks the pixel to the lower-right of
1699 // the input coordinate, but it's a wart on the API.
1700 return WebPoint(rect.x + rect.width - 1, rect.y + rect.height - 1);
1703 static WebRect elementBounds(WebFrame* frame, const WebString& id)
1705 return frame->document().getElementById(id).boundsInViewportSpace();
1708 static std::string selectionAsString(WebFrame* frame)
1710 return std::string(frame->selectionAsText().utf8().data());
1713 TEST_F(WebFrameTest, SelectRange)
1716 WebRect startWebRect;
1719 registerMockedHttpURLLoad("select_range_basic.html");
1720 registerMockedHttpURLLoad("select_range_scroll.html");
1721 registerMockedHttpURLLoad("select_range_iframe.html");
1722 registerMockedHttpURLLoad("select_range_editable.html");
1724 m_webView = createWebViewForTextSelection(m_baseURL + "select_range_basic.html");
1725 frame = m_webView->mainFrame();
1726 EXPECT_EQ("Some test text for testing.", selectionAsString(frame));
1727 m_webView->selectionBounds(startWebRect, endWebRect);
1728 frame->executeCommand(WebString::fromUTF8("Unselect"));
1729 EXPECT_EQ("", selectionAsString(frame));
1730 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
1731 EXPECT_EQ("Some test text for testing.", selectionAsString(frame));
1735 m_webView = createWebViewForTextSelection(m_baseURL + "select_range_scroll.html");
1736 frame = m_webView->mainFrame();
1737 EXPECT_EQ("Some offscreen test text for testing.", selectionAsString(frame));
1738 m_webView->selectionBounds(startWebRect, endWebRect);
1739 frame->executeCommand(WebString::fromUTF8("Unselect"));
1740 EXPECT_EQ("", selectionAsString(frame));
1741 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
1742 EXPECT_EQ("Some offscreen test text for testing.", selectionAsString(frame));
1746 m_webView = createWebViewForTextSelection(m_baseURL + "select_range_iframe.html");
1747 frame = m_webView->mainFrame();
1748 WebFrame* subframe = frame->findChildByExpression(WebString::fromUTF8("/html/body/iframe"));
1749 EXPECT_EQ("Some test text for testing.", selectionAsString(subframe));
1750 m_webView->selectionBounds(startWebRect, endWebRect);
1751 subframe->executeCommand(WebString::fromUTF8("Unselect"));
1752 EXPECT_EQ("", selectionAsString(subframe));
1753 subframe->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
1754 EXPECT_EQ("Some test text for testing.", selectionAsString(subframe));
1758 // Select the middle of an editable element, then try to extend the selection to the top of the document.
1759 // The selection range should be clipped to the bounds of the editable element.
1760 m_webView = createWebViewForTextSelection(m_baseURL + "select_range_editable.html");
1761 frame = m_webView->mainFrame();
1762 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
1763 m_webView->selectionBounds(startWebRect, endWebRect);
1764 frame->selectRange(bottomRightMinusOne(endWebRect), WebPoint(0, 0));
1765 EXPECT_EQ("16-char header. This text is initially selected.", selectionAsString(frame));
1769 // As above, but extending the selection to the bottom of the document.
1770 m_webView = createWebViewForTextSelection(m_baseURL + "select_range_editable.html");
1771 frame = m_webView->mainFrame();
1772 EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
1773 m_webView->selectionBounds(startWebRect, endWebRect);
1774 frame->selectRange(topLeft(startWebRect), WebPoint(640, 480));
1775 EXPECT_EQ("This text is initially selected. 16-char footer.", selectionAsString(frame));
1780 TEST_F(WebFrameTest, SelectRangeCanMoveSelectionStart)
1782 registerMockedHttpURLLoad("text_selection.html");
1783 m_webView = createWebViewForTextSelection(m_baseURL + "text_selection.html");
1784 WebFrame* frame = m_webView->mainFrame();
1786 // Select second span. We can move the start to include the first span.
1787 frame->executeScript(WebScriptSource("selectElement('header_2');"));
1788 EXPECT_EQ("Header 2.", selectionAsString(frame));
1789 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "header_2")), topLeft(elementBounds(frame, "header_1")));
1790 EXPECT_EQ("Header 1. Header 2.", selectionAsString(frame));
1792 // We can move the start and end together.
1793 frame->executeScript(WebScriptSource("selectElement('header_1');"));
1794 EXPECT_EQ("Header 1.", selectionAsString(frame));
1795 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "header_1")));
1796 EXPECT_EQ("", selectionAsString(frame));
1797 // Selection is a caret, not empty.
1798 EXPECT_FALSE(frame->selectionRange().isNull());
1800 // We can move the start across the end.
1801 frame->executeScript(WebScriptSource("selectElement('header_1');"));
1802 EXPECT_EQ("Header 1.", selectionAsString(frame));
1803 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "header_2")));
1804 EXPECT_EQ(" Header 2.", selectionAsString(frame));
1806 // Can't extend the selection part-way into an editable element.
1807 frame->executeScript(WebScriptSource("selectElement('footer_2');"));
1808 EXPECT_EQ("Footer 2.", selectionAsString(frame));
1809 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "footer_2")), topLeft(elementBounds(frame, "editable_2")));
1810 EXPECT_EQ(" [ Footer 1. Footer 2.", selectionAsString(frame));
1812 // Can extend the selection completely across editable elements.
1813 frame->executeScript(WebScriptSource("selectElement('footer_2');"));
1814 EXPECT_EQ("Footer 2.", selectionAsString(frame));
1815 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "footer_2")), topLeft(elementBounds(frame, "header_2")));
1816 EXPECT_EQ("Header 2. ] [ Editable 1. Editable 2. ] [ Footer 1. Footer 2.", selectionAsString(frame));
1818 // If the selection is editable text, we can't extend it into non-editable text.
1819 frame->executeScript(WebScriptSource("selectElement('editable_2');"));
1820 EXPECT_EQ("Editable 2.", selectionAsString(frame));
1821 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "editable_2")), topLeft(elementBounds(frame, "header_2")));
1822 EXPECT_EQ("[ Editable 1. Editable 2.", selectionAsString(frame));
1825 TEST_F(WebFrameTest, SelectRangeCanMoveSelectionEnd)
1827 registerMockedHttpURLLoad("text_selection.html");
1828 m_webView = createWebViewForTextSelection(m_baseURL + "text_selection.html");
1829 WebFrame* frame = m_webView->mainFrame();
1831 // Select first span. We can move the end to include the second span.
1832 frame->executeScript(WebScriptSource("selectElement('header_1');"));
1833 EXPECT_EQ("Header 1.", selectionAsString(frame));
1834 frame->selectRange(topLeft(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "header_2")));
1835 EXPECT_EQ("Header 1. Header 2.", selectionAsString(frame));
1837 // We can move the start and end together.
1838 frame->executeScript(WebScriptSource("selectElement('header_2');"));
1839 EXPECT_EQ("Header 2.", selectionAsString(frame));
1840 frame->selectRange(topLeft(elementBounds(frame, "header_2")), topLeft(elementBounds(frame, "header_2")));
1841 EXPECT_EQ("", selectionAsString(frame));
1842 // Selection is a caret, not empty.
1843 EXPECT_FALSE(frame->selectionRange().isNull());
1845 // We can move the end across the start.
1846 frame->executeScript(WebScriptSource("selectElement('header_2');"));
1847 EXPECT_EQ("Header 2.", selectionAsString(frame));
1848 frame->selectRange(topLeft(elementBounds(frame, "header_2")), topLeft(elementBounds(frame, "header_1")));
1849 EXPECT_EQ("Header 1. ", selectionAsString(frame));
1851 // Can't extend the selection part-way into an editable element.
1852 frame->executeScript(WebScriptSource("selectElement('header_1');"));
1853 EXPECT_EQ("Header 1.", selectionAsString(frame));
1854 frame->selectRange(topLeft(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "editable_1")));
1855 EXPECT_EQ("Header 1. Header 2. ] ", selectionAsString(frame));
1857 // Can extend the selection completely across editable elements.
1858 frame->executeScript(WebScriptSource("selectElement('header_1');"));
1859 EXPECT_EQ("Header 1.", selectionAsString(frame));
1860 frame->selectRange(topLeft(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "footer_1")));
1861 EXPECT_EQ("Header 1. Header 2. ] [ Editable 1. Editable 2. ] [ Footer 1.", selectionAsString(frame));
1863 // If the selection is editable text, we can't extend it into non-editable text.
1864 frame->executeScript(WebScriptSource("selectElement('editable_1');"));
1865 EXPECT_EQ("Editable 1.", selectionAsString(frame));
1866 frame->selectRange(topLeft(elementBounds(frame, "editable_1")), bottomRightMinusOne(elementBounds(frame, "footer_1")));
1867 EXPECT_EQ("Editable 1. Editable 2. ]", selectionAsString(frame));
1871 TEST_F(WebFrameTest, MoveCaretStaysHorizontallyAlignedWhenMoved)
1873 WebFrameImpl* frame;
1874 registerMockedHttpURLLoad("move_caret.html");
1876 m_webView = createWebViewForTextSelection(m_baseURL + "move_caret.html");
1877 frame = (WebFrameImpl*)m_webView->mainFrame();
1879 WebRect initialStartRect;
1880 WebRect initialEndRect;
1884 frame->executeScript(WebScriptSource("select();"));
1885 m_webView->selectionBounds(initialStartRect, initialEndRect);
1886 WebPoint moveTo(topLeft(initialStartRect));
1889 frame->moveCaretSelectionTowardsWindowPoint(moveTo);
1890 m_webView->selectionBounds(startRect, endRect);
1891 EXPECT_EQ(startRect, initialStartRect);
1892 EXPECT_EQ(endRect, initialEndRect);
1895 frame->moveCaretSelectionTowardsWindowPoint(moveTo);
1896 m_webView->selectionBounds(startRect, endRect);
1897 EXPECT_EQ(startRect, initialStartRect);
1898 EXPECT_EQ(endRect, initialEndRect);
1902 class DisambiguationPopupTestWebViewClient : public WebViewClient {
1904 virtual bool didTapMultipleTargets(const WebGestureEvent&, const WebVector<WebRect>& targetRects) OVERRIDE
1906 EXPECT_GE(targetRects.size(), 2u);
1911 bool triggered() const { return m_triggered; }
1912 void resetTriggered() { m_triggered = false; }
1916 static WebGestureEvent fatTap(int x, int y)
1918 WebGestureEvent event;
1919 event.type = WebInputEvent::GestureTap;
1922 event.data.tap.width = 50;
1923 event.data.tap.height = 50;
1927 TEST_F(WebFrameTest, DisambiguationPopup)
1929 const std::string htmlFile = "disambiguation_popup.html";
1930 registerMockedHttpURLLoad(htmlFile);
1932 DisambiguationPopupTestWebViewClient client;
1934 // Make sure we initialize to minimum scale, even if the window size
1935 // only becomes available after the load begins.
1936 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + htmlFile, true, 0, &client);
1937 m_webView->settings()->setApplyDeviceScaleFactorInCompositor(true);
1938 m_webView->settings()->setApplyPageScaleFactorInCompositor(true);
1939 m_webView->resize(WebSize(1000, 1000));
1940 m_webView->layout();
1942 client.resetTriggered();
1943 m_webView->handleInputEvent(fatTap(0, 0));
1944 EXPECT_FALSE(client.triggered());
1946 client.resetTriggered();
1947 m_webView->handleInputEvent(fatTap(200, 115));
1948 EXPECT_FALSE(client.triggered());
1950 for (int i = 0; i <= 46; i++) {
1951 client.resetTriggered();
1952 m_webView->handleInputEvent(fatTap(120, 230 + i * 5));
1955 if (j >= 7 && j <= 9)
1956 EXPECT_TRUE(client.triggered());
1958 EXPECT_FALSE(client.triggered());
1961 for (int i = 0; i <= 46; i++) {
1962 client.resetTriggered();
1963 m_webView->handleInputEvent(fatTap(10 + i * 5, 590));
1966 if (j >= 7 && j <= 9)
1967 EXPECT_TRUE(client.triggered());
1969 EXPECT_FALSE(client.triggered());
1977 TEST_F(WebFrameTest, DisambiguationPopupNoContainer)
1979 registerMockedHttpURLLoad("disambiguation_popup_no_container.html");
1981 DisambiguationPopupTestWebViewClient client;
1983 // Make sure we initialize to minimum scale, even if the window size
1984 // only becomes available after the load begins.
1985 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "disambiguation_popup_no_container.html", true, 0, &client);
1986 m_webView->settings()->setApplyDeviceScaleFactorInCompositor(true);
1987 m_webView->settings()->setApplyPageScaleFactorInCompositor(true);
1988 m_webView->resize(WebSize(1000, 1000));
1989 m_webView->layout();
1991 client.resetTriggered();
1992 m_webView->handleInputEvent(fatTap(50, 50));
1993 EXPECT_FALSE(client.triggered());
1999 TEST_F(WebFrameTest, DisambiguationPopupMobileSite)
2001 const std::string htmlFile = "disambiguation_popup_mobile_site.html";
2002 registerMockedHttpURLLoad(htmlFile);
2004 DisambiguationPopupTestWebViewClient client;
2006 // Make sure we initialize to minimum scale, even if the window size
2007 // only becomes available after the load begins.
2008 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + htmlFile, true, 0, &client);
2009 m_webView->settings()->setApplyDeviceScaleFactorInCompositor(true);
2010 m_webView->settings()->setApplyPageScaleFactorInCompositor(true);
2011 m_webView->resize(WebSize(1000, 1000));
2012 m_webView->layout();
2014 client.resetTriggered();
2015 m_webView->handleInputEvent(fatTap(0, 0));
2016 EXPECT_FALSE(client.triggered());
2018 client.resetTriggered();
2019 m_webView->handleInputEvent(fatTap(200, 115));
2020 EXPECT_FALSE(client.triggered());
2022 for (int i = 0; i <= 46; i++) {
2023 client.resetTriggered();
2024 m_webView->handleInputEvent(fatTap(120, 230 + i * 5));
2025 EXPECT_FALSE(client.triggered());
2028 for (int i = 0; i <= 46; i++) {
2029 client.resetTriggered();
2030 m_webView->handleInputEvent(fatTap(10 + i * 5, 590));
2031 EXPECT_FALSE(client.triggered());
2038 TEST_F(WebFrameTest, DisambiguationPopupBlacklist)
2040 const unsigned viewportWidth = 500;
2041 const unsigned viewportHeight = 1000;
2042 const unsigned divHeight = 100;
2043 const std::string htmlFile = "disambiguation_popup_blacklist.html";
2044 registerMockedHttpURLLoad(htmlFile);
2046 DisambiguationPopupTestWebViewClient client;
2048 // Make sure we initialize to minimum scale, even if the window size
2049 // only becomes available after the load begins.
2050 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + htmlFile, true, 0, &client);
2051 m_webView->settings()->setApplyDeviceScaleFactorInCompositor(true);
2052 m_webView->settings()->setApplyPageScaleFactorInCompositor(true);
2053 m_webView->resize(WebSize(viewportWidth, viewportHeight));
2054 m_webView->layout();
2056 // Click somewhere where the popup shouldn't appear.
2057 client.resetTriggered();
2058 m_webView->handleInputEvent(fatTap(viewportWidth / 2, 0));
2059 EXPECT_FALSE(client.triggered());
2061 // Click directly in between two container divs with click handlers, with children that don't handle clicks.
2062 client.resetTriggered();
2063 m_webView->handleInputEvent(fatTap(viewportWidth / 2, divHeight));
2064 EXPECT_TRUE(client.triggered());
2066 // The third div container should be blacklisted if you click on the link it contains.
2067 client.resetTriggered();
2068 m_webView->handleInputEvent(fatTap(viewportWidth / 2, divHeight * 3.25));
2069 EXPECT_FALSE(client.triggered());
2075 TEST_F(WebFrameTest, DisambiguationPopupPageScale)
2077 registerMockedHttpURLLoad("disambiguation_popup_page_scale.html");
2079 DisambiguationPopupTestWebViewClient client;
2081 // Make sure we initialize to minimum scale, even if the window size
2082 // only becomes available after the load begins.
2083 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "disambiguation_popup_page_scale.html", true, 0, &client);
2084 m_webView->settings()->setApplyDeviceScaleFactorInCompositor(true);
2085 m_webView->settings()->setApplyPageScaleFactorInCompositor(true);
2086 m_webView->resize(WebSize(1000, 1000));
2087 m_webView->layout();
2089 client.resetTriggered();
2090 m_webView->handleInputEvent(fatTap(80, 80));
2091 EXPECT_TRUE(client.triggered());
2093 client.resetTriggered();
2094 m_webView->handleInputEvent(fatTap(230, 190));
2095 EXPECT_TRUE(client.triggered());
2097 m_webView->setPageScaleFactor(3.0f, WebPoint(0, 0));
2098 m_webView->layout();
2100 client.resetTriggered();
2101 m_webView->handleInputEvent(fatTap(240, 240));
2102 EXPECT_TRUE(client.triggered());
2104 client.resetTriggered();
2105 m_webView->handleInputEvent(fatTap(690, 570));
2106 EXPECT_FALSE(client.triggered());
2112 class TestSubstituteDataWebFrameClient : public WebFrameClient {
2114 TestSubstituteDataWebFrameClient()
2115 : m_commitCalled(false)
2119 virtual void didFailProvisionalLoad(WebFrame* frame, const WebURLError& error)
2121 frame->loadHTMLString("This should appear", toKURL("data:text/html,chromewebdata"), error.unreachableURL, true);
2125 virtual void didCommitProvisionalLoad(WebFrame* frame, bool)
2127 if (frame->dataSource()->response().url() != WebURL(URLTestHelpers::toKURL("about:blank")))
2128 m_commitCalled = true;
2131 bool commitCalled() const { return m_commitCalled; }
2134 bool m_commitCalled;
2137 TEST_F(WebFrameTest, ReplaceNavigationAfterHistoryNavigation)
2139 TestSubstituteDataWebFrameClient webFrameClient;
2141 m_webView = FrameTestHelpers::createWebViewAndLoad("about:blank", true, &webFrameClient);
2143 WebFrame* frame = m_webView->mainFrame();
2145 // Load a url as a history navigation that will return an error. TestSubstituteDataWebFrameClient
2146 // will start a SubstituteData load in response to the load failure, which should get fully committed.
2147 // Due to https://bugs.webkit.org/show_bug.cgi?id=91685, FrameLoader::didReceiveData() wasn't getting
2148 // called in this case, which resulted in the SubstituteData document not getting displayed.
2150 error.reason = 1337;
2151 error.domain = "WebFrameTest";
2152 std::string errorURL = "http://0.0.0.0";
2153 WebURLResponse response;
2154 response.initialize();
2155 response.setURL(URLTestHelpers::toKURL(errorURL));
2156 response.setMIMEType("text/html");
2157 response.setHTTPStatusCode(500);
2158 WebHistoryItem errorHistoryItem;
2159 errorHistoryItem.initialize();
2160 errorHistoryItem.setURLString(WebString::fromUTF8(errorURL.c_str(), errorURL.length()));
2161 errorHistoryItem.setOriginalURLString(WebString::fromUTF8(errorURL.c_str(), errorURL.length()));
2162 Platform::current()->unitTestSupport()->registerMockedErrorURL(URLTestHelpers::toKURL(errorURL), response, error);
2163 frame->loadHistoryItem(errorHistoryItem);
2164 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
2166 WebString text = frame->contentAsText(std::numeric_limits<size_t>::max());
2167 EXPECT_EQ("This should appear", std::string(text.utf8().data()));
2168 EXPECT_TRUE(webFrameClient.commitCalled());
2174 class TestWillInsertBodyWebFrameClient : public WebFrameClient {
2176 TestWillInsertBodyWebFrameClient() : m_numBodies(0), m_didLoad(false)
2180 virtual void didCommitProvisionalLoad(WebFrame*, bool) OVERRIDE
2186 virtual void didCreateDocumentElement(WebFrame*) OVERRIDE
2188 EXPECT_EQ(0, m_numBodies);
2191 virtual void willInsertBody(WebFrame*) OVERRIDE
2200 TEST_F(WebFrameTest, HTMLDocument)
2202 registerMockedHttpURLLoad("clipped-body.html");
2204 TestWillInsertBodyWebFrameClient webFrameClient;
2205 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "clipped-body.html", false, &webFrameClient);
2207 EXPECT_TRUE(webFrameClient.m_didLoad);
2208 EXPECT_EQ(1, webFrameClient.m_numBodies);
2214 TEST_F(WebFrameTest, EmptyDocument)
2216 registerMockedHttpURLLoad("pageserializer/green_rectangle.svg");
2218 TestWillInsertBodyWebFrameClient webFrameClient;
2219 m_webView = FrameTestHelpers::createWebView(false, &webFrameClient);
2221 EXPECT_FALSE(webFrameClient.m_didLoad);
2222 EXPECT_EQ(1, webFrameClient.m_numBodies); // The empty document that a new frame starts with triggers this.
2227 TEST_F(WebFrameTest, MoveCaretSelectionTowardsWindowPointWithNoSelection)
2229 m_webView = FrameTestHelpers::createWebViewAndLoad("about:blank", true);
2230 WebFrame* frame = m_webView->mainFrame();
2232 // This test passes if this doesn't crash.
2233 frame->moveCaretSelectionTowardsWindowPoint(WebPoint(0, 0));