static Node*
findLastFocusableNode(Frame* frame, const IntRect* specificRect)
{
#if PLATFORM(WKC)
    CRASH_IF_STACK_OVERFLOW(WKC_STACK_MARGIN_DEFAULT);
#endif
    Node* node = frame->document()->lastChild();
    while (node) {
        if (!isNodeInSpecificRect(node, specificRect)) {
            node = node->traversePreviousNodePostOrder();
            continue;
        }
        if (node->isFrameOwnerElement()) {
            HTMLFrameOwnerElement* owner = static_cast<HTMLFrameOwnerElement*>(node);
            if (owner->contentFrame()) {
                node = findLastFocusableNode(owner->contentFrame(), specificRect);
                if (node)
                    break;
                node = owner;
            }
        } else if (isScrollableContainerNode(node) && !node->renderer()->isTextArea()) {
            node = node->lastChild();
        }
        if (node->isFocusable() && !node->isFrameOwnerElement()) {
            break;
        }
        node = node->traversePreviousNodePostOrder();
    }

    if (node) {
        return node->isFocusable() ? node : 0;
    }
    return 0;
}
bool InspectorBackend::addSourceToFrame(const String& mimeType, const String& source, Node* frameNode)
{
    ASSERT_ARG(frameNode, frameNode);

    if (!frameNode)
        return false;

    if (!frameNode->attached()) {
        ASSERT_NOT_REACHED();
        return false;
    }

    ASSERT(frameNode->isElementNode());
    if (!frameNode->isElementNode())
        return false;

    Element* element = static_cast<Element*>(frameNode);
    ASSERT(element->isFrameOwnerElement());
    if (!element->isFrameOwnerElement())
        return false;

    HTMLFrameOwnerElement* frameOwner = static_cast<HTMLFrameOwnerElement*>(element);
    ASSERT(frameOwner->contentFrame());
    if (!frameOwner->contentFrame())
        return false;

    FrameLoader* loader = frameOwner->contentFrame()->loader();

    loader->setResponseMIMEType(mimeType);
    loader->begin();
    loader->write(source);
    loader->end();

    return true;
}
Beispiel #3
0
// intersectingRegions and remainingFingerRegion are all in main frame contents coordinates,
// even on recursive calls of ::findIntersectingRegions.
bool FatFingers::findIntersectingRegions(Document* document,
                                         Vector<IntersectingRegion>& intersectingRegions, Platform::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)));

