9ef5002174676402ad70931451d23b77caa8ea26
[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 = TextIterator::rangeFromLocationAndLength(frame()->selection()->rootEditableElementOrDocumentElement(), markers[0]->startOffset(), markers[0]->endOffset() - markers[0]->startOffset());
1314     if (!markerRange.get() || !frame()->selection()->shouldChangeSelection(markerRange.get()))
1315         return;
1316     frame()->selection()->setSelection(markerRange.get(), CharacterGranularity);
1317     frame()->editor()->replaceSelectionWithText(text, false, true);
1318 }
1319
1320 bool WebFrameImpl::hasSelection() const
1321 {
1322     WebPluginContainerImpl* pluginContainer = pluginContainerFromFrame(frame());
1323     if (pluginContainer)
1324         return pluginContainer->plugin()->hasSelection();
1325
1326     // frame()->selection()->isNone() never returns true.
1327     return (frame()->selection()->start() != frame()->selection()->end());
1328 }
1329
1330 WebRange WebFrameImpl::selectionRange() const
1331 {
1332     return frame()->selection()->toNormalizedRange();
1333 }
1334
1335 WebString WebFrameImpl::selectionAsText() const
1336 {
1337     WebPluginContainerImpl* pluginContainer = pluginContainerFromFrame(frame());
1338     if (pluginContainer)
1339         return pluginContainer->plugin()->selectionAsText();
1340
1341     RefPtr<Range> range = frame()->selection()->toNormalizedRange();
1342     if (!range)
1343         return WebString();
1344
1345     String text = range->text();
1346 #if OS(WINDOWS)
1347     replaceNewlinesWithWindowsStyleNewlines(text);
1348 #endif
1349     replaceNBSPWithSpace(text);
1350     return text;
1351 }
1352
1353 WebString WebFrameImpl::selectionAsMarkup() const
1354 {
1355     WebPluginContainerImpl* pluginContainer = pluginContainerFromFrame(frame());
1356     if (pluginContainer)
1357         return pluginContainer->plugin()->selectionAsMarkup();
1358
1359     RefPtr<Range> range = frame()->selection()->toNormalizedRange();
1360     if (!range)
1361         return WebString();
1362
1363     return createMarkup(range.get(), 0, AnnotateForInterchange, false, ResolveNonLocalURLs);
1364 }
1365
1366 void WebFrameImpl::selectWordAroundPosition(Frame* frame, VisiblePosition position)
1367 {
1368     VisibleSelection selection(position);
1369     selection.expandUsingGranularity(WordGranularity);
1370
1371     if (frame->selection()->shouldChangeSelection(selection)) {
1372         TextGranularity granularity = selection.isRange() ? WordGranularity : CharacterGranularity;
1373         frame->selection()->setSelection(selection, granularity);
1374     }
1375 }
1376
1377 bool WebFrameImpl::selectWordAroundCaret()
1378 {
1379     FrameSelection* selection = frame()->selection();
1380     ASSERT(!selection->isNone());
1381     if (selection->isNone() || selection->isRange())
1382         return false;
1383     selectWordAroundPosition(frame(), selection->selection().visibleStart());
1384     return true;
1385 }
1386
1387 void WebFrameImpl::selectRange(const WebPoint& base, const WebPoint& extent)
1388 {
1389     IntPoint unscaledBase = base;
1390     IntPoint unscaledExtent = extent;
1391     if (frame()->page()->settings()->applyPageScaleFactorInCompositor()) {
1392         unscaledExtent.scale(1 / view()->pageScaleFactor(), 1 / view()->pageScaleFactor());
1393         unscaledBase.scale(1 / view()->pageScaleFactor(), 1 / view()->pageScaleFactor());
1394     }
1395     VisiblePosition basePosition = visiblePositionForWindowPoint(unscaledBase);
1396     VisiblePosition extentPosition = visiblePositionForWindowPoint(unscaledExtent);
1397     VisibleSelection newSelection = VisibleSelection(basePosition, extentPosition);
1398     if (frame()->selection()->shouldChangeSelection(newSelection))
1399         frame()->selection()->setSelection(newSelection, CharacterGranularity);
1400 }
1401
1402 void WebFrameImpl::selectRange(const WebRange& webRange)
1403 {
1404     if (RefPtr<Range> range = static_cast<PassRefPtr<Range> >(webRange))
1405         frame()->selection()->setSelectedRange(range.get(), WebCore::VP_DEFAULT_AFFINITY, false);
1406 }
1407
1408 void WebFrameImpl::moveCaretSelectionTowardsWindowPoint(const WebPoint& point)
1409 {
1410     IntPoint unscaledPoint(point);
1411     if (frame()->page()->settings()->applyPageScaleFactorInCompositor())
1412         unscaledPoint.scale(1 / view()->pageScaleFactor(), 1 / view()->pageScaleFactor());
1413
1414     Element* editable = frame()->selection()->rootEditableElement();
1415     if (!editable)
1416         return;
1417
1418     IntPoint contentsPoint = frame()->view()->windowToContents(unscaledPoint);
1419     LayoutPoint localPoint(editable->convertFromPage(contentsPoint));
1420     VisiblePosition position = editable->renderer()->positionForPoint(localPoint);
1421     if (frame()->selection()->shouldChangeSelection(position))
1422         frame()->selection()->moveTo(position, UserTriggered);
1423 }
1424
1425 VisiblePosition WebFrameImpl::visiblePositionForWindowPoint(const WebPoint& point)
1426 {
1427     HitTestRequest request = HitTestRequest::Move | HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping;
1428     HitTestResult result(frame()->view()->windowToContents(IntPoint(point)));
1429
1430     frame()->document()->renderView()->layer()->hitTest(request, result);
1431
1432     Node* node = result.targetNode();
1433     if (!node)
1434         return VisiblePosition();
1435     return node->renderer()->positionForPoint(result.localPoint());
1436 }
1437
1438 int WebFrameImpl::printBegin(const WebPrintParams& printParams, const WebNode& constrainToNode, bool* useBrowserOverlays)
1439 {
1440     ASSERT(!frame()->document()->isFrameSet());
1441     WebPluginContainerImpl* pluginContainer = 0;
1442     if (constrainToNode.isNull()) {
1443         // If this is a plugin document, check if the plugin supports its own
1444         // printing. If it does, we will delegate all printing to that.
1445         pluginContainer = pluginContainerFromFrame(frame());
1446     } else {
1447         // We only support printing plugin nodes for now.
1448         pluginContainer = static_cast<WebPluginContainerImpl*>(constrainToNode.pluginContainer());
1449     }
1450
1451     if (pluginContainer && pluginContainer->supportsPaginatedPrint())
1452         m_printContext = adoptPtr(new ChromePluginPrintContext(frame(), pluginContainer, printParams));
1453     else
1454         m_printContext = adoptPtr(new ChromePrintContext(frame()));
1455
1456     FloatRect rect(0, 0, static_cast<float>(printParams.printContentArea.width), static_cast<float>(printParams.printContentArea.height));
1457     m_printContext->begin(rect.width(), rect.height());
1458     float pageHeight;
1459     // We ignore the overlays calculation for now since they are generated in the
1460     // browser. pageHeight is actually an output parameter.
1461     m_printContext->computePageRects(rect, 0, 0, 1.0, pageHeight);
1462     if (useBrowserOverlays)
1463         *useBrowserOverlays = m_printContext->shouldUseBrowserOverlays();
1464
1465     return m_printContext->pageCount();
1466 }
1467
1468 float WebFrameImpl::getPrintPageShrink(int page)
1469 {
1470     ASSERT(m_printContext && page >= 0);
1471     return m_printContext->getPageShrink(page);
1472 }
1473
1474 float WebFrameImpl::printPage(int page, WebCanvas* canvas)
1475 {
1476 #if ENABLE(PRINTING)
1477     ASSERT(m_printContext && page >= 0 && frame() && frame()->document());
1478
1479     GraphicsContextBuilder builder(canvas);
1480     GraphicsContext& graphicsContext = builder.context();
1481     graphicsContext.platformContext()->setPrinting(true);
1482     return m_printContext->spoolPage(graphicsContext, page);
1483 #else
1484     return 0;
1485 #endif
1486 }
1487
1488 void WebFrameImpl::printEnd()
1489 {
1490     ASSERT(m_printContext);
1491     m_printContext->end();
1492     m_printContext.clear();
1493 }
1494
1495 bool WebFrameImpl::isPrintScalingDisabledForPlugin(const WebNode& node)
1496 {
1497     WebPluginContainerImpl* pluginContainer =  node.isNull() ? pluginContainerFromFrame(frame()) : static_cast<WebPluginContainerImpl*>(node.pluginContainer());
1498
1499     if (!pluginContainer || !pluginContainer->supportsPaginatedPrint())
1500         return false;
1501
1502     return pluginContainer->isPrintScalingDisabled();
1503 }
1504
1505 bool WebFrameImpl::hasCustomPageSizeStyle(int pageIndex)
1506 {
1507     return frame()->document()->styleForPage(pageIndex)->pageSizeType() != PAGE_SIZE_AUTO;
1508 }
1509
1510 bool WebFrameImpl::isPageBoxVisible(int pageIndex)
1511 {
1512     return frame()->document()->isPageBoxVisible(pageIndex);
1513 }
1514
1515 void WebFrameImpl::pageSizeAndMarginsInPixels(int pageIndex, WebSize& pageSize, int& marginTop, int& marginRight, int& marginBottom, int& marginLeft)
1516 {
1517     IntSize size = pageSize;
1518     frame()->document()->pageSizeAndMarginsInPixels(pageIndex, size, marginTop, marginRight, marginBottom, marginLeft);
1519     pageSize = size;
1520 }
1521
1522 WebString WebFrameImpl::pageProperty(const WebString& propertyName, int pageIndex)
1523 {
1524     ASSERT(m_printContext);
1525     return m_printContext->pageProperty(frame(), propertyName.utf8().data(), pageIndex);
1526 }
1527
1528 bool WebFrameImpl::find(int identifier, const WebString& searchText, const WebFindOptions& options, bool wrapWithinFrame, WebRect* selectionRect)
1529 {
1530     if (!frame() || !frame()->page())
1531         return false;
1532
1533     WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl();
1534
1535     if (!options.findNext)
1536         frame()->page()->unmarkAllTextMatches();
1537     else
1538         setMarkerActive(m_activeMatch.get(), false);
1539
1540     if (m_activeMatch && m_activeMatch->ownerDocument() != frame()->document())
1541         m_activeMatch = 0;
1542
1543     // If the user has selected something since the last Find operation we want
1544     // to start from there. Otherwise, we start searching from where the last Find
1545     // operation left off (either a Find or a FindNext operation).
1546     VisibleSelection selection(frame()->selection()->selection());
1547     bool activeSelection = !selection.isNone();
1548     if (activeSelection) {
1549         m_activeMatch = selection.firstRange().get();
1550         frame()->selection()->clear();
1551     }
1552
1553     ASSERT(frame() && frame()->view());
1554     const FindOptions findOptions = (options.forward ? 0 : Backwards)
1555         | (options.matchCase ? 0 : CaseInsensitive)
1556         | (wrapWithinFrame ? WrapAround : 0)
1557         | (!options.findNext ? StartInSelection : 0);
1558     m_activeMatch = frame()->editor()->findStringAndScrollToVisible(searchText, m_activeMatch.get(), findOptions);
1559
1560     if (!m_activeMatch) {
1561         // If we're finding next the next active match might not be in the current frame.
1562         // In this case we don't want to clear the matches cache.
1563         if (!options.findNext)
1564             clearFindMatchesCache();
1565         invalidateArea(InvalidateAll);
1566         return false;
1567     }
1568
1569 #if OS(ANDROID)
1570     viewImpl()->zoomToFindInPageRect(frameView()->contentsToWindow(enclosingIntRect(RenderObject::absoluteBoundingBoxRectForRange(m_activeMatch.get()))));
1571 #endif
1572
1573     setMarkerActive(m_activeMatch.get(), true);
1574     WebFrameImpl* oldActiveFrame = mainFrameImpl->m_currentActiveMatchFrame;
1575     mainFrameImpl->m_currentActiveMatchFrame = this;
1576
1577     // Make sure no node is focused. See http://crbug.com/38700.
1578     frame()->document()->setFocusedNode(0);
1579
1580     if (!options.findNext || activeSelection) {
1581         // This is either a Find operation or a Find-next from a new start point
1582         // due to a selection, so we set the flag to ask the scoping effort
1583         // to find the active rect for us and report it back to the UI.
1584         m_locatingActiveRect = true;
1585     } else {
1586         if (oldActiveFrame != this) {
1587             if (options.forward)
1588                 m_activeMatchIndexInCurrentFrame = 0;
1589             else
1590                 m_activeMatchIndexInCurrentFrame = m_lastMatchCount - 1;
1591         } else {
1592             if (options.forward)
1593                 ++m_activeMatchIndexInCurrentFrame;
1594             else
1595                 --m_activeMatchIndexInCurrentFrame;
1596
1597             if (m_activeMatchIndexInCurrentFrame + 1 > m_lastMatchCount)
1598                 m_activeMatchIndexInCurrentFrame = 0;
1599             if (m_activeMatchIndexInCurrentFrame == -1)
1600                 m_activeMatchIndexInCurrentFrame = m_lastMatchCount - 1;
1601         }
1602         if (selectionRect) {
1603             *selectionRect = frameView()->contentsToWindow(m_activeMatch->boundingBox());
1604             reportFindInPageSelection(*selectionRect, m_activeMatchIndexInCurrentFrame + 1, identifier);
1605         }
1606     }
1607
1608     return true;
1609 }
1610
1611 void WebFrameImpl::stopFinding(bool clearSelection)
1612 {
1613     if (!clearSelection)
1614         setFindEndstateFocusAndSelection();
1615     cancelPendingScopingEffort();
1616
1617     // Remove all markers for matches found and turn off the highlighting.
1618     frame()->document()->markers()->removeMarkers(DocumentMarker::TextMatch);
1619     frame()->editor()->setMarkedTextMatchesAreHighlighted(false);
1620     clearFindMatchesCache();
1621
1622     // Let the frame know that we don't want tickmarks or highlighting anymore.
1623     invalidateArea(InvalidateAll);
1624 }
1625
1626 void WebFrameImpl::scopeStringMatches(int identifier, const WebString& searchText, const WebFindOptions& options, bool reset)
1627 {
1628     if (reset) {
1629         // This is a brand new search, so we need to reset everything.
1630         // Scoping is just about to begin.
1631         m_scopingInProgress = true;
1632
1633         // Need to keep the current identifier locally in order to finish the
1634         // request in case the frame is detached during the process.
1635         m_findRequestIdentifier = identifier;
1636
1637         // Clear highlighting for this frame.
1638         if (frame() && frame()->page() && frame()->editor()->markedTextMatchesAreHighlighted())
1639             frame()->page()->unmarkAllTextMatches();
1640
1641         // Clear the tickmarks and results cache.
1642         clearFindMatchesCache();
1643
1644         // Clear the counters from last operation.
1645         m_lastMatchCount = 0;
1646         m_nextInvalidateAfter = 0;
1647
1648         m_resumeScopingFromRange = 0;
1649
1650         // The view might be null on detached frames.
1651         if (frame() && frame()->page())
1652             viewImpl()->mainFrameImpl()->m_framesScopingCount++;
1653
1654         // Now, defer scoping until later to allow find operation to finish quickly.
1655         scopeStringMatchesSoon(identifier, searchText, options, false); // false means just reset, so don't do it again.
1656         return;
1657     }
1658
1659     if (!shouldScopeMatches(searchText)) {
1660         // Note that we want to defer the final update when resetting even if shouldScopeMatches returns false.
1661         // This is done in order to prevent sending a final message based only on the results of the first frame
1662         // since m_framesScopingCount would be 0 as other frames have yet to reset.
1663         finishCurrentScopingEffort(identifier);
1664         return;
1665     }
1666
1667     WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl();
1668     RefPtr<Range> searchRange(rangeOfContents(frame()->document()));
1669
1670     Node* originalEndContainer = searchRange->endContainer();
1671     int originalEndOffset = searchRange->endOffset();
1672
1673     ExceptionCode ec = 0, ec2 = 0;
1674     if (m_resumeScopingFromRange) {
1675         // This is a continuation of a scoping operation that timed out and didn't
1676         // complete last time around, so we should start from where we left off.
1677         searchRange->setStart(m_resumeScopingFromRange->startContainer(),
1678                               m_resumeScopingFromRange->startOffset(ec2) + 1,
1679                               ec);
1680         if (ec || ec2) {
1681             if (ec2) // A non-zero |ec| happens when navigating during search.
1682                 ASSERT_NOT_REACHED();
1683             return;
1684         }
1685     }
1686
1687     // This timeout controls how long we scope before releasing control.  This
1688     // value does not prevent us from running for longer than this, but it is
1689     // periodically checked to see if we have exceeded our allocated time.
1690     const double maxScopingDuration = 0.1; // seconds
1691
1692     int matchCount = 0;
1693     bool timedOut = false;
1694     double startTime = currentTime();
1695     do {
1696         // Find next occurrence of the search string.
1697         // FIXME: (http://b/1088245) This WebKit operation may run for longer
1698         // than the timeout value, and is not interruptible as it is currently
1699         // written. We may need to rewrite it with interruptibility in mind, or
1700         // find an alternative.
1701         RefPtr<Range> resultRange(findPlainText(searchRange.get(),
1702                                                 searchText,
1703                                                 options.matchCase ? 0 : CaseInsensitive));
1704         if (resultRange->collapsed(ec)) {
1705             if (!resultRange->startContainer()->isInShadowTree())
1706                 break;
1707
1708             searchRange->setStartAfter(
1709                 resultRange->startContainer()->deprecatedShadowAncestorNode(), ec);
1710             searchRange->setEnd(originalEndContainer, originalEndOffset, ec);
1711             continue;
1712         }
1713
1714         ++matchCount;
1715
1716         // Catch a special case where Find found something but doesn't know what
1717         // the bounding box for it is. In this case we set the first match we find
1718         // as the active rect.
1719         IntRect resultBounds = resultRange->boundingBox();
1720         IntRect activeSelectionRect;
1721         if (m_locatingActiveRect) {
1722             activeSelectionRect = m_activeMatch.get() ?
1723                 m_activeMatch->boundingBox() : resultBounds;
1724         }
1725
1726         // If the Find function found a match it will have stored where the
1727         // match was found in m_activeSelectionRect on the current frame. If we
1728         // find this rect during scoping it means we have found the active
1729         // tickmark.
1730         bool foundActiveMatch = false;
1731         if (m_locatingActiveRect && (activeSelectionRect == resultBounds)) {
1732             // We have found the active tickmark frame.
1733             mainFrameImpl->m_currentActiveMatchFrame = this;
1734             foundActiveMatch = true;
1735             // We also know which tickmark is active now.
1736             m_activeMatchIndexInCurrentFrame = matchCount - 1;
1737             // To stop looking for the active tickmark, we set this flag.
1738             m_locatingActiveRect = false;
1739
1740             // Notify browser of new location for the selected rectangle.
1741             reportFindInPageSelection(
1742                 frameView()->contentsToWindow(resultBounds),
1743                 m_activeMatchIndexInCurrentFrame + 1,
1744                 identifier);
1745         }
1746
1747         addMarker(resultRange.get(), foundActiveMatch);
1748
1749         m_findMatchesCache.append(FindMatch(resultRange.get(), m_lastMatchCount + matchCount));
1750
1751         // Set the new start for the search range to be the end of the previous
1752         // result range. There is no need to use a VisiblePosition here,
1753         // since findPlainText will use a TextIterator to go over the visible
1754         // text nodes.
1755         searchRange->setStart(resultRange->endContainer(ec), resultRange->endOffset(ec), ec);
1756
1757         Node* shadowTreeRoot = searchRange->shadowRoot();
1758         if (searchRange->collapsed(ec) && shadowTreeRoot)
1759             searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->childNodeCount(), ec);
1760
1761         m_resumeScopingFromRange = resultRange;
1762         timedOut = (currentTime() - startTime) >= maxScopingDuration;
1763     } while (!timedOut);
1764
1765     // Remember what we search for last time, so we can skip searching if more
1766     // letters are added to the search string (and last outcome was 0).
1767     m_lastSearchString = searchText;
1768
1769     if (matchCount > 0) {
1770         frame()->editor()->setMarkedTextMatchesAreHighlighted(true);
1771
1772         m_lastMatchCount += matchCount;
1773
1774         // Let the mainframe know how much we found during this pass.
1775         mainFrameImpl->increaseMatchCount(matchCount, identifier);
1776     }
1777
1778     if (timedOut) {
1779         // If we found anything during this pass, we should redraw. However, we
1780         // don't want to spam too much if the page is extremely long, so if we
1781         // reach a certain point we start throttling the redraw requests.
1782         if (matchCount > 0)
1783             invalidateIfNecessary();
1784
1785         // Scoping effort ran out of time, lets ask for another time-slice.
1786         scopeStringMatchesSoon(
1787             identifier,
1788             searchText,
1789             options,
1790             false); // don't reset.
1791         return; // Done for now, resume work later.
1792     }
1793
1794     finishCurrentScopingEffort(identifier);
1795 }
1796
1797 void WebFrameImpl::flushCurrentScopingEffort(int identifier)
1798 {
1799     if (!frame() || !frame()->page())
1800         return;
1801
1802     WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl();
1803
1804     // This frame has no further scoping left, so it is done. Other frames might,
1805     // of course, continue to scope matches.
1806     mainFrameImpl->m_framesScopingCount--;
1807
1808     // If this is the last frame to finish scoping we need to trigger the final
1809     // update to be sent.
1810     if (!mainFrameImpl->m_framesScopingCount)
1811         mainFrameImpl->increaseMatchCount(0, identifier);
1812 }
1813
1814 void WebFrameImpl::finishCurrentScopingEffort(int identifier)
1815 {
1816     flushCurrentScopingEffort(identifier);
1817
1818     m_scopingInProgress = false;
1819     m_lastFindRequestCompletedWithNoMatches = !m_lastMatchCount;
1820
1821     // This frame is done, so show any scrollbar tickmarks we haven't drawn yet.
1822     invalidateArea(InvalidateScrollbar);
1823 }
1824
1825 void WebFrameImpl::cancelPendingScopingEffort()
1826 {
1827     deleteAllValues(m_deferredScopingWork);
1828     m_deferredScopingWork.clear();
1829
1830     m_activeMatchIndexInCurrentFrame = -1;
1831
1832     // Last request didn't complete.
1833     if (m_scopingInProgress)
1834         m_lastFindRequestCompletedWithNoMatches = false;
1835
1836     m_scopingInProgress = false;
1837 }
1838
1839 void WebFrameImpl::increaseMatchCount(int count, int identifier)
1840 {
1841     // This function should only be called on the mainframe.
1842     ASSERT(!parent());
1843
1844     if (count)
1845         ++m_findMatchMarkersVersion;
1846
1847     m_totalMatchCount += count;
1848
1849     // Update the UI with the latest findings.
1850     if (client())
1851         client()->reportFindInPageMatchCount(identifier, m_totalMatchCount, !m_framesScopingCount);
1852 }
1853
1854 void WebFrameImpl::reportFindInPageSelection(const WebRect& selectionRect, int activeMatchOrdinal, int identifier)
1855 {
1856     // Update the UI with the latest selection rect.
1857     if (client())
1858         client()->reportFindInPageSelection(identifier, ordinalOfFirstMatchForFrame(this) + activeMatchOrdinal, selectionRect);
1859 }
1860
1861 void WebFrameImpl::resetMatchCount()
1862 {
1863     if (m_totalMatchCount > 0)
1864         ++m_findMatchMarkersVersion;
1865
1866     m_totalMatchCount = 0;
1867     m_framesScopingCount = 0;
1868 }
1869
1870 void WebFrameImpl::sendOrientationChangeEvent(int orientation)
1871 {
1872 #if ENABLE(ORIENTATION_EVENTS)
1873     if (frame())
1874         frame()->sendOrientationChangeEvent(orientation);
1875 #endif
1876 }
1877
1878 void WebFrameImpl::addEventListener(const WebString& eventType, WebDOMEventListener* listener, bool useCapture)
1879 {
1880     DOMWindow* window = frame()->document()->domWindow();
1881     EventListenerWrapper* listenerWrapper = listener->createEventListenerWrapper(eventType, useCapture, window);
1882     window->addEventListener(eventType, adoptRef(listenerWrapper), useCapture);
1883 }
1884
1885 void WebFrameImpl::removeEventListener(const WebString& eventType, WebDOMEventListener* listener, bool useCapture)
1886 {
1887     DOMWindow* window = frame()->document()->domWindow();
1888     EventListenerWrapper* listenerWrapper = listener->getEventListenerWrapper(eventType, useCapture, window);
1889     window->removeEventListener(eventType, listenerWrapper, useCapture);
1890 }
1891
1892 bool WebFrameImpl::dispatchEvent(const WebDOMEvent& event)
1893 {
1894     ASSERT(!event.isNull());
1895     return frame()->document()->domWindow()->dispatchEvent(event);
1896 }
1897
1898 void WebFrameImpl::dispatchMessageEventWithOriginCheck(const WebSecurityOrigin& intendedTargetOrigin, const WebDOMEvent& event)
1899 {
1900     ASSERT(!event.isNull());
1901     frame()->document()->domWindow()->dispatchMessageEventWithOriginCheck(intendedTargetOrigin.get(), event, 0);
1902 }
1903
1904 int WebFrameImpl::findMatchMarkersVersion() const
1905 {
1906     ASSERT(!parent());
1907     return m_findMatchMarkersVersion;
1908 }
1909
1910 void WebFrameImpl::clearFindMatchesCache()
1911 {
1912     if (!m_findMatchesCache.isEmpty())
1913         viewImpl()->mainFrameImpl()->m_findMatchMarkersVersion++;
1914
1915     m_findMatchesCache.clear();
1916     m_findMatchRectsAreValid = false;
1917 }
1918
1919 bool WebFrameImpl::isActiveMatchFrameValid() const
1920 {
1921     WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl();
1922     WebFrameImpl* activeMatchFrame = mainFrameImpl->activeMatchFrame();
1923     return activeMatchFrame && activeMatchFrame->m_activeMatch && activeMatchFrame->frame()->tree()->isDescendantOf(mainFrameImpl->frame());
1924 }
1925
1926 void WebFrameImpl::updateFindMatchRects()
1927 {
1928     IntSize currentContentsSize = contentsSize();
1929     if (m_contentsSizeForCurrentFindMatchRects != currentContentsSize) {
1930         m_contentsSizeForCurrentFindMatchRects = currentContentsSize;
1931         m_findMatchRectsAreValid = false;
1932     }
1933
1934     size_t deadMatches = 0;
1935     for (Vector<FindMatch>::iterator it = m_findMatchesCache.begin(); it != m_findMatchesCache.end(); ++it) {
1936         if (!it->m_range->boundaryPointsValid() || !it->m_range->startContainer()->inDocument())
1937             it->m_rect = FloatRect();
1938         else if (!m_findMatchRectsAreValid)
1939             it->m_rect = findInPageRectFromRange(it->m_range.get());
1940
1941         if (it->m_rect.isEmpty())
1942             ++deadMatches;
1943     }
1944
1945     // Remove any invalid matches from the cache.
1946     if (deadMatches) {
1947         Vector<FindMatch> filteredMatches;
1948         filteredMatches.reserveCapacity(m_findMatchesCache.size() - deadMatches);
1949
1950         for (Vector<FindMatch>::const_iterator it = m_findMatchesCache.begin(); it != m_findMatchesCache.end(); ++it)
1951             if (!it->m_rect.isEmpty())
1952                 filteredMatches.append(*it);
1953
1954         m_findMatchesCache.swap(filteredMatches);
1955     }
1956
1957     // Invalidate the rects in child frames. Will be updated later during traversal.
1958     if (!m_findMatchRectsAreValid)
1959         for (WebFrame* child = firstChild(); child; child = child->nextSibling())
1960             static_cast<WebFrameImpl*>(child)->m_findMatchRectsAreValid = false;
1961
1962     m_findMatchRectsAreValid = true;
1963 }
1964
1965 WebFloatRect WebFrameImpl::activeFindMatchRect()
1966 {
1967     ASSERT(!parent());
1968
1969     if (!isActiveMatchFrameValid())
1970         return WebFloatRect();
1971
1972     return WebFloatRect(findInPageRectFromRange(m_currentActiveMatchFrame->m_activeMatch.get()));
1973 }
1974
1975 void WebFrameImpl::findMatchRects(WebVector<WebFloatRect>& outputRects)
1976 {
1977     ASSERT(!parent());
1978
1979     Vector<WebFloatRect> matchRects;
1980     for (WebFrameImpl* frame = this; frame; frame = static_cast<WebFrameImpl*>(frame->traverseNext(false)))
1981         frame->appendFindMatchRects(matchRects);
1982
1983     outputRects = matchRects;
1984 }
1985
1986 void WebFrameImpl::appendFindMatchRects(Vector<WebFloatRect>& frameRects)
1987 {
1988     updateFindMatchRects();
1989     frameRects.reserveCapacity(frameRects.size() + m_findMatchesCache.size());
1990     for (Vector<FindMatch>::const_iterator it = m_findMatchesCache.begin(); it != m_findMatchesCache.end(); ++it) {
1991         ASSERT(!it->m_rect.isEmpty());
1992         frameRects.append(it->m_rect);
1993     }
1994 }
1995
1996 int WebFrameImpl::selectNearestFindMatch(const WebFloatPoint& point, WebRect* selectionRect)
1997 {
1998     ASSERT(!parent());
1999
2000     WebFrameImpl* bestFrame = 0;
2001     int indexInBestFrame = -1;
2002     float distanceInBestFrame = FLT_MAX;
2003
2004     for (WebFrameImpl* frame = this; frame; frame = static_cast<WebFrameImpl*>(frame->traverseNext(false))) {
2005         float distanceInFrame;
2006         int indexInFrame = frame->nearestFindMatch(point, distanceInFrame);
2007         if (distanceInFrame < distanceInBestFrame) {
2008             bestFrame = frame;
2009             indexInBestFrame = indexInFrame;
2010             distanceInBestFrame = distanceInFrame;
2011         }
2012     }
2013
2014     if (indexInBestFrame != -1)
2015         return bestFrame->selectFindMatch(static_cast<unsigned>(indexInBestFrame), selectionRect);
2016
2017     return -1;
2018 }
2019
2020 int WebFrameImpl::nearestFindMatch(const FloatPoint& point, float& distanceSquared)
2021 {
2022     updateFindMatchRects();
2023
2024     int nearest = -1;
2025     distanceSquared = FLT_MAX;
2026     for (size_t i = 0; i < m_findMatchesCache.size(); ++i) {
2027         ASSERT(!m_findMatchesCache[i].m_rect.isEmpty());
2028         FloatSize offset = point - m_findMatchesCache[i].m_rect.center();
2029         float width = offset.width();
2030         float height = offset.height();
2031         float currentDistanceSquared = width * width + height * height;
2032         if (currentDistanceSquared < distanceSquared) {
2033             nearest = i;
2034             distanceSquared = currentDistanceSquared;
2035         }
2036     }
2037     return nearest;
2038 }
2039
2040 int WebFrameImpl::selectFindMatch(unsigned index, WebRect* selectionRect)
2041 {
2042     ASSERT_WITH_SECURITY_IMPLICATION(index < m_findMatchesCache.size());
2043
2044     RefPtr<Range> range = m_findMatchesCache[index].m_range;
2045     if (!range->boundaryPointsValid() || !range->startContainer()->inDocument())
2046         return -1;
2047
2048     // Check if the match is already selected.
2049     WebFrameImpl* activeMatchFrame = viewImpl()->mainFrameImpl()->m_currentActiveMatchFrame;
2050     if (this != activeMatchFrame || !m_activeMatch || !areRangesEqual(m_activeMatch.get(), range.get())) {
2051         if (isActiveMatchFrameValid())
2052             activeMatchFrame->setMarkerActive(activeMatchFrame->m_activeMatch.get(), false);
2053
2054         m_activeMatchIndexInCurrentFrame = m_findMatchesCache[index].m_ordinal - 1;
2055
2056         // Set this frame as the active frame (the one with the active highlight).
2057         viewImpl()->mainFrameImpl()->m_currentActiveMatchFrame = this;
2058         viewImpl()->setFocusedFrame(this);
2059
2060         m_activeMatch = range.release();
2061         setMarkerActive(m_activeMatch.get(), true);
2062
2063         // Clear any user selection, to make sure Find Next continues on from the match we just activated.
2064         frame()->selection()->clear();
2065
2066         // Make sure no node is focused. See http://crbug.com/38700.
2067         frame()->document()->setFocusedNode(0);
2068     }
2069
2070     IntRect activeMatchRect;
2071     IntRect activeMatchBoundingBox = enclosingIntRect(RenderObject::absoluteBoundingBoxRectForRange(m_activeMatch.get()));
2072
2073     if (!activeMatchBoundingBox.isEmpty()) {
2074         if (m_activeMatch->firstNode() && m_activeMatch->firstNode()->renderer())
2075             m_activeMatch->firstNode()->renderer()->scrollRectToVisible(activeMatchBoundingBox,
2076                     ScrollAlignment::alignCenterIfNeeded, ScrollAlignment::alignCenterIfNeeded);
2077
2078         // Zoom to the active match.
2079         activeMatchRect = frameView()->contentsToWindow(activeMatchBoundingBox);
2080         viewImpl()->zoomToFindInPageRect(activeMatchRect);
2081     }
2082
2083     if (selectionRect)
2084         *selectionRect = activeMatchRect;
2085
2086     return ordinalOfFirstMatchForFrame(this) + m_activeMatchIndexInCurrentFrame + 1;
2087 }
2088
2089 void WebFrameImpl::deliverIntent(const WebIntent& intent, WebMessagePortChannelArray* ports, WebDeliveredIntentClient* intentClient)
2090 {
2091 #if ENABLE(WEB_INTENTS)
2092     OwnPtr<WebCore::DeliveredIntentClient> client(adoptPtr(new DeliveredIntentClientImpl(intentClient)));
2093
2094     WebSerializedScriptValue intentData = WebSerializedScriptValue::fromString(intent.data());
2095     const WebCore::Intent* webcoreIntent = intent;
2096
2097     // See PlatformMessagePortChannel.cpp
2098     OwnPtr<MessagePortChannelArray> channels;
2099     if (ports && ports->size()) {
2100         channels = adoptPtr(new MessagePortChannelArray(ports->size()));
2101         for (size_t i = 0; i < ports->size(); ++i) {
2102             RefPtr<PlatformMessagePortChannel> platformChannel = PlatformMessagePortChannel::create((*ports)[i]);
2103             (*ports)[i]->setClient(platformChannel.get());
2104             (*channels)[i] = MessagePortChannel::create(platformChannel);
2105         }
2106     }
2107     OwnPtr<MessagePortArray> portArray = WebCore::MessagePort::entanglePorts(*(frame()->document()), channels.release());
2108
2109     RefPtr<DeliveredIntent> deliveredIntent = DeliveredIntent::create(frame(), client.release(), intent.action(), intent.type(), intentData, portArray.release(), webcoreIntent->extras());
2110
2111     DOMWindowIntents::from(frame()->document()->domWindow())->deliver(deliveredIntent.release());
2112 #endif
2113 }
2114
2115 WebString WebFrameImpl::contentAsText(size_t maxChars) const
2116 {
2117     if (!frame())
2118         return WebString();
2119     Vector<UChar> text;
2120     frameContentAsPlainText(maxChars, frame(), &text);
2121     return String::adopt(text);
2122 }
2123
2124 WebString WebFrameImpl::contentAsMarkup() const
2125 {
2126     if (!frame())
2127         return WebString();
2128     return createFullMarkup(frame()->document());
2129 }
2130
2131 WebString WebFrameImpl::renderTreeAsText(RenderAsTextControls toShow) const
2132 {
2133     RenderAsTextBehavior behavior = RenderAsTextBehaviorNormal;
2134
2135     if (toShow & RenderAsTextDebug)
2136         behavior |= RenderAsTextShowCompositedLayers | RenderAsTextShowAddresses | RenderAsTextShowIDAndClass | RenderAsTextShowLayerNesting;
2137
2138     if (toShow & RenderAsTextPrinting)
2139         behavior |= RenderAsTextPrintingMode;
2140
2141     return externalRepresentation(frame(), behavior);
2142 }
2143
2144 WebString WebFrameImpl::markerTextForListItem(const WebElement& webElement) const
2145 {
2146     return WebCore::markerTextForListItem(const_cast<Element*>(webElement.constUnwrap<Element>()));
2147 }
2148
2149 void WebFrameImpl::printPagesWithBoundaries(WebCanvas* canvas, const WebSize& pageSizeInPixels)
2150 {
2151     ASSERT(m_printContext);
2152
2153     GraphicsContextBuilder builder(canvas);
2154     GraphicsContext& graphicsContext = builder.context();
2155     graphicsContext.platformContext()->setPrinting(true);
2156
2157     m_printContext->spoolAllPagesWithBoundaries(graphicsContext, FloatSize(pageSizeInPixels.width, pageSizeInPixels.height));
2158 }
2159
2160 WebRect WebFrameImpl::selectionBoundsRect() const
2161 {
2162     return hasSelection() ? WebRect(IntRect(frame()->selection()->bounds(false))) : WebRect();
2163 }
2164
2165 bool WebFrameImpl::selectionStartHasSpellingMarkerFor(int from, int length) const
2166 {
2167     if (!frame())
2168         return false;
2169     return frame()->editor()->selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length);
2170 }
2171
2172 WebString WebFrameImpl::layerTreeAsText(bool showDebugInfo) const
2173 {
2174     if (!frame())
2175         return WebString();
2176     
2177     LayerTreeFlags flags = showDebugInfo ? LayerTreeFlagsIncludeDebugInfo : 0;
2178     return WebString(frame()->layerTreeAsText(flags));
2179 }
2180
2181 // WebFrameImpl public ---------------------------------------------------------
2182
2183 PassRefPtr<WebFrameImpl> WebFrameImpl::create(WebFrameClient* client)
2184 {
2185     return adoptRef(new WebFrameImpl(client));
2186 }
2187
2188 WebFrameImpl::WebFrameImpl(WebFrameClient* client)
2189     : FrameDestructionObserver(0)
2190     , m_frameLoaderClient(this)
2191     , m_client(client)
2192     , m_currentActiveMatchFrame(0)
2193     , m_activeMatchIndexInCurrentFrame(-1)
2194     , m_locatingActiveRect(false)
2195     , m_resumeScopingFromRange(0)
2196     , m_lastMatchCount(-1)
2197     , m_totalMatchCount(-1)
2198     , m_framesScopingCount(-1)
2199     , m_findRequestIdentifier(-1)
2200     , m_scopingInProgress(false)
2201     , m_lastFindRequestCompletedWithNoMatches(false)
2202     , m_nextInvalidateAfter(0)
2203     , m_findMatchMarkersVersion(0)
2204     , m_findMatchRectsAreValid(false)
2205     , m_animationController(this)
2206     , m_identifier(generateFrameIdentifier())
2207     , m_inSameDocumentHistoryLoad(false)
2208 {
2209     WebKit::Platform::current()->incrementStatsCounter(webFrameActiveCount);
2210     frameCount++;
2211 }
2212
2213 WebFrameImpl::~WebFrameImpl()
2214 {
2215     WebKit::Platform::current()->decrementStatsCounter(webFrameActiveCount);
2216     frameCount--;
2217
2218     cancelPendingScopingEffort();
2219 }
2220
2221 void WebFrameImpl::setWebCoreFrame(WebCore::Frame* frame)
2222 {
2223     ASSERT(frame);
2224     observeFrame(frame);
2225 }
2226
2227 void WebFrameImpl::initializeAsMainFrame(WebCore::Page* page)
2228 {
2229     RefPtr<Frame> mainFrame = Frame::create(page, 0, &m_frameLoaderClient);
2230     setWebCoreFrame(mainFrame.get());
2231
2232     // Add reference on behalf of FrameLoader.  See comments in
2233     // WebFrameLoaderClient::frameLoaderDestroyed for more info.
2234     ref();
2235
2236     // We must call init() after m_frame is assigned because it is referenced
2237     // during init().
2238     frame()->init();
2239 }
2240
2241 PassRefPtr<Frame> WebFrameImpl::createChildFrame(const FrameLoadRequest& request, HTMLFrameOwnerElement* ownerElement)
2242 {
2243     RefPtr<WebFrameImpl> webframe(adoptRef(new WebFrameImpl(m_client)));
2244
2245     // Add an extra ref on behalf of the Frame/FrameLoader, which references the
2246     // WebFrame via the FrameLoaderClient interface. See the comment at the top
2247     // of this file for more info.
2248     webframe->ref();
2249
2250     RefPtr<Frame> childFrame = Frame::create(frame()->page(), ownerElement, &webframe->m_frameLoaderClient);
2251     webframe->setWebCoreFrame(childFrame.get());
2252
2253     childFrame->tree()->setName(request.frameName());
2254
2255     frame()->tree()->appendChild(childFrame);
2256
2257     // Frame::init() can trigger onload event in the parent frame,
2258     // which may detach this frame and trigger a null-pointer access
2259     // in FrameTree::removeChild. Move init() after appendChild call
2260     // so that webframe->mFrame is in the tree before triggering
2261     // onload event handler.
2262     // Because the event handler may set webframe->mFrame to null,
2263     // it is necessary to check the value after calling init() and
2264     // return without loading URL.
2265     // (b:791612)
2266     childFrame->init(); // create an empty document
2267     if (!childFrame->tree()->parent())
2268         return 0;
2269
2270     frame()->loader()->loadURLIntoChildFrame(request.resourceRequest().url(), request.resourceRequest().httpReferrer(), childFrame.get());
2271
2272     // A synchronous navigation (about:blank) would have already processed
2273     // onload, so it is possible for the frame to have already been destroyed by
2274     // script in the page.
2275     if (!childFrame->tree()->parent())
2276         return 0;
2277
2278     if (m_client)
2279         m_client->didCreateFrame(this, webframe.get());
2280
2281     return childFrame.release();
2282 }
2283
2284 void WebFrameImpl::didChangeContentsSize(const IntSize& size)
2285 {
2286     // This is only possible on the main frame.
2287     if (m_totalMatchCount > 0) {
2288         ASSERT(!parent());
2289         ++m_findMatchMarkersVersion;
2290     }
2291 }
2292
2293 void WebFrameImpl::createFrameView()
2294 {
2295     TRACE_EVENT0("webkit", "WebFrameImpl::createFrameView");
2296
2297     ASSERT(frame()); // If frame() doesn't exist, we probably didn't init properly.
2298
2299     WebViewImpl* webView = viewImpl();
2300     bool isMainFrame = webView->mainFrameImpl()->frame() == frame();
2301     if (isMainFrame)
2302         webView->suppressInvalidations(true);
2303  
2304     frame()->createView(webView->size(), Color::white, webView->isTransparent(), webView->fixedLayoutSize(), IntRect(), isMainFrame ? webView->isFixedLayoutModeEnabled() : 0);
2305     if (webView->shouldAutoResize() && isMainFrame)
2306         frame()->view()->enableAutoSizeMode(true, webView->minAutoSize(), webView->maxAutoSize());
2307
2308     if (isMainFrame)
2309         webView->suppressInvalidations(false);
2310  
2311     if (isMainFrame && webView->devToolsAgentPrivate())
2312         webView->devToolsAgentPrivate()->mainFrameViewCreated(this);
2313 }
2314
2315 WebFrameImpl* WebFrameImpl::fromFrame(Frame* frame)
2316 {
2317     if (!frame)
2318         return 0;
2319     return static_cast<FrameLoaderClientImpl*>(frame->loader()->client())->webFrame();
2320 }
2321
2322 WebFrameImpl* WebFrameImpl::fromFrameOwnerElement(Element* element)
2323 {
2324     // FIXME: Why do we check specifically for <iframe> and <frame> here? Why can't we get the WebFrameImpl from an <object> element, for example.
2325     if (!element || !element->isFrameOwnerElement() || (!element->hasTagName(HTMLNames::iframeTag) && !element->hasTagName(HTMLNames::frameTag)))
2326         return 0;
2327     HTMLFrameOwnerElement* frameElement = static_cast<HTMLFrameOwnerElement*>(element);
2328     return fromFrame(frameElement->contentFrame());
2329 }
2330
2331 WebViewImpl* WebFrameImpl::viewImpl() const
2332 {
2333     if (!frame())
2334         return 0;
2335     return WebViewImpl::fromPage(frame()->page());
2336 }
2337
2338 WebDataSourceImpl* WebFrameImpl::dataSourceImpl() const
2339 {
2340     return static_cast<WebDataSourceImpl*>(dataSource());
2341 }
2342
2343 WebDataSourceImpl* WebFrameImpl::provisionalDataSourceImpl() const
2344 {
2345     return static_cast<WebDataSourceImpl*>(provisionalDataSource());
2346 }
2347
2348 void WebFrameImpl::setFindEndstateFocusAndSelection()
2349 {
2350     WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl();
2351
2352     if (this == mainFrameImpl->activeMatchFrame() && m_activeMatch.get()) {
2353         // If the user has set the selection since the match was found, we
2354         // don't focus anything.
2355         VisibleSelection selection(frame()->selection()->selection());
2356         if (!selection.isNone())
2357             return;
2358
2359         // Try to find the first focusable node up the chain, which will, for
2360         // example, focus links if we have found text within the link.
2361         Node* node = m_activeMatch->firstNode();
2362         if (node && node->isInShadowTree()) {
2363             Node* host = node->deprecatedShadowAncestorNode();
2364             if (host->hasTagName(HTMLNames::inputTag) || host->hasTagName(HTMLNames::textareaTag))
2365                 node = host;
2366         }
2367         while (node && !node->isFocusable() && node != frame()->document())
2368             node = node->parentNode();
2369
2370         if (node && node != frame()->document()) {
2371             // Found a focusable parent node. Set the active match as the
2372             // selection and focus to the focusable node.
2373             frame()->selection()->setSelection(m_activeMatch.get());
2374             frame()->document()->setFocusedNode(node);
2375             return;
2376         }
2377
2378         // Iterate over all the nodes in the range until we find a focusable node.
2379         // This, for example, sets focus to the first link if you search for
2380         // text and text that is within one or more links.
2381         node = m_activeMatch->firstNode();
2382         while (node && node != m_activeMatch->pastLastNode()) {
2383             if (node->isFocusable()) {
2384                 frame()->document()->setFocusedNode(node);
2385                 return;
2386             }
2387             node = NodeTraversal::next(node);
2388         }
2389
2390         // No node related to the active match was focusable, so set the
2391         // active match as the selection (so that when you end the Find session,
2392         // you'll have the last thing you found highlighted) and make sure that
2393         // we have nothing focused (otherwise you might have text selected but
2394         // a link focused, which is weird).
2395         frame()->selection()->setSelection(m_activeMatch.get());
2396         frame()->document()->setFocusedNode(0);
2397
2398         // Finally clear the active match, for two reasons:
2399         // We just finished the find 'session' and we don't want future (potentially
2400         // unrelated) find 'sessions' operations to start at the same place.
2401         // The WebFrameImpl could get reused and the m_activeMatch could end up pointing
2402         // to a document that is no longer valid. Keeping an invalid reference around
2403         // is just asking for trouble.
2404         m_activeMatch = 0;
2405     }
2406 }
2407
2408 void WebFrameImpl::didFail(const ResourceError& error, bool wasProvisional)
2409 {
2410     if (!client())
2411         return;
2412     WebURLError webError = error;
2413     if (wasProvisional)
2414         client()->didFailProvisionalLoad(this, webError);
2415     else
2416         client()->didFailLoad(this, webError);
2417 }
2418
2419 void WebFrameImpl::setCanHaveScrollbars(bool canHaveScrollbars)
2420 {
2421     frame()->view()->setCanHaveScrollbars(canHaveScrollbars);
2422 }
2423
2424 void WebFrameImpl::invalidateArea(AreaToInvalidate area)
2425 {
2426     ASSERT(frame() && frame()->view());
2427     FrameView* view = frame()->view();
2428
2429     if ((area & InvalidateAll) == InvalidateAll)
2430         view->invalidateRect(view->frameRect());
2431     else {
2432         if ((area & InvalidateContentArea) == InvalidateContentArea) {
2433             IntRect contentArea(
2434                 view->x(), view->y(), view->visibleWidth(), view->visibleHeight());
2435             IntRect frameRect = view->frameRect();
2436             contentArea.move(-frameRect.x(), -frameRect.y());
2437             view->invalidateRect(contentArea);
2438         }
2439     }
2440
2441     if ((area & InvalidateScrollbar) == InvalidateScrollbar) {
2442         // Invalidate the vertical scroll bar region for the view.
2443         Scrollbar* scrollbar = view->verticalScrollbar();
2444         if (scrollbar)
2445             scrollbar->invalidate();
2446     }
2447 }
2448
2449 void WebFrameImpl::addMarker(Range* range, bool activeMatch)
2450 {
2451     frame()->document()->markers()->addTextMatchMarker(range, activeMatch);
2452 }
2453
2454 void WebFrameImpl::setMarkerActive(Range* range, bool active)
2455 {
2456     WebCore::ExceptionCode ec;
2457     if (!range || range->collapsed(ec))
2458         return;
2459     frame()->document()->markers()->setMarkersActive(range, active);
2460 }
2461
2462 int WebFrameImpl::ordinalOfFirstMatchForFrame(WebFrameImpl* frame) const
2463 {
2464     int ordinal = 0;
2465     WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl();
2466     // Iterate from the main frame up to (but not including) |frame| and
2467     // add up the number of matches found so far.
2468     for (WebFrameImpl* it = mainFrameImpl; it != frame; it = static_cast<WebFrameImpl*>(it->traverseNext(true))) {
2469         if (it->m_lastMatchCount > 0)
2470             ordinal += it->m_lastMatchCount;
2471     }
2472     return ordinal;
2473 }
2474
2475 bool WebFrameImpl::shouldScopeMatches(const String& searchText)
2476 {
2477     // Don't scope if we can't find a frame or a view.
2478     // The user may have closed the tab/application, so abort.
2479     // Also ignore detached frames, as many find operations report to the main frame.
2480     if (!frame() || !frame()->view() || !frame()->page() || !hasVisibleContent())
2481         return false;
2482
2483     ASSERT(frame()->document() && frame()->view());
2484
2485     // If the frame completed the scoping operation and found 0 matches the last
2486     // time it was searched, then we don't have to search it again if the user is
2487     // just adding to the search string or sending the same search string again.
2488     if (m_lastFindRequestCompletedWithNoMatches && !m_lastSearchString.isEmpty()) {
2489         // Check to see if the search string prefixes match.
2490         String previousSearchPrefix =
2491             searchText.substring(0, m_lastSearchString.length());
2492
2493         if (previousSearchPrefix == m_lastSearchString)
2494             return false; // Don't search this frame, it will be fruitless.
2495     }
2496
2497     return true;
2498 }
2499
2500 void WebFrameImpl::scopeStringMatchesSoon(int identifier, const WebString& searchText, const WebFindOptions& options, bool reset)
2501 {
2502     m_deferredScopingWork.append(new DeferredScopeStringMatches(this, identifier, searchText, options, reset));
2503 }
2504
2505 void WebFrameImpl::callScopeStringMatches(DeferredScopeStringMatches* caller, int identifier, const WebString& searchText, const WebFindOptions& options, bool reset)
2506 {
2507     m_deferredScopingWork.remove(m_deferredScopingWork.find(caller));
2508     scopeStringMatches(identifier, searchText, options, reset);
2509
2510     // This needs to happen last since searchText is passed by reference.
2511     delete caller;
2512 }
2513
2514 void WebFrameImpl::invalidateIfNecessary()
2515 {
2516     if (m_lastMatchCount <= m_nextInvalidateAfter)
2517         return;
2518
2519     // FIXME: (http://b/1088165) Optimize the drawing of the tickmarks and
2520     // remove this. This calculation sets a milestone for when next to
2521     // invalidate the scrollbar and the content area. We do this so that we
2522     // don't spend too much time drawing the scrollbar over and over again.
2523     // Basically, up until the first 500 matches there is no throttle.
2524     // After the first 500 matches, we set set the milestone further and
2525     // further out (750, 1125, 1688, 2K, 3K).
2526     static const int startSlowingDownAfter = 500;
2527     static const int slowdown = 750;
2528
2529     int i = m_lastMatchCount / startSlowingDownAfter;
2530     m_nextInvalidateAfter += i * slowdown;
2531     invalidateArea(InvalidateScrollbar);
2532 }
2533
2534 void WebFrameImpl::loadJavaScriptURL(const KURL& url)
2535 {
2536     // This is copied from ScriptController::executeIfJavaScriptURL.
2537     // Unfortunately, we cannot just use that method since it is private, and
2538     // it also doesn't quite behave as we require it to for bookmarklets.  The
2539     // key difference is that we need to suppress loading the string result
2540     // from evaluating the JS URL if executing the JS URL resulted in a
2541     // location change.  We also allow a JS URL to be loaded even if scripts on
2542     // the page are otherwise disabled.
2543
2544     if (!frame()->document() || !frame()->page())
2545         return;
2546
2547     RefPtr<Document> ownerDocument(frame()->document());
2548
2549     // Protect privileged pages against bookmarklets and other javascript manipulations.
2550     if (SchemeRegistry::shouldTreatURLSchemeAsNotAllowingJavascriptURLs(frame()->document()->url().protocol()))
2551         return;
2552
2553     String script = decodeURLEscapeSequences(url.string().substring(strlen("javascript:")));
2554     ScriptValue result = frame()->script()->executeScript(script, true);
2555
2556     String scriptResult;
2557     if (!result.getString(scriptResult))
2558         return;
2559
2560     if (!frame()->navigationScheduler()->locationChangePending())
2561         frame()->document()->loader()->writer()->replaceDocument(scriptResult, ownerDocument.get());
2562 }
2563
2564 void WebFrameImpl::willDetachPage()
2565 {
2566     if (!frame() || !frame()->page())
2567         return;
2568
2569     // Do not expect string scoping results from any frames that got detached
2570     // in the middle of the operation.
2571     if (m_scopingInProgress) {
2572
2573         // There is a possibility that the frame being detached was the only
2574         // pending one. We need to make sure final replies can be sent.
2575         flushCurrentScopingEffort(m_findRequestIdentifier);
2576
2577         cancelPendingScopingEffort();
2578     }
2579 }
2580
2581 } // namespace WebKit