{"id":9299,"date":"2026-07-23T04:35:21","date_gmt":"2026-07-23T11:35:21","guid":{"rendered":"https:\/\/blog.mozilla.org\/addons\/?p=9299"},"modified":"2026-07-23T04:35:21","modified_gmt":"2026-07-23T11:35:21","slug":"firefox-153-webextensions-api-updates","status":"publish","type":"post","link":"https:\/\/blog.mozilla.org\/addons\/2026\/07\/23\/firefox-153-webextensions-api-updates\/","title":{"rendered":"Firefox 153 WebExtensions API updates"},"content":{"rendered":"<p>We had a bumper release of <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Mozilla\/Firefox\/Releases\/153#changes_for_add-on_developers\">WebExtensions API updates in Firefox 153<\/a>. To start, there is a permissions change that affects how your extensions access local files. We then have two contributions from the community members: <span style=\"color: #339966;\">userScripts.execute()<\/span> and the new <span style=\"color: #339966;\">publicSuffix<\/span> API. We&#8217;re covering those contributions in more depth, including the people behind them, in a separate post. And there is more, read on\u2026<\/p>\n<h2><b>File access now requires a dedicated permission<\/b><\/h2>\n<p>Extensions that need to read <span style=\"color: #339966;\">file:\/\/<\/span> URLs used to get that access as part of the &#8220;Access your data for all websites&#8221; host permission. Starting in Firefox 153, file access is a separate, explicit permission, &#8220;Access local files on your computer&#8221;, shown in the extension&#8217;s permissions settings. It&#8217;s off by default for every extension, including ones already installed.<\/p>\n<p>This change has a few concrete effects on code:<\/p>\n<ul>\n<li aria-level=\"1\"><b>Before:<\/b> an extension with <span style=\"color: #339966;\">&lt;all_urls&gt;<\/span> or a matching host permission could read <span style=\"color: #339966;\">file:\/\/<\/span> pages without any additional grant, and <span style=\"color: #339966;\">extension.isAllowedFileSchemeAccess()<\/span> always returned <span style=\"color: #339966;\">false<\/span> regardless of the permission setting.<\/li>\n<li aria-level=\"1\"><b>After:<\/b> the extension must have the new file-access permission granted, and <span style=\"color: #339966;\">extension.isAllowedFileSchemeAccess()<\/span> correctly reflects whether the user has granted it.<\/li>\n<\/ul>\n<pre>async function checkFileSchemeAccess() {\r\n  const isAllowed = await browser.extension.isAllowedFileSchemeAccess();\r\n\r\n  if (!isAllowed) {\r\n    await browser.notifications.create(\"file-scheme-access-needed\", {\r\n      type: \"basic\",\r\n      iconUrl: browser.runtime.getURL(\"icons\/icon-48.png\"),\r\n      title: \"Local file access required\",\r\n      message:\r\n        'This extension needs \"Allow access to file URLs\" enabled to work ' +\r\n        \"with local files. Go to about:addons \u2192 select this extension \u2192 \" +\r\n        \"turn on that setting, then reload the page.\",\r\n    });\r\n    return false;\r\n  }\r\n\r\n  return true;\r\n}<\/pre>\n<p><span style=\"color: #339966;\">devtools.inspectedWindow.eval()<\/span> calls targeting <span style=\"color: #339966;\">file:\/\/<\/span> URLs are affected the same way; they now require this permission to succeed.<\/p>\n<p>If your extension depends on <span style=\"color: #339966;\">file:\/\/<\/span> access, expect existing users to see that access stops after upgrading (until they enable the permission), and consider adding a prompt or fallback path, for example by specifying an embedded options page (<span style=\"color: #339966;\">options_ui<\/span>) and calling <span style=\"color: #339966;\">browser.runtime.openOptionsPage()<\/span> to open <span style=\"color: #339966;\">about:addons<\/span> and including instructions to toggle the setting in the \u201cPermissions and data\u201d tab.<\/p>\n<h2><b>userScripts.execute() and publicSuffix: covered in our next post<\/b><\/h2>\n<p>Firefox 153 adds two community-contributed APIs:<\/p>\n<ul>\n<li aria-level=\"1\"><span style=\"color: #339966;\">userScripts.execute()<\/span>, which provides for one-off injection of one or more user script sources into a tab or frame, in a defined order, as a complement to the persistent, URL-pattern-based <span style=\"color: #339966;\">userScripts.register()<\/span>.<\/li>\n<li aria-level=\"1\"><span style=\"color: #339966;\">publicSuffix<\/span>, which enables synchronous lookups against the browser&#8217;s built-in <a href=\"https:\/\/publicsuffix.org\/\">Public Suffix List<\/a> using <span style=\"color: #339966;\">publicSuffix.isKnownSuffix()<\/span>, <span style=\"color: #339966;\">publicSuffix.getKnownSuffix()<\/span>, and <span style=\"color: #339966;\">publicSuffix.getDomain()<\/span>. This API means that extensions no longer need to bundle or maintain a suffix list to determine a hostname&#8217;s registrable domain (eTLD+1).<\/li>\n<\/ul>\n<p>Both APIs were built by contributors motivated by real needs in their extensions. We take an in-depth look at these contributions, their developers, impact, and history in a forthcoming post.<\/p>\n<h2><b>documentId support across more APIs<\/b><\/h2>\n<p>Firefox 153 introduces <span style=\"color: #339966;\">documentId<\/span>, a stable identifier for a document instance, including a new <span style=\"color: #339966;\">runtime.getDocumentId()<\/span> method, several <span style=\"color: #339966;\">webNavigation<\/span> events and methods, <span style=\"color: #339966;\">webRequest<\/span> events, scripting injection targets, and the extension messaging APIs.<\/p>\n<p>Many WebExtension APIs use <span style=\"color: #339966;\">tabId<\/span> and <span style=\"color: #339966;\">frameId<\/span> to identify where to perform an operation. However, because <span style=\"color: #339966;\">frameId<\/span> identifies the frame rather than its content, the loaded document can change and the extension&#8217;s subsequent operation ends up targeting the new (intended) document. <span style=\"color: #339966;\">documentId<\/span> addresses this problem by providing a unique ID for the document. Now, if an extension uses the ID and the frame\u2019s document has changed, the operation fails rather than silently targeting the wrong document.<\/p>\n<p>See <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Mozilla\/Add-ons\/WebExtensions\/Work_with_documentId\">Work with documentId<\/a> for the full list of supported events and methods, along with guidance on using it.<\/p>\n<h2><b>Content scripts can read and modify adopted stylesheets<\/b><\/h2>\n<p>Content scripts can now access <span style=\"color: #339966;\">document.adoptedStyleSheets<\/span> and <span style=\"color: #339966;\">ShadowRoot.adoptedStyleSheets<\/span> directly.<\/p>\n<pre>const sheet = new CSSStyleSheet();\r\nsheet.replaceSync(\"* { background: pink; }\");\r\ndocument.adoptedStyleSheets = [sheet];<\/pre>\n<p>This enables extensions to inspect or modify constructed stylesheets from a content script, without using <span style=\"color: #339966;\">.wrappedJSObject<\/span>, a workaround that risks interference from the web page.<\/p>\n<h2><b>Theme manifest key: gradients in additional backgrounds<\/b><\/h2>\n<p>The <span style=\"color: #339966;\">theme<\/span> manifest key&#8217;s <span style=\"color: #339966;\">images.additional_backgrounds<\/span> property now accepts CSS gradients alongside image URLs. A new <span style=\"color: #339966;\">properties.additional_backgrounds_size<\/span> property controls the size of each additional background item.<\/p>\n<h2><b>Contextual identities (containers)<\/b><\/h2>\n<p>If your extension supports contextual identities, you now have access to two new methods: <span style=\"color: #339966;\">contextualIdentities.getSupportedColors()<\/span> and <span style=\"color: #339966;\">contextualIdentities.getSupportedIcons()<\/span>. These methods return the supported colors and icons, so your extension doesn&#8217;t need to hardcode either list.<\/p>\n<p>Also, the colors have been updated to align with the new UI theme: <span style=\"color: #339966;\">&#8220;turquoise&#8221;<\/span> is now <span style=\"color: #339966;\">&#8220;cyan&#8221;<\/span>, <span style=\"color: #339966;\">&#8220;toolbar&#8221;<\/span> is now <span style=\"color: #339966;\">&#8220;gray&#8221;<\/span>, and <span style=\"color: #339966;\">&#8220;violet&#8221;<\/span> has been added. The old names still work for backward compatibility, but your extension should switch to using <span style=\"color: #339966;\">getSupportedColors()<\/span> rather than hardcoding either the old or new names.<\/p>\n<h2><b>Add a build-for-amo script<\/b><\/h2>\n<p>While this isn\u2019t about new APIs, I wanted to mention a change that\u2019s part of our work to make source code review faster and more reliable. When you submit an extension version, AMO now attempts to build your extensions from the submitted source code and compares the result to the package you uploaded. When the two match, reviewers don&#8217;t have to verify the build manually. This means submission can move through its review faster.<\/p>\n<p>For now, this applies only if you submit source code that includes a <span style=\"color: #339966;\">package.json<\/span> file to build your extension. If your extension has no build step, or you use a different build system, nothing changes. The AMO builder keeps its zero-config approach.<\/p>\n<p>So, if your extension\u2019s source code uses a <span style=\"color: #339966;\">package.json<\/span> file, add an <a href=\"https:\/\/docs.npmjs.com\/cli\/v11\/using-npm\/scripts\">npm script<\/a> named <span style=\"color: #339966;\">build-for-amo<\/span> that runs the commands needed to build your extension for Firefox:<\/p>\n<pre>{\r\n  \"scripts\": {\r\n    \"fx-build\": \"some commands to build your add-on for Firefox\",\r\n    \"build-for-amo\": \"npm run fx-build\"\r\n  }\r\n}<\/pre>\n<p>If you\u2019ve a Firefox-specific build command, just point <span style=\"color: #339966;\">build-for-amo<\/span> at it. When present, the builder invokes this script instead of guessing how to build your extension. And while you are at it, make sure all your dev dependencies are listed in the <span style=\"color: #339966;\">package.json<\/span> file.<\/p>\n<hr \/>\n<p>For more information, including documentation and Bugzilla links, see the <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Mozilla\/Firefox\/Releases\/153#changes_for_add-on_developers\">Changes for add-on developers<\/a> section of the Firefox 153 for developers release notes on MDN.<\/p>\n<p>As always, file extension-related issues on <a href=\"https:\/\/bugzilla.mozilla.org\/\">Bugzilla<\/a> under the WebExtensions product, cross-browser API proposals are discussed in the <a href=\"https:\/\/github.com\/w3c\/webextensions\">W3C WebExtensions Community Group<\/a>, and questions are welcome on the <a href=\"https:\/\/discourse.mozilla.org\/c\/add-ons\/35\">Add-ons Discourse<\/a>.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>We had a bumper release of WebExtensions API updates in Firefox 153. To start, there is a permissions change that affects how your extensions access local files. We then have &hellip; <a class=\"go\" href=\"https:\/\/blog.mozilla.org\/addons\/2026\/07\/23\/firefox-153-webextensions-api-updates\/\">Read more<\/a><\/p>\n","protected":false},"author":2039,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[44,278886],"tags":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v22.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Firefox 153 WebExtensions API updates<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blog.mozilla.org\/addons\/2026\/07\/23\/firefox-153-webextensions-api-updates\/\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"cbacharakis@mozilla.com\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/blog.mozilla.org\/addons\/2026\/07\/23\/firefox-153-webextensions-api-updates\/\",\"url\":\"https:\/\/blog.mozilla.org\/addons\/2026\/07\/23\/firefox-153-webextensions-api-updates\/\",\"name\":\"Firefox 153 WebExtensions API updates\",\"isPartOf\":{\"@id\":\"https:\/\/blog.mozilla.org\/addons\/#website\"},\"datePublished\":\"2026-07-23T11:35:21+00:00\",\"dateModified\":\"2026-07-23T11:35:21+00:00\",\"author\":{\"@id\":\"https:\/\/blog.mozilla.org\/addons\/#\/schema\/person\/83a047c76910255b455ef06faafc194a\"},\"breadcrumb\":{\"@id\":\"https:\/\/blog.mozilla.org\/addons\/2026\/07\/23\/firefox-153-webextensions-api-updates\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/blog.mozilla.org\/addons\/2026\/07\/23\/firefox-153-webextensions-api-updates\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/blog.mozilla.org\/addons\/2026\/07\/23\/firefox-153-webextensions-api-updates\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/blog.mozilla.org\/addons\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Firefox 153 WebExtensions API updates\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/blog.mozilla.org\/addons\/#website\",\"url\":\"https:\/\/blog.mozilla.org\/addons\/\",\"name\":\"Mozilla Add-ons Community Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/blog.mozilla.org\/addons\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/blog.mozilla.org\/addons\/#\/schema\/person\/83a047c76910255b455ef06faafc194a\",\"name\":\"cbacharakis@mozilla.com\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/blog.mozilla.org\/addons\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/8b0f872ddf5a2dd99475e60360cdabd1?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/8b0f872ddf5a2dd99475e60360cdabd1?s=96&d=mm&r=g\",\"caption\":\"cbacharakis@mozilla.com\"},\"url\":\"https:\/\/blog.mozilla.org\/addons\/author\/cbacharakismozilla-com\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Firefox 153 WebExtensions API updates","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blog.mozilla.org\/addons\/2026\/07\/23\/firefox-153-webextensions-api-updates\/","twitter_misc":{"Written by":"cbacharakis@mozilla.com","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/blog.mozilla.org\/addons\/2026\/07\/23\/firefox-153-webextensions-api-updates\/","url":"https:\/\/blog.mozilla.org\/addons\/2026\/07\/23\/firefox-153-webextensions-api-updates\/","name":"Firefox 153 WebExtensions API updates","isPartOf":{"@id":"https:\/\/blog.mozilla.org\/addons\/#website"},"datePublished":"2026-07-23T11:35:21+00:00","dateModified":"2026-07-23T11:35:21+00:00","author":{"@id":"https:\/\/blog.mozilla.org\/addons\/#\/schema\/person\/83a047c76910255b455ef06faafc194a"},"breadcrumb":{"@id":"https:\/\/blog.mozilla.org\/addons\/2026\/07\/23\/firefox-153-webextensions-api-updates\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blog.mozilla.org\/addons\/2026\/07\/23\/firefox-153-webextensions-api-updates\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/blog.mozilla.org\/addons\/2026\/07\/23\/firefox-153-webextensions-api-updates\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blog.mozilla.org\/addons\/"},{"@type":"ListItem","position":2,"name":"Firefox 153 WebExtensions API updates"}]},{"@type":"WebSite","@id":"https:\/\/blog.mozilla.org\/addons\/#website","url":"https:\/\/blog.mozilla.org\/addons\/","name":"Mozilla Add-ons Community Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blog.mozilla.org\/addons\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/blog.mozilla.org\/addons\/#\/schema\/person\/83a047c76910255b455ef06faafc194a","name":"cbacharakis@mozilla.com","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blog.mozilla.org\/addons\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/8b0f872ddf5a2dd99475e60360cdabd1?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/8b0f872ddf5a2dd99475e60360cdabd1?s=96&d=mm&r=g","caption":"cbacharakis@mozilla.com"},"url":"https:\/\/blog.mozilla.org\/addons\/author\/cbacharakismozilla-com\/"}]}},"_links":{"self":[{"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/posts\/9299"}],"collection":[{"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/users\/2039"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/comments?post=9299"}],"version-history":[{"count":0,"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/posts\/9299\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/media?parent=9299"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/categories?post=9299"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/tags?post=9299"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}