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

210 Posts
Sort by:
Post not yet marked as solved
1 Answers
172 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 leggett.
Last updated
.
Post not yet marked as solved
6 Answers
1.4k 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
2 Answers
84 Views
Hi all, I have a stand-alone Chrome extension app, and used the xcrun converter last year to create a desktop Safari app, and used the xcrun converter again to create a mobile safari extension. Now I want to bundle that extension into an existing iOS app. However I also want the ability to update the extension as if it were a cocoapod or a swift package. Is this possible?
Posted
by Gettediah.
Last updated
.
Post not yet marked as solved
5 Answers
676 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
1 Answers
122 Views
I’m developing safari web extension on macOS using Xcode. I need to send message from web extension’s background.js to containing APP. As “Messaging a Web Extension’s Native App” describe, I create a port in background.js as follow: let port = browser.runtime.connectNative("application.id"); In background.js send message as follow: port.postMessage("Hello from JavaScript Port"); how can I receive this message in containing APP? I would be very grateful if you could give an example. Thanks! Another problem is how can connectNative start the containg APP on macOS. As runtime.connectNative describe in MDN(https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/connectNative) “It starts the native application and returns a runtime.Port object to the caller.The caller can then use the Port to exchange messages with the native application using Port.postMessage() and port.onMessage” In safari, connectNative seems cannot start the containing APP. How can I make it start the containing APP?
Posted Last updated
.
Post not yet marked as solved
1 Answers
95 Views
Hello, How can I change the commands originally set in the manifest? Is there a special internal url like in chrome since browser.commands.update does not seem to exist in Safari. Thank you
Posted
by bruno.cm.
Last updated
.
Post not yet marked as solved
2 Answers
177 Views
I made a Safari Web extension that's supposed to work like this: WHEN: Safari is opening http://example.com/ THEN: The extension opens a page embedded in the extension instead. This is the implementation of background.js: browser.tabs.onUpdated.addListener(async function (tabId) { const tab = await browser.tabs.get(tabId); if (tab.url == "http://example.com/") { const destination = browser.runtime.getURL("embedded-page.html"); browser.tabs.update(tabId, { url: destination }); } }, null); This is the source project: https://www.icloud.com/iclouddrive/042qIjivEoJ0V3qIcLGcytAPA When opening http://www.example.com/ for the first time, it successfully navigates to the embedded page. However, once that navigation is done, the extension no longer works that way unless I re-enable the extension. It's like the listeners are removed by that navigation. This is the video of this issue: https://www.icloud.com/iclouddrive/0f9Yl1jC9eQ8OmgH8vAtEA6Pw Can you replicate this on your Mac? And do you know what's the cause? This happens for a listener of browser.webNavigation.onBeforeNavigate too. Maybe more. On the other hand, when I set a normal page such as https://www.apple.com/ to destination, It always works fine for me. So I'm wondering if this issue is related to the embedded page. FYI, I already reported this issue as FB9967637 on 27th March but no reply from Apple as of now. My environment macOS Monterey 12.3.1 (21E258) Safari 15.4
Posted
by normal.
Last updated
.
Post not yet marked as solved
1 Answers
110 Views
Hi, I'm trying to convert my chrome extension to work in Safari. I've got it mostly working but there is one issue with the webRequest.onResponseStarted.addListener api. The callback is missing fields including ip. Here is an example: webRequest.onResponseStarted.addListener((r) => { console.log(r); }, {"urls": ["<all_urls>"]) In chrome this will print all the fields described in the spec. But in safari it is missing a lot of fields, including ip, type, etc. Does anyone know if this is a bug or if I am doing something wrong? Thanks!
Posted
by mjbford89.
Last updated
.
Post not yet marked as solved
1 Answers
87 Views
I am creating a Safari Web Extension to add some security features to Safari browser. Web Extension has 2 parts, 1st - script code, which loads in browser and 2nd - a separate application/process called Native App which gets notifications and data of browser activities. I am able to get notifications of various browser activities in Safari Native App. When such notification is received, this needs to be sent to other daemon process running on same MacOS machine over unix domain socket (used for local IPC). This Safari Native App is running within a sandbox. The issue is, when trying to connect to already listening socket of other process from Safari Native App, the sandbox of Native App denies outbound socket network connection. Question: Is there a way to communicate from sandboxed Native App using socket with other processes. Disclaimers: Sandbox cannot be disabled, if disabled it stops getting notifications from Safari for activities, which is its basic work. Entitlements and app groups addition can be done, but the process to which it has to communicate cannot be added to app group. Please help/suggest what can be way out from this problem.
Posted Last updated
.
Post not yet marked as solved
1 Answers
113 Views
I'm converting a Chrome extension to work in Safari 15 using the xcrun safari-web-extension-converter. It partially works, but seems to fail with CORS permission issues in both the background script and content scripts. Oddly enough neither issue exists in Chrome. I have granted all websites permission via Safari itself after installation. In manifest.json, I have this in the permissions key: "http://*/", "https://*/" I've tried a variety of permutations, including "https://*/*" but nothing works. Every XMLHttpRequest results in the same error: Failed to load resource: Origin safari-web-extension://... is not allowed by Access-Control-Allow-Origin. Status code: 200 As mentioned, it works fine in Chrome with the same permissions. What have I missed?
Posted Last updated
.
Post not yet marked as solved
2 Answers
263 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 mt2107.
Last updated
.
Post not yet marked as solved
1 Answers
56 Views
Safari 15.4 Release Notes shows that webpage-to-extension messaging using externally_connectable is supported. https://developer.apple.com/documentation/safari-release-notes/safari-15_4-release-notes However, when I tried testing it, I was not really able to get it to work. What I have tried: Added matches array to the externally_connectable object in manifest.json Obtain the extensionID using browser.runtime.id Added listener to onMessageExternal for extension Send a message from a webpage, that is in the matches array, using chrome.runtime.sendMessage with the extensionID obtained above With these steps, I wasn't able to receive a message sending to the extension. I am not sure if the extensionID is wrong or if I am missing any crucial steps. Can someone please recommend what I should try?
Posted Last updated
.
Post not yet marked as solved
1 Answers
45 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 Dannark.
Last updated
.
Post not yet marked as solved
0 Answers
43 Views
I am building a safari extension app. the code(html, css, javascript) for the safari extension that is in the AppExtension directory works good, but when I added button to Main.html to make an Action, to make the app dynamically change (the application itself not the extension), and I want to send data from the app to the extension on Safari. Could anyone help me to fix this issue. This my html code: <!--Main.html --> <!DOCTYPE html> <html> <head>     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">     <meta http-equiv="Content-Security-Policy" content="default-src 'self'">     <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">     <link rel="stylesheet" href="../Style.css">     <script src="../Script.js" defer></script> </head> <body> <!--The makeAction() function is defined in the `Script.js` file -->         <button onclick="makeAction()">Dropdown</button> </body> </html> And this is the files structure
Posted
by osos.
Last updated
.
Post not yet marked as solved
1 Answers
98 Views
I have used Safari as my primary browser for years now and it has evolved. Some very good updates and some bad. I have noticed since iOS 14 I believe when Apple started slowly implementing more security features that pages would show up wonky or unresponsive at times, but a clear browsing history and cookies would fix this issue. Then in iOS 15 and now 16b1 it’s become almost unusable on certain pages.  Again these issues have been ongoing since the updated security features started rolling out and in non beta releases For example. Some pages won’t load completely or when you try to use a drop down menu the pictures would overlap the drop down. Resets or clearing cookies/cache, history would not fix this issue. Even turning off some of the privacy features wouldn’t resolve this. Menus have become unresponsive, ie. registering a new user on a forum. The menus would are static with no way to change or update your dob or address.  I hope this makes sense so far. So here is what I have turned on and added extensions. Tracking is off in privacy & security [on] Block pop ups [on] Prevent cross-tracking [on] Hide IP and Address - Trackers & Websites // I can’t see it but I believe the Trackers & Websites is set to general location// [on] Fraudulent website warnings [on] Privacy Preserving Ad Measurements  All Advanced Safari settings are default and have not been touched  Extensions - 1Blocker (only these below are on) [on] Block Ads [on] Block Adult Sites [on] Block Annoyances [on] Block Trackers I have tested things for months now, toggling these off and back on. Trying to find the combination that works. I even removed all extensions and ran just the safari settings by themselves and it still renders some type of misfire with sites (menus being static or pictures over lapping drop down menus) The title says it all. How can I get safari back to working and have these privacy features on without the extra bugginess that Safari is doing? Thanks in advance!
Posted
by Whiskey.
Last updated
.
Post not yet marked as solved
4 Answers
897 Views
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 &#9;.then(tab => { &#9;&#9;// tab is undefined &#9;}); 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?
Posted
by lollimatt.
Last updated
.
Post not yet marked as solved
3 Answers
945 Views
Hello I am facing issue while implementing browser.tabs.onUpdated.addListener(function (tabID, changeInfo, tab).... This is only working while page is getting reloaded but if only URL is updated without reloading the page this event is not firing. The same thing is working fine in firefox and chrome. Do I need to add something extra?
Posted
by ganeshj.
Last updated
.