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/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/LocalDOMWindow.h" 44 #include "core/frame/EventHandlerRegistry.h" 45 #include "core/frame/FrameConsole.h" 46 #include "core/frame/FrameHost.h" 47 #include "core/frame/FrameView.h" 48 #include "core/frame/Settings.h" 49 #include "core/html/HTMLFrameElementBase.h" 50 #include "core/inspector/InspectorInstrumentation.h" 51 #include "core/loader/FrameLoaderClient.h" 52 #include "core/page/Chrome.h" 53 #include "core/page/EventHandler.h" 54 #include "core/page/FocusController.h" 55 #include "core/page/scrolling/ScrollingCoordinator.h" 56 #include "core/rendering/HitTestResult.h" 57 #include "core/rendering/RenderLayer.h" 58 #include "core/rendering/RenderView.h" 59 #include "core/rendering/compositing/RenderLayerCompositor.h" 60 #include "core/svg/SVGDocumentExtensions.h" 61 #include "platform/DragImage.h" 62 #include "platform/RuntimeEnabledFeatures.h" 63 #include "platform/graphics/GraphicsContext.h" 64 #include "platform/graphics/ImageBuffer.h" 65 #include "platform/text/TextStream.h" 66 #include "wtf/PassOwnPtr.h" 67 #include "wtf/StdLibExtras.h" 68 69 namespace WebCore { 70 71 using namespace HTMLNames; 72 73 static inline float parentPageZoomFactor(LocalFrame* frame) 74 { 75 Frame* parent = frame->tree().parent(); 76 if (!parent || !parent->isLocalFrame()) 77 return 1; 78 return toLocalFrame(parent)->pageZoomFactor(); 79 } 80 81 static inline float parentTextZoomFactor(LocalFrame* frame) 82 { 83 Frame* parent = frame->tree().parent(); 84 if (!parent || !parent->isLocalFrame()) 85 return 1; 86 return toLocalFrame(parent)->textZoomFactor(); 87 } 88 89 inline LocalFrame::LocalFrame(FrameLoaderClient* client, FrameHost* host, FrameOwner* owner) 90 : Frame(client, host, owner) 91 , m_loader(this) 92 , m_navigationScheduler(this) 93 , m_script(adoptPtr(new ScriptController(this))) 94 , m_editor(Editor::create(*this)) 95 , m_spellChecker(SpellChecker::create(*this)) 96 , m_selection(FrameSelection::create(this)) 97 , m_eventHandler(adoptPtrWillBeNoop(new EventHandler(this))) 98 , m_console(FrameConsole::create(*this)) 99 , m_inputMethodController(InputMethodController::create(*this)) 100 , m_pageZoomFactor(parentPageZoomFactor(this)) 101 , m_textZoomFactor(parentTextZoomFactor(this)) 102 , m_inViewSourceMode(false) 103 { 104 } 105 106 PassRefPtr<LocalFrame> LocalFrame::create(FrameLoaderClient* client, FrameHost* host, FrameOwner* owner) 107 { 108 RefPtr<LocalFrame> frame = adoptRef(new LocalFrame(client, host, owner)); 109 InspectorInstrumentation::frameAttachedToParent(frame.get()); 110 return frame.release(); 111 } 112 113 LocalFrame::~LocalFrame() 114 { 115 setView(nullptr); 116 loader().clear(); 117 setDOMWindow(nullptr); 118 } 119 120 bool LocalFrame::inScope(TreeScope* scope) const 121 { 122 ASSERT(scope); 123 Document* doc = document(); 124 if (!doc) 125 return false; 126 // FIXME: This check is broken in for OOPI. 127 HTMLFrameOwnerElement* owner = doc->ownerElement(); 128 if (!owner) 129 return false; 130 return owner->treeScope() == scope; 131 } 132 133 void LocalFrame::setView(PassRefPtr<FrameView> view) 134 { 135 // We the custom scroll bars as early as possible to prevent m_doc->detach() 136 // from messing with the view such that its scroll bars won't be torn down. 137 // FIXME: We should revisit this. 138 if (m_view) 139 m_view->prepareForDetach(); 140 141 // Prepare for destruction now, so any unload event handlers get run and the LocalDOMWindow is 142 // notified. If we wait until the view is destroyed, then things won't be hooked up enough for 143 // these calls to work. 144 if (!view && document() && document()->isActive()) { 145 // FIXME: We don't call willRemove here. Why is that OK? 146 document()->prepareForDestruction(); 147 } 148 149 eventHandler().clear(); 150 151 m_view = view; 152 153 if (m_view && isMainFrame()) { 154 if (settings()->pinchVirtualViewportEnabled()) 155 m_host->pinchViewport().mainFrameDidChangeSize(); 156 else 157 m_view->setVisibleContentScaleFactor(page()->pageScaleFactor()); 158 } 159 } 160 161 void LocalFrame::sendOrientationChangeEvent() 162 { 163 if (!RuntimeEnabledFeatures::orientationEventEnabled() && !RuntimeEnabledFeatures::screenOrientationEnabled()) 164 return; 165 166 if (page()->visibilityState() != PageVisibilityStateVisible) 167 return; 168 169 LocalDOMWindow* window = domWindow(); 170 if (!window) 171 return; 172 window->dispatchEvent(Event::create(EventTypeNames::orientationchange)); 173 174 // Notify subframes. 175 Vector<RefPtr<LocalFrame> > childFrames; 176 for (Frame* child = tree().firstChild(); child; child = child->tree().nextSibling()) { 177 if (child->isLocalFrame()) 178 childFrames.append(toLocalFrame(child)); 179 } 180 181 for (size_t i = 0; i < childFrames.size(); ++i) 182 childFrames[i]->sendOrientationChangeEvent(); 183 } 184 185 void LocalFrame::setPrinting(bool printing, const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkRatio) 186 { 187 // In setting printing, we should not validate resources already cached for the document. 188 // See https://bugs.webkit.org/show_bug.cgi?id=43704 189 ResourceCacheValidationSuppressor validationSuppressor(document()->fetcher()); 190 191 document()->setPrinting(printing); 192 view()->adjustMediaTypeForPrinting(printing); 193 194 document()->styleResolverChanged(); 195 if (shouldUsePrintingLayout()) { 196 view()->forceLayoutForPagination(pageSize, originalPageSize, maximumShrinkRatio); 197 } else { 198 view()->forceLayout(); 199 view()->adjustViewSize(); 200 } 201 202 // Subframes of the one we're printing don't lay out to the page size. 203 for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling()) { 204 if (child->isLocalFrame()) 205 toLocalFrame(child.get())->setPrinting(printing, FloatSize(), FloatSize(), 0); 206 } 207 } 208 209 bool LocalFrame::shouldUsePrintingLayout() const 210 { 211 // Only top frame being printed should be fit to page size. 212 // Subframes should be constrained by parents only. 213 return document()->printing() && (!tree().parent() || !tree().parent()->isLocalFrame() || !toLocalFrame(tree().parent())->document()->printing()); 214 } 215 216 FloatSize LocalFrame::resizePageRectsKeepingRatio(const FloatSize& originalSize, const FloatSize& expectedSize) 217 { 218 FloatSize resultSize; 219 if (!contentRenderer()) 220 return FloatSize(); 221 222 if (contentRenderer()->style()->isHorizontalWritingMode()) { 223 ASSERT(fabs(originalSize.width()) > std::numeric_limits<float>::epsilon()); 224 float ratio = originalSize.height() / originalSize.width(); 225 resultSize.setWidth(floorf(expectedSize.width())); 226 resultSize.setHeight(floorf(resultSize.width() * ratio)); 227 } else { 228 ASSERT(fabs(originalSize.height()) > std::numeric_limits<float>::epsilon()); 229 float ratio = originalSize.width() / originalSize.height(); 230 resultSize.setHeight(floorf(expectedSize.height())); 231 resultSize.setWidth(floorf(resultSize.height() * ratio)); 232 } 233 return resultSize; 234 } 235 236 void LocalFrame::setDOMWindow(PassRefPtrWillBeRawPtr<LocalDOMWindow> domWindow) 237 { 238 InspectorInstrumentation::frameWindowDiscarded(this, m_domWindow.get()); 239 if (domWindow) 240 script().clearWindowShell(); 241 Frame::setDOMWindow(domWindow); 242 } 243 244 void LocalFrame::didChangeVisibilityState() 245 { 246 if (document()) 247 document()->didChangeVisibilityState(); 248 249 Vector<RefPtr<LocalFrame> > childFrames; 250 for (Frame* child = tree().firstChild(); child; child = child->tree().nextSibling()) { 251 if (child->isLocalFrame()) 252 childFrames.append(toLocalFrame(child)); 253 } 254 255 for (size_t i = 0; i < childFrames.size(); ++i) 256 childFrames[i]->didChangeVisibilityState(); 257 } 258 259 void LocalFrame::willDetachFrameHost() 260 { 261 // We should never be detatching the page during a Layout. 262 RELEASE_ASSERT(!m_view || !m_view->isInPerformLayout()); 263 264 Frame* parent = tree().parent(); 265 if (parent && parent->isLocalFrame()) 266 toLocalFrame(parent)->loader().checkLoadComplete(); 267 268 Frame::willDetachFrameHost(); 269 script().clearScriptObjects(); 270 271 if (page() && page()->scrollingCoordinator() && m_view) 272 page()->scrollingCoordinator()->willDestroyScrollableArea(m_view.get()); 273 } 274 275 void LocalFrame::detachFromFrameHost() 276 { 277 // We should never be detatching the page during a Layout. 278 RELEASE_ASSERT(!m_view || !m_view->isInPerformLayout()); 279 Frame::detachFromFrameHost(); 280 } 281 282 String LocalFrame::documentTypeString() const 283 { 284 if (DocumentType* doctype = document()->doctype()) 285 return createMarkup(doctype); 286 287 return String(); 288 } 289 290 String LocalFrame::selectedText() const 291 { 292 return selection().selectedText(); 293 } 294 295 String LocalFrame::selectedTextForClipboard() const 296 { 297 return selection().selectedTextForClipboard(); 298 } 299 300 VisiblePosition LocalFrame::visiblePositionForPoint(const IntPoint& framePoint) 301 { 302 HitTestResult result = eventHandler().hitTestResultAtPoint(framePoint); 303 Node* node = result.innerNonSharedNode(); 304 if (!node) 305 return VisiblePosition(); 306 RenderObject* renderer = node->renderer(); 307 if (!renderer) 308 return VisiblePosition(); 309 VisiblePosition visiblePos = VisiblePosition(renderer->positionForPoint(result.localPoint())); 310 if (visiblePos.isNull()) 311 visiblePos = VisiblePosition(firstPositionInOrBeforeNode(node)); 312 return visiblePos; 313 } 314 315 RenderView* LocalFrame::contentRenderer() const 316 { 317 return document() ? document()->renderView() : 0; 318 } 319 320 Document* LocalFrame::document() const 321 { 322 return m_domWindow ? m_domWindow->document() : 0; 323 } 324 325 Document* LocalFrame::documentAtPoint(const IntPoint& point) 326 { 327 if (!view()) 328 return 0; 329 330 IntPoint pt = view()->windowToContents(point); 331 HitTestResult result = HitTestResult(pt); 332 333 if (contentRenderer()) 334 result = eventHandler().hitTestResultAtPoint(pt, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent); 335 return result.innerNode() ? &result.innerNode()->document() : 0; 336 } 337 338 PassRefPtrWillBeRawPtr<Range> LocalFrame::rangeForPoint(const IntPoint& framePoint) 339 { 340 VisiblePosition position = visiblePositionForPoint(framePoint); 341 if (position.isNull()) 342 return nullptr; 343 344 VisiblePosition previous = position.previous(); 345 if (previous.isNotNull()) { 346 RefPtrWillBeRawPtr<Range> previousCharacterRange = makeRange(previous, position); 347 LayoutRect rect = editor().firstRectForRange(previousCharacterRange.get()); 348 if (rect.contains(framePoint)) 349 return previousCharacterRange.release(); 350 } 351 352 VisiblePosition next = position.next(); 353 if (RefPtrWillBeRawPtr<Range> nextCharacterRange = makeRange(position, next)) { 354 LayoutRect rect = editor().firstRectForRange(nextCharacterRange.get()); 355 if (rect.contains(framePoint)) 356 return nextCharacterRange.release(); 357 } 358 359 return nullptr; 360 } 361 362 void LocalFrame::createView(const IntSize& viewportSize, const Color& backgroundColor, bool transparent, 363 ScrollbarMode horizontalScrollbarMode, bool horizontalLock, 364 ScrollbarMode verticalScrollbarMode, bool verticalLock) 365 { 366 ASSERT(this); 367 ASSERT(page()); 368 369 bool isMainFrame = this->isMainFrame(); 370 371 if (isMainFrame && view()) 372 view()->setParentVisible(false); 373 374 setView(nullptr); 375 376 RefPtr<FrameView> frameView; 377 if (isMainFrame) { 378 frameView = FrameView::create(this, viewportSize); 379 380 // The layout size is set by WebViewImpl to support @viewport 381 frameView->setLayoutSizeFixedToFrameSize(false); 382 } else 383 frameView = FrameView::create(this); 384 385 frameView->setScrollbarModes(horizontalScrollbarMode, verticalScrollbarMode, horizontalLock, verticalLock); 386 387 setView(frameView); 388 389 frameView->updateBackgroundRecursively(backgroundColor, transparent); 390 391 if (isMainFrame) 392 frameView->setParentVisible(true); 393 394 // FIXME: Not clear what the right thing for OOPI is here. 395 if (ownerRenderer()) { 396 HTMLFrameOwnerElement* owner = deprecatedLocalOwner(); 397 ASSERT(owner); 398 owner->setWidget(frameView); 399 } 400 401 if (HTMLFrameOwnerElement* owner = deprecatedLocalOwner()) 402 view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff); 403 } 404 405 406 void LocalFrame::countObjectsNeedingLayout(unsigned& needsLayoutObjects, unsigned& totalObjects, bool& isPartial) 407 { 408 RenderObject* root = view()->layoutRoot(); 409 isPartial = true; 410 if (!root) { 411 isPartial = false; 412 root = contentRenderer(); 413 } 414 415 needsLayoutObjects = 0; 416 totalObjects = 0; 417 418 for (RenderObject* o = root; o; o = o->nextInPreOrder(root)) { 419 ++totalObjects; 420 if (o->needsLayout()) 421 ++needsLayoutObjects; 422 } 423 } 424 425 String LocalFrame::layerTreeAsText(LayerTreeFlags flags) const 426 { 427 TextStream textStream; 428 textStream << localLayerTreeAsText(flags); 429 430 for (Frame* child = tree().firstChild(); child; child = child->tree().traverseNext(this)) { 431 if (!child->isLocalFrame()) 432 continue; 433 String childLayerTree = toLocalFrame(child)->localLayerTreeAsText(flags); 434 if (!childLayerTree.length()) 435 continue; 436 437 textStream << "\n\n--------\nFrame: '"; 438 textStream << child->tree().uniqueName(); 439 textStream << "'\n--------\n"; 440 textStream << childLayerTree; 441 } 442 443 return textStream.release(); 444 } 445 446 String LocalFrame::localLayerTreeAsText(unsigned flags) const 447 { 448 if (!contentRenderer()) 449 return String(); 450 451 return contentRenderer()->compositor()->layerTreeAsText(static_cast<LayerTreeFlags>(flags)); 452 } 453 454 String LocalFrame::trackedRepaintRectsAsText() const 455 { 456 if (!m_view) 457 return String(); 458 return m_view->trackedPaintInvalidationRectsAsText(); 459 } 460 461 void LocalFrame::setPageZoomFactor(float factor) 462 { 463 setPageAndTextZoomFactors(factor, m_textZoomFactor); 464 } 465 466 void LocalFrame::setTextZoomFactor(float factor) 467 { 468 setPageAndTextZoomFactors(m_pageZoomFactor, factor); 469 } 470 471 void LocalFrame::setPageAndTextZoomFactors(float pageZoomFactor, float textZoomFactor) 472 { 473 if (m_pageZoomFactor == pageZoomFactor && m_textZoomFactor == textZoomFactor) 474 return; 475 476 Page* page = this->page(); 477 if (!page) 478 return; 479 480 Document* document = this->document(); 481 if (!document) 482 return; 483 484 // Respect SVGs zoomAndPan="disabled" property in standalone SVG documents. 485 // FIXME: How to handle compound documents + zoomAndPan="disabled"? Needs SVG WG clarification. 486 if (document->isSVGDocument()) { 487 if (!document->accessSVGExtensions().zoomAndPanEnabled()) 488 return; 489 } 490 491 if (m_pageZoomFactor != pageZoomFactor) { 492 if (FrameView* view = this->view()) { 493 // Update the scroll position when doing a full page zoom, so the content stays in relatively the same position. 494 LayoutPoint scrollPosition = view->scrollPosition(); 495 float percentDifference = (pageZoomFactor / m_pageZoomFactor); 496 view->setScrollPosition(IntPoint(scrollPosition.x() * percentDifference, scrollPosition.y() * percentDifference)); 497 } 498 } 499 500 m_pageZoomFactor = pageZoomFactor; 501 m_textZoomFactor = textZoomFactor; 502 503 for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling()) { 504 if (child->isLocalFrame()) 505 toLocalFrame(child.get())->setPageAndTextZoomFactors(m_pageZoomFactor, m_textZoomFactor); 506 } 507 508 document->setNeedsStyleRecalc(SubtreeStyleChange); 509 document->updateLayoutIgnorePendingStylesheets(); 510 } 511 512 void LocalFrame::deviceOrPageScaleFactorChanged() 513 { 514 document()->mediaQueryAffectingValueChanged(); 515 for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling()) { 516 if (child->isLocalFrame()) 517 toLocalFrame(child.get())->deviceOrPageScaleFactorChanged(); 518 } 519 } 520 521 bool LocalFrame::isURLAllowed(const KURL& url) const 522 { 523 // We allow one level of self-reference because some sites depend on that, 524 // but we don't allow more than one. 525 if (page()->subframeCount() >= Page::maxNumberOfFrames) 526 return false; 527 bool foundSelfReference = false; 528 for (const Frame* frame = this; frame; frame = frame->tree().parent()) { 529 if (!frame->isLocalFrame()) 530 continue; 531 if (equalIgnoringFragmentIdentifier(toLocalFrame(frame)->document()->url(), url)) { 532 if (foundSelfReference) 533 return false; 534 foundSelfReference = true; 535 } 536 } 537 return true; 538 } 539 540 struct ScopedFramePaintingState { 541 ScopedFramePaintingState(LocalFrame* frame, Node* node) 542 : frame(frame) 543 , node(node) 544 , paintBehavior(frame->view()->paintBehavior()) 545 { 546 ASSERT(!node || node->renderer()); 547 if (node) 548 node->renderer()->updateDragState(true); 549 } 550 551 ~ScopedFramePaintingState() 552 { 553 if (node && node->renderer()) 554 node->renderer()->updateDragState(false); 555 frame->view()->setPaintBehavior(paintBehavior); 556 frame->view()->setNodeToDraw(0); 557 } 558 559 LocalFrame* frame; 560 Node* node; 561 PaintBehavior paintBehavior; 562 }; 563 564 PassOwnPtr<DragImage> LocalFrame::nodeImage(Node& node) 565 { 566 if (!node.renderer()) 567 return nullptr; 568 569 const ScopedFramePaintingState state(this, &node); 570 571 m_view->updateLayoutAndStyleForPainting(); 572 573 m_view->setPaintBehavior(state.paintBehavior | PaintBehaviorFlattenCompositingLayers); 574 575 m_view->setNodeToDraw(&node); // Enable special sub-tree drawing mode. 576 577 // Document::updateLayout may have blown away the original RenderObject. 578 RenderObject* renderer = node.renderer(); 579 if (!renderer) 580 return nullptr; 581 582 LayoutRect topLevelRect; 583 IntRect paintingRect = pixelSnappedIntRect(renderer->paintingRootRect(topLevelRect)); 584 585 ASSERT(document()->isActive()); 586 float deviceScaleFactor = m_host->deviceScaleFactor(); 587 paintingRect.setWidth(paintingRect.width() * deviceScaleFactor); 588 paintingRect.setHeight(paintingRect.height() * deviceScaleFactor); 589 590 OwnPtr<ImageBuffer> buffer = ImageBuffer::create(paintingRect.size()); 591 if (!buffer) 592 return nullptr; 593 buffer->context()->scale(deviceScaleFactor, deviceScaleFactor); 594 buffer->context()->translate(-paintingRect.x(), -paintingRect.y()); 595 buffer->context()->clip(FloatRect(0, 0, paintingRect.maxX(), paintingRect.maxY())); 596 597 m_view->paintContents(buffer->context(), paintingRect); 598 599 RefPtr<Image> image = buffer->copyImage(); 600 return DragImage::create(image.get(), renderer->shouldRespectImageOrientation(), deviceScaleFactor); 601 } 602 603 PassOwnPtr<DragImage> LocalFrame::dragImageForSelection() 604 { 605 if (!selection().isRange()) 606 return nullptr; 607 608 const ScopedFramePaintingState state(this, 0); 609 m_view->setPaintBehavior(PaintBehaviorSelectionOnly | PaintBehaviorFlattenCompositingLayers); 610 document()->updateLayout(); 611 612 IntRect paintingRect = enclosingIntRect(selection().bounds()); 613 614 ASSERT(document()->isActive()); 615 float deviceScaleFactor = m_host->deviceScaleFactor(); 616 paintingRect.setWidth(paintingRect.width() * deviceScaleFactor); 617 paintingRect.setHeight(paintingRect.height() * deviceScaleFactor); 618 619 OwnPtr<ImageBuffer> buffer = ImageBuffer::create(paintingRect.size()); 620 if (!buffer) 621 return nullptr; 622 buffer->context()->scale(deviceScaleFactor, deviceScaleFactor); 623 buffer->context()->translate(-paintingRect.x(), -paintingRect.y()); 624 buffer->context()->clip(FloatRect(0, 0, paintingRect.maxX(), paintingRect.maxY())); 625 626 m_view->paintContents(buffer->context(), paintingRect); 627 628 RefPtr<Image> image = buffer->copyImage(); 629 return DragImage::create(image.get(), DoNotRespectImageOrientation, deviceScaleFactor); 630 } 631 632 double LocalFrame::devicePixelRatio() const 633 { 634 if (!m_host) 635 return 0; 636 637 double ratio = m_host->deviceScaleFactor(); 638 ratio *= pageZoomFactor(); 639 return ratio; 640 } 641 642 void LocalFrame::disconnectOwnerElement() 643 { 644 if (owner()) { 645 if (Document* doc = document()) 646 doc->topDocument().clearAXObjectCache(); 647 } 648 Frame::disconnectOwnerElement(); 649 } 650 651 LocalFrame* LocalFrame::localFrameRoot() 652 { 653 LocalFrame* curFrame = this; 654 while (curFrame && curFrame->tree().parent() && curFrame->tree().parent()->isLocalFrame()) 655 curFrame = toLocalFrame(curFrame->tree().parent()); 656 657 return curFrame; 658 } 659 660 } // namespace WebCore 661