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

Workaround for #179 - use datalink for Chrome iOS #240

Merged
merged 1 commit into from
Jun 16, 2016

Conversation

ph4r05
Copy link
Contributor

@ph4r05 ph4r05 commented Jun 15, 2016

  • Blob links / url objects are not supported in Chrome iOS for now

closes #179

@@ -31,6 +31,7 @@ var saveAs = saveAs || (function(view) {
node.dispatchEvent(event);
}
, is_safari = /constructor/i.test(view.HTMLElement)
, is_chrome_ios =/CriOS\/[\d]+/.test(navigator.userAgent)
Copy link
Collaborator

@jimmywarting jimmywarting Jun 15, 2016

Choose a reason for hiding this comment

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

Not long ago i have switched the is_safari to test a webkit feature instead of doing browser sniffing on user agent

Safari's /constructor/i.test(view.HTMLElement) is uniq for Safari for Safari's webkit

And since Apple don't allow 3rd party browser engine chrome is basically stuck with running uiwebview or wkwebview
which is the same as running Safari basically.

So the conclusion here is: We can as well use is_safari instead of is_chrome_ios
Since chrome for ios also reports true for /constructor/i.test(view.HTMLElement)

@jimmywarting
Copy link
Collaborator

What those this really solve? see my comment. Chrome on ios should fall in to the same category as is_safari since it's the same rendering engine.

@ph4r05
Copy link
Contributor Author

ph4r05 commented Jun 15, 2016

With this condition datalink is used in case of Chrome for iOS.
I can test your suggestion, to use only is_safari and I will let you know how it works on Safari and Chrome for iOS.

Whats your opinion on:

  • opening a new page vs using previous with view.location.href. EDIT: Opening a new page with view.open(datalink, "_blank"); does not work in Safari, does work in CriOS.
  • using blob.type instead of "data:attachment/file" - which does not work in Chrome iOS?

@ph4r05
Copy link
Contributor Author

ph4r05 commented Jun 15, 2016

And I forgot, difference from is_safari is that for CriOS force == false thus datalink was not used

@ph4r05
Copy link
Contributor Author

ph4r05 commented Jun 15, 2016

Also a big difference for Safari & CriOS - blob: object links are working in Safari, not in CriOS. (Also the reason why force == false for CriOS. It uses object links, which do not work).

@jimmywarting
Copy link
Collaborator

jimmywarting commented Jun 15, 2016

My opinion on opening a new page vs current page is: open a new page if possible otherwise use current page.

There is some scenarios where opening a new page won't work.
That is when a you try to open a new page that is made "to long ago" after a user interaction, since window.open() only allow to open on user interaction like onClick - default behavior is to block annoying popups otherwise
I have found out that you can run window.open() if you do it somewhere between 0-1000 ms after a user interaction occurred

So my preference would be

popup = window.open(x)
if(!popup) window.location.href = x

@jimmywarting
Copy link
Collaborator

Also a big difference for Safari & CriOS - blob: object links are working in Safari, not in CriOS. (Also the reason why force == false for CriOS. It uses object links, which do not work).

So what your commit really comes down to is this?

force = type === force_saveable_type || /CriOS\/[\d]+/.test(navigator.userAgent)

@ph4r05
Copy link
Contributor Author

ph4r05 commented Jun 15, 2016

force = type === force_saveable_type || /CriOS\/[\d]+/.test(navigator.userAgent)

Almost, but not exactly I think. If force == true the datalink is used, thats great.

  1. difference is to open it in a new tab in CriOS - approach you suggested recently works fine.
  2. Datalink with "data:attachment/file" does not work in CriOS. But datalink with "data:" + blob.type or "data:application/octet-stream" worked for me in CriOS.

@jimmywarting
Copy link
Collaborator

jimmywarting commented Jun 15, 2016

Just a observation, what happens if the blob don't have a type?
i.e. new Blob(["hello world"])

@ph4r05
Copy link
Contributor Author

ph4r05 commented Jun 15, 2016

Nice one! It is empty.
https://jsfiddle.net/jv1fhkst/

I've just tested the empty datatype also works in CriOS.

Or we can then use:

blob.type || "application/octet-stream"

Both display plaintext "hello world" in a new tab.

}
var dataType = is_chrome_ios ? blob.type : 'attachment/file';
var popup = window.open("data:" + dataType + base64Data.slice(base64Data.search(/[,;]/)), '_blank');
if(!popup) window.location.href = "data:" + dataType + base64Data.slice(base64Data.search(/[,;]/));
Copy link
Collaborator

@jimmywarting jimmywarting Jun 15, 2016

Choose a reason for hiding this comment

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

Feels like we could do something smarter... we are basically reconstructing the same result we get from the reader if it's CriOS? So something like this would be better?

var url = is_chrome_ios ? reader.result : reader.result.replace(/mimetype/, 'attachment/file')
var popup = view.open(url, '_blank')
if(!popup) view.location.href = url

(regex is wrong, but a quick google search may find something)

Something along that line... Probably should use view instead of window also

Copy link
Contributor Author

Choose a reason for hiding this comment

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

  • Regarding view instead of window - sure! it was a bug. my fault.
  • Regarding url - will let you know after I test it

@ph4r05
Copy link
Contributor Author

ph4r05 commented Jun 15, 2016

It works quite nice! thanks for suggestion

@ph4r05
Copy link
Contributor Author

ph4r05 commented Jun 15, 2016

Once we have a solution, I can squash it to a single commit so it does not mess the commit history if you want.

@eligrey
Copy link
Owner

eligrey commented Jun 16, 2016

lgtm

@ph4r05 ph4r05 force-pushed the chromeIosSaveFix branch 2 times, most recently from 12f5b77 to 3843680 Compare June 16, 2016 07:04
- Blob links / url objects are not supported in Chrome iOS for now
- thx @jimmywarting for suggestions & help with improving this PR
@ph4r05
Copy link
Contributor Author

ph4r05 commented Jun 16, 2016

squashed, minified version updated

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

Successfully merging this pull request may close these issues.

FileSaver opens blank tab on Chrome for iOS
3 participants