Bug 242827

Summary: REGRESSION (252335@main): overriding language per WKContext no longer works
Product: WebKit Reporter: Yury Semikhatsky <yurys>
Component: WebKit APIAssignee: Myles C. Maxfield <mmaxfield>
Status: RESOLVED MOVED    
Severity: Normal CC: ap, cdumez, mmaxfield, webkit-bug-importer, wenson_hsieh
Priority: P2 Keywords: InRadar
Version: WebKit Nightly Build   
Hardware: Unspecified   
OS: Unspecified   
See Also: https://bugs.webkit.org/show_bug.cgi?id=242584
Bug Depends on: 242581, 242584    
Bug Blocks:    

Yury Semikhatsky
Reported 2022-07-15 16:32:48 PDT
After 252335@main it is no longer possible to override language per WKContext via public API. We are actively using that API to run multiple pages with different language settings (in playwright automation tests). I'm not sure what breaks when the language differs between GPU process and Web Process but the previous logic served our customers well. Is it possible to revert the part of the PR that removed WKContextConfigurationSetOverrideLanguages implementation or add a new way that would allow to run multiple pages in the same browser instance that have different language settings?
Attachments
Alexey Proskuryakov
Comment 1 2022-07-15 17:30:34 PDT
Could you please clarify which public API you are using?
Radar WebKit Bug Importer
Comment 2 2022-07-15 17:30:49 PDT
Yury Semikhatsky
Comment 3 2022-07-15 18:52:30 PDT
(In reply to Alexey Proskuryakov from comment #1) > Could you please clarify which public API you are using? WKContextConfigurationSetOverrideLanguages (https://github.com/WebKit/WebKit/blob/8f75ae36260cdc7aff28822500d04e423e1b2c73/Source/WebKit/UIProcess/API/C/WKContextConfigurationRef.h#L73)
Yury Semikhatsky
Comment 4 2022-07-15 18:55:26 PDT
We'd actually want it to be exposed in the Cocoa, WPE and GTK APIs as well (can contribute that).
Myles C. Maxfield
Comment 5 2022-07-16 12:55:55 PDT
This is SPI, not API, and is just supposed to be for testing… I guess I can out it back… Do you need to have 2 web views alive at the same time with different override languages set?
Myles C. Maxfield
Comment 6 2022-07-16 12:58:16 PDT
Can you migrate to +[WKWebView setOverrideLanguagesForTesting:] ?
Myles C. Maxfield
Comment 7 2022-07-18 21:17:58 PDT
EWS
Comment 8 2022-07-20 10:08:01 PDT
Committed 252646@main (7b1621ce397b): <https://commits.webkit.org/252646@main> Reviewed commits have been landed. Closing PR #2535 and removing active labels.
Yury Semikhatsky
Comment 9 2022-07-25 11:28:22 PDT
(In reply to Myles C. Maxfield from comment #5) > This is SPI, not API, and is just supposed to be for testing… > Can you explain what you mean by this? Affected methods are called by the WebKit embedder and normally such methods are considered a part of the library API (as opposed to SPI provided by the embedder and called by WebKit itslelf), is it defined differently in in this case? Also the methods are declared in UIProcess/API/C/WKContextConfigurationRef.h which I believe is a part of the public C API (not a *Private.h header). > I guess I can out it back… > > Do you need to have 2 web views alive at the same time with different > override languages set? Yes. In our scenarios we need to be able to create multiple views with different language overrides. Before the change it worked as each WKContext could have different language override which was shared by the pages in the corresponding process pool but not affect pages from other process pools. (In reply to Myles C. Maxfield from comment #7) > Pull request: https://github.com/WebKit/WebKit/pull/2535 This doesn't actually restore previous behavior as it's the overrides are not isolated between process pools any more. Can we actually have the previous behavior that would address the case with different language overrides in different webviews as you mentioned above?
Yury Semikhatsky
Comment 10 2022-07-25 11:31:04 PDT
Myles, could you share more details on why it is important to have the same language override in the GPU process as in all web processes?
Myles C. Maxfield
Comment 11 2022-08-15 22:29:11 PDT
(Sorry, I didn't see this until now) > > This is SPI, not API, and is just supposed to be for testing… > Can you explain what you mean by this? Sure. The API to the macOS/iOS ports of WebKit is all written in Objective-C. See https://developer.apple.com/documentation/webkit?language=objc to list the official API. WKContextConfigurationSetOverrideLanguages() is a C function (not Objective-C) and isn't listed in the official API documentation. The only reason it exists is so WebKitTestRunner can implement the "<!-- webkit-test-runner: lang=something -->" feature. It's not intended for developers to use in production apps. The entire C interface to WebKit is considered to be SPI. Maybe we should move it to a folder named SPI/ to make this more clear... > why it is important to have the same language override in the GPU process as in all web processes Sure, you're right that the original bug didn't have much information about the motivation for this change. The original bug for that is rdar://96836865, which occurs when the user types the "[]" characters in Mail on iPad when the system language is set to Chinese. In this situation, the web process correctly looks up the Chinese system font and asks it which glyphs should be rendered for the "[]" characters. It then attempts to send the Chinese system font, along with the necessary "[]" glyphs, to the GPU Process for rendering. However, the system font is not a specific file on disk for macOS / iOS; instead, it's a higher-level concept that gets converted to a specific font late(r) in the rendering process. Thus, when we tell the GPU Process "please render these glyphs in the system font" the GPU Process looks up the system font _according to its own set locale_, finds a font, and renders those glyphs in it. However, the font the GPU Process found is not the same font that the web process found, so the glyphs turn out to draw arbitrary random characters. The solution was to make the locale of the web process equal to the locale of the GPU Process, so they both found the same system font. (There are probably other situations where rendering is locale-sensitive that this patch would have fixed too.) The problem, though, is that there's only ever a single GPU Process (per UI Process). So it's simple enough to mirror the locales in the Web Processes and the GPU Process from the UI process's locale, but if you want two Web Processes with different locales to render to the same GPU Process, the system font (and who knows what else) isn't going to work. This is kind of the result of the current single-GPU-Process architecture. Because WKContextConfigurationSetOverrideLanguages() is SPI and was only intended to be used by WebKitTestRunner (among other reasons), we think (thought?) this single-GPU-process architecture is an acceptable design. Maybe one day there will be multiple GPU processes, at which point we can support this use-case again. But who knows! I can't make any promises or predictions. The most straightforward workaround (though it's not a perfect one) would be to make sure the content uses the `lang` attribute. A more perfect workaround, albeit a large engineering task, would be for your own app to use multiple UI processes itself, so each one could get its own GPU Process and therefore its own language.
Yury Semikhatsky
Comment 12 2022-08-16 09:41:28 PDT
(In reply to Myles C. Maxfield from comment #11) > (Sorry, I didn't see this until now) > > > > This is SPI, not API, and is just supposed to be for testing… > > Can you explain what you mean by this? > > Sure. The API to the macOS/iOS ports of WebKit is all written in > Objective-C. See > https://developer.apple.com/documentation/webkit?language=objc to list the > official API. WKContextConfigurationSetOverrideLanguages() is a C function > (not Objective-C) and isn't listed in the official API documentation. The > only reason it exists is so WebKitTestRunner can implement the "<!-- > webkit-test-runner: lang=something -->" feature. It's not intended for > developers to use in production apps. > > The entire C interface to WebKit is considered to be SPI. Maybe we should > move it to a folder named SPI/ to make this more clear... > This is not how I read this document https://trac.webkit.org/wiki/WebKit2#CAPI that clearly states "WebKit2 provides a stable C-based non-blocking API that is mostly platform agnostic". Has that changed at some point? There are also port-specific APIs but they do not supersede C-API. Also this this is the only API which exists in WinCairo. > > why it is important to have the same language override in the GPU process as in all web processes > > Sure, you're right that the original bug didn't have much information about > the motivation for this change. The original bug for that is > rdar://96836865, which occurs when the user types the "[]" characters in > Mail on iPad when the system language is set to Chinese. In this situation, > the web process correctly looks up the Chinese system font and asks it which > glyphs should be rendered for the "[]" characters. It then attempts to send > the Chinese system font, along with the necessary "[]" glyphs, to the GPU > Process for rendering. However, the system font is not a specific file on > disk for macOS / iOS; instead, it's a higher-level concept that gets > converted to a specific font late(r) in the rendering process. Thus, when we > tell the GPU Process "please render these glyphs in the system font" the GPU > Process looks up the system font _according to its own set locale_, finds a > font, and renders those glyphs in it. However, the font the GPU Process > found is not the same font that the web process found, so the glyphs turn > out to draw arbitrary random characters. > > The solution was to make the locale of the web process equal to the locale > of the GPU Process, so they both found the same system font. (There are > probably other situations where rendering is locale-sensitive that this > patch would have fixed too.) The problem, though, is that there's only ever > a single GPU Process (per UI Process). So it's simple enough to mirror the > locales in the Web Processes and the GPU Process from the UI process's > locale, but if you want two Web Processes with different locales to render > to the same GPU Process, the system font (and who knows what else) isn't > going to work. > > This is kind of the result of the current single-GPU-Process architecture. > Because WKContextConfigurationSetOverrideLanguages() is SPI and was only > intended to be used by WebKitTestRunner (among other reasons), we think > (thought?) this single-GPU-process architecture is an acceptable design. > > Maybe one day there will be multiple GPU processes, at which point we can > support this use-case again. But who knows! I can't make any promises or > predictions. > Thanks for the detailed explanation, now it's more clear. Is it possible (at least in theory) to have a map WebProcess -> language in the GPU process and use that when deciding to which system font to use for rendering? From your description it sounds like the effect would be similar to having multiple GPU processes. > The most straightforward workaround (though it's not a perfect one) would be > to make sure the content uses the `lang` attribute. Unfortunately, this doesn't quite work as we can't modify the web app we are testing. Also the whole point is to test how the app will behave depending on the browser default locale. > A more perfect workaround, albeit a large engineering task, would be for your own app to > use multiple UI processes itself, so each one could get its own GPU Process > and therefore its own language. This could work as a fallback solution but would be much heavier than using browser context (WebSiteDataStore+WebProcessPool) for test isolation as it would require starting new UI, network, gpu, web processes for every test case while now we only need new web process. This is a big issue in terms of resource requirements especially when this is run on CI/in the cloud.
Myles C. Maxfield
Comment 13 2022-08-16 14:33:50 PDT
> This is not how I read this document https://trac.webkit.org/wiki/WebKit2#CAPI that clearly states "WebKit2 provides a stable C-based non-blocking API that is mostly platform agnostic". Has that changed at some point? There are also port-specific APIs but they do not supersede C-API. Also this this is the only API which exists in WinCairo. That text was written 12 years ago, and is stale. It was written before WebKit 2 was shipped in any port. I'll update that wiki text to make this more clear. Each port is solely responsible for determining its own API. The macOS / iOS ports chose to not include these functions in their API. Other ports may or may not make different decisions. > Is it possible (at least in theory) to have a map WebProcess -> language in the GPU process and use that when deciding to which system font to use for rendering? Right now, with the current architecture, this isn't possible: - Core Text functions don't accept the system language as an argument. Instead, they read the system language from the platform directly. So we can't directly tell Core Text which language to be using, but instead have to change the system language for the process as a whole. - The mechanism for changing the system language (NSNotification) is an asynchronous method, that does not have any affordances for knowing when the notification has been delivered, or ordering notification delivery. We can't send the notification from the Web Process to the GPU Process _and then_ relayout/repaint, because of the "and then" requirement - there are no ordering guarantees. The GPU Process can run code after it has received the notification, but it would be a mistake to add any mechanism for the GPU Process to cause the Web Process to relayout - that's a fundamentally backward information flow direction. The only way this could work is if Core Text released new, different, functions, which accept the system language as an argument. But Core Text is a native API so I can't comment on anything about that possibility. > Unfortunately, this doesn't quite work as we can't modify the web app we are testing. Also the whole point is to test how the app will behave depending on the browser default locale. Ah, yes, this makes sense. > This could work as a fallback solution but would be much heavier than using browser context (WebSiteDataStore+WebProcessPool) for test isolation as it would require starting new UI, network, gpu, web processes for every test case while now we only need new web process. This is a big issue in terms of resource requirements especially when this is run on CI/in the cloud. Yep, I get it. It seems like there's not a good solution right now :(
Myles C. Maxfield
Comment 14 2022-08-16 18:39:56 PDT
> The mechanism for changing the system language (NSNotification) Thinking about this more, there may be another mechanism. Let me think a bit more about this.
Myles C. Maxfield
Comment 15 2022-08-20 13:37:49 PDT
(Still discussing with the team.)
Myles C. Maxfield
Comment 16 2022-08-24 00:46:50 PDT
We're investigating this in rdar://99072008.
Myles C. Maxfield
Comment 17 2022-08-24 23:55:35 PDT
Yeah, it sounds like in order for this to work, there will need to be platform API involvement :( We can't just have the GPU Process change the system language around every call to font deserialization because Core Text internally caches things. There's no other way without Core Text involvement. Marking as MOVED to rdar://99072008. Sorry I couldn't get this working immediately :(
Note You need to log in before you can comment on or make changes to this bug.