Safari Extensions

RSS for tag

Enhance and customize the web browsing experience on Mac, iPhone, and iPad with Safari Extensions

Safari Extensions Documentation

Posts under Safari Extensions tag

174 Posts
Sort by:
Post not yet marked as solved
8 Replies
1.9k Views
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'); });
Posted
by leggett.
Last updated
.
Post not yet marked as solved
1 Replies
479 Views
I have a working Chrome extension using manifest version 3, and I am following the porting instructions to turn it into a Safari extension on MacOS (Monterey) - using xcrun from the Xcode toolset. I have Safari v. 15.5. There are two problems. First, the documentation says "Safari 15.4 and later supports manifest versions 2 and 3". So how come xcrun complains about all of the following keys: manifest_version, icons, description, version, js, matches, service_worker, type, action, tabs, activeTab, storage, alarms, webNavigation, web_accessible_resources, name, css? At least some of those are basic to v3 manifests. Second, when I try to install it in Safari (it builds OK under Xcode despite the above "problem") I get an error. In my background (service worker) script I call self.importScripts("Platform.js"); which should load said JavaScript file. It's in the same folder as the script that calls it. This works in Chrome but fails in Safari with the error: Failed to load resource: unsupported URL safari-web-extension://FE580C4D-9931-4639-ABF9-...../Platform.js I tried changing that dynamic import to a static import: import Platform from "./Platform.mjs"; (After converting Platform.js to a module Platform.mjs.) This also works on chrome but now my converted extension for Safari won't even load. I get: The service_worker script failed to load due to an error. But I can find no way of determining what that error is (there is no information in the service worker console). I would appreciate help with either or both of these problems. Perhaps they are connected and there is something missing/wrong about my version 3 manifest - even though Chrome is happy with it.
Posted Last updated
.
Post not yet marked as solved
1 Replies
68 Views
I migrated my extension from Manifest V2 to V3 recently, and it works fine on Chrome/Edge, but got failed on Safari. The only error message that I can see is: 由于出现错误,service_worker脚本载入失败。 It says service_worker failed to load. There is no other messages I can found. Can you please tell me how to get more informations about the error? Thanks!
Posted Last updated
.
Post marked as solved
7 Replies
535 Views
FB7597364 (attached video there) Hello, I have filled a radar but I'm wondering if I am misunderstanding the following (Safari TP 104+): Make the extension open a new tab with the baseURI and a parameter, eg.: safari-extension://2CB967-22BA-44F3-B604-72611F/aafefbf/test.html?title=Apple&color=red Here's the code I'm using: SFSafariApplication.getActiveWindow { activeWindow in 						SFSafariExtension.getBaseURI { baseURI in 								guard let baseURI = baseURI else { return } 								var urlComponents = URLComponents(string: baseURI.appendingPathComponent("test.html").absoluteString); 							 								urlComponents?.queryItems = [ 									 URLQueryItem(name: "title", value: "Apple"), 									 URLQueryItem(name: "color", value: "red"), 								]; 								activeWindow?.openTab(with: (urlComponents?.url)!, makeActiveIfPossible: true, completionHandler: {_ in }); 						} 				} 2. Wait for the page to load 3. Quit Safari 4. Open Safari Expected: Safari updates the baseURL of that tab and keeps the query parameters, eg: safari-extension://11111-new-baseURI-44F3-B604-72611F/o213s/test.html?title=Apple&color=red Actual: Safari updates the baseURL of that tab and strips the query parameters, eg: safari-extension://11111-new-baseURI-44F3-B604-72611F/o213s/test.html
Posted
by bruno.cm.
Last updated
.
Post marked as solved
1 Replies
61 Views
We have a few content scripts designed to run mostly on our domains with maybe a couple of exception of specific sites where we provide exact URLs, (no wildcards). We do use wildcard for own domains though but that includes at least top level domain. Safari still doesn't allow the web extension to inject content scripts into these pages until the user explicitly allows them. And this would be fine except when using all_frames option which is actually supported by Safari but is not taken into account when requesting permission from the user. So when user clicks "Always allow on this site" it only includes the top level page but not the iframes within which also require their own instance of content script. And the user has no chance to allow that unless they use "Always allow on all sites" option but it's not like we're going to guide every user to use that option. Is it possible to trigger the prompt for access programmatically or indicate that Safari should give access to certain domains by default?
Posted Last updated
.
Post marked as solved
6 Replies
3.7k Views
I am trying to run JavaScript only after the page has loaded, and according to here - https://developer.apple.com/documentation/safariservices/safari_app_extensions/injecting_a_script_into_a_webpage, I should use DOMContentLoaded. However, it does not seem to work. This is my content.js file: function runOnStart() {     document.addEventListener('DOMContentLoaded', function(e) {         document.body.style.background = "rgb(20, 20, 20)";         document.html.style.background = "rgb(20, 20, 20)";                var divElements = document.body.getElementsByTagName('div');         for(var i = 0; i < divElements.length; i++) {             let elem = divElements[i];             elem.style.background = "rgba(255, 255, 255, 0.05)";         }     }); } runOnStart(); If I take the code outside of the event listener, it runs fine, but a lot of the elements haven't loaded in yet so it doesn't work as it should. The function is definitely running, but the event listener simply doesn't work. I appreciate any help you can give!
Posted
by JakeShort.
Last updated
.
Post not yet marked as solved
1 Replies
119 Views
I'm trying to make a request using fetch to my api inside a safari extension background page. This is a manifest v3 extension converted from a chrome extension (which works). Inspecting the background page, I see an error message which reads Refused to connect to <site> because it does not appear in the connect-src directive of the Content Security Policy. I have tried setting a policy for default-src and connect-src in the extension_pages field of the content_security_policy key in the manifest.json file, but the error persists. How can I make a fetch request to an api in a background page?
Posted Last updated
.
Post not yet marked as solved
2 Replies
134 Views
We have a browser extension using manifest v3 that we publish to the Chrome web store, and soon as a Firefox add-on. We'd also like to publish it for Safari, so we followed the instructions here: https://developer.apple.com/documentation/safariservices/safari_web_extensions/converting_a_web_extension_for_safari This worked just fine, and running the XCode project will install the extension in Safari. The problem is that we do not want to distribute this with a macOS app. We only need the extension itself, all background work is done via a web worker. If I remove the macOS app from the XCode project, it does not seem as if there is a way to try and distribute it via App Store Connect. Is there way to just build and distribute the .webex extension?
Posted Last updated
.
Post not yet marked as solved
8 Replies
25k Views
Safari / El Capitain 10.11.6Yesterday ended up downloading Safari 11 for Sierra in error - Strangely it allowed installation - but obviously didnt run-long story short I was able to get Safari 11/El Capitain pre release beta to overwite via Pacafist ( installer wouldnt work as it saw Safari as newer)and all working , except now I get :"SafariBookmarksSyncAgent quit unexpectedly" every 10 seconds.It goes away if I remove "SafariBookmarksSyncAgent" ( which along with other files in the bundle has a mod date 08/09/17 so hasnt been updated) I have El capiatin 10.11.6 OS final image /Safari EC beta image and the Safari 11 Sierra image.Anyone know what files I can swap over to sort this out.Any advice much appreciated.Some details..more if needed :Dyld Error Message: Symbol not found: _OBJC_CLASS_$_WBSAnalyticsLogger Referenced from: /System/Library/CoreServices/SafariSupport.bundle/Contents/MacOS/SafariBookmarksSyncAgent (which was built for Mac OS X 10.12) Expected in: /System/Library/PrivateFrameworks/SafariCore.framework/Versions/A/SafariCorein /System/Library/CoreServices/SafariSupport.bundle/Contents/MacOS/SafariBookmarksSyncAgent
Posted
by tgordine.
Last updated
.
Post not yet marked as solved
1 Replies
368 Views
I'm using manifest v3 and working on a Safari extension. When I try to run a function within activeTab. I can not get the proper return from the the function. For example: browser.scripting.executeScript({ target:{tabId:tab.id}, func:()=>'test', }).then(result=>{ console.log('result',result) }) Here the result is always null. Is it a bug? Nothing wrong with permission settings because if I use files instead of func, the return value works properly. Safari: Version 16.1 (18614.2.3.1.1) macOS 13.0 Beta Xcode: Version 14.0 beta 5 Thanks
Posted
by Zijar.
Last updated
.
Post not yet marked as solved
0 Replies
178 Views
I would like to be able to receive images from Safari in my Share Extension. To do this I need to add public.url in NSExtensionActivationRule. This works and my app can receive shared images from Safari. The problem is that my app also appears in the list when sharing a URL to a website and not an image. Now I'm looking for a way to hide my app when sharing in Safari if the URL doesn't lead to an image.
Posted
by vsmedia.
Last updated
.
Post not yet marked as solved
0 Replies
158 Views
I have created an iOS app and in the app after finishing some activities, it opens a URL in safari browser. Each time the URL is open in a new tab in Safari. I would like to open the URLs in same tab itself instead of opening multiple duplicate tabs in the browser. Is there any possibility to set the maximum tab count or open URL in same tab if the domain is same.
Posted
by sumeshms.
Last updated
.
Post marked as solved
2 Replies
840 Views
Hello dear Apple Community, I'm pretty new to this, so probably this is a simple fix... I just created a Safari Web Extension from the "official" template in Xcode (File > New > Project > Safari Extension App). I ran it an it popped a window open which has a button that says something like "Quit and open Safari Preferences". I press it and nothing happens. Weirdly though, a week ago, I tried pretty much the same -> worked perfectly. But now it doesn't. So I made the button press event look like this:  @IBAction func openSafariExtensionPreferences(_ sender: AnyObject?) { SFSafariApplication.showPreferencesForExtension(withIdentifier: extensionBundleIdentifier) { error in             guard error == nil else {                 print(error.debugDescription)                 return             }             DispatchQueue.main.async {                 NSApplication.shared.terminate(nil)             }         }     } And it printed me out this error:  (Error Domain=SFErrorDomain Code=1 "(null)") I checked "Allow Unsigned Extensions" and even tried it with the "Sea Creator" Example code found here - https://developer.apple.com/documentation/safariservices/safari_web_extensions/developing_a_safari_web_extension?language=objc and some other Safari Web Extensions that I wrote a week ago. They all seem to throw the same error. I guess it could be a corrupted file or something - about that: yup, I already restarted my Mac. Is there a way to "reinstall" Safari without restoring my entire machine? What am I missing? Afaik the error means that my extension wasn't found or that I'm not the owner, but how could that be... because why would Xcode give me an invalid template and why would it have worked then a week ago? I'm just confused. Thanks in advance! :)
Posted
by M4GG1.
Last updated
.
Post not yet marked as solved
5 Replies
1.1k Views
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) => { &#9;&#9;console.log("Received response: ", response); }); // NEVER FIRES browser.runtime.onMessage.addListener((request, sender, sendResponse) => { &#9;&#9;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?
Posted Last updated
.
Post not yet marked as solved
3 Replies
224 Views
I'm building an extension for Safari on IOS and would like to have the extension pop up automatically on specific URLs. Currently I am using Dom content load as a listener to see if the page has changed but on some websites, this listener doesn't work. I have to reload the page for it to work. Is there another listener I can use that can detect any change the URL?
Posted
by ben888218.
Last updated
.
Post not yet marked as solved
1 Replies
177 Views
I'm here to request clarification on a question we have. One of the flagship features of our iOS app is our Safari extension. We are worried that some users might activate, and never return to the app itself. after 90 days of no use for an app, the system usually offloads the app. What we wanted to know is, does having an enabled Safari extension prevent the app getting offloaded? Thanks for any help
Posted Last updated
.
Post not yet marked as solved
0 Replies
165 Views
I have a list keyword want to block. I want to write a single rule to block them. For example, I want to block "foo", "bar" or "funny". As url-filter is regular expression. I tried to write rule as below but seems not working. // Not working {   "trigger": {    "url-filter": "foo|bar|funny" } } // Not working either {   "trigger": {    "url-filter": "(foo|bar|funny)" } } Any idea to support OR condition in url-filter ?
Posted
by iret.
Last updated
.
Post not yet marked as solved
0 Replies
188 Views
IOS Safari extensions loose connection when safari page gets saved as standalone on a mobile device. By removing the captivating newsfeed, we make social media less addictive so that people can still stay connected, not distracted. In other words, joining Apple's mission to improve focus/screentime to get hours. back in their life. You can check out our safari extension at: Mac Store. Our users are pleading us every day to extend our solution to mobile as that's where majority of social media distraction lies. As we can't modify a native app, the closest thing we can do is ask users to add the modified safari social media page to their homescreen which they're completely value as it still makes them still feel they're using the native app without the distraction. However, since safari extensions lose connection at standalone despite our users' intention, they can no longer live a life without distraction. As a result, we are forced to ask the user to also allow content blockers as a workaround which makes for a poor user experience for the following reasons.  The User is confused about why he has to install two extensions to do the job of one, hence creating a logical leap. Content ways are turned on in a completely different way than Safari Extension, the former is in iPhone’s setting the latter is in the Safari toolbar. Thereby, such poor user experience leaves the user frustrated given the simplicity a user expects from Apple’s product. Because the user has to install two Extensions to do the job of one, this can negatively impact the battery and performance of the user’s phone. As the name implies, content blockers only block content. Hence, we can't 4. developer any feature aside blocking that users want. Even worse, content blockers are inefficient for blocking due to the fact that some HTML elements don’t have unique identifiers while others share IDs due to being SWA (making it impossible to make targeted blocking always work).
Posted Last updated
.
Post not yet marked as solved
0 Replies
188 Views
As an app that's making social media less addictive for thousands of iPhoners, we’re wholeheartedly requesting to allow content blocker permissions via a permission pop. This will dramatically improve the user experience because the current method is puzzling for the following reasons: Navigating for the “Content Blocker” permissions in settings is challenging, confusing, and frustrating. Even as the developers ourselves, we sometimes get lost on the way. Hence, users are upset on why such a binary permission can’t just be done via a popup like other permissions (including family controls). sometimes when a user search “Content Blocker” to make navigation easier, the app shown in the picture gets shown instead which ends up misleading and frustrating the user even more. users don’t always know what “content blocker” is in their native language to be able to navigate to it via a search. BeTimeful shares Apple’s mission to bring back time to people’s lives with introductions of family controls and screen times. Unfortunately, the current voyage to just turn on a binary permission is making it hard for us and other developers to fulfil the mission. At the same time, we all choose Apple due to the simplicity of it's UX, not complexity. Hence, on behalf of our current and future users, we plead to simplify content blocker permission as well 🙏💜
Posted Last updated
.