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