morgan pushed to branch tor-browser-128.11.0esr-14.5-1 at The Tor Project / Applications / Tor Browser
Commits:
- 
cf2ad16e
by smayya at 2025-05-23T15:19:13+02:00
- 
cfce6bf9
by hackademix at 2025-05-23T15:32:07+02:00
- 
35fdd814
by Oskar Mansfeld at 2025-05-23T15:32:20+02:00
- 
43f9f11c
by Daniel Holbert at 2025-05-23T15:32:21+02:00
- 
52f4b900
by Daniel Holbert at 2025-05-23T15:32:22+02:00
- 
bec689db
by Daniel Holbert at 2025-05-23T15:32:22+02:00
- 
bdc25770
by Gijs Kruitbosch at 2025-05-23T16:01:30+02:00
- 
ab178f3e
by morgan at 2025-05-26T15:45:37+00:00
15 changed files:
- browser/app/profile/001-base-profile.js
- dom/svg/DOMSVGLength.cpp
- dom/svg/DOMSVGLength.h
- dom/svg/DOMSVGPoint.cpp
- dom/svg/DOMSVGPoint.h
- dom/svg/DOMSVGPointList.cpp
- dom/svg/DOMSVGPointList.h
- dom/svg/DOMSVGStringList.cpp
- dom/svg/DOMSVGStringList.h
- modules/libpref/init/StaticPrefList.yaml
- netwerk/base/nsIOService.cpp
- netwerk/base/nsSocketTransport2.cpp
- netwerk/protocol/http/HttpConnectionUDP.cpp
- netwerk/test/unit/trr_common.js
- toolkit/components/aboutmemory/content/aboutMemory.js
Changes:
| ... | ... | @@ -536,6 +536,11 @@ pref("network.proxy.failover_direct", false, locked); | 
| 536 | 536 |  // alters content load order in a page. See tor-browser#24686
 | 
| 537 | 537 |  pref("network.http.tailing.enabled", true, locked);
 | 
| 538 | 538 | |
| 539 | +// Block 0.0.0.0
 | |
| 540 | +// https://bugzilla.mozilla.org/show_bug.cgi?id=1889130
 | |
| 541 | +// tor-browser#43811
 | |
| 542 | +pref("network.socket.ip_addr_any.disabled", true);
 | |
| 543 | + | |
| 539 | 544 |  // tor-browser#23044: Make sure we don't have any GIO supported protocols
 | 
| 540 | 545 |  // (defense in depth measure).
 | 
| 541 | 546 |  // As of Firefox 118 (Bug 1843763), upstream does not add any protocol by
 | 