#if DEBUG_FAT_FINGERS
    IntRect fingerRect(fingerRectForPoint(frameContentPos));
    IntRect screenFingerRect = m_webPage->mapToTransformed(fingerRect);
    log(LogLevelInfo, "fat finger rect now %d, %d, %d, %d", screenFingerRect.x(), screenFingerRect.y(), screenFingerRect.width(), screenFingerRect.height());

    // 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;
}
Node* FocusController::deepFocusableNode(FocusDirection direction, Node* node, KeyboardEvent* event)
{
    // The node we found might be a HTMLFrameOwnerElement or a shadow host, so descend down the tree until we find either:
    // 1) a focusable node, or
    // 2) the deepest-nested HTMLFrameOwnerElement or shadow host.
    while (isTreeScopeOwner(node)) {
        Node* foundNode;
        if (node->isFrameOwnerElement()) {
            HTMLFrameOwnerElement* owner = static_cast<HTMLFrameOwnerElement*>(node);
            if (!owner->contentFrame())
                break;
            Document* document = owner->contentFrame()->document();
            foundNode = findFocusableNode(direction, document, 0, event);
        } else {
            ASSERT(shadowRoot(node));
            // FIXME: Some elements (e.g. HTMLInputElement and HTMLTextAreaElement) do extra work in their focus() methods.
            // Skipping these elements is the safest fix until we find a better way.
            if (node->hasTagName(inputTag) || node->hasTagName(textareaTag))
                break;
            foundNode = findFocusableNode(direction, shadowRoot(node), 0, event);
        }
        if (!foundNode)
            break;
        ASSERT(node != foundNode);
        node = foundNode;
    }
    return node;
}
Beispiel #5
0
void FocusController::deepFindFocusableNodeInDirection(Node* focusedNode, Node* candidate, FocusDirection direction, KeyboardEvent* event, FocusCandidate& closestFocusCandidate)
{
    HTMLFrameOwnerElement* owner = static_cast<HTMLFrameOwnerElement*>(candidate);
    if (!owner->contentFrame())
        return;

    Document* innerDocument = owner->contentFrame()->document();
    if (!innerDocument)
        return;

    if (innerDocument == focusedNode->document())
        findFocusableNodeInDirection(innerDocument, focusedNode, direction, event, closestFocusCandidate);
    else {
        // Check if the current {i}frame element itself is a good candidate
        // to move focus to. If it is, then we traverse its inner nodes.
        // Lets pass a copy of the best candidate, to not get fooled by a
        // frame without focusable elements.
        FocusCandidate focusCandidateCopy = closestFocusCandidate;
        long long distance = distanceInDirection(focusedNode, candidate, direction, focusCandidateCopy);
        if (distance < focusCandidateCopy.distance) {
            focusCandidateCopy.parentAlignment = focusCandidateCopy.alignment;
            focusCandidateCopy.parentDistance = distance;

            findFocusableNodeInDirection(innerDocument, focusedNode, direction, event, focusCandidateCopy);

            // If we really have an inner closer focus candidate node, take it.
            if (closestFocusCandidate.node != focusCandidateCopy.node)
                closestFocusCandidate = focusCandidateCopy;
        }
    }
}
void FocusController::findHorizontallyFocusableNodeInRect(FocusDirection direction, Node* start, KeyboardEvent* event, const IntRect* rect, Node** candidateNode, IntRect& candidateNodeRect)
{
#if PLATFORM(WKC)
    CRASH_IF_STACK_OVERFLOW(WKC_STACK_MARGIN_DEFAULT);
#endif
//    ASSERT(direction == FocusDirectionLeft || direction == FocusDirectionRight);
    if (!start)
        return ;

    Node* node = start;
    HTMLFrameOwnerElement* owner;
    Document* document;
    IntRect nodeRect;

    while (node) {
        if (!isNodeInSpecificRect(node, rect)) {
            node = getClosestNode(node, direction);
            continue;
        }
        owner = 0;
        if (node->isFrameOwnerElement()) {
            owner = static_cast<HTMLFrameOwnerElement*>(node);
            if (!owner->contentFrame()) {
                *candidateNode = 0;
                return;
            }
            document = owner->contentFrame()->document();
            findHorizontallyFocusableNodeInRect(direction, document, event, rect, candidateNode, candidateNodeRect);
        } else if (isScrollableContainerNode(node) && !node->renderer()->isTextArea()) {
            findHorizontallyFocusableNodeInRect(direction, node->firstChild(), event, rect, candidateNode, candidateNodeRect);
        } else {
            if (node->isFocusable() && !node->isFrameOwnerElement()) {
                nodeRect = node->renderer()->absoluteBoundingBoxRect();
                FrameView* frameView = node->document()->view();
                if (!frameView) {
                    *candidateNode = 0;
                    return;
                }                
                nodeRect = frameView->contentsToWindow(nodeRect);
                nodeRect.intersect(*rect);
                if (!nodeRect.isEmpty()) {
                    if (candidateNodeRect.isEmpty()) {
                        *candidateNode = node;
                        candidateNodeRect = nodeRect;
                    }
                    if (direction == FocusDirectionRight && candidateNodeRect.x() > nodeRect.x()) {
                        *candidateNode = node;
                        candidateNodeRect = nodeRect;
                    } else if (direction == FocusDirectionLeft && candidateNodeRect.x() < nodeRect.x()) {
                        *candidateNode = node;
                        candidateNodeRect = nodeRect;
                    }
                }
            }
        }
        node = getClosestNode(node, direction);
    }
}
Beispiel #7
0
void FocusController::deepFindFocusableNodeInDirection(Node* container, Node* focusedNode,
                                                       FocusDirection direction, KeyboardEvent* event,
                                                       FocusCandidate& closest)
{
    ASSERT(container->hasTagName(frameTag)
        || container->hasTagName(iframeTag)
        || isScrollableContainerNode(container));

    // 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 = isNodeDeepDescendantOfDocument(focusedNode, innerDocument);
        firstChild = innerDocument->firstChild();

    // Scrollable block elements (e.g. <div>, etc)
    } else if (isScrollableContainerNode(container)) {

        firstChild = container->firstChild();
        descendantOfContainer = focusedNode->isDescendantOf(container);
    }

    if (descendantOfContainer) {
        findFocusableNodeInDirection(firstChild, focusedNode, direction, event, closest);
        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 < closest.distance)
        findFocusableNodeInDirection(firstChild, focusedNode, direction, event, closest, candidateParent);
}
Beispiel #8
0
void LocalFrame::createView(const IntSize& viewportSize,
                            const Color& backgroundColor,
                            bool transparent,
                            ScrollbarMode horizontalScrollbarMode,
                            bool horizontalLock,
                            ScrollbarMode verticalScrollbarMode,
                            bool verticalLock) {
  ASSERT(this);
  ASSERT(page());

  bool isLocalRoot = this->isLocalRoot();

  if (isLocalRoot && view())
    view()->setParentVisible(false);

  setView(nullptr);

  FrameView* frameView = nullptr;
  if (isLocalRoot) {
    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 (isLocalRoot)
    frameView->setParentVisible(true);

  // FIXME: Not clear what the right thing for OOPI is here.
  if (!ownerLayoutItem().isNull()) {
    HTMLFrameOwnerElement* owner = deprecatedLocalOwner();
    ASSERT(owner);
    // FIXME: OOPI might lead to us temporarily lying to a frame and telling it
    // that it's owned by a FrameOwner that knows nothing about it. If we're
    // lying to this frame, don't let it clobber the existing widget.
    if (owner->contentFrame() == this)
      owner->setWidget(frameView);
  }

  if (owner())
    view()->setCanHaveScrollbars(owner()->scrollingMode() !=
                                 ScrollbarAlwaysOff);
}
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;
}
bool LayoutPart::requiresAcceleratedCompositing() const
{
    // There are two general cases in which we can return true. First, if this is a plugin
    // LayoutObject and the plugin has a layer, then we need a layer. Second, if this is
    // a LayoutObject 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 = toHTMLFrameOwnerElement(node());
    if (element->contentFrame() && element->contentFrame()->isRemoteFrame())
        return true;

    if (Document* contentDocument = element->contentDocument()) {
        if (LayoutView* view = contentDocument->layoutView())
            return view->usesCompositing();
    }

    return false;
}
Beispiel #11
0
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;
}
Beispiel #12
0
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);
}
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;
}
Beispiel #14
0
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;
}
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;
}