2010-09-10 Adam Barth <abarth@webkit.org>
[WebKit-https.git] / 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 "Chrome.h"
75 #include "ChromiumBridge.h"
76 #include "ClipboardUtilitiesChromium.h"
77 #include "Console.h"
78 #include "DOMUtilitiesPrivate.h"
79 #include "DOMWindow.h"
80 #include "Document.h"
81 #include "DocumentFragment.h" // Only needed for ReplaceSelectionCommand.h :(
82 #include "DocumentLoader.h"
83 #include "DocumentMarker.h"
84 #include "Editor.h"
85 #include "EventHandler.h"
86 #include "FormState.h"
87 #include "FrameLoadRequest.h"
88 #include "FrameLoader.h"
89 #include "FrameTree.h"
90 #include "FrameView.h"
91 #include "GraphicsContext.h"
92 #include "HTMLCollection.h"
93 #include "HTMLFormElement.h"
94 #include "HTMLFrameOwnerElement.h"
95 #include "HTMLHeadElement.h"
96 #include "HTMLInputElement.h"
97 #include "HTMLLinkElement.h"
98 #include "HTMLNames.h"
99 #include "HistoryItem.h"
100 #include "InspectorController.h"
101 #include "Page.h"
102 #include "PlatformContextSkia.h"
103 #include "PluginDocument.h"
104 #include "PrintContext.h"
105 #include "RenderFrame.h"
106 #include "RenderTreeAsText.h"
107 #include "RenderView.h"
108 #include "RenderWidget.h"
109 #include "ReplaceSelectionCommand.h"
110 #include "ResourceHandle.h"
111 #include "ResourceRequest.h"
112 #include "ScriptController.h"
113 #include "ScriptSourceCode.h"
114 #include "ScriptValue.h"
115 #include "ScrollTypes.h"
116 #include "ScrollbarTheme.h"
117 #include "SelectionController.h"
118 #include "Settings.h"
119 #include "SkiaUtils.h"
120 #include "SubstituteData.h"
121 #include "TextAffinity.h"
122 #include "TextIterator.h"
123 #include "WebAnimationControllerImpl.h"
124 #include "WebConsoleMessage.h"
125 #include "WebDataSourceImpl.h"
126 #include "WebDocument.h"
127 #include "WebFindOptions.h"
128 #include "WebFormElement.h"
129 #include "WebFrameClient.h"
130 #include "WebHistoryItem.h"
131 #include "WebInputElement.h"
132 #include "WebPasswordAutocompleteListener.h"
133 #include "WebPlugin.h"
134 #include "WebPluginContainerImpl.h"
135 #include "WebRange.h"
136 #include "WebRect.h"
137 #include "WebScriptSource.h"
138 #include "WebSecurityOrigin.h"
139 #include "WebSize.h"
140 #include "WebURLError.h"
141 #include "WebVector.h"
142 #include "WebViewImpl.h"
143 #include "XPathResult.h"
144 #include "markup.h"
145
146 #include <algorithm>
147 #include <wtf/CurrentTime.h>
148
149
150 #if OS(DARWIN)
151 #include "LocalCurrentGraphicsContext.h"
152 #endif
153
154 #if OS(LINUX)
155 #include <gdk/gdk.h>
156 #endif
157
158 using namespace WebCore;
159
160 namespace WebKit {
161
162 static int frameCount = 0;
163
164 // Key for a StatsCounter tracking how many WebFrames are active.
165 static const char* const webFrameActiveCount = "WebFrameActiveCount";
166
167 static const char* const osdType = "application/opensearchdescription+xml";
168 static const char* const osdRel = "search";
169
170 // Backend for contentAsPlainText, this is a recursive function that gets
171 // the text for the current frame and all of its subframes. It will append
172 // the text of each frame in turn to the |output| up to |maxChars| length.
173 //
174 // The |frame| must be non-null.
175 static void frameContentAsPlainText(size_t maxChars, Frame* frame,
176                                     Vector<UChar>* output)
177 {
178     Document* doc = frame->document();
179     if (!doc)
180         return;
181
182     if (!frame->view())
183         return;
184
185     // TextIterator iterates over the visual representation of the DOM. As such,
186     // it requires you to do a layout before using it (otherwise it'll crash).
187     if (frame->view()->needsLayout())
188         frame->view()->layout();
189
190     // Select the document body.
191     RefPtr<Range> range(doc->createRange());
192     ExceptionCode exception = 0;
193     range->selectNodeContents(doc->body(), exception);
194
195     if (!exception) {
196         // The text iterator will walk nodes giving us text. This is similar to
197         // the plainText() function in TextIterator.h, but we implement the maximum
198         // size and also copy the results directly into a wstring, avoiding the
199         // string conversion.
200         for (TextIterator it(range.get()); !it.atEnd(); it.advance()) {
201             const UChar* chars = it.characters();
202             if (!chars) {
203                 if (it.length()) {
204                     // It appears from crash reports that an iterator can get into a state
205                     // where the character count is nonempty but the character pointer is
206                     // null. advance()ing it will then just add that many to the null
207                     // pointer which won't be caught in a null check but will crash.
208                     //
209                     // A null pointer and 0 length is common for some nodes.
210                     //
211                     // IF YOU CATCH THIS IN A DEBUGGER please let brettw know. We don't
212                     // currently understand the conditions for this to occur. Ideally, the
213                     // iterators would never get into the condition so we should fix them
214                     // if we can.
215                     ASSERT_NOT_REACHED();
216                     break;
217                 }
218
219                 // Just got a null node, we can forge ahead!
220                 continue;
221             }
222             size_t toAppend =
223                 std::min(static_cast<size_t>(it.length()), maxChars - output->size());
224             output->append(chars, toAppend);
225             if (output->size() >= maxChars)
226                 return; // Filled up the buffer.
227         }
228     }
229
230     // The separator between frames when the frames are converted to plain text.
231     const UChar frameSeparator[] = { '\n', '\n' };
232     const size_t frameSeparatorLen = 2;
233
234     // Recursively walk the children.
235     FrameTree* frameTree = frame->tree();
236     for (Frame* curChild = frameTree->firstChild(); curChild; curChild = curChild->tree()->nextSibling()) {
237         // Ignore the text of non-visible frames.
238         RenderView* contentRenderer = curChild->contentRenderer();
239         RenderPart* ownerRenderer = curChild->ownerRenderer();        
240         if (!contentRenderer || !contentRenderer->width() || !contentRenderer->height()
241             || (contentRenderer->x() + contentRenderer->width() <= 0) || (contentRenderer->y() + contentRenderer->height() <= 0)
242             || (ownerRenderer && ownerRenderer->style() && ownerRenderer->style()->visibility() != VISIBLE)) {
243             continue;
244         }
245
246         // Make sure the frame separator won't fill up the buffer, and give up if
247         // it will. The danger is if the separator will make the buffer longer than
248         // maxChars. This will cause the computation above:
249         //   maxChars - output->size()
250         // to be a negative number which will crash when the subframe is added.
251         if (output->size() >= maxChars - frameSeparatorLen)
252             return;
253
254         output->append(frameSeparator, frameSeparatorLen);
255         frameContentAsPlainText(maxChars, curChild, output);
256         if (output->size() >= maxChars)
257             return; // Filled up the buffer.
258     }
259 }
260
261 WebPluginContainerImpl* WebFrameImpl::pluginContainerFromFrame(Frame* frame)
262 {
263     if (!frame)
264         return 0;
265     if (!frame->document() || !frame->document()->isPluginDocument())
266         return 0;
267     PluginDocument* pluginDocument = static_cast<PluginDocument*>(frame->document());
268     return static_cast<WebPluginContainerImpl *>(pluginDocument->pluginWidget());
269 }
270
271 // Simple class to override some of PrintContext behavior. Some of the methods
272 // made virtual so that they can be overriden by ChromePluginPrintContext.
273 class ChromePrintContext : public PrintContext, public Noncopyable {
274 public:
275     ChromePrintContext(Frame* frame)
276         : PrintContext(frame)
277         , m_printedPageWidth(0)
278     {
279     }
280
281     virtual void begin(float width)
282     {
283         ASSERT(!m_printedPageWidth);
284         m_printedPageWidth = width;
285         PrintContext::begin(m_printedPageWidth);
286     }
287
288     virtual void end()
289     {
290         PrintContext::end();
291     }
292
293     virtual float getPageShrink(int pageNumber) const
294     {
295         IntRect pageRect = m_pageRects[pageNumber];
296         return m_printedPageWidth / pageRect.width();
297     }
298
299     // Spools the printed page, a subrect of m_frame. Skip the scale step.
300     // NativeTheme doesn't play well with scaling. Scaling is done browser side
301     // instead. Returns the scale to be applied.
302     // On Linux, we don't have the problem with NativeTheme, hence we let WebKit
303     // do the scaling and ignore the return value.
304     virtual float spoolPage(GraphicsContext& ctx, int pageNumber)
305     {
306         IntRect pageRect = m_pageRects[pageNumber];
307         float scale = m_printedPageWidth / pageRect.width();
308
309         ctx.save();
310 #if OS(LINUX)
311         ctx.scale(WebCore::FloatSize(scale, scale));
312 #endif
313         ctx.translate(static_cast<float>(-pageRect.x()),
314                       static_cast<float>(-pageRect.y()));
315         ctx.clip(pageRect);
316         m_frame->view()->paintContents(&ctx, pageRect);
317         ctx.restore();
318         return scale;
319     }
320
321     virtual void computePageRects(const FloatRect& printRect, float headerHeight, float footerHeight, float userScaleFactor, float& outPageHeight)
322     {
323         return PrintContext::computePageRects(printRect, headerHeight, footerHeight, userScaleFactor, outPageHeight);
324     }
325
326     virtual int pageCount() const
327     {
328         return PrintContext::pageCount();
329     }
330
331     virtual bool shouldUseBrowserOverlays() const
332     {
333         return true;
334     }
335
336 private:
337     // Set when printing.
338     float m_printedPageWidth;
339 };
340
341 // Simple class to override some of PrintContext behavior. This is used when
342 // the frame hosts a plugin that supports custom printing. In this case, we
343 // want to delegate all printing related calls to the plugin.
344 class ChromePluginPrintContext : public ChromePrintContext {
345 public:
346     ChromePluginPrintContext(Frame* frame, int printerDPI)
347         : ChromePrintContext(frame), m_pageCount(0), m_printerDPI(printerDPI)
348     {
349         // This HAS to be a frame hosting a full-mode plugin
350         ASSERT(frame->document()->isPluginDocument());
351     }
352
353     virtual void begin(float width)
354     {
355     }
356
357     virtual void end()
358     {
359         WebPluginContainerImpl* pluginContainer = WebFrameImpl::pluginContainerFromFrame(m_frame);
360         if (pluginContainer && pluginContainer->supportsPaginatedPrint())
361             pluginContainer->printEnd();
362         else
363             ASSERT_NOT_REACHED();
364     }
365
366     virtual float getPageShrink(int pageNumber) const
367     {
368         // We don't shrink the page (maybe we should ask the widget ??)
369         return 1.0;
370     }
371
372     virtual void computePageRects(const FloatRect& printRect, float headerHeight, float footerHeight, float userScaleFactor, float& outPageHeight)
373     {
374         WebPluginContainerImpl* pluginContainer = WebFrameImpl::pluginContainerFromFrame(m_frame);
375         if (pluginContainer && pluginContainer->supportsPaginatedPrint())
376             m_pageCount = pluginContainer->printBegin(IntRect(printRect), m_printerDPI);
377         else
378             ASSERT_NOT_REACHED();
379     }
380
381     virtual int pageCount() const
382     {
383         return m_pageCount;
384     }
385
386     // Spools the printed page, a subrect of m_frame.  Skip the scale step.
387     // NativeTheme doesn't play well with scaling. Scaling is done browser side
388     // instead.  Returns the scale to be applied.
389     virtual float spoolPage(GraphicsContext& ctx, int pageNumber)
390     {
391         WebPluginContainerImpl* pluginContainer = WebFrameImpl::pluginContainerFromFrame(m_frame);
392         if (pluginContainer && pluginContainer->supportsPaginatedPrint())
393             pluginContainer->printPage(pageNumber, &ctx);
394         else
395             ASSERT_NOT_REACHED();
396         return 1.0;
397     }
398
399     virtual bool shouldUseBrowserOverlays() const
400     {
401         return false;
402     }
403
404 private:
405     // Set when printing.
406     int m_pageCount;
407     int m_printerDPI;
408 };
409
410 static WebDataSource* DataSourceForDocLoader(DocumentLoader* loader)
411 {
412     return loader ? WebDataSourceImpl::fromDocumentLoader(loader) : 0;
413 }
414
415
416 // WebFrame -------------------------------------------------------------------
417
418 class WebFrameImpl::DeferredScopeStringMatches {
419 public:
420     DeferredScopeStringMatches(WebFrameImpl* webFrame,
421                                int identifier,
422                                const WebString& searchText,
423                                const WebFindOptions& options,
424                                bool reset)
425         : m_timer(this, &DeferredScopeStringMatches::doTimeout)
426         , m_webFrame(webFrame)
427         , m_identifier(identifier)
428         , m_searchText(searchText)
429         , m_options(options)
430         , m_reset(reset)
431     {
432         m_timer.startOneShot(0.0);
433     }
434
435 private:
436     void doTimeout(Timer<DeferredScopeStringMatches>*)
437     {
438         m_webFrame->callScopeStringMatches(
439             this, m_identifier, m_searchText, m_options, m_reset);
440     }
441
442     Timer<DeferredScopeStringMatches> m_timer;
443     RefPtr<WebFrameImpl> m_webFrame;
444     int m_identifier;
445     WebString m_searchText;
446     WebFindOptions m_options;
447     bool m_reset;
448 };
449
450
451 // WebFrame -------------------------------------------------------------------
452
453 int WebFrame::instanceCount()
454 {
455     return frameCount;
456 }
457
458 WebFrame* WebFrame::frameForEnteredContext()
459 {
460     Frame* frame =
461         ScriptController::retrieveFrameForEnteredContext();
462     return WebFrameImpl::fromFrame(frame);
463 }
464
465 WebFrame* WebFrame::frameForCurrentContext()
466 {
467     Frame* frame =
468         ScriptController::retrieveFrameForCurrentContext();
469     return WebFrameImpl::fromFrame(frame);
470 }
471
472 WebFrame* WebFrame::fromFrameOwnerElement(const WebElement& element)
473 {
474     return WebFrameImpl::fromFrameOwnerElement(
475         PassRefPtr<Element>(element).get());
476 }
477
478 WebString WebFrameImpl::name() const
479 {
480     return m_frame->tree()->name();
481 }
482
483 void WebFrameImpl::setName(const WebString& name)
484 {
485     m_frame->tree()->setName(name);
486 }
487
488 WebURL WebFrameImpl::url() const
489 {
490     const WebDataSource* ds = dataSource();
491     if (!ds)
492         return WebURL();
493     return ds->request().url();
494 }
495
496 WebURL WebFrameImpl::favIconURL() const
497 {
498     FrameLoader* frameLoader = m_frame->loader();
499     // The URL to the favicon may be in the header. As such, only
500     // ask the loader for the favicon if it's finished loading.
501     if (frameLoader->state() == FrameStateComplete) {
502         const KURL& url = frameLoader->iconURL();
503         if (!url.isEmpty())
504             return url;
505     }
506     return WebURL();
507 }
508
509 WebURL WebFrameImpl::openSearchDescriptionURL() const
510 {
511     FrameLoader* frameLoader = m_frame->loader();
512     if (frameLoader->state() == FrameStateComplete
513         && m_frame->document() && m_frame->document()->head()
514         && !m_frame->tree()->parent()) {
515         HTMLHeadElement* head = m_frame->document()->head();
516         if (head) {
517             RefPtr<HTMLCollection> children = head->children();
518             for (Node* child = children->firstItem(); child; child = children->nextItem()) {
519                 HTMLLinkElement* linkElement = toHTMLLinkElement(child);
520                 if (linkElement
521                     && linkElement->type() == osdType
522                     && linkElement->rel() == osdRel
523                     && !linkElement->href().isEmpty())
524                     return linkElement->href();
525             }
526         }
527     }
528     return WebURL();
529 }
530
531 WebString WebFrameImpl::encoding() const
532 {
533     return frame()->loader()->writer()->encoding();
534 }
535
536 WebSize WebFrameImpl::scrollOffset() const
537 {
538     FrameView* view = frameView();
539     if (view)
540         return view->scrollOffset();
541
542     return WebSize();
543 }
544
545 WebSize WebFrameImpl::contentsSize() const
546 {
547     return frame()->view()->contentsSize();
548 }
549
550 int WebFrameImpl::contentsPreferredWidth() const
551 {
552     if (m_frame->document() && m_frame->document()->renderView())
553         return m_frame->document()->renderView()->minPrefWidth();
554     return 0;
555 }
556
557 int WebFrameImpl::documentElementScrollHeight() const
558 {
559     if (m_frame->document() && m_frame->document()->documentElement())
560         return m_frame->document()->documentElement()->scrollHeight();
561     return 0;
562 }
563
564 bool WebFrameImpl::hasVisibleContent() const
565 {
566     return frame()->view()->visibleWidth() > 0 && frame()->view()->visibleHeight() > 0;
567 }
568
569 WebView* WebFrameImpl::view() const
570 {
571     return viewImpl();
572 }
573
574 WebFrame* WebFrameImpl::opener() const
575 {
576     Frame* opener = 0;
577     if (m_frame)
578         opener = m_frame->loader()->opener();
579     return fromFrame(opener);
580 }
581
582 WebFrame* WebFrameImpl::parent() const
583 {
584     Frame* parent = 0;
585     if (m_frame)
586         parent = m_frame->tree()->parent();
587     return fromFrame(parent);
588 }
589
590 WebFrame* WebFrameImpl::top() const
591 {
592     if (m_frame)
593         return fromFrame(m_frame->tree()->top());
594
595     return 0;
596 }
597
598 WebFrame* WebFrameImpl::firstChild() const
599 {
600     return fromFrame(frame()->tree()->firstChild());
601 }
602
603 WebFrame* WebFrameImpl::lastChild() const
604 {
605     return fromFrame(frame()->tree()->lastChild());
606 }
607
608 WebFrame* WebFrameImpl::nextSibling() const
609 {
610     return fromFrame(frame()->tree()->nextSibling());
611 }
612
613 WebFrame* WebFrameImpl::previousSibling() const
614 {
615     return fromFrame(frame()->tree()->previousSibling());
616 }
617
618 WebFrame* WebFrameImpl::traverseNext(bool wrap) const
619 {
620     return fromFrame(frame()->tree()->traverseNextWithWrap(wrap));
621 }
622
623 WebFrame* WebFrameImpl::traversePrevious(bool wrap) const
624 {
625     return fromFrame(frame()->tree()->traversePreviousWithWrap(wrap));
626 }
627
628 WebFrame* WebFrameImpl::findChildByName(const WebString& name) const
629 {
630     return fromFrame(frame()->tree()->child(name));
631 }
632
633 WebFrame* WebFrameImpl::findChildByExpression(const WebString& xpath) const
634 {
635     if (xpath.isEmpty())
636         return 0;
637
638     Document* document = m_frame->document();
639
640     ExceptionCode ec = 0;
641     PassRefPtr<XPathResult> xpathResult =
642         document->evaluate(xpath,
643         document,
644         0, // namespace
645         XPathResult::ORDERED_NODE_ITERATOR_TYPE,
646         0, // XPathResult object
647         ec);
648     if (!xpathResult.get())
649         return 0;
650
651     Node* node = xpathResult->iterateNext(ec);
652
653     if (!node || !node->isFrameOwnerElement())
654         return 0;
655     HTMLFrameOwnerElement* frameElement =
656         static_cast<HTMLFrameOwnerElement*>(node);
657     return fromFrame(frameElement->contentFrame());
658 }
659
660 WebDocument WebFrameImpl::document() const
661 {
662     if (!m_frame || !m_frame->document())
663         return WebDocument();
664     return WebDocument(m_frame->document());
665 }
666
667 void WebFrameImpl::forms(WebVector<WebFormElement>& results) const
668 {
669     if (!m_frame)
670         return;
671
672     RefPtr<HTMLCollection> forms = m_frame->document()->forms();
673     size_t formCount = 0;
674     for (size_t i = 0; i < forms->length(); ++i) {
675         Node* node = forms->item(i);
676         if (node && node->isHTMLElement())
677             ++formCount;
678     }
679
680     WebVector<WebFormElement> temp(formCount);
681     for (size_t i = 0; i < formCount; ++i) {
682         Node* node = forms->item(i);
683         // Strange but true, sometimes item can be 0.
684         if (node && node->isHTMLElement())
685             temp[i] = static_cast<HTMLFormElement*>(node);
686     }
687     results.swap(temp);
688 }
689
690 WebAnimationController* WebFrameImpl::animationController()
691 {
692     return &m_animationController;
693 }
694
695 WebSecurityOrigin WebFrameImpl::securityOrigin() const
696 {
697     if (!m_frame || !m_frame->document())
698         return WebSecurityOrigin();
699
700     return WebSecurityOrigin(m_frame->document()->securityOrigin());
701 }
702
703 void WebFrameImpl::grantUniversalAccess()
704 {
705     ASSERT(m_frame && m_frame->document());
706     if (m_frame && m_frame->document())
707         m_frame->document()->securityOrigin()->grantUniversalAccess();
708 }
709
710 NPObject* WebFrameImpl::windowObject() const
711 {
712     if (!m_frame)
713         return 0;
714
715     return m_frame->script()->windowScriptNPObject();
716 }
717
718 void WebFrameImpl::bindToWindowObject(const WebString& name, NPObject* object)
719 {
720     ASSERT(m_frame);
721     if (!m_frame || !m_frame->script()->canExecuteScripts(NotAboutToExecuteScript))
722         return;
723
724     String key = name;
725 #if USE(V8)
726     m_frame->script()->bindToWindowObject(m_frame, key, object);
727 #else
728     notImplemented();
729 #endif
730 }
731
732 void WebFrameImpl::executeScript(const WebScriptSource& source)
733 {
734     m_frame->script()->executeScript(
735         ScriptSourceCode(source.code, source.url, source.startLine));
736 }
737
738 void WebFrameImpl::executeScriptInIsolatedWorld(
739     int worldId, const WebScriptSource* sourcesIn, unsigned numSources,
740     int extensionGroup)
741 {
742     Vector<ScriptSourceCode> sources;
743
744     for (unsigned i = 0; i < numSources; ++i) {
745         sources.append(ScriptSourceCode(
746             sourcesIn[i].code, sourcesIn[i].url, sourcesIn[i].startLine));
747     }
748
749     m_frame->script()->evaluateInIsolatedWorld(worldId, sources, extensionGroup);
750 }
751
752 void WebFrameImpl::addMessageToConsole(const WebConsoleMessage& message)
753 {
754     ASSERT(frame());
755
756     MessageLevel webCoreMessageLevel;
757     switch (message.level) {
758     case WebConsoleMessage::LevelTip:
759         webCoreMessageLevel = TipMessageLevel;
760         break;
761     case WebConsoleMessage::LevelLog:
762         webCoreMessageLevel = LogMessageLevel;
763         break;
764     case WebConsoleMessage::LevelWarning:
765         webCoreMessageLevel = WarningMessageLevel;
766         break;
767     case WebConsoleMessage::LevelError:
768         webCoreMessageLevel = ErrorMessageLevel;
769         break;
770     default:
771         ASSERT_NOT_REACHED();
772         return;
773     }
774
775     frame()->domWindow()->console()->addMessage(
776         OtherMessageSource, LogMessageType, webCoreMessageLevel, message.text,
777         1, String());
778 }
779
780 void WebFrameImpl::collectGarbage()
781 {
782     if (!m_frame)
783         return;
784     if (!m_frame->settings()->isJavaScriptEnabled())
785         return;
786     // FIXME: Move this to the ScriptController and make it JS neutral.
787 #if USE(V8)
788     m_frame->script()->collectGarbage();
789 #else
790     notImplemented();
791 #endif
792 }
793
794 #if USE(V8)
795 v8::Handle<v8::Value> WebFrameImpl::executeScriptAndReturnValue(
796     const WebScriptSource& source)
797 {
798     return m_frame->script()->executeScript(
799         ScriptSourceCode(source.code, source.url, source.startLine)).v8Value();
800 }
801
802 // Returns the V8 context for this frame, or an empty handle if there is none.
803 v8::Local<v8::Context> WebFrameImpl::mainWorldScriptContext() const
804 {
805     if (!m_frame)
806         return v8::Local<v8::Context>();
807
808     return V8Proxy::mainWorldContext(m_frame);
809 }
810 #endif
811
812 bool WebFrameImpl::insertStyleText(
813     const WebString& css, const WebString& id) {
814     Document* document = frame()->document();
815     if (!document)
816         return false;
817     Element* documentElement = document->documentElement();
818     if (!documentElement)
819         return false;
820
821     ExceptionCode err = 0;
822
823     if (!id.isEmpty()) {
824         Element* oldElement = document->getElementById(id);
825         if (oldElement) {
826             Node* parent = oldElement->parent();
827             if (!parent)
828                 return false;
829             parent->removeChild(oldElement, err);
830         }
831     }
832
833     RefPtr<Element> stylesheet = document->createElement(
834         HTMLNames::styleTag, false);
835     if (!id.isEmpty())
836         stylesheet->setAttribute(HTMLNames::idAttr, id);
837     stylesheet->setTextContent(css, err);
838     ASSERT(!err);
839     Node* first = documentElement->firstChild();
840     bool success = documentElement->insertBefore(stylesheet, first, err);
841     ASSERT(success);
842     return success;
843 }
844
845 void WebFrameImpl::reload(bool ignoreCache)
846 {
847     m_frame->loader()->history()->saveDocumentAndScrollState();
848     m_frame->loader()->reload(ignoreCache);
849 }
850
851 void WebFrameImpl::loadRequest(const WebURLRequest& request)
852 {
853     ASSERT(!request.isNull());
854     const ResourceRequest& resourceRequest = request.toResourceRequest();
855
856     if (resourceRequest.url().protocolIs("javascript")) {
857         loadJavaScriptURL(resourceRequest.url());
858         return;
859     }
860
861     m_frame->loader()->load(resourceRequest, false);
862 }
863
864 void WebFrameImpl::loadHistoryItem(const WebHistoryItem& item)
865 {
866     RefPtr<HistoryItem> historyItem = PassRefPtr<HistoryItem>(item);
867     ASSERT(historyItem.get());
868
869     // If there is no currentItem, which happens when we are navigating in
870     // session history after a crash, we need to manufacture one otherwise WebKit
871     // hoarks. This is probably the wrong thing to do, but it seems to work.
872     RefPtr<HistoryItem> currentItem = m_frame->loader()->history()->currentItem();
873     if (!currentItem) {
874         currentItem = HistoryItem::create();
875         currentItem->setLastVisitWasFailure(true);
876         m_frame->loader()->history()->setCurrentItem(currentItem.get());
877         viewImpl()->setCurrentHistoryItem(currentItem.get());
878     }
879
880     m_frame->loader()->history()->goToItem(
881         historyItem.get(), FrameLoadTypeIndexedBackForward);
882 }
883
884 void WebFrameImpl::loadData(const WebData& data,
885                             const WebString& mimeType,
886                             const WebString& textEncoding,
887                             const WebURL& baseURL,
888                             const WebURL& unreachableURL,
889                             bool replace)
890 {
891     SubstituteData substData(data, mimeType, textEncoding, unreachableURL);
892     ASSERT(substData.isValid());
893
894     // If we are loading substitute data to replace an existing load, then
895     // inherit all of the properties of that original request.  This way,
896     // reload will re-attempt the original request.  It is essential that
897     // we only do this when there is an unreachableURL since a non-empty
898     // unreachableURL informs FrameLoader::reload to load unreachableURL
899     // instead of the currently loaded URL.
900     ResourceRequest request;
901     if (replace && !unreachableURL.isEmpty())
902         request = m_frame->loader()->originalRequest();
903     request.setURL(baseURL);
904
905     m_frame->loader()->load(request, substData, false);
906     if (replace) {
907         // Do this to force WebKit to treat the load as replacing the currently
908         // loaded page.
909         m_frame->loader()->setReplacing();
910     }
911 }
912
913 void WebFrameImpl::loadHTMLString(const WebData& data,
914                                   const WebURL& baseURL,
915                                   const WebURL& unreachableURL,
916                                   bool replace)
917 {
918     loadData(data,
919              WebString::fromUTF8("text/html"),
920              WebString::fromUTF8("UTF-8"),
921              baseURL,
922              unreachableURL,
923              replace);
924 }
925
926 bool WebFrameImpl::isLoading() const
927 {
928     if (!m_frame)
929         return false;
930     return m_frame->loader()->isLoading();
931 }
932
933 void WebFrameImpl::stopLoading()
934 {
935     if (!m_frame)
936       return;
937
938     // FIXME: Figure out what we should really do here.  It seems like a bug
939     // that FrameLoader::stopLoading doesn't call stopAllLoaders.
940     m_frame->loader()->stopAllLoaders();
941     m_frame->loader()->stopLoading(UnloadEventPolicyNone);
942 }
943
944 WebDataSource* WebFrameImpl::provisionalDataSource() const
945 {
946     FrameLoader* frameLoader = m_frame->loader();
947
948     // We regard the policy document loader as still provisional.
949     DocumentLoader* docLoader = frameLoader->provisionalDocumentLoader();
950     if (!docLoader)
951         docLoader = frameLoader->policyDocumentLoader();
952
953     return DataSourceForDocLoader(docLoader);
954 }
955
956 WebDataSource* WebFrameImpl::dataSource() const
957 {
958     return DataSourceForDocLoader(m_frame->loader()->documentLoader());
959 }
960
961 WebHistoryItem WebFrameImpl::previousHistoryItem() const
962 {
963     // We use the previous item here because documentState (filled-out forms)
964     // only get saved to history when it becomes the previous item.  The caller
965     // is expected to query the history item after a navigation occurs, after
966     // the desired history item has become the previous entry.
967     return WebHistoryItem(viewImpl()->previousHistoryItem());
968 }
969
970 WebHistoryItem WebFrameImpl::currentHistoryItem() const
971 {
972     // If we are still loading, then we don't want to clobber the current
973     // history item as this could cause us to lose the scroll position and
974     // document state.  However, it is OK for new navigations.
975     if (m_frame->loader()->loadType() == FrameLoadTypeStandard
976         || !m_frame->loader()->activeDocumentLoader()->isLoadingInAPISense())
977         m_frame->loader()->history()->saveDocumentAndScrollState();
978
979     return WebHistoryItem(m_frame->page()->backForwardList()->currentItem());
980 }
981
982 void WebFrameImpl::enableViewSourceMode(bool enable)
983 {
984     if (m_frame)
985         m_frame->setInViewSourceMode(enable);
986 }
987
988 bool WebFrameImpl::isViewSourceModeEnabled() const
989 {
990     if (m_frame)
991         return m_frame->inViewSourceMode();
992
993     return false;
994 }
995
996 void WebFrameImpl::setReferrerForRequest(
997     WebURLRequest& request, const WebURL& referrerURL) {
998     String referrer;
999     if (referrerURL.isEmpty())
1000         referrer = m_frame->loader()->outgoingReferrer();
1001     else
1002         referrer = referrerURL.spec().utf16();
1003     if (SecurityOrigin::shouldHideReferrer(request.url(), referrer))
1004         return;
1005     request.setHTTPHeaderField(WebString::fromUTF8("Referer"), referrer);
1006 }
1007
1008 void WebFrameImpl::dispatchWillSendRequest(WebURLRequest& request)
1009 {
1010     ResourceResponse response;
1011     m_frame->loader()->client()->dispatchWillSendRequest(
1012         0, 0, request.toMutableResourceRequest(), response);
1013 }
1014
1015 // FIXME: This function should be moved into WebCore.
1016 void WebFrameImpl::commitDocumentData(const char* data, size_t length)
1017 {
1018     DocumentLoader* documentLoader = m_frame->loader()->documentLoader();
1019
1020     // Set the text encoding.  This calls begin() for us.  It is safe to call
1021     // this multiple times (Mac does: page/mac/WebCoreFrameBridge.mm).
1022     bool userChosen = true;
1023     String encoding = documentLoader->overrideEncoding();
1024     if (encoding.isNull()) {
1025         userChosen = false;
1026         encoding = documentLoader->response().textEncodingName();
1027     }
1028     m_frame->loader()->writer()->setEncoding(encoding, userChosen);
1029     m_frame->documentLoader()->addData(data, length);
1030 }
1031
1032 unsigned WebFrameImpl::unloadListenerCount() const
1033 {
1034     return frame()->domWindow()->pendingUnloadEventListeners();
1035 }
1036
1037 bool WebFrameImpl::isProcessingUserGesture() const
1038 {
1039     return frame()->loader()->isProcessingUserGesture();
1040 }
1041
1042 bool WebFrameImpl::willSuppressOpenerInNewFrame() const
1043 {
1044     return frame()->loader()->suppressOpenerInNewFrame();
1045 }
1046
1047 void WebFrameImpl::replaceSelection(const WebString& text)
1048 {
1049     RefPtr<DocumentFragment> fragment = createFragmentFromText(
1050         frame()->selection()->toNormalizedRange().get(), text);
1051     applyCommand(ReplaceSelectionCommand::create(
1052         frame()->document(), fragment.get(), false, true, true));
1053 }
1054
1055 void WebFrameImpl::insertText(const WebString& text)
1056 {
1057     frame()->editor()->insertText(text, 0);
1058 }
1059
1060 void WebFrameImpl::setMarkedText(
1061     const WebString& text, unsigned location, unsigned length)
1062 {
1063     Editor* editor = frame()->editor();
1064
1065     editor->confirmComposition(text);
1066
1067     Vector<CompositionUnderline> decorations;
1068     editor->setComposition(text, decorations, location, length);
1069 }
1070
1071 void WebFrameImpl::unmarkText()
1072 {
1073     frame()->editor()->confirmCompositionWithoutDisturbingSelection();
1074 }
1075
1076 bool WebFrameImpl::hasMarkedText() const
1077 {
1078     return frame()->editor()->hasComposition();
1079 }
1080
1081 WebRange WebFrameImpl::markedRange() const
1082 {
1083     return frame()->editor()->compositionRange();
1084 }
1085
1086 bool WebFrameImpl::executeCommand(const WebString& name)
1087 {
1088     ASSERT(frame());
1089
1090     if (name.length() <= 2)
1091         return false;
1092
1093     // Since we don't have NSControl, we will convert the format of command
1094     // string and call the function on Editor directly.
1095     String command = name;
1096
1097     // Make sure the first letter is upper case.
1098     command.replace(0, 1, command.substring(0, 1).upper());
1099
1100     // Remove the trailing ':' if existing.
1101     if (command[command.length() - 1] == UChar(':'))
1102         command = command.substring(0, command.length() - 1);
1103
1104     if (command == "Copy") {
1105         WebPluginContainerImpl* pluginContainer = pluginContainerFromFrame(frame());
1106         if (pluginContainer) {
1107             pluginContainer->copy();
1108             return true;
1109         }
1110     }
1111
1112     bool rv = true;
1113
1114     // Specially handling commands that Editor::execCommand does not directly
1115     // support.
1116     if (command == "DeleteToEndOfParagraph") {
1117         Editor* editor = frame()->editor();
1118         if (!editor->deleteWithDirection(SelectionController::DirectionForward,
1119                                          ParagraphBoundary,
1120                                          true,
1121                                          false)) {
1122             editor->deleteWithDirection(SelectionController::DirectionForward,
1123                                         CharacterGranularity,
1124                                         true,
1125                                         false);
1126         }
1127     } else if (command == "Indent")
1128         frame()->editor()->indent();
1129     else if (command == "Outdent")
1130         frame()->editor()->outdent();
1131     else if (command == "DeleteBackward")
1132         rv = frame()->editor()->command(AtomicString("BackwardDelete")).execute();
1133     else if (command == "DeleteForward")
1134         rv = frame()->editor()->command(AtomicString("ForwardDelete")).execute();
1135     else if (command == "AdvanceToNextMisspelling") {
1136         // False must be passed here, or the currently selected word will never be
1137         // skipped.
1138         frame()->editor()->advanceToNextMisspelling(false);
1139     } else if (command == "ToggleSpellPanel")
1140         frame()->editor()->showSpellingGuessPanel();
1141     else
1142         rv = frame()->editor()->command(command).execute();
1143     return rv;
1144 }
1145
1146 bool WebFrameImpl::executeCommand(const WebString& name, const WebString& value)
1147 {
1148     ASSERT(frame());
1149     String webName = name;
1150
1151     // moveToBeginningOfDocument and moveToEndfDocument are only handled by WebKit
1152     // for editable nodes.
1153     if (!frame()->editor()->canEdit() && webName == "moveToBeginningOfDocument")
1154         return viewImpl()->propagateScroll(ScrollUp, ScrollByDocument);
1155
1156     if (!frame()->editor()->canEdit() && webName == "moveToEndOfDocument")
1157         return viewImpl()->propagateScroll(ScrollDown, ScrollByDocument);
1158
1159     return frame()->editor()->command(webName).execute(value);
1160 }
1161
1162 bool WebFrameImpl::isCommandEnabled(const WebString& name) const
1163 {
1164     ASSERT(frame());
1165     return frame()->editor()->command(name).isEnabled();
1166 }
1167
1168 void WebFrameImpl::enableContinuousSpellChecking(bool enable)
1169 {
1170     if (enable == isContinuousSpellCheckingEnabled())
1171         return;
1172     frame()->editor()->toggleContinuousSpellChecking();
1173 }
1174
1175 bool WebFrameImpl::isContinuousSpellCheckingEnabled() const
1176 {
1177     return frame()->editor()->isContinuousSpellCheckingEnabled();
1178 }
1179
1180 bool WebFrameImpl::hasSelection() const
1181 {
1182     WebPluginContainerImpl* pluginContainer = pluginContainerFromFrame(frame());
1183     if (pluginContainer)
1184         return pluginContainer->plugin()->hasSelection();
1185
1186     // frame()->selection()->isNone() never returns true.
1187     return (frame()->selection()->start() != frame()->selection()->end());
1188 }
1189
1190 WebRange WebFrameImpl::selectionRange() const
1191 {
1192     return frame()->selection()->toNormalizedRange();
1193 }
1194
1195 WebString WebFrameImpl::selectionAsText() const
1196 {
1197     WebPluginContainerImpl* pluginContainer = pluginContainerFromFrame(frame());
1198     if (pluginContainer)
1199         return pluginContainer->plugin()->selectionAsText();
1200
1201     RefPtr<Range> range = frame()->selection()->toNormalizedRange();
1202     if (!range.get())
1203         return WebString();
1204
1205     String text = range->text();
1206 #if OS(WINDOWS)
1207     replaceNewlinesWithWindowsStyleNewlines(text);
1208 #endif
1209     replaceNBSPWithSpace(text);
1210     return text;
1211 }
1212
1213 WebString WebFrameImpl::selectionAsMarkup() const
1214 {
1215     WebPluginContainerImpl* pluginContainer = pluginContainerFromFrame(frame());
1216     if (pluginContainer)
1217         return pluginContainer->plugin()->selectionAsMarkup();
1218
1219     RefPtr<Range> range = frame()->selection()->toNormalizedRange();
1220     if (!range.get())
1221         return WebString();
1222
1223     return createMarkup(range.get(), 0);
1224 }
1225
1226 void WebFrameImpl::selectWordAroundPosition(Frame* frame, VisiblePosition pos)
1227 {
1228     VisibleSelection selection(pos);
1229     selection.expandUsingGranularity(WordGranularity);
1230
1231     if (frame->shouldChangeSelection(selection)) {
1232         TextGranularity granularity = selection.isRange() ? WordGranularity : CharacterGranularity;
1233         frame->selection()->setSelection(selection, granularity);
1234     }
1235 }
1236
1237 bool WebFrameImpl::selectWordAroundCaret()
1238 {
1239     SelectionController* controller = frame()->selection();
1240     ASSERT(!controller->isNone());
1241     if (controller->isNone() || controller->isRange())
1242         return false;
1243     selectWordAroundPosition(frame(), controller->selection().visibleStart());
1244     return true;
1245 }
1246
1247 int WebFrameImpl::printBegin(const WebSize& pageSize, int printerDPI, bool *useBrowserOverlays)
1248 {
1249     ASSERT(!frame()->document()->isFrameSet());
1250     // If this is a plugin document, check if the plugin supports its own
1251     // printing. If it does, we will delegate all printing to that.
1252     WebPluginContainerImpl* pluginContainer = pluginContainerFromFrame(frame());
1253     if (pluginContainer && pluginContainer->supportsPaginatedPrint())
1254         m_printContext.set(new ChromePluginPrintContext(frame(), printerDPI));
1255     else
1256         m_printContext.set(new ChromePrintContext(frame()));
1257
1258     FloatRect rect(0, 0, static_cast<float>(pageSize.width),
1259                          static_cast<float>(pageSize.height));
1260     m_printContext->begin(rect.width());
1261     float pageHeight;
1262     // We ignore the overlays calculation for now since they are generated in the
1263     // browser. pageHeight is actually an output parameter.
1264     m_printContext->computePageRects(rect, 0, 0, 1.0, pageHeight);
1265     if (useBrowserOverlays)
1266         *useBrowserOverlays = m_printContext->shouldUseBrowserOverlays();
1267
1268     return m_printContext->pageCount();
1269 }
1270
1271 float WebFrameImpl::getPrintPageShrink(int page)
1272 {
1273     // Ensure correct state.
1274     if (!m_printContext.get() || page < 0) {
1275         ASSERT_NOT_REACHED();
1276         return 0;
1277     }
1278
1279     return m_printContext->getPageShrink(page);
1280 }
1281
1282 float WebFrameImpl::printPage(int page, WebCanvas* canvas)
1283 {
1284     // Ensure correct state.
1285     if (!m_printContext.get() || page < 0 || !frame() || !frame()->document()) {
1286         ASSERT_NOT_REACHED();
1287         return 0;
1288     }
1289
1290 #if OS(WINDOWS) || OS(LINUX) || OS(FREEBSD) || OS(SOLARIS)
1291     PlatformContextSkia context(canvas);
1292     GraphicsContext spool(&context);
1293 #elif OS(DARWIN)
1294     GraphicsContext spool(canvas);
1295     LocalCurrentGraphicsContext localContext(&spool);
1296 #endif
1297
1298     return m_printContext->spoolPage(spool, page);
1299 }
1300
1301 void WebFrameImpl::printEnd()
1302 {
1303     ASSERT(m_printContext.get());
1304     if (m_printContext.get())
1305         m_printContext->end();
1306     m_printContext.clear();
1307 }
1308
1309 bool WebFrameImpl::isPageBoxVisible(int pageIndex)
1310 {
1311     return frame()->document()->isPageBoxVisible(pageIndex);
1312 }
1313
1314 void WebFrameImpl::pageSizeAndMarginsInPixels(int pageIndex,
1315                                               WebSize& pageSize,
1316                                               int& marginTop,
1317                                               int& marginRight,
1318                                               int& marginBottom,
1319                                               int& marginLeft)
1320 {
1321     IntSize size(pageSize.width, pageSize.height);
1322     frame()->document()->pageSizeAndMarginsInPixels(pageIndex,
1323                                                     size,
1324                                                     marginTop,
1325                                                     marginRight,
1326                                                     marginBottom,
1327                                                     marginLeft);
1328     pageSize = size;
1329 }
1330
1331 bool WebFrameImpl::find(int identifier,
1332                         const WebString& searchText,
1333                         const WebFindOptions& options,
1334                         bool wrapWithinFrame,
1335                         WebRect* selectionRect)
1336 {
1337     WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl();
1338
1339     if (!options.findNext)
1340         frame()->page()->unmarkAllTextMatches();
1341     else
1342         setMarkerActive(m_activeMatch.get(), false); // Active match is changing.
1343
1344     // Starts the search from the current selection.
1345     bool startInSelection = true;
1346
1347     // If the user has selected something since the last Find operation we want
1348     // to start from there. Otherwise, we start searching from where the last Find
1349     // operation left off (either a Find or a FindNext operation).
1350     VisibleSelection selection(frame()->selection()->selection());
1351     bool activeSelection = !selection.isNone();
1352     if (!activeSelection && m_activeMatch) {
1353         selection = VisibleSelection(m_activeMatch.get());
1354         frame()->selection()->setSelection(selection);
1355     }
1356
1357     ASSERT(frame() && frame()->view());
1358     bool found = frame()->editor()->findString(
1359         searchText, options.forward, options.matchCase, wrapWithinFrame,
1360         startInSelection);
1361     if (found) {
1362         // Store which frame was active. This will come in handy later when we
1363         // change the active match ordinal below.
1364         WebFrameImpl* oldActiveFrame = mainFrameImpl->m_activeMatchFrame;
1365         // Set this frame as the active frame (the one with the active highlight).
1366         mainFrameImpl->m_activeMatchFrame = this;
1367
1368         // We found something, so we can now query the selection for its position.
1369         VisibleSelection newSelection(frame()->selection()->selection());
1370         IntRect currSelectionRect;
1371
1372         // If we thought we found something, but it couldn't be selected (perhaps
1373         // because it was marked -webkit-user-select: none), we can't set it to
1374         // be active but we still continue searching. This matches Safari's
1375         // behavior, including some oddities when selectable and un-selectable text
1376         // are mixed on a page: see https://bugs.webkit.org/show_bug.cgi?id=19127.
1377         if (newSelection.isNone() || (newSelection.start() == newSelection.end()))
1378             m_activeMatch = 0;
1379         else {
1380             m_activeMatch = newSelection.toNormalizedRange();
1381             currSelectionRect = m_activeMatch->boundingBox();
1382             setMarkerActive(m_activeMatch.get(), true); // Active.
1383             // WebKit draws the highlighting for all matches.
1384             executeCommand(WebString::fromUTF8("Unselect"));
1385         }
1386
1387         // Make sure no node is focused. See http://crbug.com/38700.
1388         frame()->document()->setFocusedNode(0);
1389
1390         if (!options.findNext || activeSelection) {
1391             // This is either a Find operation or a Find-next from a new start point
1392             // due to a selection, so we set the flag to ask the scoping effort
1393             // to find the active rect for us so we can update the ordinal (n of m).
1394             m_locatingActiveRect = true;
1395         } else {
1396             if (oldActiveFrame != this) {
1397                 // If the active frame has changed it means that we have a multi-frame
1398                 // page and we just switch to searching in a new frame. Then we just
1399                 // want to reset the index.
1400                 if (options.forward)
1401                     m_activeMatchIndex = 0;
1402                 else
1403                     m_activeMatchIndex = m_lastMatchCount - 1;
1404             } else {
1405                 // We are still the active frame, so increment (or decrement) the
1406                 // |m_activeMatchIndex|, wrapping if needed (on single frame pages).
1407                 options.forward ? ++m_activeMatchIndex : --m_activeMatchIndex;
1408                 if (m_activeMatchIndex + 1 > m_lastMatchCount)
1409                     m_activeMatchIndex = 0;
1410                 if (m_activeMatchIndex == -1)
1411                     m_activeMatchIndex = m_lastMatchCount - 1;
1412             }
1413             if (selectionRect) {
1414                 WebRect rect = frame()->view()->convertToContainingWindow(currSelectionRect);
1415                 rect.x -= frameView()->scrollOffset().width();
1416                 rect.y -= frameView()->scrollOffset().height();
1417                 *selectionRect = rect;
1418
1419                 reportFindInPageSelection(rect, m_activeMatchIndex + 1, identifier);
1420             }
1421         }
1422     } else {
1423         // Nothing was found in this frame.
1424         m_activeMatch = 0;
1425
1426         // Erase all previous tickmarks and highlighting.
1427         invalidateArea(InvalidateAll);
1428     }
1429
1430     return found;
1431 }
1432
1433 void WebFrameImpl::stopFinding(bool clearSelection)
1434 {
1435     if (!clearSelection)
1436         setFindEndstateFocusAndSelection();
1437     cancelPendingScopingEffort();
1438
1439     // Remove all markers for matches found and turn off the highlighting.
1440     frame()->document()->markers()->removeMarkers(DocumentMarker::TextMatch);
1441     frame()->editor()->setMarkedTextMatchesAreHighlighted(false);
1442
1443     // Let the frame know that we don't want tickmarks or highlighting anymore.
1444     invalidateArea(InvalidateAll);
1445 }
1446
1447 void WebFrameImpl::scopeStringMatches(int identifier,
1448                                       const WebString& searchText,
1449                                       const WebFindOptions& options,
1450                                       bool reset)
1451 {
1452     if (!shouldScopeMatches(searchText))
1453         return;
1454
1455     WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl();
1456
1457     if (reset) {
1458         // This is a brand new search, so we need to reset everything.
1459         // Scoping is just about to begin.
1460         m_scopingComplete = false;
1461         // Clear highlighting for this frame.
1462         if (frame()->editor()->markedTextMatchesAreHighlighted())
1463             frame()->page()->unmarkAllTextMatches();
1464         // Clear the counters from last operation.
1465         m_lastMatchCount = 0;
1466         m_nextInvalidateAfter = 0;
1467
1468         m_resumeScopingFromRange = 0;
1469
1470         mainFrameImpl->m_framesScopingCount++;
1471
1472         // Now, defer scoping until later to allow find operation to finish quickly.
1473         scopeStringMatchesSoon(
1474             identifier,
1475             searchText,
1476             options,
1477             false); // false=we just reset, so don't do it again.
1478         return;
1479     }
1480
1481     RefPtr<Range> searchRange(rangeOfContents(frame()->document()));
1482
1483     ExceptionCode ec = 0, ec2 = 0;
1484     if (m_resumeScopingFromRange.get()) {
1485         // This is a continuation of a scoping operation that timed out and didn't
1486         // complete last time around, so we should start from where we left off.
1487         searchRange->setStart(m_resumeScopingFromRange->startContainer(),
1488                               m_resumeScopingFromRange->startOffset(ec2) + 1,
1489                               ec);
1490         if (ec || ec2) {
1491             if (ec2) // A non-zero |ec| happens when navigating during search.
1492                 ASSERT_NOT_REACHED();
1493             return;
1494         }
1495     }
1496
1497     // This timeout controls how long we scope before releasing control.  This
1498     // value does not prevent us from running for longer than this, but it is
1499     // periodically checked to see if we have exceeded our allocated time.
1500     const double maxScopingDuration = 0.1; // seconds
1501
1502     int matchCount = 0;
1503     bool timedOut = false;
1504     double startTime = currentTime();
1505     do {
1506         // Find next occurrence of the search string.
1507         // FIXME: (http://b/1088245) This WebKit operation may run for longer
1508         // than the timeout value, and is not interruptible as it is currently
1509         // written. We may need to rewrite it with interruptibility in mind, or
1510         // find an alternative.
1511         RefPtr<Range> resultRange(findPlainText(searchRange.get(),
1512                                                 searchText,
1513                                                 true,
1514                                                 options.matchCase));
1515         if (resultRange->collapsed(ec)) {
1516             if (!resultRange->startContainer()->isInShadowTree())
1517                 break;
1518
1519             searchRange = rangeOfContents(frame()->document());
1520             searchRange->setStartAfter(
1521                 resultRange->startContainer()->shadowAncestorNode(), ec);
1522             continue;
1523         }
1524
1525         // A non-collapsed result range can in some funky whitespace cases still not
1526         // advance the range's start position (4509328). Break to avoid infinite
1527         // loop. (This function is based on the implementation of
1528         // Frame::markAllMatchesForText, which is where this safeguard comes from).
1529         VisiblePosition newStart = endVisiblePosition(resultRange.get(), DOWNSTREAM);
1530         if (newStart == startVisiblePosition(searchRange.get(), DOWNSTREAM))
1531             break;
1532
1533         // Only treat the result as a match if it is visible
1534         if (frame()->editor()->insideVisibleArea(resultRange.get())) {
1535             ++matchCount;
1536
1537             setStart(searchRange.get(), newStart);
1538             Node* shadowTreeRoot = searchRange->shadowTreeRootNode();
1539             if (searchRange->collapsed(ec) && shadowTreeRoot)
1540                 searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->childNodeCount(), ec);
1541
1542             // Catch a special case where Find found something but doesn't know what
1543             // the bounding box for it is. In this case we set the first match we find
1544             // as the active rect.
1545             IntRect resultBounds = resultRange->boundingBox();
1546             IntRect activeSelectionRect;
1547             if (m_locatingActiveRect) {
1548                 activeSelectionRect = m_activeMatch.get() ?
1549                     m_activeMatch->boundingBox() : resultBounds;
1550             }
1551
1552             // If the Find function found a match it will have stored where the
1553             // match was found in m_activeSelectionRect on the current frame. If we
1554             // find this rect during scoping it means we have found the active
1555             // tickmark.
1556             bool foundActiveMatch = false;
1557             if (m_locatingActiveRect && (activeSelectionRect == resultBounds)) {
1558                 // We have found the active tickmark frame.
1559                 mainFrameImpl->m_activeMatchFrame = this;
1560                 foundActiveMatch = true;
1561                 // We also know which tickmark is active now.
1562                 m_activeMatchIndex = matchCount - 1;
1563                 // To stop looking for the active tickmark, we set this flag.
1564                 m_locatingActiveRect = false;
1565
1566                 // Notify browser of new location for the selected rectangle.
1567                 resultBounds.move(-frameView()->scrollOffset().width(),
1568                                   -frameView()->scrollOffset().height());
1569                 reportFindInPageSelection(
1570                     frame()->view()->convertToContainingWindow(resultBounds),
1571                     m_activeMatchIndex + 1,
1572                     identifier);
1573             }
1574
1575             addMarker(resultRange.get(), foundActiveMatch);
1576         }
1577
1578         m_resumeScopingFromRange = resultRange;
1579         timedOut = (currentTime() - startTime) >= maxScopingDuration;
1580     } while (!timedOut);
1581
1582     // Remember what we search for last time, so we can skip searching if more
1583     // letters are added to the search string (and last outcome was 0).
1584     m_lastSearchString = searchText;
1585
1586     if (matchCount > 0) {
1587         frame()->editor()->setMarkedTextMatchesAreHighlighted(true);
1588
1589         m_lastMatchCount += matchCount;
1590
1591         // Let the mainframe know how much we found during this pass.
1592         mainFrameImpl->increaseMatchCount(matchCount, identifier);
1593     }
1594
1595     if (timedOut) {
1596         // If we found anything during this pass, we should redraw. However, we
1597         // don't want to spam too much if the page is extremely long, so if we
1598         // reach a certain point we start throttling the redraw requests.
1599         if (matchCount > 0)
1600             invalidateIfNecessary();
1601
1602         // Scoping effort ran out of time, lets ask for another time-slice.
1603         scopeStringMatchesSoon(
1604             identifier,
1605             searchText,
1606             options,
1607             false); // don't reset.
1608         return; // Done for now, resume work later.
1609     }
1610
1611     // This frame has no further scoping left, so it is done. Other frames might,
1612     // of course, continue to scope matches.
1613     m_scopingComplete = true;
1614     mainFrameImpl->m_framesScopingCount--;
1615
1616     // If this is the last frame to finish scoping we need to trigger the final
1617     // update to be sent.
1618     if (!mainFrameImpl->m_framesScopingCount)
1619         mainFrameImpl->increaseMatchCount(0, identifier);
1620
1621     // This frame is done, so show any scrollbar tickmarks we haven't drawn yet.
1622     invalidateArea(InvalidateScrollbar);
1623 }
1624
1625 void WebFrameImpl::cancelPendingScopingEffort()
1626 {
1627     deleteAllValues(m_deferredScopingWork);
1628     m_deferredScopingWork.clear();
1629
1630     m_activeMatchIndex = -1;
1631 }
1632
1633 void WebFrameImpl::increaseMatchCount(int count, int identifier)
1634 {
1635     // This function should only be called on the mainframe.
1636     ASSERT(!parent());
1637
1638     m_totalMatchCount += count;
1639
1640     // Update the UI with the latest findings.
1641     if (client())
1642         client()->reportFindInPageMatchCount(identifier, m_totalMatchCount, !m_framesScopingCount);
1643 }
1644
1645 void WebFrameImpl::reportFindInPageSelection(const WebRect& selectionRect,
1646                                              int activeMatchOrdinal,
1647                                              int identifier)
1648 {
1649     // Update the UI with the latest selection rect.
1650     if (client())
1651         client()->reportFindInPageSelection(identifier, ordinalOfFirstMatchForFrame(this) + activeMatchOrdinal, selectionRect);
1652 }
1653
1654 void WebFrameImpl::resetMatchCount()
1655 {
1656     m_totalMatchCount = 0;
1657     m_framesScopingCount = 0;
1658 }
1659
1660 WebString WebFrameImpl::contentAsText(size_t maxChars) const
1661 {
1662     if (!m_frame)
1663         return WebString();
1664
1665     Vector<UChar> text;
1666     frameContentAsPlainText(maxChars, m_frame, &text);
1667     return String::adopt(text);
1668 }
1669
1670 WebString WebFrameImpl::contentAsMarkup() const
1671 {
1672     return createFullMarkup(m_frame->document());
1673 }
1674
1675 WebString WebFrameImpl::renderTreeAsText() const
1676 {
1677     return externalRepresentation(m_frame);
1678 }
1679
1680 WebString WebFrameImpl::counterValueForElementById(const WebString& id) const
1681 {
1682     if (!m_frame)
1683         return WebString();
1684
1685     Element* element = m_frame->document()->getElementById(id);
1686     if (!element)
1687         return WebString();
1688
1689     return counterValueForElement(element);
1690 }
1691
1692 WebString WebFrameImpl::markerTextForListItem(const WebElement& webElement) const
1693 {
1694     return WebCore::markerTextForListItem(const_cast<Element*>(webElement.constUnwrap<Element>()));
1695 }
1696
1697 int WebFrameImpl::pageNumberForElementById(const WebString& id,
1698                                            float pageWidthInPixels,
1699                                            float pageHeightInPixels) const
1700 {
1701     if (!m_frame)
1702         return -1;
1703
1704     Element* element = m_frame->document()->getElementById(id);
1705     if (!element)
1706         return -1;
1707
1708     FloatSize pageSize(pageWidthInPixels, pageHeightInPixels);
1709     return PrintContext::pageNumberForElement(element, pageSize);
1710 }
1711
1712 WebRect WebFrameImpl::selectionBoundsRect() const
1713 {
1714     if (hasSelection())
1715         return IntRect(frame()->selectionBounds(false));
1716
1717     return WebRect();
1718 }
1719
1720 // WebFrameImpl public ---------------------------------------------------------
1721
1722 PassRefPtr<WebFrameImpl> WebFrameImpl::create(WebFrameClient* client)
1723 {
1724     return adoptRef(new WebFrameImpl(client));
1725 }
1726
1727 WebFrameImpl::WebFrameImpl(WebFrameClient* client)
1728     : m_frameLoaderClient(this)
1729     , m_client(client)
1730     , m_activeMatchFrame(0)
1731     , m_activeMatchIndex(-1)
1732     , m_locatingActiveRect(false)
1733     , m_resumeScopingFromRange(0)
1734     , m_lastMatchCount(-1)
1735     , m_totalMatchCount(-1)
1736     , m_framesScopingCount(-1)
1737     , m_scopingComplete(false)
1738     , m_nextInvalidateAfter(0)
1739     , m_animationController(this)
1740 {
1741     ChromiumBridge::incrementStatsCounter(webFrameActiveCount);
1742     frameCount++;
1743 }
1744
1745 WebFrameImpl::~WebFrameImpl()
1746 {
1747     ChromiumBridge::decrementStatsCounter(webFrameActiveCount);
1748     frameCount--;
1749
1750     cancelPendingScopingEffort();
1751     clearPasswordListeners();
1752 }
1753
1754 void WebFrameImpl::initializeAsMainFrame(WebViewImpl* webViewImpl)
1755 {
1756     RefPtr<Frame> frame = Frame::create(webViewImpl->page(), 0, &m_frameLoaderClient);
1757     m_frame = frame.get();
1758
1759     // Add reference on behalf of FrameLoader.  See comments in
1760     // WebFrameLoaderClient::frameLoaderDestroyed for more info.
1761     ref();
1762
1763     // We must call init() after m_frame is assigned because it is referenced
1764     // during init().
1765     m_frame->init();
1766 }
1767
1768 PassRefPtr<Frame> WebFrameImpl::createChildFrame(
1769     const FrameLoadRequest& request, HTMLFrameOwnerElement* ownerElement)
1770 {
1771     RefPtr<WebFrameImpl> webframe(adoptRef(new WebFrameImpl(m_client)));
1772
1773     // Add an extra ref on behalf of the Frame/FrameLoader, which references the
1774     // WebFrame via the FrameLoaderClient interface. See the comment at the top
1775     // of this file for more info.
1776     webframe->ref();
1777
1778     RefPtr<Frame> childFrame = Frame::create(
1779         m_frame->page(), ownerElement, &webframe->m_frameLoaderClient);
1780     webframe->m_frame = childFrame.get();
1781
1782     childFrame->tree()->setName(request.frameName());
1783
1784     m_frame->tree()->appendChild(childFrame);
1785
1786     // Frame::init() can trigger onload event in the parent frame,
1787     // which may detach this frame and trigger a null-pointer access
1788     // in FrameTree::removeChild. Move init() after appendChild call
1789     // so that webframe->mFrame is in the tree before triggering
1790     // onload event handler.
1791     // Because the event handler may set webframe->mFrame to null,
1792     // it is necessary to check the value after calling init() and
1793     // return without loading URL.
1794     // (b:791612)
1795     childFrame->init(); // create an empty document
1796     if (!childFrame->tree()->parent())
1797         return 0;
1798
1799     m_frame->loader()->loadURLIntoChildFrame(
1800         request.resourceRequest().url(),
1801         request.resourceRequest().httpReferrer(),
1802         childFrame.get());
1803
1804     // A synchronous navigation (about:blank) would have already processed
1805     // onload, so it is possible for the frame to have already been destroyed by
1806     // script in the page.
1807     if (!childFrame->tree()->parent())
1808         return 0;
1809
1810     return childFrame.release();
1811 }
1812
1813 void WebFrameImpl::layout()
1814 {
1815     // layout this frame
1816     FrameView* view = m_frame->view();
1817     if (view)
1818         view->updateLayoutAndStyleIfNeededRecursive();
1819 }
1820
1821 void WebFrameImpl::paintWithContext(GraphicsContext& gc, const WebRect& rect)
1822 {
1823     IntRect dirtyRect(rect);
1824     gc.save();
1825     if (m_frame->document() && frameView()) {
1826         gc.clip(dirtyRect);
1827         frameView()->paint(&gc, dirtyRect);
1828         m_frame->page()->inspectorController()->drawNodeHighlight(gc);
1829     } else
1830         gc.fillRect(dirtyRect, Color::white, DeviceColorSpace);
1831     gc.restore();
1832 }
1833
1834 void WebFrameImpl::paint(WebCanvas* canvas, const WebRect& rect)
1835 {
1836     if (rect.isEmpty())
1837         return;
1838 #if WEBKIT_USING_CG
1839     GraphicsContext gc(canvas);
1840     LocalCurrentGraphicsContext localContext(&gc);
1841 #elif WEBKIT_USING_SKIA
1842     PlatformContextSkia context(canvas);
1843
1844     // PlatformGraphicsContext is actually a pointer to PlatformContextSkia
1845     GraphicsContext gc(reinterpret_cast<PlatformGraphicsContext*>(&context));
1846 #else
1847     notImplemented();
1848 #endif
1849     paintWithContext(gc, rect);
1850 }
1851
1852 void WebFrameImpl::createFrameView()
1853 {
1854     ASSERT(m_frame); // If m_frame doesn't exist, we probably didn't init properly.
1855
1856     Page* page = m_frame->page();
1857     ASSERT(page);
1858     ASSERT(page->mainFrame());
1859
1860     bool isMainFrame = m_frame == page->mainFrame();
1861     if (isMainFrame && m_frame->view())
1862         m_frame->view()->setParentVisible(false);
1863
1864     m_frame->setView(0);
1865
1866     WebViewImpl* webView = viewImpl();
1867
1868     RefPtr<FrameView> view;
1869     if (isMainFrame)
1870         view = FrameView::create(m_frame, webView->size());
1871     else
1872         view = FrameView::create(m_frame);
1873
1874     m_frame->setView(view);
1875
1876     if (webView->isTransparent())
1877         view->setTransparent(true);
1878
1879     // FIXME: The Mac code has a comment about this possibly being unnecessary.
1880     // See installInFrame in WebCoreFrameBridge.mm
1881     if (m_frame->ownerRenderer())
1882         m_frame->ownerRenderer()->setWidget(view.get());
1883
1884     if (HTMLFrameOwnerElement* owner = m_frame->ownerElement())
1885         view->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff);
1886
1887     if (isMainFrame)
1888         view->setParentVisible(true);
1889 }
1890
1891 WebFrameImpl* WebFrameImpl::fromFrame(Frame* frame)
1892 {
1893     if (!frame)
1894         return 0;
1895
1896     return static_cast<FrameLoaderClientImpl*>(frame->loader()->client())->webFrame();
1897 }
1898
1899 WebFrameImpl* WebFrameImpl::fromFrameOwnerElement(Element* element)
1900 {
1901     if (!element
1902         || !element->isFrameOwnerElement()
1903         || (!element->hasTagName(HTMLNames::iframeTag)
1904             && !element->hasTagName(HTMLNames::frameTag)))
1905         return 0;
1906
1907     HTMLFrameOwnerElement* frameElement =
1908         static_cast<HTMLFrameOwnerElement*>(element);
1909     return fromFrame(frameElement->contentFrame());
1910 }
1911
1912 WebViewImpl* WebFrameImpl::viewImpl() const
1913 {
1914     if (!m_frame)
1915         return 0;
1916
1917     return WebViewImpl::fromPage(m_frame->page());
1918 }
1919
1920 WebDataSourceImpl* WebFrameImpl::dataSourceImpl() const
1921 {
1922     return static_cast<WebDataSourceImpl*>(dataSource());
1923 }
1924
1925 WebDataSourceImpl* WebFrameImpl::provisionalDataSourceImpl() const
1926 {
1927     return static_cast<WebDataSourceImpl*>(provisionalDataSource());
1928 }
1929
1930 void WebFrameImpl::setFindEndstateFocusAndSelection()
1931 {
1932     WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl();
1933
1934     if (this == mainFrameImpl->activeMatchFrame() && m_activeMatch.get()) {
1935         // If the user has set the selection since the match was found, we
1936         // don't focus anything.
1937         VisibleSelection selection(frame()->selection()->selection());
1938         if (!selection.isNone())
1939             return;
1940
1941         // Try to find the first focusable node up the chain, which will, for
1942         // example, focus links if we have found text within the link.
1943         Node* node = m_activeMatch->firstNode();
1944         while (node && !node->isFocusable() && node != frame()->document())
1945             node = node->parent();
1946
1947         if (node && node != frame()->document()) {
1948             // Found a focusable parent node. Set focus to it.
1949             frame()->document()->setFocusedNode(node);
1950             return;
1951         }
1952
1953         // Iterate over all the nodes in the range until we find a focusable node.
1954         // This, for example, sets focus to the first link if you search for
1955         // text and text that is within one or more links.
1956         node = m_activeMatch->firstNode();
1957         while (node && node != m_activeMatch->pastLastNode()) {
1958             if (node->isFocusable()) {
1959                 frame()->document()->setFocusedNode(node);
1960                 return;
1961             }
1962             node = node->traverseNextNode();
1963         }
1964
1965         // No node related to the active match was focusable, so set the
1966         // active match as the selection (so that when you end the Find session,
1967         // you'll have the last thing you found highlighted) and make sure that
1968         // we have nothing focused (otherwise you might have text selected but
1969         // a link focused, which is weird).
1970         frame()->selection()->setSelection(m_activeMatch.get());
1971         frame()->document()->setFocusedNode(0);
1972     }
1973 }
1974
1975 void WebFrameImpl::didFail(const ResourceError& error, bool wasProvisional)
1976 {
1977     if (!client())
1978         return;
1979     WebURLError webError = error;
1980     if (wasProvisional)
1981         client()->didFailProvisionalLoad(this, webError);
1982     else
1983         client()->didFailLoad(this, webError);
1984 }
1985
1986 void WebFrameImpl::setCanHaveScrollbars(bool canHaveScrollbars)
1987 {
1988     m_frame->view()->setCanHaveScrollbars(canHaveScrollbars);
1989 }
1990
1991 bool WebFrameImpl::registerPasswordListener(
1992     WebInputElement inputElement,
1993     WebPasswordAutocompleteListener* listener)
1994 {
1995     RefPtr<HTMLInputElement> element(inputElement.unwrap<HTMLInputElement>());
1996     if (!m_passwordListeners.add(element, listener).second) {
1997         delete listener;
1998         return false;
1999     }
2000     return true;
2001 }
2002
2003 void WebFrameImpl::notifiyPasswordListenerOfAutocomplete(
2004     const WebInputElement& inputElement)
2005 {
2006     const HTMLInputElement* element = inputElement.constUnwrap<HTMLInputElement>();
2007     WebPasswordAutocompleteListener* listener = getPasswordListener(element);
2008     // Password listeners need to autocomplete other fields that depend on the
2009     // input element with autofill suggestions.
2010     if (listener)
2011         listener->performInlineAutocomplete(element->value(), false, false);
2012 }
2013
2014 WebPasswordAutocompleteListener* WebFrameImpl::getPasswordListener(
2015     const HTMLInputElement* inputElement)
2016 {
2017     return m_passwordListeners.get(RefPtr<HTMLInputElement>(const_cast<HTMLInputElement*>(inputElement)));
2018 }
2019
2020 // WebFrameImpl private --------------------------------------------------------
2021
2022 void WebFrameImpl::closing()
2023 {
2024     m_frame = 0;
2025 }
2026
2027 void WebFrameImpl::invalidateArea(AreaToInvalidate area)
2028 {
2029     ASSERT(frame() && frame()->view());
2030     FrameView* view = frame()->view();
2031
2032     if ((area & InvalidateAll) == InvalidateAll)
2033         view->invalidateRect(view->frameRect());
2034     else {
2035         if ((area & InvalidateContentArea) == InvalidateContentArea) {
2036             IntRect contentArea(
2037                 view->x(), view->y(), view->visibleWidth(), view->visibleHeight());
2038             IntRect frameRect = view->frameRect();
2039             contentArea.move(-frameRect.topLeft().x(), -frameRect.topLeft().y());
2040             view->invalidateRect(contentArea);
2041         }
2042
2043         if ((area & InvalidateScrollbar) == InvalidateScrollbar) {
2044             // Invalidate the vertical scroll bar region for the view.
2045             IntRect scrollBarVert(
2046                 view->x() + view->visibleWidth(), view->y(),
2047                 ScrollbarTheme::nativeTheme()->scrollbarThickness(),
2048                 view->visibleHeight());
2049             IntRect frameRect = view->frameRect();
2050             scrollBarVert.move(-frameRect.topLeft().x(), -frameRect.topLeft().y());
2051             view->invalidateRect(scrollBarVert);
2052         }
2053     }
2054 }
2055
2056 void WebFrameImpl::addMarker(Range* range, bool activeMatch)
2057 {
2058     // Use a TextIterator to visit the potentially multiple nodes the range
2059     // covers.
2060     TextIterator markedText(range);
2061     for (; !markedText.atEnd(); markedText.advance()) {
2062         RefPtr<Range> textPiece = markedText.range();
2063         int exception = 0;
2064
2065         DocumentMarker marker = {
2066             DocumentMarker::TextMatch,
2067             textPiece->startOffset(exception),
2068             textPiece->endOffset(exception),
2069             "",
2070             activeMatch
2071         };
2072
2073         if (marker.endOffset > marker.startOffset) {
2074             // Find the node to add a marker to and add it.
2075             Node* node = textPiece->startContainer(exception);
2076             frame()->document()->markers()->addMarker(node, marker);
2077
2078             // Rendered rects for markers in WebKit are not populated until each time
2079             // the markers are painted. However, we need it to happen sooner, because
2080             // the whole purpose of tickmarks on the scrollbar is to show where
2081             // matches off-screen are (that haven't been painted yet).
2082             Vector<DocumentMarker> markers = frame()->document()->markers()->markersForNode(node);
2083             frame()->document()->markers()->setRenderedRectForMarker(
2084                 textPiece->startContainer(exception),
2085                 markers[markers.size() - 1],
2086                 range->boundingBox());
2087         }
2088     }
2089 }
2090
2091 void WebFrameImpl::setMarkerActive(Range* range, bool active)
2092 {
2093     WebCore::ExceptionCode ec;
2094     if (!range || range->collapsed(ec))
2095         return;
2096
2097     frame()->document()->markers()->setMarkersActive(range, active);
2098 }
2099
2100 int WebFrameImpl::ordinalOfFirstMatchForFrame(WebFrameImpl* frame) const
2101 {
2102     int ordinal = 0;
2103     WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl();
2104     // Iterate from the main frame up to (but not including) |frame| and
2105     // add up the number of matches found so far.
2106     for (WebFrameImpl* it = mainFrameImpl;
2107          it != frame;
2108          it = static_cast<WebFrameImpl*>(it->traverseNext(true))) {
2109         if (it->m_lastMatchCount > 0)
2110             ordinal += it->m_lastMatchCount;
2111     }
2112     return ordinal;
2113 }
2114
2115 bool WebFrameImpl::shouldScopeMatches(const String& searchText)
2116 {
2117     // Don't scope if we can't find a frame or a view or if the frame is not visible.
2118     // The user may have closed the tab/application, so abort.
2119     if (!frame() || !frame()->view() || !hasVisibleContent())
2120         return false;
2121
2122     ASSERT(frame()->document() && frame()->view());
2123
2124     // If the frame completed the scoping operation and found 0 matches the last
2125     // time it was searched, then we don't have to search it again if the user is
2126     // just adding to the search string or sending the same search string again.
2127     if (m_scopingComplete && !m_lastSearchString.isEmpty() && !m_lastMatchCount) {
2128         // Check to see if the search string prefixes match.
2129         String previousSearchPrefix =
2130             searchText.substring(0, m_lastSearchString.length());
2131
2132         if (previousSearchPrefix == m_lastSearchString)
2133             return false; // Don't search this frame, it will be fruitless.
2134     }
2135
2136     return true;
2137 }
2138
2139 void WebFrameImpl::scopeStringMatchesSoon(int identifier, const WebString& searchText,
2140                                           const WebFindOptions& options, bool reset)
2141 {
2142     m_deferredScopingWork.append(new DeferredScopeStringMatches(
2143         this, identifier, searchText, options, reset));
2144 }
2145
2146 void WebFrameImpl::callScopeStringMatches(DeferredScopeStringMatches* caller,
2147                                           int identifier, const WebString& searchText,
2148                                           const WebFindOptions& options, bool reset)
2149 {
2150     m_deferredScopingWork.remove(m_deferredScopingWork.find(caller));
2151
2152     scopeStringMatches(identifier, searchText, options, reset);
2153
2154     // This needs to happen last since searchText is passed by reference.
2155     delete caller;
2156 }
2157
2158 void WebFrameImpl::invalidateIfNecessary()
2159 {
2160     if (m_lastMatchCount > m_nextInvalidateAfter) {
2161         // FIXME: (http://b/1088165) Optimize the drawing of the tickmarks and
2162         // remove this. This calculation sets a milestone for when next to
2163         // invalidate the scrollbar and the content area. We do this so that we
2164         // don't spend too much time drawing the scrollbar over and over again.
2165         // Basically, up until the first 500 matches there is no throttle.
2166         // After the first 500 matches, we set set the milestone further and
2167         // further out (750, 1125, 1688, 2K, 3K).
2168         static const int startSlowingDownAfter = 500;
2169         static const int slowdown = 750;
2170         int i = (m_lastMatchCount / startSlowingDownAfter);
2171         m_nextInvalidateAfter += i * slowdown;
2172
2173         invalidateArea(InvalidateScrollbar);
2174     }
2175 }
2176
2177 void WebFrameImpl::clearPasswordListeners()
2178 {
2179     deleteAllValues(m_passwordListeners);
2180     m_passwordListeners.clear();
2181 }
2182
2183 void WebFrameImpl::loadJavaScriptURL(const KURL& url)
2184 {
2185     // This is copied from ScriptController::executeIfJavaScriptURL.
2186     // Unfortunately, we cannot just use that method since it is private, and
2187     // it also doesn't quite behave as we require it to for bookmarklets.  The
2188     // key difference is that we need to suppress loading the string result
2189     // from evaluating the JS URL if executing the JS URL resulted in a
2190     // location change.  We also allow a JS URL to be loaded even if scripts on
2191     // the page are otherwise disabled.
2192
2193     if (!m_frame->document() || !m_frame->page())
2194         return;
2195
2196     String script = decodeURLEscapeSequences(url.string().substring(strlen("javascript:")));
2197     ScriptValue result = m_frame->script()->executeScript(script, true);
2198
2199     String scriptResult;
2200     if (!result.getString(scriptResult))
2201         return;
2202
2203     if (!m_frame->redirectScheduler()->locationChangePending())
2204         m_frame->loader()->writer()->replaceDocument(scriptResult);
2205 }
2206
2207 } // namespace WebKit