Skip to content

fix(ios): load host page, keyboards through a consistent WKURLSchemeHandler#16136

Merged
jahorton merged 4 commits into
masterfrom
fix/ios/load-via-scheme-handler
Jul 1, 2026
Merged

fix(ios): load host page, keyboards through a consistent WKURLSchemeHandler#16136
jahorton merged 4 commits into
masterfrom
fix/ios/load-via-scheme-handler

Conversation

@jahorton

@jahorton jahorton commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

These changes bypass any need to modify KMW keyboard loading (say, via .fetch), instead forcing all engine files and resources to load via the new scheme/protocol in order to accomplish its goal.

Alternate approaches considered:

  • monkeypatching fetches on file:// protocol calls to ping Swift for a file load, then pass the results back via JS call that resolves the associated fetch Promise.
    • Would require fewer changes, but would require that one point of monkeypatching.

Build-bot: skip release:ios,web

User Testing

TEST_IOS:

  • Install Keyman for iPhone and iPad from this PR
  • Verify that a keyboard properly shows
  • Verify that the predictive-text banner shows suggestions (use a keyboard/language with an associated lexical model)

TEST_IOS_CAMEROON:

  • Install Keyman for iPhone and iPad from this PR
  • Download and install the sil_cameroon_azerty keyboard
  • Verify that the keyboard's custom CSS displays properly.
  • Verify that the keyboard's display font (for the main keys) differs from that of sil_euro_latin.

TEST_FIRSTVOICES:

  • Install FirstVoices App from this PR
  • Verify that a keyboard properly shows

TEST_WEB:

  • Open KeymanWeb test page, navigate to any test
  • Select a keyboard and verify that it displays the OSK and that the console window doesn't show errors

TEST_WEB_KBD_DOCS:

  • Open KeymanWeb test page titled "Tests keyboard documentation rendering"
  • Verify that all keyboard renders load correctly and lack any obvious visual errors.

@github-project-automation github-project-automation Bot moved this to Todo in Keyman Jun 24, 2026
@keymanapp-test-bot keymanapp-test-bot Bot added the user-test-missing User tests have not yet been defined for the PR label Jun 24, 2026
@keymanapp-test-bot

keymanapp-test-bot Bot commented Jun 24, 2026

Copy link
Copy Markdown

User Test Results

Test specification and instructions

Test Artifacts

@mcdurdin mcdurdin left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like where this is going, some feedback and thoughts on how to tighten it up.

