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

Support for apps loaded from Windows file shares #2774

Merged
merged 1 commit into from
Jun 6, 2019
Merged

Support for apps loaded from Windows file shares #2774

merged 1 commit into from
Jun 6, 2019

Conversation

theozaurus
Copy link
Contributor

When loading an application from a Windows file share (not mapped to a network letter), Chrome will throw an error (cannot be created in a document with origin 'null') when replaceState is called. This happens because while protocol is file: and host is vboxsvr the origin is file:// as opposed to file://vboxsvr. This means the absolute path is not created correctly.

Only Windows shares that are not mapped to a drive letter are affected. If a drive letter is mapped then while origin will still be file://, pathname will include the information instead (e.g. /Z:/dist/index.html)

This code removes the reliance on the origin attribute and calculates the absolute path from protocol and host.

…k drives

When loading an application from a Windows file share (not mapped to a network letter), Chrome will throw an error ("cannot be created in a document with origin 'null'") when `replaceState` is called. This happens because while `protocol` is `file:` and `host` is `vboxsvr` the `origin` is `file://` as opposed to `file://vboxsvr`. This means the absolute path is not created correctly.

Only Windows shares that are not mapped to a drive letter are affected. If a drive letter is mapped then while origin will still be `file://`, pathname will include the information instead (e.g. `/Z:/dist/index.html`)

This code removes the reliance on the origin attribute and calculates the absolute path from `protocol` and `host`.
@posva
Copy link
Member

posva commented May 21, 2019

hey, thanks for the PR, do you have a repro when this happens (the content of an HTML file) + repro steps?

@theozaurus
Copy link
Contributor Author

@posva, I've got a large app that has the issue. It should be easy enough to create a small test case though provided a VM can be setup with the right network shares (I did it just using Virtualbox). Would you like me to create a small app to reproduce it?

@posva
Copy link
Member

posva commented May 21, 2019

yes, please the boiled down repro would be nice (fits in one small HTML file). Regarding the URL, shouldn't it also happen on UNIX-based filesystems file:///the-path/to/the/file.html?

@theozaurus
Copy link
Contributor Author

theozaurus commented May 21, 2019

Okay I've got a demo here: https://gist.github.com/theozaurus/7a13df223772a4e9b3459d9017eb0079

It works fine on a UNIX-based filesystem as the URL will be file:///the/path/to/the/file. With the tripple / the pathname gets set to /the/path/to/the/file. However, on a windows file share that does not have a drive letter associate with it the path is file://fileserver/sharename/path/to/the/file'. Here the pathname is only /sharename/path/to/the/file`.

@posva
Copy link
Member

posva commented May 21, 2019

Great, thank you very much for the indications, I will take a look in the following weeks!

@posva posva merged commit c2c78a3 into vuejs:dev Jun 6, 2019
@vue-bot
Copy link

vue-bot commented Jun 6, 2019

Hey @theozaurus, thank you for your time and effort spent on this PR, contributions like yours help make Vue better for everyone. Cheers! 💚

@tbl0605
Copy link

tbl0605 commented Mar 20, 2020

Hi,
I would like to share a specific problem I'm having using Edge and local windows filesystems.
I made a little gist inspired from the original gist made by @theozaurus to show the problem: https://gist.github.com/tbl0605/84ddbbd611390b70fc67e0ef2a059b20
When you host a file on a local windows filesystem, say "C:\2774_example.html",
and you open it using Edge, the URL in Edge will become "file:///C:/C:/2774_example.html",
which of course is totally wrong.
I don't know why but Edge's implementation of window.history.replaceState() doesn't handle well such kind of calls:

window.history.replaceState(null, '', '/C:/2774_example.html'); // URL will become "file:///C:/C:/2774_example.html"

but such kind of calls will work perfectly:

window.history.replaceState(null, '', 'C:/2774_example.html'); // URL will become "file:///C:/2774_example.html"

For now, I made an ugly workaround to overwrite method window.history.replaceState() so it can be correctly used by current vue-router's function setupScroll(): https://gist.github.com/tbl0605/a6af0b3208057ee6cf4fa4cac8c5e71e

And here is my workaround:

      function detectIE() {
        if (!window || !window.navigator || !window.navigator.userAgent) {
          return false;
        }
        var ua = window.navigator.userAgent;
        var msie = ua.indexOf('MSIE ');
        if (msie > 0) {
          // IE 10 or older => return version number
          return true;
        }
        var trident = ua.indexOf('Trident/');
        if (trident > 0) {
          // IE 11 => return version number
          return true;
        }
        var edge = ua.indexOf('Edge/');
        if (edge > 0) {
          // Edge (IE 12+) => return version number
          return true;
        }
        // other browser
        return false;
      }

      if (detectIE()) {
        let oldReplaceState = window.history.replaceState;
        window.history.replaceState = function(...args) {
          let matches,
            newArgs = [...args];
          if (
            newArgs.length >= 3 &&
            newArgs[2] &&
            // URLs like '/C:/my/path/to/2774_example.html' will be rewritten as 'my/path/to/2774_example.html'
            (matches = /^\/[A-Z]:(\/.*)$/gi.exec(newArgs[2].toString())) &&
            matches.length == 2
          ) {
            newArgs[2] = matches[1];
          }
          return oldReplaceState.apply(this, newArgs);
        };
      }

I don't know if there is much to do in vue-router's code to fix such kind of issue, but I wanted at least to share my workaround if some other people have same problem ;)

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.

4 participants