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