添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
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. 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? Hi all. My app has a custom keyboard extension and I am trying to figure out a way to differentiate between a user manually exiting my keyboard vs the entire keyboard being collapsed or hidden. My problem is specifically on on iPhones >= X aka models that do not have a home button. The viewWillDisappear lifecycle method is great for handling both of the above. But I need a way to separate them. I have my own button that advances to the next input which I can account for (green circle). What I do not know how to account for is the user pressing Apple's globe icon to advance to the next input (red circle). Does anyone know a way to react to a user pressing the globe icon/a generic way to know if the user has switched keyboards as opposed to the keyboard going away. I'm working on an "Issuer Provisioning" extension for iOS. Instances of my root PKIssuerProvisioningExtensionHandler subclass are initialised and reinitialised often (every time the user taps the "+" button in the Wallet app) and live for a few milliseconds. So far, so good. The head-scratching part is that the extensions' process lives on across multiple invocations. This in turn has the effect that static member values also live on, meaning they are not in a predictable state during instantiation. Some of my static-loving dependencies are unhappy with this pattern. Is this "process outliving instances" extension pattern a common one? Is it described anywhere? Can it be disabled? I have an app which uses the Call Directory Extension to identify callers. It has been downloaded a few hundred times and a small percentage of users are reporting this error. They are logged in to the app but when they go to phone -> settings -> call blocking & identification they get one of two error messages. "An error occurred while attempting to enable app." "Failed to request data for app. You may try enabling the extension again and if the problem persists contact the application developer." I'm not sure how this could be an issue with the app because it works for the majority of users. Furthermore users still experience the error when I ask them to log in with a test account. One user even reported that they could enable it in settings but a little while later it will disable itself. I have seen similar posts where it's been suggested that the error may be due to bad data (out of order, duplicate contacts, etc) but this error shows before the app even begins to load the data. Does anyone know under what conditions this error popup shows? Many thanks I am building a Safari Web Extension and I am seeing this warning in my console: [NSExtension] Extension request contains input items but the extension point does not specify a set of allowed payload classes. The extension point’s NSExtensionContext subclass must implement +_allowedItemPayloadClasses. This must return the set of allowed NSExtensionItem payload classes. In future, this request will fail with an error. Extension: ) The same code works as expected on iOS, printing the shared URL to the console. Do I have to somehow convert this NSSecureCoding to URL or another object? Or should I do this in a completely different way on macOS? The goal is to access the page's URL from the Share Extension activated when the user selects it in the Share Menu. We have an iOS app with Safari and Content Blocker extensions. Everything works fine when running the app on M1 devices except for the content blocker. The issue is with the following code: contentBlockerManager.getStateOfContentBlocker(withIdentifier: "...") { [ weak self ] in state, error I receive an error which I believe means the content blocker was not found: SFErrorDomain error 1 Now, when running the exact same app with Mac Catalyst all works as expected. Is there a reason for this to happen? Thanks. 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": [ "", "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: I implemented a broadcast upload extension and it requests local notifications. The local notification works normally on broadcastStarted(withSetupInfo:), but the Banner of the local notification does not work on processSampleBuffer(_: with:) though its Notification Center works normally. What am I missing? Here is my code snippets. container app class AppDelegate: NSObject, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. requestAuthorization() private func requestAuthorization() { let center = UNUserNotificationCenter.current() center.requestAuthorization(options: [.alert]) { granted, error in if let error = error { // Handle the error here. print(error) if granted == true { center.delegate = self center.getNotificationSettings(completionHandler: { setting in print(setting) else { print("not permitted") upload extension class SampleHandler: RPBroadcastSampleHandler { override func broadcastStarted(withSetupInfo setupInfo: [String : NSObject]?) { super.broadcastStarted(withSetupInfo: setupInfo) notification(title: "Upload Extension", body: "broadcastStarted") override func processSampleBuffer(_ sampleBuffer: CMSampleBuffer, with sampleBufferType: RPSampleBufferType) { super.processSampleBuffer(sampleBuffer, with: sampleBufferType) if some condition { notification(title: "Upload Extension", body: "processSampleBuffer") private func notification(title: String, body: String) { let content = UNMutableNotificationContent() content.title = title content.body = body let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: nil) let notificationCenter = UNUserNotificationCenter.current() notificationCenter.add(request) { error in if error != nil { print(error) Issue Summary Hi all, I'm working on an Intents Extension for my app, however when I try to run an intent, Xcode pops up the following error: Could not attach to pid: "965" attach failed (Not allowed to attach to process. Look in the console messages (Console.app), near the debugserver entries, when the attach failed. The subsystem that denied the attach permission will likely have logged an informative message about why it was denied.) An image of the error: This only happens when I try debugging the Intent Extension. Running the main app target or another extension target (e.g. notifications) doesn't produce this error. Build Setup Here are the details of my build setup: Mac Mini M1 Xcode 13 Building to iPhone 11 Pro Max, iOS 15.0.2. I've also tried building to my iPad Pro 12.9 w/ iOS 15.1 and hit the same issue. Things I've tried: Make sure "Debug executable" is unchecked in the scheme I've tried changing the Launch setting to "Automatic" and "Wait for the executable to be launched" I've made sure to run sudo DevToolsSecurity -enable on my mac Rebooted iPhone devices + mac mini Uninstalled / reinstalled the app Deleted derived data Removing / reinstalling the development certs in my keychain --> this actually seemed to work initially, but then the problem came back and now it doesn't work anymore. Console Logs I've looked at the console logs while this error occurs to see if it can shed light on the issue. Here are the ones that seemed notable to me. These logs seem to show that Siri is trying to save / write to a file that it does not have access too. Seems very suspicious error 11:42:38.341470-0800 kernel System Policy: assistantd(31) deny(1) file-read-metadata /private/var/mobile/Library/com.apple.siri.inference error 11:42:38.342204-0800 assistantd failed to save contact runtime data. error=Error Domain=NSCocoaErrorDomain Code=512 "The file “com.apple.siri.inference” couldn’t be saved in the folder “Library”." UserInfo={NSFilePath=/var/mobile/Library/com.apple.siri.inference, NSUnderlyingError=0x100fb03a0 {Error Domain=NSPOSIXErrorDomain Code=5 "Input/output error"}} error 11:42:38.342403-0800 assistantd InferenceError error 11:42:38.465702-0800 kernel 1 duplicate report for System Policy: assistantd(31) deny(1) file-read-metadata /private/var/mobile/Library/com.apple.siri.inference Looking for "debugserver" entries, like the error suggests, shows these logs: default 11:42:44.814362-0800 debugserver error: [LaunchAttach] MachTask::TaskPortForProcessID task_for_pid(965) failed: ::task_for_pid ( target_tport = 0x0203, pid = 965, &task ) => err = 0x00000005 ((os/kern) failure) default 11:42:44.814476-0800 debugserver 10 +0.011525 sec [03c6/0103]: error: ::task_for_pid ( target_tport = 0x0203, pid = 965, &task ) => err = 0x00000005 ((os/kern) failure) err = ::task_for_pid ( target_tport = 0x0203, pid = 965, &task ) => err = 0x00000005 ((os/kern) failure) (0x00000005) default 11:42:44.825704-0800 debugserver error: MachTask::StartExceptionThread (): task invalid, exception thread start failed. default 11:42:44.825918-0800 debugserver error: [LaunchAttach] END (966) MachProcess::AttachForDebug failed to start exception thread attaching to pid 965: unable to start the exception thread default 11:42:44.826025-0800 debugserver error: Attach failed default 11:42:44.828923-0800 debugserver error: Attach failed: "Not allowed to attach to process. Look in the console messages (Console.app), near the debugserver entries, when the attach failed. The subsystem that denied the attach permission will likely have logged an informative message about why it was denied.". I've also attached the full details of the error below via a text file if it helps. Any help with this issue would be great, and I'm happy to provide more information if needed. Thanks in advance! Xcode Attach Full Error Details Hi everyone and thanks for your time. Intro I'm developing an iOS app that has Content Blockers as one of its features. For this, we have a list of predefined rules the user can enable/disable at will, and also an option to enter custom rules. Whenever there's a change (enable, disable, add or remove), I get all the rules and recreate the JSON files, one file for every 150K rules (we have more than one content blocker). Most users just need one JSON file though. And then call the content blockers reload. The Problem Most of the time, it works well. The content blocker reloads and I can verify in Safari that it's working. But, sometimes within the completionHandler of: SFContentBlockerManager.reloadContentBlocker(withIdentifier:completionHandler:) It returns the following error: Error Domain=NSCocoaErrorDomain Code=4097 "connection to service named com.apple.SafariServices.ContentBlockerLoader" UserInfo={NSDebugDescription=connection to service named com.apple.SafariServices.ContentBlockerLoader} Localized description: Couldn’t communicate with a helper application. Can't find a reason why this is happening. Some previous research said this could be related to: App groups, but I verified them and they are correctly set (even because the blockers reload works most of the time); Content blocker process being killed. But why would it be killed just sometimes? And how to I verify if this is the case? I'm seeing a number of these errors (added a log) in production. Thanks for the help. Other iOS Safari extension show an "Additional Permissions Requested" header with a Review button on pages that require extension access. On my own extension this is not showing. Content scripts aren't injected until a user finds the extension in the toolbar opened from the browser address bar, and gives permission there. How can I get this permission dialog to show for my own extension on pages where I want to inject content scripts? I am creating in the application support for the Unwanted Communication Reporting extension. All I found is this guide from Apple: https://developer.apple.com/documentation/sms_and_call_reporting/sms_and_call_spam_reporting and i follow it. I've done: Instantiates my ViewController from ILClassificationUIExtensionViewController. Calls controller’s prepare(for:) method to customize UI. Create button to notify the system when you have completed gathering information (setting setting isReadyForClassificationResponse property to true.) Configure classificationResponse(for:) method after pressing Done button. I want to send a response over the network so I add an associated domain to extension by following this instruction: https://developer.apple.com/documentation/xcode/supporting-associated-domain and advises from interenet.  Create file apple-app-site-association, use classificationreport instead of webcredentials when specifying the domains.  "applinks": {   "apps": [],   "details": [     "appID": “XXXX.com.project.UnwantedCommunicationExtension",     "paths": ["*"]  "classificationreport": {    "apps": ["XXXX.com.project.UnwantedCommunicationExtension"] Add domain to the entitlement: Specify the network endpoint’s address using the ILClassificationExtensionNetworkReportDestination key in extension’s Info.plist file: Create test server and sent the apple-app-site-association file to this server.  Debugging and proxying my app, it doesn’t send any requests to the server. I can’t find any information about what request type should be sent, what data type will the server receive. Can anyone help to find information about it? Maybe advice what I did wrong, what settings should be on the server? 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. I am writing a keyboard-extension, there are several buttons and these buttons have a text, therefor I am using localized strings. So the extension is always in the "correct" language. When opening the keyboard-extension with the "world"-button (pressing it long, so that the menu is shown) there is always a line below the name of the app showing "English". As far as I know this is the primary language, there is also one entry for "PrimaryLanguage" in the info.plist (NSExtension/NSExtensionAttributes, set to "en-US"). I tried to remove this entry, but after this the app does not start anymore. Is there a different way to remove this entry or is it possible to change it to the language of the localization? The premises are Open ID Connect, Redirect Extension and a supervised iOS 13 device running with MDM. The extension triggers and the host app successfully retrieves HTTPURLResponse and Data the extension. The flow is as follows: Host app calls AssociatedDomainURL. The SSO extension make an API call to AnotherURL. Inside the extension's beginAuthorization(with:), call complete(httpResponse:httpBody:) and pass AnotherURL's HTTPURLResponse and Data. The host app retrieves AnotherURL's HTTPURLResponse and Data through the extension. In a web browser, the extension triggers when AssociatedDomainURL is entered into the search bar. How does a web app AnotherURL's HTTPURLResponse and Data like the host app? There are many cases where you want to do long-running network operations in a short-lived app extension. For example, you might be creating a share extension that needs to upload a large image to an Internet server. Doing this correctly is quite tricky. The rest of this post describes some of these pitfalls and explains how to get around them. Just by way of context: Most of the following was written during the iOS 8.1 timeframe, although AFAIK there’s been no specific changes in this space since then. The specific focus here is a share extension, although the behaviour is likely to be similar for other short-lived extensions. I wasn’t using SLComposeServiceViewController, although I have no reason to believe that makes a difference. I was testing on a device, not the simulator. In my experience the simulator is much less likely to terminate a share extension, which affects how things behave as I’ll explain later. My app and its share extension have an app group in common. I started by verifying that this app group was working as expected (using UserDefaults). The URLSession must be in that app group; set this via the sharedContainerIdentifier property of the URLSessionConfiguration object you use to create the session. The app and the share extension must use the same URLSession background session identifier (the value you pass in to background(withIdentifier:) when creating the configuration that you use to create the session). When an URLSession background session is shared like this, it’s critical to understand that the session only allows one process to ‘connect’ to it at a time. If a process is connected to the session and another tries to connect, the second process has its session immediately invalidated with NSURLErrorBackgroundSessionInUseByAnotherProcess. The connected session is the one that receives the session’s delegate callbacks. IMPORTANT If callbacks are generated when no process is connected, the background session resumes (or relaunches) the app rather than the extension. If a process is connected to a session and is then suspended or terminates, the session disconnects internally. If the process was terminated, the reconnection happens when your code creates its URLSession object on next launch. If the process was suspended, the reconnect happens when the app is resumed with the application(_:handleEventsForBackgroundURLSession:completionHandler:) delegate callback (and remember that this is always the app, not the extension, per the previous paragraph). The only way to programmatically disconnect from a session is to invalidate it. The expected behaviour here is that the extension will start an URLSession task and then immediately quit (by calling completeRequest(returningItems:completionHandler:)). The system will then resume (or relaunch) the container app to handle any delegate callbacks. When the system resumes or relaunches the container app to handle background session events, it calls application(_:handleEventsForBackgroundURLSession:completionHandler:). The container app is expected to: Save away the completion handler. Reconnect to the session, if necessary. This involves creating the URLSession object if it doesn’t currently exist. Handle delegate events from that session. Invalidate the session when those events are all done. The app knows this because the session calls the urlSessionDidFinishEvents(forBackgroundURLSession:) delegate callback. Call the completion handler that was saved in step 1. This leaves the app disconnected from the session, so future invocations of the extension don’t have to worry about the NSURLErrorBackgroundSessionInUseByAnotherProcess problem I mentioned earlier. This design works best if each extension hosted by the app has its own shared session. If the app hosts multiple extensions, and they all used the same shared session, they could end up stomping on each other. In my tests I’ve noticed that some annoying behaviour falls out of this design: If you start a task from an extension, it’s non-deterministic as to whether the app or extension gets the ‘did complete’ callback. If the task runs super quickly, the extension typically gets the callback. If the task takes longer, the system has time to terminate the extension and the app is resumed to handle it. There’s really no way around this. The workaround is to put the code that handles request completion in both your app and your extension (possibly sharing the code via a framework). It would be nice if the extension could disconnect from the session immediately upon starting its request. Alas, that’s not currently possible (r. 18748008). The only way to programmatically disconnect from the session is to invalidate it, and that either cancels all the running tasks (invalidateAndCancel()) or waits for them to complete (finishTasksAndInvalidate()), neither of which is appropriate. One interesting edge case occurs when the app is in the foreground while the share extension comes up. For example, the app might have a share button, from which the user can invoke the share extension. If the share extension starts an URLSession task in that case, it can result in the app’s application(_:handleEventsForBackgroundURLSession:completionHandler:) callback being called while the app is in the foreground. The app doesn’t need to behave differently in this case, but it’s a little unusual. Xcode’s debugger prevents the system from suspending the process being debugged. So, if you run your extension from Xcode, or you attach to its process some time after launch, the process will continue to execute in situations where the system would otherwise have suspended it. This makes it tricky to investigate problems with the ‘extension was suspended before the network request finished’ case. The best way to investigate any issues you encounter is via logging. Note For more information about debugging problems with background networking, see Testing Background Session Code. Keep in mind that not all networking done by your extension has to use a background session. You should use a background session for long-running requests, but if you have short-running requests then it’s best to run them in a standard session. For example, imagine you have a share extension that needs to make two requests: The first request simply gets an upload authorisation token from the server. This request is expected to finish very quickly. The second request actually uploads the file (including the upload authorisation token from the previous request), and is expected to take a long time. It makes sense to only use a background session for the second request. The first request, being short-running, can be done in a standard session, and that will definitely simplify your code. When doing this you have to prevent your extension from suspending while the short-lived request is in flight. You can use ProcessInfo.performExpiringActivity(withReason:using:) for this. Share and Enjoy Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Revision History 2023-08-30 Fixed the formatting. Adopted Swift terminology throughout. Made other minor editorial changes. 2017-04-26 Moved to the new DevForums. Made many editorial changes. Added the section on Xcode’s debugger. Added a section on short-running network requests. 2014-12-05 First posted on the old DevForums.
This site contains user submitted content, comments and opinions and is for informational purposes only. Apple disclaims any and all liability for the acts, omissions and conduct of any third parties in connection with or related to your use of the site. All postings and use of the content on this site are subject to the Apple Developer Forums Participation Agreement .
  • Forums
  • Terms of Use Privacy Policy License Agreements