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