This is still an issue. How can we allow users to download arbitrary files from an extension page/popup??
Post
Replies
Boosts
Views
Activity
Good questions.
Just a note:
header-based modifications in the coming days
Even with mv2, Safari lacks some of the implementation for modifying headers compared to all other modern browsers. You can check out the support on the MDN docs for webRequest which I believe is deprecated in favor of declarativeNetRequest.
I've used declarativeNetRequest with both mv2 and mv3 Safari extensions and was disappointed to see that header modification still lacks with that API implementation. action.type: "modifyHeaders" is not supported as of writing this comment :/
I'm hopeful they will reverse their current stance on header modifications.
Are there any updates to this?
This also affects bundled html extension pages within a web extension. Using the Safari App Extension API (as compared to the Web Extension API), it is possible to download arbitrary files using the method above, but with the Web Extension API, the download attribute is not respect and a new tab opens with the download content.
Is your extension Web Extension format or Safari App Extension?
In the case of Web Extensions, ensure you have proper permissions in your manifest.
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/create
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/windows (window api docs if you really want to open a new window)
Create a new tab with Web Extension:
browser.tabs.create({url: "https://www.apple.com"}, response => {
// ...
});
Create new tab with Safari App Extensions:
func openTab() {
guard let url = URL(string: "https://apple.com/") else { return }
SFSafariApplication.getActiveWindow { (window) in
window?.openTab(with: url, makeActiveIfPossible: true) { (tab) in
// ...
}
}
}
There are other ways to accomplish a redirect within the extension, but none will likely have as good UX by doing it the way you described.
Building out the declarativeNetRequest api in Safari would be really beneficial to developers and I am sure filing feedback would help get that point across.
browser.webRequest could be used, however it is only supported for persistent background pages, which is incompatible with iOS and manifest v3 project. - https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest
You could use a content script to redirect, however depending on the amount of logic in your app, this could be less optimal UX.
You could use browser.tabs.update, but again, less than optimal user experience: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/update
Hopefully Apple will build out the rest of this API for Safari. Here's a somewhat related thread: https://developer.apple.com/forums/thread/682541
Here's a forum post with a reply for an Apple employee: https://developer.apple.com/forums/thread/659029
In my experience, the user has to click "Allow Unsigned Extensions" every time they open Safari.
Also in my experience, distributing web extensions this way is far from optimal.
Can we get more info on this?
Not having access to the actual tabId limits extension potential for pre-processing before the load events.
This is still the case with Safari 15.2
browser.webRequest is not available when the background is persistent: false, that is why I could not access it
Restarting XCode and my computer did not resolve it. However, doing the following did:
I removed and re-added the account that owned the signing certificate in the XCode -> Preferences -> Accounts menu. You can remove the account by highlighting it and then hitting the minus (-) button, and re-add it using the + button.
What API would you use to build this?
A solution for this off the top of my head, whilst using the WebExtension API goes something like this.
JavaScript files of extensions are not loaded for that error page either.
That's right. Content scripts are not loaded in that kind of error page. The background page is loaded however.
You could try to listen for browser.webNavigation.onCompleted and then check the currently active tab:
browser.tabs.query({currentWindow: true, active: true}, tabs => {
const active = tabs[0];
// do something with the tab data
});
You could read the active.title and derive if the page failed to load or even run your own fetch and get the status code back and decide what to do from there.
I haven't tested this so I can't confirm whether or not browser.webNavigation.onCompleted actually fires for those kind of error pages, but worth a try if you're invested in this.
This was throwing an error because I was hitting the 6mb memory limit. Example of console error posted here: https://developer.apple.com/forums/thread/687642?answerId=691678022#691678022
If you're like me and your extension is randomly breaking and you suspect a memory issue, here's what the console message looks like. Be aware it's not a fault or error in the console, this caused me to miss it initially. Side note, I still have no idea how to monitor memory usage in mobile safari whilst developing.
@DSNET to be honest, I don't remember what I ended up doing. I don't use any analytics in my recent extensions, but you can see the source code for the extension I was working on when I made this question here: https://github.com/quoid/coin-ticker - Keep in mind this was the old Safari JS api (hence the 3 year old question)
How do we monitor memory usage of an iOS Safari Web Extension? Does the iOS app memory usage indicate what the Safari Web Extension is using in iOS?
To add some additional clarity, the message that is failing returns an array of of dictionaries [[String: Any]]. It seems that when the array length is greater than 6 the error occurs, however if the array is less than 6 it does not occur.