1 /* 2 * Copyright (C) 1998, 1999 Torben Weis <weis (at) kde.org> 3 * 1999 Lars Knoll <knoll (at) kde.org> 4 * 1999 Antti Koivisto <koivisto (at) kde.org> 5 * 2000 Simon Hausmann <hausmann (at) kde.org> 6 * 2000 Stefan Schimanski <1Stein (at) gmx.de> 7 * 2001 George Staikos <staikos (at) 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 (at) nypop.com> 10 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) 11 * Copyright (C) 2008 Eric Seidel <eric (at) 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 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 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 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 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 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 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 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 175 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 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 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 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 247 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 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 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 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 305 void LocalFrame::addDestructionObserver(FrameDestructionObserver* observer) 306 { 307 m_destructionObservers.add(observer); 308 } 309 310 void LocalFrame::removeDestructionObserver(FrameDestructionObserver* observer) 311 { 312 m_destructionObservers.remove(observer); 313 } 314 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 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 346 String LocalFrame::documentTypeString() const 347 { 348 if (DocumentType* doctype = document()->doctype()) 349 return createMarkup(doctype); 350 351 return String(); 352 } 353 354 String LocalFrame::selectedText() const 355 { 356 return selection().selectedText(); 357 } 358 359 String LocalFrame::selectedTextForClipboard() const 360 { 361 return selection().selectedTextForClipboard(); 362 } 363 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 379 RenderView* LocalFrame::contentRenderer() const 380 { 381 return document() ? document()->renderView() : 0; 382 } 383 384 Document* LocalFrame::document() const 385 { 386 return m_domWindow ? m_domWindow->document() : 0; 387 } 388 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 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 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 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 489 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 510 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 518 void LocalFrame::setPageZoomFactor(float factor) 519 { 520 setPageAndTextZoomFactors(factor, m_textZoomFactor); 521 } 522 523 void LocalFrame::setTextZoomFactor(float factor) 524 { 525 setPageAndTextZoomFactors(m_pageZoomFactor, factor); 526 } 527 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 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 578 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 597 bool LocalFrame::shouldReuseDefaultView(const KURL& url) const 598 { 599 return loader().stateMachine()->isDisplayingInitialEmptyDocument() && document()->isSecureTransitionTo(url); 600 } 601 602 void LocalFrame::removeSpellingMarkersUnderWords(const Vector<String>& words) 603 { 604 spellChecker().removeSpellingMarkersUnderWords(words); 605 } 606 607 struct ScopedFramePaintingState { 608 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 618 ~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 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 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 699 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 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 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 734 void LocalFrame::setPagePopupOwner(Element& owner) 735 { 736 m_pagePopupOwner = &owner; 737 } 738 739 } // namespace blink 740