WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
236750
AX: AccessibilityScrollView should be resilient to destruction of underlying scroll view
https://bugs.webkit.org/show_bug.cgi?id=236750
Summary
AX: AccessibilityScrollView should be resilient to destruction of underlying ...
Tyler Wilcock
Reported
2022-02-16 21:04:21 PST
Sometimes, we can get into a state where we have a valid AccessibilityScrollView, backed by an iframe, with a destroyed WeakPtr<ScrollView> m_scrollView. When this happens, all of the content inside the iframe becomes inaccessible. We need to handle the case where an iframe changes the frame it holds (e.g. respect the current frame in HTMLFrameOwner::contentFrame, which can change).
Attachments
Patch
(13.01 KB, patch)
2022-02-16 21:35 PST
,
Tyler Wilcock
no flags
Details
Formatted Diff
Diff
Patch
(13.33 KB, patch)
2022-02-17 12:00 PST
,
Tyler Wilcock
no flags
Details
Formatted Diff
Diff
Minimal reproduction of issue
(939 bytes, text/plain)
2022-02-17 18:51 PST
,
Tyler Wilcock
andresg_22
: review+
Details
Show Obsolete
(1)
View All
Add attachment
proposed patch, testcase, etc.
Radar WebKit Bug Importer
Comment 1
2022-02-16 21:04:34 PST
<
rdar://problem/89066221
>
Tyler Wilcock
Comment 2
2022-02-16 21:35:10 PST
Created
attachment 452311
[details]
Patch
chris fleizach
Comment 3
2022-02-16 21:52:37 PST
patch looks good. is there any way to test this?
Andres Gonzalez
Comment 4
2022-02-17 05:17:38 PST
(In reply to Tyler Wilcock from
comment #2
)
> Created
attachment 452311
[details]
> Patch
--- a/Source/WebCore/accessibility/AccessibilityScrollView.cpp +++ a/Source/WebCore/accessibility/AccessibilityScrollView.cpp +AXObjectCache* AccessibilityScrollView::currentAxObjectCache() const +{ + if (auto* cache = axObjectCache()) + return cache; + + // It's possible that the document associated with `this` was destroyed (and thus axObjectCache() will return null), + // but also that `this` still represents a valid frame owner (e.g. iframe). Return the cache of the iframe in this case. + return m_frameOwnerElement ? m_frameOwnerElement->document().axObjectCache() : nullptr; +} Can we just override AXCoreObject::axObjectCache instead of adding a new method? The comment here only makes sense for the reader who knows the implementation of AccessibilityObject::axObjectCache. this could be written more succinctly and clearer like: auto* document = this->document(); return document ? document->axObjectCache() : m_frameOwnerElement ? m_frameOwnerElement->document().axObjectCache() : nullptr; Or perhaps better yet to override document(), and then you wouldn't need to override axObjectCache(). +Document* AccessibilityScrollView::contentDocument() const +{ + if (m_frameOwnerElement) + return m_frameOwnerElement->contentDocument(); + return nullptr; +} do we need this method separate from document()? Or we can just override document()? If we need this, it could be written in two lines with the ? :, which I think it is better. +FrameView* AccessibilityScrollView::contentDocumentFrameView() const +{ + if (auto* document = contentDocument()) + return document->view(); + return nullptr; +} Can we override documentFrameView() instead? @@ -157,7 +194,7 @@ AccessibilityScrollbar* AccessibilityScrollView::addChildScrollbar(Scrollbar* sc if (!scrollbar) return nullptr; - AXObjectCache* cache = axObjectCache(); + AXObjectCache* cache = currentAxObjectCache(); No need for this if you override axObjectCache(). AccessibilityObject* AccessibilityScrollView::webAreaObject() const { - if (!is<FrameView>(m_scrollView)) - return nullptr; + auto* document = contentDocument(); + if (is<FrameView>(m_scrollView)) + document = downcast<FrameView>(*m_scrollView).frame().document(); - Document* document = downcast<FrameView>(*m_scrollView).frame().document(); if (!document || !document->hasLivingRenderTree()) return nullptr; - if (AXObjectCache* cache = axObjectCache()) + if (auto* cache = currentAxObjectCache()) return cache->getOrCreate(document); I think this can be simplified with the right overrides. AccessibilityObject* AccessibilityScrollView::parentObject() const { - if (!is<FrameView>(m_scrollView)) + if (!is<FrameView>(m_scrollView)) { + if (m_frameOwnerElement) { + if (auto* cache = m_frameOwnerElement->document().axObjectCache()) + return cache->getOrCreate(m_frameOwnerElement.get()); + } return nullptr; + } AXObjectCache* cache = axObjectCache(); if (!cache) Can this be simplified with the right overrides? i.e., no need to get the cache in two different places. ScrollableArea* AccessibilityScrollView::getScrollableAreaIfScrollable() const { - return m_scrollView.get(); + return currentScrollView(); } Can we inline this in the header like scrollView() for consistency? --- a/Source/WebCore/accessibility/AccessibilityScrollView.h +++ a/Source/WebCore/accessibility/AccessibilityScrollView.h + // Returns the document for m_frameOwnerElement's current `contentFrame` (if present). + Document* contentDocument() const; + FrameView* contentDocumentFrameView() const; ... + AXObjectCache* currentAxObjectCache() const; Do we need these, or we can just override document() and documentFrameView()?
Tyler Wilcock
Comment 5
2022-02-17 12:00:08 PST
Created
attachment 452400
[details]
Patch
Tyler Wilcock
Comment 6
2022-02-17 12:00:57 PST
Fixed all of your comments. Still trying to get a minimal test case reproducing the issue.
Andres Gonzalez
Comment 7
2022-02-17 12:55:12 PST
(In reply to Tyler Wilcock from
comment #5
)
> Created
attachment 452400
[details]
> Patch
bool AccessibilityScrollView::isAttachment() const { - return m_scrollView && m_scrollView->platformWidget(); + if (auto* scrollView = currentScrollView()) + return scrollView->platformWidget(); + return false; I personally prefer the two line version: auto* scrollView = currentScrollView(); return scrollView ? scrollView->platformWidget() : false; But not big deal. PlatformWidget AccessibilityScrollView::platformWidget() const { - return m_scrollView ? m_scrollView->platformWidget() : nullptr; + if (auto* scrollView = currentScrollView()) + return scrollView->platformWidget(); + return nullptr; } Same here: auto* scrollView = currentScrollView(); return scrollView ? scrollView->platformWidget() : nullptr;
Tyler Wilcock
Comment 8
2022-02-17 18:51:06 PST
Created
attachment 452465
[details]
Minimal reproduction of issue
EWS
Comment 9
2022-02-18 08:48:52 PST
Committed
r290130
(
247474@main
): <
https://commits.webkit.org/247474@main
> All reviewed patches have been landed. Closing bug and clearing flags on
attachment 452400
[details]
.
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug