Post not yet marked as solved
Safari Version 14.0.1 (16610.2.11.51.8)
I am porting a Chrome/Firefox/Edge extension to Safari Web Extension. Mostly, the process was painless, I am, however, seeing quite different behavior in the tab ids generated by Safari compared to Chrome, Firefox, and Edge. My extension has callbacks for each of these browser.webNavigation events:
browser.webNavigation.onBeforeNavigate
browser.webNavigation.onCommitted
browser.webNavigation.onDOMContentLoaded
In each of these I rely on the tab id for various future tab targeting operations. When opening a new tab, the details object passed to each of these callbacks has a non-zero tabId on Chrome, Firefox, and Edge. However, in Safari, the tabId is always zero. To debug, I added one more callback:
browser.webNavigation.onCompleted
At this point Safari finally has a non-zero tabId in the details param. Needless to say this is causing some consternation with achieving the same outcomes as tab tracking on Chrome, Firefox, and Edge. It's like Safari is treating new tabs as "non tabs" until navigation completes. You can even see it when trying to get the tab by tabId=0:
browser.tabs.get(tabId) // tabId=0 here
	.then(tab => {
		// tab is undefined
	});
Seems like this might be a bug. I can't imagine why the behavior is so different from other browsers. Any ideas on how to work around?
Hey everyone, so I have a Safari Web Extension live in the Mac App Store, and it seems like it's working for most of my users, however I have a user saying that the extension is not appearing in Safari's extension window for him after running the app.
After performing basic troubleshooting (making sure he's using Big Sur and Safari 14, restarting his computer, reinstalling the extension), it still seems to not be working for him.
I've narrowed the issue down to this piece of code:
SFSafariExtensionManager.getStateOfSafariExtension
Normally in the ViewController, it runs this function and says either "\(appName) is currently on." or "\(appName) is currently off." in the main window.
However, for my user, his window just says "\(appName)", which tells me that "getStateOfSafariExtension" is throwing an error.
What would my next troubleshooting steps be to figure out what's going on for this user? Trying to get the extension successfully installed for him.
Thanks so much! Sorry for the long post.
Post not yet marked as solved
When the sandbox directive is included in the contentsecuritypolicy, even when it includes allow-scripts, it breaks all functionality from the extensions. It seems allow-scripts is simply ignored.
When including something like http: or https: in the connect-src and img-src directives of the contentsecuritypolicy of webextensions, they are simply ignored.
Other matches like https://*.example.com/ work as expected.
Post not yet marked as solved
Hi!
What is basic difference between Safari extension which has NSExtensionPointIdentifier set to com.apple.Safari.extension and Safari web extension with NSExtensionPointIdentifier value set to com.apple.Safari.web-extension.
I'm asking because to me it seems that permissions for those two work differently.
When I set same set of permissions to manifest.json of extension I have different behaviour.
Case 1:
For com.apple.Safari.extension when user turns on the extension in Safari preferences, there is a popup with question: Are you sure you want to turn on the extension "extension_name"?. User can either cancel it and not turn on extension, or user can click Turn on and allow all extension requested permissions on all pages.
Case 2:
For com.apple.Safari.web-extension when user turns on the extension in Safari preferences, there is no popup, but there are 2 buttons, Edit websites where user can enable/disable extension separately for each and every website and there is Always allow on Every Website which basically does the same as Turn On in first example. But if user does not accept some webpage, when user gets to that page first time and tries to click on extension icon, there will be popup with warning about permissions and with several options for user to allow or disable extension.
To create extension I used safari-web-extension-converter tool which automatically creates Safari web extension, but problem is our users do not like permission behaviour that happens in Case 2.
Is there a way to have Safari web extensions (com.apple.Safari.web-extension) which has behaviour described in Case 1.
Post not yet marked as solved
I'm trying to use browser.storage.onChanged - https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/onChanged to detect when changes are made to browser.storage.local where I save all the preferences for my Safari Web Extension.
This works on Chrome, Firefox, Edge, and Opera. But I can't get it to work on Safari. When I call browser.storage.local.set, the onChanged listener is not called.
Below is the code I'm using to test this in Safari. This has to be in an extension with the Storage permission. - https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions
Given this works in all other browsers and I'm following the documentation, I'm inclined to believe this is a bug in Safari. Am I missing something?
/* Function to handle changes to storage */
function handleChange(changes) {
	for (var key in changes) {
		var storageChange = changes[key];
		console.log('onChanged triggered. '+
				 'Storage key "%s" changed. ' +
				 'Old value was "%s", new value is "%s".',
				 key,
				 storageChange.oldValue,
				 storageChange.newValue);
	}
}
/* Add listener for storage changing */
browser.storage.onChanged.addListener(handleChange)
/* Confirm that the listener has been attached (expect "true" to be returned)*/
browser.storage.onChanged.hasListener(handleChange)
/* Set value for ['testKey] (should trigger onChanged event which calls handleChange) */
browser.storage.local.set({testKey: true}, () => { console.log('Storage updated'); });
/* Get current value for ['testKey] in storage.local, should return {testKey: true}*/
browser.storage.local.get(['testKey'], (result) => { console.log(result); });
/* Change value for ['testKey] (should trigger onChanged event which calls handleChange) */
browser.storage.local.set({testKey: false}, () => { console.log('Storage updated'); });
I am porting my chrome extension to Safari. The extension requires the user to sign-in and I use the OAuth code flow, which requires a redirect url.
In Chrome, I can use chrome.runtime.getURL('/mypage.html') as a redirect url because in chrome the extension id is never changed.
In Safari, however, the extension id keeps changing in every (xcode) build. This is similar to the behaviour of Firefox but in Firefox, I can use browser.identity.getRedirectURL(). Although not reachable, it guarantees to stay the same.
As in Safari, there is NO browser.identity and safari-web-extension:// is blocked by Safari, what url can I use as a redirect URL?
According to https://developer.apple.com/documentation/safariservices/safari_web_extensions/assessing_your_safari_web_extension_s_browser_compatibility, tabs.onUpdated should be fully supported. However, I have noticed that the changeInfo only contains 'status'. This is insufficient because it does not give enough information what has actually changed on a tab.
For example, 'url' is expected to be in the changeInfo if tab's URL has changed. See https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/onUpdated#changeInfo.
Note: already submitted a feedback to Safari via apple standard feedback channel. Don't know what will happen with that as I have never heard anything back from Apple. Coming from Microsoft platform, I find Apple awkwardly unreachable. And they don't provide enough information on their documentation. Do you guys share the same feelings? or it's just me.
Post not yet marked as solved
I'm trying to convert a Safari App Extension to the newer Safari Web Extension API, and having an issue with an injected iFrame we use to protect user data. Inside our provided iFrame which which we source from:
safari-web-extension://<ID_HERE>/<HTML_FILE_HERE>
and is externally_connectable via the manifest.json.
Any scripts that run inside the iFrame are able to initiate communication with background scripts with no problem. However, any message initiated from background never registers on any onMessage listener. For example:
// iframe.js
// WORKS FINE
browser.runtime.sendMessage({ greeting: "hello" })
.then((response) => {
		console.log("Received response: ", response);
});
// NEVER FIRES
browser.runtime.onMessage.addListener((request, sender, sendResponse) => {
		console.log("Received request: ", request);
});
I'm convinced this is an Apple bug because this same scenario for the App Extensions receives the request from the background scripts no problem. Can anyone prove me otherwise?
Post not yet marked as solved
I'm trying to put a view (html page) from a web extension into an iframe on a website. The html file is listed correctly in web\_accessible\_resources, however when I'm trying to load it, I get the following error:
Failed to load resource: The operation couldn’t be completed. (Cocoa error -1008.)
When trying to Submit an update for review, I get the following message:
Unable to Submit for Review
The items below are required to start the review process:
You must provide copyright information for the app you are adding.
However, there is not any box where I can fill in copyright info for my app. What to do now?
Post not yet marked as solved
I used the xcode tool "sarfari-web-extension-converter" and it worked well for a bit, the app built, and the extension was installed in Safari.
But then I must've done something weird because now I build and run my XCode app (for the extension) and it says
"***'s extension is currently on." With the button to "Quit and Open Safar Extensions Preferences..."
But when I do that then the extension is not installed. The extensions tab shows "No Extensions".
How do I get it re-installed so I can continue developing?
Post not yet marked as solved
runtime.oninstalled is invoked when I install the extension for the first time in the browser. But if I uninstalled it again (by dragging the app to bin), and tried reinstalling the runtime.oninstalled is not invoked.
is that an expected behavior?
If so, how can I test this case during extension development? Because it is difficult to find a new browser to test this case every time.
Thanks.
Post not yet marked as solved
Hi in my web extension I have a button, which I programmatically create a file for download when the user clicks it.
Here is my code: a.click()
However, this does nothing when I do it within the popup. It works fine on the main Safari webpage. Am I doing something wrong?
Post not yet marked as solved
I currently have an architecture where I need to forward messages from the Safari Web Extension to another app through the App Extension.
I understand from the docs on Apple, App Extensions are not meant to be used as a long running background task, but if it is just proxying messages, is it advisable to keep pinging the app extension to keep it alive and use it as a long running task in the background for proxying messages ?
Post not yet marked as solved
I was turning on and off experimental features in Safari, and now I
don’t remember the default. Could you please go to settings, safari,
advanced, experimental features and tell me what you’ve got? Thanks so
much!
Post not yet marked as solved
Hi. I'm trying to port my Safari app extension with an injected content script to a Safari web extension on iOS. Content scripts in a macOS Safari app extension always behave as if run_at document_start were specified in the manifest of a Chrome extension. This is crucial to my extension for several reasons: I need to load my JavaScript before any of the page scripts load, and I need to start fetching my site-specific preferences ASAP.
Unfortunately, document_start doesn't work right with Safari web extensions in Safari 14 or Safari 15 on macOS. This is made even worse if Preload Top Hit is enabled in Safari, but document_start is unreliable even with Preload Top Hit disabled.
I've been testing with Safari on the iOS 15 beta, and I've noticed that document_start does seem to work right (unlike Safari Mac) with Preload Top Hit disabled. However, enabling Preload Top Hit still causes it to be unreliable on iOS.
This is all in contrast to Safari app extensions, which just always load at the start, regardless of whether Preload Top Hit is enabled. Though of course Safari app extensions do not exist on iOS.
I'm wondering if Apple's Safari engineers could comment about this. Are there differences in web extension implementation between iOS and macOS? Can I depend on iOS document_start working right with Preload Top Hit disabled? Is there any way that you could fix the Preload Top Hit behavior? (In my testing, document_start seems to work with preload in Google Chrome.)
The developer forums don't see to allow me to attach a zip file (is this possible?) but I've got a sample Xcode project that can demonstrate this behavior.
Post not yet marked as solved
Hi. I've started a Slack for Safari extension developers! Email me for an invitation: slack at lapcatsoftware.com
The purpose of this Slack is mutual support for Safari extension development on iOS and/or macOS.
Apple engineers who work on Safari extensions are welcome too!
Post not yet marked as solved
We want to debug our web extension on iOS, by default, we can access web extension background page from Desktop Safari -> Top Menu -> Develop -> Web Extension Background Pages
This works perfectly for extensions installed on macOS, but how to access the ones installed on iOS/iPadOS?
Post not yet marked as solved
I have the Zoom for outlook on my Outlook account.
It works great on the Chrome, but when I try to add a zoom to a meeting in the calendar in Safari, I get into an endless loop of Allow screen, entering my company domain and again and again.