Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / web / tests / PinchViewportTest.cpp
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "config.h"
6
7 #include "core/frame/PinchViewport.h"
8
9 #include "core/frame/FrameHost.h"
10 #include "core/frame/LocalFrame.h"
11 #include "core/rendering/RenderView.h"
12 #include "core/rendering/compositing/CompositedLayerMapping.h"
13 #include "core/rendering/compositing/RenderLayerCompositor.h"
14 #include "public/platform/Platform.h"
15 #include "public/platform/WebLayerTreeView.h"
16 #include "public/platform/WebUnitTestSupport.h"
17 #include "public/web/WebScriptSource.h"
18 #include "public/web/WebSettings.h"
19 #include "public/web/WebViewClient.h"
20 #include "web/WebLocalFrameImpl.h"
21 #include "web/tests/FrameTestHelpers.h"
22 #include "web/tests/URLTestHelpers.h"
23 #include <gmock/gmock.h>
24 #include <gtest/gtest.h>
25
26 #define EXPECT_POINT_EQ(expected, actual) \
27     do { \
28         EXPECT_EQ((expected).x(), (actual).x()); \
29         EXPECT_EQ((expected).y(), (actual).y()); \
30     } while (false)
31
32 #define EXPECT_FLOAT_POINT_EQ(expected, actual) \
33     do { \
34         EXPECT_FLOAT_EQ((expected).x(), (actual).x()); \
35         EXPECT_FLOAT_EQ((expected).y(), (actual).y()); \
36     } while (false)
37
38 #define EXPECT_POINT_EQ(expected, actual) \
39     do { \
40         EXPECT_EQ((expected).x(), (actual).x()); \
41         EXPECT_EQ((expected).y(), (actual).y()); \
42     } while (false)
43
44 #define EXPECT_SIZE_EQ(expected, actual) \
45     do { \
46         EXPECT_EQ((expected).width(), (actual).width()); \
47         EXPECT_EQ((expected).height(), (actual).height()); \
48     } while (false)
49
50 #define EXPECT_FLOAT_SIZE_EQ(expected, actual) \
51     do { \
52         EXPECT_FLOAT_EQ((expected).width(), (actual).width()); \
53         EXPECT_FLOAT_EQ((expected).height(), (actual).height()); \
54     } while (false)
55
56 #define EXPECT_FLOAT_RECT_EQ(expected, actual) \
57     do { \
58         EXPECT_FLOAT_EQ((expected).x(), (actual).x()); \
59         EXPECT_FLOAT_EQ((expected).y(), (actual).y()); \
60         EXPECT_FLOAT_EQ((expected).width(), (actual).width()); \
61         EXPECT_FLOAT_EQ((expected).height(), (actual).height()); \
62     } while (false)
63
64
65 using namespace WebCore;
66 using namespace blink;
67 using blink::FrameTestHelpers::runPendingTasks;
68
69 namespace {
70
71 class PinchViewportTest : public testing::Test {
72 public:
73     PinchViewportTest()
74         : m_baseURL("http://www.test.com/")
75     {
76     }
77
78     void initializeWithDesktopSettings(void (*overrideSettingsFunc)(WebSettings*) = 0)
79     {
80         if (!overrideSettingsFunc)
81             overrideSettingsFunc = &configureSettings;
82         m_helper.initialize(true, 0, &m_mockWebViewClient, overrideSettingsFunc);
83         webViewImpl()->setPageScaleFactorLimits(1, 4);
84     }
85
86     void initializeWithAndroidSettings(void (*overrideSettingsFunc)(WebSettings*) = 0)
87     {
88         if (!overrideSettingsFunc)
89             overrideSettingsFunc = &configureAndroidSettings;
90         m_helper.initialize(true, 0, &m_mockWebViewClient, overrideSettingsFunc);
91     }
92
93     virtual ~PinchViewportTest()
94     {
95         Platform::current()->unitTestSupport()->unregisterAllMockedURLs();
96     }
97
98     void navigateTo(const std::string& url)
99     {
100         FrameTestHelpers::loadFrame(webViewImpl()->mainFrame(), url);
101         Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
102     }
103
104     void forceFullCompositingUpdate()
105     {
106         webViewImpl()->layout();
107     }
108
109     void registerMockedHttpURLLoad(const std::string& fileName)
110     {
111         URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8(fileName.c_str()));
112     }
113
114     void executeScript(const WebString& code)
115     {
116         webViewImpl()->mainFrame()->executeScript(WebScriptSource(code));
117         runPendingTasks();
118     }
119
120     WebLayer* getRootScrollLayer()
121     {
122         RenderLayerCompositor* compositor = frame()->contentRenderer()->compositor();
123         ASSERT(compositor);
124         ASSERT(compositor->scrollLayer());
125
126         WebLayer* webScrollLayer = compositor->scrollLayer()->platformLayer();
127         return webScrollLayer;
128     }
129
130     WebViewImpl* webViewImpl() const { return m_helper.webViewImpl(); }
131     LocalFrame* frame() const { return m_helper.webViewImpl()->mainFrameImpl()->frame(); }
132
133     static void configureSettings(WebSettings* settings)
134     {
135         settings->setJavaScriptEnabled(true);
136         settings->setForceCompositingMode(true);
137         settings->setAcceleratedCompositingEnabled(true);
138         settings->setAcceleratedCompositingForFixedPositionEnabled(true);
139         settings->setAcceleratedCompositingForOverflowScrollEnabled(true);
140         settings->setCompositedScrollingForFramesEnabled(true);
141         settings->setPinchVirtualViewportEnabled(true);
142     }
143
144     static void configureAndroidSettings(WebSettings* settings)
145     {
146         configureSettings(settings);
147         settings->setViewportEnabled(true);
148         settings->setViewportMetaEnabled(true);
149         settings->setShrinksViewportContentToFit(true);
150     }
151
152 protected:
153     std::string m_baseURL;
154     FrameTestHelpers::TestWebViewClient m_mockWebViewClient;
155
156 private:
157     FrameTestHelpers::WebViewHelper m_helper;
158 };
159
160 // Test that resizing the PinchViewport works as expected and that resizing the
161 // WebView resizes the PinchViewport.
162 TEST_F(PinchViewportTest, TestResize)
163 {
164     initializeWithDesktopSettings();
165     webViewImpl()->resize(IntSize(320, 240));
166
167     navigateTo("about:blank");
168     forceFullCompositingUpdate();
169
170     PinchViewport& pinchViewport = frame()->page()->frameHost().pinchViewport();
171
172     IntSize webViewSize = webViewImpl()->size();
173
174     // Make sure the pinch viewport was initialized.
175     EXPECT_SIZE_EQ(webViewSize, pinchViewport.size());
176
177     // Resizing the WebView should change the PinchViewport.
178     webViewSize = IntSize(640, 480);
179     webViewImpl()->resize(webViewSize);
180     EXPECT_SIZE_EQ(webViewSize, IntSize(webViewImpl()->size()));
181     EXPECT_SIZE_EQ(webViewSize, pinchViewport.size());
182
183     // Resizing the pinch viewport shouldn't affect the WebView.
184     IntSize newViewportSize = IntSize(320, 200);
185     pinchViewport.setSize(newViewportSize);
186     EXPECT_SIZE_EQ(webViewSize, IntSize(webViewImpl()->size()));
187     EXPECT_SIZE_EQ(newViewportSize, pinchViewport.size());
188 }
189
190 static void turnOffForceCompositingMode(WebSettings* settings)
191 {
192     PinchViewportTest::configureSettings(settings);
193     settings->setForceCompositingMode(false);
194 }
195
196 // Test that the container layer gets sized properly if the WebView is resized
197 // prior to the PinchViewport being attached to the layer tree.
198 TEST_F(PinchViewportTest, TestWebViewResizedBeforeAttachment)
199 {
200     initializeWithDesktopSettings(turnOffForceCompositingMode);
201     webViewImpl()->resize(IntSize(320, 240));
202
203     navigateTo("about:blank");
204     forceFullCompositingUpdate();
205     webViewImpl()->enterForceCompositingMode(true);
206
207     PinchViewport& pinchViewport = frame()->page()->frameHost().pinchViewport();
208     EXPECT_FLOAT_SIZE_EQ(FloatSize(320, 240), pinchViewport.rootGraphicsLayer()->size());
209 }
210
211 // Make sure that the visibleRect method acurately reflects the scale and scroll location
212 // of the viewport.
213 TEST_F(PinchViewportTest, TestVisibleRect)
214 {
215     initializeWithDesktopSettings();
216     webViewImpl()->resize(IntSize(320, 240));
217
218     navigateTo("about:blank");
219     forceFullCompositingUpdate();
220
221     PinchViewport& pinchViewport = frame()->page()->frameHost().pinchViewport();
222
223     // Initial visible rect should be the whole frame.
224     EXPECT_SIZE_EQ(IntSize(webViewImpl()->size()), pinchViewport.size());
225
226     // Viewport is whole frame.
227     IntSize size = IntSize(400, 200);
228     webViewImpl()->resize(size);
229     webViewImpl()->layout();
230     pinchViewport.setSize(size);
231
232     // Scale the viewport to 2X; size should not change.
233     FloatRect expectedRect(FloatPoint(0, 0), size);
234     expectedRect.scale(0.5);
235     pinchViewport.setScale(2);
236     EXPECT_EQ(2, pinchViewport.scale());
237     EXPECT_SIZE_EQ(size, pinchViewport.size());
238     EXPECT_FLOAT_RECT_EQ(expectedRect, pinchViewport.visibleRect());
239
240     // Move the viewport.
241     expectedRect.setLocation(FloatPoint(5, 7));
242     pinchViewport.setLocation(expectedRect.location());
243     EXPECT_FLOAT_RECT_EQ(expectedRect, pinchViewport.visibleRect());
244
245     expectedRect.setLocation(FloatPoint(200, 100));
246     pinchViewport.setLocation(expectedRect.location());
247     EXPECT_FLOAT_RECT_EQ(expectedRect, pinchViewport.visibleRect());
248
249     // Scale the viewport to 3X to introduce some non-int values.
250     FloatPoint oldLocation = expectedRect.location();
251     expectedRect = FloatRect(FloatPoint(), size);
252     expectedRect.scale(1 / 3.0f);
253     expectedRect.setLocation(oldLocation);
254     pinchViewport.setScale(3);
255     EXPECT_FLOAT_RECT_EQ(expectedRect, pinchViewport.visibleRect());
256
257     expectedRect.setLocation(FloatPoint(0.25f, 0.333f));
258     pinchViewport.setLocation(expectedRect.location());
259     EXPECT_FLOAT_RECT_EQ(expectedRect, pinchViewport.visibleRect());
260 }
261
262 // Test that the viewport's scroll offset is always appropriately bounded such that the
263 // pinch viewport always stays within the bounds of the main frame.
264 TEST_F(PinchViewportTest, TestOffsetClamping)
265 {
266     initializeWithDesktopSettings();
267     webViewImpl()->resize(IntSize(320, 240));
268
269     navigateTo("about:blank");
270     forceFullCompositingUpdate();
271
272     // Pinch viewport should be initialized to same size as frame so no scrolling possible.
273     PinchViewport& pinchViewport = frame()->page()->frameHost().pinchViewport();
274     EXPECT_FLOAT_POINT_EQ(FloatPoint(0, 0), pinchViewport.visibleRect().location());
275
276     pinchViewport.setLocation(FloatPoint(-1, -2));
277     EXPECT_FLOAT_POINT_EQ(FloatPoint(0, 0), pinchViewport.visibleRect().location());
278
279     pinchViewport.setLocation(FloatPoint(100, 200));
280     EXPECT_FLOAT_POINT_EQ(FloatPoint(0, 0), pinchViewport.visibleRect().location());
281
282     pinchViewport.setLocation(FloatPoint(-5, 10));
283     EXPECT_FLOAT_POINT_EQ(FloatPoint(0, 0), pinchViewport.visibleRect().location());
284
285     // Scale by 2x. The viewport's visible rect should now have a size of 160x120.
286     pinchViewport.setScale(2);
287     FloatPoint location(10, 50);
288     pinchViewport.setLocation(location);
289     EXPECT_FLOAT_POINT_EQ(location, pinchViewport.visibleRect().location());
290
291     pinchViewport.setLocation(FloatPoint(1000, 2000));
292     EXPECT_FLOAT_POINT_EQ(FloatPoint(160, 120), pinchViewport.visibleRect().location());
293
294     pinchViewport.setLocation(FloatPoint(-1000, -2000));
295     EXPECT_FLOAT_POINT_EQ(FloatPoint(0, 0), pinchViewport.visibleRect().location());
296
297     // Make sure offset gets clamped on scale out. Scale to 1.25 so the viewport is 256x192.
298     pinchViewport.setLocation(FloatPoint(160, 120));
299     pinchViewport.setScale(1.25);
300     EXPECT_FLOAT_POINT_EQ(FloatPoint(64, 48), pinchViewport.visibleRect().location());
301
302     // Scale out smaller than 1.
303     pinchViewport.setScale(0.25);
304     EXPECT_FLOAT_POINT_EQ(FloatPoint(0, 0), pinchViewport.visibleRect().location());
305 }
306
307 // Test that the viewport can be scrolled around only within the main frame in the presence
308 // of viewport resizes, as would be the case if the on screen keyboard came up.
309 TEST_F(PinchViewportTest, TestOffsetClampingWithResize)
310 {
311     initializeWithDesktopSettings();
312     webViewImpl()->resize(IntSize(320, 240));
313
314     navigateTo("about:blank");
315     forceFullCompositingUpdate();
316
317     // Pinch viewport should be initialized to same size as frame so no scrolling possible.
318     PinchViewport& pinchViewport = frame()->page()->frameHost().pinchViewport();
319     EXPECT_FLOAT_POINT_EQ(FloatPoint(0, 0), pinchViewport.visibleRect().location());
320
321     // Shrink the viewport vertically. The resize shouldn't affect the location, but it
322     // should allow vertical scrolling.
323     pinchViewport.setSize(IntSize(320, 200));
324     EXPECT_FLOAT_POINT_EQ(FloatPoint(0, 0), pinchViewport.visibleRect().location());
325     pinchViewport.setLocation(FloatPoint(10, 20));
326     EXPECT_FLOAT_POINT_EQ(FloatPoint(0, 20), pinchViewport.visibleRect().location());
327     pinchViewport.setLocation(FloatPoint(0, 100));
328     EXPECT_FLOAT_POINT_EQ(FloatPoint(0, 40), pinchViewport.visibleRect().location());
329     pinchViewport.setLocation(FloatPoint(0, 10));
330     EXPECT_FLOAT_POINT_EQ(FloatPoint(0, 10), pinchViewport.visibleRect().location());
331     pinchViewport.setLocation(FloatPoint(0, -100));
332     EXPECT_FLOAT_POINT_EQ(FloatPoint(0, 0), pinchViewport.visibleRect().location());
333
334     // Repeat the above but for horizontal dimension.
335     pinchViewport.setSize(IntSize(280, 240));
336     EXPECT_FLOAT_POINT_EQ(FloatPoint(0, 0), pinchViewport.visibleRect().location());
337     pinchViewport.setLocation(FloatPoint(10, 20));
338     EXPECT_FLOAT_POINT_EQ(FloatPoint(10, 0), pinchViewport.visibleRect().location());
339     pinchViewport.setLocation(FloatPoint(100, 0));
340     EXPECT_FLOAT_POINT_EQ(FloatPoint(40, 0), pinchViewport.visibleRect().location());
341     pinchViewport.setLocation(FloatPoint(10, 0));
342     EXPECT_FLOAT_POINT_EQ(FloatPoint(10, 0), pinchViewport.visibleRect().location());
343     pinchViewport.setLocation(FloatPoint(-100, 0));
344     EXPECT_FLOAT_POINT_EQ(FloatPoint(0, 0), pinchViewport.visibleRect().location());
345
346     // Now with both dimensions.
347     pinchViewport.setSize(IntSize(280, 200));
348     EXPECT_FLOAT_POINT_EQ(FloatPoint(0, 0), pinchViewport.visibleRect().location());
349     pinchViewport.setLocation(FloatPoint(10, 20));
350     EXPECT_FLOAT_POINT_EQ(FloatPoint(10, 20), pinchViewport.visibleRect().location());
351     pinchViewport.setLocation(FloatPoint(100, 100));
352     EXPECT_FLOAT_POINT_EQ(FloatPoint(40, 40), pinchViewport.visibleRect().location());
353     pinchViewport.setLocation(FloatPoint(10, 3));
354     EXPECT_FLOAT_POINT_EQ(FloatPoint(10, 3), pinchViewport.visibleRect().location());
355     pinchViewport.setLocation(FloatPoint(-10, -4));
356     EXPECT_FLOAT_POINT_EQ(FloatPoint(0, 0), pinchViewport.visibleRect().location());
357 }
358
359 // Test that the viewport is scrollable but bounded appropriately within the main frame
360 // when we apply both scaling and resizes.
361 TEST_F(PinchViewportTest, TestOffsetClampingWithResizeAndScale)
362 {
363     initializeWithDesktopSettings();
364     webViewImpl()->resize(IntSize(320, 240));
365
366     navigateTo("about:blank");
367     forceFullCompositingUpdate();
368
369     // Pinch viewport should be initialized to same size as WebView so no scrolling possible.
370     PinchViewport& pinchViewport = frame()->page()->frameHost().pinchViewport();
371     EXPECT_FLOAT_POINT_EQ(FloatPoint(0, 0), pinchViewport.visibleRect().location());
372
373     // Zoom in to 2X so we can scroll the viewport to 160x120.
374     pinchViewport.setScale(2);
375     pinchViewport.setLocation(FloatPoint(200, 200));
376     EXPECT_FLOAT_POINT_EQ(FloatPoint(160, 120), pinchViewport.visibleRect().location());
377
378     // Now resize the viewport to make it 10px smaller. Since we're zoomed in by 2X it should
379     // allow us to scroll by 5px more.
380     pinchViewport.setSize(IntSize(310, 230));
381     pinchViewport.setLocation(FloatPoint(200, 200));
382     EXPECT_FLOAT_POINT_EQ(FloatPoint(165, 125), pinchViewport.visibleRect().location());
383
384     // The viewport can be larger than the main frame (currently 320, 240) though typically
385     // the scale will be clamped to prevent it from actually being larger. Make sure size
386     // changes clamp the offset so the inner remains within the outer.
387     pinchViewport.setSize(IntSize(330, 250));
388     EXPECT_SIZE_EQ(IntSize(330, 250), pinchViewport.size());
389     EXPECT_FLOAT_POINT_EQ(FloatPoint(155, 115), pinchViewport.visibleRect().location());
390     pinchViewport.setLocation(FloatPoint(200, 200));
391     EXPECT_FLOAT_POINT_EQ(FloatPoint(155, 115), pinchViewport.visibleRect().location());
392
393     // Resize both the viewport and the frame to be larger.
394     webViewImpl()->resize(IntSize(640, 480));
395     webViewImpl()->layout();
396     EXPECT_SIZE_EQ(IntSize(webViewImpl()->size()), pinchViewport.size());
397     EXPECT_SIZE_EQ(IntSize(webViewImpl()->size()), frame()->view()->frameRect().size());
398     pinchViewport.setLocation(FloatPoint(1000, 1000));
399     EXPECT_FLOAT_POINT_EQ(FloatPoint(320, 240), pinchViewport.visibleRect().location());
400
401     // Make sure resizing the viewport doesn't change its offset if the resize doesn't make
402     // the viewport go out of bounds.
403     pinchViewport.setLocation(FloatPoint(200, 200));
404     pinchViewport.setSize(IntSize(880, 560));
405     EXPECT_FLOAT_POINT_EQ(FloatPoint(200, 200), pinchViewport.visibleRect().location());
406
407     // Resizing the viewport such that the viewport is out of bounds should move the
408     // viewport.
409     pinchViewport.setSize(IntSize(920, 640));
410     EXPECT_FLOAT_POINT_EQ(FloatPoint(180, 160), pinchViewport.visibleRect().location());
411 }
412
413 // The main FrameView's size should be set such that its the size of the pinch viewport
414 // at minimum scale. If there's no explicit minimum scale set, the FrameView should be
415 // set to the content width and height derived by the aspect ratio.
416 TEST_F(PinchViewportTest, TestFrameViewSizedToContent)
417 {
418     initializeWithAndroidSettings();
419     webViewImpl()->resize(IntSize(320, 240));
420
421     registerMockedHttpURLLoad("200-by-300-viewport.html");
422     navigateTo(m_baseURL + "200-by-300-viewport.html");
423
424     webViewImpl()->resize(IntSize(600, 800));
425     webViewImpl()->layout();
426
427     EXPECT_SIZE_EQ(IntSize(200, 266),
428         webViewImpl()->mainFrameImpl()->frameView()->frameRect().size());
429 }
430
431 // The main FrameView's size should be set such that its the size of the pinch viewport
432 // at minimum scale. On Desktop, the minimum scale is set at 1 so make sure the FrameView
433 // is sized to the viewport.
434 TEST_F(PinchViewportTest, TestFrameViewSizedToMinimumScale)
435 {
436     initializeWithDesktopSettings();
437     webViewImpl()->resize(IntSize(320, 240));
438
439     registerMockedHttpURLLoad("200-by-300.html");
440     navigateTo(m_baseURL + "200-by-300.html");
441
442     webViewImpl()->resize(IntSize(100, 160));
443     webViewImpl()->layout();
444
445     EXPECT_SIZE_EQ(IntSize(100, 160),
446         webViewImpl()->mainFrameImpl()->frameView()->frameRect().size());
447 }
448
449 // The main FrameView's size should be set such that its the size of the pinch viewport
450 // at minimum scale. Test that the FrameView is appropriately sized in the presence
451 // of a viewport <meta> tag.
452 TEST_F(PinchViewportTest, TestFrameViewSizedToViewportMetaMinimumScale)
453 {
454     initializeWithAndroidSettings();
455     webViewImpl()->resize(IntSize(320, 240));
456
457     registerMockedHttpURLLoad("200-by-300-min-scale-2.html");
458     navigateTo(m_baseURL + "200-by-300-min-scale-2.html");
459
460     webViewImpl()->resize(IntSize(100, 160));
461     webViewImpl()->layout();
462
463     EXPECT_SIZE_EQ(IntSize(50, 80),
464         webViewImpl()->mainFrameImpl()->frameView()->frameRect().size());
465 }
466
467 // Test that the pinch viewport still gets sized in AutoSize/AutoResize mode.
468 TEST_F(PinchViewportTest, TestPinchViewportGetsSizeInAutoSizeMode)
469 {
470     initializeWithDesktopSettings();
471
472     EXPECT_SIZE_EQ(IntSize(0, 0), IntSize(webViewImpl()->size()));
473     EXPECT_SIZE_EQ(IntSize(0, 0), frame()->page()->frameHost().pinchViewport().size());
474
475     webViewImpl()->enableAutoResizeMode(WebSize(10, 10), WebSize(1000, 1000));
476
477     registerMockedHttpURLLoad("200-by-300.html");
478     navigateTo(m_baseURL + "200-by-300.html");
479
480     EXPECT_SIZE_EQ(IntSize(200, 300), frame()->page()->frameHost().pinchViewport().size());
481 }
482
483 // Test that the text selection handle's position accounts for the pinch viewport.
484 TEST_F(PinchViewportTest, TestTextSelectionHandles)
485 {
486     initializeWithDesktopSettings();
487     webViewImpl()->resize(IntSize(500, 800));
488
489     registerMockedHttpURLLoad("pinch-viewport-input-field.html");
490     navigateTo(m_baseURL + "pinch-viewport-input-field.html");
491
492     PinchViewport& pinchViewport = frame()->page()->frameHost().pinchViewport();
493     webViewImpl()->setInitialFocus(false);
494
495     WebRect originalAnchor;
496     WebRect originalFocus;
497     webViewImpl()->selectionBounds(originalAnchor, originalFocus);
498
499     webViewImpl()->setPageScaleFactor(2);
500     pinchViewport.setLocation(FloatPoint(100, 400));
501
502     WebRect anchor;
503     WebRect focus;
504     webViewImpl()->selectionBounds(anchor, focus);
505
506     IntPoint expected(IntRect(originalAnchor).location());
507     expected.moveBy(-flooredIntPoint(pinchViewport.visibleRect().location()));
508     expected.scale(pinchViewport.scale(), pinchViewport.scale());
509
510     EXPECT_POINT_EQ(expected, IntRect(anchor).location());
511     EXPECT_POINT_EQ(expected, IntRect(focus).location());
512
513     // FIXME(bokan) - http://crbug.com/364154 - Figure out how to test text selection
514     // as well rather than just carret.
515 }
516
517 // Test that the HistoryItem for the page stores the pinch viewport's offset and scale.
518 TEST_F(PinchViewportTest, TestSavedToHistoryItem)
519 {
520     initializeWithDesktopSettings();
521     webViewImpl()->resize(IntSize(200, 300));
522     webViewImpl()->layout();
523
524     registerMockedHttpURLLoad("200-by-300.html");
525     navigateTo(m_baseURL + "200-by-300.html");
526
527     EXPECT_FLOAT_POINT_EQ(FloatPoint(0, 0),
528         webViewImpl()->page()->mainFrame()->loader().currentItem()->pinchViewportScrollPoint());
529
530     PinchViewport& pinchViewport = frame()->page()->frameHost().pinchViewport();
531     pinchViewport.setScale(2);
532
533     EXPECT_EQ(2, webViewImpl()->page()->mainFrame()->loader().currentItem()->pageScaleFactor());
534
535     pinchViewport.setLocation(FloatPoint(10, 20));
536
537     EXPECT_FLOAT_POINT_EQ(FloatPoint(10, 20),
538         webViewImpl()->page()->mainFrame()->loader().currentItem()->pinchViewportScrollPoint());
539 }
540
541 // Test restoring a HistoryItem properly restores the pinch viewport's state.
542 TEST_F(PinchViewportTest, TestRestoredFromHistoryItem)
543 {
544     initializeWithDesktopSettings();
545     webViewImpl()->resize(IntSize(200, 300));
546
547     registerMockedHttpURLLoad("200-by-300.html");
548
549     WebHistoryItem item;
550     item.initialize();
551     WebURL destinationURL(blink::URLTestHelpers::toKURL(m_baseURL + "200-by-300.html"));
552     item.setURLString(destinationURL.string());
553     item.setPinchViewportScrollOffset(WebFloatPoint(100, 120));
554     item.setPageScaleFactor(2);
555
556     webViewImpl()->mainFrame()->loadHistoryItem(item, WebHistoryDifferentDocumentLoad, WebURLRequest::UseProtocolCachePolicy);
557     Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
558
559     PinchViewport& pinchViewport = frame()->page()->frameHost().pinchViewport();
560     EXPECT_EQ(2, pinchViewport.scale());
561
562     EXPECT_FLOAT_POINT_EQ(FloatPoint(100, 120), pinchViewport.visibleRect().location());
563 }
564
565 // Test restoring a HistoryItem without the pinch viewport offset falls back to distributing
566 // the scroll offset between the main frame and the pinch viewport.
567 TEST_F(PinchViewportTest, TestRestoredFromLegacyHistoryItem)
568 {
569     initializeWithDesktopSettings();
570     webViewImpl()->resize(IntSize(100, 150));
571
572     registerMockedHttpURLLoad("200-by-300-viewport.html");
573
574     WebHistoryItem item;
575     item.initialize();
576     WebURL destinationURL(blink::URLTestHelpers::toKURL(m_baseURL + "200-by-300-viewport.html"));
577     item.setURLString(destinationURL.string());
578     // (-1, -1) will be used if the HistoryItem is an older version prior to having
579     // pinch viewport scroll offset.
580     item.setPinchViewportScrollOffset(WebFloatPoint(-1, -1));
581     item.setScrollOffset(WebPoint(120, 180));
582     item.setPageScaleFactor(2);
583
584     webViewImpl()->mainFrame()->loadHistoryItem(item, WebHistoryDifferentDocumentLoad, WebURLRequest::UseProtocolCachePolicy);
585     Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
586
587     PinchViewport& pinchViewport = frame()->page()->frameHost().pinchViewport();
588     EXPECT_EQ(2, pinchViewport.scale());
589     EXPECT_POINT_EQ(IntPoint(100, 150), frame()->view()->scrollPosition());
590     EXPECT_FLOAT_POINT_EQ(FloatPoint(20, 30), pinchViewport.visibleRect().location());
591 }
592
593 // Test that the scrollFocusedNodeIntoRect method works with the pinch viewport.
594 TEST_F(PinchViewportTest, TestScrollFocusedNodeIntoRect)
595 {
596     initializeWithDesktopSettings();
597     webViewImpl()->resize(IntSize(500, 300));
598
599     registerMockedHttpURLLoad("pinch-viewport-input-field.html");
600     navigateTo(m_baseURL + "pinch-viewport-input-field.html");
601
602     PinchViewport& pinchViewport = frame()->page()->frameHost().pinchViewport();
603     webViewImpl()->resizePinchViewport(IntSize(200, 100));
604     webViewImpl()->setInitialFocus(false);
605     webViewImpl()->scrollFocusedNodeIntoRect(IntRect(0, 0, 500, 200));
606
607     EXPECT_POINT_EQ(IntPoint(0, frame()->view()->maximumScrollPosition().y()),
608         frame()->view()->scrollPosition());
609     EXPECT_FLOAT_POINT_EQ(FloatPoint(150, 200), pinchViewport.visibleRect().location());
610
611     // Try it again but with the page zoomed in
612     frame()->view()->notifyScrollPositionChanged(IntPoint(0, 0));
613     webViewImpl()->resizePinchViewport(IntSize(500, 300));
614     pinchViewport.setLocation(FloatPoint(0, 0));
615
616     webViewImpl()->setPageScaleFactor(2);
617     webViewImpl()->scrollFocusedNodeIntoRect(IntRect(0, 0, 500, 200));
618     EXPECT_POINT_EQ(IntPoint(0, frame()->view()->maximumScrollPosition().y()),
619         frame()->view()->scrollPosition());
620     EXPECT_FLOAT_POINT_EQ(FloatPoint(125, 150), pinchViewport.visibleRect().location());
621
622     // Once more but make sure that we don't move the pinch viewport unless necessary.
623     registerMockedHttpURLLoad("pinch-viewport-input-field-long-and-wide.html");
624     navigateTo(m_baseURL + "pinch-viewport-input-field-long-and-wide.html");
625     webViewImpl()->setInitialFocus(false);
626     frame()->view()->notifyScrollPositionChanged(IntPoint(0, 0));
627     webViewImpl()->resizePinchViewport(IntSize(500, 300));
628     pinchViewport.setLocation(FloatPoint(30, 50));
629
630     webViewImpl()->setPageScaleFactor(2);
631     webViewImpl()->scrollFocusedNodeIntoRect(IntRect(0, 0, 500, 200));
632     EXPECT_POINT_EQ(IntPoint(200-30-75, 600-50-65), frame()->view()->scrollPosition());
633     EXPECT_FLOAT_POINT_EQ(FloatPoint(30, 50), pinchViewport.visibleRect().location());
634 }
635
636 } // namespace