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