AccessibilityObject* AccessibilityScrollView::parentObject() const { if (!m_scrollView || !m_scrollView->isFrameView()) return 0; AXObjectCache* cache = axObjectCache(); if (!cache) return nullptr; HTMLFrameOwnerElement* owner = toFrameView(m_scrollView)->frame().ownerElement(); if (owner && owner->renderer()) return cache->getOrCreate(owner); return 0; }
RenderPart* Frame::ownerRenderer() const { HTMLFrameOwnerElement* ownerElement = m_ownerElement; if (!ownerElement) return 0; RenderObject* object = ownerElement->renderer(); if (!object) return 0; // FIXME: If <object> is ever fixed to disassociate itself from frames // that it has started but canceled, then this can turn into an ASSERT // since m_ownerElement would be 0 when the load is canceled. // https://bugs.webkit.org/show_bug.cgi?id=18585 if (!object->isRenderPart()) return 0; return toRenderPart(object); }
RenderWidget* Frame::ownerRenderer() const { HTMLFrameOwnerElement* ownerElement = m_ownerElement; if (!ownerElement) return nullptr; auto* object = ownerElement->renderer(); if (!object) return nullptr; // FIXME: If <object> is ever fixed to disassociate itself from frames // that it has started but canceled, then this can turn into an ASSERT // since m_ownerElement would be 0 when the load is canceled. // https://bugs.webkit.org/show_bug.cgi?id=18585 if (!is<RenderWidget>(*object)) return nullptr; return downcast<RenderWidget>(object); }
Node* FocusController::findFocusableNodeDecendingDownIntoFrameDocument(FocusDirection direction, Node* node, KeyboardEvent* event) { // The node we found might be a HTMLFrameOwnerElement, so descend down the tree until we find either: // 1) a focusable node, or // 2) the deepest-nested HTMLFrameOwnerElement. while (node && node->isFrameOwnerElement()) { HTMLFrameOwnerElement* owner = static_cast<HTMLFrameOwnerElement*>(node); if (!owner->contentFrame()) break; Node* foundNode = findFocusableNode(direction, FocusNavigationScope::focusNavigationScopeOwnedByIFrame(owner), 0, event); if (!foundNode) break; ASSERT(node != foundNode); node = foundNode; } return node; }
void SerializerMarkupAccumulator::appendCustomAttributes(StringBuilder& out, Element* element, Namespaces* namespaces) { if (!element->isFrameOwnerElement()) return; HTMLFrameOwnerElement* frameOwner = static_cast<HTMLFrameOwnerElement*>(element); Frame* frame = frameOwner->contentFrame(); if (!frame) return; KURL url = frame->document()->url(); if (url.isValid() && !url.protocolIs("about")) return; // We need to give a fake location to blank frames so they can be referenced by the serialized frame. url = m_serializer->urlForBlankFrame(frame); appendAttribute(out, element, Attribute(frameOwnerURLAttributeName(*frameOwner), url.string()), namespaces); }
void FocusController::deepFindFocusableNodeInDirection(Node* container, Node* focusedNode, FocusDirection direction, KeyboardEvent* event, FocusCandidate& closestFocusCandidate) { ASSERT(container->hasTagName(frameTag) || container->hasTagName(iframeTag)); // Track if focusedNode is a descendant of the current container node being processed. bool descendantOfContainer = false; Node* firstChild = 0; // Iframe or Frame. if (container->hasTagName(frameTag) || container->hasTagName(iframeTag)) { HTMLFrameOwnerElement* owner = static_cast<HTMLFrameOwnerElement*>(container); if (!owner->contentFrame()) return; Document* innerDocument = owner->contentFrame()->document(); if (!innerDocument) return; descendantOfContainer = innerDocument == focusedNode->document(); firstChild = innerDocument->firstChild(); } if (descendantOfContainer) { findFocusableNodeInDirection(firstChild, focusedNode, direction, event, closestFocusCandidate); return; } // Check if the current container element itself is a good candidate // to move focus to. If it is, then we traverse its inner nodes. FocusCandidate candidateParent = FocusCandidate(container); distanceDataForNode(direction, focusedNode, candidateParent); // Bail out if distance is maximum. if (candidateParent.distance == maxDistance()) return; // FIXME: Consider alignment? if (candidateParent.distance < closestFocusCandidate.distance) findFocusableNodeInDirection(firstChild, focusedNode, direction, event, closestFocusCandidate, candidateParent); }
void LocalFrame::createView(const IntSize& viewportSize, const Color& backgroundColor, bool transparent, ScrollbarMode horizontalScrollbarMode, bool horizontalLock, ScrollbarMode verticalScrollbarMode, bool verticalLock) { ASSERT(this); ASSERT(page()); bool isMainFrame = this->isMainFrame(); if (isMainFrame && view()) view()->setParentVisible(false); setView(nullptr); RefPtr<FrameView> frameView; if (isMainFrame) { frameView = FrameView::create(this, viewportSize); // The layout size is set by WebViewImpl to support @viewport frameView->setLayoutSizeFixedToFrameSize(false); } else frameView = FrameView::create(this); frameView->setScrollbarModes(horizontalScrollbarMode, verticalScrollbarMode, horizontalLock, verticalLock); setView(frameView); frameView->updateBackgroundRecursively(backgroundColor, transparent); if (isMainFrame) frameView->setParentVisible(true); // FIXME: Not clear what the right thing for OOPI is here. if (ownerRenderer()) { HTMLFrameOwnerElement* owner = deprecatedLocalOwner(); ASSERT(owner); owner->setWidget(frameView); } if (HTMLFrameOwnerElement* owner = deprecatedLocalOwner()) view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff); }
bool RenderPart::requiresAcceleratedCompositing() const { // There are two general cases in which we can return true. First, if this is a plugin // renderer and the plugin has a layer, then we need a layer. Second, if this is // a renderer with a contentDocument and that document needs a layer, then we need // a layer. if (widget() && widget()->isPluginView() && toPluginView(widget())->platformLayer()) return true; if (!node() || !node()->isFrameOwnerElement()) return false; HTMLFrameOwnerElement* element = toFrameOwnerElement(node()); if (Document* contentDocument = element->contentDocument()) { if (RenderView* view = contentDocument->renderView()) return view->usesCompositing(); } return false; }
Element* TopDocumentRootScrollerController::findGlobalRootScrollerElement() { if (!topDocument()) return nullptr; DCHECK(topDocument()->rootScrollerController()); Element* element = topDocument()->rootScrollerController()->effectiveRootScroller(); while (element && element->isFrameOwnerElement()) { HTMLFrameOwnerElement* frameOwner = toHTMLFrameOwnerElement(element); DCHECK(frameOwner); Document* iframeDocument = frameOwner->contentDocument(); if (!iframeDocument) return element; DCHECK(iframeDocument->rootScrollerController()); element = iframeDocument->rootScrollerController()->effectiveRootScroller(); } return element; }
static Node* deepFocusableNode(FocusDirection direction, Node* node, KeyboardEvent* event) { // The node we found might be a HTMLFrameOwnerElement, so descend down the frame tree until we find either: // 1) a focusable node, or // 2) the deepest-nested HTMLFrameOwnerElement while (node && node->isFrameOwnerElement()) { HTMLFrameOwnerElement* owner = static_cast<HTMLFrameOwnerElement*>(node); if (!owner->contentFrame()) break; Document* document = owner->contentFrame()->document(); node = (direction == FocusDirectionForward) ? document->nextFocusableNode(0, event) : document->previousFocusableNode(0, event); if (!node) { node = owner; break; } } return node; }
Node* FocusController::findVerticallyFocusableNodeInRect(FocusDirection direction, Node* start, KeyboardEvent* event, const IntRect* rect) { #if PLATFORM(WKC) CRASH_IF_STACK_OVERFLOW(WKC_STACK_MARGIN_DEFAULT); #endif ASSERT(direction == FocusDirectionUp || direction == FocusDirectionDown); if (!start) return 0; Node* node = start; HTMLFrameOwnerElement* owner; Document* document; while (node) { if (!isNodeInSpecificRect(node, rect)) { node = getClosestNode(node, direction); continue; } owner = 0; if (node->isFrameOwnerElement()) { owner = static_cast<HTMLFrameOwnerElement*>(node); if (!owner->contentFrame()) { node = 0; break; } document = owner->contentFrame()->document(); if (direction == FocusDirectionUp) { node = findVerticallyFocusableNodeInRect(direction, document->lastChild(), event, rect); } else { node = findVerticallyFocusableNodeInRect(direction, document->firstChild(), event, rect); } if (node) break; node = getClosestNode(owner, direction); continue; } else if (isScrollableContainerNode(node) && !node->renderer()->isTextArea()) { Node* childNode = 0; if (direction == FocusDirectionUp) { childNode = findVerticallyFocusableNodeInRect(direction, node->lastChild(), event, rect); } else { ASSERT(direction == FocusDirectionDown); childNode = findVerticallyFocusableNodeInRect(direction, node->firstChild(), event, rect); } if (!childNode) { node = getClosestNode(node, direction, true); if (!node) break; } else { node = childNode; break; } } if (node->isFocusable() && !node->isFrameOwnerElement()) { break; } if (owner) { node = owner; } node = getClosestNode(node, direction); } return node; }
bool FocusController::advanceFocusInDocumentOrder(FocusDirection direction, KeyboardEvent* event, bool initialFocus) { Frame* frame = focusedOrMainFrame(); ASSERT(frame); Document* document = frame->document(); Node* currentNode = document->focusedNode(); // FIXME: Not quite correct when it comes to focus transitions leaving/entering the WebView itself bool caretBrowsing = frame->settings() && frame->settings()->caretBrowsingEnabled(); if (caretBrowsing && !currentNode) currentNode = frame->selection()->start().deprecatedNode(); document->updateLayoutIgnorePendingStylesheets(); RefPtr<Node> node = findFocusableNodeAcrossFocusScope(direction, FocusNavigationScope::focusNavigationScopeOf(currentNode ? currentNode : document), currentNode, event); if (!node) { // We didn't find a node to focus, so we should try to pass focus to Chrome. if (!initialFocus && m_page->chrome()->canTakeFocus(direction)) { document->setFocusedNode(0); setFocusedFrame(0); m_page->chrome()->takeFocus(direction); return true; } // Chrome doesn't want focus, so we should wrap focus. node = findFocusableNodeRecursively(direction, FocusNavigationScope::focusNavigationScopeOf(m_page->mainFrame()->document()), 0, event); node = findFocusableNodeDecendingDownIntoFrameDocument(direction, node.get(), event); if (!node) return false; } ASSERT(node); if (node == document->focusedNode()) // Focus wrapped around to the same node. return true; if (!node->isElementNode()) // FIXME: May need a way to focus a document here. return false; if (node->isFrameOwnerElement() && (!node->isPluginElement() || !node->isKeyboardFocusable(event))) { // We focus frames rather than frame owners. // FIXME: We should not focus frames that have no scrollbars, as focusing them isn't useful to the user. HTMLFrameOwnerElement* owner = static_cast<HTMLFrameOwnerElement*>(node.get()); if (!owner->contentFrame()) return false; document->setFocusedNode(0); setFocusedFrame(owner->contentFrame()); return true; } // FIXME: It would be nice to just be able to call setFocusedNode(node) here, but we can't do // that because some elements (e.g. HTMLInputElement and HTMLTextAreaElement) do extra work in // their focus() methods. Document* newDocument = node->document(); if (newDocument != document) // Focus is going away from this document, so clear the focused node. document->setFocusedNode(0); if (newDocument) setFocusedFrame(newDocument->frame()); if (caretBrowsing) { Position position = firstPositionInOrBeforeNode(node.get()); VisibleSelection newSelection(position, position, DOWNSTREAM); if (frame->selection()->shouldChangeSelection(newSelection)) frame->selection()->setSelection(newSelection); } static_cast<Element*>(node.get())->focus(false); return true; }
bool FocusController::advanceFocus(FocusDirection direction, KeyboardEvent* event, bool initialFocus) { Frame* frame = focusedOrMainFrame(); ASSERT(frame); Document* document = frame->document(); Node* currentNode = document->focusedNode(); // FIXME: Not quite correct when it comes to focus transitions leaving/entering the WebView itself bool caretBrowsing = focusedOrMainFrame()->settings()->caretBrowsingEnabled(); if (caretBrowsing && !currentNode) currentNode = frame->selection()->start().node(); document->updateLayoutIgnorePendingStylesheets(); Node* node = (direction == FocusDirectionForward) ? document->nextFocusableNode(currentNode, event) : document->previousFocusableNode(currentNode, event); // If there's no focusable node to advance to, move up the frame tree until we find one. while (!node && frame) { Frame* parentFrame = frame->tree()->parent(); if (!parentFrame) break; Document* parentDocument = parentFrame->document(); HTMLFrameOwnerElement* owner = frame->ownerElement(); if (!owner) break; node = (direction == FocusDirectionForward) ? parentDocument->nextFocusableNode(owner, event) : parentDocument->previousFocusableNode(owner, event); frame = parentFrame; } node = deepFocusableNode(direction, node, event); if (!node) { // We didn't find a node to focus, so we should try to pass focus to Chrome. if (!initialFocus && m_page->chrome()->canTakeFocus(direction)) { document->setFocusedNode(0); setFocusedFrame(0); m_page->chrome()->takeFocus(direction); return true; } // Chrome doesn't want focus, so we should wrap focus. Document* d = m_page->mainFrame()->document(); node = (direction == FocusDirectionForward) ? d->nextFocusableNode(0, event) : d->previousFocusableNode(0, event); node = deepFocusableNode(direction, node, event); if (!node) return false; } ASSERT(node); if (node == document->focusedNode()) // Focus wrapped around to the same node. return true; if (!node->isElementNode()) // FIXME: May need a way to focus a document here. return false; if (node->isFrameOwnerElement()) { // We focus frames rather than frame owners. // FIXME: We should not focus frames that have no scrollbars, as focusing them isn't useful to the user. HTMLFrameOwnerElement* owner = static_cast<HTMLFrameOwnerElement*>(node); if (!owner->contentFrame()) return false; document->setFocusedNode(0); setFocusedFrame(owner->contentFrame()); return true; } // FIXME: It would be nice to just be able to call setFocusedNode(node) here, but we can't do // that because some elements (e.g. HTMLInputElement and HTMLTextAreaElement) do extra work in // their focus() methods. Document* newDocument = node->document(); if (newDocument != document) // Focus is going away from this document, so clear the focused node. document->setFocusedNode(0); if (newDocument) setFocusedFrame(newDocument->frame()); if (caretBrowsing) { VisibleSelection newSelection(Position(node, 0), Position(node, 0), DOWNSTREAM); if (frame->shouldChangeSelection(newSelection)) frame->selection()->setSelection(newSelection); } static_cast<Element*>(node)->focus(false); return true; }
// intersectingRegions and remainingFingerRegion are all in main frame contents coordinates, // even on recursive calls of ::findIntersectingRegions. bool FatFingers::findIntersectingRegions(Document* document, Vector<IntersectingRegion>& intersectingRegions, IntRectRegion& remainingFingerRegion) { if (!document || !document->frame()->view()) return false; // The layout needs to be up-to-date to determine if a node is focusable. document->updateLayoutIgnorePendingStylesheets(); // Create fingerRect. IntPoint frameContentPos(document->frame()->view()->windowToContents(m_webPage->m_mainFrame->view()->contentsToWindow(m_contentPos))); IntRect viewportRect = m_webPage->mainFrame()->view()->visibleContentRect(); // Ensure the frameContentPos is inside the viewport. frameContentPos = Platform::pointClampedToRect(frameContentPos, viewportRect); #if DEBUG_FAT_FINGERS IntRect fingerRect(fingerRectForPoint(frameContentPos)); Platform::IntRect screenFingerRect = m_webPage->mapToTransformed(fingerRect); Platform::logAlways(Platform::LogLevelInfo, "fat finger rect now %s", screenFingerRect.toString().c_str()); // only record the first finger rect if (document == m_webPage->m_mainFrame->document()) m_debugFatFingerRect = m_webPage->mapToTransformed(m_webPage->mapFromContentsToViewport(fingerRect)); #endif bool foundOne = false; RenderLayer* lowestPositionedEnclosingLayerSoFar = 0; // Iterate over the list of nodes (and subrects of nodes where possible), for each saving the // intersection of the bounding box with the finger rect. ListHashSet<RefPtr<Node> > intersectedNodes; getNodesFromRect(document, frameContentPos, intersectedNodes); ListHashSet<RefPtr<Node> >::const_iterator it = intersectedNodes.begin(); ListHashSet<RefPtr<Node> >::const_iterator end = intersectedNodes.end(); for ( ; it != end; ++it) { Node* curNode = (*it).get(); if (!curNode || !curNode->renderer()) continue; if (remainingFingerRegion.isEmpty()) break; bool isElement = curNode->isElementNode(); if (isElement && isValidFrameOwner(toElement(curNode))) { HTMLFrameOwnerElement* owner = static_cast<HTMLFrameOwnerElement*>(curNode); Document* childDocument = owner && owner->contentFrame() ? owner->contentFrame()->document() : 0; if (!childDocument) continue; ASSERT(childDocument->frame()->view()); foundOne |= findIntersectingRegions(childDocument, intersectingRegions, remainingFingerRegion); } else if (isElement && m_targetType == ClickableElement) { foundOne |= checkForClickableElement(toElement(curNode), intersectingRegions, remainingFingerRegion, lowestPositionedEnclosingLayerSoFar); } else if (m_targetType == Text) foundOne |= checkForText(curNode, intersectingRegions, remainingFingerRegion); } return foundOne; }
static JSValueRef addSourceToFrame(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* /*exception*/) { JSValueRef undefined = JSValueMakeUndefined(ctx); InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject)); if (argumentCount < 2 || !controller) return undefined; JSValueRef identifierValue = arguments[0]; if (!JSValueIsNumber(ctx, identifierValue)) return undefined; unsigned long identifier = static_cast<unsigned long>(JSValueToNumber(ctx, identifierValue, 0)); RefPtr<InspectorResource> resource = controller->resources().get(identifier); ASSERT(resource); if (!resource) return undefined; RefPtr<SharedBuffer> buffer; if (resource->requestURL == resource->loader->requestURL()) buffer = resource->loader->mainResourceData(); else { FrameLoader* frameLoader = resource->loader->frameLoader(); if (!frameLoader) return undefined; Document* doc = frameLoader->frame()->document(); if (!doc) return undefined; CachedResource* cachedResource = doc->docLoader()->cachedResource(resource->requestURL.url()); if (!cachedResource) return undefined; buffer = cachedResource->data(); } if (!buffer) return undefined; String textEncodingName = resource->loader->overrideEncoding(); if (!textEncodingName) textEncodingName = resource->textEncodingName; TextEncoding encoding(textEncodingName); if (!encoding.isValid()) encoding = WindowsLatin1Encoding(); String sourceString = encoding.decode(buffer->data(), buffer->size()); Node* node = toNode(toJS(arguments[1])); ASSERT(node); if (!node) return undefined; if (!node->attached()) { ASSERT_NOT_REACHED(); return undefined; } ASSERT(node->isElementNode()); if (!node->isElementNode()) return undefined; Element* element = static_cast<Element*>(node); ASSERT(element->isFrameOwnerElement()); if (!element->isFrameOwnerElement()) return undefined; HTMLFrameOwnerElement* frameOwner = static_cast<HTMLFrameOwnerElement*>(element); ASSERT(frameOwner->contentFrame()); if (!frameOwner->contentFrame()) return undefined; FrameLoader* loader = frameOwner->contentFrame()->loader(); loader->setResponseMIMEType(resource->mimeType); loader->begin(); loader->write(sourceString); loader->end(); return undefined; }
bool WebFrame::swap(WebFrame* frame) { using std::swap; RefPtrWillBeRawPtr<Frame> oldFrame = toCoreFrame(this); // All child frames must be detached first. oldFrame->detachChildren(); // If the frame has been detached during detaching its children, return // immediately. // FIXME: There is no unit test for this condition, so one needs to be // written. if (!oldFrame->host()) return false; if (m_parent) { if (m_parent->m_firstChild == this) m_parent->m_firstChild = frame; if (m_parent->m_lastChild == this) m_parent->m_lastChild = frame; swap(m_parent, frame->m_parent); } if (m_previousSibling) { m_previousSibling->m_nextSibling = frame; swap(m_previousSibling, frame->m_previousSibling); } if (m_nextSibling) { m_nextSibling->m_previousSibling = frame; swap(m_nextSibling, frame->m_nextSibling); } if (m_opener) { m_opener->m_openedFrameTracker->remove(this); m_opener->m_openedFrameTracker->add(frame); swap(m_opener, frame->m_opener); } if (!m_openedFrameTracker->isEmpty()) { m_openedFrameTracker->updateOpener(frame); frame->m_openedFrameTracker.reset(m_openedFrameTracker.release()); } // Finally, clone the state of the current Frame into one matching // the type of the passed in WebFrame. // FIXME: This is a bit clunky; this results in pointless decrements and // increments of connected subframes. FrameOwner* owner = oldFrame->owner(); oldFrame->disconnectOwnerElement(); if (Frame* newFrame = toCoreFrame(frame)) { ASSERT(owner == newFrame->owner()); if (owner->isLocal()) { HTMLFrameOwnerElement* ownerElement = toHTMLFrameOwnerElement(owner); ownerElement->setContentFrame(*newFrame); if (newFrame->isLocalFrame()) ownerElement->setWidget(toLocalFrame(newFrame)->view()); } } else if (frame->isWebLocalFrame()) { toWebLocalFrameImpl(frame)->initializeCoreFrame(oldFrame->host(), owner, oldFrame->tree().name(), nullAtom); } else { toWebRemoteFrameImpl(frame)->initializeCoreFrame(oldFrame->host(), owner, oldFrame->tree().name()); } return true; }