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