Bug 225333

Summary: Add SPI to suspend / resume a WKWebView
Product: WebKit Reporter: Chris Dumez <cdumez>
Component: WebKit2Assignee: Chris Dumez <cdumez>
Status: RESOLVED FIXED    
Severity: Normal CC: achristensen, annulen, beidson, commit-queue, ews-watchlist, ggaren, gyuyoung.kim, hi, kkinnunen, mkwst, ryuan.choi, sam, sergio, webkit-bug-importer
Priority: P2 Keywords: InRadar
Version: WebKit Nightly Build   
Hardware: Unspecified   
OS: Unspecified   
Bug Depends on: 225685    
Bug Blocks:    
Attachments:
Description Flags
WIP Patch
ews-feeder: commit-queue-
WIP Patch
none
WIP Patch (with test)
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch
ews-feeder: commit-queue-
Patch
none
Patch
none
Patch
ews-feeder: commit-queue-
Patch
none
Patch
none
Patch
none
Patch none

Chris Dumez
Reported 2021-05-03 16:15:41 PDT
Add SPI to suspend / resume a WKWebView.
Attachments
WIP Patch (10.83 KB, patch)
2021-05-03 16:17 PDT, Chris Dumez
ews-feeder: commit-queue-
WIP Patch (13.87 KB, patch)
2021-05-03 16:45 PDT, Chris Dumez
no flags
WIP Patch (with test) (22.22 KB, patch)
2021-05-03 17:11 PDT, Chris Dumez
no flags
Patch (29.51 KB, patch)
2021-05-04 08:17 PDT, Chris Dumez
no flags
Patch (33.88 KB, patch)
2021-05-05 10:05 PDT, Chris Dumez
no flags
Patch (37.36 KB, patch)
2021-05-05 14:43 PDT, Chris Dumez
no flags
Patch (38.00 KB, patch)
2021-05-05 15:42 PDT, Chris Dumez
no flags
Patch (132.01 KB, patch)
2021-05-10 15:40 PDT, Chris Dumez
ews-feeder: commit-queue-
Patch (132.04 KB, patch)
2021-05-10 16:28 PDT, Chris Dumez
no flags
Patch (132.49 KB, patch)
2021-05-11 11:11 PDT, Chris Dumez
no flags
Patch (129.20 KB, patch)
2021-05-11 11:15 PDT, Chris Dumez
ews-feeder: commit-queue-
Patch (129.30 KB, patch)
2021-05-11 11:41 PDT, Chris Dumez
no flags
Patch (129.29 KB, patch)
2021-05-11 21:02 PDT, Chris Dumez
no flags
Patch (129.20 KB, patch)
2021-05-11 21:05 PDT, Chris Dumez
no flags
Patch (129.20 KB, patch)
2021-05-11 21:26 PDT, Chris Dumez
no flags
Chris Dumez
Comment 1 2021-05-03 16:15:58 PDT
Chris Dumez
Comment 2 2021-05-03 16:17:58 PDT
Created attachment 427613 [details] WIP Patch
Chris Dumez
Comment 3 2021-05-03 16:45:53 PDT
Created attachment 427619 [details] WIP Patch
Chris Dumez
Comment 4 2021-05-03 17:11:33 PDT
Created attachment 427623 [details] WIP Patch (with test)
Chris Dumez
Comment 5 2021-05-04 08:17:49 PDT
Sam Weinig
Comment 6 2021-05-04 09:00:24 PDT
Comment on attachment 427670 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=427670&action=review > Source/WebKit/ChangeLog:12 > + Add SPI to suspend / resume a WKWebView. This suspends the page as if it was in > + the back/forward cache but the suspension happens in-place, no need to navigate. > + The suspended page is also not part of the Back/Forward cache so its cap on the > + number of suspended pages does not apply here. What are the rules for what you can do with a suspended WKWebView? Can you call loadRequest:? Will that resume it?
Geoffrey Garen
Comment 7 2021-05-04 11:07:52 PDT
> What are the rules for what you can do with a suspended WKWebView? Can you > call loadRequest:? Will that resume it? This question makes me wonder if we really want suspension to be a state on the WebView, or if it would be better to model it more explicitly like a navigation to about:blank. (Not that we would require the client to actually navigate to about:blank -- just that the implementation of suspend would navigate to about:blank or about:suspended or whatever, and the implementation of resume would navigate back. Perhaps we would also hide the actual about:blank or about:suspended entry from history and/or back/forward list.)
Chris Dumez
Comment 8 2021-05-04 11:39:26 PDT
(In reply to Sam Weinig from comment #6) > Comment on attachment 427670 [details] > Patch > > View in context: > https://bugs.webkit.org/attachment.cgi?id=427670&action=review > > > Source/WebKit/ChangeLog:12 > > + Add SPI to suspend / resume a WKWebView. This suspends the page as if it was in > > + the back/forward cache but the suspension happens in-place, no need to navigate. > > + The suspended page is also not part of the Back/Forward cache so its cap on the > > + number of suspended pages does not apply here. > > What are the rules for what you can do with a suspended WKWebView? Can you > call loadRequest:? Will that resume it? With the current implementation, it isn't safe to do much with a suspended view besides resuming it or destroying it. We could support loadRequest if we wanted. This is not a use case we have currently though.
Chris Dumez
Comment 9 2021-05-04 11:42:15 PDT
(In reply to Geoffrey Garen from comment #7) > > What are the rules for what you can do with a suspended WKWebView? Can you > > call loadRequest:? Will that resume it? > > This question makes me wonder if we really want suspension to be a state on > the WebView, or if it would be better to model it more explicitly like a > navigation to about:blank. (Not that we would require the client to actually > navigate to about:blank -- just that the implementation of suspend would > navigate to about:blank or about:suspended or whatever, and the > implementation of resume would navigate back. Perhaps we would also hide the > actual about:blank or about:suspended entry from history and/or back/forward > list.) 2 issues: a. Yes, we'd need logic to hide the about:blank / about:suspended from the back/forward list. This was a major point to introducing this SPI vs having the client navigate. b. Your statement assumes we have a history item to go back to. Unlike back/forward cache, this new suspension mechanism does not require a HistoryItem. Note that calling loadHTMLString or loadData on a WKWebView does NOT create a HistoryItem. Yet I think we should be able to suspend it.
Chris Dumez
Comment 10 2021-05-04 11:49:00 PDT
(In reply to Sam Weinig from comment #6) > Comment on attachment 427670 [details] > Patch > > View in context: > https://bugs.webkit.org/attachment.cgi?id=427670&action=review > > > Source/WebKit/ChangeLog:12 > > + Add SPI to suspend / resume a WKWebView. This suspends the page as if it was in > > + the back/forward cache but the suspension happens in-place, no need to navigate. > > + The suspended page is also not part of the Back/Forward cache so its cap on the > > + number of suspended pages does not apply here. > > What are the rules for what you can do with a suspended WKWebView? Can you > call loadRequest:? Will that resume it? I did not focus on all these cases because this is not API yet, just SPI for now used in a very specific way. If it were API, I agree we'd need to go through each WKWebView API and decide what their behavior should be when suspended. Since I think the SPI would eventually be useful as API, I do think I should follow-up and figure those cases out though. I was hoping to land this ASAP to unblock the client app that needs it but if people think we need a better story for what each WKWebView API does when suspended before landing, I can prioritize it.
Chris Dumez
Comment 11 2021-05-05 10:05:41 PDT
Sam Weinig
Comment 12 2021-05-05 14:07:38 PDT
(In reply to Chris Dumez from comment #10) > (In reply to Sam Weinig from comment #6) > > Comment on attachment 427670 [details] > > Patch > > > > View in context: > > https://bugs.webkit.org/attachment.cgi?id=427670&action=review > > > > > Source/WebKit/ChangeLog:12 > > > + Add SPI to suspend / resume a WKWebView. This suspends the page as if it was in > > > + the back/forward cache but the suspension happens in-place, no need to navigate. > > > + The suspended page is also not part of the Back/Forward cache so its cap on the > > > + number of suspended pages does not apply here. > > > > What are the rules for what you can do with a suspended WKWebView? Can you > > call loadRequest:? Will that resume it? > > I did not focus on all these cases because this is not API yet, just SPI for > now used in a very specific way. If it were API, I agree we'd need to go > through each WKWebView API and decide what their behavior should be when > suspended. > > Since I think the SPI would eventually be useful as API, I do think I should > follow-up and figure those cases out though. I was hoping to land this ASAP > to unblock the client app that needs it but if people think we need a better > story for what each WKWebView API does when suspended before landing, I can > prioritize it. I generally think we should be very careful with any new SPI as they can be quite hard to remove once adopted. For something as big as this, I think we need the functionality to be fleshed out and tested before we would want anyone using it.
Chris Dumez
Comment 13 2021-05-05 14:13:07 PDT
(In reply to Sam Weinig from comment #12) > (In reply to Chris Dumez from comment #10) > > (In reply to Sam Weinig from comment #6) > > > Comment on attachment 427670 [details] > > > Patch > > > > > > View in context: > > > https://bugs.webkit.org/attachment.cgi?id=427670&action=review > > > > > > > Source/WebKit/ChangeLog:12 > > > > + Add SPI to suspend / resume a WKWebView. This suspends the page as if it was in > > > > + the back/forward cache but the suspension happens in-place, no need to navigate. > > > > + The suspended page is also not part of the Back/Forward cache so its cap on the > > > > + number of suspended pages does not apply here. > > > > > > What are the rules for what you can do with a suspended WKWebView? Can you > > > call loadRequest:? Will that resume it? > > > > I did not focus on all these cases because this is not API yet, just SPI for > > now used in a very specific way. If it were API, I agree we'd need to go > > through each WKWebView API and decide what their behavior should be when > > suspended. > > > > Since I think the SPI would eventually be useful as API, I do think I should > > follow-up and figure those cases out though. I was hoping to land this ASAP > > to unblock the client app that needs it but if people think we need a better > > story for what each WKWebView API does when suspended before landing, I can > > prioritize it. > > I generally think we should be very careful with any new SPI as they can be > quite hard to remove once adopted. > > For something as big as this, I think we need the functionality to be > fleshed out and tested before we would want anyone using it. I did flesh it out more in my latest iteration. Requests to navigate or run JS are now handled in particular.
Chris Dumez
Comment 14 2021-05-05 14:43:01 PDT
Chris Dumez
Comment 15 2021-05-05 15:42:58 PDT
Sam Weinig
Comment 16 2021-05-06 17:51:52 PDT
(In reply to Chris Dumez from comment #13) > (In reply to Sam Weinig from comment #12) > > (In reply to Chris Dumez from comment #10) > > > (In reply to Sam Weinig from comment #6) > > > > Comment on attachment 427670 [details] > > > > Patch > > > > > > > > View in context: > > > > https://bugs.webkit.org/attachment.cgi?id=427670&action=review > > > > > > > > > Source/WebKit/ChangeLog:12 > > > > > + Add SPI to suspend / resume a WKWebView. This suspends the page as if it was in > > > > > + the back/forward cache but the suspension happens in-place, no need to navigate. > > > > > + The suspended page is also not part of the Back/Forward cache so its cap on the > > > > > + number of suspended pages does not apply here. > > > > > > > > What are the rules for what you can do with a suspended WKWebView? Can you > > > > call loadRequest:? Will that resume it? > > > > > > I did not focus on all these cases because this is not API yet, just SPI for > > > now used in a very specific way. If it were API, I agree we'd need to go > > > through each WKWebView API and decide what their behavior should be when > > > suspended. > > > > > > Since I think the SPI would eventually be useful as API, I do think I should > > > follow-up and figure those cases out though. I was hoping to land this ASAP > > > to unblock the client app that needs it but if people think we need a better > > > story for what each WKWebView API does when suspended before landing, I can > > > prioritize it. > > > > I generally think we should be very careful with any new SPI as they can be > > quite hard to remove once adopted. > > > > For something as big as this, I think we need the functionality to be > > fleshed out and tested before we would want anyone using it. > > I did flesh it out more in my latest iteration. Requests to navigate or run > JS are now handled in particular. Is the rule then that any use of API that would ordinarily work should work when suspended, resuming the page? Do some functions not resume the webview?
Sam Weinig
Comment 17 2021-05-06 17:54:26 PDT
I should add, my personal opinion would be that all WKWebView API/SPI throw or crash if the page is suspended (except resume of course).
Chris Dumez
Comment 18 2021-05-06 18:19:51 PDT
(In reply to Sam Weinig from comment #17) > I should add, my personal opinion would be that all WKWebView API/SPI throw > or crash if the page is suspended (except resume of course). What I implemented is so far is my personal preference (but I am happy to change if others feel differently): 1. Navigating the views unsuspends the page before navigating 2. Operations that do not require the WebProcess keep working 2. Operations that need the WebProcess (e.g. evaluateJS(), find(), takeSnapshot(), createWebArchive, createPDF, ...) fail (as in I am calling their completion handler with an error). I have no covered everything in this case but the top ones. Throwing an exception for every SPI/API call besides resume() seems super aggressive but then again, that's pretty much the contract we have with the client. That said, there are a lot of API/SPIs that do not need the WebProcess in any way (e.g. WKWebView.URL, WKWebView.isLoading, WKWebView.title, WKWebView.canGoBack) and could keep working just fine while suspended I think.
Sam Weinig
Comment 19 2021-05-07 09:12:27 PDT
(In reply to Chris Dumez from comment #18) > (In reply to Sam Weinig from comment #17) > > I should add, my personal opinion would be that all WKWebView API/SPI throw > > or crash if the page is suspended (except resume of course). > > What I implemented is so far is my personal preference (but I am happy to > change if others feel differently): > 1. Navigating the views unsuspends the page before navigating > 2. Operations that do not require the WebProcess keep working > 2. Operations that need the WebProcess (e.g. evaluateJS(), find(), > takeSnapshot(), createWebArchive, createPDF, ...) fail (as in I am calling > their completion handler with an error). I have no covered everything in > this case but the top ones. > > Throwing an exception for every SPI/API call besides resume() seems super > aggressive but then again, that's pretty much the contract we have with the > client. That said, there are a lot of API/SPIs that do not need the > WebProcess in any way (e.g. WKWebView.URL, WKWebView.isLoading, > WKWebView.title, WKWebView.canGoBack) and could keep working just fine while > suspended I think. I realize I didn't really add my reasons for my opinion. There are a few reasons I think being heavy handed makes sense. 1) It is much easier to relax things in the future than it is to make them stricter. For instance, if we want to make it valid to call WKWebView.canGoBack when suspended, we can remove the check and document in the header that WKWebView.canGoBack can be called when suspended. 2) Side effects for methods like loadRequest: resuming the view are hard to teach, especially when it is no 100% clear which methods will have the side effects and which won't.
Geoffrey Garen
Comment 20 2021-05-10 10:42:34 PDT
I think I agree that throwing an exception when an operation obviously can't work because we're suspended is a helpful approach -- and more helpful than auto-unsuspending, since that might put the app in an invalid state. Why don't we compromise and throw an exception in APIs that (a) can't work while suspended or (b) it's not obvious whether they can work or not while suspended. But for the APIs where it is obvious that they can work while suspended, let's not throw. It just doesn't make sense. And I worry that we'll create a long tail of trivial exception noise that doesn't help anyone -- for example, just because Interface Builder has the WebView's URL or title hooked up to some view, which seems like an obviously valid thing to do even while suspended.
Geoffrey Garen
Comment 21 2021-05-10 10:46:48 PDT
Side note: This discussion reminds me of the setDefersLoading() API, and the numerous costly "blank WebView" / "load failed" bugs it caused. Hopefully throwing an exception in APIs that obviously won't work, including loading APIs, will help avoid that kind of problem this time around.
Chris Dumez
Comment 22 2021-05-10 15:40:22 PDT
Chris Dumez
Comment 23 2021-05-10 15:41:07 PDT
(In reply to Geoffrey Garen from comment #20) > I think I agree that throwing an exception when an operation obviously can't > work because we're suspended is a helpful approach -- and more helpful than > auto-unsuspending, since that might put the app in an invalid state. > > Why don't we compromise and throw an exception in APIs that (a) can't work > while suspended or (b) it's not obvious whether they can work or not while > suspended. But for the APIs where it is obvious that they can work while > suspended, let's not throw. It just doesn't make sense. And I worry that > we'll create a long tail of trivial exception noise that doesn't help anyone > -- for example, just because Interface Builder has the WebView's URL or > title hooked up to some view, which seems like an obviously valid thing to > do even while suspended. Ok, I have implemented this proposal and extended API test coverage accordingly.
Chris Dumez
Comment 24 2021-05-10 16:28:40 PDT
Geoffrey Garen
Comment 25 2021-05-11 10:46:06 PDT
iOS EWS is angry: TestWebKitAPI.ProcessSuspension.WKWebViewSuspendPage
Chris Dumez
Comment 26 2021-05-11 10:54:25 PDT
(In reply to Geoffrey Garen from comment #25) > iOS EWS is angry: TestWebKitAPI.ProcessSuspension.WKWebViewSuspendPage It is minor, will fix. TestWebKitAPI.ProcessSuspension.WKWebViewSuspendPage /Volumes/Data/worker/iOS-14-Simulator-Build-EWS/build/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSuspension.mm:192 Value of: [webView allowsLinkPreview] Actual: true Expected: false Looks like this property has a different default value on iOS than macOS is all.
Chris Dumez
Comment 27 2021-05-11 11:10:28 PDT
(In reply to Chris Dumez from comment #26) > (In reply to Geoffrey Garen from comment #25) > > iOS EWS is angry: TestWebKitAPI.ProcessSuspension.WKWebViewSuspendPage > > It is minor, will fix. > > TestWebKitAPI.ProcessSuspension.WKWebViewSuspendPage > > > /Volumes/Data/worker/iOS-14-Simulator-Build-EWS/build/Tools/TestWebKitAPI/ > Tests/WebKitCocoa/ProcessSuspension.mm:192 > Value of: [webView allowsLinkPreview] > Actual: true > Expected: false > > Looks like this property has a different default value on iOS than macOS is > all. ``` /*! @abstract A Boolean value indicating whether link preview is allowed for any links inside this WKWebView. @discussion The default value is YES on Mac and iOS. */ @property (nonatomic) BOOL allowsLinkPreview WK_API_AVAILABLE(macos(10.11), ios(9.0)); ``` That doc seems to be a lie. Turns out it is true on both platforms.
Chris Dumez
Comment 28 2021-05-11 11:11:53 PDT
Chris Dumez
Comment 29 2021-05-11 11:15:39 PDT
Chris Dumez
Comment 30 2021-05-11 11:16:44 PDT
(In reply to Chris Dumez from comment #27) > (In reply to Chris Dumez from comment #26) > > (In reply to Geoffrey Garen from comment #25) > > > iOS EWS is angry: TestWebKitAPI.ProcessSuspension.WKWebViewSuspendPage > > > > It is minor, will fix. > > > > TestWebKitAPI.ProcessSuspension.WKWebViewSuspendPage > > > > > > /Volumes/Data/worker/iOS-14-Simulator-Build-EWS/build/Tools/TestWebKitAPI/ > > Tests/WebKitCocoa/ProcessSuspension.mm:192 > > Value of: [webView allowsLinkPreview] > > Actual: true > > Expected: false > > > > Looks like this property has a different default value on iOS than macOS is > > all. > > ``` > /*! @abstract A Boolean value indicating whether link preview is allowed for > any > links inside this WKWebView. > @discussion The default value is YES on Mac and iOS. > */ > @property (nonatomic) BOOL allowsLinkPreview WK_API_AVAILABLE(macos(10.11), > ios(9.0)); > ``` > > That doc seems to be a lie. Turns out it is true on both platforms. Never mind, looks like I misread the doc...
Chris Dumez
Comment 31 2021-05-11 11:41:10 PDT
Geoffrey Garen
Comment 32 2021-05-11 12:36:35 PDT
Comment on attachment 428303 [details] Patch r=me
EWS
Comment 33 2021-05-11 14:39:22 PDT
Committed r277341 (237600@main): <https://commits.webkit.org/237600@main> All reviewed patches have been landed. Closing bug and clearing flags on attachment 428303 [details].
Ryan Haddad
Comment 34 2021-05-11 20:38:35 PDT
This change has caused all WK2 layout tests to exit with an exception. It seems that there is a ton of this logging during test runs: Error: Attempt to call WKPageRef API/SPI on a suspended page, this is a client bug. https://build.webkit.org/#/builders/70/builds/2492
WebKit Commit Bot
Comment 35 2021-05-11 20:48:01 PDT
Re-opened since this is blocked by bug 225685
Chris Dumez
Comment 36 2021-05-11 21:02:48 PDT
Chris Dumez
Comment 37 2021-05-11 21:05:44 PDT
Chris Dumez
Comment 38 2021-05-11 21:26:39 PDT
EWS
Comment 39 2021-05-11 22:53:23 PDT
Committed r277356 (237614@main): <https://commits.webkit.org/237614@main> All reviewed patches have been landed. Closing bug and clearing flags on attachment 428344 [details].
Note You need to log in before you can comment on or make changes to this bug.