From 264d6b5edf59d15937ee9264dda1ff3b1322dc19 Mon Sep 17 00:00:00 2001 From: Andrew Osmond Date: Mon, 18 Sep 2017 19:53:03 -0400 Subject: [PATCH 01/83] Bug 1380649 - Part 1. Ensure SurfaceCache::CollectSizeOfSurfaces removes purged volatile buffer-backed surfaces. r=tnikkel When we lookup a surface in the cache, we are careful to remove any surfaces which were backed by volatile memory and got purged before we could reacquire the buffer. We were not so careful in doing that when generating memory reports. ISurfaceProvider::AddSizeOfExcludingThis will cause us to acquire the buffer, and if it was purged, forget about its purged status. Later when we performed a lookup, we would forget the purged status, and assume we have the right data. This would appear as completely transparent for BGRA surfaces, and completely black for BGRX surfaces. With this patch, we now properly remove purged surfaces instead of including them in the report. This ensures that the cache state is consistent. This also resolves memory reports of surfaces which reported using no data -- they were purged when the report was generated. Additionally, there was a bug in SurfaceCache::PruneImage where we did not discard surfaces outside the module lock. Both PruneImage and CollectSizeOfSurfaces now free any discarded surfaces outside the lock. --- image/SurfaceCache.cpp | 54 ++++++++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/image/SurfaceCache.cpp b/image/SurfaceCache.cpp index 877893fd3c7b..3af3a0149b11 100644 --- a/image/SurfaceCache.cpp +++ b/image/SurfaceCache.cpp @@ -614,12 +614,26 @@ public: return false; } + template void CollectSizeOfSurfaces(nsTArray& aCounters, - MallocSizeOf aMallocSizeOf) + MallocSizeOf aMallocSizeOf, + Function&& aRemoveCallback) { CachedSurface::SurfaceMemoryReport report(aCounters, aMallocSizeOf); - for (auto iter = ConstIter(); !iter.Done(); iter.Next()) { + for (auto iter = mSurfaces.Iter(); !iter.Done(); iter.Next()) { NotNull surface = WrapNotNull(iter.UserData()); + + // We don't need the drawable surface for ourselves, but adding a surface + // to the report will trigger this indirectly. If the surface was + // discarded by the OS because it was in volatile memory, we should remove + // it from the cache immediately rather than include it in the report. + DrawableSurface drawableSurface = surface->GetDrawableSurface(); + if (!drawableSurface) { + aRemoveCallback(surface); + iter.Remove(); + continue; + } + const IntSize& size = surface->GetSurfaceKey().Size(); bool factor2Size = false; if (mFactor2Mode) { @@ -1073,6 +1087,8 @@ public: cache->Prune([this, &aAutoLock](NotNull aSurface) -> void { StopTracking(aSurface, /* aIsTracked */ true, aAutoLock); + // Individual surfaces must be freed outside the lock. + mCachedSurfacesDiscard.AppendElement(aSurface); }); } @@ -1165,7 +1181,8 @@ public: void CollectSizeOfSurfaces(const ImageKey aImageKey, nsTArray& aCounters, - MallocSizeOf aMallocSizeOf) + MallocSizeOf aMallocSizeOf, + const StaticMutexAutoLock& aAutoLock) { RefPtr cache = GetImageCache(aImageKey); if (!cache) { @@ -1173,7 +1190,12 @@ public: } // Report all surfaces in the per-image cache. - cache->CollectSizeOfSurfaces(aCounters, aMallocSizeOf); + cache->CollectSizeOfSurfaces(aCounters, aMallocSizeOf, + [this, &aAutoLock](NotNull aSurface) -> void { + StopTracking(aSurface, /* aIsTracked */ true, aAutoLock); + // Individual surfaces must be freed outside the lock. + mCachedSurfacesDiscard.AppendElement(aSurface); + }); } private: @@ -1544,9 +1566,13 @@ SurfaceCache::RemoveImage(const ImageKey aImageKey) /* static */ void SurfaceCache::PruneImage(const ImageKey aImageKey) { - StaticMutexAutoLock lock(sInstanceMutex); - if (sInstance) { - sInstance->PruneImage(aImageKey, lock); + nsTArray> discard; + { + StaticMutexAutoLock lock(sInstanceMutex); + if (sInstance) { + sInstance->PruneImage(aImageKey, lock); + sInstance->TakeDiscard(discard, lock); + } } } @@ -1568,12 +1594,16 @@ SurfaceCache::CollectSizeOfSurfaces(const ImageKey aImageKey, nsTArray& aCounters, MallocSizeOf aMallocSizeOf) { - StaticMutexAutoLock lock(sInstanceMutex); - if (!sInstance) { - return; - } + nsTArray> discard; + { + StaticMutexAutoLock lock(sInstanceMutex); + if (!sInstance) { + return; + } - return sInstance->CollectSizeOfSurfaces(aImageKey, aCounters, aMallocSizeOf); + sInstance->CollectSizeOfSurfaces(aImageKey, aCounters, aMallocSizeOf, lock); + sInstance->TakeDiscard(discard, lock); + } } /* static */ size_t From 9df74d4975e0b1fce8a85276bec31edbd0350bf5 Mon Sep 17 00:00:00 2001 From: Andrew Osmond Date: Mon, 18 Sep 2017 20:08:05 -0400 Subject: [PATCH 02/83] Bug 1380649 - Part 2. Ensure SourceSurfaceVolatileData does not forget its purged state. r=jrmuizel Currently if SourceSurfaceVolatileData::Map fails due to being purged, we expect that the surface will be discarded by the caller. This has not consistently been the case, and as such, we should ensure we do not forget if a buffer was previously purged when we reacquire it. Since we do not at this time support repopulating an already allocated buffer with new data, we cannot reset this state once it has been set. --- gfx/layers/SourceSurfaceVolatileData.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/gfx/layers/SourceSurfaceVolatileData.h b/gfx/layers/SourceSurfaceVolatileData.h index 7641733621a6..a97bf08ee73c 100644 --- a/gfx/layers/SourceSurfaceVolatileData.h +++ b/gfx/layers/SourceSurfaceVolatileData.h @@ -32,6 +32,7 @@ public: , mStride(0) , mMapCount(0) , mFormat(SurfaceFormat::UNKNOWN) + , mWasPurged(false) { } @@ -66,10 +67,14 @@ public: bool Map(MapType, MappedSurface *aMappedSurface) override { MutexAutoLock lock(mMutex); + if (mWasPurged) { + return false; + } if (mMapCount == 0) { mVBufPtr = mVBuf; } if (mVBufPtr.WasBufferPurged()) { + mWasPurged = true; return false; } aMappedSurface->mData = mVBufPtr; @@ -82,6 +87,7 @@ public: { MutexAutoLock lock(mMutex); MOZ_ASSERT(mMapCount > 0); + MOZ_ASSERT(!mWasPurged); if (--mMapCount == 0) { mVBufPtr = nullptr; } @@ -100,6 +106,7 @@ private: RefPtr mVBuf; VolatileBufferPtr mVBufPtr; SurfaceFormat mFormat; + bool mWasPurged; }; } // namespace gfx From 280bab46eb4a6431fd09c1cb31a0186c976abbd9 Mon Sep 17 00:00:00 2001 From: Rail Aliiev Date: Mon, 18 Sep 2017 20:40:53 -0400 Subject: [PATCH 03/83] Bug 1395697 - Syntax fix r=nthomas --- testing/mozharness/configs/releases/bouncer_firefox_release.py | 1 + 1 file changed, 1 insertion(+) diff --git a/testing/mozharness/configs/releases/bouncer_firefox_release.py b/testing/mozharness/configs/releases/bouncer_firefox_release.py index 5be892cce6fc..ab5be1a74a36 100644 --- a/testing/mozharness/configs/releases/bouncer_firefox_release.py +++ b/testing/mozharness/configs/releases/bouncer_firefox_release.py @@ -188,6 +188,7 @@ config = { "bouncer-platform": "win64", }, }, + }, }, "partials": { "releases-dir": { From 82a08c647e37de978ecad8e712b4916756912041 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Mon, 18 Sep 2017 21:24:37 -0400 Subject: [PATCH 04/83] Bug 991271. Restore our assertions about how wrapping failure should mean an exception was thrown. r=mccr8 Now that Gecko controls error reporting and the JS engine is no longer doing JS_IsRunning checks, we should consistently have exceptions here. MozReview-Commit-ID: IqBe5ArJc2l --- dom/bindings/Codegen.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 5742c2a24dbd..54a332ca2bbc 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -6851,8 +6851,7 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode, if not descriptor.hasXPConnectImpls: # Can only fail to wrap as a new-binding object # if they already threw an exception. - # XXX Assertion disabled for now, see bug 991271. - failed = ("MOZ_ASSERT(true || JS_IsExceptionPending(cx));\n" + + failed = ("MOZ_ASSERT(JS_IsExceptionPending(cx));\n" + exceptionCode) else: if descriptor.notflattened: @@ -15371,8 +15370,7 @@ class CGJSImplMethod(CGJSImplMember): MOZ_ASSERT(js::IsObjectInContextCompartment(scopeObj, cx)); JS::Rooted wrappedVal(cx); if (!GetOrCreateDOMReflector(cx, impl, &wrappedVal, aGivenProto)) { - //XXX Assertion disabled for now, see bug 991271. - MOZ_ASSERT(true || JS_IsExceptionPending(cx)); + MOZ_ASSERT(JS_IsExceptionPending(cx)); aRv.Throw(NS_ERROR_UNEXPECTED); return nullptr; } From 005450266e36555b9d84f96d3b4f037711bc3b32 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Mon, 18 Sep 2017 21:24:37 -0400 Subject: [PATCH 05/83] Bug 1400139 part 1. Add infrastructure for marking WebIDL interface members as non-enumerable. r=qdot MozReview-Commit-ID: 9F0ZNverS63 --- dom/bindings/Codegen.py | 19 +++++++---------- dom/bindings/parser/WebIDL.py | 28 ++++++++++++++++++------- dom/bindings/test/TestBindingHeader.h | 4 ++++ dom/bindings/test/TestCodeGen.webidl | 8 +++++++ dom/bindings/test/TestExampleGen.webidl | 8 +++++++ dom/bindings/test/TestJSImplGen.webidl | 8 +++++++ 6 files changed, 56 insertions(+), 19 deletions(-) diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 54a332ca2bbc..a2e2c5384660 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -2361,6 +2361,12 @@ def IDLToCIdentifier(name): return name.replace("-", "_") +def EnumerabilityFlags(member): + if member.getExtendedAttribute("NonEnumerable"): + return "0" + return "JSPROP_ENUMERATE" + + class MethodDefiner(PropertyDefiner): """ A class for defining methods on a prototype object. @@ -2421,18 +2427,11 @@ class MethodDefiner(PropertyDefiner): }) continue - # Iterable methods should be enumerable, maplike/setlike methods - # should not. - isMaplikeOrSetlikeMethod = (m.isMaplikeOrSetlikeOrIterableMethod() and - (m.maplikeOrSetlikeOrIterable.isMaplike() or - m.maplikeOrSetlikeOrIterable.isSetlike())) method = { "name": m.identifier.name, "methodInfo": not m.isStatic(), "length": methodLength(m), - # Methods generated for a maplike/setlike declaration are not - # enumerable. - "flags": "JSPROP_ENUMERATE" if not isMaplikeOrSetlikeMethod else "0", + "flags": EnumerabilityFlags(m), "condition": PropertyDefiner.getControllingCondition(m, descriptor), "allowCrossOriginThis": m.getExtendedAttribute("CrossOriginCallable"), "returnsPromise": m.returnsPromise(), @@ -2728,9 +2727,7 @@ class AttrDefiner(PropertyDefiner): def flags(attr): unforgeable = " | JSPROP_PERMANENT" if self.unforgeable else "" - # Attributes generated as part of a maplike/setlike declaration are - # not enumerable. - enumerable = " | JSPROP_ENUMERATE" if not attr.isMaplikeOrSetlikeAttr() else "" + enumerable = " | %s" % EnumerabilityFlags(attr) return ("JSPROP_SHARED" + enumerable + unforgeable) def getter(attr): diff --git a/dom/bindings/parser/WebIDL.py b/dom/bindings/parser/WebIDL.py index 2d5166d10162..56d558bf2810 100644 --- a/dom/bindings/parser/WebIDL.py +++ b/dom/bindings/parser/WebIDL.py @@ -3703,6 +3703,11 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember): if isIteratorAlias: method.addExtendedAttributes( [IDLExtendedAttribute(self.location, ("Alias", "@@iterator"))]) + # Methods generated for iterables should be enumerable, but the ones for + # maplike/setlike should not be. + if not self.isIterable(): + method.addExtendedAttributes( + [IDLExtendedAttribute(self.location, ("NonEnumerable",))]) members.append(method) def resolve(self, parentScope): @@ -3826,11 +3831,15 @@ class IDLMaplikeOrSetlike(IDLMaplikeOrSetlikeOrIterableBase): specification during parsing. """ # Both maplike and setlike have a size attribute - members.append(IDLAttribute(self.location, - IDLUnresolvedIdentifier(BuiltinLocation(""), "size"), - BuiltinTypes[IDLBuiltinType.Types.unsigned_long], - True, - maplikeOrSetlike=self)) + sizeAttr = IDLAttribute(self.location, + IDLUnresolvedIdentifier(BuiltinLocation(""), "size"), + BuiltinTypes[IDLBuiltinType.Types.unsigned_long], + True, + maplikeOrSetlike=self) + # This should be non-enumerable. + sizeAttr.addExtendedAttributes( + [IDLExtendedAttribute(self.location, ("NonEnumerable",))]) + members.append(sizeAttr) self.reserved_ro_names = ["size"] self.disallowedMemberNames.append("size") @@ -3966,7 +3975,8 @@ class IDLConst(IDLInterfaceMember): elif (identifier == "Pref" or identifier == "ChromeOnly" or identifier == "Func" or - identifier == "SecureContext"): + identifier == "SecureContext" or + identifier == "NonEnumerable"): # Known attributes that we don't need to do anything with here pass else: @@ -4344,7 +4354,8 @@ class IDLAttribute(IDLInterfaceMember): identifier == "NeedsSubjectPrincipal" or identifier == "NeedsCallerType" or identifier == "ReturnValueNeedsContainsHack" or - identifier == "BinaryName"): + identifier == "BinaryName" or + identifier == "NonEnumerable"): # Known attributes that we don't need to do anything with here pass else: @@ -5081,7 +5092,8 @@ class IDLMethod(IDLInterfaceMember, IDLScope): identifier == "BinaryName" or identifier == "NeedsSubjectPrincipal" or identifier == "NeedsCallerType" or - identifier == "StaticClassOverride"): + identifier == "StaticClassOverride" or + identifier == "NonEnumerable"): # Known attributes that we don't need to do anything with here pass else: diff --git a/dom/bindings/test/TestBindingHeader.h b/dom/bindings/test/TestBindingHeader.h index 97964bb679bd..e1cd5d74427c 100644 --- a/dom/bindings/test/TestBindingHeader.h +++ b/dom/bindings/test/TestBindingHeader.h @@ -978,6 +978,10 @@ public: int8_t Dashed_attribute(); void Dashed_method(); + bool NonEnumerableAttr() const; + void SetNonEnumerableAttr(bool); + void NonEnumerableMethod(); + // Methods and properties imported via "implements" bool ImplementedProperty(); void SetImplementedProperty(bool); diff --git a/dom/bindings/test/TestCodeGen.webidl b/dom/bindings/test/TestCodeGen.webidl index e971e5226b32..7b350afac3f1 100644 --- a/dom/bindings/test/TestCodeGen.webidl +++ b/dom/bindings/test/TestCodeGen.webidl @@ -975,6 +975,14 @@ interface TestInterface { attribute byte dashed-attribute; void dashed-method(); + // [NonEnumerable] tests + [NonEnumerable] + attribute boolean nonEnumerableAttr; + [NonEnumerable] + const boolean nonEnumerableConst = true; + [NonEnumerable] + void nonEnumerableMethod(); + // If you add things here, add them to TestExampleGen and TestJSImplGen as well }; diff --git a/dom/bindings/test/TestExampleGen.webidl b/dom/bindings/test/TestExampleGen.webidl index e2a04bc7a606..7703b341127a 100644 --- a/dom/bindings/test/TestExampleGen.webidl +++ b/dom/bindings/test/TestExampleGen.webidl @@ -802,6 +802,14 @@ interface TestExampleInterface { attribute byte dashed-attribute; void dashed-method(); + // [NonEnumerable] tests + [NonEnumerable] + attribute boolean nonEnumerableAttr; + [NonEnumerable] + const boolean nonEnumerableConst = true; + [NonEnumerable] + void nonEnumerableMethod(); + // If you add things here, add them to TestCodeGen and TestJSImplGen as well }; diff --git a/dom/bindings/test/TestJSImplGen.webidl b/dom/bindings/test/TestJSImplGen.webidl index d729f2239b2b..907896a62571 100644 --- a/dom/bindings/test/TestJSImplGen.webidl +++ b/dom/bindings/test/TestJSImplGen.webidl @@ -822,6 +822,14 @@ interface TestJSImplInterface { attribute byte dashed-attribute; void dashed-method(); + // [NonEnumerable] tests + [NonEnumerable] + attribute boolean nonEnumerableAttr; + [NonEnumerable] + const boolean nonEnumerableConst = true; + [NonEnumerable] + void nonEnumerableMethod(); + // If you add things here, add them to TestCodeGen as well }; From 3dc9073bd53ddaa33853c3bf55db3b20cd446fa6 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Mon, 18 Sep 2017 21:24:38 -0400 Subject: [PATCH 06/83] Bug 1400139 part 2. Make window.content non-enumerable. r=mystor MozReview-Commit-ID: LQkEkdG8wKf --- dom/base/test/mochitest.ini | 1 + dom/base/test/test_window_content.html | 28 ++++++++++++++++++++++++++ dom/webidl/Window.webidl | 3 ++- 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 dom/base/test/test_window_content.html diff --git a/dom/base/test/mochitest.ini b/dom/base/test/mochitest.ini index df3b0e9b799b..cc0baeddb7a5 100644 --- a/dom/base/test/mochitest.ini +++ b/dom/base/test/mochitest.ini @@ -814,6 +814,7 @@ skip-if = toolkit == 'android' [test_websocket5.html] skip-if = toolkit == 'android' [test_window_constructor.html] +[test_window_content.html] [test_window_cross_origin_props.html] [test_window_define_nonconfigurable.html] [test_window_define_symbol.html] diff --git a/dom/base/test/test_window_content.html b/dom/base/test/test_window_content.html new file mode 100644 index 000000000000..7ca17d6da1e9 --- /dev/null +++ b/dom/base/test/test_window_content.html @@ -0,0 +1,28 @@ + + + + + + Test for Bug 1400139 + + + + + +Mozilla Bug 1400139 +

+ +
+
+ + diff --git a/dom/webidl/Window.webidl b/dom/webidl/Window.webidl index 00a1c942247d..50b2965a72e0 100644 --- a/dom/webidl/Window.webidl +++ b/dom/webidl/Window.webidl @@ -340,7 +340,8 @@ partial interface Window { #ifdef NIGHTLY_BUILD ChromeOnly, #endif - Replaceable, Throws, NeedsCallerType] readonly attribute object? content; + NonEnumerable, Replaceable, Throws, NeedsCallerType] + readonly attribute object? content; [Throws, ChromeOnly] any getInterface(IID iid); From c1bab3a2f82b36e65f3f43eca8ae7ca6b7581237 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Mon, 18 Sep 2017 21:24:38 -0400 Subject: [PATCH 07/83] Bug 1400139 part 3. Add a use counter when the window.content getter is called from untrusted code. r=mystor MozReview-Commit-ID: LFMK7lxs46Z --- dom/base/nsDeprecatedOperationList.h | 1 + dom/base/nsGlobalWindow.cpp | 3 +++ dom/locales/en-US/chrome/dom/dom.properties | 2 ++ 3 files changed, 6 insertions(+) diff --git a/dom/base/nsDeprecatedOperationList.h b/dom/base/nsDeprecatedOperationList.h index 1c9389f69bff..ac2eb7e6810e 100644 --- a/dom/base/nsDeprecatedOperationList.h +++ b/dom/base/nsDeprecatedOperationList.h @@ -50,3 +50,4 @@ DEPRECATED_OPERATION(ImageBitmapRenderingContext_TransferImageBitmap) DEPRECATED_OPERATION(URLCreateObjectURL_MediaStream) DEPRECATED_OPERATION(XMLBaseAttribute) DEPRECATED_OPERATION(XMLBaseAttributeForStyleAttr) +DEPRECATED_OPERATION(WindowContentUntrusted) diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 58925b7b0242..31db4edc5ff3 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -4989,6 +4989,9 @@ nsGlobalWindow::GetContentInternal(ErrorResult& aError, CallerType aCallerType) nsCOMPtr primaryContent; if (aCallerType != CallerType::System) { + if (mDoc) { + mDoc->WarnOnceAbout(nsIDocument::eWindowContentUntrusted); + } // If we're called by non-chrome code, make sure we don't return // the primary content window if the calling tab is hidden. In // such a case we return the same-type root in the hidden tab, diff --git a/dom/locales/en-US/chrome/dom/dom.properties b/dom/locales/en-US/chrome/dom/dom.properties index 3a750ecfa6d4..1d60925a7a66 100644 --- a/dom/locales/en-US/chrome/dom/dom.properties +++ b/dom/locales/en-US/chrome/dom/dom.properties @@ -330,6 +330,8 @@ MozAutoGainControlWarning=mozAutoGainControl is deprecated. Use autoGainControl MozNoiseSuppressionWarning=mozNoiseSuppression is deprecated. Use noiseSuppression instead. # LOCALIZATION NOTE: Do not translate xml:base. XMLBaseAttributeWarning=Use of xml:base attribute is deprecated and will be removed soon. Please remove any use of it. +# LOCALIZATION NOTE: Do not translate "content", "Window", and "window.top" +WindowContentUntrustedWarning=The ‘content’ attribute of Window objects is deprecated. Please use ‘window.top’ instead. # LOCALIZATION NOTE: %S is the tag name of the element that starts the loop SVGReferenceLoopWarning=There is an SVG <%S> reference loop in this document, which will prevent the document rendering correctly. # LOCALIZATION NOTE: %S is the tag name of the element that starts the chain From e3883c1255332cf3c4c42efa7fe28ded58516fb6 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Mon, 18 Sep 2017 21:24:38 -0400 Subject: [PATCH 08/83] Bug 1400501. Store a list of ancestor principals on docshell and document. r=mystor Right now every document in a docshell makes a copy of the list. In practice, this list is usually pretty short (limited by depth of iframe nesting), so this is probably not a problem. We could add a bit of complexity and have a refcounted struct that contains the list... I wish we had something as simple as Rust's Arc that we could use here. MozReview-Commit-ID: 8jGIlkhp1DU --- docshell/base/nsDocShell.h | 39 ++++++++++++++++++++++++++++++++++++++ dom/base/nsDocument.cpp | 2 ++ dom/base/nsFrameLoader.cpp | 12 +++++++++++- dom/base/nsIDocument.h | 20 ++++++++++++++++++- 4 files changed, 71 insertions(+), 2 deletions(-) diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h index 7bc0ad2b1729..f8c54034870f 100644 --- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -19,6 +19,7 @@ #include "nsIDOMStorageManager.h" #include "nsDocLoader.h" #include "mozilla/BasePrincipal.h" +#include "mozilla/Move.h" #include "mozilla/UniquePtr.h" #include "mozilla/WeakPtr.h" #include "mozilla/TimeStamp.h" @@ -291,6 +292,41 @@ public: nsDOMNavigationTiming* GetNavigationTiming() const; + /** + * Get the list of ancestor principals for this docshell. The list is meant + * to be the list of principals of the documents this docshell is "nested + * through" in the sense of + * . + * In practice, it is defined as follows: + * + * If this is an