Hi.
I created a Message Filter Extension target to filter spam sms messages, deferring the request to my backend. The extension makes the call and send this payload:
POST /server-endpoint HTTP/1.1
Accept: */*
Content-Type: application/json; charset=utf-8
Content-Length: 148
{
"_version": 1,
"query": {
"sender": "14085550001",
"message": {
"text": "This is a message"
}
},
"app": {
"version": "1.1"
}
}
My question is, is possible modify this payload to send the "receiver" number (is possible get the receiver number in this extension?), or use an identifier, to let my backend know which user number the filter was applied to.
I think is impossible because the extension makes the call and create the payload, and I don't see anything in docs to add other prop, but there's other way to know the "receiver" number of the sms?
Thanks:)
Extensions
RSS for tagGive users access to your app's functionality and content throughout iOS and macOS using extensions.
Posts under Extensions tag
200 Posts
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hi,
I want to block incoming calls using my backend server, like the unwantend sms using message filter extension. I saw that Call Directory Extension can block numbers, but you need update the list, is not in real time. I was reading the Live Caller ID Look up extension documentation, and it seems that with this extension is possible send the number to backend and retrieve a value to know if the call should be block or not.
Am I right? Or is not possible this feature with this extension?
Thanks!
I am working on a banking application (includes iPhone and iPad) which includes add to wallet feature.
During the implementation I saw one document it is mentioned that for iPad app, the app must be extended to support Apple pay functionality.
Details from document says "Card Issuers with an iOS mobile banking app must support Card Issuer iOS Wallet extension functionality to enable Card issuer mobile app customers to provision new cards directly from the iOS Wallet app with all eligible Apple iOS devices. If the Card Issuer has a dedicated iPad App, that App must be extended to support Apple Pay functionality. "
Is wallet extension implementation required for Apple pay to work in iPhone and iPad?
Is wallet extension a mandatory implementation for Add to Apple Wallet feature to work and approved by Apple?
I am little confused in this.
Anyone who integrated Apple pay or done add to Apple Wallet feature recently without wallet extension faced any rejection?
Any help would be much appreciated.
DNR rules redirecting to an extension path lead to an error page: “Safari can’t open the page. The error is: “The operation couldn’t be completed. (NSURLErrorDomain error -1008.)” (NSURLErrorDomain:-1,008).”
Here is a demo extension that replicates the bug: https://github.com/lenacohen/Safari-Test-Extensions/tree/main/dnr-extension-path-redirect
This is an example of a redirect rule that leads to an error page instead of the extension path page:
chrome.declarativeNetRequest.updateDynamicRules({addRules: [
{
id: 2,
priority: 1,
action: {
type: "redirect",
redirect: {
extensionPath: "/web_accessible_resources/test_redirect.html"
}
},
condition: {
urlFilter: "||washingtonpost.com^",
resourceTypes: [
"main_frame"
]
}
}
]});
The extension path is included in web_accessible_resources in the extension manifest:
"web_accessible_resources": [{
"resources": [
"web_accessible_resources/test_redirect.html"
],
I also submitted a bug report on Apple's Feedback Assistant: FB16607632
I get the ApplicationSupportDirectory path like this:
let path = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true)[0] as String
however for FileProvider plugin it looks like:
/var/mobile/Containers/Data/PluginKitPlugin/.../Library/Application Support/rclone.conf
instead of what I get for an Application:
/var/mobile/Containers/Data/Application/.../Library/Application Support
I need a way to get the Application's Support Directory from the FileProvider plugin.
Is that possible? If not, what other shared location I could use to access shared file between these two?
In a project to create a web extension for Safari, using scripting.registerContentScript() API to inject a bunch of scripts into web pages, I needed to manage a dynamic whitelist (i.e., web pages where the scripts should not be injected).
Fortunately, scripting.registerContentScripts() gives you the option of defining a list of web pages to be considered as a whitelist, using the excludeMatches parameter in the directive, to represent an array of pages where the script should not be injected.
Here just a sample of what I mean:
const matches = ['*://*/*'];
const excludeMatches = ['*://*.example.com/*'];
const directive = {
id: 'injected-jstest',
js: ['injectedscript.js'],
matches: matches,
excludeMatches: excludeMatches,
persistAcrossSessions: false,
runAt: 'document_start'
};
await browser.scripting.registerContentScripts([directive])
.catch(reason => { console.log("[SW] >>> inject script error:",reason); });
Of course, the whitelist (the excludeMatches array) is not static, but varies over time according to the needs of the moment.
Everything works perfectly in Chromium browsers (Chrome, Edge, ...) and Firefox, but fails miserably in Safari. In fact, Safari seems to completely ignore the excludeMatches parameter and injects the script even where it should not.
Has anyone had the same problem and solved it somehow?
NOTE : To test the correctness and capabilities of the API in each browser, I created a simple repository on Github with the extension code for Chromium, Firefox and Safari (XCode project).
We are testing our safari web extension (https://apps.apple.com/us/app/whatfix-for-jnj-centris/id6723895659) on an iPad 7th Gen (iPadOS v - 17.4.1)
I am sharing a video link where you can see the widget (named Self Help) appears on the application. However after a couple of refreshes, it vanishes. This widget is powered by the extension.
We tried connecting the iPad to Mac and opened the webinspector. The extension content script sends a message to the service worker and it is expected to send back a response which it is not doing
We believe it is related to an issue that has been highlighted multiple times in the developer forum -
https://developer.apple.com/forums/thread/758346
We have tried using several workaorunds as suggested by peer developers in the thread but we are unable to revive the service worker once it is killed.
We would like to understand from you, how to recover from this issue. Is there any workaround that we can apply to make sure that extension works fine?
It would be immensely helpful if we can get on a call to explain the issue further
Video Link: https://www.icloud.com/iclouddrive/0a7NR7BzDQHHU8zCHERuySBMw#RPReplay%5FFinal1740034010
How can NEPacketTunnelProvider launch the companion application, or notify user to launch the application?
I have built an iOS VPN that uses credentials stored in the keychain, and it works as expected. Now I'm trying to add OAuth login support.
Everything works fine at first. I login from the companion application, store tokens in the keychain, then launch the VPN from either System Settings or the companion application.
However, when the OAuth refresh tokens expire, or the OAuth IdP otherwise requires login, I can't perform the OAuth login from the NEPacketTunnelProvider. Login must happen from the companion application, which likely isn't running. I need the NEPacketTunnelProvider to either launch the companion application directly or to notify the user to do so.
Searching and reading docs yields:
You can't perform OAuth login from within the NEPacketTunnelProvider because it requires user interaction
There is no way to guarantee that the companion application is running on iOS (otherwise one would use NEVPNStatusDidChange)
You can't launch the companion application from NEPacketTunnelProvider using a custom URL because of security concerns
You might be able to launch the companion application from a system extension...
Some sources say you still can't guarantee that the system extension is loaded whenever the NEPacketTunnelProvider needs it anyway.
Of course, any of these conclusions could be wrong.
At this point I'm not sure where to begin. Is there another approach that could be initiated by the NEPacketTunnelProvider (push notifications, system notifications, smoke signals)?
Any help would be appreciated.
Thanks,
Bill Welch
Topic:
App & System Services
SubTopic:
Networking
Tags:
Extensions
Network Extension
User Notifications
Hello! What is the TTL for evaluation key(s) used in Live Caller ID feature on iOS client side? We would like to align our server-side key storage TTL with the iOS client implementation to optimize memory usage.
Would really appreciate your help on this.
Issue Summary:
In our Flutter application, we utilize Tencent's TRTC API for voice and video communication. While the broadcast functionality operates correctly on Android, it fails to respond on iOS devices. Attempting to initiate a broadcast results in no action, and long-pressing the broadcast button does not reveal the broadcast extension.
Steps to Reproduce:
Add Broadcast Upload Extension:
In Xcode, navigate to File > New > Target.
Select Broadcast Upload Extension and add it to the project.
2. Build the Project:
Attempt to build the project.
Encounter the error: "Cycle inside Runner; building could produce unreliable results."
3. Resolve Build Cycle Error:
Go to the project’s Build Phases.
Locate the Embed App Extensions phase.
Move Embed App Extensions just below Copy Bundle Resources.
Ensure the Copy only when installing option is selected.
Rebuild the project; the cycle error is resolved.
4.Test Broadcast Functionality:
Install the app on an iOS device.
Tap the broadcast button; observe no response.
Long-press the broadcast button in the top right hand scroll down menu; the broadcast extension is not listed.
5. Isolate the Issue:
Create a new Flutter project.
Repeat the above steps to add the broadcast upload extension.
The issue persists: broadcast functionality remains unresponsive on iOS.
We are building a Safari web extension utilising native messaging, to send messages to the Swift native part of the app. We sometimes experience, that the beginRequest handler is executed multiple times, at the same time.
We have a special part of the code in the handler, that must be run only once. Because it uses NS defaults storage, and also because it calls our servers. We have tried to use a serial dispatch queue, as well as other locking and mutex techniques, to no success.
We suspect that the instances of the handler are isolated in a way, that these locks don’t work (maybe they don’t share memory?). But we are not sure. When looking at os_logs from the handlers, they all share the same PID.
Has anyone experienced anything similar and can shed some light on what's going on?
❌ Could not find email_ai.py in the app bundle. Available files: []
The error above is what I’m encountering.
I’ve placed the referenced file both in the project directory and inside the app. However, every time I remove and reinsert the file into the folder within the app, it prompts me to designate the targets—I select all, but this doesn’t resolve the issue.
I’m unsure how to properly reference the file so that it is recognised and included in the bundle. Any guidance would be greatly appreciated.
this is my build phase:
#!/bin/sh
set -x # Prints each command before running it (for debugging)
pwd # Shows the current working directory
echo "$SRCROOT" # Shows what Xcode thinks is the project root
ls -l "$SRCROOT/EmailAssistant/EmailAssistant/PythonScripts" # Lists files in the script folder
export PYTHONPATH="/Users/caesar/.pyenv/versions/3.11.6/bin"
/Users/caesar/.pyenv/versions/3.11.6/bin/python3 "$SRCROOT/EmailAssistant/EmailAssistant/PythonScripts/email_ai.py"
echo "Script completed."
hi, I'm having an issue with Safari devlop menu "Web Extension Background Content" menu item being grayed out. I cant do any debugging right now and its becoming mission critical for us. Any help is appreciated.
Thank you,
Topic:
Safari & Web
SubTopic:
General
Tags:
Extensions
Web Inspector
Safari Developer Tools
Safari Extensions
We have a Web Extension that uses firebase for auth. It was working fine until the latest version of Safari 18.3 got released few days ago on January 27, 2025.
All of out extension versions stopped working on it; even the ones that are published on App Store. It uses FirebaseJS v9.23.0.
Same version of the extension are working fine on other browsers. We use onAuthStateChanged to listen to auth related events; but it is never fired now.
I have a content blocker that generally works correctly, but I need to block an element that has certain text in it.
For example, <span id="theId">Some text</span> is easy enough to block because I can locate the id and block that, but what if there is no id, or the id is completely random? What if it's just <span>Some text</span>? How do I block that?
Let's say this is my only content blocker rule:
[
{
"action": {
"type": "css-display-none",
"selector": ":has-text(/Some text/i)"
},
"trigger": {
"url-filter": ".*"
}
}
]
No errors are seen when the rule is loaded, so it's syntactically correct, it just doesn't block the HTML. I gather this is because :has-text() works on attributes, not contents, so it works on alt, href, aria-label etc. but not on the contents of the element itself.
How do I block Some text in my example above? Thanks!
I am currently developing a custom-protocol VPN application for iOS using PacketTunnelProvider. I have also integrated an HTTP proxy service, which is launched via a dylib.
The overall flow is as follows:
App -> VPN TUN -> Local HTTP Proxy -> External Network
I have a question:
I am capturing all traffic, and normally, requests sent out by the HTTP proxy are also captured again by the VPN. However, when I send requests using createUdpSession in my code, they are not being captured by the virtual interface (TUN).
What could be the reason for this?
override func startTunnel(options: [String : NSObject]?, completionHandler: @escaping (Error?) -> Void) {
let tunnelNetworkSettings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "192.168.18.0")
tunnelNetworkSettings.mtu=1400
let ipv4Settings = NEIPv4Settings(addresses: ["192.169.10.10"], subnetMasks: ["255.255.255.0"])
ipv4Settings.includedRoutes=[NEIPv4Route.default()]
ipv4Settings.excludedRoutes = [NEIPv4Route(destinationAddress: "10.0.0.0", subnetMask: "255.0.0.0"),
NEIPv4Route(destinationAddress: "172.16.0.0", subnetMask: "255.240.0.0"),
NEIPv4Route(destinationAddress: "192.168.0.0", subnetMask: "255.255.0.0"),
NEIPv4Route(destinationAddress:"127.0.0.0", subnetMask: "255.0.0.0"),
]
tunnelNetworkSettings.ipv4Settings = ipv4Settings
// Configure proxy settings
let proxySettings = NEProxySettings()
proxySettings.httpEnabled = true
proxySettings.httpServer = NEProxyServer(address: "127.0.0.1", port: 7890)
proxySettings.httpsEnabled = true
proxySettings.httpsServer = NEProxyServer(address: "127.0.0.1", port: 7890)
proxySettings.excludeSimpleHostnames = true
proxySettings.exceptionList=["localhost","127.0.0.1"]
tunnelNetworkSettings.proxySettings = proxySettings
setTunnelNetworkSettings(tunnelNetworkSettings) { [weak self] error in
if error != nil {
completionHandler(error)
return
}
completionHandler(nil)
let stack = TUNInterface(packetFlow: self!.packetFlow)
RawScoketFactory.TunnelProvider=self
stack.register(stack: UDPDirectStack())
stack.register(stack: TCPDirectStack())
stack.start()
}
}
NWUdpSession.swift
//
// NWUDPSocket.swift
// supervpn
//
// Created by TobbyQuinn on 2025/2/3.
//
import Foundation
import NetworkExtension
import CocoaLumberjack
public protocol NWUDPSocketDelegate: AnyObject{
func didReceive(data:Data,from:NWUDPSocket)
func didCancel(socket:NWUDPSocket)
}
public class NWUDPSocket:NSObject{
private let session:NWUDPSession
private let timeout:Int
private var pendingWriteData: [Data] = []
private var writing = false
private let queue:DispatchQueue=QueueFactory.getQueue()
public weak var delegate:NWUDPSocketDelegate?
public init?(host:String,port:UInt16,timeout:Int=Opt.UDPSocketActiveTimeout){
guard let udpSession = RawScoketFactory.TunnelProvider?.createUDPSession(to: NWHostEndpoint(hostname: host, port: "\(port)"), from: nil) else{
return nil
}
session = udpSession
self.timeout=timeout
super.init()
session.addObserver(self, forKeyPath: #keyPath(NWUDPSession.state),options: [.new], context: nil)
session.setReadHandler({ dataArray, error in
self.queueCall{
guard error == nil, let dataArray = dataArray else {
print("Error when reading from remote server or connection reset")
return
}
for data in dataArray{
self.delegate?.didReceive(data: data, from: self)
}
}
}, maxDatagrams: 32)
}
/**
Send data to remote.
- parameter data: The data to send.
*/
public func write(data: Data) {
pendingWriteData.append(data)
checkWrite()
}
public func disconnect() {
session.cancel()
}
public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
guard keyPath == "state" else {
return
}
switch session.state {
case .cancelled:
queueCall {
self.delegate?.didCancel(socket: self)
}
case .ready:
checkWrite()
default:
break
}
}
private func checkWrite() {
guard session.state == .ready else {
return
}
guard !writing else {
return
}
guard pendingWriteData.count > 0 else {
return
}
writing = true
session.writeMultipleDatagrams(self.pendingWriteData) {_ in
self.queueCall {
self.writing = false
self.checkWrite()
}
}
self.pendingWriteData.removeAll(keepingCapacity: true)
}
private func queueCall(block:@escaping ()->Void){
queue.async {
block()
}
}
deinit{
session.removeObserver(self, forKeyPath: #keyPath(NWUDPSession.state))
}
}
Hello
My app has implementation of In App Provisioning which is working fine. We have now added Wallet Extensions to it, but my App is not shown in Apple Wallet "From apps on your iphone"
I have uploaded Feedback (FB16450547) at
https://feedbackassistant.apple.com/feedback/16450547
Kindly request for your advice
Hi Apple Developers,
I am currently working on a message filtering application and facing issues specifically with filtering RCS (Rich Communication Services) messages. To debug this, I created a sample app that consistently categorizes all incoming messages as "junk." However, the filtering behaviour is inconsistent and not functioning as expected.
Here are the key issues observed during testing on iOS versions 18.2.1 and 18.3:
Inconsistent Filtering Behavior:
When a message is received from an unknown number, it sometimes gets moved to the Junk folder momentarily but is then immediately moved back to the main Messages inbox.
In some cases, the message does not get moved to the Junk folder at all, despite the app returning the verdict as "junk."
Duplicate Contact Tiles:
The Messages app displays two separate conversation tiles for the same mobile number, which is unexpected behavior.
For reference, my carrier partner is T-Mobile. Please let me know if you need any additional information to investigate this issue further.
Looking forward to your insights and guidance.
Best regards,
Rijul Singhal
Use case: When users open any URL in iOS Safari and tap the share button, the share extension can automatically receive the PDF version of the webpage from Safari.
We've observed that the system Markup app and the Apple Books app can automatically receive a PDF file from Safari. However, our custom share extension only receives the webpage URL.
While iOS Safari provides an "Options" button to manually share a webpage as a PDF, this feature is not intuitive and requires user education.
Could someone help to identify the correct NSExtensionActivationRule (or any other solution) that would allow our share extension to directly receive the PDF snapshot from Safari without requiring additional user actions?
I am implementing a new Intents UI Extension and am noticing that the viewWillDisappear, viewDidDisappear, and deinit methods are not being called on my UIViewController that implements INUIHostedViewControlling, when pressing the "Done" button and dismissing the UIViewController.
This causes the memory for the UI Extension to slowly increase each time I re-run the UI Extension until it reaches the 120MB limit and crashes.
Any ideas as to what's going on here and how to solve this issue?
Worth noting that while the memory does continuously increase on iOS versions before iOS 17, only in 17 and later does the 120MB memory limit kick in and crash the extension.