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
frameContentAsPlainText(size_t maxChars,LocalFrame * frame,StringBuilder & output)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
pluginContainerFromFrame(LocalFrame * frame)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
pluginContainerFromNode(WebCore::LocalFrame * frame,const WebNode & node)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:
ChromePrintContext(LocalFrame * frame)294 ChromePrintContext(LocalFrame* frame)
295 : PrintContext(frame)
296 , m_printedPageWidth(0)
297 {
298 }
299
~ChromePrintContext()300 virtual ~ChromePrintContext() { }
301
begin(float width,float height)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
end()309 virtual void end()
310 {
311 PrintContext::end();
312 }
313
getPageShrink(int pageNumber) const314 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.
spoolPage(GraphicsContext & context,int pageNumber)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
spoolAllPagesWithBoundaries(GraphicsContext & graphicsContext,const FloatSize & pageSizeInPixels)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
computePageRects(const FloatRect & printRect,float headerHeight,float footerHeight,float userScaleFactor,float & outPageHeight)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
pageCount() const393 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:
ChromePluginPrintContext(LocalFrame * frame,WebPluginContainerImpl * plugin,const WebPrintParams & printParams)408 ChromePluginPrintContext(LocalFrame* frame, WebPluginContainerImpl* plugin, const WebPrintParams& printParams)
409 : ChromePrintContext(frame), m_plugin(plugin), m_pageCount(0), m_printParams(printParams)
410 {
411 }
412
~ChromePluginPrintContext()413 virtual ~ChromePluginPrintContext() { }
414
begin(float width,float height)415 virtual void begin(float width, float height)
416 {
417 }
418
end()419 virtual void end()
420 {
421 m_plugin->printEnd();
422 }
423
getPageShrink(int pageNumber) const424 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
computePageRects(const FloatRect & printRect,float headerHeight,float footerHeight,float userScaleFactor,float & outPageHeight)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
pageCount() const436 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.
spoolPage(GraphicsContext & context,int pageNumber)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
DataSourceForDocLoader(DocumentLoader * loader)458 static WebDataSource* DataSourceForDocLoader(DocumentLoader* loader)
459 {
460 return loader ? WebDataSourceImpl::fromDocumentLoader(loader) : 0;
461 }
462
463 // WebFrame -------------------------------------------------------------------
464
instanceCount()465 int WebFrame::instanceCount()
466 {
467 return frameCount;
468 }
469
frameForCurrentContext()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
frameForContext(v8::Handle<v8::Context> context)478 WebLocalFrame* WebLocalFrame::frameForContext(v8::Handle<v8::Context> context)
479 {
480 return WebLocalFrameImpl::fromFrame(toFrameIfNotDetached(context));
481 }
482
fromFrameOwnerElement(const WebElement & element)483 WebLocalFrame* WebLocalFrame::fromFrameOwnerElement(const WebElement& element)
484 {
485 return WebLocalFrameImpl::fromFrameOwnerElement(PassRefPtrWillBeRawPtr<Element>(element).get());
486 }
487
isWebLocalFrame() const488 bool WebLocalFrameImpl::isWebLocalFrame() const
489 {
490 return true;
491 }
492
toWebLocalFrame()493 WebLocalFrame* WebLocalFrameImpl::toWebLocalFrame()
494 {
495 return this;
496 }
497
isWebRemoteFrame() const498 bool WebLocalFrameImpl::isWebRemoteFrame() const
499 {
500 return false;
501 }
502
toWebRemoteFrame()503 WebRemoteFrame* WebLocalFrameImpl::toWebRemoteFrame()
504 {
505 ASSERT_NOT_REACHED();
506 return 0;
507 }
508
close()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
uniqueName() const524 WebString WebLocalFrameImpl::uniqueName() const
525 {
526 return frame()->tree().uniqueName();
527 }
528
assignedName() const529 WebString WebLocalFrameImpl::assignedName() const
530 {
531 return frame()->tree().name();
532 }
533
setName(const WebString & name)534 void WebLocalFrameImpl::setName(const WebString& name)
535 {
536 frame()->tree().setName(name);
537 }
538
iconURLs(int iconTypesMask) const539 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
setIsRemote(bool isRemote)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
setRemoteWebLayer(WebLayer * webLayer)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
setPermissionClient(WebPermissionClient * permissionClient)572 void WebLocalFrameImpl::setPermissionClient(WebPermissionClient* permissionClient)
573 {
574 m_permissionClient = permissionClient;
575 }
576
setSharedWorkerRepositoryClient(WebSharedWorkerRepositoryClient * client)577 void WebLocalFrameImpl::setSharedWorkerRepositoryClient(WebSharedWorkerRepositoryClient* client)
578 {
579 m_sharedWorkerRepositoryClient = SharedWorkerRepositoryClientImpl::create(client);
580 }
581
scrollOffset() const582 WebSize WebLocalFrameImpl::scrollOffset() const
583 {
584 FrameView* view = frameView();
585 if (!view)
586 return WebSize();
587 return view->scrollOffset();
588 }
589
minimumScrollOffset() const590 WebSize WebLocalFrameImpl::minimumScrollOffset() const
591 {
592 FrameView* view = frameView();
593 if (!view)
594 return WebSize();
595 return toIntSize(view->minimumScrollPosition());
596 }
597
maximumScrollOffset() const598 WebSize WebLocalFrameImpl::maximumScrollOffset() const
599 {
600 FrameView* view = frameView();
601 if (!view)
602 return WebSize();
603 return toIntSize(view->maximumScrollPosition());
604 }
605
setScrollOffset(const WebSize & offset)606 void WebLocalFrameImpl::setScrollOffset(const WebSize& offset)
607 {
608 if (FrameView* view = frameView())
609 view->setScrollOffset(IntPoint(offset.width, offset.height));
610 }
611
contentsSize() const612 WebSize WebLocalFrameImpl::contentsSize() const
613 {
614 return frame()->view()->contentsSize();
615 }
616
hasVisibleContent() const617 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
visibleContentRect() const626 WebRect WebLocalFrameImpl::visibleContentRect() const
627 {
628 return frame()->view()->visibleContentRect();
629 }
630
hasHorizontalScrollbar() const631 bool WebLocalFrameImpl::hasHorizontalScrollbar() const
632 {
633 return frame() && frame()->view() && frame()->view()->horizontalScrollbar();
634 }
635
hasVerticalScrollbar() const636 bool WebLocalFrameImpl::hasVerticalScrollbar() const
637 {
638 return frame() && frame()->view() && frame()->view()->verticalScrollbar();
639 }
640
view() const641 WebView* WebLocalFrameImpl::view() const
642 {
643 return viewImpl();
644 }
645
setOpener(WebFrame * opener)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
document() const659 WebDocument WebLocalFrameImpl::document() const
660 {
661 if (!frame() || !frame()->document())
662 return WebDocument();
663 return WebDocument(frame()->document());
664 }
665
performance() const666 WebPerformance WebLocalFrameImpl::performance() const
667 {
668 if (!frame())
669 return WebPerformance();
670 return WebPerformance(&frame()->domWindow()->performance());
671 }
672
dispatchBeforeUnloadEvent()673 bool WebLocalFrameImpl::dispatchBeforeUnloadEvent()
674 {
675 if (!frame())
676 return true;
677 return frame()->loader().shouldClose();
678 }
679
dispatchUnloadEvent()680 void WebLocalFrameImpl::dispatchUnloadEvent()
681 {
682 if (!frame())
683 return;
684 frame()->loader().closeURL();
685 }
686
windowObject() const687 NPObject* WebLocalFrameImpl::windowObject() const
688 {
689 if (!frame())
690 return 0;
691 return frame()->script().windowScriptNPObject();
692 }
693
bindToWindowObject(const WebString & name,NPObject * object)694 void WebLocalFrameImpl::bindToWindowObject(const WebString& name, NPObject* object)
695 {
696 bindToWindowObject(name, object, 0);
697 }
698
bindToWindowObject(const WebString & name,NPObject * object,void *)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
executeScript(const WebScriptSource & source)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
executeScriptInIsolatedWorld(int worldID,const WebScriptSource * sourcesIn,unsigned numSources,int extensionGroup)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
setIsolatedWorldSecurityOrigin(int worldID,const WebSecurityOrigin & securityOrigin)730 void WebLocalFrameImpl::setIsolatedWorldSecurityOrigin(int worldID, const WebSecurityOrigin& securityOrigin)
731 {
732 ASSERT(frame());
733 DOMWrapperWorld::setIsolatedWorldSecurityOrigin(worldID, securityOrigin.get());
734 }
735
setIsolatedWorldContentSecurityPolicy(int worldID,const WebString & policy)736 void WebLocalFrameImpl::setIsolatedWorldContentSecurityPolicy(int worldID, const WebString& policy)
737 {
738 ASSERT(frame());
739 DOMWrapperWorld::setIsolatedWorldContentSecurityPolicy(worldID, policy);
740 }
741
addMessageToConsole(const WebConsoleMessage & message)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
collectGarbage()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
checkIfRunInsecureContent(const WebURL & url) const777 bool WebLocalFrameImpl::checkIfRunInsecureContent(const WebURL& url) const
778 {
779 ASSERT(frame());
780 return frame()->loader().mixedContentChecker()->canRunInsecureContent(frame()->document()->securityOrigin(), url);
781 }
782
executeScriptAndReturnValue(const WebScriptSource & source)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
executeScriptInIsolatedWorld(int worldID,const WebScriptSource * sourcesIn,unsigned numSources,int extensionGroup,WebVector<v8::Local<v8::Value>> * results)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
callFunctionEvenIfScriptDisabled(v8::Handle<v8::Function> function,v8::Handle<v8::Value> receiver,int argc,v8::Handle<v8::Value> argv[])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
mainWorldScriptContext() const829 v8::Local<v8::Context> WebLocalFrameImpl::mainWorldScriptContext() const
830 {
831 return toV8Context(frame(), DOMWrapperWorld::mainWorld());
832 }
833
reload(bool ignoreCache)834 void WebLocalFrameImpl::reload(bool ignoreCache)
835 {
836 ASSERT(frame());
837 frame()->loader().reload(ignoreCache ? EndToEndReload : NormalReload);
838 }
839
reloadWithOverrideURL(const WebURL & overrideUrl,bool ignoreCache)840 void WebLocalFrameImpl::reloadWithOverrideURL(const WebURL& overrideUrl, bool ignoreCache)
841 {
842 ASSERT(frame());
843 frame()->loader().reload(ignoreCache ? EndToEndReload : NormalReload, overrideUrl);
844 }
845
loadRequest(const WebURLRequest & request)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
loadHistoryItem(const WebHistoryItem & item,WebHistoryLoadType loadType,WebURLRequest::CachePolicy cachePolicy)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
loadData(const WebData & data,const WebString & mimeType,const WebString & textEncoding,const WebURL & baseURL,const WebURL & unreachableURL,bool replace)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
loadHTMLString(const WebData & data,const WebURL & baseURL,const WebURL & unreachableURL,bool replace)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
isLoading() const895 bool WebLocalFrameImpl::isLoading() const
896 {
897 if (!frame())
898 return false;
899 return frame()->loader().isLoading();
900 }
901
stopLoading()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
provisionalDataSource() const911 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
dataSource() const923 WebDataSource* WebLocalFrameImpl::dataSource() const
924 {
925 ASSERT(frame());
926 return DataSourceForDocLoader(frame()->loader().documentLoader());
927 }
928
enableViewSourceMode(bool enable)929 void WebLocalFrameImpl::enableViewSourceMode(bool enable)
930 {
931 if (frame())
932 frame()->setInViewSourceMode(enable);
933 }
934
isViewSourceModeEnabled() const935 bool WebLocalFrameImpl::isViewSourceModeEnabled() const
936 {
937 if (!frame())
938 return false;
939 return frame()->inViewSourceMode();
940 }
941
setReferrerForRequest(WebURLRequest & request,const WebURL & referrerURL)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
dispatchWillSendRequest(WebURLRequest & request)951 void WebLocalFrameImpl::dispatchWillSendRequest(WebURLRequest& request)
952 {
953 ResourceResponse response;
954 frame()->loader().client()->dispatchWillSendRequest(0, 0, request.toMutableResourceRequest(), response);
955 }
956
createAssociatedURLLoader(const WebURLLoaderOptions & options)957 WebURLLoader* WebLocalFrameImpl::createAssociatedURLLoader(const WebURLLoaderOptions& options)
958 {
959 return new AssociatedURLLoader(this, options);
960 }
961
unloadListenerCount() const962 unsigned WebLocalFrameImpl::unloadListenerCount() const
963 {
964 return frame()->domWindow()->pendingUnloadEventListeners();
965 }
966
replaceSelection(const WebString & text)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
insertText(const WebString & text)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
setMarkedText(const WebString & text,unsigned location,unsigned length)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
unmarkText()988 void WebLocalFrameImpl::unmarkText()
989 {
990 frame()->inputMethodController().cancelComposition();
991 }
992
hasMarkedText() const993 bool WebLocalFrameImpl::hasMarkedText() const
994 {
995 return frame()->inputMethodController().hasComposition();
996 }
997
markedRange() const998 WebRange WebLocalFrameImpl::markedRange() const
999 {
1000 return frame()->inputMethodController().compositionRange();
1001 }
1002
firstRectForCharacterRange(unsigned location,unsigned length,WebRect & rect) const1003 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
characterIndexForPoint(const WebPoint & webPoint) const1019 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
executeCommand(const WebString & name,const WebNode & node)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
executeCommand(const WebString & name,const WebString & value,const WebNode & node)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
isCommandEnabled(const WebString & name) const1106 bool WebLocalFrameImpl::isCommandEnabled(const WebString& name) const
1107 {
1108 ASSERT(frame());
1109 return frame()->editor().command(name).isEnabled();
1110 }
1111
enableContinuousSpellChecking(bool enable)1112 void WebLocalFrameImpl::enableContinuousSpellChecking(bool enable)
1113 {
1114 if (enable == isContinuousSpellCheckingEnabled())
1115 return;
1116 frame()->spellChecker().toggleContinuousSpellChecking();
1117 }
1118
isContinuousSpellCheckingEnabled() const1119 bool WebLocalFrameImpl::isContinuousSpellCheckingEnabled() const
1120 {
1121 return frame()->spellChecker().isContinuousSpellCheckingEnabled();
1122 }
1123
requestTextChecking(const WebElement & webElement)1124 void WebLocalFrameImpl::requestTextChecking(const WebElement& webElement)
1125 {
1126 if (webElement.isNull())
1127 return;
1128 frame()->spellChecker().requestTextChecking(*webElement.constUnwrap<Element>());
1129 }
1130
replaceMisspelledRange(const WebString & text)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
removeSpellingMarkers()1149 void WebLocalFrameImpl::removeSpellingMarkers()
1150 {
1151 frame()->document()->markers().removeMarkers(DocumentMarker::MisspellingMarkers());
1152 }
1153
hasSelection() const1154 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
selectionRange() const1164 WebRange WebLocalFrameImpl::selectionRange() const
1165 {
1166 return frame()->selection().toNormalizedRange();
1167 }
1168
selectionAsText() const1169 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
selectionAsMarkup() const1187 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
selectWordAroundPosition(LocalFrame * frame,VisiblePosition position)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
selectWordAroundCaret()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
selectRange(const WebPoint & base,const WebPoint & extent)1218 void WebLocalFrameImpl::selectRange(const WebPoint& base, const WebPoint& extent)
1219 {
1220 moveRangeSelection(base, extent);
1221 }
1222
selectRange(const WebRange & webRange)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
moveRangeSelection(const WebPoint & base,const WebPoint & extent)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
moveCaretSelection(const WebPoint & point)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
setEditableSelectionOffsets(int start,int end)1247 bool WebLocalFrameImpl::setEditableSelectionOffsets(int start, int end)
1248 {
1249 return frame()->inputMethodController().setEditableSelectionOffsets(PlainTextRange(start, end));
1250 }
1251
setCompositionFromExistingText(int compositionStart,int compositionEnd,const WebVector<WebCompositionUnderline> & underlines)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
extendSelectionAndDelete(int before,int after)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
setCaretVisible(bool visible)1277 void WebLocalFrameImpl::setCaretVisible(bool visible)
1278 {
1279 frame()->selection().setCaretVisible(visible);
1280 }
1281
visiblePositionForWindowPoint(const WebPoint & point)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
focusedPluginIfInputMethodSupported()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
printBegin(const WebPrintParams & printParams,const WebNode & constrainToNode)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
getPrintPageShrink(int page)1336 float WebLocalFrameImpl::getPrintPageShrink(int page)
1337 {
1338 ASSERT(m_printContext && page >= 0);
1339 return m_printContext->getPageShrink(page);
1340 }
1341
printPage(int page,WebCanvas * canvas)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
printEnd()1355 void WebLocalFrameImpl::printEnd()
1356 {
1357 ASSERT(m_printContext);
1358 m_printContext->end();
1359 m_printContext.clear();
1360 }
1361
isPrintScalingDisabledForPlugin(const WebNode & node)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
hasCustomPageSizeStyle(int pageIndex)1372 bool WebLocalFrameImpl::hasCustomPageSizeStyle(int pageIndex)
1373 {
1374 return frame()->document()->styleForPage(pageIndex)->pageSizeType() != PAGE_SIZE_AUTO;
1375 }
1376
isPageBoxVisible(int pageIndex)1377 bool WebLocalFrameImpl::isPageBoxVisible(int pageIndex)
1378 {
1379 return frame()->document()->isPageBoxVisible(pageIndex);
1380 }
1381
pageSizeAndMarginsInPixels(int pageIndex,WebSize & pageSize,int & marginTop,int & marginRight,int & marginBottom,int & marginLeft)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
pageProperty(const WebString & propertyName,int pageIndex)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
find(int identifier,const WebString & searchText,const WebFindOptions & options,bool wrapWithinFrame,WebRect * selectionRect)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
stopFinding(bool clearSelection)1400 void WebLocalFrameImpl::stopFinding(bool clearSelection)
1401 {
1402 if (m_textFinder) {
1403 if (!clearSelection)
1404 setFindEndstateFocusAndSelection();
1405 m_textFinder->stopFindingAndClearSelection();
1406 }
1407 }
1408
scopeStringMatches(int identifier,const WebString & searchText,const WebFindOptions & options,bool reset)1409 void WebLocalFrameImpl::scopeStringMatches(int identifier, const WebString& searchText, const WebFindOptions& options, bool reset)
1410 {
1411 ensureTextFinder().scopeStringMatches(identifier, searchText, options, reset);
1412 }
1413
cancelPendingScopingEffort()1414 void WebLocalFrameImpl::cancelPendingScopingEffort()
1415 {
1416 if (m_textFinder)
1417 m_textFinder->cancelPendingScopingEffort();
1418 }
1419
increaseMatchCount(int count,int identifier)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
resetMatchCount()1427 void WebLocalFrameImpl::resetMatchCount()
1428 {
1429 ensureTextFinder().resetMatchCount();
1430 }
1431
sendOrientationChangeEvent()1432 void WebLocalFrameImpl::sendOrientationChangeEvent()
1433 {
1434 if (frame())
1435 frame()->sendOrientationChangeEvent();
1436 }
1437
dispatchMessageEventWithOriginCheck(const WebSecurityOrigin & intendedTargetOrigin,const WebDOMEvent & event)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
findMatchMarkersVersion() const1444 int WebLocalFrameImpl::findMatchMarkersVersion() const
1445 {
1446 ASSERT(!parent());
1447
1448 if (m_textFinder)
1449 return m_textFinder->findMatchMarkersVersion();
1450 return 0;
1451 }
1452
selectNearestFindMatch(const WebFloatPoint & point,WebRect * selectionRect)1453 int WebLocalFrameImpl::selectNearestFindMatch(const WebFloatPoint& point, WebRect* selectionRect)
1454 {
1455 ASSERT(!parent());
1456 return ensureTextFinder().selectNearestFindMatch(point, selectionRect);
1457 }
1458
activeFindMatchRect()1459 WebFloatRect WebLocalFrameImpl::activeFindMatchRect()
1460 {
1461 ASSERT(!parent());
1462
1463 if (m_textFinder)
1464 return m_textFinder->activeFindMatchRect();
1465 return WebFloatRect();
1466 }
1467
findMatchRects(WebVector<WebFloatRect> & outputRects)1468 void WebLocalFrameImpl::findMatchRects(WebVector<WebFloatRect>& outputRects)
1469 {
1470 ASSERT(!parent());
1471 ensureTextFinder().findMatchRects(outputRects);
1472 }
1473
setTickmarks(const WebVector<WebRect> & tickmarks)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
contentAsText(size_t maxChars) const1485 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
contentAsMarkup() const1494 WebString WebLocalFrameImpl::contentAsMarkup() const
1495 {
1496 if (!frame())
1497 return WebString();
1498 return createFullMarkup(frame()->document());
1499 }
1500
renderTreeAsText(RenderAsTextControls toShow) const1501 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
markerTextForListItem(const WebElement & webElement) const1514 WebString WebLocalFrameImpl::markerTextForListItem(const WebElement& webElement) const
1515 {
1516 return WebCore::markerTextForListItem(const_cast<Element*>(webElement.constUnwrap<Element>()));
1517 }
1518
printPagesWithBoundaries(WebCanvas * canvas,const WebSize & pageSizeInPixels)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
selectionBoundsRect() const1529 WebRect WebLocalFrameImpl::selectionBoundsRect() const
1530 {
1531 return hasSelection() ? WebRect(IntRect(frame()->selection().bounds(false))) : WebRect();
1532 }
1533
selectionStartHasSpellingMarkerFor(int from,int length) const1534 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
layerTreeAsText(bool showDebugInfo) const1541 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
create(WebFrameClient * client)1551 WebLocalFrame* WebLocalFrame::create(WebFrameClient* client)
1552 {
1553 return WebLocalFrameImpl::create(client);
1554 }
1555
create(WebFrameClient * client)1556 WebLocalFrameImpl* WebLocalFrameImpl::create(WebFrameClient* client)
1557 {
1558 return adoptRef(new WebLocalFrameImpl(client)).leakRef();
1559 }
1560
WebLocalFrameImpl(WebFrameClient * client)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
~WebLocalFrameImpl()1573 WebLocalFrameImpl::~WebLocalFrameImpl()
1574 {
1575 blink::Platform::current()->decrementStatsCounter(webFrameActiveCount);
1576 frameCount--;
1577
1578 cancelPendingScopingEffort();
1579 }
1580
setWebCoreFrame(PassRefPtr<WebCore::LocalFrame> frame)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
initializeAsMainFrame(WebCore::Page * page)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
createChildFrame(const FrameLoadRequest & request,HTMLFrameOwnerElement * ownerElement)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
didChangeContentsSize(const IntSize & size)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
createFrameView()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
fromFrame(LocalFrame * frame)1676 WebLocalFrameImpl* WebLocalFrameImpl::fromFrame(LocalFrame* frame)
1677 {
1678 if (!frame)
1679 return 0;
1680 return fromFrame(*frame);
1681 }
1682
fromFrame(LocalFrame & frame)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
fromFrameOwnerElement(Element * element)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
viewImpl() const1699 WebViewImpl* WebLocalFrameImpl::viewImpl() const
1700 {
1701 if (!frame())
1702 return 0;
1703 return WebViewImpl::fromPage(frame()->page());
1704 }
1705
dataSourceImpl() const1706 WebDataSourceImpl* WebLocalFrameImpl::dataSourceImpl() const
1707 {
1708 return static_cast<WebDataSourceImpl*>(dataSource());
1709 }
1710
provisionalDataSourceImpl() const1711 WebDataSourceImpl* WebLocalFrameImpl::provisionalDataSourceImpl() const
1712 {
1713 return static_cast<WebDataSourceImpl*>(provisionalDataSource());
1714 }
1715
setFindEndstateFocusAndSelection()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
didFail(const ResourceError & error,bool wasProvisional)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
setCanHaveScrollbars(bool canHaveScrollbars)1795 void WebLocalFrameImpl::setCanHaveScrollbars(bool canHaveScrollbars)
1796 {
1797 frame()->view()->setCanHaveScrollbars(canHaveScrollbars);
1798 }
1799
setInputEventsTransformForEmulation(const IntSize & offset,float contentScaleFactor)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
loadJavaScriptURL(const KURL & url)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
addStyleSheetByURL(const WebString & url)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
willDetachParent()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
activeMatchFrame() const1863 WebLocalFrameImpl* WebLocalFrameImpl::activeMatchFrame() const
1864 {
1865 ASSERT(!parent());
1866
1867 if (m_textFinder)
1868 return m_textFinder->activeMatchFrame();
1869 return 0;
1870 }
1871
activeMatch() const1872 WebCore::Range* WebLocalFrameImpl::activeMatch() const
1873 {
1874 if (m_textFinder)
1875 return m_textFinder->activeMatch();
1876 return 0;
1877 }
1878
ensureTextFinder()1879 TextFinder& WebLocalFrameImpl::ensureTextFinder()
1880 {
1881 if (!m_textFinder)
1882 m_textFinder = TextFinder::create(*this);
1883
1884 return *m_textFinder;
1885 }
1886
invalidateScrollbar() const1887 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
invalidateAll() const1897 void WebLocalFrameImpl::invalidateAll() const
1898 {
1899 ASSERT(frame() && frame()->view());
1900 FrameView* view = frame()->view();
1901 view->invalidateRect(view->frameRect());
1902 invalidateScrollbar();
1903 }
1904
initializeAsChildFrame(FrameHost * host,FrameOwner * owner,const AtomicString & name,const AtomicString & fallbackName)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
1916