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