Version in base suite: 102.15.0esr-1~deb11u1 Version in overlay suite: 115.4.0esr-1~deb11u1 Base version: firefox-esr_115.4.0esr-1~deb11u1 Target version: firefox-esr_115.5.0esr-1~deb11u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/f/firefox-esr/firefox-esr_115.4.0esr-1~deb11u1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/f/firefox-esr/firefox-esr_115.5.0esr-1~deb11u1.dsc CLOBBER | 2 accessible/atk/AccessibleWrap.cpp | 2 accessible/base/CachedTableAccessible.cpp | 20 accessible/generic/DocAccessible.cpp | 2 accessible/ipc/DocAccessibleChildBase.cpp | 102 accessible/ipc/DocAccessibleChildBase.h | 10 accessible/ipc/DocAccessibleParent.cpp | 211 accessible/ipc/DocAccessibleParent.h | 14 accessible/ipc/RemoteAccessibleBase.h | 4 accessible/ipc/other/PDocAccessible.ipdl | 14 accessible/ipc/other/RemoteAccessible.h | 4 accessible/ipc/win/PDocAccessible.ipdl | 14 accessible/ipc/win/RemoteAccessible.h | 4 accessible/tests/browser/e10s/browser.ini | 1 accessible/tests/browser/e10s/browser_caching_large_update.js | 66 accessible/windows/msaa/MsaaAccessible.cpp | 6 browser/base/content/browser-fullScreenAndPointerLock.js | 7 browser/base/content/browser.js | 25 browser/components/enterprisepolicies/Policies.sys.mjs | 7 browser/components/enterprisepolicies/schemas/policies-schema.json | 4 browser/components/preferences/dialogs/browserLanguages.xhtml | 9 browser/components/preferences/dialogs/languages.xhtml | 9 browser/components/search/SearchSERPTelemetry.sys.mjs | 5 browser/components/search/extensions/daum-kr/manifest.json | 6 browser/components/search/extensions/salidzinilv/manifest.json | 6 browser/components/search/extensions/yahoo-jp-auctions/manifest.json | 6 browser/components/search/metrics.yaml | 17 browser/components/search/schema/search-telemetry-schema.json | 12 browser/components/search/schema/search-telemetry-ui-schema.json | 1 browser/components/search/test/browser/browser_search_telemetry_engagement_content.js | 48 browser/components/search/test/unit/test_search_telemetry_config_validation.js | 10 browser/config/version.txt | 2 browser/config/version_display.txt | 2 browser/locales/en-US/browser/policies/policies-descriptions.ftl | 2 browser/themes/shared/preferences/preferences.css | 13 config/milestone.txt | 2 debian/changelog | 18 debian/patches/debian-hacks/Set-DPI-to-system-settings.patch | 4 dom/base/nsGlobalWindowOuter.cpp | 5 dom/canvas/WebGLContext.cpp | 12 dom/canvas/WebGLTextureUpload.cpp | 1 dom/canvas/test/webgl-conf/generated-mochitest.ini | 1 dom/canvas/test/webgl-conf/mochitest-errata.ini | 1 dom/fs/api/FileSystemWritableFileStream.cpp | 369 dom/fs/api/FileSystemWritableFileStream.h | 33 dom/fs/child/FileSystemRequestHandler.cpp | 99 dom/fs/test/crashtests/1841702.html | 16 dom/fs/test/crashtests/crashtests.list | 1 dom/media/gtest/TestCDMStorage.cpp | 33 dom/media/gtest/TestGMPCrossOrigin.cpp | 3 dom/messagechannel/MessagePort.cpp | 8 dom/streams/ReadableByteStreamController.cpp | 154 dom/streams/ReadableByteStreamController.h | 138 dom/workers/sharedworkers/SharedWorkerService.cpp | 7 editor/libeditor/HTMLStyleEditor.cpp | 4 gfx/gl/GLLibraryEGL.cpp | 8 gfx/layers/NativeLayerCA.mm | 1 gfx/layers/apz/src/AsyncPanZoomController.cpp | 52 gfx/layers/apz/src/AsyncPanZoomController.h | 1 gfx/layers/ipc/CompositorBridgeParent.cpp | 27 gfx/thebes/gfxDWriteFontList.cpp | 17 gfx/thebes/gfxTextRun.cpp | 10 js/src/vm/JSContext.cpp | 2 layout/base/nsRefreshDriver.cpp | 295 layout/base/nsRefreshDriver.h | 10 layout/generic/nsFrameSelection.cpp | 7 modules/libpref/init/StaticPrefList.yaml | 21 netwerk/base/nsIOService.cpp | 7 netwerk/base/nsSocketTransportService2.cpp | 8 netwerk/base/nsStandardURL.cpp | 10 netwerk/dns/effective_tld_names.dat | 545 + netwerk/test/unit/test_dooh.js | 4 netwerk/test/unit/test_race_cache_with_network.js | 2 security/manager/ssl/StaticHPKPins.h | 2 security/manager/ssl/nsSTSPreloadList.inc | 4124 +++++----- services/settings/dumps/blocklists/addons-bloomfilters.json | 90 services/settings/dumps/main/cookie-banner-rules-list.json | 750 + services/settings/dumps/main/devtools-compatibility-browsers.json | 396 services/settings/dumps/main/search-telemetry-v2.json | 499 - services/settings/dumps/security-state/intermediates.json | 758 - sourcestamp.txt | 4 testing/web-platform/tests/editing/other/inserttext-after-bold-in-font-face-monospace.html | 32 toolkit/components/places/Database.cpp | 35 toolkit/components/places/tests/maintenance/head.js | 14 toolkit/components/printing/tests/browser.ini | 1 toolkit/components/printing/tests/browser_print_disabled.js | 43 toolkit/components/telemetry/Histograms.json | 26 toolkit/content/gmp-sources/widevinecdm.json | 40 toolkit/content/widgets/wizard.js | 4 widget/windows/nsDragService.cpp | 15 xpcom/base/CycleCollectedJSContext.h | 5 xpcom/base/CycleCollectedJSRuntime.cpp | 83 xpcom/base/CycleCollectedJSRuntime.h | 12 xpcom/base/nsCycleCollector.cpp | 4 xpcom/ds/nsObserverService.cpp | 10 95 files changed, 5493 insertions(+), 4057 deletions(-) diff -Nru firefox-esr-115.4.0esr/CLOBBER firefox-esr-115.5.0esr/CLOBBER --- firefox-esr-115.4.0esr/CLOBBER 2023-10-17 02:48:49.000000000 +0000 +++ firefox-esr-115.5.0esr/CLOBBER 2023-11-13 20:53:44.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 2023-09-25 \ No newline at end of file +Merge day clobber 2023-10-23 \ No newline at end of file diff -Nru firefox-esr-115.4.0esr/accessible/atk/AccessibleWrap.cpp firefox-esr-115.5.0esr/accessible/atk/AccessibleWrap.cpp --- firefox-esr-115.4.0esr/accessible/atk/AccessibleWrap.cpp 2023-10-17 02:48:49.000000000 +0000 +++ firefox-esr-115.5.0esr/accessible/atk/AccessibleWrap.cpp 2023-11-13 20:53:44.000000000 +0000 @@ -927,6 +927,8 @@ } void a11y::ProxyCreated(RemoteAccessible* aProxy) { + MOZ_ASSERT(aProxy->RemoteParent() || aProxy->IsDoc(), + "Need parent to check for HyperLink interface"); GType type = GetMaiAtkType(GetInterfacesForProxy(aProxy)); NS_ASSERTION(type, "why don't we have a type!"); diff -Nru firefox-esr-115.4.0esr/accessible/base/CachedTableAccessible.cpp firefox-esr-115.5.0esr/accessible/base/CachedTableAccessible.cpp --- firefox-esr-115.4.0esr/accessible/base/CachedTableAccessible.cpp 2023-10-17 02:48:49.000000000 +0000 +++ firefox-esr-115.5.0esr/accessible/base/CachedTableAccessible.cpp 2023-11-13 20:53:44.000000000 +0000 @@ -230,11 +230,25 @@ Accessible* aAcc) { MOZ_ASSERT(aAcc->IsTableCell()); for (Accessible* parent = aAcc; parent; parent = parent->Parent()) { - if (auto* table = static_cast(parent->AsTable())) { - if (auto cellIdx = table->mAccToCellIdx.Lookup(aAcc)) { - return &table->mCells[*cellIdx]; + if (parent->IsDoc()) { + break; // Never cross document boundaries. + } + TableAccessible* table = parent->AsTable(); + if (!table) { + continue; + } + if (LocalAccessible* local = parent->AsLocal()) { + nsIContent* content = local->GetContent(); + if (content && content->IsXULElement()) { + // XUL tables don't use CachedTableAccessible. + break; } } + // Non-XUL tables only use CachedTableAccessible. + auto* cachedTable = static_cast(table); + if (auto cellIdx = cachedTable->mAccToCellIdx.Lookup(aAcc)) { + return &cachedTable->mCells[*cellIdx]; + } } return nullptr; } diff -Nru firefox-esr-115.4.0esr/accessible/generic/DocAccessible.cpp firefox-esr-115.5.0esr/accessible/generic/DocAccessible.cpp --- firefox-esr-115.4.0esr/accessible/generic/DocAccessible.cpp 2023-10-17 02:48:49.000000000 +0000 +++ firefox-esr-115.5.0esr/accessible/generic/DocAccessible.cpp 2023-11-13 20:53:44.000000000 +0000 @@ -1673,7 +1673,7 @@ SendCache(CacheDomain::All, CacheUpdateType::Initial); for (auto idx = 0U; idx < mChildren.Length(); idx++) { - ipcDoc->InsertIntoIpcTree(this, mChildren.ElementAt(idx), idx, true); + ipcDoc->InsertIntoIpcTree(mChildren.ElementAt(idx), true); } } } diff -Nru firefox-esr-115.4.0esr/accessible/ipc/DocAccessibleChildBase.cpp firefox-esr-115.5.0esr/accessible/ipc/DocAccessibleChildBase.cpp --- firefox-esr-115.4.0esr/accessible/ipc/DocAccessibleChildBase.cpp 2023-10-17 02:48:49.000000000 +0000 +++ firefox-esr-115.5.0esr/accessible/ipc/DocAccessibleChildBase.cpp 2023-11-13 20:53:43.000000000 +0000 @@ -4,6 +4,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/. */ +#include "chrome/common/ipc_channel.h" #include "mozilla/a11y/DocAccessibleChildBase.h" #include "mozilla/a11y/CacheConstants.h" #include "mozilla/a11y/RemoteAccessible.h" @@ -35,71 +36,76 @@ } /* static */ -void DocAccessibleChildBase::SerializeTree(nsTArray& aTree, - nsTArray& aData) { - for (LocalAccessible* acc : aTree) { - uint64_t id = reinterpret_cast(acc->UniqueID()); - a11y::role role = acc->Role(); - uint32_t childCount = acc->IsOuterDoc() ? 0 : acc->ChildCount(); - - uint32_t genericTypes = acc->mGenericTypes; - if (acc->ARIAHasNumericValue()) { - // XXX: We need to do this because this requires a state check. - genericTypes |= eNumericValue; - } - if (acc->IsTextLeaf() || acc->IsImage()) { - // Ideally, we'd set eActionable for any Accessible with an ancedstor - // action. However, that requires an ancestor walk which is too expensive - // here. eActionable is only used by ATK. For now, we only expose ancestor - // actions on text leaf and image Accessibles. This means that we don't - // support "click ancestor" for ATK. - if (acc->ActionCount()) { - genericTypes |= eActionable; - } - } else if (acc->HasPrimaryAction()) { +AccessibleData DocAccessibleChildBase::SerializeAcc(LocalAccessible* aAcc) { + uint32_t genericTypes = aAcc->mGenericTypes; + if (aAcc->ARIAHasNumericValue()) { + // XXX: We need to do this because this requires a state check. + genericTypes |= eNumericValue; + } + if (aAcc->IsTextLeaf() || aAcc->IsImage()) { + // Ideally, we'd set eActionable for any Accessible with an ancedstor + // action. However, that requires an ancestor walk which is too expensive + // here. eActionable is only used by ATK. For now, we only expose ancestor + // actions on text leaf and image Accessibles. This means that we don't + // support "click ancestor" for ATK. + if (aAcc->ActionCount()) { genericTypes |= eActionable; } + } else if (aAcc->HasPrimaryAction()) { + genericTypes |= eActionable; + } - RefPtr fields; - // Even though we send moves as a hide and a show, we don't want to - // push the cache again for moves. - if (!acc->Document()->IsAccessibleBeingMoved(acc)) { - fields = - acc->BundleFieldsForCache(CacheDomain::All, CacheUpdateType::Initial); - if (fields->Count() == 0) { - fields = nullptr; - } + RefPtr fields; + // Even though we send moves as a hide and a show, we don't want to + // push the cache again for moves. + if (!aAcc->Document()->IsAccessibleBeingMoved(aAcc)) { + fields = + aAcc->BundleFieldsForCache(CacheDomain::All, CacheUpdateType::Initial); + if (fields->Count() == 0) { + fields = nullptr; } - - aData.AppendElement( - AccessibleData(id, role, childCount, static_cast(acc->mType), - static_cast(genericTypes), - acc->mRoleMapEntryIndex, fields)); } + + return AccessibleData(aAcc->ID(), aAcc->Role(), aAcc->LocalParent()->ID(), + static_cast(aAcc->IndexInParent()), + static_cast(aAcc->mType), + static_cast(genericTypes), + aAcc->mRoleMapEntryIndex, fields); } -void DocAccessibleChildBase::InsertIntoIpcTree(LocalAccessible* aParent, - LocalAccessible* aChild, - uint32_t aIdxInParent, +void DocAccessibleChildBase::InsertIntoIpcTree(LocalAccessible* aChild, bool aSuppressShowEvent) { - uint64_t parentID = - aParent->IsDoc() ? 0 : reinterpret_cast(aParent->UniqueID()); nsTArray shownTree; FlattenTree(aChild, shownTree); - ShowEventData data(parentID, aIdxInParent, - nsTArray(shownTree.Length()), - aSuppressShowEvent); - SerializeTree(shownTree, data.NewTree()); + uint32_t totalAccs = shownTree.Length(); + // Exceeding the IPDL maximum message size will cause a crash. Try to avoid + // this by only including kMaxAccsPerMessage Accessibels in a single IPDL + // call. If there are Accessibles beyond this, they will be split across + // multiple calls. + constexpr uint32_t kMaxAccsPerMessage = + IPC::Channel::kMaximumMessageSize / (2 * 1024); + nsTArray data(std::min(kMaxAccsPerMessage, totalAccs)); + for (LocalAccessible* child : shownTree) { + if (data.Length() == kMaxAccsPerMessage) { + if (ipc::ProcessChild::ExpectingShutdown()) { + return; + } + SendShowEvent(data, aSuppressShowEvent, false, false); + data.ClearAndRetainStorage(); + } + data.AppendElement(SerializeAcc(child)); + } if (ipc::ProcessChild::ExpectingShutdown()) { return; } - MaybeSendShowEvent(data, false); + if (!data.IsEmpty()) { + SendShowEvent(data, aSuppressShowEvent, true, false); + } } void DocAccessibleChildBase::ShowEvent(AccShowEvent* aShowEvent) { LocalAccessible* child = aShowEvent->GetAccessible(); - InsertIntoIpcTree(aShowEvent->LocalParent(), child, child->IndexInParent(), - false); + InsertIntoIpcTree(child, false); } mozilla::ipc::IPCResult DocAccessibleChildBase::RecvTakeFocus( diff -Nru firefox-esr-115.4.0esr/accessible/ipc/DocAccessibleChildBase.h firefox-esr-115.5.0esr/accessible/ipc/DocAccessibleChildBase.h --- firefox-esr-115.4.0esr/accessible/ipc/DocAccessibleChildBase.h 2023-10-17 02:48:49.000000000 +0000 +++ firefox-esr-115.5.0esr/accessible/ipc/DocAccessibleChildBase.h 2023-11-13 20:53:44.000000000 +0000 @@ -43,8 +43,7 @@ /** * Serializes a shown tree and sends it to the chrome process. */ - void InsertIntoIpcTree(LocalAccessible* aParent, LocalAccessible* aChild, - uint32_t aIdxInParent, bool aSuppressShowEvent); + void InsertIntoIpcTree(LocalAccessible* aChild, bool aSuppressShowEvent); void ShowEvent(AccShowEvent* aShowEvent); virtual void ActorDestroy(ActorDestroyReason) override { @@ -122,12 +121,7 @@ static void FlattenTree(LocalAccessible* aRoot, nsTArray& aTree); - static void SerializeTree(nsTArray& aTree, - nsTArray& aData); - - virtual void MaybeSendShowEvent(ShowEventData& aData, bool aFromUser) { - Unused << SendShowEvent(aData, aFromUser); - } + static AccessibleData SerializeAcc(LocalAccessible* aAcc); void DetachDocument() { if (mDoc) { diff -Nru firefox-esr-115.4.0esr/accessible/ipc/DocAccessibleParent.cpp firefox-esr-115.5.0esr/accessible/ipc/DocAccessibleParent.cpp --- firefox-esr-115.4.0esr/accessible/ipc/DocAccessibleParent.cpp 2023-10-17 02:48:49.000000000 +0000 +++ firefox-esr-115.5.0esr/accessible/ipc/DocAccessibleParent.cpp 2023-11-13 20:53:44.000000000 +0000 @@ -83,64 +83,102 @@ } mozilla::ipc::IPCResult DocAccessibleParent::RecvShowEvent( - const ShowEventData& aData, const bool& aFromUser) { + nsTArray&& aNewTree, const bool& aEventSuppressed, + const bool& aComplete, const bool& aFromUser) { ACQUIRE_ANDROID_LOCK if (mShutdown) return IPC_OK(); MOZ_ASSERT(CheckDocTree()); - if (aData.NewTree().IsEmpty()) { + if (aNewTree.IsEmpty()) { return IPC_FAIL(this, "No children being added"); } - RemoteAccessible* parent = GetAccessible(aData.ID()); - - // XXX This should really never happen, but sometimes we fail to fire the - // required show events. - if (!parent) { - NS_ERROR("adding child to unknown accessible"); + RemoteAccessible* root = nullptr; + RemoteAccessible* rootParent = nullptr; + RemoteAccessible* lastParent = this; + uint64_t lastParentID = 0; + for (const auto& accData : aNewTree) { + RemoteAccessible* parent = accData.ParentID() == lastParentID + ? lastParent + : GetAccessible(accData.ParentID()); + // XXX This should really never happen, but sometimes we fail to fire the + // required show events. + if (!parent) { + NS_ERROR("adding child to unknown accessible"); #ifdef DEBUG - return IPC_FAIL(this, "unknown parent accessible"); + return IPC_FAIL(this, "unknown parent accessible"); #else - return IPC_OK(); + return IPC_OK(); #endif - } + } - uint32_t newChildIdx = aData.Idx(); - if (newChildIdx > parent->ChildCount()) { - NS_ERROR("invalid index to add child at"); + uint32_t childIdx = accData.IndexInParent(); + if (childIdx > parent->ChildCount()) { + NS_ERROR("invalid index to add child at"); #ifdef DEBUG - return IPC_FAIL(this, "invalid index"); + return IPC_FAIL(this, "invalid index"); #else - return IPC_OK(); + return IPC_OK(); #endif - } - - uint32_t consumed = AddSubtree(parent, aData.NewTree(), 0, newChildIdx); - MOZ_ASSERT(consumed == aData.NewTree().Length()); - - // XXX This shouldn't happen, but if we failed to add children then the below - // is pointless and can crash. - if (!consumed) { - return IPC_FAIL(this, "failed to add children"); - } + } -#ifdef DEBUG - for (uint32_t i = 0; i < consumed; i++) { - uint64_t id = aData.NewTree()[i].ID(); - MOZ_ASSERT(mAccessibles.GetEntry(id)); + RemoteAccessible* child = CreateAcc(accData); + if (!child) { + // This shouldn't happen. + return IPC_FAIL(this, "failed to add children"); + } + if (!root && !mPendingShowChild) { + // This is the first Accessible, which is the root of the shown subtree. + root = child; + rootParent = parent; + } + // If this show event has been split across multiple messages and this is + // not the last message, don't attach the shown root to the tree yet. + // Otherwise, clients might crawl the incomplete subtree and they won't get + // mutation events for the remaining pieces. + if (aComplete || root != child) { + AttachChild(parent, childIdx, child); + } } -#endif MOZ_ASSERT(CheckDocTree()); + if (!aComplete && !mPendingShowChild) { + // This is the first message for a show event split across multiple + // messages. Save the show target for subsequent messages and return. + const auto& accData = aNewTree[0]; + mPendingShowChild = accData.ID(); + mPendingShowParent = accData.ParentID(); + mPendingShowIndex = accData.IndexInParent(); + return IPC_OK(); + } + if (!aComplete) { + // This show event has been split into multiple messages, but this is + // neither the first nor the last message. There's nothing more to do here. + return IPC_OK(); + } + MOZ_ASSERT(aComplete); + if (mPendingShowChild) { + // This is the last message for a show event split across multiple + // messages. Retrieve the saved show target, attach it to the tree and fire + // an event if appropriate. + rootParent = GetAccessible(mPendingShowParent); + MOZ_ASSERT(rootParent); + root = GetAccessible(mPendingShowChild); + MOZ_ASSERT(root); + AttachChild(rootParent, mPendingShowIndex, root); + mPendingShowChild = 0; + mPendingShowParent = 0; + mPendingShowIndex = 0; + } + // Just update, no events. - if (aData.EventSuppressed()) { + if (aEventSuppressed) { return IPC_OK(); } - RemoteAccessible* target = parent->RemoteChildAt(newChildIdx); - ProxyShowHideEvent(target, parent, true, aFromUser); + ProxyShowHideEvent(root, rootParent, true, aFromUser); if (nsCOMPtr obsService = services::GetObserverService()) { @@ -152,7 +190,7 @@ } uint32_t type = nsIAccessibleEvent::EVENT_SHOW; - xpcAccessibleGeneric* xpcAcc = GetXPCAccessible(target); + xpcAccessibleGeneric* xpcAcc = GetXPCAccessible(root); xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this); nsINode* node = nullptr; RefPtr event = @@ -162,71 +200,60 @@ return IPC_OK(); } -uint32_t DocAccessibleParent::AddSubtree( - RemoteAccessible* aParent, const nsTArray& aNewTree, - uint32_t aIdx, uint32_t aIdxInParent) { - if (aNewTree.Length() <= aIdx) { - NS_ERROR("bad index in serialized tree!"); - return 0; - } - - const AccessibleData& newChild = aNewTree[aIdx]; - +RemoteAccessible* DocAccessibleParent::CreateAcc( + const AccessibleData& aAccData) { RemoteAccessible* newProxy; - if ((newProxy = GetAccessible(newChild.ID()))) { + if ((newProxy = GetAccessible(aAccData.ID()))) { // This is a move. Reuse the Accessible; don't destroy it. MOZ_ASSERT(!newProxy->RemoteParent()); - aParent->AddChildAt(aIdxInParent, newProxy); - newProxy->SetParent(aParent); - } else { - if (!aria::IsRoleMapIndexValid(newChild.RoleMapEntryIndex())) { - MOZ_ASSERT_UNREACHABLE("Invalid role map entry index"); - return 0; - } - newProxy = new RemoteAccessible( - newChild.ID(), aParent, this, newChild.Role(), newChild.Type(), - newChild.GenericTypes(), newChild.RoleMapEntryIndex()); - - aParent->AddChildAt(aIdxInParent, newProxy); - mAccessibles.PutEntry(newChild.ID())->mProxy = newProxy; - ProxyCreated(newProxy); + return newProxy; + } - if (RefPtr fields = newChild.CacheFields()) { - newProxy->ApplyCache(CacheUpdateType::Initial, fields); - } + if (!aria::IsRoleMapIndexValid(aAccData.RoleMapEntryIndex())) { + MOZ_ASSERT_UNREACHABLE("Invalid role map entry index"); + return nullptr; + } + + newProxy = new RemoteAccessible(aAccData.ID(), this, aAccData.Role(), + aAccData.Type(), aAccData.GenericTypes(), + aAccData.RoleMapEntryIndex()); + mAccessibles.PutEntry(aAccData.ID())->mProxy = newProxy; + + if (RefPtr fields = aAccData.CacheFields()) { + newProxy->ApplyCache(CacheUpdateType::Initial, fields); + } + return newProxy; +} + +void DocAccessibleParent::AttachChild(RemoteAccessible* aParent, + uint32_t aIndex, + RemoteAccessible* aChild) { + aParent->AddChildAt(aIndex, aChild); + aChild->SetParent(aParent); + // ProxyCreated might have already been called if aChild is being moved. + if (!aChild->GetWrapper()) { + ProxyCreated(aChild); + } + if (aChild->IsTableCell()) { + CachedTableAccessible::Invalidate(aChild); + } + if (aChild->IsOuterDoc()) { + // We can only do this after ProxyCreated is called because it will fire an + // event on aChild. mPendingOOPChildDocs.RemoveIf([&](dom::BrowserBridgeParent* bridge) { MOZ_ASSERT(bridge->GetBrowserParent(), "Pending BrowserBridgeParent should be alive"); - if (bridge->GetEmbedderAccessibleId() != newChild.ID()) { + if (bridge->GetEmbedderAccessibleId() != aChild->ID()) { return false; } MOZ_ASSERT(bridge->GetEmbedderAccessibleDoc() == this); if (DocAccessibleParent* childDoc = bridge->GetDocAccessibleParent()) { - AddChildDoc(childDoc, newChild.ID(), false); + AddChildDoc(childDoc, aChild->ID(), false); } return true; }); } - - if (newProxy->IsTableCell()) { - CachedTableAccessible::Invalidate(newProxy); - } - - DebugOnly isOuterDoc = newProxy->ChildCount() == 1; - - uint32_t accessibles = 1; - uint32_t kids = newChild.ChildrenCount(); - for (uint32_t i = 0; i < kids; i++) { - uint32_t consumed = AddSubtree(newProxy, aNewTree, aIdx + accessibles, i); - if (!consumed) return 0; - - accessibles += consumed; - } - - MOZ_ASSERT((isOuterDoc && kids == 0) || newProxy->ChildCount() == kids); - - return accessibles; } void DocAccessibleParent::ShutdownOrPrepareForMove(RemoteAccessible* aAcc) { @@ -323,6 +350,10 @@ if (mShutdown) { return IPC_OK(); } + if (aEventType == 0 || aEventType >= nsIAccessibleEvent::EVENT_LAST_ENTRY) { + MOZ_ASSERT_UNREACHABLE("Invalid event"); + return IPC_FAIL(this, "Invalid event"); + } RemoteAccessible* remote = GetAccessible(aID); if (!remote) { @@ -516,6 +547,10 @@ if (mShutdown) { return IPC_OK(); } + if (aType == 0 || aType >= nsIAccessibleEvent::EVENT_LAST_ENTRY) { + MOZ_ASSERT_UNREACHABLE("Invalid event"); + return IPC_FAIL(this, "Invalid event"); + } RemoteAccessible* target = GetAccessible(aID); RemoteAccessible* widget = GetAccessible(aWidgetID); @@ -588,6 +623,10 @@ if (mShutdown) { return IPC_OK(); } + if (aType == 0 || aType >= nsIAccessibleEvent::EVENT_LAST_ENTRY) { + MOZ_ASSERT_UNREACHABLE("Invalid event"); + return IPC_FAIL(this, "Invalid event"); + } RemoteAccessible* target = GetAccessible(aID); if (!target) { @@ -764,6 +803,10 @@ if (mShutdown) { return IPC_OK(); } + if (!aria::IsRoleMapIndexValid(aRoleMapEntryIndex)) { + MOZ_ASSERT_UNREACHABLE("Invalid role map entry index"); + return IPC_FAIL(this, "Invalid role map entry index"); + } mRole = aRole; mRoleMapEntryIndex = aRoleMapEntryIndex; diff -Nru firefox-esr-115.4.0esr/accessible/ipc/DocAccessibleParent.h firefox-esr-115.5.0esr/accessible/ipc/DocAccessibleParent.h --- firefox-esr-115.4.0esr/accessible/ipc/DocAccessibleParent.h 2023-10-17 02:48:49.000000000 +0000 +++ firefox-esr-115.5.0esr/accessible/ipc/DocAccessibleParent.h 2023-11-13 20:53:44.000000000 +0000 @@ -106,8 +106,9 @@ virtual mozilla::ipc::IPCResult RecvEvent(const uint64_t& aID, const uint32_t& aType) override; - virtual mozilla::ipc::IPCResult RecvShowEvent(const ShowEventData& aData, - const bool& aFromUser) override; + virtual mozilla::ipc::IPCResult RecvShowEvent( + nsTArray&& aNewTree, const bool& aEventSuppressed, + const bool& aComplete, const bool& aFromUser) override; virtual mozilla::ipc::IPCResult RecvHideEvent(const uint64_t& aRootID, const bool& aFromUser) override; mozilla::ipc::IPCResult RecvStateChangeEvent(const uint64_t& aID, @@ -379,9 +380,9 @@ RemoteAccessible* mProxy; }; - uint32_t AddSubtree(RemoteAccessible* aParent, - const nsTArray& aNewTree, uint32_t aIdx, - uint32_t aIdxInParent); + RemoteAccessible* CreateAcc(const AccessibleData& aAccData); + void AttachChild(RemoteAccessible* aParent, uint32_t aIndex, + RemoteAccessible* aChild); [[nodiscard]] bool CheckDocTree() const; xpcAccessibleGeneric* GetXPCAccessible(RemoteAccessible* aProxy); @@ -406,6 +407,9 @@ * proxy object so we can't use a real map. */ nsTHashtable mAccessibles; + uint64_t mPendingShowChild = 0; + uint64_t mPendingShowParent = 0; + uint32_t mPendingShowIndex = 0; nsTHashSet mMovingIDs; uint64_t mActorID; bool mTopLevel; diff -Nru firefox-esr-115.4.0esr/accessible/ipc/RemoteAccessibleBase.h firefox-esr-115.5.0esr/accessible/ipc/RemoteAccessibleBase.h --- firefox-esr-115.4.0esr/accessible/ipc/RemoteAccessibleBase.h 2023-10-17 02:48:49.000000000 +0000 +++ firefox-esr-115.5.0esr/accessible/ipc/RemoteAccessibleBase.h 2023-11-13 20:53:44.000000000 +0000 @@ -421,11 +421,11 @@ virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf); protected: - RemoteAccessibleBase(uint64_t aID, Derived* aParent, + RemoteAccessibleBase(uint64_t aID, DocAccessibleParent* aDoc, role aRole, AccType aType, AccGenericType aGenericTypes, uint8_t aRoleMapEntryIndex) : Accessible(aType, aGenericTypes, aRoleMapEntryIndex), - mParent(aParent->ID()), + mParent(kNoParent), mDoc(aDoc), mWrapper(0), mID(aID), diff -Nru firefox-esr-115.4.0esr/accessible/ipc/other/PDocAccessible.ipdl firefox-esr-115.5.0esr/accessible/ipc/other/PDocAccessible.ipdl --- firefox-esr-115.4.0esr/accessible/ipc/other/PDocAccessible.ipdl 2023-10-17 02:48:49.000000000 +0000 +++ firefox-esr-115.5.0esr/accessible/ipc/other/PDocAccessible.ipdl 2023-11-13 20:53:44.000000000 +0000 @@ -28,7 +28,8 @@ { uint64_t ID; role Role; - uint32_t ChildrenCount; + uint64_t ParentID; + uint32_t IndexInParent; AccType Type; AccGenericType GenericTypes; uint8_t RoleMapEntryIndex; @@ -40,14 +41,6 @@ PDocAccessible; }; -struct ShowEventData -{ - uint64_t ID; - uint32_t Idx; - AccessibleData[] NewTree; - bool EventSuppressed; -}; - struct RelationTargets { uint32_t Type; @@ -77,7 +70,8 @@ * event. */ async Event(uint64_t aID, uint32_t type); - async ShowEvent(ShowEventData data, bool aFromuser); + async ShowEvent(AccessibleData[] aNewTree, bool aEventSuppressed, + bool aComplete, bool aFromuser); async HideEvent(uint64_t aRootID, bool aFromUser); async StateChangeEvent(uint64_t aID, uint64_t aState, bool aEnabled); async CaretMoveEvent(uint64_t aID, int32_t aOffset, diff -Nru firefox-esr-115.4.0esr/accessible/ipc/other/RemoteAccessible.h firefox-esr-115.5.0esr/accessible/ipc/other/RemoteAccessible.h --- firefox-esr-115.4.0esr/accessible/ipc/other/RemoteAccessible.h 2023-10-17 02:48:49.000000000 +0000 +++ firefox-esr-115.5.0esr/accessible/ipc/other/RemoteAccessible.h 2023-11-13 20:53:44.000000000 +0000 @@ -25,10 +25,10 @@ */ class RemoteAccessible : public RemoteAccessibleBase { public: - RemoteAccessible(uint64_t aID, RemoteAccessible* aParent, + RemoteAccessible(uint64_t aID, DocAccessibleParent* aDoc, role aRole, AccType aType, AccGenericType aGenericTypes, uint8_t aRoleMapEntryIndex) - : RemoteAccessibleBase(aID, aParent, aDoc, aRole, aType, aGenericTypes, + : RemoteAccessibleBase(aID, aDoc, aRole, aType, aGenericTypes, aRoleMapEntryIndex) { MOZ_COUNT_CTOR(RemoteAccessible); } diff -Nru firefox-esr-115.4.0esr/accessible/ipc/win/PDocAccessible.ipdl firefox-esr-115.5.0esr/accessible/ipc/win/PDocAccessible.ipdl --- firefox-esr-115.4.0esr/accessible/ipc/win/PDocAccessible.ipdl 2023-10-17 02:48:50.000000000 +0000 +++ firefox-esr-115.5.0esr/accessible/ipc/win/PDocAccessible.ipdl 2023-11-13 20:53:44.000000000 +0000 @@ -26,21 +26,14 @@ { uint64_t ID; role Role; - uint32_t ChildrenCount; + uint64_t ParentID; + uint32_t IndexInParent; AccType Type; AccGenericType GenericTypes; uint8_t RoleMapEntryIndex; nullable AccAttributes CacheFields; }; -struct ShowEventData -{ - uint64_t ID; - uint32_t Idx; - AccessibleData[] NewTree; - bool EventSuppressed; -}; - struct TextRangeData { uint64_t StartID; @@ -62,7 +55,8 @@ * event. */ async Event(uint64_t aID, uint32_t type); - async ShowEvent(ShowEventData data, bool aFromUser); + async ShowEvent(AccessibleData[] aNewTree, bool aEventSuppressed, + bool aComplete, bool aFromuser); async HideEvent(uint64_t aRootID, bool aFromUser); async StateChangeEvent(uint64_t aID, uint64_t aState, bool aEnabled); async CaretMoveEvent(uint64_t aID, LayoutDeviceIntRect aCaretRect, diff -Nru firefox-esr-115.4.0esr/accessible/ipc/win/RemoteAccessible.h firefox-esr-115.5.0esr/accessible/ipc/win/RemoteAccessible.h --- firefox-esr-115.4.0esr/accessible/ipc/win/RemoteAccessible.h 2023-10-17 02:48:50.000000000 +0000 +++ firefox-esr-115.5.0esr/accessible/ipc/win/RemoteAccessible.h 2023-11-13 20:53:44.000000000 +0000 @@ -19,10 +19,10 @@ */ class RemoteAccessible : public RemoteAccessibleBase { public: - RemoteAccessible(uint64_t aID, RemoteAccessible* aParent, + RemoteAccessible(uint64_t aID, DocAccessibleParent* aDoc, role aRole, AccType aType, AccGenericType aGenericTypes, uint8_t aRoleMapEntryIndex) - : RemoteAccessibleBase(aID, aParent, aDoc, aRole, aType, aGenericTypes, + : RemoteAccessibleBase(aID, aDoc, aRole, aType, aGenericTypes, aRoleMapEntryIndex) { MOZ_COUNT_CTOR(RemoteAccessible); } diff -Nru firefox-esr-115.4.0esr/accessible/tests/browser/e10s/browser.ini firefox-esr-115.5.0esr/accessible/tests/browser/e10s/browser.ini --- firefox-esr-115.4.0esr/accessible/tests/browser/e10s/browser.ini 2023-10-17 02:48:49.000000000 +0000 +++ firefox-esr-115.5.0esr/accessible/tests/browser/e10s/browser.ini 2023-11-13 20:53:44.000000000 +0000 @@ -28,6 +28,7 @@ [browser_caching_innerHTML.js] skip-if = os != 'win' [browser_caching_interfaces.js] +[browser_caching_large_update.js] [browser_caching_name.js] [browser_caching_position.js] [browser_caching_relations.js] diff -Nru firefox-esr-115.4.0esr/accessible/tests/browser/e10s/browser_caching_large_update.js firefox-esr-115.5.0esr/accessible/tests/browser/e10s/browser_caching_large_update.js --- firefox-esr-115.4.0esr/accessible/tests/browser/e10s/browser_caching_large_update.js 1970-01-01 00:00:00.000000000 +0000 +++ firefox-esr-115.5.0esr/accessible/tests/browser/e10s/browser_caching_large_update.js 2023-11-13 20:53:44.000000000 +0000 @@ -0,0 +1,66 @@ +/* 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/. */ + +"use strict"; + +/** + * Test a large update which adds many thousands of Accessibles with a + * lot of content in each. + */ +addAccessibleTask( + `
`, + async function (browser, docAcc) { + let shown = waitForEvent(EVENT_SHOW, "main"); + await invokeContentTask(browser, [], () => { + // Make a long string. + let text = ""; + for (let i = 0; i < 100; ++i) { + text += "a"; + } + // Create lots of nodes which include the long string. + const contMain = content.document.getElementById("main"); + // 15000 children of main. + for (let w = 0; w < 15000; ++w) { + // Each of those goes 9 deep. + let parent = contMain; + for (let d = 0; d < 10; ++d) { + const div = content.document.createElement("div"); + div.setAttribute("aria-label", `${w} ${d} ${text}`); + parent.append(div); + parent = div; + } + } + contMain.hidden = false; + }); + const main = (await shown).accessible; + is(main.childCount, 15000, "main has correct number of children"); + + // We don't want to output passes for every check, since that would output + // hundreds of thousands of lines, which slows the test to a crawl. Instead, + // output any failures and keep track of overall success/failure. + let treeOk = true; + function check(val, msg) { + if (!val) { + ok(false, msg); + treeOk = false; + } + } + + info("Checking tree"); + for (let w = 0; w < 15000; ++w) { + let acc = main.getChildAt(w); + let parent = main; + for (let d = 0; d < 10; ++d) { + check(acc, `Got child ${w} depth ${d}`); + const name = `${w} ${d}`; + check(acc.name.startsWith(name + " "), `${name}: correct name`); + check(acc.parent == parent, `${name}: correct parent`); + parent = acc; + acc = acc.firstChild; + } + } + // check() sets treeOk to false for any failure. + ok(treeOk, "Tree is correct"); + } +); diff -Nru firefox-esr-115.4.0esr/accessible/windows/msaa/MsaaAccessible.cpp firefox-esr-115.5.0esr/accessible/windows/msaa/MsaaAccessible.cpp --- firefox-esr-115.4.0esr/accessible/windows/msaa/MsaaAccessible.cpp 2023-10-17 02:48:49.000000000 +0000 +++ firefox-esr-115.5.0esr/accessible/windows/msaa/MsaaAccessible.cpp 2023-11-13 20:53:44.000000000 +0000 @@ -206,8 +206,10 @@ nsIAccessibleEvent::EVENT_LAST_ENTRY, "MSAA event map skewed"); - NS_ASSERTION(aEventType > 0 && aEventType < ArrayLength(gWinEventMap), - "invalid event type"); + if (aEventType == 0 || aEventType >= ArrayLength(gWinEventMap)) { + MOZ_ASSERT_UNREACHABLE("invalid event type"); + return; + } uint32_t winEvent = gWinEventMap[aEventType]; if (!winEvent) return; diff -Nru firefox-esr-115.4.0esr/browser/base/content/browser-fullScreenAndPointerLock.js firefox-esr-115.5.0esr/browser/base/content/browser-fullScreenAndPointerLock.js --- firefox-esr-115.4.0esr/browser/base/content/browser-fullScreenAndPointerLock.js 2023-10-17 02:48:49.000000000 +0000 +++ firefox-esr-115.5.0esr/browser/base/content/browser-fullScreenAndPointerLock.js 2023-11-13 20:53:44.000000000 +0000 @@ -6,6 +6,8 @@ // This file is loaded into the browser window scope. /* eslint-env mozilla/browser-window */ +const FS_PERM_PROMPT_TIME_SHOWN_OFFSET_MS = 2000; + var PointerlockFsWarning = { _element: null, _origin: null, @@ -466,6 +468,11 @@ this._permissionNotificationIDs ).filter(n => !n.dismissed).length ) { + if (PopupNotifications.panel.firstChild) { + PopupNotifications.panel.firstChild.notification.timeShown += + FS_PERM_PROMPT_TIME_SHOWN_OFFSET_MS; + } + this.exitDomFullScreen(); this._logWarningPermissionPromptFS("fullScreenCanceled"); } diff -Nru firefox-esr-115.4.0esr/browser/base/content/browser.js firefox-esr-115.5.0esr/browser/base/content/browser.js --- firefox-esr-115.4.0esr/browser/base/content/browser.js 2023-10-17 02:48:49.000000000 +0000 +++ firefox-esr-115.5.0esr/browser/base/content/browser.js 2023-11-13 20:53:44.000000000 +0000 @@ -579,6 +579,16 @@ XPCOMUtils.defineLazyPreferenceGetter( this, + "gPrintEnabled", + "print.enabled", + false, + (aPref, aOldVal, aNewVal) => { + updatePrintCommands(aNewVal); + } +); + +XPCOMUtils.defineLazyPreferenceGetter( + this, "gScreenshotsComponentEnabled", "screenshots.browser.component.enabled", false, @@ -811,6 +821,19 @@ } } +function updatePrintCommands(enabled) { + var printCommand = document.getElementById("cmd_print"); + var printPreviewCommand = document.getElementById("cmd_printPreviewToggle"); + + if (enabled) { + printCommand.removeAttribute("disabled"); + printPreviewCommand.removeAttribute("disabled"); + } else { + printCommand.setAttribute("disabled", "true"); + printPreviewCommand.setAttribute("disabled", "true"); + } +} + /** * Click-and-Hold implementation for the Back and Forward buttons * XXXmano: should this live in toolbarbutton.js? @@ -1636,6 +1659,8 @@ updateFxaToolbarMenu(gFxaToolbarEnabled, true); + updatePrintCommands(gPrintEnabled); + gUnifiedExtensions.init(); // Setting the focus will cause a style flush, it's preferable to call anything diff -Nru firefox-esr-115.4.0esr/browser/components/enterprisepolicies/Policies.sys.mjs firefox-esr-115.5.0esr/browser/components/enterprisepolicies/Policies.sys.mjs --- firefox-esr-115.4.0esr/browser/components/enterprisepolicies/Policies.sys.mjs 2023-10-17 02:48:50.000000000 +0000 +++ firefox-esr-115.5.0esr/browser/components/enterprisepolicies/Policies.sys.mjs 2023-11-13 20:53:44.000000000 +0000 @@ -1712,6 +1712,7 @@ "network.", "pdfjs.", "places.", + "pref.", "print.", "signon.", "spellchecker.", @@ -1863,6 +1864,12 @@ }, }, + PrintingEnabled: { + onBeforeUIStartup(manager, param) { + setAndLockPref("print.enabled", param); + }, + }, + PromptForDownloadLocation: { onBeforeAddons(manager, param) { setAndLockPref("browser.download.useDownloadDir", !param); diff -Nru firefox-esr-115.4.0esr/browser/components/enterprisepolicies/schemas/policies-schema.json firefox-esr-115.5.0esr/browser/components/enterprisepolicies/schemas/policies-schema.json --- firefox-esr-115.4.0esr/browser/components/enterprisepolicies/schemas/policies-schema.json 2023-10-17 02:48:49.000000000 +0000 +++ firefox-esr-115.5.0esr/browser/components/enterprisepolicies/schemas/policies-schema.json 2023-11-13 20:53:44.000000000 +0000 @@ -1141,6 +1141,10 @@ "type": "boolean" }, + "PrintingEnabled": { + "type": "boolean" + }, + "PromptForDownloadLocation": { "type": "boolean" }, diff -Nru firefox-esr-115.4.0esr/browser/components/preferences/dialogs/browserLanguages.xhtml firefox-esr-115.5.0esr/browser/components/preferences/dialogs/browserLanguages.xhtml --- firefox-esr-115.4.0esr/browser/components/preferences/dialogs/browserLanguages.xhtml 2023-10-17 02:48:50.000000000 +0000 +++ firefox-esr-115.5.0esr/browser/components/preferences/dialogs/browserLanguages.xhtml 2023-11-13 20:53:44.000000000 +0000 @@ -31,14 +31,7 @@ - +