WWDC Quick Look 💓 By SwiftGGTeam
Meet Safari Web Extensions

Meet Safari Web Extensions

Watch original video

Highlight

Safari supports Web Extensions built with JavaScript, HTML, and CSS on macOS, and provides Xcode conversion tools, per-site authorization, Web Inspector debugging, and native messaging, allowing existing Chrome, Firefox, and Edge extensions to enter the Safari and App Store distribution process.

Core Content

If you already have a browser extension, the most troublesome part is often the migration cost. Old Safari app extensions are aimed at native app developers who are familiar with Swift or Objective-C. When web developers already have JavaScript, HTML, and CSS extensions in hand, they don’t want to rewrite a native implementation just to enter Safari.

This session announced Safari support for Safari web extensions on macOS. It uses the extension model and API familiar to other major browsers while retaining Safari’s user privacy controls. The extension is still packaged with the native app; when the app is installed, the extension is also installed in Safari and the distribution path goes to the App Store.

Apple puts migration portal into Xcode 12. Existing extensions can use the Safari web extension converter to generate Xcode projects. The converter will read the manifest, prompt Safari for keys that are not currently supported, and package the extension into a native app. When there is no ready-made extension, you can also create it from scratch using the Safari extension app template in Xcode.

The second half will solve several problems before the actual launch. Permissions no longer mean that the extension can directly read whichever site it wants to read. Safari will hand over the selection of activeTab, content scripts, optional permissions and all_urls to the user for confirmation. When debugging, Web Inspector can inspect popovers, background pages, and content scripts separately. When it is necessary to exchange data with the container app, the extension communicates with the app extension and the app through native messaging.

Detailed Content

Use converter to turn existing extensions into Xcode projects

(02:16) Safari web extensions, like other Safari extensions, are packaged in native apps. After the native app is installed, the extension is also installed to Safari. This app can be distributed through the App Store; development and operation require Xcode 12 or higher.

(02:52) The command-line converter that comes with Xcode only needs to be run once. It creates a default Xcode project based on the extension manifest, allowing the project to build and run the native app containing the extension. When a key that is not currently supported by Safari appears in the manifest, the converter will prompt the developer.

(04:19) After the Sea Creator extension in the demonstration is processed by the converter, the tool prompts whether the manifest information is correct, and also reports that the notifications API is not supported in the current Safari version. After the conversion continues, the Xcode project can run a default app; this app shows whether the extension is enabled and provides a button to open Safari Preferences.

Key points:

  • converter creates Xcode projects using manifest information, with the goal of wrapping existing web extensions rather than rewriting extension logic.
  • The largest icon in the manifest will become the app icon. Session recommends adding 512 x 512 and 1024 x 1024 icons.
  • If new files are added to the extension later, these files must also be added to the Xcode project.
  • Extensions of ad-hoc signed apps will not appear in Safari by default. When testing, you must first open the Develop menu and then allow unsigned extensions.

When creating a new Web Extension from Xcode, first look at the manifest

(07:21) When there is no other browser extension, you can use Xcode’s Safari extension app template to create it. If you already have a Mac app, you can add the Safari Extension target under the macOS tab and select the type as web extension. The scenario in the demo is to add a Safari extension to a recipe app to allow users to save recipes in Safari.

(08:44) Manifest defines the extension structure.namekey can point to a localizable string, which is then used by the locales foldermessages.jsonContinue with the definition. The three main parts of an extension are background scripts, content scripts, and popover.

(09:32) Background scripts have no visible UI and can hold logic that drives extensions. Content scripts will be injected into web pages and run in an isolated world to avoid conflicts with web page JavaScript;matchesDecide which domains to inject into. The popover is defined by the browser action key and is displayed when the user clicks the toolbar button.

Key points:

  • Manifest is the entry file of Safari web extension. It first defines the name, structure, script and permissions.
  • Background scripts are suitable for extending internal logic.
  • Content scripts can change the appearance and behavior of web pages, but run in an isolated environment.
  • The permissions key can contain API names, such as cookies, or URL match strings.

Narrow the permission request to the scope actually triggered by the user

(11:23) Safari’s permissions model starts from browsing privacy. Once a user installs an extension, Safari lets the user control what website data can be accessed by the extension. The demonstration uses activeTab first: the extension can only access the page of the current tab and inject scripts when the user explicitly uses the extension through the toolbar icon, context menu item or keyboard shortcut.

(12:52) If you write the content script into the manifest and let it be automatically injected into wikipedia.org, Safari will display a warning badge on the toolbar button. After the user clicks, they will see which website the extension wants to visit and can allow it for one day. When visiting other Wikipedia pages later, the selection will be remembered and the content script will be injected directly.

(14:10) Optional permissions are used to handle non-core capabilities. Demonstrates putting the URL match pattern of shiny.com into the manifest, and then calling it when the user clicks the Share buttonbrowser.permissions.requestRequest access to this origin. After the user approves, the extension continues to execute sharing-related logic.

(16:24) The advice given by Session is very straightforward: use activeTab first. When activeTab is not suitable, request expansion to the minimum range that can work. Use optional permissions for non-core functionality. Only consider all_urls if your extension really needs to access all web pages.

Key points:

  • activeTab binds access to web pages to user actions.
  • The content script declared in the manifest still needs to go through Safari’s site authorization experience.
  • Optional permissions are suitable for additional functions such as sharing and integrating third-party sites.
  • all_urls will cause Safari to remind the user that the extension has the ability to access all websites.

Use Web Inspector to check popover, background page and content scripts respectively

