Document* XSLStyleSheet::ownerDocument() { for (XSLStyleSheet* styleSheet = this; styleSheet; styleSheet = styleSheet->parentStyleSheet()) { Node* node = styleSheet->ownerNode(); if (node) return &node->document(); } return 0; }
void EditorClient::handleKeyboardEvent(KeyboardEvent* event) { Node* node = event->target()->toNode(); ASSERT(node); Frame* frame = node->document()->frame(); ASSERT(frame); const PlatformKeyboardEvent* platformEvent = event->keyEvent(); if (!platformEvent) return; if (keyboardEventHadCompositionResults(event)) return; KeyBindingTranslator::EventType type = event->type() == eventNames().keydownEvent ? KeyBindingTranslator::KeyDown : KeyBindingTranslator::KeyPress; m_keyBindingTranslator.getEditorCommandsForKeyEvent(platformEvent->gdkEventKey(), type, m_pendingEditorCommands); if (m_pendingEditorCommands.size() > 0) { // During RawKeyDown events if an editor command will insert text, defer // the insertion until the keypress event. We want keydown to bubble up // through the DOM first. if (platformEvent->type() == PlatformEvent::RawKeyDown) { if (executePendingEditorCommands(frame, false)) event->setDefaultHandled(); return; } // Only allow text insertion commands if the current node is editable. if (executePendingEditorCommands(frame, frame->editor()->canEdit())) { event->setDefaultHandled(); return; } } // Don't allow text insertion for nodes that cannot edit. if (!frame->editor()->canEdit()) return; // This is just a normal text insertion, so wait to execute the insertion // until a keypress event happens. This will ensure that the insertion will not // be reflected in the contents of the field until the keyup DOM event. if (event->type() != eventNames().keypressEvent) return; // Don't insert null or control characters as they can result in unexpected behaviour if (event->charCode() < ' ') return; // Don't insert anything if a modifier is pressed if (platformEvent->ctrlKey() || platformEvent->altKey()) return; if (frame->editor()->insertText(platformEvent->text(), event)) event->setDefaultHandled(); }
void SelectorDataList::executeQueryAll(Node& rootNode, Vector<RefPtr<Node> >& matchedElements) const { if (!canUseFastQuery(rootNode)) return executeSlowQueryAll(rootNode, matchedElements); ASSERT(m_selectors.size() == 1); ASSERT(m_selectors[0].selector); const CSSSelector* firstSelector = m_selectors[0].selector; if (!firstSelector->tagHistory()) { // Fast path for querySelectorAll('#id'), querySelectorAl('.foo'), and querySelectorAll('div'). switch (firstSelector->m_match) { case CSSSelector::Id: { if (rootNode.document().containsMultipleElementsWithId(firstSelector->value())) break; // Just the same as getElementById. Element* element = rootNode.treeScope().getElementById(firstSelector->value()); if (element && (isTreeScopeRoot(rootNode) || element->isDescendantOf(&rootNode))) matchedElements.append(element); return; } case CSSSelector::Class: return collectElementsByClassName(rootNode, firstSelector->value(), matchedElements); case CSSSelector::Tag: return collectElementsByTagName(rootNode, firstSelector->tagQName(), matchedElements); default: break; // If we need another fast path, add here. } } bool matchTraverseRoots; OwnPtr<SimpleNodeList> traverseRoots = findTraverseRoots(&rootNode, matchTraverseRoots); if (traverseRoots->isEmpty()) return; const SelectorData& selector = m_selectors[0]; if (matchTraverseRoots) { while (!traverseRoots->isEmpty()) { Node& node = *traverseRoots->next(); Element& element = toElement(node); if (selectorMatches(selector, element, rootNode)) matchedElements.append(&element); } return; } while (!traverseRoots->isEmpty()) { Node* traverseRoot = traverseRoots->next(); for (Element* element = ElementTraversal::firstWithin(traverseRoot); element; element = ElementTraversal::next(element, traverseRoot)) { if (selectorMatches(selector, *element, rootNode)) matchedElements.append(element); } } }
String createFullMarkup(const Range& range) { Node* node = range.startContainer(); if (!node) return String(); // FIXME: This is always "for interchange". Is that right? return documentTypeString(node->document()) + createMarkup(range, 0, AnnotateForInterchange); }
void WebEditorClient::handleKeyboardEvent(KeyboardEvent* event) { Node* node = event->target()->toNode(); ASSERT(node); Frame* frame = node->document().frame(); ASSERT(frame); const PlatformKeyboardEvent* platformEvent = event->keyEvent(); if (!platformEvent) return; // If this was an IME event don't do anything. if (platformEvent->windowsVirtualKeyCode() == VK_PROCESSKEY) return; Vector<WTF::String> pendingEditorCommands; getEditorCommandsForKeyEvent(event, pendingEditorCommands); if (!pendingEditorCommands.isEmpty()) { // During RawKeyDown events if an editor command will insert text, defer // the insertion until the keypress event. We want keydown to bubble up // through the DOM first. if (platformEvent->type() == PlatformEvent::RawKeyDown) { if (executePendingEditorCommands(frame, pendingEditorCommands, false)) event->setDefaultHandled(); return; } // Only allow text insertion commands if the current node is editable. if (executePendingEditorCommands(frame, pendingEditorCommands, frame->editor().canEdit())) { event->setDefaultHandled(); return; } } // Don't allow text insertion for nodes that cannot edit. if (!frame->editor().canEdit()) return; // This is just a normal text insertion, so wait to execute the insertion // until a keypress event happens. This will ensure that the insertion will not // be reflected in the contents of the field until the keyup DOM event. if (event->type() != eventNames().keypressEvent) return; // Don't insert null or control characters as they can result in unexpected behaviour if (event->charCode() < ' ') return; // Don't insert anything if a modifier is pressed if (platformEvent->ctrlKey() || platformEvent->altKey()) return; if (frame->editor().insertText(platformEvent->text(), event)) event->setDefaultHandled(); }
bool RenderTheme::isFocused(const RenderObject* o) const { Node* node = o->node(); if (!node) return false; Document* document = node->document(); Frame* frame = document->frame(); return node == document->focusedNode() && frame && frame->selection()->isFocusedAndActive(); }
void notifyChildNodeRemoved(ContainerNode& insertionPoint, Node& child) { if (!child.inDocument()) { if (is<ContainerNode>(child)) notifyNodeRemovedFromTree(insertionPoint, downcast<ContainerNode>(child)); return; } notifyNodeRemovedFromDocument(insertionPoint, child); child.document().notifyRemovePendingSheetIfNeeded(); }
// Rules of self-closure // 1. No elements in HTML documents use the self-closing syntax. // 2. Elements w/ children never self-close because they use a separate end tag. // 3. HTML elements which do not have a "forbidden" end tag will close with a separate end tag. // 4. Other elements self-close. bool MarkupAccumulator::shouldSelfClose(const Node& node) { if (!inXMLFragmentSerialization() && node.document().isHTMLDocument()) return false; if (node.hasChildNodes()) return false; if (node.isHTMLElement() && !elementCannotHaveEndTag(node)) return false; return true; }
void Document::updateRangesAfterNodeMovedToAnotherDocument(const Node& node) { ASSERT(node.document() != this); if (m_ranges.isEmpty()) return; AttachedRangeSet ranges = m_ranges; AttachedRangeSet::const_iterator end = ranges.end(); for (AttachedRangeSet::const_iterator it = ranges.begin(); it != end; ++it) (*it)->updateOwnerDocumentIfNeeded(); }
void EditorClientBlackBerry::handleKeyboardEvent(KeyboardEvent* event) { Node* node = event->target()->toNode(); ASSERT(node); Frame* frame = node->document()->frame(); ASSERT(frame); ASSERT(m_page->d->m_inputHandler); const PlatformKeyboardEvent* platformEvent = event->keyEvent(); if (!platformEvent) return; Node* start = frame->selection()->start().node(); if (!start) return; if (start->isContentEditable()) { // Text insertion commands should only be triggered from keypressEvent. // There is an assert guaranteeing this in // EventHandler::handleTextInputEvent. Note that windowsVirtualKeyCode // is not set for keypressEvent: special keys should have been already // handled in keydownEvent, which is called first. if (event->type() == eventNames().keypressEvent) { if (event->charCode() == '\r') { // \n has been converted to \r in PlatformKeyboardEventOlympia if (frame->editor()->command("InsertNewline").execute(event)) event->setDefaultHandled(); } else if (event->charCode() >= ' ' // Don't insert null or control characters as they can result in unexpected behaviour && !platformEvent->text().isEmpty()) { if (frame->editor()->insertText(platformEvent->text(), event)) event->setDefaultHandled(); } return; } if (event->type() != eventNames().keydownEvent) return; bool handledEvent = false; switch (platformEvent->windowsVirtualKeyCode()) { case VK_BACK: handledEvent = frame->editor()->deleteWithDirection(SelectionController::DirectionBackward, CharacterGranularity, false, true); break; case VK_DELETE: handledEvent = frame->editor()->deleteWithDirection(SelectionController::DirectionForward, CharacterGranularity, false, true); break; case VK_ESCAPE: handledEvent = frame->page()->focusController()->setFocusedNode(0, frame); break; } if (handledEvent) event->setDefaultHandled(); } }
Position VisiblePosition::canonicalPosition(const Position& position) { // FIXME (9535): Canonicalizing to the leftmost candidate means that if we're at a line wrap, we will // ask renderers to paint downstream carets for other renderers. // To fix this, we need to either a) add code to all paintCarets to pass the responsibility off to // the appropriate renderer for VisiblePosition's like these, or b) canonicalize to the rightmost candidate // unless the affinity is upstream. Node* node = position.node(); if (!node) return Position(); node->document()->updateLayoutIgnorePendingStylesheets(); Position candidate = position.upstream(); if (candidate.inRenderedContent()) return candidate; candidate = position.downstream(); if (candidate.inRenderedContent()) return candidate; // When neither upstream or downstream gets us to a candidate (upstream/downstream won't leave // blocks or enter new ones), we search forward and backward until we find one. Position next = nextVisiblePosition(position); Position prev = previousVisiblePosition(position); Node* nextNode = next.node(); Node* prevNode = prev.node(); // The new position must be in the same editable element. Enforce that first. Node* editingRoot = node->rootEditableElement(); // If the html element is editable, descending into its body will look like a descent // from non-editable to editable content since rootEditableElement stops at the body // even if the html element is editable. if (editingRoot && editingRoot->hasTagName(htmlTag)) return next.isNotNull() ? next : prev; bool prevIsInSameEditableElement = prevNode && prevNode->rootEditableElement() == editingRoot; bool nextIsInSameEditableElement = nextNode && nextNode->rootEditableElement() == editingRoot; if (prevIsInSameEditableElement && !nextIsInSameEditableElement) return prev; if (nextIsInSameEditableElement && !prevIsInSameEditableElement) return next; if (!nextIsInSameEditableElement && !prevIsInSameEditableElement) return Position(); // The new position should be in the same block flow element. Favor that. Node *originalBlock = node->enclosingBlockFlowElement(); bool nextIsOutsideOriginalBlock = !nextNode->isAncestor(originalBlock) && nextNode != originalBlock; bool prevIsOutsideOriginalBlock = !prevNode->isAncestor(originalBlock) && prevNode != originalBlock; if (nextIsOutsideOriginalBlock && !prevIsOutsideOriginalBlock) return prev; return next; }
bool LayoutTheme::isFocused(const LayoutObject& o) { Node* node = o.node(); if (!node) return false; node = node->focusDelegate(); Document& document = node->document(); LocalFrame* frame = document.frame(); return node == document.focusedElement() && node->focused() && node->shouldHaveFocusAppearance() && frame && frame->selection().isFocusedAndActive(); }
String createFullMarkup(const Node& node) { // FIXME: This is never "for interchange". Is that right? String markupString = createMarkup(node, IncludeNode, 0); Node::NodeType nodeType = node.nodeType(); if (nodeType != Node::DOCUMENT_NODE && nodeType != Node::DOCUMENT_TYPE_NODE) markupString = documentTypeString(node.document()) + markupString; return markupString; }
EventDispatcher::EventDispatcher(Node& node, PassRefPtrWillBeRawPtr<Event> event) : m_node(node) , m_event(event) #if ENABLE(ASSERT) , m_eventDispatched(false) #endif { ASSERT(m_event.get()); m_view = node.document().view(); m_event->initEventPath(*m_node); }
static void writeDebugInfo(LayoutObject* layoutObject, const AtomicString& output) { Node* node = layoutObject->node(); if (!node) return; if (node->isDocumentNode()) node = toDocument(node)->documentElement(); if (!node->isElementNode()) return; node->document().postTask(adoptPtr(new WriteDebugInfoTask(toElement(node), output))); }
Document* XSLStyleSheet::ownerDocument() { for (XSLStyleSheet* styleSheet = this; styleSheet; styleSheet = styleSheet->parentStyleSheet()) { if (styleSheet->m_ownerDocument) return styleSheet->m_ownerDocument.get(); Node* node = styleSheet->ownerNode(); if (node) return &node->document(); } return nullptr; }
bool RenderTheme::isFocused(const RenderObject* o) const { Node* node = o->node(); if (!node) return false; node = node->focusDelegate(); Document& document = node->document(); Frame* frame = document.frame(); return node == document.focusedElement() && node->shouldHaveFocusAppearance() && frame && frame->selection().isFocusedAndActive(); }
bool RenderTheme::isActive(const RenderObject* o) const { Node* node = o->node(); if (!node) return false; Page* page = node->document().page(); if (!page) return false; return page->focusController().isActive(); }
WebFrame* InjectedBundleHitTestResult::frame() const { Node* node = m_hitTestResult.innerNonSharedNode(); if (!node) return nullptr; Frame* frame = node->document().frame(); if (!frame) return nullptr; return WebFrame::fromCoreFrame(*frame); }
void AXObjectCache::nodeTextChangePlatformNotification(AccessibilityObject* object, AXTextChange textChange, unsigned offset, const String& text) { if (!object || text.isEmpty()) return; AccessibilityObject* parentObject = object->parentObjectUnignored(); if (!parentObject) return; AtkObject* wrapper = parentObject->wrapper(); if (!wrapper || !ATK_IS_TEXT(wrapper)) return; Node* node = object->node(); if (!node) return; // Ensure document's layout is up-to-date before using TextIterator. Document& document = node->document(); document.updateLayout(); // Select the right signal to be emitted CString detail; switch (textChange) { case AXTextInserted: detail = "text-insert"; break; case AXTextDeleted: detail = "text-remove"; break; case AXTextAttributesChanged: detail = "text-attributes-changed"; break; } String textToEmit = text; unsigned offsetToEmit = offset; // If the object we're emitting the signal from represents a // password field, we will emit the masked text. if (parentObject->isPasswordField()) { String maskedText = parentObject->passwordFieldValue(); textToEmit = maskedText.substring(offset, text.length()); } else { // Consider previous text objects that might be present for // the current accessibility object to ensure we emit the // right offset (e.g. multiline text areas). RefPtr<Range> range = Range::create(document, node->parentNode(), 0, node, 0); offsetToEmit = offset + TextIterator::rangeLength(range.get()); } g_signal_emit_by_name(wrapper, detail.data(), offsetToEmit, textToEmit.length(), textToEmit.utf8().data()); }
bool LayoutTheme::isActive(const LayoutObject& o) { Node* node = o.node(); if (!node) return false; Page* page = node->document().page(); if (!page) return false; return page->focusController().isActive(); }
WebFrame* InjectedBundleHitTestResult::frame() const { Node* node = m_hitTestResult.innerNonSharedNode(); if (!node) return 0; Frame* frame = node->document().frame(); if (!frame) return 0; WebFrameLoaderClient* webFrameLoaderClient = toWebFrameLoaderClient(frame->loader().client()); return webFrameLoaderClient ? webFrameLoaderClient->webFrame() : 0; }
void AnimationControllerPrivate::animationTimerFired(Timer<AnimationControllerPrivate>* timer) { // When the timer fires, all we do is call setChanged on all DOM nodes with running animations and then do an immediate // updateRendering. It will then call back to us with new information. bool animating = false; RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end(); for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it) { CompositeAnimation* compAnim = it->second; if (!compAnim->suspended() && compAnim->animating()) { animating = true; compAnim->setAnimating(false); Node* node = it->first->element(); ASSERT(!node || (node->document() && !node->document()->inPageCache())); node->setChanged(AnimationStyleChange); } } m_frame->document()->updateRendering(); updateAnimationTimer(); }
DragImageRef ClipboardWin::createDragImage(IntPoint& loc) const { HBITMAP result = 0; if (m_dragImage) { result = createDragImageFromImage(m_dragImage->image()); loc = m_dragLoc; } else if (m_dragImageElement) { Node* node = m_dragImageElement.get(); result = node->document()->frame()->nodeImage(node); loc = m_dragLoc; } return result; }
void SelectionController::nodeWillBeRemoved(Node *node) { if (isNone()) return; Node* base = m_sel.base().node(); Node* extent = m_sel.extent().node(); Node* start = m_sel.start().node(); Node* end = m_sel.end().node(); bool baseRemoved = node == base || (base && base->isAncestor(node)); bool extentRemoved = node == extent || (extent && extent->isAncestor(node)); bool startRemoved = node == start || (start && start->isAncestor(node)); bool endRemoved = node == end || (end && end->isAncestor(node)); bool clearRenderTreeSelection = false; bool clearDOMTreeSelection = false; if (startRemoved || endRemoved) { // FIXME: When endpoints are removed, we should just alter the selection, instead of blowing it away. clearRenderTreeSelection = true; clearDOMTreeSelection = true; } else if (baseRemoved || extentRemoved) { if (m_sel.isBaseFirst()) { m_sel.setBase(m_sel.start()); m_sel.setExtent(m_sel.end()); } else { m_sel.setBase(m_sel.start()); m_sel.setExtent(m_sel.end()); } // FIXME: This could be more efficient if we had an isNodeInRange function on Ranges. } else if (Range::compareBoundaryPoints(m_sel.start(), Position(node, 0)) == -1 && Range::compareBoundaryPoints(m_sel.end(), Position(node, 0)) == 1) { // If we did nothing here, when this node's renderer was destroyed, the rect that it // occupied would be invalidated, but, selection gaps that change as a result of // the removal wouldn't be invalidated. // FIXME: Don't do so much unnecessary invalidation. clearRenderTreeSelection = true; } if (clearRenderTreeSelection) { // FIXME (6498): This doesn't notify the editing delegate of a selection change. RefPtr<Document> document = start->document(); document->updateRendering(); if (RenderView* view = static_cast<RenderView*>(document->renderer())) view->clearSelection(); } if (clearDOMTreeSelection) setSelection(Selection()); }
void RenderNamedFlowThread::clearContentNodes() { for (NamedFlowContentNodes::iterator it = m_contentNodes.begin(); it != m_contentNodes.end(); ++it) { Node* contentNode = *it; ASSERT(contentNode && contentNode->isElementNode()); ASSERT(contentNode->inNamedFlow()); ASSERT(contentNode->document() == document()); contentNode->clearInNamedFlow(); } m_contentNodes.clear(); }
void EventPath::adjustForRelatedTarget(Node& target, EventTarget* relatedTarget) { if (!relatedTarget) return; Node* relatedNode = relatedTarget->toNode(); if (!relatedNode) return; if (target.document() != relatedNode->document()) return; if (!target.inDocument() || !relatedNode->inDocument()) return; RelatedTargetMap relatedNodeMap; buildRelatedNodeMap(*relatedNode, relatedNodeMap); for (const auto& treeScopeEventContext : m_treeScopeEventContexts) { EventTarget* adjustedRelatedTarget = findRelatedNode(treeScopeEventContext->treeScope(), relatedNodeMap); ASSERT(adjustedRelatedTarget); treeScopeEventContext.get()->setRelatedTarget(adjustedRelatedTarget); } shrinkIfNeeded(target, *relatedTarget); }
RefPtr<LegacyWebArchive> LegacyWebArchive::create(Node& node, std::function<bool (Frame&)> frameFilter) { Frame* frame = node.document().frame(); if (!frame) return create(); // If the page was loaded with javascript enabled, we don't want to archive <noscript> tags // In practice we don't actually know whether scripting was enabled when the page was originally loaded // but we can approximate that by checking if scripting is enabled right now. std::unique_ptr<Vector<QualifiedName>> tagNamesToFilter; if (frame->page() && frame->page()->settings().isScriptEnabled()) { tagNamesToFilter = std::make_unique<Vector<QualifiedName>>(); tagNamesToFilter->append(HTMLNames::noscriptTag); } Vector<Node*> nodeList; String markupString = createMarkup(node, IncludeNode, &nodeList, DoNotResolveURLs, tagNamesToFilter.get()); Node::NodeType nodeType = node.nodeType(); if (nodeType != Node::DOCUMENT_NODE && nodeType != Node::DOCUMENT_TYPE_NODE) markupString = documentTypeString(node.document()) + markupString; return create(markupString, *frame, nodeList, WTFMove(frameFilter)); }
String createMarkup(const Node& node, EChildrenOnly childrenOnly, Vector<Node*>* nodes, EAbsoluteURLs shouldResolveURLs, Vector<QualifiedName>* tagNamesToSkip, EFragmentSerialization fragmentSerialization) { HTMLElement* deleteButtonContainerElement = 0; #if ENABLE(DELETION_UI) if (Frame* frame = node.document().frame()) { deleteButtonContainerElement = frame->editor().deleteButtonController().containerElement(); if (node.isDescendantOf(deleteButtonContainerElement)) return emptyString(); } #endif MarkupAccumulator accumulator(nodes, shouldResolveURLs, 0, fragmentSerialization); return accumulator.serializeNodes(const_cast<Node&>(node), deleteButtonContainerElement, childrenOnly, tagNamesToSkip); }
void WebPage::findZoomableAreaForPoint(const IntPoint& point, const IntSize& area) { UNUSED_PARAM(area); Frame* mainframe = m_mainFrame->coreFrame(); HitTestResult result = mainframe->eventHandler().hitTestResultAtPoint(mainframe->view()->windowToContents(point), HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowShadowContent); Node* node = result.innerNode(); if (!node) return; IntRect zoomableArea = node->pixelSnappedBoundingBox(); while (true) { bool found = !node->isTextNode() && !node->isShadowRoot(); // No candidate found, bail out. if (!found && !node->parentNode()) return; // Candidate found, and it is a better candidate than its parent. // NB: A parent is considered a better candidate iff the node is // contained by it and it is the only child. if (found && (!node->parentNode() || node->parentNode()->childNodeCount() != 1)) break; node = node->parentNode(); zoomableArea.unite(node->pixelSnappedBoundingBox()); } if (node->document().frame() && node->document().frame()->view()) { const ScrollView* view = node->document().frame()->view(); zoomableArea = view->contentsToWindow(zoomableArea); } send(Messages::WebPageProxy::DidFindZoomableArea(point, zoomableArea)); }