| ... | ... | @@ -51,6 +51,7 @@ DOMSVGLength::DOMSVGLength(DOMSVGLengthList* aList, uint8_t aAttrEnum, | 
| 51 | 51 |        mListIndex(aListIndex),
 | 
| 52 | 52 |        mAttrEnum(aAttrEnum),
 | 
| 53 | 53 |        mIsAnimValItem(aIsAnimValItem),
 | 
| 54 | +      mIsInTearoffTable(false),
 | |
| 54 | 55 |        mUnit(SVGLength_Binding::SVG_LENGTHTYPE_NUMBER) {
 | 
| 55 | 56 |    MOZ_ASSERT(aList, "bad arg");
 | 
| 56 | 57 |    MOZ_ASSERT(mAttrEnum == aAttrEnum, "bitfield too small");
 | 
| ... | ... | @@ -63,6 +64,7 @@ DOMSVGLength::DOMSVGLength() | 
| 63 | 64 |        mListIndex(0),
 | 
| 64 | 65 |        mAttrEnum(0),
 | 
| 65 | 66 |        mIsAnimValItem(false),
 | 
| 67 | +      mIsInTearoffTable(false),
 | |
| 66 | 68 |        mUnit(SVGLength_Binding::SVG_LENGTHTYPE_NUMBER) {}
 | 
| 67 | 69 | |
| 68 | 70 |  DOMSVGLength::DOMSVGLength(SVGAnimatedLength* aVal, SVGElement* aSVGElement,
 | 
| ... | ... | @@ -71,6 +73,7 @@ DOMSVGLength::DOMSVGLength(SVGAnimatedLength* aVal, SVGElement* aSVGElement, | 
| 71 | 73 |        mListIndex(0),
 | 
| 72 | 74 |        mAttrEnum(aVal->mAttrEnum),
 | 
| 73 | 75 |        mIsAnimValItem(aAnimVal),
 | 
| 76 | +      mIsInTearoffTable(false),
 | |
| 74 | 77 |        mUnit(SVGLength_Binding::SVG_LENGTHTYPE_NUMBER) {
 | 
| 75 | 78 |    MOZ_ASSERT(aVal, "bad arg");
 | 
| 76 | 79 |    MOZ_ASSERT(mAttrEnum == aVal->mAttrEnum, "bitfield too small");
 | 
| ... | ... | @@ -88,22 +91,33 @@ void DOMSVGLength::CleanupWeakRefs() { | 
| 88 | 91 | |
| 89 | 92 |    // Similarly, we must update the tearoff table to remove its (non-owning)
 | 
| 90 | 93 |    // pointer to mVal.
 | 
| 91 | -  if (nsCOMPtr<SVGElement> svg = do_QueryInterface(mOwner)) {
 | |
| 92 | -    auto& table = mIsAnimValItem ? sAnimSVGLengthTearOffTable
 | |
| 93 | -                                 : sBaseSVGLengthTearOffTable;
 | |
| 94 | -    table.RemoveTearoff(svg->GetAnimatedLength(mAttrEnum));
 | |
| 94 | +  if (mIsInTearoffTable) {
 | |
| 95 | +    nsCOMPtr<SVGElement> svg = do_QueryInterface(mOwner);
 | |
| 96 | +    MOZ_ASSERT(svg,
 | |
| 97 | +               "We need our svgElement reference in order to remove "
 | |
| 98 | +               "ourselves from tearoff table...");
 | |
| 99 | +    if (MOZ_LIKELY(svg)) {
 | |
| 100 | +      auto& table = mIsAnimValItem ? sAnimSVGLengthTearOffTable
 | |
| 101 | +                                   : sBaseSVGLengthTearOffTable;
 | |
| 102 | +      table.RemoveTearoff(svg->GetAnimatedLength(mAttrEnum));
 | |
| 103 | +      mIsInTearoffTable = false;
 | |
| 104 | +    }
 | |
| 95 | 105 |    }
 | 
| 96 | 106 |  }
 | 
| 97 | 107 | |
| 98 | 108 |  already_AddRefed<DOMSVGLength> DOMSVGLength::GetTearOff(SVGAnimatedLength* aVal,
 | 
| 99 | 109 |                                                          SVGElement* aSVGElement,
 | 
| 100 | 110 |                                                          bool aAnimVal) {
 | 
| 111 | +  MOZ_ASSERT(aVal && aSVGElement, "Expecting non-null aVal and aSVGElement");
 | |
| 112 | +  MOZ_ASSERT(aVal == aSVGElement->GetAnimatedLength(aVal->mAttrEnum),
 | |
| 113 | +             "Mismatched aVal/SVGElement?");
 | |
| 101 | 114 |    auto& table =
 | 
| 102 | 115 |        aAnimVal ? sAnimSVGLengthTearOffTable : sBaseSVGLengthTearOffTable;
 | 
| 103 | 116 |    RefPtr<DOMSVGLength> domLength = table.GetTearoff(aVal);
 | 
| 104 | 117 |    if (!domLength) {
 | 
| 105 | 118 |      domLength = new DOMSVGLength(aVal, aSVGElement, aAnimVal);
 | 
| 106 | 119 |      table.AddTearoff(aVal, domLength);
 | 
| 120 | +    domLength->mIsInTearoffTable = true;
 | |
| 107 | 121 |    }
 | 
| 108 | 122 | |
| 109 | 123 |    return domLength.forget();
 | 
| ... | ... | @@ -15,7 +15,7 @@ | 
| 15 | 15 |  #include "mozilla/Attributes.h"
 | 
| 16 | 16 |  #include "nsWrapperCache.h"
 | 
| 17 | 17 | |
| 18 | -#define MOZ_SVG_LIST_INDEX_BIT_COUNT 22  // supports > 4 million list items
 | |
| 18 | +#define MOZ_SVG_LIST_INDEX_BIT_COUNT 21  // supports > 2 million list items
 | |
| 19 | 19 | |
| 20 | 20 |  namespace mozilla {
 | 
| 21 | 21 | |
| ... | ... | @@ -204,6 +204,13 @@ class DOMSVGLength final : public nsWrapperCache { | 
| 204 | 204 |    uint32_t mAttrEnum : 4;  // supports up to 16 attributes
 | 
| 205 | 205 |    uint32_t mIsAnimValItem : 1;
 | 
| 206 | 206 | |
| 207 | +  // Tracks whether we're in the tearoff table. Initialized to false in the
 | |
| 208 | +  // ctor, but then immediately set to true after we're added to the table
 | |
| 209 | +  // (unless we're an instance created via 'Copy()'; those never get added to
 | |
| 210 | +  // the table).  Updated to false when we're removed from the table (at which
 | |
| 211 | +  // point we're being destructed or soon-to-be destructed).
 | |
| 212 | +  uint32_t mIsInTearoffTable : 1;
 | |
| 213 | + | |
| 207 | 214 |    // The following members are only used when we're not in a list:
 | 
| 208 | 215 |    uint32_t mUnit : 5;  // can handle 31 units (the 10 SVG 1.1 units + rem, vw,
 | 
| 209 | 216 |                         // vh, wm, calc + future additions)
 | 
| ... | ... | @@ -167,6 +167,7 @@ already_AddRefed<DOMSVGPoint> DOMSVGPoint::GetTranslateTearOff( | 
| 167 | 167 |    if (!domPoint) {
 | 
| 168 | 168 |      domPoint = new DOMSVGPoint(aVal, aSVGSVGElement);
 | 
| 169 | 169 |      sSVGTranslateTearOffTable.AddTearoff(aVal, domPoint);
 | 
| 170 | +    domPoint->mIsInTearoffTable = true;
 | |
| 170 | 171 |    }
 | 
| 171 | 172 | |
| 172 | 173 |    return domPoint.forget();
 | 
| ... | ... | @@ -203,12 +204,18 @@ void DOMSVGPoint::CleanupWeakRefs() { | 
| 203 | 204 |      pointList->mItems[mListIndex] = nullptr;
 | 
| 204 | 205 |    }
 | 
| 205 | 206 | |
| 207 | +  if (mIsInTearoffTable) {
 | |
| 208 | +    // Similarly, we must update the tearoff table to remove its (non-owning)
 | |
| 209 | +    // pointer to mVal.
 | |
| 210 | +    MOZ_ASSERT(mVal && mIsTranslatePoint,
 | |
| 211 | +               "Tearoff table should only be used for translate-point objects "
 | |
| 212 | +               "with non-null mVal (see GetTranslateTearOff and its callers)");
 | |
| 213 | +    sSVGTranslateTearOffTable.RemoveTearoff(mVal);
 | |
| 214 | +    mIsInTearoffTable = false;
 | |
| 215 | +  }
 | |
| 216 | + | |
| 206 | 217 |    if (mVal) {
 | 
| 207 | -    if (mIsTranslatePoint) {
 | |
| 208 | -      // Similarly, we must update the tearoff table to remove its (non-owning)
 | |
| 209 | -      // pointer to mVal.
 | |
| 210 | -      sSVGTranslateTearOffTable.RemoveTearoff(mVal);
 | |
| 211 | -    } else {
 | |
| 218 | +    if (!mIsTranslatePoint) {
 | |
| 212 | 219 |        // In this case we own mVal
 | 
| 213 | 220 |        delete mVal;
 | 
| 214 | 221 |      }
 | 
| ... | ... | @@ -17,7 +17,7 @@ | 
| 17 | 17 |  #include "mozilla/dom/SVGSVGElement.h"
 | 
| 18 | 18 |  #include "mozilla/gfx/2D.h"
 | 
| 19 | 19 | |
| 20 | -#define MOZ_SVG_LIST_INDEX_BIT_COUNT 30
 | |
| 20 | +#define MOZ_SVG_LIST_INDEX_BIT_COUNT 29
 | |
| 21 | 21 | |
| 22 | 22 |  namespace mozilla::dom {
 | 
| 23 | 23 |  struct DOMMatrix2DInit;
 | 
| ... | ... | @@ -51,7 +51,8 @@ class DOMSVGPoint final : public nsWrapperCache { | 
| 51 | 51 |          mOwner(aList),
 | 
| 52 | 52 |          mListIndex(aListIndex),
 | 
| 53 | 53 |          mIsAnimValItem(aIsAnimValItem),
 | 
| 54 | -        mIsTranslatePoint(false) {
 | |
| 54 | +        mIsTranslatePoint(false),
 | |
| 55 | +        mIsInTearoffTable(false) {
 | |
| 55 | 56 |      // These shifts are in sync with the members.
 | 
| 56 | 57 |      MOZ_ASSERT(aList && aListIndex <= MaxListIndex(), "bad arg");
 | 
| 57 | 58 | |
| ... | ... | @@ -60,7 +61,10 @@ class DOMSVGPoint final : public nsWrapperCache { | 
| 60 | 61 | |
| 61 | 62 |    // Constructor for unowned points and SVGSVGElement.createSVGPoint
 | 
| 62 | 63 |    explicit DOMSVGPoint(const Point& aPt)
 | 
| 63 | -      : mListIndex(0), mIsAnimValItem(false), mIsTranslatePoint(false) {
 | |
| 64 | +      : mListIndex(0),
 | |
| 65 | +        mIsAnimValItem(false),
 | |
| 66 | +        mIsTranslatePoint(false),
 | |
| 67 | +        mIsInTearoffTable(false) {
 | |
| 64 | 68 |      // In this case we own mVal
 | 
| 65 | 69 |      mVal = new SVGPoint(aPt.x, aPt.y);
 | 
| 66 | 70 |    }
 | 
| ... | ... | @@ -72,7 +76,8 @@ class DOMSVGPoint final : public nsWrapperCache { | 
| 72 | 76 |          mOwner(ToSupports(aSVGSVGElement)),
 | 
| 73 | 77 |          mListIndex(0),
 | 
| 74 | 78 |          mIsAnimValItem(false),
 | 
| 75 | -        mIsTranslatePoint(true) {}
 | |
| 79 | +        mIsTranslatePoint(true),
 | |
| 80 | +        mIsInTearoffTable(false) {}
 | |
| 76 | 81 | |
| 77 | 82 |    virtual ~DOMSVGPoint() { CleanupWeakRefs(); }
 | 
| 78 | 83 | |
| ... | ... | @@ -178,6 +183,12 @@ class DOMSVGPoint final : public nsWrapperCache { | 
| 178 | 183 |    uint32_t mListIndex : MOZ_SVG_LIST_INDEX_BIT_COUNT;
 | 
| 179 | 184 |    uint32_t mIsAnimValItem : 1;     // True if We're the animated value of a list
 | 
| 180 | 185 |    uint32_t mIsTranslatePoint : 1;  // true iff our owner is a SVGSVGElement
 | 
| 186 | + | |
| 187 | +  // Tracks whether we're in the tearoff table. Initialized to false in the
 | |
| 188 | +  // ctor, but then immediately set to true if/when we're added to the table
 | |
| 189 | +  // (not all instances are).  Updated to false when we're removed from the
 | |
| 190 | +  // table (at which point we're being destructed or soon-to-be destructed).
 | |
| 191 | +  uint32_t mIsInTearoffTable : 1;
 | |
| 181 | 192 |  };
 | 
| 182 | 193 | |
| 183 | 194 |  }  // namespace mozilla::dom
 | 
| ... | ... | @@ -90,9 +90,12 @@ void DOMSVGPointList::RemoveFromTearoffTable() { | 
| 90 | 90 |    //
 | 
| 91 | 91 |    // There are now no longer any references to us held by script or list items.
 | 
| 92 | 92 |    // Note we must use GetAnimValKey/GetBaseValKey here, NOT InternalList()!
 | 
| 93 | -  void* key = mIsAnimValList ? InternalAList().GetAnimValKey()
 | |
| 94 | -                             : InternalAList().GetBaseValKey();
 | |
| 95 | -  SVGPointListTearoffTable().RemoveTearoff(key);
 | |
| 93 | +  if (mIsInTearoffTable) {
 | |
| 94 | +    void* key = mIsAnimValList ? InternalAList().GetAnimValKey()
 | |
| 95 | +                               : InternalAList().GetBaseValKey();
 | |
| 96 | +    SVGPointListTearoffTable().RemoveTearoff(key);
 | |
| 97 | +    mIsInTearoffTable = false;
 | |
| 98 | +  }
 | |
| 96 | 99 |  }
 | 
| 97 | 100 | |
| 98 | 101 |  DOMSVGPointList::~DOMSVGPointList() { RemoveFromTearoffTable(); }
 | 
| ... | ... | @@ -251,6 +251,12 @@ class DOMSVGPointList final : public nsISupports, public nsWrapperCache { | 
| 251 | 251 |    RefPtr<dom::SVGElement> mElement;
 | 
| 252 | 252 | |
| 253 | 253 |    bool mIsAnimValList;
 | 
| 254 | + | |
| 255 | +  // Tracks whether we're in the tearoff table. Initialized to true, since all
 | |
| 256 | +  // new instances are added to the table right after construction. Updated to
 | |
| 257 | +  // false when we're removed from the table (at which point we're being
 | |
| 258 | +  // destructed or soon-to-be destructed).
 | |
| 259 | +  bool mIsInTearoffTable = true;
 | |
| 254 | 260 |  };
 | 
| 255 | 261 | |
| 256 | 262 |  NS_DEFINE_STATIC_IID_ACCESSOR(DOMSVGPointList, MOZILLA_DOMSVGPOINTLIST_IID)
 | 
| ... | ... | @@ -91,7 +91,10 @@ already_AddRefed<DOMSVGStringList> DOMSVGStringList::GetDOMWrapper( | 
| 91 | 91 | |
| 92 | 92 |  void DOMSVGStringList::RemoveFromTearoffTable() {
 | 
| 93 | 93 |    // Script no longer has any references to us.
 | 
| 94 | -  SVGStringListTearoffTable().RemoveTearoff(&InternalList());
 | |
| 94 | +  if (mIsInTearoffTable) {
 | |
| 95 | +    SVGStringListTearoffTable().RemoveTearoff(&InternalList());
 | |
| 96 | +    mIsInTearoffTable = false;
 | |
| 97 | +  }
 | |
| 95 | 98 |  }
 | 
| 96 | 99 | |
| 97 | 100 |  DOMSVGStringList::~DOMSVGStringList() { RemoveFromTearoffTable(); }
 | 
| ... | ... | @@ -108,6 +108,12 @@ class DOMSVGStringList final : public nsISupports, public nsWrapperCache { | 
| 108 | 108 |    uint8_t mAttrEnum;
 | 
| 109 | 109 | |
| 110 | 110 |    bool mIsConditionalProcessingAttribute;
 | 
| 111 | + | |
| 112 | +  // Tracks whether we're in the tearoff table. Initialized to true, since all
 | |
| 113 | +  // new instances are added to the table right after construction. Updated to
 | |
| 114 | +  // false when we're removed from the table (at which point we're being
 | |
| 115 | +  // destructed or soon-to-be destructed).
 | |
| 116 | +  bool mIsInTearoffTable = true;
 | |
| 111 | 117 |  };
 | 
| 112 | 118 | |
| 113 | 119 |  }  // namespace dom
 | 
| ... | ... | @@ -12183,6 +12183,13 @@ | 
| 12183 | 12183 |    value: true
 | 
| 12184 | 12184 |    mirror: always
 | 
| 12185 | 12185 | |
| 12186 | +# Disable requests to 0.0.0.0
 | |
| 12187 | +# See Bug 1889130
 | |
| 12188 | +- name: network.socket.ip_addr_any.disabled
 | |
| 12189 | +  type: RelaxedAtomicBool
 | |
| 12190 | +  value: @IS_EARLY_BETA_OR_EARLIER@
 | |
| 12191 | +  mirror: always
 | |
| 12192 | + | |
| 12186 | 12193 |  # Set true to allow resolving proxy for localhost
 | 
| 12187 | 12194 |  - name: network.proxy.allow_hijacking_localhost
 | 
| 12188 | 12195 |    type: RelaxedAtomicBool
 | 
| ... | ... | @@ -239,6 +239,7 @@ static const char* gCallbackPrefsForSocketProcess[] = { | 
| 239 | 239 |      "network.proxy.allow_hijacking_localhost",
 | 
| 240 | 240 |      "network.connectivity-service.",
 | 
| 241 | 241 |      "network.captive-portal-service.testMode",
 | 
| 242 | +    "network.socket.ip_addr_any.disabled",
 | |
| 242 | 243 |      nullptr,
 | 
| 243 | 244 |  };
 | 
| 244 | 245 | 
| ... | ... | @@ -1247,6 +1247,15 @@ nsresult nsSocketTransport::InitiateSocket() { | 
| 1247 | 1247 |    if (gIOService->IsNetTearingDown()) {
 | 
| 1248 | 1248 |      return NS_ERROR_ABORT;
 | 
| 1249 | 1249 |    }
 | 
| 1250 | + | |
| 1251 | +  // Since https://github.com/whatwg/fetch/pull/1763,
 | |
| 1252 | +  // we need to disable access to 0.0.0.0 for non-test purposes
 | |
| 1253 | +  if (StaticPrefs::network_socket_ip_addr_any_disabled() &&
 | |
| 1254 | +      mNetAddr.IsIPAddrAny() && !mProxyTransparentResolvesHost) {
 | |
| 1255 | +    SOCKET_LOG(("connection refused NS_ERROR_CONNECTION_REFUSED\n"));
 | |
| 1256 | +    return NS_ERROR_CONNECTION_REFUSED;
 | |
| 1257 | +  }
 | |
| 1258 | + | |
| 1250 | 1259 |    if (gIOService->IsOffline()) {
 | 
| 1251 | 1260 |      if (StaticPrefs::network_disable_localhost_when_offline() || !isLocal) {
 | 
| 1252 | 1261 |        return NS_ERROR_OFFLINE;
 | 
| ... | ... | @@ -19,6 +19,7 @@ | 
| 19 | 19 | |
| 20 | 20 |  #include "ASpdySession.h"
 | 
| 21 | 21 |  #include "mozilla/StaticPrefs_network.h"
 | 
| 22 | +#include "mozilla/glean/NetwerkMetrics.h"
 | |
| 22 | 23 |  #include "mozilla/Telemetry.h"
 | 
| 23 | 24 |  #include "HttpConnectionUDP.h"
 | 
| 24 | 25 |  #include "nsHttpHandler.h"
 | 
| ... | ... | @@ -88,6 +89,22 @@ nsresult HttpConnectionUDP::Init(nsHttpConnectionInfo* info, | 
| 88 | 89 |      return rv;
 | 
| 89 | 90 |    }
 | 
| 90 | 91 | |
| 92 | +  // We are disabling 0.0.0.0 for non-test purposes.
 | |
| 93 | +  // See https://github.com/whatwg/fetch/pull/1763 for context.
 | |
| 94 | +  if (peerAddr.IsIPAddrAny()) {
 | |
| 95 | +    if (StaticPrefs::network_socket_ip_addr_any_disabled()) {
 | |
| 96 | +      mozilla::glean::networking::http_ip_addr_any_count
 | |
| 97 | +          .Get("blocked_requests"_ns)
 | |
| 98 | +          .Add(1);
 | |
| 99 | +      LOG(("Connection refused because of 0.0.0.0 IP address\n"));
 | |
| 100 | +      return NS_ERROR_CONNECTION_REFUSED;
 | |
| 101 | +    }
 | |
| 102 | + | |
| 103 | +    mozilla::glean::networking::http_ip_addr_any_count
 | |
| 104 | +        .Get("not_blocked_requests"_ns)
 | |
| 105 | +        .Add(1);
 | |
| 106 | +  }
 | |
| 107 | + | |
| 91 | 108 |    mSocket = do_CreateInstance("@mozilla.org/network/udp-socket;1", &rv);
 | 
| 92 | 109 |    if (NS_FAILED(rv)) {
 | 
| 93 | 110 |      return rv;
 | 
| ... | ... | @@ -1027,6 +1027,7 @@ async function test_ipv4_trr_fallback() { | 
| 1027 | 1027 |  async function test_no_retry_without_doh() {
 | 
| 1028 | 1028 |    info("Bug 1648147 - if the TRR returns 0.0.0.0 we should not retry with DNS");
 | 
| 1029 | 1029 |    Services.prefs.setBoolPref("network.trr.fallback-on-zero-response", false);
 | 
| 1030 | +  Services.prefs.setBoolPref("network.socket.ip_addr_any.disabled", false);
 | |
| 1030 | 1031 | |
| 1031 | 1032 |    async function test(url, ip) {
 | 
| 1032 | 1033 |      setModeAndURI(2, `doh?responseIP=${ip}`);
 | 
| ... | ... | @@ -1073,6 +1074,8 @@ async function test_no_retry_without_doh() { | 
| 1073 | 1074 |      await test(`http://unknown.ipv4.stuff:666/path`, "0.0.0.0");
 | 
| 1074 | 1075 |      await test(`http://unknown.ipv6.stuff:666/path`, "::");
 | 
| 1075 | 1076 |    }
 | 
| 1077 | + | |
| 1078 | +  Services.prefs.clearUserPref("network.socket.ip_addr_any.disabled");
 | |
| 1076 | 1079 |  }
 | 
| 1077 | 1080 | |
| 1078 | 1081 |  async function test_connection_reuse_and_cycling() {
 | 
| ... | ... | @@ -508,19 +508,11 @@ window.onload = function () { | 
| 508 | 508 |    appendElementWithText(gFooter, "div", "legend", legendText1);
 | 
| 509 | 509 |    appendElementWithText(gFooter, "div", "legend hiddenOnMobile", legendText2);
 | 
| 510 | 510 | |
| 511 | -  // See if we're loading from a file.  (Because about:memory is a non-standard
 | |
| 512 | -  // URL, location.search is undefined, so we have to use location.href
 | |
| 513 | -  // instead.)
 | |
| 514 | -  let search = location.href.split("?")[1];
 | |
| 515 | -  if (search) {
 | |
| 516 | -    let searchSplit = search.split("&");
 | |
| 517 | -    for (let s of searchSplit) {
 | |
| 518 | -      if (s.toLowerCase().startsWith("file=")) {
 | |
| 519 | -        let filename = s.substring("file=".length);
 | |
| 520 | -        updateAboutMemoryFromFile(decodeURIComponent(filename));
 | |
| 521 | -        return;
 | |
| 522 | -      }
 | |
| 523 | -    }
 | |
| 511 | +  // See if we're loading from a file.
 | |
| 512 | +  let { searchParams } = URL.fromURI(document.documentURIObject);
 | |
| 513 | +  let fileParam = searchParams.get("file");
 | |
| 514 | +  if (fileParam) {
 | |
| 515 | +    updateAboutMemoryFromFile(fileParam);
 | |
| 524 | 516 |    }
 | 
| 525 | 517 |  };
 | 
| 526 | 518 |