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