• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
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.
17  *
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.
29  */
30 
31 #include "config.h"
32 
33 #include "public/web/WebFrame.h"
34 
35 #include "SkBitmap.h"
36 #include "SkCanvas.h"
37 #include "core/UserAgentStyleSheets.h"
38 #include "core/clipboard/Clipboard.h"
39 #include "core/css/StyleSheetContents.h"
40 #include "core/css/resolver/ViewportStyleResolver.h"
41 #include "core/dom/DocumentMarkerController.h"
42 #include "core/dom/FullscreenElementStack.h"
43 #include "core/dom/Range.h"
44 #include "core/editing/Editor.h"
45 #include "core/editing/FrameSelection.h"
46 #include "core/editing/SpellChecker.h"
47 #include "core/editing/VisiblePosition.h"
48 #include "core/events/MouseEvent.h"
49 #include "core/frame/FrameView.h"
50 #include "core/frame/LocalFrame.h"
51 #include "core/frame/Settings.h"
52 #include "core/html/HTMLFormElement.h"
53 #include "core/loader/FrameLoadRequest.h"
54 #include "core/page/EventHandler.h"
55 #include "core/rendering/HitTestResult.h"
56 #include "core/rendering/RenderView.h"
57 #include "core/rendering/TextAutosizer.h"
58 #include "core/rendering/compositing/RenderLayerCompositor.h"
59 #include "platform/DragImage.h"
60 #include "platform/RuntimeEnabledFeatures.h"
61 #include "platform/UserGestureIndicator.h"
62 #include "platform/geometry/FloatRect.h"
63 #include "platform/network/ResourceError.h"
64 #include "platform/scroll/ScrollbarTheme.h"
65 #include "public/platform/Platform.h"
66 #include "public/platform/WebFloatRect.h"
67 #include "public/platform/WebThread.h"
68 #include "public/platform/WebURL.h"
69 #include "public/platform/WebURLResponse.h"
70 #include "public/platform/WebUnitTestSupport.h"
71 #include "public/web/WebDataSource.h"
72 #include "public/web/WebDocument.h"
73 #include "public/web/WebFindOptions.h"
74 #include "public/web/WebFormElement.h"
75 #include "public/web/WebFrameClient.h"
76 #include "public/web/WebHistoryItem.h"
77 #include "public/web/WebRange.h"
78 #include "public/web/WebScriptSource.h"
79 #include "public/web/WebSearchableFormData.h"
80 #include "public/web/WebSecurityOrigin.h"
81 #include "public/web/WebSecurityPolicy.h"
82 #include "public/web/WebSettings.h"
83 #include "public/web/WebSpellCheckClient.h"
84 #include "public/web/WebTextCheckingCompletion.h"
85 #include "public/web/WebTextCheckingResult.h"
86 #include "public/web/WebViewClient.h"
87 #include "web/WebLocalFrameImpl.h"
88 #include "web/WebViewImpl.h"
89 #include "web/tests/FrameTestHelpers.h"
90 #include "web/tests/URLTestHelpers.h"
91 #include "wtf/Forward.h"
92 #include "wtf/dtoa/utils.h"
93 #include <gmock/gmock.h>
94 #include <gtest/gtest.h>
95 #include <map>
96 #include <v8.h>
97 
98 using namespace blink;
99 using WebCore::Document;
100 using WebCore::DocumentMarker;
101 using WebCore::Element;
102 using WebCore::FloatRect;
103 using WebCore::HitTestRequest;
104 using WebCore::Range;
105 using blink::URLTestHelpers::toKURL;
106 using blink::FrameTestHelpers::runPendingTasks;
107 
108 namespace {
109 
110 const int touchPointPadding = 32;
111 
112 #define EXPECT_EQ_RECT(a, b) \
113     EXPECT_EQ(a.x(), b.x()); \
114     EXPECT_EQ(a.y(), b.y()); \
115     EXPECT_EQ(a.width(), b.width()); \
116     EXPECT_EQ(a.height(), b.height());
117 
118 class FakeCompositingWebViewClient : public FrameTestHelpers::TestWebViewClient {
119 public:
enterFullScreen()120     virtual bool enterFullScreen() OVERRIDE { return true; }
121 };
122 
123 class WebFrameTest : public testing::Test {
124 protected:
WebFrameTest()125     WebFrameTest()
126         : m_baseURL("http://www.test.com/")
127         , m_chromeURL("chrome://")
128     {
129     }
130 
~WebFrameTest()131     virtual ~WebFrameTest()
132     {
133         Platform::current()->unitTestSupport()->unregisterAllMockedURLs();
134     }
135 
registerMockedHttpURLLoad(const std::string & fileName)136     void registerMockedHttpURLLoad(const std::string& fileName)
137     {
138         URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8(fileName.c_str()));
139     }
140 
registerMockedChromeURLLoad(const std::string & fileName)141     void registerMockedChromeURLLoad(const std::string& fileName)
142     {
143         URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_chromeURL.c_str()), WebString::fromUTF8(fileName.c_str()));
144     }
145 
applyViewportStyleOverride(FrameTestHelpers::WebViewHelper * webViewHelper)146     void applyViewportStyleOverride(FrameTestHelpers::WebViewHelper* webViewHelper)
147     {
148         RefPtrWillBeRawPtr<WebCore::StyleSheetContents> styleSheet = WebCore::StyleSheetContents::create(WebCore::CSSParserContext(WebCore::UASheetMode, 0));
149         styleSheet->parseString(String(WebCore::viewportAndroidUserAgentStyleSheet, sizeof(WebCore::viewportAndroidUserAgentStyleSheet)));
150         OwnPtrWillBeRawPtr<WebCore::RuleSet> ruleSet = WebCore::RuleSet::create();
151         ruleSet->addRulesFromSheet(styleSheet.get(), WebCore::MediaQueryEvaluator("screen"));
152 
153         Document* document = toLocalFrame(webViewHelper->webViewImpl()->page()->mainFrame())->document();
154         document->ensureStyleResolver().viewportStyleResolver()->collectViewportRules(ruleSet.get(), WebCore::ViewportStyleResolver::UserAgentOrigin);
155         document->ensureStyleResolver().viewportStyleResolver()->resolve();
156     }
157 
configueCompositingWebView(WebSettings * settings)158     static void configueCompositingWebView(WebSettings* settings)
159     {
160         settings->setAcceleratedCompositingEnabled(true);
161         settings->setAcceleratedCompositingForFixedPositionEnabled(true);
162         settings->setAcceleratedCompositingForOverflowScrollEnabled(true);
163         settings->setCompositedScrollingForFramesEnabled(true);
164     }
165 
initializeTextSelectionWebView(const std::string & url,FrameTestHelpers::WebViewHelper * webViewHelper)166     void initializeTextSelectionWebView(const std::string& url, FrameTestHelpers::WebViewHelper* webViewHelper)
167     {
168         webViewHelper->initializeAndLoad(url, true);
169         webViewHelper->webView()->settings()->setDefaultFontSize(12);
170         webViewHelper->webView()->resize(WebSize(640, 480));
171     }
172 
nodeImageTestSetup(FrameTestHelpers::WebViewHelper * webViewHelper,const std::string & testcase)173     PassOwnPtr<WebCore::DragImage> nodeImageTestSetup(FrameTestHelpers::WebViewHelper* webViewHelper, const std::string& testcase)
174     {
175         registerMockedHttpURLLoad("nodeimage.html");
176         webViewHelper->initializeAndLoad(m_baseURL + "nodeimage.html");
177         webViewHelper->webView()->resize(WebSize(640, 480));
178         webViewHelper->webView()->layout();
179         RefPtr<WebCore::LocalFrame> frame = toLocalFrame(webViewHelper->webViewImpl()->page()->mainFrame());
180         WebCore::Element* element = frame->document()->getElementById(testcase.c_str());
181         return frame->nodeImage(*element);
182     }
183 
184     std::string m_baseURL;
185     std::string m_chromeURL;
186 };
187 
188 class UseMockScrollbarSettings {
189 public:
UseMockScrollbarSettings()190     UseMockScrollbarSettings()
191     {
192         WebCore::Settings::setMockScrollbarsEnabled(true);
193         WebCore::RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(true);
194         EXPECT_TRUE(WebCore::ScrollbarTheme::theme()->usesOverlayScrollbars());
195     }
196 
~UseMockScrollbarSettings()197     ~UseMockScrollbarSettings()
198     {
199         WebCore::Settings::setMockScrollbarsEnabled(false);
200         WebCore::RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(false);
201     }
202 };
203 
TEST_F(WebFrameTest,ContentText)204 TEST_F(WebFrameTest, ContentText)
205 {
206     registerMockedHttpURLLoad("iframes_test.html");
207     registerMockedHttpURLLoad("visible_iframe.html");
208     registerMockedHttpURLLoad("invisible_iframe.html");
209     registerMockedHttpURLLoad("zero_sized_iframe.html");
210 
211     FrameTestHelpers::WebViewHelper webViewHelper;
212     webViewHelper.initializeAndLoad(m_baseURL + "iframes_test.html");
213 
214     // Now retrieve the frames text and test it only includes visible elements.
215     std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
216     EXPECT_NE(std::string::npos, content.find(" visible paragraph"));
217     EXPECT_NE(std::string::npos, content.find(" visible iframe"));
218     EXPECT_EQ(std::string::npos, content.find(" invisible pararaph"));
219     EXPECT_EQ(std::string::npos, content.find(" invisible iframe"));
220     EXPECT_EQ(std::string::npos, content.find("iframe with zero size"));
221 }
222 
TEST_F(WebFrameTest,FrameForEnteredContext)223 TEST_F(WebFrameTest, FrameForEnteredContext)
224 {
225     registerMockedHttpURLLoad("iframes_test.html");
226     registerMockedHttpURLLoad("visible_iframe.html");
227     registerMockedHttpURLLoad("invisible_iframe.html");
228     registerMockedHttpURLLoad("zero_sized_iframe.html");
229 
230     FrameTestHelpers::WebViewHelper webViewHelper;
231     webViewHelper.initializeAndLoad(m_baseURL + "iframes_test.html", true);
232 
233     v8::HandleScope scope(v8::Isolate::GetCurrent());
234     EXPECT_EQ(webViewHelper.webView()->mainFrame(), WebLocalFrame::frameForContext(webViewHelper.webView()->mainFrame()->mainWorldScriptContext()));
235     EXPECT_EQ(webViewHelper.webView()->mainFrame()->firstChild(), WebLocalFrame::frameForContext(webViewHelper.webView()->mainFrame()->firstChild()->mainWorldScriptContext()));
236 }
237 
TEST_F(WebFrameTest,FormWithNullFrame)238 TEST_F(WebFrameTest, FormWithNullFrame)
239 {
240     registerMockedHttpURLLoad("form.html");
241 
242     FrameTestHelpers::WebViewHelper webViewHelper;
243     webViewHelper.initializeAndLoad(m_baseURL + "form.html");
244 
245     WebVector<WebFormElement> forms;
246     webViewHelper.webView()->mainFrame()->document().forms(forms);
247     webViewHelper.reset();
248 
249     EXPECT_EQ(forms.size(), 1U);
250 
251     // This test passes if this doesn't crash.
252     WebSearchableFormData searchableDataForm(forms[0]);
253 }
254 
TEST_F(WebFrameTest,ChromePageJavascript)255 TEST_F(WebFrameTest, ChromePageJavascript)
256 {
257     registerMockedChromeURLLoad("history.html");
258 
259     // Pass true to enable JavaScript.
260     FrameTestHelpers::WebViewHelper webViewHelper;
261     webViewHelper.initializeAndLoad(m_chromeURL + "history.html", true);
262 
263     // Try to run JS against the chrome-style URL.
264     FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.appendChild(document.createTextNode('Clobbered'))");
265 
266     // Required to see any updates in contentAsText.
267     webViewHelper.webView()->layout();
268 
269     // Now retrieve the frame's text and ensure it was modified by running javascript.
270     std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
271     EXPECT_NE(std::string::npos, content.find("Clobbered"));
272 }
273 
TEST_F(WebFrameTest,ChromePageNoJavascript)274 TEST_F(WebFrameTest, ChromePageNoJavascript)
275 {
276     registerMockedChromeURLLoad("history.html");
277 
278     /// Pass true to enable JavaScript.
279     FrameTestHelpers::WebViewHelper webViewHelper;
280     webViewHelper.initializeAndLoad(m_chromeURL + "history.html", true);
281 
282     // Try to run JS against the chrome-style URL after prohibiting it.
283     WebSecurityPolicy::registerURLSchemeAsNotAllowingJavascriptURLs("chrome");
284     FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.appendChild(document.createTextNode('Clobbered'))");
285 
286     // Required to see any updates in contentAsText.
287     webViewHelper.webView()->layout();
288 
289     // Now retrieve the frame's text and ensure it wasn't modified by running javascript.
290     std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
291     EXPECT_EQ(std::string::npos, content.find("Clobbered"));
292 }
293 
TEST_F(WebFrameTest,LocationSetHostWithMissingPort)294 TEST_F(WebFrameTest, LocationSetHostWithMissingPort)
295 {
296     std::string fileName = "print-location-href.html";
297     registerMockedHttpURLLoad(fileName);
298     URLTestHelpers::registerMockedURLLoad(toKURL("http://www.test.com:0/" + fileName), WebString::fromUTF8(fileName));
299 
300     FrameTestHelpers::WebViewHelper webViewHelper;
301 
302     /// Pass true to enable JavaScript.
303     webViewHelper.initializeAndLoad(m_baseURL + fileName, true);
304 
305     // Setting host to "hostname:" should be treated as "hostname:0".
306     FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:location.host = 'www.test.com:'; void 0;");
307 
308     FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.textContent = location.href; void 0;");
309 
310     std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
311     EXPECT_EQ("http://www.test.com:0/" + fileName, content);
312 }
313 
TEST_F(WebFrameTest,LocationSetEmptyPort)314 TEST_F(WebFrameTest, LocationSetEmptyPort)
315 {
316     std::string fileName = "print-location-href.html";
317     registerMockedHttpURLLoad(fileName);
318     URLTestHelpers::registerMockedURLLoad(toKURL("http://www.test.com:0/" + fileName), WebString::fromUTF8(fileName));
319 
320     FrameTestHelpers::WebViewHelper webViewHelper;
321 
322     /// Pass true to enable JavaScript.
323     webViewHelper.initializeAndLoad(m_baseURL + fileName, true);
324 
325     FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:location.port = ''; void 0;");
326 
327     FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.textContent = location.href; void 0;");
328 
329     std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
330     EXPECT_EQ("http://www.test.com:0/" + fileName, content);
331 }
332 
333 class CSSCallbackWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
334 public:
CSSCallbackWebFrameClient()335     CSSCallbackWebFrameClient() : m_updateCount(0) { }
336     virtual void didMatchCSS(WebLocalFrame*, const WebVector<WebString>& newlyMatchingSelectors, const WebVector<WebString>& stoppedMatchingSelectors) OVERRIDE;
337 
338     std::map<WebLocalFrame*, std::set<std::string> > m_matchedSelectors;
339     int m_updateCount;
340 };
341 
didMatchCSS(WebLocalFrame * frame,const WebVector<WebString> & newlyMatchingSelectors,const WebVector<WebString> & stoppedMatchingSelectors)342 void CSSCallbackWebFrameClient::didMatchCSS(WebLocalFrame* frame, const WebVector<WebString>& newlyMatchingSelectors, const WebVector<WebString>& stoppedMatchingSelectors)
343 {
344     ++m_updateCount;
345     std::set<std::string>& frameSelectors = m_matchedSelectors[frame];
346     for (size_t i = 0; i < newlyMatchingSelectors.size(); ++i) {
347         std::string selector = newlyMatchingSelectors[i].utf8();
348         EXPECT_EQ(0U, frameSelectors.count(selector)) << selector;
349         frameSelectors.insert(selector);
350     }
351     for (size_t i = 0; i < stoppedMatchingSelectors.size(); ++i) {
352         std::string selector = stoppedMatchingSelectors[i].utf8();
353         EXPECT_EQ(1U, frameSelectors.count(selector)) << selector;
354         frameSelectors.erase(selector);
355     }
356 }
357 
358 class WebFrameCSSCallbackTest : public testing::Test {
359 protected:
WebFrameCSSCallbackTest()360     WebFrameCSSCallbackTest()
361     {
362 
363         m_frame = m_helper.initializeAndLoad("about:blank", true, &m_client)->mainFrame()->toWebLocalFrame();
364     }
365 
~WebFrameCSSCallbackTest()366     ~WebFrameCSSCallbackTest()
367     {
368         EXPECT_EQ(1U, m_client.m_matchedSelectors.size());
369     }
370 
doc() const371     WebDocument doc() const
372     {
373         return m_frame->document();
374     }
375 
updateCount() const376     int updateCount() const
377     {
378         return m_client.m_updateCount;
379     }
380 
matchedSelectors()381     const std::set<std::string>& matchedSelectors()
382     {
383         return m_client.m_matchedSelectors[m_frame];
384     }
385 
loadHTML(const std::string & html)386     void loadHTML(const std::string& html)
387     {
388         FrameTestHelpers::loadHTMLString(m_frame, html, toKURL("about:blank"));
389     }
390 
executeScript(const WebString & code)391     void executeScript(const WebString& code)
392     {
393         m_frame->executeScript(WebScriptSource(code));
394         m_frame->view()->layout();
395         runPendingTasks();
396     }
397 
398     CSSCallbackWebFrameClient m_client;
399     FrameTestHelpers::WebViewHelper m_helper;
400     WebLocalFrame* m_frame;
401 };
402 
TEST_F(WebFrameCSSCallbackTest,AuthorStyleSheet)403 TEST_F(WebFrameCSSCallbackTest, AuthorStyleSheet)
404 {
405     loadHTML(
406         "<style>"
407         // This stylesheet checks that the internal property and value can't be
408         // set by a stylesheet, only WebDocument::watchCSSSelectors().
409         "div.initial_on { -internal-callback: none; }"
410         "div.initial_off { -internal-callback: -internal-presence; }"
411         "</style>"
412         "<div class=\"initial_on\"></div>"
413         "<div class=\"initial_off\"></div>");
414 
415     std::vector<WebString> selectors;
416     selectors.push_back(WebString::fromUTF8("div.initial_on"));
417     m_frame->document().watchCSSSelectors(WebVector<WebString>(selectors));
418     m_frame->view()->layout();
419     runPendingTasks();
420     EXPECT_EQ(1, updateCount());
421     EXPECT_THAT(matchedSelectors(), testing::ElementsAre("div.initial_on"));
422 
423     // Check that adding a watched selector calls back for already-present nodes.
424     selectors.push_back(WebString::fromUTF8("div.initial_off"));
425     doc().watchCSSSelectors(WebVector<WebString>(selectors));
426     m_frame->view()->layout();
427     runPendingTasks();
428     EXPECT_EQ(2, updateCount());
429     EXPECT_THAT(matchedSelectors(), testing::ElementsAre("div.initial_off", "div.initial_on"));
430 
431     // Check that we can turn off callbacks for certain selectors.
432     doc().watchCSSSelectors(WebVector<WebString>());
433     m_frame->view()->layout();
434     runPendingTasks();
435     EXPECT_EQ(3, updateCount());
436     EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
437 }
438 
TEST_F(WebFrameCSSCallbackTest,SharedRenderStyle)439 TEST_F(WebFrameCSSCallbackTest, SharedRenderStyle)
440 {
441     // Check that adding an element calls back when it matches an existing rule.
442     std::vector<WebString> selectors;
443     selectors.push_back(WebString::fromUTF8("span"));
444     doc().watchCSSSelectors(WebVector<WebString>(selectors));
445 
446     executeScript(
447         "i1 = document.createElement('span');"
448         "i1.id = 'first_span';"
449         "document.body.appendChild(i1)");
450     EXPECT_EQ(1, updateCount());
451     EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
452 
453     // Adding a second element that shares a RenderStyle shouldn't call back.
454     // We use <span>s to avoid default style rules that can set
455     // RenderStyle::unique().
456     executeScript(
457         "i2 = document.createElement('span');"
458         "i2.id = 'second_span';"
459         "i1 = document.getElementById('first_span');"
460         "i1.parentNode.insertBefore(i2, i1.nextSibling);");
461     EXPECT_EQ(1, updateCount());
462     EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
463 
464     // Removing the first element shouldn't call back.
465     executeScript(
466         "i1 = document.getElementById('first_span');"
467         "i1.parentNode.removeChild(i1);");
468     EXPECT_EQ(1, updateCount());
469     EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
470 
471     // But removing the second element *should* call back.
472     executeScript(
473         "i2 = document.getElementById('second_span');"
474         "i2.parentNode.removeChild(i2);");
475     EXPECT_EQ(2, updateCount());
476     EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
477 }
478 
TEST_F(WebFrameCSSCallbackTest,CatchesAttributeChange)479 TEST_F(WebFrameCSSCallbackTest, CatchesAttributeChange)
480 {
481     loadHTML("<span></span>");
482 
483     std::vector<WebString> selectors;
484     selectors.push_back(WebString::fromUTF8("span[attr=\"value\"]"));
485     doc().watchCSSSelectors(WebVector<WebString>(selectors));
486     runPendingTasks();
487 
488     EXPECT_EQ(0, updateCount());
489     EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
490 
491     executeScript(
492         "document.querySelector('span').setAttribute('attr', 'value');");
493     EXPECT_EQ(1, updateCount());
494     EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span[attr=\"value\"]"));
495 }
496 
TEST_F(WebFrameCSSCallbackTest,DisplayNone)497 TEST_F(WebFrameCSSCallbackTest, DisplayNone)
498 {
499     loadHTML("<div style='display:none'><span></span></div>");
500 
501     std::vector<WebString> selectors;
502     selectors.push_back(WebString::fromUTF8("span"));
503     doc().watchCSSSelectors(WebVector<WebString>(selectors));
504     runPendingTasks();
505 
506     EXPECT_EQ(0, updateCount()) << "Don't match elements in display:none trees.";
507 
508     executeScript(
509         "d = document.querySelector('div');"
510         "d.style.display = 'block';");
511     EXPECT_EQ(1, updateCount()) << "Match elements when they become displayed.";
512     EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
513 
514     executeScript(
515         "d = document.querySelector('div');"
516         "d.style.display = 'none';");
517     EXPECT_EQ(2, updateCount()) << "Unmatch elements when they become undisplayed.";
518     EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
519 
520     executeScript(
521         "s = document.querySelector('span');"
522         "s.style.display = 'none';");
523     EXPECT_EQ(2, updateCount()) << "No effect from no-display'ing a span that's already undisplayed.";
524 
525     executeScript(
526         "d = document.querySelector('div');"
527         "d.style.display = 'block';");
528     EXPECT_EQ(2, updateCount()) << "No effect from displaying a div whose span is display:none.";
529 
530     executeScript(
531         "s = document.querySelector('span');"
532         "s.style.display = 'inline';");
533     EXPECT_EQ(3, updateCount()) << "Now the span is visible and produces a callback.";
534     EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
535 
536     executeScript(
537         "s = document.querySelector('span');"
538         "s.style.display = 'none';");
539     EXPECT_EQ(4, updateCount()) << "Undisplaying the span directly should produce another callback.";
540     EXPECT_THAT(matchedSelectors(), testing::ElementsAre());
541 }
542 
TEST_F(WebFrameCSSCallbackTest,Reparenting)543 TEST_F(WebFrameCSSCallbackTest, Reparenting)
544 {
545     loadHTML(
546         "<div id='d1'><span></span></div>"
547         "<div id='d2'></div>");
548 
549     std::vector<WebString> selectors;
550     selectors.push_back(WebString::fromUTF8("span"));
551     doc().watchCSSSelectors(WebVector<WebString>(selectors));
552     m_frame->view()->layout();
553     runPendingTasks();
554 
555     EXPECT_EQ(1, updateCount());
556     EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
557 
558     executeScript(
559         "s = document.querySelector('span');"
560         "d2 = document.getElementById('d2');"
561         "d2.appendChild(s);");
562     EXPECT_EQ(1, updateCount()) << "Just moving an element that continues to match shouldn't send a spurious callback.";
563     EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"));
564 }
565 
TEST_F(WebFrameCSSCallbackTest,MultiSelector)566 TEST_F(WebFrameCSSCallbackTest, MultiSelector)
567 {
568     loadHTML("<span></span>");
569 
570     // Check that selector lists match as the whole list, not as each element
571     // independently.
572     std::vector<WebString> selectors;
573     selectors.push_back(WebString::fromUTF8("span"));
574     selectors.push_back(WebString::fromUTF8("span,p"));
575     doc().watchCSSSelectors(WebVector<WebString>(selectors));
576     m_frame->view()->layout();
577     runPendingTasks();
578 
579     EXPECT_EQ(1, updateCount());
580     EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span", "span, p"));
581 }
582 
TEST_F(WebFrameCSSCallbackTest,InvalidSelector)583 TEST_F(WebFrameCSSCallbackTest, InvalidSelector)
584 {
585     loadHTML("<p><span></span></p>");
586 
587     // Build a list with one valid selector and one invalid.
588     std::vector<WebString> selectors;
589     selectors.push_back(WebString::fromUTF8("span"));
590     selectors.push_back(WebString::fromUTF8("[")); // Invalid.
591     selectors.push_back(WebString::fromUTF8("p span")); // Not compound.
592     doc().watchCSSSelectors(WebVector<WebString>(selectors));
593     m_frame->view()->layout();
594     runPendingTasks();
595 
596     EXPECT_EQ(1, updateCount());
597     EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span"))
598         << "An invalid selector shouldn't prevent other selectors from matching.";
599 }
600 
TEST_F(WebFrameTest,DispatchMessageEventWithOriginCheck)601 TEST_F(WebFrameTest, DispatchMessageEventWithOriginCheck)
602 {
603     registerMockedHttpURLLoad("postmessage_test.html");
604 
605     // Pass true to enable JavaScript.
606     FrameTestHelpers::WebViewHelper webViewHelper;
607     webViewHelper.initializeAndLoad(m_baseURL + "postmessage_test.html", true);
608 
609     // Send a message with the correct origin.
610     WebSecurityOrigin correctOrigin(WebSecurityOrigin::create(toKURL(m_baseURL)));
611     WebDOMEvent event = webViewHelper.webView()->mainFrame()->document().createEvent("MessageEvent");
612     WebDOMMessageEvent message = event.to<WebDOMMessageEvent>();
613     WebSerializedScriptValue data(WebSerializedScriptValue::fromString("foo"));
614     message.initMessageEvent("message", false, false, data, "http://origin.com", 0, "");
615     webViewHelper.webView()->mainFrame()->dispatchMessageEventWithOriginCheck(correctOrigin, message);
616 
617     // Send another message with incorrect origin.
618     WebSecurityOrigin incorrectOrigin(WebSecurityOrigin::create(toKURL(m_chromeURL)));
619     webViewHelper.webView()->mainFrame()->dispatchMessageEventWithOriginCheck(incorrectOrigin, message);
620 
621     // Required to see any updates in contentAsText.
622     webViewHelper.webView()->layout();
623 
624     // Verify that only the first addition is in the body of the page.
625     std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
626     EXPECT_NE(std::string::npos, content.find("Message 1."));
627     EXPECT_EQ(std::string::npos, content.find("Message 2."));
628 }
629 
TEST_F(WebFrameTest,PostMessageThenDetach)630 TEST_F(WebFrameTest, PostMessageThenDetach)
631 {
632     FrameTestHelpers::WebViewHelper webViewHelper;
633     webViewHelper.initializeAndLoad("about:blank");
634 
635     RefPtr<WebCore::LocalFrame> frame = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame());
636     WebCore::NonThrowableExceptionState exceptionState;
637     frame->domWindow()->postMessage(WebCore::SerializedScriptValue::create("message"), 0, "*", frame->domWindow(), exceptionState);
638     webViewHelper.reset();
639     EXPECT_FALSE(exceptionState.hadException());
640 
641     // Success is not crashing.
642     runPendingTasks();
643 }
644 
645 class FixedLayoutTestWebViewClient : public FrameTestHelpers::TestWebViewClient {
646  public:
screenInfo()647     virtual WebScreenInfo screenInfo() OVERRIDE { return m_screenInfo; }
648 
649     WebScreenInfo m_screenInfo;
650 };
651 
652 // Viewport settings need to be set before the page gets loaded
enableViewportSettings(WebSettings * settings)653 static void enableViewportSettings(WebSettings* settings)
654 {
655     settings->setViewportMetaEnabled(true);
656     settings->setViewportEnabled(true);
657     settings->setMainFrameResizesAreOrientationChanges(true);
658     settings->setShrinksViewportContentToFit(true);
659 }
660 
TEST_F(WebFrameTest,FrameViewNeedsLayoutOnFixedLayoutResize)661 TEST_F(WebFrameTest, FrameViewNeedsLayoutOnFixedLayoutResize)
662 {
663     UseMockScrollbarSettings mockScrollbarSettings;
664     registerMockedHttpURLLoad("fixed_layout.html");
665 
666     FixedLayoutTestWebViewClient client;
667     int viewportWidth = 640;
668     int viewportHeight = 480;
669 
670     // Make sure we initialize to minimum scale, even if the window size
671     // only becomes available after the load begins.
672     FrameTestHelpers::WebViewHelper webViewHelper;
673     webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
674     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
675     webViewHelper.webView()->layout();
676 
677     webViewHelper.webViewImpl()->setFixedLayoutSize(WebCore::IntSize(100, 100));
678     EXPECT_TRUE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
679 
680     int prevLayoutCount = webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount();
681     webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->setFrameRect(WebCore::IntRect(0, 0, 641, 481));
682     EXPECT_EQ(prevLayoutCount, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount());
683 
684     webViewHelper.webViewImpl()->layout();
685 }
686 
687 // Helper function to check or set text autosizing multipliers on a document.
checkOrSetTextAutosizingMultiplier(Document * document,float multiplier,bool setMultiplier)688 static bool checkOrSetTextAutosizingMultiplier(Document* document, float multiplier, bool setMultiplier)
689 {
690     bool multiplierCheckedOrSetAtLeastOnce = false;
691     for (WebCore::RenderObject* renderer = document->renderView(); renderer; renderer = renderer->nextInPreOrder()) {
692         if (renderer->style()) {
693             if (setMultiplier)
694                 renderer->style()->setTextAutosizingMultiplier(multiplier);
695             EXPECT_EQ(multiplier, renderer->style()->textAutosizingMultiplier());
696             multiplierCheckedOrSetAtLeastOnce = true;
697         }
698     }
699     return multiplierCheckedOrSetAtLeastOnce;
700 
701 }
702 
setTextAutosizingMultiplier(Document * document,float multiplier)703 static bool setTextAutosizingMultiplier(Document* document, float multiplier)
704 {
705     return checkOrSetTextAutosizingMultiplier(document, multiplier, true);
706 }
707 
checkTextAutosizingMultiplier(Document * document,float multiplier)708 static bool checkTextAutosizingMultiplier(Document* document, float multiplier)
709 {
710     return checkOrSetTextAutosizingMultiplier(document, multiplier, false);
711 }
712 
TEST_F(WebFrameTest,ChangeInFixedLayoutResetsTextAutosizingMultipliers)713 TEST_F(WebFrameTest, ChangeInFixedLayoutResetsTextAutosizingMultipliers)
714 {
715     UseMockScrollbarSettings mockScrollbarSettings;
716     registerMockedHttpURLLoad("fixed_layout.html");
717 
718     FixedLayoutTestWebViewClient client;
719     int viewportWidth = 640;
720     int viewportHeight = 480;
721 
722     FrameTestHelpers::WebViewHelper webViewHelper;
723     webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
724 
725     WebCore::Document* document = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document();
726     document->settings()->setTextAutosizingEnabled(true);
727     EXPECT_TRUE(document->settings()->textAutosizingEnabled());
728     webViewHelper.webViewImpl()->resize(WebSize(viewportWidth, viewportHeight));
729     webViewHelper.webViewImpl()->layout();
730 
731     EXPECT_TRUE(setTextAutosizingMultiplier(document, 2));
732 
733     WebCore::ViewportDescription description = document->viewportDescription();
734     // Choose a width that's not going match the viewport width of the loaded document.
735     description.minWidth = WebCore::Length(100, WebCore::Fixed);
736     description.maxWidth = WebCore::Length(100, WebCore::Fixed);
737     webViewHelper.webViewImpl()->updatePageDefinedViewportConstraints(description);
738 
739     EXPECT_TRUE(checkTextAutosizingMultiplier(document, 1));
740 }
741 
TEST_F(WebFrameTest,SetFrameRectInvalidatesTextAutosizingMultipliers)742 TEST_F(WebFrameTest, SetFrameRectInvalidatesTextAutosizingMultipliers)
743 {
744     UseMockScrollbarSettings mockScrollbarSettings;
745     registerMockedHttpURLLoad("iframe_reload.html");
746     registerMockedHttpURLLoad("visible_iframe.html");
747 
748     FixedLayoutTestWebViewClient client;
749     int viewportWidth = 640;
750     int viewportHeight = 480;
751 
752     FrameTestHelpers::WebViewHelper webViewHelper;
753     webViewHelper.initializeAndLoad(m_baseURL + "iframe_reload.html", true, 0, &client, enableViewportSettings);
754 
755     WebCore::LocalFrame* mainFrame = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame());
756     WebCore::Document* document = mainFrame->document();
757     WebCore::FrameView* frameView = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
758     document->settings()->setTextAutosizingEnabled(true);
759     EXPECT_TRUE(document->settings()->textAutosizingEnabled());
760     webViewHelper.webViewImpl()->resize(WebSize(viewportWidth, viewportHeight));
761     webViewHelper.webViewImpl()->layout();
762 
763     for (WebCore::Frame* frame = mainFrame; frame; frame = frame->tree().traverseNext()) {
764         if (!frame->isLocalFrame())
765             continue;
766         EXPECT_TRUE(setTextAutosizingMultiplier(toLocalFrame(frame)->document(), 2));
767         for (WebCore::RenderObject* renderer = toLocalFrame(frame)->document()->renderView(); renderer; renderer = renderer->nextInPreOrder()) {
768             if (renderer->isText())
769                 EXPECT_FALSE(renderer->needsLayout());
770         }
771     }
772 
773     frameView->setFrameRect(WebCore::IntRect(0, 0, 200, 200));
774     for (WebCore::Frame* frame = mainFrame; frame; frame = frame->tree().traverseNext()) {
775         if (!frame->isLocalFrame())
776             continue;
777         for (WebCore::RenderObject* renderer = toLocalFrame(frame)->document()->renderView(); renderer; renderer = renderer->nextInPreOrder()) {
778             if (renderer->isText())
779                 EXPECT_TRUE(renderer->needsLayout());
780         }
781     }
782 }
783 
TEST_F(WebFrameTest,FixedLayoutSizeStopsResizeFromChangingLayoutSize)784 TEST_F(WebFrameTest, FixedLayoutSizeStopsResizeFromChangingLayoutSize)
785 {
786     UseMockScrollbarSettings mockScrollbarSettings;
787     registerMockedHttpURLLoad("fixed_layout.html");
788 
789     int viewportWidth = 640;
790     int viewportHeight = 480;
791 
792     int fixedLayoutWidth = viewportWidth / 2;
793     int fixedLayoutHeight = viewportHeight / 2;
794 
795     FrameTestHelpers::WebViewHelper webViewHelper;
796     webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, 0, enableViewportSettings);
797     webViewHelper.webView()->setFixedLayoutSize(WebSize(fixedLayoutWidth, fixedLayoutHeight));
798     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
799     webViewHelper.webView()->layout();
800 
801     EXPECT_EQ(fixedLayoutWidth, toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->view()->layoutSize().width());
802     EXPECT_EQ(fixedLayoutHeight, toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->view()->layoutSize().height());
803 }
804 
TEST_F(WebFrameTest,FixedLayoutSizePreventsResizeFromChangingPageScale)805 TEST_F(WebFrameTest, FixedLayoutSizePreventsResizeFromChangingPageScale)
806 {
807     UseMockScrollbarSettings mockScrollbarSettings;
808     registerMockedHttpURLLoad("fixed_layout.html");
809 
810     int viewportWidth = 640;
811     int viewportHeight = 480;
812 
813     int fixedLayoutWidth = viewportWidth / 2;
814     int fixedLayoutHeight = viewportHeight / 2;
815 
816     FrameTestHelpers::WebViewHelper webViewHelper;
817     webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, 0, enableViewportSettings);
818     webViewHelper.webView()->setFixedLayoutSize(WebSize(fixedLayoutWidth, fixedLayoutHeight));
819     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
820     webViewHelper.webView()->layout();
821     float pageScaleFactor = webViewHelper.webView()->pageScaleFactor();
822 
823     webViewHelper.webView()->resize(WebSize(viewportWidth * 2, viewportHeight * 2));
824 
825     EXPECT_EQ(pageScaleFactor, webViewHelper.webView()->pageScaleFactor());
826 }
827 
TEST_F(WebFrameTest,FixedLayoutSizePreventsLayoutFromChangingPageScale)828 TEST_F(WebFrameTest, FixedLayoutSizePreventsLayoutFromChangingPageScale)
829 {
830     UseMockScrollbarSettings mockScrollbarSettings;
831     registerMockedHttpURLLoad("fixed_layout.html");
832 
833     int viewportWidth = 640;
834     int viewportHeight = 480;
835 
836     int fixedLayoutWidth = viewportWidth * 2;
837     int fixedLayoutHeight = viewportHeight * 2;
838 
839     FrameTestHelpers::WebViewHelper webViewHelper;
840     webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, 0, enableViewportSettings);
841     webViewHelper.webView()->setFixedLayoutSize(WebSize(viewportWidth, viewportHeight));
842     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
843     webViewHelper.webView()->layout();
844     float pageScaleFactor = webViewHelper.webView()->pageScaleFactor();
845 
846     webViewHelper.webView()->setFixedLayoutSize(WebSize(fixedLayoutWidth, fixedLayoutHeight));
847     webViewHelper.webView()->layout();
848 
849     EXPECT_EQ(pageScaleFactor, webViewHelper.webView()->pageScaleFactor());
850 }
851 
TEST_F(WebFrameTest,PreferredSizeAndContentSizeReportedCorrectlyWithZeroHeightFixedLayout)852 TEST_F(WebFrameTest, PreferredSizeAndContentSizeReportedCorrectlyWithZeroHeightFixedLayout)
853 {
854     UseMockScrollbarSettings mockScrollbarSettings;
855     registerMockedHttpURLLoad("200-by-300.html");
856 
857     int windowWidth = 100;
858     int windowHeight = 100;
859     int viewportWidth = 100;
860     int viewportHeight = 0;
861     int divWidth = 200;
862     int divHeight = 300;
863 
864     FixedLayoutTestWebViewClient client;
865     client.m_screenInfo.deviceScaleFactor = 1;
866 
867     FrameTestHelpers::WebViewHelper webViewHelper;
868     webViewHelper.initializeAndLoad(m_baseURL + "200-by-300.html", true, 0, &client, enableViewportSettings);
869     webViewHelper.webView()->resize(WebSize(windowWidth, windowHeight));
870     webViewHelper.webView()->setFixedLayoutSize(WebSize(viewportWidth, viewportHeight));
871     webViewHelper.webView()->layout();
872 
873     EXPECT_EQ(divWidth, webViewHelper.webView()->mainFrame()->contentsSize().width);
874     EXPECT_EQ(divHeight, webViewHelper.webView()->mainFrame()->contentsSize().height);
875 
876     EXPECT_EQ(divWidth, webViewHelper.webView()->contentsPreferredMinimumSize().width);
877     EXPECT_EQ(divHeight, webViewHelper.webView()->contentsPreferredMinimumSize().height);
878 }
879 
TEST_F(WebFrameTest,DisablingFixedLayoutSizeSetsCorrectLayoutSize)880 TEST_F(WebFrameTest, DisablingFixedLayoutSizeSetsCorrectLayoutSize)
881 {
882     UseMockScrollbarSettings mockScrollbarSettings;
883     registerMockedHttpURLLoad("no_viewport_tag.html");
884 
885     FixedLayoutTestWebViewClient client;
886     client.m_screenInfo.deviceScaleFactor = 1;
887     int viewportWidth = 640;
888     int viewportHeight = 480;
889 
890     FrameTestHelpers::WebViewHelper webViewHelper;
891     webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client, enableViewportSettings);
892     applyViewportStyleOverride(&webViewHelper);
893     webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
894     webViewHelper.webView()->settings()->setUseWideViewport(true);
895     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
896 
897     webViewHelper.webView()->setFixedLayoutSize(WebSize(viewportWidth, viewportHeight));
898     EXPECT_TRUE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
899     webViewHelper.webView()->layout();
900     EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
901 
902     webViewHelper.webView()->setFixedLayoutSize(WebSize(0, 0));
903     EXPECT_TRUE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
904     webViewHelper.webView()->layout();
905     EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
906 }
907 
TEST_F(WebFrameTest,ZeroHeightPositiveWidthNotIgnored)908 TEST_F(WebFrameTest, ZeroHeightPositiveWidthNotIgnored)
909 {
910     UseMockScrollbarSettings mockScrollbarSettings;
911 
912     FixedLayoutTestWebViewClient client;
913     client.m_screenInfo.deviceScaleFactor = 1;
914     int viewportWidth = 1280;
915     int viewportHeight = 0;
916 
917     FrameTestHelpers::WebViewHelper webViewHelper;
918     webViewHelper.initialize(true, 0, &client, enableViewportSettings);
919     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
920 
921     EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
922     EXPECT_EQ(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
923 }
924 
TEST_F(WebFrameTest,DeviceScaleFactorUsesDefaultWithoutViewportTag)925 TEST_F(WebFrameTest, DeviceScaleFactorUsesDefaultWithoutViewportTag)
926 {
927     UseMockScrollbarSettings mockScrollbarSettings;
928     registerMockedHttpURLLoad("no_viewport_tag.html");
929 
930     int viewportWidth = 640;
931     int viewportHeight = 480;
932 
933     FixedLayoutTestWebViewClient client;
934     client.m_screenInfo.deviceScaleFactor = 2;
935 
936     FrameTestHelpers::WebViewHelper webViewHelper;
937     webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client, enableViewportSettings);
938 
939     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
940     webViewHelper.webView()->layout();
941 
942     EXPECT_EQ(2, webViewHelper.webView()->deviceScaleFactor());
943 
944     // Device scale factor should be independent of page scale.
945     webViewHelper.webView()->setPageScaleFactorLimits(1, 2);
946     webViewHelper.webView()->setPageScaleFactor(0.5);
947     webViewHelper.webView()->layout();
948     EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor());
949 
950     // Force the layout to happen before leaving the test.
951     webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8();
952 }
953 
TEST_F(WebFrameTest,FixedLayoutInitializeAtMinimumScale)954 TEST_F(WebFrameTest, FixedLayoutInitializeAtMinimumScale)
955 {
956     UseMockScrollbarSettings mockScrollbarSettings;
957 
958     registerMockedHttpURLLoad("fixed_layout.html");
959 
960     FixedLayoutTestWebViewClient client;
961     client.m_screenInfo.deviceScaleFactor = 1;
962     int viewportWidth = 640;
963     int viewportHeight = 480;
964 
965     // Make sure we initialize to minimum scale, even if the window size
966     // only becomes available after the load begins.
967     FrameTestHelpers::WebViewHelper webViewHelper;
968     webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
969     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
970 
971     int defaultFixedLayoutWidth = 980;
972     float minimumPageScaleFactor = viewportWidth / (float) defaultFixedLayoutWidth;
973     EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
974     EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->minimumPageScaleFactor());
975 
976     // Assume the user has pinch zoomed to page scale factor 2.
977     float userPinchPageScaleFactor = 2;
978     webViewHelper.webView()->setPageScaleFactor(userPinchPageScaleFactor);
979     webViewHelper.webView()->layout();
980 
981     // Make sure we don't reset to initial scale if the page continues to load.
982     webViewHelper.webViewImpl()->didCommitLoad(false, false);
983     webViewHelper.webViewImpl()->didChangeContentsSize();
984     EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
985 
986     // Make sure we don't reset to initial scale if the viewport size changes.
987     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight + 100));
988     EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
989 }
990 
TEST_F(WebFrameTest,WideDocumentInitializeAtMinimumScale)991 TEST_F(WebFrameTest, WideDocumentInitializeAtMinimumScale)
992 {
993     UseMockScrollbarSettings mockScrollbarSettings;
994 
995     registerMockedHttpURLLoad("wide_document.html");
996 
997     FixedLayoutTestWebViewClient client;
998     client.m_screenInfo.deviceScaleFactor = 1;
999     int viewportWidth = 640;
1000     int viewportHeight = 480;
1001 
1002     // Make sure we initialize to minimum scale, even if the window size
1003     // only becomes available after the load begins.
1004     FrameTestHelpers::WebViewHelper webViewHelper;
1005     webViewHelper.initializeAndLoad(m_baseURL + "wide_document.html", true, 0, &client, enableViewportSettings);
1006     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1007 
1008     int wideDocumentWidth = 1500;
1009     float minimumPageScaleFactor = viewportWidth / (float) wideDocumentWidth;
1010     EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1011     EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->minimumPageScaleFactor());
1012 
1013     // Assume the user has pinch zoomed to page scale factor 2.
1014     float userPinchPageScaleFactor = 2;
1015     webViewHelper.webView()->setPageScaleFactor(userPinchPageScaleFactor);
1016     webViewHelper.webView()->layout();
1017 
1018     // Make sure we don't reset to initial scale if the page continues to load.
1019     webViewHelper.webViewImpl()->didCommitLoad(false, false);
1020     webViewHelper.webViewImpl()->didChangeContentsSize();
1021     EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1022 
1023     // Make sure we don't reset to initial scale if the viewport size changes.
1024     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight + 100));
1025     EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1026 }
1027 
TEST_F(WebFrameTest,DelayedViewportInitialScale)1028 TEST_F(WebFrameTest, DelayedViewportInitialScale)
1029 {
1030     UseMockScrollbarSettings mockScrollbarSettings;
1031     registerMockedHttpURLLoad("viewport-auto-initial-scale.html");
1032 
1033     FixedLayoutTestWebViewClient client;
1034     client.m_screenInfo.deviceScaleFactor = 1;
1035     int viewportWidth = 640;
1036     int viewportHeight = 480;
1037 
1038     FrameTestHelpers::WebViewHelper webViewHelper;
1039     webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings);
1040     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1041 
1042     EXPECT_EQ(0.25f, webViewHelper.webView()->pageScaleFactor());
1043 
1044     WebCore::Document* document = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document();
1045     WebCore::ViewportDescription description = document->viewportDescription();
1046     description.zoom = 2;
1047     document->setViewportDescription(description);
1048     webViewHelper.webView()->layout();
1049     EXPECT_EQ(2, webViewHelper.webView()->pageScaleFactor());
1050 }
1051 
TEST_F(WebFrameTest,setLoadWithOverviewModeToFalse)1052 TEST_F(WebFrameTest, setLoadWithOverviewModeToFalse)
1053 {
1054     UseMockScrollbarSettings mockScrollbarSettings;
1055     registerMockedHttpURLLoad("viewport-auto-initial-scale.html");
1056 
1057     FixedLayoutTestWebViewClient client;
1058     client.m_screenInfo.deviceScaleFactor = 1;
1059     int viewportWidth = 640;
1060     int viewportHeight = 480;
1061 
1062     FrameTestHelpers::WebViewHelper webViewHelper;
1063     webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings);
1064     webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1065     webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1066     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1067 
1068     // The page must be displayed at 100% zoom.
1069     EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
1070 }
1071 
TEST_F(WebFrameTest,SetLoadWithOverviewModeToFalseAndNoWideViewport)1072 TEST_F(WebFrameTest, SetLoadWithOverviewModeToFalseAndNoWideViewport)
1073 {
1074     UseMockScrollbarSettings mockScrollbarSettings;
1075     registerMockedHttpURLLoad("large-div.html");
1076 
1077     FixedLayoutTestWebViewClient client;
1078     client.m_screenInfo.deviceScaleFactor = 1;
1079     int viewportWidth = 640;
1080     int viewportHeight = 480;
1081 
1082     FrameTestHelpers::WebViewHelper webViewHelper;
1083     webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client, enableViewportSettings);
1084     webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1085     webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1086     webViewHelper.webView()->settings()->setUseWideViewport(false);
1087     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1088 
1089     // The page must be displayed at 100% zoom, despite that it hosts a wide div element.
1090     EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
1091 }
1092 
TEST_F(WebFrameTest,NoWideViewportIgnoresPageViewportWidth)1093 TEST_F(WebFrameTest, NoWideViewportIgnoresPageViewportWidth)
1094 {
1095     UseMockScrollbarSettings mockScrollbarSettings;
1096     registerMockedHttpURLLoad("viewport-auto-initial-scale.html");
1097 
1098     FixedLayoutTestWebViewClient client;
1099     client.m_screenInfo.deviceScaleFactor = 1;
1100     int viewportWidth = 640;
1101     int viewportHeight = 480;
1102 
1103     FrameTestHelpers::WebViewHelper webViewHelper;
1104     webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings);
1105     webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1106     webViewHelper.webView()->settings()->setUseWideViewport(false);
1107     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1108 
1109     // The page sets viewport width to 3000, but with UseWideViewport == false is must be ignored.
1110     EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1111     EXPECT_EQ(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
1112 }
1113 
TEST_F(WebFrameTest,NoWideViewportIgnoresPageViewportWidthButAccountsScale)1114 TEST_F(WebFrameTest, NoWideViewportIgnoresPageViewportWidthButAccountsScale)
1115 {
1116     UseMockScrollbarSettings mockScrollbarSettings;
1117     registerMockedHttpURLLoad("viewport-wide-2x-initial-scale.html");
1118 
1119     FixedLayoutTestWebViewClient client;
1120     client.m_screenInfo.deviceScaleFactor = 1;
1121     int viewportWidth = 640;
1122     int viewportHeight = 480;
1123 
1124     FrameTestHelpers::WebViewHelper webViewHelper;
1125     webViewHelper.initializeAndLoad(m_baseURL + "viewport-wide-2x-initial-scale.html", true, 0, &client, enableViewportSettings);
1126     webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1127     webViewHelper.webView()->settings()->setUseWideViewport(false);
1128     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1129 
1130     // The page sets viewport width to 3000, but with UseWideViewport == false it must be ignored.
1131     // While the initial scale specified by the page must be accounted.
1132     EXPECT_EQ(viewportWidth / 2, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1133     EXPECT_EQ(viewportHeight / 2, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
1134 }
1135 
TEST_F(WebFrameTest,WideViewportSetsTo980WithoutViewportTag)1136 TEST_F(WebFrameTest, WideViewportSetsTo980WithoutViewportTag)
1137 {
1138     UseMockScrollbarSettings mockScrollbarSettings;
1139     registerMockedHttpURLLoad("no_viewport_tag.html");
1140 
1141     FixedLayoutTestWebViewClient client;
1142     client.m_screenInfo.deviceScaleFactor = 1;
1143     int viewportWidth = 640;
1144     int viewportHeight = 480;
1145 
1146     FrameTestHelpers::WebViewHelper webViewHelper;
1147     webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client, enableViewportSettings);
1148     applyViewportStyleOverride(&webViewHelper);
1149     webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1150     webViewHelper.webView()->settings()->setUseWideViewport(true);
1151     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1152 
1153     EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1154     EXPECT_EQ(980.0 / viewportWidth * viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
1155 }
1156 
TEST_F(WebFrameTest,NoWideViewportAndHeightInMeta)1157 TEST_F(WebFrameTest, NoWideViewportAndHeightInMeta)
1158 {
1159     UseMockScrollbarSettings mockScrollbarSettings;
1160     registerMockedHttpURLLoad("viewport-height-1000.html");
1161 
1162     FixedLayoutTestWebViewClient client;
1163     client.m_screenInfo.deviceScaleFactor = 1;
1164     int viewportWidth = 640;
1165     int viewportHeight = 480;
1166 
1167     FrameTestHelpers::WebViewHelper webViewHelper;
1168     webViewHelper.initializeAndLoad(m_baseURL + "viewport-height-1000.html", true, 0, &client, enableViewportSettings);
1169     webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1170     webViewHelper.webView()->settings()->setUseWideViewport(false);
1171     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1172 
1173     EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1174 }
1175 
TEST_F(WebFrameTest,WideViewportSetsTo980WithAutoWidth)1176 TEST_F(WebFrameTest, WideViewportSetsTo980WithAutoWidth)
1177 {
1178     UseMockScrollbarSettings mockScrollbarSettings;
1179     registerMockedHttpURLLoad("viewport-2x-initial-scale.html");
1180 
1181     FixedLayoutTestWebViewClient client;
1182     client.m_screenInfo.deviceScaleFactor = 1;
1183     int viewportWidth = 640;
1184     int viewportHeight = 480;
1185 
1186     FrameTestHelpers::WebViewHelper webViewHelper;
1187     webViewHelper.initializeAndLoad(m_baseURL + "viewport-2x-initial-scale.html", true, 0, &client, enableViewportSettings);
1188     applyViewportStyleOverride(&webViewHelper);
1189     webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1190     webViewHelper.webView()->settings()->setUseWideViewport(true);
1191     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1192 
1193     EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1194     EXPECT_EQ(980.0 / viewportWidth * viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height());
1195 }
1196 
TEST_F(WebFrameTest,PageViewportInitialScaleOverridesLoadWithOverviewMode)1197 TEST_F(WebFrameTest, PageViewportInitialScaleOverridesLoadWithOverviewMode)
1198 {
1199     UseMockScrollbarSettings mockScrollbarSettings;
1200     registerMockedHttpURLLoad("viewport-wide-2x-initial-scale.html");
1201 
1202     FixedLayoutTestWebViewClient client;
1203     client.m_screenInfo.deviceScaleFactor = 1;
1204     int viewportWidth = 640;
1205     int viewportHeight = 480;
1206 
1207     FrameTestHelpers::WebViewHelper webViewHelper;
1208     webViewHelper.initializeAndLoad(m_baseURL + "viewport-wide-2x-initial-scale.html", true, 0, &client, enableViewportSettings);
1209     webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1210     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1211 
1212     // The page must be displayed at 200% zoom, as specified in its viewport meta tag.
1213     EXPECT_EQ(2.0f, webViewHelper.webView()->pageScaleFactor());
1214 }
1215 
TEST_F(WebFrameTest,setInitialPageScaleFactorPermanently)1216 TEST_F(WebFrameTest, setInitialPageScaleFactorPermanently)
1217 {
1218     UseMockScrollbarSettings mockScrollbarSettings;
1219 
1220     registerMockedHttpURLLoad("fixed_layout.html");
1221 
1222     FixedLayoutTestWebViewClient client;
1223     client.m_screenInfo.deviceScaleFactor = 1;
1224     float enforcedPageScaleFactor = 2.0f;
1225 
1226     FrameTestHelpers::WebViewHelper webViewHelper;
1227     webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1228     applyViewportStyleOverride(&webViewHelper);
1229     webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1230     webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1231     webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1232     webViewHelper.webView()->layout();
1233 
1234     EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1235 
1236     int viewportWidth = 640;
1237     int viewportHeight = 480;
1238     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1239     webViewHelper.webView()->layout();
1240 
1241     EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1242 
1243     webViewHelper.webView()->setInitialPageScaleOverride(-1);
1244     webViewHelper.webView()->layout();
1245     EXPECT_EQ(1.0, webViewHelper.webView()->pageScaleFactor());
1246 }
1247 
TEST_F(WebFrameTest,PermanentInitialPageScaleFactorOverridesLoadWithOverviewMode)1248 TEST_F(WebFrameTest, PermanentInitialPageScaleFactorOverridesLoadWithOverviewMode)
1249 {
1250     UseMockScrollbarSettings mockScrollbarSettings;
1251     registerMockedHttpURLLoad("viewport-auto-initial-scale.html");
1252 
1253     FixedLayoutTestWebViewClient client;
1254     client.m_screenInfo.deviceScaleFactor = 1;
1255     int viewportWidth = 640;
1256     int viewportHeight = 480;
1257     float enforcedPageScaleFactor = 0.5f;
1258 
1259     FrameTestHelpers::WebViewHelper webViewHelper;
1260     webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings);
1261     webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1262     webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1263     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1264 
1265     EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1266 }
1267 
TEST_F(WebFrameTest,PermanentInitialPageScaleFactorOverridesPageViewportInitialScale)1268 TEST_F(WebFrameTest, PermanentInitialPageScaleFactorOverridesPageViewportInitialScale)
1269 {
1270     UseMockScrollbarSettings mockScrollbarSettings;
1271     registerMockedHttpURLLoad("viewport-wide-2x-initial-scale.html");
1272 
1273     FixedLayoutTestWebViewClient client;
1274     client.m_screenInfo.deviceScaleFactor = 1;
1275     int viewportWidth = 640;
1276     int viewportHeight = 480;
1277     float enforcedPageScaleFactor = 0.5f;
1278 
1279     FrameTestHelpers::WebViewHelper webViewHelper;
1280     webViewHelper.initializeAndLoad(m_baseURL + "viewport-wide-2x-initial-scale.html", true, 0, &client, enableViewportSettings);
1281     webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1282     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1283 
1284     EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1285 }
1286 
TEST_F(WebFrameTest,SmallPermanentInitialPageScaleFactorIsClobbered)1287 TEST_F(WebFrameTest, SmallPermanentInitialPageScaleFactorIsClobbered)
1288 {
1289     UseMockScrollbarSettings mockScrollbarSettings;
1290     const char* pages[] = {
1291         // These pages trigger the clobbering condition. There must be a matching item in "pageScaleFactors" array.
1292         "viewport-device-0.5x-initial-scale.html",
1293         "viewport-initial-scale-1.html",
1294         // These ones do not.
1295         "viewport-auto-initial-scale.html",
1296         "viewport-target-densitydpi-device-and-fixed-width.html"
1297     };
1298     float pageScaleFactors[] = { 0.5f, 1.0f };
1299     for (size_t i = 0; i < ARRAY_SIZE(pages); ++i)
1300         registerMockedHttpURLLoad(pages[i]);
1301 
1302     FixedLayoutTestWebViewClient client;
1303     client.m_screenInfo.deviceScaleFactor = 1;
1304     int viewportWidth = 400;
1305     int viewportHeight = 300;
1306     float enforcedPageScaleFactor = 0.75f;
1307 
1308     for (size_t i = 0; i < ARRAY_SIZE(pages); ++i) {
1309         for (int quirkEnabled = 0; quirkEnabled <= 1; ++quirkEnabled) {
1310             FrameTestHelpers::WebViewHelper webViewHelper;
1311             webViewHelper.initializeAndLoad(m_baseURL + pages[i], true, 0, &client, enableViewportSettings);
1312             applyViewportStyleOverride(&webViewHelper);
1313             webViewHelper.webView()->settings()->setClobberUserAgentInitialScaleQuirk(quirkEnabled);
1314             webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1315             webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1316 
1317             float expectedPageScaleFactor = quirkEnabled && i < ARRAY_SIZE(pageScaleFactors) ? pageScaleFactors[i] : enforcedPageScaleFactor;
1318             EXPECT_EQ(expectedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1319         }
1320     }
1321 }
1322 
TEST_F(WebFrameTest,PermanentInitialPageScaleFactorAffectsLayoutWidth)1323 TEST_F(WebFrameTest, PermanentInitialPageScaleFactorAffectsLayoutWidth)
1324 {
1325     UseMockScrollbarSettings mockScrollbarSettings;
1326 
1327     FixedLayoutTestWebViewClient client;
1328     client.m_screenInfo.deviceScaleFactor = 1;
1329     int viewportWidth = 640;
1330     int viewportHeight = 480;
1331     float enforcedPageScaleFactor = 0.5;
1332 
1333     FrameTestHelpers::WebViewHelper webViewHelper;
1334     webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings);
1335     webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1336     webViewHelper.webView()->settings()->setUseWideViewport(false);
1337     webViewHelper.webView()->settings()->setLoadWithOverviewMode(false);
1338     webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1339     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1340 
1341     EXPECT_EQ(viewportWidth / enforcedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1342     EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1343 }
1344 
TEST_F(WebFrameTest,WideViewportInitialScaleDoesNotExpandFixedLayoutWidth)1345 TEST_F(WebFrameTest, WideViewportInitialScaleDoesNotExpandFixedLayoutWidth)
1346 {
1347     UseMockScrollbarSettings mockScrollbarSettings;
1348     registerMockedHttpURLLoad("viewport-device-0.5x-initial-scale.html");
1349 
1350     FixedLayoutTestWebViewClient client;
1351     client.m_screenInfo.deviceScaleFactor = 1;
1352     int viewportWidth = 640;
1353     int viewportHeight = 480;
1354 
1355     FrameTestHelpers::WebViewHelper webViewHelper;
1356     webViewHelper.initializeAndLoad(m_baseURL + "viewport-device-0.5x-initial-scale.html", true, 0, &client, enableViewportSettings);
1357     webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1358     webViewHelper.webView()->settings()->setUseWideViewport(true);
1359     webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1360     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1361 
1362     EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1363     EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor());
1364 
1365     webViewHelper.webView()->setFixedLayoutSize(WebSize(2000, 1500));
1366     webViewHelper.webView()->layout();
1367     EXPECT_EQ(2000, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1368     EXPECT_EQ(0.5f, webViewHelper.webView()->pageScaleFactor());
1369 }
1370 
TEST_F(WebFrameTest,SetForceZeroLayoutHeight)1371 TEST_F(WebFrameTest, SetForceZeroLayoutHeight)
1372 {
1373     UseMockScrollbarSettings mockScrollbarSettings;
1374     registerMockedHttpURLLoad("200-by-300.html");
1375 
1376     FixedLayoutTestWebViewClient client;
1377     client.m_screenInfo.deviceScaleFactor = 1;
1378     int viewportWidth = 640;
1379     int viewportHeight = 480;
1380 
1381     FrameTestHelpers::WebViewHelper webViewHelper;
1382 
1383     webViewHelper.initializeAndLoad(m_baseURL + "200-by-300.html", true, 0, &client, enableViewportSettings);
1384     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1385     webViewHelper.webView()->layout();
1386 
1387     EXPECT_LE(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1388     webViewHelper.webView()->settings()->setForceZeroLayoutHeight(true);
1389     EXPECT_TRUE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
1390 
1391     EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1392 
1393     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight * 2));
1394     EXPECT_FALSE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
1395     EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1396 
1397     webViewHelper.webView()->resize(WebSize(viewportWidth * 2, viewportHeight));
1398     webViewHelper.webView()->layout();
1399     EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1400 
1401     webViewHelper.webView()->settings()->setForceZeroLayoutHeight(false);
1402     EXPECT_LE(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1403 }
1404 
TEST_F(WebFrameTest,SetForceZeroLayoutHeightWorksAcrossNavigations)1405 TEST_F(WebFrameTest, SetForceZeroLayoutHeightWorksAcrossNavigations)
1406 {
1407     UseMockScrollbarSettings mockScrollbarSettings;
1408     registerMockedHttpURLLoad("200-by-300.html");
1409     registerMockedHttpURLLoad("large-div.html");
1410 
1411     FixedLayoutTestWebViewClient client;
1412     client.m_screenInfo.deviceScaleFactor = 1;
1413     int viewportWidth = 640;
1414     int viewportHeight = 480;
1415 
1416     FrameTestHelpers::WebViewHelper webViewHelper;
1417 
1418     webViewHelper.initializeAndLoad(m_baseURL + "200-by-300.html", true, 0, &client, enableViewportSettings);
1419     webViewHelper.webView()->settings()->setForceZeroLayoutHeight(true);
1420     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1421     webViewHelper.webView()->layout();
1422 
1423     FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "large-div.html");
1424     webViewHelper.webView()->layout();
1425 
1426     EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1427 }
1428 
TEST_F(WebFrameTest,SetForceZeroLayoutHeightWithWideViewportQuirk)1429 TEST_F(WebFrameTest, SetForceZeroLayoutHeightWithWideViewportQuirk)
1430 {
1431     UseMockScrollbarSettings mockScrollbarSettings;
1432     registerMockedHttpURLLoad("200-by-300.html");
1433 
1434     FixedLayoutTestWebViewClient client;
1435     client.m_screenInfo.deviceScaleFactor = 1;
1436     int viewportWidth = 640;
1437     int viewportHeight = 480;
1438 
1439     FrameTestHelpers::WebViewHelper webViewHelper;
1440 
1441     webViewHelper.initializeAndLoad(m_baseURL + "200-by-300.html", true, 0, &client, enableViewportSettings);
1442     webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1443     webViewHelper.webView()->settings()->setUseWideViewport(true);
1444     webViewHelper.webView()->settings()->setForceZeroLayoutHeight(true);
1445     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1446     webViewHelper.webView()->layout();
1447 
1448     EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1449 }
1450 
TEST_F(WebFrameTest,WideViewportAndWideContentWithInitialScale)1451 TEST_F(WebFrameTest, WideViewportAndWideContentWithInitialScale)
1452 {
1453     UseMockScrollbarSettings mockScrollbarSettings;
1454     registerMockedHttpURLLoad("wide_document_width_viewport.html");
1455 
1456     FixedLayoutTestWebViewClient client;
1457     client.m_screenInfo.deviceScaleFactor = 1;
1458     int viewportWidth = 600;
1459     int viewportHeight = 800;
1460 
1461     FrameTestHelpers::WebViewHelper webViewHelper;
1462     webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings);
1463     webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1464     webViewHelper.webView()->settings()->setUseWideViewport(true);
1465     webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1466     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1467 
1468     FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "wide_document_width_viewport.html");
1469     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1470 
1471     int wideDocumentWidth = 800;
1472     float minimumPageScaleFactor = viewportWidth / (float) wideDocumentWidth;
1473     EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1474     EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->minimumPageScaleFactor());
1475 }
1476 
TEST_F(WebFrameTest,WideViewportQuirkClobbersHeight)1477 TEST_F(WebFrameTest, WideViewportQuirkClobbersHeight)
1478 {
1479     UseMockScrollbarSettings mockScrollbarSettings;
1480     registerMockedHttpURLLoad("viewport-height-1000.html");
1481 
1482     FixedLayoutTestWebViewClient client;
1483     client.m_screenInfo.deviceScaleFactor = 1;
1484     int viewportWidth = 600;
1485     int viewportHeight = 800;
1486 
1487     FrameTestHelpers::WebViewHelper webViewHelper;
1488     webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings);
1489     webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1490     webViewHelper.webView()->settings()->setUseWideViewport(false);
1491     webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1492     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1493 
1494     FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport-height-1000.html");
1495     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1496 
1497     EXPECT_EQ(800, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1498     EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor());
1499 }
1500 
TEST_F(WebFrameTest,LayoutSize320Quirk)1501 TEST_F(WebFrameTest, LayoutSize320Quirk)
1502 {
1503     UseMockScrollbarSettings mockScrollbarSettings;
1504     registerMockedHttpURLLoad("viewport/viewport-30.html");
1505 
1506     FixedLayoutTestWebViewClient client;
1507     client.m_screenInfo.deviceScaleFactor = 1;
1508     int viewportWidth = 600;
1509     int viewportHeight = 800;
1510 
1511     FrameTestHelpers::WebViewHelper webViewHelper;
1512     webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings);
1513     webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1514     webViewHelper.webView()->settings()->setUseWideViewport(true);
1515     webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1516     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1517 
1518     FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport/viewport-30.html");
1519     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1520 
1521     EXPECT_EQ(600, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1522     EXPECT_EQ(800, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1523     EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor());
1524 
1525     // The magic number to snap to device-width is 320, so test that 321 is
1526     // respected.
1527     WebCore::Document* document = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document();
1528     WebCore::ViewportDescription description = document->viewportDescription();
1529     description.minWidth = WebCore::Length(321, WebCore::Fixed);
1530     description.maxWidth = WebCore::Length(321, WebCore::Fixed);
1531     document->setViewportDescription(description);
1532     webViewHelper.webView()->layout();
1533     EXPECT_EQ(321, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1534 
1535     description.minWidth = WebCore::Length(320, WebCore::Fixed);
1536     description.maxWidth = WebCore::Length(320, WebCore::Fixed);
1537     document->setViewportDescription(description);
1538     webViewHelper.webView()->layout();
1539     EXPECT_EQ(600, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1540 
1541     description = document->viewportDescription();
1542     description.maxHeight = WebCore::Length(1000, WebCore::Fixed);
1543     document->setViewportDescription(description);
1544     webViewHelper.webView()->layout();
1545     EXPECT_EQ(1000, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1546 
1547     description.maxHeight = WebCore::Length(320, WebCore::Fixed);
1548     document->setViewportDescription(description);
1549     webViewHelper.webView()->layout();
1550     EXPECT_EQ(800, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
1551 }
1552 
TEST_F(WebFrameTest,ZeroValuesQuirk)1553 TEST_F(WebFrameTest, ZeroValuesQuirk)
1554 {
1555     UseMockScrollbarSettings mockScrollbarSettings;
1556     registerMockedHttpURLLoad("viewport-zero-values.html");
1557 
1558     FixedLayoutTestWebViewClient client;
1559     client.m_screenInfo.deviceScaleFactor = 1;
1560     int viewportWidth = 640;
1561     int viewportHeight = 480;
1562 
1563     FrameTestHelpers::WebViewHelper webViewHelper;
1564     webViewHelper.initialize(true, 0, &client, enableViewportSettings);
1565     webViewHelper.webView()->settings()->setViewportMetaZeroValuesQuirk(true);
1566     webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1567     webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true);
1568     FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport-zero-values.html");
1569     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1570 
1571     EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1572     EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
1573 
1574     webViewHelper.webView()->settings()->setUseWideViewport(true);
1575     webViewHelper.webView()->layout();
1576     EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1577     EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor());
1578 }
1579 
TEST_F(WebFrameTest,OverflowHiddenDisablesScrolling)1580 TEST_F(WebFrameTest, OverflowHiddenDisablesScrolling)
1581 {
1582     registerMockedHttpURLLoad("body-overflow-hidden.html");
1583 
1584     FixedLayoutTestWebViewClient client;
1585     client.m_screenInfo.deviceScaleFactor = 1;
1586     int viewportWidth = 640;
1587     int viewportHeight = 480;
1588 
1589     FrameTestHelpers::WebViewHelper webViewHelper;
1590     webViewHelper.initialize(true, 0, &client);
1591     FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "body-overflow-hidden.html");
1592     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1593 
1594     WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
1595     EXPECT_FALSE(view->userInputScrollable(WebCore::VerticalScrollbar));
1596 }
1597 
TEST_F(WebFrameTest,IgnoreOverflowHiddenQuirk)1598 TEST_F(WebFrameTest, IgnoreOverflowHiddenQuirk)
1599 {
1600     registerMockedHttpURLLoad("body-overflow-hidden.html");
1601 
1602     FixedLayoutTestWebViewClient client;
1603     client.m_screenInfo.deviceScaleFactor = 1;
1604     int viewportWidth = 640;
1605     int viewportHeight = 480;
1606 
1607     FrameTestHelpers::WebViewHelper webViewHelper;
1608     webViewHelper.initialize(true, 0, &client);
1609     webViewHelper.webView()->settings()->setIgnoreMainFrameOverflowHiddenQuirk(true);
1610     FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "body-overflow-hidden.html");
1611     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1612 
1613     WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
1614     EXPECT_TRUE(view->userInputScrollable(WebCore::VerticalScrollbar));
1615 }
1616 
TEST_F(WebFrameTest,NonZeroValuesNoQuirk)1617 TEST_F(WebFrameTest, NonZeroValuesNoQuirk)
1618 {
1619     UseMockScrollbarSettings mockScrollbarSettings;
1620     registerMockedHttpURLLoad("viewport-nonzero-values.html");
1621 
1622     FixedLayoutTestWebViewClient client;
1623     client.m_screenInfo.deviceScaleFactor = 1;
1624     int viewportWidth = 640;
1625     int viewportHeight = 480;
1626     float expectedPageScaleFactor = 0.5f;
1627 
1628     FrameTestHelpers::WebViewHelper webViewHelper;
1629     webViewHelper.initialize(true, 0, &client, enableViewportSettings);
1630     webViewHelper.webView()->settings()->setViewportMetaZeroValuesQuirk(true);
1631     webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1632     FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport-nonzero-values.html");
1633     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1634 
1635     EXPECT_EQ(viewportWidth / expectedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1636     EXPECT_EQ(expectedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1637 
1638     webViewHelper.webView()->settings()->setUseWideViewport(true);
1639     webViewHelper.webView()->layout();
1640     EXPECT_EQ(viewportWidth / expectedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width());
1641     EXPECT_EQ(expectedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
1642 }
1643 
TEST_F(WebFrameTest,setPageScaleFactorDoesNotLayout)1644 TEST_F(WebFrameTest, setPageScaleFactorDoesNotLayout)
1645 {
1646     UseMockScrollbarSettings mockScrollbarSettings;
1647     registerMockedHttpURLLoad("fixed_layout.html");
1648 
1649     FixedLayoutTestWebViewClient client;
1650     client.m_screenInfo.deviceScaleFactor = 1;
1651     // Small viewport to ensure there are always scrollbars.
1652     int viewportWidth = 64;
1653     int viewportHeight = 48;
1654 
1655     FrameTestHelpers::WebViewHelper webViewHelper;
1656     webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1657     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1658     webViewHelper.webView()->layout();
1659 
1660     int prevLayoutCount = webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount();
1661     webViewHelper.webViewImpl()->setPageScaleFactor(3);
1662     EXPECT_FALSE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
1663     EXPECT_EQ(prevLayoutCount, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount());
1664 }
1665 
TEST_F(WebFrameTest,setPageScaleFactorWithOverlayScrollbarsDoesNotLayout)1666 TEST_F(WebFrameTest, setPageScaleFactorWithOverlayScrollbarsDoesNotLayout)
1667 {
1668     UseMockScrollbarSettings mockScrollbarSettings;
1669 
1670     registerMockedHttpURLLoad("fixed_layout.html");
1671 
1672     FixedLayoutTestWebViewClient client;
1673     client.m_screenInfo.deviceScaleFactor = 1;
1674     int viewportWidth = 640;
1675     int viewportHeight = 480;
1676 
1677     FrameTestHelpers::WebViewHelper webViewHelper;
1678     webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1679     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1680     webViewHelper.webView()->layout();
1681 
1682     int prevLayoutCount = webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount();
1683     webViewHelper.webViewImpl()->setPageScaleFactor(30);
1684     EXPECT_FALSE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
1685     EXPECT_EQ(prevLayoutCount, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount());
1686 
1687 }
1688 
TEST_F(WebFrameTest,pageScaleFactorWrittenToHistoryItem)1689 TEST_F(WebFrameTest, pageScaleFactorWrittenToHistoryItem)
1690 {
1691     UseMockScrollbarSettings mockScrollbarSettings;
1692     registerMockedHttpURLLoad("fixed_layout.html");
1693 
1694     FixedLayoutTestWebViewClient client;
1695     client.m_screenInfo.deviceScaleFactor = 1;
1696     int viewportWidth = 640;
1697     int viewportHeight = 480;
1698 
1699     FrameTestHelpers::WebViewHelper webViewHelper;
1700     webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1701     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1702     webViewHelper.webView()->layout();
1703 
1704     webViewHelper.webView()->setPageScaleFactor(3);
1705     EXPECT_EQ(3, toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->loader().currentItem()->pageScaleFactor());
1706 }
1707 
TEST_F(WebFrameTest,initialScaleWrittenToHistoryItem)1708 TEST_F(WebFrameTest, initialScaleWrittenToHistoryItem)
1709 {
1710     UseMockScrollbarSettings mockScrollbarSettings;
1711     registerMockedHttpURLLoad("fixed_layout.html");
1712 
1713     FixedLayoutTestWebViewClient client;
1714     client.m_screenInfo.deviceScaleFactor = 1;
1715     int viewportWidth = 640;
1716     int viewportHeight = 480;
1717 
1718     FrameTestHelpers::WebViewHelper webViewHelper;
1719     webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1720     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1721     webViewHelper.webView()->layout();
1722 
1723     int defaultFixedLayoutWidth = 980;
1724     float minimumPageScaleFactor = viewportWidth / (float) defaultFixedLayoutWidth;
1725     EXPECT_EQ(minimumPageScaleFactor, toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->loader().currentItem()->pageScaleFactor());
1726 }
1727 
TEST_F(WebFrameTest,pageScaleFactorShrinksViewport)1728 TEST_F(WebFrameTest, pageScaleFactorShrinksViewport)
1729 {
1730     UseMockScrollbarSettings mockScrollbarSettings;
1731     registerMockedHttpURLLoad("large-div.html");
1732 
1733     FixedLayoutTestWebViewClient client;
1734     client.m_screenInfo.deviceScaleFactor = 1;
1735     // Small viewport to ensure there are always scrollbars.
1736     int viewportWidth = 64;
1737     int viewportHeight = 48;
1738 
1739     FrameTestHelpers::WebViewHelper webViewHelper;
1740     webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client, enableViewportSettings);
1741     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1742     webViewHelper.webView()->layout();
1743 
1744     WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
1745     int viewportWidthMinusScrollbar = viewportWidth - (view->verticalScrollbar()->isOverlayScrollbar() ? 0 : 15);
1746     int viewportHeightMinusScrollbar = viewportHeight - (view->horizontalScrollbar()->isOverlayScrollbar() ? 0 : 15);
1747 
1748     webViewHelper.webView()->setPageScaleFactor(2);
1749 
1750     WebCore::IntSize unscaledSize = view->unscaledVisibleContentSize(WebCore::IncludeScrollbars);
1751     EXPECT_EQ(viewportWidth, unscaledSize.width());
1752     EXPECT_EQ(viewportHeight, unscaledSize.height());
1753 
1754     WebCore::IntSize unscaledSizeMinusScrollbar = view->unscaledVisibleContentSize(WebCore::ExcludeScrollbars);
1755     EXPECT_EQ(viewportWidthMinusScrollbar, unscaledSizeMinusScrollbar.width());
1756     EXPECT_EQ(viewportHeightMinusScrollbar, unscaledSizeMinusScrollbar.height());
1757 
1758     WebCore::IntSize scaledSize = view->visibleContentRect().size();
1759     EXPECT_EQ(ceil(viewportWidthMinusScrollbar / 2.0), scaledSize.width());
1760     EXPECT_EQ(ceil(viewportHeightMinusScrollbar / 2.0), scaledSize.height());
1761 }
1762 
TEST_F(WebFrameTest,pageScaleFactorDoesNotApplyCssTransform)1763 TEST_F(WebFrameTest, pageScaleFactorDoesNotApplyCssTransform)
1764 {
1765     UseMockScrollbarSettings mockScrollbarSettings;
1766     registerMockedHttpURLLoad("fixed_layout.html");
1767 
1768     FixedLayoutTestWebViewClient client;
1769     client.m_screenInfo.deviceScaleFactor = 1;
1770     int viewportWidth = 640;
1771     int viewportHeight = 480;
1772 
1773     FrameTestHelpers::WebViewHelper webViewHelper;
1774     webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
1775     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1776     webViewHelper.webView()->layout();
1777 
1778     webViewHelper.webView()->setPageScaleFactor(2);
1779 
1780     EXPECT_EQ(980, toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->contentRenderer()->unscaledDocumentRect().width());
1781     EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
1782 }
1783 
TEST_F(WebFrameTest,targetDensityDpiHigh)1784 TEST_F(WebFrameTest, targetDensityDpiHigh)
1785 {
1786     UseMockScrollbarSettings mockScrollbarSettings;
1787     registerMockedHttpURLLoad("viewport-target-densitydpi-high.html");
1788 
1789     FixedLayoutTestWebViewClient client;
1790     // high-dpi = 240
1791     float targetDpi = 240.0f;
1792     float deviceScaleFactors[] = { 1.0f, 4.0f / 3.0f, 2.0f };
1793     int viewportWidth = 640;
1794     int viewportHeight = 480;
1795 
1796     for (size_t i = 0; i < ARRAY_SIZE(deviceScaleFactors); ++i) {
1797         float deviceScaleFactor = deviceScaleFactors[i];
1798         float deviceDpi = deviceScaleFactor * 160.0f;
1799         client.m_screenInfo.deviceScaleFactor = deviceScaleFactor;
1800 
1801         FrameTestHelpers::WebViewHelper webViewHelper;
1802         webViewHelper.initializeAndLoad(m_baseURL + "viewport-target-densitydpi-high.html", true, 0, &client, enableViewportSettings);
1803         webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1804         webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1805         webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1806 
1807         // We need to account for the fact that logical pixels are unconditionally multiplied by deviceScaleFactor to produce
1808         // physical pixels.
1809         float densityDpiScaleRatio = deviceScaleFactor * targetDpi / deviceDpi;
1810         EXPECT_NEAR(viewportWidth * densityDpiScaleRatio, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1811         EXPECT_NEAR(viewportHeight * densityDpiScaleRatio, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1812         EXPECT_NEAR(1.0f / densityDpiScaleRatio, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1813     }
1814 }
1815 
TEST_F(WebFrameTest,targetDensityDpiDevice)1816 TEST_F(WebFrameTest, targetDensityDpiDevice)
1817 {
1818     UseMockScrollbarSettings mockScrollbarSettings;
1819     registerMockedHttpURLLoad("viewport-target-densitydpi-device.html");
1820 
1821     float deviceScaleFactors[] = { 1.0f, 4.0f / 3.0f, 2.0f };
1822 
1823     FixedLayoutTestWebViewClient client;
1824     int viewportWidth = 640;
1825     int viewportHeight = 480;
1826 
1827     for (size_t i = 0; i < ARRAY_SIZE(deviceScaleFactors); ++i) {
1828         client.m_screenInfo.deviceScaleFactor = deviceScaleFactors[i];
1829 
1830         FrameTestHelpers::WebViewHelper webViewHelper;
1831         webViewHelper.initializeAndLoad(m_baseURL + "viewport-target-densitydpi-device.html", true, 0, &client, enableViewportSettings);
1832         webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1833         webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1834         webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1835 
1836         EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1837         EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1838         EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1839     }
1840 }
1841 
TEST_F(WebFrameTest,targetDensityDpiDeviceAndFixedWidth)1842 TEST_F(WebFrameTest, targetDensityDpiDeviceAndFixedWidth)
1843 {
1844     UseMockScrollbarSettings mockScrollbarSettings;
1845     registerMockedHttpURLLoad("viewport-target-densitydpi-device-and-fixed-width.html");
1846 
1847     float deviceScaleFactors[] = { 1.0f, 4.0f / 3.0f, 2.0f };
1848 
1849     FixedLayoutTestWebViewClient client;
1850     int viewportWidth = 640;
1851     int viewportHeight = 480;
1852 
1853     for (size_t i = 0; i < ARRAY_SIZE(deviceScaleFactors); ++i) {
1854         client.m_screenInfo.deviceScaleFactor = deviceScaleFactors[i];
1855 
1856         FrameTestHelpers::WebViewHelper webViewHelper;
1857         webViewHelper.initializeAndLoad(m_baseURL + "viewport-target-densitydpi-device-and-fixed-width.html", true, 0, &client, enableViewportSettings);
1858         webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1859         webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1860         webViewHelper.webView()->settings()->setUseWideViewport(true);
1861         webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1862 
1863         EXPECT_NEAR(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1864         EXPECT_NEAR(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1865         EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1866     }
1867 }
1868 
TEST_F(WebFrameTest,NoWideViewportAndScaleLessThanOne)1869 TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOne)
1870 {
1871     UseMockScrollbarSettings mockScrollbarSettings;
1872     registerMockedHttpURLLoad("viewport-initial-scale-less-than-1.html");
1873 
1874     FixedLayoutTestWebViewClient client;
1875     client.m_screenInfo.deviceScaleFactor = 1.33f;
1876     int viewportWidth = 640;
1877     int viewportHeight = 480;
1878 
1879     FrameTestHelpers::WebViewHelper webViewHelper;
1880     webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-less-than-1.html", true, 0, &client, enableViewportSettings);
1881     webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1882     webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1883     webViewHelper.webView()->settings()->setUseWideViewport(false);
1884     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1885     webViewHelper.webView()->layout();
1886 
1887     EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1888     EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1889     EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1890 }
1891 
TEST_F(WebFrameTest,NoWideViewportAndScaleLessThanOneWithDeviceWidth)1892 TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOneWithDeviceWidth)
1893 {
1894     UseMockScrollbarSettings mockScrollbarSettings;
1895     registerMockedHttpURLLoad("viewport-initial-scale-less-than-1-device-width.html");
1896 
1897     FixedLayoutTestWebViewClient client;
1898     client.m_screenInfo.deviceScaleFactor = 1.33f;
1899     int viewportWidth = 640;
1900     int viewportHeight = 480;
1901 
1902     FrameTestHelpers::WebViewHelper webViewHelper;
1903     webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-less-than-1-device-width.html", true, 0, &client, enableViewportSettings);
1904     webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1905     webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1906     webViewHelper.webView()->settings()->setUseWideViewport(false);
1907     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1908     webViewHelper.webView()->layout();
1909 
1910     const float pageZoom = 0.25f;
1911     EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor / pageZoom, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1912     EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor / pageZoom, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1913     EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1914 }
1915 
TEST_F(WebFrameTest,NoWideViewportAndNoViewportWithInitialPageScaleOverride)1916 TEST_F(WebFrameTest, NoWideViewportAndNoViewportWithInitialPageScaleOverride)
1917 {
1918     UseMockScrollbarSettings mockScrollbarSettings;
1919     registerMockedHttpURLLoad("large-div.html");
1920 
1921     FixedLayoutTestWebViewClient client;
1922     int viewportWidth = 640;
1923     int viewportHeight = 480;
1924     float enforcedPageScaleFactor = 5.0f;
1925 
1926     FrameTestHelpers::WebViewHelper webViewHelper;
1927     webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client, enableViewportSettings);
1928     webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1929     webViewHelper.webView()->settings()->setUseWideViewport(false);
1930     webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor);
1931     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1932     webViewHelper.webView()->layout();
1933 
1934     EXPECT_NEAR(viewportWidth / enforcedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1935     EXPECT_NEAR(viewportHeight / enforcedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1936     EXPECT_NEAR(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1937 }
1938 
TEST_F(WebFrameTest,NoUserScalableQuirkIgnoresViewportScale)1939 TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScale)
1940 {
1941     UseMockScrollbarSettings mockScrollbarSettings;
1942     registerMockedHttpURLLoad("viewport-initial-scale-and-user-scalable-no.html");
1943 
1944     FixedLayoutTestWebViewClient client;
1945     int viewportWidth = 640;
1946     int viewportHeight = 480;
1947 
1948     FrameTestHelpers::WebViewHelper webViewHelper;
1949     webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-and-user-scalable-no.html", true, 0, &client, enableViewportSettings);
1950     webViewHelper.webView()->settings()->setViewportMetaNonUserScalableQuirk(true);
1951     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1952     webViewHelper.webView()->layout();
1953 
1954     EXPECT_NEAR(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1955     EXPECT_NEAR(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1956     EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1957 }
1958 
TEST_F(WebFrameTest,NoUserScalableQuirkIgnoresViewportScaleForNonWideViewport)1959 TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScaleForNonWideViewport)
1960 {
1961     UseMockScrollbarSettings mockScrollbarSettings;
1962     registerMockedHttpURLLoad("viewport-initial-scale-and-user-scalable-no.html");
1963 
1964     FixedLayoutTestWebViewClient client;
1965     client.m_screenInfo.deviceScaleFactor = 1.33f;
1966     int viewportWidth = 640;
1967     int viewportHeight = 480;
1968 
1969     FrameTestHelpers::WebViewHelper webViewHelper;
1970     webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-and-user-scalable-no.html", true, 0, &client, enableViewportSettings);
1971     webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true);
1972     webViewHelper.webView()->settings()->setViewportMetaNonUserScalableQuirk(true);
1973     webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1974     webViewHelper.webView()->settings()->setUseWideViewport(false);
1975     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1976     webViewHelper.webView()->layout();
1977 
1978     EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
1979     EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
1980     EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f);
1981 }
1982 
TEST_F(WebFrameTest,NoUserScalableQuirkIgnoresViewportScaleForWideViewport)1983 TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScaleForWideViewport)
1984 {
1985     UseMockScrollbarSettings mockScrollbarSettings;
1986     registerMockedHttpURLLoad("viewport-2x-initial-scale-non-user-scalable.html");
1987 
1988     FixedLayoutTestWebViewClient client;
1989     int viewportWidth = 640;
1990     int viewportHeight = 480;
1991 
1992     FrameTestHelpers::WebViewHelper webViewHelper;
1993     webViewHelper.initializeAndLoad(m_baseURL + "viewport-2x-initial-scale-non-user-scalable.html", true, 0, &client, enableViewportSettings);
1994     webViewHelper.webView()->settings()->setViewportMetaNonUserScalableQuirk(true);
1995     webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
1996     webViewHelper.webView()->settings()->setUseWideViewport(true);
1997     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
1998 
1999     EXPECT_NEAR(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f);
2000     EXPECT_NEAR(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f);
2001     EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f);
2002 }
2003 
TEST_F(WebFrameTest,DesktopPageCanBeZoomedInWhenWideViewportIsTurnedOff)2004 TEST_F(WebFrameTest, DesktopPageCanBeZoomedInWhenWideViewportIsTurnedOff)
2005 {
2006     UseMockScrollbarSettings mockScrollbarSettings;
2007     registerMockedHttpURLLoad("no_viewport_tag.html");
2008 
2009     FixedLayoutTestWebViewClient client;
2010     int viewportWidth = 640;
2011     int viewportHeight = 480;
2012 
2013     FrameTestHelpers::WebViewHelper webViewHelper;
2014     webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client, enableViewportSettings);
2015     webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
2016     webViewHelper.webView()->settings()->setUseWideViewport(false);
2017     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2018 
2019     EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f);
2020     EXPECT_NEAR(1.0f, webViewHelper.webView()->minimumPageScaleFactor(), 0.01f);
2021     EXPECT_NEAR(5.0f, webViewHelper.webView()->maximumPageScaleFactor(), 0.01f);
2022 }
2023 
2024 class WebFrameResizeTest : public WebFrameTest {
2025 protected:
2026 
computeRelativeOffset(const WebCore::IntPoint & absoluteOffset,const WebCore::LayoutRect & rect)2027     static WebCore::FloatSize computeRelativeOffset(const WebCore::IntPoint& absoluteOffset, const WebCore::LayoutRect& rect)
2028     {
2029         WebCore::FloatSize relativeOffset = WebCore::FloatPoint(absoluteOffset) - rect.location();
2030         relativeOffset.scale(1.f / rect.width(), 1.f / rect.height());
2031         return relativeOffset;
2032     }
2033 
testResizeYieldsCorrectScrollAndScale(const char * url,const float initialPageScaleFactor,const WebSize scrollOffset,const WebSize viewportSize,const bool shouldScaleRelativeToViewportWidth)2034     void testResizeYieldsCorrectScrollAndScale(const char* url,
2035                                                const float initialPageScaleFactor,
2036                                                const WebSize scrollOffset,
2037                                                const WebSize viewportSize,
2038                                                const bool shouldScaleRelativeToViewportWidth) {
2039         UseMockScrollbarSettings mockScrollbarSettings;
2040         registerMockedHttpURLLoad(url);
2041 
2042         const float aspectRatio = static_cast<float>(viewportSize.width) / viewportSize.height;
2043 
2044         FrameTestHelpers::WebViewHelper webViewHelper;
2045         webViewHelper.initializeAndLoad(m_baseURL + url, true, 0, 0, enableViewportSettings);
2046 
2047         // Origin scrollOffsets preserved under resize.
2048         {
2049             webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height));
2050             webViewHelper.webViewImpl()->setPageScaleFactor(initialPageScaleFactor);
2051             ASSERT_EQ(viewportSize, webViewHelper.webViewImpl()->size());
2052             ASSERT_EQ(initialPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor());
2053             webViewHelper.webViewImpl()->resize(WebSize(viewportSize.height, viewportSize.width));
2054             float expectedPageScaleFactor = initialPageScaleFactor * (shouldScaleRelativeToViewportWidth ? 1 / aspectRatio : 1);
2055             EXPECT_NEAR(expectedPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor(), 0.05f);
2056             EXPECT_EQ(WebSize(), webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
2057         }
2058 
2059         // Resizing just the height should not affect pageScaleFactor or scrollOffset.
2060         {
2061             webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height));
2062             webViewHelper.webViewImpl()->setPageScaleFactor(initialPageScaleFactor);
2063             webViewHelper.webViewImpl()->setMainFrameScrollOffset(WebPoint(scrollOffset.width, scrollOffset.height));
2064             webViewHelper.webViewImpl()->layout();
2065             const WebSize expectedScrollOffset = webViewHelper.webViewImpl()->mainFrame()->scrollOffset();
2066             webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height * 0.8f));
2067             EXPECT_EQ(initialPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor());
2068             EXPECT_EQ(expectedScrollOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
2069             webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height * 0.8f));
2070             EXPECT_EQ(initialPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor());
2071             EXPECT_EQ(expectedScrollOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
2072         }
2073 
2074         // Generic resize preserves scrollOffset relative to anchor node located
2075         // the top center of the screen.
2076         {
2077             webViewHelper.webViewImpl()->resize(WebSize(viewportSize.height, viewportSize.width));
2078             float pageScaleFactor = webViewHelper.webViewImpl()->pageScaleFactor();
2079             webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height));
2080             float expectedPageScaleFactor = pageScaleFactor * (shouldScaleRelativeToViewportWidth ? aspectRatio : 1);
2081             EXPECT_NEAR(expectedPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor(), 0.05f);
2082             webViewHelper.webViewImpl()->mainFrame()->setScrollOffset(scrollOffset);
2083 
2084             WebCore::IntPoint anchorPoint = WebCore::IntPoint(scrollOffset) + WebCore::IntPoint(viewportSize.width / 2, 0);
2085             RefPtrWillBeRawPtr<WebCore::Node> anchorNode = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->eventHandler().hitTestResultAtPoint(anchorPoint, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent).innerNode();
2086             ASSERT(anchorNode);
2087 
2088             pageScaleFactor = webViewHelper.webViewImpl()->pageScaleFactor();
2089             const WebCore::FloatSize preResizeRelativeOffset
2090                 = computeRelativeOffset(anchorPoint, anchorNode->boundingBox());
2091             webViewHelper.webViewImpl()->resize(WebSize(viewportSize.height, viewportSize.width));
2092             WebCore::IntPoint newAnchorPoint = WebCore::IntPoint(webViewHelper.webViewImpl()->mainFrame()->scrollOffset()) + WebCore::IntPoint(viewportSize.height / 2, 0);
2093             const WebCore::FloatSize postResizeRelativeOffset
2094                 = computeRelativeOffset(newAnchorPoint, anchorNode->boundingBox());
2095             EXPECT_NEAR(preResizeRelativeOffset.width(), postResizeRelativeOffset.width(), 0.15f);
2096             expectedPageScaleFactor = pageScaleFactor * (shouldScaleRelativeToViewportWidth ? 1 / aspectRatio : 1);
2097             EXPECT_NEAR(expectedPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor(), 0.05f);
2098         }
2099     }
2100 };
2101 
TEST_F(WebFrameResizeTest,ResizeYieldsCorrectScrollAndScaleForWidthEqualsDeviceWidth)2102 TEST_F(WebFrameResizeTest, ResizeYieldsCorrectScrollAndScaleForWidthEqualsDeviceWidth)
2103 {
2104     // With width=device-width, pageScaleFactor is preserved across resizes as
2105     // long as the content adjusts according to the device-width.
2106     const char* url = "resize_scroll_mobile.html";
2107     const float initialPageScaleFactor = 1;
2108     const WebSize scrollOffset(0, 50);
2109     const WebSize viewportSize(120, 160);
2110     const bool shouldScaleRelativeToViewportWidth = true;
2111 
2112     testResizeYieldsCorrectScrollAndScale(
2113         url, initialPageScaleFactor, scrollOffset, viewportSize, shouldScaleRelativeToViewportWidth);
2114 }
2115 
TEST_F(WebFrameResizeTest,ResizeYieldsCorrectScrollAndScaleForFixedWidth)2116 TEST_F(WebFrameResizeTest, ResizeYieldsCorrectScrollAndScaleForFixedWidth)
2117 {
2118     // With a fixed width, pageScaleFactor scales by the relative change in viewport width.
2119     const char* url = "resize_scroll_fixed_width.html";
2120     const float initialPageScaleFactor = 2;
2121     const WebSize scrollOffset(0, 200);
2122     const WebSize viewportSize(240, 320);
2123     const bool shouldScaleRelativeToViewportWidth = true;
2124 
2125     testResizeYieldsCorrectScrollAndScale(
2126         url, initialPageScaleFactor, scrollOffset, viewportSize, shouldScaleRelativeToViewportWidth);
2127 }
2128 
TEST_F(WebFrameResizeTest,ResizeYieldsCorrectScrollAndScaleForFixedLayout)2129 TEST_F(WebFrameResizeTest, ResizeYieldsCorrectScrollAndScaleForFixedLayout)
2130 {
2131     // With a fixed layout, pageScaleFactor scales by the relative change in viewport width.
2132     const char* url = "resize_scroll_fixed_layout.html";
2133     const float initialPageScaleFactor = 2;
2134     const WebSize scrollOffset(200, 400);
2135     const WebSize viewportSize(320, 240);
2136     const bool shouldScaleRelativeToViewportWidth = true;
2137 
2138     testResizeYieldsCorrectScrollAndScale(
2139         url, initialPageScaleFactor, scrollOffset, viewportSize, shouldScaleRelativeToViewportWidth);
2140 }
2141 
TEST_F(WebFrameTest,pageScaleFactorScalesPaintClip)2142 TEST_F(WebFrameTest, pageScaleFactorScalesPaintClip)
2143 {
2144     UseMockScrollbarSettings mockScrollbarSettings;
2145     registerMockedHttpURLLoad("large-div.html");
2146 
2147     FixedLayoutTestWebViewClient client;
2148     client.m_screenInfo.deviceScaleFactor = 1;
2149     int viewportWidth = 50;
2150     int viewportHeight = 50;
2151 
2152     FrameTestHelpers::WebViewHelper webViewHelper;
2153     webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client);
2154     // FIXME: This test breaks if the viewport is enabled before loading the page due to the paint
2155     // calls below not working on composited layers. For some reason, enabling the viewport here
2156     // doesn't cause compositing
2157     webViewHelper.webView()->settings()->setViewportEnabled(true);
2158     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2159     webViewHelper.webView()->layout();
2160 
2161     // Set <1 page scale so that the clip rect should be larger than
2162     // the viewport size as passed into resize().
2163     webViewHelper.webView()->setPageScaleFactor(0.5);
2164 
2165     SkBitmap bitmap;
2166     ASSERT_TRUE(bitmap.allocN32Pixels(200, 200));
2167     bitmap.eraseColor(0);
2168     SkCanvas canvas(bitmap);
2169 
2170     WebCore::GraphicsContext context(&canvas);
2171     context.setTrackOpaqueRegion(true);
2172 
2173     EXPECT_EQ_RECT(WebCore::IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
2174 
2175     WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
2176     WebCore::IntRect paintRect(0, 0, 200, 200);
2177     view->paint(&context, paintRect);
2178 
2179     // FIXME: This test broke in release builds when changing the FixedLayoutTestWebViewClient
2180     // to return a non-null layerTreeView, which is what all our shipping configurations do,
2181     // so this is just exposing an existing bug.
2182     // crbug.com/365812
2183 #ifndef NDEBUG
2184     int viewportWidthMinusScrollbar = 50 - (view->verticalScrollbar()->isOverlayScrollbar() ? 0 : 15);
2185     int viewportHeightMinusScrollbar = 50 - (view->horizontalScrollbar()->isOverlayScrollbar() ? 0 : 15);
2186     WebCore::IntRect clippedRect(0, 0, viewportWidthMinusScrollbar * 2, viewportHeightMinusScrollbar * 2);
2187     EXPECT_EQ_RECT(clippedRect, context.opaqueRegion().asRect());
2188 #endif
2189 }
2190 
TEST_F(WebFrameTest,pageScaleFactorUpdatesScrollbars)2191 TEST_F(WebFrameTest, pageScaleFactorUpdatesScrollbars)
2192 {
2193     UseMockScrollbarSettings mockScrollbarSettings;
2194     registerMockedHttpURLLoad("fixed_layout.html");
2195 
2196     FixedLayoutTestWebViewClient client;
2197     client.m_screenInfo.deviceScaleFactor = 1;
2198     int viewportWidth = 640;
2199     int viewportHeight = 480;
2200 
2201     FrameTestHelpers::WebViewHelper webViewHelper;
2202     webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings);
2203     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2204     webViewHelper.webView()->layout();
2205 
2206     WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
2207     EXPECT_EQ(view->scrollSize(WebCore::HorizontalScrollbar), view->contentsSize().width() - view->visibleContentRect().width());
2208     EXPECT_EQ(view->scrollSize(WebCore::VerticalScrollbar), view->contentsSize().height() - view->visibleContentRect().height());
2209 
2210     webViewHelper.webView()->setPageScaleFactor(10);
2211 
2212     EXPECT_EQ(view->scrollSize(WebCore::HorizontalScrollbar), view->contentsSize().width() - view->visibleContentRect().width());
2213     EXPECT_EQ(view->scrollSize(WebCore::VerticalScrollbar), view->contentsSize().height() - view->visibleContentRect().height());
2214 }
2215 
TEST_F(WebFrameTest,CanOverrideScaleLimits)2216 TEST_F(WebFrameTest, CanOverrideScaleLimits)
2217 {
2218     UseMockScrollbarSettings mockScrollbarSettings;
2219 
2220     registerMockedHttpURLLoad("no_scale_for_you.html");
2221 
2222     FixedLayoutTestWebViewClient client;
2223     client.m_screenInfo.deviceScaleFactor = 1;
2224     int viewportWidth = 640;
2225     int viewportHeight = 480;
2226 
2227     FrameTestHelpers::WebViewHelper webViewHelper;
2228     webViewHelper.initializeAndLoad(m_baseURL + "no_scale_for_you.html", true, 0, &client, enableViewportSettings);
2229     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2230 
2231     EXPECT_EQ(2.0f, webViewHelper.webView()->minimumPageScaleFactor());
2232     EXPECT_EQ(2.0f, webViewHelper.webView()->maximumPageScaleFactor());
2233 
2234     webViewHelper.webView()->setIgnoreViewportTagScaleLimits(true);
2235     webViewHelper.webView()->layout();
2236 
2237     EXPECT_EQ(1.0f, webViewHelper.webView()->minimumPageScaleFactor());
2238     EXPECT_EQ(5.0f, webViewHelper.webView()->maximumPageScaleFactor());
2239 
2240     webViewHelper.webView()->setIgnoreViewportTagScaleLimits(false);
2241     webViewHelper.webView()->layout();
2242 
2243     EXPECT_EQ(2.0f, webViewHelper.webView()->minimumPageScaleFactor());
2244     EXPECT_EQ(2.0f, webViewHelper.webView()->maximumPageScaleFactor());
2245 }
2246 
TEST_F(WebFrameTest,updateOverlayScrollbarLayers)2247 TEST_F(WebFrameTest, updateOverlayScrollbarLayers)
2248 {
2249     UseMockScrollbarSettings mockScrollbarSettings;
2250 
2251     registerMockedHttpURLLoad("large-div.html");
2252 
2253     int viewWidth = 500;
2254     int viewHeight = 500;
2255 
2256     OwnPtr<FakeCompositingWebViewClient> fakeCompositingWebViewClient = adoptPtr(new FakeCompositingWebViewClient());
2257     FrameTestHelpers::WebViewHelper webViewHelper;
2258     webViewHelper.initialize(true, 0, fakeCompositingWebViewClient.get(), &configueCompositingWebView);
2259 
2260     webViewHelper.webView()->setPageScaleFactorLimits(1, 1);
2261     webViewHelper.webView()->resize(WebSize(viewWidth, viewHeight));
2262     FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "large-div.html");
2263 
2264     WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
2265     EXPECT_TRUE(view->renderView()->compositor()->layerForHorizontalScrollbar());
2266     EXPECT_TRUE(view->renderView()->compositor()->layerForVerticalScrollbar());
2267 
2268     webViewHelper.webView()->resize(WebSize(viewWidth * 10, viewHeight * 10));
2269     webViewHelper.webView()->layout();
2270     EXPECT_FALSE(view->renderView()->compositor()->layerForHorizontalScrollbar());
2271     EXPECT_FALSE(view->renderView()->compositor()->layerForVerticalScrollbar());
2272 }
2273 
setScaleAndScrollAndLayout(blink::WebView * webView,WebPoint scroll,float scale)2274 void setScaleAndScrollAndLayout(blink::WebView* webView, WebPoint scroll, float scale)
2275 {
2276     webView->setPageScaleFactor(scale);
2277     webView->setMainFrameScrollOffset(WebPoint(scroll.x, scroll.y));
2278     webView->layout();
2279 }
2280 
TEST_F(WebFrameTest,DivAutoZoomParamsTest)2281 TEST_F(WebFrameTest, DivAutoZoomParamsTest)
2282 {
2283     registerMockedHttpURLLoad("get_scale_for_auto_zoom_into_div_test.html");
2284 
2285     const float deviceScaleFactor = 2.0f;
2286     int viewportWidth = 640 / deviceScaleFactor;
2287     int viewportHeight = 1280 / deviceScaleFactor;
2288     float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2289     FrameTestHelpers::WebViewHelper webViewHelper;
2290     webViewHelper.initializeAndLoad(m_baseURL + "get_scale_for_auto_zoom_into_div_test.html");
2291     webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2292     webViewHelper.webView()->setPageScaleFactorLimits(0.01f, 4);
2293     webViewHelper.webView()->setPageScaleFactor(0.5f);
2294     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2295     webViewHelper.webView()->layout();
2296 
2297     WebRect wideDiv(200, 100, 400, 150);
2298     WebRect tallDiv(200, 300, 400, 800);
2299     WebRect doubleTapPointWide(wideDiv.x + 50, wideDiv.y + 50, touchPointPadding, touchPointPadding);
2300     WebRect doubleTapPointTall(tallDiv.x + 50, tallDiv.y + 50, touchPointPadding, touchPointPadding);
2301     WebRect wideBlockBounds;
2302     WebRect tallBlockBounds;
2303     float scale;
2304     WebPoint scroll;
2305 
2306     float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2307 
2308     // Test double-tap zooming into wide div.
2309     wideBlockBounds = webViewHelper.webViewImpl()->computeBlockBounds(doubleTapPointWide, false);
2310     webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(doubleTapPointWide.x, doubleTapPointWide.y), wideBlockBounds, touchPointPadding, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2311     // The div should horizontally fill the screen (modulo margins), and
2312     // vertically centered (modulo integer rounding).
2313     EXPECT_NEAR(viewportWidth / (float) wideDiv.width, scale, 0.1);
2314     EXPECT_NEAR(wideDiv.x, scroll.x, 20);
2315     EXPECT_EQ(0, scroll.y);
2316 
2317     setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), scroll, scale);
2318 
2319     // Test zoom out back to minimum scale.
2320     wideBlockBounds = webViewHelper.webViewImpl()->computeBlockBounds(doubleTapPointWide, false);
2321     webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(doubleTapPointWide.x, doubleTapPointWide.y), wideBlockBounds, touchPointPadding, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2322 
2323     scale = webViewHelper.webViewImpl()->minimumPageScaleFactor();
2324     setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), scale);
2325 
2326     // Test double-tap zooming into tall div.
2327     tallBlockBounds = webViewHelper.webViewImpl()->computeBlockBounds(doubleTapPointTall, false);
2328     webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(doubleTapPointTall.x, doubleTapPointTall.y), tallBlockBounds, touchPointPadding, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2329     // The div should start at the top left of the viewport.
2330     EXPECT_NEAR(viewportWidth / (float) tallDiv.width, scale, 0.1);
2331     EXPECT_NEAR(tallDiv.x, scroll.x, 20);
2332     EXPECT_NEAR(tallDiv.y, scroll.y, 20);
2333 
2334     // Test for Non-doubletap scaling
2335     // Test zooming into div.
2336     webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(250, 250), webViewHelper.webViewImpl()->computeBlockBounds(WebRect(250, 250, 10, 10), true), 0, doubleTapZoomAlreadyLegibleScale, scale, scroll);
2337     EXPECT_NEAR(viewportWidth / (float) wideDiv.width, scale, 0.1);
2338 }
2339 
simulatePageScale(WebViewImpl * webViewImpl,float & scale)2340 void simulatePageScale(WebViewImpl* webViewImpl, float& scale)
2341 {
2342     WebCore::IntSize scrollDelta = webViewImpl->fakePageScaleAnimationTargetPositionForTesting() - webViewImpl->mainFrameImpl()->frameView()->scrollPosition();
2343     float scaleDelta = webViewImpl->fakePageScaleAnimationPageScaleForTesting() / webViewImpl->pageScaleFactor();
2344     webViewImpl->applyScrollAndScale(scrollDelta, scaleDelta);
2345     scale = webViewImpl->pageScaleFactor();
2346 }
2347 
simulateMultiTargetZoom(WebViewImpl * webViewImpl,const WebRect & rect,float & scale)2348 void simulateMultiTargetZoom(WebViewImpl* webViewImpl, const WebRect& rect, float& scale)
2349 {
2350     if (webViewImpl->zoomToMultipleTargetsRect(rect))
2351         simulatePageScale(webViewImpl, scale);
2352 }
2353 
simulateDoubleTap(WebViewImpl * webViewImpl,WebPoint & point,float & scale)2354 void simulateDoubleTap(WebViewImpl* webViewImpl, WebPoint& point, float& scale)
2355 {
2356     webViewImpl->animateDoubleTapZoom(point);
2357     EXPECT_TRUE(webViewImpl->fakeDoubleTapAnimationPendingForTesting());
2358     simulatePageScale(webViewImpl, scale);
2359 }
2360 
TEST_F(WebFrameTest,DivAutoZoomWideDivTest)2361 TEST_F(WebFrameTest, DivAutoZoomWideDivTest)
2362 {
2363     registerMockedHttpURLLoad("get_wide_div_for_auto_zoom_test.html");
2364 
2365     const float deviceScaleFactor = 2.0f;
2366     int viewportWidth = 640 / deviceScaleFactor;
2367     int viewportHeight = 1280 / deviceScaleFactor;
2368     float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2369     FrameTestHelpers::WebViewHelper webViewHelper;
2370     webViewHelper.initializeAndLoad(m_baseURL + "get_wide_div_for_auto_zoom_test.html");
2371     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2372     webViewHelper.webView()->setPageScaleFactorLimits(1.0f, 4);
2373     webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2374     webViewHelper.webView()->setPageScaleFactor(1.0f);
2375     webViewHelper.webView()->layout();
2376 
2377     webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2378 
2379     float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2380 
2381     WebRect div(0, 100, viewportWidth, 150);
2382     WebPoint point(div.x + 50, div.y + 50);
2383     float scale;
2384     setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2385 
2386     simulateDoubleTap(webViewHelper.webViewImpl(), point, scale);
2387     EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2388     simulateDoubleTap(webViewHelper.webViewImpl(), point, scale);
2389     EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2390 }
2391 
TEST_F(WebFrameTest,DivAutoZoomVeryTallTest)2392 TEST_F(WebFrameTest, DivAutoZoomVeryTallTest)
2393 {
2394     // When a block is taller than the viewport and a zoom targets a lower part
2395     // of it, then we should keep the target point onscreen instead of snapping
2396     // back up the top of the block.
2397     registerMockedHttpURLLoad("very_tall_div.html");
2398 
2399     const float deviceScaleFactor = 2.0f;
2400     int viewportWidth = 640 / deviceScaleFactor;
2401     int viewportHeight = 1280 / deviceScaleFactor;
2402     FrameTestHelpers::WebViewHelper webViewHelper;
2403     webViewHelper.initializeAndLoad(m_baseURL + "very_tall_div.html", true, 0, 0, enableViewportSettings);
2404     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2405     webViewHelper.webView()->setPageScaleFactorLimits(1.0f, 4);
2406     webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2407     webViewHelper.webView()->setPageScaleFactor(1.0f);
2408     webViewHelper.webView()->layout();
2409 
2410     WebRect div(200, 300, 400, 5000);
2411     WebPoint point(div.x + 50, div.y + 3000);
2412     float scale;
2413     WebPoint scroll;
2414 
2415     WebRect blockBounds = webViewHelper.webViewImpl()->computeBlockBounds(WebRect(point.x, point.y, 0, 0), true);
2416     webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(point, blockBounds, 0, 1.0f, scale, scroll);
2417     EXPECT_EQ(scale, 1.0f);
2418     EXPECT_EQ(scroll.y, 2660);
2419 }
2420 
TEST_F(WebFrameTest,DivAutoZoomMultipleDivsTest)2421 TEST_F(WebFrameTest, DivAutoZoomMultipleDivsTest)
2422 {
2423     registerMockedHttpURLLoad("get_multiple_divs_for_auto_zoom_test.html");
2424 
2425     const float deviceScaleFactor = 2.0f;
2426     int viewportWidth = 640 / deviceScaleFactor;
2427     int viewportHeight = 1280 / deviceScaleFactor;
2428     float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2429     FrameTestHelpers::WebViewHelper webViewHelper;
2430     webViewHelper.initializeAndLoad(m_baseURL + "get_multiple_divs_for_auto_zoom_test.html");
2431     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2432     webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2433     webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2434     webViewHelper.webView()->setPageScaleFactor(0.5f);
2435     webViewHelper.webView()->layout();
2436 
2437     webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2438 
2439     WebRect topDiv(200, 100, 200, 150);
2440     WebRect bottomDiv(200, 300, 200, 150);
2441     WebPoint topPoint(topDiv.x + 50, topDiv.y + 50);
2442     WebPoint bottomPoint(bottomDiv.x + 50, bottomDiv.y + 50);
2443     float scale;
2444     setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2445 
2446     // Test double tap on two different divs
2447     // After first zoom, we should go back to minimum page scale with a second double tap.
2448     simulateDoubleTap(webViewHelper.webViewImpl(), topPoint, scale);
2449     EXPECT_FLOAT_EQ(1, scale);
2450     simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2451     EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2452 
2453     // If the user pinch zooms after double tap, a second double tap should zoom back to the div.
2454     simulateDoubleTap(webViewHelper.webViewImpl(), topPoint, scale);
2455     EXPECT_FLOAT_EQ(1, scale);
2456     webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 0.6f);
2457     simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2458     EXPECT_FLOAT_EQ(1, scale);
2459     simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2460     EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2461 
2462     // If we didn't yet get an auto-zoom update and a second double-tap arrives, should go back to minimum scale.
2463     webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2464     webViewHelper.webViewImpl()->animateDoubleTapZoom(topPoint);
2465     EXPECT_TRUE(webViewHelper.webViewImpl()->fakeDoubleTapAnimationPendingForTesting());
2466     simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale);
2467     EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2468 }
2469 
TEST_F(WebFrameTest,DivAutoZoomScaleBoundsTest)2470 TEST_F(WebFrameTest, DivAutoZoomScaleBoundsTest)
2471 {
2472     registerMockedHttpURLLoad("get_scale_bounds_check_for_auto_zoom_test.html");
2473 
2474     int viewportWidth = 320;
2475     int viewportHeight = 480;
2476     float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2477     FrameTestHelpers::WebViewHelper webViewHelper;
2478     webViewHelper.initializeAndLoad(m_baseURL + "get_scale_bounds_check_for_auto_zoom_test.html");
2479     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2480     webViewHelper.webView()->setDeviceScaleFactor(1.5f);
2481     webViewHelper.webView()->layout();
2482 
2483     webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2484 
2485     WebRect div(200, 100, 200, 150);
2486     WebPoint doubleTapPoint(div.x + 50, div.y + 50);
2487     float scale;
2488 
2489     // Test double tap scale bounds.
2490     // minimumPageScale < doubleTapZoomAlreadyLegibleScale < 1
2491     webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2492     webViewHelper.webView()->layout();
2493     float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2494     setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2495     simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2496     EXPECT_FLOAT_EQ(1, scale);
2497     simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2498     EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2499     simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2500     EXPECT_FLOAT_EQ(1, scale);
2501 
2502     // Zoom in to reset double_tap_zoom_in_effect flag.
2503     webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2504     // 1 < minimumPageScale < doubleTapZoomAlreadyLegibleScale
2505     webViewHelper.webView()->setPageScaleFactorLimits(1.1f, 4);
2506     webViewHelper.webView()->layout();
2507     doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2508     setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2509     simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2510     EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2511     simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2512     EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2513     simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2514     EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2515 
2516     // Zoom in to reset double_tap_zoom_in_effect flag.
2517     webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2518     // minimumPageScale < 1 < doubleTapZoomAlreadyLegibleScale
2519     webViewHelper.webView()->setPageScaleFactorLimits(0.95f, 4);
2520     webViewHelper.webView()->layout();
2521     doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2522     setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2523     simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2524     EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2525     simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2526     EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2527     simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2528     EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2529 }
2530 
TEST_F(WebFrameTest,DivAutoZoomScaleFontScaleFactorTest)2531 TEST_F(WebFrameTest, DivAutoZoomScaleFontScaleFactorTest)
2532 {
2533     registerMockedHttpURLLoad("get_scale_bounds_check_for_auto_zoom_test.html");
2534 
2535     int viewportWidth = 320;
2536     int viewportHeight = 480;
2537     float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2538     float accessibilityFontScaleFactor = 1.13f;
2539     FrameTestHelpers::WebViewHelper webViewHelper;
2540     webViewHelper.initializeAndLoad(m_baseURL + "get_scale_bounds_check_for_auto_zoom_test.html");
2541     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2542     webViewHelper.webView()->layout();
2543 
2544     webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2545     webViewHelper.webViewImpl()->page()->settings().setTextAutosizingEnabled(true);
2546     webViewHelper.webViewImpl()->page()->settings().setAccessibilityFontScaleFactor(accessibilityFontScaleFactor);
2547 
2548     WebRect div(200, 100, 200, 150);
2549     WebPoint doubleTapPoint(div.x + 50, div.y + 50);
2550     float scale;
2551 
2552     // Test double tap scale bounds.
2553     // minimumPageScale < doubleTapZoomAlreadyLegibleScale < 1 < accessibilityFontScaleFactor
2554     float legibleScale = accessibilityFontScaleFactor;
2555     setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2556     float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2557     webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2558     webViewHelper.webView()->layout();
2559     simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2560     EXPECT_FLOAT_EQ(legibleScale, scale);
2561     simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2562     EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2563     simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2564     EXPECT_FLOAT_EQ(legibleScale, scale);
2565 
2566     // Zoom in to reset double_tap_zoom_in_effect flag.
2567     webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2568     // 1 < accessibilityFontScaleFactor < minimumPageScale < doubleTapZoomAlreadyLegibleScale
2569     webViewHelper.webView()->setPageScaleFactorLimits(1.0f, 4);
2570     webViewHelper.webView()->layout();
2571     doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2572     setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2573     simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2574     EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2575     simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2576     EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2577     simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2578     EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2579 
2580     // Zoom in to reset double_tap_zoom_in_effect flag.
2581     webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2582     // minimumPageScale < 1 < accessibilityFontScaleFactor < doubleTapZoomAlreadyLegibleScale
2583     webViewHelper.webView()->setPageScaleFactorLimits(0.95f, 4);
2584     webViewHelper.webView()->layout();
2585     doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2586     setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2587     simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2588     EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2589     simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2590     EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2591     simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2592     EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale);
2593 
2594     // Zoom in to reset double_tap_zoom_in_effect flag.
2595     webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f);
2596     // minimumPageScale < 1 < doubleTapZoomAlreadyLegibleScale < accessibilityFontScaleFactor
2597     webViewHelper.webView()->setPageScaleFactorLimits(0.9f, 4);
2598     webViewHelper.webView()->layout();
2599     doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio;
2600     setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2601     simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2602     EXPECT_FLOAT_EQ(legibleScale, scale);
2603     simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2604     EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale);
2605     simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale);
2606     EXPECT_FLOAT_EQ(legibleScale, scale);
2607 }
2608 
TEST_F(WebFrameTest,DivMultipleTargetZoomMultipleDivsTest)2609 TEST_F(WebFrameTest, DivMultipleTargetZoomMultipleDivsTest)
2610 {
2611     registerMockedHttpURLLoad("get_multiple_divs_for_auto_zoom_test.html");
2612 
2613     const float deviceScaleFactor = 2.0f;
2614     int viewportWidth = 640 / deviceScaleFactor;
2615     int viewportHeight = 1280 / deviceScaleFactor;
2616     float doubleTapZoomAlreadyLegibleRatio = 1.2f;
2617     FrameTestHelpers::WebViewHelper webViewHelper;
2618     webViewHelper.initializeAndLoad(m_baseURL + "get_multiple_divs_for_auto_zoom_test.html");
2619     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2620     webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4);
2621     webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor);
2622     webViewHelper.webView()->setPageScaleFactor(0.5f);
2623     webViewHelper.webView()->layout();
2624 
2625     webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2626 
2627     WebRect viewportRect(0, 0, viewportWidth, viewportHeight);
2628     WebRect topDiv(200, 100, 200, 150);
2629     WebRect bottomDiv(200, 300, 200, 150);
2630     float scale;
2631     setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2);
2632 
2633     simulateMultiTargetZoom(webViewHelper.webViewImpl(), topDiv, scale);
2634     EXPECT_FLOAT_EQ(1, scale);
2635     simulateMultiTargetZoom(webViewHelper.webViewImpl(), bottomDiv, scale);
2636     EXPECT_FLOAT_EQ(1, scale);
2637     simulateMultiTargetZoom(webViewHelper.webViewImpl(), viewportRect, scale);
2638     EXPECT_FLOAT_EQ(1, scale);
2639     webViewHelper.webViewImpl()->setPageScaleFactor(webViewHelper.webViewImpl()->minimumPageScaleFactor());
2640     simulateMultiTargetZoom(webViewHelper.webViewImpl(), topDiv, scale);
2641     EXPECT_FLOAT_EQ(1, scale);
2642 }
2643 
TEST_F(WebFrameTest,DivScrollIntoEditableTest)2644 TEST_F(WebFrameTest, DivScrollIntoEditableTest)
2645 {
2646     registerMockedHttpURLLoad("get_scale_for_zoom_into_editable_test.html");
2647 
2648     int viewportWidth = 450;
2649     int viewportHeight = 300;
2650     float leftBoxRatio = 0.3f;
2651     int caretPadding = 10;
2652     float minReadableCaretHeight = 18.0f;
2653     FrameTestHelpers::WebViewHelper webViewHelper;
2654     webViewHelper.initializeAndLoad(m_baseURL + "get_scale_for_zoom_into_editable_test.html");
2655     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2656     webViewHelper.webView()->setPageScaleFactorLimits(1, 4);
2657     webViewHelper.webView()->layout();
2658     webViewHelper.webView()->setDeviceScaleFactor(1.5f);
2659     webViewHelper.webView()->settings()->setAutoZoomFocusedNodeToLegibleScale(true);
2660 
2661     webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true);
2662 
2663     WebRect editBoxWithText(200, 200, 250, 20);
2664     WebRect editBoxWithNoText(200, 250, 250, 20);
2665 
2666     // Test scrolling the focused node
2667     // The edit box is shorter and narrower than the viewport when legible.
2668     webViewHelper.webView()->advanceFocus(false);
2669     // Set the caret to the end of the input box.
2670     webViewHelper.webView()->mainFrame()->document().getElementById("EditBoxWithText").to<WebInputElement>().setSelectionRange(1000, 1000);
2671     setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), 1);
2672     WebRect rect, caret;
2673     webViewHelper.webViewImpl()->selectionBounds(caret, rect);
2674 
2675     float scale;
2676     WebCore::IntPoint scroll;
2677     bool needAnimation;
2678     webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2679     EXPECT_TRUE(needAnimation);
2680     // The edit box should be left aligned with a margin for possible label.
2681     int hScroll = editBoxWithText.x - leftBoxRatio * viewportWidth / scale;
2682     EXPECT_NEAR(hScroll, scroll.x(), 1);
2683     int vScroll = editBoxWithText.y - (viewportHeight / scale - editBoxWithText.height) / 2;
2684     EXPECT_NEAR(vScroll, scroll.y(), 1);
2685     EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1);
2686 
2687     // The edit box is wider than the viewport when legible.
2688     viewportWidth = 200;
2689     viewportHeight = 150;
2690     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
2691     setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), 1);
2692     webViewHelper.webViewImpl()->selectionBounds(caret, rect);
2693     webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2694     EXPECT_TRUE(needAnimation);
2695     // The caret should be right aligned since the caret would be offscreen when the edit box is left aligned.
2696     hScroll = caret.x + caret.width + caretPadding - viewportWidth / scale;
2697     EXPECT_NEAR(hScroll, scroll.x(), 1);
2698     EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1);
2699 
2700     setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), 1);
2701     // Move focus to edit box with text.
2702     webViewHelper.webView()->advanceFocus(false);
2703     webViewHelper.webViewImpl()->selectionBounds(caret, rect);
2704     webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2705     EXPECT_TRUE(needAnimation);
2706     // The edit box should be left aligned.
2707     hScroll = editBoxWithNoText.x;
2708     EXPECT_NEAR(hScroll, scroll.x(), 1);
2709     vScroll = editBoxWithNoText.y - (viewportHeight / scale - editBoxWithNoText.height) / 2;
2710     EXPECT_NEAR(vScroll, scroll.y(), 1);
2711     EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1);
2712 
2713     setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), scroll, scale);
2714 
2715     // Move focus back to the first edit box.
2716     webViewHelper.webView()->advanceFocus(true);
2717     webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation);
2718     // The position should have stayed the same since this box was already on screen with the right scale.
2719     EXPECT_FALSE(needAnimation);
2720 }
2721 
2722 class TestReloadDoesntRedirectWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
2723 public:
decidePolicyForNavigation(WebLocalFrame *,WebDataSource::ExtraData *,const WebURLRequest &,WebNavigationType,WebNavigationPolicy defaultPolicy,bool isRedirect)2724     virtual WebNavigationPolicy decidePolicyForNavigation(
2725         WebLocalFrame*, WebDataSource::ExtraData*, const WebURLRequest&, WebNavigationType,
2726         WebNavigationPolicy defaultPolicy, bool isRedirect) OVERRIDE
2727     {
2728         EXPECT_FALSE(isRedirect);
2729         return WebNavigationPolicyCurrentTab;
2730     }
2731 };
2732 
TEST_F(WebFrameTest,ReloadDoesntSetRedirect)2733 TEST_F(WebFrameTest, ReloadDoesntSetRedirect)
2734 {
2735     // Test for case in http://crbug.com/73104. Reloading a frame very quickly
2736     // would sometimes call decidePolicyForNavigation with isRedirect=true
2737     registerMockedHttpURLLoad("form.html");
2738 
2739     TestReloadDoesntRedirectWebFrameClient webFrameClient;
2740     FrameTestHelpers::WebViewHelper webViewHelper;
2741     webViewHelper.initializeAndLoad(m_baseURL + "form.html", false, &webFrameClient);
2742 
2743     webViewHelper.webView()->mainFrame()->reload(true);
2744     // start another reload before request is delivered.
2745     FrameTestHelpers::reloadFrameIgnoringCache(webViewHelper.webView()->mainFrame());
2746 }
2747 
2748 class ReloadWithOverrideURLTask : public WebThread::Task {
2749 public:
ReloadWithOverrideURLTask(WebFrame * frame,const WebCore::KURL & url,bool ignoreCache)2750     ReloadWithOverrideURLTask(WebFrame* frame, const WebCore::KURL& url, bool ignoreCache)
2751         : m_frame(frame), m_url(url), m_ignoreCache(ignoreCache)
2752     {
2753     }
2754 
run()2755     virtual void run() OVERRIDE
2756     {
2757         m_frame->reloadWithOverrideURL(m_url, m_ignoreCache);
2758     }
2759 
2760 private:
2761     WebFrame* const m_frame;
2762     const WebCore::KURL m_url;
2763     const bool m_ignoreCache;
2764 };
2765 
TEST_F(WebFrameTest,ReloadWithOverrideURLPreservesState)2766 TEST_F(WebFrameTest, ReloadWithOverrideURLPreservesState)
2767 {
2768     const std::string firstURL = "find.html";
2769     const std::string secondURL = "form.html";
2770     const std::string thirdURL = "history.html";
2771     const float pageScaleFactor = 1.1684f;
2772     const int pageWidth = 640;
2773     const int pageHeight = 480;
2774 
2775     registerMockedHttpURLLoad(firstURL);
2776     registerMockedHttpURLLoad(secondURL);
2777     registerMockedHttpURLLoad(thirdURL);
2778 
2779     FrameTestHelpers::WebViewHelper webViewHelper;
2780     webViewHelper.initializeAndLoad(m_baseURL + firstURL, true);
2781     webViewHelper.webViewImpl()->resize(WebSize(pageWidth, pageHeight));
2782     webViewHelper.webViewImpl()->mainFrame()->setScrollOffset(WebSize(pageWidth / 4, pageHeight / 4));
2783     webViewHelper.webViewImpl()->setPageScaleFactor(pageScaleFactor);
2784 
2785     WebSize previousOffset = webViewHelper.webViewImpl()->mainFrame()->scrollOffset();
2786     float previousScale = webViewHelper.webViewImpl()->pageScaleFactor();
2787 
2788     // Reload the page using the cache.
2789     Platform::current()->currentThread()->postTask(
2790         new ReloadWithOverrideURLTask(webViewHelper.webViewImpl()->mainFrame(), toKURL(m_baseURL + secondURL), false));
2791     FrameTestHelpers::pumpPendingRequestsDoNotUse(webViewHelper.webViewImpl()->mainFrame());
2792     ASSERT_EQ(previousOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
2793     ASSERT_EQ(previousScale, webViewHelper.webViewImpl()->pageScaleFactor());
2794 
2795     // Reload the page while ignoring the cache.
2796     Platform::current()->currentThread()->postTask(
2797         new ReloadWithOverrideURLTask(webViewHelper.webViewImpl()->mainFrame(), toKURL(m_baseURL + thirdURL), true));
2798     FrameTestHelpers::pumpPendingRequestsDoNotUse(webViewHelper.webViewImpl()->mainFrame());
2799     ASSERT_EQ(previousOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset());
2800     ASSERT_EQ(previousScale, webViewHelper.webViewImpl()->pageScaleFactor());
2801 }
2802 
TEST_F(WebFrameTest,ReloadWhileProvisional)2803 TEST_F(WebFrameTest, ReloadWhileProvisional)
2804 {
2805     // Test that reloading while the previous load is still pending does not cause the initial
2806     // request to get lost.
2807     registerMockedHttpURLLoad("fixed_layout.html");
2808 
2809     FrameTestHelpers::WebViewHelper webViewHelper;
2810     webViewHelper.initialize();
2811     WebURLRequest request;
2812     request.initialize();
2813     request.setURL(toKURL(m_baseURL + "fixed_layout.html"));
2814     webViewHelper.webView()->mainFrame()->loadRequest(request);
2815     // start reload before first request is delivered.
2816     FrameTestHelpers::reloadFrameIgnoringCache(webViewHelper.webView()->mainFrame());
2817 
2818     WebDataSource* dataSource = webViewHelper.webView()->mainFrame()->dataSource();
2819     ASSERT_TRUE(dataSource);
2820     EXPECT_EQ(toKURL(m_baseURL + "fixed_layout.html"), toKURL(dataSource->request().url().spec()));
2821 }
2822 
TEST_F(WebFrameTest,AppendRedirects)2823 TEST_F(WebFrameTest, AppendRedirects)
2824 {
2825     const std::string firstURL = "about:blank";
2826     const std::string secondURL = "http://www.test.com";
2827 
2828     FrameTestHelpers::WebViewHelper webViewHelper;
2829     webViewHelper.initializeAndLoad(firstURL, true);
2830 
2831     WebDataSource* dataSource = webViewHelper.webView()->mainFrame()->dataSource();
2832     ASSERT_TRUE(dataSource);
2833     dataSource->appendRedirect(toKURL(secondURL));
2834 
2835     WebVector<WebURL> redirects;
2836     dataSource->redirectChain(redirects);
2837     ASSERT_EQ(2U, redirects.size());
2838     EXPECT_EQ(toKURL(firstURL), toKURL(redirects[0].spec().data()));
2839     EXPECT_EQ(toKURL(secondURL), toKURL(redirects[1].spec().data()));
2840 }
2841 
TEST_F(WebFrameTest,IframeRedirect)2842 TEST_F(WebFrameTest, IframeRedirect)
2843 {
2844     registerMockedHttpURLLoad("iframe_redirect.html");
2845     registerMockedHttpURLLoad("visible_iframe.html");
2846 
2847     FrameTestHelpers::WebViewHelper webViewHelper;
2848     webViewHelper.initializeAndLoad(m_baseURL + "iframe_redirect.html", true);
2849     // Pump pending requests one more time. The test page loads script that navigates.
2850     FrameTestHelpers::pumpPendingRequestsDoNotUse(webViewHelper.webView()->mainFrame());
2851 
2852     WebFrame* iframe = webViewHelper.webView()->findFrameByName(WebString::fromUTF8("ifr"));
2853     ASSERT_TRUE(iframe);
2854     WebDataSource* iframeDataSource = iframe->dataSource();
2855     ASSERT_TRUE(iframeDataSource);
2856     WebVector<WebURL> redirects;
2857     iframeDataSource->redirectChain(redirects);
2858     ASSERT_EQ(2U, redirects.size());
2859     EXPECT_EQ(toKURL("about:blank"), toKURL(redirects[0].spec().data()));
2860     EXPECT_EQ(toKURL("http://www.test.com/visible_iframe.html"), toKURL(redirects[1].spec().data()));
2861 }
2862 
TEST_F(WebFrameTest,ClearFocusedNodeTest)2863 TEST_F(WebFrameTest, ClearFocusedNodeTest)
2864 {
2865     registerMockedHttpURLLoad("iframe_clear_focused_node_test.html");
2866     registerMockedHttpURLLoad("autofocus_input_field_iframe.html");
2867 
2868     FrameTestHelpers::WebViewHelper webViewHelper;
2869     webViewHelper.initializeAndLoad(m_baseURL + "iframe_clear_focused_node_test.html", true);
2870 
2871     // Clear the focused node.
2872     webViewHelper.webView()->clearFocusedElement();
2873 
2874     // Now retrieve the FocusedNode and test it should be null.
2875     EXPECT_EQ(0, webViewHelper.webViewImpl()->focusedElement());
2876 }
2877 
2878 // Implementation of WebFrameClient that tracks the v8 contexts that are created
2879 // and destroyed for verification.
2880 class ContextLifetimeTestWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
2881 public:
2882     struct Notification {
2883     public:
Notification__anonf4dfb8060111::ContextLifetimeTestWebFrameClient::Notification2884         Notification(WebLocalFrame* frame, v8::Handle<v8::Context> context, int worldId)
2885             : frame(frame)
2886             , context(context->GetIsolate(), context)
2887             , worldId(worldId)
2888         {
2889         }
2890 
~Notification__anonf4dfb8060111::ContextLifetimeTestWebFrameClient::Notification2891         ~Notification()
2892         {
2893             context.Reset();
2894         }
2895 
Equals__anonf4dfb8060111::ContextLifetimeTestWebFrameClient::Notification2896         bool Equals(Notification* other)
2897         {
2898             return other && frame == other->frame && context == other->context && worldId == other->worldId;
2899         }
2900 
2901         WebLocalFrame* frame;
2902         v8::Persistent<v8::Context> context;
2903         int worldId;
2904     };
2905 
~ContextLifetimeTestWebFrameClient()2906     virtual ~ContextLifetimeTestWebFrameClient()
2907     {
2908         reset();
2909     }
2910 
reset()2911     void reset()
2912     {
2913         for (size_t i = 0; i < createNotifications.size(); ++i)
2914             delete createNotifications[i];
2915 
2916         for (size_t i = 0; i < releaseNotifications.size(); ++i)
2917             delete releaseNotifications[i];
2918 
2919         createNotifications.clear();
2920         releaseNotifications.clear();
2921     }
2922 
2923     std::vector<Notification*> createNotifications;
2924     std::vector<Notification*> releaseNotifications;
2925 
2926  private:
didCreateScriptContext(WebLocalFrame * frame,v8::Handle<v8::Context> context,int extensionGroup,int worldId)2927     virtual void didCreateScriptContext(WebLocalFrame* frame, v8::Handle<v8::Context> context, int extensionGroup, int worldId) OVERRIDE
2928     {
2929         createNotifications.push_back(new Notification(frame, context, worldId));
2930     }
2931 
willReleaseScriptContext(WebLocalFrame * frame,v8::Handle<v8::Context> context,int worldId)2932     virtual void willReleaseScriptContext(WebLocalFrame* frame, v8::Handle<v8::Context> context, int worldId) OVERRIDE
2933     {
2934         releaseNotifications.push_back(new Notification(frame, context, worldId));
2935     }
2936 };
2937 
2938 // TODO(aa): Deflake this test.
TEST_F(WebFrameTest,FLAKY_ContextNotificationsLoadUnload)2939 TEST_F(WebFrameTest, FLAKY_ContextNotificationsLoadUnload)
2940 {
2941     v8::HandleScope handleScope(v8::Isolate::GetCurrent());
2942 
2943     registerMockedHttpURLLoad("context_notifications_test.html");
2944     registerMockedHttpURLLoad("context_notifications_test_frame.html");
2945 
2946     // Load a frame with an iframe, make sure we get the right create notifications.
2947     ContextLifetimeTestWebFrameClient webFrameClient;
2948     FrameTestHelpers::WebViewHelper webViewHelper;
2949     webViewHelper.initializeAndLoad(m_baseURL + "context_notifications_test.html", true, &webFrameClient);
2950 
2951     WebFrame* mainFrame = webViewHelper.webView()->mainFrame();
2952     WebFrame* childFrame = mainFrame->firstChild();
2953 
2954     ASSERT_EQ(2u, webFrameClient.createNotifications.size());
2955     EXPECT_EQ(0u, webFrameClient.releaseNotifications.size());
2956 
2957     ContextLifetimeTestWebFrameClient::Notification* firstCreateNotification = webFrameClient.createNotifications[0];
2958     ContextLifetimeTestWebFrameClient::Notification* secondCreateNotification = webFrameClient.createNotifications[1];
2959 
2960     EXPECT_EQ(mainFrame, firstCreateNotification->frame);
2961     EXPECT_EQ(mainFrame->mainWorldScriptContext(), firstCreateNotification->context);
2962     EXPECT_EQ(0, firstCreateNotification->worldId);
2963 
2964     EXPECT_EQ(childFrame, secondCreateNotification->frame);
2965     EXPECT_EQ(childFrame->mainWorldScriptContext(), secondCreateNotification->context);
2966     EXPECT_EQ(0, secondCreateNotification->worldId);
2967 
2968     // Close the view. We should get two release notifications that are exactly the same as the create ones, in reverse order.
2969     webViewHelper.reset();
2970 
2971     ASSERT_EQ(2u, webFrameClient.releaseNotifications.size());
2972     ContextLifetimeTestWebFrameClient::Notification* firstReleaseNotification = webFrameClient.releaseNotifications[0];
2973     ContextLifetimeTestWebFrameClient::Notification* secondReleaseNotification = webFrameClient.releaseNotifications[1];
2974 
2975     ASSERT_TRUE(firstCreateNotification->Equals(secondReleaseNotification));
2976     ASSERT_TRUE(secondCreateNotification->Equals(firstReleaseNotification));
2977 }
2978 
TEST_F(WebFrameTest,ContextNotificationsReload)2979 TEST_F(WebFrameTest, ContextNotificationsReload)
2980 {
2981     v8::HandleScope handleScope(v8::Isolate::GetCurrent());
2982 
2983     registerMockedHttpURLLoad("context_notifications_test.html");
2984     registerMockedHttpURLLoad("context_notifications_test_frame.html");
2985 
2986     ContextLifetimeTestWebFrameClient webFrameClient;
2987     FrameTestHelpers::WebViewHelper webViewHelper;
2988     webViewHelper.initializeAndLoad(m_baseURL + "context_notifications_test.html", true, &webFrameClient);
2989 
2990     // Refresh, we should get two release notifications and two more create notifications.
2991     FrameTestHelpers::reloadFrame(webViewHelper.webView()->mainFrame());
2992     ASSERT_EQ(4u, webFrameClient.createNotifications.size());
2993     ASSERT_EQ(2u, webFrameClient.releaseNotifications.size());
2994 
2995     // The two release notifications we got should be exactly the same as the first two create notifications.
2996     for (size_t i = 0; i < webFrameClient.releaseNotifications.size(); ++i) {
2997       EXPECT_TRUE(webFrameClient.releaseNotifications[i]->Equals(
2998           webFrameClient.createNotifications[webFrameClient.createNotifications.size() - 3 - i]));
2999     }
3000 
3001     // The last two create notifications should be for the current frames and context.
3002     WebFrame* mainFrame = webViewHelper.webView()->mainFrame();
3003     WebFrame* childFrame = mainFrame->firstChild();
3004     ContextLifetimeTestWebFrameClient::Notification* firstRefreshNotification = webFrameClient.createNotifications[2];
3005     ContextLifetimeTestWebFrameClient::Notification* secondRefreshNotification = webFrameClient.createNotifications[3];
3006 
3007     EXPECT_EQ(mainFrame, firstRefreshNotification->frame);
3008     EXPECT_EQ(mainFrame->mainWorldScriptContext(), firstRefreshNotification->context);
3009     EXPECT_EQ(0, firstRefreshNotification->worldId);
3010 
3011     EXPECT_EQ(childFrame, secondRefreshNotification->frame);
3012     EXPECT_EQ(childFrame->mainWorldScriptContext(), secondRefreshNotification->context);
3013     EXPECT_EQ(0, secondRefreshNotification->worldId);
3014 }
3015 
TEST_F(WebFrameTest,ContextNotificationsIsolatedWorlds)3016 TEST_F(WebFrameTest, ContextNotificationsIsolatedWorlds)
3017 {
3018     v8::Isolate* isolate = v8::Isolate::GetCurrent();
3019     v8::HandleScope handleScope(isolate);
3020 
3021     registerMockedHttpURLLoad("context_notifications_test.html");
3022     registerMockedHttpURLLoad("context_notifications_test_frame.html");
3023 
3024     ContextLifetimeTestWebFrameClient webFrameClient;
3025     FrameTestHelpers::WebViewHelper webViewHelper;
3026     webViewHelper.initializeAndLoad(m_baseURL + "context_notifications_test.html", true, &webFrameClient);
3027 
3028     // Add an isolated world.
3029     webFrameClient.reset();
3030 
3031     int isolatedWorldId = 42;
3032     WebScriptSource scriptSource("hi!");
3033     int numSources = 1;
3034     int extensionGroup = 0;
3035     webViewHelper.webView()->mainFrame()->executeScriptInIsolatedWorld(isolatedWorldId, &scriptSource, numSources, extensionGroup);
3036 
3037     // We should now have a new create notification.
3038     ASSERT_EQ(1u, webFrameClient.createNotifications.size());
3039     ContextLifetimeTestWebFrameClient::Notification* notification = webFrameClient.createNotifications[0];
3040     ASSERT_EQ(isolatedWorldId, notification->worldId);
3041     ASSERT_EQ(webViewHelper.webView()->mainFrame(), notification->frame);
3042 
3043     // We don't have an API to enumarate isolated worlds for a frame, but we can at least assert that the context we got is *not* the main world's context.
3044     ASSERT_NE(webViewHelper.webView()->mainFrame()->mainWorldScriptContext(), v8::Local<v8::Context>::New(isolate, notification->context));
3045 
3046     webViewHelper.reset();
3047 
3048     // We should have gotten three release notifications (one for each of the frames, plus one for the isolated context).
3049     ASSERT_EQ(3u, webFrameClient.releaseNotifications.size());
3050 
3051     // And one of them should be exactly the same as the create notification for the isolated context.
3052     int matchCount = 0;
3053     for (size_t i = 0; i < webFrameClient.releaseNotifications.size(); ++i) {
3054       if (webFrameClient.releaseNotifications[i]->Equals(webFrameClient.createNotifications[0]))
3055         ++matchCount;
3056     }
3057     EXPECT_EQ(1, matchCount);
3058 }
3059 
TEST_F(WebFrameTest,FindInPage)3060 TEST_F(WebFrameTest, FindInPage)
3061 {
3062     registerMockedHttpURLLoad("find.html");
3063     FrameTestHelpers::WebViewHelper webViewHelper;
3064     webViewHelper.initializeAndLoad(m_baseURL + "find.html");
3065     WebFrame* frame = webViewHelper.webView()->mainFrame();
3066     const int findIdentifier = 12345;
3067     WebFindOptions options;
3068 
3069     // Find in a <div> element.
3070     EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar1"), options, false, 0));
3071     frame->stopFinding(false);
3072     WebRange range = frame->selectionRange();
3073     EXPECT_EQ(5, range.startOffset());
3074     EXPECT_EQ(9, range.endOffset());
3075     EXPECT_TRUE(frame->document().focusedElement().isNull());
3076 
3077     // Find in an <input> value.
3078     EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar2"), options, false, 0));
3079     // Confirm stopFinding(false) sets the selection on the found text.
3080     frame->stopFinding(false);
3081     range = frame->selectionRange();
3082     ASSERT_FALSE(range.isNull());
3083     EXPECT_EQ(5, range.startOffset());
3084     EXPECT_EQ(9, range.endOffset());
3085     EXPECT_EQ(WebString::fromUTF8("INPUT"), frame->document().focusedElement().tagName());
3086 
3087     // Find in a <textarea> content.
3088     EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar3"), options, false, 0));
3089     // Confirm stopFinding(false) sets the selection on the found text.
3090     frame->stopFinding(false);
3091     range = frame->selectionRange();
3092     ASSERT_FALSE(range.isNull());
3093     EXPECT_EQ(5, range.startOffset());
3094     EXPECT_EQ(9, range.endOffset());
3095     EXPECT_EQ(WebString::fromUTF8("TEXTAREA"), frame->document().focusedElement().tagName());
3096 
3097     // Find in a contentEditable element.
3098     EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar4"), options, false, 0));
3099     // Confirm stopFinding(false) sets the selection on the found text.
3100     frame->stopFinding(false);
3101     range = frame->selectionRange();
3102     ASSERT_FALSE(range.isNull());
3103     EXPECT_EQ(0, range.startOffset());
3104     EXPECT_EQ(4, range.endOffset());
3105     // "bar4" is surrounded by <span>, but the focusable node should be the parent <div>.
3106     EXPECT_EQ(WebString::fromUTF8("DIV"), frame->document().focusedElement().tagName());
3107 
3108     // Find in <select> content.
3109     EXPECT_FALSE(frame->find(findIdentifier, WebString::fromUTF8("bar5"), options, false, 0));
3110     // If there are any matches, stopFinding will set the selection on the found text.
3111     // However, we do not expect any matches, so check that the selection is null.
3112     frame->stopFinding(false);
3113     range = frame->selectionRange();
3114     ASSERT_TRUE(range.isNull());
3115 }
3116 
TEST_F(WebFrameTest,GetContentAsPlainText)3117 TEST_F(WebFrameTest, GetContentAsPlainText)
3118 {
3119     FrameTestHelpers::WebViewHelper webViewHelper;
3120     webViewHelper.initializeAndLoad("about:blank", true);
3121     // We set the size because it impacts line wrapping, which changes the
3122     // resulting text value.
3123     webViewHelper.webView()->resize(WebSize(640, 480));
3124     WebFrame* frame = webViewHelper.webView()->mainFrame();
3125 
3126     // Generate a simple test case.
3127     const char simpleSource[] = "<div>Foo bar</div><div></div>baz";
3128     WebCore::KURL testURL = toKURL("about:blank");
3129     FrameTestHelpers::loadHTMLString(frame, simpleSource, testURL);
3130 
3131     // Make sure it comes out OK.
3132     const std::string expected("Foo bar\nbaz");
3133     WebString text = frame->contentAsText(std::numeric_limits<size_t>::max());
3134     EXPECT_EQ(expected, text.utf8());
3135 
3136     // Try reading the same one with clipping of the text.
3137     const int length = 5;
3138     text = frame->contentAsText(length);
3139     EXPECT_EQ(expected.substr(0, length), text.utf8());
3140 
3141     // Now do a new test with a subframe.
3142     const char outerFrameSource[] = "Hello<iframe></iframe> world";
3143     FrameTestHelpers::loadHTMLString(frame, outerFrameSource, testURL);
3144 
3145     // Load something into the subframe.
3146     WebFrame* subframe = frame->firstChild();
3147     ASSERT_TRUE(subframe);
3148     FrameTestHelpers::loadHTMLString(subframe, "sub<p>text", testURL);
3149 
3150     text = frame->contentAsText(std::numeric_limits<size_t>::max());
3151     EXPECT_EQ("Hello world\n\nsub\ntext", text.utf8());
3152 
3153     // Get the frame text where the subframe separator falls on the boundary of
3154     // what we'll take. There used to be a crash in this case.
3155     text = frame->contentAsText(12);
3156     EXPECT_EQ("Hello world", text.utf8());
3157 }
3158 
TEST_F(WebFrameTest,GetFullHtmlOfPage)3159 TEST_F(WebFrameTest, GetFullHtmlOfPage)
3160 {
3161     FrameTestHelpers::WebViewHelper webViewHelper;
3162     webViewHelper.initializeAndLoad("about:blank", true);
3163     WebFrame* frame = webViewHelper.webView()->mainFrame();
3164 
3165     // Generate a simple test case.
3166     const char simpleSource[] = "<p>Hello</p><p>World</p>";
3167     WebCore::KURL testURL = toKURL("about:blank");
3168     FrameTestHelpers::loadHTMLString(frame, simpleSource, testURL);
3169 
3170     WebString text = frame->contentAsText(std::numeric_limits<size_t>::max());
3171     EXPECT_EQ("Hello\n\nWorld", text.utf8());
3172 
3173     const std::string html = frame->contentAsMarkup().utf8();
3174 
3175     // Load again with the output html.
3176     FrameTestHelpers::loadHTMLString(frame, html, testURL);
3177 
3178     EXPECT_EQ(html, frame->contentAsMarkup().utf8());
3179 
3180     text = frame->contentAsText(std::numeric_limits<size_t>::max());
3181     EXPECT_EQ("Hello\n\nWorld", text.utf8());
3182 
3183     // Test selection check
3184     EXPECT_FALSE(frame->hasSelection());
3185     frame->executeCommand(WebString::fromUTF8("SelectAll"));
3186     EXPECT_TRUE(frame->hasSelection());
3187     frame->executeCommand(WebString::fromUTF8("Unselect"));
3188     EXPECT_FALSE(frame->hasSelection());
3189     WebString selectionHtml = frame->selectionAsMarkup();
3190     EXPECT_TRUE(selectionHtml.isEmpty());
3191 }
3192 
3193 class TestExecuteScriptDuringDidCreateScriptContext : public FrameTestHelpers::TestWebFrameClient {
3194 public:
didCreateScriptContext(WebLocalFrame * frame,v8::Handle<v8::Context> context,int extensionGroup,int worldId)3195     virtual void didCreateScriptContext(WebLocalFrame* frame, v8::Handle<v8::Context> context, int extensionGroup, int worldId) OVERRIDE
3196     {
3197         frame->executeScript(WebScriptSource("window.history = 'replaced';"));
3198     }
3199 };
3200 
TEST_F(WebFrameTest,ExecuteScriptDuringDidCreateScriptContext)3201 TEST_F(WebFrameTest, ExecuteScriptDuringDidCreateScriptContext)
3202 {
3203     registerMockedHttpURLLoad("hello_world.html");
3204 
3205     TestExecuteScriptDuringDidCreateScriptContext webFrameClient;
3206     FrameTestHelpers::WebViewHelper webViewHelper;
3207     webViewHelper.initializeAndLoad(m_baseURL + "hello_world.html", true, &webFrameClient);
3208 
3209     FrameTestHelpers::reloadFrame(webViewHelper.webView()->mainFrame());
3210 }
3211 
3212 class FindUpdateWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
3213 public:
FindUpdateWebFrameClient()3214     FindUpdateWebFrameClient()
3215         : m_findResultsAreReady(false)
3216         , m_count(-1)
3217     {
3218     }
3219 
reportFindInPageMatchCount(int,int count,bool finalUpdate)3220     virtual void reportFindInPageMatchCount(int, int count, bool finalUpdate) OVERRIDE
3221     {
3222         m_count = count;
3223         if (finalUpdate)
3224             m_findResultsAreReady = true;
3225     }
3226 
findResultsAreReady() const3227     bool findResultsAreReady() const { return m_findResultsAreReady; }
count() const3228     int count() const { return m_count; }
3229 
3230 private:
3231     bool m_findResultsAreReady;
3232     int m_count;
3233 };
3234 
3235 // This fails on Mac https://bugs.webkit.org/show_bug.cgi?id=108574
3236 // Also failing on Android: http://crbug.com/341314
3237 #if OS(MACOSX) || OS(ANDROID)
TEST_F(WebFrameTest,DISABLED_FindInPageMatchRects)3238 TEST_F(WebFrameTest, DISABLED_FindInPageMatchRects)
3239 #else
3240 TEST_F(WebFrameTest, FindInPageMatchRects)
3241 #endif
3242 {
3243     registerMockedHttpURLLoad("find_in_page.html");
3244     registerMockedHttpURLLoad("find_in_page_frame.html");
3245 
3246     FindUpdateWebFrameClient client;
3247     FrameTestHelpers::WebViewHelper webViewHelper;
3248     webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3249     webViewHelper.webView()->resize(WebSize(640, 480));
3250     webViewHelper.webView()->layout();
3251     runPendingTasks();
3252 
3253     // Note that the 'result 19' in the <select> element is not expected to produce a match.
3254     static const char* kFindString = "result";
3255     static const int kFindIdentifier = 12345;
3256     static const int kNumResults = 19;
3257 
3258     WebFindOptions options;
3259     WebString searchText = WebString::fromUTF8(kFindString);
3260     WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3261     EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
3262 
3263     mainFrame->resetMatchCount();
3264 
3265     for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3266         frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3267 
3268     runPendingTasks();
3269     EXPECT_TRUE(client.findResultsAreReady());
3270 
3271     WebVector<WebFloatRect> webMatchRects;
3272     mainFrame->findMatchRects(webMatchRects);
3273     ASSERT_EQ(webMatchRects.size(), static_cast<size_t>(kNumResults));
3274     int rectsVersion = mainFrame->findMatchMarkersVersion();
3275 
3276     for (int resultIndex = 0; resultIndex < kNumResults; ++resultIndex) {
3277         FloatRect resultRect = static_cast<FloatRect>(webMatchRects[resultIndex]);
3278 
3279         // Select the match by the center of its rect.
3280         EXPECT_EQ(mainFrame->selectNearestFindMatch(resultRect.center(), 0), resultIndex + 1);
3281 
3282         // Check that the find result ordering matches with our expectations.
3283         Range* result = mainFrame->activeMatchFrame()->activeMatch();
3284         ASSERT_TRUE(result);
3285         result->setEnd(result->endContainer(), result->endOffset() + 3);
3286         EXPECT_EQ(result->text(), String::format("%s %02d", kFindString, resultIndex));
3287 
3288         // Verify that the expected match rect also matches the currently active match.
3289         // Compare the enclosing rects to prevent precision issues caused by CSS transforms.
3290         FloatRect activeMatch = mainFrame->activeFindMatchRect();
3291         EXPECT_EQ(enclosingIntRect(activeMatch), enclosingIntRect(resultRect));
3292 
3293         // The rects version should not have changed.
3294         EXPECT_EQ(mainFrame->findMatchMarkersVersion(), rectsVersion);
3295     }
3296 
3297     // All results after the first two ones should be below between them in find-in-page coordinates.
3298     // This is because results 2 to 9 are inside an iframe located between results 0 and 1. This applies to the fixed div too.
3299     EXPECT_TRUE(webMatchRects[0].y < webMatchRects[1].y);
3300     for (int resultIndex = 2; resultIndex < kNumResults; ++resultIndex) {
3301         EXPECT_TRUE(webMatchRects[0].y < webMatchRects[resultIndex].y);
3302         EXPECT_TRUE(webMatchRects[1].y > webMatchRects[resultIndex].y);
3303     }
3304 
3305     // Result 3 should be below both 2 and 4. This is caused by the CSS transform in the containing div.
3306     // If the transform doesn't work then 3 will be between 2 and 4.
3307     EXPECT_TRUE(webMatchRects[3].y > webMatchRects[2].y);
3308     EXPECT_TRUE(webMatchRects[3].y > webMatchRects[4].y);
3309 
3310     // Results 6, 7, 8 and 9 should be one below the other in that same order.
3311     // If overflow:scroll is not properly handled then result 8 would be below result 9 or
3312     // result 7 above result 6 depending on the scroll.
3313     EXPECT_TRUE(webMatchRects[6].y < webMatchRects[7].y);
3314     EXPECT_TRUE(webMatchRects[7].y < webMatchRects[8].y);
3315     EXPECT_TRUE(webMatchRects[8].y < webMatchRects[9].y);
3316 
3317     // Results 11, 12, 13 and 14 should be between results 10 and 15, as they are inside the table.
3318     EXPECT_TRUE(webMatchRects[11].y > webMatchRects[10].y);
3319     EXPECT_TRUE(webMatchRects[12].y > webMatchRects[10].y);
3320     EXPECT_TRUE(webMatchRects[13].y > webMatchRects[10].y);
3321     EXPECT_TRUE(webMatchRects[14].y > webMatchRects[10].y);
3322     EXPECT_TRUE(webMatchRects[11].y < webMatchRects[15].y);
3323     EXPECT_TRUE(webMatchRects[12].y < webMatchRects[15].y);
3324     EXPECT_TRUE(webMatchRects[13].y < webMatchRects[15].y);
3325     EXPECT_TRUE(webMatchRects[14].y < webMatchRects[15].y);
3326 
3327     // Result 11 should be above 12, 13 and 14 as it's in the table header.
3328     EXPECT_TRUE(webMatchRects[11].y < webMatchRects[12].y);
3329     EXPECT_TRUE(webMatchRects[11].y < webMatchRects[13].y);
3330     EXPECT_TRUE(webMatchRects[11].y < webMatchRects[14].y);
3331 
3332     // Result 11 should also be right to 12, 13 and 14 because of the colspan.
3333     EXPECT_TRUE(webMatchRects[11].x > webMatchRects[12].x);
3334     EXPECT_TRUE(webMatchRects[11].x > webMatchRects[13].x);
3335     EXPECT_TRUE(webMatchRects[11].x > webMatchRects[14].x);
3336 
3337     // Result 12 should be left to results 11, 13 and 14 in the table layout.
3338     EXPECT_TRUE(webMatchRects[12].x < webMatchRects[11].x);
3339     EXPECT_TRUE(webMatchRects[12].x < webMatchRects[13].x);
3340     EXPECT_TRUE(webMatchRects[12].x < webMatchRects[14].x);
3341 
3342     // Results 13, 12 and 14 should be one above the other in that order because of the rowspan
3343     // and vertical-align: middle by default.
3344     EXPECT_TRUE(webMatchRects[13].y < webMatchRects[12].y);
3345     EXPECT_TRUE(webMatchRects[12].y < webMatchRects[14].y);
3346 
3347     // Result 16 should be below result 15.
3348     EXPECT_TRUE(webMatchRects[15].y > webMatchRects[14].y);
3349 
3350     // Result 18 should be normalized with respect to the position:relative div, and not it's
3351     // immediate containing div. Consequently, result 18 should be above result 17.
3352     EXPECT_TRUE(webMatchRects[17].y > webMatchRects[18].y);
3353 
3354     // Resizing should update the rects version.
3355     webViewHelper.webView()->resize(WebSize(800, 600));
3356     runPendingTasks();
3357     EXPECT_TRUE(mainFrame->findMatchMarkersVersion() != rectsVersion);
3358 }
3359 
TEST_F(WebFrameTest,FindInPageSkipsHiddenFrames)3360 TEST_F(WebFrameTest, FindInPageSkipsHiddenFrames)
3361 {
3362     registerMockedHttpURLLoad("find_in_hidden_frame.html");
3363 
3364     FindUpdateWebFrameClient client;
3365     FrameTestHelpers::WebViewHelper webViewHelper;
3366     webViewHelper.initializeAndLoad(m_baseURL + "find_in_hidden_frame.html", true, &client);
3367     webViewHelper.webView()->resize(WebSize(640, 480));
3368     webViewHelper.webView()->layout();
3369     runPendingTasks();
3370 
3371     static const char* kFindString = "hello";
3372     static const int kFindIdentifier = 12345;
3373     static const int kNumResults = 1;
3374 
3375     WebFindOptions options;
3376     WebString searchText = WebString::fromUTF8(kFindString);
3377     WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3378     EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
3379 
3380     mainFrame->resetMatchCount();
3381 
3382     for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3383         frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3384 
3385     runPendingTasks();
3386     EXPECT_TRUE(client.findResultsAreReady());
3387     EXPECT_EQ(kNumResults, client.count());
3388 }
3389 
TEST_F(WebFrameTest,FindOnDetachedFrame)3390 TEST_F(WebFrameTest, FindOnDetachedFrame)
3391 {
3392     registerMockedHttpURLLoad("find_in_page.html");
3393     registerMockedHttpURLLoad("find_in_page_frame.html");
3394 
3395     FindUpdateWebFrameClient client;
3396     FrameTestHelpers::WebViewHelper webViewHelper;
3397     webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3398     webViewHelper.webView()->resize(WebSize(640, 480));
3399     webViewHelper.webView()->layout();
3400     runPendingTasks();
3401 
3402     static const char* kFindString = "result";
3403     static const int kFindIdentifier = 12345;
3404 
3405     WebFindOptions options;
3406     WebString searchText = WebString::fromUTF8(kFindString);
3407     WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3408     RefPtr<WebLocalFrameImpl> secondFrame = toWebLocalFrameImpl(mainFrame->traverseNext(false));
3409     RefPtr<WebCore::LocalFrame> holdSecondFrame = secondFrame->frame();
3410 
3411     // Detach the frame before finding.
3412     EXPECT_TRUE(mainFrame->document().getElementById("frame").remove());
3413 
3414     EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
3415     EXPECT_FALSE(secondFrame->find(kFindIdentifier, searchText, options, false, 0));
3416 
3417     runPendingTasks();
3418     EXPECT_FALSE(client.findResultsAreReady());
3419 
3420     mainFrame->resetMatchCount();
3421 
3422     for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3423         frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3424 
3425     runPendingTasks();
3426     EXPECT_TRUE(client.findResultsAreReady());
3427 
3428     holdSecondFrame.release();
3429 }
3430 
TEST_F(WebFrameTest,FindDetachFrameBeforeScopeStrings)3431 TEST_F(WebFrameTest, FindDetachFrameBeforeScopeStrings)
3432 {
3433     registerMockedHttpURLLoad("find_in_page.html");
3434     registerMockedHttpURLLoad("find_in_page_frame.html");
3435 
3436     FindUpdateWebFrameClient client;
3437     FrameTestHelpers::WebViewHelper webViewHelper;
3438     webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3439     webViewHelper.webView()->resize(WebSize(640, 480));
3440     webViewHelper.webView()->layout();
3441     runPendingTasks();
3442 
3443     static const char* kFindString = "result";
3444     static const int kFindIdentifier = 12345;
3445 
3446     WebFindOptions options;
3447     WebString searchText = WebString::fromUTF8(kFindString);
3448     WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3449     WebLocalFrameImpl* secondFrame = toWebLocalFrameImpl(mainFrame->traverseNext(false));
3450     RefPtr<WebCore::LocalFrame> holdSecondFrame = secondFrame->frame();
3451 
3452     for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3453         EXPECT_TRUE(frame->find(kFindIdentifier, searchText, options, false, 0));
3454 
3455     runPendingTasks();
3456     EXPECT_FALSE(client.findResultsAreReady());
3457 
3458     // Detach the frame between finding and scoping.
3459     EXPECT_TRUE(mainFrame->document().getElementById("frame").remove());
3460 
3461     mainFrame->resetMatchCount();
3462 
3463     for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3464         frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3465 
3466     runPendingTasks();
3467     EXPECT_TRUE(client.findResultsAreReady());
3468 
3469     holdSecondFrame.release();
3470 }
3471 
TEST_F(WebFrameTest,FindDetachFrameWhileScopingStrings)3472 TEST_F(WebFrameTest, FindDetachFrameWhileScopingStrings)
3473 {
3474     registerMockedHttpURLLoad("find_in_page.html");
3475     registerMockedHttpURLLoad("find_in_page_frame.html");
3476 
3477     FindUpdateWebFrameClient client;
3478     FrameTestHelpers::WebViewHelper webViewHelper;
3479     webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client);
3480     webViewHelper.webView()->resize(WebSize(640, 480));
3481     webViewHelper.webView()->layout();
3482     runPendingTasks();
3483 
3484     static const char* kFindString = "result";
3485     static const int kFindIdentifier = 12345;
3486 
3487     WebFindOptions options;
3488     WebString searchText = WebString::fromUTF8(kFindString);
3489     WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3490     WebLocalFrameImpl* secondFrame = toWebLocalFrameImpl(mainFrame->traverseNext(false));
3491     RefPtr<WebCore::LocalFrame> holdSecondFrame = secondFrame->frame();
3492 
3493     for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3494         EXPECT_TRUE(frame->find(kFindIdentifier, searchText, options, false, 0));
3495 
3496     runPendingTasks();
3497     EXPECT_FALSE(client.findResultsAreReady());
3498 
3499     mainFrame->resetMatchCount();
3500 
3501     for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false))
3502         frame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3503 
3504     // The first scopeStringMatches will have reset the state. Detach before it actually scopes.
3505     EXPECT_TRUE(mainFrame->document().getElementById("frame").remove());
3506 
3507     runPendingTasks();
3508     EXPECT_TRUE(client.findResultsAreReady());
3509 
3510     holdSecondFrame.release();
3511 }
3512 
TEST_F(WebFrameTest,ResetMatchCount)3513 TEST_F(WebFrameTest, ResetMatchCount)
3514 {
3515     registerMockedHttpURLLoad("find_in_generated_frame.html");
3516 
3517     FindUpdateWebFrameClient client;
3518     FrameTestHelpers::WebViewHelper webViewHelper;
3519     webViewHelper.initializeAndLoad(m_baseURL + "find_in_generated_frame.html", true, &client);
3520     webViewHelper.webView()->resize(WebSize(640, 480));
3521     webViewHelper.webView()->layout();
3522     runPendingTasks();
3523 
3524     static const char* kFindString = "result";
3525     static const int kFindIdentifier = 12345;
3526 
3527     WebFindOptions options;
3528     WebString searchText = WebString::fromUTF8(kFindString);
3529     WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3530 
3531     // Check that child frame exists.
3532     EXPECT_TRUE(!!mainFrame->traverseNext(false));
3533 
3534     for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false)) {
3535         EXPECT_FALSE(frame->find(kFindIdentifier, searchText, options, false, 0));
3536     }
3537 
3538     runPendingTasks();
3539     EXPECT_FALSE(client.findResultsAreReady());
3540 
3541     mainFrame->resetMatchCount();
3542 }
3543 
TEST_F(WebFrameTest,SetTickmarks)3544 TEST_F(WebFrameTest, SetTickmarks)
3545 {
3546     registerMockedHttpURLLoad("find.html");
3547 
3548     FindUpdateWebFrameClient client;
3549     FrameTestHelpers::WebViewHelper webViewHelper;
3550     webViewHelper.initializeAndLoad(m_baseURL + "find.html", true, &client);
3551     webViewHelper.webView()->resize(WebSize(640, 480));
3552     webViewHelper.webView()->layout();
3553     runPendingTasks();
3554 
3555     static const char* kFindString = "foo";
3556     static const int kFindIdentifier = 12345;
3557 
3558     WebFindOptions options;
3559     WebString searchText = WebString::fromUTF8(kFindString);
3560     WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3561     EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0));
3562 
3563     mainFrame->resetMatchCount();
3564     mainFrame->scopeStringMatches(kFindIdentifier, searchText, options, true);
3565 
3566     runPendingTasks();
3567     EXPECT_TRUE(client.findResultsAreReady());
3568 
3569     // Get the tickmarks for the original find request.
3570     WebCore::FrameView* frameView = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
3571     RefPtr<WebCore::Scrollbar> scrollbar = frameView->createScrollbar(WebCore::HorizontalScrollbar);
3572     Vector<WebCore::IntRect> originalTickmarks;
3573     scrollbar->getTickmarks(originalTickmarks);
3574     EXPECT_EQ(4u, originalTickmarks.size());
3575 
3576     // Override the tickmarks.
3577     Vector<WebCore::IntRect> overridingTickmarksExpected;
3578     overridingTickmarksExpected.append(WebCore::IntRect(0, 0, 100, 100));
3579     overridingTickmarksExpected.append(WebCore::IntRect(0, 20, 100, 100));
3580     overridingTickmarksExpected.append(WebCore::IntRect(0, 30, 100, 100));
3581     mainFrame->setTickmarks(overridingTickmarksExpected);
3582 
3583     // Check the tickmarks are overriden correctly.
3584     Vector<WebCore::IntRect> overridingTickmarksActual;
3585     scrollbar->getTickmarks(overridingTickmarksActual);
3586     EXPECT_EQ(overridingTickmarksExpected, overridingTickmarksActual);
3587 
3588     // Reset the tickmark behavior.
3589     Vector<WebCore::IntRect> resetTickmarks;
3590     mainFrame->setTickmarks(resetTickmarks);
3591 
3592     // Check that the original tickmarks are returned
3593     Vector<WebCore::IntRect> originalTickmarksAfterReset;
3594     scrollbar->getTickmarks(originalTickmarksAfterReset);
3595     EXPECT_EQ(originalTickmarks, originalTickmarksAfterReset);
3596 }
3597 
topLeft(const WebRect & rect)3598 static WebPoint topLeft(const WebRect& rect)
3599 {
3600     return WebPoint(rect.x, rect.y);
3601 }
3602 
bottomRightMinusOne(const WebRect & rect)3603 static WebPoint bottomRightMinusOne(const WebRect& rect)
3604 {
3605     // FIXME: If we don't subtract 1 from the x- and y-coordinates of the
3606     // selection bounds, selectRange() will select the *next* element. That's
3607     // strictly correct, as hit-testing checks the pixel to the lower-right of
3608     // the input coordinate, but it's a wart on the API.
3609     return WebPoint(rect.x + rect.width - 1, rect.y + rect.height - 1);
3610 }
3611 
elementBounds(WebFrame * frame,const WebString & id)3612 static WebRect elementBounds(WebFrame* frame, const WebString& id)
3613 {
3614     return frame->document().getElementById(id).boundsInViewportSpace();
3615 }
3616 
selectionAsString(WebFrame * frame)3617 static std::string selectionAsString(WebFrame* frame)
3618 {
3619     return frame->selectionAsText().utf8();
3620 }
3621 
TEST_F(WebFrameTest,SelectRange)3622 TEST_F(WebFrameTest, SelectRange)
3623 {
3624     WebFrame* frame;
3625     WebRect startWebRect;
3626     WebRect endWebRect;
3627 
3628     registerMockedHttpURLLoad("select_range_basic.html");
3629     registerMockedHttpURLLoad("select_range_scroll.html");
3630 
3631     FrameTestHelpers::WebViewHelper webViewHelper;
3632     initializeTextSelectionWebView(m_baseURL + "select_range_basic.html", &webViewHelper);
3633     frame = webViewHelper.webView()->mainFrame();
3634     EXPECT_EQ("Some test text for testing.", selectionAsString(frame));
3635     webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3636     frame->executeCommand(WebString::fromUTF8("Unselect"));
3637     EXPECT_EQ("", selectionAsString(frame));
3638     frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3639     EXPECT_EQ("Some test text for testing.", selectionAsString(frame));
3640 
3641     initializeTextSelectionWebView(m_baseURL + "select_range_scroll.html", &webViewHelper);
3642     frame = webViewHelper.webView()->mainFrame();
3643     EXPECT_EQ("Some offscreen test text for testing.", selectionAsString(frame));
3644     webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3645     frame->executeCommand(WebString::fromUTF8("Unselect"));
3646     EXPECT_EQ("", selectionAsString(frame));
3647     frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3648     EXPECT_EQ("Some offscreen test text for testing.", selectionAsString(frame));
3649 }
3650 
TEST_F(WebFrameTest,SelectRangeInIframe)3651 TEST_F(WebFrameTest, SelectRangeInIframe)
3652 {
3653     WebFrame* frame;
3654     WebRect startWebRect;
3655     WebRect endWebRect;
3656 
3657     registerMockedHttpURLLoad("select_range_iframe.html");
3658     registerMockedHttpURLLoad("select_range_basic.html");
3659 
3660     FrameTestHelpers::WebViewHelper webViewHelper;
3661     initializeTextSelectionWebView(m_baseURL + "select_range_iframe.html", &webViewHelper);
3662     frame = webViewHelper.webView()->mainFrame();
3663     WebFrame* subframe = frame->firstChild();
3664     EXPECT_EQ("Some test text for testing.", selectionAsString(subframe));
3665     webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3666     subframe->executeCommand(WebString::fromUTF8("Unselect"));
3667     EXPECT_EQ("", selectionAsString(subframe));
3668     subframe->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3669     EXPECT_EQ("Some test text for testing.", selectionAsString(subframe));
3670 }
3671 
TEST_F(WebFrameTest,SelectRangeDivContentEditable)3672 TEST_F(WebFrameTest, SelectRangeDivContentEditable)
3673 {
3674     WebFrame* frame;
3675     WebRect startWebRect;
3676     WebRect endWebRect;
3677 
3678     registerMockedHttpURLLoad("select_range_div_editable.html");
3679 
3680     // Select the middle of an editable element, then try to extend the selection to the top of the document.
3681     // The selection range should be clipped to the bounds of the editable element.
3682     FrameTestHelpers::WebViewHelper webViewHelper;
3683     initializeTextSelectionWebView(m_baseURL + "select_range_div_editable.html", &webViewHelper);
3684     frame = webViewHelper.webView()->mainFrame();
3685     EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3686     webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3687 
3688     frame->selectRange(bottomRightMinusOne(endWebRect), WebPoint(0, 0));
3689     EXPECT_EQ("16-char header. This text is initially selected.", selectionAsString(frame));
3690 
3691     // As above, but extending the selection to the bottom of the document.
3692     initializeTextSelectionWebView(m_baseURL + "select_range_div_editable.html", &webViewHelper);
3693     frame = webViewHelper.webView()->mainFrame();
3694 
3695     webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3696     frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3697     EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3698     webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3699 
3700     webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3701     frame->selectRange(topLeft(startWebRect), WebPoint(640, 480));
3702     EXPECT_EQ("This text is initially selected. 16-char footer.", selectionAsString(frame));
3703 }
3704 
3705 // positionForPoint returns the wrong values for contenteditable spans. See
3706 // http://crbug.com/238334.
TEST_F(WebFrameTest,DISABLED_SelectRangeSpanContentEditable)3707 TEST_F(WebFrameTest, DISABLED_SelectRangeSpanContentEditable)
3708 {
3709     WebFrame* frame;
3710     WebRect startWebRect;
3711     WebRect endWebRect;
3712 
3713     registerMockedHttpURLLoad("select_range_span_editable.html");
3714 
3715     // Select the middle of an editable element, then try to extend the selection to the top of the document.
3716     // The selection range should be clipped to the bounds of the editable element.
3717     FrameTestHelpers::WebViewHelper webViewHelper;
3718     initializeTextSelectionWebView(m_baseURL + "select_range_span_editable.html", &webViewHelper);
3719     frame = webViewHelper.webView()->mainFrame();
3720     EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3721     webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3722 
3723     frame->selectRange(bottomRightMinusOne(endWebRect), WebPoint(0, 0));
3724     EXPECT_EQ("16-char header. This text is initially selected.", selectionAsString(frame));
3725 
3726     // As above, but extending the selection to the bottom of the document.
3727     initializeTextSelectionWebView(m_baseURL + "select_range_span_editable.html", &webViewHelper);
3728     frame = webViewHelper.webView()->mainFrame();
3729 
3730     webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3731     frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect));
3732     EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3733     webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3734 
3735     EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
3736     webViewHelper.webView()->selectionBounds(startWebRect, endWebRect);
3737     frame->selectRange(topLeft(startWebRect), WebPoint(640, 480));
3738     EXPECT_EQ("This text is initially selected. 16-char footer.", selectionAsString(frame));
3739 }
3740 
TEST_F(WebFrameTest,SelectRangeCanMoveSelectionStart)3741 TEST_F(WebFrameTest, SelectRangeCanMoveSelectionStart)
3742 {
3743     registerMockedHttpURLLoad("text_selection.html");
3744     FrameTestHelpers::WebViewHelper webViewHelper;
3745     initializeTextSelectionWebView(m_baseURL + "text_selection.html", &webViewHelper);
3746     WebFrame* frame = webViewHelper.webView()->mainFrame();
3747 
3748     // Select second span. We can move the start to include the first span.
3749     frame->executeScript(WebScriptSource("selectElement('header_2');"));
3750     EXPECT_EQ("Header 2.", selectionAsString(frame));
3751     frame->selectRange(bottomRightMinusOne(elementBounds(frame, "header_2")), topLeft(elementBounds(frame, "header_1")));
3752     EXPECT_EQ("Header 1. Header 2.", selectionAsString(frame));
3753 
3754     // We can move the start and end together.
3755     frame->executeScript(WebScriptSource("selectElement('header_1');"));
3756     EXPECT_EQ("Header 1.", selectionAsString(frame));
3757     frame->selectRange(bottomRightMinusOne(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "header_1")));
3758     EXPECT_EQ("", selectionAsString(frame));
3759     // Selection is a caret, not empty.
3760     EXPECT_FALSE(frame->selectionRange().isNull());
3761 
3762     // We can move the start across the end.
3763     frame->executeScript(WebScriptSource("selectElement('header_1');"));
3764     EXPECT_EQ("Header 1.", selectionAsString(frame));
3765     frame->selectRange(bottomRightMinusOne(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "header_2")));
3766     EXPECT_EQ(" Header 2.", selectionAsString(frame));
3767 
3768     // Can't extend the selection part-way into an editable element.
3769     frame->executeScript(WebScriptSource("selectElement('footer_2');"));
3770     EXPECT_EQ("Footer 2.", selectionAsString(frame));
3771     frame->selectRange(bottomRightMinusOne(elementBounds(frame, "footer_2")), topLeft(elementBounds(frame, "editable_2")));
3772     EXPECT_EQ(" [ Footer 1. Footer 2.", selectionAsString(frame));
3773 
3774     // Can extend the selection completely across editable elements.
3775     frame->executeScript(WebScriptSource("selectElement('footer_2');"));
3776     EXPECT_EQ("Footer 2.", selectionAsString(frame));
3777     frame->selectRange(bottomRightMinusOne(elementBounds(frame, "footer_2")), topLeft(elementBounds(frame, "header_2")));
3778     EXPECT_EQ("Header 2. ] [ Editable 1. Editable 2. ] [ Footer 1. Footer 2.", selectionAsString(frame));
3779 
3780     // If the selection is editable text, we can't extend it into non-editable text.
3781     frame->executeScript(WebScriptSource("selectElement('editable_2');"));
3782     EXPECT_EQ("Editable 2.", selectionAsString(frame));
3783     frame->selectRange(bottomRightMinusOne(elementBounds(frame, "editable_2")), topLeft(elementBounds(frame, "header_2")));
3784     // positionForPoint returns the wrong values for contenteditable spans. See
3785     // http://crbug.com/238334.
3786     // EXPECT_EQ("[ Editable 1. Editable 2.", selectionAsString(frame));
3787 }
3788 
TEST_F(WebFrameTest,SelectRangeCanMoveSelectionEnd)3789 TEST_F(WebFrameTest, SelectRangeCanMoveSelectionEnd)
3790 {
3791     registerMockedHttpURLLoad("text_selection.html");
3792     FrameTestHelpers::WebViewHelper webViewHelper;
3793     initializeTextSelectionWebView(m_baseURL + "text_selection.html", &webViewHelper);
3794     WebFrame* frame = webViewHelper.webView()->mainFrame();
3795 
3796     // Select first span. We can move the end to include the second span.
3797     frame->executeScript(WebScriptSource("selectElement('header_1');"));
3798     EXPECT_EQ("Header 1.", selectionAsString(frame));
3799     frame->selectRange(topLeft(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "header_2")));
3800     EXPECT_EQ("Header 1. Header 2.", selectionAsString(frame));
3801 
3802     // We can move the start and end together.
3803     frame->executeScript(WebScriptSource("selectElement('header_2');"));
3804     EXPECT_EQ("Header 2.", selectionAsString(frame));
3805     frame->selectRange(topLeft(elementBounds(frame, "header_2")), topLeft(elementBounds(frame, "header_2")));
3806     EXPECT_EQ("", selectionAsString(frame));
3807     // Selection is a caret, not empty.
3808     EXPECT_FALSE(frame->selectionRange().isNull());
3809 
3810     // We can move the end across the start.
3811     frame->executeScript(WebScriptSource("selectElement('header_2');"));
3812     EXPECT_EQ("Header 2.", selectionAsString(frame));
3813     frame->selectRange(topLeft(elementBounds(frame, "header_2")), topLeft(elementBounds(frame, "header_1")));
3814     EXPECT_EQ("Header 1. ", selectionAsString(frame));
3815 
3816     // Can't extend the selection part-way into an editable element.
3817     frame->executeScript(WebScriptSource("selectElement('header_1');"));
3818     EXPECT_EQ("Header 1.", selectionAsString(frame));
3819     frame->selectRange(topLeft(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "editable_1")));
3820     EXPECT_EQ("Header 1. Header 2. ] ", selectionAsString(frame));
3821 
3822     // Can extend the selection completely across editable elements.
3823     frame->executeScript(WebScriptSource("selectElement('header_1');"));
3824     EXPECT_EQ("Header 1.", selectionAsString(frame));
3825     frame->selectRange(topLeft(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "footer_1")));
3826     EXPECT_EQ("Header 1. Header 2. ] [ Editable 1. Editable 2. ] [ Footer 1.", selectionAsString(frame));
3827 
3828     // If the selection is editable text, we can't extend it into non-editable text.
3829     frame->executeScript(WebScriptSource("selectElement('editable_1');"));
3830     EXPECT_EQ("Editable 1.", selectionAsString(frame));
3831     frame->selectRange(topLeft(elementBounds(frame, "editable_1")), bottomRightMinusOne(elementBounds(frame, "footer_1")));
3832     // positionForPoint returns the wrong values for contenteditable spans. See
3833     // http://crbug.com/238334.
3834     // EXPECT_EQ("Editable 1. Editable 2. ]", selectionAsString(frame));
3835 }
3836 
computeOffset(WebCore::RenderObject * renderer,int x,int y)3837 static int computeOffset(WebCore::RenderObject* renderer, int x, int y)
3838 {
3839     return WebCore::VisiblePosition(renderer->positionForPoint(WebCore::LayoutPoint(x, y))).deepEquivalent().computeOffsetInContainerNode();
3840 }
3841 
3842 // positionForPoint returns the wrong values for contenteditable spans. See
3843 // http://crbug.com/238334.
TEST_F(WebFrameTest,DISABLED_PositionForPointTest)3844 TEST_F(WebFrameTest, DISABLED_PositionForPointTest)
3845 {
3846     registerMockedHttpURLLoad("select_range_span_editable.html");
3847     FrameTestHelpers::WebViewHelper webViewHelper;
3848     initializeTextSelectionWebView(m_baseURL + "select_range_span_editable.html", &webViewHelper);
3849     WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3850     WebCore::RenderObject* renderer = mainFrame->frame()->selection().rootEditableElement()->renderer();
3851     EXPECT_EQ(0, computeOffset(renderer, -1, -1));
3852     EXPECT_EQ(64, computeOffset(renderer, 1000, 1000));
3853 
3854     registerMockedHttpURLLoad("select_range_div_editable.html");
3855     initializeTextSelectionWebView(m_baseURL + "select_range_div_editable.html", &webViewHelper);
3856     mainFrame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3857     renderer = mainFrame->frame()->selection().rootEditableElement()->renderer();
3858     EXPECT_EQ(0, computeOffset(renderer, -1, -1));
3859     EXPECT_EQ(64, computeOffset(renderer, 1000, 1000));
3860 }
3861 
3862 #if !OS(MACOSX) && !OS(LINUX)
TEST_F(WebFrameTest,SelectRangeStaysHorizontallyAlignedWhenMoved)3863 TEST_F(WebFrameTest, SelectRangeStaysHorizontallyAlignedWhenMoved)
3864 {
3865     registerMockedHttpURLLoad("move_caret.html");
3866 
3867     FrameTestHelpers::WebViewHelper webViewHelper;
3868     initializeTextSelectionWebView(m_baseURL + "move_caret.html", &webViewHelper);
3869     WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
3870 
3871     WebRect initialStartRect;
3872     WebRect initialEndRect;
3873     WebRect startRect;
3874     WebRect endRect;
3875 
3876     frame->executeScript(WebScriptSource("selectRange();"));
3877     webViewHelper.webView()->selectionBounds(initialStartRect, initialEndRect);
3878     WebPoint movedStart(topLeft(initialStartRect));
3879 
3880     movedStart.y += 40;
3881     frame->selectRange(movedStart, bottomRightMinusOne(initialEndRect));
3882     webViewHelper.webView()->selectionBounds(startRect, endRect);
3883     EXPECT_EQ(startRect, initialStartRect);
3884     EXPECT_EQ(endRect, initialEndRect);
3885 
3886     movedStart.y -= 80;
3887     frame->selectRange(movedStart, bottomRightMinusOne(initialEndRect));
3888     webViewHelper.webView()->selectionBounds(startRect, endRect);
3889     EXPECT_EQ(startRect, initialStartRect);
3890     EXPECT_EQ(endRect, initialEndRect);
3891 
3892     WebPoint movedEnd(bottomRightMinusOne(initialEndRect));
3893 
3894     movedEnd.y += 40;
3895     frame->selectRange(topLeft(initialStartRect), movedEnd);
3896     webViewHelper.webView()->selectionBounds(startRect, endRect);
3897     EXPECT_EQ(startRect, initialStartRect);
3898     EXPECT_EQ(endRect, initialEndRect);
3899 
3900     movedEnd.y -= 80;
3901     frame->selectRange(topLeft(initialStartRect), movedEnd);
3902     webViewHelper.webView()->selectionBounds(startRect, endRect);
3903     EXPECT_EQ(startRect, initialStartRect);
3904     EXPECT_EQ(endRect, initialEndRect);
3905 }
3906 
TEST_F(WebFrameTest,MoveCaretStaysHorizontallyAlignedWhenMoved)3907 TEST_F(WebFrameTest, MoveCaretStaysHorizontallyAlignedWhenMoved)
3908 {
3909     WebLocalFrameImpl* frame;
3910     registerMockedHttpURLLoad("move_caret.html");
3911 
3912     FrameTestHelpers::WebViewHelper webViewHelper;
3913     initializeTextSelectionWebView(m_baseURL + "move_caret.html", &webViewHelper);
3914     frame = (WebLocalFrameImpl*)webViewHelper.webView()->mainFrame();
3915 
3916     WebRect initialStartRect;
3917     WebRect initialEndRect;
3918     WebRect startRect;
3919     WebRect endRect;
3920 
3921     frame->executeScript(WebScriptSource("selectCaret();"));
3922     webViewHelper.webView()->selectionBounds(initialStartRect, initialEndRect);
3923     WebPoint moveTo(topLeft(initialStartRect));
3924 
3925     moveTo.y += 40;
3926     frame->moveCaretSelection(moveTo);
3927     webViewHelper.webView()->selectionBounds(startRect, endRect);
3928     EXPECT_EQ(startRect, initialStartRect);
3929     EXPECT_EQ(endRect, initialEndRect);
3930 
3931     moveTo.y -= 80;
3932     frame->moveCaretSelection(moveTo);
3933     webViewHelper.webView()->selectionBounds(startRect, endRect);
3934     EXPECT_EQ(startRect, initialStartRect);
3935     EXPECT_EQ(endRect, initialEndRect);
3936 }
3937 #endif
3938 
3939 class DisambiguationPopupTestWebViewClient : public FrameTestHelpers::TestWebViewClient {
3940 public:
didTapMultipleTargets(const WebGestureEvent &,const WebVector<WebRect> & targetRects)3941     virtual bool didTapMultipleTargets(const WebGestureEvent&, const WebVector<WebRect>& targetRects) OVERRIDE
3942     {
3943         EXPECT_GE(targetRects.size(), 2u);
3944         m_triggered = true;
3945         return true;
3946     }
3947 
triggered() const3948     bool triggered() const { return m_triggered; }
resetTriggered()3949     void resetTriggered() { m_triggered = false; }
3950     bool m_triggered;
3951 };
3952 
fatTap(int x,int y)3953 static WebGestureEvent fatTap(int x, int y)
3954 {
3955     WebGestureEvent event;
3956     event.type = WebInputEvent::GestureTap;
3957     event.x = x;
3958     event.y = y;
3959     event.data.tap.width = 50;
3960     event.data.tap.height = 50;
3961     return event;
3962 }
3963 
TEST_F(WebFrameTest,DisambiguationPopup)3964 TEST_F(WebFrameTest, DisambiguationPopup)
3965 {
3966     const std::string htmlFile = "disambiguation_popup.html";
3967     registerMockedHttpURLLoad(htmlFile);
3968 
3969     DisambiguationPopupTestWebViewClient client;
3970 
3971     // Make sure we initialize to minimum scale, even if the window size
3972     // only becomes available after the load begins.
3973     FrameTestHelpers::WebViewHelper webViewHelper;
3974     webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client);
3975     webViewHelper.webView()->resize(WebSize(1000, 1000));
3976     webViewHelper.webView()->layout();
3977 
3978     client.resetTriggered();
3979     webViewHelper.webView()->handleInputEvent(fatTap(0, 0));
3980     EXPECT_FALSE(client.triggered());
3981 
3982     client.resetTriggered();
3983     webViewHelper.webView()->handleInputEvent(fatTap(200, 115));
3984     EXPECT_FALSE(client.triggered());
3985 
3986     for (int i = 0; i <= 46; i++) {
3987         client.resetTriggered();
3988         webViewHelper.webView()->handleInputEvent(fatTap(120, 230 + i * 5));
3989 
3990         int j = i % 10;
3991         if (j >= 7 && j <= 9)
3992             EXPECT_TRUE(client.triggered());
3993         else
3994             EXPECT_FALSE(client.triggered());
3995     }
3996 
3997     for (int i = 0; i <= 46; i++) {
3998         client.resetTriggered();
3999         webViewHelper.webView()->handleInputEvent(fatTap(10 + i * 5, 590));
4000 
4001         int j = i % 10;
4002         if (j >= 7 && j <= 9)
4003             EXPECT_TRUE(client.triggered());
4004         else
4005             EXPECT_FALSE(client.triggered());
4006     }
4007 }
4008 
TEST_F(WebFrameTest,DisambiguationPopupNoContainer)4009 TEST_F(WebFrameTest, DisambiguationPopupNoContainer)
4010 {
4011     registerMockedHttpURLLoad("disambiguation_popup_no_container.html");
4012 
4013     DisambiguationPopupTestWebViewClient client;
4014 
4015     // Make sure we initialize to minimum scale, even if the window size
4016     // only becomes available after the load begins.
4017     FrameTestHelpers::WebViewHelper webViewHelper;
4018     webViewHelper.initializeAndLoad(m_baseURL + "disambiguation_popup_no_container.html", true, 0, &client);
4019     webViewHelper.webView()->resize(WebSize(1000, 1000));
4020     webViewHelper.webView()->layout();
4021 
4022     client.resetTriggered();
4023     webViewHelper.webView()->handleInputEvent(fatTap(50, 50));
4024     EXPECT_FALSE(client.triggered());
4025 }
4026 
TEST_F(WebFrameTest,DisambiguationPopupMobileSite)4027 TEST_F(WebFrameTest, DisambiguationPopupMobileSite)
4028 {
4029     UseMockScrollbarSettings mockScrollbarSettings;
4030     const std::string htmlFile = "disambiguation_popup_mobile_site.html";
4031     registerMockedHttpURLLoad(htmlFile);
4032 
4033     DisambiguationPopupTestWebViewClient client;
4034 
4035     // Make sure we initialize to minimum scale, even if the window size
4036     // only becomes available after the load begins.
4037     FrameTestHelpers::WebViewHelper webViewHelper;
4038     webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client, enableViewportSettings);
4039     webViewHelper.webView()->resize(WebSize(1000, 1000));
4040     webViewHelper.webView()->layout();
4041 
4042     client.resetTriggered();
4043     webViewHelper.webView()->handleInputEvent(fatTap(0, 0));
4044     EXPECT_FALSE(client.triggered());
4045 
4046     client.resetTriggered();
4047     webViewHelper.webView()->handleInputEvent(fatTap(200, 115));
4048     EXPECT_FALSE(client.triggered());
4049 
4050     for (int i = 0; i <= 46; i++) {
4051         client.resetTriggered();
4052         webViewHelper.webView()->handleInputEvent(fatTap(120, 230 + i * 5));
4053         EXPECT_FALSE(client.triggered());
4054     }
4055 
4056     for (int i = 0; i <= 46; i++) {
4057         client.resetTriggered();
4058         webViewHelper.webView()->handleInputEvent(fatTap(10 + i * 5, 590));
4059         EXPECT_FALSE(client.triggered());
4060     }
4061 }
4062 
TEST_F(WebFrameTest,DisambiguationPopupViewportSite)4063 TEST_F(WebFrameTest, DisambiguationPopupViewportSite)
4064 {
4065     UseMockScrollbarSettings mockScrollbarSettings;
4066     const std::string htmlFile = "disambiguation_popup_viewport_site.html";
4067     registerMockedHttpURLLoad(htmlFile);
4068 
4069     DisambiguationPopupTestWebViewClient client;
4070 
4071     // Make sure we initialize to minimum scale, even if the window size
4072     // only becomes available after the load begins.
4073     FrameTestHelpers::WebViewHelper webViewHelper;
4074     webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client, enableViewportSettings);
4075     webViewHelper.webView()->resize(WebSize(1000, 1000));
4076     webViewHelper.webView()->layout();
4077 
4078     client.resetTriggered();
4079     webViewHelper.webView()->handleInputEvent(fatTap(0, 0));
4080     EXPECT_FALSE(client.triggered());
4081 
4082     client.resetTriggered();
4083     webViewHelper.webView()->handleInputEvent(fatTap(200, 115));
4084     EXPECT_FALSE(client.triggered());
4085 
4086     for (int i = 0; i <= 46; i++) {
4087         client.resetTriggered();
4088         webViewHelper.webView()->handleInputEvent(fatTap(120, 230 + i * 5));
4089         EXPECT_FALSE(client.triggered());
4090     }
4091 
4092     for (int i = 0; i <= 46; i++) {
4093         client.resetTriggered();
4094         webViewHelper.webView()->handleInputEvent(fatTap(10 + i * 5, 590));
4095         EXPECT_FALSE(client.triggered());
4096     }
4097 }
4098 
TEST_F(WebFrameTest,DisambiguationPopupBlacklist)4099 TEST_F(WebFrameTest, DisambiguationPopupBlacklist)
4100 {
4101     const unsigned viewportWidth = 500;
4102     const unsigned viewportHeight = 1000;
4103     const unsigned divHeight = 100;
4104     const std::string htmlFile = "disambiguation_popup_blacklist.html";
4105     registerMockedHttpURLLoad(htmlFile);
4106 
4107     DisambiguationPopupTestWebViewClient client;
4108 
4109     // Make sure we initialize to minimum scale, even if the window size
4110     // only becomes available after the load begins.
4111     FrameTestHelpers::WebViewHelper webViewHelper;
4112     webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client);
4113     webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
4114     webViewHelper.webView()->layout();
4115 
4116     // Click somewhere where the popup shouldn't appear.
4117     client.resetTriggered();
4118     webViewHelper.webView()->handleInputEvent(fatTap(viewportWidth / 2, 0));
4119     EXPECT_FALSE(client.triggered());
4120 
4121     // Click directly in between two container divs with click handlers, with children that don't handle clicks.
4122     client.resetTriggered();
4123     webViewHelper.webView()->handleInputEvent(fatTap(viewportWidth / 2, divHeight));
4124     EXPECT_TRUE(client.triggered());
4125 
4126     // The third div container should be blacklisted if you click on the link it contains.
4127     client.resetTriggered();
4128     webViewHelper.webView()->handleInputEvent(fatTap(viewportWidth / 2, divHeight * 3.25));
4129     EXPECT_FALSE(client.triggered());
4130 }
4131 
TEST_F(WebFrameTest,DisambiguationPopupPageScale)4132 TEST_F(WebFrameTest, DisambiguationPopupPageScale)
4133 {
4134     registerMockedHttpURLLoad("disambiguation_popup_page_scale.html");
4135 
4136     DisambiguationPopupTestWebViewClient client;
4137 
4138     // Make sure we initialize to minimum scale, even if the window size
4139     // only becomes available after the load begins.
4140     FrameTestHelpers::WebViewHelper webViewHelper;
4141     webViewHelper.initializeAndLoad(m_baseURL + "disambiguation_popup_page_scale.html", true, 0, &client);
4142     webViewHelper.webView()->resize(WebSize(1000, 1000));
4143     webViewHelper.webView()->layout();
4144 
4145     client.resetTriggered();
4146     webViewHelper.webView()->handleInputEvent(fatTap(80, 80));
4147     EXPECT_TRUE(client.triggered());
4148 
4149     client.resetTriggered();
4150     webViewHelper.webView()->handleInputEvent(fatTap(230, 190));
4151     EXPECT_TRUE(client.triggered());
4152 
4153     webViewHelper.webView()->setPageScaleFactor(3.0f);
4154     webViewHelper.webView()->layout();
4155 
4156     client.resetTriggered();
4157     webViewHelper.webView()->handleInputEvent(fatTap(240, 240));
4158     EXPECT_TRUE(client.triggered());
4159 
4160     client.resetTriggered();
4161     webViewHelper.webView()->handleInputEvent(fatTap(690, 570));
4162     EXPECT_FALSE(client.triggered());
4163 }
4164 
4165 class TestSubstituteDataWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
4166 public:
TestSubstituteDataWebFrameClient()4167     TestSubstituteDataWebFrameClient()
4168         : m_commitCalled(false)
4169     {
4170     }
4171 
didFailProvisionalLoad(WebLocalFrame * frame,const WebURLError & error)4172     virtual void didFailProvisionalLoad(WebLocalFrame* frame, const WebURLError& error)
4173     {
4174         frame->loadHTMLString("This should appear", toKURL("data:text/html,chromewebdata"), error.unreachableURL, true);
4175     }
4176 
didCommitProvisionalLoad(WebLocalFrame * frame,const WebHistoryItem &,WebHistoryCommitType)4177     virtual void didCommitProvisionalLoad(WebLocalFrame* frame, const WebHistoryItem&, WebHistoryCommitType)
4178     {
4179         if (frame->dataSource()->response().url() != WebURL(URLTestHelpers::toKURL("about:blank")))
4180             m_commitCalled = true;
4181     }
4182 
commitCalled() const4183     bool commitCalled() const { return m_commitCalled; }
4184 
4185 private:
4186     bool m_commitCalled;
4187 };
4188 
TEST_F(WebFrameTest,ReplaceNavigationAfterHistoryNavigation)4189 TEST_F(WebFrameTest, ReplaceNavigationAfterHistoryNavigation)
4190 {
4191     TestSubstituteDataWebFrameClient webFrameClient;
4192 
4193     FrameTestHelpers::WebViewHelper webViewHelper;
4194     webViewHelper.initializeAndLoad("about:blank", true, &webFrameClient);
4195     WebFrame* frame = webViewHelper.webView()->mainFrame();
4196 
4197     // Load a url as a history navigation that will return an error. TestSubstituteDataWebFrameClient
4198     // will start a SubstituteData load in response to the load failure, which should get fully committed.
4199     // Due to https://bugs.webkit.org/show_bug.cgi?id=91685, FrameLoader::didReceiveData() wasn't getting
4200     // called in this case, which resulted in the SubstituteData document not getting displayed.
4201     WebURLError error;
4202     error.reason = 1337;
4203     error.domain = "WebFrameTest";
4204     std::string errorURL = "http://0.0.0.0";
4205     WebURLResponse response;
4206     response.initialize();
4207     response.setURL(URLTestHelpers::toKURL(errorURL));
4208     response.setMIMEType("text/html");
4209     response.setHTTPStatusCode(500);
4210     WebHistoryItem errorHistoryItem;
4211     errorHistoryItem.initialize();
4212     errorHistoryItem.setURLString(WebString::fromUTF8(errorURL.c_str(), errorURL.length()));
4213     Platform::current()->unitTestSupport()->registerMockedErrorURL(URLTestHelpers::toKURL(errorURL), response, error);
4214     FrameTestHelpers::loadHistoryItem(frame, errorHistoryItem, WebHistoryDifferentDocumentLoad, WebURLRequest::UseProtocolCachePolicy);
4215 
4216     WebString text = frame->contentAsText(std::numeric_limits<size_t>::max());
4217     EXPECT_EQ("This should appear", text.utf8());
4218     EXPECT_TRUE(webFrameClient.commitCalled());
4219 }
4220 
4221 class TestWillInsertBodyWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
4222 public:
TestWillInsertBodyWebFrameClient()4223     TestWillInsertBodyWebFrameClient() : m_numBodies(0), m_didLoad(false)
4224     {
4225     }
4226 
didCommitProvisionalLoad(WebLocalFrame *,const WebHistoryItem &,WebHistoryCommitType)4227     virtual void didCommitProvisionalLoad(WebLocalFrame*, const WebHistoryItem&, WebHistoryCommitType) OVERRIDE
4228     {
4229         m_numBodies = 0;
4230         m_didLoad = true;
4231     }
4232 
didCreateDocumentElement(WebLocalFrame *)4233     virtual void didCreateDocumentElement(WebLocalFrame*) OVERRIDE
4234     {
4235         EXPECT_EQ(0, m_numBodies);
4236     }
4237 
willInsertBody(WebLocalFrame *)4238     virtual void willInsertBody(WebLocalFrame*) OVERRIDE
4239     {
4240         m_numBodies++;
4241     }
4242 
4243     int m_numBodies;
4244     bool m_didLoad;
4245 };
4246 
TEST_F(WebFrameTest,HTMLDocument)4247 TEST_F(WebFrameTest, HTMLDocument)
4248 {
4249     registerMockedHttpURLLoad("clipped-body.html");
4250 
4251     TestWillInsertBodyWebFrameClient webFrameClient;
4252     FrameTestHelpers::WebViewHelper webViewHelper;
4253     webViewHelper.initializeAndLoad(m_baseURL + "clipped-body.html", false, &webFrameClient);
4254 
4255     EXPECT_TRUE(webFrameClient.m_didLoad);
4256     EXPECT_EQ(1, webFrameClient.m_numBodies);
4257 }
4258 
TEST_F(WebFrameTest,EmptyDocument)4259 TEST_F(WebFrameTest, EmptyDocument)
4260 {
4261     registerMockedHttpURLLoad("pageserializer/green_rectangle.svg");
4262 
4263     TestWillInsertBodyWebFrameClient webFrameClient;
4264     FrameTestHelpers::WebViewHelper webViewHelper;
4265     webViewHelper.initialize(false, &webFrameClient);
4266 
4267     EXPECT_FALSE(webFrameClient.m_didLoad);
4268     EXPECT_EQ(1, webFrameClient.m_numBodies); // The empty document that a new frame starts with triggers this.
4269 }
4270 
TEST_F(WebFrameTest,MoveCaretSelectionTowardsWindowPointWithNoSelection)4271 TEST_F(WebFrameTest, MoveCaretSelectionTowardsWindowPointWithNoSelection)
4272 {
4273     FrameTestHelpers::WebViewHelper webViewHelper;
4274     webViewHelper.initializeAndLoad("about:blank", true);
4275     WebFrame* frame = webViewHelper.webView()->mainFrame();
4276 
4277     // This test passes if this doesn't crash.
4278     frame->moveCaretSelection(WebPoint(0, 0));
4279 }
4280 
4281 class SpellCheckClient : public WebSpellCheckClient {
4282 public:
SpellCheckClient(uint32_t hash=0)4283     explicit SpellCheckClient(uint32_t hash = 0) : m_numberOfTimesChecked(0), m_hash(hash) { }
~SpellCheckClient()4284     virtual ~SpellCheckClient() { }
requestCheckingOfText(const blink::WebString &,const blink::WebVector<uint32_t> &,const blink::WebVector<unsigned> &,blink::WebTextCheckingCompletion * completion)4285     virtual void requestCheckingOfText(const blink::WebString&, const blink::WebVector<uint32_t>&, const blink::WebVector<unsigned>&, blink::WebTextCheckingCompletion* completion) OVERRIDE
4286     {
4287         ++m_numberOfTimesChecked;
4288         Vector<WebTextCheckingResult> results;
4289         const int misspellingStartOffset = 1;
4290         const int misspellingLength = 8;
4291         results.append(WebTextCheckingResult(WebTextDecorationTypeSpelling, misspellingStartOffset, misspellingLength, WebString(), m_hash));
4292         completion->didFinishCheckingText(results);
4293     }
numberOfTimesChecked() const4294     int numberOfTimesChecked() const { return m_numberOfTimesChecked; }
4295 private:
4296     int m_numberOfTimesChecked;
4297     uint32_t m_hash;
4298 };
4299 
TEST_F(WebFrameTest,ReplaceMisspelledRange)4300 TEST_F(WebFrameTest, ReplaceMisspelledRange)
4301 {
4302     registerMockedHttpURLLoad("spell.html");
4303     FrameTestHelpers::WebViewHelper webViewHelper;
4304     webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4305     SpellCheckClient spellcheck;
4306     webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4307 
4308     WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4309     Document* document = frame->frame()->document();
4310     Element* element = document->getElementById("data");
4311 
4312     webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4313     webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4314     webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4315 
4316     element->focus();
4317     document->execCommand("InsertText", false, "_wellcome_.");
4318 
4319     const int allTextBeginOffset = 0;
4320     const int allTextLength = 11;
4321     frame->selectRange(WebRange::fromDocumentRange(frame, allTextBeginOffset, allTextLength));
4322     RefPtrWillBeRawPtr<Range> selectionRange = frame->frame()->selection().toNormalizedRange();
4323 
4324     EXPECT_EQ(1, spellcheck.numberOfTimesChecked());
4325     EXPECT_EQ(1U, document->markers().markersInRange(selectionRange.get(), DocumentMarker::Spelling).size());
4326 
4327     frame->replaceMisspelledRange("welcome");
4328     EXPECT_EQ("_welcome_.", frame->contentAsText(std::numeric_limits<size_t>::max()).utf8());
4329 }
4330 
TEST_F(WebFrameTest,RemoveSpellingMarkers)4331 TEST_F(WebFrameTest, RemoveSpellingMarkers)
4332 {
4333     registerMockedHttpURLLoad("spell.html");
4334     FrameTestHelpers::WebViewHelper webViewHelper;
4335     webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4336     SpellCheckClient spellcheck;
4337     webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4338 
4339     WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4340     Document* document = frame->frame()->document();
4341     Element* element = document->getElementById("data");
4342 
4343     webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4344     webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4345     webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4346 
4347     element->focus();
4348     document->execCommand("InsertText", false, "_wellcome_.");
4349 
4350     frame->removeSpellingMarkers();
4351 
4352     const int allTextBeginOffset = 0;
4353     const int allTextLength = 11;
4354     frame->selectRange(WebRange::fromDocumentRange(frame, allTextBeginOffset, allTextLength));
4355     RefPtrWillBeRawPtr<Range> selectionRange = frame->frame()->selection().toNormalizedRange();
4356 
4357     EXPECT_EQ(0U, document->markers().markersInRange(selectionRange.get(), DocumentMarker::Spelling).size());
4358 }
4359 
TEST_F(WebFrameTest,MarkerHashIdentifiers)4360 TEST_F(WebFrameTest, MarkerHashIdentifiers) {
4361     registerMockedHttpURLLoad("spell.html");
4362     FrameTestHelpers::WebViewHelper webViewHelper;
4363     webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4364 
4365     static const uint32_t kHash = 42;
4366     SpellCheckClient spellcheck(kHash);
4367     webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4368 
4369     WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4370     Document* document = frame->frame()->document();
4371     Element* element = document->getElementById("data");
4372 
4373     webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4374     webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4375     webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4376 
4377     element->focus();
4378     document->execCommand("InsertText", false, "wellcome.");
4379 
4380     WebVector<uint32_t> documentMarkers;
4381     webViewHelper.webView()->spellingMarkers(&documentMarkers);
4382     EXPECT_EQ(1U, documentMarkers.size());
4383     EXPECT_EQ(kHash, documentMarkers[0]);
4384 }
4385 
4386 class StubbornSpellCheckClient : public WebSpellCheckClient {
4387 public:
StubbornSpellCheckClient()4388     StubbornSpellCheckClient() : m_completion(0) { }
~StubbornSpellCheckClient()4389     virtual ~StubbornSpellCheckClient() { }
4390 
requestCheckingOfText(const blink::WebString &,const blink::WebVector<uint32_t> &,const blink::WebVector<unsigned> &,blink::WebTextCheckingCompletion * completion)4391     virtual void requestCheckingOfText(
4392         const blink::WebString&,
4393         const blink::WebVector<uint32_t>&,
4394         const blink::WebVector<unsigned>&,
4395         blink::WebTextCheckingCompletion* completion) OVERRIDE
4396     {
4397         m_completion = completion;
4398     }
4399 
kickNoResults()4400     void kickNoResults()
4401     {
4402         kick(-1, -1, WebTextDecorationTypeSpelling);
4403     }
4404 
kick()4405     void kick()
4406     {
4407         kick(1, 8, WebTextDecorationTypeSpelling);
4408     }
4409 
kickGrammar()4410     void kickGrammar()
4411     {
4412         kick(1, 8, WebTextDecorationTypeGrammar);
4413     }
4414 
kickInvisibleSpellcheck()4415     void kickInvisibleSpellcheck()
4416     {
4417         kick(1, 8, WebTextDecorationTypeInvisibleSpellcheck);
4418     }
4419 
4420 private:
kick(int misspellingStartOffset,int misspellingLength,WebTextDecorationType type)4421     void kick(int misspellingStartOffset, int misspellingLength, WebTextDecorationType type)
4422     {
4423         if (!m_completion)
4424             return;
4425         Vector<WebTextCheckingResult> results;
4426         if (misspellingStartOffset >= 0 && misspellingLength > 0)
4427             results.append(WebTextCheckingResult(type, misspellingStartOffset, misspellingLength));
4428         m_completion->didFinishCheckingText(results);
4429         m_completion = 0;
4430     }
4431 
4432     blink::WebTextCheckingCompletion* m_completion;
4433 };
4434 
TEST_F(WebFrameTest,SlowSpellcheckMarkerPosition)4435 TEST_F(WebFrameTest, SlowSpellcheckMarkerPosition)
4436 {
4437     registerMockedHttpURLLoad("spell.html");
4438     FrameTestHelpers::WebViewHelper webViewHelper;
4439     webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4440 
4441     StubbornSpellCheckClient spellcheck;
4442     webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4443 
4444     WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4445     WebInputElement webInputElement = frame->document().getElementById("data").to<WebInputElement>();
4446     Document* document = frame->frame()->document();
4447     Element* element = document->getElementById("data");
4448 
4449     webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4450     webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4451     webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4452 
4453     element->focus();
4454     document->execCommand("InsertText", false, "wellcome ");
4455     webInputElement.setSelectionRange(0, 0);
4456     document->execCommand("InsertText", false, "he");
4457 
4458     spellcheck.kick();
4459 
4460     WebVector<uint32_t> documentMarkers;
4461     webViewHelper.webView()->spellingMarkers(&documentMarkers);
4462     EXPECT_EQ(0U, documentMarkers.size());
4463 }
4464 
4465 // This test verifies that cancelling spelling request does not cause a
4466 // write-after-free when there's no spellcheck client set.
TEST_F(WebFrameTest,CancelSpellingRequestCrash)4467 TEST_F(WebFrameTest, CancelSpellingRequestCrash)
4468 {
4469     registerMockedHttpURLLoad("spell.html");
4470     FrameTestHelpers::WebViewHelper webViewHelper;
4471     webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4472     webViewHelper.webView()->setSpellCheckClient(0);
4473 
4474     WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4475     Document* document = frame->frame()->document();
4476     Element* element = document->getElementById("data");
4477 
4478     webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4479     webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4480     webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4481 
4482     element->focus();
4483     frame->frame()->editor().replaceSelectionWithText("A", false, false);
4484     frame->frame()->spellChecker().cancelCheck();
4485 }
4486 
TEST_F(WebFrameTest,SpellcheckResultErasesMarkers)4487 TEST_F(WebFrameTest, SpellcheckResultErasesMarkers)
4488 {
4489     registerMockedHttpURLLoad("spell.html");
4490     FrameTestHelpers::WebViewHelper webViewHelper;
4491     webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4492 
4493     StubbornSpellCheckClient spellcheck;
4494     webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4495 
4496     WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4497     WebInputElement webInputElement = frame->document().getElementById("data").to<WebInputElement>();
4498     Document* document = frame->frame()->document();
4499     Element* element = document->getElementById("data");
4500 
4501     webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4502     webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4503     webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4504 
4505     element->focus();
4506     document->execCommand("InsertText", false, "welcome ");
4507     document->markers().addMarker(rangeOfContents(element->toNode()).get(), DocumentMarker::Spelling);
4508     document->markers().addMarker(rangeOfContents(element->toNode()).get(), DocumentMarker::Grammar);
4509     document->markers().addMarker(rangeOfContents(element->toNode()).get(), DocumentMarker::InvisibleSpellcheck);
4510     EXPECT_EQ(3U, document->markers().markers().size());
4511 
4512     spellcheck.kickNoResults();
4513     EXPECT_EQ(0U, document->markers().markers().size());
4514 }
4515 
TEST_F(WebFrameTest,SpellcheckResultsSavedInDocument)4516 TEST_F(WebFrameTest, SpellcheckResultsSavedInDocument)
4517 {
4518     registerMockedHttpURLLoad("spell.html");
4519     FrameTestHelpers::WebViewHelper webViewHelper;
4520     webViewHelper.initializeAndLoad(m_baseURL + "spell.html");
4521 
4522     StubbornSpellCheckClient spellcheck;
4523     webViewHelper.webView()->setSpellCheckClient(&spellcheck);
4524 
4525     WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
4526     WebInputElement webInputElement = frame->document().getElementById("data").to<WebInputElement>();
4527     Document* document = frame->frame()->document();
4528     Element* element = document->getElementById("data");
4529 
4530     webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true);
4531     webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true);
4532     webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin);
4533 
4534     element->focus();
4535     document->execCommand("InsertText", false, "wellcome ");
4536 
4537     spellcheck.kick();
4538     ASSERT_EQ(1U, document->markers().markers().size());
4539     ASSERT_NE(static_cast<DocumentMarker*>(0), document->markers().markers()[0]);
4540     EXPECT_EQ(DocumentMarker::Spelling, document->markers().markers()[0]->type());
4541 
4542     document->execCommand("InsertText", false, "wellcome ");
4543 
4544     spellcheck.kickGrammar();
4545     ASSERT_EQ(1U, document->markers().markers().size());
4546     ASSERT_NE(static_cast<DocumentMarker*>(0), document->markers().markers()[0]);
4547     EXPECT_EQ(DocumentMarker::Grammar, document->markers().markers()[0]->type());
4548 
4549     document->execCommand("InsertText", false, "wellcome ");
4550 
4551     spellcheck.kickInvisibleSpellcheck();
4552     ASSERT_EQ(1U, document->markers().markers().size());
4553     ASSERT_NE(static_cast<DocumentMarker*>(0), document->markers().markers()[0]);
4554     EXPECT_EQ(DocumentMarker::InvisibleSpellcheck, document->markers().markers()[0]->type());
4555 }
4556 
4557 class TestAccessInitialDocumentWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
4558 public:
TestAccessInitialDocumentWebFrameClient()4559     TestAccessInitialDocumentWebFrameClient() : m_didAccessInitialDocument(false)
4560     {
4561     }
4562 
didAccessInitialDocument(WebLocalFrame * frame)4563     virtual void didAccessInitialDocument(WebLocalFrame* frame)
4564     {
4565         EXPECT_TRUE(!m_didAccessInitialDocument);
4566         m_didAccessInitialDocument = true;
4567     }
4568 
4569     bool m_didAccessInitialDocument;
4570 };
4571 
TEST_F(WebFrameTest,DidAccessInitialDocumentBody)4572 TEST_F(WebFrameTest, DidAccessInitialDocumentBody)
4573 {
4574     // FIXME: Why is this local webViewClient needed instead of the default
4575     // WebViewHelper one? With out it there's some mysterious crash in the
4576     // WebViewHelper destructor.
4577     FrameTestHelpers::TestWebViewClient webViewClient;
4578     TestAccessInitialDocumentWebFrameClient webFrameClient;
4579     FrameTestHelpers::WebViewHelper webViewHelper;
4580     webViewHelper.initialize(true, &webFrameClient, &webViewClient);
4581     runPendingTasks();
4582     EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4583 
4584     // Create another window that will try to access it.
4585     FrameTestHelpers::WebViewHelper newWebViewHelper;
4586     WebView* newView = newWebViewHelper.initialize(true);
4587     newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
4588     runPendingTasks();
4589     EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4590 
4591     // Access the initial document by modifying the body.
4592     newView->mainFrame()->executeScript(
4593         WebScriptSource("window.opener.document.body.innerHTML += 'Modified';"));
4594     runPendingTasks();
4595     EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4596 
4597     // Access the initial document again, to ensure we don't notify twice.
4598     newView->mainFrame()->executeScript(
4599         WebScriptSource("window.opener.document.body.innerHTML += 'Modified';"));
4600     runPendingTasks();
4601     EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4602 }
4603 
TEST_F(WebFrameTest,DidAccessInitialDocumentNavigator)4604 TEST_F(WebFrameTest, DidAccessInitialDocumentNavigator)
4605 {
4606     // FIXME: Why is this local webViewClient needed instead of the default
4607     // WebViewHelper one? With out it there's some mysterious crash in the
4608     // WebViewHelper destructor.
4609     FrameTestHelpers::TestWebViewClient webViewClient;
4610     TestAccessInitialDocumentWebFrameClient webFrameClient;
4611     FrameTestHelpers::WebViewHelper webViewHelper;
4612     webViewHelper.initialize(true, &webFrameClient, &webViewClient);
4613     runPendingTasks();
4614     EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4615 
4616     // Create another window that will try to access it.
4617     FrameTestHelpers::WebViewHelper newWebViewHelper;
4618     WebView* newView = newWebViewHelper.initialize(true);
4619     newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
4620     runPendingTasks();
4621     EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4622 
4623     // Access the initial document to get to the navigator object.
4624     newView->mainFrame()->executeScript(
4625         WebScriptSource("console.log(window.opener.navigator);"));
4626     runPendingTasks();
4627     EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4628 }
4629 
TEST_F(WebFrameTest,DidAccessInitialDocumentViaJavascriptUrl)4630 TEST_F(WebFrameTest, DidAccessInitialDocumentViaJavascriptUrl)
4631 {
4632     TestAccessInitialDocumentWebFrameClient webFrameClient;
4633     FrameTestHelpers::WebViewHelper webViewHelper;
4634     webViewHelper.initialize(true, &webFrameClient);
4635     runPendingTasks();
4636     EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4637 
4638     // Access the initial document from a javascript: URL.
4639     FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.appendChild(document.createTextNode('Modified'))");
4640     EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4641 }
4642 
4643 // Fails on the WebKit XP (deps) bot. http://crbug.com/312192
4644 #if OS(WIN)
TEST_F(WebFrameTest,DISABLED_DidAccessInitialDocumentBodyBeforeModalDialog)4645 TEST_F(WebFrameTest, DISABLED_DidAccessInitialDocumentBodyBeforeModalDialog)
4646 #else
4647 TEST_F(WebFrameTest, DidAccessInitialDocumentBodyBeforeModalDialog)
4648 #endif
4649 {
4650     // FIXME: Why is this local webViewClient needed instead of the default
4651     // WebViewHelper one? With out it there's some mysterious crash in the
4652     // WebViewHelper destructor.
4653     FrameTestHelpers::TestWebViewClient webViewClient;
4654     TestAccessInitialDocumentWebFrameClient webFrameClient;
4655     FrameTestHelpers::WebViewHelper webViewHelper;
4656     webViewHelper.initialize(true, &webFrameClient, &webViewClient);
4657     runPendingTasks();
4658     EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4659 
4660     // Create another window that will try to access it.
4661     FrameTestHelpers::WebViewHelper newWebViewHelper;
4662     WebView* newView = newWebViewHelper.initialize(true);
4663     newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
4664     runPendingTasks();
4665     EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4666 
4667     // Access the initial document by modifying the body. We normally set a
4668     // timer to notify the client.
4669     newView->mainFrame()->executeScript(
4670         WebScriptSource("window.opener.document.body.innerHTML += 'Modified';"));
4671     EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4672 
4673     // Make sure that a modal dialog forces us to notify right away.
4674     newView->mainFrame()->executeScript(
4675         WebScriptSource("window.opener.confirm('Modal');"));
4676     EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4677 
4678     // Ensure that we don't notify again later.
4679     runPendingTasks();
4680     EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4681 }
4682 
4683 // Fails on the WebKit XP (deps) bot. http://crbug.com/312192
4684 #if OS(WIN)
TEST_F(WebFrameTest,DISABLED_DidWriteToInitialDocumentBeforeModalDialog)4685 TEST_F(WebFrameTest, DISABLED_DidWriteToInitialDocumentBeforeModalDialog)
4686 #else
4687 TEST_F(WebFrameTest, DidWriteToInitialDocumentBeforeModalDialog)
4688 #endif
4689 {
4690     // FIXME: Why is this local webViewClient needed instead of the default
4691     // WebViewHelper one? With out it there's some mysterious crash in the
4692     // WebViewHelper destructor.
4693     FrameTestHelpers::TestWebViewClient webViewClient;
4694     TestAccessInitialDocumentWebFrameClient webFrameClient;
4695     FrameTestHelpers::WebViewHelper webViewHelper;
4696     webViewHelper.initialize(true, &webFrameClient, &webViewClient);
4697     runPendingTasks();
4698     EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4699 
4700     // Create another window that will try to access it.
4701     FrameTestHelpers::WebViewHelper newWebViewHelper;
4702     WebView* newView = newWebViewHelper.initialize(true);
4703     newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame());
4704     runPendingTasks();
4705     EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4706 
4707     // Access the initial document with document.write, which moves us past the
4708     // initial empty document state of the state machine. We normally set a
4709     // timer to notify the client.
4710     newView->mainFrame()->executeScript(
4711         WebScriptSource("window.opener.document.write('Modified');"));
4712     EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
4713 
4714     // Make sure that a modal dialog forces us to notify right away.
4715     newView->mainFrame()->executeScript(
4716         WebScriptSource("window.opener.confirm('Modal');"));
4717     EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4718 
4719     // Ensure that we don't notify again later.
4720     runPendingTasks();
4721     EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
4722 }
4723 
4724 class TestMainFrameUserOrProgrammaticScrollFrameClient : public FrameTestHelpers::TestWebFrameClient {
4725 public:
TestMainFrameUserOrProgrammaticScrollFrameClient()4726     TestMainFrameUserOrProgrammaticScrollFrameClient() { reset(); }
reset()4727     void reset()
4728     {
4729         m_didScrollMainFrame = false;
4730         m_wasProgrammaticScroll = false;
4731     }
wasUserScroll() const4732     bool wasUserScroll() const { return m_didScrollMainFrame && !m_wasProgrammaticScroll; }
wasProgrammaticScroll() const4733     bool wasProgrammaticScroll() const { return m_didScrollMainFrame && m_wasProgrammaticScroll; }
4734 
4735     // WebFrameClient:
didChangeScrollOffset(WebLocalFrame * frame)4736     virtual void didChangeScrollOffset(WebLocalFrame* frame) OVERRIDE
4737     {
4738         if (frame->parent())
4739             return;
4740         EXPECT_FALSE(m_didScrollMainFrame);
4741         WebCore::FrameView* view = toWebLocalFrameImpl(frame)->frameView();
4742         // FrameView can be scrolled in FrameView::setFixedVisibleContentRect
4743         // which is called from LocalFrame::createView (before the frame is associated
4744         // with the the view).
4745         if (view) {
4746             m_didScrollMainFrame = true;
4747             m_wasProgrammaticScroll = view->inProgrammaticScroll();
4748         }
4749     }
4750 private:
4751     bool m_didScrollMainFrame;
4752     bool m_wasProgrammaticScroll;
4753 };
4754 
TEST_F(WebFrameTest,CompositorScrollIsUserScrollLongPage)4755 TEST_F(WebFrameTest, CompositorScrollIsUserScrollLongPage)
4756 {
4757     registerMockedHttpURLLoad("long_scroll.html");
4758     TestMainFrameUserOrProgrammaticScrollFrameClient client;
4759 
4760     // Make sure we initialize to minimum scale, even if the window size
4761     // only becomes available after the load begins.
4762     FrameTestHelpers::WebViewHelper webViewHelper;
4763     webViewHelper.initializeAndLoad(m_baseURL + "long_scroll.html", true, &client);
4764     webViewHelper.webView()->resize(WebSize(1000, 1000));
4765     webViewHelper.webView()->layout();
4766 
4767     EXPECT_FALSE(client.wasUserScroll());
4768     EXPECT_FALSE(client.wasProgrammaticScroll());
4769 
4770     // Do a compositor scroll, verify that this is counted as a user scroll.
4771     webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(0, 1), 1.1f);
4772     EXPECT_TRUE(client.wasUserScroll());
4773     client.reset();
4774 
4775     EXPECT_FALSE(client.wasUserScroll());
4776     EXPECT_FALSE(client.wasProgrammaticScroll());
4777 
4778     // The page scale 1.0f and scroll.
4779     webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(0, 1), 1.0f);
4780     EXPECT_TRUE(client.wasUserScroll());
4781     client.reset();
4782 
4783     // No scroll event if there is no scroll delta.
4784     webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.0f);
4785     EXPECT_FALSE(client.wasUserScroll());
4786     EXPECT_FALSE(client.wasProgrammaticScroll());
4787     client.reset();
4788 
4789     // Non zero page scale and scroll.
4790     webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(9, 13), 0.6f);
4791     EXPECT_TRUE(client.wasUserScroll());
4792     client.reset();
4793 
4794     // Programmatic scroll.
4795     WebLocalFrameImpl* frameImpl = webViewHelper.webViewImpl()->mainFrameImpl();
4796     frameImpl->executeScript(WebScriptSource("window.scrollTo(0, 20);"));
4797     EXPECT_FALSE(client.wasUserScroll());
4798     EXPECT_TRUE(client.wasProgrammaticScroll());
4799     client.reset();
4800 
4801     // Programmatic scroll to same offset. No scroll event should be generated.
4802     frameImpl->executeScript(WebScriptSource("window.scrollTo(0, 20);"));
4803     EXPECT_FALSE(client.wasProgrammaticScroll());
4804     EXPECT_FALSE(client.wasUserScroll());
4805     client.reset();
4806 }
4807 
TEST_F(WebFrameTest,CompositorScrollIsUserScrollShortPage)4808 TEST_F(WebFrameTest, CompositorScrollIsUserScrollShortPage)
4809 {
4810     registerMockedHttpURLLoad("short_scroll.html");
4811 
4812     TestMainFrameUserOrProgrammaticScrollFrameClient client;
4813 
4814     // Short page tests.
4815     FrameTestHelpers::WebViewHelper webViewHelper;
4816     webViewHelper.initializeAndLoad(m_baseURL + "short_scroll.html", true, &client);
4817 
4818     webViewHelper.webView()->resize(WebSize(1000, 1000));
4819     webViewHelper.webView()->layout();
4820 
4821     EXPECT_FALSE(client.wasUserScroll());
4822     EXPECT_FALSE(client.wasProgrammaticScroll());
4823 
4824     // Non zero page scale and scroll.
4825     webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(9, 13), 2.0f);
4826     EXPECT_FALSE(client.wasProgrammaticScroll());
4827     EXPECT_TRUE(client.wasUserScroll());
4828     client.reset();
4829 }
4830 
TEST_F(WebFrameTest,FirstPartyForCookiesForRedirect)4831 TEST_F(WebFrameTest, FirstPartyForCookiesForRedirect)
4832 {
4833     WTF::String filePath = Platform::current()->unitTestSupport()->webKitRootDir();
4834     filePath.append("/Source/web/tests/data/first_party.html");
4835 
4836     WebURL testURL(toKURL("http://www.test.com/first_party_redirect.html"));
4837     char redirect[] = "http://www.test.com/first_party.html";
4838     WebURL redirectURL(toKURL(redirect));
4839     WebURLResponse redirectResponse;
4840     redirectResponse.initialize();
4841     redirectResponse.setMIMEType("text/html");
4842     redirectResponse.setHTTPStatusCode(302);
4843     redirectResponse.setHTTPHeaderField("Location", redirect);
4844     Platform::current()->unitTestSupport()->registerMockedURL(testURL, redirectResponse, filePath);
4845 
4846     WebURLResponse finalResponse;
4847     finalResponse.initialize();
4848     finalResponse.setMIMEType("text/html");
4849     Platform::current()->unitTestSupport()->registerMockedURL(redirectURL, finalResponse, filePath);
4850 
4851     FrameTestHelpers::WebViewHelper webViewHelper;
4852     webViewHelper.initializeAndLoad(m_baseURL + "first_party_redirect.html", true);
4853     EXPECT_TRUE(webViewHelper.webView()->mainFrame()->document().firstPartyForCookies() == redirectURL);
4854 }
4855 
4856 class TestNavigationPolicyWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
4857 public:
4858 
didNavigateWithinPage(WebLocalFrame *,const WebHistoryItem &,WebHistoryCommitType)4859     virtual void didNavigateWithinPage(WebLocalFrame*, const WebHistoryItem&, WebHistoryCommitType) OVERRIDE
4860     {
4861         EXPECT_TRUE(false);
4862     }
4863 };
4864 
TEST_F(WebFrameTest,SimulateFragmentAnchorMiddleClick)4865 TEST_F(WebFrameTest, SimulateFragmentAnchorMiddleClick)
4866 {
4867     registerMockedHttpURLLoad("fragment_middle_click.html");
4868     TestNavigationPolicyWebFrameClient client;
4869     FrameTestHelpers::WebViewHelper webViewHelper;
4870     webViewHelper.initializeAndLoad(m_baseURL + "fragment_middle_click.html", true, &client);
4871 
4872     WebCore::Document* document = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document();
4873     WebCore::KURL destination = document->url();
4874     destination.setFragmentIdentifier("test");
4875 
4876     RefPtrWillBeRawPtr<WebCore::Event> event = WebCore::MouseEvent::create(WebCore::EventTypeNames::click, false, false,
4877         document->domWindow(), 0, 0, 0, 0, 0, 0, 0, false, false, false, false, 1, nullptr, nullptr);
4878     WebCore::FrameLoadRequest frameRequest(document, WebCore::ResourceRequest(destination));
4879     frameRequest.setTriggeringEvent(event);
4880     toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->loader().load(frameRequest);
4881 }
4882 
4883 class TestNewWindowWebViewClient : public FrameTestHelpers::TestWebViewClient {
4884 public:
createView(WebLocalFrame *,const WebURLRequest &,const WebWindowFeatures &,const WebString &,WebNavigationPolicy,bool)4885     virtual WebView* createView(WebLocalFrame*, const WebURLRequest&, const WebWindowFeatures&,
4886         const WebString&, WebNavigationPolicy, bool) OVERRIDE
4887     {
4888         EXPECT_TRUE(false);
4889         return 0;
4890     }
4891 };
4892 
4893 class TestNewWindowWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
4894 public:
TestNewWindowWebFrameClient()4895     TestNewWindowWebFrameClient()
4896         : m_decidePolicyCallCount(0)
4897     {
4898     }
4899 
decidePolicyForNavigation(WebLocalFrame *,WebDataSource::ExtraData *,const WebURLRequest &,WebNavigationType,WebNavigationPolicy policy,bool)4900     virtual WebNavigationPolicy decidePolicyForNavigation(WebLocalFrame*, WebDataSource::ExtraData*, const WebURLRequest&,
4901         WebNavigationType, WebNavigationPolicy policy, bool) OVERRIDE
4902     {
4903         m_decidePolicyCallCount++;
4904         return policy;
4905     }
4906 
decidePolicyCallCount() const4907     int decidePolicyCallCount() const { return m_decidePolicyCallCount; }
4908 
4909 private:
4910     int m_decidePolicyCallCount;
4911 };
4912 
TEST_F(WebFrameTest,ModifiedClickNewWindow)4913 TEST_F(WebFrameTest, ModifiedClickNewWindow)
4914 {
4915     registerMockedHttpURLLoad("ctrl_click.html");
4916     registerMockedHttpURLLoad("hello_world.html");
4917     TestNewWindowWebViewClient webViewClient;
4918     TestNewWindowWebFrameClient webFrameClient;
4919     FrameTestHelpers::WebViewHelper webViewHelper;
4920     webViewHelper.initializeAndLoad(m_baseURL + "ctrl_click.html", true, &webFrameClient, &webViewClient);
4921 
4922     WebCore::Document* document = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document();
4923     WebCore::KURL destination = toKURL(m_baseURL + "hello_world.html");
4924 
4925     // ctrl+click event
4926     RefPtrWillBeRawPtr<WebCore::Event> event = WebCore::MouseEvent::create(WebCore::EventTypeNames::click, false, false,
4927         document->domWindow(), 0, 0, 0, 0, 0, 0, 0, true, false, false, false, 0, nullptr, nullptr);
4928     WebCore::FrameLoadRequest frameRequest(document, WebCore::ResourceRequest(destination));
4929     frameRequest.setTriggeringEvent(event);
4930     WebCore::UserGestureIndicator gesture(WebCore::DefinitelyProcessingUserGesture);
4931     toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->loader().load(frameRequest);
4932     FrameTestHelpers::pumpPendingRequestsDoNotUse(webViewHelper.webView()->mainFrame());
4933 
4934     // decidePolicyForNavigation should be called both for the original request and the ctrl+click.
4935     EXPECT_EQ(2, webFrameClient.decidePolicyCallCount());
4936 }
4937 
TEST_F(WebFrameTest,BackToReload)4938 TEST_F(WebFrameTest, BackToReload)
4939 {
4940     registerMockedHttpURLLoad("fragment_middle_click.html");
4941     FrameTestHelpers::WebViewHelper webViewHelper;
4942     webViewHelper.initializeAndLoad(m_baseURL + "fragment_middle_click.html", true);
4943     WebFrame* frame = webViewHelper.webView()->mainFrame();
4944     const WebCore::FrameLoader& mainFrameLoader = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->loader();
4945     RefPtr<WebCore::HistoryItem> firstItem = mainFrameLoader.currentItem();
4946     EXPECT_TRUE(firstItem);
4947 
4948     registerMockedHttpURLLoad("white-1x1.png");
4949     FrameTestHelpers::loadFrame(frame, m_baseURL + "white-1x1.png");
4950     EXPECT_NE(firstItem.get(), mainFrameLoader.currentItem());
4951 
4952     FrameTestHelpers::loadHistoryItem(frame, WebHistoryItem(firstItem.get()), WebHistoryDifferentDocumentLoad, WebURLRequest::UseProtocolCachePolicy);
4953     EXPECT_EQ(firstItem.get(), mainFrameLoader.currentItem());
4954 
4955     FrameTestHelpers::reloadFrame(frame);
4956     EXPECT_EQ(WebURLRequest::ReloadIgnoringCacheData, frame->dataSource()->request().cachePolicy());
4957 }
4958 
TEST_F(WebFrameTest,BackDuringChildFrameReload)4959 TEST_F(WebFrameTest, BackDuringChildFrameReload)
4960 {
4961     registerMockedHttpURLLoad("page_with_blank_iframe.html");
4962     FrameTestHelpers::WebViewHelper webViewHelper;
4963     webViewHelper.initializeAndLoad(m_baseURL + "page_with_blank_iframe.html", true);
4964     WebFrame* mainFrame = webViewHelper.webView()->mainFrame();
4965     const WebCore::FrameLoader& mainFrameLoader = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->loader();
4966     WebFrame* childFrame = mainFrame->firstChild();
4967     ASSERT_TRUE(childFrame);
4968 
4969     // Start a history navigation, then have a different frame commit a navigation.
4970     // In this case, reload an about:blank frame, which will commit synchronously.
4971     // After the history navigation completes, both the appropriate document url and
4972     // the current history item should reflect the history navigation.
4973     registerMockedHttpURLLoad("white-1x1.png");
4974     WebHistoryItem item;
4975     item.initialize();
4976     WebURL historyURL(toKURL(m_baseURL + "white-1x1.png"));
4977     item.setURLString(historyURL.string());
4978     mainFrame->loadHistoryItem(item, WebHistoryDifferentDocumentLoad, WebURLRequest::UseProtocolCachePolicy);
4979 
4980     FrameTestHelpers::reloadFrame(childFrame);
4981     EXPECT_EQ(item.urlString(), mainFrame->document().url().string());
4982     EXPECT_EQ(item.urlString(), WebString(mainFrameLoader.currentItem()->urlString()));
4983 }
4984 
TEST_F(WebFrameTest,ReloadPost)4985 TEST_F(WebFrameTest, ReloadPost)
4986 {
4987     registerMockedHttpURLLoad("reload_post.html");
4988     FrameTestHelpers::WebViewHelper webViewHelper;
4989     webViewHelper.initializeAndLoad(m_baseURL + "reload_post.html", true);
4990     WebFrame* frame = webViewHelper.webView()->mainFrame();
4991 
4992     FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.forms[0].submit()");
4993     // Pump requests one more time after the javascript URL has executed to
4994     // trigger the actual POST load request.
4995     FrameTestHelpers::pumpPendingRequestsDoNotUse(webViewHelper.webView()->mainFrame());
4996     EXPECT_EQ(WebString::fromUTF8("POST"), frame->dataSource()->request().httpMethod());
4997 
4998     FrameTestHelpers::reloadFrame(frame);
4999     EXPECT_EQ(WebURLRequest::ReloadIgnoringCacheData, frame->dataSource()->request().cachePolicy());
5000     EXPECT_EQ(WebNavigationTypeFormResubmitted, frame->dataSource()->navigationType());
5001 }
5002 
TEST_F(WebFrameTest,LoadHistoryItemReload)5003 TEST_F(WebFrameTest, LoadHistoryItemReload)
5004 {
5005     registerMockedHttpURLLoad("fragment_middle_click.html");
5006     FrameTestHelpers::WebViewHelper webViewHelper;
5007     webViewHelper.initializeAndLoad(m_baseURL + "fragment_middle_click.html", true);
5008     WebFrame* frame = webViewHelper.webView()->mainFrame();
5009     const WebCore::FrameLoader& mainFrameLoader = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->loader();
5010     RefPtr<WebCore::HistoryItem> firstItem = mainFrameLoader.currentItem();
5011     EXPECT_TRUE(firstItem);
5012 
5013     registerMockedHttpURLLoad("white-1x1.png");
5014     FrameTestHelpers::loadFrame(frame, m_baseURL + "white-1x1.png");
5015     EXPECT_NE(firstItem.get(), mainFrameLoader.currentItem());
5016 
5017     // Cache policy overrides should take.
5018     FrameTestHelpers::loadHistoryItem(frame, WebHistoryItem(firstItem), WebHistoryDifferentDocumentLoad, WebURLRequest::ReloadIgnoringCacheData);
5019     EXPECT_EQ(firstItem.get(), mainFrameLoader.currentItem());
5020     EXPECT_EQ(WebURLRequest::ReloadIgnoringCacheData, frame->dataSource()->request().cachePolicy());
5021 }
5022 
5023 
5024 class TestCachePolicyWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5025 public:
TestCachePolicyWebFrameClient(TestCachePolicyWebFrameClient * parentClient)5026     explicit TestCachePolicyWebFrameClient(TestCachePolicyWebFrameClient* parentClient)
5027         : m_parentClient(parentClient)
5028         , m_policy(WebURLRequest::UseProtocolCachePolicy)
5029         , m_childClient(0)
5030         , m_willSendRequestCallCount(0)
5031         , m_childFrameCreationCount(0)
5032     {
5033     }
5034 
setChildWebFrameClient(TestCachePolicyWebFrameClient * client)5035     void setChildWebFrameClient(TestCachePolicyWebFrameClient* client) { m_childClient = client; }
cachePolicy() const5036     WebURLRequest::CachePolicy cachePolicy() const { return m_policy; }
willSendRequestCallCount() const5037     int willSendRequestCallCount() const { return m_willSendRequestCallCount; }
childFrameCreationCount() const5038     int childFrameCreationCount() const { return m_childFrameCreationCount; }
5039 
createChildFrame(WebLocalFrame * parent,const WebString &)5040     virtual WebFrame* createChildFrame(WebLocalFrame* parent, const WebString&)
5041     {
5042         ASSERT(m_childClient);
5043         m_childFrameCreationCount++;
5044         WebFrame* frame = WebLocalFrame::create(m_childClient);
5045         parent->appendChild(frame);
5046         return frame;
5047     }
5048 
didStartLoading(bool toDifferentDocument)5049     virtual void didStartLoading(bool toDifferentDocument)
5050     {
5051         if (m_parentClient) {
5052             m_parentClient->didStartLoading(toDifferentDocument);
5053             return;
5054         }
5055         TestWebFrameClient::didStartLoading(toDifferentDocument);
5056     }
5057 
didStopLoading()5058     virtual void didStopLoading()
5059     {
5060         if (m_parentClient) {
5061             m_parentClient->didStopLoading();
5062             return;
5063         }
5064         TestWebFrameClient::didStopLoading();
5065     }
5066 
willSendRequest(WebLocalFrame * frame,unsigned,WebURLRequest & request,const WebURLResponse &)5067     virtual void willSendRequest(WebLocalFrame* frame, unsigned, WebURLRequest& request, const WebURLResponse&) OVERRIDE
5068     {
5069         m_policy = request.cachePolicy();
5070         m_willSendRequestCallCount++;
5071     }
5072 
5073 private:
5074     TestCachePolicyWebFrameClient* m_parentClient;
5075 
5076     WebURLRequest::CachePolicy m_policy;
5077     TestCachePolicyWebFrameClient* m_childClient;
5078     int m_willSendRequestCallCount;
5079     int m_childFrameCreationCount;
5080 };
5081 
TEST_F(WebFrameTest,ReloadIframe)5082 TEST_F(WebFrameTest, ReloadIframe)
5083 {
5084     registerMockedHttpURLLoad("iframe_reload.html");
5085     registerMockedHttpURLLoad("visible_iframe.html");
5086     TestCachePolicyWebFrameClient mainClient(0);
5087     TestCachePolicyWebFrameClient childClient(&mainClient);
5088     mainClient.setChildWebFrameClient(&childClient);
5089 
5090     FrameTestHelpers::WebViewHelper webViewHelper;
5091     webViewHelper.initializeAndLoad(m_baseURL + "iframe_reload.html", true, &mainClient);
5092 
5093     WebLocalFrameImpl* mainFrame = webViewHelper.webViewImpl()->mainFrameImpl();
5094     RefPtr<WebLocalFrameImpl> childFrame = toWebLocalFrameImpl(mainFrame->firstChild());
5095     ASSERT_EQ(childFrame->client(), &childClient);
5096     EXPECT_EQ(mainClient.childFrameCreationCount(), 1);
5097     EXPECT_EQ(childClient.willSendRequestCallCount(), 1);
5098     EXPECT_EQ(childClient.cachePolicy(), WebURLRequest::UseProtocolCachePolicy);
5099 
5100     FrameTestHelpers::reloadFrame(mainFrame);
5101 
5102     // A new WebFrame should have been created, but the child WebFrameClient should be reused.
5103     ASSERT_NE(childFrame, toWebLocalFrameImpl(mainFrame->firstChild()));
5104     ASSERT_EQ(toWebLocalFrameImpl(mainFrame->firstChild())->client(), &childClient);
5105 
5106     EXPECT_EQ(mainClient.childFrameCreationCount(), 2);
5107     EXPECT_EQ(childClient.willSendRequestCallCount(), 2);
5108     EXPECT_EQ(childClient.cachePolicy(), WebURLRequest::ReloadIgnoringCacheData);
5109 }
5110 
5111 class TestSameDocumentWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5112 public:
TestSameDocumentWebFrameClient()5113     TestSameDocumentWebFrameClient()
5114         : m_frameLoadTypeSameSeen(false)
5115     {
5116     }
5117 
willSendRequest(WebLocalFrame * frame,unsigned,WebURLRequest &,const WebURLResponse &)5118     virtual void willSendRequest(WebLocalFrame* frame, unsigned, WebURLRequest&, const WebURLResponse&)
5119     {
5120         if (toWebLocalFrameImpl(frame)->frame()->loader().loadType() == WebCore::FrameLoadTypeSame)
5121             m_frameLoadTypeSameSeen = true;
5122     }
5123 
frameLoadTypeSameSeen() const5124     bool frameLoadTypeSameSeen() const { return m_frameLoadTypeSameSeen; }
5125 
5126 private:
5127     bool m_frameLoadTypeSameSeen;
5128 };
5129 
TEST_F(WebFrameTest,NavigateToSame)5130 TEST_F(WebFrameTest, NavigateToSame)
5131 {
5132     registerMockedHttpURLLoad("navigate_to_same.html");
5133     TestSameDocumentWebFrameClient client;
5134     FrameTestHelpers::WebViewHelper webViewHelper;
5135     webViewHelper.initializeAndLoad(m_baseURL + "navigate_to_same.html", true, &client);
5136     EXPECT_FALSE(client.frameLoadTypeSameSeen());
5137 
5138     WebCore::FrameLoadRequest frameRequest(0, WebCore::ResourceRequest(toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->document()->url()));
5139     toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame())->loader().load(frameRequest);
5140     FrameTestHelpers::pumpPendingRequestsDoNotUse(webViewHelper.webView()->mainFrame());
5141 
5142     EXPECT_TRUE(client.frameLoadTypeSameSeen());
5143 }
5144 
TEST_F(WebFrameTest,WebNodeImageContents)5145 TEST_F(WebFrameTest, WebNodeImageContents)
5146 {
5147     FrameTestHelpers::WebViewHelper webViewHelper;
5148     webViewHelper.initializeAndLoad("about:blank", true);
5149     WebFrame* frame = webViewHelper.webView()->mainFrame();
5150 
5151     static const char bluePNG[] = "<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAGElEQVQYV2NkYPj/n4EIwDiqEF8oUT94AFIQE/cCn90IAAAAAElFTkSuQmCC\">";
5152 
5153     // Load up the image and test that we can extract the contents.
5154     WebCore::KURL testURL = toKURL("about:blank");
5155     FrameTestHelpers::loadHTMLString(frame, bluePNG, testURL);
5156 
5157     WebNode node = frame->document().body().firstChild();
5158     EXPECT_TRUE(node.isElementNode());
5159     WebElement element = node.to<WebElement>();
5160     WebImage image = element.imageContents();
5161     ASSERT_FALSE(image.isNull());
5162     EXPECT_EQ(image.size().width, 10);
5163     EXPECT_EQ(image.size().height, 10);
5164 //    FIXME: The rest of this test is disabled since the ImageDecodeCache state may be inconsistent when this test runs.
5165 //    crbug.com/266088
5166 //    SkBitmap bitmap = image.getSkBitmap();
5167 //    SkAutoLockPixels locker(bitmap);
5168 //    EXPECT_EQ(bitmap.getColor(0, 0), SK_ColorBLUE);
5169 }
5170 
5171 class TestStartStopCallbackWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5172 public:
TestStartStopCallbackWebFrameClient()5173     TestStartStopCallbackWebFrameClient()
5174         : m_startLoadingCount(0)
5175         , m_stopLoadingCount(0)
5176         , m_differentDocumentStartCount(0)
5177     {
5178     }
5179 
didStartLoading(bool toDifferentDocument)5180     virtual void didStartLoading(bool toDifferentDocument) OVERRIDE
5181     {
5182         TestWebFrameClient::didStartLoading(toDifferentDocument);
5183         m_startLoadingCount++;
5184         if (toDifferentDocument)
5185             m_differentDocumentStartCount++;
5186     }
5187 
didStopLoading()5188     virtual void didStopLoading() OVERRIDE
5189     {
5190         TestWebFrameClient::didStopLoading();
5191         m_stopLoadingCount++;
5192     }
5193 
startLoadingCount() const5194     int startLoadingCount() const { return m_startLoadingCount; }
stopLoadingCount() const5195     int stopLoadingCount() const { return m_stopLoadingCount; }
differentDocumentStartCount() const5196     int differentDocumentStartCount() const { return m_differentDocumentStartCount; }
5197 
5198 private:
5199     int m_startLoadingCount;
5200     int m_stopLoadingCount;
5201     int m_differentDocumentStartCount;
5202 };
5203 
TEST_F(WebFrameTest,PushStateStartsAndStops)5204 TEST_F(WebFrameTest, PushStateStartsAndStops)
5205 {
5206     registerMockedHttpURLLoad("push_state.html");
5207     TestStartStopCallbackWebFrameClient client;
5208     FrameTestHelpers::WebViewHelper webViewHelper;
5209     webViewHelper.initializeAndLoad(m_baseURL + "push_state.html", true, &client);
5210 
5211     EXPECT_EQ(client.startLoadingCount(), 2);
5212     EXPECT_EQ(client.stopLoadingCount(), 2);
5213     EXPECT_EQ(client.differentDocumentStartCount(), 1);
5214 }
5215 
5216 class TestDidNavigateCommitTypeWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5217 public:
TestDidNavigateCommitTypeWebFrameClient()5218     TestDidNavigateCommitTypeWebFrameClient()
5219         : m_lastCommitType(WebHistoryInertCommit)
5220     {
5221     }
5222 
didNavigateWithinPage(WebLocalFrame *,const WebHistoryItem &,WebHistoryCommitType type)5223     virtual void didNavigateWithinPage(WebLocalFrame*, const WebHistoryItem&, WebHistoryCommitType type) OVERRIDE
5224     {
5225         m_lastCommitType = type;
5226     }
5227 
lastCommitType() const5228     WebHistoryCommitType lastCommitType() const { return m_lastCommitType; }
5229 
5230 private:
5231     WebHistoryCommitType m_lastCommitType;
5232 };
5233 
TEST_F(WebFrameTest,SameDocumentHistoryNavigationCommitType)5234 TEST_F(WebFrameTest, SameDocumentHistoryNavigationCommitType)
5235 {
5236     registerMockedHttpURLLoad("push_state.html");
5237     TestDidNavigateCommitTypeWebFrameClient client;
5238     FrameTestHelpers::WebViewHelper webViewHelper;
5239     WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "push_state.html", true, &client);
5240     RefPtr<WebCore::HistoryItem> item = toLocalFrame(webViewImpl->page()->mainFrame())->loader().currentItem();
5241     runPendingTasks();
5242 
5243     toLocalFrame(webViewImpl->page()->mainFrame())->loader().loadHistoryItem(item.get(), WebCore::HistorySameDocumentLoad);
5244     EXPECT_EQ(WebBackForwardCommit, client.lastCommitType());
5245 }
5246 
5247 class TestHistoryWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5248 public:
TestHistoryWebFrameClient()5249     TestHistoryWebFrameClient()
5250     {
5251         m_replacesCurrentHistoryItem = false;
5252         m_frame = 0;
5253     }
didStartProvisionalLoad(WebLocalFrame * frame)5254     void didStartProvisionalLoad(WebLocalFrame* frame)
5255     {
5256         WebDataSource* ds = frame->provisionalDataSource();
5257         m_replacesCurrentHistoryItem = ds->replacesCurrentHistoryItem();
5258         m_frame = frame;
5259     }
5260 
replacesCurrentHistoryItem()5261     bool replacesCurrentHistoryItem() { return m_replacesCurrentHistoryItem; }
frame()5262     WebFrame* frame() { return m_frame; }
5263 
5264 private:
5265     bool m_replacesCurrentHistoryItem;
5266     WebFrame* m_frame;
5267 };
5268 
5269 // Test which ensures that the first navigation in a subframe will always
5270 // result in history entry being replaced and not a new one added.
TEST_F(WebFrameTest,DISABLED_FirstFrameNavigationReplacesHistory)5271 TEST_F(WebFrameTest, DISABLED_FirstFrameNavigationReplacesHistory)
5272 {
5273     registerMockedHttpURLLoad("history.html");
5274     registerMockedHttpURLLoad("find.html");
5275 
5276     FrameTestHelpers::WebViewHelper webViewHelper;
5277     TestHistoryWebFrameClient client;
5278     webViewHelper.initializeAndLoad("about:blank", true, &client);
5279     EXPECT_TRUE(client.replacesCurrentHistoryItem());
5280 
5281     WebFrame* frame = webViewHelper.webView()->mainFrame();
5282 
5283     FrameTestHelpers::loadFrame(frame,
5284         "javascript:document.body.appendChild(document.createElement('iframe'))");
5285     WebFrame* iframe = frame->firstChild();
5286     EXPECT_EQ(client.frame(), iframe);
5287     EXPECT_TRUE(client.replacesCurrentHistoryItem());
5288 
5289     FrameTestHelpers::loadFrame(frame,
5290         "javascript:window.frames[0].location.assign('" + m_baseURL + "history.html')");
5291     EXPECT_EQ(client.frame(), iframe);
5292     EXPECT_TRUE(client.replacesCurrentHistoryItem());
5293 
5294     FrameTestHelpers::loadFrame(frame,
5295         "javascript:window.frames[0].location.assign('" + m_baseURL + "find.html')");
5296     EXPECT_EQ(client.frame(), iframe);
5297     EXPECT_FALSE(client.replacesCurrentHistoryItem());
5298 
5299     // Repeat the test, but start out the iframe with initial URL, which is not
5300     // "about:blank".
5301     FrameTestHelpers::loadFrame(frame,
5302         "javascript:var f = document.createElement('iframe'); "
5303         "f.src = '" + m_baseURL + "history.html';"
5304         "document.body.appendChild(f)");
5305 
5306     iframe = frame->firstChild()->nextSibling();
5307     EXPECT_EQ(client.frame(), iframe);
5308     EXPECT_TRUE(client.replacesCurrentHistoryItem());
5309 
5310     FrameTestHelpers::loadFrame(frame,
5311         "javascript:window.frames[1].location.assign('" + m_baseURL + "find.html')");
5312     EXPECT_EQ(client.frame(), iframe);
5313     EXPECT_FALSE(client.replacesCurrentHistoryItem());
5314 }
5315 
5316 // Test verifies that layout will change a layer's scrollable attibutes
TEST_F(WebFrameTest,overflowHiddenRewrite)5317 TEST_F(WebFrameTest, overflowHiddenRewrite)
5318 {
5319     registerMockedHttpURLLoad("non-scrollable.html");
5320     TestMainFrameUserOrProgrammaticScrollFrameClient client;
5321     OwnPtr<FakeCompositingWebViewClient> fakeCompositingWebViewClient = adoptPtr(new FakeCompositingWebViewClient());
5322     FrameTestHelpers::WebViewHelper webViewHelper;
5323     webViewHelper.initialize(true, 0, fakeCompositingWebViewClient.get(), &configueCompositingWebView);
5324 
5325     webViewHelper.webView()->resize(WebSize(100, 100));
5326     FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "non-scrollable.html");
5327 
5328     WebCore::RenderLayerCompositor* compositor =  webViewHelper.webViewImpl()->compositor();
5329     ASSERT_TRUE(compositor->scrollLayer());
5330 
5331     // Verify that the WebLayer is not scrollable initially.
5332     WebCore::GraphicsLayer* scrollLayer = compositor->scrollLayer();
5333     WebLayer* webScrollLayer = scrollLayer->platformLayer();
5334     ASSERT_FALSE(webScrollLayer->userScrollableHorizontal());
5335     ASSERT_FALSE(webScrollLayer->userScrollableVertical());
5336 
5337     // Call javascript to make the layer scrollable, and verify it.
5338     WebLocalFrameImpl* frame = (WebLocalFrameImpl*)webViewHelper.webView()->mainFrame();
5339     frame->executeScript(WebScriptSource("allowScroll();"));
5340     webViewHelper.webView()->layout();
5341     ASSERT_TRUE(webScrollLayer->userScrollableHorizontal());
5342     ASSERT_TRUE(webScrollLayer->userScrollableVertical());
5343 }
5344 
5345 // Test that currentHistoryItem reflects the current page, not the provisional load.
TEST_F(WebFrameTest,CurrentHistoryItem)5346 TEST_F(WebFrameTest, CurrentHistoryItem)
5347 {
5348     registerMockedHttpURLLoad("fixed_layout.html");
5349     std::string url = m_baseURL + "fixed_layout.html";
5350 
5351     FrameTestHelpers::WebViewHelper webViewHelper;
5352     webViewHelper.initialize();
5353     WebFrame* frame = webViewHelper.webView()->mainFrame();
5354     const WebCore::FrameLoader& mainFrameLoader = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->loader();
5355     WebURLRequest request;
5356     request.initialize();
5357     request.setURL(toKURL(url));
5358     frame->loadRequest(request);
5359 
5360     // Before commit, there is no history item.
5361     EXPECT_FALSE(mainFrameLoader.currentItem());
5362 
5363     FrameTestHelpers::pumpPendingRequestsDoNotUse(frame);
5364 
5365     // After commit, there is.
5366     WebCore::HistoryItem* item = mainFrameLoader.currentItem();
5367     ASSERT_TRUE(item);
5368     EXPECT_EQ(WTF::String(url.data()), item->urlString());
5369 }
5370 
5371 class FailCreateChildFrame : public FrameTestHelpers::TestWebFrameClient {
5372 public:
FailCreateChildFrame()5373     FailCreateChildFrame() : m_callCount(0) { }
5374 
createChildFrame(WebLocalFrame * parent,const WebString & frameName)5375     virtual WebFrame* createChildFrame(WebLocalFrame* parent, const WebString& frameName) OVERRIDE
5376     {
5377         ++m_callCount;
5378         return 0;
5379     }
5380 
callCount() const5381     int callCount() const { return m_callCount; }
5382 
5383 private:
5384     int m_callCount;
5385 };
5386 
5387 // Test that we don't crash if WebFrameClient::createChildFrame() fails.
TEST_F(WebFrameTest,CreateChildFrameFailure)5388 TEST_F(WebFrameTest, CreateChildFrameFailure)
5389 {
5390     registerMockedHttpURLLoad("create_child_frame_fail.html");
5391     FailCreateChildFrame client;
5392     FrameTestHelpers::WebViewHelper webViewHelper;
5393     webViewHelper.initializeAndLoad(m_baseURL + "create_child_frame_fail.html", true, &client);
5394 
5395     EXPECT_EQ(1, client.callCount());
5396 }
5397 
TEST_F(WebFrameTest,fixedPositionInFixedViewport)5398 TEST_F(WebFrameTest, fixedPositionInFixedViewport)
5399 {
5400     UseMockScrollbarSettings mockScrollbarSettings;
5401     registerMockedHttpURLLoad("fixed-position-in-fixed-viewport.html");
5402     FrameTestHelpers::WebViewHelper webViewHelper;
5403     webViewHelper.initializeAndLoad(m_baseURL + "fixed-position-in-fixed-viewport.html", true, 0, 0, enableViewportSettings);
5404 
5405     WebView* webView = webViewHelper.webView();
5406     webView->resize(WebSize(100, 100));
5407     webView->layout();
5408 
5409     Document* document = toWebLocalFrameImpl(webView->mainFrame())->frame()->document();
5410     Element* bottomFixed = document->getElementById("bottom-fixed");
5411     Element* topBottomFixed = document->getElementById("top-bottom-fixed");
5412     Element* rightFixed = document->getElementById("right-fixed");
5413     Element* leftRightFixed = document->getElementById("left-right-fixed");
5414 
5415     webView->resize(WebSize(100, 200));
5416     webView->layout();
5417     EXPECT_EQ(200, bottomFixed->offsetTop() + bottomFixed->offsetHeight());
5418     EXPECT_EQ(200, topBottomFixed->offsetHeight());
5419 
5420     webView->settings()->setMainFrameResizesAreOrientationChanges(false);
5421     webView->resize(WebSize(200, 200));
5422     webView->layout();
5423     EXPECT_EQ(200, rightFixed->offsetLeft() + rightFixed->offsetWidth());
5424     EXPECT_EQ(200, leftRightFixed->offsetWidth());
5425 
5426     webView->settings()->setMainFrameResizesAreOrientationChanges(true);
5427     // Will scale the page by 1.5.
5428     webView->resize(WebSize(300, 330));
5429     webView->layout();
5430     EXPECT_EQ(220, bottomFixed->offsetTop() + bottomFixed->offsetHeight());
5431     EXPECT_EQ(220, topBottomFixed->offsetHeight());
5432     EXPECT_EQ(200, rightFixed->offsetLeft() + rightFixed->offsetWidth());
5433     EXPECT_EQ(200, leftRightFixed->offsetWidth());
5434 }
5435 
TEST_F(WebFrameTest,FrameViewSetFrameRect)5436 TEST_F(WebFrameTest, FrameViewSetFrameRect)
5437 {
5438     FrameTestHelpers::WebViewHelper webViewHelper;
5439     webViewHelper.initializeAndLoad("about:blank");
5440 
5441     WebCore::FrameView* frameView = webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
5442     frameView->setFrameRect(WebCore::IntRect(0, 0, 200, 200));
5443     EXPECT_EQ_RECT(WebCore::IntRect(0, 0, 200, 200), frameView->frameRect());
5444     frameView->setFrameRect(WebCore::IntRect(100, 100, 200, 200));
5445     EXPECT_EQ_RECT(WebCore::IntRect(100, 100, 200, 200), frameView->frameRect());
5446 }
5447 
TEST_F(WebFrameTest,FullscreenLayerNonScrollable)5448 TEST_F(WebFrameTest, FullscreenLayerNonScrollable)
5449 {
5450     FakeCompositingWebViewClient client;
5451     registerMockedHttpURLLoad("fullscreen_div.html");
5452     FrameTestHelpers::WebViewHelper webViewHelper;
5453     int viewportWidth = 640;
5454     int viewportHeight = 480;
5455     WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "fullscreen_div.html", true, 0, &client, &configueCompositingWebView);
5456     webViewImpl->resize(WebSize(viewportWidth, viewportHeight));
5457     webViewImpl->layout();
5458 
5459     Document* document = toWebLocalFrameImpl(webViewImpl->mainFrame())->frame()->document();
5460     WebCore::UserGestureIndicator gesture(WebCore::DefinitelyProcessingUserGesture);
5461     Element* divFullscreen = document->getElementById("div1");
5462     divFullscreen->webkitRequestFullscreen();
5463     webViewImpl->willEnterFullScreen();
5464     webViewImpl->didEnterFullScreen();
5465     webViewImpl->layout();
5466 
5467     // Verify that the main frame is not scrollable.
5468     ASSERT_TRUE(WebCore::FullscreenElementStack::isFullScreen(*document));
5469     WebLayer* webScrollLayer = webViewImpl->compositor()->scrollLayer()->platformLayer();
5470     ASSERT_FALSE(webScrollLayer->scrollable());
5471 
5472     // Verify that the main frame is scrollable upon exiting fullscreen.
5473     webViewImpl->willExitFullScreen();
5474     webViewImpl->didExitFullScreen();
5475     webViewImpl->layout();
5476     ASSERT_FALSE(WebCore::FullscreenElementStack::isFullScreen(*document));
5477     webScrollLayer = webViewImpl->compositor()->scrollLayer()->platformLayer();
5478     ASSERT_TRUE(webScrollLayer->scrollable());
5479 }
5480 
TEST_F(WebFrameTest,FullscreenMainFrameScrollable)5481 TEST_F(WebFrameTest, FullscreenMainFrameScrollable)
5482 {
5483     FakeCompositingWebViewClient client;
5484     registerMockedHttpURLLoad("fullscreen_div.html");
5485     FrameTestHelpers::WebViewHelper webViewHelper;
5486     int viewportWidth = 640;
5487     int viewportHeight = 480;
5488     WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "fullscreen_div.html", true, 0, &client, &configueCompositingWebView);
5489     webViewImpl->resize(WebSize(viewportWidth, viewportHeight));
5490     webViewImpl->layout();
5491 
5492     Document* document = toWebLocalFrameImpl(webViewImpl->mainFrame())->frame()->document();
5493     WebCore::UserGestureIndicator gesture(WebCore::DefinitelyProcessingUserGesture);
5494     document->documentElement()->webkitRequestFullscreen();
5495     webViewImpl->willEnterFullScreen();
5496     webViewImpl->didEnterFullScreen();
5497     webViewImpl->layout();
5498 
5499     // Verify that the main frame is still scrollable.
5500     ASSERT_TRUE(WebCore::FullscreenElementStack::isFullScreen(*document));
5501     WebLayer* webScrollLayer = webViewImpl->compositor()->scrollLayer()->platformLayer();
5502     ASSERT_TRUE(webScrollLayer->scrollable());
5503 }
5504 
TEST_F(WebFrameTest,RenderBlockPercentHeightDescendants)5505 TEST_F(WebFrameTest, RenderBlockPercentHeightDescendants)
5506 {
5507     registerMockedHttpURLLoad("percent-height-descendants.html");
5508     FrameTestHelpers::WebViewHelper webViewHelper;
5509     webViewHelper.initializeAndLoad(m_baseURL + "percent-height-descendants.html");
5510 
5511     WebView* webView = webViewHelper.webView();
5512     webView->resize(WebSize(800, 800));
5513     webView->layout();
5514 
5515     Document* document = toWebLocalFrameImpl(webView->mainFrame())->frame()->document();
5516     WebCore::RenderBlock* container = WebCore::toRenderBlock(document->getElementById("container")->renderer());
5517     WebCore::RenderBox* percentHeightInAnonymous = WebCore::toRenderBox(document->getElementById("percent-height-in-anonymous")->renderer());
5518     WebCore::RenderBox* percentHeightDirectChild = WebCore::toRenderBox(document->getElementById("percent-height-direct-child")->renderer());
5519 
5520     EXPECT_TRUE(WebCore::RenderBlock::hasPercentHeightDescendant(percentHeightInAnonymous));
5521     EXPECT_TRUE(WebCore::RenderBlock::hasPercentHeightDescendant(percentHeightDirectChild));
5522 
5523     ASSERT_TRUE(container->percentHeightDescendants());
5524     ASSERT_TRUE(container->hasPercentHeightDescendants());
5525     EXPECT_EQ(2U, container->percentHeightDescendants()->size());
5526     EXPECT_TRUE(container->percentHeightDescendants()->contains(percentHeightInAnonymous));
5527     EXPECT_TRUE(container->percentHeightDescendants()->contains(percentHeightDirectChild));
5528 
5529     WebCore::RenderBlock* anonymousBlock = percentHeightInAnonymous->containingBlock();
5530     EXPECT_TRUE(anonymousBlock->isAnonymous());
5531     EXPECT_FALSE(anonymousBlock->hasPercentHeightDescendants());
5532 }
5533 
TEST_F(WebFrameTest,HasVisibleContentOnVisibleFrames)5534 TEST_F(WebFrameTest, HasVisibleContentOnVisibleFrames)
5535 {
5536     registerMockedHttpURLLoad("visible_frames.html");
5537     FrameTestHelpers::WebViewHelper webViewHelper;
5538     WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "visible_frames.html");
5539     for (WebFrame* frame = webViewImpl->mainFrameImpl()->traverseNext(false); frame; frame = frame->traverseNext(false)) {
5540         EXPECT_TRUE(frame->hasVisibleContent());
5541     }
5542 }
5543 
TEST_F(WebFrameTest,HasVisibleContentOnHiddenFrames)5544 TEST_F(WebFrameTest, HasVisibleContentOnHiddenFrames)
5545 {
5546     registerMockedHttpURLLoad("hidden_frames.html");
5547     FrameTestHelpers::WebViewHelper webViewHelper;
5548     WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(m_baseURL + "hidden_frames.html");
5549     for (WebFrame* frame = webViewImpl->mainFrameImpl()->traverseNext(false); frame; frame = frame->traverseNext(false)) {
5550         EXPECT_FALSE(frame->hasVisibleContent());
5551     }
5552 }
5553 
5554 class ManifestChangeWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5555 public:
ManifestChangeWebFrameClient()5556     ManifestChangeWebFrameClient() : m_manifestChangeCount(0) { }
didChangeManifest(WebLocalFrame *)5557     virtual void didChangeManifest(WebLocalFrame*) OVERRIDE
5558     {
5559         ++m_manifestChangeCount;
5560     }
5561 
manifestChangeCount()5562     int manifestChangeCount() { return m_manifestChangeCount; }
5563 
5564 private:
5565     int m_manifestChangeCount;
5566 };
5567 
TEST_F(WebFrameTest,NotifyManifestChange)5568 TEST_F(WebFrameTest, NotifyManifestChange)
5569 {
5570     registerMockedHttpURLLoad("link-manifest-change.html");
5571 
5572     ManifestChangeWebFrameClient webFrameClient;
5573     FrameTestHelpers::WebViewHelper webViewHelper;
5574     webViewHelper.initializeAndLoad(m_baseURL + "link-manifest-change.html", true, &webFrameClient);
5575 
5576     EXPECT_EQ(14, webFrameClient.manifestChangeCount());
5577 }
5578 
TEST_F(WebFrameTest,ReloadBypassingCache)5579 TEST_F(WebFrameTest, ReloadBypassingCache)
5580 {
5581     // Check that a reload ignoring cache on a frame will result in the cache
5582     // policy of the request being set to ReloadBypassingCache.
5583     registerMockedHttpURLLoad("foo.html");
5584     FrameTestHelpers::WebViewHelper webViewHelper;
5585     webViewHelper.initializeAndLoad(m_baseURL + "foo.html", true);
5586     WebFrame* frame = webViewHelper.webView()->mainFrame();
5587     FrameTestHelpers::reloadFrameIgnoringCache(frame);
5588     EXPECT_EQ(WebURLRequest::ReloadBypassingCache, frame->dataSource()->request().cachePolicy());
5589 }
5590 
nodeImageTestValidation(const WebCore::IntSize & referenceBitmapSize,WebCore::DragImage * dragImage)5591 static void nodeImageTestValidation(const WebCore::IntSize& referenceBitmapSize, WebCore::DragImage* dragImage)
5592 {
5593     // Prepare the reference bitmap.
5594     SkBitmap bitmap;
5595     ASSERT_TRUE(bitmap.allocN32Pixels(referenceBitmapSize.width(), referenceBitmapSize.height()));
5596     SkCanvas canvas(bitmap);
5597     canvas.drawColor(SK_ColorGREEN);
5598 
5599     EXPECT_EQ(referenceBitmapSize.width(), dragImage->size().width());
5600     EXPECT_EQ(referenceBitmapSize.height(), dragImage->size().height());
5601     const SkBitmap& dragBitmap = dragImage->bitmap();
5602     SkAutoLockPixels lockPixel(dragBitmap);
5603     EXPECT_EQ(0, memcmp(bitmap.getPixels(), dragBitmap.getPixels(), bitmap.getSize()));
5604 }
5605 
TEST_F(WebFrameTest,NodeImageTestCSSTransform)5606 TEST_F(WebFrameTest, NodeImageTestCSSTransform)
5607 {
5608     FrameTestHelpers::WebViewHelper webViewHelper;
5609     OwnPtr<WebCore::DragImage> dragImage = nodeImageTestSetup(&webViewHelper, std::string("case-css-transform"));
5610     EXPECT_TRUE(dragImage);
5611 
5612     nodeImageTestValidation(WebCore::IntSize(40, 40), dragImage.get());
5613 }
5614 
TEST_F(WebFrameTest,NodeImageTestCSS3DTransform)5615 TEST_F(WebFrameTest, NodeImageTestCSS3DTransform)
5616 {
5617     FrameTestHelpers::WebViewHelper webViewHelper;
5618     OwnPtr<WebCore::DragImage> dragImage = nodeImageTestSetup(&webViewHelper, std::string("case-css-3dtransform"));
5619     EXPECT_TRUE(dragImage);
5620 
5621     nodeImageTestValidation(WebCore::IntSize(20, 40), dragImage.get());
5622 }
5623 
TEST_F(WebFrameTest,NodeImageTestInlineBlock)5624 TEST_F(WebFrameTest, NodeImageTestInlineBlock)
5625 {
5626     FrameTestHelpers::WebViewHelper webViewHelper;
5627     OwnPtr<WebCore::DragImage> dragImage = nodeImageTestSetup(&webViewHelper, std::string("case-inlineblock"));
5628     EXPECT_TRUE(dragImage);
5629 
5630     nodeImageTestValidation(WebCore::IntSize(40, 40), dragImage.get());
5631 }
5632 
TEST_F(WebFrameTest,NodeImageTestFloatLeft)5633 TEST_F(WebFrameTest, NodeImageTestFloatLeft)
5634 {
5635     FrameTestHelpers::WebViewHelper webViewHelper;
5636     OwnPtr<WebCore::DragImage> dragImage = nodeImageTestSetup(&webViewHelper, std::string("case-float-left-overflow-hidden"));
5637     EXPECT_TRUE(dragImage);
5638 
5639     nodeImageTestValidation(WebCore::IntSize(40, 40), dragImage.get());
5640 }
5641 
5642 class ThemeColorTestWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
5643 public:
ThemeColorTestWebFrameClient()5644     ThemeColorTestWebFrameClient()
5645         : m_didNotify(false)
5646     {
5647     }
5648 
reset()5649     void reset()
5650     {
5651         m_didNotify = false;
5652     }
5653 
didNotify() const5654     bool didNotify() const
5655     {
5656         return m_didNotify;
5657     }
5658 
5659 private:
didChangeThemeColor()5660     virtual void didChangeThemeColor()
5661     {
5662         m_didNotify = true;
5663     }
5664 
5665     bool m_didNotify;
5666 };
5667 
TEST_F(WebFrameTest,ThemeColor)5668 TEST_F(WebFrameTest, ThemeColor)
5669 {
5670     registerMockedHttpURLLoad("theme_color_test.html");
5671     FrameTestHelpers::WebViewHelper webViewHelper;
5672     ThemeColorTestWebFrameClient client;
5673     webViewHelper.initializeAndLoad(m_baseURL + "theme_color_test.html", true, &client);
5674     EXPECT_TRUE(client.didNotify());
5675     WebLocalFrameImpl* frame = webViewHelper.webViewImpl()->mainFrameImpl();
5676     EXPECT_EQ(0xff0000ff, frame->document().themeColor());
5677     // Change color by rgb.
5678     client.reset();
5679     frame->executeScript(WebScriptSource("document.getElementById('tc1').setAttribute('content', 'rgb(0, 0, 0)');"));
5680     EXPECT_TRUE(client.didNotify());
5681     EXPECT_EQ(0xff000000, frame->document().themeColor());
5682     // Change color by hsl.
5683     client.reset();
5684     frame->executeScript(WebScriptSource("document.getElementById('tc1').setAttribute('content', 'hsl(240,100%, 50%)');"));
5685     EXPECT_TRUE(client.didNotify());
5686     EXPECT_EQ(0xff0000ff, frame->document().themeColor());
5687     // Change of second theme-color meta tag will not change frame's theme
5688     // color.
5689     client.reset();
5690     frame->executeScript(WebScriptSource("document.getElementById('tc2').setAttribute('content', '#00FF00');"));
5691     EXPECT_TRUE(client.didNotify());
5692     EXPECT_EQ(0xff0000ff, frame->document().themeColor());
5693 }
5694 
5695 } // namespace
5696