⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 245872 in webkit


Ignore:
Timestamp:
May 29, 2019, 3:07:29 PM (7 years ago)
Author:
commit-queue@webkit.org
Message:

[iOS] WebPage::positionInformation() may set InteractionInformationAtPosition.isImage to true but leave image unset
https://bugs.webkit.org/show_bug.cgi?id=198202

Patch by Said Abou-Hallawa <sabouhallawa@apple.com> on 2019-05-29
Reviewed by Tim Horton.

Source/WebKit:

r192037 added the flags isLink and isImage to InteractionInformationAtPosition.
It also made WebPage::positionInformation() set isImage to true but before
ensuring there is a valid image at the position.

Safari WebKit additions assumes if isImage is true then the image has to
hold a valid ShareableBitmap pointer. Since WebPage::positionInformation()
is the only place that sets isImage, the fix is to set isImage to true
only after passing all the image validation checks.

Since WebPage::positionInformation() is a little bit difficult to read
(182 lines), It was re-factored by splitting it to static functions.

  • WebProcess/WebPage/ios/WebPageIOS.mm:

(WebKit::focusedElementPositionInformation):
(WebKit::linkIndicatorPositionInformation):
(WebKit::dataDetectorLinkPositionInformation):
(WebKit::imagePositionInformation):
(WebKit::boundsPositionInformation):
(WebKit::elementPositionInformation):
(WebKit::selectionPositionInformation):
(WebKit::textInteractionPositionInformation):
(WebKit::WebPage::positionInformation):

Tools:

The new test ensures InteractionInformationAtPosition::isImage will not
be to true for a broken image.

  • TestWebKitAPI/Tests/WebKitCocoa/WKRequestActivatedElementInfo.mm:

