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