Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / web / tests / WebViewTest.cpp
blob0a2d6b27648d487a52cf8a0e7a78fadce4e44bc1
1 /*
2 * Copyright (C) 2011, 2012 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
6 * met:
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
13 * distribution.
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.
31 #include "config.h"
32 #include "public/web/WebView.h"
34 #include "bindings/core/v8/V8Document.h"
35 #include "core/dom/Document.h"
36 #include "core/dom/Element.h"
37 #include "core/editing/FrameSelection.h"
38 #include "core/editing/markers/DocumentMarkerController.h"
39 #include "core/frame/EventHandlerRegistry.h"
40 #include "core/frame/FrameHost.h"
41 #include "core/frame/FrameView.h"
42 #include "core/frame/LocalFrame.h"
43 #include "core/frame/Settings.h"
44 #include "core/frame/VisualViewport.h"
45 #include "core/html/HTMLDocument.h"
46 #include "core/html/HTMLIFrameElement.h"
47 #include "core/html/HTMLInputElement.h"
48 #include "core/html/HTMLTextAreaElement.h"
49 #include "core/layout/LayoutView.h"
50 #include "core/loader/DocumentLoader.h"
51 #include "core/loader/FrameLoadRequest.h"
52 #include "core/page/Page.h"
53 #include "core/paint/DeprecatedPaintLayer.h"
54 #include "core/paint/DeprecatedPaintLayerPainter.h"
55 #include "core/timing/DOMWindowPerformance.h"
56 #include "core/timing/Performance.h"
57 #include "core/timing/PerformanceCompositeTiming.h"
58 #include "platform/KeyboardCodes.h"
59 #include "platform/UserGestureIndicator.h"
60 #include "platform/geometry/IntSize.h"
61 #include "platform/graphics/Color.h"
62 #include "platform/graphics/GraphicsContext.h"
63 #include "platform/graphics/paint/SkPictureBuilder.h"
64 #include "platform/testing/URLTestHelpers.h"
65 #include "platform/testing/UnitTestHelpers.h"
66 #include "public/platform/Platform.h"
67 #include "public/platform/WebClipboard.h"
68 #include "public/platform/WebDisplayMode.h"
69 #include "public/platform/WebDragData.h"
70 #include "public/platform/WebSize.h"
71 #include "public/platform/WebThread.h"
72 #include "public/platform/WebUnitTestSupport.h"
73 #include "public/web/WebAutofillClient.h"
74 #include "public/web/WebContentDetectionResult.h"
75 #include "public/web/WebDateTimeChooserCompletion.h"
76 #include "public/web/WebDeviceEmulationParams.h"
77 #include "public/web/WebDocument.h"
78 #include "public/web/WebDragOperation.h"
79 #include "public/web/WebElement.h"
80 #include "public/web/WebFrame.h"
81 #include "public/web/WebFrameClient.h"
82 #include "public/web/WebHitTestResult.h"
83 #include "public/web/WebInputEvent.h"
84 #include "public/web/WebScriptSource.h"
85 #include "public/web/WebSettings.h"
86 #include "public/web/WebTreeScopeType.h"
87 #include "public/web/WebViewClient.h"
88 #include "public/web/WebWidget.h"
89 #include "public/web/WebWidgetClient.h"
90 #include "third_party/skia/include/core/SkBitmap.h"
91 #include "third_party/skia/include/core/SkBitmapDevice.h"
92 #include "third_party/skia/include/core/SkCanvas.h"
93 #include "web/WebLocalFrameImpl.h"
94 #include "web/WebSettingsImpl.h"
95 #include "web/WebViewImpl.h"
96 #include "web/tests/FrameTestHelpers.h"
97 #include <gtest/gtest.h>
99 using blink::FrameTestHelpers::loadFrame;
100 using blink::URLTestHelpers::toKURL;
101 using blink::URLTestHelpers::registerMockedURLLoad;
102 using blink::testing::runPendingTasks;
104 namespace blink {
106 enum HorizontalScrollbarState {
107 NoHorizontalScrollbar,
108 VisibleHorizontalScrollbar,
111 enum VerticalScrollbarState {
112 NoVerticalScrollbar,
113 VisibleVerticalScrollbar,
116 class TestData {
117 public:
118 void setWebView(WebView* webView) { m_webView = toWebViewImpl(webView); }
119 void setSize(const WebSize& newSize) { m_size = newSize; }
120 HorizontalScrollbarState horizontalScrollbarState() const
122 return m_webView->hasHorizontalScrollbar() ? VisibleHorizontalScrollbar: NoHorizontalScrollbar;
124 VerticalScrollbarState verticalScrollbarState() const
126 return m_webView->hasVerticalScrollbar() ? VisibleVerticalScrollbar : NoVerticalScrollbar;
128 int width() const { return m_size.width; }
129 int height() const { return m_size.height; }
131 private:
132 WebSize m_size;
133 WebViewImpl* m_webView;
136 class AutoResizeWebViewClient : public FrameTestHelpers::TestWebViewClient {
137 public:
138 // WebViewClient methods
139 void didAutoResize(const WebSize& newSize) override { m_testData.setSize(newSize); }
141 // Local methods
142 TestData& testData() { return m_testData; }
144 private:
145 TestData m_testData;
148 class SaveImageFromDataURLWebViewClient : public FrameTestHelpers::TestWebViewClient {
149 public:
150 // WebViewClient methods
151 void saveImageFromDataURL(const WebString& dataURL) override { m_dataURL = dataURL; }
153 // Local methods
154 const WebString& result() const { return m_dataURL; }
155 void reset() { m_dataURL = WebString(); }
157 private:
158 WebString m_dataURL;
161 class TapHandlingWebViewClient : public FrameTestHelpers::TestWebViewClient {
162 public:
163 // WebViewClient methods
164 void didHandleGestureEvent(const WebGestureEvent& event, bool eventCancelled) override
166 if (event.type == WebInputEvent::GestureTap) {
167 m_tapX = event.x;
168 m_tapY = event.y;
169 } else if (event.type == WebInputEvent::GestureLongPress) {
170 m_longpressX = event.x;
171 m_longpressY = event.y;
175 // Local methods
176 void reset()
178 m_tapX = -1;
179 m_tapY = -1;
180 m_longpressX = -1;
181 m_longpressY = -1;
183 int tapX() { return m_tapX; }
184 int tapY() { return m_tapY; }
185 int longpressX() { return m_longpressX; }
186 int longpressY() { return m_longpressY; }
188 private:
189 int m_tapX;
190 int m_tapY;
191 int m_longpressX;
192 int m_longpressY;
195 class DateTimeChooserWebViewClient : public FrameTestHelpers::TestWebViewClient {
196 public:
197 WebDateTimeChooserCompletion* chooserCompletion()
199 return m_chooserCompletion;
202 void clearChooserCompletion()
204 m_chooserCompletion = 0;
207 // WebViewClient methods
208 bool openDateTimeChooser(const WebDateTimeChooserParams&, WebDateTimeChooserCompletion* chooser_completion) override
210 m_chooserCompletion = chooser_completion;
211 return true;
214 private:
215 WebDateTimeChooserCompletion* m_chooserCompletion;
219 class WebViewTest : public ::testing::Test {
220 public:
221 WebViewTest()
222 : m_baseURL("http://www.test.com/")
226 void TearDown() override
228 Platform::current()->unitTestSupport()->unregisterAllMockedURLs();
231 protected:
232 void registerMockedHttpURLLoad(const std::string& fileName)
234 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8(fileName.c_str()));
237 void testAutoResize(const WebSize& minAutoResize, const WebSize& maxAutoResize,
238 const std::string& pageWidth, const std::string& pageHeight,
239 int expectedWidth, int expectedHeight,
240 HorizontalScrollbarState expectedHorizontalState, VerticalScrollbarState expectedVerticalState);
242 void testTextInputType(WebTextInputType expectedType, const std::string& htmlFile);
243 void testInputMode(const WebString& expectedInputMode, const std::string& htmlFile);
245 std::string m_baseURL;
246 FrameTestHelpers::WebViewHelper m_webViewHelper;
249 TEST_F(WebViewTest, SaveImageAt)
251 SaveImageFromDataURLWebViewClient client;
253 std::string url = m_baseURL + "image-with-data-url.html";
254 URLTestHelpers::registerMockedURLLoad(toKURL(url), "image-with-data-url.html");
255 WebViewImpl* webView = m_webViewHelper.initializeAndLoad(url, true, 0, &client);
256 webView->resize(WebSize(400, 400));
257 webView->layout();
259 client.reset();
260 webView->saveImageAt(WebPoint(1, 1));
261 EXPECT_EQ(WebString::fromUTF8("data:image/gif;base64"
262 ",R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="), client.result());
264 client.reset();
265 webView->saveImageAt(WebPoint(1, 2));
266 EXPECT_EQ(WebString(), client.result());
268 webView->setPageScaleFactor(4);
269 webView->setVisualViewportOffset(WebFloatPoint(1, 1));
271 client.reset();
272 webView->saveImageAt(WebPoint(3, 3));
273 EXPECT_EQ(WebString::fromUTF8("data:image/gif;base64"
274 ",R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="), client.result());
276 m_webViewHelper.reset(); // Explicitly reset to break dependency on locally scoped client.
279 TEST_F(WebViewTest, SaveImageWithImageMap)
281 SaveImageFromDataURLWebViewClient client;
283 std::string url = m_baseURL + "image-map.html";
284 URLTestHelpers::registerMockedURLLoad(toKURL(url), "image-map.html");
285 WebView* webView = m_webViewHelper.initializeAndLoad(url, true, 0, &client);
286 webView->resize(WebSize(400, 400));
288 client.reset();
289 webView->saveImageAt(WebPoint(25, 25));
290 EXPECT_EQ(WebString::fromUTF8("data:image/gif;base64"
291 ",R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="), client.result());
293 client.reset();
294 webView->saveImageAt(WebPoint(75, 25));
295 EXPECT_EQ(WebString::fromUTF8("data:image/gif;base64"
296 ",R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="), client.result());
298 client.reset();
299 webView->saveImageAt(WebPoint(125, 25));
300 EXPECT_EQ(WebString(), client.result());
302 m_webViewHelper.reset(); // Explicitly reset to break dependency on locally scoped client.
305 TEST_F(WebViewTest, CopyImageAt)
307 std::string url = m_baseURL + "canvas-copy-image.html";
308 URLTestHelpers::registerMockedURLLoad(toKURL(url), "canvas-copy-image.html");
309 WebView* webView = m_webViewHelper.initializeAndLoad(url, true, 0);
310 webView->resize(WebSize(400, 400));
312 uint64_t sequence = Platform::current()->clipboard()->sequenceNumber(WebClipboard::BufferStandard);
314 webView->copyImageAt(WebPoint(50, 50));
316 EXPECT_NE(sequence, Platform::current()->clipboard()->sequenceNumber(WebClipboard::BufferStandard));
318 WebData data = Platform::current()->clipboard()->readImage(WebClipboard::Buffer());
319 WebImage image = WebImage::fromData(data, WebSize());
321 SkAutoLockPixels autoLock(image.getSkBitmap());
322 EXPECT_EQ(SkColorSetARGB(255, 255, 0, 0), image.getSkBitmap().getColor(0, 0));
325 TEST_F(WebViewTest, CopyImageAtWithPinchZoom)
327 std::string url = m_baseURL + "canvas-copy-image.html";
328 URLTestHelpers::registerMockedURLLoad(toKURL(url), "canvas-copy-image.html");
329 WebViewImpl* webView = m_webViewHelper.initializeAndLoad(url, true, 0);
330 webView->resize(WebSize(400, 400));
331 webView->layout();
332 webView->setPageScaleFactor(2);
333 webView->setVisualViewportOffset(WebFloatPoint(200, 200));
335 uint64_t sequence = Platform::current()->clipboard()->sequenceNumber(WebClipboard::BufferStandard);
337 webView->copyImageAt(WebPoint(0, 0));
339 EXPECT_NE(sequence, Platform::current()->clipboard()->sequenceNumber(WebClipboard::BufferStandard));
341 WebData data = Platform::current()->clipboard()->readImage(WebClipboard::Buffer());
342 WebImage image = WebImage::fromData(data, WebSize());
344 SkAutoLockPixels autoLock(image.getSkBitmap());
345 EXPECT_EQ(SkColorSetARGB(255, 255, 0, 0), image.getSkBitmap().getColor(0, 0));
348 TEST_F(WebViewTest, CopyImageWithImageMap)
350 SaveImageFromDataURLWebViewClient client;
352 std::string url = m_baseURL + "image-map.html";
353 URLTestHelpers::registerMockedURLLoad(toKURL(url), "image-map.html");
354 WebView* webView = m_webViewHelper.initializeAndLoad(url, true, 0, &client);
355 webView->resize(WebSize(400, 400));
357 client.reset();
358 webView->saveImageAt(WebPoint(25, 25));
359 EXPECT_EQ(WebString::fromUTF8("data:image/gif;base64"
360 ",R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="), client.result());
362 client.reset();
363 webView->saveImageAt(WebPoint(75, 25));
364 EXPECT_EQ(WebString::fromUTF8("data:image/gif;base64"
365 ",R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="), client.result());
367 client.reset();
368 webView->saveImageAt(WebPoint(125, 25));
369 EXPECT_EQ(WebString(), client.result());
371 m_webViewHelper.reset(); // Explicitly reset to break dependency on locally scoped client.
374 static bool hitTestIsContentEditable(WebView* view, int x, int y)
376 WebPoint hitPoint(x, y);
377 WebHitTestResult hitTestResult = view->hitTestResultAt(hitPoint);
378 return hitTestResult.isContentEditable();
381 static std::string hitTestElementId(WebView* view, int x, int y)
383 WebPoint hitPoint(x, y);
384 WebHitTestResult hitTestResult = view->hitTestResultAt(hitPoint);
385 return hitTestResult.node().to<WebElement>().getAttribute("id").utf8();
388 TEST_F(WebViewTest, HitTestContentEditableImageMaps)
390 std::string url = m_baseURL + "content-editable-image-maps.html";
391 URLTestHelpers::registerMockedURLLoad(toKURL(url), "content-editable-image-maps.html");
392 WebView* webView = m_webViewHelper.initializeAndLoad(url, true, 0);
393 webView->resize(WebSize(500, 500));
395 EXPECT_EQ("areaANotEditable", hitTestElementId(webView, 25, 25));
396 EXPECT_FALSE(hitTestIsContentEditable(webView, 25, 25));
397 EXPECT_EQ("imageANotEditable", hitTestElementId(webView, 75, 25));
398 EXPECT_FALSE(hitTestIsContentEditable(webView, 75, 25));
400 EXPECT_EQ("areaBNotEditable", hitTestElementId(webView, 25, 125));
401 EXPECT_FALSE(hitTestIsContentEditable(webView, 25, 125));
402 EXPECT_EQ("imageBEditable", hitTestElementId(webView, 75, 125));
403 EXPECT_TRUE(hitTestIsContentEditable(webView, 75, 125));
405 EXPECT_EQ("areaCNotEditable", hitTestElementId(webView, 25, 225));
406 EXPECT_FALSE(hitTestIsContentEditable(webView, 25, 225));
407 EXPECT_EQ("imageCNotEditable", hitTestElementId(webView, 75, 225));
408 EXPECT_FALSE(hitTestIsContentEditable(webView, 75, 225));
410 EXPECT_EQ("areaDEditable", hitTestElementId(webView, 25, 325));
411 EXPECT_TRUE(hitTestIsContentEditable(webView, 25, 325));
412 EXPECT_EQ("imageDNotEditable", hitTestElementId(webView, 75, 325));
413 EXPECT_FALSE(hitTestIsContentEditable(webView, 75, 325));
416 static std::string hitTestAbsoluteUrl(WebView* view, int x, int y)
418 WebPoint hitPoint(x, y);
419 WebHitTestResult hitTestResult = view->hitTestResultAt(hitPoint);
420 return hitTestResult.absoluteImageURL().string().utf8();
423 static WebElement hitTestUrlElement(WebView* view, int x, int y)
425 WebPoint hitPoint(x, y);
426 WebHitTestResult hitTestResult = view->hitTestResultAt(hitPoint);
427 return hitTestResult.urlElement();
430 TEST_F(WebViewTest, ImageMapUrls)
432 std::string url = m_baseURL + "image-map.html";
433 URLTestHelpers::registerMockedURLLoad(toKURL(url), "image-map.html");
434 WebView* webView = m_webViewHelper.initializeAndLoad(url, true, 0);
435 webView->resize(WebSize(400, 400));
437 std::string imageUrl = "data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=";
439 EXPECT_EQ("area", hitTestElementId(webView, 25, 25));
440 EXPECT_EQ("area", hitTestUrlElement(webView, 25, 25).getAttribute("id").utf8());
441 EXPECT_EQ(imageUrl, hitTestAbsoluteUrl(webView, 25, 25));
443 EXPECT_EQ("image", hitTestElementId(webView, 75, 25));
444 EXPECT_TRUE(hitTestUrlElement(webView, 75, 25).isNull());
445 EXPECT_EQ(imageUrl, hitTestAbsoluteUrl(webView, 75, 25));
448 TEST_F(WebViewTest, SetBaseBackgroundColor)
450 const WebColor kWhite = 0xFFFFFFFF;
451 const WebColor kBlue = 0xFF0000FF;
452 const WebColor kDarkCyan = 0xFF227788;
453 const WebColor kTranslucentPutty = 0x80BFB196;
454 const WebColor kTransparent = 0x00000000;
456 WebViewImpl* webView = m_webViewHelper.initialize();
457 EXPECT_EQ(kWhite, webView->backgroundColor());
459 webView->setBaseBackgroundColor(kBlue);
460 EXPECT_EQ(kBlue, webView->backgroundColor());
462 WebURL baseURL = URLTestHelpers::toKURL("http://example.com/");
463 FrameTestHelpers::loadHTMLString(webView->mainFrame(), "<html><head><style>body {background-color:#227788}</style></head></html>", baseURL);
464 EXPECT_EQ(kDarkCyan, webView->backgroundColor());
466 FrameTestHelpers::loadHTMLString(webView->mainFrame(), "<html><head><style>body {background-color:rgba(255,0,0,0.5)}</style></head></html>", baseURL);
467 // Expected: red (50% alpha) blended atop base of kBlue.
468 EXPECT_EQ(0xFF7F0080, webView->backgroundColor());
470 webView->setBaseBackgroundColor(kTranslucentPutty);
471 // Expected: red (50% alpha) blended atop kTranslucentPutty. Note the alpha.
472 EXPECT_EQ(0xBFE93B32, webView->backgroundColor());
474 webView->setBaseBackgroundColor(kTransparent);
475 FrameTestHelpers::loadHTMLString(webView->mainFrame(), "<html><head><style>body {background-color:transparent}</style></head></html>", baseURL);
476 // Expected: transparent on top of kTransparent will still be transparent.
477 EXPECT_EQ(kTransparent, webView->backgroundColor());
479 LocalFrame* frame = webView->mainFrameImpl()->frame();
480 // The detach() and dispose() calls are a hack to prevent this test
481 // from violating invariants about frame state during navigation/detach.
482 frame->document()->detach();
484 // Creating a new frame view with the background color having 0 alpha.
485 frame->createView(IntSize(1024, 768), Color::transparent, true);
486 EXPECT_EQ(kTransparent, frame->view()->baseBackgroundColor());
487 frame->view()->dispose();
489 Color kTransparentRed(100, 0, 0, 0);
490 frame->createView(IntSize(1024, 768), kTransparentRed, true);
491 EXPECT_EQ(kTransparentRed, frame->view()->baseBackgroundColor());
492 frame->view()->dispose();
495 TEST_F(WebViewTest, SetBaseBackgroundColorBeforeMainFrame)
497 const WebColor kBlue = 0xFF0000FF;
498 FrameTestHelpers::TestWebViewClient webViewClient;
499 WebView* webView = WebViewImpl::create(&webViewClient);
500 EXPECT_NE(kBlue, webView->backgroundColor());
501 // webView does not have a frame yet, but we should still be able to set the background color.
502 webView->setBaseBackgroundColor(kBlue);
503 EXPECT_EQ(kBlue, webView->backgroundColor());
504 WebLocalFrameImpl* frame = WebLocalFrameImpl::create(WebTreeScopeType::Document, nullptr);
505 webView->setMainFrame(frame);
506 webView->close();
507 frame->close();
510 TEST_F(WebViewTest, SetBaseBackgroundColorAndBlendWithExistingContent)
512 const WebColor kAlphaRed = 0x80FF0000;
513 const WebColor kAlphaGreen = 0x8000FF00;
514 const int kWidth = 100;
515 const int kHeight = 100;
517 WebView* webView = m_webViewHelper.initialize();
519 // Set WebView background to green with alpha.
520 webView->setBaseBackgroundColor(kAlphaGreen);
521 webView->settings()->setShouldClearDocumentBackground(false);
522 webView->resize(WebSize(kWidth, kHeight));
523 webView->layout();
525 // Set canvas background to red with alpha.
526 SkBitmap bitmap;
527 bitmap.allocN32Pixels(kWidth, kHeight);
528 SkCanvas canvas(bitmap);
529 canvas.clear(kAlphaRed);
531 SkPictureBuilder pictureBuilder(FloatRect(0, 0, kWidth, kHeight));
533 // Paint the root of the main frame in the way that CompositedLayerMapping would.
534 FrameView* view = m_webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
535 DeprecatedPaintLayer* rootLayer = view->layoutView()->layer();
536 LayoutRect paintRect(0, 0, kWidth, kHeight);
537 DeprecatedPaintLayerPaintingInfo paintingInfo(rootLayer, paintRect, GlobalPaintNormalPhase, LayoutSize());
538 DeprecatedPaintLayerPainter(*rootLayer).paintLayerContents(&pictureBuilder.context(), paintingInfo, PaintLayerPaintingCompositingAllPhases);
540 pictureBuilder.endRecording()->playback(&canvas);
542 // The result should be a blend of red and green.
543 SkColor color = bitmap.getColor(kWidth / 2, kHeight / 2);
544 EXPECT_TRUE(redChannel(color));
545 EXPECT_TRUE(greenChannel(color));
548 TEST_F(WebViewTest, FocusIsInactive)
550 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), "visible_iframe.html");
551 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "visible_iframe.html");
553 webView->setFocus(true);
554 webView->setIsActive(true);
555 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
556 EXPECT_TRUE(frame->frame()->document()->isHTMLDocument());
558 HTMLDocument* document = toHTMLDocument(frame->frame()->document());
559 EXPECT_TRUE(document->hasFocus());
560 webView->setFocus(false);
561 webView->setIsActive(false);
562 EXPECT_FALSE(document->hasFocus());
563 webView->setFocus(true);
564 webView->setIsActive(true);
565 EXPECT_TRUE(document->hasFocus());
566 webView->setFocus(true);
567 webView->setIsActive(false);
568 EXPECT_FALSE(document->hasFocus());
569 webView->setFocus(false);
570 webView->setIsActive(true);
571 EXPECT_FALSE(document->hasFocus());
574 TEST_F(WebViewTest, ActiveState)
576 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), "visible_iframe.html");
577 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "visible_iframe.html");
579 ASSERT_TRUE(webView);
581 webView->setIsActive(true);
582 EXPECT_TRUE(webView->isActive());
584 webView->setIsActive(false);
585 EXPECT_FALSE(webView->isActive());
587 webView->setIsActive(true);
588 EXPECT_TRUE(webView->isActive());
591 TEST_F(WebViewTest, HitTestResultAtWithPageScale)
593 std::string url = m_baseURL + "specify_size.html?" + "50px" + ":" + "50px";
594 URLTestHelpers::registerMockedURLLoad(toKURL(url), "specify_size.html");
595 WebView* webView = m_webViewHelper.initializeAndLoad(url, true, 0);
596 webView->resize(WebSize(100, 100));
597 WebPoint hitPoint(75, 75);
599 // Image is at top left quandrant, so should not hit it.
600 WebHitTestResult negativeResult = webView->hitTestResultAt(hitPoint);
601 ASSERT_EQ(WebNode::ElementNode, negativeResult.node().nodeType());
602 EXPECT_FALSE(negativeResult.node().to<WebElement>().hasHTMLTagName("img"));
603 negativeResult.reset();
605 // Scale page up 2x so image should occupy the whole viewport.
606 webView->setPageScaleFactor(2.0f);
607 WebHitTestResult positiveResult = webView->hitTestResultAt(hitPoint);
608 ASSERT_EQ(WebNode::ElementNode, positiveResult.node().nodeType());
609 EXPECT_TRUE(positiveResult.node().to<WebElement>().hasHTMLTagName("img"));
610 positiveResult.reset();
613 TEST_F(WebViewTest, HitTestResultAtWithPageScaleAndPan)
615 std::string url = m_baseURL + "specify_size.html?" + "50px" + ":" + "50px";
616 URLTestHelpers::registerMockedURLLoad(toKURL(url), "specify_size.html");
617 WebView* webView = m_webViewHelper.initialize(true);
618 loadFrame(webView->mainFrame(), url);
619 webView->resize(WebSize(100, 100));
620 WebPoint hitPoint(75, 75);
622 // Image is at top left quandrant, so should not hit it.
623 WebHitTestResult negativeResult = webView->hitTestResultAt(hitPoint);
624 ASSERT_EQ(WebNode::ElementNode, negativeResult.node().nodeType());
625 EXPECT_FALSE(negativeResult.node().to<WebElement>().hasHTMLTagName("img"));
626 negativeResult.reset();
628 // Scale page up 2x so image should occupy the whole viewport.
629 webView->setPageScaleFactor(2.0f);
630 WebHitTestResult positiveResult = webView->hitTestResultAt(hitPoint);
631 ASSERT_EQ(WebNode::ElementNode, positiveResult.node().nodeType());
632 EXPECT_TRUE(positiveResult.node().to<WebElement>().hasHTMLTagName("img"));
633 positiveResult.reset();
635 // Pan around the zoomed in page so the image is not visible in viewport.
636 webView->setVisualViewportOffset(WebFloatPoint(100, 100));
637 WebHitTestResult negativeResult2 = webView->hitTestResultAt(hitPoint);
638 ASSERT_EQ(WebNode::ElementNode, negativeResult2.node().nodeType());
639 EXPECT_FALSE(negativeResult2.node().to<WebElement>().hasHTMLTagName("img"));
640 negativeResult2.reset();
643 TEST_F(WebViewTest, HitTestResultForTapWithTapArea)
645 std::string url = m_baseURL + "hit_test.html";
646 URLTestHelpers::registerMockedURLLoad(toKURL(url), "hit_test.html");
647 WebView* webView = m_webViewHelper.initializeAndLoad(url, true, 0);
648 webView->resize(WebSize(100, 100));
649 WebPoint hitPoint(55, 55);
651 // Image is at top left quandrant, so should not hit it.
652 WebHitTestResult negativeResult = webView->hitTestResultAt(hitPoint);
653 ASSERT_EQ(WebNode::ElementNode, negativeResult.node().nodeType());
654 EXPECT_FALSE(negativeResult.node().to<WebElement>().hasHTMLTagName("img"));
655 negativeResult.reset();
657 // The tap area is 20 by 20 square, centered at 55, 55.
658 WebSize tapArea(20, 20);
659 WebHitTestResult positiveResult = webView->hitTestResultForTap(hitPoint, tapArea);
660 ASSERT_EQ(WebNode::ElementNode, positiveResult.node().nodeType());
661 EXPECT_TRUE(positiveResult.node().to<WebElement>().hasHTMLTagName("img"));
662 positiveResult.reset();
664 // Move the hit point the image is just outside the tapped area now.
665 hitPoint = WebPoint(61, 61);
666 WebHitTestResult negativeResult2 = webView->hitTestResultForTap(hitPoint, tapArea);
667 ASSERT_EQ(WebNode::ElementNode, negativeResult2.node().nodeType());
668 EXPECT_FALSE(negativeResult2.node().to<WebElement>().hasHTMLTagName("img"));
669 negativeResult2.reset();
672 TEST_F(WebViewTest, HitTestResultForTapWithTapAreaPageScaleAndPan)
674 std::string url = m_baseURL + "hit_test.html";
675 URLTestHelpers::registerMockedURLLoad(toKURL(url), "hit_test.html");
676 WebView* webView = m_webViewHelper.initialize(true);
677 loadFrame(webView->mainFrame(), url);
678 webView->resize(WebSize(100, 100));
679 WebPoint hitPoint(55, 55);
681 // Image is at top left quandrant, so should not hit it.
682 WebHitTestResult negativeResult = webView->hitTestResultAt(hitPoint);
683 ASSERT_EQ(WebNode::ElementNode, negativeResult.node().nodeType());
684 EXPECT_FALSE(negativeResult.node().to<WebElement>().hasHTMLTagName("img"));
685 negativeResult.reset();
687 // The tap area is 20 by 20 square, centered at 55, 55.
688 WebSize tapArea(20, 20);
689 WebHitTestResult positiveResult = webView->hitTestResultForTap(hitPoint, tapArea);
690 ASSERT_EQ(WebNode::ElementNode, positiveResult.node().nodeType());
691 EXPECT_TRUE(positiveResult.node().to<WebElement>().hasHTMLTagName("img"));
692 positiveResult.reset();
694 // Zoom in and pan around the page so the image is not visible in viewport.
695 webView->setPageScaleFactor(2.0f);
696 webView->setVisualViewportOffset(WebFloatPoint(100, 100));
697 WebHitTestResult negativeResult2 = webView->hitTestResultForTap(hitPoint, tapArea);
698 ASSERT_EQ(WebNode::ElementNode, negativeResult2.node().nodeType());
699 EXPECT_FALSE(negativeResult2.node().to<WebElement>().hasHTMLTagName("img"));
700 negativeResult2.reset();
703 void WebViewTest::testAutoResize(const WebSize& minAutoResize, const WebSize& maxAutoResize,
704 const std::string& pageWidth, const std::string& pageHeight,
705 int expectedWidth, int expectedHeight,
706 HorizontalScrollbarState expectedHorizontalState, VerticalScrollbarState expectedVerticalState)
708 AutoResizeWebViewClient client;
709 std::string url = m_baseURL + "specify_size.html?" + pageWidth + ":" + pageHeight;
710 URLTestHelpers::registerMockedURLLoad(toKURL(url), "specify_size.html");
711 WebView* webView = m_webViewHelper.initializeAndLoad(url, true, 0, &client);
712 client.testData().setWebView(webView);
714 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
715 FrameView* frameView = frame->frame()->view();
716 frameView->layout();
717 EXPECT_FALSE(frameView->layoutPending());
718 EXPECT_FALSE(frameView->needsLayout());
720 webView->enableAutoResizeMode(minAutoResize, maxAutoResize);
721 EXPECT_TRUE(frameView->layoutPending());
722 EXPECT_TRUE(frameView->needsLayout());
723 frameView->layout();
725 EXPECT_TRUE(frame->frame()->document()->isHTMLDocument());
727 EXPECT_EQ(expectedWidth, client.testData().width());
728 EXPECT_EQ(expectedHeight, client.testData().height());
730 // Android disables main frame scrollbars.
731 #if !OS(ANDROID)
732 EXPECT_EQ(expectedHorizontalState, client.testData().horizontalScrollbarState());
733 EXPECT_EQ(expectedVerticalState, client.testData().verticalScrollbarState());
734 #endif
736 m_webViewHelper.reset(); // Explicitly reset to break dependency on locally scoped client.
739 TEST_F(WebViewTest, AutoResizeMinimumSize)
741 WebSize minAutoResize(91, 56);
742 WebSize maxAutoResize(403, 302);
743 std::string pageWidth = "91px";
744 std::string pageHeight = "56px";
745 int expectedWidth = 91;
746 int expectedHeight = 56;
747 testAutoResize(minAutoResize, maxAutoResize, pageWidth, pageHeight,
748 expectedWidth, expectedHeight, NoHorizontalScrollbar, NoVerticalScrollbar);
751 TEST_F(WebViewTest, AutoResizeHeightOverflowAndFixedWidth)
753 WebSize minAutoResize(90, 95);
754 WebSize maxAutoResize(90, 100);
755 std::string pageWidth = "60px";
756 std::string pageHeight = "200px";
757 int expectedWidth = 90;
758 int expectedHeight = 100;
759 testAutoResize(minAutoResize, maxAutoResize, pageWidth, pageHeight,
760 expectedWidth, expectedHeight, NoHorizontalScrollbar, VisibleVerticalScrollbar);
763 TEST_F(WebViewTest, AutoResizeFixedHeightAndWidthOverflow)
765 WebSize minAutoResize(90, 100);
766 WebSize maxAutoResize(200, 100);
767 std::string pageWidth = "300px";
768 std::string pageHeight = "80px";
769 int expectedWidth = 200;
770 int expectedHeight = 100;
771 testAutoResize(minAutoResize, maxAutoResize, pageWidth, pageHeight,
772 expectedWidth, expectedHeight, VisibleHorizontalScrollbar, NoVerticalScrollbar);
775 // Next three tests disabled for https://bugs.webkit.org/show_bug.cgi?id=92318 .
776 // It seems we can run three AutoResize tests, then the next one breaks.
777 TEST_F(WebViewTest, AutoResizeInBetweenSizes)
779 WebSize minAutoResize(90, 95);
780 WebSize maxAutoResize(200, 300);
781 std::string pageWidth = "100px";
782 std::string pageHeight = "200px";
783 int expectedWidth = 100;
784 int expectedHeight = 200;
785 testAutoResize(minAutoResize, maxAutoResize, pageWidth, pageHeight,
786 expectedWidth, expectedHeight, NoHorizontalScrollbar, NoVerticalScrollbar);
789 TEST_F(WebViewTest, AutoResizeOverflowSizes)
791 WebSize minAutoResize(90, 95);
792 WebSize maxAutoResize(200, 300);
793 std::string pageWidth = "300px";
794 std::string pageHeight = "400px";
795 int expectedWidth = 200;
796 int expectedHeight = 300;
797 testAutoResize(minAutoResize, maxAutoResize, pageWidth, pageHeight,
798 expectedWidth, expectedHeight, VisibleHorizontalScrollbar, VisibleVerticalScrollbar);
801 TEST_F(WebViewTest, AutoResizeMaxSize)
803 WebSize minAutoResize(90, 95);
804 WebSize maxAutoResize(200, 300);
805 std::string pageWidth = "200px";
806 std::string pageHeight = "300px";
807 int expectedWidth = 200;
808 int expectedHeight = 300;
809 testAutoResize(minAutoResize, maxAutoResize, pageWidth, pageHeight,
810 expectedWidth, expectedHeight, NoHorizontalScrollbar, NoVerticalScrollbar);
813 void WebViewTest::testTextInputType(WebTextInputType expectedType, const std::string& htmlFile)
815 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8(htmlFile.c_str()));
816 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + htmlFile);
817 webView->setInitialFocus(false);
818 EXPECT_EQ(expectedType, webView->textInputInfo().type);
821 TEST_F(WebViewTest, TextInputType)
823 testTextInputType(WebTextInputTypeText, "input_field_default.html");
824 testTextInputType(WebTextInputTypePassword, "input_field_password.html");
825 testTextInputType(WebTextInputTypeEmail, "input_field_email.html");
826 testTextInputType(WebTextInputTypeSearch, "input_field_search.html");
827 testTextInputType(WebTextInputTypeNumber, "input_field_number.html");
828 testTextInputType(WebTextInputTypeTelephone, "input_field_tel.html");
829 testTextInputType(WebTextInputTypeURL, "input_field_url.html");
832 void WebViewTest::testInputMode(const WebString& expectedInputMode, const std::string& htmlFile)
834 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8(htmlFile.c_str()));
835 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + htmlFile);
836 webView->setInitialFocus(false);
837 EXPECT_EQ(expectedInputMode, webView->textInputInfo().inputMode);
840 TEST_F(WebViewTest, InputMode)
842 testInputMode(WebString(), "input_mode_default.html");
843 testInputMode(WebString("unknown"), "input_mode_default_unknown.html");
844 testInputMode(WebString("verbatim"), "input_mode_default_verbatim.html");
845 testInputMode(WebString("verbatim"), "input_mode_type_text_verbatim.html");
846 testInputMode(WebString("verbatim"), "input_mode_type_search_verbatim.html");
847 testInputMode(WebString(), "input_mode_type_url_verbatim.html");
848 testInputMode(WebString("verbatim"), "input_mode_textarea_verbatim.html");
851 TEST_F(WebViewTest, TextInputInfoWithReplacedElements)
853 std::string url = m_baseURL + "div_with_image.html";
854 URLTestHelpers::registerMockedURLLoad(toKURL(url), "div_with_image.html");
855 WebView* webView = m_webViewHelper.initializeAndLoad(url);
856 webView->setInitialFocus(false);
857 WebTextInputInfo info = webView->textInputInfo();
859 EXPECT_EQ("foo\xef\xbf\xbc", info.value.utf8());
862 TEST_F(WebViewTest, SetEditableSelectionOffsetsAndTextInputInfo)
864 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
865 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html");
866 webView->setInitialFocus(false);
867 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
868 frame->setEditableSelectionOffsets(5, 13);
869 EXPECT_EQ("56789abc", frame->selectionAsText());
870 WebTextInputInfo info = webView->textInputInfo();
871 EXPECT_EQ("0123456789abcdefghijklmnopqrstuvwxyz", info.value);
872 EXPECT_EQ(5, info.selectionStart);
873 EXPECT_EQ(13, info.selectionEnd);
874 EXPECT_EQ(-1, info.compositionStart);
875 EXPECT_EQ(-1, info.compositionEnd);
877 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("content_editable_populated.html"));
878 webView = m_webViewHelper.initializeAndLoad(m_baseURL + "content_editable_populated.html");
879 webView->setInitialFocus(false);
880 frame = toWebLocalFrameImpl(webView->mainFrame());
881 frame->setEditableSelectionOffsets(8, 19);
882 EXPECT_EQ("89abcdefghi", frame->selectionAsText());
883 info = webView->textInputInfo();
884 EXPECT_EQ("0123456789abcdefghijklmnopqrstuvwxyz", info.value);
885 EXPECT_EQ(8, info.selectionStart);
886 EXPECT_EQ(19, info.selectionEnd);
887 EXPECT_EQ(-1, info.compositionStart);
888 EXPECT_EQ(-1, info.compositionEnd);
891 TEST_F(WebViewTest, ConfirmCompositionCursorPositionChange)
893 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
894 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html");
895 webView->setInitialFocus(false);
897 // Set up a composition that needs to be committed.
898 std::string compositionText("hello");
900 WebVector<WebCompositionUnderline> emptyUnderlines;
901 webView->setComposition(WebString::fromUTF8(compositionText.c_str()), emptyUnderlines, 3, 3);
903 WebTextInputInfo info = webView->textInputInfo();
904 EXPECT_EQ("hello", std::string(info.value.utf8().data()));
905 EXPECT_EQ(3, info.selectionStart);
906 EXPECT_EQ(3, info.selectionEnd);
907 EXPECT_EQ(0, info.compositionStart);
908 EXPECT_EQ(5, info.compositionEnd);
910 webView->confirmComposition(WebWidget::KeepSelection);
911 info = webView->textInputInfo();
912 EXPECT_EQ(3, info.selectionStart);
913 EXPECT_EQ(3, info.selectionEnd);
914 EXPECT_EQ(-1, info.compositionStart);
915 EXPECT_EQ(-1, info.compositionEnd);
917 webView->setComposition(WebString::fromUTF8(compositionText.c_str()), emptyUnderlines, 3, 3);
918 info = webView->textInputInfo();
919 EXPECT_EQ("helhellolo", std::string(info.value.utf8().data()));
920 EXPECT_EQ(6, info.selectionStart);
921 EXPECT_EQ(6, info.selectionEnd);
922 EXPECT_EQ(3, info.compositionStart);
923 EXPECT_EQ(8, info.compositionEnd);
925 webView->confirmComposition(WebWidget::DoNotKeepSelection);
926 info = webView->textInputInfo();
927 EXPECT_EQ(8, info.selectionStart);
928 EXPECT_EQ(8, info.selectionEnd);
929 EXPECT_EQ(-1, info.compositionStart);
930 EXPECT_EQ(-1, info.compositionEnd);
933 TEST_F(WebViewTest, InsertNewLinePlacementAfterConfirmComposition)
935 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("text_area_populated.html"));
936 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "text_area_populated.html");
937 webView->setInitialFocus(false);
939 WebVector<WebCompositionUnderline> emptyUnderlines;
941 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
942 frame->setEditableSelectionOffsets(4, 4);
943 frame->setCompositionFromExistingText(8, 12, emptyUnderlines);
945 WebTextInputInfo info = webView->textInputInfo();
946 EXPECT_EQ("0123456789abcdefghijklmnopqrstuvwxyz", std::string(info.value.utf8().data()));
947 EXPECT_EQ(4, info.selectionStart);
948 EXPECT_EQ(4, info.selectionEnd);
949 EXPECT_EQ(8, info.compositionStart);
950 EXPECT_EQ(12, info.compositionEnd);
952 webView->confirmComposition(WebWidget::KeepSelection);
953 info = webView->textInputInfo();
954 EXPECT_EQ(4, info.selectionStart);
955 EXPECT_EQ(4, info.selectionEnd);
956 EXPECT_EQ(-1, info.compositionStart);
957 EXPECT_EQ(-1, info.compositionEnd);
959 std::string compositionText("\n");
960 webView->confirmComposition(WebString::fromUTF8(compositionText.c_str()));
961 info = webView->textInputInfo();
962 EXPECT_EQ(5, info.selectionStart);
963 EXPECT_EQ(5, info.selectionEnd);
964 EXPECT_EQ(-1, info.compositionStart);
965 EXPECT_EQ(-1, info.compositionEnd);
966 EXPECT_EQ("0123\n456789abcdefghijklmnopqrstuvwxyz", std::string(info.value.utf8().data()));
969 TEST_F(WebViewTest, ExtendSelectionAndDelete)
971 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
972 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html");
973 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
974 webView->setInitialFocus(false);
975 frame->setEditableSelectionOffsets(10, 10);
976 frame->extendSelectionAndDelete(5, 8);
977 WebTextInputInfo info = webView->textInputInfo();
978 EXPECT_EQ("01234ijklmnopqrstuvwxyz", std::string(info.value.utf8().data()));
979 EXPECT_EQ(5, info.selectionStart);
980 EXPECT_EQ(5, info.selectionEnd);
981 frame->extendSelectionAndDelete(10, 0);
982 info = webView->textInputInfo();
983 EXPECT_EQ("ijklmnopqrstuvwxyz", std::string(info.value.utf8().data()));
986 TEST_F(WebViewTest, SetCompositionFromExistingText)
988 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
989 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html");
990 webView->setInitialFocus(false);
991 WebVector<WebCompositionUnderline> underlines(static_cast<size_t>(1));
992 underlines[0] = WebCompositionUnderline(0, 4, 0, false, 0);
993 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
994 frame->setEditableSelectionOffsets(4, 10);
995 frame->setCompositionFromExistingText(8, 12, underlines);
996 WebTextInputInfo info = webView->textInputInfo();
997 EXPECT_EQ(4, info.selectionStart);
998 EXPECT_EQ(10, info.selectionEnd);
999 EXPECT_EQ(8, info.compositionStart);
1000 EXPECT_EQ(12, info.compositionEnd);
1001 WebVector<WebCompositionUnderline> emptyUnderlines;
1002 frame->setCompositionFromExistingText(0, 0, emptyUnderlines);
1003 info = webView->textInputInfo();
1004 EXPECT_EQ(4, info.selectionStart);
1005 EXPECT_EQ(10, info.selectionEnd);
1006 EXPECT_EQ(-1, info.compositionStart);
1007 EXPECT_EQ(-1, info.compositionEnd);
1010 TEST_F(WebViewTest, SetCompositionFromExistingTextInTextArea)
1012 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("text_area_populated.html"));
1013 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "text_area_populated.html");
1014 webView->setInitialFocus(false);
1015 WebVector<WebCompositionUnderline> underlines(static_cast<size_t>(1));
1016 underlines[0] = WebCompositionUnderline(0, 4, 0, false, 0);
1017 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
1018 frame->setEditableSelectionOffsets(27, 27);
1019 std::string newLineText("\n");
1020 webView->confirmComposition(WebString::fromUTF8(newLineText.c_str()));
1021 WebTextInputInfo info = webView->textInputInfo();
1022 EXPECT_EQ("0123456789abcdefghijklmnopq\nrstuvwxyz", std::string(info.value.utf8().data()));
1024 frame->setEditableSelectionOffsets(31, 31);
1025 frame->setCompositionFromExistingText(30, 34, underlines);
1026 info = webView->textInputInfo();
1027 EXPECT_EQ("0123456789abcdefghijklmnopq\nrstuvwxyz", std::string(info.value.utf8().data()));
1028 EXPECT_EQ(31, info.selectionStart);
1029 EXPECT_EQ(31, info.selectionEnd);
1030 EXPECT_EQ(30, info.compositionStart);
1031 EXPECT_EQ(34, info.compositionEnd);
1033 std::string compositionText("yolo");
1034 webView->confirmComposition(WebString::fromUTF8(compositionText.c_str()));
1035 info = webView->textInputInfo();
1036 EXPECT_EQ("0123456789abcdefghijklmnopq\nrsyoloxyz", std::string(info.value.utf8().data()));
1037 EXPECT_EQ(34, info.selectionStart);
1038 EXPECT_EQ(34, info.selectionEnd);
1039 EXPECT_EQ(-1, info.compositionStart);
1040 EXPECT_EQ(-1, info.compositionEnd);
1043 TEST_F(WebViewTest, SetCompositionFromExistingTextInRichText)
1045 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("content_editable_rich_text.html"));
1046 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "content_editable_rich_text.html");
1047 webView->setInitialFocus(false);
1048 WebVector<WebCompositionUnderline> underlines(static_cast<size_t>(1));
1049 underlines[0] = WebCompositionUnderline(0, 4, 0, false, 0);
1050 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
1051 frame->setEditableSelectionOffsets(1, 1);
1052 WebDocument document = webView->mainFrame()->document();
1053 EXPECT_FALSE(document.getElementById("bold").isNull());
1054 frame->setCompositionFromExistingText(0, 4, underlines);
1055 EXPECT_FALSE(document.getElementById("bold").isNull());
1058 TEST_F(WebViewTest, SetEditableSelectionOffsetsKeepsComposition)
1060 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
1061 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html");
1062 webView->setInitialFocus(false);
1064 std::string compositionTextFirst("hello ");
1065 std::string compositionTextSecond("world");
1066 WebVector<WebCompositionUnderline> emptyUnderlines;
1068 webView->confirmComposition(WebString::fromUTF8(compositionTextFirst.c_str()));
1069 webView->setComposition(WebString::fromUTF8(compositionTextSecond.c_str()), emptyUnderlines, 5, 5);
1071 WebTextInputInfo info = webView->textInputInfo();
1072 EXPECT_EQ("hello world", std::string(info.value.utf8().data()));
1073 EXPECT_EQ(11, info.selectionStart);
1074 EXPECT_EQ(11, info.selectionEnd);
1075 EXPECT_EQ(6, info.compositionStart);
1076 EXPECT_EQ(11, info.compositionEnd);
1078 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
1079 frame->setEditableSelectionOffsets(6, 6);
1080 info = webView->textInputInfo();
1081 EXPECT_EQ("hello world", std::string(info.value.utf8().data()));
1082 EXPECT_EQ(6, info.selectionStart);
1083 EXPECT_EQ(6, info.selectionEnd);
1084 EXPECT_EQ(6, info.compositionStart);
1085 EXPECT_EQ(11, info.compositionEnd);
1087 frame->setEditableSelectionOffsets(8, 8);
1088 info = webView->textInputInfo();
1089 EXPECT_EQ("hello world", std::string(info.value.utf8().data()));
1090 EXPECT_EQ(8, info.selectionStart);
1091 EXPECT_EQ(8, info.selectionEnd);
1092 EXPECT_EQ(6, info.compositionStart);
1093 EXPECT_EQ(11, info.compositionEnd);
1095 frame->setEditableSelectionOffsets(11, 11);
1096 info = webView->textInputInfo();
1097 EXPECT_EQ("hello world", std::string(info.value.utf8().data()));
1098 EXPECT_EQ(11, info.selectionStart);
1099 EXPECT_EQ(11, info.selectionEnd);
1100 EXPECT_EQ(6, info.compositionStart);
1101 EXPECT_EQ(11, info.compositionEnd);
1103 frame->setEditableSelectionOffsets(6, 11);
1104 info = webView->textInputInfo();
1105 EXPECT_EQ("hello world", std::string(info.value.utf8().data()));
1106 EXPECT_EQ(6, info.selectionStart);
1107 EXPECT_EQ(11, info.selectionEnd);
1108 EXPECT_EQ(6, info.compositionStart);
1109 EXPECT_EQ(11, info.compositionEnd);
1111 frame->setEditableSelectionOffsets(2, 2);
1112 info = webView->textInputInfo();
1113 EXPECT_EQ("hello world", std::string(info.value.utf8().data()));
1114 EXPECT_EQ(2, info.selectionStart);
1115 EXPECT_EQ(2, info.selectionEnd);
1116 EXPECT_EQ(-1, info.compositionStart);
1117 EXPECT_EQ(-1, info.compositionEnd);
1120 TEST_F(WebViewTest, IsSelectionAnchorFirst)
1122 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
1123 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html");
1124 WebFrame* frame = webView->mainFrame();
1126 webView->setInitialFocus(false);
1127 frame->setEditableSelectionOffsets(4, 10);
1128 EXPECT_TRUE(webView->isSelectionAnchorFirst());
1129 WebRect anchor;
1130 WebRect focus;
1131 webView->selectionBounds(anchor, focus);
1132 frame->selectRange(WebPoint(focus.x, focus.y), WebPoint(anchor.x, anchor.y));
1133 EXPECT_FALSE(webView->isSelectionAnchorFirst());
1136 TEST_F(WebViewTest, ExitingDeviceEmulationResetsPageScale)
1138 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("200-by-300.html"));
1139 WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(m_baseURL + "200-by-300.html");
1140 webViewImpl->resize(WebSize(200, 300));
1142 float pageScaleExpected = webViewImpl->pageScaleFactor();
1144 WebDeviceEmulationParams params;
1145 params.screenPosition = WebDeviceEmulationParams::Desktop;
1146 params.deviceScaleFactor = 0;
1147 params.fitToView = false;
1148 params.offset = WebFloatPoint();
1149 params.scale = 1;
1151 webViewImpl->enableDeviceEmulation(params);
1153 webViewImpl->setPageScaleFactor(2);
1155 webViewImpl->disableDeviceEmulation();
1157 EXPECT_EQ(pageScaleExpected, webViewImpl->pageScaleFactor());
1160 TEST_F(WebViewTest, HistoryResetScrollAndScaleState)
1162 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("200-by-300.html"));
1163 WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(m_baseURL + "200-by-300.html");
1164 webViewImpl->resize(WebSize(100, 150));
1165 webViewImpl->layout();
1166 EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().width);
1167 EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().height);
1169 // Make the page scale and scroll with the given paremeters.
1170 webViewImpl->setPageScaleFactor(2.0f);
1171 webViewImpl->mainFrame()->setScrollOffset(WebSize(94, 111));
1172 EXPECT_EQ(2.0f, webViewImpl->pageScaleFactor());
1173 EXPECT_EQ(94, webViewImpl->mainFrame()->scrollOffset().width);
1174 EXPECT_EQ(111, webViewImpl->mainFrame()->scrollOffset().height);
1175 LocalFrame* mainFrameLocal = toLocalFrame(webViewImpl->page()->mainFrame());
1176 mainFrameLocal->loader().saveScrollState();
1177 EXPECT_EQ(2.0f, mainFrameLocal->loader().currentItem()->pageScaleFactor());
1178 EXPECT_EQ(94, mainFrameLocal->loader().currentItem()->scrollPoint().x());
1179 EXPECT_EQ(111, mainFrameLocal->loader().currentItem()->scrollPoint().y());
1181 // Confirm that resetting the page state resets the saved scroll position.
1182 webViewImpl->resetScrollAndScaleState();
1183 EXPECT_EQ(1.0f, webViewImpl->pageScaleFactor());
1184 EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().width);
1185 EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().height);
1186 EXPECT_EQ(1.0f, mainFrameLocal->loader().currentItem()->pageScaleFactor());
1187 EXPECT_EQ(0, mainFrameLocal->loader().currentItem()->scrollPoint().x());
1188 EXPECT_EQ(0, mainFrameLocal->loader().currentItem()->scrollPoint().y());
1191 TEST_F(WebViewTest, BackForwardRestoreScroll)
1193 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("back_forward_restore_scroll.html"));
1194 WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(m_baseURL + "back_forward_restore_scroll.html");
1195 webViewImpl->resize(WebSize(640, 480));
1196 webViewImpl->layout();
1198 // Emulate a user scroll
1199 webViewImpl->mainFrame()->setScrollOffset(WebSize(0, 900));
1200 LocalFrame* mainFrameLocal = toLocalFrame(webViewImpl->page()->mainFrame());
1201 RefPtrWillBePersistent<HistoryItem> item1 = mainFrameLocal->loader().currentItem();
1203 // Click an anchor
1204 mainFrameLocal->loader().load(FrameLoadRequest(mainFrameLocal->document(), ResourceRequest(mainFrameLocal->document()->completeURL("#a"))));
1205 RefPtrWillBePersistent<HistoryItem> item2 = mainFrameLocal->loader().currentItem();
1207 // Go back, then forward, then back again.
1208 mainFrameLocal->loader().load(
1209 FrameLoadRequest(nullptr, FrameLoader::resourceRequestFromHistoryItem(
1210 item1.get(), UseProtocolCachePolicy)),
1211 FrameLoadTypeBackForward, item1.get(), HistorySameDocumentLoad);
1212 mainFrameLocal->loader().load(
1213 FrameLoadRequest(nullptr, FrameLoader::resourceRequestFromHistoryItem(
1214 item2.get(), UseProtocolCachePolicy)),
1215 FrameLoadTypeBackForward, item2.get(), HistorySameDocumentLoad);
1216 mainFrameLocal->loader().load(
1217 FrameLoadRequest(nullptr, FrameLoader::resourceRequestFromHistoryItem(
1218 item1.get(), UseProtocolCachePolicy)),
1219 FrameLoadTypeBackForward, item1.get(), HistorySameDocumentLoad);
1221 // Click a different anchor
1222 mainFrameLocal->loader().load(FrameLoadRequest(mainFrameLocal->document(), ResourceRequest(mainFrameLocal->document()->completeURL("#b"))));
1223 RefPtrWillBePersistent<HistoryItem> item3 = mainFrameLocal->loader().currentItem();
1225 // Go back, then forward. The scroll position should be properly set on the forward navigation.
1226 mainFrameLocal->loader().load(
1227 FrameLoadRequest(nullptr, FrameLoader::resourceRequestFromHistoryItem(
1228 item1.get(), UseProtocolCachePolicy)),
1229 FrameLoadTypeBackForward, item1.get(), HistorySameDocumentLoad);
1230 mainFrameLocal->loader().load(
1231 FrameLoadRequest(nullptr, FrameLoader::resourceRequestFromHistoryItem(
1232 item3.get(), UseProtocolCachePolicy)),
1233 FrameLoadTypeBackForward, item3.get(), HistorySameDocumentLoad);
1234 EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().width);
1235 EXPECT_GT(webViewImpl->mainFrame()->scrollOffset().height, 2000);
1238 TEST_F(WebViewTest, EnterFullscreenResetScrollAndScaleState)
1240 FrameTestHelpers::TestWebViewClient client;
1241 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("200-by-300.html"));
1242 WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(m_baseURL + "200-by-300.html", true, 0, &client);
1243 webViewImpl->resize(WebSize(100, 150));
1244 webViewImpl->layout();
1245 EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().width);
1246 EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().height);
1248 // Make the page scale and scroll with the given paremeters.
1249 webViewImpl->setPageScaleFactor(2.0f);
1250 webViewImpl->mainFrame()->setScrollOffset(WebSize(94, 111));
1251 webViewImpl->setVisualViewportOffset(WebFloatPoint(12, 20));
1252 EXPECT_EQ(2.0f, webViewImpl->pageScaleFactor());
1253 EXPECT_EQ(94, webViewImpl->mainFrame()->scrollOffset().width);
1254 EXPECT_EQ(111, webViewImpl->mainFrame()->scrollOffset().height);
1255 EXPECT_EQ(12, webViewImpl->visualViewportOffset().x);
1256 EXPECT_EQ(20, webViewImpl->visualViewportOffset().y);
1258 RefPtrWillBeRawPtr<Element> element = static_cast<PassRefPtrWillBeRawPtr<Element>>(webViewImpl->mainFrame()->document().body());
1259 webViewImpl->enterFullScreenForElement(element.get());
1260 webViewImpl->didEnterFullScreen();
1262 // Page scale factor must be 1.0 during fullscreen for elements to be sized
1263 // properly.
1264 EXPECT_EQ(1.0f, webViewImpl->pageScaleFactor());
1266 // Make sure fullscreen nesting doesn't disrupt scroll/scale saving.
1267 RefPtrWillBeRawPtr<Element> otherElement = static_cast<PassRefPtrWillBeRawPtr<Element>>(webViewImpl->mainFrame()->document().head());
1268 webViewImpl->enterFullScreenForElement(otherElement.get());
1270 // Confirm that exiting fullscreen restores the parameters.
1271 webViewImpl->didExitFullScreen();
1272 EXPECT_EQ(2.0f, webViewImpl->pageScaleFactor());
1273 EXPECT_EQ(94, webViewImpl->mainFrame()->scrollOffset().width);
1274 EXPECT_EQ(111, webViewImpl->mainFrame()->scrollOffset().height);
1275 EXPECT_EQ(12, webViewImpl->visualViewportOffset().x);
1276 EXPECT_EQ(20, webViewImpl->visualViewportOffset().y);
1278 m_webViewHelper.reset(); // Explicitly reset to break dependency on locally scoped client.
1281 class PrintWebViewClient : public FrameTestHelpers::TestWebViewClient {
1282 public:
1283 PrintWebViewClient()
1284 : m_printCalled(false)
1288 // WebViewClient methods
1289 void printPage(WebLocalFrame*) override
1291 m_printCalled = true;
1294 bool printCalled() const { return m_printCalled; }
1296 private:
1297 bool m_printCalled;
1301 TEST_F(WebViewTest, PrintWithXHRInFlight)
1303 PrintWebViewClient client;
1304 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("print_with_xhr_inflight.html"));
1305 WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(m_baseURL + "print_with_xhr_inflight.html", true, 0, &client);
1307 ASSERT_TRUE(toLocalFrame(webViewImpl->page()->mainFrame())->document()->loadEventFinished());
1308 EXPECT_TRUE(client.printCalled());
1309 m_webViewHelper.reset();
1312 class DropTask : public WebTaskRunner::Task {
1313 public:
1314 explicit DropTask(WebView* webView) : m_webView(webView)
1318 void run() override
1320 const WebPoint clientPoint(0, 0);
1321 const WebPoint screenPoint(0, 0);
1322 m_webView->dragTargetDrop(clientPoint, screenPoint, 0);
1325 private:
1326 WebView* const m_webView;
1328 static void DragAndDropURL(WebViewImpl* webView, const std::string& url)
1330 WebDragData dragData;
1331 dragData.initialize();
1333 WebDragData::Item item;
1334 item.storageType = WebDragData::Item::StorageTypeString;
1335 item.stringType = "text/uri-list";
1336 item.stringData = WebString::fromUTF8(url);
1337 dragData.addItem(item);
1339 const WebPoint clientPoint(0, 0);
1340 const WebPoint screenPoint(0, 0);
1341 webView->dragTargetDragEnter(dragData, clientPoint, screenPoint, WebDragOperationCopy, 0);
1342 Platform::current()->currentThread()->taskRunner()->postTask(FROM_HERE, new DropTask(webView));
1343 FrameTestHelpers::pumpPendingRequestsDoNotUse(webView->mainFrame());
1346 TEST_F(WebViewTest, DragDropURL)
1348 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), "foo.html");
1349 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), "bar.html");
1351 const std::string fooUrl = m_baseURL + "foo.html";
1352 const std::string barUrl = m_baseURL + "bar.html";
1354 WebViewImpl* webView = m_webViewHelper.initializeAndLoad(fooUrl);
1356 ASSERT_TRUE(webView);
1358 // Drag and drop barUrl and verify that we've navigated to it.
1359 DragAndDropURL(webView, barUrl);
1360 EXPECT_EQ(barUrl, webView->mainFrame()->document().url().string().utf8());
1362 // Drag and drop fooUrl and verify that we've navigated back to it.
1363 DragAndDropURL(webView, fooUrl);
1364 EXPECT_EQ(fooUrl, webView->mainFrame()->document().url().string().utf8());
1366 // Disable navigation on drag-and-drop.
1367 webView->settingsImpl()->setNavigateOnDragDrop(false);
1369 // Attempt to drag and drop to barUrl and verify that no navigation has occurred.
1370 DragAndDropURL(webView, barUrl);
1371 EXPECT_EQ(fooUrl, webView->mainFrame()->document().url().string().utf8());
1374 class ContentDetectorClient : public FrameTestHelpers::TestWebViewClient {
1375 public:
1376 ContentDetectorClient() { reset(); }
1378 WebContentDetectionResult detectContentAround(const WebHitTestResult& hitTest) override
1380 m_contentDetectionRequested = true;
1381 return m_contentDetectionResult;
1384 void scheduleContentIntent(const WebURL& url) override
1386 m_scheduledIntentURL = url;
1389 void cancelScheduledContentIntents() override
1391 m_pendingIntentsCancelled = true;
1394 void reset()
1396 m_contentDetectionRequested = false;
1397 m_pendingIntentsCancelled = false;
1398 m_scheduledIntentURL = WebURL();
1399 m_contentDetectionResult = WebContentDetectionResult();
1402 bool contentDetectionRequested() const { return m_contentDetectionRequested; }
1403 bool pendingIntentsCancelled() const { return m_pendingIntentsCancelled; }
1404 const WebURL& scheduledIntentURL() const { return m_scheduledIntentURL; }
1405 void setContentDetectionResult(const WebContentDetectionResult& result) { m_contentDetectionResult = result; }
1407 private:
1408 bool m_contentDetectionRequested;
1409 bool m_pendingIntentsCancelled;
1410 WebURL m_scheduledIntentURL;
1411 WebContentDetectionResult m_contentDetectionResult;
1414 static bool tapElementById(WebView* webView, WebInputEvent::Type type, const WebString& id)
1416 ASSERT(webView);
1417 RefPtrWillBeRawPtr<Element> element = static_cast<PassRefPtrWillBeRawPtr<Element>>(webView->mainFrame()->document().getElementById(id));
1418 if (!element)
1419 return false;
1421 element->scrollIntoViewIfNeeded();
1423 // TODO(bokan): Technically incorrect, event positions should be in viewport space. crbug.com/371902.
1424 IntPoint center = element->screenRect().center();
1426 WebGestureEvent event;
1427 event.type = type;
1428 event.x = center.x();
1429 event.y = center.y();
1431 webView->handleInputEvent(event);
1432 runPendingTasks();
1433 return true;
1436 TEST_F(WebViewTest, DetectContentAroundPosition)
1438 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("content_listeners.html"));
1440 ContentDetectorClient client;
1441 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "content_listeners.html", true, 0, &client);
1442 webView->resize(WebSize(500, 300));
1443 webView->layout();
1444 runPendingTasks();
1446 WebString clickListener = WebString::fromUTF8("clickListener");
1447 WebString touchstartListener = WebString::fromUTF8("touchstartListener");
1448 WebString mousedownListener = WebString::fromUTF8("mousedownListener");
1449 WebString noListener = WebString::fromUTF8("noListener");
1450 WebString link = WebString::fromUTF8("link");
1452 // Ensure content detection is not requested for nodes listening to click,
1453 // mouse or touch events when we do simple taps.
1454 EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, clickListener));
1455 EXPECT_FALSE(client.contentDetectionRequested());
1456 client.reset();
1458 EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, touchstartListener));
1459 EXPECT_FALSE(client.contentDetectionRequested());
1460 client.reset();
1462 EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, mousedownListener));
1463 EXPECT_FALSE(client.contentDetectionRequested());
1464 client.reset();
1466 // Content detection should work normally without these event listeners.
1467 // The click listener in the body should be ignored as a special case.
1468 EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, noListener));
1469 EXPECT_TRUE(client.contentDetectionRequested());
1470 EXPECT_FALSE(client.scheduledIntentURL().isValid());
1472 WebURL intentURL = toKURL(m_baseURL);
1473 client.setContentDetectionResult(WebContentDetectionResult(WebRange(), WebString(), intentURL));
1474 EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, noListener));
1475 EXPECT_TRUE(client.scheduledIntentURL() == intentURL);
1477 // Tapping elsewhere should cancel the scheduled intent.
1478 WebGestureEvent event;
1479 event.type = WebInputEvent::GestureTap;
1480 webView->handleInputEvent(event);
1481 runPendingTasks();
1482 EXPECT_TRUE(client.pendingIntentsCancelled());
1484 m_webViewHelper.reset(); // Explicitly reset to break dependency on locally scoped client.
1487 TEST_F(WebViewTest, ClientTapHandling)
1489 TapHandlingWebViewClient client;
1490 client.reset();
1491 WebView* webView = m_webViewHelper.initializeAndLoad("about:blank", true, 0, &client);
1492 WebGestureEvent event;
1493 event.type = WebInputEvent::GestureTap;
1494 event.x = 3;
1495 event.y = 8;
1496 webView->handleInputEvent(event);
1497 runPendingTasks();
1498 EXPECT_EQ(3, client.tapX());
1499 EXPECT_EQ(8, client.tapY());
1500 client.reset();
1501 event.type = WebInputEvent::GestureLongPress;
1502 event.x = 25;
1503 event.y = 7;
1504 webView->handleInputEvent(event);
1505 runPendingTasks();
1506 EXPECT_EQ(25, client.longpressX());
1507 EXPECT_EQ(7, client.longpressY());
1509 m_webViewHelper.reset(); // Explicitly reset to break dependency on locally scoped client.
1512 TEST_F(WebViewTest, ClientTapHandlingNullWebViewClient)
1514 WebViewImpl* webView = WebViewImpl::create(nullptr);
1515 WebLocalFrame* localFrame = WebLocalFrame::create(WebTreeScopeType::Document, nullptr);
1516 webView->setMainFrame(localFrame);
1517 WebGestureEvent event;
1518 event.type = WebInputEvent::GestureTap;
1519 event.x = 3;
1520 event.y = 8;
1521 EXPECT_FALSE(webView->handleInputEvent(event));
1522 webView->close();
1523 // Explicitly close as the frame as no frame client to do so on frameDetached().
1524 localFrame->close();
1527 #if OS(ANDROID)
1528 TEST_F(WebViewTest, LongPressSelection)
1530 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("longpress_selection.html"));
1532 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "longpress_selection.html", true);
1533 webView->resize(WebSize(500, 300));
1534 webView->layout();
1535 runPendingTasks();
1537 WebString target = WebString::fromUTF8("target");
1538 WebString onselectstartfalse = WebString::fromUTF8("onselectstartfalse");
1539 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
1541 EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureLongPress, onselectstartfalse));
1542 EXPECT_EQ("", std::string(frame->selectionAsText().utf8().data()));
1543 EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureLongPress, target));
1544 EXPECT_EQ("testword", std::string(frame->selectionAsText().utf8().data()));
1547 TEST_F(WebViewTest, BlinkCaretOnTypingAfterLongPress)
1549 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("blink_caret_on_typing_after_long_press.html"));
1551 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "blink_caret_on_typing_after_long_press.html", true);
1552 webView->resize(WebSize(640, 480));
1553 webView->layout();
1554 runPendingTasks();
1556 WebString target = WebString::fromUTF8("target");
1557 WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webView->mainFrame());
1559 EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureLongPress, target));
1560 EXPECT_TRUE(mainFrame->frame()->selection().isCaretBlinkingSuspended());
1562 WebKeyboardEvent keyEvent;
1563 keyEvent.type = WebInputEvent::RawKeyDown;
1564 webView->handleInputEvent(keyEvent);
1565 keyEvent.type = WebInputEvent::KeyUp;
1566 webView->handleInputEvent(keyEvent);
1567 EXPECT_FALSE(mainFrame->frame()->selection().isCaretBlinkingSuspended());
1569 #endif
1571 TEST_F(WebViewTest, SelectionOnReadOnlyInput)
1573 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("selection_readonly.html"));
1574 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "selection_readonly.html", true);
1575 webView->resize(WebSize(640, 480));
1576 webView->layout();
1577 runPendingTasks();
1579 std::string testWord = "This text should be selected.";
1581 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
1582 EXPECT_EQ(testWord, std::string(frame->selectionAsText().utf8().data()));
1584 size_t location;
1585 size_t length;
1586 EXPECT_TRUE(toWebViewImpl(webView)->caretOrSelectionRange(&location, &length));
1587 EXPECT_EQ(location, 0UL);
1588 EXPECT_EQ(length, testWord.length());
1591 static void configueCompositingWebView(WebSettings* settings)
1593 settings->setAcceleratedCompositingEnabled(true);
1594 settings->setPreferCompositingToLCDTextEnabled(true);
1597 TEST_F(WebViewTest, ShowPressOnTransformedLink)
1599 OwnPtr<FrameTestHelpers::TestWebViewClient> fakeCompositingWebViewClient = adoptPtr(new FrameTestHelpers::TestWebViewClient());
1600 FrameTestHelpers::WebViewHelper webViewHelper;
1601 WebViewImpl* webViewImpl = webViewHelper.initialize(true, 0, fakeCompositingWebViewClient.get(), &configueCompositingWebView);
1603 int pageWidth = 640;
1604 int pageHeight = 480;
1605 webViewImpl->resize(WebSize(pageWidth, pageHeight));
1607 WebURL baseURL = URLTestHelpers::toKURL("http://example.com/");
1608 FrameTestHelpers::loadHTMLString(webViewImpl->mainFrame(), "<a href='http://www.test.com' style='position: absolute; left: 20px; top: 20px; width: 200px; transform:translateZ(0);'>A link to highlight</a>", baseURL);
1610 WebGestureEvent event;
1611 event.type = WebInputEvent::GestureShowPress;
1612 event.x = 20;
1613 event.y = 20;
1615 // Just make sure we don't hit any asserts.
1616 webViewImpl->handleInputEvent(event);
1619 class MockAutofillClient : public WebAutofillClient {
1620 public:
1621 MockAutofillClient()
1622 : m_ignoreTextChanges(false)
1623 , m_textChangesFromUserGesture(0)
1624 , m_textChangesWhileIgnored(0)
1625 , m_textChangesWhileNotIgnored(0)
1626 , m_userGestureNotificationsCount(0) {}
1628 ~MockAutofillClient() override {}
1630 void setIgnoreTextChanges(bool ignore) override { m_ignoreTextChanges = ignore; }
1631 void textFieldDidChange(const WebFormControlElement&) override
1633 if (m_ignoreTextChanges)
1634 ++m_textChangesWhileIgnored;
1635 else
1636 ++m_textChangesWhileNotIgnored;
1638 if (UserGestureIndicator::processingUserGesture())
1639 ++m_textChangesFromUserGesture;
1641 void firstUserGestureObserved() override { ++m_userGestureNotificationsCount; }
1643 void clearChangeCounts()
1645 m_textChangesWhileIgnored = 0;
1646 m_textChangesWhileNotIgnored = 0;
1649 int textChangesFromUserGesture() { return m_textChangesFromUserGesture; }
1650 int textChangesWhileIgnored() { return m_textChangesWhileIgnored; }
1651 int textChangesWhileNotIgnored() { return m_textChangesWhileNotIgnored; }
1652 int getUserGestureNotificationsCount() { return m_userGestureNotificationsCount; }
1654 private:
1655 bool m_ignoreTextChanges;
1656 int m_textChangesFromUserGesture;
1657 int m_textChangesWhileIgnored;
1658 int m_textChangesWhileNotIgnored;
1659 int m_userGestureNotificationsCount;
1663 TEST_F(WebViewTest, LosingFocusDoesNotTriggerAutofillTextChange)
1665 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
1666 MockAutofillClient client;
1667 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html");
1668 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
1669 frame->setAutofillClient(&client);
1670 webView->setInitialFocus(false);
1672 // Set up a composition that needs to be committed.
1673 WebVector<WebCompositionUnderline> emptyUnderlines;
1674 frame->setEditableSelectionOffsets(4, 10);
1675 frame->setCompositionFromExistingText(8, 12, emptyUnderlines);
1676 WebTextInputInfo info = webView->textInputInfo();
1677 EXPECT_EQ(4, info.selectionStart);
1678 EXPECT_EQ(10, info.selectionEnd);
1679 EXPECT_EQ(8, info.compositionStart);
1680 EXPECT_EQ(12, info.compositionEnd);
1682 // Clear the focus and track that the subsequent composition commit does not trigger a
1683 // text changed notification for autofill.
1684 client.clearChangeCounts();
1685 webView->setFocus(false);
1686 EXPECT_EQ(0, client.textChangesWhileNotIgnored());
1688 frame->setAutofillClient(0);
1691 static void verifySelectionAndComposition(WebView* webView, int selectionStart, int selectionEnd, int compositionStart, int compositionEnd, const char* failMessage)
1693 WebTextInputInfo info = webView->textInputInfo();
1694 EXPECT_EQ(selectionStart, info.selectionStart) << failMessage;
1695 EXPECT_EQ(selectionEnd, info.selectionEnd) << failMessage;
1696 EXPECT_EQ(compositionStart, info.compositionStart) << failMessage;
1697 EXPECT_EQ(compositionEnd, info.compositionEnd) << failMessage;
1700 TEST_F(WebViewTest, CompositionNotCancelledByBackspace)
1702 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("composition_not_cancelled_by_backspace.html"));
1703 MockAutofillClient client;
1704 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "composition_not_cancelled_by_backspace.html");
1705 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
1706 frame->setAutofillClient(&client);
1707 webView->setInitialFocus(false);
1709 // Test both input elements.
1710 for (int i = 0; i < 2; ++i) {
1711 // Select composition and do sanity check.
1712 WebVector<WebCompositionUnderline> emptyUnderlines;
1713 frame->setEditableSelectionOffsets(6, 6);
1714 EXPECT_TRUE(webView->setComposition("fghij", emptyUnderlines, 0, 5));
1715 frame->setEditableSelectionOffsets(11, 11);
1716 verifySelectionAndComposition(webView, 11, 11, 6, 11, "initial case");
1718 // Press Backspace and verify composition didn't get cancelled. This is to verify the fix
1719 // for crbug.com/429916.
1720 WebKeyboardEvent keyEvent;
1721 keyEvent.windowsKeyCode = VKEY_BACK;
1722 keyEvent.setKeyIdentifierFromWindowsKeyCode();
1723 keyEvent.type = WebInputEvent::RawKeyDown;
1724 webView->handleInputEvent(keyEvent);
1726 frame->setEditableSelectionOffsets(6, 6);
1727 EXPECT_TRUE(webView->setComposition("fghi", emptyUnderlines, 0, 4));
1728 frame->setEditableSelectionOffsets(10, 10);
1729 verifySelectionAndComposition(webView, 10, 10, 6, 10, "after pressing Backspace");
1731 keyEvent.type = WebInputEvent::KeyUp;
1732 webView->handleInputEvent(keyEvent);
1734 webView->advanceFocus(false);
1737 frame->setAutofillClient(0);
1740 TEST_F(WebViewTest, ConfirmCompositionTriggersAutofillTextChange)
1742 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
1743 MockAutofillClient client;
1744 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html");
1745 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
1746 frame->setAutofillClient(&client);
1747 webView->setInitialFocus(false);
1749 // Set up a composition that needs to be committed.
1750 std::string compositionText("testingtext");
1752 WebVector<WebCompositionUnderline> emptyUnderlines;
1753 webView->setComposition(WebString::fromUTF8(compositionText.c_str()), emptyUnderlines, 0, compositionText.length());
1755 WebTextInputInfo info = webView->textInputInfo();
1756 EXPECT_EQ(0, info.selectionStart);
1757 EXPECT_EQ((int) compositionText.length(), info.selectionEnd);
1758 EXPECT_EQ(0, info.compositionStart);
1759 EXPECT_EQ((int) compositionText.length(), info.compositionEnd);
1761 client.clearChangeCounts();
1762 webView->confirmComposition();
1763 EXPECT_EQ(0, client.textChangesWhileIgnored());
1764 EXPECT_EQ(1, client.textChangesWhileNotIgnored());
1766 frame->setAutofillClient(0);
1769 TEST_F(WebViewTest, SetCompositionFromExistingTextTriggersAutofillTextChange)
1771 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
1772 MockAutofillClient client;
1773 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html", true);
1774 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
1775 frame->setAutofillClient(&client);
1776 webView->setInitialFocus(false);
1778 WebVector<WebCompositionUnderline> emptyUnderlines;
1780 client.clearChangeCounts();
1781 frame->setCompositionFromExistingText(8, 12, emptyUnderlines);
1783 WebTextInputInfo info = webView->textInputInfo();
1784 EXPECT_EQ("0123456789abcdefghijklmnopqrstuvwxyz", std::string(info.value.utf8().data()));
1785 EXPECT_EQ(8, info.compositionStart);
1786 EXPECT_EQ(12, info.compositionEnd);
1788 EXPECT_EQ(0, client.textChangesWhileIgnored());
1789 EXPECT_EQ(0, client.textChangesWhileNotIgnored());
1791 WebDocument document = webView->mainFrame()->document();
1792 EXPECT_EQ(WebString::fromUTF8("none"), document.getElementById("inputEvent").firstChild().nodeValue());
1794 frame->setAutofillClient(0);
1797 class ViewCreatingWebViewClient : public FrameTestHelpers::TestWebViewClient {
1798 public:
1799 ViewCreatingWebViewClient()
1800 : m_didFocusCalled(false)
1804 // WebViewClient methods
1805 WebView* createView(WebLocalFrame*, const WebURLRequest&, const WebWindowFeatures&, const WebString& name, WebNavigationPolicy, bool) override
1807 return m_webViewHelper.initialize(true, 0, 0);
1810 // WebWidgetClient methods
1811 void didFocus() override
1813 m_didFocusCalled = true;
1816 bool didFocusCalled() const { return m_didFocusCalled; }
1817 WebView* createdWebView() const { return m_webViewHelper.webView(); }
1819 private:
1820 FrameTestHelpers::WebViewHelper m_webViewHelper;
1821 bool m_didFocusCalled;
1824 TEST_F(WebViewTest, DoNotFocusCurrentFrameOnNavigateFromLocalFrame)
1826 ViewCreatingWebViewClient client;
1827 FrameTestHelpers::WebViewHelper m_webViewHelper;
1828 WebViewImpl* webViewImpl = m_webViewHelper.initialize(true, 0, &client);
1829 webViewImpl->page()->settings().setJavaScriptCanOpenWindowsAutomatically(true);
1831 WebURL baseURL = URLTestHelpers::toKURL("http://example.com/");
1832 FrameTestHelpers::loadHTMLString(webViewImpl->mainFrame(), "<html><body><iframe src=\"about:blank\"></iframe></body></html>", baseURL);
1834 // Make a request from a local frame.
1835 WebURLRequest webURLRequestWithTargetStart;
1836 webURLRequestWithTargetStart.initialize();
1837 LocalFrame* localFrame = toWebLocalFrameImpl(webViewImpl->mainFrame()->firstChild())->frame();
1838 FrameLoadRequest requestWithTargetStart(localFrame->document(), webURLRequestWithTargetStart.toResourceRequest(), "_top");
1839 localFrame->loader().load(requestWithTargetStart);
1840 EXPECT_FALSE(client.didFocusCalled());
1842 m_webViewHelper.reset(); // Remove dependency on locally scoped client.
1845 TEST_F(WebViewTest, FocusExistingFrameOnNavigate)
1847 ViewCreatingWebViewClient client;
1848 FrameTestHelpers::WebViewHelper m_webViewHelper;
1849 WebViewImpl* webViewImpl = m_webViewHelper.initialize(true, 0, &client);
1850 webViewImpl->page()->settings().setJavaScriptCanOpenWindowsAutomatically(true);
1851 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewImpl->mainFrame());
1852 frame->setName("_start");
1854 // Make a request that will open a new window
1855 WebURLRequest webURLRequest;
1856 webURLRequest.initialize();
1857 FrameLoadRequest request(0, webURLRequest.toResourceRequest(), "_blank");
1858 toLocalFrame(webViewImpl->page()->mainFrame())->loader().load(request);
1859 ASSERT_TRUE(client.createdWebView());
1860 EXPECT_FALSE(client.didFocusCalled());
1862 // Make a request from the new window that will navigate the original window. The original window should be focused.
1863 WebURLRequest webURLRequestWithTargetStart;
1864 webURLRequestWithTargetStart.initialize();
1865 FrameLoadRequest requestWithTargetStart(0, webURLRequestWithTargetStart.toResourceRequest(), "_start");
1866 toLocalFrame(toWebViewImpl(client.createdWebView())->page()->mainFrame())->loader().load(requestWithTargetStart);
1867 EXPECT_TRUE(client.didFocusCalled());
1869 m_webViewHelper.reset(); // Remove dependency on locally scoped client.
1872 TEST_F(WebViewTest, DispatchesFocusOutFocusInOnViewToggleFocus)
1874 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), "focusout_focusin_events.html");
1875 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "focusout_focusin_events.html", true, 0);
1877 webView->setFocus(true);
1878 webView->setFocus(false);
1879 webView->setFocus(true);
1881 WebElement element = webView->mainFrame()->document().getElementById("message");
1882 EXPECT_STREQ("focusoutfocusin", element.textContent().utf8().data());
1885 TEST_F(WebViewTest, DispatchesDomFocusOutDomFocusInOnViewToggleFocus)
1887 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), "domfocusout_domfocusin_events.html");
1888 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "domfocusout_domfocusin_events.html", true, 0);
1890 webView->setFocus(true);
1891 webView->setFocus(false);
1892 webView->setFocus(true);
1894 WebElement element = webView->mainFrame()->document().getElementById("message");
1895 EXPECT_STREQ("DOMFocusOutDOMFocusIn", element.textContent().utf8().data());
1898 #if !ENABLE(INPUT_MULTIPLE_FIELDS_UI)
1899 static void openDateTimeChooser(WebView* webView, HTMLInputElement* inputElement)
1901 inputElement->focus();
1903 WebKeyboardEvent keyEvent;
1904 keyEvent.windowsKeyCode = VKEY_SPACE;
1905 keyEvent.type = WebInputEvent::RawKeyDown;
1906 keyEvent.setKeyIdentifierFromWindowsKeyCode();
1907 webView->handleInputEvent(keyEvent);
1909 keyEvent.type = WebInputEvent::KeyUp;
1910 webView->handleInputEvent(keyEvent);
1913 TEST_F(WebViewTest, ChooseValueFromDateTimeChooser)
1915 DateTimeChooserWebViewClient client;
1916 std::string url = m_baseURL + "date_time_chooser.html";
1917 URLTestHelpers::registerMockedURLLoad(toKURL(url), "date_time_chooser.html");
1918 WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(url, true, 0, &client);
1920 Document* document = webViewImpl->mainFrameImpl()->frame()->document();
1922 HTMLInputElement* inputElement;
1924 inputElement = toHTMLInputElement(document->getElementById("date"));
1925 openDateTimeChooser(webViewImpl, inputElement);
1926 client.chooserCompletion()->didChooseValue(0);
1927 client.clearChooserCompletion();
1928 EXPECT_STREQ("1970-01-01", inputElement->value().utf8().data());
1930 openDateTimeChooser(webViewImpl, inputElement);
1931 client.chooserCompletion()->didChooseValue(std::numeric_limits<double>::quiet_NaN());
1932 client.clearChooserCompletion();
1933 EXPECT_STREQ("", inputElement->value().utf8().data());
1935 inputElement = toHTMLInputElement(document->getElementById("datetimelocal"));
1936 openDateTimeChooser(webViewImpl, inputElement);
1937 client.chooserCompletion()->didChooseValue(0);
1938 client.clearChooserCompletion();
1939 EXPECT_STREQ("1970-01-01T00:00", inputElement->value().utf8().data());
1941 openDateTimeChooser(webViewImpl, inputElement);
1942 client.chooserCompletion()->didChooseValue(std::numeric_limits<double>::quiet_NaN());
1943 client.clearChooserCompletion();
1944 EXPECT_STREQ("", inputElement->value().utf8().data());
1946 inputElement = toHTMLInputElement(document->getElementById("month"));
1947 openDateTimeChooser(webViewImpl, inputElement);
1948 client.chooserCompletion()->didChooseValue(0);
1949 client.clearChooserCompletion();
1950 EXPECT_STREQ("1970-01", inputElement->value().utf8().data());
1952 openDateTimeChooser(webViewImpl, inputElement);
1953 client.chooserCompletion()->didChooseValue(std::numeric_limits<double>::quiet_NaN());
1954 client.clearChooserCompletion();
1955 EXPECT_STREQ("", inputElement->value().utf8().data());
1957 inputElement = toHTMLInputElement(document->getElementById("time"));
1958 openDateTimeChooser(webViewImpl, inputElement);
1959 client.chooserCompletion()->didChooseValue(0);
1960 client.clearChooserCompletion();
1961 EXPECT_STREQ("00:00", inputElement->value().utf8().data());
1963 openDateTimeChooser(webViewImpl, inputElement);
1964 client.chooserCompletion()->didChooseValue(std::numeric_limits<double>::quiet_NaN());
1965 client.clearChooserCompletion();
1966 EXPECT_STREQ("", inputElement->value().utf8().data());
1968 inputElement = toHTMLInputElement(document->getElementById("week"));
1969 openDateTimeChooser(webViewImpl, inputElement);
1970 client.chooserCompletion()->didChooseValue(0);
1971 client.clearChooserCompletion();
1972 EXPECT_STREQ("1970-W01", inputElement->value().utf8().data());
1974 openDateTimeChooser(webViewImpl, inputElement);
1975 client.chooserCompletion()->didChooseValue(std::numeric_limits<double>::quiet_NaN());
1976 client.clearChooserCompletion();
1977 EXPECT_STREQ("", inputElement->value().utf8().data());
1979 // Clear the WebViewClient from the webViewHelper to avoid use-after-free in the
1980 // WebViewHelper destructor.
1981 m_webViewHelper.reset();
1983 #endif
1985 TEST_F(WebViewTest, DispatchesFocusBlurOnViewToggle)
1987 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), "focus_blur_events.html");
1988 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "focus_blur_events.html", true, 0);
1990 webView->setFocus(true);
1991 webView->setFocus(false);
1992 webView->setFocus(true);
1994 WebElement element = webView->mainFrame()->document().getElementById("message");
1995 // Expect not to see duplication of events.
1996 EXPECT_STREQ("blurfocus", element.textContent().utf8().data());
1999 TEST_F(WebViewTest, SmartClipData)
2001 static const char* kExpectedClipText = "\nPrice 10,000,000won";
2002 static const char* kExpectedClipHtml =
2003 "<div id=\"div4\" style=\"padding: 10px; margin: 10px; border: 2px "
2004 "solid skyblue; float: left; width: 190px; height: 30px; "
2005 "color: rgb(0, 0, 0); font-family: myahem; font-size: 8px; font-style: "
2006 "normal; font-variant: normal; font-weight: normal; letter-spacing: "
2007 "normal; line-height: normal; orphans: auto; text-align: start; "
2008 "text-indent: 0px; text-transform: none; white-space: normal; widows: "
2009 "1; word-spacing: 0px; -webkit-text-stroke-width: 0px;\">Air "
2010 "conditioner</div><div id=\"div5\" style=\"padding: 10px; margin: "
2011 "10px; border: 2px solid skyblue; float: left; width: "
2012 "190px; height: 30px; color: rgb(0, 0, 0); font-family: myahem; "
2013 "font-size: 8px; font-style: normal; font-variant: normal; "
2014 "font-weight: normal; letter-spacing: normal; line-height: normal; "
2015 "orphans: auto; text-align: start; text-indent: 0px; text-transform: "
2016 "none; white-space: normal; widows: 1; word-spacing: 0px; "
2017 "-webkit-text-stroke-width: 0px;\">Price 10,000,000won</div>";
2018 WebString clipText;
2019 WebString clipHtml;
2020 WebRect clipRect;
2021 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("Ahem.ttf"));
2022 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("smartclip.html"));
2023 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "smartclip.html");
2024 webView->resize(WebSize(500, 500));
2025 webView->layout();
2026 WebRect cropRect(300, 125, 152, 50);
2027 webView->extractSmartClipData(cropRect, clipText, clipHtml, clipRect);
2028 EXPECT_STREQ(kExpectedClipText, clipText.utf8().c_str());
2029 EXPECT_STREQ(kExpectedClipHtml, clipHtml.utf8().c_str());
2032 TEST_F(WebViewTest, SmartClipDataWithPinchZoom)
2034 static const char* kExpectedClipText = "\nPrice 10,000,000won";
2035 static const char* kExpectedClipHtml =
2036 "<div id=\"div4\" style=\"padding: 10px; margin: 10px; border: 2px "
2037 "solid skyblue; float: left; width: 190px; height: 30px; "
2038 "color: rgb(0, 0, 0); font-family: myahem; font-size: 8px; font-style: "
2039 "normal; font-variant: normal; font-weight: normal; letter-spacing: "
2040 "normal; line-height: normal; orphans: auto; text-align: start; "
2041 "text-indent: 0px; text-transform: none; white-space: normal; widows: "
2042 "1; word-spacing: 0px; -webkit-text-stroke-width: 0px;\">Air "
2043 "conditioner</div><div id=\"div5\" style=\"padding: 10px; margin: "
2044 "10px; border: 2px solid skyblue; float: left; width: "
2045 "190px; height: 30px; color: rgb(0, 0, 0); font-family: myahem; "
2046 "font-size: 8px; font-style: normal; font-variant: normal; "
2047 "font-weight: normal; letter-spacing: normal; line-height: normal; "
2048 "orphans: auto; text-align: start; text-indent: 0px; text-transform: "
2049 "none; white-space: normal; widows: 1; word-spacing: 0px; "
2050 "-webkit-text-stroke-width: 0px;\">Price 10,000,000won</div>";
2051 WebString clipText;
2052 WebString clipHtml;
2053 WebRect clipRect;
2054 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("Ahem.ttf"));
2055 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("smartclip.html"));
2056 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "smartclip.html");
2057 webView->resize(WebSize(500, 500));
2058 webView->layout();
2059 webView->setPageScaleFactor(1.5);
2060 webView->setVisualViewportOffset(WebFloatPoint(167, 100));
2061 WebRect cropRect(200, 38, 228, 75);
2062 webView->extractSmartClipData(cropRect, clipText, clipHtml, clipRect);
2063 EXPECT_STREQ(kExpectedClipText, clipText.utf8().c_str());
2064 EXPECT_STREQ(kExpectedClipHtml, clipHtml.utf8().c_str());
2067 TEST_F(WebViewTest, SmartClipReturnsEmptyStringsWhenUserSelectIsNone)
2069 WebString clipText;
2070 WebString clipHtml;
2071 WebRect clipRect;
2072 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("Ahem.ttf"));
2073 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("smartclip_user_select_none.html"));
2074 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "smartclip_user_select_none.html");
2075 webView->resize(WebSize(500, 500));
2076 webView->layout();
2077 WebRect cropRect(0, 0, 100, 100);
2078 webView->extractSmartClipData(cropRect, clipText, clipHtml, clipRect);
2079 EXPECT_STREQ("", clipText.utf8().c_str());
2080 EXPECT_STREQ("", clipHtml.utf8().c_str());
2083 class CreateChildCounterFrameClient : public FrameTestHelpers::TestWebFrameClient {
2084 public:
2085 CreateChildCounterFrameClient() : m_count(0) { }
2086 WebFrame* createChildFrame(WebLocalFrame* parent, WebTreeScopeType, const WebString& frameName, WebSandboxFlags) override;
2088 int count() const { return m_count; }
2090 private:
2091 int m_count;
2094 WebFrame* CreateChildCounterFrameClient::createChildFrame(WebLocalFrame* parent, WebTreeScopeType scope, const WebString& frameName, WebSandboxFlags sandboxFlags)
2096 ++m_count;
2097 return TestWebFrameClient::createChildFrame(parent, scope, frameName, sandboxFlags);
2100 TEST_F(WebViewTest, ChangeDisplayMode)
2102 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("display_mode.html"));
2103 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "display_mode.html", true);
2105 std::string content = webView->mainFrame()->contentAsText(21).utf8();
2106 EXPECT_EQ("regular-ui", content);
2108 webView->setDisplayMode(WebDisplayModeMinimalUi);
2109 content = webView->mainFrame()->contentAsText(21).utf8();
2110 EXPECT_EQ("minimal-ui", content);
2111 m_webViewHelper.reset();
2114 TEST_F(WebViewTest, AddFrameInCloseUnload)
2116 CreateChildCounterFrameClient frameClient;
2117 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("add_frame_in_unload.html"));
2118 m_webViewHelper.initializeAndLoad(m_baseURL + "add_frame_in_unload.html", true, &frameClient);
2119 m_webViewHelper.reset();
2120 EXPECT_EQ(0, frameClient.count());
2123 TEST_F(WebViewTest, AddFrameInCloseURLUnload)
2125 CreateChildCounterFrameClient frameClient;
2126 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("add_frame_in_unload.html"));
2127 m_webViewHelper.initializeAndLoad(m_baseURL + "add_frame_in_unload.html", true, &frameClient);
2128 m_webViewHelper.webViewImpl()->mainFrame()->dispatchUnloadEvent();
2129 EXPECT_EQ(0, frameClient.count());
2130 m_webViewHelper.reset();
2133 TEST_F(WebViewTest, AddFrameInNavigateUnload)
2135 CreateChildCounterFrameClient frameClient;
2136 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("add_frame_in_unload.html"));
2137 m_webViewHelper.initializeAndLoad(m_baseURL + "add_frame_in_unload.html", true, &frameClient);
2138 FrameTestHelpers::loadFrame(m_webViewHelper.webView()->mainFrame(), "about:blank");
2139 EXPECT_EQ(0, frameClient.count());
2140 m_webViewHelper.reset();
2143 TEST_F(WebViewTest, AddFrameInChildInNavigateUnload)
2145 CreateChildCounterFrameClient frameClient;
2146 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("add_frame_in_unload_wrapper.html"));
2147 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("add_frame_in_unload.html"));
2148 m_webViewHelper.initializeAndLoad(m_baseURL + "add_frame_in_unload_wrapper.html", true, &frameClient);
2149 FrameTestHelpers::loadFrame(m_webViewHelper.webView()->mainFrame(), "about:blank");
2150 EXPECT_EQ(1, frameClient.count());
2151 m_webViewHelper.reset();
2154 class TouchEventHandlerWebViewClient : public FrameTestHelpers::TestWebViewClient {
2155 public:
2156 // WebWidgetClient methods
2157 void hasTouchEventHandlers(bool state) override
2159 m_hasTouchEventHandlerCount[state]++;
2162 // Local methods
2163 TouchEventHandlerWebViewClient() : m_hasTouchEventHandlerCount()
2167 int getAndResetHasTouchEventHandlerCallCount(bool state)
2169 int value = m_hasTouchEventHandlerCount[state];
2170 m_hasTouchEventHandlerCount[state] = 0;
2171 return value;
2174 private:
2175 int m_hasTouchEventHandlerCount[2];
2178 // This test verifies that WebWidgetClient::hasTouchEventHandlers is called
2179 // accordingly for various calls to EventHandlerRegistry::did{Add|Remove|
2180 // RemoveAll}EventHandler(..., TouchEvent). Verifying that those calls are made
2181 // correctly is the job of LayoutTests/fast/events/event-handler-count.html.
2182 TEST_F(WebViewTest, HasTouchEventHandlers)
2184 TouchEventHandlerWebViewClient client;
2185 std::string url = m_baseURL + "has_touch_event_handlers.html";
2186 URLTestHelpers::registerMockedURLLoad(toKURL(url), "has_touch_event_handlers.html");
2187 WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(url, true, 0, &client);
2188 const EventHandlerRegistry::EventHandlerClass touchEvent = EventHandlerRegistry::TouchEvent;
2190 // The page is initialized with at least one no-handlers call.
2191 // In practice we get two such calls because WebViewHelper::initializeAndLoad first
2192 // initializes and empty frame, and then loads a document into it, so there are two
2193 // FrameLoader::commitProvisionalLoad calls.
2194 EXPECT_GE(client.getAndResetHasTouchEventHandlerCallCount(false), 1);
2195 EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
2197 // Adding the first document handler results in a has-handlers call.
2198 Document* document = webViewImpl->mainFrameImpl()->frame()->document();
2199 EventHandlerRegistry* registry = &document->frameHost()->eventHandlerRegistry();
2200 registry->didAddEventHandler(*document, touchEvent);
2201 EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
2202 EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(true));
2204 // Adding another handler has no effect.
2205 registry->didAddEventHandler(*document, touchEvent);
2206 EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
2207 EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
2209 // Removing the duplicate handler has no effect.
2210 registry->didRemoveEventHandler(*document, touchEvent);
2211 EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
2212 EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
2214 // Removing the final handler results in a no-handlers call.
2215 registry->didRemoveEventHandler(*document, touchEvent);
2216 EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(false));
2217 EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
2219 // Adding a handler on a div results in a has-handlers call.
2220 Element* parentDiv = document->getElementById("parentdiv");
2221 ASSERT(parentDiv);
2222 registry->didAddEventHandler(*parentDiv, touchEvent);
2223 EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
2224 EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(true));
2226 // Adding a duplicate handler on the div, clearing all document handlers
2227 // (of which there are none) and removing the extra handler on the div
2228 // all have no effect.
2229 registry->didAddEventHandler(*parentDiv, touchEvent);
2230 registry->didRemoveAllEventHandlers(*document);
2231 registry->didRemoveEventHandler(*parentDiv, touchEvent);
2232 EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
2233 EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
2235 // Removing the final handler on the div results in a no-handlers call.
2236 registry->didRemoveEventHandler(*parentDiv, touchEvent);
2237 EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(false));
2238 EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
2240 // Adding two handlers then clearing them in a single call results in a
2241 // has-handlers then no-handlers call.
2242 registry->didAddEventHandler(*parentDiv, touchEvent);
2243 EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
2244 EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(true));
2245 registry->didAddEventHandler(*parentDiv, touchEvent);
2246 EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
2247 EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
2248 registry->didRemoveAllEventHandlers(*parentDiv);
2249 EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(false));
2250 EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
2252 // Adding a handler inside of a child iframe results in a has-handlers call.
2253 Element* childFrame = document->getElementById("childframe");
2254 ASSERT(childFrame);
2255 Document* childDocument = toHTMLIFrameElement(childFrame)->contentDocument();
2256 Element* childDiv = childDocument->getElementById("childdiv");
2257 ASSERT(childDiv);
2258 registry->didAddEventHandler(*childDiv, touchEvent);
2259 EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
2260 EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(true));
2262 // Adding and clearing handlers in the parent doc or elsewhere in the child doc
2263 // has no impact.
2264 registry->didAddEventHandler(*document, touchEvent);
2265 registry->didAddEventHandler(*childFrame, touchEvent);
2266 registry->didAddEventHandler(*childDocument, touchEvent);
2267 registry->didRemoveAllEventHandlers(*document);
2268 registry->didRemoveAllEventHandlers(*childFrame);
2269 registry->didRemoveAllEventHandlers(*childDocument);
2270 EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
2271 EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
2273 // Removing the final handler inside the child frame results in a no-handlers call.
2274 registry->didRemoveAllEventHandlers(*childDiv);
2275 EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(false));
2276 EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
2278 // Adding a handler inside the child frame results in a has-handlers call.
2279 registry->didAddEventHandler(*childDocument, touchEvent);
2280 EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
2281 EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(true));
2283 // Adding a handler in the parent document and removing the one in the frame
2284 // has no effect.
2285 registry->didAddEventHandler(*childFrame, touchEvent);
2286 registry->didRemoveEventHandler(*childDocument, touchEvent);
2287 registry->didRemoveAllEventHandlers(*childDocument);
2288 registry->didRemoveAllEventHandlers(*document);
2289 EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
2290 EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
2292 // Now removing the handler in the parent document results in a no-handlers call.
2293 registry->didRemoveEventHandler(*childFrame, touchEvent);
2294 EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(false));
2295 EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
2297 // Free the webView before the TouchEventHandlerWebViewClient gets freed.
2298 m_webViewHelper.reset();
2301 // This test checks that deleting nodes which have only non-JS-registered touch
2302 // handlers also removes them from the event handler registry. Note that this
2303 // is different from detaching and re-attaching the same node, which is covered
2304 // by layout tests under fast/events/.
2305 TEST_F(WebViewTest, DeleteElementWithRegisteredHandler)
2307 std::string url = m_baseURL + "simple_div.html";
2308 URLTestHelpers::registerMockedURLLoad(toKURL(url), "simple_div.html");
2309 WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(url, true);
2311 RefPtrWillBePersistent<Document> document = webViewImpl->mainFrameImpl()->frame()->document();
2312 Element* div = document->getElementById("div");
2313 EventHandlerRegistry& registry = document->frameHost()->eventHandlerRegistry();
2315 registry.didAddEventHandler(*div, EventHandlerRegistry::ScrollEvent);
2316 EXPECT_TRUE(registry.hasEventHandlers(EventHandlerRegistry::ScrollEvent));
2318 TrackExceptionState exceptionState;
2319 div->remove(exceptionState);
2320 #if ENABLE(OILPAN)
2321 // For oilpan we have to force a GC to ensure the event handlers have been removed when
2322 // checking below. We do a precise GC (collectAllGarbage does not scan the stack)
2323 // to ensure the div element dies. This is also why the Document is in a Persistent
2324 // since we want that to stay around.
2325 Heap::collectAllGarbage();
2326 #endif
2327 EXPECT_FALSE(registry.hasEventHandlers(EventHandlerRegistry::ScrollEvent));
2330 class NonUserInputTextUpdateWebViewClient : public FrameTestHelpers::TestWebViewClient {
2331 public:
2332 NonUserInputTextUpdateWebViewClient() : m_textIsUpdated(false) { }
2334 // WebWidgetClient methods
2335 void didUpdateTextOfFocusedElementByNonUserInput() override
2337 m_textIsUpdated = true;
2340 void reset()
2342 m_textIsUpdated = false;
2345 bool textIsUpdated() const
2347 return m_textIsUpdated;
2350 private:
2351 int m_textIsUpdated;
2354 // This test verifies the text input flags are correctly exposed to script.
2355 TEST_F(WebViewTest, TextInputFlags)
2357 NonUserInputTextUpdateWebViewClient client;
2358 std::string url = m_baseURL + "text_input_flags.html";
2359 URLTestHelpers::registerMockedURLLoad(toKURL(url), "text_input_flags.html");
2360 WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(url, true, 0, &client);
2361 webViewImpl->setInitialFocus(false);
2363 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewImpl->mainFrame());
2364 HTMLDocument* document = toHTMLDocument(frame->frame()->document());
2366 // (A) <input>
2367 // (A.1) Verifies autocorrect/autocomplete/spellcheck flags are Off and
2368 // autocapitalize is set to none.
2369 HTMLInputElement* inputElement = toHTMLInputElement(document->getElementById("input"));
2370 document->setFocusedElement(inputElement);
2371 webViewImpl->setFocus(true);
2372 WebTextInputInfo info = webViewImpl->textInputInfo();
2373 EXPECT_EQ(
2374 WebTextInputFlagAutocompleteOff | WebTextInputFlagAutocorrectOff | WebTextInputFlagSpellcheckOff | WebTextInputFlagAutocapitalizeNone,
2375 info.flags);
2377 // (A.2) Verifies autocorrect/autocomplete/spellcheck flags are On and
2378 // autocapitalize is set to sentences.
2379 inputElement = toHTMLInputElement(document->getElementById("input2"));
2380 document->setFocusedElement(inputElement);
2381 webViewImpl->setFocus(true);
2382 info = webViewImpl->textInputInfo();
2383 EXPECT_EQ(
2384 WebTextInputFlagAutocompleteOn | WebTextInputFlagAutocorrectOn | WebTextInputFlagSpellcheckOn | WebTextInputFlagAutocapitalizeSentences,
2385 info.flags);
2387 // (B) <textarea> Verifies the default text input flags are
2388 // WebTextInputFlagAutocapitalizeSentences.
2389 HTMLTextAreaElement* textAreaElement = toHTMLTextAreaElement(document->getElementById("textarea"));
2390 document->setFocusedElement(textAreaElement);
2391 webViewImpl->setFocus(true);
2392 info = webViewImpl->textInputInfo();
2393 EXPECT_EQ(WebTextInputFlagAutocapitalizeSentences, info.flags);
2395 // Free the webView before freeing the NonUserInputTextUpdateWebViewClient.
2396 m_webViewHelper.reset();
2399 // This test verifies that WebWidgetClient::didUpdateTextOfFocusedElementByNonUserInput is
2400 // called iff value of a focused element is modified via script.
2401 TEST_F(WebViewTest, NonUserInputTextUpdate)
2403 NonUserInputTextUpdateWebViewClient client;
2404 std::string url = m_baseURL + "non_user_input_text_update.html";
2405 URLTestHelpers::registerMockedURLLoad(toKURL(url), "non_user_input_text_update.html");
2406 WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(url, true, 0, &client);
2407 webViewImpl->setInitialFocus(false);
2409 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewImpl->mainFrame());
2410 HTMLDocument* document = toHTMLDocument(frame->frame()->document());
2412 // (A) <input>
2413 // (A.1) Focused and value is changed by script.
2414 client.reset();
2415 EXPECT_FALSE(client.textIsUpdated());
2417 HTMLInputElement* inputElement = toHTMLInputElement(document->getElementById("input"));
2418 document->setFocusedElement(inputElement);
2419 webViewImpl->setFocus(true);
2420 EXPECT_EQ(document->focusedElement(), static_cast<Element*>(inputElement));
2422 // Emulate value change from script.
2423 inputElement->setValue("testA");
2424 EXPECT_TRUE(client.textIsUpdated());
2425 WebTextInputInfo info = webViewImpl->textInputInfo();
2426 EXPECT_EQ("testA", std::string(info.value.utf8().data()));
2428 // (A.2) Focused and user input modifies value.
2429 client.reset();
2430 EXPECT_FALSE(client.textIsUpdated());
2432 WebVector<WebCompositionUnderline> emptyUnderlines;
2433 webViewImpl->setComposition(WebString::fromUTF8("2"), emptyUnderlines, 1, 1);
2434 webViewImpl->confirmComposition(WebWidget::KeepSelection);
2435 EXPECT_FALSE(client.textIsUpdated());
2436 info = webViewImpl->textInputInfo();
2437 EXPECT_EQ("testA2", std::string(info.value.utf8().data()));
2439 // (A.3) Unfocused and value is changed by script.
2440 client.reset();
2441 EXPECT_FALSE(client.textIsUpdated());
2442 document->setFocusedElement(nullptr);
2443 webViewImpl->setFocus(false);
2444 EXPECT_NE(document->focusedElement(), static_cast<Element*>(inputElement));
2445 inputElement->setValue("testA3");
2446 EXPECT_FALSE(client.textIsUpdated());
2448 // (B) <textarea>
2449 // (B.1) Focused and value is changed by script.
2450 client.reset();
2451 EXPECT_FALSE(client.textIsUpdated());
2452 HTMLTextAreaElement* textAreaElement = toHTMLTextAreaElement(document->getElementById("textarea"));
2453 document->setFocusedElement(textAreaElement);
2454 webViewImpl->setFocus(true);
2455 EXPECT_EQ(document->focusedElement(), static_cast<Element*>(textAreaElement));
2456 textAreaElement->setValue("testB");
2457 EXPECT_TRUE(client.textIsUpdated());
2458 info = webViewImpl->textInputInfo();
2459 EXPECT_EQ("testB", std::string(info.value.utf8().data()));
2461 // (B.2) Focused and user input modifies value.
2462 client.reset();
2463 EXPECT_FALSE(client.textIsUpdated());
2464 webViewImpl->setComposition(WebString::fromUTF8("2"), emptyUnderlines, 1, 1);
2465 webViewImpl->confirmComposition(WebWidget::KeepSelection);
2466 info = webViewImpl->textInputInfo();
2467 EXPECT_EQ("testB2", std::string(info.value.utf8().data()));
2469 // (B.3) Unfocused and value is changed by script.
2470 client.reset();
2471 EXPECT_FALSE(client.textIsUpdated());
2472 document->setFocusedElement(nullptr);
2473 webViewImpl->setFocus(false);
2474 EXPECT_NE(document->focusedElement(), static_cast<Element*>(textAreaElement));
2475 inputElement->setValue("testB3");
2476 EXPECT_FALSE(client.textIsUpdated());
2478 // Free the webView before freeing the NonUserInputTextUpdateWebViewClient.
2479 m_webViewHelper.reset();
2482 // Check that the WebAutofillClient is correctly notified about first user
2483 // gestures after load, following various input events.
2484 TEST_F(WebViewTest, FirstUserGestureObservedKeyEvent)
2486 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("form.html"));
2487 MockAutofillClient client;
2488 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "form.html", true);
2489 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
2490 frame->setAutofillClient(&client);
2491 webView->setInitialFocus(false);
2493 EXPECT_EQ(0, client.getUserGestureNotificationsCount());
2495 WebKeyboardEvent keyEvent;
2496 keyEvent.windowsKeyCode = VKEY_SPACE;
2497 keyEvent.type = WebInputEvent::RawKeyDown;
2498 keyEvent.setKeyIdentifierFromWindowsKeyCode();
2499 webView->handleInputEvent(keyEvent);
2500 keyEvent.type = WebInputEvent::KeyUp;
2501 webView->handleInputEvent(keyEvent);
2503 EXPECT_EQ(1, client.getUserGestureNotificationsCount());
2504 frame->setAutofillClient(0);
2507 TEST_F(WebViewTest, FirstUserGestureObservedMouseEvent)
2509 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("form.html"));
2510 MockAutofillClient client;
2511 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "form.html", true);
2512 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
2513 frame->setAutofillClient(&client);
2514 webView->setInitialFocus(false);
2516 EXPECT_EQ(0, client.getUserGestureNotificationsCount());
2518 WebMouseEvent mouseEvent;
2519 mouseEvent.button = WebMouseEvent::ButtonLeft;
2520 mouseEvent.x = 1;
2521 mouseEvent.y = 1;
2522 mouseEvent.clickCount = 1;
2523 mouseEvent.type = WebInputEvent::MouseDown;
2524 webView->handleInputEvent(mouseEvent);
2525 mouseEvent.type = WebInputEvent::MouseUp;
2526 webView->handleInputEvent(mouseEvent);
2528 EXPECT_EQ(1, client.getUserGestureNotificationsCount());
2529 frame->setAutofillClient(0);
2532 TEST_F(WebViewTest, FirstUserGestureObservedGestureTap)
2534 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("longpress_selection.html"));
2535 MockAutofillClient client;
2536 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "longpress_selection.html", true);
2537 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
2538 frame->setAutofillClient(&client);
2539 webView->setInitialFocus(false);
2541 EXPECT_EQ(0, client.getUserGestureNotificationsCount());
2543 EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, WebString::fromUTF8("target")));
2545 EXPECT_EQ(1, client.getUserGestureNotificationsCount());
2546 frame->setAutofillClient(0);
2549 TEST_F(WebViewTest, CompositionIsUserGesture)
2551 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
2552 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html");
2553 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
2554 MockAutofillClient client;
2555 frame->setAutofillClient(&client);
2556 webView->setInitialFocus(false);
2558 EXPECT_TRUE(webView->setComposition(WebString::fromUTF8(std::string("hello").c_str()), WebVector<WebCompositionUnderline>(), 3, 3));
2559 EXPECT_EQ(1, client.textChangesFromUserGesture());
2560 EXPECT_FALSE(UserGestureIndicator::processingUserGesture());
2561 EXPECT_TRUE(frame->hasMarkedText());
2563 frame->setAutofillClient(0);
2566 TEST_F(WebViewTest, CompareSelectAllToContentAsText)
2568 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("longpress_selection.html"));
2569 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "longpress_selection.html", true);
2571 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
2572 frame->executeScript(WebScriptSource(WebString::fromUTF8("document.execCommand('SelectAll', false, null)")));
2573 std::string actual = frame->selectionAsText().utf8();
2575 const int kMaxOutputCharacters = 1024;
2576 std::string expected = frame->contentAsText(kMaxOutputCharacters).utf8();
2577 EXPECT_EQ(expected, actual);
2580 TEST_F(WebViewTest, AutoResizeSubtreeLayout)
2582 std::string url = m_baseURL + "subtree-layout.html";
2583 URLTestHelpers::registerMockedURLLoad(toKURL(url), "subtree-layout.html");
2584 WebView* webView = m_webViewHelper.initialize(true);
2586 webView->enableAutoResizeMode(WebSize(200, 200), WebSize(200, 200));
2587 loadFrame(webView->mainFrame(), url);
2589 FrameView* frameView = m_webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
2591 // Auto-resizing used to ASSERT(needsLayout()) in LayoutBlockFlow::layout. This EXPECT is
2592 // merely a dummy. The real test is that we don't trigger asserts in debug builds.
2593 EXPECT_FALSE(frameView->needsLayout());
2596 TEST_F(WebViewTest, PreferredSize)
2598 std::string url = m_baseURL + "specify_size.html?100px:100px";
2599 URLTestHelpers::registerMockedURLLoad(toKURL(url), "specify_size.html");
2600 WebView* webView = m_webViewHelper.initializeAndLoad(url, true);
2602 WebSize size = webView->contentsPreferredMinimumSize();
2603 EXPECT_EQ(100, size.width);
2604 EXPECT_EQ(100, size.height);
2606 webView->setZoomLevel(WebView::zoomFactorToZoomLevel(2.0));
2607 size = webView->contentsPreferredMinimumSize();
2608 EXPECT_EQ(200, size.width);
2609 EXPECT_EQ(200, size.height);
2611 // Verify that both width and height are rounded (in this case up)
2612 webView->setZoomLevel(WebView::zoomFactorToZoomLevel(0.9995));
2613 size = webView->contentsPreferredMinimumSize();
2614 EXPECT_EQ(100, size.width);
2615 EXPECT_EQ(100, size.height);
2617 // Verify that both width and height are rounded (in this case down)
2618 webView->setZoomLevel(WebView::zoomFactorToZoomLevel(1.0005));
2619 size = webView->contentsPreferredMinimumSize();
2620 EXPECT_EQ(100, size.width);
2621 EXPECT_EQ(100, size.height);
2623 url = m_baseURL + "specify_size.html?1.5px:1.5px";
2624 URLTestHelpers::registerMockedURLLoad(toKURL(url), "specify_size.html");
2625 webView = m_webViewHelper.initializeAndLoad(url, true);
2627 webView->setZoomLevel(WebView::zoomFactorToZoomLevel(1));
2628 size = webView->contentsPreferredMinimumSize();
2629 EXPECT_EQ(2, size.width);
2630 EXPECT_EQ(2, size.height);
2633 TEST_F(WebViewTest, PreferredSizeDirtyLayout)
2635 std::string url = m_baseURL + "specify_size.html?100px:100px";
2636 URLTestHelpers::registerMockedURLLoad(toKURL(url), "specify_size.html");
2637 WebView* webView = m_webViewHelper.initializeAndLoad(url, true);
2638 WebElement documentElement = webView->mainFrame()->document().documentElement();
2640 WebSize size = webView->contentsPreferredMinimumSize();
2641 EXPECT_EQ(100, size.width);
2642 EXPECT_EQ(100, size.height);
2644 bool setStyle = documentElement.setAttribute("style", "display: none");
2645 EXPECT_TRUE(setStyle);
2647 size = webView->contentsPreferredMinimumSize();
2648 EXPECT_EQ(0, size.width);
2649 EXPECT_EQ(0, size.height);
2652 class UnhandledTapWebViewClient : public FrameTestHelpers::TestWebViewClient {
2653 public:
2654 void showUnhandledTapUIIfNeeded(const WebPoint& tappedPosition, const WebNode& tappedNode, bool pageChanged) override
2656 m_wasCalled = true;
2657 m_tappedPosition = tappedPosition;
2658 m_tappedNode = tappedNode;
2659 m_pageChanged = pageChanged;
2661 bool getWasCalled() const { return m_wasCalled; }
2662 int getTappedXPos() const { return m_tappedPosition.x(); }
2663 int getTappedYPos() const { return m_tappedPosition.y(); }
2664 bool isTappedNodeNull() const { return m_tappedNode.isNull(); }
2665 const WebNode& getWebNode() const { return m_tappedNode; }
2666 bool getPageChanged() const { return m_pageChanged; }
2667 void reset()
2669 m_wasCalled = false;
2670 m_tappedPosition = IntPoint();
2671 m_tappedNode = WebNode();
2672 m_pageChanged = false;
2674 private:
2675 bool m_wasCalled = false;
2676 IntPoint m_tappedPosition;
2677 WebNode m_tappedNode;
2678 bool m_pageChanged = false;
2681 TEST_F(WebViewTest, ShowUnhandledTapUIIfNeeded)
2683 std::string testFile = "show_unhandled_tap.html";
2684 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("Ahem.ttf"));
2685 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8(testFile));
2686 UnhandledTapWebViewClient client;
2687 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + testFile, true, 0, &client);
2688 webView->resize(WebSize(500, 300));
2689 webView->layout();
2690 runPendingTasks();
2692 // Scroll the bottom into view so we can distinguish window coordinates from document coordinates.
2693 EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, WebString::fromUTF8("bottom")));
2694 EXPECT_TRUE(client.getWasCalled());
2695 EXPECT_EQ(64, client.getTappedXPos());
2696 EXPECT_EQ(278, client.getTappedYPos());
2697 EXPECT_FALSE(client.isTappedNodeNull());
2698 EXPECT_TRUE(client.getWebNode().isTextNode());
2700 // Test basic tap handling and notification.
2701 client.reset();
2702 EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, WebString::fromUTF8("target")));
2703 EXPECT_TRUE(client.getWasCalled());
2704 EXPECT_EQ(144, client.getTappedXPos());
2705 EXPECT_EQ(82, client.getTappedYPos());
2706 EXPECT_FALSE(client.isTappedNodeNull());
2707 EXPECT_TRUE(client.getWebNode().isTextNode());
2708 // Make sure the returned text node has the parent element that was our target.
2709 EXPECT_EQ(webView->mainFrame()->document().getElementById("target"), client.getWebNode().parentNode());
2711 // Test correct conversion of coordinates to viewport space under pinch-zoom.
2712 webView->setPageScaleFactor(2);
2713 webView->setVisualViewportOffset(WebFloatPoint(50, 20));
2714 client.reset();
2715 EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, WebString::fromUTF8("target")));
2716 EXPECT_TRUE(client.getWasCalled());
2717 EXPECT_EQ(188, client.getTappedXPos());
2718 EXPECT_EQ(124, client.getTappedYPos());
2720 m_webViewHelper.reset(); // Remove dependency on locally scoped client.
2723 #define TEST_EACH_MOUSEEVENT(handler, EXPECT) \
2724 frame->executeScript(WebScriptSource("setTest('mousedown-" handler "');")); \
2725 EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, WebString::fromUTF8("target"))); \
2726 EXPECT_##EXPECT(client.getPageChanged()); \
2727 client.reset(); \
2728 frame->executeScript(WebScriptSource("setTest('mouseup-" handler "');")); \
2729 EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, WebString::fromUTF8("target"))); \
2730 EXPECT_##EXPECT(client.getPageChanged()); \
2731 client.reset(); \
2732 frame->executeScript(WebScriptSource("setTest('mousemove-" handler "');")); \
2733 EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, WebString::fromUTF8("target"))); \
2734 EXPECT_##EXPECT(client.getPageChanged()); \
2735 client.reset(); \
2736 frame->executeScript(WebScriptSource("setTest('click-" handler "');")); \
2737 EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, WebString::fromUTF8("target"))); \
2738 EXPECT_##EXPECT(client.getPageChanged());
2740 TEST_F(WebViewTest, ShowUnhandledTapUIIfNeededWithMutateDom)
2742 std::string testFile = "show_unhandled_tap.html";
2743 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("Ahem.ttf"));
2744 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8(testFile));
2745 UnhandledTapWebViewClient client;
2746 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + testFile, true, 0, &client);
2747 webView->resize(WebSize(500, 300));
2748 webView->layout();
2749 runPendingTasks();
2750 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
2752 // Test dom mutation.
2753 TEST_EACH_MOUSEEVENT("mutateDom", TRUE);
2755 // Test without any DOM mutation.
2756 client.reset();
2757 frame->executeScript(WebScriptSource("setTest('none');"));
2758 EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, WebString::fromUTF8("target")));
2759 EXPECT_FALSE(client.getPageChanged());
2761 m_webViewHelper.reset(); // Remove dependency on locally scoped client.
2764 TEST_F(WebViewTest, ShowUnhandledTapUIIfNeededWithMutateStyle)
2766 std::string testFile = "show_unhandled_tap.html";
2767 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("Ahem.ttf"));
2768 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8(testFile));
2769 UnhandledTapWebViewClient client;
2770 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + testFile, true, 0, &client);
2771 webView->resize(WebSize(500, 300));
2772 webView->layout();
2773 runPendingTasks();
2774 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
2776 // Test style mutation.
2777 TEST_EACH_MOUSEEVENT("mutateStyle", TRUE);
2779 // Test checkbox:indeterminate style mutation.
2780 TEST_EACH_MOUSEEVENT("mutateIndeterminate", TRUE);
2782 // Test click div with :active style but it is not covered for now.
2783 client.reset();
2784 EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, WebString::fromUTF8("style_active")));
2785 EXPECT_FALSE(client.getPageChanged());
2787 // Test without any style mutation.
2788 client.reset();
2789 frame->executeScript(WebScriptSource("setTest('none');"));
2790 EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, WebString::fromUTF8("target")));
2791 EXPECT_FALSE(client.getPageChanged());
2793 m_webViewHelper.reset(); // Remove dependency on locally scoped client.
2796 TEST_F(WebViewTest, ShowUnhandledTapUIIfNeededWithPreventDefault)
2798 std::string testFile = "show_unhandled_tap.html";
2799 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("Ahem.ttf"));
2800 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8(testFile));
2801 UnhandledTapWebViewClient client;
2802 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + testFile, true, 0, &client);
2803 webView->resize(WebSize(500, 300));
2804 webView->layout();
2805 runPendingTasks();
2806 WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
2808 // Testswallowing.
2809 TEST_EACH_MOUSEEVENT("preventDefault", FALSE);
2811 // Test without any preventDefault.
2812 client.reset();
2813 frame->executeScript(WebScriptSource("setTest('none');"));
2814 EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, WebString::fromUTF8("target")));
2815 EXPECT_TRUE(client.getWasCalled());
2817 m_webViewHelper.reset(); // Remove dependency on locally scoped client.
2820 // Test 3 frames, all on the same layer (i.e. [1 2 3])
2821 TEST_F(WebViewTest, TestPushFrameTimingRequestRectsToGraphicsLayer1)
2823 std::string url = m_baseURL + "frame_timing_inner.html?100px:100px";
2824 registerMockedURLLoad(toKURL(url), "frame_timing_inner.html");
2825 url = m_baseURL + "frame_timing_inner.html?200px:200px";
2826 registerMockedURLLoad(toKURL(url), "frame_timing_inner.html");
2827 url = m_baseURL + "frame_timing_inner.html?300px:300px";
2828 registerMockedURLLoad(toKURL(url), "frame_timing_inner.html");
2829 url = m_baseURL + "frame_timing_1.html";
2830 registerMockedURLLoad(toKURL(url), "frame_timing_1.html");
2832 WebView* webView = m_webViewHelper.initialize(true);
2833 loadFrame(webView->mainFrame(), url);
2835 webView->resize(WebSize(800, 600));
2836 webView->layout();
2838 WebViewImpl* webViewImpl = toWebViewImpl(webView);
2840 Frame* frame = webViewImpl->page()->mainFrame();
2841 int64_t id = frame->frameID();
2843 EXPECT_EQ(3u, frame->tree().childCount());
2845 WebVector<std::pair<int64_t, WebRect>> frameTimingRequests =
2846 toLocalFrame(frame)->document()
2847 ->layoutView()->enclosingLayer()
2848 ->enclosingLayerForPaintInvalidationCrossingFrameBoundaries()
2849 ->graphicsLayerBacking()->platformLayer()->frameTimingRequests();
2851 EXPECT_EQ(4u, frameTimingRequests.size());
2852 EXPECT_EQ(id + 0, frameTimingRequests[0].first);
2853 EXPECT_EQ(WebRect(0, 0, 800, 600), frameTimingRequests[0].second);
2854 EXPECT_EQ(id + 1, frameTimingRequests[1].first);
2855 EXPECT_EQ(WebRect(2, 2, 100, 100), frameTimingRequests[1].second);
2856 EXPECT_EQ(id + 2, frameTimingRequests[2].first);
2857 EXPECT_EQ(WebRect(106, 2, 200, 200), frameTimingRequests[2].second);
2858 EXPECT_EQ(id + 3, frameTimingRequests[3].first);
2859 EXPECT_EQ(WebRect(310, 2, 300, 300), frameTimingRequests[3].second);
2862 // Test 3 frames, where frame 2 is on a different GraphicsLayer (i.e. [1 2' 3])
2863 TEST_F(WebViewTest, TestPushFrameTimingRequestRectsToGraphicsLayer2)
2865 std::string url = m_baseURL + "frame_timing_inner.html?100px:100px";
2866 registerMockedURLLoad(toKURL(url), "frame_timing_inner.html");
2867 url = m_baseURL + "frame_timing_inner.html?200px:200px";
2868 registerMockedURLLoad(toKURL(url), "frame_timing_inner.html");
2869 url = m_baseURL + "frame_timing_inner.html?300px:300px";
2870 registerMockedURLLoad(toKURL(url), "frame_timing_inner.html");
2871 url = m_baseURL + "frame_timing_2.html";
2872 registerMockedURLLoad(toKURL(url), "frame_timing_2.html");
2874 WebView* webView = m_webViewHelper.initialize(true);
2875 loadFrame(webView->mainFrame(), url);
2877 webView->resize(WebSize(800, 600));
2878 webView->layout();
2880 WebViewImpl* webViewImpl = toWebViewImpl(webView);
2882 Frame* frame = webViewImpl->page()->mainFrame();
2883 int64_t id = frame->frameID();
2885 EXPECT_EQ(3u, frame->tree().childCount());
2887 const WebLayer* graphicsLayer1 =
2888 toLocalFrame(webViewImpl->page()->mainFrame())->document()
2889 ->layoutView()->enclosingLayer()
2890 ->enclosingLayerForPaintInvalidationCrossingFrameBoundaries()
2891 ->graphicsLayerBacking()->platformLayer();
2892 WebVector<std::pair<int64_t, WebRect>> frameTimingRequests1 =
2893 graphicsLayer1->frameTimingRequests();
2895 EXPECT_EQ(3u, frameTimingRequests1.size());
2896 EXPECT_EQ(id + 0, frameTimingRequests1[0].first);
2897 EXPECT_EQ(WebRect(0, 0, 800, 600), frameTimingRequests1[0].second);
2898 EXPECT_EQ(id + 1, frameTimingRequests1[1].first);
2899 EXPECT_EQ(WebRect(2, 2, 100, 100), frameTimingRequests1[1].second);
2900 EXPECT_EQ(id + 3, frameTimingRequests1[2].first);
2901 EXPECT_EQ(WebRect(310, 2, 300, 300), frameTimingRequests1[2].second);
2903 const WebLayer* graphicsLayer2 = nullptr;
2904 for (Frame* frame = webViewImpl->page()->mainFrame(); frame;
2905 frame = frame->tree().traverseNext()) {
2906 graphicsLayer2 = toLocalFrame(frame)->document()->layoutView()
2907 ->enclosingLayer()
2908 ->enclosingLayerForPaintInvalidationCrossingFrameBoundaries()
2909 ->graphicsLayerBacking()->platformLayer();
2910 if (graphicsLayer2 != graphicsLayer1)
2911 break;
2913 WebVector<std::pair<int64_t, WebRect>> frameTimingRequests2 =
2914 graphicsLayer2->frameTimingRequests();
2915 EXPECT_EQ(1u, frameTimingRequests2.size());
2916 EXPECT_EQ(id + 2, frameTimingRequests2[0].first);
2917 EXPECT_EQ(WebRect(2, 2, 200, 200), frameTimingRequests2[0].second);
2921 // Test nested frames (i.e. [1 2'[4 5'] 3])
2922 TEST_F(WebViewTest, TestPushFrameTimingRequestRectsToGraphicsLayer3)
2924 std::string url = m_baseURL + "frame_timing_inner.html?100px:100px";
2925 registerMockedURLLoad(toKURL(url), "frame_timing_inner.html");
2926 url = m_baseURL + "frame_timing_inner.html?200px:200px";
2927 registerMockedURLLoad(toKURL(url), "frame_timing_inner.html");
2928 url = m_baseURL + "frame_timing_inner.html?300px:300px";
2929 registerMockedURLLoad(toKURL(url), "frame_timing_inner.html");
2930 url = m_baseURL + "frame_timing_b.html";
2931 registerMockedURLLoad(toKURL(url), "frame_timing_b.html");
2932 url = m_baseURL + "frame_timing_3.html";
2933 registerMockedURLLoad(toKURL(url), "frame_timing_3.html");
2935 WebView* webView = m_webViewHelper.initialize(true);
2936 loadFrame(webView->mainFrame(), url);
2938 webView->resize(WebSize(800, 600));
2939 webView->layout();
2941 WebViewImpl* webViewImpl = toWebViewImpl(webView);
2943 Frame* frame = webViewImpl->page()->mainFrame();
2944 int64_t id = frame->frameID();
2946 EXPECT_EQ(3u, frame->tree().childCount());
2948 const WebLayer* graphicsLayer1 =
2949 toLocalFrame(webViewImpl->page()->mainFrame())->document()
2950 ->layoutView()->enclosingLayer()
2951 ->enclosingLayerForPaintInvalidationCrossingFrameBoundaries()
2952 ->graphicsLayerBacking()->platformLayer();
2953 WebVector<std::pair<int64_t, WebRect>> frameTimingRequests1 =
2954 graphicsLayer1->frameTimingRequests();
2956 EXPECT_EQ(3u, frameTimingRequests1.size());
2957 EXPECT_EQ(id + 0, frameTimingRequests1[0].first);
2958 EXPECT_EQ(WebRect(0, 0, 800, 600), frameTimingRequests1[0].second);
2959 EXPECT_EQ(WebRect(2, 2, 100, 100), frameTimingRequests1[1].second);
2960 EXPECT_EQ(WebRect(410, 2, 200, 200), frameTimingRequests1[2].second);
2962 const WebLayer* graphicsLayer2 = nullptr;
2963 for (Frame* frame = webViewImpl->page()->mainFrame(); frame;
2964 frame = frame->tree().traverseNext()) {
2965 graphicsLayer2 = toLocalFrame(frame)->document()->layoutView()
2966 ->enclosingLayer()
2967 ->enclosingLayerForPaintInvalidationCrossingFrameBoundaries()
2968 ->graphicsLayerBacking()->platformLayer();
2969 if (graphicsLayer2 != graphicsLayer1)
2970 break;
2972 WebVector<std::pair<int64_t, WebRect>> frameTimingRequests2 =
2973 graphicsLayer2->frameTimingRequests();
2974 EXPECT_EQ(2u, frameTimingRequests2.size());
2975 EXPECT_EQ(WebRect(0, 0, 300, 300), frameTimingRequests2[0].second);
2976 EXPECT_EQ(WebRect(2, 2, 100, 100), frameTimingRequests2[1].second);
2978 const WebLayer* graphicsLayer3 = nullptr;
2979 for (Frame* frame = webViewImpl->page()->mainFrame(); frame;
2980 frame = frame->tree().traverseNext()) {
2981 graphicsLayer3 = toLocalFrame(frame)->document()->layoutView()
2982 ->enclosingLayer()
2983 ->enclosingLayerForPaintInvalidationCrossingFrameBoundaries()
2984 ->graphicsLayerBacking()->platformLayer();
2985 if (graphicsLayer3 != graphicsLayer1 && graphicsLayer3 != graphicsLayer2)
2986 break;
2988 WebVector<std::pair<int64_t, WebRect>> frameTimingRequests3 =
2989 graphicsLayer3->frameTimingRequests();
2990 EXPECT_EQ(1u, frameTimingRequests3.size());
2991 EXPECT_EQ(WebRect(2, 2, 100, 100), frameTimingRequests3[0].second);
2994 // Test 3 frames, all on the same layer (i.e. [1 2 3])
2995 // Fails on android, see crbug.com/488381.
2996 #if OS(ANDROID)
2997 TEST_F(WebViewTest, DISABLED_TestRecordFrameTimingEvents)
2998 #else
2999 TEST_F(WebViewTest, TestRecordFrameTimingEvents)
3000 #endif
3002 std::string url = m_baseURL + "frame_timing_inner.html?100px:100px";
3003 registerMockedURLLoad(toKURL(url), "frame_timing_inner.html");
3004 url = m_baseURL + "frame_timing_inner.html?200px:200px";
3005 registerMockedURLLoad(toKURL(url), "frame_timing_inner.html");
3006 url = m_baseURL + "frame_timing_inner.html?300px:300px";
3007 registerMockedURLLoad(toKURL(url), "frame_timing_inner.html");
3008 url = m_baseURL + "frame_timing_1.html";
3009 registerMockedURLLoad(toKURL(url), "frame_timing_1.html");
3011 WebView* webView = m_webViewHelper.initialize(true);
3012 loadFrame(webView->mainFrame(), url);
3014 webView->resize(WebSize(800, 600));
3015 webView->layout();
3017 WebViewImpl* webViewImpl = toWebViewImpl(webView);
3019 Frame* frame = webViewImpl->page()->mainFrame();
3020 int64_t id = frame->frameID();
3022 std::vector<WebFrameTimingEvent> compositePairs(3);
3023 compositePairs[0] = WebFrameTimingEvent(1, 2.0);
3024 compositePairs[1] = WebFrameTimingEvent(2, 3.0);
3025 compositePairs[2] = WebFrameTimingEvent(3, 4.0);
3026 WebVector<WebFrameTimingEvent> compositeEvents(compositePairs);
3027 webViewImpl->recordFrameTimingEvent(WebView::CompositeEvent, id, compositeEvents);
3028 PerformanceEntryVector composites = DOMWindowPerformance::performance(*frame->domWindow())->getEntriesByType("composite");
3029 PerformanceEntryVector renders = DOMWindowPerformance::performance(*frame->domWindow())->getEntriesByType("render");
3030 ASSERT_EQ(3ul, composites.size());
3031 ASSERT_EQ(0ul, renders.size());
3032 for (size_t i = 0; i < composites.size(); ++i) {
3033 double docTime = frame->domWindow()->document()->loader()->timing().monotonicTimeToZeroBasedDocumentTime(compositePairs[i].startTime) * 1000.0;
3034 ASSERT_EQ(docTime, composites[i]->startTime());
3037 // Skip ahead to subframe 2.
3038 frame = frame->tree().traverseNext();
3039 frame = frame->tree().traverseNext();
3040 id += 2;
3042 std::vector<WebFrameTimingEvent> renderPairs(4);
3043 renderPairs[0] = WebFrameTimingEvent(4, 5.0, 6.0);
3044 renderPairs[1] =WebFrameTimingEvent(5, 6.0, 7.0);
3045 renderPairs[2] =WebFrameTimingEvent(6, 7.0, 8.0);
3046 renderPairs[3] =WebFrameTimingEvent(7, 8.0, 9.0);
3047 WebVector<WebFrameTimingEvent> renderEvents(renderPairs);
3048 webViewImpl->recordFrameTimingEvent(WebView::RenderEvent, id, renderEvents);
3049 composites = DOMWindowPerformance::performance(*frame->domWindow())->getEntriesByType("composite");
3050 renders = DOMWindowPerformance::performance(*frame->domWindow())->getEntriesByType("render");
3051 ASSERT_EQ(0ul, composites.size());
3052 ASSERT_EQ(4ul, renders.size());
3053 for (size_t i = 0; i < renders.size(); ++i) {
3054 double docStartTime = frame->domWindow()->document()->loader()->timing().monotonicTimeToZeroBasedDocumentTime(renderPairs[i].startTime) * 1000.0;
3055 ASSERT_DOUBLE_EQ(docStartTime, renders[i]->startTime());
3056 double docFinishTime = frame->domWindow()->document()->loader()->timing().monotonicTimeToZeroBasedDocumentTime(renderPairs[i].finishTime) * 1000.0;
3057 double docDuration = docFinishTime - docStartTime;
3058 ASSERT_DOUBLE_EQ(docDuration, renders[i]->duration());
3063 TEST_F(WebViewTest, StopLoadingIfJavaScriptURLReturnsNoStringResult)
3065 ViewCreatingWebViewClient client;
3066 FrameTestHelpers::WebViewHelper mainWebView;
3067 mainWebView.initializeAndLoad("about:blank", true, 0, &client);
3068 mainWebView.webViewImpl()->page()->settings().setJavaScriptCanOpenWindowsAutomatically(true);
3070 WebFrame* frame = mainWebView.webView()->mainFrame();
3071 v8::HandleScope scope(v8::Isolate::GetCurrent());
3072 v8::Local<v8::Value> v8Value = frame->executeScriptAndReturnValue(WebScriptSource("var win = window.open('javascript:false'); win.document"));
3073 ASSERT_TRUE(v8Value->IsObject());
3074 Document* document = V8Document::toImplWithTypeCheck(v8::Isolate::GetCurrent(), v8Value);
3075 ASSERT_TRUE(document);
3076 EXPECT_FALSE(document->frame()->isLoading());
3079 } // namespace blink