Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

History API unavailable for URLs with 'file:' protocol #1592

Conversation

eliotsykes
Copy link

Browsers that usually support the History API will disable it when the current URL is served off the filesystem with the file: protocol.

By including this protocol check, this becomes a more accurate test for apps running in Cordova/PhoneGap/similar, as HTML files in these scenarios are served locally off the device filesystem (so with location.protocol === 'file:'). Although the browser used by the Cordova app may support the history API, it doesn't with the file: protocol.

Browsers that usually support the History API will disable it when
the current URL is served off the filesystem with the 'file:'
protocol.

By including this protocol check, this becomes a more accurate test for
apps running in Cordova/PhoneGap/similar, as HTML files in these
scenarios are served locally off the device filesystem (so with
location.protocol === 'file:'). Although the browser used by the
Cordova app may support the history API, it doesn't with the 'file:'
protocol.
@eliotsykes
Copy link
Author

If this is accepted, I'd like to add a test for this feature detect, though I'll need a nudge in the right direction please! Many thanks :-)

@modernizr-savage
Copy link

Tests failed. Automated cross-browser testing via Sauce Labs and Travis CI shows that the JavaScript changes in this pull request are: BUSTED

Commit: 56d0c21
Build details: https://travis-ci.org/modernizr-savage/Modernizr/builds/61789388

(Please note that this is a fully automated comment.)

@eliotsykes
Copy link
Author

I'm unsure how to proceed debugging this test failure on Travis, advice very much welcome:

Tested http://localhost:9999/test/index.html
Platform: ,firefox,beta
Passed: false
Url https://saucelabs.com/jobs/1bcddaea880444978037ac26abaa83c3

@eliotsykes
Copy link
Author

Ok, it looks like that CI failure is acceptable.

@patrickkettner
Copy link
Member

A test would be great. I am not sure if we can have one that will work on sauce, but we can get one that should work in at least phantom and when run locally via a redirect in the grunt-connect block (similar to how we do the transforms redirect)

Would you happen to be able to find if this is just the standard behavior, or is it spec`ed as a standards behavior?

@eliotsykes
Copy link
Author

Thanks @patrickkettner,

In my excitement to get this fixed, I'd wrongly and naively assumed all browsers with the History API would disable it on file: protocol URLs.

Turns out that isn't the case - sorry...

Would you happen to be able to find if this is just the standard behavior, or is it spec`ed as a standards behavior?

There's nothing in the spec about the file: protocol. (The security precautions mentioned in the spec seem to be around allowing access to the History API for navigation to URLs under the same origin.)

It appears Chrome has never fully supported the history API for file: URLs, and there doesn't appear to be a plan to enable it: https://code.google.com/p/chromium/issues/detail?id=301210

Firefox 37.0.2 does not support the history API on file: URLs. Its unclear if this has always been the case. (Mozilla Security Review on pushState: https://wiki.mozilla.org/Firefox_3.6/PushState_Security_Review)

Safari 7.1.6 and Opera 12 support the history API on file: URLs.

For both Chrome and Firefox, with the file: protocol, they do have limited support for the history API. pushState operations are allowed if they don't specify a new URL, or only change the fragment identifier/hashtag. For example, all of these seemed to work ok in Chrome and Firefox:

Address Bar URL: file://some/path/to/test.html

Worked in console:

history.pushState({}, "title");
history.pushState({}, "title", "test.html") // Same URL
history.pushState({}, "title", "#xyz") // Only changes fragment identifier

Bearing all of this in mind, I'm not sure where to take this next. Options include:

  • Forget these corner cases and leave history feature detect as it was

Or add (some of) these to the history feature detect:

  • User agent sniffing for Chrome, Firefox paired with a location.protocol === 'file:' check
  • Try a history operation. pushState, replaceState throw a SecurityError in Chrome if its not possible. Catch error.

Feedback, ideas welcome

@patrickkettner
Copy link
Member

So I think the way we would do this would be to change the url then change it back to what it was previously, but that feels really dangerous. I have always been of the opinion that we shouldn't try to update the url, but in theory that operation should be safe - it would either break before the first change or never.

@ryanseddon @stucox @SlexAxton - what do yall think?

@eliotsykes
Copy link
Author

@patrickkettner this earlier PR is relevant, about various (potentially intrusive) history detect methods: #1270

Also starting to wonder if there's scope for finer-grained detects here, such as:

  • history-protocol-file
  • history-protocol-http
  • history-protocol-https (if history became a TLS/SSL-only feature in any browsers)
  • history-hashchange-only
  • history-full-support
  • history-half-baked-support

Are you aware of any other detects that have been broken down to support finer-grained detects?

Regarding the potentially dangerous history test, where modernizr performs a push/replaceState, could that be an opt-in only test, that is off by default? Are off-by-default, opt-in-required detects already in the library for other features?

@patrickkettner
Copy link
Member

Also starting to wonder if there's scope for finer-grained detects here, such as:

ehhhhhh....... put yourself in the shoes of Joe Developer, who has no idea about all of these edge cases. Having that many detects would almost certainly just cause more confusion. Ideally those things are contained within the detect itself. The closest thing to being broken down in a kindof sort of not really way is the flexbox detects, which have separate tests for the separate versions of flexbox that shipped over the years.

could that be an opt-in only test

all the tests are opt in - the issue is how do we let users know we are mucking about with their history. I am pretty sure it would be ok to do this, since it should either work in the switch and switch back, or won't work at all. I would just like some input from other memebers of the @Modernizr/modernizr-commit team

patrickkettner added a commit to patrickkettner/Modernizr that referenced this pull request Jul 15, 2016
patrickkettner added a commit that referenced this pull request Jul 15, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants