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//    |           WebFrame
39//    |              O
40//    |              |
41//   Page O------- LocalFrame (m_mainFrame) O-------O FrameView
42//                   ||
43//                   ||
44//               FrameLoader
45//
46// FrameLoader and LocalFrame are formerly one object that was split apart because
47// it got too big. They basically have the same lifetime, hence the double line.
48//
49// From the perspective of the embedder, WebFrame is simply an object that it
50// allocates by calling WebFrame::create() and must be freed by calling close().
51// Internally, WebFrame is actually refcounted and it holds a reference to its
52// corresponding LocalFrame in WebCore.
53//
54// How frames are destroyed
55// ------------------------
56//
57// The main frame is never destroyed and is re-used. The FrameLoader is re-used
58// and a reference to the main frame is kept by the Page.
59//
60// When frame content is replaced, all subframes are destroyed. This happens
61// in FrameLoader::detachFromParent for each subframe in a pre-order depth-first
62// traversal. Note that child node order may not match DOM node order!
63// detachFromParent() calls FrameLoaderClient::detachedFromParent(), which calls
64// WebFrame::frameDetached(). This triggers WebFrame to clear its reference to
65// LocalFrame, and also notifies the embedder via WebFrameClient that the frame is
66// detached. Most embedders will invoke close() on the WebFrame at this point,
67// triggering its deletion unless something else is still retaining a reference.
68//
69// Thie client is expected to be set whenever the WebLocalFrameImpl is attached to
70// the DOM.
71
72#include "config.h"
73#include "web/WebLocalFrameImpl.h"
74
75#include "bindings/v8/DOMWrapperWorld.h"
76#include "bindings/v8/ExceptionState.h"
77#include "bindings/v8/ExceptionStatePlaceholder.h"
78#include "bindings/v8/ScriptController.h"
79#include "bindings/v8/ScriptSourceCode.h"
80#include "bindings/v8/ScriptValue.h"
81#include "bindings/v8/V8GCController.h"
82#include "bindings/v8/V8PerIsolateData.h"
83#include "core/HTMLNames.h"
84#include "core/dom/Document.h"
85#include "core/dom/DocumentMarker.h"
86#include "core/dom/DocumentMarkerController.h"
87#include "core/dom/IconURL.h"
88#include "core/dom/MessagePort.h"
89#include "core/dom/Node.h"
90#include "core/dom/NodeTraversal.h"
91#include "core/dom/shadow/ShadowRoot.h"
92#include "core/editing/Editor.h"
93#include "core/editing/FrameSelection.h"
94#include "core/editing/InputMethodController.h"
95#include "core/editing/PlainTextRange.h"
96#include "core/editing/SpellChecker.h"
97#include "core/editing/TextAffinity.h"
98#include "core/editing/TextIterator.h"
99#include "core/editing/htmlediting.h"
100#include "core/editing/markup.h"
101#include "core/frame/Console.h"
102#include "core/frame/LocalDOMWindow.h"
103#include "core/frame/FrameHost.h"
104#include "core/frame/FrameView.h"
105#include "core/frame/Settings.h"
106#include "core/html/HTMLCollection.h"
107#include "core/html/HTMLFormElement.h"
108#include "core/html/HTMLFrameElementBase.h"
109#include "core/html/HTMLFrameOwnerElement.h"
110#include "core/html/HTMLHeadElement.h"
111#include "core/html/HTMLInputElement.h"
112#include "core/html/HTMLLinkElement.h"
113#include "core/html/PluginDocument.h"
114#include "core/inspector/InspectorController.h"
115#include "core/inspector/ScriptCallStack.h"
116#include "core/loader/DocumentLoader.h"
117#include "core/loader/FrameLoadRequest.h"
118#include "core/loader/FrameLoader.h"
119#include "core/loader/HistoryItem.h"
120#include "core/loader/SubstituteData.h"
121#include "core/page/Chrome.h"
122#include "core/page/EventHandler.h"
123#include "core/page/FocusController.h"
124#include "core/page/FrameTree.h"
125#include "core/page/Page.h"
126#include "core/page/PrintContext.h"
127#include "core/rendering/HitTestResult.h"
128#include "core/rendering/RenderBox.h"
129#include "core/rendering/RenderFrame.h"
130#include "core/rendering/RenderLayer.h"
131#include "core/rendering/RenderObject.h"
132#include "core/rendering/RenderTreeAsText.h"
133#include "core/rendering/RenderView.h"
134#include "core/rendering/style/StyleInheritedData.h"
135#include "core/timing/Performance.h"
136#include "modules/geolocation/GeolocationController.h"
137#include "modules/notifications/NotificationController.h"
138#include "modules/screen_orientation/ScreenOrientationController.h"
139#include "platform/TraceEvent.h"
140#include "platform/UserGestureIndicator.h"
141#include "platform/clipboard/ClipboardUtilities.h"
142#include "platform/fonts/FontCache.h"
143#include "platform/graphics/GraphicsContext.h"
144#include "platform/graphics/GraphicsLayerClient.h"
145#include "platform/graphics/skia/SkiaUtils.h"
146#include "platform/heap/Handle.h"
147#include "platform/network/ResourceRequest.h"
148#include "platform/scroll/ScrollTypes.h"
149#include "platform/scroll/ScrollbarTheme.h"
150#include "platform/weborigin/KURL.h"
151#include "platform/weborigin/SchemeRegistry.h"
152#include "platform/weborigin/SecurityPolicy.h"
153#include "public/platform/Platform.h"
154#include "public/platform/WebFloatPoint.h"
155#include "public/platform/WebFloatRect.h"
156#include "public/platform/WebLayer.h"
157#include "public/platform/WebPoint.h"
158#include "public/platform/WebRect.h"
159#include "public/platform/WebSize.h"
160#include "public/platform/WebURLError.h"
161#include "public/platform/WebVector.h"
162#include "public/web/WebConsoleMessage.h"
163#include "public/web/WebDOMEvent.h"
164#include "public/web/WebDOMEventListener.h"
165#include "public/web/WebDocument.h"
166#include "public/web/WebFindOptions.h"
167#include "public/web/WebFormElement.h"
168#include "public/web/WebFrameClient.h"
169#include "public/web/WebHistoryItem.h"
170#include "public/web/WebIconURL.h"
171#include "public/web/WebInputElement.h"
172#include "public/web/WebNode.h"
173#include "public/web/WebPerformance.h"
174#include "public/web/WebPlugin.h"
175#include "public/web/WebPrintParams.h"
176#include "public/web/WebRange.h"
177#include "public/web/WebScriptSource.h"
178#include "public/web/WebSecurityOrigin.h"
179#include "public/web/WebSerializedScriptValue.h"
180#include "web/AssociatedURLLoader.h"
181#include "web/CompositionUnderlineVectorBuilder.h"
182#include "web/EventListenerWrapper.h"
183#include "web/FindInPageCoordinates.h"
184#include "web/GeolocationClientProxy.h"
185#include "web/LocalFileSystemClient.h"
186#include "web/MIDIClientProxy.h"
187#include "web/PageOverlay.h"
188#include "web/SharedWorkerRepositoryClientImpl.h"
189#include "web/TextFinder.h"
190#include "web/WebDataSourceImpl.h"
191#include "web/WebDevToolsAgentPrivate.h"
192#include "web/WebPluginContainerImpl.h"
193#include "web/WebViewImpl.h"
194#include "wtf/CurrentTime.h"
195#include "wtf/HashMap.h"
196#include <algorithm>
197
198using namespace WebCore;
199
200namespace blink {
201
202static int frameCount = 0;
203
204// Key for a StatsCounter tracking how many WebFrames are active.
205static const char webFrameActiveCount[] = "WebFrameActiveCount";
206
207static void frameContentAsPlainText(size_t maxChars, LocalFrame* frame, StringBuilder& output)
208{
209    Document* document = frame->document();
210    if (!document)
211        return;
212
213    if (!frame->view())
214        return;
215
216    // TextIterator iterates over the visual representation of the DOM. As such,
217    // it requires you to do a layout before using it (otherwise it'll crash).
218    document->updateLayout();
219
220    // Select the document body.
221    RefPtrWillBeRawPtr<Range> range(document->createRange());
222    TrackExceptionState exceptionState;
223    range->selectNodeContents(document->body(), exceptionState);
224
225    if (!exceptionState.hadException()) {
226        // The text iterator will walk nodes giving us text. This is similar to
227        // the plainText() function in core/editing/TextIterator.h, but we implement the maximum
228        // size and also copy the results directly into a wstring, avoiding the
229        // string conversion.
230        for (TextIterator it(range.get()); !it.atEnd(); it.advance()) {
231            it.appendTextToStringBuilder(output, 0, maxChars - output.length());
232            if (output.length() >= maxChars)
233                return; // Filled up the buffer.
234        }
235    }
236
237    // The separator between frames when the frames are converted to plain text.
238    const LChar frameSeparator[] = { '\n', '\n' };
239    const size_t frameSeparatorLength = WTF_ARRAY_LENGTH(frameSeparator);
240
241    // Recursively walk the children.
242    const FrameTree& frameTree = frame->tree();
243    for (Frame* curChild = frameTree.firstChild(); curChild; curChild = curChild->tree().nextSibling()) {
244        if (!curChild->isLocalFrame())
245            continue;
246        LocalFrame* curLocalChild = toLocalFrame(curChild);
247        // Ignore the text of non-visible frames.
248        RenderView* contentRenderer = curLocalChild->contentRenderer();
249        RenderPart* ownerRenderer = curLocalChild->ownerRenderer();
250        if (!contentRenderer || !contentRenderer->width() || !contentRenderer->height()
251            || (contentRenderer->x() + contentRenderer->width() <= 0) || (contentRenderer->y() + contentRenderer->height() <= 0)
252            || (ownerRenderer && ownerRenderer->style() && ownerRenderer->style()->visibility() != VISIBLE)) {
253            continue;
254        }
255
256        // Make sure the frame separator won't fill up the buffer, and give up if
257        // it will. The danger is if the separator will make the buffer longer than
258        // maxChars. This will cause the computation above:
259        //   maxChars - output->size()
260        // to be a negative number which will crash when the subframe is added.
261        if (output.length() >= maxChars - frameSeparatorLength)
262            return;
263
264        output.append(frameSeparator, frameSeparatorLength);
265        frameContentAsPlainText(maxChars, curLocalChild, output);
266        if (output.length() >= maxChars)
267            return; // Filled up the buffer.
268    }
269}
270
271WebPluginContainerImpl* WebLocalFrameImpl::pluginContainerFromFrame(LocalFrame* frame)
272{
273    if (!frame)
274        return 0;
275    if (!frame->document() || !frame->document()->isPluginDocument())
276        return 0;
277    PluginDocument* pluginDocument = toPluginDocument(frame->document());
278    return toWebPluginContainerImpl(pluginDocument->pluginWidget());
279}
280
281WebPluginContainerImpl* WebLocalFrameImpl::pluginContainerFromNode(WebCore::LocalFrame* frame, const WebNode& node)
282{
283    WebPluginContainerImpl* pluginContainer = pluginContainerFromFrame(frame);
284    if (pluginContainer)
285        return pluginContainer;
286    return toWebPluginContainerImpl(node.pluginContainer());
287}
288
289// Simple class to override some of PrintContext behavior. Some of the methods
290// made virtual so that they can be overridden by ChromePluginPrintContext.
291class ChromePrintContext : public PrintContext {
292    WTF_MAKE_NONCOPYABLE(ChromePrintContext);
293public:
294    ChromePrintContext(LocalFrame* frame)
295        : PrintContext(frame)
296        , m_printedPageWidth(0)
297    {
298    }
299
300    virtual ~ChromePrintContext() { }
301
302    virtual void begin(float width, float height)
303    {
304        ASSERT(!m_printedPageWidth);
305        m_printedPageWidth = width;
306        PrintContext::begin(m_printedPageWidth, height);
307    }
308
309    virtual void end()
310    {
311        PrintContext::end();
312    }
313
314    virtual float getPageShrink(int pageNumber) const
315    {
316        IntRect pageRect = m_pageRects[pageNumber];
317        return m_printedPageWidth / pageRect.width();
318    }
319
320    // Spools the printed page, a subrect of frame(). Skip the scale step.
321    // NativeTheme doesn't play well with scaling. Scaling is done browser side
322    // instead. Returns the scale to be applied.
323    // On Linux, we don't have the problem with NativeTheme, hence we let WebKit
324    // do the scaling and ignore the return value.
325    virtual float spoolPage(GraphicsContext& context, int pageNumber)
326    {
327        IntRect pageRect = m_pageRects[pageNumber];
328        float scale = m_printedPageWidth / pageRect.width();
329
330        context.save();
331#if OS(POSIX) && !OS(MACOSX)
332        context.scale(scale, scale);
333#endif
334        context.translate(static_cast<float>(-pageRect.x()), static_cast<float>(-pageRect.y()));
335        context.clip(pageRect);
336        frame()->view()->paintContents(&context, pageRect);
337        if (context.supportsURLFragments())
338            outputLinkedDestinations(context, frame()->document(), pageRect);
339        context.restore();
340        return scale;
341    }
342
343    void spoolAllPagesWithBoundaries(GraphicsContext& graphicsContext, const FloatSize& pageSizeInPixels)
344    {
345        if (!frame()->document() || !frame()->view() || !frame()->document()->renderView())
346            return;
347
348        frame()->document()->updateLayout();
349
350        float pageHeight;
351        computePageRects(FloatRect(FloatPoint(0, 0), pageSizeInPixels), 0, 0, 1, pageHeight);
352
353        const float pageWidth = pageSizeInPixels.width();
354        size_t numPages = pageRects().size();
355        int totalHeight = numPages * (pageSizeInPixels.height() + 1) - 1;
356
357        // Fill the whole background by white.
358        graphicsContext.setFillColor(Color::white);
359        graphicsContext.fillRect(FloatRect(0, 0, pageWidth, totalHeight));
360
361        int currentHeight = 0;
362        for (size_t pageIndex = 0; pageIndex < numPages; pageIndex++) {
363            // Draw a line for a page boundary if this isn't the first page.
364            if (pageIndex > 0) {
365                graphicsContext.save();
366                graphicsContext.setStrokeColor(Color(0, 0, 255));
367                graphicsContext.setFillColor(Color(0, 0, 255));
368                graphicsContext.drawLine(IntPoint(0, currentHeight), IntPoint(pageWidth, currentHeight));
369                graphicsContext.restore();
370            }
371
372            graphicsContext.save();
373
374            graphicsContext.translate(0, currentHeight);
375#if OS(WIN) || OS(MACOSX)
376            // Account for the disabling of scaling in spoolPage. In the context
377            // of spoolAllPagesWithBoundaries the scale HAS NOT been pre-applied.
378            float scale = getPageShrink(pageIndex);
379            graphicsContext.scale(scale, scale);
380#endif
381            spoolPage(graphicsContext, pageIndex);
382            graphicsContext.restore();
383
384            currentHeight += pageSizeInPixels.height() + 1;
385        }
386    }
387
388    virtual void computePageRects(const FloatRect& printRect, float headerHeight, float footerHeight, float userScaleFactor, float& outPageHeight)
389    {
390        PrintContext::computePageRects(printRect, headerHeight, footerHeight, userScaleFactor, outPageHeight);
391    }
392
393    virtual int pageCount() const
394    {
395        return PrintContext::pageCount();
396    }
397
398private:
399    // Set when printing.
400    float m_printedPageWidth;
401};
402
403// Simple class to override some of PrintContext behavior. This is used when
404// the frame hosts a plugin that supports custom printing. In this case, we
405// want to delegate all printing related calls to the plugin.
406class ChromePluginPrintContext : public ChromePrintContext {
407public:
408    ChromePluginPrintContext(LocalFrame* frame, WebPluginContainerImpl* plugin, const WebPrintParams& printParams)
409        : ChromePrintContext(frame), m_plugin(plugin), m_pageCount(0), m_printParams(printParams)
410    {
411    }
412
413    virtual ~ChromePluginPrintContext() { }
414
415    virtual void begin(float width, float height)
416    {
417    }
418
419    virtual void end()
420    {
421        m_plugin->printEnd();
422    }
423
424    virtual float getPageShrink(int pageNumber) const
425    {
426        // We don't shrink the page (maybe we should ask the widget ??)
427        return 1.0;
428    }
429
430    virtual void computePageRects(const FloatRect& printRect, float headerHeight, float footerHeight, float userScaleFactor, float& outPageHeight)
431    {
432        m_printParams.printContentArea = IntRect(printRect);
433        m_pageCount = m_plugin->printBegin(m_printParams);
434    }
435
436    virtual int pageCount() const
437    {
438        return m_pageCount;
439    }
440
441    // Spools the printed page, a subrect of frame(). Skip the scale step.
442    // NativeTheme doesn't play well with scaling. Scaling is done browser side
443    // instead. Returns the scale to be applied.
444    virtual float spoolPage(GraphicsContext& context, int pageNumber)
445    {
446        m_plugin->printPage(pageNumber, &context);
447        return 1.0;
448    }
449
450private:
451    // Set when printing.
452    WebPluginContainerImpl* m_plugin;
453    int m_pageCount;
454    WebPrintParams m_printParams;
455
456};
457
458static WebDataSource* DataSourceForDocLoader(DocumentLoader* loader)
459{
460    return loader ? WebDataSourceImpl::fromDocumentLoader(loader) : 0;
461}
462
463// WebFrame -------------------------------------------------------------------
464
465int WebFrame::instanceCount()
466{
467    return frameCount;
468}
469
470WebLocalFrame* WebLocalFrame::frameForCurrentContext()
471{
472    v8::Handle<v8::Context> context = v8::Isolate::GetCurrent()->GetCurrentContext();
473    if (context.IsEmpty())
474        return 0;
475    return frameForContext(context);
476}
477
478WebLocalFrame* WebLocalFrame::frameForContext(v8::Handle<v8::Context> context)
479{
480    return WebLocalFrameImpl::fromFrame(toFrameIfNotDetached(context));
481}
482
483WebLocalFrame* WebLocalFrame::fromFrameOwnerElement(const WebElement& element)
484{
485    return WebLocalFrameImpl::fromFrameOwnerElement(PassRefPtrWillBeRawPtr<Element>(element).get());
486}
487
488bool WebLocalFrameImpl::isWebLocalFrame() const
489{
490    return true;
491}
492
493WebLocalFrame* WebLocalFrameImpl::toWebLocalFrame()
494{
495    return this;
496}
497
498bool WebLocalFrameImpl::isWebRemoteFrame() const
499{
500    return false;
501}
502
503WebRemoteFrame* WebLocalFrameImpl::toWebRemoteFrame()
504{
505    ASSERT_NOT_REACHED();
506    return 0;
507}
508
509void WebLocalFrameImpl::close()
510{
511    m_client = 0;
512
513    // FIXME: Oilpan: Signal to LocalFrame and its supplements that the frame is
514    // being torn down so it can do prompt clean-up. For example, this will
515    // clear the raw back pointer to m_geolocationClientProxy. Once
516    // GeolocationClientProxy is on-heap it looks like we can completely remove
517    // |willBeDestroyed| from supplements since tracing will ensure safety.
518    if (m_frame)
519        m_frame->willBeDestroyed();
520
521    deref(); // Balances ref() acquired in WebFrame::create
522}
523
524WebString WebLocalFrameImpl::uniqueName() const
525{
526    return frame()->tree().uniqueName();
527}
528
529WebString WebLocalFrameImpl::assignedName() const
530{
531    return frame()->tree().name();
532}
533
534void WebLocalFrameImpl::setName(const WebString& name)
535{
536    frame()->tree().setName(name);
537}
538
539WebVector<WebIconURL> WebLocalFrameImpl::iconURLs(int iconTypesMask) const
540{
541    // The URL to the icon may be in the header. As such, only
542    // ask the loader for the icon if it's finished loading.
543    if (frame()->loader().state() == FrameStateComplete)
544        return frame()->document()->iconURLs(iconTypesMask);
545    return WebVector<WebIconURL>();
546}
547
548void WebLocalFrameImpl::setIsRemote(bool isRemote)
549{
550    m_isRemote = isRemote;
551    if (isRemote)
552        client()->initializeChildFrame(frame()->view()->frameRect(), frame()->view()->visibleContentScaleFactor());
553}
554
555void WebLocalFrameImpl::setRemoteWebLayer(WebLayer* webLayer)
556{
557    if (!frame())
558        return;
559
560    if (frame()->remotePlatformLayer())
561        GraphicsLayer::unregisterContentsLayer(frame()->remotePlatformLayer());
562    if (webLayer)
563        GraphicsLayer::registerContentsLayer(webLayer);
564    frame()->setRemotePlatformLayer(webLayer);
565    // FIXME: This should be moved to WebRemoteFrame.
566    ASSERT(frame()->deprecatedLocalOwner());
567    frame()->deprecatedLocalOwner()->setNeedsCompositingUpdate();
568    if (RenderPart* renderer = frame()->ownerRenderer())
569        renderer->layer()->updateSelfPaintingLayer();
570}
571
572void WebLocalFrameImpl::setPermissionClient(WebPermissionClient* permissionClient)
573{
574    m_permissionClient = permissionClient;
575}
576
577void WebLocalFrameImpl::setSharedWorkerRepositoryClient(WebSharedWorkerRepositoryClient* client)
578{
579    m_sharedWorkerRepositoryClient = SharedWorkerRepositoryClientImpl::create(client);
580}
581
582WebSize WebLocalFrameImpl::scrollOffset() const
583{
584    FrameView* view = frameView();
585    if (!view)
586        return WebSize();
587    return view->scrollOffset();
588}
589
590WebSize WebLocalFrameImpl::minimumScrollOffset() const
591{
592    FrameView* view = frameView();
593    if (!view)
594        return WebSize();
595    return toIntSize(view->minimumScrollPosition());
596}
597
598WebSize WebLocalFrameImpl::maximumScrollOffset() const
599{
600    FrameView* view = frameView();
601    if (!view)
602        return WebSize();
603    return toIntSize(view->maximumScrollPosition());
604}
605
606void WebLocalFrameImpl::setScrollOffset(const WebSize& offset)
607{
608    if (FrameView* view = frameView())
609        view->setScrollOffset(IntPoint(offset.width, offset.height));
610}
611
612WebSize WebLocalFrameImpl::contentsSize() const
613{
614    return frame()->view()->contentsSize();
615}
616
617bool WebLocalFrameImpl::hasVisibleContent() const
618{
619    if (RenderPart* renderer = frame()->ownerRenderer()) {
620        if (renderer->style()->visibility() != VISIBLE)
621            return false;
622    }
623    return frame()->view()->visibleWidth() > 0 && frame()->view()->visibleHeight() > 0;
624}
625
626WebRect WebLocalFrameImpl::visibleContentRect() const
627{
628    return frame()->view()->visibleContentRect();
629}
630
631bool WebLocalFrameImpl::hasHorizontalScrollbar() const
632{
633    return frame() && frame()->view() && frame()->view()->horizontalScrollbar();
634}
635
636bool WebLocalFrameImpl::hasVerticalScrollbar() const
637{
638    return frame() && frame()->view() && frame()->view()->verticalScrollbar();
639}
640
641WebView* WebLocalFrameImpl::view() const
642{
643    return viewImpl();
644}
645
646void WebLocalFrameImpl::setOpener(WebFrame* opener)
647{
648    // FIXME: Does this need to move up into WebFrame too?
649    if (WebFrame::opener() && !opener && m_client)
650        m_client->didDisownOpener(this);
651
652    WebFrame::setOpener(opener);
653
654    ASSERT(m_frame);
655    if (m_frame && m_frame->document())
656        m_frame->document()->initSecurityContext();
657}
658
659WebDocument WebLocalFrameImpl::document() const
660{
661    if (!frame() || !frame()->document())
662        return WebDocument();
663    return WebDocument(frame()->document());
664}
665
666WebPerformance WebLocalFrameImpl::performance() const
667{
668    if (!frame())
669        return WebPerformance();
670    return WebPerformance(&frame()->domWindow()->performance());
671}
672
673bool WebLocalFrameImpl::dispatchBeforeUnloadEvent()
674{
675    if (!frame())
676        return true;
677    return frame()->loader().shouldClose();
678}
679
680void WebLocalFrameImpl::dispatchUnloadEvent()
681{
682    if (!frame())
683        return;
684    frame()->loader().closeURL();
685}
686
687NPObject* WebLocalFrameImpl::windowObject() const
688{
689    if (!frame())
690        return 0;
691    return frame()->script().windowScriptNPObject();
692}
693
694void WebLocalFrameImpl::bindToWindowObject(const WebString& name, NPObject* object)
695{
696    bindToWindowObject(name, object, 0);
697}
698
699void WebLocalFrameImpl::bindToWindowObject(const WebString& name, NPObject* object, void*)
700{
701    if (!frame() || !frame()->script().canExecuteScripts(NotAboutToExecuteScript))
702        return;
703    frame()->script().bindToWindowObject(frame(), String(name), object);
704}
705
706void WebLocalFrameImpl::executeScript(const WebScriptSource& source)
707{
708    ASSERT(frame());
709    TextPosition position(OrdinalNumber::fromOneBasedInt(source.startLine), OrdinalNumber::first());
710    v8::HandleScope handleScope(toIsolate(frame()));
711    frame()->script().executeScriptInMainWorld(ScriptSourceCode(source.code, source.url, position));
712}
713
714void WebLocalFrameImpl::executeScriptInIsolatedWorld(int worldID, const WebScriptSource* sourcesIn, unsigned numSources, int extensionGroup)
715{
716    ASSERT(frame());
717    RELEASE_ASSERT(worldID > 0);
718    RELEASE_ASSERT(worldID < EmbedderWorldIdLimit);
719
720    Vector<ScriptSourceCode> sources;
721    for (unsigned i = 0; i < numSources; ++i) {
722        TextPosition position(OrdinalNumber::fromOneBasedInt(sourcesIn[i].startLine), OrdinalNumber::first());
723        sources.append(ScriptSourceCode(sourcesIn[i].code, sourcesIn[i].url, position));
724    }
725
726    v8::HandleScope handleScope(toIsolate(frame()));
727    frame()->script().executeScriptInIsolatedWorld(worldID, sources, extensionGroup, 0);
728}
729
730void WebLocalFrameImpl::setIsolatedWorldSecurityOrigin(int worldID, const WebSecurityOrigin& securityOrigin)
731{
732    ASSERT(frame());
733    DOMWrapperWorld::setIsolatedWorldSecurityOrigin(worldID, securityOrigin.get());
734}
735
736void WebLocalFrameImpl::setIsolatedWorldContentSecurityPolicy(int worldID, const WebString& policy)
737{
738    ASSERT(frame());
739    DOMWrapperWorld::setIsolatedWorldContentSecurityPolicy(worldID, policy);
740}
741
742void WebLocalFrameImpl::addMessageToConsole(const WebConsoleMessage& message)
743{
744    ASSERT(frame());
745
746    MessageLevel webCoreMessageLevel;
747    switch (message.level) {
748    case WebConsoleMessage::LevelDebug:
749        webCoreMessageLevel = DebugMessageLevel;
750        break;
751    case WebConsoleMessage::LevelLog:
752        webCoreMessageLevel = LogMessageLevel;
753        break;
754    case WebConsoleMessage::LevelWarning:
755        webCoreMessageLevel = WarningMessageLevel;
756        break;
757    case WebConsoleMessage::LevelError:
758        webCoreMessageLevel = ErrorMessageLevel;
759        break;
760    default:
761        ASSERT_NOT_REACHED();
762        return;
763    }
764
765    frame()->document()->addConsoleMessage(OtherMessageSource, webCoreMessageLevel, message.text);
766}
767
768void WebLocalFrameImpl::collectGarbage()
769{
770    if (!frame())
771        return;
772    if (!frame()->settings()->scriptEnabled())
773        return;
774    V8GCController::collectGarbage(v8::Isolate::GetCurrent());
775}
776
777bool WebLocalFrameImpl::checkIfRunInsecureContent(const WebURL& url) const
778{
779    ASSERT(frame());
780    return frame()->loader().mixedContentChecker()->canRunInsecureContent(frame()->document()->securityOrigin(), url);
781}
782
783v8::Handle<v8::Value> WebLocalFrameImpl::executeScriptAndReturnValue(const WebScriptSource& source)
784{
785    ASSERT(frame());
786
787    // FIXME: This fake user gesture is required to make a bunch of pyauto
788    // tests pass. If this isn't needed in non-test situations, we should
789    // consider removing this code and changing the tests.
790    // http://code.google.com/p/chromium/issues/detail?id=86397
791    UserGestureIndicator gestureIndicator(DefinitelyProcessingNewUserGesture);
792
793    TextPosition position(OrdinalNumber::fromOneBasedInt(source.startLine), OrdinalNumber::first());
794    return frame()->script().executeScriptInMainWorldAndReturnValue(ScriptSourceCode(source.code, source.url, position));
795}
796
797void WebLocalFrameImpl::executeScriptInIsolatedWorld(int worldID, const WebScriptSource* sourcesIn, unsigned numSources, int extensionGroup, WebVector<v8::Local<v8::Value> >* results)
798{
799    ASSERT(frame());
800    RELEASE_ASSERT(worldID > 0);
801    RELEASE_ASSERT(worldID < EmbedderWorldIdLimit);
802
803    Vector<ScriptSourceCode> sources;
804
805    for (unsigned i = 0; i < numSources; ++i) {
806        TextPosition position(OrdinalNumber::fromOneBasedInt(sourcesIn[i].startLine), OrdinalNumber::first());
807        sources.append(ScriptSourceCode(sourcesIn[i].code, sourcesIn[i].url, position));
808    }
809
810    if (results) {
811        Vector<v8::Local<v8::Value> > scriptResults;
812        frame()->script().executeScriptInIsolatedWorld(worldID, sources, extensionGroup, &scriptResults);
813        WebVector<v8::Local<v8::Value> > v8Results(scriptResults.size());
814        for (unsigned i = 0; i < scriptResults.size(); i++)
815            v8Results[i] = v8::Local<v8::Value>::New(toIsolate(frame()), scriptResults[i]);
816        results->swap(v8Results);
817    } else {
818        v8::HandleScope handleScope(toIsolate(frame()));
819        frame()->script().executeScriptInIsolatedWorld(worldID, sources, extensionGroup, 0);
820    }
821}
822
823v8::Handle<v8::Value> WebLocalFrameImpl::callFunctionEvenIfScriptDisabled(v8::Handle<v8::Function> function, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> argv[])
824{
825    ASSERT(frame());
826    return frame()->script().callFunction(function, receiver, argc, argv);
827}
828
829v8::Local<v8::Context> WebLocalFrameImpl::mainWorldScriptContext() const
830{
831    return toV8Context(frame(), DOMWrapperWorld::mainWorld());
832}
833
834void WebLocalFrameImpl::reload(bool ignoreCache)
835{
836    ASSERT(frame());
837    frame()->loader().reload(ignoreCache ? EndToEndReload : NormalReload);
838}
839
840void WebLocalFrameImpl::reloadWithOverrideURL(const WebURL& overrideUrl, bool ignoreCache)
841{
842    ASSERT(frame());
843    frame()->loader().reload(ignoreCache ? EndToEndReload : NormalReload, overrideUrl);
844}
845
846void WebLocalFrameImpl::loadRequest(const WebURLRequest& request)
847{
848    ASSERT(frame());
849    ASSERT(!request.isNull());
850    const ResourceRequest& resourceRequest = request.toResourceRequest();
851
852    if (resourceRequest.url().protocolIs("javascript")) {
853        loadJavaScriptURL(resourceRequest.url());
854        return;
855    }
856
857    frame()->loader().load(FrameLoadRequest(0, resourceRequest));
858}
859
860void WebLocalFrameImpl::loadHistoryItem(const WebHistoryItem& item, WebHistoryLoadType loadType, WebURLRequest::CachePolicy cachePolicy)
861{
862    ASSERT(frame());
863    RefPtr<HistoryItem> historyItem = PassRefPtr<HistoryItem>(item);
864    ASSERT(historyItem);
865    frame()->loader().loadHistoryItem(historyItem.get(), static_cast<HistoryLoadType>(loadType), static_cast<ResourceRequestCachePolicy>(cachePolicy));
866}
867
868void WebLocalFrameImpl::loadData(const WebData& data, const WebString& mimeType, const WebString& textEncoding, const WebURL& baseURL, const WebURL& unreachableURL, bool replace)
869{
870    ASSERT(frame());
871
872    // If we are loading substitute data to replace an existing load, then
873    // inherit all of the properties of that original request. This way,
874    // reload will re-attempt the original request. It is essential that
875    // we only do this when there is an unreachableURL since a non-empty
876    // unreachableURL informs FrameLoader::reload to load unreachableURL
877    // instead of the currently loaded URL.
878    ResourceRequest request;
879    if (replace && !unreachableURL.isEmpty() && frame()->loader().provisionalDocumentLoader())
880        request = frame()->loader().provisionalDocumentLoader()->originalRequest();
881    request.setURL(baseURL);
882
883    FrameLoadRequest frameRequest(0, request, SubstituteData(data, mimeType, textEncoding, unreachableURL));
884    ASSERT(frameRequest.substituteData().isValid());
885    frameRequest.setLockBackForwardList(replace);
886    frame()->loader().load(frameRequest);
887}
888
889void WebLocalFrameImpl::loadHTMLString(const WebData& data, const WebURL& baseURL, const WebURL& unreachableURL, bool replace)
890{
891    ASSERT(frame());
892    loadData(data, WebString::fromUTF8("text/html"), WebString::fromUTF8("UTF-8"), baseURL, unreachableURL, replace);
893}
894
895bool WebLocalFrameImpl::isLoading() const
896{
897    if (!frame())
898        return false;
899    return frame()->loader().isLoading();
900}
901
902void WebLocalFrameImpl::stopLoading()
903{
904    if (!frame())
905        return;
906    // FIXME: Figure out what we should really do here. It seems like a bug
907    // that FrameLoader::stopLoading doesn't call stopAllLoaders.
908    frame()->loader().stopAllLoaders();
909}
910
911WebDataSource* WebLocalFrameImpl::provisionalDataSource() const
912{
913    ASSERT(frame());
914
915    // We regard the policy document loader as still provisional.
916    DocumentLoader* documentLoader = frame()->loader().provisionalDocumentLoader();
917    if (!documentLoader)
918        documentLoader = frame()->loader().policyDocumentLoader();
919
920    return DataSourceForDocLoader(documentLoader);
921}
922
923WebDataSource* WebLocalFrameImpl::dataSource() const
924{
925    ASSERT(frame());
926    return DataSourceForDocLoader(frame()->loader().documentLoader());
927}
928
929void WebLocalFrameImpl::enableViewSourceMode(bool enable)
930{
931    if (frame())
932        frame()->setInViewSourceMode(enable);
933}
934
935bool WebLocalFrameImpl::isViewSourceModeEnabled() const
936{
937    if (!frame())
938        return false;
939    return frame()->inViewSourceMode();
940}
941
942void WebLocalFrameImpl::setReferrerForRequest(WebURLRequest& request, const WebURL& referrerURL)
943{
944    String referrer = referrerURL.isEmpty() ? frame()->document()->outgoingReferrer() : String(referrerURL.spec().utf16());
945    referrer = SecurityPolicy::generateReferrerHeader(frame()->document()->referrerPolicy(), request.url(), referrer);
946    if (referrer.isEmpty())
947        return;
948    request.setHTTPReferrer(referrer, static_cast<WebReferrerPolicy>(frame()->document()->referrerPolicy()));
949}
950
951void WebLocalFrameImpl::dispatchWillSendRequest(WebURLRequest& request)
952{
953    ResourceResponse response;
954    frame()->loader().client()->dispatchWillSendRequest(0, 0, request.toMutableResourceRequest(), response);
955}
956
957WebURLLoader* WebLocalFrameImpl::createAssociatedURLLoader(const WebURLLoaderOptions& options)
958{
959    return new AssociatedURLLoader(this, options);
960}
961
962unsigned WebLocalFrameImpl::unloadListenerCount() const
963{
964    return frame()->domWindow()->pendingUnloadEventListeners();
965}
966
967void WebLocalFrameImpl::replaceSelection(const WebString& text)
968{
969    bool selectReplacement = false;
970    bool smartReplace = true;
971    frame()->editor().replaceSelectionWithText(text, selectReplacement, smartReplace);
972}
973
974void WebLocalFrameImpl::insertText(const WebString& text)
975{
976    if (frame()->inputMethodController().hasComposition())
977        frame()->inputMethodController().confirmComposition(text);
978    else
979        frame()->editor().insertText(text, 0);
980}
981
982void WebLocalFrameImpl::setMarkedText(const WebString& text, unsigned location, unsigned length)
983{
984    Vector<CompositionUnderline> decorations;
985    frame()->inputMethodController().setComposition(text, decorations, location, length);
986}
987
988void WebLocalFrameImpl::unmarkText()
989{
990    frame()->inputMethodController().cancelComposition();
991}
992
993bool WebLocalFrameImpl::hasMarkedText() const
994{
995    return frame()->inputMethodController().hasComposition();
996}
997
998WebRange WebLocalFrameImpl::markedRange() const
999{
1000    return frame()->inputMethodController().compositionRange();
1001}
1002
1003bool WebLocalFrameImpl::firstRectForCharacterRange(unsigned location, unsigned length, WebRect& rect) const
1004{
1005    if ((location + length < location) && (location + length))
1006        length = 0;
1007
1008    Element* editable = frame()->selection().rootEditableElementOrDocumentElement();
1009    ASSERT(editable);
1010    RefPtrWillBeRawPtr<Range> range = PlainTextRange(location, location + length).createRange(*editable);
1011    if (!range)
1012        return false;
1013    IntRect intRect = frame()->editor().firstRectForRange(range.get());
1014    rect = WebRect(intRect);
1015    rect = frame()->view()->contentsToWindow(rect);
1016    return true;
1017}
1018
1019size_t WebLocalFrameImpl::characterIndexForPoint(const WebPoint& webPoint) const
1020{
1021    if (!frame())
1022        return kNotFound;
1023
1024    IntPoint point = frame()->view()->windowToContents(webPoint);
1025    HitTestResult result = frame()->eventHandler().hitTestResultAtPoint(point, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent);
1026    RefPtrWillBeRawPtr<Range> range = frame()->rangeForPoint(result.roundedPointInInnerNodeFrame());
1027    if (!range)
1028        return kNotFound;
1029    Element* editable = frame()->selection().rootEditableElementOrDocumentElement();
1030    ASSERT(editable);
1031    return PlainTextRange::create(*editable, *range.get()).start();
1032}
1033
1034bool WebLocalFrameImpl::executeCommand(const WebString& name, const WebNode& node)
1035{
1036    ASSERT(frame());
1037
1038    if (name.length() <= 2)
1039        return false;
1040
1041    // Since we don't have NSControl, we will convert the format of command
1042    // string and call the function on Editor directly.
1043    String command = name;
1044
1045    // Make sure the first letter is upper case.
1046    command.replace(0, 1, command.substring(0, 1).upper());
1047
1048    // Remove the trailing ':' if existing.
1049    if (command[command.length() - 1] == UChar(':'))
1050        command = command.substring(0, command.length() - 1);
1051
1052    WebPluginContainerImpl* pluginContainer = pluginContainerFromNode(frame(), node);
1053    if (pluginContainer && pluginContainer->executeEditCommand(name))
1054        return true;
1055
1056    bool result = true;
1057
1058    // Specially handling commands that Editor::execCommand does not directly
1059    // support.
1060    if (command == "DeleteToEndOfParagraph") {
1061        if (!frame()->editor().deleteWithDirection(DirectionForward, ParagraphBoundary, true, false))
1062            frame()->editor().deleteWithDirection(DirectionForward, CharacterGranularity, true, false);
1063    } else if (command == "Indent") {
1064        frame()->editor().indent();
1065    } else if (command == "Outdent") {
1066        frame()->editor().outdent();
1067    } else if (command == "DeleteBackward") {
1068        result = frame()->editor().command(AtomicString("BackwardDelete")).execute();
1069    } else if (command == "DeleteForward") {
1070        result = frame()->editor().command(AtomicString("ForwardDelete")).execute();
1071    } else if (command == "AdvanceToNextMisspelling") {
1072        // Wee need to pass false here or else the currently selected word will never be skipped.
1073        frame()->spellChecker().advanceToNextMisspelling(false);
1074    } else if (command == "ToggleSpellPanel") {
1075        frame()->spellChecker().showSpellingGuessPanel();
1076    } else {
1077        result = frame()->editor().command(command).execute();
1078    }
1079    return result;
1080}
1081
1082bool WebLocalFrameImpl::executeCommand(const WebString& name, const WebString& value, const WebNode& node)
1083{
1084    ASSERT(frame());
1085    String webName = name;
1086
1087    WebPluginContainerImpl* pluginContainer = pluginContainerFromNode(frame(), node);
1088    if (pluginContainer && pluginContainer->executeEditCommand(name, value))
1089        return true;
1090
1091    // moveToBeginningOfDocument and moveToEndfDocument are only handled by WebKit for editable nodes.
1092    if (!frame()->editor().canEdit() && webName == "moveToBeginningOfDocument")
1093        return viewImpl()->bubblingScroll(ScrollUp, ScrollByDocument);
1094
1095    if (!frame()->editor().canEdit() && webName == "moveToEndOfDocument")
1096        return viewImpl()->bubblingScroll(ScrollDown, ScrollByDocument);
1097
1098    if (webName == "showGuessPanel") {
1099        frame()->spellChecker().showSpellingGuessPanel();
1100        return true;
1101    }
1102
1103    return frame()->editor().command(webName).execute(value);
1104}
1105
1106bool WebLocalFrameImpl::isCommandEnabled(const WebString& name) const
1107{
1108    ASSERT(frame());
1109    return frame()->editor().command(name).isEnabled();
1110}
1111
1112void WebLocalFrameImpl::enableContinuousSpellChecking(bool enable)
1113{
1114    if (enable == isContinuousSpellCheckingEnabled())
1115        return;
1116    frame()->spellChecker().toggleContinuousSpellChecking();
1117}
1118
1119bool WebLocalFrameImpl::isContinuousSpellCheckingEnabled() const
1120{
1121    return frame()->spellChecker().isContinuousSpellCheckingEnabled();
1122}
1123
1124void WebLocalFrameImpl::requestTextChecking(const WebElement& webElement)
1125{
1126    if (webElement.isNull())
1127        return;
1128    frame()->spellChecker().requestTextChecking(*webElement.constUnwrap<Element>());
1129}
1130
1131void WebLocalFrameImpl::replaceMisspelledRange(const WebString& text)
1132{
1133    // 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.
1134    if (pluginContainerFromFrame(frame()))
1135        return;
1136    RefPtrWillBeRawPtr<Range> caretRange = frame()->selection().toNormalizedRange();
1137    if (!caretRange)
1138        return;
1139    WillBeHeapVector<DocumentMarker*> markers = frame()->document()->markers().markersInRange(caretRange.get(), DocumentMarker::MisspellingMarkers());
1140    if (markers.size() < 1 || markers[0]->startOffset() >= markers[0]->endOffset())
1141        return;
1142    RefPtrWillBeRawPtr<Range> markerRange = Range::create(caretRange->ownerDocument(), caretRange->startContainer(), markers[0]->startOffset(), caretRange->endContainer(), markers[0]->endOffset());
1143    if (!markerRange)
1144        return;
1145    frame()->selection().setSelection(VisibleSelection(markerRange.get()), CharacterGranularity);
1146    frame()->editor().replaceSelectionWithText(text, false, false);
1147}
1148
1149void WebLocalFrameImpl::removeSpellingMarkers()
1150{
1151    frame()->document()->markers().removeMarkers(DocumentMarker::MisspellingMarkers());
1152}
1153
1154bool WebLocalFrameImpl::hasSelection() const
1155{
1156    WebPluginContainerImpl* pluginContainer = pluginContainerFromFrame(frame());
1157    if (pluginContainer)
1158        return pluginContainer->plugin()->hasSelection();
1159
1160    // frame()->selection()->isNone() never returns true.
1161    return frame()->selection().start() != frame()->selection().end();
1162}
1163
1164WebRange WebLocalFrameImpl::selectionRange() const
1165{
1166    return frame()->selection().toNormalizedRange();
1167}
1168
1169WebString WebLocalFrameImpl::selectionAsText() const
1170{
1171    WebPluginContainerImpl* pluginContainer = pluginContainerFromFrame(frame());
1172    if (pluginContainer)
1173        return pluginContainer->plugin()->selectionAsText();
1174
1175    RefPtrWillBeRawPtr<Range> range = frame()->selection().toNormalizedRange();
1176    if (!range)
1177        return WebString();
1178
1179    String text = range->text();
1180#if OS(WIN)
1181    replaceNewlinesWithWindowsStyleNewlines(text);
1182#endif
1183    replaceNBSPWithSpace(text);
1184    return text;
1185}
1186
1187WebString WebLocalFrameImpl::selectionAsMarkup() const
1188{
1189    WebPluginContainerImpl* pluginContainer = pluginContainerFromFrame(frame());
1190    if (pluginContainer)
1191        return pluginContainer->plugin()->selectionAsMarkup();
1192
1193    RefPtrWillBeRawPtr<Range> range = frame()->selection().toNormalizedRange();
1194    if (!range)
1195        return WebString();
1196
1197    return createMarkup(range.get(), 0, AnnotateForInterchange, false, ResolveNonLocalURLs);
1198}
1199
1200void WebLocalFrameImpl::selectWordAroundPosition(LocalFrame* frame, VisiblePosition position)
1201{
1202    VisibleSelection selection(position);
1203    selection.expandUsingGranularity(WordGranularity);
1204
1205    TextGranularity granularity = selection.isRange() ? WordGranularity : CharacterGranularity;
1206    frame->selection().setSelection(selection, granularity);
1207}
1208
1209bool WebLocalFrameImpl::selectWordAroundCaret()
1210{
1211    FrameSelection& selection = frame()->selection();
1212    if (selection.isNone() || selection.isRange())
1213        return false;
1214    selectWordAroundPosition(frame(), selection.selection().visibleStart());
1215    return true;
1216}
1217
1218void WebLocalFrameImpl::selectRange(const WebPoint& base, const WebPoint& extent)
1219{
1220    moveRangeSelection(base, extent);
1221}
1222
1223void WebLocalFrameImpl::selectRange(const WebRange& webRange)
1224{
1225    if (RefPtrWillBeRawPtr<Range> range = static_cast<PassRefPtrWillBeRawPtr<Range> >(webRange))
1226        frame()->selection().setSelectedRange(range.get(), WebCore::VP_DEFAULT_AFFINITY, FrameSelection::NonDirectional, NotUserTriggered);
1227}
1228
1229void WebLocalFrameImpl::moveRangeSelection(const WebPoint& base, const WebPoint& extent)
1230{
1231    VisiblePosition basePosition = visiblePositionForWindowPoint(base);
1232    VisiblePosition extentPosition = visiblePositionForWindowPoint(extent);
1233    VisibleSelection newSelection = VisibleSelection(basePosition, extentPosition);
1234    frame()->selection().setSelection(newSelection, CharacterGranularity);
1235}
1236
1237void WebLocalFrameImpl::moveCaretSelection(const WebPoint& point)
1238{
1239    Element* editable = frame()->selection().rootEditableElement();
1240    if (!editable)
1241        return;
1242
1243    VisiblePosition position = visiblePositionForWindowPoint(point);
1244    frame()->selection().moveTo(position, UserTriggered);
1245}
1246
1247bool WebLocalFrameImpl::setEditableSelectionOffsets(int start, int end)
1248{
1249    return frame()->inputMethodController().setEditableSelectionOffsets(PlainTextRange(start, end));
1250}
1251
1252bool WebLocalFrameImpl::setCompositionFromExistingText(int compositionStart, int compositionEnd, const WebVector<WebCompositionUnderline>& underlines)
1253{
1254    if (!frame()->editor().canEdit())
1255        return false;
1256
1257    InputMethodController& inputMethodController = frame()->inputMethodController();
1258    inputMethodController.cancelComposition();
1259
1260    if (compositionStart == compositionEnd)
1261        return true;
1262
1263    inputMethodController.setCompositionFromExistingText(CompositionUnderlineVectorBuilder(underlines), compositionStart, compositionEnd);
1264
1265    return true;
1266}
1267
1268void WebLocalFrameImpl::extendSelectionAndDelete(int before, int after)
1269{
1270    if (WebPlugin* plugin = focusedPluginIfInputMethodSupported()) {
1271        plugin->extendSelectionAndDelete(before, after);
1272        return;
1273    }
1274    frame()->inputMethodController().extendSelectionAndDelete(before, after);
1275}
1276
1277void WebLocalFrameImpl::setCaretVisible(bool visible)
1278{
1279    frame()->selection().setCaretVisible(visible);
1280}
1281
1282VisiblePosition WebLocalFrameImpl::visiblePositionForWindowPoint(const WebPoint& point)
1283{
1284    // FIXME(bokan): crbug.com/371902 - These scale/pinch transforms shouldn't
1285    // be ad hoc and explicit.
1286    PinchViewport& pinchViewport = frame()->page()->frameHost().pinchViewport();
1287    FloatPoint unscaledPoint(point);
1288    unscaledPoint.scale(1 / view()->pageScaleFactor(), 1 / view()->pageScaleFactor());
1289    unscaledPoint.moveBy(pinchViewport.visibleRect().location());
1290
1291    HitTestRequest request = HitTestRequest::Move | HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent;
1292    HitTestResult result(frame()->view()->windowToContents(roundedIntPoint(unscaledPoint)));
1293    frame()->document()->renderView()->layer()->hitTest(request, result);
1294
1295    if (Node* node = result.targetNode())
1296        return frame()->selection().selection().visiblePositionRespectingEditingBoundary(result.localPoint(), node);
1297    return VisiblePosition();
1298}
1299
1300WebPlugin* WebLocalFrameImpl::focusedPluginIfInputMethodSupported()
1301{
1302    WebPluginContainerImpl* container = WebLocalFrameImpl::pluginContainerFromNode(frame(), WebNode(frame()->document()->focusedElement()));
1303    if (container && container->supportsInputMethod())
1304        return container->plugin();
1305    return 0;
1306}
1307
1308int WebLocalFrameImpl::printBegin(const WebPrintParams& printParams, const WebNode& constrainToNode)
1309{
1310    ASSERT(!frame()->document()->isFrameSet());
1311    WebPluginContainerImpl* pluginContainer = 0;
1312    if (constrainToNode.isNull()) {
1313        // If this is a plugin document, check if the plugin supports its own
1314        // printing. If it does, we will delegate all printing to that.
1315        pluginContainer = pluginContainerFromFrame(frame());
1316    } else {
1317        // We only support printing plugin nodes for now.
1318        pluginContainer = toWebPluginContainerImpl(constrainToNode.pluginContainer());
1319    }
1320
1321    if (pluginContainer && pluginContainer->supportsPaginatedPrint())
1322        m_printContext = adoptPtr(new ChromePluginPrintContext(frame(), pluginContainer, printParams));
1323    else
1324        m_printContext = adoptPtr(new ChromePrintContext(frame()));
1325
1326    FloatRect rect(0, 0, static_cast<float>(printParams.printContentArea.width), static_cast<float>(printParams.printContentArea.height));
1327    m_printContext->begin(rect.width(), rect.height());
1328    float pageHeight;
1329    // We ignore the overlays calculation for now since they are generated in the
1330    // browser. pageHeight is actually an output parameter.
1331    m_printContext->computePageRects(rect, 0, 0, 1.0, pageHeight);
1332
1333    return m_printContext->pageCount();
1334}
1335
1336float WebLocalFrameImpl::getPrintPageShrink(int page)
1337{
1338    ASSERT(m_printContext && page >= 0);
1339    return m_printContext->getPageShrink(page);
1340}
1341
1342float WebLocalFrameImpl::printPage(int page, WebCanvas* canvas)
1343{
1344#if ENABLE(PRINTING)
1345    ASSERT(m_printContext && page >= 0 && frame() && frame()->document());
1346
1347    GraphicsContext graphicsContext(canvas);
1348    graphicsContext.setPrinting(true);
1349    return m_printContext->spoolPage(graphicsContext, page);
1350#else
1351    return 0;
1352#endif
1353}
1354
1355void WebLocalFrameImpl::printEnd()
1356{
1357    ASSERT(m_printContext);
1358    m_printContext->end();
1359    m_printContext.clear();
1360}
1361
1362bool WebLocalFrameImpl::isPrintScalingDisabledForPlugin(const WebNode& node)
1363{
1364    WebPluginContainerImpl* pluginContainer =  node.isNull() ? pluginContainerFromFrame(frame()) : toWebPluginContainerImpl(node.pluginContainer());
1365
1366    if (!pluginContainer || !pluginContainer->supportsPaginatedPrint())
1367        return false;
1368
1369    return pluginContainer->isPrintScalingDisabled();
1370}
1371
1372bool WebLocalFrameImpl::hasCustomPageSizeStyle(int pageIndex)
1373{
1374    return frame()->document()->styleForPage(pageIndex)->pageSizeType() != PAGE_SIZE_AUTO;
1375}
1376
1377bool WebLocalFrameImpl::isPageBoxVisible(int pageIndex)
1378{
1379    return frame()->document()->isPageBoxVisible(pageIndex);
1380}
1381
1382void WebLocalFrameImpl::pageSizeAndMarginsInPixels(int pageIndex, WebSize& pageSize, int& marginTop, int& marginRight, int& marginBottom, int& marginLeft)
1383{
1384    IntSize size = pageSize;
1385    frame()->document()->pageSizeAndMarginsInPixels(pageIndex, size, marginTop, marginRight, marginBottom, marginLeft);
1386    pageSize = size;
1387}
1388
1389WebString WebLocalFrameImpl::pageProperty(const WebString& propertyName, int pageIndex)
1390{
1391    ASSERT(m_printContext);
1392    return m_printContext->pageProperty(frame(), propertyName.utf8().data(), pageIndex);
1393}
1394
1395bool WebLocalFrameImpl::find(int identifier, const WebString& searchText, const WebFindOptions& options, bool wrapWithinFrame, WebRect* selectionRect)
1396{
1397    return ensureTextFinder().find(identifier, searchText, options, wrapWithinFrame, selectionRect);
1398}
1399
1400void WebLocalFrameImpl::stopFinding(bool clearSelection)
1401{
1402    if (m_textFinder) {
1403        if (!clearSelection)
1404            setFindEndstateFocusAndSelection();
1405        m_textFinder->stopFindingAndClearSelection();
1406    }
1407}
1408
1409void WebLocalFrameImpl::scopeStringMatches(int identifier, const WebString& searchText, const WebFindOptions& options, bool reset)
1410{
1411    ensureTextFinder().scopeStringMatches(identifier, searchText, options, reset);
1412}
1413
1414void WebLocalFrameImpl::cancelPendingScopingEffort()
1415{
1416    if (m_textFinder)
1417        m_textFinder->cancelPendingScopingEffort();
1418}
1419
1420void WebLocalFrameImpl::increaseMatchCount(int count, int identifier)
1421{
1422    // This function should only be called on the mainframe.
1423    ASSERT(!parent());
1424    ensureTextFinder().increaseMatchCount(identifier, count);
1425}
1426
1427void WebLocalFrameImpl::resetMatchCount()
1428{
1429    ensureTextFinder().resetMatchCount();
1430}
1431
1432void WebLocalFrameImpl::sendOrientationChangeEvent()
1433{
1434    if (frame())
1435        frame()->sendOrientationChangeEvent();
1436}
1437
1438void WebLocalFrameImpl::dispatchMessageEventWithOriginCheck(const WebSecurityOrigin& intendedTargetOrigin, const WebDOMEvent& event)
1439{
1440    ASSERT(!event.isNull());
1441    frame()->domWindow()->dispatchMessageEventWithOriginCheck(intendedTargetOrigin.get(), event, nullptr);
1442}
1443
1444int WebLocalFrameImpl::findMatchMarkersVersion() const
1445{
1446    ASSERT(!parent());
1447
1448    if (m_textFinder)
1449        return m_textFinder->findMatchMarkersVersion();
1450    return 0;
1451}
1452
1453int WebLocalFrameImpl::selectNearestFindMatch(const WebFloatPoint& point, WebRect* selectionRect)
1454{
1455    ASSERT(!parent());
1456    return ensureTextFinder().selectNearestFindMatch(point, selectionRect);
1457}
1458
1459WebFloatRect WebLocalFrameImpl::activeFindMatchRect()
1460{
1461    ASSERT(!parent());
1462
1463    if (m_textFinder)
1464        return m_textFinder->activeFindMatchRect();
1465    return WebFloatRect();
1466}
1467
1468void WebLocalFrameImpl::findMatchRects(WebVector<WebFloatRect>& outputRects)
1469{
1470    ASSERT(!parent());
1471    ensureTextFinder().findMatchRects(outputRects);
1472}
1473
1474void WebLocalFrameImpl::setTickmarks(const WebVector<WebRect>& tickmarks)
1475{
1476    if (frameView()) {
1477        Vector<IntRect> tickmarksConverted(tickmarks.size());
1478        for (size_t i = 0; i < tickmarks.size(); ++i)
1479            tickmarksConverted[i] = tickmarks[i];
1480        frameView()->setTickmarks(tickmarksConverted);
1481        invalidateScrollbar();
1482    }
1483}
1484
1485WebString WebLocalFrameImpl::contentAsText(size_t maxChars) const
1486{
1487    if (!frame())
1488        return WebString();
1489    StringBuilder text;
1490    frameContentAsPlainText(maxChars, frame(), text);
1491    return text.toString();
1492}
1493
1494WebString WebLocalFrameImpl::contentAsMarkup() const
1495{
1496    if (!frame())
1497        return WebString();
1498    return createFullMarkup(frame()->document());
1499}
1500
1501WebString WebLocalFrameImpl::renderTreeAsText(RenderAsTextControls toShow) const
1502{
1503    RenderAsTextBehavior behavior = RenderAsTextBehaviorNormal;
1504
1505    if (toShow & RenderAsTextDebug)
1506        behavior |= RenderAsTextShowCompositedLayers | RenderAsTextShowAddresses | RenderAsTextShowIDAndClass | RenderAsTextShowLayerNesting;
1507
1508    if (toShow & RenderAsTextPrinting)
1509        behavior |= RenderAsTextPrintingMode;
1510
1511    return externalRepresentation(frame(), behavior);
1512}
1513
1514WebString WebLocalFrameImpl::markerTextForListItem(const WebElement& webElement) const
1515{
1516    return WebCore::markerTextForListItem(const_cast<Element*>(webElement.constUnwrap<Element>()));
1517}
1518
1519void WebLocalFrameImpl::printPagesWithBoundaries(WebCanvas* canvas, const WebSize& pageSizeInPixels)
1520{
1521    ASSERT(m_printContext);
1522
1523    GraphicsContext graphicsContext(canvas);
1524    graphicsContext.setPrinting(true);
1525
1526    m_printContext->spoolAllPagesWithBoundaries(graphicsContext, FloatSize(pageSizeInPixels.width, pageSizeInPixels.height));
1527}
1528
1529WebRect WebLocalFrameImpl::selectionBoundsRect() const
1530{
1531    return hasSelection() ? WebRect(IntRect(frame()->selection().bounds(false))) : WebRect();
1532}
1533
1534bool WebLocalFrameImpl::selectionStartHasSpellingMarkerFor(int from, int length) const
1535{
1536    if (!frame())
1537        return false;
1538    return frame()->spellChecker().selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length);
1539}
1540
1541WebString WebLocalFrameImpl::layerTreeAsText(bool showDebugInfo) const
1542{
1543    if (!frame())
1544        return WebString();
1545
1546    return WebString(frame()->layerTreeAsText(showDebugInfo ? LayerTreeIncludesDebugInfo : LayerTreeNormal));
1547}
1548
1549// WebLocalFrameImpl public ---------------------------------------------------------
1550
1551WebLocalFrame* WebLocalFrame::create(WebFrameClient* client)
1552{
1553    return WebLocalFrameImpl::create(client);
1554}
1555
1556WebLocalFrameImpl* WebLocalFrameImpl::create(WebFrameClient* client)
1557{
1558    return adoptRef(new WebLocalFrameImpl(client)).leakRef();
1559}
1560
1561WebLocalFrameImpl::WebLocalFrameImpl(WebFrameClient* client)
1562    : m_frameLoaderClientImpl(this)
1563    , m_client(client)
1564    , m_permissionClient(0)
1565    , m_inputEventsScaleFactorForEmulation(1)
1566    , m_userMediaClientImpl(this)
1567    , m_geolocationClientProxy(adoptPtr(new GeolocationClientProxy(client ? client->geolocationClient() : 0)))
1568{
1569    blink::Platform::current()->incrementStatsCounter(webFrameActiveCount);
1570    frameCount++;
1571}
1572
1573WebLocalFrameImpl::~WebLocalFrameImpl()
1574{
1575    blink::Platform::current()->decrementStatsCounter(webFrameActiveCount);
1576    frameCount--;
1577
1578    cancelPendingScopingEffort();
1579}
1580
1581void WebLocalFrameImpl::setWebCoreFrame(PassRefPtr<WebCore::LocalFrame> frame)
1582{
1583    m_frame = frame;
1584
1585    // FIXME: we shouldn't add overhead to every frame by registering these objects when they're not used.
1586    if (m_frame) {
1587        OwnPtr<NotificationPresenterImpl> notificationPresenter = adoptPtr(new NotificationPresenterImpl());
1588        if (m_client)
1589            notificationPresenter->initialize(m_client->notificationPresenter());
1590
1591        provideNotification(*m_frame, notificationPresenter.release());
1592        provideUserMediaTo(*m_frame, &m_userMediaClientImpl);
1593        provideGeolocationTo(*m_frame, m_geolocationClientProxy.get());
1594        m_geolocationClientProxy->setController(GeolocationController::from(m_frame.get()));
1595        provideMIDITo(*m_frame, MIDIClientProxy::create(m_client ? m_client->webMIDIClient() : 0));
1596        if (RuntimeEnabledFeatures::screenOrientationEnabled())
1597            ScreenOrientationController::provideTo(*m_frame, m_client ? m_client->webScreenOrientationClient() : 0);
1598        provideLocalFileSystemTo(*m_frame, LocalFileSystemClient::create());
1599    }
1600}
1601
1602void WebLocalFrameImpl::initializeAsMainFrame(WebCore::Page* page)
1603{
1604    setWebCoreFrame(LocalFrame::create(&m_frameLoaderClientImpl, &page->frameHost(), 0));
1605
1606    // We must call init() after m_frame is assigned because it is referenced
1607    // during init().
1608    m_frame->init();
1609}
1610
1611PassRefPtr<LocalFrame> WebLocalFrameImpl::createChildFrame(const FrameLoadRequest& request, HTMLFrameOwnerElement* ownerElement)
1612{
1613    ASSERT(m_client);
1614    WebLocalFrameImpl* webframeChild = toWebLocalFrameImpl(m_client->createChildFrame(this, request.frameName()));
1615    if (!webframeChild)
1616        return nullptr;
1617
1618    // FIXME: Using subResourceAttributeName as fallback is not a perfect
1619    // solution. subResourceAttributeName returns just one attribute name. The
1620    // element might not have the attribute, and there might be other attributes
1621    // which can identify the element.
1622    RefPtr<LocalFrame> child = webframeChild->initializeAsChildFrame(frame()->host(), ownerElement, request.frameName(), ownerElement->getAttribute(ownerElement->subResourceAttributeName()));
1623    // Initializing the WebCore frame may cause the new child to be detached, since it may dispatch a load event in the parent.
1624    if (!child->tree().parent())
1625        return nullptr;
1626
1627    // If we're moving in the back/forward list, we might want to replace the content
1628    // of this child frame with whatever was there at that point.
1629    RefPtr<HistoryItem> childItem;
1630    if (isBackForwardLoadType(frame()->loader().loadType()) && !frame()->document()->loadEventFinished())
1631        childItem = PassRefPtr<HistoryItem>(webframeChild->client()->historyItemForNewChildFrame(webframeChild));
1632
1633    if (childItem)
1634        child->loader().loadHistoryItem(childItem.get());
1635    else
1636        child->loader().load(FrameLoadRequest(0, request.resourceRequest(), "_self"));
1637
1638    // Note a synchronous navigation (about:blank) would have already processed
1639    // onload, so it is possible for the child frame to have already been
1640    // detached by script in the page.
1641    if (!child->tree().parent())
1642        return nullptr;
1643    return child;
1644}
1645
1646void WebLocalFrameImpl::didChangeContentsSize(const IntSize& size)
1647{
1648    // This is only possible on the main frame.
1649    if (m_textFinder && m_textFinder->totalMatchCount() > 0) {
1650        ASSERT(!parent());
1651        m_textFinder->increaseMarkerVersion();
1652    }
1653}
1654
1655void WebLocalFrameImpl::createFrameView()
1656{
1657    TRACE_EVENT0("webkit", "WebLocalFrameImpl::createFrameView");
1658
1659    ASSERT(frame()); // If frame() doesn't exist, we probably didn't init properly.
1660
1661    WebViewImpl* webView = viewImpl();
1662    bool isMainFrame = webView->mainFrameImpl()->frame() == frame();
1663    if (isMainFrame)
1664        webView->suppressInvalidations(true);
1665
1666    frame()->createView(webView->size(), webView->baseBackgroundColor(), webView->isTransparent());
1667    if (webView->shouldAutoResize() && isMainFrame)
1668        frame()->view()->enableAutoSizeMode(true, webView->minAutoSize(), webView->maxAutoSize());
1669
1670    frame()->view()->setInputEventsTransformForEmulation(m_inputEventsOffsetForEmulation, m_inputEventsScaleFactorForEmulation);
1671
1672    if (isMainFrame)
1673        webView->suppressInvalidations(false);
1674}
1675
1676WebLocalFrameImpl* WebLocalFrameImpl::fromFrame(LocalFrame* frame)
1677{
1678    if (!frame)
1679        return 0;
1680    return fromFrame(*frame);
1681}
1682
1683WebLocalFrameImpl* WebLocalFrameImpl::fromFrame(LocalFrame& frame)
1684{
1685    FrameLoaderClient* client = frame.loader().client();
1686    if (!client || !client->isFrameLoaderClientImpl())
1687        return 0;
1688    return toFrameLoaderClientImpl(client)->webFrame();
1689}
1690
1691WebLocalFrameImpl* WebLocalFrameImpl::fromFrameOwnerElement(Element* element)
1692{
1693    // FIXME: Why do we check specifically for <iframe> and <frame> here? Why can't we get the WebLocalFrameImpl from an <object> element, for example.
1694    if (!isHTMLFrameElementBase(element))
1695        return 0;
1696    return fromFrame(toLocalFrame(toHTMLFrameElementBase(element)->contentFrame()));
1697}
1698
1699WebViewImpl* WebLocalFrameImpl::viewImpl() const
1700{
1701    if (!frame())
1702        return 0;
1703    return WebViewImpl::fromPage(frame()->page());
1704}
1705
1706WebDataSourceImpl* WebLocalFrameImpl::dataSourceImpl() const
1707{
1708    return static_cast<WebDataSourceImpl*>(dataSource());
1709}
1710
1711WebDataSourceImpl* WebLocalFrameImpl::provisionalDataSourceImpl() const
1712{
1713    return static_cast<WebDataSourceImpl*>(provisionalDataSource());
1714}
1715
1716void WebLocalFrameImpl::setFindEndstateFocusAndSelection()
1717{
1718    WebLocalFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl();
1719
1720    if (this != mainFrameImpl->activeMatchFrame())
1721        return;
1722
1723    if (Range* activeMatch = m_textFinder->activeMatch()) {
1724        // If the user has set the selection since the match was found, we
1725        // don't focus anything.
1726        VisibleSelection selection(frame()->selection().selection());
1727        if (!selection.isNone())
1728            return;
1729
1730        // Try to find the first focusable node up the chain, which will, for
1731        // example, focus links if we have found text within the link.
1732        Node* node = activeMatch->firstNode();
1733        if (node && node->isInShadowTree()) {
1734            if (Node* host = node->shadowHost()) {
1735                if (isHTMLInputElement(*host) || isHTMLTextAreaElement(*host))
1736                    node = host;
1737            }
1738        }
1739        for (; node; node = node->parentNode()) {
1740            if (!node->isElementNode())
1741                continue;
1742            Element* element = toElement(node);
1743            if (element->isFocusable()) {
1744                // Found a focusable parent node. Set the active match as the
1745                // selection and focus to the focusable node.
1746                frame()->selection().setSelection(VisibleSelection(activeMatch));
1747                frame()->document()->setFocusedElement(element);
1748                return;
1749            }
1750        }
1751
1752        // Iterate over all the nodes in the range until we find a focusable node.
1753        // This, for example, sets focus to the first link if you search for
1754        // text and text that is within one or more links.
1755        node = activeMatch->firstNode();
1756        for (; node && node != activeMatch->pastLastNode(); node = NodeTraversal::next(*node)) {
1757            if (!node->isElementNode())
1758                continue;
1759            Element* element = toElement(node);
1760            if (element->isFocusable()) {
1761                frame()->document()->setFocusedElement(element);
1762                return;
1763            }
1764        }
1765
1766        // No node related to the active match was focusable, so set the
1767        // active match as the selection (so that when you end the Find session,
1768        // you'll have the last thing you found highlighted) and make sure that
1769        // we have nothing focused (otherwise you might have text selected but
1770        // a link focused, which is weird).
1771        frame()->selection().setSelection(VisibleSelection(activeMatch));
1772        frame()->document()->setFocusedElement(nullptr);
1773
1774        // Finally clear the active match, for two reasons:
1775        // We just finished the find 'session' and we don't want future (potentially
1776        // unrelated) find 'sessions' operations to start at the same place.
1777        // The WebLocalFrameImpl could get reused and the activeMatch could end up pointing
1778        // to a document that is no longer valid. Keeping an invalid reference around
1779        // is just asking for trouble.
1780        m_textFinder->resetActiveMatch();
1781    }
1782}
1783
1784void WebLocalFrameImpl::didFail(const ResourceError& error, bool wasProvisional)
1785{
1786    if (!client())
1787        return;
1788    WebURLError webError = error;
1789    if (wasProvisional)
1790        client()->didFailProvisionalLoad(this, webError);
1791    else
1792        client()->didFailLoad(this, webError);
1793}
1794
1795void WebLocalFrameImpl::setCanHaveScrollbars(bool canHaveScrollbars)
1796{
1797    frame()->view()->setCanHaveScrollbars(canHaveScrollbars);
1798}
1799
1800void WebLocalFrameImpl::setInputEventsTransformForEmulation(const IntSize& offset, float contentScaleFactor)
1801{
1802    m_inputEventsOffsetForEmulation = offset;
1803    m_inputEventsScaleFactorForEmulation = contentScaleFactor;
1804    if (frame()->view())
1805        frame()->view()->setInputEventsTransformForEmulation(m_inputEventsOffsetForEmulation, m_inputEventsScaleFactorForEmulation);
1806}
1807
1808void WebLocalFrameImpl::loadJavaScriptURL(const KURL& url)
1809{
1810    // This is copied from ScriptController::executeScriptIfJavaScriptURL.
1811    // Unfortunately, we cannot just use that method since it is private, and
1812    // it also doesn't quite behave as we require it to for bookmarklets. The
1813    // key difference is that we need to suppress loading the string result
1814    // from evaluating the JS URL if executing the JS URL resulted in a
1815    // location change. We also allow a JS URL to be loaded even if scripts on
1816    // the page are otherwise disabled.
1817
1818    if (!frame()->document() || !frame()->page())
1819        return;
1820
1821    RefPtrWillBeRawPtr<Document> ownerDocument(frame()->document());
1822
1823    // Protect privileged pages against bookmarklets and other javascript manipulations.
1824    if (SchemeRegistry::shouldTreatURLSchemeAsNotAllowingJavascriptURLs(frame()->document()->url().protocol()))
1825        return;
1826
1827    String script = decodeURLEscapeSequences(url.string().substring(strlen("javascript:")));
1828    UserGestureIndicator gestureIndicator(DefinitelyProcessingNewUserGesture);
1829    v8::HandleScope handleScope(toIsolate(frame()));
1830    v8::Local<v8::Value> result = frame()->script().executeScriptInMainWorldAndReturnValue(ScriptSourceCode(script));
1831    if (result.IsEmpty() || !result->IsString())
1832        return;
1833    String scriptResult = toCoreString(v8::Handle<v8::String>::Cast(result));
1834    if (!frame()->navigationScheduler().locationChangePending())
1835        frame()->document()->loader()->replaceDocument(scriptResult, ownerDocument.get());
1836}
1837
1838void WebLocalFrameImpl::addStyleSheetByURL(const WebString& url)
1839{
1840    RefPtrWillBeRawPtr<Element> styleElement = frame()->document()->createElement(HTMLNames::linkTag, false);
1841
1842    styleElement->setAttribute(HTMLNames::typeAttr, "text/css");
1843    styleElement->setAttribute(HTMLNames::relAttr, "stylesheet");
1844    styleElement->setAttribute(HTMLNames::hrefAttr, url);
1845
1846    frame()->document()->head()->appendChild(styleElement.release(), IGNORE_EXCEPTION);
1847}
1848
1849void WebLocalFrameImpl::willDetachParent()
1850{
1851    // Do not expect string scoping results from any frames that got detached
1852    // in the middle of the operation.
1853    if (m_textFinder && m_textFinder->scopingInProgress()) {
1854
1855        // There is a possibility that the frame being detached was the only
1856        // pending one. We need to make sure final replies can be sent.
1857        m_textFinder->flushCurrentScoping();
1858
1859        m_textFinder->cancelPendingScopingEffort();
1860    }
1861}
1862
1863WebLocalFrameImpl* WebLocalFrameImpl::activeMatchFrame() const
1864{
1865    ASSERT(!parent());
1866
1867    if (m_textFinder)
1868        return m_textFinder->activeMatchFrame();
1869    return 0;
1870}
1871
1872WebCore::Range* WebLocalFrameImpl::activeMatch() const
1873{
1874    if (m_textFinder)
1875        return m_textFinder->activeMatch();
1876    return 0;
1877}
1878
1879TextFinder& WebLocalFrameImpl::ensureTextFinder()
1880{
1881    if (!m_textFinder)
1882        m_textFinder = TextFinder::create(*this);
1883
1884    return *m_textFinder;
1885}
1886
1887void WebLocalFrameImpl::invalidateScrollbar() const
1888{
1889    ASSERT(frame() && frame()->view());
1890    FrameView* view = frame()->view();
1891    // Invalidate the vertical scroll bar region for the view.
1892    Scrollbar* scrollbar = view->verticalScrollbar();
1893    if (scrollbar)
1894        scrollbar->invalidate();
1895}
1896
1897void WebLocalFrameImpl::invalidateAll() const
1898{
1899    ASSERT(frame() && frame()->view());
1900    FrameView* view = frame()->view();
1901    view->invalidateRect(view->frameRect());
1902    invalidateScrollbar();
1903}
1904
1905PassRefPtr<LocalFrame> WebLocalFrameImpl::initializeAsChildFrame(FrameHost* host, FrameOwner* owner, const AtomicString& name, const AtomicString& fallbackName)
1906{
1907    RefPtr<LocalFrame> frame = LocalFrame::create(&m_frameLoaderClientImpl, host, owner);
1908    setWebCoreFrame(frame);
1909    frame->tree().setName(name, fallbackName);
1910    // May dispatch JS events; frame may be detached after this.
1911    frame->init();
1912    return frame;
1913}
1914
1915} // namespace blink
1916