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

112 Posts
Sort by:
Post not yet marked as solved
7 Replies
7.3k Views
Smart App Banners in Safari will open the app store if the viewer of your web page does not have your app installed.Any way to code the link with a Campaign from the new App Analytics?E.g. Campaign link: https://itunes.apple.com/app/apple-store/id888917601?pt=10633139&ct=demo1&mt=8E.g. Meta tag for App Banner:<meta name="apple-itunes-app" content="app-id=888917601, app-argument=notestream://open">Is there some way to put "ct=demo1" into the meta tag for App Banner?Thanks.
Posted
by
Post marked as solved
9 Replies
7.4k 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
Post not yet marked as solved
12 Replies
4.6k Views
All of my third party extensions have blue icons now, in Safari 14.0. It looks pretty awful. Is there a way to keep the monochrome colors or a way for us, as developers, to provide a different kind of icon to sustain the monochrome colors for our extensions? I am assuming the blue color denotes something, like the extension being "active". I wasn't able to find documentation on this change nor any related api doc.
Posted
by
Post marked as solved
14 Replies
3k Views
Hi folks, We're building a Safari web extension and experiencing an issue to see it among extensions in Safari after installing the container app to /Applications and launching it. The app and extension is notarized and signed with Developer ID After an extensive investigation, we found the following log records in the Console app (the extension ID is redacted): Computing the code signing dictionary failed for extension with identifier com.youcompany.safariext Blocking extension with identifier: com.youcompany.safariext To debug the issue, we've created a HelloWorld-like extension generated by Xcode 12.2 beta 4 (http s://sharedartifacts.s3.eu-central-1.amazonaws.com/safariext.app.zip contains a signed app bundle) It also is under the same code signing issue. According to https://developer.apple.com/documentation/xcode/notarizing_macos_software_before_distribution/resolving_common_notarization_issues, we've run a few checks to verify: code signature ➜&#9;Desktop codesign -vvv --deep --strict ./safariext.app&#9;&#9;&#9;&#9;&#9; ...-prepared:/Users/nikolay/Desktop/safariext.app/Contents/PlugIns/safariext Extension.appex ...-validated:/Users/nikolay/Desktop/safariext.app/Contents/PlugIns/safariext Extension.appex ... ./safariext.app: valid on disk ./safariext.app: satisfies its Designated Requirement signing certificate ➜&#9;Desktop spctl -vvv --assess --type exec ./safariext.app&#9;&#9; ./safariext.app: accepted source=Notarized Developer ID origin=Developer ID secure timestamp ... Timestamp=25 Nov 2020 at 22:23:54 ... We seemed to have all checks good, the extension can be installed only if Safari is allowed to run unsigned extensions. Could anyone assist to debug/resolve this issue? Thanks
Posted
by
Post marked as solved
4 Replies
2.9k Views
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?
Posted
by
Post not yet marked as solved
3 Replies
1.7k Views
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.
Posted
by
Post not yet marked as solved
2 Replies
2.3k Views
What can we expect from Apple / Safari in terms of Manifest v3? When/if will it be supported? When is the end of life for manifest v2?
Posted
by
Post not yet marked as solved
1 Replies
1.7k Views
I've developed a ios safari web extension for my app and everything seemed to work fine in the simulator and on my device. However, I've noticed that in some cases when the user tries to give permission to the extension inside safari, the system displays an alert asking for permissions to all the sites saved in the user's keychain. It's really strange. I've not been able to always reproduce this behavior, sometimes it works normally and it asks for permission just for the domain where the user is on. The issue has become a real problem when I've discovered that when the user has a lot of saved passwords for sites in the keychain, the Safari freezes when asking for permission and becomes absolutely unusable, forcing the user to close it. Here is the manifest for my extension: { "manifest_version": 2, "content_security_policy": "script-src 'self' https://ssl.google-analytics.com; object-src 'self'", "background": { "scripts": [ "browser-polyfill.js", "background.js" ], "persistent": false }, "content_scripts": [{ "js": [ "browser-polyfill.js", "document-start.js" ], "matches": [ "http://*/*", "https://*/*" ], "run_at": "document_start" }, { "js": [ "browser-polyfill.js", "contentscript.js" ], "matches": [ "http://*/*", "https://*/*" ], "run_at": "document_idle" } ], "browser_action": { "default_icon": { "19": "assets/images/logos/16x16_logo.png", "38": "assets/images/logos/48x48_logo.png", "48": "assets/images/logos/48x48_logo.png", "64": "assets/images/logos/64x64_logo.png", "128": "assets/images/logos/128x128_logo.png", "256": "assets/images/logos/256x256_logo.png", "512": "assets/images/logos/512x512_logo.png" }, "default_popup": "popup.html" }, "icons": { "16": "assets/images/logos/16x16_logo.png", "48": "assets/images/logos/48x48_logo.png", "64": "assets/images/logos/64x64_logo.png", "128": "assets/images/logos/128x128_logo.png", "256": "assets/images/logos/256x256_logo.png", "512": "assets/images/logos/512x512_logo.png" }, "web_accessible_resources": [ "assets/*" ], "permissions": [ "<all_urls>", "cookies", "storage", "unlimitedStorage", "webNavigation", "notifications", "nativeMessaging" ] } Here is the screenshot of the safari asking for permission to the extension to access 653 different websites that are registered in the user's keychain:
Posted
by
Post not yet marked as solved
3 Replies
1.3k Views
I am trying to write a safari web extension that redirects users to Y URL if they type X URL without ever loading the X URL. The piece of code that I have attached below works smoothly on chrome, but not on safari. background.js function onBeforeNavigate(event) { const redirectURL = "https://google.com/" chrome.tabs.update(event.tabId, { url: redirectURL }) } chrome.webNavigation.onBeforeNavigate.addListener(onBeforeNavigate,{ url: [ {urlMatches: "https://girlcodeit.com/*"}, {urlMatches: "http://girlcodeit.com/*"} ] }) manifest.json "manifest_version": 2, "name": "", "description": "", "version": "1.0", "background": { "scripts": [ "background.js" ] }, "permissions": [ "webNavigation", "tabs" ] } I have tried writing browser.tabs.update and just tabs.update in place of chrome.tabs.update in safari version, no change. I want to achieve the redirection anyhow through a safari web extension, please suggest changes in this one or share any other approaches. webRequestBlocking is not supported by Safari, so that doesn't work either.
Posted
by
Post not yet marked as solved
1 Replies
858 Views
Hello, I would like to track the amount of downloads, on Apple Store, of users coming from the Safari Smart Banner. The smart banner is displayed but we don't have any data in Apple Store. How can I track these downloads? We have a campaign link and I've tried three different ways and it didn't work. Thanks. I've tried: <meta name="apple-itunes-app" content="app-id=605512447, affiliate-data=pt=2000418&ct=iOS%20Smart%20Banner&mt=8”/> <meta name="apple-itunes-app" content="app-id=605512447, affiliate-data=pt=2000418&ct=iOS%20Smart%20Banner”/> <meta name="apple-itunes-app" content="app-id=605512447, affiliate-data=ct=iOS%20Smart%20Banner”/>
Posted
by
Post not yet marked as solved
1 Replies
1k Views
Hi, According to Blocking Content with Your Safari Web Extension, we can now use the Declarative Net Request API to block content in a Safari Web Extension. However, not everything in the API has been implemented just yet. The supported RuleCondition are domainType, excludedResourceTypes, isUrlFilterCaseSensitive, regexFilter, and resourceTypes. Does anyone know when the initiatorDomains rule condition will be supported? In the meantime, is there a way for an extension to block requests based on an originator domain? Thanks
Posted
by
Post not yet marked as solved
3 Replies
1.3k Views
I'm not sure what is special about Gmail, but my declarativeNetRequest rules are totally ignored. I make an web extension that blocks email trackers (1x1 pixel images embedded in emails to track if and when you open email sent to you). All images in Gmail are loaded through Google's proxy: googleusercontent.com/proxy/#originalURL But no matter what I do, I can't block a single image that is loaded in an email. To try and prove it is a bug in Safari, I created a new template web extension in Xcode. I block all resourceTypes (images and other should be all that is needed) and added two rules: Block all images loaded through Google's proxy server (this should block all embedded images in all emails) Block any image with copper in the URL (just in case the blocking doesn't apply to the proxy root url for some reason).  {   "id": 1,   "priority": 1,   "action": { "type": "block" },   "isUrlFilterCaseSensitive": false,   "condition": {    "regexFilter": "googleusercontent.com/proxy",    "resourceTypes": [     "image",     "media",     "main_frame",     "sub_frame",     "stylesheet",     "script",     "font",     "xmlhttprequest",     "ping",     "websocket",     "other"    ]   }  },  {   "id": 2,   "priority": 1,   "action": { "type": "block" },   "isUrlFilterCaseSensitive": false,   "condition": {    "regexFilter": "copper",    "resourceTypes": [     "image",     "media",     "main_frame",     "sub_frame",     "stylesheet",     "script",     "font",     "xmlhttprequest",     "ping",     "websocket",     "other"    ]   }  } ] Even though I know this isn't needed, I also added the requester domain (mail.google.com) and the proxy domain (googleusercontent.com) to the permissions list in the manifest file: ... "declarative_net_request": {    "rule_resources": [{      "id": "ruleset_1",      "enabled": true,      "path": "rules.json"     }]   },  "permissions": [    "declarativeNetRequest",    "*://mail.google.com/*",   "*://*.googleusercontent.com/proxy/*" ] If I open an email from copper, the image still loads in Gmail If I right click and select "Open Image in New Tab", the image will not load and I am told it was blocked If I open a test page that has two images in it, one the image from the email, the image is blocked and the other image is not (as expected, the second image is from wikipedia and should not be blocked) Running the same extension in Chrome DOES block the image in Gmail (and in all the other cases too)
Posted
by
Post not yet marked as solved
3 Replies
2.0k Views
So I've been trying to debug / read console.logs from background scripts when using manifest v3 but it never fires any log. It works well in manifest v2 though. I have set the persmission and host_permission as well changed my background to service_work in manifest but nothing really happens: "background": { "service_worker": "scripts/background.js" }, My Qyestion is, is it currently possible to use manifest v3 on iOS safari web extension? Some Notes: Reading this page: https://developer.apple.com/documentation/safariservices/safari_web_extensions/assessing_your_safari_web_extension_s_browser_compatibility It says: "background: In iOS, you must set the persistent attribute to false. With manifest version 3, all background pages are nonpersistent." So I'm guessing it is somehow possible to use right?
Posted
by
Post not yet marked as solved
4 Replies
2.8k 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
by
Post not yet marked as solved
1 Replies
1.8k Views
I'm getting the following error when I try to import my service worker script: [Error] Failed to load resource: unsupported URL (background_ah.worker.js, line 0) [Error] NetworkError: Load failed Using the following code: try { self.importScripts('./background_ah.worker.js'); } catch (e) { console.error(e); } Am I doing something wrong? The file is there but from the error it seems the extension protocol is not supported at all. It works in Chrome and it's based on this: https://stackoverflow.com/questions/66406672/chrome-extension-mv3-modularize-service-worker-js-file
Posted
by
Post not yet marked as solved
2 Replies
1.7k Views
I have a chrome extension that was converted to Safari extension using xcode safari-web-extension-converter utility. With that, everything except one thing seems to be fine. In the background script, I am loading some data from a web accessible resource like so: export const fetchConfig = async () => { let dataURL = ''; if (!checkBrowser(BROWSERS.Chrome, true)) { dataURL = chrome.runtime.getURL('config.json'); } else { dataURL = browser.runtime.getURL('config.json'); } const res = await fetch(dataURL); return await res.json(); } This works for all browsers except Safari. Where I am getting the runtime URL as: safari-web-extension://E522689D-94A6-4561-90F3-BF22C7848965/config.json but the fetch call fails with the error: Failed to load resource: unsupported URL I have not been able to find anything on this in the documentation, but can we not access the web accessible resources in background in Safari? My manifest file looks like this: { "manifest_version": 3, "name": "Ext Dev", "author": "Test", "description": "Test", "version": "1.1.0", "icons": { "16": "assets/icon/icon16.png", "32": "assets/icon/icon32.png", "48": "assets/icon/icon48.png", "128": "assets/icon/icon128.png" }, "host_permissions": [ ... host addresses here ... ], "permissions": ["storage", "tabs"], "content_security_policy": { "extension_pages": "script-src 'self'; object-src 'self';" }, "web_accessible_resources": [{ "resources": ["config.json"], "matches": ["<all_urls>"] }], "content_scripts": [ { "matches": ["<all_urls>"], "js": ["content.js"], "css": ["commonstyles.css"], "run_at": "document_end", "all_frames": true } ], "background": { "service_worker": "background.js" }, "action": { "default_title": "Ext Client", "default_icon": { "20": "assets/icon/icon20.png", "40": "assets/icon/icon40.png" } }
Posted
by
Post marked as solved
4 Replies
1.7k 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
Post not yet marked as solved
1 Replies
1.2k Views
I'm porting a Chrome extension to Safari. All works well besides the auth flow, which uses SameSite=Strict cookies. On Chrome, such cookies are easily set and work as expected, but not on Safari. Now, as I understand, technically, requests from chrome-extension:// and safari-web-extension:// origins are cross-site in relation to the server, which makes me think that on Chrome, the SameSite=Strict attribute is simply ignored as an exception for extensions. With that said, the backend team wants to keep the attribute for security reasons and so removing it or replacing it with SameSite=None isn't an option. Is this an intended behavior of Safari or a bug? Is there a way to get around this without changing the attribute?
Posted
by