void PaintLayerCompositor::updateIfNeededRecursive() { FrameView* view = m_layoutView.frameView(); if (view->shouldThrottleRendering()) return; for (Frame* child = m_layoutView.frameView()->frame().tree().firstChild(); child; child = child->tree().nextSibling()) { if (!child->isLocalFrame()) continue; LocalFrame* localFrame = toLocalFrame(child); // It's possible for trusted Pepper plugins to force hit testing in situations where // the frame tree is in an inconsistent state, such as in the middle of frame detach. // TODO(bbudge) Remove this check when trusted Pepper plugins are gone. if (localFrame->document()->isActive()) localFrame->contentLayoutObject()->compositor()->updateIfNeededRecursive(); } TRACE_EVENT0("blink", "PaintLayerCompositor::updateIfNeededRecursive"); ASSERT(!m_layoutView.needsLayout()); ScriptForbiddenScope forbidScript; // FIXME: enableCompositingModeIfNeeded can trigger a CompositingUpdateRebuildTree, // which asserts that it's not InCompositingUpdate. enableCompositingModeIfNeeded(); if (m_needsUpdateDescendantDependentFlags) { updateDescendantDependentFlagsForEntireSubtree(*rootLayer()); m_needsUpdateDescendantDependentFlags = false; } m_layoutView.commitPendingSelection(); lifecycle().advanceTo(DocumentLifecycle::InCompositingUpdate); updateIfNeeded(); lifecycle().advanceTo(DocumentLifecycle::CompositingClean); DocumentAnimations::updateCompositorAnimations(m_layoutView.document()); m_layoutView.frameView()->scrollableArea()->updateCompositorScrollAnimations(); if (const FrameView::ScrollableAreaSet* animatingScrollableAreas = m_layoutView.frameView()->animatingScrollableAreas()) { for (ScrollableArea* scrollableArea : *animatingScrollableAreas) scrollableArea->updateCompositorScrollAnimations(); } #if ENABLE(ASSERT) ASSERT(lifecycle().state() == DocumentLifecycle::CompositingClean); assertNoUnresolvedDirtyBits(); for (Frame* child = m_layoutView.frameView()->frame().tree().firstChild(); child; child = child->tree().nextSibling()) { if (!child->isLocalFrame()) continue; LocalFrame* localFrame = toLocalFrame(child); if (localFrame->shouldThrottleRendering()) continue; localFrame->contentLayoutObject()->compositor()->assertNoUnresolvedDirtyBits(); } #endif }
bool InspectorOverlay::handleMouseMove(const PlatformMouseEvent& event) { if (!shouldSearchForNode()) return false; LocalFrame* frame = m_webViewImpl->mainFrameImpl()->frame(); if (!frame->view() || !frame->contentLayoutObject()) return false; Node* node = hoveredNodeForEvent(frame, event, event.shiftKey()); // Do not highlight within user agent shadow root unless requested. if (m_inspectMode != InspectorDOMAgent::SearchingForUAShadow) { ShadowRoot* shadowRoot = InspectorDOMAgent::userAgentShadowRoot(node); if (shadowRoot) node = shadowRoot->host(); } // Shadow roots don't have boxes - use host element instead. if (node && node->isShadowRoot()) node = node->parentOrShadowHostNode(); if (!node) return true; Node* eventTarget = event.shiftKey() ? hoveredNodeForEvent(m_webViewImpl->mainFrameImpl()->frame(), event, false) : nullptr; if (eventTarget == node) eventTarget = nullptr; if (node && m_inspectModeHighlightConfig) { m_hoveredNodeForInspectMode = node; m_domAgent->nodeHighlightedInOverlay(node); highlightNode(node, eventTarget, *m_inspectModeHighlightConfig, event.ctrlKey() || event.metaKey()); } return true; }
static void frameContentAsPlainText(size_t maxChars, LocalFrame* frame, StringBuilder& output) { Document* document = frame->document(); if (!document) return; if (!frame->view()) return; // Select the document body. if (document->body()) { const EphemeralRange range = EphemeralRange::rangeOfContents(*document->body()); // The text iterator will walk nodes giving us text. This is similar to // the plainText() function in core/editing/TextIterator.h, but we implement the maximum // size and also copy the results directly into a wstring, avoiding the // string conversion. for (TextIterator it(range.startPosition(), range.endPosition()); !it.atEnd(); it.advance()) { it.text().appendTextToStringBuilder(output, 0, maxChars - output.length()); if (output.length() >= maxChars) return; // Filled up the buffer. } } // The separator between frames when the frames are converted to plain text. const LChar frameSeparator[] = { '\n', '\n' }; const size_t frameSeparatorLength = WTF_ARRAY_LENGTH(frameSeparator); // Recursively walk the children. const FrameTree& frameTree = frame->tree(); for (Frame* curChild = frameTree.firstChild(); curChild; curChild = curChild->tree().nextSibling()) { if (!curChild->isLocalFrame()) continue; LocalFrame* curLocalChild = toLocalFrame(curChild); // Ignore the text of non-visible frames. LayoutView* contentLayoutObject = curLocalChild->contentLayoutObject(); LayoutPart* ownerLayoutObject = curLocalChild->ownerLayoutObject(); if (!contentLayoutObject || !contentLayoutObject->size().width() || !contentLayoutObject->size().height() || (contentLayoutObject->location().x() + contentLayoutObject->size().width() <= 0) || (contentLayoutObject->location().y() + contentLayoutObject->size().height() <= 0) || (ownerLayoutObject && ownerLayoutObject->style() && ownerLayoutObject->style()->visibility() != VISIBLE)) { continue; } // Make sure the frame separator won't fill up the buffer, and give up if // it will. The danger is if the separator will make the buffer longer than // maxChars. This will cause the computation above: // maxChars - output->size() // to be a negative number which will crash when the subframe is added. if (output.length() >= maxChars - frameSeparatorLength) return; output.append(frameSeparator, frameSeparatorLength); frameContentAsPlainText(maxChars, curLocalChild, output); if (output.length() >= maxChars) return; // Filled up the buffer. } }