WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
229116
WebKit might load custom URI scheme request content multiple times
https://bugs.webkit.org/show_bug.cgi?id=229116
Summary
WebKit might load custom URI scheme request content multiple times
Yu-Wei Wu
Reported
2021-08-14 21:53:02 PDT
Here's the repo and steps to reproduce the subtle bug I encountered:
https://github.com/wusyong/gtkbrowser
It opens 10 webview windows. All of them share the same web context which registers a "gtk" URL scheme that loads a simple HTML. But some window's pages will be stolen by others. (One window will show nothing and the other will display two HTML files) I've tried adding locks but it has to be added after "load_changed" signal. Otherwise, the situation is still the same. And if I do so, it'll take a long time to show all windows (each window is displayed one by one)
Attachments
Patch
(6.41 KB, patch)
2021-09-07 20:03 PDT
,
Michael Catanzaro
no flags
Details
Formatted Diff
Diff
Test case
(1.63 KB, text/x-csrc)
2021-09-09 14:00 PDT
,
Michael Catanzaro
no flags
Details
Patch
(12.46 KB, patch)
2021-09-09 18:13 PDT
,
Michael Catanzaro
ews-feeder
: commit-queue-
Details
Formatted Diff
Diff
Patch
(11.82 KB, patch)
2021-09-09 18:19 PDT
,
Michael Catanzaro
no flags
Details
Formatted Diff
Diff
Patch
(11.82 KB, patch)
2021-09-09 18:21 PDT
,
Michael Catanzaro
ews-feeder
: commit-queue-
Details
Formatted Diff
Diff
Patch
(11.83 KB, patch)
2021-09-09 18:25 PDT
,
Michael Catanzaro
no flags
Details
Formatted Diff
Diff
Patch
(12.55 KB, patch)
2021-09-09 19:20 PDT
,
Michael Catanzaro
no flags
Details
Formatted Diff
Diff
Patch
(15.34 KB, patch)
2021-09-14 15:52 PDT
,
Michael Catanzaro
no flags
Details
Formatted Diff
Diff
Patch
(13.04 KB, patch)
2021-09-20 12:08 PDT
,
Alex Christensen
no flags
Details
Formatted Diff
Diff
Show Obsolete
(7)
View All
Add attachment
proposed patch, testcase, etc.
Michael Catanzaro
Comment 1
2021-09-07 19:19:40 PDT
Unfortunately WebKit is invoking the WebKitURISchemeRequestCallback multiple times with the same WebKitURISchemeRequest object. Then WebKit gets very confused because the application called webkit_uri_scheme_request_finish() multiple times with the same object, but this is WebKit's fault for reusing the same WebKitURISchemeRequest in the first place. It actually trips an assert in WebKit::WebKitURISchemeHandler::platformStartTask, in WebKitWebContext.cpp: ASSERT(addResult.isNewEntry); but we compile out ASSERTs in release builds, and nobody tests debug builds because they ASSERT too much, because nobody tests debug builds. :) The problem is that the UI process uses task IDs to distinguish between different WebURLSchemeTask objects, and reasonably expects the task IDs to be globally-unique. But the task IDs are actually generated in the web process in WebURLSchemeTaskProxy::startLoading using ResourceLoader::identifier, which uses ProgressTracker::createUniqueIdentifier, which just increments a counter variable, so they're only unique to a given web process, not unique in the web process. In your test program, all 10 tasks have the same ID: 1. Oops! It's a cross-platform bug btw, nothing GTK-specific here. Probably not hard to fix, but I'm too tired to think it through tonight.
Michael Catanzaro
Comment 2
2021-09-07 20:03:37 PDT
Created
attachment 437584
[details]
Patch
Michael Catanzaro
Comment 3
2021-09-07 20:09:09 PDT
(In reply to Michael Catanzaro from
comment #1
)
> It's a cross-platform bug btw, nothing GTK-specific here. Probably not hard > to fix, but I'm too tired to think it through tonight.
Well actually it was easy. The attached patch fixes the bug, but I need to write an API test before it is ready for real review. That said, I'm CCing WK2 owners early to make sure owners are OK with this approach. Basically I just have WebURLSchemeTask store the task ID it receives from the web process and use it for all communications with the web process, but expose an entirely different task ID to the UI process. BTW: great bug report, your test program made it easy to reproduce.
Michael Catanzaro
Comment 4
2021-09-07 20:11:09 PDT
(In reply to Michael Catanzaro from
comment #1
)
> so they're only unique to a given web process, not unique in the > web process.
I meant to write: not unique in the UI process.
Michael Catanzaro
Comment 5
2021-09-09 14:00:20 PDT
Created
attachment 437779
[details]
Test case For posterity, I'm attaching the test case from
https://github.com/wusyong/gtkbrowser/blob/master/browser.c
Michael Catanzaro
Comment 6
2021-09-09 18:13:56 PDT
Created
attachment 437816
[details]
Patch
Michael Catanzaro
Comment 7
2021-09-09 18:14:53 PDT
Hi owners, this patch needs owner review. Thank you!
Darin Adler
Comment 8
2021-09-09 18:15:30 PDT
Comment on
attachment 437816
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=437816&action=review
> Source/WebKit/ChangeLog:13 > + unique in the web process. Ouch! Since we have multiple tasks with the same ID, they clobber
s/in the web process/in the UI process/
Michael Catanzaro
Comment 9
2021-09-09 18:19:12 PDT
Created
attachment 437817
[details]
Patch
Michael Catanzaro
Comment 10
2021-09-09 18:21:17 PDT
(In reply to Darin Adler from
comment #8
)
> s/in the web process/in the UI process/
Oops, yes, copied that typo straight from
comment #1
.
Michael Catanzaro
Comment 11
2021-09-09 18:21:26 PDT
Created
attachment 437818
[details]
Patch
Michael Catanzaro
Comment 12
2021-09-09 18:25:43 PDT
Created
attachment 437820
[details]
Patch
Michael Catanzaro
Comment 13
2021-09-09 19:20:25 PDT
Created
attachment 437825
[details]
Patch
Alex Christensen
Comment 14
2021-09-09 20:45:24 PDT
Comment on
attachment 437825
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=437825&action=review
I looked into whether this problem affects WKWebView and it doesn't seem that it does because in WKWebView._initializeWithConfiguration we create a WebURLSchemeHandlerCocoa for each WKWebView and for each scheme. You might consider doing something similar in webkit_web_context_register_uri_scheme to fix this instead to make the ports more similar instead of adding code only needed by one port in common port-agnostic code.
> Source/WebKit/UIProcess/WebURLSchemeTask.h:105 > uint64_t m_identifier; > + uint64_t m_webProcessTaskIdentifier;
We want to use strongly typed identifiers instead of expanding the use of uint64_t. See PageIdentifier.h et al.
Michael Catanzaro
Comment 15
2021-09-10 07:43:10 PDT
(In reply to Alex Christensen from
comment #14
)
> I looked into whether this problem affects WKWebView and it doesn't seem > that it does because in WKWebView._initializeWithConfiguration we create a > WebURLSchemeHandlerCocoa for each WKWebView and for each scheme. You might > consider doing something similar in webkit_web_context_register_uri_scheme > to fix this instead to make the ports more similar instead of adding code > only needed by one port in common port-agnostic code.
Hm, that seems OK to me, but it would only make sense if we make some bigger cross-platform changes in WebURLSchemeHandler.h. Currently WebURLSchemeHandler::startTask and WebURLSchemeHandler::stopTask take a WebPageProxy parameter, implying that each task may safely use a different WebPageProxy. There is also WebURLSchemeHandler::stopAllTasksForPage. If we go with your approach, then we should change WebURLSchemeHandler to take the WebPageProxy as a parameter of its constructor instead, drop it as a parameter from the other functions, and rename stopAllTasksForPage to just stopAllTasks. Agreed? I kinda prefer my existing solution, but I'll try to implement this if you prefer. But I don't want to leave WebURLSchemeHandler broken, so it requires cross-platform changes either way.
> > Source/WebKit/UIProcess/WebURLSchemeTask.h:105 > > uint64_t m_identifier; > > + uint64_t m_webProcessTaskIdentifier; > > We want to use strongly typed identifiers instead of expanding the use of > uint64_t. See PageIdentifier.h et al.
Yeah OK, makes sense.
Alex Christensen
Comment 16
2021-09-10 09:30:37 PDT
I don't think I have a strong opinion on the approach. Your approach actually seemed fine to me, and I think it matches the WKURLSchemeHandler API closer to have one object that can be attached to multiple pages. We may want to change WKWebView._initializeWithConfiguration. But the strongly typed identifiers will help everything.
Michael Catanzaro
Comment 17
2021-09-10 15:19:00 PDT
OK, in that case I'll change to a strongly-typed identifier but otherwise keep the patch the same.
Michael Catanzaro
Comment 18
2021-09-10 15:29:31 PDT
(In reply to Michael Catanzaro from
comment #17
)
> OK, in that case I'll change to a strongly-typed identifier but otherwise > keep the patch the same.
Actually, changing these to use ObjectIdentifier will require a significant amount of code changes that will significantly complicate this patch. It's cleaner to leave this patch as-is, and convert to ObjectIdentifier in a follow-up patch in a different bug. Will try that now.
Michael Catanzaro
Comment 19
2021-09-10 17:32:38 PDT
(In reply to Alex Christensen from
comment #16
)
> But the strongly typed identifiers will help everything.
This was a good idea, because it found a bug. My patch actually breaks WebPageProxy::stopURLSchemeTask by misusing the web process identifier in the UI process, which I failed to notice until I tried converting it to strongly typed identifiers. I don't immediately see an easy way to fix it, so will need to continue this next week.
Michael Catanzaro
Comment 20
2021-09-13 13:47:39 PDT
(In reply to Michael Catanzaro from
comment #19
)
> This was a good idea, because it found a bug.
FWIW there was actually no bug in the initial patch after all. I just got confused when doing the refactoring to strongly-typed identifiers.
Michael Catanzaro
Comment 21
2021-09-13 14:05:58 PDT
(In reply to Michael Catanzaro from
comment #20
)
> FWIW there was actually no bug in the initial patch after all. I just got > confused when doing the refactoring to strongly-typed identifiers.
Just kidding, there really is a bug, but one level deeper, in WebURLSchemeHandler::stopTask. After my patch, this function receives web process task IDs but expects to operate on the UI process task IDs. Oops.
Michael Catanzaro
Comment 22
2021-09-14 15:52:36 PDT
Created
attachment 438183
[details]
Patch
Michael Catanzaro
Comment 23
2021-09-14 15:54:29 PDT
Comment on
attachment 438183
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=438183&action=review
OK Alex, here is round two. This is basically the same as the original patch but with WebURLSchemeHandler::stopTask fixed. OK? I have a separate patch in
bug #230278
that converts to strongly-typed identifiers. That patch is pretty big and would obscure the fix here if combined into one, so I think it's more appropriate to land them separately.
> Source/WebKit/UIProcess/WebURLSchemeHandler.cpp:95 > -void WebURLSchemeHandler::stopTask(WebPageProxy& page, uint64_t taskIdentifier) > +void WebURLSchemeHandler::stopTaskWithIdentifier(WebPageProxy& page, uint64_t taskIdentifier)
This is a little confusing, but it will be cleaned up in the patch in
bug #230278
.
Alex Christensen
Comment 24
2021-09-14 20:20:53 PDT
Comment on
attachment 438183
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=438183&action=review
I really think the strong typing needs to be done before this. It's hard to see whether this is correct or not.
> Source/WebKit/UIProcess/WebURLSchemeHandler.cpp:113 > + for (auto& t : m_tasks.values()) { > + if (t->webProcessTaskID() == webProcessTaskIdentifier) {
This isn't good. The whole point of a HashMap is so that we don't have to look at all the values. This takes a O(1) algorithm and makes it an O(n) algorithm.
Michael Catanzaro
Comment 25
2021-09-15 08:14:53 PDT
(In reply to Alex Christensen from
comment #24
)
> I really think the strong typing needs to be done before this. It's hard to > see whether this is correct or not.
Problem is strong typing works really hard to avoid bugs like this, so it's quite awkward to introduce the strong typing without fixing this bug at the same time. It's possible, but I would have to explicitly write the mistake into the strong typing patch by explicitly converting from WebURLSchemeTaskProxyIdentifier to uint64 to WebURLSchemeTaskIdentifier. Then this follow-up patch would be simplified to just removing that forced mistake. So really it doesn't make sense to do it that way. Another alternative would be to do it all in one patch, which is actually what I have in
bug #230278
right now, but that really obscures the nature of the fix by hiding it among a much larger diff. So that's why I split it up this way. ObjectIdentifier is pretty great. The more we use it, the fewer mistakes we'll have.
> > Source/WebKit/UIProcess/WebURLSchemeHandler.cpp:113 > > + for (auto& t : m_tasks.values()) { > > + if (t->webProcessTaskID() == webProcessTaskIdentifier) { > > This isn't good. The whole point of a HashMap is so that we don't have to > look at all the values. This takes a O(1) algorithm and makes it an O(n) > algorithm.
That's true. I was thinking it'd be OK because I would expect the number of URL scheme tasks to always be very small (in general, there should only be one), but considering it today, I agree with you: there is already a second HashMap here to avoid iterating over the primary map elsewhere in this file, and its presence implies a design decision to avoid the cost of looping, and it would be inconsistent to loop here but not there. The solution to avoid this is to add a third HashMap to WebURLSchemeHandler. Extra storage cost should be negligible since, again, the normal case is going to be zero or one task in flight. There will be some additional accounting complexity in the other functions of this file since WebURLSchemeHandler would be maintaining three HashMaps in sync rather than the current two. So there is a trade-off between time vs. storage. But I suspect it doesn't matter much at all either way, because the maps should be very small, so I'm fine with whichever way you prefer. Do you want me to add the third HashMap? (If not, we would need to retain the loop here.)
Michael Catanzaro
Comment 26
2021-09-15 08:19:47 PDT
Hm, it looks like this latest patch actually broke the URI scheme handler test for both GTK and Mac ports (two separate tests). That's no good. I'll need to investigate it.
Michael Catanzaro
Comment 27
2021-09-15 08:51:15 PDT
(In reply to Michael Catanzaro from
comment #26
)
> Hm, it looks like this latest patch actually broke the URI scheme handler > test for both GTK and Mac ports (two separate tests). That's no good. I'll > need to investigate it.
Unfortunately the GTK test always passes for me locally. Drat. That makes this hard. :/
Alex Christensen
Comment 28
2021-09-20 12:08:12 PDT
Created
attachment 438707
[details]
Patch
EWS
Comment 29
2021-09-20 14:36:51 PDT
Committed
r282783
(
241918@main
): <
https://commits.webkit.org/241918@main
> All reviewed patches have been landed. Closing bug and clearing flags on
attachment 438707
[details]
.
Radar WebKit Bug Importer
Comment 30
2021-09-20 14:37:19 PDT
<
rdar://problem/83324926
>
Michael Catanzaro
Comment 31
2021-09-21 08:21:15 PDT
Thanks Alex!
Yu-Wei Wu
Comment 32
2021-09-21 08:25:17 PDT
The comments are detailed and patches are quick. Realy appreciated. Thank you all!
Michael Catanzaro
Comment 33
2021-09-21 08:29:02 PDT
Unfortunately the new test is timing out on the bots. :/ Follow-up in
bug #230556
.
Michael Catanzaro
Comment 34
2021-09-21 08:42:30 PDT
(In reply to Yu-Wei Wu from
comment #32
)
> The comments are detailed and patches are quick. > Realy appreciated. Thank you all!
Note the version of this patch that landed fixed the cross-platform bug, but the GTK/WPE API is still broken, so doesn't actually help you. We will follow up in that
bug #230556
.
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