diff --git a/packages/wxt/src/core/resolve-config.ts b/packages/wxt/src/core/resolve-config.ts index d1489f47..211d425b 100644 --- a/packages/wxt/src/core/resolve-config.ts +++ b/packages/wxt/src/core/resolve-config.ts @@ -227,6 +227,7 @@ export async function resolveConfig( userConfigMetadata: userConfigMetadata ?? {}, alias, experimental: defu(mergedConfig.experimental, {}), + suppressWarnings: mergedConfig.suppressWarnings ?? {}, dev: { server: devServerConfig, reloadCommand, diff --git a/packages/wxt/src/core/utils/__tests__/manifest.test.ts b/packages/wxt/src/core/utils/__tests__/manifest.test.ts index fffd2e80..5e0ffbfa 100644 --- a/packages/wxt/src/core/utils/__tests__/manifest.test.ts +++ b/packages/wxt/src/core/utils/__tests__/manifest.test.ts @@ -1578,6 +1578,9 @@ describe('Manifest Utils', () => { // @ts-ignore: Purposefully removing version from fake object version: null, }, + suppressWarnings: { + firefoxDataCollection: true, + }, }, }); @@ -2011,6 +2014,9 @@ describe('Manifest Utils', () => { manifest: { manifest_version: 3, }, + suppressWarnings: { + firefoxDataCollection: true, + }, }, }); diff --git a/packages/wxt/src/core/utils/manifest.ts b/packages/wxt/src/core/utils/manifest.ts index eef0c78c..24ee0087 100644 --- a/packages/wxt/src/core/utils/manifest.ts +++ b/packages/wxt/src/core/utils/manifest.ts @@ -115,6 +115,20 @@ export async function generateManifest( ? undefined : versionName; + // Warn if building for Firefox without data_collection_permissions + if ( + wxt.config.browser === 'firefox' && + !userManifest.browser_specific_settings?.gecko + ?.data_collection_permissions && + !wxt.config.suppressWarnings?.firefoxDataCollection + ) { + wxt.logger.warn( + 'Firefox requires `data_collection_permissions` for new extensions from November 3, 2025. Existing extensions are exempt for now.\n' + + 'For more details, see: https://extensionworkshop.com/documentation/develop/firefox-builtin-data-consent/\n' + + 'To suppress this warning, set `suppressWarnings.firefoxDataCollection` to `true` in your wxt config.\n', + ); + } + addEntrypoints(manifest, entrypoints, buildOutput); if (wxt.config.browser === 'firefox') { diff --git a/packages/wxt/src/core/utils/testing/fake-objects.ts b/packages/wxt/src/core/utils/testing/fake-objects.ts index ddae3af7..9a97e666 100644 --- a/packages/wxt/src/core/utils/testing/fake-objects.ts +++ b/packages/wxt/src/core/utils/testing/fake-objects.ts @@ -26,7 +26,7 @@ import { vi } from 'vitest'; import { setWxtForTesting } from '../../wxt'; import type { Browser } from '@wxt-dev/browser'; -faker.seed(import.meta.test.SEED); +faker.seed(import.meta.env.TEST_SEED); type DeepPartial = T extends object ? { @@ -302,6 +302,7 @@ export const fakeResolvedConfig = fakeObjectCreator(() => { hooks: {}, vite: () => ({}), plugins: [], + suppressWarnings: {}, }; }); diff --git a/packages/wxt/src/types.ts b/packages/wxt/src/types.ts index 968b4f5b..9c9f4d09 100644 --- a/packages/wxt/src/types.ts +++ b/packages/wxt/src/types.ts @@ -143,6 +143,25 @@ export interface InlineConfig { * function that returns an object or promise. */ manifest?: UserManifest | Promise | UserManifestFn; + /** + * Suppress specific warnings during the build process. + * + * @example + * ```ts + * export default defineConfig({ + * suppressWarnings: { + * firefoxDataCollection: true, + * }, + * }) + * ```; + */ + suppressWarnings?: { + /** + * Suppress warnings for: + * https://extensionworkshop.com/documentation/develop/firefox-builtin-data-consent + */ + firefoxDataCollection?: boolean; + }; /** * Configure browser startup. Options set here can be overridden in a * `web-ext.config.ts` file. @@ -944,6 +963,41 @@ export type ResolvedPerBrowserOptions = { : T[key]; } & { [key in TOmitted]: T[key] }; +/** + * Firefox data collection permission types for personal data. See: + * https://extensionworkshop.com/documentation/develop/firefox-builtin-data-consent/#specifying-data-types + */ +export type FirefoxDataCollectionType = + | 'locationInfo' + | 'browsingActivity' + | 'websiteContent' + | 'websiteActivity' + | 'searchTerms' + | 'bookmarksInfo' + | 'healthInfo' + | 'contactInfo' + | 'socialInfo' + | (string & {}); + +/** + * Firefox data collection permissions configuration. See: + * https://extensionworkshop.com/documentation/develop/firefox-builtin-data-consent/#specifying-data-types + */ +export interface FirefoxDataCollectionPermissions { + /** + * Required data collection permissions. Users must opt in to use the + * extension. Can include personal data types or "none" to explicitly indicate + * no data collection. + */ + required?: Array; + /** + * Optional data collection permissions. Users can opt in after installation. + * Can include personal data types or "technicalAndInteraction" (which can + * only be optional). + */ + optional?: Array; +} + /** * Manifest customization available in the `wxt.config.ts` file. You cannot * configure entrypoints here, they are configured inline. @@ -982,6 +1036,11 @@ export type UserManifest = { strict_min_version?: string; strict_max_version?: string; update_url?: string; + /** + * Firefox data collection permissions configuration. See: + * https://extensionworkshop.com/documentation/develop/firefox-builtin-data-consent/#specifying-data-types + */ + data_collection_permissions?: FirefoxDataCollectionPermissions; }; gecko_android?: { strict_min_version?: string; @@ -1442,6 +1501,8 @@ export interface ResolvedConfig { /** Import aliases to absolute paths. */ alias: Record; experimental: {}; + /** List of warning identifiers to suppress during the build process. */ + suppressWarnings: { firefoxDataCollection?: boolean }; dev: { /** Only defined during dev command */ server?: { diff --git a/packages/wxt/vitest.config.ts b/packages/wxt/vitest.config.ts index 0c25b962..733e7b92 100644 --- a/packages/wxt/vitest.config.ts +++ b/packages/wxt/vitest.config.ts @@ -19,7 +19,7 @@ export default defineConfig({ ignored: '**/dist/**', }, }, - plugins: [RandomSeed()], + plugins: [RandomSeed({ define: 'import.meta.env.TEST_SEED' })], resolve: { alias: { 'wxt/testing': path.resolve('src/testing'),