(TestWebKitAPI::TEST):

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r245868 r245872  
     12019-05-29  Said Abou-Hallawa  <sabouhallawa@apple.com>
     2
     3        [iOS] WebPage::positionInformation() may set InteractionInformationAtPosition.isImage to true but leave image unset
     4        https://bugs.webkit.org/show_bug.cgi?id=198202
     5
     6        Reviewed by Tim Horton.
     7
     8        r192037 added the flags isLink and isImage to InteractionInformationAtPosition.
     9        It also made WebPage::positionInformation() set isImage to true but before
     10        ensuring there is a valid image at the position.
     11
     12        Safari WebKit additions assumes if isImage is true then the image has to
     13        hold a valid ShareableBitmap pointer. Since WebPage::positionInformation()
     14        is the only place that sets isImage, the fix is to set isImage to true
     15        only  after passing all the image validation checks.
     16
     17        Since WebPage::positionInformation() is a little bit difficult to read
     18        (182 lines), It was re-factored by splitting it to static functions.
     19
     20        * WebProcess/WebPage/ios/WebPageIOS.mm:
     21        (WebKit::focusedElementPositionInformation):
     22        (WebKit::linkIndicatorPositionInformation):
     23        (WebKit::dataDetectorLinkPositionInformation):
     24        (WebKit::imagePositionInformation):
     25        (WebKit::boundsPositionInformation):
     26        (WebKit::elementPositionInformation):
     27        (WebKit::selectionPositionInformation):
     28        (WebKit::textInteractionPositionInformation):
     29        (WebKit::WebPage::positionInformation):
     30
    1312019-05-29  Geoffrey Garen  <ggaren@apple.com>
    232
  • trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm

    r245803 r245872  
    24982498        reply(WTFMove(information));
    24992499}
     2500   
     2501static void focusedElementPositionInformation(WebPage& page, Element& focusedElement, const InteractionInformationRequest& request, InteractionInformationAtPosition& info)
     2502{
     2503    const Frame& frame = page.corePage()->focusController().focusedOrMainFrame();
     2504    if (!frame.editor().hasComposition())
     2505        return;
     2506
     2507    const uint32_t kHitAreaWidth = 66;
     2508    const uint32_t kHitAreaHeight = 66;
     2509    FrameView& view = *frame.view();
     2510    IntPoint adjustedPoint(view.rootViewToContents(request.point));
     2511    IntPoint constrainedPoint = constrainPoint(adjustedPoint, frame, focusedElement);
     2512    VisiblePosition position = frame.visiblePositionForPoint(constrainedPoint);
     2513
     2514    RefPtr<Range> compositionRange = frame.editor().compositionRange();
     2515    if (position < compositionRange->startPosition())
     2516        position = compositionRange->startPosition();
     2517    else if (position > compositionRange->endPosition())
     2518        position = compositionRange->endPosition();
     2519    IntRect caretRect = view.contentsToRootView(position.absoluteCaretBounds());
     2520    float deltaX = abs(caretRect.x() + (caretRect.width() / 2) - request.point.x());
     2521    float deltaYFromTheTop = abs(caretRect.y() - request.point.y());
     2522    float deltaYFromTheBottom = abs(caretRect.y() + caretRect.height() - request.point.y());
     2523
     2524    info.isNearMarkedText = !(deltaX > kHitAreaWidth || deltaYFromTheTop > kHitAreaHeight || deltaYFromTheBottom > kHitAreaHeight);
     2525}
     2526
     2527static void linkIndicatorPositionInformation(WebPage& page, Element& element, Element& linkElement, const InteractionInformationRequest& request, InteractionInformationAtPosition& info)
     2528{
     2529    if (!request.includeLinkIndicator)
     2530        return;
     2531
     2532    auto linkRange = rangeOfContents(linkElement);
     2533    float deviceScaleFactor = page.corePage()->deviceScaleFactor();
     2534    const float marginInPoints = 4;
     2535
     2536    auto textIndicator = TextIndicator::createWithRange(linkRange.get(),
     2537        TextIndicatorOptionTightlyFitContent | TextIndicatorOptionRespectTextColor | TextIndicatorOptionPaintBackgrounds |
     2538        TextIndicatorOptionUseBoundingRectAndPaintAllContentForComplexRanges | TextIndicatorOptionIncludeMarginIfRangeMatchesSelection,
     2539        TextIndicatorPresentationTransition::None, FloatSize(marginInPoints * deviceScaleFactor, marginInPoints * deviceScaleFactor));
     2540       
     2541    if (textIndicator)
     2542        info.linkIndicator = textIndicator->data();
     2543}
     2544   
     2545#if ENABLE(DATA_DETECTION)
     2546static void dataDetectorLinkPositionInformation(Element& element, InteractionInformationAtPosition& info)
     2547{
     2548    if (!DataDetection::isDataDetectorLink(element))
     2549        return;
     2550   
     2551    info.isDataDetectorLink = true;
     2552    const int dataDetectionExtendedContextLength = 350;
     2553    info.dataDetectorIdentifier = DataDetection::dataDetectorIdentifier(element);
     2554    info.dataDetectorResults = element.document().frame()->dataDetectionResults();
     2555
     2556    if (!DataDetection::requiresExtendedContext(element))
     2557        return;
     2558   
     2559    auto linkRange = Range::create(element.document());
     2560    linkRange->selectNodeContents(element);
     2561    info.textBefore = plainTextReplacingNoBreakSpace(rangeExpandedByCharactersInDirectionAtWordBoundary(linkRange->startPosition(),
     2562        dataDetectionExtendedContextLength, DirectionBackward).get(), TextIteratorDefaultBehavior, true);
     2563    info.textAfter = plainTextReplacingNoBreakSpace(rangeExpandedByCharactersInDirectionAtWordBoundary(linkRange->endPosition(),
     2564        dataDetectionExtendedContextLength, DirectionForward).get(), TextIteratorDefaultBehavior, true);
     2565}
     2566#endif
     2567
     2568static void imagePositionInformation(WebPage& page, Element& element, const InteractionInformationRequest& request, InteractionInformationAtPosition& info)
     2569{
     2570    auto& renderImage = downcast<RenderImage>(*(element.renderer()));
     2571    if (!renderImage.cachedImage() || renderImage.cachedImage()->errorOccurred())
     2572        return;
     2573
     2574    auto* image = renderImage.cachedImage()->imageForRenderer(&renderImage);
     2575    if (!image || image->width() <= 1 || image->height() <= 1)
     2576        return;
     2577
     2578    info.isImage = true;
     2579    info.imageURL = element.document().completeURL(renderImage.cachedImage()->url());
     2580    info.isAnimatedImage = image->isAnimated();
     2581
     2582    if (!request.includeSnapshot)
     2583        return;
     2584
     2585    FloatSize screenSizeInPixels = screenSize();
     2586    screenSizeInPixels.scale(page.corePage()->deviceScaleFactor());
     2587    FloatSize scaledSize = largestRectWithAspectRatioInsideRect(image->size().width() / image->size().height(), FloatRect(0, 0, screenSizeInPixels.width(), screenSizeInPixels.height())).size();
     2588    FloatSize bitmapSize = scaledSize.width() < image->size().width() ? scaledSize : image->size();
     2589    // FIXME: Only select ExtendedColor on images known to need wide gamut
     2590    ShareableBitmap::Configuration bitmapConfiguration;
     2591    bitmapConfiguration.colorSpace.cgColorSpace = screenColorSpace(page.corePage()->mainFrame().view());
     2592
     2593    auto sharedBitmap = ShareableBitmap::createShareable(IntSize(bitmapSize), bitmapConfiguration);
     2594    if (!sharedBitmap)
     2595        return;
     2596
     2597    auto graphicsContext = sharedBitmap->createGraphicsContext();
     2598    if (!graphicsContext)
     2599        return;
     2600
     2601    graphicsContext->drawImage(*image, FloatRect(0, 0, bitmapSize.width(), bitmapSize.height()));
     2602    info.image = sharedBitmap;
     2603}
     2604
     2605static void boundsPositionInformation(RenderElement& renderer, InteractionInformationAtPosition& info)
     2606{
     2607    if (renderer.isRenderImage())
     2608        info.bounds = downcast<RenderImage>(renderer).absoluteContentQuad().enclosingBoundingBox();
     2609    else
     2610        info.bounds = renderer.absoluteBoundingBoxRect();
     2611
     2612    if (!renderer.document().frame()->isMainFrame()) {
     2613        FrameView *view = renderer.document().frame()->view();
     2614        info.bounds = view->contentsToRootView(info.bounds);
     2615    }
     2616}
     2617
     2618static void elementPositionInformation(WebPage& page, Element& element, const InteractionInformationRequest& request, InteractionInformationAtPosition& info)
     2619{
     2620    Element* linkElement = nullptr;
     2621    if (element.renderer() && element.renderer()->isRenderImage())
     2622        linkElement = containingLinkElement(&element);
     2623    else if (element.isLink())
     2624        linkElement = &element;
     2625
     2626    info.isElement = true;
     2627    info.idAttribute = element.getIdAttribute();
     2628
     2629    info.title = element.attributeWithoutSynchronization(HTMLNames::titleAttr).string();
     2630    if (linkElement && info.title.isEmpty())
     2631        info.title = element.innerText();
     2632    if (element.renderer())
     2633        info.touchCalloutEnabled = element.renderer()->style().touchCalloutEnabled();
     2634
     2635    if (linkElement) {
     2636        info.isLink = true;
     2637        info.url = linkElement->document().completeURL(stripLeadingAndTrailingHTMLSpaces(linkElement->getAttribute(HTMLNames::hrefAttr)));
     2638
     2639        linkIndicatorPositionInformation(page, element, *linkElement, request, info);
     2640#if ENABLE(DATA_DETECTION)
     2641        dataDetectorLinkPositionInformation(element, info);
     2642#endif
     2643    }
     2644
     2645    if (auto* renderer = element.renderer()) {
     2646        if (renderer->isRenderImage())
     2647            imagePositionInformation(page, element, request, info);
     2648        boundsPositionInformation(*renderer, info);
     2649    }
     2650}
     2651   
     2652static void selectionPositionInformation(WebPage& page, const InteractionInformationRequest& request, InteractionInformationAtPosition& info)
     2653{
     2654    HitTestResult result = page.corePage()->mainFrame().eventHandler().hitTestResultAtPoint(request.point, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::DisallowUserAgentShadowContent | HitTestRequest::AllowChildFrameContent);
     2655    Node* hitNode = result.innerNode();
     2656
     2657    // Hit test could return HTMLHtmlElement that has no renderer, if the body is smaller than the document.
     2658    if (!hitNode || !hitNode->renderer())
     2659        return;
     2660
     2661    RenderObject* renderer = hitNode->renderer();
     2662    if (!request.readonly)
     2663        page.corePage()->focusController().setFocusedFrame(result.innerNodeFrame());
     2664
     2665    info.bounds = renderer->absoluteBoundingBoxRect(true);
     2666    // We don't want to select blocks that are larger than 97% of the visible area of the document.
     2667    if (is<HTMLAttachmentElement>(*hitNode)) {
     2668        info.isAttachment = true;
     2669        const HTMLAttachmentElement& attachment = downcast<HTMLAttachmentElement>(*hitNode);
     2670        info.title = attachment.attachmentTitle();
     2671        if (attachment.file())
     2672            info.url = URL::fileURLWithFileSystemPath(downcast<HTMLAttachmentElement>(*hitNode).file()->path());
     2673    } else {
     2674        info.isSelectable = renderer->style().userSelect() != UserSelect::None;
     2675        if (info.isSelectable && !hitNode->isTextNode())
     2676            info.isSelectable = !isAssistableElement(*downcast<Element>(hitNode)) && !rectIsTooBigForSelection(info.bounds, *result.innerNodeFrame());
     2677    }
     2678
     2679#if PLATFORM(IOSMAC)
     2680    bool isInsideFixedPosition;
     2681    VisiblePosition caretPosition(renderer->positionForPoint(request.point, nullptr));
     2682    info.caretRect = caretPosition.absoluteCaretBounds(&isInsideFixedPosition);
     2683#endif
     2684}
     2685
     2686#if ENABLE(DATALIST_ELEMENT)
     2687static void textInteractionPositionInformation(WebPage& page, const HTMLInputElement& input, const InteractionInformationRequest& request, InteractionInformationAtPosition& info)
     2688{
     2689    if (!input.list())
     2690        return;
     2691
     2692    HitTestResult result = page.corePage()->mainFrame().eventHandler().hitTestResultAtPoint(request.point, HitTestRequest::ReadOnly | HitTestRequest::Active);
     2693    if (result.innerNode() == input.dataListButtonElement())
     2694        info.preventTextInteraction = true;
     2695}
     2696#endif
    25002697
    25012698InteractionInformationAtPosition WebPage::positionInformation(const InteractionInformationRequest& request)
     
    25082705
    25092706    info.nodeAtPositionIsFocusedElement = hitNode == m_focusedElement;
    2510     if (m_focusedElement) {
    2511         const Frame& frame = m_page->focusController().focusedOrMainFrame();
    2512         if (frame.editor().hasComposition()) {
    2513             const uint32_t kHitAreaWidth = 66;
    2514             const uint32_t kHitAreaHeight = 66;
    2515             FrameView& view = *frame.view();
    2516             IntPoint adjustedPoint(view.rootViewToContents(request.point));
    2517             IntPoint constrainedPoint = m_focusedElement ? constrainPoint(adjustedPoint, frame, *m_focusedElement) : adjustedPoint;
    2518             VisiblePosition position = frame.visiblePositionForPoint(constrainedPoint);
    2519 
    2520             RefPtr<Range> compositionRange = frame.editor().compositionRange();
    2521             if (position < compositionRange->startPosition())
    2522                 position = compositionRange->startPosition();
    2523             else if (position > compositionRange->endPosition())
    2524                 position = compositionRange->endPosition();
    2525             IntRect caretRect = view.contentsToRootView(position.absoluteCaretBounds());
    2526             float deltaX = abs(caretRect.x() + (caretRect.width() / 2) - request.point.x());
    2527             float deltaYFromTheTop = abs(caretRect.y() - request.point.y());
    2528             float deltaYFromTheBottom = abs(caretRect.y() + caretRect.height() - request.point.y());
    2529 
    2530             info.isNearMarkedText = !(deltaX > kHitAreaWidth || deltaYFromTheTop > kHitAreaHeight || deltaYFromTheBottom > kHitAreaHeight);
    2531         }
    2532     }
    2533     bool elementIsLinkOrImage = false;
    2534     if (hitNode) {
    2535         Element* element = is<Element>(*hitNode) ? downcast<Element>(hitNode) : nullptr;
    2536         if (element) {
    2537             info.isElement = true;
    2538             info.idAttribute = element->getIdAttribute();
    2539             Element* linkElement = nullptr;
    2540             if (element->renderer() && element->renderer()->isRenderImage()) {
    2541                 elementIsLinkOrImage = true;
    2542                 linkElement = containingLinkElement(element);
    2543             } else if (element->isLink()) {
    2544                 linkElement = element;
    2545                 elementIsLinkOrImage = true;
    2546             }
    2547 
    2548             if (elementIsLinkOrImage) {
    2549                 if (linkElement) {
    2550                     info.isLink = true;
    2551 
    2552                     if (request.includeSnapshot) {
    2553                         // Ensure that the image contains at most 600K pixels, so that it is not too big.
    2554                         if (RefPtr<WebImage> snapshot = snapshotNode(*element, SnapshotOptionsShareable, 600 * 1024))
    2555                             info.image = &snapshot->bitmap();
    2556                     }
    2557 
    2558                     if (request.includeLinkIndicator) {
    2559                         auto linkRange = rangeOfContents(*linkElement);
    2560                         float deviceScaleFactor = corePage()->deviceScaleFactor();
    2561                         const float marginInPoints = 4;
    2562 
    2563                         auto textIndicator = TextIndicator::createWithRange(linkRange.get(), TextIndicatorOptionTightlyFitContent | TextIndicatorOptionRespectTextColor | TextIndicatorOptionPaintBackgrounds | TextIndicatorOptionUseBoundingRectAndPaintAllContentForComplexRanges |
    2564                             TextIndicatorOptionIncludeMarginIfRangeMatchesSelection, TextIndicatorPresentationTransition::None, FloatSize(marginInPoints * deviceScaleFactor, marginInPoints * deviceScaleFactor));
    2565 
    2566                         if (textIndicator)
    2567                             info.linkIndicator = textIndicator->data();
    2568                     }
    2569 
    2570 #if ENABLE(DATA_DETECTION)
    2571                     info.isDataDetectorLink = DataDetection::isDataDetectorLink(*element);
    2572                     if (info.isDataDetectorLink) {
    2573                         const int dataDetectionExtendedContextLength = 350;
    2574                         info.dataDetectorIdentifier = DataDetection::dataDetectorIdentifier(*element);
    2575                         info.dataDetectorResults = element->document().frame()->dataDetectionResults();
    2576                         if (DataDetection::requiresExtendedContext(*element)) {
    2577                             auto linkRange = Range::create(element->document());
    2578                             linkRange->selectNodeContents(*element);
    2579                             info.textBefore = plainTextReplacingNoBreakSpace(rangeExpandedByCharactersInDirectionAtWordBoundary(linkRange->startPosition(), dataDetectionExtendedContextLength, DirectionBackward).get(), TextIteratorDefaultBehavior, true);
    2580                             info.textAfter = plainTextReplacingNoBreakSpace(rangeExpandedByCharactersInDirectionAtWordBoundary(linkRange->endPosition(), dataDetectionExtendedContextLength, DirectionForward).get(), TextIteratorDefaultBehavior, true);
    2581                         }
    2582                     }
     2707    info.adjustedPointForNodeRespondingToClickEvents = adjustedPoint;
     2708
     2709#if ENABLE(DATA_INTERACTION)
     2710    info.hasSelectionAtPosition = m_page->hasSelectionAtPosition(adjustedPoint);
    25832711#endif
    2584                 }
    2585                 if (element->renderer() && element->renderer()->isRenderImage()) {
    2586                     info.isImage = true;
    2587                     auto& renderImage = downcast<RenderImage>(*(element->renderer()));
    2588                     if (renderImage.cachedImage() && !renderImage.cachedImage()->errorOccurred()) {
    2589                         if (Image* image = renderImage.cachedImage()->imageForRenderer(&renderImage)) {
    2590                             if (image->width() > 1 && image->height() > 1) {
    2591                                 info.imageURL = element->document().completeURL(renderImage.cachedImage()->url());
    2592                                 info.isAnimatedImage = image->isAnimated();
    2593 
    2594                                 if (request.includeSnapshot) {
    2595                                     FloatSize screenSizeInPixels = screenSize();
    2596                                     screenSizeInPixels.scale(corePage()->deviceScaleFactor());
    2597                                     FloatSize scaledSize = largestRectWithAspectRatioInsideRect(image->size().width() / image->size().height(), FloatRect(0, 0, screenSizeInPixels.width(), screenSizeInPixels.height())).size();
    2598                                     FloatSize bitmapSize = scaledSize.width() < image->size().width() ? scaledSize : image->size();
    2599                                     // FIXME: Only select ExtendedColor on images known to need wide gamut
    2600                                     ShareableBitmap::Configuration bitmapConfiguration;
    2601                                     bitmapConfiguration.colorSpace.cgColorSpace = screenColorSpace(m_page->mainFrame().view());
    2602                                     if (auto sharedBitmap = ShareableBitmap::createShareable(IntSize(bitmapSize), bitmapConfiguration)) {
    2603                                         auto graphicsContext = sharedBitmap->createGraphicsContext();
    2604                                         graphicsContext->drawImage(*image, FloatRect(0, 0, bitmapSize.width(), bitmapSize.height()));
    2605                                         info.image = sharedBitmap;
    2606                                     }
    2607                                 }
    2608                             }
    2609                         }
    2610                     }
    2611                 }
    2612             }
    2613             if (linkElement)
    2614                 info.url = linkElement->document().completeURL(stripLeadingAndTrailingHTMLSpaces(linkElement->getAttribute(HTMLNames::hrefAttr)));
    2615             info.title = element->attributeWithoutSynchronization(HTMLNames::titleAttr).string();
    2616             if (linkElement && info.title.isEmpty())
    2617                 info.title = element->innerText();
    2618             if (element->renderer())
    2619                 info.touchCalloutEnabled = element->renderer()->style().touchCalloutEnabled();
    2620 
    2621             if (RenderElement* renderer = element->renderer()) {
    2622                 if (renderer->isRenderImage())
    2623                     info.bounds = downcast<RenderImage>(*renderer).absoluteContentQuad().enclosingBoundingBox();
    2624                 else
    2625                     info.bounds = renderer->absoluteBoundingBoxRect();
    2626 
    2627                 if (!renderer->document().frame()->isMainFrame()) {
    2628                     FrameView *view = renderer->document().frame()->view();
    2629                     info.bounds = view->contentsToRootView(info.bounds);
    2630                 }
    2631             }
    2632         }
    2633     }
    2634 
    2635     if (!elementIsLinkOrImage) {
    2636         HitTestResult result = m_page->mainFrame().eventHandler().hitTestResultAtPoint(request.point, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::DisallowUserAgentShadowContent | HitTestRequest::AllowChildFrameContent);
    2637         hitNode = result.innerNode();
    2638         // Hit test could return HTMLHtmlElement that has no renderer, if the body is smaller than the document.
    2639         if (hitNode && hitNode->renderer()) {
    2640             RenderObject* renderer = hitNode->renderer();
    2641             if (!request.readonly)
    2642                 m_page->focusController().setFocusedFrame(result.innerNodeFrame());
    2643             info.bounds = renderer->absoluteBoundingBoxRect(true);
    2644             // We don't want to select blocks that are larger than 97% of the visible area of the document.
    2645             if (is<HTMLAttachmentElement>(*hitNode)) {
    2646                 info.isAttachment = true;
    2647                 const HTMLAttachmentElement& attachment = downcast<HTMLAttachmentElement>(*hitNode);
    2648                 info.title = attachment.attachmentTitle();
    2649                 if (attachment.file())
    2650                     info.url = URL::fileURLWithFileSystemPath(downcast<HTMLAttachmentElement>(*hitNode).file()->path());
    2651             } else {
    2652                 info.isSelectable = renderer->style().userSelect() != UserSelect::None;
    2653                 if (info.isSelectable && !hitNode->isTextNode())
    2654                     info.isSelectable = !isAssistableElement(*downcast<Element>(hitNode)) && !rectIsTooBigForSelection(info.bounds, *result.innerNodeFrame());
    2655             }
    2656 #if PLATFORM(IOSMAC)
    2657             bool isInsideFixedPosition;
    2658             VisiblePosition caretPosition(renderer->positionForPoint(request.point, nullptr));
    2659             info.caretRect = caretPosition.absoluteCaretBounds(&isInsideFixedPosition);
    2660 #endif
    2661         }
    2662     }
     2712
     2713    if (m_focusedElement)
     2714        focusedElementPositionInformation(*this, *m_focusedElement, request, info);
     2715
     2716    if (is<Element>(hitNode)) {
     2717        Element& element = downcast<Element>(*hitNode);
     2718        elementPositionInformation(*this, element, request, info);
     2719
     2720        if (info.isLink && !info.isImage && request.includeSnapshot) {
     2721            // Ensure that the image contains at most 600K pixels, so that it is not too big.
     2722            if (RefPtr<WebImage> snapshot = snapshotNode(element, SnapshotOptionsShareable, 600 * 1024))
     2723                info.image = &snapshot->bitmap();
     2724        }
     2725    }
     2726
     2727    if (!(info.isLink || info.isImage))
     2728        selectionPositionInformation(*this, request, info);
    26632729
    26642730    // Prevent the callout bar from showing when tapping on the datalist button.
     
    26662732    if (is<HTMLInputElement>(hitNode)) {
    26672733        const HTMLInputElement& input = downcast<HTMLInputElement>(*hitNode);
    2668         if (input.list()) {
    2669             HitTestResult result = m_page->mainFrame().eventHandler().hitTestResultAtPoint(request.point, HitTestRequest::ReadOnly | HitTestRequest::Active);
    2670             if (result.innerNode() == input.dataListButtonElement())
    2671                 info.preventTextInteraction = true;
    2672         }
     2734        textInteractionPositionInformation(*this, input, request, info);
    26732735    }
    26742736#endif
    2675 
    2676 #if ENABLE(DATA_INTERACTION)
    2677     info.hasSelectionAtPosition = m_page->hasSelectionAtPosition(adjustedPoint);
    2678 #endif
    2679     info.adjustedPointForNodeRespondingToClickEvents = adjustedPoint;
    26802737
    26812738    return info;
  • trunk/Tools/ChangeLog

    r245870 r245872  
     12019-05-29  Said Abou-Hallawa  <sabouhallawa@apple.com>
     2
     3        [iOS] WebPage::positionInformation() may set InteractionInformationAtPosition.isImage to true but leave image unset
     4        https://bugs.webkit.org/show_bug.cgi?id=198202
     5
     6        Reviewed by Tim Horton.
     7
     8        The new test ensures InteractionInformationAtPosition::isImage will not
     9        be to true for a broken image.
     10
     11        * TestWebKitAPI/Tests/WebKitCocoa/WKRequestActivatedElementInfo.mm:
     12        (TestWebKitAPI::TEST):
     13
    1142019-05-29  David Kilzer  <ddkilzer@apple.com>
    215
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKRequestActivatedElementInfo.mm

    r244368 r245872  
    115115    TestWebKitAPI::Util::run(&finished);
    116116}
     117
     118TEST(WebKit, RequestActivatedElementInfoForBrokenImage)
     119{
     120    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
     121    [webView loadHTMLString:@"<html><head><meta name='viewport' content='initial-scale=1'></head><body style = 'margin: 0px;'><img  src='missing.gif' height='100' width='100'></body></html>" baseURL:nil];
     122    [webView _test_waitForDidFinishNavigation];
    117123   
     124    __block bool finished = false;
     125    [webView _requestActivatedElementAtPosition:CGPointMake(50, 50) completionBlock: ^(_WKActivatedElementInfo *elementInfo) {
     126       
     127        EXPECT_TRUE(elementInfo.type == _WKActivatedElementTypeUnspecified);
     128        EXPECT_EQ(elementInfo.boundingRect.size.width, 100);
     129        EXPECT_EQ(elementInfo.boundingRect.size.height, 100);
     130       
     131        finished = true;
     132    }];
     133   
     134    TestWebKitAPI::Util::run(&finished);
     135}
     136
    118137TEST(WebKit, RequestActivatedElementInfoWithNestedSynchronousUpdates)
    119138{
Note: See TracChangeset for help on using the changeset viewer.