Version in base suite: 140.12.0esr-1~deb13u1
Version in overlay suite: 140.14.0esr-1~deb13u1
Base version: thunderbird_140.14.0esr-1~deb13u1
Target version: thunderbird_140.15.0esr-1~deb13u1
Base file: /srv/ftp-master.debian.org/ftp/pool/main/t/thunderbird/thunderbird_140.14.0esr-1~deb13u1.dsc
Target file: /srv/ftp-master.debian.org/policy/pool/main/t/thunderbird/thunderbird_140.15.0esr-1~deb13u1.dsc
/srv/release.debian.org/tmp/_o8inwuTol/thunderbird-140.15.0esr/services/settings/dumps/blocklists/addons-bloomfilters/addons-mlbf.bin |binary
/srv/release.debian.org/tmp/_o8inwuTol/thunderbird-140.15.0esr/services/settings/dumps/blocklists/addons-bloomfilters/softblocks-addons-mlbf.bin |binary
thunderbird-140.15.0esr/CLOBBER | 2
thunderbird-140.15.0esr/accessible/ipc/DocAccessibleParent.cpp | 2
thunderbird-140.15.0esr/browser/app/winlauncher/freestanding/SharedSection.cpp | 20
thunderbird-140.15.0esr/browser/app/winlauncher/freestanding/moz.build | 1
thunderbird-140.15.0esr/browser/app/winlauncher/test/TestCrossProcessWin.cpp | 13
thunderbird-140.15.0esr/browser/app/winlauncher/test/moz.build | 1
thunderbird-140.15.0esr/browser/base/content/nsContextMenu.sys.mjs | 21
thunderbird-140.15.0esr/browser/base/content/test/contextMenu/browser.toml | 3
thunderbird-140.15.0esr/browser/base/content/test/contextMenu/browser_contextmenu_blocked_image_protocols.js | 63
thunderbird-140.15.0esr/browser/base/content/test/contextMenu/file_blocked_image_protocols.html | 9
thunderbird-140.15.0esr/browser/base/content/test/siteIdentity/browser_secure_transport_insecure_scheme.js | 2
thunderbird-140.15.0esr/browser/base/content/test/static/browser_all_files_referenced.js | 5
thunderbird-140.15.0esr/browser/base/content/test/static/browser_parsable_css.js | 8
thunderbird-140.15.0esr/browser/components/asrouter/tests/browser/browser_asrouter_experimentsAPILoader.js | 2
thunderbird-140.15.0esr/browser/components/asrouter/tests/browser/browser_asrouter_targeting.js | 1
thunderbird-140.15.0esr/browser/components/asrouter/tests/browser/browser_trigger_messagesLoaded.js | 2
thunderbird-140.15.0esr/browser/components/asrouter/tests/browser/head.js | 6
thunderbird-140.15.0esr/browser/components/preferences/tests/head.js | 4
thunderbird-140.15.0esr/browser/components/shell/nsWindowsShellService.cpp | 18
thunderbird-140.15.0esr/browser/components/tabbrowser/test/browser/tabs/browser_new_tab_in_privilegedabout_process_pref.js | 7
thunderbird-140.15.0esr/browser/config/version.txt | 2
thunderbird-140.15.0esr/browser/config/version_display.txt | 2
thunderbird-140.15.0esr/comm/.gecko_rev.yml | 2
thunderbird-140.15.0esr/comm/mail/branding/nightly/content/inAppNotificationData.json | 14
thunderbird-140.15.0esr/comm/mail/branding/tb_beta/content/inAppNotificationData.json | 14
thunderbird-140.15.0esr/comm/mail/branding/thunderbird/content/inAppNotificationData.json | 14
thunderbird-140.15.0esr/comm/mail/config/version.txt | 2
thunderbird-140.15.0esr/comm/mail/config/version_display.txt | 2
thunderbird-140.15.0esr/comm/mail/modules/LinkHelper.sys.mjs | 1
thunderbird-140.15.0esr/comm/mail/modules/WindowsJumpLists.sys.mjs | 4
thunderbird-140.15.0esr/comm/mailnews/imap/src/nsImapGenericParser.cpp | 44
thunderbird-140.15.0esr/comm/mailnews/imap/src/nsImapGenericParser.h | 1
thunderbird-140.15.0esr/comm/mailnews/imap/test/unit/test_imapIDLiteralParenGroup.js | 65
thunderbird-140.15.0esr/comm/mailnews/imap/test/unit/xpcshell-shared.toml | 2
thunderbird-140.15.0esr/comm/mailnews/local/src/components.conf | 1
thunderbird-140.15.0esr/comm/mailnews/local/src/nsParseMailbox.cpp | 2
thunderbird-140.15.0esr/comm/mailnews/local/test/unit/test_nsIMsgParseMailMsgState.js | 14
thunderbird-140.15.0esr/comm/mailnews/mime/src/mimemrel.cpp | 47
thunderbird-140.15.0esr/config/milestone.txt | 2
thunderbird-140.15.0esr/debian/changelog | 27
thunderbird-140.15.0esr/docshell/base/BrowsingContext.cpp | 11
thunderbird-140.15.0esr/docshell/base/nsDocShell.cpp | 40
thunderbird-140.15.0esr/docshell/base/nsDocShellLoadState.cpp | 103
thunderbird-140.15.0esr/docshell/shistory/SessionHistoryEntry.cpp | 11
thunderbird-140.15.0esr/dom/base/Document.cpp | 11
thunderbird-140.15.0esr/dom/base/nsContentUtils.cpp | 6
thunderbird-140.15.0esr/dom/base/nsContentUtils.h | 7
thunderbird-140.15.0esr/dom/base/nsFocusManager.cpp | 5
thunderbird-140.15.0esr/dom/base/nsObjectLoadingContent.cpp | 11
thunderbird-140.15.0esr/dom/broadcastchannel/BroadcastChannel.cpp | 16
thunderbird-140.15.0esr/dom/cache/CacheStorage.cpp | 8
thunderbird-140.15.0esr/dom/cache/PrincipalVerifier.cpp | 7
thunderbird-140.15.0esr/dom/cache/test/mochitest/test_chrome_constructor.html | 9
thunderbird-140.15.0esr/dom/clients/manager/ClientManagerParent.cpp | 11
thunderbird-140.15.0esr/dom/clients/manager/ClientManagerService.cpp | 4
thunderbird-140.15.0esr/dom/clients/manager/ClientManagerService.h | 3
thunderbird-140.15.0esr/dom/clients/manager/ClientNavigateOpChild.cpp | 10
thunderbird-140.15.0esr/dom/clients/manager/ClientSource.cpp | 4
thunderbird-140.15.0esr/dom/clients/manager/ClientSourceParent.cpp | 9
thunderbird-140.15.0esr/dom/clients/manager/ClientSourceParent.h | 13
thunderbird-140.15.0esr/dom/clients/manager/ClientValidation.cpp | 22
thunderbird-140.15.0esr/dom/clients/manager/ClientValidation.h | 3
thunderbird-140.15.0esr/dom/events/EventStateManager.cpp | 11
thunderbird-140.15.0esr/dom/filesystem/FileSystemSecurity.cpp | 5
thunderbird-140.15.0esr/dom/fs/child/FileSystemBackgroundRequestHandler.cpp | 13
thunderbird-140.15.0esr/dom/gamepad/linux/LinuxGamepad.cpp | 20
thunderbird-140.15.0esr/dom/html/HTMLMediaElement.cpp | 6
thunderbird-140.15.0esr/dom/indexedDB/ActorsParent.cpp | 25
thunderbird-140.15.0esr/dom/indexedDB/IDBFactory.cpp | 16
thunderbird-140.15.0esr/dom/indexedDB/IndexedDBCommon.cpp | 10
thunderbird-140.15.0esr/dom/indexedDB/IndexedDBCommon.h | 3
thunderbird-140.15.0esr/dom/indexedDB/test/test_message_manager_ipc.html | 4
thunderbird-140.15.0esr/dom/indexedDB/test/unit/xpcshell-head-child-process.js | 3
thunderbird-140.15.0esr/dom/indexedDB/test/unit/xpcshell-parent-process.toml | 1
thunderbird-140.15.0esr/dom/ipc/BrowserParent.cpp | 59
thunderbird-140.15.0esr/dom/ipc/ContentChild.cpp | 30
thunderbird-140.15.0esr/dom/ipc/ContentChild.h | 3
thunderbird-140.15.0esr/dom/ipc/ContentParent.cpp | 23
thunderbird-140.15.0esr/dom/ipc/ContentParent.h | 2
thunderbird-140.15.0esr/dom/ipc/PContent.ipdl | 4
thunderbird-140.15.0esr/dom/ipc/ProcessIsolation.cpp | 44
thunderbird-140.15.0esr/dom/ipc/gtest/ProcessIsolationTest.cpp | 71
thunderbird-140.15.0esr/dom/localstorage/ActorsParent.cpp | 199
thunderbird-140.15.0esr/dom/media/gmp/GMPChild.cpp | 6
thunderbird-140.15.0esr/dom/media/gmp/GMPPlatform.cpp | 66
thunderbird-140.15.0esr/dom/media/gmp/GMPPlatform.h | 12
thunderbird-140.15.0esr/dom/media/gmp/GMPVideoDecoderChild.cpp | 2
thunderbird-140.15.0esr/dom/media/gmp/GMPVideoEncoderChild.cpp | 2
thunderbird-140.15.0esr/dom/media/ipc/MFMediaEngineParent.cpp | 20
thunderbird-140.15.0esr/dom/media/ipc/MFMediaEngineParent.h | 4
thunderbird-140.15.0esr/dom/media/ipc/RemoteDecoderParent.cpp | 6
thunderbird-140.15.0esr/dom/media/ipc/RemoteDecoderParent.h | 1
thunderbird-140.15.0esr/dom/media/platforms/apple/AppleVTDecoder.cpp | 18
thunderbird-140.15.0esr/dom/media/platforms/apple/AppleVTEncoder.cpp | 148
thunderbird-140.15.0esr/dom/media/platforms/wmf/MFMediaEngineStream.cpp | 45
thunderbird-140.15.0esr/dom/media/platforms/wmf/MFMediaEngineStream.h | 12
thunderbird-140.15.0esr/dom/quota/ActorsParent.cpp | 6
thunderbird-140.15.0esr/dom/quota/RemoteQuotaObjectParent.cpp | 5
thunderbird-140.15.0esr/dom/quota/test/xpcshell/test_estimateOrigin.js | 17
thunderbird-140.15.0esr/dom/security/nsContentSecurityManager.cpp | 29
thunderbird-140.15.0esr/dom/security/nsContentSecurityUtils.cpp | 1
thunderbird-140.15.0esr/dom/security/test/crashtests/1583044.html | 11
thunderbird-140.15.0esr/dom/security/test/crashtests/crashtests.list | 1
thunderbird-140.15.0esr/dom/security/test/general/chrome.toml | 3
thunderbird-140.15.0esr/dom/security/test/general/test_image_protocol_document_context.html | 78
thunderbird-140.15.0esr/dom/serviceworkers/ServiceWorkerPrivate.cpp | 36
thunderbird-140.15.0esr/dom/simpledb/SDBConnection.cpp | 6
thunderbird-140.15.0esr/dom/storage/LocalStorageManager.cpp | 7
thunderbird-140.15.0esr/dom/storage/StorageActivityService.cpp | 5
thunderbird-140.15.0esr/dom/storage/components.conf | 1
thunderbird-140.15.0esr/dom/webbrowserpersist/PWebBrowserPersistDocument.ipdl | 6
thunderbird-140.15.0esr/dom/webbrowserpersist/WebBrowserPersistDocumentChild.cpp | 10
thunderbird-140.15.0esr/dom/webbrowserpersist/WebBrowserPersistDocumentParent.cpp | 17
thunderbird-140.15.0esr/dom/webbrowserpersist/WebBrowserPersistDocumentParent.h | 6
thunderbird-140.15.0esr/dom/webbrowserpersist/WebBrowserPersistRemoteDocument.cpp | 16
thunderbird-140.15.0esr/dom/webbrowserpersist/WebBrowserPersistRemoteDocument.h | 4
thunderbird-140.15.0esr/dom/workers/sharedworkers/SharedWorker.cpp | 10
thunderbird-140.15.0esr/dom/workers/sharedworkers/SharedWorkerService.cpp | 85
thunderbird-140.15.0esr/dom/workers/sharedworkers/SharedWorkerService.h | 4
thunderbird-140.15.0esr/dom/xslt/tests/mochitest/test_bug1769155.html | 2
thunderbird-140.15.0esr/editor/libeditor/EditorBase.cpp | 2
thunderbird-140.15.0esr/editor/libeditor/HTMLEditor.cpp | 2
thunderbird-140.15.0esr/editor/libeditor/HTMLEditorDeleteHandler.cpp | 2
thunderbird-140.15.0esr/editor/libeditor/HTMLTableEditor.cpp | 2
thunderbird-140.15.0esr/gfx/2d/DrawTargetCairo.cpp | 3
thunderbird-140.15.0esr/gfx/layers/wr/AsyncImagePipelineManager.cpp | 10
thunderbird-140.15.0esr/gfx/layers/wr/WebRenderBridgeParent.cpp | 8
thunderbird-140.15.0esr/gfx/thebes/gfxFont.h | 35
thunderbird-140.15.0esr/gfx/webrender_bindings/RenderTextureHost.h | 2
thunderbird-140.15.0esr/gfx/webrender_bindings/RenderTextureHostSWGL.cpp | 21
thunderbird-140.15.0esr/gfx/webrender_bindings/RenderTextureHostSWGL.h | 10
thunderbird-140.15.0esr/gfx/webrender_bindings/RenderTextureHostWrapper.cpp | 6
thunderbird-140.15.0esr/gfx/webrender_bindings/RenderTextureHostWrapper.h | 1
thunderbird-140.15.0esr/gfx/webrender_bindings/WebRenderAPI.cpp | 10
thunderbird-140.15.0esr/gfx/webrender_bindings/WebRenderAPI.h | 9
thunderbird-140.15.0esr/gfx/webrender_bindings/src/bindings.rs | 6
thunderbird-140.15.0esr/gfx/wr/example-compositor/compositor/src/main.rs | 4
thunderbird-140.15.0esr/gfx/wr/examples/common/boilerplate.rs | 2
thunderbird-140.15.0esr/gfx/wr/examples/document.rs | 1
thunderbird-140.15.0esr/gfx/wr/examples/iframe.rs | 1
thunderbird-140.15.0esr/gfx/wr/examples/multiwindow.rs | 1
thunderbird-140.15.0esr/gfx/wr/webrender/src/render_api.rs | 9
thunderbird-140.15.0esr/gfx/wr/webrender/src/scene.rs | 7
thunderbird-140.15.0esr/gfx/wr/webrender/src/scene_builder_thread.rs | 2
thunderbird-140.15.0esr/gfx/wr/webrender/src/scene_building.rs | 132
thunderbird-140.15.0esr/gfx/wr/wrench/src/rawtest.rs | 4
thunderbird-140.15.0esr/gfx/wr/wrench/src/wrench.rs | 29
thunderbird-140.15.0esr/image/ImageBlocker.cpp | 4
thunderbird-140.15.0esr/image/decoders/icon/components.conf | 1
thunderbird-140.15.0esr/image/decoders/icon/nsIconProtocolHandler.cpp | 10
thunderbird-140.15.0esr/ipc/glue/BackgroundChild.h | 13
thunderbird-140.15.0esr/ipc/glue/BackgroundImpl.cpp | 48
thunderbird-140.15.0esr/ipc/glue/BackgroundParent.h | 12
thunderbird-140.15.0esr/ipc/glue/BackgroundParentImpl.cpp | 57
thunderbird-140.15.0esr/ipc/glue/BackgroundParentImpl.h | 3
thunderbird-140.15.0esr/ipc/glue/GeckoChildProcessHost.h | 1
thunderbird-140.15.0esr/js/src/gc/Nursery.cpp | 9
thunderbird-140.15.0esr/js/src/proxy/Proxy.cpp | 9
thunderbird-140.15.0esr/js/src/wasm/WasmBCFrame.cpp | 2
thunderbird-140.15.0esr/js/src/wasm/WasmBaselineCompile.cpp | 28
thunderbird-140.15.0esr/layout/build/components.conf | 10
thunderbird-140.15.0esr/layout/generic/nsTextFrame.cpp | 2
thunderbird-140.15.0esr/media/libcubeb/moz.yaml | 2
thunderbird-140.15.0esr/media/libcubeb/src/cubeb.c | 11
thunderbird-140.15.0esr/media/libcubeb/src/cubeb_wasapi.cpp | 3
thunderbird-140.15.0esr/media/libcubeb/src/cubeb_winmm.c | 76
thunderbird-140.15.0esr/media/libcubeb/test/test_sanity.cpp | 23
thunderbird-140.15.0esr/media/libcubeb/wasapi-output-mix-channel-count.patch | 84
thunderbird-140.15.0esr/media/libcubeb/winmm-destroy-work-item-uaf.patch | 187
thunderbird-140.15.0esr/modules/libjar/components.conf | 2
thunderbird-140.15.0esr/modules/libpref/init/StaticPrefList.yaml | 6
thunderbird-140.15.0esr/netwerk/build/components.conf | 13
thunderbird-140.15.0esr/netwerk/dns/effective_tld_names.dat | 33
thunderbird-140.15.0esr/netwerk/ipc/DocumentLoadListener.cpp | 10
thunderbird-140.15.0esr/netwerk/ipc/NeckoParent.cpp | 9
thunderbird-140.15.0esr/netwerk/protocol/http/SpeculativeTransaction.cpp | 13
thunderbird-140.15.0esr/netwerk/protocol/res/PageThumbProtocolHandler.cpp | 11
thunderbird-140.15.0esr/netwerk/protocol/res/PageThumbProtocolHandler.h | 2
thunderbird-140.15.0esr/netwerk/protocol/websocket/WebSocketChannelChild.cpp | 31
thunderbird-140.15.0esr/netwerk/protocol/webtransport/WebTransportSessionProxy.cpp | 61
thunderbird-140.15.0esr/security/ct/CTKnownLogs.h | 2
thunderbird-140.15.0esr/security/manager/ssl/StaticHPKPins.h | 20
thunderbird-140.15.0esr/security/manager/ssl/components.conf | 1
thunderbird-140.15.0esr/security/manager/ssl/nsSTSPreloadList.inc | 1819
thunderbird-140.15.0esr/security/manager/tools/log_list.json | 4
thunderbird-140.15.0esr/security/sandbox/chromium-shim/patches/55_dont_broker_dir_creation_or_write.patch | 56
thunderbird-140.15.0esr/security/sandbox/chromium/sandbox/win/src/filesystem_dispatcher.cc | 29
thunderbird-140.15.0esr/security/sandbox/chromium/sandbox/win/src/registry_dispatcher.cc | 12
thunderbird-140.15.0esr/security/sandbox/chromium/sandbox/win/src/registry_policy.cc | 67
thunderbird-140.15.0esr/security/sandbox/chromium/sandbox/win/src/registry_policy.h | 14
thunderbird-140.15.0esr/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp | 24
thunderbird-140.15.0esr/services/settings/dumps/blocklists/addons-bloomfilters.json | 5941 -
thunderbird-140.15.0esr/services/settings/dumps/blocklists/addons-bloomfilters/addons-mlbf.bin.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/blocklists/addons-bloomfilters/softblocks-addons-mlbf.bin.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/blocklists/addons.json |20428 +++---
thunderbird-140.15.0esr/services/settings/dumps/blocklists/gfx.json | 1214
thunderbird-140.15.0esr/services/settings/dumps/main/anti-tracking-url-decoration.json | 6
thunderbird-140.15.0esr/services/settings/dumps/main/cookie-banner-rules-list.json | 2248
thunderbird-140.15.0esr/services/settings/dumps/main/devtools-compatibility-browsers.json | 450
thunderbird-140.15.0esr/services/settings/dumps/main/devtools-devices.json | 772
thunderbird-140.15.0esr/services/settings/dumps/main/hijack-blocklists.json | 18
thunderbird-140.15.0esr/services/settings/dumps/main/language-dictionaries.json | 320
thunderbird-140.15.0esr/services/settings/dumps/main/moz-essential-domain-fallbacks.json | 48
thunderbird-140.15.0esr/services/settings/dumps/main/password-recipes.json | 116
thunderbird-140.15.0esr/services/settings/dumps/main/password-rules.json | 1612
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons.json | 883
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/001500a9-1a6c-3f5a-ba15-a5f5a075d256.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/06cf7432-efd7-f244-927b-5e423005e1ea.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/0d7668a8-c3f4-cfee-cbc8-536511528937.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/0eec5640-6fde-d6fe-322a-c72c6d5bd5a2.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/101ce01d-2691-b729-7f16-9d389803384b.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/177aba42-9bed-4078-e36b-580e8794cd7f.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/25de0352-aabb-d31f-15f7-bf9299fb004c.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/2bbe48f4-d3b8-c9e0-86e3-a54c37ec3335.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/2e835b0e-9709-d1bb-9725-87f59f3445ca.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/32d26d19-aeb0-5c01-32e8-f8970be9246f.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/41f0d805-3775-4988-8d8c-5ad8ccd86d1c.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/47da97b5-600f-c450-fd15-a52bb2169c11.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/4e271681-3e0f-91ac-9750-03f665efc171.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/50f6171f-8e7a-b41b-862e-f97397038fb2.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/5ded611d-44b2-dc46-fd67-fb116888d75d.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/5e03d6f4-6ee9-8bc8-cf22-7a5f2cf55c41.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/6d10d702-7bd6-1452-90a5-3df665a38f66.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/6f4da442-d31e-28f8-03af-797d16bbdd27.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/70fdd651-6c50-b7bb-09ec-7e85da259173.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/74793ce1-a918-a5eb-d3c0-2aadaff3c88c.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/7bf4ca37-e2b8-4d31-a1c3-979bc0e85131.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/7efbed51-813c-581d-d8d3-f8758434e451.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/84bb4962-e571-227a-9ef6-2ac5f2aac361.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/87ac4cde-f581-398b-1e32-eb4079183b36.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/8831ce10-b1e4-6eb4-4975-83c67457288e.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/890de5c4-0941-a116-473a-5d240e79497a.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/91a9672d-e945-8e1e-0996-aefdb0190716.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/96327a73-c433-5eb4-a16d-b090cadfb80b.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/9802e63d-05ec-48ba-93f9-746e0981ad98.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/9d96547d-7575-49ca-8908-1e046b8ea90e.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/a06db97d-1210-ea2e-5474-0e2f7d295bfd.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/a06dc3fd-4bdb-41f3-2ebc-4cbed06a9bd3.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/a2c7d4e9-f770-51e1-0963-3c2c8401631d.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/b64f09fd-52d1-c48e-af23-4ce918e7bf3b.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/b8ca5a94-8fff-27ad-6e00-96e244a32e21.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/c411adc1-9661-4fb5-a4c1-8cfe74911943.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/cbf9e891-d079-2b28-5617-283450d463dd.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/d87f251c-3e12-a8bf-e2d0-afd43d36c5f9.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/e02f23df-8d48-2b1b-3b5c-6dd27302c61c.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/e718e983-09aa-e8f6-b25f-cd4b395d4785.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/e7547f62-187b-b641-d462-e54a3f813d9a.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/f312610a-ebfb-a106-ea92-fd643c5d3636.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/fa0fc42c-d91d-fca7-34eb-806ff46062dc.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/fca3e3ee-56cd-f474-dc31-307fd24a891d.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-icons/fed4f021-ff3e-942a-010e-afa43fda2136.meta.json | 2
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-overrides-v2.json | 16
thunderbird-140.15.0esr/services/settings/dumps/main/search-config-v2.json | 26
thunderbird-140.15.0esr/services/settings/dumps/main/search-default-override-allowlist.json | 202
thunderbird-140.15.0esr/services/settings/dumps/main/search-telemetry-v2.json | 1549
thunderbird-140.15.0esr/services/settings/dumps/main/sites-classification.json | 86
thunderbird-140.15.0esr/services/settings/dumps/main/top-sites.json | 234
thunderbird-140.15.0esr/services/settings/dumps/main/translations-models.json |14068 ++--
thunderbird-140.15.0esr/services/settings/dumps/main/translations-wasm.json | 104
thunderbird-140.15.0esr/services/settings/dumps/main/url-classifier-skip-urls.json | 24
thunderbird-140.15.0esr/services/settings/dumps/main/url-parser-default-unknown-schemes-interventions.json | 30
thunderbird-140.15.0esr/services/settings/dumps/main/urlbar-persisted-search-terms.json | 46
thunderbird-140.15.0esr/services/settings/dumps/main/websites-with-shared-credential-backends.json | 6
thunderbird-140.15.0esr/services/settings/dumps/security-state/intermediates.json |31222 +++++-----
thunderbird-140.15.0esr/services/settings/dumps/security-state/onecrl.json |26318 ++++----
thunderbird-140.15.0esr/sourcestamp.txt | 6
thunderbird-140.15.0esr/testing/web-platform/meta/service-workers/service-worker/windowclient-navigate.https.html.ini | 3
thunderbird-140.15.0esr/thunderbird-l10n/af/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/ar/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/ast/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/be/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/bg/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/br/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/ca/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/cak/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/cs/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/cy/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/da/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/de/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/dsb/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/el/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/en-CA/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/en-GB/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/es-AR/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/es-ES/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/es-MX/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/et/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/eu/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/fi/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/fr/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/fy-NL/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/ga-IE/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/gd/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/gl/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/he/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/hr/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/hsb/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/hu/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/hy-AM/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/id/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/is/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/it/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/ja/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/ka/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/kab/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/kk/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/ko/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/lt/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/lv/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/ms/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/nb-NO/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/nl/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/nn-NO/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/pa-IN/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/pl/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/pt-BR/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/pt-PT/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/rm/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/ro/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/ru/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/sk/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/sl/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/sq/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/sr/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/sv-SE/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/th/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/tr/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/uk/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/uz/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/vi/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/zh-CN/manifest.json | 4
thunderbird-140.15.0esr/thunderbird-l10n/zh-TW/manifest.json | 4
thunderbird-140.15.0esr/toolkit/components/gfx/SanityTest.sys.mjs | 2
thunderbird-140.15.0esr/toolkit/components/gfx/content/gfxFrameScript.js | 2
thunderbird-140.15.0esr/toolkit/components/gfx/content/sanitytest.html | 2
thunderbird-140.15.0esr/toolkit/components/gfx/jar.mn | 7
thunderbird-140.15.0esr/toolkit/components/nimbus/lib/RemoteSettingsExperimentLoader.sys.mjs | 1
thunderbird-140.15.0esr/toolkit/components/nimbus/test/NimbusTestUtils.sys.mjs | 30
thunderbird-140.15.0esr/toolkit/components/nimbus/test/browser/head.js | 2
thunderbird-140.15.0esr/toolkit/components/places/PageIconProtocolHandler.cpp | 10
thunderbird-140.15.0esr/toolkit/components/places/nsCachedFaviconProtocolHandler.cpp | 4
thunderbird-140.15.0esr/uriloader/exthandler/nsExternalHelperAppService.cpp | 8
thunderbird-140.15.0esr/widget/gtk/DMABufSurface.cpp | 28
thunderbird-140.15.0esr/widget/nsDragServiceProxy.cpp | 1
thunderbird-140.15.0esr/widget/windows/DirectManipulationOwner.cpp | 141
thunderbird-140.15.0esr/widget/windows/DirectManipulationOwner.h | 2
thunderbird-140.15.0esr/widget/windows/WinUtils.h | 34
thunderbird-140.15.0esr/xpcom/components/StaticComponents.h | 3
thunderbird-140.15.0esr/xpcom/components/gen_static_components.py | 2
thunderbird-140.15.0esr/xpcom/io/moz.build | 2
thunderbird-140.15.0esr/xpcom/io/nsBinaryStream.cpp | 29
353 files changed, 55513 insertions(+), 58338 deletions(-)
dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmps5o9hgr5/thunderbird_140.14.0esr-1~deb13u1.dsc: no acceptable signature found
dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmps5o9hgr5/thunderbird_140.15.0esr-1~deb13u1.dsc: no acceptable signature found
diff -Nru thunderbird-140.14.0esr/CLOBBER thunderbird-140.15.0esr/CLOBBER
--- thunderbird-140.14.0esr/CLOBBER 2026-08-18 02:52:31.000000000 +0000
+++ thunderbird-140.15.0esr/CLOBBER 2026-08-28 17:33:04.000000000 +0000
@@ -22,4 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
-Merge day clobber 2026-07-20
\ No newline at end of file
+Merge day clobber 2026-08-13
\ No newline at end of file
diff -Nru thunderbird-140.14.0esr/accessible/ipc/DocAccessibleParent.cpp thunderbird-140.15.0esr/accessible/ipc/DocAccessibleParent.cpp
--- thunderbird-140.14.0esr/accessible/ipc/DocAccessibleParent.cpp 2026-08-18 02:52:31.000000000 +0000
+++ thunderbird-140.15.0esr/accessible/ipc/DocAccessibleParent.cpp 2026-08-28 17:33:04.000000000 +0000
@@ -1118,7 +1118,7 @@
// XXX This indirection through the hash map of live documents shouldn't be
// needed, but be paranoid for now.
- int32_t actorID = mActorID;
+ uint64_t actorID = mActorID;
for (uint32_t i = childDocCount - 1; i < childDocCount; i--) {
DocAccessibleParent* thisDoc = LiveDocs().Get(actorID);
MOZ_ASSERT(thisDoc);
diff -Nru thunderbird-140.14.0esr/browser/app/winlauncher/freestanding/SharedSection.cpp thunderbird-140.15.0esr/browser/app/winlauncher/freestanding/SharedSection.cpp
--- thunderbird-140.14.0esr/browser/app/winlauncher/freestanding/SharedSection.cpp 2026-08-18 02:52:31.000000000 +0000
+++ thunderbird-140.15.0esr/browser/app/winlauncher/freestanding/SharedSection.cpp 2026-08-28 17:33:04.000000000 +0000
@@ -151,9 +151,23 @@
kSharedViewSize >= sizeof(Layout),
"kSharedViewSize is too small to represent SharedSection::Layout.");
- HANDLE section =
- ::CreateFileMappingW(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0,
- kSharedViewSize, nullptr);
+ // Create with an empty DACL to limit the duplicated handle's access rights.
+ // See shared_memory::CreateImpl for details.
+ SECURITY_DESCRIPTOR sd;
+ ACL dacl;
+ if (!::InitializeAcl(&dacl, sizeof(dacl), ACL_REVISION) ||
+ !::InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION) ||
+ !::SetSecurityDescriptorDacl(&sd, TRUE, &dacl, FALSE)) {
+ return LAUNCHER_ERROR_FROM_LAST();
+ }
+
+ SECURITY_ATTRIBUTES sa;
+ sa.nLength = sizeof(sa);
+ sa.lpSecurityDescriptor = &sd;
+ sa.bInheritHandle = FALSE;
+
+ HANDLE section = ::CreateFileMappingW(
+ INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE, 0, kSharedViewSize, nullptr);
if (!section) {
return LAUNCHER_ERROR_FROM_LAST();
}
diff -Nru thunderbird-140.14.0esr/browser/app/winlauncher/freestanding/moz.build thunderbird-140.15.0esr/browser/app/winlauncher/freestanding/moz.build
--- thunderbird-140.14.0esr/browser/app/winlauncher/freestanding/moz.build 2026-08-18 02:52:31.000000000 +0000
+++ thunderbird-140.15.0esr/browser/app/winlauncher/freestanding/moz.build 2026-08-28 17:33:04.000000000 +0000
@@ -38,6 +38,7 @@
CXXFLAGS += [SRCDIR + "/Freestanding.h"]
OS_LIBS += [
+ "advapi32",
"ntdll",
"ntdll_freestanding",
]
diff -Nru thunderbird-140.14.0esr/browser/app/winlauncher/test/TestCrossProcessWin.cpp thunderbird-140.15.0esr/browser/app/winlauncher/test/TestCrossProcessWin.cpp
--- thunderbird-140.14.0esr/browser/app/winlauncher/test/TestCrossProcessWin.cpp 2026-08-18 02:52:31.000000000 +0000
+++ thunderbird-140.15.0esr/browser/app/winlauncher/test/TestCrossProcessWin.cpp 2026-08-28 17:33:04.000000000 +0000
@@ -70,6 +70,7 @@
(offsetof(SharedSection::Layout, mFirstBlockEntry) +
sizeof(DllBlockInfo));
}
+ static HANDLE GetSectionHandle() { return SharedSection::sSectionHandle; }
};
} // namespace mozilla::freestanding
@@ -527,6 +528,18 @@
return 1;
}
+ // The empty DACL should prevent writable handles.
+ HANDLE writableHandle;
+ if (::DuplicateHandle(
+ nt::kCurrentProcess, SharedSectionTestHelper::GetSectionHandle(),
+ nt::kCurrentProcess, &writableHandle, GENERIC_WRITE, FALSE, 0)) {
+ ::CloseHandle(writableHandle);
+ printf(
+ "TEST-FAILED | TestCrossProcessWin | "
+ "The handle was writable.\n");
+ return 1;
+ }
+
if (!VerifySharedSection(gSharedSection)) {
return 1;
}
diff -Nru thunderbird-140.14.0esr/browser/app/winlauncher/test/moz.build thunderbird-140.15.0esr/browser/app/winlauncher/test/moz.build
--- thunderbird-140.14.0esr/browser/app/winlauncher/test/moz.build 2026-08-18 02:52:31.000000000 +0000
+++ thunderbird-140.15.0esr/browser/app/winlauncher/test/moz.build 2026-08-28 17:33:04.000000000 +0000
@@ -20,6 +20,7 @@
]
OS_LIBS += [
+ "advapi32",
"ntdll",
]
diff -Nru thunderbird-140.14.0esr/browser/base/content/nsContextMenu.sys.mjs thunderbird-140.15.0esr/browser/base/content/nsContextMenu.sys.mjs
--- thunderbird-140.14.0esr/browser/base/content/nsContextMenu.sys.mjs 2026-08-18 02:52:31.000000000 +0000
+++ thunderbird-140.15.0esr/browser/base/content/nsContextMenu.sys.mjs 2026-08-28 17:33:03.000000000 +0000
@@ -91,6 +91,13 @@
const PASSWORD_FIELDNAME_HINTS = ["current-password", "new-password"];
const USERNAME_FIELDNAME_HINT = "username";
+const IMAGE_ONLY_PROTOCOLS = [
+ "cached-favicon:",
+ "moz-icon:",
+ "moz-page-thumb:",
+ "page-icon:",
+];
+
export class nsContextMenu {
/**
* A promise to retrieve the translations language pair
@@ -729,6 +736,12 @@
this.onImage && !this.onCompletedImage
);
+ // Some protocols only return images in an image context and can no longer
+ // be loaded otherwise.
+ const mediaURL = URL.parse(this.mediaURL);
+ const isImageOnlyProtocol =
+ mediaURL && IMAGE_ONLY_PROTOCOLS.includes(mediaURL.protocol);
+
// View image depends on having an image that's not standalone
// (or is in a frame), or a canvas. If this isn't an image, check
// if there is a background image.
@@ -748,12 +761,16 @@
!this.onAudio &&
!this.onLink &&
!this.onTextInput;
- this.showItem("context-viewimage", showViewImage || showBGImage);
+ this.showItem(
+ "context-viewimage",
+ (showViewImage || showBGImage) && !isImageOnlyProtocol
+ );
// Save image depends on having loaded its content.
this.showItem(
"context-saveimage",
- (this.onLoadedImage || this.onCanvas) && !this.inPDFEditor
+ ((this.onLoadedImage && !isImageOnlyProtocol) || this.onCanvas) &&
+ !this.inPDFEditor
);
if (Services.policies.status === Services.policies.ACTIVE) {
diff -Nru thunderbird-140.14.0esr/browser/base/content/test/contextMenu/browser.toml thunderbird-140.15.0esr/browser/base/content/test/contextMenu/browser.toml
--- thunderbird-140.14.0esr/browser/base/content/test/contextMenu/browser.toml 2026-08-18 02:52:31.000000000 +0000
+++ thunderbird-140.15.0esr/browser/base/content/test/contextMenu/browser.toml 2026-08-28 17:33:03.000000000 +0000
@@ -33,6 +33,9 @@
"os == 'linux' && socketprocess_networking",
]
+["browser_contextmenu_blocked_image_protocols.js"]
+support-files = ["file_blocked_image_protocols.html"]
+
["browser_contextmenu_contenteditable.js"]
["browser_contextmenu_cross_boundary_selection.js"]
diff -Nru thunderbird-140.14.0esr/browser/base/content/test/contextMenu/browser_contextmenu_blocked_image_protocols.js thunderbird-140.15.0esr/browser/base/content/test/contextMenu/browser_contextmenu_blocked_image_protocols.js
--- thunderbird-140.14.0esr/browser/base/content/test/contextMenu/browser_contextmenu_blocked_image_protocols.js 1970-01-01 00:00:00.000000000 +0000
+++ thunderbird-140.15.0esr/browser/base/content/test/contextMenu/browser_contextmenu_blocked_image_protocols.js 2026-08-28 17:33:04.000000000 +0000
@@ -0,0 +1,63 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+Services.scriptloader.loadSubScript(
+ getRootDirectory(gTestPath) + "contextmenu_common.js",
+ this
+);
+
+const IMAGE_PROTOCOLS_IDS = [
+ "cached-favicon",
+ "moz-icon",
+ "moz-page-thumb",
+ "page-icon",
+];
+
+add_task(async function test_blocked() {
+ for (const protocol of IMAGE_PROTOCOLS_IDS) {
+ info(`Testing contextmenu with the ${protocol}: protocol`);
+
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: getRootDirectory(gTestPath) + "file_blocked_image_protocols.html",
+ },
+ async browser => {
+ await SpecialPowers.spawn(browser, [`#${protocol}`], async selector => {
+ const img = content.document.querySelector(selector);
+ if (!img.complete) {
+ await ContentTaskUtils.waitForEvent(img, "load");
+ }
+ });
+
+ let contextMenu = document.getElementById("contentAreaContextMenu");
+ let popupShown = BrowserTestUtils.waitForEvent(
+ contextMenu,
+ "popupshown"
+ );
+
+ await BrowserTestUtils.synthesizeMouse(
+ `#${protocol}`,
+ 2,
+ 2,
+ { type: "contextmenu", button: 2 },
+ browser
+ );
+ await popupShown;
+
+ let viewImageItem = document.getElementById("context-viewimage");
+ ok(viewImageItem.hidden, "View Image menu item should be hidden");
+
+ let saveImageItem = document.getElementById("context-saveimage");
+ ok(saveImageItem.hidden, "Save Image menu item should be hidden");
+
+ let sendImageItem = document.getElementById("context-sendimage");
+ ok(!sendImageItem.hidden, "Send Image menu item should be shown");
+
+ contextMenu.hidePopup();
+ }
+ );
+ }
+});
diff -Nru thunderbird-140.14.0esr/browser/base/content/test/contextMenu/file_blocked_image_protocols.html thunderbird-140.15.0esr/browser/base/content/test/contextMenu/file_blocked_image_protocols.html
--- thunderbird-140.14.0esr/browser/base/content/test/contextMenu/file_blocked_image_protocols.html 1970-01-01 00:00:00.000000000 +0000
+++ thunderbird-140.15.0esr/browser/base/content/test/contextMenu/file_blocked_image_protocols.html 2026-08-28 17:33:03.000000000 +0000
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff -Nru thunderbird-140.14.0esr/browser/base/content/test/siteIdentity/browser_secure_transport_insecure_scheme.js thunderbird-140.15.0esr/browser/base/content/test/siteIdentity/browser_secure_transport_insecure_scheme.js
--- thunderbird-140.14.0esr/browser/base/content/test/siteIdentity/browser_secure_transport_insecure_scheme.js 2026-08-18 02:52:31.000000000 +0000
+++ thunderbird-140.15.0esr/browser/base/content/test/siteIdentity/browser_secure_transport_insecure_scheme.js 2026-08-28 17:33:04.000000000 +0000
@@ -56,7 +56,7 @@
let blob = new Blob([JSON.stringify(debug, null, 2)], {
type: "application/json",
});
- let blobUri = URL.createObjectURL(blob);
+ let blobUri = content.URL.createObjectURL(blob);
content.document.location = blobUri;
});
await BrowserTestUtils.browserLoaded(browser);
diff -Nru thunderbird-140.14.0esr/browser/base/content/test/static/browser_all_files_referenced.js thunderbird-140.15.0esr/browser/base/content/test/static/browser_all_files_referenced.js
--- thunderbird-140.14.0esr/browser/base/content/test/static/browser_all_files_referenced.js 2026-08-18 02:52:31.000000000 +0000
+++ thunderbird-140.15.0esr/browser/base/content/test/static/browser_all_files_referenced.js 2026-08-28 17:33:04.000000000 +0000
@@ -121,6 +121,11 @@
"chrome://newtab/",
];
+if (AppConstants.platform == "win") {
+ // Referenced via resource://gfxsanity/
+ gExceptionPaths.push("resource://gre-resources/gfxsanity/");
+}
+
// These are not part of the omni.ja file, so we find them only when running
// the test on a non-packaged build.
if (AppConstants.platform == "macosx") {
diff -Nru thunderbird-140.14.0esr/browser/base/content/test/static/browser_parsable_css.js thunderbird-140.15.0esr/browser/base/content/test/static/browser_parsable_css.js
--- thunderbird-140.14.0esr/browser/base/content/test/static/browser_parsable_css.js 2026-08-18 02:52:31.000000000 +0000
+++ thunderbird-140.15.0esr/browser/base/content/test/static/browser_parsable_css.js 2026-08-28 17:33:04.000000000 +0000
@@ -416,8 +416,14 @@
function chromeFileExists(aURI) {
let available = 0;
try {
+ let uri = NetUtil.newURI(aURI);
+ // moz-icon: is only loadable as an image, so we pretend to do that.
+ let contentPolicyType = uri.schemeIs("moz-icon")
+ ? Ci.nsIContentPolicy.TYPE_IMAGE
+ : Ci.nsIContentPolicy.TYPE_OTHER;
let channel = NetUtil.newChannel({
- uri: aURI,
+ uri,
+ contentPolicyType,
loadUsingSystemPrincipal: true,
});
let stream = channel.open();
diff -Nru thunderbird-140.14.0esr/browser/components/asrouter/tests/browser/browser_asrouter_experimentsAPILoader.js thunderbird-140.15.0esr/browser/components/asrouter/tests/browser/browser_asrouter_experimentsAPILoader.js
--- thunderbird-140.14.0esr/browser/components/asrouter/tests/browser/browser_asrouter_experimentsAPILoader.js 2026-08-18 02:52:31.000000000 +0000
+++ thunderbird-140.15.0esr/browser/components/asrouter/tests/browser/browser_asrouter_experimentsAPILoader.js 2026-08-28 17:33:04.000000000 +0000
@@ -4,7 +4,7 @@
const { ASRouter } = ChromeUtils.importESModule(
"resource:///modules/asrouter/ASRouter.sys.mjs"
);
-const { EnrollmentType, ExperimentAPI } = ChromeUtils.importESModule(
+const { EnrollmentType } = ChromeUtils.importESModule(
"resource://nimbus/ExperimentAPI.sys.mjs"
);
const { NimbusTestUtils } = ChromeUtils.importESModule(
diff -Nru thunderbird-140.14.0esr/browser/components/asrouter/tests/browser/browser_asrouter_targeting.js thunderbird-140.15.0esr/browser/components/asrouter/tests/browser/browser_asrouter_targeting.js
--- thunderbird-140.14.0esr/browser/components/asrouter/tests/browser/browser_asrouter_targeting.js 2026-08-18 02:52:32.000000000 +0000
+++ thunderbird-140.15.0esr/browser/components/asrouter/tests/browser/browser_asrouter_targeting.js 2026-08-28 17:33:03.000000000 +0000
@@ -9,7 +9,6 @@
BuiltInThemes: "resource:///modules/BuiltInThemes.sys.mjs",
CFRMessageProvider: "resource:///modules/asrouter/CFRMessageProvider.sys.mjs",
ClientID: "resource://gre/modules/ClientID.sys.mjs",
- ExperimentAPI: "resource://nimbus/ExperimentAPI.sys.mjs",
FxAccounts: "resource://gre/modules/FxAccounts.sys.mjs",
HomePage: "resource:///modules/HomePage.sys.mjs",
InfoBar: "resource:///modules/asrouter/InfoBar.sys.mjs",
diff -Nru thunderbird-140.14.0esr/browser/components/asrouter/tests/browser/browser_trigger_messagesLoaded.js thunderbird-140.15.0esr/browser/components/asrouter/tests/browser/browser_trigger_messagesLoaded.js
--- thunderbird-140.14.0esr/browser/components/asrouter/tests/browser/browser_trigger_messagesLoaded.js 2026-08-18 02:52:31.000000000 +0000
+++ thunderbird-140.15.0esr/browser/components/asrouter/tests/browser/browser_trigger_messagesLoaded.js 2026-08-28 17:33:04.000000000 +0000
@@ -8,7 +8,7 @@
const { RemoteSettings } = ChromeUtils.importESModule(
"resource://services-settings/remote-settings.sys.mjs"
);
-const { EnrollmentType, ExperimentAPI } = ChromeUtils.importESModule(
+const { EnrollmentType } = ChromeUtils.importESModule(
"resource://nimbus/ExperimentAPI.sys.mjs"
);
const { NimbusTestUtils } = ChromeUtils.importESModule(
diff -Nru thunderbird-140.14.0esr/browser/components/asrouter/tests/browser/head.js thunderbird-140.15.0esr/browser/components/asrouter/tests/browser/head.js
--- thunderbird-140.14.0esr/browser/components/asrouter/tests/browser/head.js 2026-08-18 02:52:31.000000000 +0000
+++ thunderbird-140.15.0esr/browser/components/asrouter/tests/browser/head.js 2026-08-28 17:33:04.000000000 +0000
@@ -2,6 +2,7 @@
ChromeUtils.defineESModuleGetters(this, {
ASRouter: "resource:///modules/asrouter/ASRouter.sys.mjs",
+ ExperimentAPI: "resource://nimbus/ExperimentAPI.sys.mjs",
FeatureCallout: "resource:///modules/asrouter/FeatureCallout.sys.mjs",
FeatureCalloutBroker:
@@ -10,6 +11,7 @@
FeatureCalloutMessages:
"resource:///modules/asrouter/FeatureCalloutMessages.sys.mjs",
+ NimbusTestUtils: "resource://testing-common/NimbusTestUtils.sys.mjs",
PlacesTestUtils: "resource://testing-common/PlacesTestUtils.sys.mjs",
QueryCache: "resource:///modules/asrouter/ASRouterTargeting.sys.mjs",
AboutWelcomeParent: "resource:///actors/AboutWelcomeParent.sys.mjs",
@@ -29,6 +31,10 @@
const calloutDismissSelector = `#${calloutId} .dismiss-button`;
const CTASelector = `#${calloutId} :is(.primary, .secondary)`;
+add_setup(function setup() {
+ registerCleanupFunction(NimbusTestUtils.disableSignatureVerification());
+});
+
function pushPrefs(...prefs) {
return SpecialPowers.pushPrefEnv({ set: prefs });
}
diff -Nru thunderbird-140.14.0esr/browser/components/preferences/tests/head.js thunderbird-140.15.0esr/browser/components/preferences/tests/head.js
--- thunderbird-140.14.0esr/browser/components/preferences/tests/head.js 2026-08-18 02:52:31.000000000 +0000
+++ thunderbird-140.15.0esr/browser/components/preferences/tests/head.js 2026-08-28 17:33:04.000000000 +0000
@@ -486,6 +486,9 @@
];
async function setupLabsTest(recipes) {
+ const restoreSignatureVerification =
+ NimbusTestUtils.disableSignatureVerification();
+
await SpecialPowers.pushPrefEnv({
set: [
["app.normandy.run_interval_seconds", 0],
@@ -517,6 +520,7 @@
return async function cleanup() {
await NimbusTestUtils.removeStore(ExperimentAPI.manager.store);
await SpecialPowers.popPrefEnv();
+ restoreSignatureVerification();
};
}
diff -Nru thunderbird-140.14.0esr/browser/components/shell/nsWindowsShellService.cpp thunderbird-140.15.0esr/browser/components/shell/nsWindowsShellService.cpp
--- thunderbird-140.14.0esr/browser/components/shell/nsWindowsShellService.cpp 2026-08-18 02:52:31.000000000 +0000
+++ thunderbird-140.15.0esr/browser/components/shell/nsWindowsShellService.cpp 2026-08-28 17:33:04.000000000 +0000
@@ -94,24 +94,6 @@
#define REG_FAILED(val) (val != ERROR_SUCCESS)
-#ifdef DEBUG
-# define NS_ENSURE_HRESULT(hres, ret) \
- do { \
- HRESULT result = hres; \
- if (MOZ_UNLIKELY(FAILED(result))) { \
- mozilla::SmprintfPointer msg = mozilla::Smprintf( \
- "NS_ENSURE_HRESULT(%s, %s) failed with " \
- "result 0x%" PRIX32, \
- #hres, #ret, static_cast(result)); \
- NS_WARNING(msg.get()); \
- return ret; \
- } \
- } while (false)
-#else
-# define NS_ENSURE_HRESULT(hres, ret) \
- if (MOZ_UNLIKELY(FAILED(hres))) return ret
-#endif
-
using namespace mozilla;
using mozilla::intl::Localization;
diff -Nru thunderbird-140.14.0esr/browser/components/tabbrowser/test/browser/tabs/browser_new_tab_in_privilegedabout_process_pref.js thunderbird-140.15.0esr/browser/components/tabbrowser/test/browser/tabs/browser_new_tab_in_privilegedabout_process_pref.js
--- thunderbird-140.14.0esr/browser/components/tabbrowser/test/browser/tabs/browser_new_tab_in_privilegedabout_process_pref.js 2026-08-18 02:52:31.000000000 +0000
+++ thunderbird-140.15.0esr/browser/components/tabbrowser/test/browser/tabs/browser_new_tab_in_privilegedabout_process_pref.js 2026-08-28 17:33:04.000000000 +0000
@@ -216,13 +216,6 @@
BrowserTestUtils.startLoadingURIString(browser, TEST_HTTP);
await BrowserTestUtils.browserLoaded(browser, false, TEST_HTTP);
checkBrowserRemoteType(browser, E10SUtils.WEB_REMOTE_TYPE);
-
- // Check that location change causes a change in process type as well.
- await SpecialPowers.spawn(browser, [ABOUT_NEWTAB], uri => {
- content.location = uri;
- });
- await BrowserTestUtils.browserLoaded(browser, false, ABOUT_NEWTAB);
- assertIsPrivilegedProcess(browser, "about:newtab after location change");
}
);
diff -Nru thunderbird-140.14.0esr/browser/config/version.txt thunderbird-140.15.0esr/browser/config/version.txt
--- thunderbird-140.14.0esr/browser/config/version.txt 2026-08-18 02:52:31.000000000 +0000
+++ thunderbird-140.15.0esr/browser/config/version.txt 2026-08-28 17:33:04.000000000 +0000
@@ -1 +1 @@
-140.14.0
+140.15.0
diff -Nru thunderbird-140.14.0esr/browser/config/version_display.txt thunderbird-140.15.0esr/browser/config/version_display.txt
--- thunderbird-140.14.0esr/browser/config/version_display.txt 2026-08-18 02:52:31.000000000 +0000
+++ thunderbird-140.15.0esr/browser/config/version_display.txt 2026-08-28 17:33:04.000000000 +0000
@@ -1 +1 @@
-140.14.0esr
+140.15.0esr
diff -Nru thunderbird-140.14.0esr/comm/.gecko_rev.yml thunderbird-140.15.0esr/comm/.gecko_rev.yml
--- thunderbird-140.14.0esr/comm/.gecko_rev.yml 2026-08-18 02:53:04.000000000 +0000
+++ thunderbird-140.15.0esr/comm/.gecko_rev.yml 2026-08-28 17:33:36.000000000 +0000
@@ -1,7 +1,7 @@
---
GECKO_BASE_REPOSITORY: https://hg.mozilla.org/mozilla-unified
GECKO_HEAD_REPOSITORY: https://hg.mozilla.org/releases/mozilla-esr140
-GECKO_HEAD_REV: ee9f2b2aedc3c58347d66ca8d7b9f92ef1df3f53
+GECKO_HEAD_REV: 1ace7e56a446a26f61ef013ac6967e8186f47704
######
diff -Nru thunderbird-140.14.0esr/comm/mail/branding/nightly/content/inAppNotificationData.json thunderbird-140.15.0esr/comm/mail/branding/nightly/content/inAppNotificationData.json
--- thunderbird-140.14.0esr/comm/mail/branding/nightly/content/inAppNotificationData.json 2026-08-18 02:53:04.000000000 +0000
+++ thunderbird-140.15.0esr/comm/mail/branding/nightly/content/inAppNotificationData.json 2026-08-28 17:33:36.000000000 +0000
@@ -1,19 +1,5 @@
[
{
- "id": "PREBAKED-Spring26",
- "start_at": "2026-04-01T00:00:00.000Z",
- "end_at": "2026-06-30T23:59:59.000Z",
- "title": "Prebaked Appeal Spring26",
- "description": "",
- "URL": "https://updates.thunderbird.net/%LOCALE%/thunderbird/appeal/?locale=%LOCALE%&version=%VERSION%&channel=%CHANNEL%&os=%OS%&buildid=%APPBUILDID%&ID=PREBAKED-Spring26",
- "CTA": "",
- "severity": 3,
- "type": "donation_tab",
- "targeting": {
- "percent_chance": 100
- }
- },
- {
"id": "PREBAKED-ESR26",
"start_at": "2026-07-01T00:00:00.000Z",
"end_at": "2026-11-02T23:59:59.000Z",
diff -Nru thunderbird-140.14.0esr/comm/mail/branding/tb_beta/content/inAppNotificationData.json thunderbird-140.15.0esr/comm/mail/branding/tb_beta/content/inAppNotificationData.json
--- thunderbird-140.14.0esr/comm/mail/branding/tb_beta/content/inAppNotificationData.json 2026-08-18 02:53:04.000000000 +0000
+++ thunderbird-140.15.0esr/comm/mail/branding/tb_beta/content/inAppNotificationData.json 2026-08-28 17:33:36.000000000 +0000
@@ -1,19 +1,5 @@
[
{
- "id": "PREBAKED-Spring26",
- "start_at": "2026-04-01T00:00:00.000Z",
- "end_at": "2026-06-30T23:59:59.000Z",
- "title": "Prebaked Appeal Spring26",
- "description": "",
- "URL": "https://updates.thunderbird.net/%LOCALE%/thunderbird/appeal/?locale=%LOCALE%&version=%VERSION%&channel=%CHANNEL%&os=%OS%&buildid=%APPBUILDID%&ID=PREBAKED-Spring26",
- "CTA": "",
- "severity": 3,
- "type": "donation_tab",
- "targeting": {
- "percent_chance": 100
- }
- },
- {
"id": "PREBAKED-ESR26",
"start_at": "2026-07-01T00:00:00.000Z",
"end_at": "2026-11-02T23:59:59.000Z",
diff -Nru thunderbird-140.14.0esr/comm/mail/branding/thunderbird/content/inAppNotificationData.json thunderbird-140.15.0esr/comm/mail/branding/thunderbird/content/inAppNotificationData.json
--- thunderbird-140.14.0esr/comm/mail/branding/thunderbird/content/inAppNotificationData.json 2026-08-18 02:53:04.000000000 +0000
+++ thunderbird-140.15.0esr/comm/mail/branding/thunderbird/content/inAppNotificationData.json 2026-08-28 17:33:36.000000000 +0000
@@ -1,19 +1,5 @@
[
{
- "id": "PREBAKED-Spring26",
- "start_at": "2026-04-01T00:00:00.000Z",
- "end_at": "2026-06-30T23:59:59.000Z",
- "title": "Prebaked Appeal Spring26",
- "description": "",
- "URL": "https://updates.thunderbird.net/%LOCALE%/thunderbird/appeal/?locale=%LOCALE%&version=%VERSION%&channel=%CHANNEL%&os=%OS%&buildid=%APPBUILDID%&ID=PREBAKED-Spring26",
- "CTA": "",
- "severity": 3,
- "type": "donation_tab",
- "targeting": {
- "percent_chance": 100
- }
- },
- {
"id": "PREBAKED-ESR26",
"start_at": "2026-07-01T00:00:00.000Z",
"end_at": "2026-11-02T23:59:59.000Z",
diff -Nru thunderbird-140.14.0esr/comm/mail/config/version.txt thunderbird-140.15.0esr/comm/mail/config/version.txt
--- thunderbird-140.14.0esr/comm/mail/config/version.txt 2026-08-18 02:53:04.000000000 +0000
+++ thunderbird-140.15.0esr/comm/mail/config/version.txt 2026-08-28 17:33:36.000000000 +0000
@@ -1 +1 @@
-140.14.0
+140.15.0
diff -Nru thunderbird-140.14.0esr/comm/mail/config/version_display.txt thunderbird-140.15.0esr/comm/mail/config/version_display.txt
--- thunderbird-140.14.0esr/comm/mail/config/version_display.txt 2026-08-18 02:53:04.000000000 +0000
+++ thunderbird-140.15.0esr/comm/mail/config/version_display.txt 2026-08-28 17:33:36.000000000 +0000
@@ -1 +1 @@
-140.14.0esr
+140.15.0esr
diff -Nru thunderbird-140.14.0esr/comm/mail/modules/LinkHelper.sys.mjs thunderbird-140.15.0esr/comm/mail/modules/LinkHelper.sys.mjs
--- thunderbird-140.14.0esr/comm/mail/modules/LinkHelper.sys.mjs 2026-08-18 02:53:04.000000000 +0000
+++ thunderbird-140.15.0esr/comm/mail/modules/LinkHelper.sys.mjs 2026-08-28 17:33:36.000000000 +0000
@@ -95,6 +95,7 @@
? getClonedPrincipalWithProtocolPermission(principal, uri)
: getContentPrincipalWithProtocolPermission(uri);
}
+ principal ??= Services.scriptSecurityManager.getSystemPrincipal();
Cc["@mozilla.org/uriloader/external-protocol-service;1"]
.getService(Ci.nsIExternalProtocolService)
diff -Nru thunderbird-140.14.0esr/comm/mail/modules/WindowsJumpLists.sys.mjs thunderbird-140.15.0esr/comm/mail/modules/WindowsJumpLists.sys.mjs
--- thunderbird-140.14.0esr/comm/mail/modules/WindowsJumpLists.sys.mjs 2026-08-18 02:53:04.000000000 +0000
+++ thunderbird-140.15.0esr/comm/mail/modules/WindowsJumpLists.sys.mjs 2026-08-28 17:33:36.000000000 +0000
@@ -49,7 +49,7 @@
get description() {
return _getString("taskbar.tasks.composeMessage.description");
},
- args: "-compose",
+ args: ["-compose"],
iconIndex: 2, // Write message icon
},
@@ -61,7 +61,7 @@
get description() {
return _getString("taskbar.tasks.openAddressBook.description");
},
- args: "-addressbook",
+ args: ["-addressbook"],
iconIndex: 3, // Open address book icon
},
];
diff -Nru thunderbird-140.14.0esr/comm/mailnews/imap/src/nsImapGenericParser.cpp thunderbird-140.15.0esr/comm/mailnews/imap/src/nsImapGenericParser.cpp
--- thunderbird-140.14.0esr/comm/mailnews/imap/src/nsImapGenericParser.cpp 2026-08-18 02:53:04.000000000 +0000
+++ thunderbird-140.15.0esr/comm/mailnews/imap/src/nsImapGenericParser.cpp 2026-08-28 17:33:36.000000000 +0000
@@ -91,19 +91,29 @@
}
}
+// (Re)initialize the tokenizer over the current line if it isn't already set
+// up. Returns false and reports a memory failure if the buffer can't be
+// allocated. The tokenizer buffer is a private copy of fCurrentLine that
+// NS_strtok() mutates in place; fLineOfTokens and fCurrentTokenPlaceHolder
+// point into it, so they must never outlive it (see AdvanceToNextLine()).
+bool nsImapGenericParser::InitTokenizer() {
+ if (!fStartOfLineOfTokens) {
+ fStartOfLineOfTokens = PL_strdup(fCurrentLine);
+ if (!fStartOfLineOfTokens) {
+ HandleMemoryFailure();
+ return false;
+ }
+ fLineOfTokens = fStartOfLineOfTokens;
+ fCurrentTokenPlaceHolder = fStartOfLineOfTokens;
+ }
+ return true;
+}
+
void nsImapGenericParser::AdvanceToNextToken() {
if (!fCurrentLine || fAtEndOfLine) AdvanceToNextLine();
if (Connected()) {
- if (!fStartOfLineOfTokens) {
- // this is the first token of the line; setup tokenizer now
- fStartOfLineOfTokens = PL_strdup(fCurrentLine);
- if (!fStartOfLineOfTokens) {
- HandleMemoryFailure();
- return;
- }
- fLineOfTokens = fStartOfLineOfTokens;
- fCurrentTokenPlaceHolder = fStartOfLineOfTokens;
- }
+ // if this is the first token of the line, setup the tokenizer now
+ if (!InitTokenizer()) return;
fNextToken = NS_strtok(WHITESPACE, &fCurrentTokenPlaceHolder);
if (!fNextToken) {
fAtEndOfLine = true;
@@ -117,11 +127,15 @@
PR_FREEIF(fStartOfLineOfTokens);
bool ok = GetNextLineForParser(&fCurrentLine);
+ // PR_FREEIF above freed and nulled fStartOfLineOfTokens, but fLineOfTokens
+ // and fCurrentTokenPlaceHolder still point into that freed buffer. Clear
+ // them on every path so they can't be dereferenced before InitTokenizer()
+ // reallocates the tokenizer for the new line.
+ fLineOfTokens = nullptr;
+ fCurrentTokenPlaceHolder = nullptr;
if (!ok) {
SetConnected(false);
fStartOfLineOfTokens = nullptr;
- fLineOfTokens = nullptr;
- fCurrentTokenPlaceHolder = nullptr;
fAtEndOfLine = true;
fNextToken = CRLF;
} else if (!fCurrentLine) {
@@ -375,6 +389,12 @@
returnString.Append(lit);
PR_Free(lit);
if (!ContinueParse()) break;
+ // A literal that exactly consumed its line leaves CreateLiteral() having
+ // advanced to a fresh line and released the tokenizer buffer that
+ // parenGroupStart pointed into. Re-tokenize the current line before
+ // resuming the scan, otherwise both pointers would dangle into freed
+ // memory.
+ if (!InitTokenizer()) break;
parenGroupStart = fCurrentTokenPlaceHolder;
} else if (*fCurrentTokenPlaceHolder == '"') // quoted
{
diff -Nru thunderbird-140.14.0esr/comm/mailnews/imap/src/nsImapGenericParser.h thunderbird-140.15.0esr/comm/mailnews/imap/src/nsImapGenericParser.h
--- thunderbird-140.14.0esr/comm/mailnews/imap/src/nsImapGenericParser.h 2026-08-18 02:53:04.000000000 +0000
+++ thunderbird-140.15.0esr/comm/mailnews/imap/src/nsImapGenericParser.h 2026-08-28 17:33:36.000000000 +0000
@@ -50,6 +50,7 @@
char* CreateParenGroup();
virtual void SetSyntaxError(bool error, const char* msg);
+ bool InitTokenizer();
void AdvanceToNextToken();
void AdvanceToNextLine();
void AdvanceTokenizerStartingPoint(int32_t bytesToAdvance);
diff -Nru thunderbird-140.14.0esr/comm/mailnews/imap/test/unit/test_imapIDLiteralParenGroup.js thunderbird-140.15.0esr/comm/mailnews/imap/test/unit/test_imapIDLiteralParenGroup.js
--- thunderbird-140.14.0esr/comm/mailnews/imap/test/unit/test_imapIDLiteralParenGroup.js 1970-01-01 00:00:00.000000000 +0000
+++ thunderbird-140.15.0esr/comm/mailnews/imap/test/unit/test_imapIDLiteralParenGroup.js 2026-08-28 17:33:36.000000000 +0000
@@ -0,0 +1,65 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * Regression test for bug 2057805: a server ID response whose paren group
+ * contains a literal that exactly fills its line used to leave
+ * nsImapGenericParser::CreateParenGroup() reading from a freed tokenizer
+ * buffer (heap-use-after-free). The crafted response below reproduces that
+ * exact shape; parsing it must complete cleanly and land the parsed value in
+ * the serverIDResponse pref.
+ *
+ * On the wire the server emits:
+ * * ID ({4}
+ * ab
+ * )
+ * where {4} is a literal of the four octets 'a', 'b', CR, LF -- i.e. the
+ * literal length equals the whole "ab\r\n" line including its CRLF, which is
+ * what triggered the use-after-free.
+ */
+
+/* import-globals-from ../../../test/resources/logHelper.js */
+load("../../../resources/logHelper.js");
+
+var { PromiseTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/mailnews/PromiseTestUtils.sys.mjs"
+);
+
+// The fake server joins the pieces of an ID response with a NUL, which the
+// transport turns into separate CRLF-terminated lines. Keeping the literal
+// marker and its payload here produces the crafted three-line response.
+var kIDResponse = "({4}\r\nab\r\n)";
+
+add_setup(async function () {
+ setupIMAPPump("GMail");
+ IMAPPump.daemon.idResponse = kIDResponse;
+
+ // Update the folder to kick start the ID exchange.
+ const promiseUrlListener = new PromiseTestUtils.PromiseUrlListener();
+ IMAPPump.inbox.updateFolderWithListener(null, promiseUrlListener);
+ await promiseUrlListener.promise;
+});
+
+add_task(async function updateInboxAgain() {
+ // A second update proves the connection and parser state survived parsing
+ // the crafted response (a corrupted parser would fail or hang here).
+ const promiseUrlListener = new PromiseTestUtils.PromiseUrlListener();
+ IMAPPump.inbox.updateFolderWithListener(null, promiseUrlListener);
+ await promiseUrlListener.promise;
+});
+
+add_task(function checkParsedServerID() {
+ // The literal payload must have been parsed out of the paren group without
+ // crashing and persisted to the pref.
+ const serverID = IMAPPump.incomingServer.serverIDPref;
+ Assert.ok(!!serverID, "serverIDResponse pref should be set");
+ Assert.ok(
+ serverID.includes("ab"),
+ `parsed server ID should contain the literal payload, got: ${JSON.stringify(
+ serverID
+ )}`
+ );
+});
+
+add_task(teardownIMAPPump);
diff -Nru thunderbird-140.14.0esr/comm/mailnews/imap/test/unit/xpcshell-shared.toml thunderbird-140.15.0esr/comm/mailnews/imap/test/unit/xpcshell-shared.toml
--- thunderbird-140.14.0esr/comm/mailnews/imap/test/unit/xpcshell-shared.toml 2026-08-18 02:53:04.000000000 +0000
+++ thunderbird-140.15.0esr/comm/mailnews/imap/test/unit/xpcshell-shared.toml 2026-08-28 17:33:36.000000000 +0000
@@ -59,6 +59,8 @@
["test_imapID.js"]
+["test_imapIDLiteralParenGroup.js"]
+
["test_imapMove.js"]
["test_imapPasswordFailure.js"]
diff -Nru thunderbird-140.14.0esr/comm/mailnews/local/src/components.conf thunderbird-140.15.0esr/comm/mailnews/local/src/components.conf
--- thunderbird-140.14.0esr/comm/mailnews/local/src/components.conf 2026-08-18 02:53:04.000000000 +0000
+++ thunderbird-140.15.0esr/comm/mailnews/local/src/components.conf 2026-08-28 17:33:36.000000000 +0000
@@ -57,6 +57,7 @@
"contract_ids": ["@mozilla.org/messenger/msgmailnewsurl;1"],
"type": "nsMsgMailNewsUrl",
"headers": ["/comm/mailnews/base/src/nsMsgMailNewsUrl.h"],
+ "serializable": True,
},
{
"cid": "{eef82462-cb69-11d2-8065-006008128c4e}",
diff -Nru thunderbird-140.14.0esr/comm/mailnews/local/src/nsParseMailbox.cpp thunderbird-140.15.0esr/comm/mailnews/local/src/nsParseMailbox.cpp
--- thunderbird-140.14.0esr/comm/mailnews/local/src/nsParseMailbox.cpp 2026-08-18 02:53:04.000000000 +0000
+++ thunderbird-140.15.0esr/comm/mailnews/local/src/nsParseMailbox.cpp 2026-08-28 17:33:36.000000000 +0000
@@ -716,7 +716,7 @@
header->value = value;
}
}
- if (*buf == '\r' || *buf == '\n') {
+ if (buf < buf_end && (*buf == '\r' || *buf == '\n')) {
char* last = bufWrite;
char* saveBuf = buf;
if (*buf == '\r' && buf + 1 < buf_end && buf[1] == '\n') buf++;
diff -Nru thunderbird-140.14.0esr/comm/mailnews/local/test/unit/test_nsIMsgParseMailMsgState.js thunderbird-140.15.0esr/comm/mailnews/local/test/unit/test_nsIMsgParseMailMsgState.js
--- thunderbird-140.14.0esr/comm/mailnews/local/test/unit/test_nsIMsgParseMailMsgState.js 2026-08-18 02:53:04.000000000 +0000
+++ thunderbird-140.15.0esr/comm/mailnews/local/test/unit/test_nsIMsgParseMailMsgState.js 2026-08-28 17:33:36.000000000 +0000
@@ -14,6 +14,7 @@
await test_parse_headers_without_crash("./data/mailformed_recipients.eml");
await test_parse_headers_without_crash("./data/mailformed_subject.eml");
await test_parse_headers_without_crash("./data/invalid_mozilla_keys.eml");
+ await test_parse_header_without_linebreak();
});
async function test_parse_headers_without_crash(eml) {
@@ -40,3 +41,16 @@
// in a row.
await PromiseTestUtils.promiseDelay(200);
}
+
+async function test_parse_header_without_linebreak() {
+ const parser = Cc[
+ "@mozilla.org/messenger/messagestateparser;1"
+ ].createInstance(Ci.nsIMsgParseMailMsgState);
+
+ parser.SetMailDB(localAccountUtils.inboxFolder.getDatabaseWOReparse());
+ parser.state = Ci.nsIMsgParseMailMsgState.ParseHeadersState;
+
+ const header = "X:" + "A".repeat(16382);
+ parser.ParseAFolderLine(header, header.length);
+ parser.ParseAFolderLine(MSG_LINEBREAK, MSG_LINEBREAK.length);
+}
diff -Nru thunderbird-140.14.0esr/comm/mailnews/mime/src/mimemrel.cpp thunderbird-140.15.0esr/comm/mailnews/mime/src/mimemrel.cpp
--- thunderbird-140.14.0esr/comm/mailnews/mime/src/mimemrel.cpp 2026-08-18 02:53:04.000000000 +0000
+++ thunderbird-140.15.0esr/comm/mailnews/mime/src/mimemrel.cpp 2026-08-28 17:33:36.000000000 +0000
@@ -98,6 +98,7 @@
*/
#include "mimehdrs.h"
+#include "mozilla/ScopeExit.h"
#include "nsCOMPtr.h"
#include "mimemrel.h"
#include "mimemapl.h"
@@ -355,6 +356,11 @@
char* MakeAbsoluteURL(char* base_url, char* relative_url) {
char* retString = nullptr;
nsIURI* base = nullptr;
+ nsIURI* url = nullptr;
+ auto releaseUris = mozilla::MakeScopeExit([&] {
+ NS_IF_RELEASE(url);
+ NS_IF_RELEASE(base);
+ });
// if either is NULL, just return the relative if safe...
if (!base_url || !relative_url) {
@@ -369,20 +375,15 @@
nsAutoCString spec;
- nsIURI* url = nullptr;
err = nsMimeNewURI(&url, relative_url, base);
- if (NS_FAILED(err)) goto done;
+ if (NS_FAILED(err)) return nullptr;
err = url->GetSpec(spec);
if (NS_FAILED(err)) {
- retString = nullptr;
- goto done;
+ return nullptr;
}
retString = ToNewCString(spec);
-done:
- NS_IF_RELEASE(url);
- NS_IF_RELEASE(base);
return retString;
}
@@ -958,7 +959,7 @@
const char* dct;
status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_eof(obj, abort_p);
- if (status < 0) goto FAIL;
+ if (status < 0) return status;
if (!relobj->headobj) return 0;
@@ -970,6 +971,10 @@
relobj->real_output_fn = obj->options->output_fn;
relobj->real_output_closure = obj->options->output_closure;
+ auto restoreOutput = mozilla::MakeScopeExit([&] {
+ obj->options->output_fn = relobj->real_output_fn;
+ obj->options->output_closure = relobj->real_output_closure;
+ });
obj->options->output_fn = mime_multipart_related_output_fn;
obj->options->output_closure =
@@ -981,7 +986,7 @@
PR_FREEIF(ct);
if (!body) {
status = MIME_OUT_OF_MEMORY;
- goto FAIL;
+ return status;
}
// replace the existing head object with the new object
for (int iChild = 0; iChild < cont->nchildren; iChild++) {
@@ -996,7 +1001,7 @@
if (!body->parent) {
NS_WARNING("unexpected mime multipart related structure");
- goto FAIL;
+ return status;
}
body->dontShowAsAttachment =
@@ -1026,7 +1031,7 @@
/* Now that we've added this new object to our list of children,
start its parser going. */
status = body->clazz->parse_begin(body);
- if (status < 0) goto FAIL;
+ if (status < 0) return status;
if (relobj->head_buffer) {
/* Read it out of memory. */
@@ -1043,14 +1048,15 @@
PR_ASSERT(relobj->file_buffer);
if (!relobj->file_buffer) {
status = -1;
- goto FAIL;
+ return status;
}
buf = (char*)PR_MALLOC(FILE_IO_BUFFER_SIZE);
if (!buf) {
status = MIME_OUT_OF_MEMORY;
- goto FAIL;
+ return status;
}
+ auto freeBuffer = mozilla::MakeScopeExit([buf] { PR_Free(buf); });
// First, close the output file to open the input file!
if (relobj->output_file_stream) relobj->output_file_stream->Close();
@@ -1058,9 +1064,8 @@
nsresult rv = NS_NewLocalFileInputStream(
getter_AddRefs(relobj->input_file_stream), relobj->file_buffer);
if (NS_FAILED(rv)) {
- PR_Free(buf);
status = MIME_UNABLE_TO_OPEN_TMP_FILE;
- goto FAIL;
+ return status;
}
while (1) {
@@ -1080,18 +1085,15 @@
if (status < 0) break;
}
}
- PR_Free(buf);
}
- if (status < 0) goto FAIL;
+ if (status < 0) return status;
/* Done parsing. */
status = body->clazz->parse_eof(body, false);
- if (status < 0) goto FAIL;
+ if (status < 0) return status;
status = body->clazz->parse_end(body, false);
- if (status < 0) goto FAIL;
-
-FAIL:
+ if (status < 0) return status;
#ifdef MIME_DRAFTS
if (obj->options && obj->options->decompose_file_p &&
@@ -1103,9 +1105,6 @@
}
#endif /* MIME_DRAFTS */
- obj->options->output_fn = relobj->real_output_fn;
- obj->options->output_closure = relobj->real_output_closure;
-
return status;
}
diff -Nru thunderbird-140.14.0esr/config/milestone.txt thunderbird-140.15.0esr/config/milestone.txt
--- thunderbird-140.14.0esr/config/milestone.txt 2026-08-18 02:52:32.000000000 +0000
+++ thunderbird-140.15.0esr/config/milestone.txt 2026-08-28 17:33:04.000000000 +0000
@@ -10,4 +10,4 @@
# hardcoded milestones in the tree from these two files.
#--------------------------------------------------------
-140.14.0
+140.15.0
diff -Nru thunderbird-140.14.0esr/debian/changelog thunderbird-140.15.0esr/debian/changelog
--- thunderbird-140.14.0esr/debian/changelog 2026-08-21 15:46:03.000000000 +0000
+++ thunderbird-140.15.0esr/debian/changelog 2026-09-02 13:10:45.000000000 +0000
@@ -1,3 +1,30 @@
+thunderbird (1:140.15.0esr-1~deb13u1) trixie-security; urgency=medium
+
+ * [4095154] New upstream version 140.15.0esr
+ Fixed CVE issues in upstream version 140.15 (MFSA 2026-87):
+ CVE-2026-84639: Uninitialized memory in MIME parsing
+ CVE-2026-84640: One byte overflow read in mail parser
+ CVE-2026-84641: Information disclosure due to malicious IMAP server
+ response
+ CVE-2026-75874: Sandbox escape in the Remote Settings Client component
+ CVE-2026-16365: Privilege escalation in the DOM: Workers component
+ CVE-2026-84119: Sandbox escape due to use-after-free in the DOM:
+ Navigation component
+ CVE-2026-84120: Use-after-free in the Audio/Video component
+ CVE-2026-84121: Sandbox escape due to use-after-free in the DOM: Security
+ component
+ CVE-2026-84122: Use-after-free in the Audio/Video component
+ CVE-2026-84124: Use-after-free in the DOM: Core & HTML component
+ CVE-2026-16371: Privilege escalation in the DOM: Navigation component
+ CVE-2026-84131: Privilege escalation due to invalid pointer in the
+ Graphics component
+ CVE-2026-84143: Internally found bugs fixed in Thunderbird 155,
+ Thunderbird ESR 153.2 and Thunderbird ESR 140.15
+ CVE-2026-84145: Internally found bugs fixed in Thunderbird 155,
+ Thunderbird ESR 153.2 and Thunderbird ESR 140.15
+
+ -- Christoph Goehre Wed, 02 Sep 2026 09:10:45 -0400
+
thunderbird (1:140.14.0esr-1~deb13u1) trixie-security; urgency=medium
* Rebuild for trixie-security
diff -Nru thunderbird-140.14.0esr/docshell/base/BrowsingContext.cpp thunderbird-140.15.0esr/docshell/base/BrowsingContext.cpp
--- thunderbird-140.14.0esr/docshell/base/BrowsingContext.cpp 2026-08-18 02:52:31.000000000 +0000
+++ thunderbird-140.15.0esr/docshell/base/BrowsingContext.cpp 2026-08-28 17:33:04.000000000 +0000
@@ -865,6 +865,17 @@
parent->mOriginAttributes.EqualsIgnoringFPD(mOriginAttributes));
}
+ if (aOriginProcess) {
+ if (GetBrowserId() == 0) {
+ return "Content BC must have a nonzero BrowserId";
+ }
+ if (!GetParent()) {
+ uint64_t browserProc =
+ std::get<0>(nsContentUtils::SplitProcessSpecificId(GetBrowserId()));
+ COHERENCY_ASSERT(browserProc == aOriginProcess->ChildID());
+ }
+ }
+
// UseRemoteSubframes and UseRemoteTabs must match.
if (mUseRemoteSubframes && !mUseRemoteTabs) {
return "Cannot set useRemoteSubframes without also setting useRemoteTabs";
diff -Nru thunderbird-140.14.0esr/docshell/base/nsDocShell.cpp thunderbird-140.15.0esr/docshell/base/nsDocShell.cpp
--- thunderbird-140.14.0esr/docshell/base/nsDocShell.cpp 2026-08-18 02:52:32.000000000 +0000
+++ thunderbird-140.15.0esr/docshell/base/nsDocShell.cpp 2026-08-28 17:33:04.000000000 +0000
@@ -12226,48 +12226,24 @@
return NS_OK;
}
+ // https://html.spec.whatwg.org/#navigate-to-a-javascript:-url
+ // Step 13: historyEntry should store entryToReplace's URL.
+ if (aLoadState->URI()->SchemeIs("javascript")) {
+ MOZ_ASSERT_UNREACHABLE("javascript: URIs should not enter session history");
+ return NS_ERROR_FAILURE;
+ }
+
// We are setting load type afterwards so we don't have to
// send it in an IPC message
aLoadState->SetLoadType(aLoadType);
- nsresult rv;
- if (aLoadState->URI()->SchemeIs("javascript")) {
- // We're loading a URL that will execute script from inside asyncOpen.
- // Replace the current document with about:blank now to prevent
- // anything from the current document from leaking into any JavaScript
- // code in the URL.
- // Don't cache the presentation if we're going to just reload the
- // current entry. Caching would lead to trying to save the different
- // content viewers in the same nsISHEntry object.
- rv = CreateAboutBlankDocumentViewer(
- aLoadState->PrincipalToInherit(),
- aLoadState->PartitionedPrincipalToInherit(), nullptr, nullptr,
- /* aIsInitialDocument */ false, Nothing(), !aLoadingCurrentEntry);
-
- if (NS_FAILED(rv)) {
- // The creation of the intermittent about:blank content
- // viewer failed for some reason (potentially because the
- // user prevented it). Interrupt the history load.
- return NS_OK;
- }
-
- if (!aLoadState->TriggeringPrincipal()) {
- // Ensure that we have a triggeringPrincipal. Otherwise javascript:
- // URIs will pick it up from the about:blank page we just loaded,
- // and we don't really want even that in this case.
- nsCOMPtr principal =
- NullPrincipal::Create(GetOriginAttributes());
- aLoadState->SetTriggeringPrincipal(principal);
- }
- }
-
/* If there is a valid postdata *and* the user pressed
* reload or shift-reload, take user's permission before we
* repost the data to the server.
*/
if ((aLoadType & LOAD_CMD_RELOAD) && aLoadState->PostDataStream()) {
bool repost;
- rv = ConfirmRepost(&repost);
+ nsresult rv = ConfirmRepost(&repost);
if (NS_FAILED(rv)) {
return rv;
}
diff -Nru thunderbird-140.14.0esr/docshell/base/nsDocShellLoadState.cpp thunderbird-140.15.0esr/docshell/base/nsDocShellLoadState.cpp
--- thunderbird-140.14.0esr/docshell/base/nsDocShellLoadState.cpp 2026-08-18 02:52:32.000000000 +0000
+++ thunderbird-140.15.0esr/docshell/base/nsDocShellLoadState.cpp 2026-08-28 17:33:05.000000000 +0000
@@ -9,15 +9,18 @@
#include "nsDocShell.h"
#include "nsILoadInfo.h"
#include "nsIProtocolHandler.h"
+#include "nsIScriptSecurityManager.h"
#include "nsISHEntry.h"
#include "nsIURIFixup.h"
#include "nsIWebNavigation.h"
#include "nsIChannel.h"
#include "nsIURLQueryStringStripper.h"
#include "nsIXULRuntime.h"
+#include "nsAboutProtocolUtils.h"
#include "nsNetUtil.h"
#include "nsQueryObject.h"
#include "ReferrerInfo.h"
+#include "xpcpublic.h"
#include "mozilla/BasePrincipal.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/Components.h"
@@ -26,6 +29,7 @@
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/FormData.h"
#include "mozilla/dom/LoadURIOptionsBinding.h"
+#include "mozilla/dom/ProcessIsolation.h"
#include "mozilla/dom/nsHTTPSOnlyUtils.h"
#include "mozilla/StaticPrefs_browser.h"
#include "mozilla/StaticPrefs_fission.h"
@@ -43,6 +47,65 @@
// Global reference to the URI fixup service.
static mozilla::StaticRefPtr sURIFixup;
+static bool ContentTriggeredURILoadIsAllowed(
+ nsIURI* aURI, const nsACString& aEffectiveRemoteType) {
+ MOZ_ASSERT(aEffectiveRemoteType != NOT_REMOTE_TYPE);
+ MOZ_ASSERT(!aURI->SchemeIs("javascript"), "Should have been blocked already");
+
+ // view-source: URIs are not linkable from web content, but the "View Page
+ // Source" context menu has the content process itself load them,
+ // so decide based on the inner URI instead.
+ if (aURI->SchemeIs("view-source")) {
+ nsCOMPtr nestedURI = do_QueryInterface(aURI);
+ MOZ_ASSERT(nestedURI);
+
+ nsCOMPtr innerURI;
+ return NS_SUCCEEDED(nestedURI->GetInnerURI(getter_AddRefs(innerURI))) &&
+ ContentTriggeredURILoadIsAllowed(innerURI, aEffectiveRemoteType);
+ }
+
+ // A null principal is the least privileged principal there is, so any URI it
+ // is allowed to link to may be loaded from any content process.
+ nsCOMPtr genericNullPrincipal = NullPrincipal::Create({});
+
+ nsCOMPtr secMan =
+ do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
+
+ if (NS_SUCCEEDED(secMan->CheckLoadURIWithPrincipal(
+ genericNullPrincipal, aURI,
+ nsIScriptSecurityManager::DISALLOW_SCRIPT |
+ nsIScriptSecurityManager::DONT_REPORT_ERRORS,
+ 0))) {
+ return true;
+ }
+
+ nsCOMPtr principal =
+ BasePrincipal::CreateContentPrincipal(aURI, {});
+ if (principal->GetIsNullPrincipal()) {
+ // Only allow null principals from URIs that have the
+ // URI_LOADABLE_BY_SUBSUMERS (i.e. blob:) flag. Other null principals likely
+ // correspond to internal, unsafe-to-load in content, resources.
+ bool loadableBySubsumers = false;
+ if (NS_FAILED(NS_URIChainHasFlags(
+ aURI, nsIProtocolHandler::URI_LOADABLE_BY_SUBSUMERS,
+ &loadableBySubsumers))) {
+ return false;
+ }
+ return loadableBySubsumers;
+ }
+
+ // Automation-Only: Allow loading of chrome://reftest/* URLs.
+ if (aURI->SchemeIs("chrome") && xpc::IsInAutomation()) {
+ nsAutoCString host;
+ if (NS_SUCCEEDED(aURI->GetHost(host)) && host.EqualsLiteral("reftest")) {
+ return true;
+ }
+ }
+
+ return ValidatePrincipalCouldPotentiallyBeLoadedBy(principal,
+ aEffectiveRemoteType, {});
+}
+
nsDocShellLoadState::nsDocShellLoadState(nsIURI* aURI)
: nsDocShellLoadState(aURI, nsContentUtils::GenerateLoadIdentifier()) {}
@@ -157,6 +220,46 @@
return;
}
}
+
+ if (!ValidatePrincipalCouldPotentiallyBeLoadedBy(
+ mTriggeringPrincipal, GetEffectiveTriggeringRemoteType(),
+ {ValidatePrincipalOptions::AllowExpanded,
+ ValidatePrincipalOptions::AllowSystem})) {
+ aActor->FatalError(
+ "nsDocShellLoadState with invalid triggering principal");
+ return;
+ }
+ EnumSet principalToInheritOptions = {
+ ValidatePrincipalOptions::AllowNullPtr};
+ if (xpc::IsInAutomation()) {
+ // Bug 2011307, chrome reftests run in content.
+ principalToInheritOptions += ValidatePrincipalOptions::AllowSystem;
+ }
+ if (!ValidatePrincipalCouldPotentiallyBeLoadedBy(
+ mPrincipalToInherit, GetEffectiveTriggeringRemoteType(),
+ principalToInheritOptions)) {
+ aActor->FatalError("nsDocShellLoadState with invalid principalToInherit");
+ return;
+ }
+
+ const nsCString& effectiveRemoteType = GetEffectiveTriggeringRemoteType();
+ if (effectiveRemoteType != NOT_REMOTE_TYPE &&
+ !ContentTriggeredURILoadIsAllowed(mURI, effectiveRemoteType)) {
+ nsAutoCString aboutModuleOrScheme;
+ if (mURI->SchemeIs("about")) {
+ (void)NS_GetAboutModuleName(mURI, aboutModuleOrScheme);
+ aboutModuleOrScheme.InsertLiteral("about:", 0);
+ } else {
+ mURI->GetScheme(aboutModuleOrScheme);
+ aboutModuleOrScheme.AppendLiteral(":");
+ }
+ nsCString remotePrefix(RemoteTypePrefix(effectiveRemoteType));
+ aActor->FatalError(
+ nsPrintfCString("Illegal load attempt of %s URL from %s",
+ aboutModuleOrScheme.get(), remotePrefix.get())
+ .get());
+ return;
+ }
}
if (!mSrcdocData.IsVoid() && !mURI->SchemeIs("view-source") &&
diff -Nru thunderbird-140.14.0esr/docshell/shistory/SessionHistoryEntry.cpp thunderbird-140.15.0esr/docshell/shistory/SessionHistoryEntry.cpp
--- thunderbird-140.14.0esr/docshell/shistory/SessionHistoryEntry.cpp 2026-08-18 02:52:32.000000000 +0000
+++ thunderbird-140.15.0esr/docshell/shistory/SessionHistoryEntry.cpp 2026-08-28 17:33:05.000000000 +0000
@@ -59,6 +59,8 @@
aLoadState->PartitionedPrincipalToInherit(), aLoadState->Csp(),
/* FIXME Is this correct? */
aLoadState->TypeHint())) {
+ MOZ_DIAGNOSTIC_ASSERT(!mURI->SchemeIs("javascript"));
+
// Pull the upload stream off of the channel instead of the load state, as
// ownership has already been transferred from the load state to the channel.
if (nsCOMPtr postChannel = do_QueryInterface(aChannel)) {
@@ -78,6 +80,7 @@
SessionHistoryInfo::SessionHistoryInfo(
const SessionHistoryInfo& aSharedStateFrom, nsIURI* aURI)
: mURI(aURI), mSharedState(aSharedStateFrom.mSharedState) {
+ MOZ_DIAGNOSTIC_ASSERT(!mURI || !mURI->SchemeIs("javascript"));
MaybeUpdateTitleFromURI();
mHasUserInteraction = aSharedStateFrom.mHasUserInteraction;
}
@@ -91,6 +94,7 @@
mSharedState(SharedState::Create(
aTriggeringPrincipal, aPrincipalToInherit,
aPartitionedPrincipalToInherit, aCsp, aContentType)) {
+ MOZ_DIAGNOSTIC_ASSERT(!mURI || !mURI->SchemeIs("javascript"));
MaybeUpdateTitleFromURI();
}
@@ -102,6 +106,7 @@
NS_WARNING("NS_GetFinalChannelURI somehow failed in SessionHistoryInfo?");
aChannel->GetURI(getter_AddRefs(mURI));
}
+ MOZ_DIAGNOSTIC_ASSERT(!mURI->SchemeIs("javascript"));
mLoadType = aLoadType;
nsCOMPtr loadInfo;
@@ -519,6 +524,7 @@
NS_IMETHODIMP
SessionHistoryEntry::SetURI(nsIURI* aURI) {
+ MOZ_DIAGNOSTIC_ASSERT(!aURI->SchemeIs("javascript"));
mInfo->mURI = aURI;
return NS_OK;
}
@@ -1622,6 +1628,11 @@
return false;
}
+ if (aResult->mURI && aResult->mURI->SchemeIs("javascript")) {
+ aReader->FatalError("javascript: URIs should not enter session history");
+ return false;
+ }
+
nsCOMPtr triggeringPrincipal;
nsCOMPtr principalToInherit;
nsCOMPtr partitionedPrincipalToInherit;
diff -Nru thunderbird-140.14.0esr/dom/base/Document.cpp thunderbird-140.15.0esr/dom/base/Document.cpp
--- thunderbird-140.14.0esr/dom/base/Document.cpp 2026-08-18 02:52:32.000000000 +0000
+++ thunderbird-140.15.0esr/dom/base/Document.cpp 2026-08-28 17:33:04.000000000 +0000
@@ -15244,6 +15244,12 @@
// we would actually do nothing below except crashing ourselves via
// dispatching the "MozDOMFullscreen:Exited" event to an nonexistent
// document.
+ //
+ // We still reset this document, otherwise it could keep a stale element
+ // in its top layer with the fullscreen flag set.
+ if (aMaybeNotARootDoc->GetUnretargetedFullscreenElement()) {
+ aMaybeNotARootDoc->CleanupFullscreenState();
+ }
return;
}
@@ -15729,6 +15735,7 @@
nsTArray elements;
for (const nsWeakPtr& ptr : mTopLayer) {
if (nsCOMPtr elem = do_QueryReferent(ptr)) {
+ MOZ_DIAGNOSTIC_ASSERT(elem->GetComposedDoc() == this);
elements.AppendElement(elem);
}
}
@@ -16349,6 +16356,10 @@
RefPtr doc = aRequest->Document();
doc->HideAllPopoversUntil(*hideUntil, false, true);
+ if (!FullscreenElementReadyCheck(*aRequest)) {
+ return false;
+ }
+
// Stash a reference to any existing fullscreen doc, we'll use this later
// to detect if the origin which is fullscreen has changed.
nsCOMPtr previousFullscreenDoc = GetFullscreenLeaf(this);
diff -Nru thunderbird-140.14.0esr/dom/base/nsContentUtils.cpp thunderbird-140.15.0esr/dom/base/nsContentUtils.cpp
--- thunderbird-140.14.0esr/dom/base/nsContentUtils.cpp 2026-08-18 02:52:32.000000000 +0000
+++ thunderbird-140.15.0esr/dom/base/nsContentUtils.cpp 2026-08-28 17:33:05.000000000 +0000
@@ -9682,6 +9682,12 @@
}
// static
+bool nsContentUtils::IsImageType(ExtContentPolicy aType) {
+ return aType == ExtContentPolicy::TYPE_IMAGE ||
+ aType == ExtContentPolicy::TYPE_IMAGESET;
+}
+
+// static
ReferrerPolicy nsContentUtils::GetReferrerPolicyFromChannel(
nsIChannel* aChannel) {
nsCOMPtr httpChannel = do_QueryInterface(aChannel);
diff -Nru thunderbird-140.14.0esr/dom/base/nsContentUtils.h thunderbird-140.15.0esr/dom/base/nsContentUtils.h
--- thunderbird-140.14.0esr/dom/base/nsContentUtils.h 2026-08-18 02:52:32.000000000 +0000
+++ thunderbird-140.15.0esr/dom/base/nsContentUtils.h 2026-08-28 17:33:04.000000000 +0000
@@ -1504,6 +1504,13 @@
static bool IsPreloadType(nsContentPolicyType aType);
/**
+ * Returns true if the content policy type is any of:
+ * * ExtContentPolicy::TYPE_IMAGE
+ * * ExtContentPolicy::TYPE_IMAGESET
+ */
+ static bool IsImageType(ExtContentPolicy aType);
+
+ /**
* Quick helper to determine whether mutation events are enabled and there are
* any mutation listeners of a given type that apply to this content or any of
* its ancestors.
diff -Nru thunderbird-140.14.0esr/dom/base/nsFocusManager.cpp thunderbird-140.15.0esr/dom/base/nsFocusManager.cpp
--- thunderbird-140.14.0esr/dom/base/nsFocusManager.cpp 2026-08-18 02:52:32.000000000 +0000
+++ thunderbird-140.15.0esr/dom/base/nsFocusManager.cpp 2026-08-28 17:33:05.000000000 +0000
@@ -2449,8 +2449,9 @@
window->UpdateCommands(u"focus"_ns);
}
- SendFocusOrBlurEvent(eBlur, presShell, element->GetComposedDoc(), element,
- false, false, aElementToFocus);
+ RefPtr doc = element->GetComposedDoc();
+ SendFocusOrBlurEvent(eBlur, presShell, doc, element, false, false,
+ aElementToFocus);
}
// if we are leaving the document or the window was lowered, make the caret
diff -Nru thunderbird-140.14.0esr/dom/base/nsObjectLoadingContent.cpp thunderbird-140.15.0esr/dom/base/nsObjectLoadingContent.cpp
--- thunderbird-140.14.0esr/dom/base/nsObjectLoadingContent.cpp 2026-08-18 02:52:32.000000000 +0000
+++ thunderbird-140.15.0esr/dom/base/nsObjectLoadingContent.cpp 2026-08-28 17:33:05.000000000 +0000
@@ -1428,6 +1428,17 @@
return NS_ERROR_NOT_AVAILABLE;
}
+ // The channel's own security check happens in the parent process, which for
+ // a document load is only reached after the nsDocShellLoadState has already
+ // crossed IPC. Check here as well so that a load which content is not
+ // allowed to trigger never gets that far.
+ rv = nsContentUtils::GetSecurityManager()->CheckLoadURIWithPrincipal(
+ el->NodePrincipal(), mURI, nsIScriptSecurityManager::STANDARD,
+ doc->InnerWindowID());
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
nsCOMPtr group = doc->GetDocumentLoadGroup();
nsCOMPtr chan;
RefPtr shim =
diff -Nru thunderbird-140.14.0esr/dom/broadcastchannel/BroadcastChannel.cpp thunderbird-140.15.0esr/dom/broadcastchannel/BroadcastChannel.cpp
--- thunderbird-140.14.0esr/dom/broadcastchannel/BroadcastChannel.cpp 2026-08-18 02:52:32.000000000 +0000
+++ thunderbird-140.15.0esr/dom/broadcastchannel/BroadcastChannel.cpp 2026-08-28 17:33:05.000000000 +0000
@@ -211,6 +211,14 @@
bc->mWorkerRef = workerRef;
}
+ // Throw if this process wouldn't be allowed to access storage.
+ if (!BackgroundChild::ValidatePrincipal(unpartitionedPrincipal, {})) {
+ MOZ_ASSERT_UNREACHABLE(
+ "ValidatePrincipal failure in UnpartitionedTestingChannel");
+ aRv.Throw(NS_ERROR_UNEXPECTED);
+ return nullptr;
+ }
+
// Register this component to PBackground.
PBackgroundChild* actorChild = BackgroundChild::GetOrCreateForCurrentThread();
if (NS_WARN_IF(!actorChild)) {
@@ -334,6 +342,14 @@
return nullptr;
}
+ // Throw if this process wouldn't be allowed to access storage.
+ if (!BackgroundChild::ValidatePrincipal(storagePrincipal, {})) {
+ MOZ_ASSERT_UNREACHABLE(
+ "ValidatePrincipal failure in UnpartitionedTestingChannel");
+ aRv.Throw(NS_ERROR_UNEXPECTED);
+ return nullptr;
+ }
+
// Register this component to PBackground.
PBackgroundChild* actorChild = BackgroundChild::GetOrCreateForCurrentThread();
if (NS_WARN_IF(!actorChild)) {
diff -Nru thunderbird-140.14.0esr/dom/cache/CacheStorage.cpp thunderbird-140.15.0esr/dom/cache/CacheStorage.cpp
--- thunderbird-140.14.0esr/dom/cache/CacheStorage.cpp 2026-08-18 02:52:32.000000000 +0000
+++ thunderbird-140.15.0esr/dom/cache/CacheStorage.cpp 2026-08-28 17:33:05.000000000 +0000
@@ -272,6 +272,14 @@
mStatus(NS_OK) {
MOZ_DIAGNOSTIC_ASSERT(mGlobal);
+ // Throw if this process wouldn't be allowed to access storage.
+ if (!BackgroundChild::ValidatePrincipalInfo(*mPrincipalInfo, {})) {
+ MOZ_ASSERT_UNREACHABLE(
+ "ValidatePrincipalInfo failed in CacheStorage constructor");
+ mStatus = NS_ERROR_UNEXPECTED;
+ return;
+ }
+
// If the PBackground actor is already initialized then we can
// immediately use it
PBackgroundChild* actor = BackgroundChild::GetOrCreateForCurrentThread();
diff -Nru thunderbird-140.14.0esr/dom/cache/PrincipalVerifier.cpp thunderbird-140.15.0esr/dom/cache/PrincipalVerifier.cpp
--- thunderbird-140.14.0esr/dom/cache/PrincipalVerifier.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/cache/PrincipalVerifier.cpp 2026-08-28 17:33:04.000000000 +0000
@@ -8,6 +8,7 @@
#include "ErrorList.h"
#include "mozilla/dom/ContentParent.h"
+#include "mozilla/dom/ProcessIsolation.h"
#include "mozilla/dom/QMResult.h"
#include "mozilla/dom/cache/ManagerId.h"
#include "mozilla/dom/quota/ResultExtensions.h"
@@ -99,6 +100,12 @@
const auto& principal, PrincipalInfoToPrincipal(mPrincipalInfo), QM_VOID,
[this](const nsresult result) { DispatchToInitiatingThread(result); });
+ if (NS_WARN_IF(mHandle && !ValidatePrincipalCouldPotentiallyBeLoadedBy(
+ principal, mHandle->GetRemoteType(), {}))) {
+ DispatchToInitiatingThread(NS_ERROR_FAILURE);
+ return;
+ }
+
// We disallow null principal on the client side, but double-check here.
if (NS_WARN_IF(principal->GetIsNullPrincipal())) {
DispatchToInitiatingThread(NS_ERROR_FAILURE);
diff -Nru thunderbird-140.14.0esr/dom/cache/test/mochitest/test_chrome_constructor.html thunderbird-140.15.0esr/dom/cache/test/mochitest/test_chrome_constructor.html
--- thunderbird-140.14.0esr/dom/cache/test/mochitest/test_chrome_constructor.html 2026-08-18 02:52:32.000000000 +0000
+++ thunderbird-140.15.0esr/dom/cache/test/mochitest/test_chrome_constructor.html 2026-08-28 17:33:05.000000000 +0000
@@ -14,12 +14,11 @@
SpecialPowers.pushPrefEnv({
"set": [[ "dom.caches.testing.enabled", true ]],
}, function() {
- // attach to a different origin's CacheStorage
- var url = "https://example.com/";
- var storage = SpecialPowers.createChromeCache("content", url);
+ // attach to our origin's CacheStorage.
+ var storage = SpecialPowers.createChromeCache("content", window.location.origin);
- // verify we can use the other origin's CacheStorage as normal
- var req = new Request("https://example.com/index.html");
+ // verify we can our origin's CacheStorage as normal
+ var req = new Request(`${window.location.origin}/index.html`);
var res = new Response("hello world");
var cache;
storage.open("foo").then(function(c) {
diff -Nru thunderbird-140.14.0esr/dom/clients/manager/ClientManagerParent.cpp thunderbird-140.15.0esr/dom/clients/manager/ClientManagerParent.cpp
--- thunderbird-140.14.0esr/dom/clients/manager/ClientManagerParent.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/clients/manager/ClientManagerParent.cpp 2026-08-28 17:33:05.000000000 +0000
@@ -12,6 +12,7 @@
#include "ClientManagerService.h"
#include "ClientSourceParent.h"
#include "ClientValidation.h"
+#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/PClientNavigateOpParent.h"
#include "mozilla/Unused.h"
@@ -75,14 +76,10 @@
already_AddRefed
ClientManagerParent::AllocPClientSourceParent(
const ClientSourceConstructorArgs& aArgs) {
- Maybe contentParentId;
+ RefPtr contentParentHandle =
+ ::mozilla::ipc::BackgroundParent::GetContentParentHandle(Manager());
- uint64_t childID = ::mozilla::ipc::BackgroundParent::GetChildID(Manager());
- if (childID) {
- contentParentId = Some(ContentParentId(childID));
- }
-
- return MakeAndAddRef(aArgs, contentParentId);
+ return MakeAndAddRef(aArgs, contentParentHandle);
}
IPCResult ClientManagerParent::RecvPClientSourceConstructor(
diff -Nru thunderbird-140.14.0esr/dom/clients/manager/ClientManagerService.cpp thunderbird-140.15.0esr/dom/clients/manager/ClientManagerService.cpp
--- thunderbird-140.14.0esr/dom/clients/manager/ClientManagerService.cpp 2026-08-18 02:52:32.000000000 +0000
+++ thunderbird-140.15.0esr/dom/clients/manager/ClientManagerService.cpp 2026-08-28 17:33:05.000000000 +0000
@@ -716,7 +716,7 @@
}
bool ClientManagerService::HasWindow(
- const Maybe& aContentParentId,
+ ThreadsafeContentParentHandle* aContentParentHandle,
const PrincipalInfo& aPrincipalInfo, const nsID& aClientId) {
AssertIsOnBackgroundThread();
@@ -733,7 +733,7 @@
return false;
}
- if (aContentParentId && !source->IsOwnedByProcess(aContentParentId.value())) {
+ if (!source->IsOwnedByProcess(aContentParentHandle)) {
return false;
}
diff -Nru thunderbird-140.14.0esr/dom/clients/manager/ClientManagerService.h thunderbird-140.15.0esr/dom/clients/manager/ClientManagerService.h
--- thunderbird-140.14.0esr/dom/clients/manager/ClientManagerService.h 2026-08-18 02:52:32.000000000 +0000
+++ thunderbird-140.15.0esr/dom/clients/manager/ClientManagerService.h 2026-08-28 17:33:05.000000000 +0000
@@ -10,7 +10,6 @@
#include "ClientOpPromise.h"
#include "mozilla/AlreadyAddRefed.h"
#include "mozilla/Assertions.h"
-#include "mozilla/Maybe.h"
#include "mozilla/MozPromise.h"
#include "mozilla/RefPtr.h"
#include "mozilla/Variant.h"
@@ -153,7 +152,7 @@
ThreadsafeContentParentHandle* aOriginContent,
const ClientOpenWindowArgs& aArgs);
- bool HasWindow(const Maybe& aContentParentId,
+ bool HasWindow(ThreadsafeContentParentHandle* aContentParentHandle,
const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
const nsID& aClientId);
diff -Nru thunderbird-140.14.0esr/dom/clients/manager/ClientNavigateOpChild.cpp thunderbird-140.15.0esr/dom/clients/manager/ClientNavigateOpChild.cpp
--- thunderbird-140.14.0esr/dom/clients/manager/ClientNavigateOpChild.cpp 2026-08-18 02:52:32.000000000 +0000
+++ thunderbird-140.15.0esr/dom/clients/manager/ClientNavigateOpChild.cpp 2026-08-28 17:33:05.000000000 +0000
@@ -240,6 +240,16 @@
nsCOMPtr principal = doc->NodePrincipal();
+ rv = nsContentUtils::GetSecurityManager()->CheckLoadURIWithPrincipal(
+ principal, url, nsIScriptSecurityManager::STANDARD, doc->InnerWindowID());
+ if (NS_FAILED(rv)) {
+ nsPrintfCString err("Navigation to \"%s\" is not allowed",
+ aArgs.url().get());
+ CopyableErrorResult result;
+ result.ThrowTypeError(err);
+ return ClientOpPromise::CreateAndReject(result, __func__);
+ }
+
nsCOMPtr docShell = window->GetDocShell();
nsCOMPtr webProgress = do_GetInterface(docShell);
if (!docShell || !webProgress) {
diff -Nru thunderbird-140.14.0esr/dom/clients/manager/ClientSource.cpp thunderbird-140.15.0esr/dom/clients/manager/ClientSource.cpp
--- thunderbird-140.14.0esr/dom/clients/manager/ClientSource.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/clients/manager/ClientSource.cpp 2026-08-28 17:33:06.000000000 +0000
@@ -15,6 +15,7 @@
#include "mozilla/Try.h"
#include "mozilla/dom/BlobURLProtocolHandler.h"
#include "mozilla/dom/ClientIPCTypes.h"
+#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/DOMMozPromiseRequestHolder.h"
#include "mozilla/dom/ipc/StructuredCloneData.h"
#include "mozilla/dom/JSExecutionManager.h"
@@ -183,7 +184,8 @@
// This can happen since we use MozURL for validation which does not handle
// some of the more obscure internal principal/url combinations. Normal
// content pages will pass this check.
- if (NS_WARN_IF(!ClientIsValidPrincipalInfo(mClientInfo.PrincipalInfo()))) {
+ if (NS_WARN_IF(!ClientIsValidPrincipalInfo(mClientInfo.PrincipalInfo(),
+ CurrentRemoteType()))) {
Shutdown();
return;
}
diff -Nru thunderbird-140.14.0esr/dom/clients/manager/ClientSourceParent.cpp thunderbird-140.15.0esr/dom/clients/manager/ClientSourceParent.cpp
--- thunderbird-140.14.0esr/dom/clients/manager/ClientSourceParent.cpp 2026-08-18 02:52:32.000000000 +0000
+++ thunderbird-140.15.0esr/dom/clients/manager/ClientSourceParent.cpp 2026-08-28 17:33:05.000000000 +0000
@@ -147,11 +147,11 @@
ClientSourceParent::ClientSourceParent(
const ClientSourceConstructorArgs& aArgs,
- const Maybe& aContentParentId)
+ ThreadsafeContentParentHandle* aContentParentHandle)
: mClientInfo(aArgs.id(), aArgs.agentClusterId(), aArgs.type(),
aArgs.principalInfo(), aArgs.creationTime(), aArgs.url(),
aArgs.frameType()),
- mContentParentId(aContentParentId),
+ mContentParentHandle(aContentParentHandle),
mService(ClientManagerService::GetOrCreateInstance()),
mExecutionReady(false),
mFrozen(false) {}
@@ -166,7 +166,10 @@
// Ensure the principal is reasonable before adding ourself to the service.
// Since we validate the principal on the child side as well, any failure
// here is treated as fatal.
- if (NS_WARN_IF(!ClientIsValidPrincipalInfo(mClientInfo.PrincipalInfo()))) {
+ if (NS_WARN_IF(!ClientIsValidPrincipalInfo(
+ mClientInfo.PrincipalInfo(),
+ mContentParentHandle ? mContentParentHandle->GetRemoteType()
+ : NOT_REMOTE_TYPE))) {
mService->ForgetFutureSource(mClientInfo.ToIPC());
return IPC_FAIL(Manager(), "Invalid PrincipalInfo!");
}
diff -Nru thunderbird-140.14.0esr/dom/clients/manager/ClientSourceParent.h thunderbird-140.15.0esr/dom/clients/manager/ClientSourceParent.h
--- thunderbird-140.14.0esr/dom/clients/manager/ClientSourceParent.h 2026-08-18 02:52:32.000000000 +0000
+++ thunderbird-140.15.0esr/dom/clients/manager/ClientSourceParent.h 2026-08-28 17:33:05.000000000 +0000
@@ -17,11 +17,12 @@
class ClientHandleParent;
class ClientManagerService;
+class ThreadsafeContentParentHandle;
class ClientSourceParent final : public PClientSourceParent {
ClientInfo mClientInfo;
Maybe mController;
- const Maybe mContentParentId;
+ const RefPtr mContentParentHandle;
RefPtr mService;
nsTArray mHandleList;
MozPromiseHolder mExecutionReadyPromise;
@@ -57,8 +58,9 @@
public:
NS_INLINE_DECL_REFCOUNTING(ClientSourceParent, override)
- explicit ClientSourceParent(const ClientSourceConstructorArgs& aArgs,
- const Maybe& aContentParentId);
+ explicit ClientSourceParent(
+ const ClientSourceConstructorArgs& aArgs,
+ ThreadsafeContentParentHandle* aContentParentHandle);
mozilla::ipc::IPCResult Init();
@@ -74,8 +76,9 @@
void ClearController();
- bool IsOwnedByProcess(ContentParentId aContentParentId) const {
- return mContentParentId && mContentParentId.value() == aContentParentId;
+ bool IsOwnedByProcess(
+ ThreadsafeContentParentHandle* aContentParentHandle) const {
+ return mContentParentHandle == aContentParentHandle;
}
void AttachHandle(ClientHandleParent* aClientSource);
diff -Nru thunderbird-140.14.0esr/dom/clients/manager/ClientValidation.cpp thunderbird-140.15.0esr/dom/clients/manager/ClientValidation.cpp
--- thunderbird-140.14.0esr/dom/clients/manager/ClientValidation.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/clients/manager/ClientValidation.cpp 2026-08-28 17:33:06.000000000 +0000
@@ -6,6 +6,7 @@
#include "ClientValidation.h"
+#include "mozilla/dom/ProcessIsolation.h"
#include "mozilla/ipc/PBackgroundSharedTypes.h"
#include "mozilla/StaticPrefs_security.h"
#include "mozilla/net/MozURL.h"
@@ -16,11 +17,22 @@
using mozilla::ipc::PrincipalInfo;
using mozilla::net::MozURL;
-bool ClientIsValidPrincipalInfo(const PrincipalInfo& aPrincipalInfo) {
- // Ideally we would verify that the source process has permission to
- // create a window or worker with the given principal, but we don't
- // currently have any such restriction in place. Instead, at least
- // verify the PrincipalInfo is an expected type and has a parsable
+bool ClientIsValidPrincipalInfo(const PrincipalInfo& aPrincipalInfo,
+ const nsACString& aRemoteType) {
+ auto result = mozilla::ipc::PrincipalInfoToPrincipal(aPrincipalInfo);
+ if (NS_WARN_IF(result.isErr())) {
+ return false;
+ }
+
+ // FIXME: Remove the system allowance once for non-inference processes once we
+ // can load documents with the system principal into content.
+ if (NS_WARN_IF(!ValidatePrincipalCouldPotentiallyBeLoadedBy(
+ result.inspect(), aRemoteType,
+ {ValidatePrincipalOptions::AllowSystem}))) {
+ return false;
+ }
+
+ // Verify the PrincipalInfo is an expected type and has a parsable
// origin/spec.
switch (aPrincipalInfo.type()) {
// Any system and null principal is acceptable.
diff -Nru thunderbird-140.14.0esr/dom/clients/manager/ClientValidation.h thunderbird-140.15.0esr/dom/clients/manager/ClientValidation.h
--- thunderbird-140.14.0esr/dom/clients/manager/ClientValidation.h 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/clients/manager/ClientValidation.h 2026-08-28 17:33:06.000000000 +0000
@@ -17,7 +17,8 @@
namespace dom {
bool ClientIsValidPrincipalInfo(
- const mozilla::ipc::PrincipalInfo& aPrincipalInfo);
+ const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
+ const nsACString& aRemoteType);
bool ClientIsValidCreationURL(const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
const nsACString& aURL);
diff -Nru thunderbird-140.14.0esr/dom/events/EventStateManager.cpp thunderbird-140.15.0esr/dom/events/EventStateManager.cpp
--- thunderbird-140.14.0esr/dom/events/EventStateManager.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/events/EventStateManager.cpp 2026-08-28 17:33:06.000000000 +0000
@@ -2909,6 +2909,8 @@
nsIContent* editingElement = aSelectionTarget->IsEditable()
? aSelectionTarget->GetEditingHost()
: nullptr;
+ nsCOMPtr principal;
+ bool fromChildProcess = false;
// In chrome, only allow dragging inside editable areas.
bool isChromeContext = !aWindow->GetBrowsingContext()->IsContent();
@@ -2916,8 +2918,9 @@
if (mGestureDownDragStartData) {
// A child process started a drag so use any data it assigned for the dnd
// session.
- mGestureDownDragStartData->AddInitialDnDDataTo(aDataTransfer, aPrincipal,
- aCsp, aCookieJarSettings);
+ mGestureDownDragStartData->AddInitialDnDDataTo(
+ aDataTransfer, getter_AddRefs(principal), aCsp, aCookieJarSettings);
+ fromChildProcess = true;
mGestureDownDragStartData.forget(aRemoteDragStartData);
*aAllowEmptyDataTransfer = true;
}
@@ -2994,6 +2997,10 @@
if (dragContent != originalDragContent) aDataTransfer->ClearAll();
*aTargetNode = dragContent;
NS_ADDREF(*aTargetNode);
+ if (!fromChildProcess) {
+ principal = dragContent->NodePrincipal();
+ }
+ principal.forget(aPrincipal);
}
}
diff -Nru thunderbird-140.14.0esr/dom/filesystem/FileSystemSecurity.cpp thunderbird-140.15.0esr/dom/filesystem/FileSystemSecurity.cpp
--- thunderbird-140.14.0esr/dom/filesystem/FileSystemSecurity.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/filesystem/FileSystemSecurity.cpp 2026-08-28 17:33:06.000000000 +0000
@@ -112,6 +112,11 @@
MOZ_ASSERT(NS_IsMainThread());
mozilla::ipc::AssertIsInMainProcess();
+ // POSIX APIs accept all other characters than NUL
+ if (aPath.FindChar(char16_t(0)) != kNotFound) {
+ return false;
+ }
+
#if defined(XP_WIN)
if (StringBeginsWith(aPath, u"..\\"_ns) ||
FindInReadable(u"\\..\\"_ns, aPath) ||
diff -Nru thunderbird-140.14.0esr/dom/fs/child/FileSystemBackgroundRequestHandler.cpp thunderbird-140.15.0esr/dom/fs/child/FileSystemBackgroundRequestHandler.cpp
--- thunderbird-140.14.0esr/dom/fs/child/FileSystemBackgroundRequestHandler.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/fs/child/FileSystemBackgroundRequestHandler.cpp 2026-08-28 17:33:06.000000000 +0000
@@ -7,6 +7,7 @@
#include "FileSystemBackgroundRequestHandler.h"
#include "fs/FileSystemChildFactory.h"
+#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/FileSystemManagerChild.h"
#include "mozilla/dom/PFileSystemManager.h"
#include "mozilla/ipc/BackgroundChild.h"
@@ -78,6 +79,18 @@
using mozilla::ipc::Endpoint;
using mozilla::ipc::PBackgroundChild;
+ // Throw if this process wouldn't be allowed to access storage.
+ EnumSet options;
+ if (CurrentRemoteType() == INFERENCE_REMOTE_TYPE) {
+ options += ValidatePrincipalOptions::AllowSystem;
+ }
+ if (!BackgroundChild::ValidatePrincipalInfo(aPrincipalInfo, options)) {
+ MOZ_ASSERT_UNREACHABLE(
+ "ValidatePrincipalInfo failure in CreateFileSystemManagerChild");
+ return FileSystemManagerChild::ActorPromise::CreateAndReject(
+ NS_ERROR_FAILURE, __func__);
+ }
+
if (!mCreatingFileSystemManagerChild) {
PBackgroundChild* backgroundChild =
BackgroundChild::GetOrCreateForCurrentThread();
diff -Nru thunderbird-140.14.0esr/dom/gamepad/linux/LinuxGamepad.cpp thunderbird-140.15.0esr/dom/gamepad/linux/LinuxGamepad.cpp
--- thunderbird-140.14.0esr/dom/gamepad/linux/LinuxGamepad.cpp 2026-08-18 02:52:32.000000000 +0000
+++ thunderbird-140.15.0esr/dom/gamepad/linux/LinuxGamepad.cpp 2026-08-28 17:33:05.000000000 +0000
@@ -62,11 +62,18 @@
guint source_id = UINT_MAX;
char idstring[256] = {0};
char devpath[PATH_MAX] = {0};
- uint8_t key_map[KEY_MAX] = {0};
- uint8_t abs_map[ABS_MAX] = {0};
+ uint8_t key_map[KEY_CNT] = {0};
+ uint8_t abs_map[ABS_CNT] = {0};
std::unordered_map abs_info;
};
+// evdev admits key/abs codes up to KEY_MAX/ABS_MAX inclusive, so the maps must
+// have KEY_CNT/ABS_CNT (== *_MAX + 1) entries to index every valid code.
+static_assert(sizeof(Gamepad::key_map) > KEY_MAX,
+ "key_map must hold every valid EV_KEY code (0..KEY_MAX)");
+static_assert(sizeof(Gamepad::abs_map) > ABS_MAX,
+ "abs_map must hold every valid EV_ABS code (0..ABS_MAX)");
+
static inline bool LoadAbsInfo(int fd, Gamepad* gamepad, uint16_t code) {
input_absinfo info{0};
if (ioctl(fd, EVIOCGABS(code), &info) < 0) {
@@ -211,7 +218,7 @@
}
// Now, go through the non-semantic buttons and handle them as extras
- for (uint16_t key = 0; key < KEY_MAX; key++) {
+ for (uint16_t key = 0; key < KEY_CNT; key++) {
// Skip standard buttons
if (gamepad->isStandardGamepad &&
std::find(kStandardButtons.begin(), kStandardButtons.end(), key) !=
@@ -237,7 +244,7 @@
LoadAbsInfo(fd, gamepad.get(), ABS_HAT0Y);
}
- for (uint16_t i = 0; i < ABS_MAX; ++i) {
+ for (uint16_t i = 0; i < ABS_CNT; ++i) {
if (gamepad->isStandardGamepad &&
(std::find(kStandardAxes.begin(), kStandardAxes.end(), i) !=
kStandardAxes.end() ||
@@ -440,6 +447,11 @@
switch (event.type) {
case EV_KEY:
+ // event.code comes from the device and is untrusted; bound it before
+ // indexing key_map.
+ if (event.code >= KEY_CNT) {
+ continue;
+ }
if (gamepad->isStandardGamepad) {
service->NewButtonEvent(gamepad->handle, gamepad->key_map[event.code],
!!event.value);
diff -Nru thunderbird-140.14.0esr/dom/html/HTMLMediaElement.cpp thunderbird-140.15.0esr/dom/html/HTMLMediaElement.cpp
--- thunderbird-140.14.0esr/dom/html/HTMLMediaElement.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/html/HTMLMediaElement.cpp 2026-08-28 17:33:05.000000000 +0000
@@ -2475,6 +2475,8 @@
RemoveMediaElementFromURITable();
mLoadingSrcTriggeringPrincipal = nullptr;
+ // The CORS mode is scoped to the current load.
+ mCORSMode = CORS_NONE;
DDLOG(DDLogCategory::Property, "loading_src", "");
DDUNLINKCHILD(mMediaSource.get());
mMediaSource = nullptr;
@@ -2775,6 +2777,9 @@
// If we have a 'src' attribute, use that exclusively.
nsAutoString src;
if (mSrcAttrStream) {
+ // Media provider objects use local mode, so a previous URL load's CORS
+ // mode does not apply.
+ mCORSMode = CORS_NONE;
SetupSrcMediaStreamPlayback(mSrcAttrStream);
} else if (GetAttr(nsGkAtoms::src, src)) {
nsCOMPtr uri;
@@ -5453,6 +5458,7 @@
void HTMLMediaElement::SetupSrcMediaStreamPlayback(DOMMediaStream* aStream) {
NS_ASSERTION(!mSrcStream, "Should have been ended already");
+ MOZ_ASSERT(mCORSMode == CORS_NONE);
mLoadingSrc = nullptr;
mSrcStream = aStream;
diff -Nru thunderbird-140.14.0esr/dom/indexedDB/ActorsParent.cpp thunderbird-140.15.0esr/dom/indexedDB/ActorsParent.cpp
--- thunderbird-140.14.0esr/dom/indexedDB/ActorsParent.cpp 2026-08-18 02:52:32.000000000 +0000
+++ thunderbird-140.15.0esr/dom/indexedDB/ActorsParent.cpp 2026-08-28 17:33:05.000000000 +0000
@@ -9088,17 +9088,22 @@
MOZ_ASSERT(principalInfo.type() == PrincipalInfo::TSystemPrincipalInfo ||
principalInfo.type() == PrincipalInfo::TContentPrincipalInfo);
- if (NS_AUUF_OR_WARN_IF(
- principalInfo.type() == PrincipalInfo::TSystemPrincipalInfo &&
- metadata.persistenceType() != PERSISTENCE_TYPE_PERSISTENT)) {
+ if (!BackgroundParent::ValidatePrincipalInfo(Manager(), principalInfo,
+ PrincipalValidationOptions())) {
+ IPC_FAIL(this, "Invalid principal!");
return nullptr;
}
- if (NS_AUUF_OR_WARN_IF(
- principalInfo.type() == PrincipalInfo::TContentPrincipalInfo &&
- QuotaManager::IsOriginInternal(
- principalInfo.get_ContentPrincipalInfo().originNoSuffix()) &&
- metadata.persistenceType() != PERSISTENCE_TYPE_PERSISTENT)) {
+ /* GetPersistenceType returns PERSISTENT for system principals and internal
+ content principals, PRIVATE for private-browsing content principals, and
+ DEFAULT for everything else. The sent value is technically redundant and
+ always deducible from the principal but we validate it here so that an
+ incorrect metadata value cannot reach other parts of the code.
+ TODO: Stop sending persistenceType from the content process and just derive it
+ on the parent side. */
+ if (metadata.persistenceType() !=
+ IDBFactory::GetPersistenceType(principalInfo)) {
+ IPC_FAIL(this, "Persistence type does not match principal!");
return nullptr;
}
@@ -9170,6 +9175,10 @@
MOZ_ASSERT(aPrincipalInfo.type() == PrincipalInfo::TSystemPrincipalInfo ||
aPrincipalInfo.type() == PrincipalInfo::TContentPrincipalInfo);
+ QM_TRY(MOZ_TO_RESULT(BackgroundParent::ValidatePrincipalInfo(
+ Manager(), aPrincipalInfo, PrincipalValidationOptions())),
+ QM_IPC_FAIL(this));
+
PersistenceType persistenceType =
IDBFactory::GetPersistenceType(aPrincipalInfo);
diff -Nru thunderbird-140.14.0esr/dom/indexedDB/IDBFactory.cpp thunderbird-140.15.0esr/dom/indexedDB/IDBFactory.cpp
--- thunderbird-140.14.0esr/dom/indexedDB/IDBFactory.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/indexedDB/IDBFactory.cpp 2026-08-28 17:33:06.000000000 +0000
@@ -7,7 +7,9 @@
#include "IDBFactory.h"
#include "BackgroundChildImpl.h"
+#include "ErrorList.h"
#include "IDBRequest.h"
+#include "IndexedDBCommon.h"
#include "IndexedDatabaseManager.h"
#include "mozilla/BasePrincipal.h"
#include "mozilla/ErrorResult.h"
@@ -468,6 +470,13 @@
return promise.forget();
}
+ // If this request would fail in the parent process, fail early in content.
+ if (!BackgroundChild::ValidatePrincipalInfo(
+ *mPrincipalInfo, indexedDB::PrincipalValidationOptions())) {
+ promise->MaybeRejectWithSecurityError(kAccessError);
+ return promise.forget();
+ }
+
PersistenceType persistenceType = GetPersistenceType(*mPrincipalInfo);
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()), [&promise](const nsresult rv) {
@@ -729,6 +738,13 @@
principalInfo = *mPrincipalInfo;
}
+ // If this request would fail in the parent process, fail early in content.
+ if (!BackgroundChild::ValidatePrincipalInfo(
+ principalInfo, indexedDB::PrincipalValidationOptions())) {
+ aRv.ThrowSecurityError(kAccessError);
+ return nullptr;
+ }
+
uint64_t version = 0;
if (!aDeleting && aVersion.WasPassed()) {
if (aVersion.Value() < 1) {
diff -Nru thunderbird-140.14.0esr/dom/indexedDB/IndexedDBCommon.cpp thunderbird-140.15.0esr/dom/indexedDB/IndexedDBCommon.cpp
--- thunderbird-140.14.0esr/dom/indexedDB/IndexedDBCommon.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/indexedDB/IndexedDBCommon.cpp 2026-08-28 17:33:06.000000000 +0000
@@ -8,9 +8,19 @@
#include "js/StructuredClone.h"
#include "mozilla/SnappyUncompressInputStream.h"
+#include "mozilla/StaticPrefs_dom.h"
namespace mozilla::dom::indexedDB {
+EnumSet PrincipalValidationOptions() {
+ EnumSet options;
+ if (StaticPrefs::dom_indexedDB_testing_allowContentSystem() &&
+ xpc::IsInAutomation()) {
+ options += ValidatePrincipalOptions::AllowSystem;
+ }
+ return options;
+}
+
// aStructuredCloneData is a parameter rather than a return value because one
// caller preallocates it on the heap not immediately before calling for some
// reason. Maybe this could be changed.
diff -Nru thunderbird-140.14.0esr/dom/indexedDB/IndexedDBCommon.h thunderbird-140.15.0esr/dom/indexedDB/IndexedDBCommon.h
--- thunderbird-140.14.0esr/dom/indexedDB/IndexedDBCommon.h 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/indexedDB/IndexedDBCommon.h 2026-08-28 17:33:06.000000000 +0000
@@ -7,6 +7,7 @@
#ifndef mozilla_dom_indexeddb_IndexedDBCommon_h
#define mozilla_dom_indexeddb_IndexedDBCommon_h
+#include "mozilla/dom/ProcessIsolation.h"
#include "mozilla/dom/quota/QuotaCommon.h"
class JSStructuredCloneData;
@@ -16,6 +17,8 @@
static constexpr uint32_t kFileCopyBufferSize = 32768;
+EnumSet PrincipalValidationOptions();
+
nsresult SnappyUncompressStructuredCloneData(
nsIInputStream& aInputStream, JSStructuredCloneData& aStructuredCloneData);
diff -Nru thunderbird-140.14.0esr/dom/indexedDB/test/test_message_manager_ipc.html thunderbird-140.15.0esr/dom/indexedDB/test/test_message_manager_ipc.html
--- thunderbird-140.14.0esr/dom/indexedDB/test/test_message_manager_ipc.html 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/indexedDB/test/test_message_manager_ipc.html 2026-08-28 17:33:06.000000000 +0000
@@ -312,6 +312,10 @@
}
add_task(async function() {
+ await SpecialPowers.pushPrefEnv({
+ set: [["dom.indexedDB.testing.allowContentSystem", true]],
+ });
+
let chromeScript = SpecialPowers.loadChromeScript(chromeScriptFunc);
await chromeScript.promiseOneMessage("done");
await chromeScript.destroy();
diff -Nru thunderbird-140.14.0esr/dom/indexedDB/test/unit/xpcshell-head-child-process.js thunderbird-140.15.0esr/dom/indexedDB/test/unit/xpcshell-head-child-process.js
--- thunderbird-140.14.0esr/dom/indexedDB/test/unit/xpcshell-head-child-process.js 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/indexedDB/test/unit/xpcshell-head-child-process.js 2026-08-28 17:33:06.000000000 +0000
@@ -6,6 +6,8 @@
function run_test() {
const INDEXEDDB_HEAD_FILE = "xpcshell-head-parent-process.js";
const INDEXEDDB_PREF_EXPERIMENTAL = "dom.indexedDB.experimental";
+ const INDEXEDDB_PREF_TESTING_ALLOW_CONTENT_SYSTEM =
+ "dom.indexedDB.testing.allowContentSystem";
// IndexedDB needs a profile.
do_get_profile();
@@ -18,6 +20,7 @@
_HEAD_FILES.push(do_get_file(INDEXEDDB_HEAD_FILE).path.replace(/\\/g, "/"));
Services.prefs.setBoolPref(INDEXEDDB_PREF_EXPERIMENTAL, true);
+ Services.prefs.setBoolPref(INDEXEDDB_PREF_TESTING_ALLOW_CONTENT_SYSTEM, true);
run_test_in_child(thisTest);
}
diff -Nru thunderbird-140.14.0esr/dom/indexedDB/test/unit/xpcshell-parent-process.toml thunderbird-140.15.0esr/dom/indexedDB/test/unit/xpcshell-parent-process.toml
--- thunderbird-140.14.0esr/dom/indexedDB/test/unit/xpcshell-parent-process.toml 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/indexedDB/test/unit/xpcshell-parent-process.toml 2026-08-28 17:33:05.000000000 +0000
@@ -64,6 +64,7 @@
["test_file_copy_failure.js"]
["test_globalObjects_ipc.js"]
+prefs = ["dom.indexedDB.testing.allowContentSystem=true"]
["test_idbSubdirUpgrade.js"]
diff -Nru thunderbird-140.14.0esr/dom/ipc/BrowserParent.cpp thunderbird-140.15.0esr/dom/ipc/BrowserParent.cpp
--- thunderbird-140.14.0esr/dom/ipc/BrowserParent.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/ipc/BrowserParent.cpp 2026-08-28 17:33:05.000000000 +0000
@@ -64,6 +64,7 @@
#include "mozilla/TouchEvents.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/Unused.h"
+#include "nsBaseDragService.h"
#include "nsCOMPtr.h"
#include "nsContentPermissionHelper.h"
#include "nsContentUtils.h"
@@ -120,6 +121,7 @@
#include "nsPIWindowRoot.h"
#include "nsReadableUtils.h"
#include "nsIAuthPrompt2.h"
+#include "nsIScriptSecurityManager.h"
#include "gfxDrawable.h"
#include "ImageOps.h"
#include "UnitTransforms.h"
@@ -930,17 +932,18 @@
// not been modified then it's safe to load those links using the
// SystemPrincipal. If they have been modified by web content, then
// we use a NullPrincipal which still allows to load web links.
- bool loadUsingSystemPrincipal = true;
- if (aLinks.Length() != mVerifyDropLinks.Length()) {
- loadUsingSystemPrincipal = false;
- }
- for (uint32_t i = 0; i < aLinks.Length(); i++) {
- if (loadUsingSystemPrincipal) {
+ const bool loadUsingSystemPrincipal = [&]() {
+ if (aLinks.Length() != mVerifyDropLinks.Length()) {
+ return false;
+ }
+ for (uint32_t i = 0; i < aLinks.Length(); i++) {
if (!aLinks[i].Equals(mVerifyDropLinks[i])) {
- loadUsingSystemPrincipal = false;
+ return false;
}
}
- }
+ return true;
+ }();
+
mVerifyDropLinks.Clear();
nsCOMPtr triggeringPrincipal;
if (loadUsingSystemPrincipal) {
@@ -1615,6 +1618,27 @@
return false;
}
+ nsCOMPtr triggeringPrincipal;
+ dragSession->GetTriggeringPrincipal(getter_AddRefs(triggeringPrincipal));
+
+ nsIScriptSecurityManager* secMan = nullptr;
+ if (triggeringPrincipal) {
+ if (!(secMan = nsContentUtils::GetSecurityManager())) {
+ NS_WARNING("No ScriptSecurityManager for links verification");
+ return false;
+ }
+ } else {
+ RefPtr sourceWC = dragSession->GetSourceWindowContext();
+ RefPtr sourceTopWC =
+ dragSession->GetSourceTopWindowContext();
+ if (sourceWC || sourceTopWC) {
+ NS_WARNING(
+ "How can we have a source window context while no triggering "
+ "principal?");
+ return false;
+ }
+ }
+
// No more than one drop event can happen simultaneously; reset the link
// verification array and store all links that are being dragged.
mVerifyDropLinks.Clear();
@@ -1633,6 +1657,22 @@
NS_WARNING("Failed to query url for verification");
break;
}
+
+ if (triggeringPrincipal) {
+ MOZ_ASSERT(secMan);
+ if (NS_FAILED(secMan->CheckLoadURIStrWithPrincipal(
+ triggeringPrincipal, NS_ConvertUTF16toUTF8(tmp),
+ nsIScriptSecurityManager::STANDARD |
+ nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL))) {
+ MOZ_DRAGSERVICE_LOG("[%p] %s | dragSession: %p | Bad URI %s from %p",
+ this, __FUNCTION__, dragSession.get(),
+ NS_ConvertUTF16toUTF8(tmp).get(),
+ triggeringPrincipal.get());
+ mVerifyDropLinks.Clear();
+ return true;
+ }
+ }
+
mVerifyDropLinks.AppendElement(tmp);
rv = item->GetName(tmp);
@@ -3904,8 +3944,7 @@
return IPC_OK();
}
- if (!Manager()->ValidatePrincipal(aPrincipal,
- {ValidatePrincipalOptions::AllowNullPtr})) {
+ if (!Manager()->ValidatePrincipal(aPrincipal, {})) {
return ContentParent::PrincipalValidationIpcFail(aPrincipal, this,
__func__);
}
diff -Nru thunderbird-140.14.0esr/dom/ipc/ContentChild.cpp thunderbird-140.15.0esr/dom/ipc/ContentChild.cpp
--- thunderbird-140.14.0esr/dom/ipc/ContentChild.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/ipc/ContentChild.cpp 2026-08-28 17:33:05.000000000 +0000
@@ -23,6 +23,7 @@
#include "imgLoader.h"
#include "ScrollingMetrics.h"
#include "mozilla/BasePrincipal.h"
+#include "mozilla/ClearOnShutdown.h"
#include "mozilla/ClipboardContentAnalysisChild.h"
#include "mozilla/ClipboardReadRequestChild.h"
#include "mozilla/Components.h"
@@ -43,6 +44,7 @@
#include "mozilla/dom/SharedScriptCache.h"
#include "mozilla/SimpleEnumerator.h"
#include "mozilla/SpinEventLoopUntil.h"
+#include "mozilla/StaticMutex.h"
#include "mozilla/StaticPrefs_browser.h"
#include "mozilla/StaticPrefs_dom.h"
#include "mozilla/StaticPrefs_fission.h"
@@ -2501,6 +2503,22 @@
return IPC_OK();
}
+static StaticMutex sCurrentRemoteTypeMutex;
+static StaticAutoPtr sCurrentRemoteType
+ MOZ_GUARDED_BY(sCurrentRemoteTypeMutex);
+
+nsCString CurrentRemoteType() {
+ if (XRE_IsContentProcess()) {
+ StaticMutexAutoLock lock(sCurrentRemoteTypeMutex);
+ if (sCurrentRemoteType) {
+ return *sCurrentRemoteType;
+ }
+ return PREALLOC_REMOTE_TYPE;
+ }
+
+ return NOT_REMOTE_TYPE;
+}
+
mozilla::ipc::IPCResult ContentChild::RecvRemoteType(
const nsCString& aRemoteType, const nsCString& aProfile) {
if (aRemoteType == mRemoteType) {
@@ -2536,6 +2554,18 @@
// Must do before SetProcessName
mRemoteType.Assign(aRemoteType);
+ {
+ StaticMutexAutoLock lock(sCurrentRemoteTypeMutex);
+ if (!sCurrentRemoteType) {
+ sCurrentRemoteType = new nsCString();
+ RunOnShutdown([] {
+ StaticMutexAutoLock lock(sCurrentRemoteTypeMutex);
+ sCurrentRemoteType = nullptr;
+ });
+ }
+ sCurrentRemoteType->Assign(mRemoteType);
+ }
+
// Update the process name so about:memory's process names are more obvious.
if (aRemoteType == FILE_REMOTE_TYPE) {
SetProcessName("file:// Content"_ns, nullptr, &aProfile);
diff -Nru thunderbird-140.14.0esr/dom/ipc/ContentChild.h thunderbird-140.15.0esr/dom/ipc/ContentChild.h
--- thunderbird-140.14.0esr/dom/ipc/ContentChild.h 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/ipc/ContentChild.h 2026-08-28 17:33:06.000000000 +0000
@@ -904,6 +904,9 @@
return static_cast(aContentChild);
}
+// Threadsafe getter for the current process's RemoteType.
+nsCString CurrentRemoteType();
+
} // namespace dom
} // namespace mozilla
diff -Nru thunderbird-140.14.0esr/dom/ipc/ContentParent.cpp thunderbird-140.15.0esr/dom/ipc/ContentParent.cpp
--- thunderbird-140.14.0esr/dom/ipc/ContentParent.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/ipc/ContentParent.cpp 2026-08-28 17:33:06.000000000 +0000
@@ -4667,7 +4667,7 @@
}
mozilla::ipc::IPCResult ContentParent::RecvLoadURIExternal(
- nsIURI* uri, nsIPrincipal* aTriggeringPrincipal,
+ NotNull uri, NotNull aTriggeringPrincipal,
nsIPrincipal* aRedirectPrincipal,
const MaybeDiscarded& aContext,
bool aWasExternallyTriggered, bool aHasValidUserGestureActivation,
@@ -4676,16 +4676,23 @@
return IPC_OK();
}
+ if (!ValidatePrincipal(aTriggeringPrincipal)) {
+ LogAndAssertFailedPrincipalValidationInfo(aTriggeringPrincipal, __func__);
+ return IPC_FAIL(this, "aTriggeringPrincipal invalid");
+ }
+
+ if (!ValidatePrincipal(aRedirectPrincipal,
+ {ValidatePrincipalOptions::AllowNullPtr})) {
+ LogAndAssertFailedPrincipalValidationInfo(aRedirectPrincipal, __func__);
+ return IPC_FAIL(this, "aRedirectPrincipal invalid");
+ }
+
nsCOMPtr extProtService(
do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID));
if (!extProtService) {
return IPC_OK();
}
- if (!uri) {
- return IPC_FAIL(this, "uri must not be null.");
- }
-
BrowsingContext* bc = aContext.get();
extProtService->LoadURI(uri, aTriggeringPrincipal, aRedirectPrincipal, bc,
aWasExternallyTriggered,
@@ -7522,7 +7529,7 @@
}
BrowsingContext* bc = aContext.GetMaybeDiscarded();
- if (!bc) {
+ if (!bc || !bc->Canonical()->IsOwnedByProcess(ChildID())) {
return IPC_OK();
}
SessionHistoryEntry* entry = bc->Canonical()->GetActiveSessionHistoryEntry();
@@ -7641,6 +7648,10 @@
return IPC_OK();
}
+ if (!aContext.get_canonical()->IsOwnedByProcess(ChildID())) {
+ return IPC_OK();
+ }
+
Maybe info;
aContext.get_canonical()->GetLoadingSessionHistoryInfoFromParent(info);
aResolver(info);
diff -Nru thunderbird-140.14.0esr/dom/ipc/ContentParent.h thunderbird-140.15.0esr/dom/ipc/ContentParent.h
--- thunderbird-140.14.0esr/dom/ipc/ContentParent.h 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/ipc/ContentParent.h 2026-08-28 17:33:06.000000000 +0000
@@ -1006,7 +1006,7 @@
mozilla::ipc::IPCResult RecvSetURITitle(nsIURI* uri, const nsAString& title);
mozilla::ipc::IPCResult RecvLoadURIExternal(
- nsIURI* uri, nsIPrincipal* triggeringPrincipal,
+ NotNull uri, NotNull triggeringPrincipal,
nsIPrincipal* redirectPrincipal,
const MaybeDiscarded& aContext,
bool aWasExternallyTriggered, bool aHasValidUserGestureActivation,
diff -Nru thunderbird-140.14.0esr/dom/ipc/PContent.ipdl thunderbird-140.15.0esr/dom/ipc/PContent.ipdl
--- thunderbird-140.14.0esr/dom/ipc/PContent.ipdl 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/ipc/PContent.ipdl 2026-08-28 17:33:05.000000000 +0000
@@ -1158,8 +1158,8 @@
async StartVisitedQueries(nullable nsIURI[] uri);
async SetURITitle(nullable nsIURI uri, nsString title);
- async LoadURIExternal(nullable nsIURI uri,
- nullable nsIPrincipal triggeringPrincipal,
+ async LoadURIExternal(nsIURI uri,
+ nsIPrincipal triggeringPrincipal,
nullable nsIPrincipal redirectPrincipal,
MaybeDiscardedBrowsingContext browsingContext,
bool wasExternallyTriggered,
diff -Nru thunderbird-140.14.0esr/dom/ipc/ProcessIsolation.cpp thunderbird-140.15.0esr/dom/ipc/ProcessIsolation.cpp
--- thunderbird-140.14.0esr/dom/ipc/ProcessIsolation.cpp 2026-08-18 02:52:32.000000000 +0000
+++ thunderbird-140.15.0esr/dom/ipc/ProcessIsolation.cpp 2026-08-28 17:33:05.000000000 +0000
@@ -210,9 +210,14 @@
* When handling a navigation, this method will be called twice: first with the
* channel's creation URI, and then it will be called with a result principal's
* URI.
+ *
+ * `aIsWorker` selects process isolation for a remote worker rather than for a
+ * document; see the file:// URI allowlist handling below for why the two
+ * differ.
*/
static IsolationBehavior IsolationBehaviorForURI(nsIURI* aURI, bool aIsSubframe,
- bool aForChannelCreationURI) {
+ bool aForChannelCreationURI,
+ bool aIsWorker) {
MOZ_ASSERT(NS_IsMainThread());
nsAutoCString scheme;
@@ -308,7 +313,8 @@
nsCOMPtr inner;
if (nsCOMPtr nested = do_QueryInterface(aURI);
nested && NS_SUCCEEDED(nested->GetInnerURI(getter_AddRefs(inner)))) {
- return IsolationBehaviorForURI(inner, aIsSubframe, aForChannelCreationURI);
+ return IsolationBehaviorForURI(inner, aIsSubframe, aForChannelCreationURI,
+ aIsWorker);
}
// If we're doing the initial check based on the channel creation URI, stop
@@ -360,12 +366,22 @@
}
}
- nsCOMPtr secMan =
- nsContentUtils::GetSecurityManager();
- bool inFileURIAllowList = false;
- if (NS_SUCCEEDED(secMan->InFileURIAllowlist(aURI, &inFileURIAllowList)) &&
- inFileURIAllowList) {
- return IsolationBehavior::File;
+ // If the domain is allowlisted to allow it to use file:// URIs, then we have
+ // to run it in a file content process, in case it uses file:// sub-resources.
+ //
+ // This only applies to documents. A worker has no sub-resources of its own to
+ // render, and forcing it into the file process would additionally mean
+ // rejecting it outright whenever the requesting process isn't the file
+ // process (see ValidateBehaviorForWorker). Workers were likewise excluded
+ // from this rule back when it lived in E10SUtils; see bug 2064648.
+ if (!aIsWorker) {
+ nsCOMPtr secMan =
+ nsContentUtils::GetSecurityManager();
+ bool inFileURIAllowList = false;
+ if (NS_SUCCEEDED(secMan->InFileURIAllowlist(aURI, &inFileURIAllowList)) &&
+ inFileURIAllowList) {
+ return IsolationBehavior::File;
+ }
}
return IsolationBehavior::WebContent;
@@ -626,7 +642,8 @@
// First, check for any special cases which should be handled using the
// channel creation URI, and handle them.
auto behavior = IsolationBehaviorForURI(aChannelCreationURI, aParentWindow,
- /* aForChannelCreationURI */ true);
+ /* aForChannelCreationURI */ true,
+ /* aIsWorker */ false);
MOZ_LOG(gProcessIsolationLog, LogLevel::Verbose,
("Channel Creation Isolation Behavior: %s",
IsolationBehaviorName(behavior)));
@@ -731,7 +748,8 @@
}
} else if (nsCOMPtr principalURI = resultOrPrecursor->GetURI()) {
behavior = IsolationBehaviorForURI(principalURI, aParentWindow,
- /* aForChannelCreationURI */ false);
+ /* aForChannelCreationURI */ false,
+ /* aIsWorker */ false);
}
}
@@ -1031,7 +1049,8 @@
if (resultOrPrecursor->GetIsContentPrincipal()) {
nsCOMPtr uri = resultOrPrecursor->GetURI();
behavior = IsolationBehaviorForURI(uri, /* aIsSubframe */ false,
- /* aForChannelCreationURI */ false);
+ /* aForChannelCreationURI */ false,
+ /* aIsWorker */ true);
} else if (resultOrPrecursor->IsSystemPrincipal()) {
MOZ_ASSERT(aWorkerKind == WorkerKindShared);
@@ -1303,7 +1322,8 @@
// NOTE: The logic for about URIs is somewhat complex, so we lean on
// IsolationBehaviorForURI to ensure it matches.
switch (IsolationBehaviorForURI(aboutURI, /* aIsSubframe */ false,
- /* aForChannelCreationURI */ true)) {
+ /* aForChannelCreationURI */ true,
+ /* aIsWorker */ false)) {
case IsolationBehavior::Parent:
return false;
case IsolationBehavior::Anywhere:
diff -Nru thunderbird-140.14.0esr/dom/ipc/gtest/ProcessIsolationTest.cpp thunderbird-140.15.0esr/dom/ipc/gtest/ProcessIsolationTest.cpp
--- thunderbird-140.14.0esr/dom/ipc/gtest/ProcessIsolationTest.cpp 2026-08-18 02:52:32.000000000 +0000
+++ thunderbird-140.15.0esr/dom/ipc/gtest/ProcessIsolationTest.cpp 2026-08-28 17:33:05.000000000 +0000
@@ -256,3 +256,74 @@
expectation.Check(false);
}
}
+
+// The file:// URI allowlist is populated from the `capability.policy.*` prefs,
+// which in practice are written by the LocalFileLinks enterprise policy so that
+// an intranet origin may link to files on a network share. Historically that
+// allowlist only made documents load in the file: content process; workers were
+// explicitly excluded (see the `!aIsWorker` guard that used to live in
+// E10SUtils). Since bug 1850589 dropped that exclusion, a service worker on an
+// allowlisted origin resolves to IsolationBehavior::File and is then rejected
+// outright by ValidateBehaviorForWorker, because ServiceWorkerPrivate passes
+// the shared "web" remote type rather than the file remote type.
+TEST(ProcessIsolationTest, FileURIAllowlistedWorkerOptions)
+{
+ MOZ_ALWAYS_SUCCEEDS(Preferences::SetCString("capability.policy.policynames",
+ "localfilelinks_policy"));
+ MOZ_ALWAYS_SUCCEEDS(Preferences::SetCString(
+ "capability.policy.localfilelinks_policy.checkloaduri.enabled",
+ "allAccess"));
+ MOZ_ALWAYS_SUCCEEDS(Preferences::SetCString(
+ "capability.policy.localfilelinks_policy.sites", "https://example.com"));
+ auto cleanup = MakeScopeExit([&] {
+ MOZ_ALWAYS_SUCCEEDS(
+ Preferences::ClearUser("capability.policy.policynames"));
+ MOZ_ALWAYS_SUCCEEDS(Preferences::ClearUser(
+ "capability.policy.localfilelinks_policy.checkloaduri.enabled"));
+ MOZ_ALWAYS_SUCCEEDS(Preferences::ClearUser(
+ "capability.policy.localfilelinks_policy.sites"));
+ });
+
+ nsCOMPtr allowlistedPrincipal =
+ MakeTestPrincipal("https://example.com");
+ nsCOMPtr filePrincipal =
+ MakeTestPrincipal("file:///path/to/dir");
+
+ nsCString fileRemoteType =
+ StaticPrefs::browser_tabs_remote_separateFileUriProcess()
+ ? FILE_REMOTE_TYPE
+ : WEB_REMOTE_TYPE;
+
+ WorkerExpectation expectations[] = {
+ // Being in the file:// URI allowlist must not change worker process
+ // selection: these are the same expectations as for a principal which
+ // isn't allowlisted at all. The current remote type mirrors what
+ // ServiceWorkerPrivate::Initialize() passes for a service worker.
+ {.mPrincipal = allowlistedPrincipal,
+ .mWorkerKind = WorkerKindService,
+ .mExpected =
+ RemoteTypes{ServiceWorkerIsolatedRemoteType(allowlistedPrincipal),
+ WEB_REMOTE_TYPE},
+ .mCurrentRemoteType = WEB_REMOTE_TYPE},
+ {.mPrincipal = allowlistedPrincipal,
+ .mWorkerKind = WorkerKindShared,
+ .mExpected = RemoteTypes{WebIsolatedRemoteType(allowlistedPrincipal),
+ WEB_REMOTE_TYPE},
+ .mCurrentRemoteType = WEB_REMOTE_TYPE},
+
+ // An actual file: principal is still confined to the file process,
+ // regardless of the allowlist.
+ {.mPrincipal = filePrincipal,
+ .mWorkerKind = WorkerKindShared,
+ .mExpected = FileWorkerOutsideFileProcessExpected(fileRemoteType)},
+ {.mPrincipal = filePrincipal,
+ .mWorkerKind = WorkerKindShared,
+ .mExpected = RemoteTypes{fileRemoteType, fileRemoteType},
+ .mCurrentRemoteType = FILE_REMOTE_TYPE},
+ };
+
+ for (auto& expectation : expectations) {
+ expectation.Check(true);
+ expectation.Check(false);
+ }
+}
diff -Nru thunderbird-140.14.0esr/dom/localstorage/ActorsParent.cpp thunderbird-140.15.0esr/dom/localstorage/ActorsParent.cpp
--- thunderbird-140.14.0esr/dom/localstorage/ActorsParent.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/localstorage/ActorsParent.cpp 2026-08-28 17:33:06.000000000 +0000
@@ -68,6 +68,7 @@
#include "mozilla/dom/PBackgroundLSSharedTypes.h"
#include "mozilla/dom/PBackgroundLSSimpleRequestParent.h"
#include "mozilla/dom/PBackgroundLSSnapshotParent.h"
+#include "mozilla/dom/ProcessIsolation.h"
#include "mozilla/dom/SnappyUtils.h"
#include "mozilla/dom/StorageDBUpdater.h"
#include "mozilla/dom/StorageUtils.h"
@@ -1676,7 +1677,7 @@
class PreparedDatastore {
RefPtr mDatastore;
nsCOMPtr mTimer;
- const Maybe mContentParentId;
+ const RefPtr mContentParentHandle;
// Strings share buffers if possible, so it's not a problem to duplicate the
// origin here.
const nsCString mOrigin;
@@ -1686,12 +1687,12 @@
public:
PreparedDatastore(Datastore* aDatastore,
- const Maybe& aContentParentId,
+ ThreadsafeContentParentHandle* aContentParentHandle,
const nsACString& aOrigin, uint64_t aDatastoreId,
bool aForPreload)
: mDatastore(aDatastore),
mTimer(NS_NewTimer()),
- mContentParentId(aContentParentId),
+ mContentParentHandle(aContentParentHandle),
mOrigin(aOrigin),
mDatastoreId(aDatastoreId),
mForPreload(aForPreload),
@@ -1730,8 +1731,8 @@
return *mDatastore;
}
- const Maybe& GetContentParentId() const {
- return mContentParentId;
+ ThreadsafeContentParentHandle* GetContentParentHandle() const {
+ return mContentParentHandle;
}
const nsCString& Origin() const { return mOrigin; }
@@ -1772,7 +1773,7 @@
RefPtr mDatastore;
Snapshot* mSnapshot;
const PrincipalInfo mPrincipalInfo;
- const Maybe mContentParentId;
+ const RefPtr mContentParentHandle;
// Strings share buffers if possible, so it's not a problem to duplicate the
// origin here.
nsCString mOrigin;
@@ -1788,7 +1789,7 @@
public:
// Created in AllocPBackgroundLSDatabaseParent.
Database(const PrincipalInfo& aPrincipalInfo,
- const Maybe& aContentParentId,
+ ThreadsafeContentParentHandle* aContentParentHandle,
const nsACString& aOrigin, uint32_t aPrivateBrowsingId);
void AssertIsOnOwningThread() const {
@@ -1809,8 +1810,8 @@
const PrincipalInfo& GetPrincipalInfo() const { return mPrincipalInfo; }
- const Maybe& ContentParentIdRef() const {
- return mContentParentId;
+ ThreadsafeContentParentHandle* ContentParentHandle() const {
+ return mContentParentHandle;
}
uint32_t PrivateBrowsingId() const { return mPrivateBrowsingId; }
@@ -2088,17 +2089,17 @@
};
class Observer final : public PBackgroundLSObserverParent {
- const Maybe mContentParentId;
+ const RefPtr mContentParentHandle;
nsCString mOrigin;
bool mActorDestroyed;
public:
// Created in AllocPBackgroundLSObserverParent.
- Observer(const Maybe& aContentParentId,
+ Observer(ThreadsafeContentParentHandle* aContentParentHandle,
const nsACString& aOrigin);
- const Maybe& ContentParentIdRef() const {
- return mContentParentId;
+ ThreadsafeContentParentHandle* ContentParentHandle() const {
+ return mContentParentHandle;
}
const nsCString& Origin() const { return mOrigin; }
@@ -2151,13 +2152,13 @@
};
const LSRequestParams mParams;
- Maybe mContentParentId;
+ RefPtr mContentParentHandle;
State mState;
bool mWaitingForFinish;
public:
LSRequestBase(const LSRequestParams& aParams,
- const Maybe& aContentParentId);
+ ThreadsafeContentParentHandle* aContentParentHandle);
void Dispatch();
@@ -2170,6 +2171,10 @@
protected:
~LSRequestBase() override;
+ ThreadsafeContentParentHandle* ContentParentHandle() const {
+ return mContentParentHandle;
+ }
+
virtual nsresult Start() = 0;
virtual nsresult NestedRun();
@@ -2319,7 +2324,7 @@
public:
PrepareDatastoreOp(const LSRequestParams& aParams,
- const Maybe& aContentParentId);
+ ThreadsafeContentParentHandle* aContentParentHandle);
Maybe MaybeDirectoryLockRef() const {
AssertIsOnBackgroundThread();
@@ -2460,7 +2465,7 @@
public:
PrepareObserverOp(const LSRequestParams& aParams,
- const Maybe& aContentParentId);
+ ThreadsafeContentParentHandle* aContentParentHandle);
private:
nsresult Start() override;
@@ -2488,12 +2493,12 @@
};
const LSSimpleRequestParams mParams;
- Maybe mContentParentId;
+ RefPtr mContentParentHandle;
State mState;
public:
LSSimpleRequestBase(const LSSimpleRequestParams& aParams,
- const Maybe& aContentParentId);
+ ThreadsafeContentParentHandle* aContentParentHandle);
void Dispatch();
@@ -2524,7 +2529,7 @@
public:
PreloadedOp(const LSSimpleRequestParams& aParams,
- const Maybe& aContentParentId);
+ ThreadsafeContentParentHandle* aContentParentHandle);
private:
nsresult Start() override;
@@ -2537,7 +2542,7 @@
public:
GetStateOp(const LSSimpleRequestParams& aParams,
- const Maybe& aContentParentId);
+ ThreadsafeContentParentHandle* aContentParentHandle);
private:
nsresult Start() override;
@@ -3118,7 +3123,8 @@
}
}
-bool VerifyPrincipalInfo(const PrincipalInfo& aPrincipalInfo,
+bool VerifyPrincipalInfo(ThreadsafeContentParentHandle* aContentParentHandle,
+ const PrincipalInfo& aPrincipalInfo,
const PrincipalInfo& aStoragePrincipalInfo,
bool aCheckClientPrincipal) {
AssertIsOnBackgroundThread();
@@ -3127,6 +3133,17 @@
return false;
}
+ auto prinResult = PrincipalInfoToPrincipal(aPrincipalInfo);
+ if (NS_WARN_IF(prinResult.isErr())) {
+ return false;
+ }
+
+ if (aContentParentHandle &&
+ NS_WARN_IF(!ValidatePrincipalCouldPotentiallyBeLoadedBy(
+ prinResult.inspect(), aContentParentHandle->GetRemoteType(), {}))) {
+ return false;
+ }
+
// Note that the client prinicpal could have a different spec than the node
// principal but they should have the same origin. It's because the client
// could be initialized when opening the initial about:blank document and pass
@@ -3150,7 +3167,7 @@
return true;
}
-bool VerifyClientId(const Maybe& aContentParentId,
+bool VerifyClientId(ThreadsafeContentParentHandle* aContentParentHandle,
const Maybe& aPrincipalInfo,
const Maybe& aClientId) {
AssertIsOnBackgroundThread();
@@ -3165,8 +3182,9 @@
}
RefPtr svc = ClientManagerService::GetInstance();
- if (svc && NS_WARN_IF(!svc->HasWindow(
- aContentParentId, aPrincipalInfo.ref(), aClientId.ref()))) {
+ if (svc &&
+ NS_WARN_IF(!svc->HasWindow(aContentParentHandle, aPrincipalInfo.ref(),
+ aClientId.ref()))) {
return false;
}
}
@@ -3280,7 +3298,7 @@
// method.
RefPtr database =
- new Database(aPrincipalInfo, preparedDatastore->GetContentParentId(),
+ new Database(aPrincipalInfo, preparedDatastore->GetContentParentHandle(),
preparedDatastore->Origin(), aPrivateBrowsingId);
return database.forget();
@@ -3416,12 +3434,8 @@
return nullptr;
}
- Maybe contentParentId;
-
- uint64_t childID = BackgroundParent::GetChildID(aBackgroundActor);
- if (childID) {
- contentParentId = Some(ContentParentId(childID));
- }
+ RefPtr contentParentHandle =
+ BackgroundParent::GetContentParentHandle(aBackgroundActor);
RefPtr actor;
@@ -3429,7 +3443,7 @@
case LSRequestParams::TLSRequestPreloadDatastoreParams:
case LSRequestParams::TLSRequestPrepareDatastoreParams: {
RefPtr prepareDatastoreOp =
- new PrepareDatastoreOp(aParams, contentParentId);
+ new PrepareDatastoreOp(aParams, contentParentHandle);
if (!gPrepareDatastoreOps) {
gPrepareDatastoreOps = new PrepareDatastoreOpArray();
@@ -3444,7 +3458,7 @@
case LSRequestParams::TLSRequestPrepareObserverParams: {
RefPtr prepareObserverOp =
- new PrepareObserverOp(aParams, contentParentId);
+ new PrepareObserverOp(aParams, contentParentHandle);
actor = std::move(prepareObserverOp);
@@ -3499,19 +3513,15 @@
return nullptr;
}
- Maybe contentParentId;
-
- uint64_t childID = BackgroundParent::GetChildID(aBackgroundActor);
- if (childID) {
- contentParentId = Some(ContentParentId(childID));
- }
+ RefPtr contentParentHandle =
+ BackgroundParent::GetContentParentHandle(aBackgroundActor);
RefPtr actor;
switch (aParams.type()) {
case LSSimpleRequestParams::TLSSimpleRequestPreloadedParams: {
RefPtr preloadedOp =
- new PreloadedOp(aParams, contentParentId);
+ new PreloadedOp(aParams, contentParentHandle);
actor = std::move(preloadedOp);
@@ -3519,7 +3529,8 @@
}
case LSSimpleRequestParams::TLSSimpleRequestGetStateParams: {
- RefPtr getStateOp = new GetStateOp(aParams, contentParentId);
+ RefPtr getStateOp =
+ new GetStateOp(aParams, contentParentHandle);
actor = std::move(getStateOp);
@@ -4595,7 +4606,7 @@
AssertIsOnBackgroundThread();
for (Database* database : mDatabases) {
- if (database->ContentParentIdRef() != aDatabase->ContentParentIdRef()) {
+ if (database->ContentParentHandle() != aDatabase->ContentParentHandle()) {
return true;
}
}
@@ -5103,7 +5114,7 @@
MOZ_ASSERT(array);
for (Observer* observer : *array) {
- if (observer->ContentParentIdRef() != aDatabase->ContentParentIdRef()) {
+ if (observer->ContentParentHandle() != aDatabase->ContentParentHandle()) {
return true;
}
}
@@ -5134,7 +5145,7 @@
// that caused the change.
for (Observer* observer : *array) {
- if (observer->ContentParentIdRef() != aDatabase->ContentParentIdRef()) {
+ if (observer->ContentParentHandle() != aDatabase->ContentParentHandle()) {
observer->Observe(aDatabase, aDocumentURI, aKey, aOldValue, aNewValue);
}
}
@@ -5155,7 +5166,7 @@
bool hasOtherProcessObservers = false;
for (Observer* observer : aObservers) {
- if (observer->ContentParentIdRef() != database->ContentParentIdRef()) {
+ if (observer->ContentParentHandle() != database->ContentParentHandle()) {
hasOtherProcessObservers = true;
break;
}
@@ -5363,11 +5374,11 @@
******************************************************************************/
Database::Database(const PrincipalInfo& aPrincipalInfo,
- const Maybe& aContentParentId,
+ ThreadsafeContentParentHandle* aContentParentHandle,
const nsACString& aOrigin, uint32_t aPrivateBrowsingId)
: mSnapshot(nullptr),
mPrincipalInfo(aPrincipalInfo),
- mContentParentId(aContentParentId),
+ mContentParentHandle(aContentParentHandle),
mOrigin(aOrigin),
mRequestAllowToCloseTimerId(0),
mPrivateBrowsingId(aPrivateBrowsingId),
@@ -5492,7 +5503,7 @@
aResult.Append(kQuotaGenericDelimiter);
aResult.AppendLiteral("OtherProcessActor:");
- aResult.AppendInt(mContentParentId.isSome());
+ aResult.AppendInt(!!mContentParentHandle);
aResult.Append(kQuotaGenericDelimiter);
aResult.AppendLiteral("Origin:");
@@ -6153,9 +6164,9 @@
* Observer
******************************************************************************/
-Observer::Observer(const Maybe& aContentParentId,
+Observer::Observer(ThreadsafeContentParentHandle* aContentParentHandle,
const nsACString& aOrigin)
- : mContentParentId(aContentParentId),
+ : mContentParentHandle(aContentParentHandle),
mOrigin(aOrigin),
mActorDestroyed(false) {
AssertIsOnBackgroundThread();
@@ -6216,10 +6227,11 @@
* LSRequestBase
******************************************************************************/
-LSRequestBase::LSRequestBase(const LSRequestParams& aParams,
- const Maybe& aContentParentId)
+LSRequestBase::LSRequestBase(
+ const LSRequestParams& aParams,
+ ThreadsafeContentParentHandle* aContentParentHandle)
: mParams(aParams),
- mContentParentId(aContentParentId),
+ mContentParentHandle(aContentParentHandle),
mState(State::Initial),
mWaitingForFinish(false) {}
@@ -6308,7 +6320,8 @@
mParams.get_LSRequestPreloadDatastoreParams().commonParams();
if (NS_WARN_IF(!VerifyPrincipalInfo(
- params.principalInfo(), params.storagePrincipalInfo(), false))) {
+ ContentParentHandle(), params.principalInfo(),
+ params.storagePrincipalInfo(), false))) {
return false;
}
@@ -6326,20 +6339,20 @@
const LSRequestCommonParams& commonParams = params.commonParams();
- if (NS_WARN_IF(!VerifyPrincipalInfo(commonParams.principalInfo(),
- commonParams.storagePrincipalInfo(),
- false))) {
+ if (NS_WARN_IF(!VerifyPrincipalInfo(
+ ContentParentHandle(), commonParams.principalInfo(),
+ commonParams.storagePrincipalInfo(), false))) {
return false;
}
if (params.clientPrincipalInfo() &&
- NS_WARN_IF(!VerifyPrincipalInfo(commonParams.principalInfo(),
- params.clientPrincipalInfo().ref(),
- true))) {
+ NS_WARN_IF(!VerifyPrincipalInfo(
+ ContentParentHandle(), commonParams.principalInfo(),
+ params.clientPrincipalInfo().ref(), true))) {
return false;
}
- if (NS_WARN_IF(!VerifyClientId(mContentParentId,
+ if (NS_WARN_IF(!VerifyClientId(ContentParentHandle(),
params.clientPrincipalInfo(),
params.clientId()))) {
return false;
@@ -6358,18 +6371,19 @@
mParams.get_LSRequestPrepareObserverParams();
if (NS_WARN_IF(!VerifyPrincipalInfo(
- params.principalInfo(), params.storagePrincipalInfo(), false))) {
+ ContentParentHandle(), params.principalInfo(),
+ params.storagePrincipalInfo(), false))) {
return false;
}
if (params.clientPrincipalInfo() &&
- NS_WARN_IF(!VerifyPrincipalInfo(params.principalInfo(),
- params.clientPrincipalInfo().ref(),
- true))) {
+ NS_WARN_IF(!VerifyPrincipalInfo(
+ ContentParentHandle(), params.principalInfo(),
+ params.clientPrincipalInfo().ref(), true))) {
return false;
}
- if (NS_WARN_IF(!VerifyClientId(mContentParentId,
+ if (NS_WARN_IF(!VerifyClientId(ContentParentHandle(),
params.clientPrincipalInfo(),
params.clientId()))) {
return false;
@@ -6612,8 +6626,8 @@
PrepareDatastoreOp::PrepareDatastoreOp(
const LSRequestParams& aParams,
- const Maybe& aContentParentId)
- : LSRequestBase(aParams, aContentParentId),
+ ThreadsafeContentParentHandle* aContentParentHandle)
+ : LSRequestBase(aParams, aContentParentHandle),
mProcessingTimerId(
glean::localstorage_request::prepare_datastore_processing_time
.Start()),
@@ -7592,8 +7606,8 @@
}
const auto& preparedDatastore = gPreparedDatastores->InsertOrUpdate(
mDatastoreId, MakeUnique(
- mDatastore, mContentParentId, Origin(), mDatastoreId,
- /* aForPreload */ mForPreload));
+ mDatastore, ContentParentHandle(), Origin(),
+ mDatastoreId, /* aForPreload */ mForPreload));
if (mInvalidated) {
preparedDatastore->Invalidate();
@@ -7972,8 +7986,8 @@
PrepareObserverOp::PrepareObserverOp(
const LSRequestParams& aParams,
- const Maybe& aContentParentId)
- : LSRequestBase(aParams, aContentParentId) {
+ ThreadsafeContentParentHandle* aContentParentHandle)
+ : LSRequestBase(aParams, aContentParentHandle) {
MOZ_ASSERT(aParams.type() ==
LSRequestParams::TLSRequestPrepareObserverParams);
}
@@ -8013,7 +8027,7 @@
uint64_t observerId = ++gLastObserverId;
- RefPtr observer = new Observer(mContentParentId, mOrigin);
+ RefPtr observer = new Observer(ContentParentHandle(), mOrigin);
if (!gPreparedObsevers) {
gPreparedObsevers = new PreparedObserverHashtable();
@@ -8033,9 +8047,9 @@
LSSimpleRequestBase::LSSimpleRequestBase(
const LSSimpleRequestParams& aParams,
- const Maybe& aContentParentId)
+ ThreadsafeContentParentHandle* aContentParentHandle)
: mParams(aParams),
- mContentParentId(aContentParentId),
+ mContentParentHandle(aContentParentHandle),
mState(State::Initial) {}
LSSimpleRequestBase::~LSSimpleRequestBase() {
@@ -8061,8 +8075,9 @@
const LSSimpleRequestPreloadedParams& params =
mParams.get_LSSimpleRequestPreloadedParams();
- if (NS_WARN_IF(!VerifyPrincipalInfo(
- params.principalInfo(), params.storagePrincipalInfo(), false))) {
+ if (NS_WARN_IF(
+ !VerifyPrincipalInfo(mContentParentHandle, params.principalInfo(),
+ params.storagePrincipalInfo(), false))) {
return false;
}
@@ -8073,8 +8088,9 @@
const LSSimpleRequestGetStateParams& params =
mParams.get_LSSimpleRequestGetStateParams();
- if (NS_WARN_IF(!VerifyPrincipalInfo(
- params.principalInfo(), params.storagePrincipalInfo(), false))) {
+ if (NS_WARN_IF(
+ !VerifyPrincipalInfo(mContentParentHandle, params.principalInfo(),
+ params.storagePrincipalInfo(), false))) {
return false;
}
@@ -8183,8 +8199,8 @@
******************************************************************************/
PreloadedOp::PreloadedOp(const LSSimpleRequestParams& aParams,
- const Maybe& aContentParentId)
- : LSSimpleRequestBase(aParams, aContentParentId) {
+ ThreadsafeContentParentHandle* aContentParentHandle)
+ : LSSimpleRequestBase(aParams, aContentParentHandle) {
MOZ_ASSERT(aParams.type() ==
LSSimpleRequestParams::TLSSimpleRequestPreloadedParams);
}
@@ -8240,8 +8256,8 @@
******************************************************************************/
GetStateOp::GetStateOp(const LSSimpleRequestParams& aParams,
- const Maybe& aContentParentId)
- : LSSimpleRequestBase(aParams, aContentParentId) {
+ ThreadsafeContentParentHandle* aContentParentHandle)
+ : LSSimpleRequestBase(aParams, aContentParentHandle) {
MOZ_ASSERT(aParams.type() ==
LSSimpleRequestParams::TLSSimpleRequestGetStateParams);
}
@@ -8894,18 +8910,15 @@
void QuotaClient::AbortOperationsForProcess(ContentParentId aContentParentId) {
AssertIsOnBackgroundThread();
- // XXX Quota Manager should do the wrapping.
- Maybe contentParentId;
-
- if (aContentParentId) {
- contentParentId = Some(aContentParentId);
- }
-
// XXX We could try to invalidate other objects here.
RequestAllowToCloseDatabasesMatching(
- [&contentParentId](const auto& database) {
- return database.ContentParentIdRef() == contentParentId;
+ [aContentParentId](const auto& database) {
+ ThreadsafeContentParentHandle* contentParentHandle =
+ database.ContentParentHandle();
+ return contentParentHandle
+ ? contentParentHandle->ChildID() == aContentParentId
+ : !aContentParentId;
});
}
diff -Nru thunderbird-140.14.0esr/dom/media/gmp/GMPChild.cpp thunderbird-140.15.0esr/dom/media/gmp/GMPChild.cpp
--- thunderbird-140.14.0esr/dom/media/gmp/GMPChild.cpp 2026-08-18 02:52:32.000000000 +0000
+++ thunderbird-140.15.0esr/dom/media/gmp/GMPChild.cpp 2026-08-28 17:33:05.000000000 +0000
@@ -581,6 +581,12 @@
mGMPContentChildren[i - 1]->Close();
}
+ if (ShutdownPlatformAPI() ==
+ PlatformShutdownResult::PluginExecutionOutstanding) {
+ ProcessChild::QuickExit();
+ return;
+ }
+
if (mGMPLoader) {
mGMPLoader->Shutdown();
}
diff -Nru thunderbird-140.14.0esr/dom/media/gmp/GMPPlatform.cpp thunderbird-140.15.0esr/dom/media/gmp/GMPPlatform.cpp
--- thunderbird-140.14.0esr/dom/media/gmp/GMPPlatform.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/media/gmp/GMPPlatform.cpp 2026-08-28 17:33:06.000000000 +0000
@@ -6,10 +6,12 @@
#include "GMPPlatform.h"
#include "GMPStorageChild.h"
#include "GMPTimerChild.h"
+#include "mozilla/Atomics.h"
#include "mozilla/Monitor.h"
#include "GMPChild.h"
#include "mozilla/Mutex.h"
#include "mozilla/ReentrantMonitor.h"
+#include "mozilla/StaticMutex.h"
#include "nsThreadUtils.h"
#include "base/task.h"
#include "base/thread.h"
@@ -25,23 +27,37 @@
static GMPChild* sChild = nullptr;
+// sShutdown is atomic so GMPRunnable::Run() can check it lock-free. The
+// counters and the shutdown snapshot are serialized by sPlatformStateMutex so
+// that closing admission and reading whether any plugin execution remains is a
+// single transaction.
+static Atomic sShutdown{false};
+static StaticMutex sPlatformStateMutex;
+static uint32_t sLiveThreads MOZ_GUARDED_BY(sPlatformStateMutex) = 0;
+static uint32_t sLivePluginObjects MOZ_GUARDED_BY(sPlatformStateMutex) = 0;
+
// We just need a refcounted wrapper for GMPTask objects.
class GMPRunnable final : public Runnable {
public:
- explicit GMPRunnable(GMPTask* aTask)
- : Runnable("mozilla::gmp::GMPRunnable"), mTask(aTask) {
+ GMPRunnable(GMPTask* aTask, bool aCancelOnShutdown)
+ : Runnable("mozilla::gmp::GMPRunnable"),
+ mTask(aTask),
+ mCancelOnShutdown(aCancelOnShutdown) {
MOZ_ASSERT(mTask);
}
NS_IMETHOD Run() override {
- mTask->Run();
- mTask->Destroy();
+ if (!(mCancelOnShutdown && sShutdown)) {
+ mTask->Run();
+ mTask->Destroy();
+ }
mTask = nullptr;
return NS_OK;
}
private:
GMPTask* mTask;
+ const bool mCancelOnShutdown;
};
class GMPSyncRunnable final : public Runnable {
@@ -99,17 +115,24 @@
return GMPGenericErr;
}
+ StaticMutexAutoLock lock(sPlatformStateMutex);
+ if (sShutdown) {
+ return GMPGenericErr;
+ }
+
*aThread = new GMPThreadImpl();
+ ++sLiveThreads;
return GMPNoErr;
}
GMPErr RunOnMainThread(GMPTask* aTask) {
- if (!aTask) {
+ if (!aTask || sShutdown) {
return GMPGenericErr;
}
- if (NS_FAILED(NS_DispatchToMainThread(MakeAndAddRef(aTask)))) {
+ if (NS_FAILED(NS_DispatchToMainThread(
+ MakeAndAddRef(aTask, /* aCancelOnShutdown */ true)))) {
return GMPGenericErr;
}
@@ -117,7 +140,7 @@
}
GMPErr SyncRunOnMainThread(GMPTask* aTask) {
- if (!aTask || NS_IsMainThread()) {
+ if (!aTask || sShutdown || NS_IsMainThread()) {
return GMPGenericErr;
}
@@ -170,7 +193,7 @@
}
GMPErr SetTimerOnMainThread(GMPTask* aTask, int64_t aTimeoutMS) {
- if (!aTask || !NS_IsMainThread()) {
+ if (!aTask || sShutdown || !NS_IsMainThread()) {
return GMPGenericErr;
}
GMPTimerChild* timers = sChild->GetGMPTimers();
@@ -201,6 +224,25 @@
aPlatformAPI.getcurrenttime = &GetClock;
}
+void AddPluginObject() {
+ StaticMutexAutoLock lock(sPlatformStateMutex);
+ ++sLivePluginObjects;
+}
+
+void RemovePluginObject() {
+ StaticMutexAutoLock lock(sPlatformStateMutex);
+ --sLivePluginObjects;
+}
+
+PlatformShutdownResult ShutdownPlatformAPI() {
+ MOZ_ASSERT(NS_IsMainThread());
+ StaticMutexAutoLock lock(sPlatformStateMutex);
+ sShutdown = true;
+ return sLiveThreads == 0 && sLivePluginObjects == 0
+ ? PlatformShutdownResult::ReadyToUnload
+ : PlatformShutdownResult::PluginExecutionOutstanding;
+}
+
void SendFOGData(ipc::ByteBuf&& buf) {
if (sChild) {
sChild->SendFOGData(std::move(buf));
@@ -220,7 +262,11 @@
GMPThreadImpl::GMPThreadImpl() { MOZ_COUNT_CTOR(GMPThread); }
-GMPThreadImpl::~GMPThreadImpl() { MOZ_COUNT_DTOR(GMPThread); }
+GMPThreadImpl::~GMPThreadImpl() {
+ MOZ_COUNT_DTOR(GMPThread);
+ StaticMutexAutoLock lock(sPlatformStateMutex);
+ --sLiveThreads;
+}
void GMPThreadImpl::Post(GMPTask* aTask) {
MutexAutoLock lock(mMutex);
@@ -233,7 +279,7 @@
}
}
- RefPtr r = new GMPRunnable(aTask);
+ RefPtr r = new GMPRunnable(aTask, /* aCancelOnShutdown */ false);
mThread.message_loop()->PostTask(
NewRunnableMethod("gmp::GMPRunnable::Run", r.get(), &GMPRunnable::Run));
}
diff -Nru thunderbird-140.14.0esr/dom/media/gmp/GMPPlatform.h thunderbird-140.15.0esr/dom/media/gmp/GMPPlatform.h
--- thunderbird-140.14.0esr/dom/media/gmp/GMPPlatform.h 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/media/gmp/GMPPlatform.h 2026-08-28 17:33:06.000000000 +0000
@@ -25,6 +25,18 @@
void InitPlatformAPI(GMPPlatformAPI& aPlatformAPI, GMPChild* aChild);
+enum class PlatformShutdownResult {
+ ReadyToUnload,
+ PluginExecutionOutstanding,
+};
+
+PlatformShutdownResult ShutdownPlatformAPI();
+
+// Count of live plugin-implemented objects (e.g. codec instances) held by GMP
+// child actors.
+void AddPluginObject();
+void RemovePluginObject();
+
GMPErr RunOnMainThread(GMPTask* aTask);
GMPTask* NewGMPTask(std::function&& aFunction);
diff -Nru thunderbird-140.14.0esr/dom/media/gmp/GMPVideoDecoderChild.cpp thunderbird-140.15.0esr/dom/media/gmp/GMPVideoDecoderChild.cpp
--- thunderbird-140.14.0esr/dom/media/gmp/GMPVideoDecoderChild.cpp 2026-08-18 02:52:32.000000000 +0000
+++ thunderbird-140.15.0esr/dom/media/gmp/GMPVideoDecoderChild.cpp 2026-08-28 17:33:05.000000000 +0000
@@ -30,6 +30,7 @@
// the worker thread.
if (mVideoDecoder) {
mVideoDecoder->DecodingComplete();
+ RemovePluginObject();
}
}
@@ -41,6 +42,7 @@
MOZ_ASSERT(aDecoder,
"Cannot initialize video decoder child without a video decoder!");
mVideoDecoder = aDecoder;
+ AddPluginObject();
}
void GMPVideoDecoderChild::Decoded(GMPVideoi420Frame* aDecodedFrame) {
diff -Nru thunderbird-140.14.0esr/dom/media/gmp/GMPVideoEncoderChild.cpp thunderbird-140.15.0esr/dom/media/gmp/GMPVideoEncoderChild.cpp
--- thunderbird-140.14.0esr/dom/media/gmp/GMPVideoEncoderChild.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/media/gmp/GMPVideoEncoderChild.cpp 2026-08-28 17:33:06.000000000 +0000
@@ -26,6 +26,7 @@
// the worker thread.
if (mVideoEncoder) {
mVideoEncoder->EncodingComplete();
+ RemovePluginObject();
}
}
@@ -37,6 +38,7 @@
MOZ_ASSERT(aEncoder,
"Cannot initialize video encoder child without a video encoder!");
mVideoEncoder = aEncoder;
+ AddPluginObject();
}
void GMPVideoEncoderChild::Encoded(GMPVideoEncodedFrame* aEncodedFrame,
diff -Nru thunderbird-140.14.0esr/dom/media/ipc/MFMediaEngineParent.cpp thunderbird-140.15.0esr/dom/media/ipc/MFMediaEngineParent.cpp
--- thunderbird-140.14.0esr/dom/media/ipc/MFMediaEngineParent.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/media/ipc/MFMediaEngineParent.cpp 2026-08-28 17:33:06.000000000 +0000
@@ -61,9 +61,14 @@
}
/* static */
-MFMediaEngineParent* MFMediaEngineParent::GetMediaEngineById(uint64_t aId) {
+already_AddRefed MFMediaEngineParent::GetMediaEngineById(
+ uint64_t aId) {
StaticMutexAutoLock lock(sMediaEnginesLock);
- return sMediaEngines->Get(aId);
+ if (!sMediaEngines) {
+ return nullptr;
+ }
+ RefPtr engine = sMediaEngines->Get(aId);
+ return engine.forget();
}
MFMediaEngineParent::MFMediaEngineParent(RemoteDecoderManagerParent* aManager,
@@ -85,14 +90,23 @@
MFMediaEngineParent::~MFMediaEngineParent() {
LOG("Destoryed MFMediaEngineParent");
+ UnregisterMedieEngine(this);
DestroyEngineIfExists();
+}
+
+void MFMediaEngineParent::ActorDestroy(ActorDestroyReason aWhy) {
+ AssertOnManagerThread();
+ LOG("ActorDestroy");
UnregisterMedieEngine(this);
+ DestroyEngineIfExists();
}
void MFMediaEngineParent::DestroyEngineIfExists(
const Maybe& aError) {
LOG("DestroyEngineIfExists, hasError=%d", aError.isSome());
ENGINE_MARKER("MFMediaEngineParent::DestroyEngineIfExists");
+ mMediaEngineEventListener.DisconnectIfExists();
+ mRequestSampleListener.DisconnectIfExists();
mMediaEngineNotify = nullptr;
mMediaEngineExtension = nullptr;
if (mMediaSource) {
@@ -109,8 +123,6 @@
LOG_IF_FAILED(mMediaEngine->Shutdown());
mMediaEngine = nullptr;
}
- mMediaEngineEventListener.DisconnectIfExists();
- mRequestSampleListener.DisconnectIfExists();
if (mDXGIDeviceManager) {
mDXGIDeviceManager = nullptr;
}
diff -Nru thunderbird-140.14.0esr/dom/media/ipc/MFMediaEngineParent.h thunderbird-140.15.0esr/dom/media/ipc/MFMediaEngineParent.h
--- thunderbird-140.14.0esr/dom/media/ipc/MFMediaEngineParent.h 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/media/ipc/MFMediaEngineParent.h 2026-08-28 17:33:05.000000000 +0000
@@ -42,7 +42,7 @@
using TrackType = TrackInfo::TrackType;
- static MFMediaEngineParent* GetMediaEngineById(uint64_t aId);
+ static already_AddRefed GetMediaEngineById(uint64_t aId);
MFMediaEngineStreamWrapper* GetMediaEngineStream(
TrackType aType, const CreateDecoderParams& aParam);
@@ -62,6 +62,8 @@
mozilla::ipc::IPCResult RecvNotifyEndOfStream(TrackInfo::TrackType aType);
mozilla::ipc::IPCResult RecvShutdown();
+ void ActorDestroy(ActorDestroyReason aWhy) override;
+
void Destroy();
private:
diff -Nru thunderbird-140.14.0esr/dom/media/ipc/RemoteDecoderParent.cpp thunderbird-140.15.0esr/dom/media/ipc/RemoteDecoderParent.cpp
--- thunderbird-140.14.0esr/dom/media/ipc/RemoteDecoderParent.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/media/ipc/RemoteDecoderParent.cpp 2026-08-28 17:33:05.000000000 +0000
@@ -48,6 +48,12 @@
return IPC_OK();
}
+ if (mInitAttempted) {
+ aResolver(MediaResult(NS_ERROR_ALREADY_INITIALIZED, __func__));
+ return IPC_OK();
+ }
+ mInitAttempted = true;
+
RefPtr self = this;
mDecoder->Init()->Then(
mManagerThread, __func__,
diff -Nru thunderbird-140.14.0esr/dom/media/ipc/RemoteDecoderParent.h thunderbird-140.15.0esr/dom/media/ipc/RemoteDecoderParent.h
--- thunderbird-140.14.0esr/dom/media/ipc/RemoteDecoderParent.h 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/media/ipc/RemoteDecoderParent.h 2026-08-28 17:33:05.000000000 +0000
@@ -61,6 +61,7 @@
// Only be used on Windows when the media engine playback is enabled.
const Maybe mMediaEngineId;
+ bool mInitAttempted = false;
bool mShutdown = false;
private:
diff -Nru thunderbird-140.14.0esr/dom/media/platforms/apple/AppleVTDecoder.cpp thunderbird-140.15.0esr/dom/media/platforms/apple/AppleVTDecoder.cpp
--- thunderbird-140.14.0esr/dom/media/platforms/apple/AppleVTDecoder.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/media/platforms/apple/AppleVTDecoder.cpp 2026-08-28 17:33:05.000000000 +0000
@@ -91,6 +91,24 @@
AppleVTDecoder::~AppleVTDecoder() { MOZ_COUNT_DTOR(AppleVTDecoder); }
RefPtr AppleVTDecoder::Init() {
+ if (mSession) {
+ MOZ_ASSERT_UNREACHABLE(
+ "Cannot initialize decoder again without shutting down");
+ return InitPromise::CreateAndReject(
+ MediaResult(NS_ERROR_ALREADY_INITIALIZED,
+ RESULT_DETAIL("Decoder initialization already attempted")),
+ __func__);
+ }
+
+ if (mFormat) {
+ MOZ_ASSERT_UNREACHABLE(
+ "Cannot initialize decoder again after previous initialization failed");
+ return InitPromise::CreateAndReject(
+ MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
+ RESULT_DETAIL("Previous decoder initialization failed")),
+ __func__);
+ }
+
MediaResult rv = InitializeSession();
if (NS_SUCCEEDED(rv)) {
diff -Nru thunderbird-140.14.0esr/dom/media/platforms/apple/AppleVTEncoder.cpp thunderbird-140.15.0esr/dom/media/platforms/apple/AppleVTEncoder.cpp
--- thunderbird-140.14.0esr/dom/media/platforms/apple/AppleVTEncoder.cpp 2026-08-18 02:52:32.000000000 +0000
+++ thunderbird-140.15.0esr/dom/media/platforms/apple/AppleVTEncoder.cpp 2026-08-28 17:33:05.000000000 +0000
@@ -11,6 +11,8 @@
#include
#include
+#include
+
#include "AnnexB.h"
#include "H264.h"
#include "ImageContainer.h"
@@ -386,9 +388,89 @@
dom::GetEnumString(aFormat).get())));
}
+static Result MapPixelFormat(gfx::SurfaceFormat aFormat) {
+ switch (aFormat) {
+ case gfx::SurfaceFormat::B8G8R8A8:
+ case gfx::SurfaceFormat::B8G8R8X8:
+ return kCVPixelFormatType_32BGRA;
+ case gfx::SurfaceFormat::R8G8B8A8:
+ case gfx::SurfaceFormat::R8G8B8X8:
+ return kCVPixelFormatType_32RGBA;
+ case gfx::SurfaceFormat::R8G8B8:
+ return kCVPixelFormatType_24RGB;
+ case gfx::SurfaceFormat::B8G8R8:
+ return kCVPixelFormatType_24BGR;
+ case gfx::SurfaceFormat::A8:
+ return kCVPixelFormatType_OneComponent8;
+ default:
+ return Err(MediaResult(NS_ERROR_NOT_IMPLEMENTED,
+ RESULT_DETAIL("surface format %d is not supported",
+ static_cast(aFormat))));
+ }
+}
+
+static bool CopySurfaceToPixelBuffer(gfx::DataSourceSurface* aSource,
+ CVPixelBufferRef aDestination) {
+ gfx::DataSourceSurface::ScopedMap map(aSource, gfx::DataSourceSurface::READ);
+ if (NS_WARN_IF(!map.IsMapped())) {
+ LOGE("Failed to map DataSurface");
+ return false;
+ }
+
+ CVReturn rv = CVPixelBufferLockBaseAddress(aDestination, 0);
+ if (rv != kCVReturnSuccess) {
+ LOGE("CVPixelBufferLockBaseAddress error: %d", rv);
+ return false;
+ }
+ auto unlockBuffer =
+ MakeScopeExit([&] { CVPixelBufferUnlockBaseAddress(aDestination, 0); });
+
+ const gfx::IntSize size = aSource->GetSize();
+ const int32_t sourceStride = map.GetStride();
+ const size_t destinationStride = CVPixelBufferGetBytesPerRow(aDestination);
+ const size_t destinationSize = CVPixelBufferGetDataSize(aDestination);
+ uint8_t* destination =
+ static_cast(CVPixelBufferGetBaseAddress(aDestination));
+ const uint8_t* source = map.GetData();
+ if (size.width <= 0 || size.height <= 0 || sourceStride < 0 || !destination ||
+ !source) {
+ LOGE("Unexpected pixel-buffer layout");
+ return false;
+ }
+ const size_t height = static_cast(size.height);
+ const size_t sourceStrideSize = static_cast(sourceStride);
+ // Positive int32_t widths at up to 4 Bpp fit in macOS's 64-bit size_t.
+ const size_t rowBytes = static_cast(size.width) *
+ gfx::BytesPerPixel(aSource->GetFormat());
+ if (sourceStrideSize < rowBytes || destinationStride < rowBytes) {
+ LOGE("Unexpected pixel-buffer layout");
+ return false;
+ }
+ if (height > destinationSize / destinationStride) {
+ LOGE("Unexpected pixel-buffer layout");
+ return false;
+ }
+ const size_t destinationPadding = destinationStride - rowBytes;
+ for (size_t y = 0; y < height; ++y) {
+ uint8_t* destinationRow = destination + y * destinationStride;
+ memcpy(destinationRow, source + y * sourceStrideSize, rowBytes);
+ if (destinationPadding) {
+ // Avoid passing uninitialized stride padding to VideoToolbox.
+ memset(destinationRow + rowBytes, 0, destinationPadding);
+ }
+ }
+ return true;
+}
+
RefPtr AppleVTEncoder::Init() {
- MOZ_ASSERT(!mSession,
- "Cannot initialize encoder again without shutting down");
+ if (mSession) {
+ MOZ_ASSERT_UNREACHABLE(
+ "Cannot initialize encoder again without shutting down");
+ return InitPromise::CreateAndReject(
+ MediaResult(NS_ERROR_ALREADY_INITIALIZED,
+ RESULT_DETAIL("Encoder is already initialized")),
+ __func__);
+ }
MediaResult r = InitSession();
if (NS_FAILED(r.Code())) {
@@ -1012,15 +1094,10 @@
using namespace layers;
-static void ReleaseSurface(void* aReleaseRef, const void* aBaseAddress) {
- RefPtr released =
- dont_AddRef(static_cast(aReleaseRef));
-}
-
static void ReleaseImage(void* aImageGrip, const void* aDataPtr,
size_t aDataSize, size_t aNumOfPlanes,
const void** aPlanes) {
- (static_cast(aImageGrip))->Release();
+ (static_cast(aImageGrip))->Release();
}
CVPixelBufferRef AppleVTEncoder::CreateCVPixelBuffer(Image* aSource) {
@@ -1058,15 +1135,20 @@
// the encoder.
}
- if (aSource->GetFormat() == ImageFormat::PLANAR_YCBCR) {
- PlanarYCbCrImage* image = aSource->AsPlanarYCbCrImage();
- if (!image || !image->GetData()) {
- LOGE("Failed to get PlanarYCbCrImage or its data");
+ if (aSource->GetFormat() == ImageFormat::PLANAR_YCBCR ||
+ aSource->GetFormat() == ImageFormat::NV_IMAGE) {
+ const PlanarYCbCrData* yuv = nullptr;
+ if (PlanarYCbCrImage* image = aSource->AsPlanarYCbCrImage()) {
+ yuv = image->GetData();
+ } else if (NVImage* image = aSource->AsNVImage()) {
+ yuv = image->GetData();
+ }
+ if (!yuv) {
+ LOGE("Failed to get YCbCr data");
return nullptr;
}
size_t numPlanes = NumberOfPlanes(pixelFormat);
- const PlanarYCbCrImage::Data* yuv = image->GetData();
auto ySize = yuv->YDataSize();
auto cbcrSize = yuv->CbCrDataSize();
@@ -1100,19 +1182,18 @@
}
CVPixelBufferRef buffer = nullptr;
- image->AddRef(); // Grip input buffers.
+ aSource->AddRef();
CVReturn rv = CVPixelBufferCreateWithPlanarBytes(
kCFAllocatorDefault, yuv->mPictureRect.width, yuv->mPictureRect.height,
pixelFormat, nullptr /* dataPtr */, 0 /* dataSize */, numPlanes,
addresses, widths, heights, strides, ReleaseImage /* releaseCallback */,
- image /* releaseRefCon */, nullptr /* pixelBufferAttributes */,
+ aSource /* releaseRefCon */, nullptr /* pixelBufferAttributes */,
&buffer);
if (rv == kCVReturnSuccess) {
return buffer;
- // |image| will be released in |ReleaseImage()|.
}
LOGE("CVPIxelBufferCreateWithPlanarBytes error");
- image->Release();
+ aSource->Release();
return nullptr;
}
@@ -1128,26 +1209,27 @@
return nullptr;
}
- gfx::DataSourceSurface::ScopedMap map(dataSurface,
- gfx::DataSourceSurface::READ);
- if (NS_WARN_IF(!map.IsMapped())) {
- LOGE("Failed to map DataSurface");
+ auto surfacePfr = MapPixelFormat(dataSurface->GetFormat());
+ if (surfacePfr.isErr()) {
+ MediaResult err = surfacePfr.unwrapErr();
+ LOGE("%s", err.Description().get());
return nullptr;
}
+ const gfx::IntSize size = dataSurface->GetSize();
CVPixelBufferRef buffer = nullptr;
- gfx::DataSourceSurface* dss = dataSurface.forget().take();
- CVReturn rv = CVPixelBufferCreateWithBytes(
- kCFAllocatorDefault, dss->GetSize().Width(), dss->GetSize().Height(),
- pixelFormat, map.GetData(), map.GetStride(), ReleaseSurface, dss, nullptr,
- &buffer);
- if (rv == kCVReturnSuccess) {
- return buffer;
- // |dss| will be released in |ReleaseSurface()|.
- }
- LOGE("CVPIxelBufferCreateWithBytes error: %d", rv);
- RefPtr released = dont_AddRef(dss);
- return nullptr;
+ CVReturn rv =
+ CVPixelBufferCreate(kCFAllocatorDefault, size.width, size.height,
+ surfacePfr.unwrap(), nullptr, &buffer);
+ if (rv != kCVReturnSuccess) {
+ LOGE("CVPixelBufferCreate error: %d", rv);
+ return nullptr;
+ }
+ if (!CopySurfaceToPixelBuffer(dataSurface, buffer)) {
+ CVPixelBufferRelease(buffer);
+ return nullptr;
+ }
+ return buffer;
}
RefPtr AppleVTEncoder::Drain() {
diff -Nru thunderbird-140.14.0esr/dom/media/platforms/wmf/MFMediaEngineStream.cpp thunderbird-140.15.0esr/dom/media/platforms/wmf/MFMediaEngineStream.cpp
--- thunderbird-140.14.0esr/dom/media/platforms/wmf/MFMediaEngineStream.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/media/platforms/wmf/MFMediaEngineStream.cpp 2026-08-28 17:33:05.000000000 +0000
@@ -137,7 +137,7 @@
HRESULT MFMediaEngineStream::RuntimeClassInitialize(
uint64_t aStreamId, const TrackInfo& aInfo, bool aIsEncrytpedCustomInit,
MFMediaSource* aParentSource) {
- mParentSource = aParentSource;
+ SetParentSource(aParentSource);
mTaskQueue = aParentSource->GetTaskQueue();
MOZ_ASSERT(mTaskQueue);
mStreamId = aStreamId;
@@ -163,14 +163,22 @@
HRESULT MFMediaEngineStream::GenerateStreamDescriptor(
ComPtr& aMediaType) {
+ ComPtr descriptor;
+ MutexAutoLock lock(mDescriptorMutex);
RETURN_IF_FAILED(wmf::MFCreateStreamDescriptor(
mStreamId, 1 /* stream amount */, aMediaType.GetAddressOf(),
- &mStreamDescriptor));
- RETURN_IF_FAILED(
- mStreamDescriptor->GetStreamIdentifier(&mStreamDescriptorId));
+ descriptor.GetAddressOf()));
+ DWORD descriptorId = 0;
+ RETURN_IF_FAILED(descriptor->GetStreamIdentifier(&descriptorId));
if (IsEncrypted()) {
- RETURN_IF_FAILED(mStreamDescriptor->SetUINT32(MF_SD_PROTECTED, 1));
+ RETURN_IF_FAILED(descriptor->SetUINT32(MF_SD_PROTECTED, 1));
+ }
+ if (!mStreamDescriptorId) {
+ mStreamDescriptorId = descriptorId;
}
+ MOZ_ASSERT(mStreamDescriptorId == descriptorId,
+ "Stream identifier must not change across a config change");
+ mStreamDescriptor.Swap(descriptor);
return S_OK;
}
@@ -249,7 +257,7 @@
MOZ_ASSERT(mTaskQueue);
Unused << mTaskQueue->Dispatch(
NS_NewRunnableFunction("MFMediaEngineStream::Shutdown", [self]() {
- self->mParentSource = nullptr;
+ self->SetParentSource(nullptr);
self->mRawDataQueueForFeedingEngine.Reset();
self->mRawDataQueueForGeneratingOutput.Reset();
self->ShutdownCleanUpOnTaskQueue();
@@ -263,16 +271,32 @@
if (IsShutdown()) {
return MF_E_SHUTDOWN;
}
+ MutexAutoLock lock(mParentSourceMutex);
+ if (!mParentSource) {
+ return MF_E_SHUTDOWN;
+ }
RETURN_IF_FAILED(mParentSource.CopyTo(aMediaSource));
return S_OK;
}
+ComPtr MFMediaEngineStream::GetParentSource() const {
+ MutexAutoLock lock(mParentSourceMutex);
+ return mParentSource;
+}
+
+void MFMediaEngineStream::SetParentSource(MFMediaSource* aParentSource) {
+ MutexAutoLock lock(mParentSourceMutex);
+ mParentSource = aParentSource;
+ SLOG("Parent source %s", aParentSource ? "set" : "cleared");
+}
+
IFACEMETHODIMP MFMediaEngineStream::GetStreamDescriptor(
IMFStreamDescriptor** aStreamDescriptor) {
AssertOnMFThreadPool();
if (IsShutdown()) {
return MF_E_SHUTDOWN;
}
+ MutexAutoLock lock(mDescriptorMutex);
if (!mStreamDescriptor) {
SLOG("Hasn't initialized stream descriptor");
return MF_E_NOT_INITIALIZED;
@@ -296,7 +320,7 @@
mSampleRequestTokens.push(token);
SLOGV("RequestSample, token amount=%zu", mSampleRequestTokens.size());
ReplySampleRequestIfPossible();
- if (!HasEnoughRawData() && mParentSource && !IsEnded()) {
+ if (!HasEnoughRawData() && GetParentSource() && !IsEnded()) {
SendRequestSampleEvent(false /* isEnough */);
}
}));
@@ -351,8 +375,9 @@
bool MFMediaEngineStream::ShouldServeSamples() const {
AssertOnTaskQueue();
- return mParentSource &&
- mParentSource->GetState() == MFMediaSource::State::Started &&
+ ComPtr parentSource = GetParentSource();
+ return parentSource &&
+ parentSource->GetState() == MFMediaSource::State::Started &&
mIsSelected;
}
@@ -534,7 +559,7 @@
SLOGV("data is %s, queue duration=%" PRId64,
aIsEnough ? "enough" : "not enough",
mRawDataQueueForFeedingEngine.PreciseDuration());
- mParentSource->mRequestSampleEvent.Notify(
+ GetParentSource()->mRequestSampleEvent.Notify(
SampleRequest{TrackType(), aIsEnough});
}
diff -Nru thunderbird-140.14.0esr/dom/media/platforms/wmf/MFMediaEngineStream.h thunderbird-140.15.0esr/dom/media/platforms/wmf/MFMediaEngineStream.h
--- thunderbird-140.14.0esr/dom/media/platforms/wmf/MFMediaEngineStream.h 2026-08-18 02:52:32.000000000 +0000
+++ thunderbird-140.15.0esr/dom/media/platforms/wmf/MFMediaEngineStream.h 2026-08-28 17:33:05.000000000 +0000
@@ -121,6 +121,10 @@
void ReplySampleRequestIfPossible();
bool ShouldServeSamples() const;
+ // Return a strong reference to the parent source, thread-safe.
+ Microsoft::WRL::ComPtr GetParentSource() const;
+ void SetParentSource(MFMediaSource* aParentSource);
+
void NotifyNewData(MediaRawData* aSample);
void NotifyEndOfStreamInternal();
@@ -146,8 +150,12 @@
// IMFMediaEventQueue is thread-safe.
Microsoft::WRL::ComPtr mMediaEventQueue;
- Microsoft::WRL::ComPtr mStreamDescriptor;
- Microsoft::WRL::ComPtr mParentSource;
+ Mutex mDescriptorMutex{"MFMediaEngineStream::mDescriptorMutex"};
+ Microsoft::WRL::ComPtr mStreamDescriptor
+ MOZ_GUARDED_BY(mDescriptorMutex);
+ mutable Mutex mParentSourceMutex{"MFMediaEngineStream::mParentSourceMutex"};
+ Microsoft::WRL::ComPtr mParentSource
+ MOZ_GUARDED_BY(mParentSourceMutex);
// This an unique ID retrieved from the IMFStreamDescriptor.
DWORD mStreamDescriptorId = 0;
diff -Nru thunderbird-140.14.0esr/dom/quota/ActorsParent.cpp thunderbird-140.15.0esr/dom/quota/ActorsParent.cpp
--- thunderbird-140.14.0esr/dom/quota/ActorsParent.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/quota/ActorsParent.cpp 2026-08-28 17:33:06.000000000 +0000
@@ -7214,8 +7214,12 @@
RefPtr originInfo =
groupInfo->LockedGetOriginInfo(aOriginMetadata.mOrigin);
+ // A persisted origin is exempt from group-limit eviction and is
+ // bound by the global temporary storage limit instead, so it
+ // reports its own origin usage against that limit.
if (originInfo && originInfo->LockedPersisted()) {
- return std::pair(mTemporaryStorageUsage, mTemporaryStorageLimit);
+ return std::pair(originInfo->LockedUsage(),
+ mTemporaryStorageLimit);
}
}
diff -Nru thunderbird-140.14.0esr/dom/quota/RemoteQuotaObjectParent.cpp thunderbird-140.15.0esr/dom/quota/RemoteQuotaObjectParent.cpp
--- thunderbird-140.14.0esr/dom/quota/RemoteQuotaObjectParent.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/quota/RemoteQuotaObjectParent.cpp 2026-08-28 17:33:06.000000000 +0000
@@ -27,6 +27,11 @@
MOZ_ASSERT(!mozilla::ipc::IsOnBackgroundThread());
MOZ_ASSERT(!GetCurrentThreadWorkerPrivate());
+ QM_TRY(OkIf(aSize >= 0), [&aResult](const auto&) {
+ *aResult = false;
+ return IPC_OK();
+ });
+
*aResult = mCanonicalQuotaObject->MaybeUpdateSize(aSize, aTruncate);
return IPC_OK();
}
diff -Nru thunderbird-140.14.0esr/dom/quota/test/xpcshell/test_estimateOrigin.js thunderbird-140.15.0esr/dom/quota/test/xpcshell/test_estimateOrigin.js
--- thunderbird-140.14.0esr/dom/quota/test/xpcshell/test_estimateOrigin.js 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/quota/test/xpcshell/test_estimateOrigin.js 2026-08-28 17:33:06.000000000 +0000
@@ -70,9 +70,24 @@
info("Verifying origin estimation");
+ // A persisted origin is exempt from group-limit eviction and is bound by the
+ // global limit instead, so it reports its own origin usage (400, not the 700
+ // group total) against that global limit.
await verifyOriginEstimation(
getPrincipal("https://foo2.example2.com"),
- 1000,
+ 400,
+ globalLimitBytes
+ );
+
+ info("Writing to an unrelated group");
+
+ await fillOrigin(getPrincipal("https://foo1.example3.com"), 500);
+
+ info("Verifying the persisted origin does not observe the unrelated write");
+
+ await verifyOriginEstimation(
+ getPrincipal("https://foo2.example2.com"),
+ 400,
globalLimitBytes
);
diff -Nru thunderbird-140.14.0esr/dom/security/nsContentSecurityManager.cpp thunderbird-140.15.0esr/dom/security/nsContentSecurityManager.cpp
--- thunderbird-140.14.0esr/dom/security/nsContentSecurityManager.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/security/nsContentSecurityManager.cpp 2026-08-28 17:33:06.000000000 +0000
@@ -1300,6 +1300,31 @@
nsCOMPtr loadInfo = aChannel->LoadInfo();
+ nsAutoCString triggeringRemoteType;
+ nsresult rv = loadInfo->GetTriggeringRemoteType(triggeringRemoteType);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // Before getting to document-load content policy checks, validate the
+ // principal to inherit against the triggering remote type.
+ EnumSet principalToInheritOptions = {
+ ValidatePrincipalOptions::AllowNullPtr};
+ if (xpc::IsInAutomation()) {
+ // Bug 2011307, chrome reftests run in content.
+ principalToInheritOptions += ValidatePrincipalOptions::AllowSystem;
+ }
+ if (!ValidatePrincipalCouldPotentiallyBeLoadedBy(
+ loadInfo->PrincipalToInherit(), triggeringRemoteType,
+ principalToInheritOptions)) {
+ if (MOZ_LOG_TEST(sUELLog, LogLevel::Warning)) {
+ nsAutoCString origin;
+ loadInfo->PrincipalToInherit()->GetOrigin(origin);
+ MOZ_LOG(sUELLog, LogLevel::Warning,
+ ("Unexpected PrincipalToInherit %s for remote %s", origin.get(),
+ triggeringRemoteType.get()));
+ }
+ return NS_ERROR_CONTENT_BLOCKED;
+ }
+
// For now, only restrict loads for documents. We currently have no
// interesting subresource checks for protocols which are are not fully
// handled within the content process.
@@ -1320,10 +1345,6 @@
return NS_OK;
}
- nsAutoCString triggeringRemoteType;
- nsresult rv = loadInfo->GetTriggeringRemoteType(triggeringRemoteType);
- NS_ENSURE_SUCCESS(rv, rv);
-
// For now, only restrict loads coming from web remote types. In the future we
// may want to expand this a bit.
if (!StringBeginsWith(triggeringRemoteType, WEB_REMOTE_TYPE)) {
diff -Nru thunderbird-140.14.0esr/dom/security/nsContentSecurityUtils.cpp thunderbird-140.15.0esr/dom/security/nsContentSecurityUtils.cpp
--- thunderbird-140.14.0esr/dom/security/nsContentSecurityUtils.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/security/nsContentSecurityUtils.cpp 2026-08-28 17:33:06.000000000 +0000
@@ -1291,7 +1291,6 @@
"chrome://formautofill/content/manageAddresses.xhtml"_ns,
"chrome://formautofill/content/manageCreditCards.xhtml"_ns,
"chrome://gfxsanity/content/sanityparent.html"_ns,
- "chrome://gfxsanity/content/sanitytest.html"_ns,
"chrome://global/content/commonDialog.xhtml"_ns,
"chrome://global/content/resetProfileProgress.xhtml"_ns,
"chrome://layoutdebug/content/layoutdebug.xhtml"_ns,
diff -Nru thunderbird-140.14.0esr/dom/security/test/crashtests/1583044.html thunderbird-140.15.0esr/dom/security/test/crashtests/1583044.html
--- thunderbird-140.14.0esr/dom/security/test/crashtests/1583044.html 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/security/test/crashtests/1583044.html 1970-01-01 00:00:00.000000000 +0000
@@ -1,11 +0,0 @@
-
-
-Bug 1583044
-
-
-
-
diff -Nru thunderbird-140.14.0esr/dom/security/test/crashtests/crashtests.list thunderbird-140.15.0esr/dom/security/test/crashtests/crashtests.list
--- thunderbird-140.14.0esr/dom/security/test/crashtests/crashtests.list 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/security/test/crashtests/crashtests.list 2026-08-28 17:33:06.000000000 +0000
@@ -1,2 +1 @@
-load 1583044.html
load 1577572.html
diff -Nru thunderbird-140.14.0esr/dom/security/test/general/chrome.toml thunderbird-140.15.0esr/dom/security/test/general/chrome.toml
--- thunderbird-140.14.0esr/dom/security/test/general/chrome.toml 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/security/test/general/chrome.toml 2026-08-28 17:33:06.000000000 +0000
@@ -10,3 +10,6 @@
["test_innerhtml_sanitizer.html"]
["test_innerhtml_sanitizer.xhtml"]
+
+["test_image_protocol_document_context.html"]
+skip-if = ["debug"] # Intentional crash in DEBUG builds
diff -Nru thunderbird-140.14.0esr/dom/security/test/general/test_image_protocol_document_context.html thunderbird-140.15.0esr/dom/security/test/general/test_image_protocol_document_context.html
--- thunderbird-140.14.0esr/dom/security/test/general/test_image_protocol_document_context.html 1970-01-01 00:00:00.000000000 +0000
+++ thunderbird-140.15.0esr/dom/security/test/general/test_image_protocol_document_context.html 2026-08-28 17:33:06.000000000 +0000
@@ -0,0 +1,78 @@
+
+
+
+
+ Bug 2044313 - page-icon and moz-icon only load in an image context
+
+
+
+
+
+
+
diff -Nru thunderbird-140.14.0esr/dom/serviceworkers/ServiceWorkerPrivate.cpp thunderbird-140.15.0esr/dom/serviceworkers/ServiceWorkerPrivate.cpp
--- thunderbird-140.14.0esr/dom/serviceworkers/ServiceWorkerPrivate.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/serviceworkers/ServiceWorkerPrivate.cpp 2026-08-28 17:33:06.000000000 +0000
@@ -512,6 +512,20 @@
AssertIsOnMainThread();
MOZ_ASSERT(mInfo);
+ // Initialize() is only ever called from our constructor and there is no retry
+ // mechanism, so on failure this ServiceWorkerPrivate can never become usable;
+ // in particular mRemoteWorkerData would stay default-constructed, and its
+ // OptionalServiceWorkerData union would fatally assert the first time
+ // RefreshRemoteWorkerData() touched it. Neutralize ourselves by clearing
+ // mInfo, which is the same state NoteDeadServiceWorkerInfo() establishes and
+ // which SpawnWorkerIfNeeded() already refuses to act on, so that every
+ // operation fails cleanly instead. For fetch that means the interception is
+ // reset and the request goes to the network.
+ //
+ // Note that we run from within ServiceWorkerInfo's constructor, so mInfo
+ // points at a not-yet-fully-constructed object; this only clears the pointer.
+ auto neutralizeOnFailure = MakeScopeExit([&] { mInfo = nullptr; });
+
nsCOMPtr principal = mInfo->Principal();
nsCOMPtr uri;
@@ -776,12 +790,14 @@
// This fills in the rest of mRemoteWorkerData.serviceWorkerData().
RefreshRemoteWorkerData(regInfo);
+ neutralizeOnFailure.release();
return NS_OK;
}
void ServiceWorkerPrivate::RegenerateClientInfo() {
// inductively, this object can only still be alive after Initialize() if the
- // mClientInfo was correctly initialized.
+ // mClientInfo was correctly initialized; a failed Initialize() clears mInfo,
+ // which stops us from ever spawning a worker and therefore from getting here.
MOZ_DIAGNOSTIC_ASSERT(mClientInfo.isSome());
mClientInfo = ClientManager::CreateInfo(
@@ -940,9 +956,15 @@
const net::CookieStruct& aCookie, bool aCookieDeleted,
RefPtr aRegistration) {
AssertIsOnMainThread();
- MOZ_ASSERT(mInfo);
MOZ_ASSERT(aRegistration);
+ // mInfo is cleared both when our ServiceWorkerInfo dies and when Initialize()
+ // failed, and unlike the ops below we dereference it before delegating to
+ // SpawnWorkerIfNeeded(), which is where that is normally caught.
+ if (NS_WARN_IF(!mInfo)) {
+ return NS_ERROR_DOM_INVALID_STATE_ERR;
+ }
+
ServiceWorkerCookieChangeEventOpArgs args;
args.cookie() = aCookie;
args.deleted() = aCookieDeleted;
@@ -984,9 +1006,15 @@
const nsAString& aMessageId, const Maybe>& aData,
RefPtr aRegistration) {
AssertIsOnMainThread();
- MOZ_ASSERT(mInfo);
MOZ_ASSERT(aRegistration);
+ // mInfo is cleared both when our ServiceWorkerInfo dies and when Initialize()
+ // failed, and unlike the ops below we dereference it before delegating to
+ // SpawnWorkerIfNeeded(), which is where that is normally caught.
+ if (NS_WARN_IF(!mInfo)) {
+ return NS_ERROR_DOM_INVALID_STATE_ERR;
+ }
+
ServiceWorkerPushEventOpArgs args;
args.messageId() = nsString(aMessageId);
@@ -1572,6 +1600,8 @@
// mInfo must be non-null at this point because NoteDeadServiceWorkerInfo
// which zeroes it calls TerminateWorker which cancels our timer which will
// ensure we don't get invoked even if the nsTimerEvent is in the event queue.
+ // The other place which zeroes mInfo, a failed Initialize(), stops us from
+ // ever spawning a worker and therefore from ever arming this timer.
ServiceWorkerManager::LocalizeAndReportToAllClients(
mInfo->Scope(), "ServiceWorkerGraceTimeoutTermination",
nsTArray{NS_ConvertUTF8toUTF16(mInfo->Scope())});
diff -Nru thunderbird-140.14.0esr/dom/simpledb/SDBConnection.cpp thunderbird-140.15.0esr/dom/simpledb/SDBConnection.cpp
--- thunderbird-140.14.0esr/dom/simpledb/SDBConnection.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/simpledb/SDBConnection.cpp 2026-08-28 17:33:05.000000000 +0000
@@ -238,6 +238,12 @@
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPrincipal);
+ if (!BackgroundChild::ValidatePrincipal(aPrincipal, {})) {
+ MOZ_ASSERT_UNREACHABLE(
+ "Process is not allowed to access simpleDB for this principal");
+ return NS_ERROR_INVALID_ARG;
+ }
+
UniquePtr principalInfo(new PrincipalInfo());
nsresult rv = PrincipalToPrincipalInfo(aPrincipal, principalInfo.get());
if (NS_WARN_IF(NS_FAILED(rv))) {
diff -Nru thunderbird-140.14.0esr/dom/storage/LocalStorageManager.cpp thunderbird-140.15.0esr/dom/storage/LocalStorageManager.cpp
--- thunderbird-140.14.0esr/dom/storage/LocalStorageManager.cpp 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/dom/storage/LocalStorageManager.cpp 2026-08-28 17:33:05.000000000 +0000
@@ -153,6 +153,13 @@
nsAutoCString originKey;
nsAutoCString quotaKey;
+ // Throw if this process shouldn't have local storage access for this origin.
+ if (!mozilla::ipc::BackgroundChild::ValidatePrincipal(aStoragePrincipal,
+ {})) {
+ MOZ_ASSERT_UNREACHABLE("ValidatePrincipal failure in GetStorageInternal");
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
aStoragePrincipal->OriginAttributesRef().CreateSuffix(originAttrSuffix);
nsresult rv = aStoragePrincipal->GetStorageOriginKey(originKey);
diff -Nru thunderbird-140.14.0esr/dom/storage/StorageActivityService.cpp thunderbird-140.15.0esr/dom/storage/StorageActivityService.cpp
--- thunderbird-140.14.0esr/dom/storage/StorageActivityService.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/storage/StorageActivityService.cpp 2026-08-28 17:33:06.000000000 +0000
@@ -191,6 +191,11 @@
return;
}
+ if (!::mozilla::ipc::BackgroundChild::ValidatePrincipal(aPrincipal, {})) {
+ MOZ_ASSERT_UNREACHABLE("ValidatePrincipal failure in SendActivityToParent");
+ return;
+ }
+
actor->SendStorageActivity(principalInfo);
}
diff -Nru thunderbird-140.14.0esr/dom/storage/components.conf thunderbird-140.15.0esr/dom/storage/components.conf
--- thunderbird-140.14.0esr/dom/storage/components.conf 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/storage/components.conf 2026-08-28 17:33:06.000000000 +0000
@@ -12,5 +12,6 @@
'interfaces': ['nsISessionStorageService'],
'singleton': True,
'type': 'nsISessionStorageService',
+ 'processes': ProcessSelector.MAIN_PROCESS_ONLY,
},
]
diff -Nru thunderbird-140.14.0esr/dom/webbrowserpersist/PWebBrowserPersistDocument.ipdl thunderbird-140.15.0esr/dom/webbrowserpersist/PWebBrowserPersistDocument.ipdl
--- thunderbird-140.14.0esr/dom/webbrowserpersist/PWebBrowserPersistDocument.ipdl 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/webbrowserpersist/PWebBrowserPersistDocument.ipdl 2026-08-28 17:33:06.000000000 +0000
@@ -14,6 +14,8 @@
include "mozilla/dom/ReferrerInfoUtils.h";
[RefCounted] using class nsIReferrerInfo from "nsIReferrerInfo.h";
+[RefCounted] using class nsIPrincipal from "nsIPrincipal.h";
+[RefCounted] using class nsIInputStream from "mozilla/ipc/IPCStreamUtils.h";
namespace mozilla {
@@ -33,7 +35,6 @@
nsString contentDisposition;
uint32_t sessionHistoryCacheKey;
uint32_t persistFlags;
- PrincipalInfo principal;
};
// IPDL doesn't have tuples, so this gives the pair of strings from
@@ -68,7 +69,8 @@
// is either a response to the constructor (if it was parent->child)
// or sent after it (if it was child->parent).
async Attributes(WebBrowserPersistDocumentAttrs aAttrs,
- IPCStream? stream);
+ nsIPrincipal aPrincipal,
+ nullable nsIInputStream aStream);
async InitFailure(nsresult aStatus);
child:
diff -Nru thunderbird-140.14.0esr/dom/webbrowserpersist/WebBrowserPersistDocumentChild.cpp thunderbird-140.15.0esr/dom/webbrowserpersist/WebBrowserPersistDocumentChild.cpp
--- thunderbird-140.14.0esr/dom/webbrowserpersist/WebBrowserPersistDocumentChild.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/webbrowserpersist/WebBrowserPersistDocumentChild.cpp 2026-08-28 17:33:06.000000000 +0000
@@ -64,7 +64,6 @@
ENSURE(aDocument->GetPersistFlags(&(attrs.persistFlags())));
ENSURE(aDocument->GetPrincipal(getter_AddRefs(principal)));
- ENSURE(ipc::PrincipalToPrincipalInfo(principal, &(attrs.principal())));
ENSURE(aDocument->GetReferrerInfo(getter_AddRefs(referrerInfo)));
attrs.referrerInfo() = referrerInfo;
@@ -76,12 +75,13 @@
ENSURE(aDocument->GetPostData(getter_AddRefs(postDataStream)));
#undef ENSURE
- Maybe stream;
- mozilla::ipc::SerializeIPCStream(postDataStream.forget(), stream,
- /* aAllowLazy */ false);
+ if (!principal) {
+ SendInitFailure(NS_ERROR_NULL_POINTER);
+ return;
+ }
mDocument = aDocument;
- SendAttributes(attrs, stream);
+ SendAttributes(attrs, WrapNotNull(principal), postDataStream);
}
mozilla::ipc::IPCResult WebBrowserPersistDocumentChild::RecvSetPersistFlags(
diff -Nru thunderbird-140.14.0esr/dom/webbrowserpersist/WebBrowserPersistDocumentParent.cpp thunderbird-140.15.0esr/dom/webbrowserpersist/WebBrowserPersistDocumentParent.cpp
--- thunderbird-140.14.0esr/dom/webbrowserpersist/WebBrowserPersistDocumentParent.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/webbrowserpersist/WebBrowserPersistDocumentParent.cpp 2026-08-28 17:33:06.000000000 +0000
@@ -7,7 +7,7 @@
#include "WebBrowserPersistDocumentParent.h"
#include "mozilla/ipc/IPCStreamUtils.h"
-#include "mozilla/dom/PContentParent.h"
+#include "mozilla/dom/ContentParent.h"
#include "nsIInputStream.h"
#include "nsThreadUtils.h"
#include "WebBrowserPersistResourcesParent.h"
@@ -53,14 +53,15 @@
}
mozilla::ipc::IPCResult WebBrowserPersistDocumentParent::RecvAttributes(
- const Attrs& aAttrs, const Maybe& aPostStream) {
- // Deserialize the postData unconditionally so that fds aren't leaked.
- nsCOMPtr postData =
- mozilla::ipc::DeserializeIPCStream(aPostStream);
- if (!mOnReady || mReflection) {
- return IPC_FAIL_NO_REASON(this);
+ Attrs&& aAttrs, NotNull aPrincipal,
+ nsIInputStream* aPostStream) {
+ auto* contentParent = dom::ContentParent::Cast(Manager());
+ if (!contentParent->ValidatePrincipal(aPrincipal, {})) {
+ return IPC_FAIL(this, "invalid principal");
}
- mReflection = new WebBrowserPersistRemoteDocument(this, aAttrs, postData);
+
+ mReflection = new WebBrowserPersistRemoteDocument(this, std::move(aAttrs),
+ aPrincipal, aPostStream);
RefPtr reflection = mReflection;
mOnReady->OnDocumentReady(reflection);
mOnReady = nullptr;
diff -Nru thunderbird-140.14.0esr/dom/webbrowserpersist/WebBrowserPersistDocumentParent.h thunderbird-140.15.0esr/dom/webbrowserpersist/WebBrowserPersistDocumentParent.h
--- thunderbird-140.14.0esr/dom/webbrowserpersist/WebBrowserPersistDocumentParent.h 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/dom/webbrowserpersist/WebBrowserPersistDocumentParent.h 2026-08-28 17:33:06.000000000 +0000
@@ -7,7 +7,6 @@
#ifndef WebBrowserPersistDocumentParent_h__
#define WebBrowserPersistDocumentParent_h__
-#include "mozilla/Maybe.h"
#include "mozilla/PWebBrowserPersistDocumentParent.h"
#include "nsCOMPtr.h"
#include "nsIWebBrowserPersistDocument.h"
@@ -45,8 +44,9 @@
using Attrs = WebBrowserPersistDocumentAttrs;
// IPDL methods:
- mozilla::ipc::IPCResult RecvAttributes(const Attrs& aAttrs,
- const Maybe& aPostStream);
+ mozilla::ipc::IPCResult RecvAttributes(Attrs&& aAttrs,
+ NotNull aPrincipal,
+ nsIInputStream* aPostStream);
mozilla::ipc::IPCResult RecvInitFailure(const nsresult& aFailure);
PWebBrowserPersistResourcesParent* AllocPWebBrowserPersistResourcesParent();
diff -Nru thunderbird-140.14.0esr/dom/webbrowserpersist/WebBrowserPersistRemoteDocument.cpp thunderbird-140.15.0esr/dom/webbrowserpersist/WebBrowserPersistRemoteDocument.cpp
--- thunderbird-140.14.0esr/dom/webbrowserpersist/WebBrowserPersistRemoteDocument.cpp 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/dom/webbrowserpersist/WebBrowserPersistRemoteDocument.cpp 2026-08-28 17:33:05.000000000 +0000
@@ -21,16 +21,12 @@
NS_IMPL_ISUPPORTS(WebBrowserPersistRemoteDocument, nsIWebBrowserPersistDocument)
WebBrowserPersistRemoteDocument ::WebBrowserPersistRemoteDocument(
- WebBrowserPersistDocumentParent* aActor, const Attrs& aAttrs,
- nsIInputStream* aPostData)
- : mActor(aActor), mAttrs(aAttrs), mPostData(aPostData) {
- auto principalOrErr = ipc::PrincipalInfoToPrincipal(mAttrs.principal());
- if (principalOrErr.isOk()) {
- mPrincipal = principalOrErr.unwrap();
- } else {
- NS_WARNING("Failed to obtain principal!");
- }
-
+ WebBrowserPersistDocumentParent* aActor, Attrs&& aAttrs,
+ nsIPrincipal* aPrincipal, nsIInputStream* aPostData)
+ : mActor(aActor),
+ mAttrs(std::move(aAttrs)),
+ mPrincipal(aPrincipal),
+ mPostData(aPostData) {
net::CookieJarSettings::Deserialize(mAttrs.cookieJarSettings(),
getter_AddRefs(mCookieJarSettings));
}
diff -Nru thunderbird-140.14.0esr/dom/webbrowserpersist/WebBrowserPersistRemoteDocument.h thunderbird-140.15.0esr/dom/webbrowserpersist/WebBrowserPersistRemoteDocument.h
--- thunderbird-140.14.0esr/dom/webbrowserpersist/WebBrowserPersistRemoteDocument.h 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/webbrowserpersist/WebBrowserPersistRemoteDocument.h 2026-08-28 17:33:06.000000000 +0000
@@ -42,12 +42,12 @@
Attrs mAttrs;
nsCOMPtr mSHEntry;
nsCOMPtr mCookieJarSettings;
- nsCOMPtr mPostData;
nsCOMPtr mPrincipal;
+ nsCOMPtr mPostData;
friend class WebBrowserPersistDocumentParent;
WebBrowserPersistRemoteDocument(WebBrowserPersistDocumentParent* aActor,
- const Attrs& aAttrs,
+ Attrs&& aAttrs, nsIPrincipal* aPrincipal,
nsIInputStream* aPostData);
~WebBrowserPersistRemoteDocument();
diff -Nru thunderbird-140.14.0esr/dom/workers/sharedworkers/SharedWorker.cpp thunderbird-140.15.0esr/dom/workers/sharedworkers/SharedWorker.cpp
--- thunderbird-140.14.0esr/dom/workers/sharedworkers/SharedWorker.cpp 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/dom/workers/sharedworkers/SharedWorker.cpp 2026-08-28 17:33:07.000000000 +0000
@@ -11,11 +11,11 @@
#include "mozilla/BasePrincipal.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/dom/ClientInfo.h"
+#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/Event.h"
#include "mozilla/dom/MessageChannel.h"
#include "mozilla/dom/MessagePort.h"
#include "mozilla/dom/PMessagePort.h"
-#include "mozilla/dom/RemoteWorkerManager.h" // RemoteWorkerManager::GetRemoteType
#include "mozilla/dom/RemoteWorkerTypes.h"
#include "mozilla/dom/SharedWorkerBinding.h"
#include "mozilla/dom/SharedWorkerChild.h"
@@ -210,6 +210,14 @@
}
}
+ // Throw early if this process would not be allowed to start a shared worker.
+ if (!BackgroundChild::ValidatePrincipal(loadInfo.mLoadingPrincipal, {})) {
+ MOZ_ASSERT_UNREACHABLE(
+ "ValidatePrincipal failure in SharedWorker::Constructor");
+ aRv.ThrowSecurityError("SharedWorker access not available.");
+ return nullptr;
+ }
+
PrincipalInfo partitionedPrincipalInfo;
if (loadInfo.mPrincipal->Equals(loadInfo.mPartitionedPrincipal)) {
partitionedPrincipalInfo = principalInfo;
diff -Nru thunderbird-140.14.0esr/dom/workers/sharedworkers/SharedWorkerService.cpp thunderbird-140.15.0esr/dom/workers/sharedworkers/SharedWorkerService.cpp
--- thunderbird-140.14.0esr/dom/workers/sharedworkers/SharedWorkerService.cpp 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/dom/workers/sharedworkers/SharedWorkerService.cpp 2026-08-28 17:33:06.000000000 +0000
@@ -174,37 +174,29 @@
void SharedWorkerService::GetOrCreateWorkerManagerOnMainThread(
nsIEventTarget* aBackgroundEventTarget,
ThreadsafeContentParentHandle* aContentParentHandle,
- SharedWorkerParent* aActor, const RemoteWorkerData& aData,
- uint64_t aWindowID, UniqueMessagePortId& aPortIdentifier) {
- MOZ_ASSERT(NS_IsMainThread());
+ SharedWorkerParent* aActor, RemoteWorkerData aData, uint64_t aWindowID,
+ UniqueMessagePortId& aPortIdentifier) {
+ AssertIsOnMainThread();
MOZ_ASSERT(aBackgroundEventTarget);
MOZ_ASSERT(aActor);
- RemoteWorkerData copyData = aData;
- auto principalOrErr = PrincipalInfoToPrincipal(copyData.principalInfo());
- if (NS_WARN_IF(principalOrErr.isErr())) {
+ RefPtr contentParent =
+ aContentParentHandle ? aContentParentHandle->GetContentParent() : nullptr;
+ if (aContentParentHandle && !contentParent) {
ErrorPropagationOnMainThread(aBackgroundEventTarget, aActor,
- principalOrErr.unwrapErr());
+ NS_ERROR_UNEXPECTED);
return;
}
- nsCOMPtr principal = principalOrErr.unwrap();
-
- nsCString currentRemoteType = aContentParentHandle
- ? aContentParentHandle->GetRemoteType()
- : NOT_REMOTE_TYPE;
- auto remoteType = RemoteWorkerManager::GetRemoteType(
- principal, WorkerKind::WorkerKindShared, currentRemoteType);
- if (NS_WARN_IF(remoteType.isErr())) {
+ auto principalOrErr = PrincipalInfoToPrincipal(aData.principalInfo());
+ if (NS_WARN_IF(principalOrErr.isErr())) {
ErrorPropagationOnMainThread(aBackgroundEventTarget, aActor,
- remoteType.unwrapErr());
+ principalOrErr.unwrapErr());
return;
}
- copyData.remoteType() = remoteType.unwrap();
-
auto partitionedPrincipalOrErr =
- PrincipalInfoToPrincipal(copyData.partitionedPrincipalInfo());
+ PrincipalInfoToPrincipal(aData.partitionedPrincipalInfo());
if (NS_WARN_IF(partitionedPrincipalOrErr.isErr())) {
ErrorPropagationOnMainThread(aBackgroundEventTarget, aActor,
partitionedPrincipalOrErr.unwrapErr());
@@ -212,32 +204,67 @@
}
auto loadingPrincipalOrErr =
- PrincipalInfoToPrincipal(copyData.loadingPrincipalInfo());
+ PrincipalInfoToPrincipal(aData.loadingPrincipalInfo());
if (NS_WARN_IF(loadingPrincipalOrErr.isErr())) {
ErrorPropagationOnMainThread(aBackgroundEventTarget, aActor,
loadingPrincipalOrErr.unwrapErr());
return;
}
- RefPtr managerHolder;
-
+ nsCOMPtr principal = principalOrErr.unwrap();
nsCOMPtr loadingPrincipal = loadingPrincipalOrErr.unwrap();
nsCOMPtr partitionedPrincipal =
partitionedPrincipalOrErr.unwrap();
+ // If this is being created by a content process, validate that that process
+ // would be allowed to load the SharedWorker.
+ //
+ // This may be hit for cross-origin loads triggered by web content which would
+ // fail later in the load process. As those loads would fail anyway, it should
+ // be OK to fail early here in those cases.
+ if (contentParent) {
+ if (NS_WARN_IF(!contentParent->ValidatePrincipal(loadingPrincipal, {})) ||
+ NS_WARN_IF(!contentParent->ValidatePrincipal(principal, {})) ||
+ NS_WARN_IF(
+ !contentParent->ValidatePrincipal(partitionedPrincipal, {}))) {
+ ErrorPropagationOnMainThread(aBackgroundEventTarget, aActor,
+ NS_ERROR_DOM_SECURITY_ERR);
+ return;
+ }
+ }
+
+ // Determine the remote type this SharedWorker should load into, and clobber
+ // the ununsed remoteType field from the passed-in `RemoteWorkerData` with it.
+ auto remoteType = RemoteWorkerManager::GetRemoteType(
+ principal, WorkerKind::WorkerKindShared,
+ contentParent ? contentParent->GetRemoteType() : NOT_REMOTE_TYPE);
+ if (NS_WARN_IF(remoteType.isErr())) {
+ ErrorPropagationOnMainThread(aBackgroundEventTarget, aActor,
+ remoteType.unwrapErr());
+ return;
+ }
+ aData.remoteType() = remoteType.unwrap();
+
nsCOMPtr effectiveStoragePrincipal = partitionedPrincipal;
- if (copyData.useRegularPrincipal()) {
+ if (aData.useRegularPrincipal()) {
effectiveStoragePrincipal = loadingPrincipal;
}
- // Let's see if there is already a SharedWorker to share.
nsCOMPtr resolvedScriptURL =
- DeserializeURI(copyData.resolvedScriptURL());
+ DeserializeURI(aData.resolvedScriptURL());
+ if (!resolvedScriptURL) {
+ ErrorPropagationOnMainThread(aBackgroundEventTarget, aActor,
+ NS_ERROR_FAILURE);
+ return;
+ }
+
+ // Let's see if there is already a SharedWorker to share.
+ RefPtr managerHolder;
for (SharedWorkerManager* workerManager : mWorkerManagers) {
bool matchNameButNotOptions = false;
managerHolder = workerManager->MatchOnMainThread(
- this, copyData, resolvedScriptURL, loadingPrincipal,
+ this, aData, resolvedScriptURL, loadingPrincipal,
BasePrincipal::Cast(effectiveStoragePrincipal)->OriginAttributesRef(),
&matchNameButNotOptions);
if (managerHolder) {
@@ -254,14 +281,14 @@
// Let's create a new one.
if (!managerHolder) {
managerHolder = SharedWorkerManager::Create(
- this, aBackgroundEventTarget, copyData, loadingPrincipal,
+ this, aBackgroundEventTarget, aData, loadingPrincipal,
BasePrincipal::Cast(effectiveStoragePrincipal)->OriginAttributesRef());
mWorkerManagers.AppendElement(managerHolder->Manager());
} else {
// We are attaching the actor to an existing one.
if (managerHolder->Manager()->IsSecureContext() !=
- copyData.isSecureContext()) {
+ aData.isSecureContext()) {
ErrorPropagationOnMainThread(aBackgroundEventTarget, aActor,
NS_ERROR_DOM_SECURITY_ERR);
return;
@@ -272,7 +299,7 @@
new SharedWorkerManagerWrapper(managerHolder.forget());
RefPtr r = new WorkerManagerCreatedRunnable(
- wrapper.forget(), aActor, copyData, aWindowID, aPortIdentifier);
+ wrapper.forget(), aActor, aData, aWindowID, aPortIdentifier);
aBackgroundEventTarget->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
}
diff -Nru thunderbird-140.14.0esr/dom/workers/sharedworkers/SharedWorkerService.h thunderbird-140.15.0esr/dom/workers/sharedworkers/SharedWorkerService.h
--- thunderbird-140.14.0esr/dom/workers/sharedworkers/SharedWorkerService.h 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/workers/sharedworkers/SharedWorkerService.h 2026-08-28 17:33:06.000000000 +0000
@@ -53,8 +53,8 @@
void GetOrCreateWorkerManagerOnMainThread(
nsIEventTarget* aBackgroundEventTarget,
ThreadsafeContentParentHandle* aContentParentHandle,
- SharedWorkerParent* aActor, const RemoteWorkerData& aData,
- uint64_t aWindowID, UniqueMessagePortId& aPortIdentifier);
+ SharedWorkerParent* aActor, RemoteWorkerData aData, uint64_t aWindowID,
+ UniqueMessagePortId& aPortIdentifier);
void RemoveWorkerManagerOnMainThread(SharedWorkerManager* aManager);
diff -Nru thunderbird-140.14.0esr/dom/xslt/tests/mochitest/test_bug1769155.html thunderbird-140.15.0esr/dom/xslt/tests/mochitest/test_bug1769155.html
--- thunderbird-140.14.0esr/dom/xslt/tests/mochitest/test_bug1769155.html 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/dom/xslt/tests/mochitest/test_bug1769155.html 2026-08-28 17:33:06.000000000 +0000
@@ -38,7 +38,7 @@
});
SpecialPowers.spawn(win, [xml], value => {
- content.location = URL.createObjectURL(new Blob([ value ], { type: "application/xml" }));
+ content.location = content.URL.createObjectURL(new Blob([ value ], { type: "application/xml" }));
});
await redirected;
diff -Nru thunderbird-140.14.0esr/editor/libeditor/EditorBase.cpp thunderbird-140.15.0esr/editor/libeditor/EditorBase.cpp
--- thunderbird-140.14.0esr/editor/libeditor/EditorBase.cpp 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/editor/libeditor/EditorBase.cpp 2026-08-28 17:33:07.000000000 +0000
@@ -313,7 +313,7 @@
// During edit action, selection is cached. But this selection is invalid
// now since selection controller is updated, so we have to update this
// cache.
- Selection* selection = aSelectionController.GetSelection(
+ RefPtr selection = aSelectionController.GetSelection(
nsISelectionController::SELECTION_NORMAL);
NS_WARNING_ASSERTION(selection,
"SelectionController::GetSelection() failed");
diff -Nru thunderbird-140.14.0esr/editor/libeditor/HTMLEditor.cpp thunderbird-140.15.0esr/editor/libeditor/HTMLEditor.cpp
--- thunderbird-140.14.0esr/editor/libeditor/HTMLEditor.cpp 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/editor/libeditor/HTMLEditor.cpp 2026-08-28 17:33:06.000000000 +0000
@@ -7614,7 +7614,7 @@
}
// Compute current editing host.
- Element* const editingHost = ComputeEditingHost();
+ const RefPtr editingHost = ComputeEditingHost();
if (NS_WARN_IF(!editingHost)) {
return;
}
diff -Nru thunderbird-140.14.0esr/editor/libeditor/HTMLEditorDeleteHandler.cpp thunderbird-140.15.0esr/editor/libeditor/HTMLEditorDeleteHandler.cpp
--- thunderbird-140.14.0esr/editor/libeditor/HTMLEditorDeleteHandler.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/editor/libeditor/HTMLEditorDeleteHandler.cpp 2026-08-28 17:33:06.000000000 +0000
@@ -1230,7 +1230,7 @@
AutoClonedSelectionRangeArray& aRangesToDelete) const {
MOZ_ASSERT(IsEditActionDataAvailable());
- Element* editingHost = ComputeEditingHost();
+ RefPtr editingHost = ComputeEditingHost();
if (!editingHost) {
aRangesToDelete.RemoveAllRanges();
return NS_ERROR_EDITOR_NO_EDITABLE_RANGE;
diff -Nru thunderbird-140.14.0esr/editor/libeditor/HTMLTableEditor.cpp thunderbird-140.15.0esr/editor/libeditor/HTMLTableEditor.cpp
--- thunderbird-140.14.0esr/editor/libeditor/HTMLTableEditor.cpp 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/editor/libeditor/HTMLTableEditor.cpp 2026-08-28 17:33:06.000000000 +0000
@@ -723,7 +723,7 @@
}
// Otherwise, insert columns immediately after the previous column.
- Element* previousCellElement =
+ RefPtr previousCellElement =
aPointToInsert.IsEndOfContainer()
? HTMLEditUtils::GetLastTableCellElementChild(
*aPointToInsert.ContainerAs())
diff -Nru thunderbird-140.14.0esr/gfx/2d/DrawTargetCairo.cpp thunderbird-140.15.0esr/gfx/2d/DrawTargetCairo.cpp
--- thunderbird-140.14.0esr/gfx/2d/DrawTargetCairo.cpp 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/gfx/2d/DrawTargetCairo.cpp 2026-08-28 17:33:07.000000000 +0000
@@ -955,7 +955,8 @@
void DrawTargetCairo::DrawFilter(FilterNode* aNode, const Rect& aSourceRect,
const Point& aDestPoint,
const DrawOptions& aOptions) {
- if (!IsValid() || !aNode) {
+ if (!IsValid() || !aNode ||
+ aNode->GetBackendType() != FILTER_BACKEND_SOFTWARE) {
gfxCriticalNote << "DrawFilter with bad surface "
<< cairo_surface_status(cairo_get_group_target(mContext));
return;
diff -Nru thunderbird-140.14.0esr/gfx/layers/wr/AsyncImagePipelineManager.cpp thunderbird-140.15.0esr/gfx/layers/wr/AsyncImagePipelineManager.cpp
--- thunderbird-140.14.0esr/gfx/layers/wr/AsyncImagePipelineManager.cpp 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/gfx/layers/wr/AsyncImagePipelineManager.cpp 2026-08-28 17:33:07.000000000 +0000
@@ -200,7 +200,7 @@
if (auto entry = mAsyncImagePipelines.Lookup(id)) {
const auto& holder = entry.Data();
wr::Epoch epoch = GetNextImageEpoch();
- aTxn.ClearDisplayList(epoch, aPipelineId);
+ aTxn.ClearDisplayList(epoch, mIdNamespace, aPipelineId);
for (wr::ImageKey key : holder->mKeys) {
aTxn.DeleteImage(key);
}
@@ -526,8 +526,9 @@
wr::BuiltDisplayList dl;
aPipeline->mDLBuilder.End(dl);
- aSceneBuilderTxn.SetDisplayList(aEpoch, aPipelineId, dl.dl_desc, dl.dl_items,
- dl.dl_cache, dl.dl_spatial_tree);
+ aSceneBuilderTxn.SetDisplayList(aEpoch, mIdNamespace, aPipelineId, dl.dl_desc,
+ dl.dl_items, dl.dl_cache,
+ dl.dl_spatial_tree);
}
void AsyncImagePipelineManager::ApplyAsyncImageForPipeline(
@@ -619,7 +620,8 @@
wr::BuiltDisplayList dl;
builder.End(dl);
- txn.SetDisplayList(epoch, aPipelineId, dl.dl_desc, dl.dl_items, dl.dl_cache,
+ txn.SetDisplayList(epoch, mIdNamespace, aPipelineId, dl.dl_desc, dl.dl_items,
+ dl.dl_cache,
dl.dl_spatial_tree);
}
diff -Nru thunderbird-140.14.0esr/gfx/layers/wr/WebRenderBridgeParent.cpp thunderbird-140.15.0esr/gfx/layers/wr/WebRenderBridgeParent.cpp
--- thunderbird-140.14.0esr/gfx/layers/wr/WebRenderBridgeParent.cpp 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/gfx/layers/wr/WebRenderBridgeParent.cpp 2026-08-28 17:33:06.000000000 +0000
@@ -1207,8 +1207,8 @@
LayoutDeviceIntRect(LayoutDeviceIntPoint(), widgetSize);
aTxn.SetDocumentView(rect);
}
- aTxn.SetDisplayList(aWrEpoch, mPipelineId, aDLDesc, dlItems, dlCache,
- dlSpatialTreeData);
+ aTxn.SetDisplayList(aWrEpoch, mIdNamespace, mPipelineId, aDLDesc, dlItems,
+ dlCache, dlSpatialTreeData);
MaybeNotifyOfLayers(aTxn, true);
@@ -2066,7 +2066,7 @@
// Clear resources
wr::TransactionBuilder txn(mApi);
txn.SetLowPriority(true);
- txn.ClearDisplayList(GetNextWrEpoch(), mPipelineId);
+ txn.ClearDisplayList(GetNextWrEpoch(), mIdNamespace, mPipelineId);
MaybeNotifyOfLayers(txn, false);
mApi->SendTransaction(txn);
@@ -2871,7 +2871,7 @@
wr::TransactionBuilder txn(mApi);
txn.SetLowPriority(true);
- txn.ClearDisplayList(wrEpoch, mPipelineId);
+ txn.ClearDisplayList(wrEpoch, mIdNamespace, mPipelineId);
for (const auto& entry : mAsyncCompositables) {
wr::PipelineId pipelineId = wr::AsPipelineId(entry.first);
diff -Nru thunderbird-140.14.0esr/gfx/thebes/gfxFont.h thunderbird-140.15.0esr/gfx/thebes/gfxFont.h
--- thunderbird-140.14.0esr/gfx/thebes/gfxFont.h 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/gfx/thebes/gfxFont.h 2026-08-28 17:33:07.000000000 +0000
@@ -1178,23 +1178,29 @@
// debug build), and we'll probably crash.
DetailedGlyph* Get(uint32_t aOffset, uint32_t aCount) {
NS_ASSERTION(mOffsetToIndex.Length() > 0, "no detailed glyph records!");
- // check common cases (fwd iteration, initial entry, etc) first
- if (mLastUsed < mOffsetToIndex.Length() - 1 &&
- aOffset == mOffsetToIndex[mLastUsed + 1].mOffset) {
- ++mLastUsed;
+ // Load the last-used-position hint.
+ nsTArray::index_type lastUsed =
+ mLastUsed.load(std::memory_order_relaxed);
+ // Check common cases (fwd iteration, initial entry, etc) first.
+ if (lastUsed < mOffsetToIndex.Length() - 1 &&
+ aOffset == mOffsetToIndex[lastUsed + 1].mOffset) {
+ ++lastUsed;
} else if (aOffset == mOffsetToIndex[0].mOffset) {
- mLastUsed = 0;
- } else if (aOffset == mOffsetToIndex[mLastUsed].mOffset) {
+ lastUsed = 0;
+ } else if (aOffset == mOffsetToIndex[lastUsed].mOffset) {
// do nothing
- } else if (mLastUsed > 0 &&
- aOffset == mOffsetToIndex[mLastUsed - 1].mOffset) {
- --mLastUsed;
+ } else if (lastUsed > 0 &&
+ aOffset == mOffsetToIndex[lastUsed - 1].mOffset) {
+ --lastUsed;
} else {
- mLastUsed = mOffsetToIndex.BinaryIndexOf(aOffset, CompareToOffset());
+ // None of the fast-paths applied, so do the binary search.
+ lastUsed = mOffsetToIndex.BinaryIndexOf(aOffset, CompareToOffset());
}
- NS_ASSERTION(mLastUsed != nsTArray::NoIndex,
+ NS_ASSERTION(lastUsed != nsTArray::NoIndex,
"detailed glyph record missing!");
- uint32_t index = mOffsetToIndex[mLastUsed].mIndex;
+ uint32_t index = mOffsetToIndex[lastUsed].mIndex;
+ // Remember the position, as a hint for next time.
+ mLastUsed.store(lastUsed, std::memory_order_relaxed);
// Ensure that |aCount| records are available, starting at |index|.
MOZ_RELEASE_ASSERT(index < mDetails.Length() &&
aCount <= mDetails.Length() - index);
@@ -1263,7 +1269,10 @@
// Records the most recently used index into mOffsetToIndex, so that
// we can support sequential access more quickly than just doing
// a binary search each time.
- nsTArray::index_type mLastUsed = 0;
+ // Atomic because multiple threads may be accessing the same shaped-
+ // word or textrun; if so, they may overwrite each other's values and
+ // degrade performance slightly, but this is harmless.
+ std::atomic::index_type> mLastUsed = 0;
};
mozilla::UniquePtr mDetailedGlyphs;
diff -Nru thunderbird-140.14.0esr/gfx/webrender_bindings/RenderTextureHost.h thunderbird-140.15.0esr/gfx/webrender_bindings/RenderTextureHost.h
--- thunderbird-140.14.0esr/gfx/webrender_bindings/RenderTextureHost.h 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/gfx/webrender_bindings/RenderTextureHost.h 2026-08-28 17:33:06.000000000 +0000
@@ -102,6 +102,8 @@
return false;
}
+ virtual void UnlockSWGLCompositeSurface() {}
+
virtual RefPtr CreateTextureSource(
layers::TextureSourceProvider* aProvider);
diff -Nru thunderbird-140.14.0esr/gfx/webrender_bindings/RenderTextureHostSWGL.cpp thunderbird-140.15.0esr/gfx/webrender_bindings/RenderTextureHostSWGL.cpp
--- thunderbird-140.14.0esr/gfx/webrender_bindings/RenderTextureHostSWGL.cpp 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/gfx/webrender_bindings/RenderTextureHostSWGL.cpp 2026-08-28 17:33:06.000000000 +0000
@@ -109,11 +109,11 @@
if (!SetContext(aContext)) {
return InvalidToWrExternalImage();
}
- if (!mLocked) {
+ if (!HasLockedSWGL()) {
if (!UpdatePlanes(aCompositor)) {
return InvalidToWrExternalImage();
}
- mLocked = true;
+ mLockedSWGL = true;
}
if (aChannelIndex >= mPlanes.size()) {
return InvalidToWrExternalImage();
@@ -134,8 +134,8 @@
}
void RenderTextureHostSWGL::UnlockSWGL() {
- if (mLocked) {
- mLocked = false;
+ if (mLockedSWGL) {
+ mLockedSWGL = false;
UnmapPlanes();
}
}
@@ -162,11 +162,11 @@
if (!SetContext(aContext)) {
return false;
}
- if (!mLocked) {
+ if (!HasLockedSWGL()) {
if (!UpdatePlanes(nullptr)) {
return false;
}
- mLocked = true;
+ mLockedSWGLCompositeSurface = true;
}
MOZ_ASSERT(mPlanes.size() <= 3);
for (size_t i = 0; i < mPlanes.size(); i++) {
@@ -197,6 +197,13 @@
return true;
}
+void RenderTextureHostSWGL::UnlockSWGLCompositeSurface() {
+ if (mLockedSWGLCompositeSurface) {
+ mLockedSWGLCompositeSurface = false;
+ UnmapPlanes();
+ }
+}
+
bool wr_swgl_lock_composite_surface(void* aContext, wr::ExternalImageId aId,
wr::SWGLCompositeSurfaceInfo* aInfo) {
RenderTextureHost* texture = RenderThread::Get()->GetRenderTexture(aId);
@@ -219,7 +226,7 @@
if (!swglTex) {
return;
}
- swglTex->UnlockSWGL();
+ swglTex->UnlockSWGLCompositeSurface();
}
} // namespace wr
diff -Nru thunderbird-140.14.0esr/gfx/webrender_bindings/RenderTextureHostSWGL.h thunderbird-140.15.0esr/gfx/webrender_bindings/RenderTextureHostSWGL.h
--- thunderbird-140.14.0esr/gfx/webrender_bindings/RenderTextureHostSWGL.h 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/gfx/webrender_bindings/RenderTextureHostSWGL.h 2026-08-28 17:33:06.000000000 +0000
@@ -51,6 +51,8 @@
bool LockSWGLCompositeSurface(void* aContext,
wr::SWGLCompositeSurfaceInfo* aInfo) override;
+ void UnlockSWGLCompositeSurface() override;
+
size_t BytesFromPlanes() {
NS_ASSERTION(mPlanes.size(), "Can't compute bytes without any planes");
size_t bytes = 0;
@@ -61,7 +63,13 @@
}
protected:
- bool mLocked = false;
+ bool mLockedSWGL = false;
+ bool mLockedSWGLCompositeSurface = false;
+
+ bool HasLockedSWGL() const {
+ return mLockedSWGL || mLockedSWGLCompositeSurface;
+ }
+
void* mContext = nullptr;
std::vector mPlanes;
diff -Nru thunderbird-140.14.0esr/gfx/webrender_bindings/RenderTextureHostWrapper.cpp thunderbird-140.15.0esr/gfx/webrender_bindings/RenderTextureHostWrapper.cpp
--- thunderbird-140.14.0esr/gfx/webrender_bindings/RenderTextureHostWrapper.cpp 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/gfx/webrender_bindings/RenderTextureHostWrapper.cpp 2026-08-28 17:33:07.000000000 +0000
@@ -76,6 +76,12 @@
return mTextureHost->LockSWGLCompositeSurface(aContext, aInfo);
}
+void RenderTextureHostWrapper::UnlockSWGLCompositeSurface() {
+ if (mTextureHost) {
+ mTextureHost->UnlockSWGLCompositeSurface();
+ }
+}
+
void RenderTextureHostWrapper::ClearCachedResources() {
if (mTextureHost) {
mTextureHost->ClearCachedResources();
diff -Nru thunderbird-140.14.0esr/gfx/webrender_bindings/RenderTextureHostWrapper.h thunderbird-140.15.0esr/gfx/webrender_bindings/RenderTextureHostWrapper.h
--- thunderbird-140.14.0esr/gfx/webrender_bindings/RenderTextureHostWrapper.h 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/gfx/webrender_bindings/RenderTextureHostWrapper.h 2026-08-28 17:33:07.000000000 +0000
@@ -71,6 +71,7 @@
void UnlockSWGL() override;
bool LockSWGLCompositeSurface(void* aContext,
wr::SWGLCompositeSurfaceInfo* aInfo) override;
+ void UnlockSWGLCompositeSurface() override;
// This is just a wrapper, so doesn't need to report the
// size of the wrapped object (which reports itself).
diff -Nru thunderbird-140.14.0esr/gfx/webrender_bindings/WebRenderAPI.cpp thunderbird-140.15.0esr/gfx/webrender_bindings/WebRenderAPI.cpp
--- thunderbird-140.14.0esr/gfx/webrender_bindings/WebRenderAPI.cpp 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/gfx/webrender_bindings/WebRenderAPI.cpp 2026-08-28 17:33:07.000000000 +0000
@@ -266,18 +266,20 @@
}
void TransactionBuilder::SetDisplayList(
- Epoch aEpoch, wr::WrPipelineId pipeline_id,
+ Epoch aEpoch, wr::IdNamespace aIdNamespace, wr::WrPipelineId pipeline_id,
wr::BuiltDisplayListDescriptor dl_descriptor,
wr::Vec& dl_items_data, wr::Vec& dl_cache_data,
wr::Vec& dl_spatial_tree) {
- wr_transaction_set_display_list(mTxn, aEpoch, pipeline_id, dl_descriptor,
- &dl_items_data.inner, &dl_cache_data.inner,
+ wr_transaction_set_display_list(mTxn, aEpoch, aIdNamespace, pipeline_id,
+ dl_descriptor, &dl_items_data.inner,
+ &dl_cache_data.inner,
&dl_spatial_tree.inner);
}
void TransactionBuilder::ClearDisplayList(Epoch aEpoch,
+ wr::IdNamespace aIdNamespace,
wr::WrPipelineId aPipelineId) {
- wr_transaction_clear_display_list(mTxn, aEpoch, aPipelineId);
+ wr_transaction_clear_display_list(mTxn, aEpoch, aIdNamespace, aPipelineId);
}
void TransactionBuilder::GenerateFrame(const VsyncId& aVsyncId, bool aPresent,
diff -Nru thunderbird-140.14.0esr/gfx/webrender_bindings/WebRenderAPI.h thunderbird-140.15.0esr/gfx/webrender_bindings/WebRenderAPI.h
--- thunderbird-140.14.0esr/gfx/webrender_bindings/WebRenderAPI.h 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/gfx/webrender_bindings/WebRenderAPI.h 2026-08-28 17:33:07.000000000 +0000
@@ -124,13 +124,18 @@
void RemovePipeline(PipelineId aPipelineId);
- void SetDisplayList(Epoch aEpoch, wr::WrPipelineId pipeline_id,
+ // aIdNamespace is the namespace whose resources the display list is allowed
+ // to reference. It must be supplied by the compositor-side owner of the
+ // pipeline.
+ void SetDisplayList(Epoch aEpoch, wr::IdNamespace aIdNamespace,
+ wr::WrPipelineId pipeline_id,
wr::BuiltDisplayListDescriptor dl_descriptor,
wr::Vec& dl_items_data,
wr::Vec& dl_cache_data,
wr::Vec& dl_spatial_tree);
- void ClearDisplayList(Epoch aEpoch, wr::WrPipelineId aPipeline);
+ void ClearDisplayList(Epoch aEpoch, wr::IdNamespace aIdNamespace,
+ wr::WrPipelineId aPipeline);
void GenerateFrame(const VsyncId& aVsyncId, bool aPresent,
wr::RenderReasons aReasons);
diff -Nru thunderbird-140.14.0esr/gfx/webrender_bindings/src/bindings.rs thunderbird-140.15.0esr/gfx/webrender_bindings/src/bindings.rs
--- thunderbird-140.14.0esr/gfx/webrender_bindings/src/bindings.rs 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/gfx/webrender_bindings/src/bindings.rs 2026-08-28 17:33:06.000000000 +0000
@@ -2238,6 +2238,7 @@
pub extern "C" fn wr_transaction_set_display_list(
txn: &mut Transaction,
epoch: WrEpoch,
+ namespace: WrIdNamespace,
pipeline_id: WrPipelineId,
dl_descriptor: BuiltDisplayListDescriptor,
dl_items_data: &mut WrVecU8,
@@ -2252,7 +2253,7 @@
let dl = BuiltDisplayList::from_data(payload, dl_descriptor);
- txn.set_display_list(epoch, (pipeline_id, dl));
+ txn.set_display_list(epoch, namespace, (pipeline_id, dl));
}
#[no_mangle]
@@ -2574,12 +2575,13 @@
pub unsafe extern "C" fn wr_transaction_clear_display_list(
txn: &mut Transaction,
epoch: WrEpoch,
+ namespace: WrIdNamespace,
pipeline_id: WrPipelineId,
) {
let mut frame_builder = WebRenderFrameBuilder::new(pipeline_id);
frame_builder.dl_builder.begin();
- txn.set_display_list(epoch, frame_builder.dl_builder.end());
+ txn.set_display_list(epoch, namespace, frame_builder.dl_builder.end());
}
#[no_mangle]
diff -Nru thunderbird-140.14.0esr/gfx/wr/example-compositor/compositor/src/main.rs thunderbird-140.15.0esr/gfx/wr/example-compositor/compositor/src/main.rs
--- thunderbird-140.14.0esr/gfx/wr/example-compositor/compositor/src/main.rs 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/gfx/wr/example-compositor/compositor/src/main.rs 2026-08-28 17:33:06.000000000 +0000
@@ -484,7 +484,7 @@
inv_mode,
);
- txn.set_display_list(current_epoch, root_builder.end());
+ txn.set_display_list(current_epoch, api.get_namespace_id(), root_builder.end());
}
txn.generate_frame(0, true, RenderReasons::empty());
@@ -517,7 +517,7 @@
inv_mode,
);
- txn.set_display_list(current_epoch, root_builder.end());
+ txn.set_display_list(current_epoch, api.get_namespace_id(), root_builder.end());
}
Invalidations::Scrolling => {
let d = 0.5 - 0.5 * (2.0 * f32::consts::PI * 5.0 * time).cos();
diff -Nru thunderbird-140.14.0esr/gfx/wr/examples/common/boilerplate.rs thunderbird-140.15.0esr/gfx/wr/examples/common/boilerplate.rs
--- thunderbird-140.14.0esr/gfx/wr/examples/common/boilerplate.rs 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/gfx/wr/examples/common/boilerplate.rs 2026-08-28 17:33:07.000000000 +0000
@@ -207,6 +207,7 @@
);
txn.set_display_list(
epoch,
+ api.get_namespace_id(),
builder.end(),
);
txn.set_root_pipeline(pipeline_id);
@@ -304,6 +305,7 @@
);
txn.set_display_list(
epoch,
+ api.get_namespace_id(),
builder.end(),
);
txn.generate_frame(0, true, RenderReasons::empty());
diff -Nru thunderbird-140.14.0esr/gfx/wr/examples/document.rs thunderbird-140.15.0esr/gfx/wr/examples/document.rs
--- thunderbird-140.14.0esr/gfx/wr/examples/document.rs 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/gfx/wr/examples/document.rs 2026-08-28 17:33:07.000000000 +0000
@@ -120,6 +120,7 @@
let mut txn = Transaction::new();
txn.set_display_list(
Epoch(0),
+ api.get_namespace_id(),
builder.end(),
);
txn.generate_frame(0, true, RenderReasons::empty());
diff -Nru thunderbird-140.14.0esr/gfx/wr/examples/iframe.rs thunderbird-140.15.0esr/gfx/wr/examples/iframe.rs
--- thunderbird-140.14.0esr/gfx/wr/examples/iframe.rs 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/gfx/wr/examples/iframe.rs 2026-08-28 17:33:07.000000000 +0000
@@ -57,6 +57,7 @@
let mut txn = Transaction::new();
txn.set_display_list(
Epoch(0),
+ api.get_namespace_id(),
sub_builder.end(),
);
api.send_transaction(document_id, txn);
diff -Nru thunderbird-140.14.0esr/gfx/wr/examples/multiwindow.rs thunderbird-140.15.0esr/gfx/wr/examples/multiwindow.rs
--- thunderbird-140.14.0esr/gfx/wr/examples/multiwindow.rs 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/gfx/wr/examples/multiwindow.rs 2026-08-28 17:33:07.000000000 +0000
@@ -275,6 +275,7 @@
txn.set_display_list(
self.epoch,
+ api.get_namespace_id(),
builder.end(),
);
txn.set_root_pipeline(self.pipeline_id);
diff -Nru thunderbird-140.14.0esr/gfx/wr/webrender/src/render_api.rs thunderbird-140.15.0esr/gfx/wr/webrender/src/render_api.rs
--- thunderbird-140.14.0esr/gfx/wr/webrender/src/render_api.rs 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/gfx/wr/webrender/src/render_api.rs 2026-08-28 17:33:07.000000000 +0000
@@ -292,11 +292,17 @@
/// Arguments:
///
/// * `epoch`: The unique Frame ID, monotonically increasing.
+ /// * `namespace`: The id namespace that owns the resources this display list
+ /// is allowed to reference. It must be provided by the (trusted) code that
+ /// submits the display list, never by whoever built the display list: it is
+ /// what lets the scene builder reject references to resources belonging to
+ /// another namespace.
/// * `pipeline_id`: The ID of the pipeline that is supplying this display list.
/// * `display_list`: The root Display list used in this frame.
pub fn set_display_list(
&mut self,
epoch: Epoch,
+ namespace: IdNamespace,
(pipeline_id, mut display_list): (PipelineId, BuiltDisplayList),
) {
display_list.set_send_time_ns(precise_time_ns());
@@ -305,6 +311,7 @@
display_list,
epoch,
pipeline_id,
+ namespace,
}
);
}
@@ -817,6 +824,8 @@
epoch: Epoch,
///
pipeline_id: PipelineId,
+ /// The id namespace owning the resources this display list may reference.
+ namespace: IdNamespace,
},
///
SetDocumentView {
diff -Nru thunderbird-140.14.0esr/gfx/wr/webrender/src/scene.rs thunderbird-140.15.0esr/gfx/wr/webrender/src/scene.rs
--- thunderbird-140.14.0esr/gfx/wr/webrender/src/scene.rs 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/gfx/wr/webrender/src/scene.rs 2026-08-28 17:33:07.000000000 +0000
@@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-use api::{BuiltDisplayList, DisplayListWithCache, ColorF, DynamicProperties, Epoch, FontRenderMode};
+use api::{BuiltDisplayList, DisplayListWithCache, ColorF, DynamicProperties, Epoch, FontRenderMode, IdNamespace};
use api::{PipelineId, PropertyBinding, PropertyBindingId, PropertyValue, MixBlendMode, StackingContext};
use api::units::*;
use api::channel::Sender;
@@ -175,6 +175,9 @@
#[derive(Clone)]
pub struct ScenePipeline {
pub display_list: DisplayListWithCache,
+ /// The id namespace that owns the resources this display list is allowed to
+ /// reference.
+ pub namespace: IdNamespace,
}
/// A complete representation of the layout bundling visible pipelines together.
@@ -204,6 +207,7 @@
&mut self,
pipeline_id: PipelineId,
epoch: Epoch,
+ namespace: IdNamespace,
display_list: BuiltDisplayList,
) {
// Adds a cache to the given display list. If this pipeline already had
@@ -218,6 +222,7 @@
let new_pipeline = ScenePipeline {
display_list,
+ namespace,
};
self.pipelines.insert(pipeline_id, new_pipeline);
diff -Nru thunderbird-140.14.0esr/gfx/wr/webrender/src/scene_builder_thread.rs thunderbird-140.15.0esr/gfx/wr/webrender/src/scene_builder_thread.rs
--- thunderbird-140.14.0esr/gfx/wr/webrender/src/scene_builder_thread.rs 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/gfx/wr/webrender/src/scene_builder_thread.rs 2026-08-28 17:33:07.000000000 +0000
@@ -559,6 +559,7 @@
epoch,
pipeline_id,
display_list,
+ namespace,
} => {
let (builder_start_time_ns, builder_end_time_ns, send_time_ns) =
display_list.times();
@@ -585,6 +586,7 @@
scene.set_display_list(
pipeline_id,
epoch,
+ namespace,
display_list,
);
}
diff -Nru thunderbird-140.14.0esr/gfx/wr/webrender/src/scene_building.rs thunderbird-140.15.0esr/gfx/wr/webrender/src/scene_building.rs
--- thunderbird-140.14.0esr/gfx/wr/webrender/src/scene_building.rs 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/gfx/wr/webrender/src/scene_building.rs 2026-08-28 17:33:07.000000000 +0000
@@ -39,7 +39,7 @@
use api::{ClipId, ColorF, CommonItemProperties, ComplexClipRegion, ComponentTransferFuncType, RasterSpace};
use api::{DebugFlags, DisplayItem, DisplayItemRef, ExtendMode, ExternalScrollId, FilterData};
use api::{FilterOp, FilterPrimitive, FontInstanceKey, FontSize, GlyphInstance, GlyphOptions, GradientStop};
-use api::{IframeDisplayItem, ImageKey, ImageRendering, ItemRange, ColorDepth, QualitySettings};
+use api::{IdNamespace, IframeDisplayItem, ImageKey, ImageRendering, ItemRange, ColorDepth, QualitySettings};
use api::{LineOrientation, LineStyle, NinePatchBorderSource, PipelineId, MixBlendMode, StackingContextFlags};
use api::{PropertyBinding, ReferenceFrameKind, ScrollFrameDescriptor};
use api::{APZScrollGeneration, HasScrollLinkedEffect, Shadow, SpatialId, StickyFrameDescriptor, ImageMask, ItemTag};
@@ -945,6 +945,9 @@
}
struct BuildContext<'a> {
pipeline_id: PipelineId,
+ /// Namespace the items traversed in this context are allowed to
+ /// reference resources from. See `ScenePipeline::namespace`.
+ namespace: IdNamespace,
kind: ContextKind<'a>,
}
@@ -964,6 +967,7 @@
let mut stack = vec![BuildContext {
pipeline_id: root_pipeline_id,
+ namespace: root_pipeline.namespace,
kind: ContextKind::Root,
}];
let mut traversal = root_pipeline.display_list.iter();
@@ -991,7 +995,9 @@
continue;
}
- let snapshot = info.snapshot.map(|snapshot| {
+ let snapshot = info.snapshot.filter(|snapshot| {
+ validate_image_key(snapshot.key.as_image(), bc.namespace)
+ }).map(|snapshot| {
// Offset the snapshot area by the stacking context origin
// so that the area is expressed in the same coordinate space
// as the items in the stacking context.
@@ -1022,6 +1028,7 @@
let new_context = BuildContext {
pipeline_id: bc.pipeline_id,
+ namespace: bc.namespace,
kind: ContextKind::StackingContext {
sc_info,
},
@@ -1039,6 +1046,7 @@
let new_context = BuildContext {
pipeline_id: bc.pipeline_id,
+ namespace: bc.namespace,
kind: ContextKind::ReferenceFrame,
};
stack.push(bc);
@@ -1054,13 +1062,20 @@
profile_scope!("iframe");
let space = self.get_space(info.space_and_clip.spatial_id);
- let subtraversal = match self.push_iframe(info, space) {
+ // Note: the referenced pipeline is not checked against the
+ // parent pipeline's namespace. Nesting pipelines across
+ // namespaces is legitimate (a content process embeds the
+ // pipelines of its out-of-process iframes and of its async
+ // image pipelines), so validating iframe references needs
+ // ownership information webrender doesn't have.
+ let (namespace, subtraversal) = match self.push_iframe(info, space) {
Some(pair) => pair,
None => continue,
};
let new_context = BuildContext {
pipeline_id: info.pipeline_id,
+ namespace,
kind: ContextKind::Iframe {
parent_traversal: mem::replace(&mut traversal, subtraversal),
},
@@ -1070,7 +1085,7 @@
continue 'outer;
}
_ => {
- self.build_item(item);
+ self.build_item(item, bc.namespace);
}
};
}
@@ -1267,7 +1282,7 @@
&mut self,
info: &IframeDisplayItem,
spatial_node_index: SpatialNodeIndex,
- ) -> Option> {
+ ) -> Option<(IdNamespace, BuiltDisplayListIter<'a>)> {
let iframe_pipeline_id = info.pipeline_id;
let pipeline = match self.scene.pipelines.get(&iframe_pipeline_id) {
Some(pipeline) => pipeline,
@@ -1346,7 +1361,7 @@
instance_id,
);
- Some(pipeline.display_list.iter())
+ Some((pipeline.namespace, pipeline.display_list.iter()))
}
fn get_space(
@@ -1450,14 +1465,22 @@
self.snap_to_device.snap_rect(&rect)
}
+ /// `namespace` is the id namespace this display list is allowed to reference
+ /// resources from; items referencing anything else are dropped. See
+ /// `validate_resource_namespace`.
fn build_item<'b>(
&'b mut self,
item: DisplayItemRef,
+ namespace: IdNamespace,
) {
match *item.item() {
DisplayItem::Image(ref info) => {
profile_scope!("image");
+ if !validate_image_key(info.image_key, namespace) {
+ return;
+ }
+
let (layout, _, spatial_node_index, clip_node_id) = self.process_common_properties_with_bounds(
&info.common,
info.bounds,
@@ -1478,6 +1501,10 @@
DisplayItem::RepeatingImage(ref info) => {
profile_scope!("repeating_image");
+ if !validate_image_key(info.image_key, namespace) {
+ return;
+ }
+
let (layout, unsnapped_rect, spatial_node_index, clip_node_id) = self.process_common_properties_with_bounds(
&info.common,
info.bounds,
@@ -1504,6 +1531,10 @@
DisplayItem::YuvImage(ref info) => {
profile_scope!("yuv_image");
+ if !validate_yuv_data(&info.yuv_data, namespace) {
+ return;
+ }
+
let (layout, _, spatial_node_index, clip_node_id) = self.process_common_properties_with_bounds(
&info.common,
info.bounds,
@@ -1523,6 +1554,10 @@
DisplayItem::Text(ref info) => {
profile_scope!("text");
+ if !validate_font_instance_key(info.font_key, namespace) {
+ return;
+ }
+
// TODO(aosmond): Snapping text primitives does not make much sense, given the
// primitive bounds and clip are supposed to be conservative, not definitive.
// E.g. they should be able to grow and not impact the output. However there
@@ -1867,6 +1902,14 @@
DisplayItem::Border(ref info) => {
profile_scope!("border");
+ if let BorderDetails::NinePatch(ref border) = info.details {
+ if let NinePatchBorderSource::Image(key, _) = border.source {
+ if !validate_image_key(key, namespace) {
+ return;
+ }
+ }
+ }
+
let (layout, _, spatial_node_index, clip_node_id) = self.process_common_properties_with_bounds(
&info.common,
info.bounds,
@@ -1883,10 +1926,23 @@
DisplayItem::ImageMaskClip(ref info) => {
profile_scope!("image_clip");
+ // The clip node has to be defined either way, since later clip
+ // chain items refer to it by id. Neutralize a foreign mask into
+ // an empty one, which clips everything out, rather than dropping
+ // the clip and letting the masked content draw unclipped.
+ let image_mask = if validate_image_key(info.image_mask.image, namespace) {
+ info.image_mask
+ } else {
+ ImageMask {
+ image: ImageKey::DUMMY,
+ rect: LayoutRect::zero(),
+ }
+ };
+
self.add_image_mask_clip_node(
info.id,
info.spatial_id,
- &info.image_mask,
+ &image_mask,
info.fill_rule,
item.points(),
);
@@ -3746,13 +3802,7 @@
image_rendering: ImageRendering,
) {
let format = yuv_data.get_format();
- let yuv_key = match yuv_data {
- YuvData::NV12(plane_0, plane_1) => [plane_0, plane_1, ImageKey::DUMMY],
- YuvData::P010(plane_0, plane_1) => [plane_0, plane_1, ImageKey::DUMMY],
- YuvData::NV16(plane_0, plane_1) => [plane_0, plane_1, ImageKey::DUMMY],
- YuvData::PlanarYCbCr(plane_0, plane_1, plane_2) => [plane_0, plane_1, plane_2],
- YuvData::InterleavedYCbCr(plane_0) => [plane_0, ImageKey::DUMMY, ImageKey::DUMMY],
- };
+ let yuv_key = yuv_planes(&yuv_data);
self.add_nonshadowable_primitive(
spatial_node_index,
@@ -4895,6 +4945,60 @@
}).collect()
}
+/// Resource keys embedded in display items are only unique within the id
+/// namespace that minted them, and all namespaces of a window share a single
+/// `ResourceCache`. A key read out of a display item must be checked against
+/// the namespace the display list was submitted with before it can be used
+/// to look a resource up.
+fn resource_namespace_matches(key_namespace: IdNamespace, namespace: IdNamespace) -> bool {
+ // Namespace 0 is never handed out, so it is only ever the "no resource"
+ // sentinel (`ImageKey::DUMMY` and friends) and cannot name a resource.
+ key_namespace == namespace || key_namespace.0 == 0
+}
+
+fn validate_resource_namespace(
+ key_namespace: IdNamespace,
+ namespace: IdNamespace,
+ kind: &'static str,
+) -> bool {
+ if resource_namespace_matches(key_namespace, namespace) {
+ return true;
+ }
+
+ warn!(
+ "Ignoring {} referencing id namespace {:?} from a display list owned by {:?}",
+ kind, key_namespace, namespace,
+ );
+ debug_assert!(false, "display list references a resource of a foreign id namespace");
+
+ false
+}
+
+fn validate_image_key(key: ImageKey, namespace: IdNamespace) -> bool {
+ validate_resource_namespace(key.0, namespace, "image key")
+}
+
+/// The planes a `YuvData` actually references, padded with `ImageKey::DUMMY`.
+/// Shared by validation and `add_yuv_image` so that the set of keys checked is
+/// by construction the set of keys used.
+fn yuv_planes(yuv_data: &YuvData) -> [ImageKey; 3] {
+ match *yuv_data {
+ YuvData::NV12(p0, p1)
+ | YuvData::P010(p0, p1)
+ | YuvData::NV16(p0, p1) => [p0, p1, ImageKey::DUMMY],
+ YuvData::PlanarYCbCr(p0, p1, p2) => [p0, p1, p2],
+ YuvData::InterleavedYCbCr(p0) => [p0, ImageKey::DUMMY, ImageKey::DUMMY],
+ }
+}
+
+fn validate_yuv_data(yuv_data: &YuvData, namespace: IdNamespace) -> bool {
+ yuv_planes(yuv_data).iter().all(|key| validate_image_key(*key, namespace))
+}
+
+fn validate_font_instance_key(key: FontInstanceKey, namespace: IdNamespace) -> bool {
+ validate_resource_namespace(key.0, namespace, "font instance key")
+}
+
/// A helper for reusing the scene builder's memory allocations and dropping
/// scene allocations on the scene builder thread to avoid lock contention in
/// jemalloc.
diff -Nru thunderbird-140.14.0esr/gfx/wr/wrench/src/rawtest.rs thunderbird-140.15.0esr/gfx/wr/wrench/src/rawtest.rs
--- thunderbird-140.14.0esr/gfx/wr/wrench/src/rawtest.rs 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/gfx/wr/wrench/src/rawtest.rs 2026-08-28 17:33:07.000000000 +0000
@@ -93,6 +93,7 @@
txn.set_display_list(
*epoch,
+ self.wrench.api.get_namespace_id(),
builder.end(),
);
epoch.0 += 1;
@@ -1235,6 +1236,7 @@
txn.set_display_list(
Epoch(0),
+ self.wrench.api.get_namespace_id(),
builder.end(),
);
txn.generate_frame(0, true, RenderReasons::TESTING);
@@ -1254,6 +1256,7 @@
let mut txn = Transaction::new();
txn.set_display_list(
Epoch(1),
+ self.wrench.api.get_namespace_id(),
builder.end(),
);
self.wrench.api.send_transaction(self.wrench.document_id, txn);
@@ -1298,6 +1301,7 @@
txn.set_root_pipeline(self.wrench.root_pipeline_id);
txn.set_display_list(
Epoch(1),
+ self.wrench.api.get_namespace_id(),
builder.end(),
);
txn.generate_frame(0, true, RenderReasons::TESTING);
diff -Nru thunderbird-140.14.0esr/gfx/wr/wrench/src/wrench.rs thunderbird-140.15.0esr/gfx/wr/wrench/src/wrench.rs
--- thunderbird-140.14.0esr/gfx/wr/wrench/src/wrench.rs 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/gfx/wr/wrench/src/wrench.rs 2026-08-28 17:33:07.000000000 +0000
@@ -441,6 +441,20 @@
)
}
+ #[cfg(all(unix, not(target_os = "android")))]
+ pub fn font_key_from_name(&mut self, font_name: &str) -> FontKey {
+ let property = system_fonts::FontPropertyBuilder::new()
+ .family(font_name)
+ .build();
+ let (font, index) = system_fonts::get(&property).unwrap();
+ self.font_key_from_bytes(font, index as u32)
+ }
+
+ #[cfg(target_os = "android")]
+ pub fn font_key_from_name(&mut self, _font_name: &str) -> FontKey {
+ unimplemented!()
+ }
+
#[cfg(target_os = "windows")]
pub fn font_key_from_properties(
&mut self,
@@ -500,20 +514,6 @@
unimplemented!()
}
- #[cfg(all(unix, not(target_os = "android")))]
- pub fn font_key_from_name(&mut self, font_name: &str) -> FontKey {
- let property = system_fonts::FontPropertyBuilder::new()
- .family(font_name)
- .build();
- let (font, index) = system_fonts::get(&property).unwrap();
- self.font_key_from_bytes(font, index as u32)
- }
-
- #[cfg(target_os = "android")]
- pub fn font_key_from_name(&mut self, _font_name: &str) -> FontKey {
- unimplemented!()
- }
-
pub fn font_key_from_bytes(&mut self, bytes: Vec, index: u32) -> FontKey {
let key = self.api.generate_font_key();
let mut txn = Transaction::new();
@@ -572,6 +572,7 @@
txn.set_display_list(
Epoch(*frame_number),
+ self.api.get_namespace_id(),
(display_list.pipeline, display_list.payload),
);
diff -Nru thunderbird-140.14.0esr/image/ImageBlocker.cpp thunderbird-140.15.0esr/image/ImageBlocker.cpp
--- thunderbird-140.14.0esr/image/ImageBlocker.cpp 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/image/ImageBlocker.cpp 2026-08-28 17:33:06.000000000 +0000
@@ -25,9 +25,7 @@
return NS_OK;
}
- ExtContentPolicyType contentType = aLoadInfo->GetExternalContentPolicyType();
- if (contentType != ExtContentPolicy::TYPE_IMAGE &&
- contentType != ExtContentPolicy::TYPE_IMAGESET) {
+ if (!nsContentUtils::IsImageType(aLoadInfo->GetExternalContentPolicyType())) {
return NS_OK;
}
diff -Nru thunderbird-140.14.0esr/image/decoders/icon/components.conf thunderbird-140.15.0esr/image/decoders/icon/components.conf
--- thunderbird-140.14.0esr/image/decoders/icon/components.conf 2026-08-18 02:52:33.000000000 +0000
+++ thunderbird-140.15.0esr/image/decoders/icon/components.conf 2026-08-28 17:33:06.000000000 +0000
@@ -25,5 +25,6 @@
'cid': '{1460df3b-774c-4205-8349-838e507c3ef9}',
'type': 'nsMozIconURI::Mutator',
'headers': ['/image/decoders/icon/nsIconURI.h'],
+ 'serializable': True,
},
]
diff -Nru thunderbird-140.14.0esr/image/decoders/icon/nsIconProtocolHandler.cpp thunderbird-140.15.0esr/image/decoders/icon/nsIconProtocolHandler.cpp
--- thunderbird-140.14.0esr/image/decoders/icon/nsIconProtocolHandler.cpp 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/image/decoders/icon/nsIconProtocolHandler.cpp 2026-08-28 17:33:07.000000000 +0000
@@ -6,6 +6,7 @@
#include "nsIconProtocolHandler.h"
+#include "nsContentUtils.h"
#include "nsIconChannel.h"
#include "nsIconURI.h"
#include "nsCRT.h"
@@ -39,16 +40,19 @@
}
NS_IMETHODIMP
-nsIconProtocolHandler::NewChannel(nsIURI* url, nsILoadInfo* aLoadInfo,
+nsIconProtocolHandler::NewChannel(nsIURI* aUrl, nsILoadInfo* aLoadInfo,
nsIChannel** result) {
- NS_ENSURE_ARG_POINTER(url);
+ if (!nsContentUtils::IsImageType(aLoadInfo->GetExternalContentPolicyType())) {
+ return NS_ERROR_CONTENT_BLOCKED;
+ }
+
nsIconChannel* channel = new nsIconChannel;
if (!channel) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(channel);
- nsresult rv = channel->Init(url, aLoadInfo);
+ nsresult rv = channel->Init(aUrl, aLoadInfo);
if (NS_FAILED(rv)) {
NS_RELEASE(channel);
return rv;
diff -Nru thunderbird-140.14.0esr/ipc/glue/BackgroundChild.h thunderbird-140.15.0esr/ipc/glue/BackgroundChild.h
--- thunderbird-140.14.0esr/ipc/glue/BackgroundChild.h 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/ipc/glue/BackgroundChild.h 2026-08-28 17:33:07.000000000 +0000
@@ -9,6 +9,8 @@
#include "mozilla/Attributes.h"
+#include "mozilla/dom/ProcessIsolation.h"
+
class nsIEventTarget;
namespace mozilla {
@@ -65,6 +67,17 @@
// See above.
static void InitContentStarter(mozilla::dom::ContentChild* aContent);
+ // Helpers for doing ValidatePrincipal checks within the content process.
+ //
+ // These can be called from any thread, and validate the given principal
+ // against the process's current remote type.
+ static bool ValidatePrincipal(
+ nsIPrincipal* aPrincipal,
+ const EnumSet& aOptions);
+ static bool ValidatePrincipalInfo(
+ const PrincipalInfo& aPrincipalInfo,
+ const EnumSet& aOptions);
+
private:
// Only called by this class's friends.
static void Startup();
diff -Nru thunderbird-140.14.0esr/ipc/glue/BackgroundImpl.cpp thunderbird-140.15.0esr/ipc/glue/BackgroundImpl.cpp
--- thunderbird-140.14.0esr/ipc/glue/BackgroundImpl.cpp 2026-08-18 02:52:35.000000000 +0000
+++ thunderbird-140.15.0esr/ipc/glue/BackgroundImpl.cpp 2026-08-28 17:33:08.000000000 +0000
@@ -27,6 +27,7 @@
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/File.h"
+#include "mozilla/dom/ProcessIsolation.h"
#include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/dom/WorkerRef.h"
#include "mozilla/ipc/BackgroundStarterChild.h"
@@ -678,6 +679,33 @@
}
// static
+nsCString BackgroundParent::GetRemoteType(PBackgroundParent* aBackgroundActor) {
+ ThreadsafeContentParentHandle* handle =
+ GetContentParentHandle(aBackgroundActor);
+ return handle ? handle->GetRemoteType() : NOT_REMOTE_TYPE;
+}
+
+// static
+bool BackgroundParent::ValidatePrincipal(
+ PBackgroundParent* aBackgroundActor, nsIPrincipal* aPrincipal,
+ const EnumSet& aOptions) {
+ return ValidatePrincipalCouldPotentiallyBeLoadedBy(
+ aPrincipal, GetRemoteType(aBackgroundActor), aOptions);
+}
+
+// static
+bool BackgroundParent::ValidatePrincipalInfo(
+ PBackgroundParent* aBackgroundActor, const PrincipalInfo& aPrincipal,
+ const EnumSet& aOptions) {
+ auto result = PrincipalInfoToPrincipal(aPrincipal);
+ if (NS_WARN_IF(result.isErr())) {
+ return false;
+ }
+
+ return ValidatePrincipal(aBackgroundActor, result.inspect(), aOptions);
+}
+
+// static
void BackgroundParent::KillHardAsync(PBackgroundParent* aBackgroundActor,
const nsACString& aReason) {
ParentImpl::KillHardAsync(aBackgroundActor, aReason);
@@ -716,6 +744,26 @@
ChildImpl::InitContentStarter(aContent);
}
+// static
+bool BackgroundChild::ValidatePrincipal(
+ nsIPrincipal* aPrincipal,
+ const EnumSet& aOptions) {
+ return ValidatePrincipalCouldPotentiallyBeLoadedBy(
+ aPrincipal, dom::CurrentRemoteType(), aOptions);
+}
+
+// static
+bool BackgroundChild::ValidatePrincipalInfo(
+ const PrincipalInfo& aPrincipalInfo,
+ const EnumSet& aOptions) {
+ auto result = PrincipalInfoToPrincipal(aPrincipalInfo);
+ if (NS_WARN_IF(result.isErr())) {
+ return false;
+ }
+
+ return ValidatePrincipal(result.inspect(), aOptions);
+}
+
// -----------------------------------------------------------------------------
// BackgroundChildImpl Public Methods
// -----------------------------------------------------------------------------
diff -Nru thunderbird-140.14.0esr/ipc/glue/BackgroundParent.h thunderbird-140.15.0esr/ipc/glue/BackgroundParent.h
--- thunderbird-140.14.0esr/ipc/glue/BackgroundParent.h 2026-08-18 02:52:35.000000000 +0000
+++ thunderbird-140.15.0esr/ipc/glue/BackgroundParent.h 2026-08-28 17:33:08.000000000 +0000
@@ -83,6 +83,18 @@
static uint64_t GetChildID(PBackgroundParent* aBackgroundActor);
+ static nsCString GetRemoteType(PBackgroundParent* aBackgroundActor);
+
+ // Whenever receiving a Principal we need to validate that Principal case
+ // by case. The options can customize the behaviour of the checks.
+ // See ContentParent::ValidatePrincipal for an analog.
+ static bool ValidatePrincipal(
+ PBackgroundParent* aBackgroundActor, nsIPrincipal* aPrincipal,
+ const EnumSet& aOptions);
+ static bool ValidatePrincipalInfo(
+ PBackgroundParent* aBackgroundActor, const PrincipalInfo& aPrincipalInfo,
+ const EnumSet& aOptions);
+
static void KillHardAsync(PBackgroundParent* aBackgroundActor,
const nsACString& aReason);
diff -Nru thunderbird-140.14.0esr/ipc/glue/BackgroundParentImpl.cpp thunderbird-140.15.0esr/ipc/glue/BackgroundParentImpl.cpp
--- thunderbird-140.14.0esr/ipc/glue/BackgroundParentImpl.cpp 2026-08-18 02:52:35.000000000 +0000
+++ thunderbird-140.15.0esr/ipc/glue/BackgroundParentImpl.cpp 2026-08-28 17:33:08.000000000 +0000
@@ -255,6 +255,10 @@
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
+ if (!BackgroundParent::ValidatePrincipalInfo(this, aPrincipalInfo, {})) {
+ return nullptr;
+ }
+
return mozilla::dom::AllocPBackgroundSDBConnectionParent(aPersistenceType,
aPrincipalInfo);
}
@@ -391,6 +395,12 @@
AssertIsOnBackgroundThread();
MOZ_ASSERT(aActor);
+ if (!BackgroundParent::ValidatePrincipalInfo(this, aPrincipalInfo, {})) {
+ return IPC_FAIL(
+ this,
+ "Invalid aPrincipalInfo in PBackgroundLocalStorageCacheConstructor");
+ }
+
return mozilla::dom::RecvPBackgroundLocalStorageCacheConstructor(
this, aActor, aPrincipalInfo, aOriginKey, aPrivateBrowsingId);
}
@@ -451,6 +461,21 @@
return MakeAndAddRef();
}
+mozilla::ipc::IPCResult
+BackgroundParentImpl::RecvPBackgroundSessionStorageServiceConstructor(
+ mozilla::dom::PBackgroundSessionStorageServiceParent* aActor) {
+ AssertIsInMainProcess();
+ AssertIsOnBackgroundThread();
+
+ // ClearStoragesForOrigin is not scoped to any origin the sender is allowed
+ // to touch, so only the parent process may construct this actor.
+ if (BackgroundParent::IsOtherProcessActor(this)) {
+ return IPC_FAIL(aActor, "Wrong actor");
+ }
+
+ return IPC_OK();
+}
+
mozilla::ipc::IPCResult BackgroundParentImpl::RecvCreateFileSystemManagerParent(
const PrincipalInfo& aPrincipalInfo,
Endpoint&& aParentEndpoint,
@@ -458,6 +483,17 @@
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
+ // The inference process uses ChromeWorkers which have a system principal,
+ // so system principals must be allowed there.
+ EnumSet options;
+ if (BackgroundParent::GetRemoteType(this) == INFERENCE_REMOTE_TYPE) {
+ options += dom::ValidatePrincipalOptions::AllowSystem;
+ }
+ if (!BackgroundParent::ValidatePrincipalInfo(this, aPrincipalInfo, options)) {
+ aResolver(NS_ERROR_FAILURE);
+ return IPC_OK();
+ }
+
return mozilla::dom::CreateFileSystemManagerParent(
this, aPrincipalInfo, std::move(aParentEndpoint), std::move(aResolver));
}
@@ -545,6 +581,12 @@
return IPC_FAIL(this, "Invalid worker type for PSharedWorkerParent");
}
+ if (!BackgroundParent::ValidatePrincipalInfo(
+ this, aData.loadingPrincipalInfo(), {})) {
+ return IPC_FAIL(this,
+ "Invalid loadingPrincipalInfo for PSharedWorkerParent");
+ }
+
mozilla::dom::SharedWorkerParent* actor =
static_cast(aActor);
actor->Initialize(aData, aWindowID, aPortIdentifier);
@@ -793,6 +835,10 @@
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
+ if (!BackgroundParent::ValidatePrincipalInfo(this, aPrincipalInfo, {})) {
+ return IPC_FAIL(this, "Invalid principal for BroadcastChannel");
+ }
+
RefPtr parent =
BackgroundParent::GetContentParentHandle(this);
@@ -885,7 +931,12 @@
already_AddRefed
BackgroundParentImpl::AllocPCacheStorageParent(
const Namespace& aNamespace, const PrincipalInfo& aPrincipalInfo) {
- return dom::cache::AllocPCacheStorageParent(this, aNamespace, aPrincipalInfo);
+ if (!BackgroundParent::ValidatePrincipalInfo(this, aPrincipalInfo, {})) {
+ return nullptr;
+ }
+
+ return dom::cache::AllocPCacheStorageParent(this, aNamespace,
+ aPrincipalInfo);
}
PMessagePortParent* BackgroundParentImpl::AllocPMessagePortParent(
@@ -1253,6 +1304,10 @@
IPCResult BackgroundParentImpl::RecvStorageActivity(
const PrincipalInfo& aPrincipalInfo) {
+ if (!BackgroundParent::ValidatePrincipalInfo(this, aPrincipalInfo, {})) {
+ return IPC_FAIL(this, "Invalid principalInfo for StorageActivity");
+ }
+
dom::StorageActivityService::SendActivity(aPrincipalInfo);
return IPC_OK();
}
diff -Nru thunderbird-140.14.0esr/ipc/glue/BackgroundParentImpl.h thunderbird-140.15.0esr/ipc/glue/BackgroundParentImpl.h
--- thunderbird-140.14.0esr/ipc/glue/BackgroundParentImpl.h 2026-08-18 02:52:35.000000000 +0000
+++ thunderbird-140.15.0esr/ipc/glue/BackgroundParentImpl.h 2026-08-28 17:33:08.000000000 +0000
@@ -116,6 +116,9 @@
already_AddRefed
AllocPBackgroundSessionStorageServiceParent() override;
+ mozilla::ipc::IPCResult RecvPBackgroundSessionStorageServiceConstructor(
+ PBackgroundSessionStorageServiceParent* aActor) override;
+
mozilla::ipc::IPCResult RecvCreateFileSystemManagerParent(
const PrincipalInfo& aPrincipalInfo,
Endpoint&& aParentEndpoint,
diff -Nru thunderbird-140.14.0esr/ipc/glue/GeckoChildProcessHost.h thunderbird-140.15.0esr/ipc/glue/GeckoChildProcessHost.h
--- thunderbird-140.14.0esr/ipc/glue/GeckoChildProcessHost.h 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/ipc/glue/GeckoChildProcessHost.h 2026-08-28 17:33:07.000000000 +0000
@@ -9,7 +9,6 @@
#include "base/file_path.h"
#include "base/process_util.h"
-#include "base/waitable_event.h"
#include "chrome/common/ipc_message.h"
#include "mojo/core/ports/port_ref.h"
diff -Nru thunderbird-140.14.0esr/js/src/gc/Nursery.cpp thunderbird-140.15.0esr/js/src/gc/Nursery.cpp
--- thunderbird-140.14.0esr/js/src/gc/Nursery.cpp 2026-08-18 02:52:34.000000000 +0000
+++ thunderbird-140.15.0esr/js/src/gc/Nursery.cpp 2026-08-28 17:33:07.000000000 +0000
@@ -997,10 +997,17 @@
// - Nursery-allocated buffer
// - A BufferRelocationOverlay inside the nursery
//
- // Note: The buffer has already be relocated. We are just patching stale
+ // Note: The buffer has already been relocated. We are just patching stale
// pointers now.
auto* buffer = reinterpret_cast(*pSlotsElems);
+ // If the pointer is to the beginning of a chunk, then that chunk cannot be a
+ // nursery chunk due to the chunk header. Also, the pointer cannot be to the
+ // end of a previous nursery chunk since the last word is never allocated.
+ if ((uintptr_t(buffer) & ChunkMask) == 0) {
+ return;
+ }
+
if (!isInside(buffer)) {
return;
}
diff -Nru thunderbird-140.14.0esr/js/src/proxy/Proxy.cpp thunderbird-140.15.0esr/js/src/proxy/Proxy.cpp
--- thunderbird-140.14.0esr/js/src/proxy/Proxy.cpp 2026-08-18 02:52:35.000000000 +0000
+++ thunderbird-140.15.0esr/js/src/proxy/Proxy.cpp 2026-08-28 17:33:07.000000000 +0000
@@ -1048,7 +1048,16 @@
MOZ_ASSERT(hasDynamicPrototype());
setHandler(handler);
+
setCrossCompartmentPrivate(priv);
+ // The post barrier may add a store buffer entry but since this may be called
+ // on a dying object we don't know if they will survive GC. Therefore we need
+ // to set a flag to ensure we clear out the nursery before doing any sweeping.
+ if (isTenured() && zone()->wasGCStarted() && priv.isGCThing() &&
+ !priv.toGCThing()->isTenured()) {
+ runtimeFromMainThread()->gc.storeBuffer().setMayHavePointersToDeadCells();
+ }
+
for (size_t i = 0; i < numReservedSlots(); i++) {
setReservedSlot(i, UndefinedValue());
}
diff -Nru thunderbird-140.14.0esr/js/src/wasm/WasmBCFrame.cpp thunderbird-140.15.0esr/js/src/wasm/WasmBCFrame.cpp
--- thunderbird-140.14.0esr/js/src/wasm/WasmBCFrame.cpp 2026-08-18 02:52:38.000000000 +0000
+++ thunderbird-140.15.0esr/js/src/wasm/WasmBCFrame.cpp 2026-08-28 17:33:10.000000000 +0000
@@ -537,7 +537,7 @@
masm.storePtr(zero, Address(p, -(wordSize * i)));
}
masm.subPtr(Imm32(UNROLL_LIMIT * wordSize), p);
- masm.branchPtr(Assembler::LessThan, lim, p, &again);
+ masm.branchPtr(Assembler::Below, lim, p, &again);
// The tail.
for (uint32_t i = 0; i < tailWords; ++i) {
diff -Nru thunderbird-140.14.0esr/js/src/wasm/WasmBaselineCompile.cpp thunderbird-140.15.0esr/js/src/wasm/WasmBaselineCompile.cpp
--- thunderbird-140.14.0esr/js/src/wasm/WasmBaselineCompile.cpp 2026-08-18 02:52:38.000000000 +0000
+++ thunderbird-140.15.0esr/js/src/wasm/WasmBaselineCompile.cpp 2026-08-28 17:33:10.000000000 +0000
@@ -4502,6 +4502,24 @@
return true;
}
+ // The block params are consumed by the try body, so keep them off the value
+ // stack while emitting the landing pad and restore them for the body, the way
+ // endTryCatch does for its results. sync() above spilled them, so the saved
+ // entries hold no registers.
+ MOZ_ASSERT(stk_.length() >= controlItem().stackSize);
+ StkVector savedParams;
+ if (!savedParams.append(stk_.begin() + controlItem().stackSize, stk_.end())) {
+ return false;
+ }
+ for (const Stk& v : savedParams) {
+ MOZ_ASSERT(v.kind() < Stk::RegisterI32 || v.kind() > Stk::RegisterRef);
+ if (v.kind() == Stk::MemRef) {
+ stackMapGenerator_.memRefsOnStk--;
+ }
+ }
+ stk_.shrinkTo(controlItem().stackSize);
+ MOZ_ASSERT(stk_.length() == controlItem().stackSize);
+
// Emit a landing pad that exceptions will jump into. Jump over it for now.
Label skipLandingPad;
masm.jump(&skipLandingPad);
@@ -4693,6 +4711,16 @@
fr.setStackHeight(prePadHeight);
masm.bind(&skipLandingPad);
+ // Restore the block params removed above, for the try body.
+ if (!stk_.appendAll(savedParams)) {
+ return false;
+ }
+ for (const Stk& v : savedParams) {
+ if (v.kind() == Stk::MemRef) {
+ stackMapGenerator_.memRefsOnStk++;
+ }
+ }
+
// Start the try note for this try block, after the landing pad
if (!startTryNote(&controlItem().tryNoteIndex)) {
return false;
diff -Nru thunderbird-140.14.0esr/layout/build/components.conf thunderbird-140.15.0esr/layout/build/components.conf
--- thunderbird-140.14.0esr/layout/build/components.conf 2026-08-18 02:52:37.000000000 +0000
+++ thunderbird-140.15.0esr/layout/build/components.conf 2026-08-28 17:33:10.000000000 +0000
@@ -53,11 +53,13 @@
'cid': '{574ce83e-fe9f-4095-b85c-7909abbf7c37}',
'type': 'nsJSURI::Mutator',
'headers': ['nsJSProtocolHandler.h'],
+ 'serializable': True,
},
{
'cid': '{58f089ee-512a-42d2-a935-d0c874128930}',
'type': 'nsJSURI::Mutator',
'headers': ['nsJSProtocolHandler.h'],
+ 'serializable': True,
},
{
'cid': '{48118355-e9a5-4452-ab18-59cc426fb817}',
@@ -67,11 +69,13 @@
'cid': '{bbe50ef2-80eb-469d-b70d-02858275389f}',
'type': 'mozilla::dom::BlobURL::Mutator',
'headers': ['mozilla/dom/BlobURL.h'],
+ 'serializable': True,
},
{
'cid': '{f5475c51-59a7-4757-b3d9-e211a9410872}',
'type': 'mozilla::dom::BlobURL::Mutator',
'headers': ['mozilla/dom/BlobURL.h'],
+ 'serializable': True,
},
{
'js_name': 'cpmm',
@@ -114,6 +118,7 @@
'contract_ids': ['@mozilla.org/cspcontext;1'],
'type': 'nsCSPContext',
'headers': ['mozilla/dom/nsCSPContext.h'],
+ 'serializable': True,
},
{
'cid': '{8d2f40b2-4875-4c95-97d9-3f7dca2cb460}',
@@ -190,6 +195,7 @@
'contract_ids': [],
'type': 'ExpandedPrincipal::Deserializer',
'headers': ['/caps/ExpandedPrincipal.h'],
+ 'serializable': True,
},
{
'js_name': 'focus',
@@ -287,6 +293,7 @@
'contract_ids': ['@mozilla.org/referrer-info;1'],
'type': 'mozilla::dom::ReferrerInfo',
'headers': ['mozilla/dom/ReferrerInfo.h'],
+ 'serializable': True,
},
{
'cid': '{bfc310d2-38a0-11d3-8cd3-0060b0fc14a3}',
@@ -317,6 +324,7 @@
'contract_ids': [],
'type': 'mozilla::NullPrincipal::Deserializer',
'headers': ['/caps/NullPrincipal.h'],
+ 'serializable': True,
},
{
'js_name': 'ppmm',
@@ -335,6 +343,7 @@
'contract_ids': [],
'type': 'mozilla::ContentPrincipal::Deserializer',
'headers': ['/caps/ContentPrincipal.h'],
+ 'serializable': True,
},
{
'cid': '{2fc2d3e3-020f-404e-b06a-6ecf3ea2334a}',
@@ -386,6 +395,7 @@
'type': 'nsIPrincipal',
'headers': ['nsScriptSecurityManager.h', '/caps/SystemPrincipal.h'],
'constructor': 'nsScriptSecurityManager::SystemPrincipalSingletonConstructor',
+ 'serializable': True,
},
{
'cid': '{caaab47f-1e31-478e-8919-970904e9cb72}',
diff -Nru thunderbird-140.14.0esr/layout/generic/nsTextFrame.cpp thunderbird-140.15.0esr/layout/generic/nsTextFrame.cpp
--- thunderbird-140.14.0esr/layout/generic/nsTextFrame.cpp 2026-08-18 02:52:37.000000000 +0000
+++ thunderbird-140.15.0esr/layout/generic/nsTextFrame.cpp 2026-08-28 17:33:10.000000000 +0000
@@ -8645,7 +8645,7 @@
// after the virama would be acceptable). So results may be imperfect,
// depending how the font has chosen to implement visible viramas.
if (usesIndicHalfForms) {
- while (i + 1 < length &&
+ while (i + 1 < length && iter.GetSkippedOffset() < aTextRun->GetLength() &&
!aTextRun->IsLigatureGroupStart(iter.GetSkippedOffset())) {
char32_t c = aFrag->ScalarValueAt(AssertedCast(aOffset + i));
if (intl::UnicodeProperties::GetCombiningClass(c) ==
diff -Nru thunderbird-140.14.0esr/media/libcubeb/moz.yaml thunderbird-140.15.0esr/media/libcubeb/moz.yaml
--- thunderbird-140.14.0esr/media/libcubeb/moz.yaml 2026-08-18 02:52:39.000000000 +0000
+++ thunderbird-140.15.0esr/media/libcubeb/moz.yaml 2026-08-28 17:33:11.000000000 +0000
@@ -26,6 +26,8 @@
- frame-sample.patch
- delay-line-bounds.patch
- wasapi-async-reconfigure-on-start.patch
+ - wasapi-output-mix-channel-count.patch
+ - winmm-destroy-work-item-uaf.patch
skip-vendoring-steps:
- update-moz-build
exclude:
diff -Nru thunderbird-140.14.0esr/media/libcubeb/src/cubeb.c thunderbird-140.15.0esr/media/libcubeb/src/cubeb.c
--- thunderbird-140.14.0esr/media/libcubeb/src/cubeb.c 2026-08-18 02:52:39.000000000 +0000
+++ thunderbird-140.15.0esr/media/libcubeb/src/cubeb.c 2026-08-28 17:33:12.000000000 +0000
@@ -7,6 +7,7 @@
#undef NDEBUG
#include "cubeb/cubeb.h"
#include "cubeb-internal.h"
+#include "cubeb_mixer.h"
#include
#include
#include
@@ -97,7 +98,10 @@
if (output_stream_params->rate < 1000 ||
output_stream_params->rate > 768000 ||
output_stream_params->channels < 1 ||
- output_stream_params->channels > UINT8_MAX) {
+ output_stream_params->channels > UINT8_MAX ||
+ (output_stream_params->layout != CUBEB_LAYOUT_UNDEFINED &&
+ cubeb_channel_layout_nb_channels(output_stream_params->layout) !=
+ output_stream_params->channels)) {
return CUBEB_ERROR_INVALID_FORMAT;
}
}
@@ -105,7 +109,10 @@
if (input_stream_params->rate < 1000 ||
input_stream_params->rate > 768000 ||
input_stream_params->channels < 1 ||
- input_stream_params->channels > UINT8_MAX) {
+ input_stream_params->channels > UINT8_MAX ||
+ (input_stream_params->layout != CUBEB_LAYOUT_UNDEFINED &&
+ cubeb_channel_layout_nb_channels(input_stream_params->layout) !=
+ input_stream_params->channels)) {
return CUBEB_ERROR_INVALID_FORMAT;
}
}
diff -Nru thunderbird-140.14.0esr/media/libcubeb/src/cubeb_wasapi.cpp thunderbird-140.15.0esr/media/libcubeb/src/cubeb_wasapi.cpp
--- thunderbird-140.14.0esr/media/libcubeb/src/cubeb_wasapi.cpp 2026-08-18 02:52:38.000000000 +0000
+++ thunderbird-140.15.0esr/media/libcubeb/src/cubeb_wasapi.cpp 2026-08-28 17:33:11.000000000 +0000
@@ -2650,7 +2650,8 @@
// Create output mixer.
if (has_output(stm) &&
- stm->output_mix_params.layout != stm->output_stream_params.layout) {
+ (stm->output_mix_params.layout != stm->output_stream_params.layout ||
+ stm->output_mix_params.channels != stm->output_stream_params.channels)) {
if (stm->output_mix_params.layout == CUBEB_LAYOUT_UNDEFINED) {
LOG("Output stream using undefined layout! Any mixing may be "
"unpredictable!\n");
diff -Nru thunderbird-140.14.0esr/media/libcubeb/src/cubeb_winmm.c thunderbird-140.15.0esr/media/libcubeb/src/cubeb_winmm.c
--- thunderbird-140.14.0esr/media/libcubeb/src/cubeb_winmm.c 2026-08-18 02:52:39.000000000 +0000
+++ thunderbird-140.15.0esr/media/libcubeb/src/cubeb_winmm.c 2026-08-28 17:33:12.000000000 +0000
@@ -86,6 +86,7 @@
HANDLE thread;
int shutdown;
PSLIST_HEADER work;
+ LONG pending_callbacks;
CRITICAL_SECTION lock;
unsigned int active_streams;
unsigned int minimum_latency_ms;
@@ -106,6 +107,7 @@
int shutdown;
int draining;
int error;
+ LONG pending_work_items;
HANDLE event;
HWAVEOUT waveout;
CRITICAL_SECTION lock;
@@ -172,12 +174,13 @@
ALOG("winmm_refill_stream");
EnterCriticalSection(&stm->lock);
+ stm->free_buffers += 1;
+ XASSERT(stm->free_buffers > 0 && stm->free_buffers <= NBUFS);
+
if (stm->error) {
LeaveCriticalSection(&stm->lock);
return;
}
- stm->free_buffers += 1;
- XASSERT(stm->free_buffers > 0 && stm->free_buffers <= NBUFS);
if (stm->draining) {
LeaveCriticalSection(&stm->lock);
@@ -185,13 +188,11 @@
ALOG("winmm_refill_stream draining");
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED);
}
- SetEvent(stm->event);
return;
}
if (stm->shutdown) {
LeaveCriticalSection(&stm->lock);
- SetEvent(stm->event);
return;
}
@@ -204,10 +205,18 @@
LeaveCriticalSection(&stm->lock);
got = stm->data_callback(stm, stm->user_ptr, NULL, hdr->lpData, wanted);
EnterCriticalSection(&stm->lock);
+ if (stm->shutdown) {
+ stm->free_buffers += 1;
+ XASSERT(stm->free_buffers > 0 && stm->free_buffers <= NBUFS);
+ LeaveCriticalSection(&stm->lock);
+ return;
+ }
+
if (got < 0) {
+ stm->free_buffers += 1;
+ XASSERT(stm->free_buffers > 0 && stm->free_buffers <= NBUFS);
stm->error = 1;
LeaveCriticalSection(&stm->lock);
- SetEvent(stm->event);
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR);
return;
} else if (got < wanted) {
@@ -238,6 +247,9 @@
r = waveOutWrite(stm->waveout, hdr, sizeof(*hdr));
if (r != MMSYSERR_NOERROR) {
+ stm->free_buffers += 1;
+ XASSERT(stm->free_buffers > 0 && stm->free_buffers <= NBUFS);
+ stm->error = 1;
LeaveCriticalSection(&stm->lock);
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR);
return;
@@ -266,9 +278,22 @@
item = InterlockedFlushSList(ctx->work);
while (item != NULL) {
PSLIST_ENTRY tmp = item;
- winmm_refill_stream(((struct cubeb_stream_item *)tmp)->stream);
+ cubeb_stream * stm = ((struct cubeb_stream_item *)tmp)->stream;
item = item->Next;
+
+ winmm_refill_stream(stm);
_aligned_free(tmp);
+
+ /* Release the work item and wake winmm_stream_destroy. Destroy sets
+ stm->shutdown under this lock before waiting, so the gated wake
+ cannot be lost nor the event closed mid-SetEvent. */
+ EnterCriticalSection(&stm->lock);
+ LONG pending = InterlockedDecrement(&stm->pending_work_items);
+ XASSERT(pending >= 0);
+ if (stm->shutdown) {
+ SetEvent(stm->event);
+ }
+ LeaveCriticalSection(&stm->lock);
}
if (ctx->shutdown) {
@@ -285,18 +310,27 @@
{
cubeb_stream * stm = (cubeb_stream *)user_ptr;
struct cubeb_stream_item * item;
+ cubeb * ctx;
if (msg != WOM_DONE) {
return;
}
+ /* The stream may be freed as soon as the published work item is consumed,
+ so stm must not be touched after the push. pending_callbacks keeps the
+ context alive through the final SetEvent; winmm_destroy drains it. */
+ ctx = stm->context;
+ InterlockedIncrement(&ctx->pending_callbacks);
+ InterlockedIncrement(&stm->pending_work_items);
+
item = _aligned_malloc(sizeof(struct cubeb_stream_item),
MEMORY_ALLOCATION_ALIGNMENT);
XASSERT(item);
item->stream = stm;
- InterlockedPushEntrySList(stm->context->work, &item->head);
+ InterlockedPushEntrySList(ctx->work, &item->head);
- SetEvent(stm->context->event);
+ SetEvent(ctx->event);
+ InterlockedDecrement(&ctx->pending_callbacks);
}
static unsigned int
@@ -405,6 +439,11 @@
}
if (ctx->event) {
+ /* Wait out any driver callback still between publishing a work item and
+ its final SetEvent before closing the event. */
+ while (InterlockedCompareExchange(&ctx->pending_callbacks, 0, 0) != 0) {
+ Sleep(1);
+ }
CloseHandle(ctx->event);
}
@@ -602,7 +641,6 @@
MMTIME time;
MMRESULT r;
int device_valid;
- int enqueued;
EnterCriticalSection(&stm->lock);
stm->shutdown = 1;
@@ -614,18 +652,26 @@
time.wType = TIME_SAMPLES;
r = waveOutGetPosition(stm->waveout, &time, sizeof(time));
device_valid = !(r == MMSYSERR_INVALHANDLE || r == MMSYSERR_NODRIVER);
-
- enqueued = NBUFS - stm->free_buffers;
LeaveCriticalSection(&stm->lock);
- /* Wait for all blocks to complete. */
- while (device_valid && enqueued > 0 && !stm->error) {
- DWORD rv = WaitForSingleObject(stm->event, INFINITE);
- XASSERT(rv == WAIT_OBJECT_0);
+ /* Wait for the device to return all buffers and for queued or in-flight
+ buffer thread work to finish with the stream. */
+ for (;;) {
+ int enqueued;
+ LONG pending_work_items;
EnterCriticalSection(&stm->lock);
enqueued = NBUFS - stm->free_buffers;
+ pending_work_items =
+ InterlockedCompareExchange(&stm->pending_work_items, 0, 0);
LeaveCriticalSection(&stm->lock);
+
+ if ((!device_valid || enqueued == 0) && pending_work_items == 0) {
+ break;
+ }
+
+ DWORD rv = WaitForSingleObject(stm->event, INFINITE);
+ XASSERT(rv == WAIT_OBJECT_0);
}
EnterCriticalSection(&stm->lock);
diff -Nru thunderbird-140.14.0esr/media/libcubeb/test/test_sanity.cpp thunderbird-140.15.0esr/media/libcubeb/test/test_sanity.cpp
--- thunderbird-140.14.0esr/media/libcubeb/test/test_sanity.cpp 2026-08-18 02:52:39.000000000 +0000
+++ thunderbird-140.15.0esr/media/libcubeb/test/test_sanity.cpp 2026-08-28 17:33:12.000000000 +0000
@@ -279,6 +279,29 @@
cubeb_destroy(ctx);
}
+TEST(cubeb, reject_inconsistent_channel_layout)
+{
+ cubeb * ctx;
+ cubeb_stream * stream;
+ cubeb_stream_params params = {};
+
+ int r = common_init(&ctx, "test_sanity");
+ ASSERT_EQ(r, CUBEB_OK);
+ ASSERT_NE(ctx, nullptr);
+
+ params.format = CUBEB_SAMPLE_FLOAT32NE;
+ params.rate = STREAM_RATE;
+ params.channels = UINT8_MAX;
+ params.layout = CUBEB_LAYOUT_STEREO;
+
+ r = cubeb_stream_init(ctx, &stream, "test", NULL, NULL, NULL, ¶ms,
+ STREAM_LATENCY, test_data_callback, test_state_callback,
+ &dummy);
+ EXPECT_EQ(r, CUBEB_ERROR_INVALID_FORMAT);
+
+ cubeb_destroy(ctx);
+}
+
static void
test_init_start_stop_destroy_multiple_streams(int early, int delay_ms)
{
diff -Nru thunderbird-140.14.0esr/media/libcubeb/wasapi-output-mix-channel-count.patch thunderbird-140.15.0esr/media/libcubeb/wasapi-output-mix-channel-count.patch
--- thunderbird-140.14.0esr/media/libcubeb/wasapi-output-mix-channel-count.patch 1970-01-01 00:00:00.000000000 +0000
+++ thunderbird-140.15.0esr/media/libcubeb/wasapi-output-mix-channel-count.patch 2026-08-28 17:33:11.000000000 +0000
@@ -0,0 +1,84 @@
+diff --git a/src/cubeb.c b/src/cubeb.c
+index b0db033d4f07..544341c8fa7d 100644
+--- a/src/cubeb.c
++++ b/src/cubeb.c
+@@ -7,6 +7,7 @@
+ #undef NDEBUG
+ #include "cubeb/cubeb.h"
+ #include "cubeb-internal.h"
++#include "cubeb_mixer.h"
+ #include
+ #include
+ #include
+@@ -97,7 +98,10 @@ validate_stream_params(cubeb_stream_params * input_stream_params,
+ if (output_stream_params->rate < 1000 ||
+ output_stream_params->rate > 768000 ||
+ output_stream_params->channels < 1 ||
+- output_stream_params->channels > UINT8_MAX) {
++ output_stream_params->channels > UINT8_MAX ||
++ (output_stream_params->layout != CUBEB_LAYOUT_UNDEFINED &&
++ cubeb_channel_layout_nb_channels(output_stream_params->layout) !=
++ output_stream_params->channels)) {
+ return CUBEB_ERROR_INVALID_FORMAT;
+ }
+ }
+@@ -105,7 +109,10 @@ validate_stream_params(cubeb_stream_params * input_stream_params,
+ if (input_stream_params->rate < 1000 ||
+ input_stream_params->rate > 768000 ||
+ input_stream_params->channels < 1 ||
+- input_stream_params->channels > UINT8_MAX) {
++ input_stream_params->channels > UINT8_MAX ||
++ (input_stream_params->layout != CUBEB_LAYOUT_UNDEFINED &&
++ cubeb_channel_layout_nb_channels(input_stream_params->layout) !=
++ input_stream_params->channels)) {
+ return CUBEB_ERROR_INVALID_FORMAT;
+ }
+ }
+diff --git a/src/cubeb_wasapi.cpp b/src/cubeb_wasapi.cpp
+index fe69ecd34fe2..2e5bef3a5ed9 100644
+--- a/src/cubeb_wasapi.cpp
++++ b/src/cubeb_wasapi.cpp
+@@ -2650,7 +2650,8 @@ setup_wasapi_stream(cubeb_stream * stm)
+
+ // Create output mixer.
+ if (has_output(stm) &&
+- stm->output_mix_params.layout != stm->output_stream_params.layout) {
++ (stm->output_mix_params.layout != stm->output_stream_params.layout ||
++ stm->output_mix_params.channels != stm->output_stream_params.channels)) {
+ if (stm->output_mix_params.layout == CUBEB_LAYOUT_UNDEFINED) {
+ LOG("Output stream using undefined layout! Any mixing may be "
+ "unpredictable!\n");
+diff --git a/test/test_sanity.cpp b/test/test_sanity.cpp
+index 17d3c542b419..35ee1a958b8c 100644
+--- a/test/test_sanity.cpp
++++ b/test/test_sanity.cpp
+@@ -279,6 +279,29 @@ TEST(cubeb, configure_stream_undefined_layout)
+ cubeb_destroy(ctx);
+ }
+
++TEST(cubeb, reject_inconsistent_channel_layout)
++{
++ cubeb * ctx;
++ cubeb_stream * stream;
++ cubeb_stream_params params = {};
++
++ int r = common_init(&ctx, "test_sanity");
++ ASSERT_EQ(r, CUBEB_OK);
++ ASSERT_NE(ctx, nullptr);
++
++ params.format = CUBEB_SAMPLE_FLOAT32NE;
++ params.rate = STREAM_RATE;
++ params.channels = UINT8_MAX;
++ params.layout = CUBEB_LAYOUT_STEREO;
++
++ r = cubeb_stream_init(ctx, &stream, "test", NULL, NULL, NULL, ¶ms,
++ STREAM_LATENCY, test_data_callback, test_state_callback,
++ &dummy);
++ EXPECT_EQ(r, CUBEB_ERROR_INVALID_FORMAT);
++
++ cubeb_destroy(ctx);
++}
++
+ static void
+ test_init_start_stop_destroy_multiple_streams(int early, int delay_ms)
+ {
diff -Nru thunderbird-140.14.0esr/media/libcubeb/winmm-destroy-work-item-uaf.patch thunderbird-140.15.0esr/media/libcubeb/winmm-destroy-work-item-uaf.patch
--- thunderbird-140.14.0esr/media/libcubeb/winmm-destroy-work-item-uaf.patch 1970-01-01 00:00:00.000000000 +0000
+++ thunderbird-140.15.0esr/media/libcubeb/winmm-destroy-work-item-uaf.patch 2026-08-28 17:33:11.000000000 +0000
@@ -0,0 +1,187 @@
+diff --git a/src/cubeb_winmm.c b/src/cubeb_winmm.c
+index b2234a9b52ac..6eb8c4d37322 100644
+--- a/src/cubeb_winmm.c
++++ b/src/cubeb_winmm.c
+@@ -86,6 +86,7 @@ struct cubeb {
+ HANDLE thread;
+ int shutdown;
+ PSLIST_HEADER work;
++ LONG pending_callbacks;
+ CRITICAL_SECTION lock;
+ unsigned int active_streams;
+ unsigned int minimum_latency_ms;
+@@ -106,6 +107,7 @@ struct cubeb_stream {
+ int shutdown;
+ int draining;
+ int error;
++ LONG pending_work_items;
+ HANDLE event;
+ HWAVEOUT waveout;
+ CRITICAL_SECTION lock;
+@@ -172,12 +174,13 @@ winmm_refill_stream(cubeb_stream * stm)
+ ALOG("winmm_refill_stream");
+
+ EnterCriticalSection(&stm->lock);
++ stm->free_buffers += 1;
++ XASSERT(stm->free_buffers > 0 && stm->free_buffers <= NBUFS);
++
+ if (stm->error) {
+ LeaveCriticalSection(&stm->lock);
+ return;
+ }
+- stm->free_buffers += 1;
+- XASSERT(stm->free_buffers > 0 && stm->free_buffers <= NBUFS);
+
+ if (stm->draining) {
+ LeaveCriticalSection(&stm->lock);
+@@ -185,13 +188,11 @@ winmm_refill_stream(cubeb_stream * stm)
+ ALOG("winmm_refill_stream draining");
+ stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED);
+ }
+- SetEvent(stm->event);
+ return;
+ }
+
+ if (stm->shutdown) {
+ LeaveCriticalSection(&stm->lock);
+- SetEvent(stm->event);
+ return;
+ }
+
+@@ -204,10 +205,18 @@ winmm_refill_stream(cubeb_stream * stm)
+ LeaveCriticalSection(&stm->lock);
+ got = stm->data_callback(stm, stm->user_ptr, NULL, hdr->lpData, wanted);
+ EnterCriticalSection(&stm->lock);
++ if (stm->shutdown) {
++ stm->free_buffers += 1;
++ XASSERT(stm->free_buffers > 0 && stm->free_buffers <= NBUFS);
++ LeaveCriticalSection(&stm->lock);
++ return;
++ }
++
+ if (got < 0) {
++ stm->free_buffers += 1;
++ XASSERT(stm->free_buffers > 0 && stm->free_buffers <= NBUFS);
+ stm->error = 1;
+ LeaveCriticalSection(&stm->lock);
+- SetEvent(stm->event);
+ stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR);
+ return;
+ } else if (got < wanted) {
+@@ -238,6 +247,9 @@ winmm_refill_stream(cubeb_stream * stm)
+
+ r = waveOutWrite(stm->waveout, hdr, sizeof(*hdr));
+ if (r != MMSYSERR_NOERROR) {
++ stm->free_buffers += 1;
++ XASSERT(stm->free_buffers > 0 && stm->free_buffers <= NBUFS);
++ stm->error = 1;
+ LeaveCriticalSection(&stm->lock);
+ stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR);
+ return;
+@@ -266,9 +278,22 @@ static unsigned __stdcall winmm_buffer_thread(void * user_ptr)
+ item = InterlockedFlushSList(ctx->work);
+ while (item != NULL) {
+ PSLIST_ENTRY tmp = item;
+- winmm_refill_stream(((struct cubeb_stream_item *)tmp)->stream);
++ cubeb_stream * stm = ((struct cubeb_stream_item *)tmp)->stream;
+ item = item->Next;
++
++ winmm_refill_stream(stm);
+ _aligned_free(tmp);
++
++ /* Release the work item and wake winmm_stream_destroy. Destroy sets
++ stm->shutdown under this lock before waiting, so the gated wake
++ cannot be lost nor the event closed mid-SetEvent. */
++ EnterCriticalSection(&stm->lock);
++ LONG pending = InterlockedDecrement(&stm->pending_work_items);
++ XASSERT(pending >= 0);
++ if (stm->shutdown) {
++ SetEvent(stm->event);
++ }
++ LeaveCriticalSection(&stm->lock);
+ }
+
+ if (ctx->shutdown) {
+@@ -285,18 +310,27 @@ winmm_buffer_callback(HWAVEOUT waveout, UINT msg, DWORD_PTR user_ptr,
+ {
+ cubeb_stream * stm = (cubeb_stream *)user_ptr;
+ struct cubeb_stream_item * item;
++ cubeb * ctx;
+
+ if (msg != WOM_DONE) {
+ return;
+ }
+
++ /* The stream may be freed as soon as the published work item is consumed,
++ so stm must not be touched after the push. pending_callbacks keeps the
++ context alive through the final SetEvent; winmm_destroy drains it. */
++ ctx = stm->context;
++ InterlockedIncrement(&ctx->pending_callbacks);
++ InterlockedIncrement(&stm->pending_work_items);
++
+ item = _aligned_malloc(sizeof(struct cubeb_stream_item),
+ MEMORY_ALLOCATION_ALIGNMENT);
+ XASSERT(item);
+ item->stream = stm;
+- InterlockedPushEntrySList(stm->context->work, &item->head);
++ InterlockedPushEntrySList(ctx->work, &item->head);
+
+- SetEvent(stm->context->event);
++ SetEvent(ctx->event);
++ InterlockedDecrement(&ctx->pending_callbacks);
+ }
+
+ static unsigned int
+@@ -405,6 +439,11 @@ winmm_destroy(cubeb * ctx)
+ }
+
+ if (ctx->event) {
++ /* Wait out any driver callback still between publishing a work item and
++ its final SetEvent before closing the event. */
++ while (InterlockedCompareExchange(&ctx->pending_callbacks, 0, 0) != 0) {
++ Sleep(1);
++ }
+ CloseHandle(ctx->event);
+ }
+
+@@ -602,7 +641,6 @@ winmm_stream_destroy(cubeb_stream * stm)
+ MMTIME time;
+ MMRESULT r;
+ int device_valid;
+- int enqueued;
+
+ EnterCriticalSection(&stm->lock);
+ stm->shutdown = 1;
+@@ -614,18 +652,26 @@ winmm_stream_destroy(cubeb_stream * stm)
+ time.wType = TIME_SAMPLES;
+ r = waveOutGetPosition(stm->waveout, &time, sizeof(time));
+ device_valid = !(r == MMSYSERR_INVALHANDLE || r == MMSYSERR_NODRIVER);
+-
+- enqueued = NBUFS - stm->free_buffers;
+ LeaveCriticalSection(&stm->lock);
+
+- /* Wait for all blocks to complete. */
+- while (device_valid && enqueued > 0 && !stm->error) {
+- DWORD rv = WaitForSingleObject(stm->event, INFINITE);
+- XASSERT(rv == WAIT_OBJECT_0);
++ /* Wait for the device to return all buffers and for queued or in-flight
++ buffer thread work to finish with the stream. */
++ for (;;) {
++ int enqueued;
++ LONG pending_work_items;
+
+ EnterCriticalSection(&stm->lock);
+ enqueued = NBUFS - stm->free_buffers;
++ pending_work_items =
++ InterlockedCompareExchange(&stm->pending_work_items, 0, 0);
+ LeaveCriticalSection(&stm->lock);
++
++ if ((!device_valid || enqueued == 0) && pending_work_items == 0) {
++ break;
++ }
++
++ DWORD rv = WaitForSingleObject(stm->event, INFINITE);
++ XASSERT(rv == WAIT_OBJECT_0);
+ }
+
+ EnterCriticalSection(&stm->lock);
diff -Nru thunderbird-140.14.0esr/modules/libjar/components.conf thunderbird-140.15.0esr/modules/libjar/components.conf
--- thunderbird-140.14.0esr/modules/libjar/components.conf 2026-08-18 02:52:39.000000000 +0000
+++ thunderbird-140.15.0esr/modules/libjar/components.conf 2026-08-28 17:33:13.000000000 +0000
@@ -34,11 +34,13 @@
'cid': '{245abae2-b947-4ded-a46d-9829d3cca462}',
'type': 'nsJARURI::Mutator',
'headers': ['nsJARURI.h'],
+ 'serializable': True,
},
{
'cid': '{19d9161b-a2a9-4518-b2c9-fcb8296d6dcd}',
'type': 'nsJARURI::Mutator',
'headers': ['nsJARURI.h'],
+ 'serializable': True,
},
{
'cid': '{608b7f6f-4b60-40d6-87ed-d933bf53d8c1}',
diff -Nru thunderbird-140.14.0esr/modules/libpref/init/StaticPrefList.yaml thunderbird-140.15.0esr/modules/libpref/init/StaticPrefList.yaml
--- thunderbird-140.14.0esr/modules/libpref/init/StaticPrefList.yaml 2026-08-18 02:52:40.000000000 +0000
+++ thunderbird-140.15.0esr/modules/libpref/init/StaticPrefList.yaml 2026-08-28 17:33:12.000000000 +0000
@@ -3174,6 +3174,12 @@
value: false
mirror: always
+# Whether or not system IndexedDB access from a content process is allowed.
+- name: dom.indexedDB.testing.allowContentSystem
+ type: RelaxedAtomicBool
+ value: false
+ mirror: always
+
# Whether or not indexedDB experimental features are enabled.
- name: dom.indexedDB.experimental
type: RelaxedAtomicBool
diff -Nru thunderbird-140.14.0esr/netwerk/build/components.conf thunderbird-140.15.0esr/netwerk/build/components.conf
--- thunderbird-140.14.0esr/netwerk/build/components.conf 2026-08-18 02:52:40.000000000 +0000
+++ thunderbird-140.15.0esr/netwerk/build/components.conf 2026-08-28 17:33:13.000000000 +0000
@@ -573,6 +573,7 @@
'type': 'mozilla::net::nsSimpleURI::Mutator',
'headers': ['nsSimpleURI.h'],
'processes': ProcessSelector.ALLOW_IN_SOCKET_PROCESS,
+ 'serializable': True,
},
{
'cid': '{04445aa0-fd27-4c99-bd41-6be6318ae92c}',
@@ -580,6 +581,7 @@
'type': 'mozilla::net::DefaultURI::Mutator',
'headers': ['/netwerk/base/DefaultURI.h'],
'processes': ProcessSelector.ALLOW_IN_SOCKET_PROCESS,
+ 'serializable': True,
},
{
'name': 'SocketTransport',
@@ -597,6 +599,7 @@
'type': 'mozilla::net::nsStandardURL::Mutator',
'headers': ['/netwerk/base/nsStandardURL.h'],
'processes': ProcessSelector.ALLOW_IN_SOCKET_PROCESS,
+ 'serializable': True,
},
{
'cid': '{831f8f13-7aa8-485f-b02e-77c881cc5773}',
@@ -711,30 +714,35 @@
'contract_ids': [],
'type': 'mozilla::net::nsNestedAboutURI::Mutator',
'headers': ['/netwerk/protocol/about/nsAboutProtocolHandler.h'],
+ 'serializable': True,
},
{
'cid': '{56388dad-287b-4240-a785-85c394012503}',
'contract_ids': [],
'type': 'mozilla::net::nsSimpleNestedURI::Mutator',
'headers': ['nsSimpleNestedURI.h'],
+ 'serializable': True,
},
{
'cid': '{9c4e9d49-ce64-4ca3-acef-3075c5e5aba7}',
'contract_ids': [],
'type': 'mozilla::net::nsSimpleNestedURI::Mutator',
'headers': ['nsSimpleNestedURI.h'],
+ 'serializable': True,
},
{
'cid': '{b0054ef3-b096-483d-8242-4ee36b7b2115}',
'contract_ids': [],
'type': 'mozilla::net::nsNestedAboutURI::Mutator',
'headers': ['/netwerk/protocol/about/nsAboutProtocolHandler.h'],
+ 'serializable': True,
},
{
'cid': '{b3cfeb91-332a-46c9-ad97-93ff39841494}',
'contract_ids': [],
'type': 'mozilla::net::SubstitutingURL::Mutator',
'headers': ['mozilla/net/SubstitutingURL.h'],
+ 'serializable': True,
},
{
'cid': '{de9472d0-8034-11d3-9399-00104ba0fd40}',
@@ -742,12 +750,14 @@
'type': 'mozilla::net::nsStandardURL::Mutator',
'headers': ['/netwerk/base/nsStandardURL.h'],
'processes': ProcessSelector.ALLOW_IN_SOCKET_PROCESS,
+ 'serializable': True,
},
{
'cid': '{dea9657c-18cf-4984-bde9-ccef5d8ab473}',
'contract_ids': [],
'type': 'mozilla::net::SubstitutingURL::Mutator',
'headers': ['mozilla/net/SubstitutingURL.h'],
+ 'serializable': True,
},
{
'cid': '{50d50ddf-f16a-4652-8705-936b19c3763b}',
@@ -755,6 +765,7 @@
'type': 'mozilla::net::SubstitutingJARURI',
'headers': ['mozilla/net/SubstitutingJARURI.h'],
'processes': ProcessSelector.ALLOW_IN_SOCKET_PROCESS,
+ 'serializable': True,
},
{
'cid': '{e0da1d70-2f7b-11d3-8cd0-0060b0fc14a3}',
@@ -762,6 +773,7 @@
'type': 'mozilla::net::nsSimpleURI::Mutator',
'headers': ['nsSimpleURI.h'],
'processes': ProcessSelector.ALLOW_IN_SOCKET_PROCESS,
+ 'serializable': True,
},
{
'js_name': 'cookies',
@@ -789,6 +801,7 @@
'type': 'nsICookieJarSettings',
'constructor': 'mozilla::net::CookieJarSettings::CreateForXPCOM',
'headers': ['mozilla/net/CookieJarSettings.h'],
+ 'serializable': True,
},
{
'cid': '{86606ba1-de17-4df4-9013-e571ab94fd94}',
diff -Nru thunderbird-140.14.0esr/netwerk/dns/effective_tld_names.dat thunderbird-140.15.0esr/netwerk/dns/effective_tld_names.dat
--- thunderbird-140.14.0esr/netwerk/dns/effective_tld_names.dat 2026-08-18 02:52:40.000000000 +0000
+++ thunderbird-140.15.0esr/netwerk/dns/effective_tld_names.dat 2026-08-28 17:33:12.000000000 +0000
@@ -5,8 +5,8 @@
// Please pull this list from, and only from https://publicsuffix.org/list/public_suffix_list.dat,
// rather than any other VCS sites. Pulling from any other URL is not guaranteed to be supported.
-// VERSION: 2026-07-25_14-20-03_UTC
-// COMMIT: e1b8015c3b2f0f4f8c18659c2480fc1a22c07b20
+// VERSION: 2026-08-19_19-18-48_UTC
+// COMMIT: e8c9a2b2b2856b6449999dd0ec0d118f364ed0cd
// Instructions on pulling and using this list can be found at https://publicsuffix.org/list/.
@@ -11308,10 +11308,6 @@
// Submitted by Ofer Kalaora
activetrail.biz
-// Adaptable.io : https://adaptable.io
-// Submitted by Mark Terrel
-adaptable.app
-
// addr.tools : https://addr.tools/
// Submitted by Brian Shea
myaddr.dev
@@ -11351,7 +11347,7 @@
// Aiven : https://aiven.io/
// Submitted by Aiven Security Team
aiven.app
-aivencloud.com
+*.aivencloud.com
// Akamai : https://www.akamai.com/
// Submitted by Akamai Team
@@ -12361,6 +12357,12 @@
// Anthropic : https://www.anthropic.com/
// Submitted by Sid Bidasaria
claude.app
+claudeusercontent.com
+frame.claudeusercontent.com
+
+// Anysphere Inc : https://cursor.com
+// Submitted by Benson Liu