Comment thread web/src/engine/src/interfaces/pathConfiguration.ts
// Absolute
if((p.replace(/^(http)s?:.*/,'$1') == 'http') || (p.replace(/^(file):.*/,'$1') == 'file')) {
return p;
if(p.indexOf(this.protocol) == 0) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if(p.indexOf(this.protocol) == 0) {
if(p.startsWith(this.protocol)) {

But note that http vs https was catered for here previously whereas this change does not allow for that (so http <--> https will no longer work). This is probably not a big deal, but something to be aware of.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am actually more worried about this one now: if a user has a local website running http but sources KeymanWeb from https://s.keyman.com, will it break?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My local testing on Mac is done via http-server, meaning the local test site is based on http. It still uses https://api.keyman.com and https://s.keyman.com with zero issue.

Comment thread web/src/engine/src/interfaces/pathConfiguration.ts Outdated
}

updateFromOptions(pathSpec: Required<PathOptionSpec>) {
const _rootPath = this.sourcePath.replace(/(https?:\/\/)([^\/]*)(.*)/,'$1$2/');

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this also need fixup?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not exactly sure what it's doing, and I didn't need to change it, so I decided to leave this be.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if that will cause subtle issues somewhere given this only works with http[s]: and not with keyman-engine:. It might be good to understand why this is needed.


// Local function to convert relative to absolute URLs
// with respect to the source path, server root and protocol
fixPath(p: string) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this whole function be replaced with new URL(p, this.sourcePath)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd want to test that out more thoroughly as its own PR, rather than rolling it in here.

Comment thread ios/engine/KMEI/KeymanEngine/Classes/Keyboard/WebViewKeyboardLoader.swift Outdated
Comment thread web/src/engine/src/interfaces/pathConfiguration.ts Outdated
Comment thread ios/engine/KMEI/KeymanEngine/Classes/Keyboard/WebViewKeyboardLoader.swift Outdated
Comment thread ios/engine/KMEI/KeymanEngine/Classes/Keyboard/WebViewKeyboardLoader.swift Outdated
// +1: include the ':' that likely exists
pathComponent = String(components.path.dropFirst(KeymanWebViewController.SCHEME.count + 1))
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused about this piece of code. Surely pathComponent should never include keyman-engine:? That would be components.scheme?

Also, I think this would be a good place to collapse repeated slashes, both at start of string and beyond, because repeated slashes when building paths is a common bug and I think we can be resilient to it without real penalty.

That also removes the need to do that work in pathConfiguration.ts.

pathComponent = components.path.replacingOccurrences(of: "/+", with: "/", options: .regularExpression)

if pathComponent.hasPrefix("/") {
  pathComponent = pathComponent.dropFirst()
}

Something like that?

@jahorton jahorton Jun 25, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was an earlier attempt to work around issues in which URLs like the following appeared: keyman-engine:/keyman-engine:/kmwosk.css

It didn't work, which led to resolving things in Web engine code - the changes to pathConfiguration.ts, oskView.ts, and visualKeyboard.ts.

Will clean up now.

That also removes the need to do that work in pathConfiguration.ts.

pathComponent = components.path.replacingOccurrences(of: "/+", with: "/", options: .regularExpression)

if pathComponent.hasPrefix("/") {
  pathComponent = pathComponent.dropFirst()
}

... about that. If there are repeated leading slashes, URLComponents will consider the 'path' as the host, not a path! For most of our resources, this then results in a nil path, which is very much something we don't want. Some of the changes seen in pathConfiguration.ts were made b/c they're the easiest workaround... or were at the time.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... and fortunately, the fixes in OSK code resolved the cases that were causing this, so we can still knock the pathConfiguration.ts double-slash handling out!

@mcdurdin

Copy link
Copy Markdown
Member

One more thought; can we base this on #16132 so that we are looking at a consolidated fix for both platforms?

@jahorton

Copy link
Copy Markdown
Contributor Author

One more thought; can we base this on #16132 so that we are looking at a consolidated fix for both platforms?

Work is still ongoing there, and there's been at least one force-push to that branch since the quoted comment was posted. I'd have to re-force-push this branch every time a force-push happens there.

@jahorton jahorton force-pushed the fix/ios/load-via-scheme-handler branch from 2e9568e to b9a3c11 Compare June 25, 2026 15:47
@keymanapp-test-bot keymanapp-test-bot Bot added has-user-test user-test-required User tests have not been completed and removed user-test-missing User tests have not yet been defined for the PR labels Jun 25, 2026
@jahorton jahorton force-pushed the fix/ios/load-via-scheme-handler branch from b9a3c11 to 1f99b2d Compare June 25, 2026 16:07
jahorton added a commit that referenced this pull request Jun 25, 2026
Pretty much just what the title says; it's been silently missing this whole time.

This doesn't fix iOS keyboard's display by itself, but it is a prerequisite for the full solution offered by #16136.

Build-bot: skip build:ios
Test-bot: skip
jahorton added a commit that referenced this pull request Jun 25, 2026
Pretty much just what the title says; it's been silently missing this whole time.

This doesn't fix iOS keyboard's display by itself, but it is a prerequisite for the full solution offered by #16136.

Build-bot: skip build:ios
Test-bot: skip
@jahorton jahorton changed the base branch from master to fix/ios/bundle-globe-hint June 25, 2026 18:23
@jahorton jahorton force-pushed the fix/ios/load-via-scheme-handler branch from 1f99b2d to 08c2f25 Compare June 25, 2026 18:23
…andler

This bypasses any need to modify KMW keyboard loading (say, via .fetch), though it does require a number of collateral changes to be made in order for CORS, etc to be satisfied.

Build-bot: skip build:ios
jahorton added a commit that referenced this pull request Jun 26, 2026
Pretty much just what the title says; it's been silently missing this whole time.

This doesn't fix iOS keyboard's display by itself, but it is a prerequisite for the full solution offered by #16136.

Build-bot: skip build:ios
Test-bot: skip
@jahorton jahorton force-pushed the fix/ios/bundle-globe-hint branch from df26dc4 to 13e154f Compare June 26, 2026 19:38
@jahorton jahorton force-pushed the fix/ios/load-via-scheme-handler branch from 08c2f25 to b3ee271 Compare June 26, 2026 19:39
@jahorton jahorton marked this pull request as ready for review June 26, 2026 19:39
@Meng-Heng

Copy link
Copy Markdown
Contributor

Test Results

  • TEST_WEB (PASSED):
  1. Navigate to KeymanWeb Test Page
  2. Go to View Keymanweb website-oriented manual test pages -> Test unminified Keymanweb (unminified)
  3. Verified: Keyboards render fine without any visual nor console errors
  4. Verified: The keyboards switch and display correctly
  5. Verified: Typing on the selected keyboard work as expected.
  6. Go to View Keymanweb website-oriented manual test pages -> Prediction - robust testing (prediction-mtnt)
  7. Verified: Keyboards and Predictive text are working as expected
  8. Verified: Typing and switching keyboards are working perfectly
  9. Verified: Throughout the test period, the console does not have any error messages.
  • TEST_WEB_KBD_DOCS (PASSED):
  1. Continue with KeymanWeb Test Page
  2. Open KeymanWeb test page titled "Tests keyboard documentation rendering"
  3. Verified: all keyboard renders load beautifully
  4. Verified: there are no error visuals.

Note

For the TEST_WEB_KBD_DOCS test, the console has the following error https://build.palaso.org/repository/download/Keymanweb_TestPullRequests/630677:id/build/publish/debug/keymanweb-osk.ttf after the OSK loaded.

@Meng-Heng

Copy link
Copy Markdown
Contributor

Test Results

  • TEST_IOS (PASSED):
  1. Download and Install Keyman for iPhone and iPad v19.0.248-alpha-test-16136
  2. Verified: The EuroLatin (SIL) keyboard shows up with the predictive text
  3. Verified: Typing and using predictive text work as expected
  • TEST_IOS_CAMEROON (PASSED):
  1. Continue from the test above without restarting the app
  2. Go to Settings -> Install Keyboard -> Download the Cameroon Azerty keyboard
  3. Verified: The CSS displays accordingly with its unique font.

Note

Screenshot 2026-06-29 at 1 55 51 in the afternoon
The App had been stuck at loading when launched without any error messages. The app was dismissed and relaunched to get through the loading screen.

@keymanapp-test-bot keymanapp-test-bot Bot removed the user-test-required User tests have not been completed label Jun 29, 2026
@jahorton

Copy link
Copy Markdown
Contributor Author

Note

For the TEST_WEB_KBD_DOCS test, the console has the following error https://build.palaso.org/repository/download/Keymanweb_TestPullRequests/630677:id/build/publish/debug/keymanweb-osk.ttf after the OSK loaded.

Thanks for catching that! Could you retest and verify that these errors no longer occur?

@keyman-test-bot retest TEST_WEB_KBD_DOCS

Comment thread ios/engine/KMEI/KeymanEngine/Classes/Keyboard/WebViewSchemeHandler.swift Outdated
Comment thread ios/engine/KMEI/KeymanEngine/Classes/Keyboard/WebViewSchemeHandler.swift Outdated
Comment on lines +1376 to +1388
browser?: DeviceSpec.Browser
} = {};

// Device emulation for target documentation.
device.formFactor = formFactor;
if (formFactor != 'desktop') {
device.OS = DeviceSpec.OperatingSystem.iOS;
device.touchable = true;
device.browser = DeviceSpec.Browser.Safari;
} else {
device.OS = DeviceSpec.OperatingSystem.Windows;
device.touchable = false;
device.browser = DeviceSpec.Browser.Chrome;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why these changes? device.browser doesn't appear to be used anywhere else in the PR?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the changes at lines 1404 - 1408 - they're needed to complete the requirements of the DeviceSpec type needed for the .hostDevice field of getResourcePath's parameter.

Alternatively, we could mock it out with null, but that could become prone to breakage. Or we could rework the getResourcePath method to use just pathConfig.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, makes sense, long term would be good if getResourcePath didn't require device info

jahorton and others added 2 commits June 29, 2026 22:21
Co-authored-by: Marc Durdin <marc@durdin.net>
We don't actually pass JSON through our scheme handler yet, but just in case... we ensure we detect JSON's MIME type and annotate appropriately
@Meng-Heng

Copy link
Copy Markdown
Contributor

TEST_WEB_KBD_DOCS (PASSED):

  1. Open KeymanWeb Test Page
  2. Navigate to KeymanWeb test page titled "Tests keyboard documentation rendering"
  3. Verified: all keyboard renders beautifully
  4. Verified: there are no error visuals
  5. Verified: no error in console.

@mcdurdin

Copy link
Copy Markdown
Member

We need a user test for FirstVoices Keyboards also

@keymanapp-test-bot keymanapp-test-bot Bot added the user-test-required User tests have not been completed label Jun 30, 2026
@jahorton

Copy link
Copy Markdown
Contributor Author

We need a user test for FirstVoices Keyboards also

Added. Also made sure it at least works on my local build.

@Meng-Heng

Copy link
Copy Markdown
Contributor

I can't seem to find the build for FirstVoices. Please help check

@mcdurdin

mcdurdin commented Jul 1, 2026

Copy link
Copy Markdown
Member

I can't seem to find the build for FirstVoices. Please help check

The iOS build is currently disabled due to updates that the FirstVoices team need to make on App Store Connect.

Given @jahorton verified that a local build works, we'll move forward with that for now.

TEST_FIRSTVOICES PASS

@keymanapp-test-bot keymanapp-test-bot Bot removed the user-test-required User tests have not been completed label Jul 1, 2026
Base automatically changed from fix/ios/bundle-globe-hint to master July 1, 2026 14:56
@jahorton jahorton merged commit 824925a into master Jul 1, 2026
10 checks passed
@github-project-automation github-project-automation Bot moved this from Todo to Done in Keyman Jul 1, 2026
@jahorton jahorton deleted the fix/ios/load-via-scheme-handler branch July 1, 2026 14:57
@keyman-server

Copy link
Copy Markdown
Collaborator

Changes in this pull request will be available for download in Keyman version 19.0.250-alpha

@ermshiperete

Copy link
Copy Markdown
Contributor

Fixes iOS part of #16096

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

bug(web): blank keyboard after installing Keyman for Android or Keyman for iOS 19.0.242 or later

5 participants