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