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