WebKit PushStateFilePathRestriction

Hello,

The iPadOS application I'm working on has a WKWebView which should provide an Angular app. That does still work but the routing in the javascript based application isn't anymore.

The error I can inspect begins with following snippet:
.

ERROR Error: Uncaught (in promise): SecurityError: Blocked attempt to use history.pushState() to change session history URL from file:///Users/rindlisbacher/Library/Developer/CoreSimulator/Devices/436628E4-8D12-43E4-AE7B-8FFADA02E510/data/Containers/Bundle/Application/A17AC11F-2251-4414-A5F4-C4BC7876A0B6/APPNAME.app/index.html/ to file:///Users/rindlisbacher/Library/Developer/CoreSimulator/Devices/436628E4-8D12-43E4-AE7B-8FFADA02E510/data/Containers/Bundle/Application/A17AC11F-2251-4414-A5F4-C4BC7876A0B6/APPNAME.app/index.html/dashboard. Only differences in query and fragment are allowed for file: URLs.

Since the the path must match in the URLs I have a problem.

What I have found so far:

It seems that the WebKit browser engine has a behaviour that isn't disabled anymore, if I interpret the source file (RuntimeApplicationsChecksCocoa.cpp) correctly:

    if (linkedBefore(dyld_spring_2023_os_versions, DYLD_IOS_VERSION_16_4, DYLD_MACOSX_VERSION_13_3)) {
        ...
        disableBehavior(SDKAlignedBehavior::PushStateFilePathRestriction);
        ...
    }

So the check is executed and my routing fails.

Check on local files:

    if (fullURL.isLocalFile()
#if PLATFORM(COCOA)
        && linkedOnOrAfterSDKWithBehavior(SDKAlignedBehavior::PushStateFilePathRestriction)
#endif
        && fullURL.fileSystemPath() != documentURL.fileSystemPath()) {
        return createBlockedURLSecurityErrorWithMessageSuffix("Only differences in query and fragment are allowed for file: URLs.");
    }

Does someone know something about that and is there a workaround or something? Maybe a configuration issue..? I couldn't find anything

macOS: 13.3.1 (22E261)
Xcode: 14.3 (14E222b)
Simulation: iPadPro (11-inch) 4th generation - iOS 16.4

Thanks in advance

José

Answered by _microwAve in 754044022

I failed so far to return after I found a solution to our problem. Just in case anyone is still interested in a possible solution, I'll share my findings.

There is an Angular interface called NavigationBehaviourOptions that has a property called skipLocationChange. If set to true, the navigation will not push the state to history, so there is no specification violation anymore.

Documentation:

https://angulardoc.com.br/api/router/NavigationBehaviorOptions

So basically, we added this property as attribute in all the routerLink anchor elements.

To tackle the routers initial navigation there is an ExtraOption to disable that:

https://angular.io/api/router/InitialNavigation

I am also having trouble with the same phenomenon.

I would appreciate it if you could let me know how to deal with it.

This is due to a change in WebKit (https://github.com/WebKit/WebKit/commit/78a55cf3976ce0b4543df42b03c335c5b89d27dd) to match the HTML spec with regards to pushState and file: URLs: https://html.spec.whatwg.org/multipage/history.html#can-have-its-url-rewritten

  1. If targetURL's scheme is "file", and targetURL and documentURL differ in their path component, then return false. (Differences in query and fragment are allowed for file: URLs.)

So it's fine to use pushState with file: URLs to go from index.html to index.html#/dashboard, but it is not allowed to go from index.html to index.html/dashboard.

Maybe your framework has an option to use hash-based URLs for routing?

The other alternative would be to use a custom scheme to serve your content instead of file: URLs.

Accepted Answer

I failed so far to return after I found a solution to our problem. Just in case anyone is still interested in a possible solution, I'll share my findings.

There is an Angular interface called NavigationBehaviourOptions that has a property called skipLocationChange. If set to true, the navigation will not push the state to history, so there is no specification violation anymore.

Documentation:

https://angulardoc.com.br/api/router/NavigationBehaviorOptions

So basically, we added this property as attribute in all the routerLink anchor elements.

To tackle the routers initial navigation there is an ExtraOption to disable that:

https://angular.io/api/router/InitialNavigation

WebKit PushStateFilePathRestriction
 
 
Q