Home | History | Annotate | Download | only in web
      1 /*
      2  * Copyright (C) 2009 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 // How ownership works
     32 // -------------------
     33 //
     34 // Big oh represents a refcounted relationship: owner O--- ownee
     35 //
     36 // WebView (for the toplevel frame only)
     37 //    O
     38 //    |
     39 //   Page O------- Frame (m_mainFrame) O-------O FrameView
     40 //                   ||
     41 //                   ||
     42 //               FrameLoader O-------- WebFrame (via FrameLoaderClient)
     43 //
     44 // FrameLoader and Frame are formerly one object that was split apart because
     45 // it got too big. They basically have the same lifetime, hence the double line.
     46 //
     47 // WebFrame is refcounted and has one ref on behalf of the FrameLoader/Frame.
     48 // This is not a normal reference counted pointer because that would require
     49 // changing WebKit code that we don't control. Instead, it is created with this
     50 // ref initially and it is removed when the FrameLoader is getting destroyed.
     51 //
     52 // WebFrames are created in two places, first in WebViewImpl when the root
     53 // frame is created, and second in WebFrame::createChildFrame when sub-frames
     54 // are created. WebKit will hook up this object to the FrameLoader/Frame
     55 // and the refcount will be correct.
     56 //
     57 // How frames are destroyed
     58 // ------------------------
     59 //
     60 // The main frame is never destroyed and is re-used. The FrameLoader is re-used
     61 // and a reference to the main frame is kept by the Page.
     62 //
     63 // When frame content is replaced, all subframes are destroyed. This happens
     64 // in FrameLoader::detachFromParent for each subframe.
     65 //
     66 // Frame going away causes the FrameLoader to get deleted. In FrameLoader's
     67 // destructor, it notifies its client with frameLoaderDestroyed. This derefs
     68 // the WebFrame and will cause it to be deleted (unless an external someone
     69 // is also holding a reference).
     70 //
     71 // Thie client is expected to be set whenever the WebFrameImpl is attached to
     72 // the DOM.
     73 
     74 #include "config.h"
     75 #include "WebFrameImpl.h"
     76 
     77 #include <algorithm>
     78 #include "AssociatedURLLoader.h"
     79 #include "DOMUtilitiesPrivate.h"
     80 #include "EventListenerWrapper.h"
     81 #include "FindInPageCoordinates.h"
     82 #include "HTMLNames.h"
     83 #include "PageOverlay.h"
     84 #include "V8DOMFileSystem.h"
     85 #include "V8DirectoryEntry.h"
     86 #include "V8FileEntry.h"
     87 #include "WebConsoleMessage.h"
     88 #include "WebDOMEvent.h"
     89 #include "WebDOMEventListener.h"
     90 #include "WebDataSourceImpl.h"
     91 #include "WebDevToolsAgentPrivate.h"
     92 #include "WebDocument.h"
     93 #include "WebFindOptions.h"
     94 #include "WebFormElement.h"
     95 #include "WebFrameClient.h"
     96 #include "WebHistoryItem.h"
     97 #include "WebIconURL.h"
     98 #include "WebInputElement.h"
     99 #include "WebNode.h"
    100 #include "WebPerformance.h"
    101 #include "WebPlugin.h"
    102 #include "WebPluginContainerImpl.h"
    103 #include "WebPrintParams.h"
    104 #include "WebRange.h"
    105 #include "WebScriptSource.h"
    106 #include "WebSecurityOrigin.h"
    107 #include "WebSerializedScriptValue.h"
    108 #include "WebViewImpl.h"
    109 #include "bindings/v8/DOMWrapperWorld.h"
    110 #include "bindings/v8/ExceptionState.h"
    111 #include "bindings/v8/ExceptionStatePlaceholder.h"
    112 #include "bindings/v8/ScriptController.h"
    113 #include "bindings/v8/ScriptSourceCode.h"
    114 #include "bindings/v8/ScriptValue.h"
    115 #include "bindings/v8/V8GCController.h"
    116 #include "core/dom/Document.h"
    117 #include "core/dom/DocumentMarker.h"
    118 #include "core/dom/DocumentMarkerController.h"
    119 #include "core/dom/IconURL.h"
    120 #include "core/dom/MessagePort.h"
    121 #include "core/dom/Node.h"
    122 #include "core/dom/NodeTraversal.h"
    123 #include "core/dom/shadow/ShadowRoot.h"
    124 #include "core/editing/Editor.h"
    125 #include "core/editing/FrameSelection.h"
    126 #include "core/editing/InputMethodController.h"
    127 #include "core/editing/PlainTextRange.h"
    128 #include "core/editing/SpellChecker.h"
    129 #include "core/editing/TextAffinity.h"
    130 #include "core/editing/TextIterator.h"
    131 #include "core/editing/htmlediting.h"
    132 #include "core/editing/markup.h"
    133 #include "core/frame/Console.h"
    134 #include "core/frame/DOMWindow.h"
    135 #include "core/frame/FrameView.h"
    136 #include "core/history/HistoryItem.h"
    137 #include "core/html/HTMLCollection.h"
    138 #include "core/html/HTMLFormElement.h"
    139 #include "core/html/HTMLFrameOwnerElement.h"
    140 #include "core/html/HTMLHeadElement.h"
    141 #include "core/html/HTMLInputElement.h"
    142 #include "core/html/HTMLLinkElement.h"
    143 #include "core/html/HTMLTextAreaElement.h"
    144 #include "core/html/PluginDocument.h"
    145 #include "core/inspector/InspectorController.h"
    146 #include "core/inspector/ScriptCallStack.h"
    147 #include "core/loader/DocumentLoader.h"
    148 #include "core/loader/FormState.h"
    149 #include "core/loader/FrameLoadRequest.h"
    150 #include "core/loader/FrameLoader.h"
    151 #include "core/loader/SubstituteData.h"
    152 #include "core/page/Chrome.h"
    153 #include "core/page/EventHandler.h"
    154 #include "core/page/FocusController.h"
    155 #include "core/page/FrameTree.h"
    156 #include "core/page/Page.h"
    157 #include "core/page/PrintContext.h"
    158 #include "core/frame/Settings.h"
    159 #include "core/rendering/HitTestResult.h"
    160 #include "core/rendering/RenderBox.h"
    161 #include "core/rendering/RenderFrame.h"
    162 #include "core/rendering/RenderLayer.h"
    163 #include "core/rendering/RenderObject.h"
    164 #include "core/rendering/RenderTreeAsText.h"
    165 #include "core/rendering/RenderView.h"
    166 #include "core/rendering/style/StyleInheritedData.h"
    167 #include "core/timing/Performance.h"
    168 #include "core/xml/DocumentXPathEvaluator.h"
    169 #include "core/xml/XPathResult.h"
    170 #include "modules/filesystem/DOMFileSystem.h"
    171 #include "modules/filesystem/DirectoryEntry.h"
    172 #include "modules/filesystem/FileEntry.h"
    173 #include "platform/FileSystemType.h"
    174 #include "platform/TraceEvent.h"
    175 #include "platform/UserGestureIndicator.h"
    176 #include "platform/clipboard/ClipboardUtilities.h"
    177 #include "platform/fonts/FontCache.h"
    178 #include "platform/graphics/GraphicsContext.h"
    179 #include "platform/graphics/GraphicsLayerClient.h"
    180 #include "platform/graphics/skia/SkiaUtils.h"
    181 #include "platform/network/ResourceRequest.h"
    182 #include "platform/scroll/ScrollbarTheme.h"
    183 #include "platform/scroll/ScrollTypes.h"
    184 #include "platform/weborigin/KURL.h"
    185 #include "platform/weborigin/SchemeRegistry.h"
    186 #include "platform/weborigin/SecurityPolicy.h"
    187 #include "public/platform/Platform.h"
    188 #include "public/platform/WebFileSystem.h"
    189 #include "public/platform/WebFloatPoint.h"
    190 #include "public/platform/WebFloatRect.h"
    191 #include "public/platform/WebLayer.h"
    192 #include "public/platform/WebPoint.h"
    193 #include "public/platform/WebRect.h"
    194 #include "public/platform/WebSize.h"
    195 #include "public/platform/WebURLError.h"
    196 #include "public/platform/WebVector.h"
    197 #include "wtf/CurrentTime.h"
    198 #include "wtf/HashMap.h"
    199 
    200 using namespace WebCore;
    201 
    202 namespace blink {
    203 
    204 static int frameCount = 0;
    205 
    206 // Key for a StatsCounter tracking how many WebFrames are active.
    207 static const char webFrameActiveCount[] = "WebFrameActiveCount";
    208 
    209 static void frameContentAsPlainText(size_t maxChars, Frame* frame, StringBuilder& output)
    210 {
    211     Document* document = frame->document();
    212     if (!document)
    213         return;
    214 
    215     if (!frame->view())
    216         return;
    217 
    218     // TextIterator iterates over the visual representation of the DOM. As such,
    219     // it requires you to do a layout before using it (otherwise it'll crash).
    220     document->updateLayout();
    221 
    222     // Select the document body.
    223     RefPtr<Range> range(document->createRange());
    224     TrackExceptionState exceptionState;
    225     range->selectNodeContents(document->body(), exceptionState);
    226 
    227     if (!exceptionState.hadException()) {
    228         // The text iterator will walk nodes giving us text. This is similar to
    229         // the plainText() function in core/editing/TextIterator.h, but we implement the maximum
    230         // size and also copy the results directly into a wstring, avoiding the
    231         // string conversion.
    232         for (TextIterator it(range.get()); !it.atEnd(); it.advance()) {
    233             it.appendTextToStringBuilder(output, 0, maxChars - output.length());
    234             if (output.length() >= maxChars)
    235                 return; // Filled up the buffer.
    236         }
    237     }
    238 
    239     // The separator between frames when the frames are converted to plain text.
    240     const LChar frameSeparator[] = { '\n', '\n' };
    241     const size_t frameSeparatorLength = WTF_ARRAY_LENGTH(frameSeparator);
    242 
    243     // Recursively walk the children.
    244     const FrameTree& frameTree = frame->tree();
    245     for (Frame* curChild = frameTree.firstChild(); curChild; curChild = curChild->tree().nextSibling()) {
    246         // Ignore the text of non-visible frames.
    247         RenderView* contentRenderer = curChild->contentRenderer();
    248         RenderPart* ownerRenderer = curChild->ownerRenderer();
    249         if (!contentRenderer || !contentRenderer->width() || !contentRenderer->height()
    250             || (contentRenderer->x() + contentRenderer->width() <= 0) || (contentRenderer->y() + contentRenderer->height() <= 0)
    251             || (ownerRenderer && ownerRenderer->style() && ownerRenderer->style()->visibility() != VISIBLE)) {
    252             continue;
    253         }
    254 
    255         // Make sure the frame separator won't fill up the buffer, and give up if
    256         // it will. The danger is if the separator will make the buffer longer than
    257         // maxChars. This will cause the computation above:
    258         //   maxChars - output->size()
    259         // to be a negative number which will crash when the subframe is added.
    260         if (output.length() >= maxChars - frameSeparatorLength)
    261             return;
    262 
    263         output.append(frameSeparator, frameSeparatorLength);
    264         frameContentAsPlainText(maxChars, curChild, output);
    265         if (output.length() >= maxChars)
    266             return; // Filled up the buffer.
    267     }
    268 }
    269 
    270 WebPluginContainerImpl* WebFrameImpl::pluginContainerFromFrame(Frame* frame)
    271 {
    272     if (!frame)
    273         return 0;
    274     if (!frame->document() || !frame->document()->isPluginDocument())
    275         return 0;
    276     PluginDocument* pluginDocument = toPluginDocument(frame->document());
    277     return toPluginContainerImpl(pluginDocument->pluginWidget());
    278 }
    279 
    280 WebPluginContainerImpl* WebFrameImpl::pluginContainerFromNode(WebCore::Frame* frame, const WebNode& node)
    281 {
    282     WebPluginContainerImpl* pluginContainer = pluginContainerFromFrame(frame);
    283     if (pluginContainer)
    284         return pluginContainer;
    285     return toPluginContainerImpl(node.pluginContainer());
    286 }
    287 
    288 // Simple class to override some of PrintContext behavior. Some of the methods
    289 // made virtual so that they can be overridden by ChromePluginPrintContext.
    290 class ChromePrintContext : public PrintContext {
    291     WTF_MAKE_NONCOPYABLE(ChromePrintContext);
    292 public:
    293     ChromePrintContext(Frame* frame)
    294         : PrintContext(frame)
    295         , m_printedPageWidth(0)
    296     {
    297     }
    298 
    299     virtual ~ChromePrintContext() { }
    300 
    301     virtual void begin(float width, float height)
    302     {
    303         ASSERT(!m_printedPageWidth);
    304         m_printedPageWidth = width;
    305         PrintContext::begin(m_printedPageWidth, height);
    306     }
    307 
    308     virtual void end()
    309     {
    310         PrintContext::end();
    311     }
    312 
    313     virtual float getPageShrink(int pageNumber) const
    314     {
    315         IntRect pageRect = m_pageRects[pageNumber];
    316         return m_printedPageWidth / pageRect.width();
    317     }
    318 
    319     // Spools the printed page, a subrect of frame(). Skip the scale step.
    320     // NativeTheme doesn't play well with scaling. Scaling is done browser side
    321     // instead. Returns the scale to be applied.
    322     // On Linux, we don't have the problem with NativeTheme, hence we let WebKit
    323     // do the scaling and ignore the return value.
    324     virtual float spoolPage(GraphicsContext& context, int pageNumber)
    325     {
    326         IntRect pageRect = m_pageRects[pageNumber];
    327         float scale = m_printedPageWidth / pageRect.width();
    328 
    329         context.save();
    330 #if OS(POSIX) && !OS(MACOSX)
    331         context.scale(WebCore::FloatSize(scale, scale));
    332 #endif
    333         context.translate(static_cast<float>(-pageRect.x()), static_cast<float>(-pageRect.y()));
    334         context.clip(pageRect);
    335         frame()->view()->paintContents(&context, pageRect);
    336         if (context.supportsURLFragments())
    337             outputLinkedDestinations(context, frame()->document(), pageRect);
    338         context.restore();
    339         return scale;
    340     }
    341 
    342     void spoolAllPagesWithBoundaries(GraphicsContext& graphicsContext, const FloatSize& pageSizeInPixels)
    343     {
    344         if (!frame()->document() || !frame()->view() || !frame()->document()->renderer())
    345             return;
    346 
    347         frame()->document()->updateLayout();
    348 
    349         float pageHeight;
    350         computePageRects(FloatRect(FloatPoint(0, 0), pageSizeInPixels), 0, 0, 1, pageHeight);
    351 
    352         const float pageWidth = pageSizeInPixels.width();
    353         size_t numPages = pageRects().size();
    354         int totalHeight = numPages * (pageSizeInPixels.height() + 1) - 1;
    355 
    356         // Fill the whole background by white.
    357         graphicsContext.setFillColor(Color::white);
    358         graphicsContext.fillRect(FloatRect(0, 0, pageWidth, totalHeight));
    359 
    360         graphicsContext.save();
    361 
    362         int currentHeight = 0;
    363         for (size_t pageIndex = 0; pageIndex < numPages; pageIndex++) {
    364             // Draw a line for a page boundary if this isn't the first page.
    365             if (pageIndex > 0) {
    366                 graphicsContext.save();
    367                 graphicsContext.setStrokeColor(Color(0, 0, 255));
    368                 graphicsContext.setFillColor(Color(0, 0, 255));
    369                 graphicsContext.drawLine(IntPoint(0, currentHeight), IntPoint(pageWidth, currentHeight));
    370                 graphicsContext.restore();
    371             }
    372 
    373             graphicsContext.save();
    374 
    375             graphicsContext.translate(0, currentHeight);
    376 #if OS(WIN) || OS(MACOSX)
    377             // Account for the disabling of scaling in spoolPage. In the context
    378             // of spoolAllPagesWithBoundaries the scale HAS NOT been pre-applied.
    379             float scale = getPageShrink(pageIndex);
    380             graphicsContext.scale(WebCore::FloatSize(scale, scale));
    381 #endif
    382             spoolPage(graphicsContext, pageIndex);
    383             graphicsContext.restore();
    384 
    385             currentHeight += pageSizeInPixels.height() + 1;
    386         }
    387 
    388         graphicsContext.restore();
    389     }
    390 
    391     virtual void computePageRects(const FloatRect& printRect, float headerHeight, float footerHeight, float userScaleFactor, float& outPageHeight)
    392     {
    393         PrintContext::computePageRects(printRect, headerHeight, footerHeight, userScaleFactor, outPageHeight);
    394     }
    395 
    396     virtual int pageCount() const
    397     {
    398         return PrintContext::pageCount();
    399     }
    400 
    401 private:
    402     // Set when printing.
    403     float m_printedPageWidth;
    404 };
    405 
    406 // Simple class to override some of PrintContext behavior. This is used when
    407 // the frame hosts a plugin that supports custom printing. In this case, we
    408 // want to delegate all printing related calls to the plugin.
    409 class ChromePluginPrintContext : public ChromePrintContext {
    410 public:
    411     ChromePluginPrintContext(Frame* frame, WebPluginContainerImpl* plugin, const WebPrintParams& printParams)
    412         : ChromePrintContext(frame), m_plugin(plugin), m_pageCount(0), m_printParams(printParams)
    413     {
    414     }
    415 
    416     virtual ~ChromePluginPrintContext() { }
    417 
    418     virtual void begin(float width, float height)
    419     {
    420     }
    421 
    422     virtual void end()
    423     {
    424         m_plugin->printEnd();
    425     }
    426 
    427     virtual float getPageShrink(int pageNumber) const
    428     {
    429         // We don't shrink the page (maybe we should ask the widget ??)
    430         return 1.0;
    431     }
    432 
    433     virtual void computePageRects(const FloatRect& printRect, float headerHeight, float footerHeight, float userScaleFactor, float& outPageHeight)
    434     {
    435         m_printParams.printContentArea = IntRect(printRect);
    436         m_pageCount = m_plugin->printBegin(m_printParams);
    437     }
    438 
    439     virtual int pageCount() const
    440     {
    441         return m_pageCount;
    442     }
    443 
    444     // Spools the printed page, a subrect of frame(). Skip the scale step.
    445     // NativeTheme doesn't play well with scaling. Scaling is done browser side
    446     // instead. Returns the scale to be applied.
    447     virtual float spoolPage(GraphicsContext& context, int pageNumber)
    448     {
    449         m_plugin->printPage(pageNumber, &context);
    450         return 1.0;
    451     }
    452 
    453 private:
    454     // Set when printing.
    455     WebPluginContainerImpl* m_plugin;
    456     int m_pageCount;
    457     WebPrintParams m_printParams;
    458 
    459 };
    460 
    461 static WebDataSource* DataSourceForDocLoader(DocumentLoader* loader)
    462 {
    463     return loader ? WebDataSourceImpl::fromDocumentLoader(loader) : 0;
    464 }
    465 
    466 WebFrameImpl::FindMatch::FindMatch(PassRefPtr<Range> range, int ordinal)
    467     : m_range(range)
    468     , m_ordinal(ordinal)
    469 {
    470 }
    471 
    472 class WebFrameImpl::DeferredScopeStringMatches {
    473 public:
    474     DeferredScopeStringMatches(WebFrameImpl* webFrame, int identifier, const WebString& searchText, const WebFindOptions& options, bool reset)
    475         : m_timer(this, &DeferredScopeStringMatches::doTimeout)
    476         , m_webFrame(webFrame)
    477         , m_identifier(identifier)
    478         , m_searchText(searchText)
    479         , m_options(options)
    480         , m_reset(reset)
    481     {
    482         m_timer.startOneShot(0.0);
    483     }
    484 
    485 private:
    486     void doTimeout(Timer<DeferredScopeStringMatches>*)
    487     {
    488         m_webFrame->callScopeStringMatches(this, m_identifier, m_searchText, m_options, m_reset);
    489     }
    490 
    491     Timer<DeferredScopeStringMatches> m_timer;
    492     RefPtr<WebFrameImpl> m_webFrame;
    493     int m_identifier;
    494     WebString m_searchText;
    495     WebFindOptions m_options;
    496     bool m_reset;
    497 };
    498 
    499 // WebFrame -------------------------------------------------------------------
    500 
    501 int WebFrame::instanceCount()
    502 {
    503     return frameCount;
    504 }
    505 
    506 WebFrame* WebFrame::frameForCurrentContext()
    507 {
    508     v8::Handle<v8::Context> context = v8::Isolate::GetCurrent()->GetCurrentContext();
    509     if (context.IsEmpty())
    510         return 0;
    511     return frameForContext(context);
    512 }
    513 
    514 WebFrame* WebFrame::frameForContext(v8::Handle<v8::Context> context)
    515 {
    516    return WebFrameImpl::fromFrame(toFrameIfNotDetached(context));
    517 }
    518 
    519 WebFrame* WebFrame::fromFrameOwnerElement(const WebElement& element)
    520 {
    521     return WebFrameImpl::fromFrameOwnerElement(PassRefPtr<Element>(element).get());
    522 }
    523 
    524 void WebFrameImpl::close()
    525 {
    526     m_client = 0;
    527     deref(); // Balances ref() acquired in WebFrame::create
    528 }
    529 
    530 WebString WebFrameImpl::uniqueName() const
    531 {
    532     return frame()->tree().uniqueName();
    533 }
    534 
    535 WebString WebFrameImpl::assignedName() const
    536 {
    537     return frame()->tree().name();
    538 }
    539 
    540 void WebFrameImpl::setName(const WebString& name)
    541 {
    542     frame()->tree().setName(name);
    543 }
    544 
    545 long long WebFrameImpl::embedderIdentifier() const
    546 {
    547     return m_frameInit->frameID();
    548 }
    549 
    550 WebVector<WebIconURL> WebFrameImpl::iconURLs(int iconTypesMask) const
    551 {
    552     // The URL to the icon may be in the header. As such, only
    553     // ask the loader for the icon if it's finished loading.
    554     if (frame()->loader().state() == FrameStateComplete)
    555         return frame()->document()->iconURLs(iconTypesMask);
    556     return WebVector<WebIconURL>();
    557 }
    558 
    559 void WebFrameImpl::setRemoteWebLayer(WebLayer* webLayer)
    560 {
    561     if (!frame())
    562         return;
    563 
    564     if (frame()->remotePlatformLayer())
    565         GraphicsLayer::unregisterContentsLayer(frame()->remotePlatformLayer());
    566     if (webLayer)
    567         GraphicsLayer::registerContentsLayer(webLayer);
    568     frame()->setRemotePlatformLayer(webLayer);
    569     frame()->ownerElement()->setNeedsStyleRecalc(WebCore::SubtreeStyleChange, WebCore::StyleChangeFromRenderer);
    570 }
    571 
    572 void WebFrameImpl::setPermissionClient(WebPermissionClient* permissionClient)
    573 {
    574     m_permissionClient = permissionClient;
    575 }
    576 
    577 WebSize WebFrameImpl::scrollOffset() const
    578 {
    579     FrameView* view = frameView();
    580     if (!view)
    581         return WebSize();
    582     return view->scrollOffset();
    583 }
    584 
    585 WebSize WebFrameImpl::minimumScrollOffset() const
    586 {
    587     FrameView* view = frameView();
    588     if (!view)
    589         return WebSize();
    590     return toIntSize(view->minimumScrollPosition());
    591 }
    592 
    593 WebSize WebFrameImpl::maximumScrollOffset() const
    594 {
    595     FrameView* view = frameView();
    596     if (!view)
    597         return WebSize();
    598     return toIntSize(view->maximumScrollPosition());
    599 }
    600 
    601 void WebFrameImpl::setScrollOffset(const WebSize& offset)
    602 {
    603     if (FrameView* view = frameView())
    604         view->setScrollOffset(IntPoint(offset.width, offset.height));
    605 }
    606 
    607 WebSize WebFrameImpl::contentsSize() const
    608 {
    609     return frame()->view()->contentsSize();
    610 }
    611 
    612 bool WebFrameImpl::hasVisibleContent() const
    613 {
    614     return frame()->view()->visibleWidth() > 0 && frame()->view()->visibleHeight() > 0;
    615 }
    616 
    617 WebRect WebFrameImpl::visibleContentRect() const
    618 {
    619     return frame()->view()->visibleContentRect();
    620 }
    621 
    622 bool WebFrameImpl::hasHorizontalScrollbar() const
    623 {
    624     return frame() && frame()->view() && frame()->view()->horizontalScrollbar();
    625 }
    626 
    627 bool WebFrameImpl::hasVerticalScrollbar() const
    628 {
    629     return frame() && frame()->view() && frame()->view()->verticalScrollbar();
    630 }
    631 
    632 WebView* WebFrameImpl::view() const
    633 {
    634     return viewImpl();
    635 }
    636 
    637 WebFrame* WebFrameImpl::opener() const
    638 {
    639     if (!frame())
    640         return 0;
    641     return fromFrame(frame()->loader().opener());
    642 }
    643 
    644 void WebFrameImpl::setOpener(const WebFrame* webFrame)
    645 {
    646     frame()->loader().setOpener(webFrame ? toWebFrameImpl(webFrame)->frame() : 0);
    647 }
    648 
    649 WebFrame* WebFrameImpl::parent() const
    650 {
    651     if (!frame())
    652         return 0;
    653     return fromFrame(frame()->tree().parent());
    654 }
    655 
    656 WebFrame* WebFrameImpl::top() const
    657 {
    658     if (!frame())
    659         return 0;
    660     return fromFrame(frame()->tree().top());
    661 }
    662 
    663 WebFrame* WebFrameImpl::firstChild() const
    664 {
    665     if (!frame())
    666         return 0;
    667     return fromFrame(frame()->tree().firstChild());
    668 }
    669 
    670 WebFrame* WebFrameImpl::lastChild() const
    671 {
    672     if (!frame())
    673         return 0;
    674     return fromFrame(frame()->tree().lastChild());
    675 }
    676 
    677 WebFrame* WebFrameImpl::nextSibling() const
    678 {
    679     if (!frame())
    680         return 0;
    681     return fromFrame(frame()->tree().nextSibling());
    682 }
    683 
    684 WebFrame* WebFrameImpl::previousSibling() const
    685 {
    686     if (!frame())
    687         return 0;
    688     return fromFrame(frame()->tree().previousSibling());
    689 }
    690 
    691 WebFrame* WebFrameImpl::traverseNext(bool wrap) const
    692 {
    693     if (!frame())
    694         return 0;
    695     return fromFrame(frame()->tree().traverseNextWithWrap(wrap));
    696 }
    697 
    698 WebFrame* WebFrameImpl::traversePrevious(bool wrap) const
    699 {
    700     if (!frame())
    701         return 0;
    702     return fromFrame(frame()->tree().traversePreviousWithWrap(wrap));
    703 }
    704 
    705 WebFrame* WebFrameImpl::findChildByName(const WebString& name) const
    706 {
    707     if (!frame())
    708         return 0;
    709     return fromFrame(frame()->tree().child(name));
    710 }
    711 
    712 WebFrame* WebFrameImpl::findChildByExpression(const WebString& xpath) const
    713 {
    714     if (xpath.isEmpty())
    715         return 0;
    716 
    717     Document* document = frame()->document();
    718 
    719     RefPtr<XPathResult> xpathResult = DocumentXPathEvaluator::evaluate(document, xpath, document, 0, XPathResult::ORDERED_NODE_ITERATOR_TYPE, 0, IGNORE_EXCEPTION);
    720     if (!xpathResult)
    721         return 0;
    722 
    723     Node* node = xpathResult->iterateNext(IGNORE_EXCEPTION);
    724     if (!node || !node->isFrameOwnerElement())
    725         return 0;
    726     return fromFrame(toHTMLFrameOwnerElement(node)->contentFrame());
    727 }
    728 
    729 WebDocument WebFrameImpl::document() const
    730 {
    731     if (!frame() || !frame()->document())
    732         return WebDocument();
    733     return WebDocument(frame()->document());
    734 }
    735 
    736 WebPerformance WebFrameImpl::performance() const
    737 {
    738     if (!frame())
    739         return WebPerformance();
    740     return WebPerformance(frame()->domWindow()->performance());
    741 }
    742 
    743 NPObject* WebFrameImpl::windowObject() const
    744 {
    745     if (!frame())
    746         return 0;
    747     return frame()->script().windowScriptNPObject();
    748 }
    749 
    750 void WebFrameImpl::bindToWindowObject(const WebString& name, NPObject* object)
    751 {
    752     bindToWindowObject(name, object, 0);
    753 }
    754 
    755 void WebFrameImpl::bindToWindowObject(const WebString& name, NPObject* object, void*)
    756 {
    757     if (!frame() || !frame()->script().canExecuteScripts(NotAboutToExecuteScript))
    758         return;
    759     frame()->script().bindToWindowObject(frame(), String(name), object);
    760 }
    761 
    762 void WebFrameImpl::executeScript(const WebScriptSource& source)
    763 {
    764     ASSERT(frame());
    765     TextPosition position(OrdinalNumber::fromOneBasedInt(source.startLine), OrdinalNumber::first());
    766     frame()->script().executeScriptInMainWorld(ScriptSourceCode(source.code, source.url, position));
    767 }
    768 
    769 void WebFrameImpl::executeScriptInIsolatedWorld(int worldID, const WebScriptSource* sourcesIn, unsigned numSources, int extensionGroup)
    770 {
    771     ASSERT(frame());
    772     RELEASE_ASSERT(worldID > 0);
    773     RELEASE_ASSERT(worldID < EmbedderWorldIdLimit);
    774 
    775     Vector<ScriptSourceCode> sources;
    776     for (unsigned i = 0; i < numSources; ++i) {
    777         TextPosition position(OrdinalNumber::fromOneBasedInt(sourcesIn[i].startLine), OrdinalNumber::first());
    778         sources.append(ScriptSourceCode(sourcesIn[i].code, sourcesIn[i].url, position));
    779     }
    780 
    781     frame()->script().executeScriptInIsolatedWorld(worldID, sources, extensionGroup, 0);
    782 }
    783 
    784 void WebFrameImpl::setIsolatedWorldSecurityOrigin(int worldID, const WebSecurityOrigin& securityOrigin)
    785 {
    786     ASSERT(frame());
    787     DOMWrapperWorld::setIsolatedWorldSecurityOrigin(worldID, securityOrigin.get());
    788 }
    789 
    790 void WebFrameImpl::setIsolatedWorldContentSecurityPolicy(int worldID, const WebString& policy)
    791 {
    792     ASSERT(frame());
    793     DOMWrapperWorld::setIsolatedWorldContentSecurityPolicy(worldID, policy);
    794 }
    795 
    796 void WebFrameImpl::addMessageToConsole(const WebConsoleMessage& message)
    797 {
    798     ASSERT(frame());
    799 
    800     MessageLevel webCoreMessageLevel;
    801     switch (message.level) {
    802     case WebConsoleMessage::LevelDebug:
    803         webCoreMessageLevel = DebugMessageLevel;
    804         break;
    805     case WebConsoleMessage::LevelLog:
    806         webCoreMessageLevel = LogMessageLevel;
    807         break;
    808     case WebConsoleMessage::LevelWarning:
    809         webCoreMessageLevel = WarningMessageLevel;
    810         break;
    811     case WebConsoleMessage::LevelError:
    812         webCoreMessageLevel = ErrorMessageLevel;
    813         break;
    814     default:
    815         ASSERT_NOT_REACHED();
    816         return;
    817     }
    818 
    819     frame()->document()->addConsoleMessage(OtherMessageSource, webCoreMessageLevel, message.text);
    820 }
    821 
    822 void WebFrameImpl::collectGarbage()
    823 {
    824     if (!frame())
    825         return;
    826     if (!frame()->settings()->isScriptEnabled())
    827         return;
    828     V8GCController::collectGarbage(v8::Isolate::GetCurrent());
    829 }
    830 
    831 bool WebFrameImpl::checkIfRunInsecureContent(const WebURL& url) const
    832 {
    833     ASSERT(frame());
    834     return frame()->loader().mixedContentChecker()->canRunInsecureContent(frame()->document()->securityOrigin(), url);
    835 }
    836 
    837 v8::Handle<v8::Value> WebFrameImpl::executeScriptAndReturnValue(const WebScriptSource& source)
    838 {
    839     ASSERT(frame());
    840 
    841     // FIXME: This fake user gesture is required to make a bunch of pyauto
    842     // tests pass. If this isn't needed in non-test situations, we should
    843     // consider removing this code and changing the tests.
    844     // http://code.google.com/p/chromium/issues/detail?id=86397
    845     UserGestureIndicator gestureIndicator(DefinitelyProcessingNewUserGesture);
    846 
    847     TextPosition position(OrdinalNumber::fromOneBasedInt(source.startLine), OrdinalNumber::first());
    848     return frame()->script().executeScriptInMainWorldAndReturnValue(ScriptSourceCode(source.code, source.url, position)).v8Value();
    849 }
    850 
    851 void WebFrameImpl::executeScriptInIsolatedWorld(int worldID, const WebScriptSource* sourcesIn, unsigned numSources, int extensionGroup, WebVector<v8::Local<v8::Value> >* results)
    852 {
    853     ASSERT(frame());
    854     RELEASE_ASSERT(worldID > 0);
    855     RELEASE_ASSERT(worldID < EmbedderWorldIdLimit);
    856 
    857     Vector<ScriptSourceCode> sources;
    858 
    859     for (unsigned i = 0; i < numSources; ++i) {
    860         TextPosition position(OrdinalNumber::fromOneBasedInt(sourcesIn[i].startLine), OrdinalNumber::first());
    861         sources.append(ScriptSourceCode(sourcesIn[i].code, sourcesIn[i].url, position));
    862     }
    863 
    864     if (results) {
    865         Vector<ScriptValue> scriptResults;
    866         frame()->script().executeScriptInIsolatedWorld(worldID, sources, extensionGroup, &scriptResults);
    867         WebVector<v8::Local<v8::Value> > v8Results(scriptResults.size());
    868         for (unsigned i = 0; i < scriptResults.size(); i++)
    869             v8Results[i] = v8::Local<v8::Value>::New(toIsolate(frame()), scriptResults[i].v8Value());
    870         results->swap(v8Results);
    871     } else {
    872         frame()->script().executeScriptInIsolatedWorld(worldID, sources, extensionGroup, 0);
    873     }
    874 }
    875 
    876 v8::Handle<v8::Value> WebFrameImpl::callFunctionEvenIfScriptDisabled(v8::Handle<v8::Function> function, v8::Handle<v8::Object> receiver, int argc, v8::Handle<v8::Value> argv[])
    877 {
    878     ASSERT(frame());
    879     return frame()->script().callFunction(function, receiver, argc, argv);
    880 }
    881 
    882 v8::Local<v8::Context> WebFrameImpl::mainWorldScriptContext() const
    883 {
    884     if (!frame())
    885         return v8::Local<v8::Context>();
    886     return ScriptController::mainWorldContext(frame());
    887 }
    888 
    889 v8::Handle<v8::Value> WebFrameImpl::createFileSystem(WebFileSystemType type, const WebString& name, const WebString& path)
    890 {
    891     ASSERT(frame());
    892     return toV8(DOMFileSystem::create(frame()->document(), name, static_cast<WebCore::FileSystemType>(type), KURL(ParsedURLString, path.utf8().data())), v8::Handle<v8::Object>(), toIsolate(frame()));
    893 }
    894 
    895 v8::Handle<v8::Value> WebFrameImpl::createSerializableFileSystem(WebFileSystemType type, const WebString& name, const WebString& path)
    896 {
    897     ASSERT(frame());
    898     RefPtr<DOMFileSystem> fileSystem = DOMFileSystem::create(frame()->document(), name, static_cast<WebCore::FileSystemType>(type), KURL(ParsedURLString, path.utf8().data()));
    899     fileSystem->makeClonable();
    900     return toV8(fileSystem.release(), v8::Handle<v8::Object>(), toIsolate(frame()));
    901 }
    902 
    903 v8::Handle<v8::Value> WebFrameImpl::createFileEntry(WebFileSystemType type, const WebString& fileSystemName, const WebString& fileSystemPath, const WebString& filePath, bool isDirectory)
    904 {
    905     ASSERT(frame());
    906 
    907     RefPtr<DOMFileSystemBase> fileSystem = DOMFileSystem::create(frame()->document(), fileSystemName, static_cast<WebCore::FileSystemType>(type), KURL(ParsedURLString, fileSystemPath.utf8().data()));
    908     if (isDirectory)
    909         return toV8(DirectoryEntry::create(fileSystem, filePath), v8::Handle<v8::Object>(), toIsolate(frame()));
    910     return toV8(FileEntry::create(fileSystem, filePath), v8::Handle<v8::Object>(), toIsolate(frame()));
    911 }
    912 
    913 void WebFrameImpl::reload(bool ignoreCache)
    914 {
    915     ASSERT(frame());
    916     frame()->loader().reload(ignoreCache ? EndToEndReload : NormalReload);
    917 }
    918 
    919 void WebFrameImpl::reloadWithOverrideURL(const WebURL& overrideUrl, bool ignoreCache)
    920 {
    921     ASSERT(frame());
    922     frame()->loader().reload(ignoreCache ? EndToEndReload : NormalReload, overrideUrl);
    923 }
    924 
    925 void WebFrameImpl::loadRequest(const WebURLRequest& request)
    926 {
    927     ASSERT(frame());
    928     ASSERT(!request.isNull());
    929     const ResourceRequest& resourceRequest = request.toResourceRequest();
    930 
    931     if (resourceRequest.url().protocolIs("javascript")) {
    932         loadJavaScriptURL(resourceRequest.url());
    933         return;
    934     }
    935 
    936     frame()->loader().load(FrameLoadRequest(0, resourceRequest));
    937 }
    938 
    939 void WebFrameImpl::loadHistoryItem(const WebHistoryItem& item)
    940 {
    941     ASSERT(frame());
    942     RefPtr<HistoryItem> historyItem = PassRefPtr<HistoryItem>(item);
    943     ASSERT(historyItem);
    944     frame()->page()->historyController().goToItem(historyItem.get());
    945 }
    946 
    947 void WebFrameImpl::loadData(const WebData& data, const WebString& mimeType, const WebString& textEncoding, const WebURL& baseURL, const WebURL& unreachableURL, bool replace)
    948 {
    949     ASSERT(frame());
    950 
    951     // If we are loading substitute data to replace an existing load, then
    952     // inherit all of the properties of that original request.  This way,
    953     // reload will re-attempt the original request.  It is essential that
    954     // we only do this when there is an unreachableURL since a non-empty
    955     // unreachableURL informs FrameLoader::reload to load unreachableURL
    956     // instead of the currently loaded URL.
    957     ResourceRequest request;
    958     if (replace && !unreachableURL.isEmpty())
    959         request = frame()->loader().originalRequest();
    960     request.setURL(baseURL);
    961 
    962     FrameLoadRequest frameRequest(0, request, SubstituteData(data, mimeType, textEncoding, unreachableURL));
    963     ASSERT(frameRequest.substituteData().isValid());
    964     frameRequest.setLockBackForwardList(replace);
    965     frame()->loader().load(frameRequest);
    966 }
    967 
    968 void WebFrameImpl::loadHTMLString(const WebData& data, const WebURL& baseURL, const WebURL& unreachableURL, bool replace)
    969 {
    970     ASSERT(frame());
    971     loadData(data, WebString::fromUTF8("text/html"), WebString::fromUTF8("UTF-8"), baseURL, unreachableURL, replace);
    972 }
    973 
    974 bool WebFrameImpl::isLoading() const
    975 {
    976     if (!frame())
    977         return false;
    978     return frame()->loader().isLoading();
    979 }
    980 
    981 void WebFrameImpl::stopLoading()
    982 {
    983     if (!frame())
    984         return;
    985     // FIXME: Figure out what we should really do here.  It seems like a bug
    986     // that FrameLoader::stopLoading doesn't call stopAllLoaders.
    987     frame()->loader().stopAllLoaders();
    988 }
    989 
    990 WebDataSource* WebFrameImpl::provisionalDataSource() const
    991 {
    992     ASSERT(frame());
    993 
    994     // We regard the policy document loader as still provisional.
    995     DocumentLoader* documentLoader = frame()->loader().provisionalDocumentLoader();
    996     if (!documentLoader)
    997         documentLoader = frame()->loader().policyDocumentLoader();
    998 
    999     return DataSourceForDocLoader(documentLoader);
   1000 }
   1001 
   1002 WebDataSource* WebFrameImpl::dataSource() const
   1003 {
   1004     ASSERT(frame());
   1005     return DataSourceForDocLoader(frame()->loader().documentLoader());
   1006 }
   1007 
   1008 WebHistoryItem WebFrameImpl::previousHistoryItem() const
   1009 {
   1010     ASSERT(frame());
   1011     // We use the previous item here because documentState (filled-out forms)
   1012     // only get saved to history when it becomes the previous item.  The caller
   1013     // is expected to query the history item after a navigation occurs, after
   1014     // the desired history item has become the previous entry.
   1015     return WebHistoryItem(frame()->page()->historyController().previousItemForExport());
   1016 }
   1017 
   1018 WebHistoryItem WebFrameImpl::currentHistoryItem() const
   1019 {
   1020     ASSERT(frame());
   1021 
   1022     // We're shutting down.
   1023     if (!frame()->loader().activeDocumentLoader())
   1024         return WebHistoryItem();
   1025 
   1026     // If we are still loading, then we don't want to clobber the current
   1027     // history item as this could cause us to lose the scroll position and
   1028     // document state.  However, it is OK for new navigations.
   1029     // FIXME: Can we make this a plain old getter, instead of worrying about
   1030     // clobbering here?
   1031     if (!frame()->page()->historyController().inSameDocumentLoad() && (frame()->loader().loadType() == FrameLoadTypeStandard
   1032         || !frame()->loader().activeDocumentLoader()->isLoadingInAPISense()))
   1033         frame()->loader().saveDocumentAndScrollState();
   1034 
   1035     if (RefPtr<HistoryItem> item = frame()->page()->historyController().provisionalItemForExport())
   1036         return WebHistoryItem(item);
   1037     return WebHistoryItem(frame()->page()->historyController().currentItemForExport());
   1038 }
   1039 
   1040 void WebFrameImpl::enableViewSourceMode(bool enable)
   1041 {
   1042     if (frame())
   1043         frame()->setInViewSourceMode(enable);
   1044 }
   1045 
   1046 bool WebFrameImpl::isViewSourceModeEnabled() const
   1047 {
   1048     if (!frame())
   1049         return false;
   1050     return frame()->inViewSourceMode();
   1051 }
   1052 
   1053 void WebFrameImpl::setReferrerForRequest(WebURLRequest& request, const WebURL& referrerURL)
   1054 {
   1055     String referrer = referrerURL.isEmpty() ? frame()->document()->outgoingReferrer() : String(referrerURL.spec().utf16());
   1056     referrer = SecurityPolicy::generateReferrerHeader(frame()->document()->referrerPolicy(), request.url(), referrer);
   1057     if (referrer.isEmpty())
   1058         return;
   1059     request.setHTTPHeaderField(WebString::fromUTF8("Referer"), referrer);
   1060 }
   1061 
   1062 void WebFrameImpl::dispatchWillSendRequest(WebURLRequest& request)
   1063 {
   1064     ResourceResponse response;
   1065     frame()->loader().client()->dispatchWillSendRequest(0, 0, request.toMutableResourceRequest(), response);
   1066 }
   1067 
   1068 WebURLLoader* WebFrameImpl::createAssociatedURLLoader(const WebURLLoaderOptions& options)
   1069 {
   1070     return new AssociatedURLLoader(this, options);
   1071 }
   1072 
   1073 unsigned WebFrameImpl::unloadListenerCount() const
   1074 {
   1075     return frame()->domWindow()->pendingUnloadEventListeners();
   1076 }
   1077 
   1078 void WebFrameImpl::replaceSelection(const WebString& text)
   1079 {
   1080     bool selectReplacement = false;
   1081     bool smartReplace = true;
   1082     frame()->editor().replaceSelectionWithText(text, selectReplacement, smartReplace);
   1083 }
   1084 
   1085 void WebFrameImpl::insertText(const WebString& text)
   1086 {
   1087     if (frame()->inputMethodController().hasComposition())
   1088         frame()->inputMethodController().confirmComposition(text);
   1089     else
   1090         frame()->editor().insertText(text, 0);
   1091 }
   1092 
   1093 void WebFrameImpl::setMarkedText(const WebString& text, unsigned location, unsigned length)
   1094 {
   1095     Vector<CompositionUnderline> decorations;
   1096     frame()->inputMethodController().setComposition(text, decorations, location, length);
   1097 }
   1098 
   1099 void WebFrameImpl::unmarkText()
   1100 {
   1101     frame()->inputMethodController().cancelComposition();
   1102 }
   1103 
   1104 bool WebFrameImpl::hasMarkedText() const
   1105 {
   1106     return frame()->inputMethodController().hasComposition();
   1107 }
   1108 
   1109 WebRange WebFrameImpl::markedRange() const
   1110 {
   1111     return frame()->inputMethodController().compositionRange();
   1112 }
   1113 
   1114 bool WebFrameImpl::firstRectForCharacterRange(unsigned location, unsigned length, WebRect& rect) const
   1115 {
   1116     if ((location + length < location) && (location + length))
   1117         length = 0;
   1118 
   1119     Element* editable = frame()->selection().rootEditableElementOrDocumentElement();
   1120     ASSERT(editable);
   1121     RefPtr<Range> range = PlainTextRange(location, location + length).createRange(*editable);
   1122     if (!range)
   1123         return false;
   1124     IntRect intRect = frame()->editor().firstRectForRange(range.get());
   1125     rect = WebRect(intRect);
   1126     rect = frame()->view()->contentsToWindow(rect);
   1127     return true;
   1128 }
   1129 
   1130 size_t WebFrameImpl::characterIndexForPoint(const WebPoint& webPoint) const
   1131 {
   1132     if (!frame())
   1133         return kNotFound;
   1134 
   1135     IntPoint point = frame()->view()->windowToContents(webPoint);
   1136     HitTestResult result = frame()->eventHandler().hitTestResultAtPoint(point, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent);
   1137     RefPtr<Range> range = frame()->rangeForPoint(result.roundedPointInInnerNodeFrame());
   1138     if (!range)
   1139         return kNotFound;
   1140     Element* editable = frame()->selection().rootEditableElementOrDocumentElement();
   1141     ASSERT(editable);
   1142     return PlainTextRange::create(*editable, *range.get()).start();
   1143 }
   1144 
   1145 bool WebFrameImpl::executeCommand(const WebString& name, const WebNode& node)
   1146 {
   1147     ASSERT(frame());
   1148 
   1149     if (name.length() <= 2)
   1150         return false;
   1151 
   1152     // Since we don't have NSControl, we will convert the format of command
   1153     // string and call the function on Editor directly.
   1154     String command = name;
   1155 
   1156     // Make sure the first letter is upper case.
   1157     command.replace(0, 1, command.substring(0, 1).upper());
   1158 
   1159     // Remove the trailing ':' if existing.
   1160     if (command[command.length() - 1] == UChar(':'))
   1161         command = command.substring(0, command.length() - 1);
   1162 
   1163     WebPluginContainerImpl* pluginContainer = pluginContainerFromNode(frame(), node);
   1164     if (pluginContainer && pluginContainer->executeEditCommand(name))
   1165         return true;
   1166 
   1167     bool result = true;
   1168 
   1169     // Specially handling commands that Editor::execCommand does not directly
   1170     // support.
   1171     if (command == "DeleteToEndOfParagraph") {
   1172         if (!frame()->editor().deleteWithDirection(DirectionForward, ParagraphBoundary, true, false))
   1173             frame()->editor().deleteWithDirection(DirectionForward, CharacterGranularity, true, false);
   1174     } else if (command == "Indent") {
   1175         frame()->editor().indent();
   1176     } else if (command == "Outdent") {
   1177         frame()->editor().outdent();
   1178     } else if (command == "DeleteBackward") {
   1179         result = frame()->editor().command(AtomicString("BackwardDelete")).execute();
   1180     } else if (command == "DeleteForward") {
   1181         result = frame()->editor().command(AtomicString("ForwardDelete")).execute();
   1182     } else if (command == "AdvanceToNextMisspelling") {
   1183         // Wee need to pass false here or else the currently selected word will never be skipped.
   1184         frame()->spellChecker().advanceToNextMisspelling(false);
   1185     } else if (command == "ToggleSpellPanel") {
   1186         frame()->spellChecker().showSpellingGuessPanel();
   1187     } else {
   1188         result = frame()->editor().command(command).execute();
   1189     }
   1190     return result;
   1191 }
   1192 
   1193 bool WebFrameImpl::executeCommand(const WebString& name, const WebString& value, const WebNode& node)
   1194 {
   1195     ASSERT(frame());
   1196     String webName = name;
   1197 
   1198     WebPluginContainerImpl* pluginContainer = pluginContainerFromNode(frame(), node);
   1199     if (pluginContainer && pluginContainer->executeEditCommand(name, value))
   1200         return true;
   1201 
   1202     // moveToBeginningOfDocument and moveToEndfDocument are only handled by WebKit for editable nodes.
   1203     if (!frame()->editor().canEdit() && webName == "moveToBeginningOfDocument")
   1204         return viewImpl()->propagateScroll(ScrollUp, ScrollByDocument);
   1205 
   1206     if (!frame()->editor().canEdit() && webName == "moveToEndOfDocument")
   1207         return viewImpl()->propagateScroll(ScrollDown, ScrollByDocument);
   1208 
   1209     if (webName == "showGuessPanel") {
   1210         frame()->spellChecker().showSpellingGuessPanel();
   1211         return true;
   1212     }
   1213 
   1214     return frame()->editor().command(webName).execute(value);
   1215 }
   1216 
   1217 bool WebFrameImpl::isCommandEnabled(const WebString& name) const
   1218 {
   1219     ASSERT(frame());
   1220     return frame()->editor().command(name).isEnabled();
   1221 }
   1222 
   1223 void WebFrameImpl::enableContinuousSpellChecking(bool enable)
   1224 {
   1225     if (enable == isContinuousSpellCheckingEnabled())
   1226         return;
   1227     frame()->spellChecker().toggleContinuousSpellChecking();
   1228 }
   1229 
   1230 bool WebFrameImpl::isContinuousSpellCheckingEnabled() const
   1231 {
   1232     return frame()->spellChecker().isContinuousSpellCheckingEnabled();
   1233 }
   1234 
   1235 void WebFrameImpl::requestTextChecking(const WebElement& webElement)
   1236 {
   1237     if (webElement.isNull())
   1238         return;
   1239     frame()->spellChecker().requestTextChecking(*webElement.constUnwrap<Element>());
   1240 }
   1241 
   1242 void WebFrameImpl::replaceMisspelledRange(const WebString& text)
   1243 {
   1244     // If this caret selection has two or more markers, this function replace the range covered by the first marker with the specified word as Microsoft Word does.
   1245     if (pluginContainerFromFrame(frame()))
   1246         return;
   1247     RefPtr<Range> caretRange = frame()->selection().toNormalizedRange();
   1248     if (!caretRange)
   1249         return;
   1250     Vector<DocumentMarker*> markers = frame()->document()->markers()->markersInRange(caretRange.get(), DocumentMarker::MisspellingMarkers());
   1251     if (markers.size() < 1 || markers[0]->startOffset() >= markers[0]->endOffset())
   1252         return;
   1253     RefPtr<Range> markerRange = Range::create(caretRange->ownerDocument(), caretRange->startContainer(), markers[0]->startOffset(), caretRange->endContainer(), markers[0]->endOffset());
   1254     if (!markerRange)
   1255         return;
   1256     frame()->selection().setSelection(markerRange.get(), CharacterGranularity);
   1257     frame()->editor().replaceSelectionWithText(text, false, false);
   1258 }
   1259 
   1260 void WebFrameImpl::removeSpellingMarkers()
   1261 {
   1262     frame()->document()->markers()->removeMarkers(DocumentMarker::MisspellingMarkers());
   1263 }
   1264 
   1265 bool WebFrameImpl::hasSelection() const
   1266 {
   1267     WebPluginContainerImpl* pluginContainer = pluginContainerFromFrame(frame());
   1268     if (pluginContainer)
   1269         return pluginContainer->plugin()->hasSelection();
   1270 
   1271     // frame()->selection()->isNone() never returns true.
   1272     return frame()->selection().start() != frame()->selection().end();
   1273 }
   1274 
   1275 WebRange WebFrameImpl::selectionRange() const
   1276 {
   1277     return frame()->selection().toNormalizedRange();
   1278 }
   1279 
   1280 WebString WebFrameImpl::selectionAsText() const
   1281 {
   1282     WebPluginContainerImpl* pluginContainer = pluginContainerFromFrame(frame());
   1283     if (pluginContainer)
   1284         return pluginContainer->plugin()->selectionAsText();
   1285 
   1286     RefPtr<Range> range = frame()->selection().toNormalizedRange();
   1287     if (!range)
   1288         return WebString();
   1289 
   1290     String text = range->text();
   1291 #if OS(WIN)
   1292     replaceNewlinesWithWindowsStyleNewlines(text);
   1293 #endif
   1294     replaceNBSPWithSpace(text);
   1295     return text;
   1296 }
   1297 
   1298 WebString WebFrameImpl::selectionAsMarkup() const
   1299 {
   1300     WebPluginContainerImpl* pluginContainer = pluginContainerFromFrame(frame());
   1301     if (pluginContainer)
   1302         return pluginContainer->plugin()->selectionAsMarkup();
   1303 
   1304     RefPtr<Range> range = frame()->selection().toNormalizedRange();
   1305     if (!range)
   1306         return WebString();
   1307 
   1308     return createMarkup(range.get(), 0, AnnotateForInterchange, false, ResolveNonLocalURLs);
   1309 }
   1310 
   1311 void WebFrameImpl::selectWordAroundPosition(Frame* frame, VisiblePosition position)
   1312 {
   1313     VisibleSelection selection(position);
   1314     selection.expandUsingGranularity(WordGranularity);
   1315 
   1316     TextGranularity granularity = selection.isRange() ? WordGranularity : CharacterGranularity;
   1317     frame->selection().setSelection(selection, granularity);
   1318 }
   1319 
   1320 bool WebFrameImpl::selectWordAroundCaret()
   1321 {
   1322     FrameSelection& selection = frame()->selection();
   1323     ASSERT(!selection.isNone());
   1324     if (selection.isNone() || selection.isRange())
   1325         return false;
   1326     selectWordAroundPosition(frame(), selection.selection().visibleStart());
   1327     return true;
   1328 }
   1329 
   1330 void WebFrameImpl::selectRange(const WebPoint& base, const WebPoint& extent)
   1331 {
   1332     moveRangeSelection(base, extent);
   1333 }
   1334 
   1335 void WebFrameImpl::selectRange(const WebRange& webRange)
   1336 {
   1337     if (RefPtr<Range> range = static_cast<PassRefPtr<Range> >(webRange))
   1338         frame()->selection().setSelectedRange(range.get(), WebCore::VP_DEFAULT_AFFINITY, false);
   1339 }
   1340 
   1341 void WebFrameImpl::moveRangeSelection(const WebPoint& base, const WebPoint& extent)
   1342 {
   1343     VisiblePosition basePosition = visiblePositionForWindowPoint(base);
   1344     VisiblePosition extentPosition = visiblePositionForWindowPoint(extent);
   1345     VisibleSelection newSelection = VisibleSelection(basePosition, extentPosition);
   1346     frame()->selection().setSelection(newSelection, CharacterGranularity);
   1347 }
   1348 
   1349 void WebFrameImpl::moveCaretSelection(const WebPoint& point)
   1350 {
   1351     Element* editable = frame()->selection().rootEditableElement();
   1352     if (!editable)
   1353         return;
   1354 
   1355     VisiblePosition position = visiblePositionForWindowPoint(point);
   1356     frame()->selection().moveTo(position, UserTriggered);
   1357 }
   1358 
   1359 void WebFrameImpl::setCaretVisible(bool visible)
   1360 {
   1361     frame()->selection().setCaretVisible(visible);
   1362 }
   1363 
   1364 VisiblePosition WebFrameImpl::visiblePositionForWindowPoint(const WebPoint& point)
   1365 {
   1366     FloatPoint unscaledPoint(point);
   1367     unscaledPoint.scale(1 / view()->pageScaleFactor(), 1 / view()->pageScaleFactor());
   1368 
   1369     HitTestRequest request = HitTestRequest::Move | HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent;
   1370     HitTestResult result(frame()->view()->windowToContents(roundedIntPoint(unscaledPoint)));
   1371     frame()->document()->renderView()->layer()->hitTest(request, result);
   1372 
   1373     if (Node* node = result.targetNode())
   1374         return frame()->selection().selection().visiblePositionRespectingEditingBoundary(result.localPoint(), node);
   1375     return VisiblePosition();
   1376 }
   1377 
   1378 int WebFrameImpl::printBegin(const WebPrintParams& printParams, const WebNode& constrainToNode)
   1379 {
   1380     ASSERT(!frame()->document()->isFrameSet());
   1381     WebPluginContainerImpl* pluginContainer = 0;
   1382     if (constrainToNode.isNull()) {
   1383         // If this is a plugin document, check if the plugin supports its own
   1384         // printing. If it does, we will delegate all printing to that.
   1385         pluginContainer = pluginContainerFromFrame(frame());
   1386     } else {
   1387         // We only support printing plugin nodes for now.
   1388         pluginContainer = toPluginContainerImpl(constrainToNode.pluginContainer());
   1389     }
   1390 
   1391     if (pluginContainer && pluginContainer->supportsPaginatedPrint())
   1392         m_printContext = adoptPtr(new ChromePluginPrintContext(frame(), pluginContainer, printParams));
   1393     else
   1394         m_printContext = adoptPtr(new ChromePrintContext(frame()));
   1395 
   1396     FloatRect rect(0, 0, static_cast<float>(printParams.printContentArea.width), static_cast<float>(printParams.printContentArea.height));
   1397     m_printContext->begin(rect.width(), rect.height());
   1398     float pageHeight;
   1399     // We ignore the overlays calculation for now since they are generated in the
   1400     // browser. pageHeight is actually an output parameter.
   1401     m_printContext->computePageRects(rect, 0, 0, 1.0, pageHeight);
   1402 
   1403     return m_printContext->pageCount();
   1404 }
   1405 
   1406 float WebFrameImpl::getPrintPageShrink(int page)
   1407 {
   1408     ASSERT(m_printContext && page >= 0);
   1409     return m_printContext->getPageShrink(page);
   1410 }
   1411 
   1412 float WebFrameImpl::printPage(int page, WebCanvas* canvas)
   1413 {
   1414 #if ENABLE(PRINTING)
   1415     ASSERT(m_printContext && page >= 0 && frame() && frame()->document());
   1416 
   1417     GraphicsContext graphicsContext(canvas);
   1418     graphicsContext.setPrinting(true);
   1419     return m_printContext->spoolPage(graphicsContext, page);
   1420 #else
   1421     return 0;
   1422 #endif
   1423 }
   1424 
   1425 void WebFrameImpl::printEnd()
   1426 {
   1427     ASSERT(m_printContext);
   1428     m_printContext->end();
   1429     m_printContext.clear();
   1430 }
   1431 
   1432 bool WebFrameImpl::isPrintScalingDisabledForPlugin(const WebNode& node)
   1433 {
   1434     WebPluginContainerImpl* pluginContainer =  node.isNull() ? pluginContainerFromFrame(frame()) : toPluginContainerImpl(node.pluginContainer());
   1435 
   1436     if (!pluginContainer || !pluginContainer->supportsPaginatedPrint())
   1437         return false;
   1438 
   1439     return pluginContainer->isPrintScalingDisabled();
   1440 }
   1441 
   1442 bool WebFrameImpl::hasCustomPageSizeStyle(int pageIndex)
   1443 {
   1444     return frame()->document()->styleForPage(pageIndex)->pageSizeType() != PAGE_SIZE_AUTO;
   1445 }
   1446 
   1447 bool WebFrameImpl::isPageBoxVisible(int pageIndex)
   1448 {
   1449     return frame()->document()->isPageBoxVisible(pageIndex);
   1450 }
   1451 
   1452 void WebFrameImpl::pageSizeAndMarginsInPixels(int pageIndex, WebSize& pageSize, int& marginTop, int& marginRight, int& marginBottom, int& marginLeft)
   1453 {
   1454     IntSize size = pageSize;
   1455     frame()->document()->pageSizeAndMarginsInPixels(pageIndex, size, marginTop, marginRight, marginBottom, marginLeft);
   1456     pageSize = size;
   1457 }
   1458 
   1459 WebString WebFrameImpl::pageProperty(const WebString& propertyName, int pageIndex)
   1460 {
   1461     ASSERT(m_printContext);
   1462     return m_printContext->pageProperty(frame(), propertyName.utf8().data(), pageIndex);
   1463 }
   1464 
   1465 bool WebFrameImpl::find(int identifier, const WebString& searchText, const WebFindOptions& options, bool wrapWithinFrame, WebRect* selectionRect)
   1466 {
   1467     if (!frame() || !frame()->page())
   1468         return false;
   1469 
   1470     WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl();
   1471 
   1472     if (!options.findNext)
   1473         frame()->page()->unmarkAllTextMatches();
   1474     else
   1475         setMarkerActive(m_activeMatch.get(), false);
   1476 
   1477     if (m_activeMatch && &m_activeMatch->ownerDocument() != frame()->document())
   1478         m_activeMatch = 0;
   1479 
   1480     // If the user has selected something since the last Find operation we want
   1481     // to start from there. Otherwise, we start searching from where the last Find
   1482     // operation left off (either a Find or a FindNext operation).
   1483     VisibleSelection selection(frame()->selection().selection());
   1484     bool activeSelection = !selection.isNone();
   1485     if (activeSelection) {
   1486         m_activeMatch = selection.firstRange().get();
   1487         frame()->selection().clear();
   1488     }
   1489 
   1490     ASSERT(frame() && frame()->view());
   1491     const FindOptions findOptions = (options.forward ? 0 : Backwards)
   1492         | (options.matchCase ? 0 : CaseInsensitive)
   1493         | (wrapWithinFrame ? WrapAround : 0)
   1494         | (options.wordStart ? AtWordStarts : 0)
   1495         | (options.medialCapitalAsWordStart ? TreatMedialCapitalAsWordStart : 0)
   1496         | (options.findNext ? 0 : StartInSelection);
   1497     m_activeMatch = frame()->editor().findStringAndScrollToVisible(searchText, m_activeMatch.get(), findOptions);
   1498 
   1499     if (!m_activeMatch) {
   1500         // If we're finding next the next active match might not be in the current frame.
   1501         // In this case we don't want to clear the matches cache.
   1502         if (!options.findNext)
   1503             clearFindMatchesCache();
   1504         invalidateArea(InvalidateAll);
   1505         return false;
   1506     }
   1507 
   1508 #if OS(ANDROID)
   1509     viewImpl()->zoomToFindInPageRect(frameView()->contentsToWindow(enclosingIntRect(RenderObject::absoluteBoundingBoxRectForRange(m_activeMatch.get()))));
   1510 #endif
   1511 
   1512     setMarkerActive(m_activeMatch.get(), true);
   1513     WebFrameImpl* oldActiveFrame = mainFrameImpl->m_currentActiveMatchFrame;
   1514     mainFrameImpl->m_currentActiveMatchFrame = this;
   1515 
   1516     // Make sure no node is focused. See http://crbug.com/38700.
   1517     frame()->document()->setFocusedElement(0);
   1518 
   1519     if (!options.findNext || activeSelection) {
   1520         // This is either a Find operation or a Find-next from a new start point
   1521         // due to a selection, so we set the flag to ask the scoping effort
   1522         // to find the active rect for us and report it back to the UI.
   1523         m_locatingActiveRect = true;
   1524     } else {
   1525         if (oldActiveFrame != this) {
   1526             if (options.forward)
   1527                 m_activeMatchIndexInCurrentFrame = 0;
   1528             else
   1529                 m_activeMatchIndexInCurrentFrame = m_lastMatchCount - 1;
   1530         } else {
   1531             if (options.forward)
   1532                 ++m_activeMatchIndexInCurrentFrame;
   1533             else
   1534                 --m_activeMatchIndexInCurrentFrame;
   1535 
   1536             if (m_activeMatchIndexInCurrentFrame + 1 > m_lastMatchCount)
   1537                 m_activeMatchIndexInCurrentFrame = 0;
   1538             if (m_activeMatchIndexInCurrentFrame == -1)
   1539                 m_activeMatchIndexInCurrentFrame = m_lastMatchCount - 1;
   1540         }
   1541         if (selectionRect) {
   1542             *selectionRect = frameView()->contentsToWindow(m_activeMatch->boundingBox());
   1543             reportFindInPageSelection(*selectionRect, m_activeMatchIndexInCurrentFrame + 1, identifier);
   1544         }
   1545     }
   1546 
   1547     return true;
   1548 }
   1549 
   1550 void WebFrameImpl::stopFinding(bool clearSelection)
   1551 {
   1552     if (!clearSelection)
   1553         setFindEndstateFocusAndSelection();
   1554     cancelPendingScopingEffort();
   1555 
   1556     // Remove all markers for matches found and turn off the highlighting.
   1557     frame()->document()->markers()->removeMarkers(DocumentMarker::TextMatch);
   1558     frame()->editor().setMarkedTextMatchesAreHighlighted(false);
   1559     clearFindMatchesCache();
   1560 
   1561     // Let the frame know that we don't want tickmarks or highlighting anymore.
   1562     invalidateArea(InvalidateAll);
   1563 }
   1564 
   1565 void WebFrameImpl::scopeStringMatches(int identifier, const WebString& searchText, const WebFindOptions& options, bool reset)
   1566 {
   1567     if (reset) {
   1568         // This is a brand new search, so we need to reset everything.
   1569         // Scoping is just about to begin.
   1570         m_scopingInProgress = true;
   1571 
   1572         // Need to keep the current identifier locally in order to finish the
   1573         // request in case the frame is detached during the process.
   1574         m_findRequestIdentifier = identifier;
   1575 
   1576         // Clear highlighting for this frame.
   1577         if (frame() && frame()->page() && frame()->editor().markedTextMatchesAreHighlighted())
   1578             frame()->page()->unmarkAllTextMatches();
   1579 
   1580         // Clear the tickmarks and results cache.
   1581         clearFindMatchesCache();
   1582 
   1583         // Clear the counters from last operation.
   1584         m_lastMatchCount = 0;
   1585         m_nextInvalidateAfter = 0;
   1586 
   1587         m_resumeScopingFromRange = 0;
   1588 
   1589         // The view might be null on detached frames.
   1590         if (frame() && frame()->page())
   1591             viewImpl()->mainFrameImpl()->m_framesScopingCount++;
   1592 
   1593         // Now, defer scoping until later to allow find operation to finish quickly.
   1594         scopeStringMatchesSoon(identifier, searchText, options, false); // false means just reset, so don't do it again.
   1595         return;
   1596     }
   1597 
   1598     if (!shouldScopeMatches(searchText)) {
   1599         // Note that we want to defer the final update when resetting even if shouldScopeMatches returns false.
   1600         // This is done in order to prevent sending a final message based only on the results of the first frame
   1601         // since m_framesScopingCount would be 0 as other frames have yet to reset.
   1602         finishCurrentScopingEffort(identifier);
   1603         return;
   1604     }
   1605 
   1606     WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl();
   1607     RefPtr<Range> searchRange(rangeOfContents(frame()->document()));
   1608 
   1609     Node* originalEndContainer = searchRange->endContainer();
   1610     int originalEndOffset = searchRange->endOffset();
   1611 
   1612     TrackExceptionState exceptionState, exceptionState2;
   1613     if (m_resumeScopingFromRange) {
   1614         // This is a continuation of a scoping operation that timed out and didn't
   1615         // complete last time around, so we should start from where we left off.
   1616         searchRange->setStart(m_resumeScopingFromRange->startContainer(), m_resumeScopingFromRange->startOffset(exceptionState2) + 1, exceptionState);
   1617         if (exceptionState.hadException() || exceptionState2.hadException()) {
   1618             if (exceptionState2.hadException()) // A non-zero |exceptionState| happens when navigating during search.
   1619                 ASSERT_NOT_REACHED();
   1620             return;
   1621         }
   1622     }
   1623 
   1624     // This timeout controls how long we scope before releasing control.  This
   1625     // value does not prevent us from running for longer than this, but it is
   1626     // periodically checked to see if we have exceeded our allocated time.
   1627     const double maxScopingDuration = 0.1; // seconds
   1628 
   1629     int matchCount = 0;
   1630     bool timedOut = false;
   1631     double startTime = currentTime();
   1632     do {
   1633         // Find next occurrence of the search string.
   1634         // FIXME: (http://b/1088245) This WebKit operation may run for longer
   1635         // than the timeout value, and is not interruptible as it is currently
   1636         // written. We may need to rewrite it with interruptibility in mind, or
   1637         // find an alternative.
   1638         RefPtr<Range> resultRange(findPlainText(searchRange.get(),
   1639                                                 searchText,
   1640                                                 options.matchCase ? 0 : CaseInsensitive));
   1641         if (resultRange->collapsed(exceptionState)) {
   1642             if (!resultRange->startContainer()->isInShadowTree())
   1643                 break;
   1644 
   1645             searchRange->setStartAfter(
   1646                 resultRange->startContainer()->deprecatedShadowAncestorNode(), exceptionState);
   1647             searchRange->setEnd(originalEndContainer, originalEndOffset, exceptionState);
   1648             continue;
   1649         }
   1650 
   1651         ++matchCount;
   1652 
   1653         // Catch a special case where Find found something but doesn't know what
   1654         // the bounding box for it is. In this case we set the first match we find
   1655         // as the active rect.
   1656         IntRect resultBounds = resultRange->boundingBox();
   1657         IntRect activeSelectionRect;
   1658         if (m_locatingActiveRect) {
   1659             activeSelectionRect = m_activeMatch.get() ?
   1660                 m_activeMatch->boundingBox() : resultBounds;
   1661         }
   1662 
   1663         // If the Find function found a match it will have stored where the
   1664         // match was found in m_activeSelectionRect on the current frame. If we
   1665         // find this rect during scoping it means we have found the active
   1666         // tickmark.
   1667         bool foundActiveMatch = false;
   1668         if (m_locatingActiveRect && (activeSelectionRect == resultBounds)) {
   1669             // We have found the active tickmark frame.
   1670             mainFrameImpl->m_currentActiveMatchFrame = this;
   1671             foundActiveMatch = true;
   1672             // We also know which tickmark is active now.
   1673             m_activeMatchIndexInCurrentFrame = matchCount - 1;
   1674             // To stop looking for the active tickmark, we set this flag.
   1675             m_locatingActiveRect = false;
   1676 
   1677             // Notify browser of new location for the selected rectangle.
   1678             reportFindInPageSelection(
   1679                 frameView()->contentsToWindow(resultBounds),
   1680                 m_activeMatchIndexInCurrentFrame + 1,
   1681                 identifier);
   1682         }
   1683 
   1684         addMarker(resultRange.get(), foundActiveMatch);
   1685 
   1686         m_findMatchesCache.append(FindMatch(resultRange.get(), m_lastMatchCount + matchCount));
   1687 
   1688         // Set the new start for the search range to be the end of the previous
   1689         // result range. There is no need to use a VisiblePosition here,
   1690         // since findPlainText will use a TextIterator to go over the visible
   1691         // text nodes.
   1692         searchRange->setStart(resultRange->endContainer(exceptionState), resultRange->endOffset(exceptionState), exceptionState);
   1693 
   1694         Node* shadowTreeRoot = searchRange->shadowRoot();
   1695         if (searchRange->collapsed(exceptionState) && shadowTreeRoot)
   1696             searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->childNodeCount(), exceptionState);
   1697 
   1698         m_resumeScopingFromRange = resultRange;
   1699         timedOut = (currentTime() - startTime) >= maxScopingDuration;
   1700     } while (!timedOut);
   1701 
   1702     // Remember what we search for last time, so we can skip searching if more
   1703     // letters are added to the search string (and last outcome was 0).
   1704     m_lastSearchString = searchText;
   1705 
   1706     if (matchCount > 0) {
   1707         frame()->editor().setMarkedTextMatchesAreHighlighted(true);
   1708 
   1709         m_lastMatchCount += matchCount;
   1710 
   1711         // Let the mainframe know how much we found during this pass.
   1712         mainFrameImpl->increaseMatchCount(matchCount, identifier);
   1713     }
   1714 
   1715     if (timedOut) {
   1716         // If we found anything during this pass, we should redraw. However, we
   1717         // don't want to spam too much if the page is extremely long, so if we
   1718         // reach a certain point we start throttling the redraw requests.
   1719         if (matchCount > 0)
   1720             invalidateIfNecessary();
   1721 
   1722         // Scoping effort ran out of time, lets ask for another time-slice.
   1723         scopeStringMatchesSoon(
   1724             identifier,
   1725             searchText,
   1726             options,
   1727             false); // don't reset.
   1728         return; // Done for now, resume work later.
   1729     }
   1730 
   1731     finishCurrentScopingEffort(identifier);
   1732 }
   1733 
   1734 void WebFrameImpl::flushCurrentScopingEffort(int identifier)
   1735 {
   1736     if (!frame() || !frame()->page())
   1737         return;
   1738 
   1739     WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl();
   1740 
   1741     // This frame has no further scoping left, so it is done. Other frames might,
   1742     // of course, continue to scope matches.
   1743     mainFrameImpl->m_framesScopingCount--;
   1744 
   1745     // If this is the last frame to finish scoping we need to trigger the final
   1746     // update to be sent.
   1747     if (!mainFrameImpl->m_framesScopingCount)
   1748         mainFrameImpl->increaseMatchCount(0, identifier);
   1749 }
   1750 
   1751 void WebFrameImpl::finishCurrentScopingEffort(int identifier)
   1752 {
   1753     flushCurrentScopingEffort(identifier);
   1754 
   1755     m_scopingInProgress = false;
   1756     m_lastFindRequestCompletedWithNoMatches = !m_lastMatchCount;
   1757 
   1758     // This frame is done, so show any scrollbar tickmarks we haven't drawn yet.
   1759     invalidateArea(InvalidateScrollbar);
   1760 }
   1761 
   1762 void WebFrameImpl::cancelPendingScopingEffort()
   1763 {
   1764     deleteAllValues(m_deferredScopingWork);
   1765     m_deferredScopingWork.clear();
   1766 
   1767     m_activeMatchIndexInCurrentFrame = -1;
   1768 
   1769     // Last request didn't complete.
   1770     if (m_scopingInProgress)
   1771         m_lastFindRequestCompletedWithNoMatches = false;
   1772 
   1773     m_scopingInProgress = false;
   1774 }
   1775 
   1776 void WebFrameImpl::increaseMatchCount(int count, int identifier)
   1777 {
   1778     // This function should only be called on the mainframe.
   1779     ASSERT(!parent());
   1780 
   1781     if (count)
   1782         ++m_findMatchMarkersVersion;
   1783 
   1784     m_totalMatchCount += count;
   1785 
   1786     // Update the UI with the latest findings.
   1787     if (client())
   1788         client()->reportFindInPageMatchCount(identifier, m_totalMatchCount, !m_framesScopingCount);
   1789 }
   1790 
   1791 void WebFrameImpl::reportFindInPageSelection(const WebRect& selectionRect, int activeMatchOrdinal, int identifier)
   1792 {
   1793     // Update the UI with the latest selection rect.
   1794     if (client())
   1795         client()->reportFindInPageSelection(identifier, ordinalOfFirstMatchForFrame(this) + activeMatchOrdinal, selectionRect);
   1796 }
   1797 
   1798 void WebFrameImpl::resetMatchCount()
   1799 {
   1800     if (m_totalMatchCount > 0)
   1801         ++m_findMatchMarkersVersion;
   1802 
   1803     m_totalMatchCount = 0;
   1804     m_framesScopingCount = 0;
   1805 }
   1806 
   1807 void WebFrameImpl::sendOrientationChangeEvent(int orientation)
   1808 {
   1809 #if ENABLE(ORIENTATION_EVENTS)
   1810     if (frame())
   1811         frame()->sendOrientationChangeEvent(orientation);
   1812 #endif
   1813 }
   1814 
   1815 void WebFrameImpl::dispatchMessageEventWithOriginCheck(const WebSecurityOrigin& intendedTargetOrigin, const WebDOMEvent& event)
   1816 {
   1817     ASSERT(!event.isNull());
   1818     frame()->domWindow()->dispatchMessageEventWithOriginCheck(intendedTargetOrigin.get(), event, 0);
   1819 }
   1820 
   1821 int WebFrameImpl::findMatchMarkersVersion() const
   1822 {
   1823     ASSERT(!parent());
   1824     return m_findMatchMarkersVersion;
   1825 }
   1826 
   1827 void WebFrameImpl::clearFindMatchesCache()
   1828 {
   1829     if (!m_findMatchesCache.isEmpty())
   1830         viewImpl()->mainFrameImpl()->m_findMatchMarkersVersion++;
   1831 
   1832     m_findMatchesCache.clear();
   1833     m_findMatchRectsAreValid = false;
   1834 }
   1835 
   1836 bool WebFrameImpl::isActiveMatchFrameValid() const
   1837 {
   1838     WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl();
   1839     WebFrameImpl* activeMatchFrame = mainFrameImpl->activeMatchFrame();
   1840     return activeMatchFrame && activeMatchFrame->m_activeMatch && activeMatchFrame->frame()->tree().isDescendantOf(mainFrameImpl->frame());
   1841 }
   1842 
   1843 void WebFrameImpl::updateFindMatchRects()
   1844 {
   1845     IntSize currentContentsSize = contentsSize();
   1846     if (m_contentsSizeForCurrentFindMatchRects != currentContentsSize) {
   1847         m_contentsSizeForCurrentFindMatchRects = currentContentsSize;
   1848         m_findMatchRectsAreValid = false;
   1849     }
   1850 
   1851     size_t deadMatches = 0;
   1852     for (Vector<FindMatch>::iterator it = m_findMatchesCache.begin(); it != m_findMatchesCache.end(); ++it) {
   1853         if (!it->m_range->boundaryPointsValid() || !it->m_range->startContainer()->inDocument())
   1854             it->m_rect = FloatRect();
   1855         else if (!m_findMatchRectsAreValid)
   1856             it->m_rect = findInPageRectFromRange(it->m_range.get());
   1857 
   1858         if (it->m_rect.isEmpty())
   1859             ++deadMatches;
   1860     }
   1861 
   1862     // Remove any invalid matches from the cache.
   1863     if (deadMatches) {
   1864         Vector<FindMatch> filteredMatches;
   1865         filteredMatches.reserveCapacity(m_findMatchesCache.size() - deadMatches);
   1866 
   1867         for (Vector<FindMatch>::const_iterator it = m_findMatchesCache.begin(); it != m_findMatchesCache.end(); ++it)
   1868             if (!it->m_rect.isEmpty())
   1869                 filteredMatches.append(*it);
   1870 
   1871         m_findMatchesCache.swap(filteredMatches);
   1872     }
   1873 
   1874     // Invalidate the rects in child frames. Will be updated later during traversal.
   1875     if (!m_findMatchRectsAreValid)
   1876         for (WebFrame* child = firstChild(); child; child = child->nextSibling())
   1877             toWebFrameImpl(child)->m_findMatchRectsAreValid = false;
   1878 
   1879     m_findMatchRectsAreValid = true;
   1880 }
   1881 
   1882 WebFloatRect WebFrameImpl::activeFindMatchRect()
   1883 {
   1884     ASSERT(!parent());
   1885 
   1886     if (!isActiveMatchFrameValid())
   1887         return WebFloatRect();
   1888 
   1889     return WebFloatRect(findInPageRectFromRange(m_currentActiveMatchFrame->m_activeMatch.get()));
   1890 }
   1891 
   1892 void WebFrameImpl::findMatchRects(WebVector<WebFloatRect>& outputRects)
   1893 {
   1894     ASSERT(!parent());
   1895 
   1896     Vector<WebFloatRect> matchRects;
   1897     for (WebFrameImpl* frame = this; frame; frame = toWebFrameImpl(frame->traverseNext(false)))
   1898         frame->appendFindMatchRects(matchRects);
   1899 
   1900     outputRects = matchRects;
   1901 }
   1902 
   1903 void WebFrameImpl::appendFindMatchRects(Vector<WebFloatRect>& frameRects)
   1904 {
   1905     updateFindMatchRects();
   1906     frameRects.reserveCapacity(frameRects.size() + m_findMatchesCache.size());
   1907     for (Vector<FindMatch>::const_iterator it = m_findMatchesCache.begin(); it != m_findMatchesCache.end(); ++it) {
   1908         ASSERT(!it->m_rect.isEmpty());
   1909         frameRects.append(it->m_rect);
   1910     }
   1911 }
   1912 
   1913 int WebFrameImpl::selectNearestFindMatch(const WebFloatPoint& point, WebRect* selectionRect)
   1914 {
   1915     ASSERT(!parent());
   1916 
   1917     WebFrameImpl* bestFrame = 0;
   1918     int indexInBestFrame = -1;
   1919     float distanceInBestFrame = FLT_MAX;
   1920 
   1921     for (WebFrameImpl* frame = this; frame; frame = toWebFrameImpl(frame->traverseNext(false))) {
   1922         float distanceInFrame;
   1923         int indexInFrame = frame->nearestFindMatch(point, distanceInFrame);
   1924         if (distanceInFrame < distanceInBestFrame) {
   1925             bestFrame = frame;
   1926             indexInBestFrame = indexInFrame;
   1927             distanceInBestFrame = distanceInFrame;
   1928         }
   1929     }
   1930 
   1931     if (indexInBestFrame != -1)
   1932         return bestFrame->selectFindMatch(static_cast<unsigned>(indexInBestFrame), selectionRect);
   1933 
   1934     return -1;
   1935 }
   1936 
   1937 int WebFrameImpl::nearestFindMatch(const FloatPoint& point, float& distanceSquared)
   1938 {
   1939     updateFindMatchRects();
   1940 
   1941     int nearest = -1;
   1942     distanceSquared = FLT_MAX;
   1943     for (size_t i = 0; i < m_findMatchesCache.size(); ++i) {
   1944         ASSERT(!m_findMatchesCache[i].m_rect.isEmpty());
   1945         FloatSize offset = point - m_findMatchesCache[i].m_rect.center();
   1946         float width = offset.width();
   1947         float height = offset.height();
   1948         float currentDistanceSquared = width * width + height * height;
   1949         if (currentDistanceSquared < distanceSquared) {
   1950             nearest = i;
   1951             distanceSquared = currentDistanceSquared;
   1952         }
   1953     }
   1954     return nearest;
   1955 }
   1956 
   1957 int WebFrameImpl::selectFindMatch(unsigned index, WebRect* selectionRect)
   1958 {
   1959     ASSERT_WITH_SECURITY_IMPLICATION(index < m_findMatchesCache.size());
   1960 
   1961     RefPtr<Range> range = m_findMatchesCache[index].m_range;
   1962     if (!range->boundaryPointsValid() || !range->startContainer()->inDocument())
   1963         return -1;
   1964 
   1965     // Check if the match is already selected.
   1966     WebFrameImpl* activeMatchFrame = viewImpl()->mainFrameImpl()->m_currentActiveMatchFrame;
   1967     if (this != activeMatchFrame || !m_activeMatch || !areRangesEqual(m_activeMatch.get(), range.get())) {
   1968         if (isActiveMatchFrameValid())
   1969             activeMatchFrame->setMarkerActive(activeMatchFrame->m_activeMatch.get(), false);
   1970 
   1971         m_activeMatchIndexInCurrentFrame = m_findMatchesCache[index].m_ordinal - 1;
   1972 
   1973         // Set this frame as the active frame (the one with the active highlight).
   1974         viewImpl()->mainFrameImpl()->m_currentActiveMatchFrame = this;
   1975         viewImpl()->setFocusedFrame(this);
   1976 
   1977         m_activeMatch = range.release();
   1978         setMarkerActive(m_activeMatch.get(), true);
   1979 
   1980         // Clear any user selection, to make sure Find Next continues on from the match we just activated.
   1981         frame()->selection().clear();
   1982 
   1983         // Make sure no node is focused. See http://crbug.com/38700.
   1984         frame()->document()->setFocusedElement(0);
   1985     }
   1986 
   1987     IntRect activeMatchRect;
   1988     IntRect activeMatchBoundingBox = enclosingIntRect(RenderObject::absoluteBoundingBoxRectForRange(m_activeMatch.get()));
   1989 
   1990     if (!activeMatchBoundingBox.isEmpty()) {
   1991         if (m_activeMatch->firstNode() && m_activeMatch->firstNode()->renderer())
   1992             m_activeMatch->firstNode()->renderer()->scrollRectToVisible(activeMatchBoundingBox,
   1993                     ScrollAlignment::alignCenterIfNeeded, ScrollAlignment::alignCenterIfNeeded);
   1994 
   1995         // Zoom to the active match.
   1996         activeMatchRect = frameView()->contentsToWindow(activeMatchBoundingBox);
   1997         viewImpl()->zoomToFindInPageRect(activeMatchRect);
   1998     }
   1999 
   2000     if (selectionRect)
   2001         *selectionRect = activeMatchRect;
   2002 
   2003     return ordinalOfFirstMatchForFrame(this) + m_activeMatchIndexInCurrentFrame + 1;
   2004 }
   2005 
   2006 WebString WebFrameImpl::contentAsText(size_t maxChars) const
   2007 {
   2008     if (!frame())
   2009         return WebString();
   2010     StringBuilder text;
   2011     frameContentAsPlainText(maxChars, frame(), text);
   2012     return text.toString();
   2013 }
   2014 
   2015 WebString WebFrameImpl::contentAsMarkup() const
   2016 {
   2017     if (!frame())
   2018         return WebString();
   2019     return createFullMarkup(frame()->document());
   2020 }
   2021 
   2022 WebString WebFrameImpl::renderTreeAsText(RenderAsTextControls toShow) const
   2023 {
   2024     RenderAsTextBehavior behavior = RenderAsTextBehaviorNormal;
   2025 
   2026     if (toShow & RenderAsTextDebug)
   2027         behavior |= RenderAsTextShowCompositedLayers | RenderAsTextShowAddresses | RenderAsTextShowIDAndClass | RenderAsTextShowLayerNesting;
   2028 
   2029     if (toShow & RenderAsTextPrinting)
   2030         behavior |= RenderAsTextPrintingMode;
   2031 
   2032     return externalRepresentation(frame(), behavior);
   2033 }
   2034 
   2035 WebString WebFrameImpl::markerTextForListItem(const WebElement& webElement) const
   2036 {
   2037     return WebCore::markerTextForListItem(const_cast<Element*>(webElement.constUnwrap<Element>()));
   2038 }
   2039 
   2040 void WebFrameImpl::printPagesWithBoundaries(WebCanvas* canvas, const WebSize& pageSizeInPixels)
   2041 {
   2042     ASSERT(m_printContext);
   2043 
   2044     GraphicsContext graphicsContext(canvas);
   2045     graphicsContext.setPrinting(true);
   2046 
   2047     m_printContext->spoolAllPagesWithBoundaries(graphicsContext, FloatSize(pageSizeInPixels.width, pageSizeInPixels.height));
   2048 }
   2049 
   2050 WebRect WebFrameImpl::selectionBoundsRect() const
   2051 {
   2052     return hasSelection() ? WebRect(IntRect(frame()->selection().bounds(false))) : WebRect();
   2053 }
   2054 
   2055 bool WebFrameImpl::selectionStartHasSpellingMarkerFor(int from, int length) const
   2056 {
   2057     if (!frame())
   2058         return false;
   2059     return frame()->spellChecker().selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length);
   2060 }
   2061 
   2062 WebString WebFrameImpl::layerTreeAsText(bool showDebugInfo) const
   2063 {
   2064     if (!frame())
   2065         return WebString();
   2066 
   2067     return WebString(frame()->layerTreeAsText(showDebugInfo ? LayerTreeIncludesDebugInfo : LayerTreeNormal));
   2068 }
   2069 
   2070 // WebFrameImpl public ---------------------------------------------------------
   2071 
   2072 WebFrame* WebFrame::create(WebFrameClient* client)
   2073 {
   2074     return WebFrameImpl::create(client);
   2075 }
   2076 
   2077 WebFrame* WebFrame::create(WebFrameClient* client, long long embedderIdentifier)
   2078 {
   2079     return WebFrameImpl::create(client, embedderIdentifier);
   2080 }
   2081 
   2082 long long WebFrame::generateEmbedderIdentifier()
   2083 {
   2084     static long long next = 0;
   2085     // Assume that 64-bit will not wrap to -1.
   2086     return ++next;
   2087 }
   2088 
   2089 WebFrameImpl* WebFrameImpl::create(WebFrameClient* client)
   2090 {
   2091     return WebFrameImpl::create(client, generateEmbedderIdentifier());
   2092 }
   2093 
   2094 WebFrameImpl* WebFrameImpl::create(WebFrameClient* client, long long embedderIdentifier)
   2095 {
   2096     return adoptRef(new WebFrameImpl(client, embedderIdentifier)).leakRef();
   2097 }
   2098 
   2099 WebFrameImpl::WebFrameImpl(WebFrameClient* client, long long embedderIdentifier)
   2100     : FrameDestructionObserver(0)
   2101     , m_frameInit(WebFrameInit::create(this, embedderIdentifier))
   2102     , m_client(client)
   2103     , m_permissionClient(0)
   2104     , m_currentActiveMatchFrame(0)
   2105     , m_activeMatchIndexInCurrentFrame(-1)
   2106     , m_locatingActiveRect(false)
   2107     , m_resumeScopingFromRange(0)
   2108     , m_lastMatchCount(-1)
   2109     , m_totalMatchCount(-1)
   2110     , m_framesScopingCount(-1)
   2111     , m_findRequestIdentifier(-1)
   2112     , m_scopingInProgress(false)
   2113     , m_lastFindRequestCompletedWithNoMatches(false)
   2114     , m_nextInvalidateAfter(0)
   2115     , m_findMatchMarkersVersion(0)
   2116     , m_findMatchRectsAreValid(false)
   2117     , m_inputEventsScaleFactorForEmulation(1)
   2118 {
   2119     blink::Platform::current()->incrementStatsCounter(webFrameActiveCount);
   2120     frameCount++;
   2121 }
   2122 
   2123 WebFrameImpl::~WebFrameImpl()
   2124 {
   2125     blink::Platform::current()->decrementStatsCounter(webFrameActiveCount);
   2126     frameCount--;
   2127 
   2128     cancelPendingScopingEffort();
   2129 }
   2130 
   2131 void WebFrameImpl::setWebCoreFrame(WebCore::Frame* frame)
   2132 {
   2133     ASSERT(frame);
   2134     observeFrame(frame);
   2135 }
   2136 
   2137 void WebFrameImpl::initializeAsMainFrame(WebCore::Page* page)
   2138 {
   2139     m_frameInit->setPage(page);
   2140     RefPtr<Frame> mainFrame = Frame::create(m_frameInit);
   2141     setWebCoreFrame(mainFrame.get());
   2142 
   2143     // Add reference on behalf of FrameLoader. See comments in
   2144     // WebFrameLoaderClient::frameLoaderDestroyed for more info.
   2145     ref();
   2146 
   2147     // We must call init() after m_frame is assigned because it is referenced
   2148     // during init().
   2149     frame()->init();
   2150 }
   2151 
   2152 PassRefPtr<Frame> WebFrameImpl::createChildFrame(const FrameLoadRequest& request, HTMLFrameOwnerElement* ownerElement)
   2153 {
   2154     ASSERT(m_client);
   2155     WebFrameImpl* webframe = toWebFrameImpl(m_client->createChildFrame(this, request.frameName()));
   2156 
   2157     // If the embedder is returning 0 from createChildFrame(), it has not been
   2158     // updated to the new ownership semantics where the embedder creates the
   2159     // WebFrame. In that case, fall back to the old logic where the
   2160     // WebFrameImpl is created here and published back to the embedder. To
   2161     // bridge between the two ownership semantics, webframeLifetimeHack is
   2162     // needeed to balance out the refcounting.
   2163     //
   2164     // FIXME: Remove once all embedders return non-null from createChildFrame().
   2165     RefPtr<WebFrameImpl> webframeLifetimeHack;
   2166     bool mustCallDidCreateFrame = false;
   2167     if (!webframe) {
   2168         mustCallDidCreateFrame = true;
   2169         webframeLifetimeHack = adoptRef(WebFrameImpl::create(m_client));
   2170         webframe = webframeLifetimeHack.get();
   2171     }
   2172 
   2173     // Add an extra ref on behalf of the page/FrameLoader, which references the
   2174     // WebFrame via the FrameLoaderClient interface. See the comment at the top
   2175     // of this file for more info.
   2176     webframe->ref();
   2177 
   2178     webframe->m_frameInit->setPage(frame()->page());
   2179     webframe->m_frameInit->setOwnerElement(ownerElement);
   2180     RefPtr<Frame> childFrame = Frame::create(webframe->m_frameInit);
   2181     webframe->setWebCoreFrame(childFrame.get());
   2182 
   2183     childFrame->tree().setName(request.frameName());
   2184 
   2185     frame()->tree().appendChild(childFrame);
   2186 
   2187     // FIXME: Remove once all embedders return non-null from createChildFrame().
   2188     if (mustCallDidCreateFrame)
   2189         m_client->didCreateFrame(this, webframe);
   2190 
   2191     // Frame::init() can trigger onload event in the parent frame,
   2192     // which may detach this frame and trigger a null-pointer access
   2193     // in FrameTree::removeChild. Move init() after appendChild call
   2194     // so that webframe->mFrame is in the tree before triggering
   2195     // onload event handler.
   2196     // Because the event handler may set webframe->mFrame to null,
   2197     // it is necessary to check the value after calling init() and
   2198     // return without loading URL.
   2199     // NOTE: m_client will be null if this frame has been detached.
   2200     // (b:791612)
   2201     childFrame->init(); // create an empty document
   2202     if (!childFrame->tree().parent())
   2203         return 0;
   2204 
   2205     // If we're moving in the back/forward list, we might want to replace the content
   2206     // of this child frame with whatever was there at that point.
   2207     HistoryItem* childItem = 0;
   2208     if (isBackForwardLoadType(frame()->loader().loadType()) && !frame()->document()->loadEventFinished())
   2209         childItem = frame()->page()->historyController().itemForNewChildFrame(childFrame.get());
   2210 
   2211     if (childItem)
   2212         childFrame->loader().loadHistoryItem(childItem);
   2213     else
   2214         childFrame->loader().load(FrameLoadRequest(0, request.resourceRequest(), "_self"));
   2215 
   2216     // A synchronous navigation (about:blank) would have already processed
   2217     // onload, so it is possible for the frame to have already been destroyed by
   2218     // script in the page.
   2219     // NOTE: m_client will be null if this frame has been detached.
   2220     if (!childFrame->tree().parent())
   2221         return 0;
   2222 
   2223     return childFrame.release();
   2224 }
   2225 
   2226 void WebFrameImpl::didChangeContentsSize(const IntSize& size)
   2227 {
   2228     // This is only possible on the main frame.
   2229     if (m_totalMatchCount > 0) {
   2230         ASSERT(!parent());
   2231         ++m_findMatchMarkersVersion;
   2232     }
   2233 }
   2234 
   2235 void WebFrameImpl::createFrameView()
   2236 {
   2237     TRACE_EVENT0("webkit", "WebFrameImpl::createFrameView");
   2238 
   2239     ASSERT(frame()); // If frame() doesn't exist, we probably didn't init properly.
   2240 
   2241     WebViewImpl* webView = viewImpl();
   2242     bool isMainFrame = webView->mainFrameImpl()->frame() == frame();
   2243     if (isMainFrame)
   2244         webView->suppressInvalidations(true);
   2245 
   2246     frame()->createView(webView->size(), webView->baseBackgroundColor(), webView->isTransparent());
   2247     if (webView->shouldAutoResize() && isMainFrame)
   2248         frame()->view()->enableAutoSizeMode(true, webView->minAutoSize(), webView->maxAutoSize());
   2249 
   2250     frame()->view()->setInputEventsTransformForEmulation(m_inputEventsOffsetForEmulation, m_inputEventsScaleFactorForEmulation);
   2251 
   2252     if (isMainFrame)
   2253         webView->suppressInvalidations(false);
   2254 }
   2255 
   2256 WebFrameImpl* WebFrameImpl::fromFrame(Frame* frame)
   2257 {
   2258     if (!frame)
   2259         return 0;
   2260     return toFrameLoaderClientImpl(frame->loader().client())->webFrame();
   2261 }
   2262 
   2263 WebFrameImpl* WebFrameImpl::fromFrameOwnerElement(Element* element)
   2264 {
   2265     // FIXME: Why do we check specifically for <iframe> and <frame> here? Why can't we get the WebFrameImpl from an <object> element, for example.
   2266     if (!element || !element->isFrameOwnerElement() || (!element->hasTagName(HTMLNames::iframeTag) && !element->hasTagName(HTMLNames::frameTag)))
   2267         return 0;
   2268     return fromFrame(toHTMLFrameOwnerElement(element)->contentFrame());
   2269 }
   2270 
   2271 WebViewImpl* WebFrameImpl::viewImpl() const
   2272 {
   2273     if (!frame())
   2274         return 0;
   2275     return WebViewImpl::fromPage(frame()->page());
   2276 }
   2277 
   2278 WebDataSourceImpl* WebFrameImpl::dataSourceImpl() const
   2279 {
   2280     return static_cast<WebDataSourceImpl*>(dataSource());
   2281 }
   2282 
   2283 WebDataSourceImpl* WebFrameImpl::provisionalDataSourceImpl() const
   2284 {
   2285     return static_cast<WebDataSourceImpl*>(provisionalDataSource());
   2286 }
   2287 
   2288 void WebFrameImpl::setFindEndstateFocusAndSelection()
   2289 {
   2290     WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl();
   2291 
   2292     if (this == mainFrameImpl->activeMatchFrame() && m_activeMatch.get()) {
   2293         // If the user has set the selection since the match was found, we
   2294         // don't focus anything.
   2295         VisibleSelection selection(frame()->selection().selection());
   2296         if (!selection.isNone())
   2297             return;
   2298 
   2299         // Try to find the first focusable node up the chain, which will, for
   2300         // example, focus links if we have found text within the link.
   2301         Node* node = m_activeMatch->firstNode();
   2302         if (node && node->isInShadowTree()) {
   2303             Node* host = node->deprecatedShadowAncestorNode();
   2304             if (host->hasTagName(HTMLNames::inputTag) || isHTMLTextAreaElement(host))
   2305                 node = host;
   2306         }
   2307         for (; node; node = node->parentNode()) {
   2308             if (!node->isElementNode())
   2309                 continue;
   2310             Element* element = toElement(node);
   2311             if (element->isFocusable()) {
   2312                 // Found a focusable parent node. Set the active match as the
   2313                 // selection and focus to the focusable node.
   2314                 frame()->selection().setSelection(m_activeMatch.get());
   2315                 frame()->document()->setFocusedElement(element);
   2316                 return;
   2317             }
   2318         }
   2319 
   2320         // Iterate over all the nodes in the range until we find a focusable node.
   2321         // This, for example, sets focus to the first link if you search for
   2322         // text and text that is within one or more links.
   2323         node = m_activeMatch->firstNode();
   2324         for (; node && node != m_activeMatch->pastLastNode(); node = NodeTraversal::next(*node)) {
   2325             if (!node->isElementNode())
   2326                 continue;
   2327             Element* element = toElement(node);
   2328             if (element->isFocusable()) {
   2329                 frame()->document()->setFocusedElement(element);
   2330                 return;
   2331             }
   2332         }
   2333 
   2334         // No node related to the active match was focusable, so set the
   2335         // active match as the selection (so that when you end the Find session,
   2336         // you'll have the last thing you found highlighted) and make sure that
   2337         // we have nothing focused (otherwise you might have text selected but
   2338         // a link focused, which is weird).
   2339         frame()->selection().setSelection(m_activeMatch.get());
   2340         frame()->document()->setFocusedElement(0);
   2341 
   2342         // Finally clear the active match, for two reasons:
   2343         // We just finished the find 'session' and we don't want future (potentially
   2344         // unrelated) find 'sessions' operations to start at the same place.
   2345         // The WebFrameImpl could get reused and the m_activeMatch could end up pointing
   2346         // to a document that is no longer valid. Keeping an invalid reference around
   2347         // is just asking for trouble.
   2348         m_activeMatch = 0;
   2349     }
   2350 }
   2351 
   2352 void WebFrameImpl::didFail(const ResourceError& error, bool wasProvisional)
   2353 {
   2354     if (!client())
   2355         return;
   2356     WebURLError webError = error;
   2357     if (wasProvisional)
   2358         client()->didFailProvisionalLoad(this, webError);
   2359     else
   2360         client()->didFailLoad(this, webError);
   2361 }
   2362 
   2363 void WebFrameImpl::setCanHaveScrollbars(bool canHaveScrollbars)
   2364 {
   2365     frame()->view()->setCanHaveScrollbars(canHaveScrollbars);
   2366 }
   2367 
   2368 void WebFrameImpl::setInputEventsTransformForEmulation(const IntSize& offset, float contentScaleFactor)
   2369 {
   2370     m_inputEventsOffsetForEmulation = offset;
   2371     m_inputEventsScaleFactorForEmulation = contentScaleFactor;
   2372     if (frame()->view())
   2373         frame()->view()->setInputEventsTransformForEmulation(m_inputEventsOffsetForEmulation, m_inputEventsScaleFactorForEmulation);
   2374 }
   2375 
   2376 void WebFrameImpl::invalidateArea(AreaToInvalidate area)
   2377 {
   2378     ASSERT(frame() && frame()->view());
   2379     FrameView* view = frame()->view();
   2380 
   2381     if ((area & InvalidateAll) == InvalidateAll)
   2382         view->invalidateRect(view->frameRect());
   2383     else {
   2384         if ((area & InvalidateContentArea) == InvalidateContentArea) {
   2385             IntRect contentArea(
   2386                 view->x(), view->y(), view->visibleWidth(), view->visibleHeight());
   2387             IntRect frameRect = view->frameRect();
   2388             contentArea.move(-frameRect.x(), -frameRect.y());
   2389             view->invalidateRect(contentArea);
   2390         }
   2391     }
   2392 
   2393     if ((area & InvalidateScrollbar) == InvalidateScrollbar) {
   2394         // Invalidate the vertical scroll bar region for the view.
   2395         Scrollbar* scrollbar = view->verticalScrollbar();
   2396         if (scrollbar)
   2397             scrollbar->invalidate();
   2398     }
   2399 }
   2400 
   2401 void WebFrameImpl::addMarker(Range* range, bool activeMatch)
   2402 {
   2403     frame()->document()->markers()->addTextMatchMarker(range, activeMatch);
   2404 }
   2405 
   2406 void WebFrameImpl::setMarkerActive(Range* range, bool active)
   2407 {
   2408     if (!range || range->collapsed(IGNORE_EXCEPTION))
   2409         return;
   2410     frame()->document()->markers()->setMarkersActive(range, active);
   2411 }
   2412 
   2413 int WebFrameImpl::ordinalOfFirstMatchForFrame(WebFrameImpl* frame) const
   2414 {
   2415     int ordinal = 0;
   2416     WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl();
   2417     // Iterate from the main frame up to (but not including) |frame| and
   2418     // add up the number of matches found so far.
   2419     for (WebFrameImpl* it = mainFrameImpl; it != frame; it = toWebFrameImpl(it->traverseNext(true))) {
   2420         if (it->m_lastMatchCount > 0)
   2421             ordinal += it->m_lastMatchCount;
   2422     }
   2423     return ordinal;
   2424 }
   2425 
   2426 bool WebFrameImpl::shouldScopeMatches(const String& searchText)
   2427 {
   2428     // Don't scope if we can't find a frame or a view.
   2429     // The user may have closed the tab/application, so abort.
   2430     // Also ignore detached frames, as many find operations report to the main frame.
   2431     if (!frame() || !frame()->view() || !frame()->page() || !hasVisibleContent())
   2432         return false;
   2433 
   2434     ASSERT(frame()->document() && frame()->view());
   2435 
   2436     // If the frame completed the scoping operation and found 0 matches the last
   2437     // time it was searched, then we don't have to search it again if the user is
   2438     // just adding to the search string or sending the same search string again.
   2439     if (m_lastFindRequestCompletedWithNoMatches && !m_lastSearchString.isEmpty()) {
   2440         // Check to see if the search string prefixes match.
   2441         String previousSearchPrefix =
   2442             searchText.substring(0, m_lastSearchString.length());
   2443 
   2444         if (previousSearchPrefix == m_lastSearchString)
   2445             return false; // Don't search this frame, it will be fruitless.
   2446     }
   2447 
   2448     return true;
   2449 }
   2450 
   2451 void WebFrameImpl::scopeStringMatchesSoon(int identifier, const WebString& searchText, const WebFindOptions& options, bool reset)
   2452 {
   2453     m_deferredScopingWork.append(new DeferredScopeStringMatches(this, identifier, searchText, options, reset));
   2454 }
   2455 
   2456 void WebFrameImpl::callScopeStringMatches(DeferredScopeStringMatches* caller, int identifier, const WebString& searchText, const WebFindOptions& options, bool reset)
   2457 {
   2458     m_deferredScopingWork.remove(m_deferredScopingWork.find(caller));
   2459     scopeStringMatches(identifier, searchText, options, reset);
   2460 
   2461     // This needs to happen last since searchText is passed by reference.
   2462     delete caller;
   2463 }
   2464 
   2465 void WebFrameImpl::invalidateIfNecessary()
   2466 {
   2467     if (m_lastMatchCount <= m_nextInvalidateAfter)
   2468         return;
   2469 
   2470     // FIXME: (http://b/1088165) Optimize the drawing of the tickmarks and
   2471     // remove this. This calculation sets a milestone for when next to
   2472     // invalidate the scrollbar and the content area. We do this so that we
   2473     // don't spend too much time drawing the scrollbar over and over again.
   2474     // Basically, up until the first 500 matches there is no throttle.
   2475     // After the first 500 matches, we set set the milestone further and
   2476     // further out (750, 1125, 1688, 2K, 3K).
   2477     static const int startSlowingDownAfter = 500;
   2478     static const int slowdown = 750;
   2479 
   2480     int i = m_lastMatchCount / startSlowingDownAfter;
   2481     m_nextInvalidateAfter += i * slowdown;
   2482     invalidateArea(InvalidateScrollbar);
   2483 }
   2484 
   2485 void WebFrameImpl::loadJavaScriptURL(const KURL& url)
   2486 {
   2487     // This is copied from ScriptController::executeScriptIfJavaScriptURL.
   2488     // Unfortunately, we cannot just use that method since it is private, and
   2489     // it also doesn't quite behave as we require it to for bookmarklets.  The
   2490     // key difference is that we need to suppress loading the string result
   2491     // from evaluating the JS URL if executing the JS URL resulted in a
   2492     // location change.  We also allow a JS URL to be loaded even if scripts on
   2493     // the page are otherwise disabled.
   2494 
   2495     if (!frame()->document() || !frame()->page())
   2496         return;
   2497 
   2498     RefPtr<Document> ownerDocument(frame()->document());
   2499 
   2500     // Protect privileged pages against bookmarklets and other javascript manipulations.
   2501     if (SchemeRegistry::shouldTreatURLSchemeAsNotAllowingJavascriptURLs(frame()->document()->url().protocol()))
   2502         return;
   2503 
   2504     String script = decodeURLEscapeSequences(url.string().substring(strlen("javascript:")));
   2505     UserGestureIndicator gestureIndicator(DefinitelyProcessingNewUserGesture);
   2506     ScriptValue result = frame()->script().executeScriptInMainWorldAndReturnValue(ScriptSourceCode(script));
   2507 
   2508     String scriptResult;
   2509     if (!result.getString(scriptResult))
   2510         return;
   2511 
   2512     if (!frame()->navigationScheduler().locationChangePending())
   2513         frame()->document()->loader()->replaceDocument(scriptResult, ownerDocument.get());
   2514 }
   2515 
   2516 void WebFrameImpl::willDetachPage()
   2517 {
   2518     if (!frame() || !frame()->page())
   2519         return;
   2520 
   2521     // Do not expect string scoping results from any frames that got detached
   2522     // in the middle of the operation.
   2523     if (m_scopingInProgress) {
   2524 
   2525         // There is a possibility that the frame being detached was the only
   2526         // pending one. We need to make sure final replies can be sent.
   2527         flushCurrentScopingEffort(m_findRequestIdentifier);
   2528 
   2529         cancelPendingScopingEffort();
   2530     }
   2531 }
   2532 
   2533 } // namespace blink
   2534