- Revision
- 258792
- Author
- [email protected]
- Date
- 2020-03-20 14:55:10 -0700 (Fri, 20 Mar 2020)
Log Message
Replace "deferred element focus" functionality with alternative solution
https://bugs.webkit.org/show_bug.cgi?id=201608
Reviewed by Wenson Hsieh.
This is a partial revert of r190278. Have the web process perform a layout, if needed, when
computing focus element information and send an editor state update immediately. If layout is
not needed then explicitly schedule a full editor state update.
Currently, fetching focus element information neither sends an editor state update nor
schedules one. As a result, when the web process tells the UI process to focus an element the
UI process may need to defer doing so if the last received update did not include details
that require up-to-date layout (e.g. the bounding rect of the focused element, which is used
to scroll and zoom to center the focused element). The UI process then schedules an async message
to the web process to fetch the full editor state, which will arrive in a layer tree commit message
from the web process. (Note that the UI process schedules this request to ensure the web process
knows that it is waiting for a layer tree commit. The web process can use this info to expedite
a layer tree commit, if needed). This deferral mechanism complicates the element focusing and
defocusing logic in the UI process and prevents fixing <https://bugs.webkit.org/show_bug.cgi?id=199960>.
Instead remove this deferral concept and have the web process ensure that a full editor state
update is sent or will be sent when computing the focus element information.
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::resetStateAfterProcessExited):
* UIProcess/WebPageProxy.h:
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::didCommitLayerTree):
(WebKit::WebPageProxy::elementDidFocus):
(WebKit::WebPageProxy::elementDidBlur):
Remove bookkeeping code to track a deferred focus event or to perform the deferred event
on layer tree commit.
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::elementDidFocus):
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::getFocusedElementInformation): Save off whether a layout is needed then
tell the page to layout if needed. If a layout was needed then send an editor state update
immediately (it's an async message): this update will be a "full editor state" update that
includes up-to-date layout details. Otherwise, schedule a full editor state update. While I
am here, I updated the code to take out a ref on the focused frame's document before performing
a layout because layout can cause arbitrary _javascript_ execution that could detach the document
from its frame view as part of destroying the document. Document destruction is detected by
checking whether the document has been detached from its frame view. If this happens then
bail out as there is no need to get focus element info.
Modified Paths
Diff
Modified: trunk/Source/WebKit/ChangeLog (258791 => 258792)
--- trunk/Source/WebKit/ChangeLog 2020-03-20 21:54:46 UTC (rev 258791)
+++ trunk/Source/WebKit/ChangeLog 2020-03-20 21:55:10 UTC (rev 258792)
@@ -1,3 +1,50 @@
+2020-03-20 Daniel Bates <[email protected]>
+
+ Replace "deferred element focus" functionality with alternative solution
+ https://bugs.webkit.org/show_bug.cgi?id=201608
+
+ Reviewed by Wenson Hsieh.
+
+ This is a partial revert of r190278. Have the web process perform a layout, if needed, when
+ computing focus element information and send an editor state update immediately. If layout is
+ not needed then explicitly schedule a full editor state update.
+
+ Currently, fetching focus element information neither sends an editor state update nor
+ schedules one. As a result, when the web process tells the UI process to focus an element the
+ UI process may need to defer doing so if the last received update did not include details
+ that require up-to-date layout (e.g. the bounding rect of the focused element, which is used
+ to scroll and zoom to center the focused element). The UI process then schedules an async message
+ to the web process to fetch the full editor state, which will arrive in a layer tree commit message
+ from the web process. (Note that the UI process schedules this request to ensure the web process
+ knows that it is waiting for a layer tree commit. The web process can use this info to expedite
+ a layer tree commit, if needed). This deferral mechanism complicates the element focusing and
+ defocusing logic in the UI process and prevents fixing <https://bugs.webkit.org/show_bug.cgi?id=199960>.
+ Instead remove this deferral concept and have the web process ensure that a full editor state
+ update is sent or will be sent when computing the focus element information.
+
+ * UIProcess/WebPageProxy.cpp:
+ (WebKit::WebPageProxy::resetStateAfterProcessExited):
+ * UIProcess/WebPageProxy.h:
+ * UIProcess/ios/WebPageProxyIOS.mm:
+ (WebKit::WebPageProxy::didCommitLayerTree):
+ (WebKit::WebPageProxy::elementDidFocus):
+ (WebKit::WebPageProxy::elementDidBlur):
+ Remove bookkeeping code to track a deferred focus event or to perform the deferred event
+ on layer tree commit.
+
+ * WebProcess/WebPage/WebPage.cpp:
+ (WebKit::WebPage::elementDidFocus):
+ * WebProcess/WebPage/ios/WebPageIOS.mm:
+ (WebKit::WebPage::getFocusedElementInformation): Save off whether a layout is needed then
+ tell the page to layout if needed. If a layout was needed then send an editor state update
+ immediately (it's an async message): this update will be a "full editor state" update that
+ includes up-to-date layout details. Otherwise, schedule a full editor state update. While I
+ am here, I updated the code to take out a ref on the focused frame's document before performing
+ a layout because layout can cause arbitrary _javascript_ execution that could detach the document
+ from its frame view as part of destroying the document. Document destruction is detected by
+ checking whether the document has been detached from its frame view. If this happens then
+ bail out as there is no need to get focus element info.
+
2020-03-20 Don Olmstead <[email protected]>
[GPUP] Add PlatformLayerContainer to hold pointer to PlatformLayer
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (258791 => 258792)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp 2020-03-20 21:54:46 UTC (rev 258791)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp 2020-03-20 21:55:10 UTC (rev 258792)
@@ -7545,8 +7545,6 @@
#if PLATFORM(IOS_FAMILY)
m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement = false;
- m_deferredElementDidFocusArguments = nullptr;
-
m_isVisibleActivity = nullptr;
m_isAudibleActivity = nullptr;
m_isCapturingActivity = nullptr;
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (258791 => 258792)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.h 2020-03-20 21:54:46 UTC (rev 258791)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h 2020-03-20 21:55:10 UTC (rev 258792)
@@ -395,14 +395,6 @@
typedef GenericCallback<const WebCore::IntPoint&, uint32_t, uint32_t> TouchesCallback;
typedef GenericCallback<const Vector<WebCore::SelectionRect>&> SelectionRectsCallback;
typedef GenericCallback<const FocusedElementInformation&> FocusedElementInformationCallback;
-struct ElementDidFocusArguments {
- WTF_MAKE_STRUCT_FAST_ALLOCATED;
- FocusedElementInformation information;
- bool userIsInteracting;
- bool blurPreviousNode;
- OptionSet<WebCore::ActivityState::Flag> activityStateChanges;
- RefPtr<API::Object> userData;
-};
#endif
#if PLATFORM(COCOA)
@@ -2665,7 +2657,6 @@
#if PLATFORM(IOS_FAMILY)
Function<bool()> m_deviceOrientationUserPermissionHandlerForTesting;
- std::unique_ptr<ElementDidFocusArguments> m_deferredElementDidFocusArguments;
bool m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement { false };
WebCore::FloatSize m_maximumUnobscuredSize;
bool m_lastObservedStateWasBackground { false };
Modified: trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm (258791 => 258792)
--- trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm 2020-03-20 21:54:46 UTC (rev 258791)
+++ trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm 2020-03-20 21:55:10 UTC (rev 258792)
@@ -404,9 +404,6 @@
m_hitRenderTreeSizeThreshold = true;
didReachLayoutMilestone(WebCore::ReachedSessionRestorationRenderTreeSizeThreshold);
}
-
- if (auto arguments = std::exchange(m_deferredElementDidFocusArguments, nullptr))
- pageClient().elementDidFocus(arguments->information, arguments->userIsInteracting, arguments->blurPreviousNode, arguments->activityStateChanges, arguments->userData.get());
}
bool WebPageProxy::updateLayoutViewportParameters(const WebKit::RemoteLayerTreeTransaction& layerTreeTransaction)
@@ -987,12 +984,6 @@
m_pendingInputModeChange = WTF::nullopt;
API::Object* userDataObject = process().transformHandlesToObjects(userData.object()).get();
- if (m_editorState.isMissingPostLayoutData) {
- // FIXME: We should try to eliminate m_deferredElementDidFocusArguments altogether, in favor of only deferring actions that are dependent on post-layout editor state information.
- m_deferredElementDidFocusArguments = makeUnique<ElementDidFocusArguments>(ElementDidFocusArguments { information, userIsInteracting, blurPreviousNode, activityStateChanges, userDataObject });
- return;
- }
-
pageClient().elementDidFocus(information, userIsInteracting, blurPreviousNode, activityStateChanges, userDataObject);
}
@@ -999,7 +990,6 @@
void WebPageProxy::elementDidBlur()
{
m_pendingInputModeChange = WTF::nullopt;
- m_deferredElementDidFocusArguments = nullptr;
pageClient().elementDidBlur();
}
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (258791 => 258792)
--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp 2020-03-20 21:54:46 UTC (rev 258791)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp 2020-03-20 21:55:10 UTC (rev 258792)
@@ -5627,8 +5627,6 @@
send(Messages::WebPageProxy::SetEditableElementIsFocused(!element.hasTagName(WebCore::HTMLNames::selectTag)));
#endif
m_recentlyBlurredElement = nullptr;
-
- scheduleFullEditorStateUpdate();
}
}
Modified: trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm (258791 => 258792)
--- trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm 2020-03-20 21:54:46 UTC (rev 258791)
+++ trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm 2020-03-20 21:55:10 UTC (rev 258792)
@@ -3037,11 +3037,23 @@
void WebPage::getFocusedElementInformation(FocusedElementInformation& information)
{
+ RefPtr<Document> document = m_page->focusController().focusedOrMainFrame().document();
+ if (!document || !document->view())
+ return;
+
auto focusedElement = m_focusedElement.copyRef();
+ bool willLayout = document->view()->needsLayout();
layoutIfNeeded();
- if (focusedElement != m_focusedElement)
+
+ // Layout may have detached the document or caused a change of focus.
+ if (!document->view() || focusedElement != m_focusedElement)
return;
+ if (willLayout)
+ sendEditorStateUpdate();
+ else
+ scheduleFullEditorStateUpdate();
+
information.lastInteractionLocation = m_lastInteractionLocation;
if (auto elementContext = contextForElement(*focusedElement))
information.elementContext = WTFMove(*elementContext);