75de3292817584d7e1423e2f4a0c40aaf70538e6
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / web / WebLocalFrameImpl.cpp
1 /*
2  * Copyright (C) 2009 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 // How ownership works
32 // -------------------
33 //
34 // Big oh represents a refcounted relationship: owner O--- ownee
35 //
36 // WebView (for the toplevel frame only)
37 //    O
38 //    |           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
213 namespace blink {
214
215 static int frameCount = 0;
216
217 // Key for a StatsCounter tracking how many WebFrames are active.
218 static const char webFrameActiveCount[] = "WebFrameActiveCount";
219
220 static 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
280 WebPluginContainerImpl* 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
290 WebPluginContainerImpl* 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.
300 class ChromePrintContext : public PrintContext {
301     WTF_MAKE_NONCOPYABLE(ChromePrintContext);
302 public:
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
377 protected:
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
400 private:
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.
408 class ChromePluginPrintContext FINAL : public ChromePrintContext {
409 public:
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
443 protected:
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
453 private:
454     // Set when printing.
455     WebPluginContainerImpl* m_plugin;
456     WebPrintParams m_printParams;
457 };
458
459 static WebDataSource* DataSourceForDocLoader(DocumentLoader* loader)
460 {
461     return loader ? WebDataSourceImpl::fromDocumentLoader(loader) : 0;
462 }
463
464 // WebFrame -------------------------------------------------------------------
465
466 int WebFrame::instanceCount()
467 {
468     return frameCount;
469 }
470
471 WebLocalFrame* 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
479 WebLocalFrame* WebLocalFrame::frameForContext(v8::Handle<v8::Context> context)
480 {
481     return WebLocalFrameImpl::fromFrame(toFrameIfNotDetached(context));
482 }
483
484 WebLocalFrame* WebLocalFrame::fromFrameOwnerElement(const WebElement& element)
485 {
486     return WebLocalFrameImpl::fromFrameOwnerElement(PassRefPtrWillBeRawPtr<Element>(element).get());
487 }
488
489 bool WebLocalFrameImpl::isWebLocalFrame() const
490 {
491     return true;
492 }
493
494 WebLocalFrame* WebLocalFrameImpl::toWebLocalFrame()
495 {
496     return this;
497 }
498
499 bool WebLocalFrameImpl::isWebRemoteFrame() const
500 {
501     return false;
502 }
503
504 WebRemoteFrame* WebLocalFrameImpl::toWebRemoteFrame()
505 {
506     ASSERT_NOT_REACHED();
507     return 0;
508 }
509
510 void 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
521 WebString WebLocalFrameImpl::uniqueName() const
522 {
523     return frame()->tree().uniqueName();
524 }
525
526 WebString WebLocalFrameImpl::assignedName() const
527 {
528     return frame()->tree().name();
529 }
530
531 void WebLocalFrameImpl::setName(const WebString& name)
532 {
533     frame()->tree().setName(name);
534 }
535
536 WebVector<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
545 void WebLocalFrameImpl::setIsRemote(bool isRemote)
546 {
547     m_isRemote = isRemote;
548     if (isRemote)
549         client()->initializeChildFrame(frame()->view()->frameRect(), frame()->view()->visibleContentScaleFactor());
550 }
551
552 void WebLocalFrameImpl::setRemoteWebLayer(WebLayer* webLayer)
553 {
554     if (!frame())
555         return;
556
557     frame()->setRemotePlatformLayer(webLayer);
558 }
559
560 void WebLocalFrameImpl::setPermissionClient(WebPermissionClient* permissionClient)
561 {
562     m_permissionClient = permissionClient;
563 }
564
565 void WebLocalFrameImpl::setSharedWorkerRepositoryClient(WebSharedWorkerRepositoryClient* client)
566 {
567     m_sharedWorkerRepositoryClient = SharedWorkerRepositoryClientImpl::create(client);
568 }
569
570 WebSize WebLocalFrameImpl::scrollOffset() const
571 {
572     FrameView* view = frameView();
573     if (!view)
574         return WebSize();
575     return view->scrollOffset();
576 }
577
578 WebSize WebLocalFrameImpl::minimumScrollOffset() const
579 {
580     FrameView* view = frameView();
581     if (!view)
582         return WebSize();
583     return toIntSize(view->minimumScrollPosition());
584 }
585
586 WebSize WebLocalFrameImpl::maximumScrollOffset() const
587 {
588     FrameView* view = frameView();
589     if (!view)
590         return WebSize();
591     return toIntSize(view->maximumScrollPosition());
592 }
593
594 void WebLocalFrameImpl::setScrollOffset(const WebSize& offset)
595 {
596     if (FrameView* view = frameView())
597         view->setScrollOffset(IntPoint(offset.width, offset.height));
598 }
599
600 WebSize WebLocalFrameImpl::contentsSize() const
601 {
602     if (FrameView* view = frameView())
603         return view->contentsSize();
604     return WebSize();
605 }
606
607 bool 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
619 WebRect WebLocalFrameImpl::visibleContentRect() const
620 {
621     if (FrameView* view = frameView())
622         return view->visibleContentRect();
623     return WebRect();
624 }
625
626 bool WebLocalFrameImpl::hasHorizontalScrollbar() const
627 {
628     return frame() && frame()->view() && frame()->view()->horizontalScrollbar();
629 }
630
631 bool WebLocalFrameImpl::hasVerticalScrollbar() const
632 {
633     return frame() && frame()->view() && frame()->view()->verticalScrollbar();
634 }
635
636 WebView* WebLocalFrameImpl::view() const
637 {
638     return viewImpl();
639 }
640
641 void 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
654 WebDocument WebLocalFrameImpl::document() const
655 {
656     if (!frame() || !frame()->document())
657         return WebDocument();
658     return WebDocument(frame()->document());
659 }
660
661 WebPerformance WebLocalFrameImpl::performance() const
662 {
663     if (!frame())
664         return WebPerformance();
665     return WebPerformance(&frame()->domWindow()->performance());
666 }
667
668 bool WebLocalFrameImpl::dispatchBeforeUnloadEvent()
669 {
670     if (!frame())
671         return true;
672     return frame()->loader().shouldClose();
673 }
674
675 void WebLocalFrameImpl::dispatchUnloadEvent()
676 {
677     if (!frame())
678         return;
679     frame()->loader().closeURL();
680 }
681
682 NPObject* WebLocalFrameImpl::windowObject() const
683 {
684     if (!frame())
685         return 0;
686     return frame()->script().windowScriptNPObject();
687 }
688
689 void WebLocalFrameImpl::bindToWindowObject(const WebString& name, NPObject* object)
690 {
691     bindToWindowObject(name, object, 0);
692 }
693
694 void 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
701 void 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
709 void 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
725 void WebLocalFrameImpl::setIsolatedWorldSecurityOrigin(int worldID, const WebSecurityOrigin& securityOrigin)
726 {
727     ASSERT(frame());
728     DOMWrapperWorld::setIsolatedWorldSecurityOrigin(worldID, securityOrigin.get());
729 }
730
731 void WebLocalFrameImpl::setIsolatedWorldContentSecurityPolicy(int worldID, const WebString& policy)
732 {
733     ASSERT(frame());
734     DOMWrapperWorld::setIsolatedWorldContentSecurityPolicy(worldID, policy);
735 }
736
737 void WebLocalFrameImpl::setIsolatedWorldHumanReadableName(int worldID, const WebString& humanReadableName)
738 {
739     ASSERT(frame());
740     DOMWrapperWorld::setIsolatedWorldHumanReadableName(worldID, humanReadableName);
741 }
742
743 void 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
769 void WebLocalFrameImpl::collectGarbage()
770 {
771     if (!frame())
772         return;
773     if (!frame()->settings()->scriptEnabled())
774         return;
775     V8GCController::collectGarbage(v8::Isolate::GetCurrent());
776 }
777
778 bool WebLocalFrameImpl::checkIfRunInsecureContent(const WebURL& url) const
779 {
780     ASSERT(frame());
781     return frame()->loader().mixedContentChecker()->canFrameInsecureContent(frame()->document()->securityOrigin(), url);
782 }
783
784 v8::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
792 void 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
818 v8::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
824 v8::Local<v8::Context> WebLocalFrameImpl::mainWorldScriptContext() const
825 {
826     return toV8Context(frame(), DOMWrapperWorld::mainWorld());
827 }
828
829 void WebLocalFrameImpl::reload(bool ignoreCache)
830 {
831     ASSERT(frame());
832     frame()->loader().reload(ignoreCache ? EndToEndReload : NormalReload);
833 }
834
835 void WebLocalFrameImpl::reloadWithOverrideURL(const WebURL& overrideUrl, bool ignoreCache)
836 {
837     ASSERT(frame());
838     frame()->loader().reload(ignoreCache ? EndToEndReload : NormalReload, overrideUrl);
839 }
840
841 void 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
855 void 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
863 void 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
884 void 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
890 void 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
899 WebDataSource* 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
911 WebDataSource* WebLocalFrameImpl::dataSource() const
912 {
913     ASSERT(frame());
914     return DataSourceForDocLoader(frame()->loader().documentLoader());
915 }
916
917 void WebLocalFrameImpl::enableViewSourceMode(bool enable)
918 {
919     if (frame())
920         frame()->setInViewSourceMode(enable);
921 }
922
923 bool WebLocalFrameImpl::isViewSourceModeEnabled() const
924 {
925     if (!frame())
926         return false;
927     return frame()->inViewSourceMode();
928 }
929
930 void 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
939 void WebLocalFrameImpl::dispatchWillSendRequest(WebURLRequest& request)
940 {
941     ResourceResponse response;
942     frame()->loader().client()->dispatchWillSendRequest(0, 0, request.toMutableResourceRequest(), response);
943 }
944
945 WebURLLoader* WebLocalFrameImpl::createAssociatedURLLoader(const WebURLLoaderOptions& options)
946 {
947     return new AssociatedURLLoader(this, options);
948 }
949
950 unsigned WebLocalFrameImpl::unloadListenerCount() const
951 {
952     return frame()->domWindow()->pendingUnloadEventListeners();
953 }
954
955 void WebLocalFrameImpl::replaceSelection(const WebString& text)
956 {
957     bool selectReplacement = false;
958     bool smartReplace = true;
959     frame()->editor().replaceSelectionWithText(text, selectReplacement, smartReplace);
960 }
961
962 void 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
970 void WebLocalFrameImpl::setMarkedText(const WebString& text, unsigned location, unsigned length)
971 {
972     Vector<CompositionUnderline> decorations;
973     frame()->inputMethodController().setComposition(text, decorations, location, length);
974 }
975
976 void WebLocalFrameImpl::unmarkText()
977 {
978     frame()->inputMethodController().cancelComposition();
979 }
980
981 bool WebLocalFrameImpl::hasMarkedText() const
982 {
983     return frame()->inputMethodController().hasComposition();
984 }
985
986 WebRange WebLocalFrameImpl::markedRange() const
987 {
988     return frame()->inputMethodController().compositionRange();
989 }
990
991 bool 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
1007 size_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
1022 bool 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
1047 bool 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
1058 bool WebLocalFrameImpl::isCommandEnabled(const WebString& name) const
1059 {
1060     ASSERT(frame());
1061     return frame()->editor().command(name).isEnabled();
1062 }
1063
1064 void WebLocalFrameImpl::enableContinuousSpellChecking(bool enable)
1065 {
1066     if (enable == isContinuousSpellCheckingEnabled())
1067         return;
1068     frame()->spellChecker().toggleContinuousSpellChecking();
1069 }
1070
1071 bool WebLocalFrameImpl::isContinuousSpellCheckingEnabled() const
1072 {
1073     return frame()->spellChecker().isContinuousSpellCheckingEnabled();
1074 }
1075
1076 void WebLocalFrameImpl::requestTextChecking(const WebElement& webElement)
1077 {
1078     if (webElement.isNull())
1079         return;
1080     frame()->spellChecker().requestTextChecking(*webElement.constUnwrap<Element>());
1081 }
1082
1083 void 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
1091 void WebLocalFrameImpl::removeSpellingMarkers()
1092 {
1093     frame()->spellChecker().removeSpellingMarkers();
1094 }
1095
1096 bool 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
1106 WebRange WebLocalFrameImpl::selectionRange() const
1107 {
1108     return frame()->selection().toNormalizedRange();
1109 }
1110
1111 WebString 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
1129 WebString 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
1142 void 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
1151 bool 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
1160 void WebLocalFrameImpl::selectRange(const WebPoint& base, const WebPoint& extent)
1161 {
1162     moveRangeSelection(base, extent);
1163 }
1164
1165 void 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
1171 void 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
1179 void 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
1189 bool WebLocalFrameImpl::setEditableSelectionOffsets(int start, int end)
1190 {
1191     return frame()->inputMethodController().setEditableSelectionOffsets(PlainTextRange(start, end));
1192 }
1193
1194 bool 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
1210 void 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
1219 void WebLocalFrameImpl::setCaretVisible(bool visible)
1220 {
1221     frame()->selection().setCaretVisible(visible);
1222 }
1223
1224 VisiblePosition 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
1242 WebPlugin* 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
1250 int 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
1278 float WebLocalFrameImpl::getPrintPageShrink(int page)
1279 {
1280     ASSERT(m_printContext && page >= 0);
1281     return m_printContext->getPageShrink(page);
1282 }
1283
1284 float 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
1297 void WebLocalFrameImpl::printEnd()
1298 {
1299     ASSERT(m_printContext);
1300     m_printContext->end();
1301     m_printContext.clear();
1302 }
1303
1304 bool 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
1314 int 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
1324 bool WebLocalFrameImpl::hasCustomPageSizeStyle(int pageIndex)
1325 {
1326     return frame()->document()->styleForPage(pageIndex)->pageSizeType() != PAGE_SIZE_AUTO;
1327 }
1328
1329 bool WebLocalFrameImpl::isPageBoxVisible(int pageIndex)
1330 {
1331     return frame()->document()->isPageBoxVisible(pageIndex);
1332 }
1333
1334 void 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
1341 WebString WebLocalFrameImpl::pageProperty(const WebString& propertyName, int pageIndex)
1342 {
1343     ASSERT(m_printContext);
1344     return m_printContext->pageProperty(frame(), propertyName.utf8().data(), pageIndex);
1345 }
1346
1347 bool 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
1352 void WebLocalFrameImpl::stopFinding(bool clearSelection)
1353 {
1354     if (m_textFinder) {
1355         if (!clearSelection)
1356             setFindEndstateFocusAndSelection();
1357         m_textFinder->stopFindingAndClearSelection();
1358     }
1359 }
1360
1361 void WebLocalFrameImpl::scopeStringMatches(int identifier, const WebString& searchText, const WebFindOptions& options, bool reset)
1362 {
1363     ensureTextFinder().scopeStringMatches(identifier, searchText, options, reset);
1364 }
1365
1366 void WebLocalFrameImpl::cancelPendingScopingEffort()
1367 {
1368     if (m_textFinder)
1369         m_textFinder->cancelPendingScopingEffort();
1370 }
1371
1372 void 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
1379 void WebLocalFrameImpl::resetMatchCount()
1380 {
1381     ensureTextFinder().resetMatchCount();
1382 }
1383
1384 void WebLocalFrameImpl::dispatchMessageEventWithOriginCheck(const WebSecurityOrigin& intendedTargetOrigin, const WebDOMEvent& event)
1385 {
1386     ASSERT(!event.isNull());
1387     frame()->domWindow()->dispatchMessageEventWithOriginCheck(intendedTargetOrigin.get(), event, nullptr);
1388 }
1389
1390 int WebLocalFrameImpl::findMatchMarkersVersion() const
1391 {
1392     ASSERT(!parent());
1393
1394     if (m_textFinder)
1395         return m_textFinder->findMatchMarkersVersion();
1396     return 0;
1397 }
1398
1399 int WebLocalFrameImpl::selectNearestFindMatch(const WebFloatPoint& point, WebRect* selectionRect)
1400 {
1401     ASSERT(!parent());
1402     return ensureTextFinder().selectNearestFindMatch(point, selectionRect);
1403 }
1404
1405 WebFloatRect WebLocalFrameImpl::activeFindMatchRect()
1406 {
1407     ASSERT(!parent());
1408
1409     if (m_textFinder)
1410         return m_textFinder->activeFindMatchRect();
1411     return WebFloatRect();
1412 }
1413
1414 void WebLocalFrameImpl::findMatchRects(WebVector<WebFloatRect>& outputRects)
1415 {
1416     ASSERT(!parent());
1417     ensureTextFinder().findMatchRects(outputRects);
1418 }
1419
1420 void 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
1431 WebString 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
1440 WebString WebLocalFrameImpl::contentAsMarkup() const
1441 {
1442     if (!frame())
1443         return WebString();
1444     return createMarkup(frame()->document());
1445 }
1446
1447 WebString 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
1460 WebString WebLocalFrameImpl::markerTextForListItem(const WebElement& webElement) const
1461 {
1462     return blink::markerTextForListItem(const_cast<Element*>(webElement.constUnwrap<Element>()));
1463 }
1464
1465 void 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
1475 WebRect WebLocalFrameImpl::selectionBoundsRect() const
1476 {
1477     return hasSelection() ? WebRect(IntRect(frame()->selection().bounds())) : WebRect();
1478 }
1479
1480 bool WebLocalFrameImpl::selectionStartHasSpellingMarkerFor(int from, int length) const
1481 {
1482     if (!frame())
1483         return false;
1484     return frame()->spellChecker().selectionStartHasSpellingMarkerFor(from, length);
1485 }
1486
1487 WebString 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
1497 WebLocalFrame* WebLocalFrame::create(WebFrameClient* client)
1498 {
1499     return WebLocalFrameImpl::create(client);
1500 }
1501
1502 WebLocalFrameImpl* 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
1512 WebLocalFrameImpl::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
1527 WebLocalFrameImpl::~WebLocalFrameImpl()
1528 {
1529     Platform::current()->decrementStatsCounter(webFrameActiveCount);
1530     frameCount--;
1531
1532     cancelPendingScopingEffort();
1533 }
1534
1535 void 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
1546 void 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
1569 PassRefPtrWillBeRawPtr<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
1581 PassRefPtrWillBeRawPtr<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
1617 void 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
1626 void 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
1647 WebLocalFrameImpl* WebLocalFrameImpl::fromFrame(LocalFrame* frame)
1648 {
1649     if (!frame)
1650         return 0;
1651     return fromFrame(*frame);
1652 }
1653
1654 WebLocalFrameImpl* 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
1662 WebLocalFrameImpl* 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
1670 WebViewImpl* WebLocalFrameImpl::viewImpl() const
1671 {
1672     if (!frame())
1673         return 0;
1674     return WebViewImpl::fromPage(frame()->page());
1675 }
1676
1677 WebDataSourceImpl* WebLocalFrameImpl::dataSourceImpl() const
1678 {
1679     return static_cast<WebDataSourceImpl*>(dataSource());
1680 }
1681
1682 WebDataSourceImpl* WebLocalFrameImpl::provisionalDataSourceImpl() const
1683 {
1684     return static_cast<WebDataSourceImpl*>(provisionalDataSource());
1685 }
1686
1687 void 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
1758 void 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
1769 void WebLocalFrameImpl::setCanHaveScrollbars(bool canHaveScrollbars)
1770 {
1771     frame()->view()->setCanHaveScrollbars(canHaveScrollbars);
1772 }
1773
1774 void 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
1782 void 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
1812 void 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
1820 bool WebLocalFrameImpl::isLoading() const
1821 {
1822     if (!frame() || !frame()->document())
1823         return false;
1824     return frame()->loader().stateMachine()->isDisplayingInitialEmptyDocument() || !frame()->document()->loadEventFinished();
1825 }
1826
1827 bool WebLocalFrameImpl::isResourceLoadInProgress() const
1828 {
1829     if (!frame() || !frame()->document())
1830         return false;
1831     return frame()->document()->fetcher()->requestCount();
1832 }
1833
1834 void 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
1845 void 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
1852 void 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
1866 v8::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
1876 void 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
1890 WebLocalFrameImpl* WebLocalFrameImpl::activeMatchFrame() const
1891 {
1892     ASSERT(!parent());
1893
1894     if (m_textFinder)
1895         return m_textFinder->activeMatchFrame();
1896     return 0;
1897 }
1898
1899 Range* WebLocalFrameImpl::activeMatch() const
1900 {
1901     if (m_textFinder)
1902         return m_textFinder->activeMatch();
1903     return 0;
1904 }
1905
1906 TextFinder& WebLocalFrameImpl::ensureTextFinder()
1907 {
1908     if (!m_textFinder)
1909         m_textFinder = TextFinder::create(*this);
1910
1911     return *m_textFinder;
1912 }
1913
1914 void 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
1924 void 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