1 /*
2 * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
3 * 1999 Lars Knoll <knoll@kde.org>
4 * 1999 Antti Koivisto <koivisto@kde.org>
5 * 2000 Simon Hausmann <hausmann@kde.org>
6 * 2000 Stefan Schimanski <1Stein@gmx.de>
7 * 2001 George Staikos <staikos@kde.org>
8 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
9 * Copyright (C) 2005 Alexey Proskuryakov <ap@nypop.com>
10 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
11 * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
12 * Copyright (C) 2008 Google Inc.
13 *
14 * This library is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU Library General Public
16 * License as published by the Free Software Foundation; either
17 * version 2 of the License, or (at your option) any later version.
18 *
19 * This library is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * Library General Public License for more details.
23 *
24 * You should have received a copy of the GNU Library General Public License
25 * along with this library; see the file COPYING.LIB. If not, write to
26 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
27 * Boston, MA 02110-1301, USA.
28 */
29
30 #include "config.h"
31 #include "core/frame/LocalFrame.h"
32
33 #include "bindings/core/v8/ScriptController.h"
34 #include "core/dom/DocumentType.h"
35 #include "core/editing/Editor.h"
36 #include "core/editing/FrameSelection.h"
37 #include "core/editing/InputMethodController.h"
38 #include "core/editing/SpellChecker.h"
39 #include "core/editing/htmlediting.h"
40 #include "core/editing/markup.h"
41 #include "core/events/Event.h"
42 #include "core/fetch/ResourceFetcher.h"
43 #include "core/frame/EventHandlerRegistry.h"
44 #include "core/frame/FrameConsole.h"
45 #include "core/frame/FrameDestructionObserver.h"
46 #include "core/frame/FrameHost.h"
47 #include "core/frame/FrameView.h"
48 #include "core/frame/LocalDOMWindow.h"
49 #include "core/frame/Settings.h"
50 #include "core/html/HTMLFrameElementBase.h"
51 #include "core/inspector/ConsoleMessageStorage.h"
52 #include "core/inspector/InspectorInstrumentation.h"
53 #include "core/loader/FrameLoaderClient.h"
54 #include "core/page/Chrome.h"
55 #include "core/page/EventHandler.h"
56 #include "core/page/FocusController.h"
57 #include "core/page/Page.h"
58 #include "core/page/scrolling/ScrollingCoordinator.h"
59 #include "core/rendering/HitTestResult.h"
60 #include "core/rendering/RenderLayer.h"
61 #include "core/rendering/RenderView.h"
62 #include "core/rendering/compositing/RenderLayerCompositor.h"
63 #include "core/svg/SVGDocumentExtensions.h"
64 #include "platform/DragImage.h"
65 #include "platform/RuntimeEnabledFeatures.h"
66 #include "platform/graphics/GraphicsContext.h"
67 #include "platform/graphics/ImageBuffer.h"
68 #include "platform/text/TextStream.h"
69 #include "wtf/PassOwnPtr.h"
70 #include "wtf/StdLibExtras.h"
71
72 namespace blink {
73
74 using namespace HTMLNames;
75
parentPageZoomFactor(LocalFrame * frame)76 static inline float parentPageZoomFactor(LocalFrame* frame)
77 {
78 Frame* parent = frame->tree().parent();
79 if (!parent || !parent->isLocalFrame())
80 return 1;
81 return toLocalFrame(parent)->pageZoomFactor();
82 }
83
parentTextZoomFactor(LocalFrame * frame)84 static inline float parentTextZoomFactor(LocalFrame* frame)
85 {
86 Frame* parent = frame->tree().parent();
87 if (!parent || !parent->isLocalFrame())
88 return 1;
89 return toLocalFrame(parent)->textZoomFactor();
90 }
91
LocalFrame(FrameLoaderClient * client,FrameHost * host,FrameOwner * owner)92 inline LocalFrame::LocalFrame(FrameLoaderClient* client, FrameHost* host, FrameOwner* owner)
93 : Frame(client, host, owner)
94 , m_loader(this)
95 , m_navigationScheduler(this)
96 , m_script(adoptPtr(new ScriptController(this)))
97 , m_editor(Editor::create(*this))
98 , m_spellChecker(SpellChecker::create(*this))
99 , m_selection(FrameSelection::create(this))
100 , m_eventHandler(adoptPtrWillBeNoop(new EventHandler(this)))
101 , m_console(FrameConsole::create(*this))
102 , m_inputMethodController(InputMethodController::create(*this))
103 , m_pageZoomFactor(parentPageZoomFactor(this))
104 , m_textZoomFactor(parentTextZoomFactor(this))
105 , m_inViewSourceMode(false)
106 {
107 }
108
create(FrameLoaderClient * client,FrameHost * host,FrameOwner * owner)109 PassRefPtrWillBeRawPtr<LocalFrame> LocalFrame::create(FrameLoaderClient* client, FrameHost* host, FrameOwner* owner)
110 {
111 RefPtrWillBeRawPtr<LocalFrame> frame = adoptRefWillBeNoop(new LocalFrame(client, host, owner));
112 InspectorInstrumentation::frameAttachedToParent(frame.get());
113 return frame.release();
114 }
115
~LocalFrame()116 LocalFrame::~LocalFrame()
117 {
118 #if ENABLE(OILPAN)
119 // Verify that the FrameView has been cleared as part of detaching
120 // the frame owner.
121 ASSERT(!m_view);
122 // Oilpan: see setDOMWindow() comment why it is acceptable not to
123 // mirror the non-Oilpan call below.
124 //
125 // Also, FrameDestructionObservers that live longer than this
126 // frame object keep weak references to the frame; those will be
127 // automatically cleared by the garbage collector. Hence, explicit
128 // frameDestroyed() notifications aren't needed.
129 #else
130 // FIXME: follow Oilpan and clear the FrameView and FrameLoader
131 // during FrameOwner detachment instead, see LocalFrame::disconnectOwnerElement().
132 setView(nullptr);
133 m_loader.clear();
134 setDOMWindow(nullptr);
135
136 HashSet<RawPtr<FrameDestructionObserver> >::iterator stop = m_destructionObservers.end();
137 for (HashSet<RawPtr<FrameDestructionObserver> >::iterator it = m_destructionObservers.begin(); it != stop; ++it)
138 (*it)->frameDestroyed();
139 #endif
140 }
141
trace(Visitor * visitor)142 void LocalFrame::trace(Visitor* visitor)
143 {
144 #if ENABLE(OILPAN)
145 visitor->trace(m_destructionObservers);
146 visitor->trace(m_loader);
147 visitor->trace(m_navigationScheduler);
148 visitor->trace(m_pagePopupOwner);
149 visitor->trace(m_editor);
150 visitor->trace(m_spellChecker);
151 visitor->trace(m_selection);
152 visitor->trace(m_eventHandler);
153 visitor->trace(m_console);
154 visitor->trace(m_inputMethodController);
155 HeapSupplementable<LocalFrame>::trace(visitor);
156 #endif
157 Frame::trace(visitor);
158 }
159
detach()160 void LocalFrame::detach()
161 {
162 // A lot of the following steps can result in the current frame being
163 // detached, so protect a reference to it.
164 RefPtrWillBeRawPtr<LocalFrame> protect(this);
165 m_loader.stopAllLoaders();
166 m_loader.closeURL();
167 detachChildren();
168 // stopAllLoaders() needs to be called after detachChildren(), because detachChildren()
169 // will trigger the unload event handlers of any child frames, and those event
170 // handlers might start a new subresource load in this frame.
171 m_loader.stopAllLoaders();
172 m_loader.detachFromParent();
173 }
174
inScope(TreeScope * scope) const175 bool LocalFrame::inScope(TreeScope* scope) const
176 {
177 ASSERT(scope);
178 Document* doc = document();
179 if (!doc)
180 return false;
181 // FIXME: This check is broken in for OOPI.
182 HTMLFrameOwnerElement* owner = doc->ownerElement();
183 if (!owner)
184 return false;
185 return owner->treeScope() == scope;
186 }
187
detachView()188 void LocalFrame::detachView()
189 {
190 // We detach the FrameView's custom scroll bars as early as
191 // possible to prevent m_doc->detach() from messing with the view
192 // such that its scroll bars won't be torn down.
193 //
194 // FIXME: We should revisit this.
195 if (m_view)
196 m_view->prepareForDetach();
197 }
198
setView(PassRefPtr<FrameView> view)199 void LocalFrame::setView(PassRefPtr<FrameView> view)
200 {
201 detachView();
202
203 // Prepare for destruction now, so any unload event handlers get run and the LocalDOMWindow is
204 // notified. If we wait until the view is destroyed, then things won't be hooked up enough for
205 // these calls to work.
206 if (!view && document() && document()->isActive()) {
207 // FIXME: We don't call willRemove here. Why is that OK?
208 document()->prepareForDestruction();
209 }
210
211 eventHandler().clear();
212
213 m_view = view;
214
215 if (m_view && isMainFrame()) {
216 if (settings()->pinchVirtualViewportEnabled())
217 m_host->pinchViewport().mainFrameDidChangeSize();
218 else
219 m_view->setVisibleContentScaleFactor(page()->pageScaleFactor());
220 }
221 }
222
setPrinting(bool printing,const FloatSize & pageSize,const FloatSize & originalPageSize,float maximumShrinkRatio)223 void LocalFrame::setPrinting(bool printing, const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkRatio)
224 {
225 // In setting printing, we should not validate resources already cached for the document.
226 // See https://bugs.webkit.org/show_bug.cgi?id=43704
227 ResourceCacheValidationSuppressor validationSuppressor(document()->fetcher());
228
229 document()->setPrinting(printing);
230 view()->adjustMediaTypeForPrinting(printing);
231
232 document()->styleResolverChanged();
233 if (shouldUsePrintingLayout()) {
234 view()->forceLayoutForPagination(pageSize, originalPageSize, maximumShrinkRatio);
235 } else {
236 view()->forceLayout();
237 view()->adjustViewSize();
238 }
239
240 // Subframes of the one we're printing don't lay out to the page size.
241 for (RefPtrWillBeRawPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling()) {
242 if (child->isLocalFrame())
243 toLocalFrame(child.get())->setPrinting(printing, FloatSize(), FloatSize(), 0);
244 }
245 }
246
shouldUsePrintingLayout() const247 bool LocalFrame::shouldUsePrintingLayout() const
248 {
249 // Only top frame being printed should be fit to page size.
250 // Subframes should be constrained by parents only.
251 return document()->printing() && (!tree().parent() || !tree().parent()->isLocalFrame() || !toLocalFrame(tree().parent())->document()->printing());
252 }
253
resizePageRectsKeepingRatio(const FloatSize & originalSize,const FloatSize & expectedSize)254 FloatSize LocalFrame::resizePageRectsKeepingRatio(const FloatSize& originalSize, const FloatSize& expectedSize)
255 {
256 FloatSize resultSize;
257 if (!contentRenderer())
258 return FloatSize();
259
260 if (contentRenderer()->style()->isHorizontalWritingMode()) {
261 ASSERT(fabs(originalSize.width()) > std::numeric_limits<float>::epsilon());
262 float ratio = originalSize.height() / originalSize.width();
263 resultSize.setWidth(floorf(expectedSize.width()));
264 resultSize.setHeight(floorf(resultSize.width() * ratio));
265 } else {
266 ASSERT(fabs(originalSize.height()) > std::numeric_limits<float>::epsilon());
267 float ratio = originalSize.width() / originalSize.height();
268 resultSize.setHeight(floorf(expectedSize.height()));
269 resultSize.setWidth(floorf(resultSize.height() * ratio));
270 }
271 return resultSize;
272 }
273
setDOMWindow(PassRefPtrWillBeRawPtr<LocalDOMWindow> domWindow)274 void LocalFrame::setDOMWindow(PassRefPtrWillBeRawPtr<LocalDOMWindow> domWindow)
275 {
276 if (m_domWindow) {
277 // Oilpan: the assumption is that FrameDestructionObserver::willDetachFrameHost()
278 // on LocalWindow will have signalled these frameWindowDiscarded() notifications.
279 //
280 // It is not invoked when finalizing the LocalFrame, as setDOMWindow() isn't
281 // performed (accessing the m_domWindow heap object is unsafe then.)
282 console().messageStorage()->frameWindowDiscarded(m_domWindow.get());
283 InspectorInstrumentation::frameWindowDiscarded(this, m_domWindow.get());
284 }
285 if (domWindow)
286 script().clearWindowProxy();
287 Frame::setDOMWindow(domWindow);
288 }
289
didChangeVisibilityState()290 void LocalFrame::didChangeVisibilityState()
291 {
292 if (document())
293 document()->didChangeVisibilityState();
294
295 WillBeHeapVector<RefPtrWillBeMember<LocalFrame> > childFrames;
296 for (Frame* child = tree().firstChild(); child; child = child->tree().nextSibling()) {
297 if (child->isLocalFrame())
298 childFrames.append(toLocalFrame(child));
299 }
300
301 for (size_t i = 0; i < childFrames.size(); ++i)
302 childFrames[i]->didChangeVisibilityState();
303 }
304
addDestructionObserver(FrameDestructionObserver * observer)305 void LocalFrame::addDestructionObserver(FrameDestructionObserver* observer)
306 {
307 m_destructionObservers.add(observer);
308 }
309
removeDestructionObserver(FrameDestructionObserver * observer)310 void LocalFrame::removeDestructionObserver(FrameDestructionObserver* observer)
311 {
312 m_destructionObservers.remove(observer);
313 }
314
willDetachFrameHost()315 void LocalFrame::willDetachFrameHost()
316 {
317 // We should never be detatching the page during a Layout.
318 RELEASE_ASSERT(!m_view || !m_view->isInPerformLayout());
319
320 Frame* parent = tree().parent();
321 if (parent && parent->isLocalFrame())
322 toLocalFrame(parent)->loader().checkLoadComplete();
323
324 WillBeHeapHashSet<RawPtrWillBeWeakMember<FrameDestructionObserver> >::iterator stop = m_destructionObservers.end();
325 for (WillBeHeapHashSet<RawPtrWillBeWeakMember<FrameDestructionObserver> >::iterator it = m_destructionObservers.begin(); it != stop; ++it)
326 (*it)->willDetachFrameHost();
327
328 // FIXME: Page should take care of updating focus/scrolling instead of Frame.
329 // FIXME: It's unclear as to why this is called more than once, but it is,
330 // so page() could be null.
331 if (page() && page()->focusController().focusedFrame() == this)
332 page()->focusController().setFocusedFrame(nullptr);
333 script().clearScriptObjects();
334
335 if (page() && page()->scrollingCoordinator() && m_view)
336 page()->scrollingCoordinator()->willDestroyScrollableArea(m_view.get());
337 }
338
detachFromFrameHost()339 void LocalFrame::detachFromFrameHost()
340 {
341 // We should never be detaching the page during a Layout.
342 RELEASE_ASSERT(!m_view || !m_view->isInPerformLayout());
343 m_host = nullptr;
344 }
345
documentTypeString() const346 String LocalFrame::documentTypeString() const
347 {
348 if (DocumentType* doctype = document()->doctype())
349 return createMarkup(doctype);
350
351 return String();
352 }
353
selectedText() const354 String LocalFrame::selectedText() const
355 {
356 return selection().selectedText();
357 }
358
selectedTextForClipboard() const359 String LocalFrame::selectedTextForClipboard() const
360 {
361 return selection().selectedTextForClipboard();
362 }
363
visiblePositionForPoint(const IntPoint & framePoint)364 VisiblePosition LocalFrame::visiblePositionForPoint(const IntPoint& framePoint)
365 {
366 HitTestResult result = eventHandler().hitTestResultAtPoint(framePoint);
367 Node* node = result.innerNonSharedNode();
368 if (!node)
369 return VisiblePosition();
370 RenderObject* renderer = node->renderer();
371 if (!renderer)
372 return VisiblePosition();
373 VisiblePosition visiblePos = VisiblePosition(renderer->positionForPoint(result.localPoint()));
374 if (visiblePos.isNull())
375 visiblePos = VisiblePosition(firstPositionInOrBeforeNode(node));
376 return visiblePos;
377 }
378
contentRenderer() const379 RenderView* LocalFrame::contentRenderer() const
380 {
381 return document() ? document()->renderView() : 0;
382 }
383
document() const384 Document* LocalFrame::document() const
385 {
386 return m_domWindow ? m_domWindow->document() : 0;
387 }
388
documentAtPoint(const IntPoint & point)389 Document* LocalFrame::documentAtPoint(const IntPoint& point)
390 {
391 if (!view())
392 return 0;
393
394 IntPoint pt = view()->windowToContents(point);
395 HitTestResult result = HitTestResult(pt);
396
397 if (contentRenderer())
398 result = eventHandler().hitTestResultAtPoint(pt, HitTestRequest::ReadOnly | HitTestRequest::Active);
399 return result.innerNode() ? &result.innerNode()->document() : 0;
400 }
401
rangeForPoint(const IntPoint & framePoint)402 PassRefPtrWillBeRawPtr<Range> LocalFrame::rangeForPoint(const IntPoint& framePoint)
403 {
404 VisiblePosition position = visiblePositionForPoint(framePoint);
405 if (position.isNull())
406 return nullptr;
407
408 VisiblePosition previous = position.previous();
409 if (previous.isNotNull()) {
410 RefPtrWillBeRawPtr<Range> previousCharacterRange = makeRange(previous, position);
411 LayoutRect rect = editor().firstRectForRange(previousCharacterRange.get());
412 if (rect.contains(framePoint))
413 return previousCharacterRange.release();
414 }
415
416 VisiblePosition next = position.next();
417 if (RefPtrWillBeRawPtr<Range> nextCharacterRange = makeRange(position, next)) {
418 LayoutRect rect = editor().firstRectForRange(nextCharacterRange.get());
419 if (rect.contains(framePoint))
420 return nextCharacterRange.release();
421 }
422
423 return nullptr;
424 }
425
createView(const IntSize & viewportSize,const Color & backgroundColor,bool transparent,ScrollbarMode horizontalScrollbarMode,bool horizontalLock,ScrollbarMode verticalScrollbarMode,bool verticalLock)426 void LocalFrame::createView(const IntSize& viewportSize, const Color& backgroundColor, bool transparent,
427 ScrollbarMode horizontalScrollbarMode, bool horizontalLock,
428 ScrollbarMode verticalScrollbarMode, bool verticalLock)
429 {
430 ASSERT(this);
431 ASSERT(page());
432
433 bool isLocalRoot = this->isLocalRoot();
434
435 if (isLocalRoot && view())
436 view()->setParentVisible(false);
437
438 setView(nullptr);
439
440 RefPtr<FrameView> frameView;
441 if (isLocalRoot) {
442 frameView = FrameView::create(this, viewportSize);
443
444 // The layout size is set by WebViewImpl to support @viewport
445 frameView->setLayoutSizeFixedToFrameSize(false);
446 } else
447 frameView = FrameView::create(this);
448
449 frameView->setScrollbarModes(horizontalScrollbarMode, verticalScrollbarMode, horizontalLock, verticalLock);
450
451 setView(frameView);
452
453 frameView->updateBackgroundRecursively(backgroundColor, transparent);
454
455 if (isLocalRoot)
456 frameView->setParentVisible(true);
457
458 // FIXME: Not clear what the right thing for OOPI is here.
459 if (ownerRenderer()) {
460 HTMLFrameOwnerElement* owner = deprecatedLocalOwner();
461 ASSERT(owner);
462 owner->setWidget(frameView);
463 }
464
465 if (HTMLFrameOwnerElement* owner = deprecatedLocalOwner())
466 view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff);
467 }
468
469
countObjectsNeedingLayout(unsigned & needsLayoutObjects,unsigned & totalObjects,bool & isPartial)470 void LocalFrame::countObjectsNeedingLayout(unsigned& needsLayoutObjects, unsigned& totalObjects, bool& isPartial)
471 {
472 RenderObject* root = view()->layoutRoot();
473 isPartial = true;
474 if (!root) {
475 isPartial = false;
476 root = contentRenderer();
477 }
478
479 needsLayoutObjects = 0;
480 totalObjects = 0;
481
482 for (RenderObject* o = root; o; o = o->nextInPreOrder(root)) {
483 ++totalObjects;
484 if (o->needsLayout())
485 ++needsLayoutObjects;
486 }
487 }
488
layerTreeAsText(LayerTreeFlags flags) const489 String LocalFrame::layerTreeAsText(LayerTreeFlags flags) const
490 {
491 TextStream textStream;
492 textStream << localLayerTreeAsText(flags);
493
494 for (Frame* child = tree().firstChild(); child; child = child->tree().traverseNext(this)) {
495 if (!child->isLocalFrame())
496 continue;
497 String childLayerTree = toLocalFrame(child)->localLayerTreeAsText(flags);
498 if (!childLayerTree.length())
499 continue;
500
501 textStream << "\n\n--------\nFrame: '";
502 textStream << child->tree().uniqueName();
503 textStream << "'\n--------\n";
504 textStream << childLayerTree;
505 }
506
507 return textStream.release();
508 }
509
localLayerTreeAsText(unsigned flags) const510 String LocalFrame::localLayerTreeAsText(unsigned flags) const
511 {
512 if (!contentRenderer())
513 return String();
514
515 return contentRenderer()->compositor()->layerTreeAsText(static_cast<LayerTreeFlags>(flags));
516 }
517
setPageZoomFactor(float factor)518 void LocalFrame::setPageZoomFactor(float factor)
519 {
520 setPageAndTextZoomFactors(factor, m_textZoomFactor);
521 }
522
setTextZoomFactor(float factor)523 void LocalFrame::setTextZoomFactor(float factor)
524 {
525 setPageAndTextZoomFactors(m_pageZoomFactor, factor);
526 }
527
setPageAndTextZoomFactors(float pageZoomFactor,float textZoomFactor)528 void LocalFrame::setPageAndTextZoomFactors(float pageZoomFactor, float textZoomFactor)
529 {
530 if (m_pageZoomFactor == pageZoomFactor && m_textZoomFactor == textZoomFactor)
531 return;
532
533 Page* page = this->page();
534 if (!page)
535 return;
536
537 Document* document = this->document();
538 if (!document)
539 return;
540
541 // Respect SVGs zoomAndPan="disabled" property in standalone SVG documents.
542 // FIXME: How to handle compound documents + zoomAndPan="disabled"? Needs SVG WG clarification.
543 if (document->isSVGDocument()) {
544 if (!document->accessSVGExtensions().zoomAndPanEnabled())
545 return;
546 }
547
548 if (m_pageZoomFactor != pageZoomFactor) {
549 if (FrameView* view = this->view()) {
550 // Update the scroll position when doing a full page zoom, so the content stays in relatively the same position.
551 LayoutPoint scrollPosition = view->scrollPosition();
552 float percentDifference = (pageZoomFactor / m_pageZoomFactor);
553 view->setScrollPosition(IntPoint(scrollPosition.x() * percentDifference, scrollPosition.y() * percentDifference));
554 }
555 }
556
557 m_pageZoomFactor = pageZoomFactor;
558 m_textZoomFactor = textZoomFactor;
559
560 for (RefPtrWillBeRawPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling()) {
561 if (child->isLocalFrame())
562 toLocalFrame(child.get())->setPageAndTextZoomFactors(m_pageZoomFactor, m_textZoomFactor);
563 }
564
565 document->setNeedsStyleRecalc(SubtreeStyleChange);
566 document->updateLayoutIgnorePendingStylesheets();
567 }
568
deviceOrPageScaleFactorChanged()569 void LocalFrame::deviceOrPageScaleFactorChanged()
570 {
571 document()->mediaQueryAffectingValueChanged();
572 for (RefPtrWillBeRawPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling()) {
573 if (child->isLocalFrame())
574 toLocalFrame(child.get())->deviceOrPageScaleFactorChanged();
575 }
576 }
577
isURLAllowed(const KURL & url) const578 bool LocalFrame::isURLAllowed(const KURL& url) const
579 {
580 // We allow one level of self-reference because some sites depend on that,
581 // but we don't allow more than one.
582 if (page()->subframeCount() >= Page::maxNumberOfFrames)
583 return false;
584 bool foundSelfReference = false;
585 for (const Frame* frame = this; frame; frame = frame->tree().parent()) {
586 if (!frame->isLocalFrame())
587 continue;
588 if (equalIgnoringFragmentIdentifier(toLocalFrame(frame)->document()->url(), url)) {
589 if (foundSelfReference)
590 return false;
591 foundSelfReference = true;
592 }
593 }
594 return true;
595 }
596
shouldReuseDefaultView(const KURL & url) const597 bool LocalFrame::shouldReuseDefaultView(const KURL& url) const
598 {
599 return loader().stateMachine()->isDisplayingInitialEmptyDocument() && document()->isSecureTransitionTo(url);
600 }
601
removeSpellingMarkersUnderWords(const Vector<String> & words)602 void LocalFrame::removeSpellingMarkersUnderWords(const Vector<String>& words)
603 {
604 spellChecker().removeSpellingMarkersUnderWords(words);
605 }
606
607 struct ScopedFramePaintingState {
ScopedFramePaintingStateblink::ScopedFramePaintingState608 ScopedFramePaintingState(LocalFrame* frame, Node* node)
609 : frame(frame)
610 , node(node)
611 , paintBehavior(frame->view()->paintBehavior())
612 {
613 ASSERT(!node || node->renderer());
614 if (node)
615 node->renderer()->updateDragState(true);
616 }
617
~ScopedFramePaintingStateblink::ScopedFramePaintingState618 ~ScopedFramePaintingState()
619 {
620 if (node && node->renderer())
621 node->renderer()->updateDragState(false);
622 frame->view()->setPaintBehavior(paintBehavior);
623 frame->view()->setNodeToDraw(0);
624 }
625
626 LocalFrame* frame;
627 Node* node;
628 PaintBehavior paintBehavior;
629 };
630
nodeImage(Node & node)631 PassOwnPtr<DragImage> LocalFrame::nodeImage(Node& node)
632 {
633 if (!node.renderer())
634 return nullptr;
635
636 const ScopedFramePaintingState state(this, &node);
637
638 m_view->updateLayoutAndStyleForPainting();
639
640 m_view->setPaintBehavior(state.paintBehavior | PaintBehaviorFlattenCompositingLayers);
641
642 m_view->setNodeToDraw(&node); // Enable special sub-tree drawing mode.
643
644 // Document::updateLayout may have blown away the original RenderObject.
645 RenderObject* renderer = node.renderer();
646 if (!renderer)
647 return nullptr;
648
649 LayoutRect topLevelRect;
650 IntRect paintingRect = pixelSnappedIntRect(renderer->paintingRootRect(topLevelRect));
651
652 ASSERT(document()->isActive());
653 float deviceScaleFactor = m_host->deviceScaleFactor();
654 paintingRect.setWidth(paintingRect.width() * deviceScaleFactor);
655 paintingRect.setHeight(paintingRect.height() * deviceScaleFactor);
656
657 OwnPtr<ImageBuffer> buffer = ImageBuffer::create(paintingRect.size());
658 if (!buffer)
659 return nullptr;
660 buffer->context()->scale(deviceScaleFactor, deviceScaleFactor);
661 buffer->context()->translate(-paintingRect.x(), -paintingRect.y());
662 buffer->context()->clip(FloatRect(0, 0, paintingRect.maxX(), paintingRect.maxY()));
663
664 m_view->paintContents(buffer->context(), paintingRect);
665
666 RefPtr<Image> image = buffer->copyImage();
667 return DragImage::create(image.get(), renderer->shouldRespectImageOrientation(), deviceScaleFactor);
668 }
669
dragImageForSelection()670 PassOwnPtr<DragImage> LocalFrame::dragImageForSelection()
671 {
672 if (!selection().isRange())
673 return nullptr;
674
675 const ScopedFramePaintingState state(this, 0);
676 m_view->setPaintBehavior(PaintBehaviorSelectionOnly | PaintBehaviorFlattenCompositingLayers);
677 m_view->updateLayoutAndStyleForPainting();
678
679 IntRect paintingRect = enclosingIntRect(selection().bounds());
680
681 ASSERT(document()->isActive());
682 float deviceScaleFactor = m_host->deviceScaleFactor();
683 paintingRect.setWidth(paintingRect.width() * deviceScaleFactor);
684 paintingRect.setHeight(paintingRect.height() * deviceScaleFactor);
685
686 OwnPtr<ImageBuffer> buffer = ImageBuffer::create(paintingRect.size());
687 if (!buffer)
688 return nullptr;
689 buffer->context()->scale(deviceScaleFactor, deviceScaleFactor);
690 buffer->context()->translate(-paintingRect.x(), -paintingRect.y());
691 buffer->context()->clip(FloatRect(0, 0, paintingRect.maxX(), paintingRect.maxY()));
692
693 m_view->paintContents(buffer->context(), paintingRect);
694
695 RefPtr<Image> image = buffer->copyImage();
696 return DragImage::create(image.get(), DoNotRespectImageOrientation, deviceScaleFactor);
697 }
698
devicePixelRatio() const699 double LocalFrame::devicePixelRatio() const
700 {
701 if (!m_host)
702 return 0;
703
704 double ratio = m_host->deviceScaleFactor();
705 ratio *= pageZoomFactor();
706 return ratio;
707 }
708
disconnectOwnerElement()709 void LocalFrame::disconnectOwnerElement()
710 {
711 if (owner()) {
712 if (Document* document = this->document())
713 document->topDocument().clearAXObjectCache();
714 #if ENABLE(OILPAN)
715 // Clear the FrameView and FrameLoader right here rather than
716 // during finalization. Too late to access various heap objects
717 // at that stage.
718 setView(nullptr);
719 loader().clear();
720 #endif
721 }
722 Frame::disconnectOwnerElement();
723 }
724
localFrameRoot()725 LocalFrame* LocalFrame::localFrameRoot()
726 {
727 LocalFrame* curFrame = this;
728 while (curFrame && curFrame->tree().parent() && curFrame->tree().parent()->isLocalFrame())
729 curFrame = toLocalFrame(curFrame->tree().parent());
730
731 return curFrame;
732 }
733
setPagePopupOwner(Element & owner)734 void LocalFrame::setPagePopupOwner(Element& owner)
735 {
736 m_pagePopupOwner = &owner;
737 }
738
739 } // namespace blink
740