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