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