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