(18:16) The popover image in the demo is broken. After right-clicking popover inspect, the error shows that the extension resource URL is hard-coded into moz-extension scheme. Safari cannot be changed to a fixed safari-web-extension scheme because the host of the extension URL will change every time Safari is started to prevent users from being fingerprinted.

(18:53) The correct way is to usebrowser.runtime.getURLGenerate extension resource URL. After repair, the picture can be displayed normally. background page You can also find the corresponding extension through the Web Extension Background Pages of the Develop menu and check it.

(19:42) The debugging entry for content scripts is on the page itself. Go to the page where the content script has been injected. After right-clicking inspect, the Sources tab will list the extension scripts and style sheets of the injected page. Since content scripts run in the isolated world, the Console points to the JavaScript world of the page by default. When debugging, you need to switch to the extended isolated world.

(20:51) There are several common bugs when converting extensions. Don’t rely on user agent checking, feature detection is more reliable. Do not assume that the scheme or host of an extended resource URL is fixed. Content scripts cannot assume that they must be injected before DOM content is loaded, because the user may open the page first and then authorize the extension to inject the script.

Key points:

  • Popover, background page, and content scripts all have independent inspection entrances.
  • Extended resource URL to be passedbrowser.runtime.getURLgenerate.
  • The Console of content scripts needs to switch to the extended isolated world.
  • Prioritize feature detection when converting extensions, and check injection timing assumptions.

Connect extensions and container apps via native messaging

(22:03) Native messaging allows apps and extensions to communicate. The difference between Safari and other browsers is that extensions can only communicate with their own container app. background page to app extension native code using APIs also available in other browsers:browser.runtime.sendNativeMessageorbrowser.runtime.connectNative, and request native messaging permission in the manifest.

(22:54) Reverse messages also have corresponding entrances. app extension native code To send a message to the background page, you can use the incomingSafariWebExtensionHandler.beginRequestofNSExtensionContextcompletion handler. If the app wants to send a message to the extension background page, useSFSafariApplication.dispatchMessage. Before using it, it is recommended to pass SessionSFSafariExtensionManager.getStateOfSafariExtensionCheck if the extension is enabled.

background page -> browser.runtime.sendNativeMessage / browser.runtime.connectNative -> app extension native code
app extension native code -> SafariWebExtensionHandler.beginRequest's NSExtensionContext completion handler -> background page
app -> SFSafariApplication.dispatchMessage -> background page
app and app extension -> NSUserDefaults or XPC connection

(24:01) Demonstrates displaying the number of text replacement script runs in the native app UI. The process is: manifest adds native messaging permission, content script notifies background page, and background page callssendNativeMessage, the native handler reads the message and writesNSUserDefaults, the parent app then reads this value and refreshes the UI. When writing defaults, you need to specify the suite, and the bundle identifier is used to put the app and app extension into the same app group.

Key points:

  • Safari only allows extensions to communicate with their own container app.
  • Before the background page sends native messages, it must request native messaging permission in the manifest.
  • Before the app sends a message to the background page, it should confirm that the extension has been enabled in Safari.
  • Can be used when sharing data between app and app extensionNSUserDefaultsor XPC connection.

Core Takeaways

  • Migrate an existing Chrome or Firefox extension to a Safari version: What to do: Take an existing extension and run Safari web extension converter, generate an Xcode project and enable it in Safari Preferences. Why it’s worth doing: Session clearly states that the converter will read the manifest, prompt for unsupported keys, and package the extension into the native app. How to start: First complete the 512 x 512 and 1024 x 1024 icons, then convert the project, and finally check every manifest warning.

  • Make a page tool authorized by site: What to do: Let the extension only access the current tab after the user clicks the toolbar button by default, and then request longer-term authorization for specific sites. Why it’s worth doing: activeTab, content scripts and optional permissions are all displayed by Session, which can limit the access scope to the pages that the user actually agrees to. How to start: First use activeTab to complete the core actions, and then integrate non-core sites into optional permissions.

  • Make a Safari extension debugging checklist: What to do: Fixed three inspection entries for popover, background page, and content scripts for the team. Why it’s worth doing: Session’s image URL bug explains that cross-browser extensions often go wrong in resource URLs, isolated worlds, injection timing, and user agent detection. How to start: First change the resource URL tobrowser.runtime.getURL, and then use Web Inspector to switch to the isolated world verification state of the content script.

  • Let the extension synchronize results to native app UI: What to do: Synchronize extension run times, web page processing results, or user actions back to the container app. Why it’s worth doing: Session demonstrates content script, background page, app extension native code,NSUserDefaultsA complete link to the parent app. How to start: First request native messaging permission, then send a minimal message from the background page, and write the native handler to the app group suite.

  • Design a permission check for site-wide injection extensions: What to do: Review whether the extension really requires all_urls and whether it can be changed to a narrower URL match pattern. Why it’s worth doing: Session explicitly reminds you that if your extension doesn’t need to access all web pages, it should limit web page access requests more precisely. How to get started: List the target domains for existing content scripts, first change them to specific matches, and then put additional sites into optional permissions.

  • What’s new in Web Inspector — After learning to use Web Inspector to check popover, background page and content scripts, see if this system can complement the Safari debugging tool.
  • What’s new for web developers — Safari Web Extensions run on top of Safari and WebKit, this provides background on the web platform updates of the same year.
  • Discover WKWebView enhancements — Safari Web Extensions rely on the native app container, and WKWebView helps understand the interface between App and Web content.
  • Meet Face ID and Touch ID for the web — Both are Safari Web platform capabilities, showing how the Web Authentication API brings device authentication to website login.
  • One-tap account security upgrades — The account authentication modification extension, like the Safari extension, connects web and system services with the user authorization experience.

Comments

GitHub Issues · utterances