зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1444580: Devirtualize the fullscreen stuff. r=smaug
MozReview-Commit-ID: CgPENqExkQh
This commit is contained in:
Родитель
0f6e1aec50
Коммит
6100eb8087
|
@ -1495,6 +1495,7 @@ nsIDocument::nsIDocument()
|
|||
mDOMCompleteSet(false),
|
||||
mAutoFocusFired(false),
|
||||
mIsScopedStyleEnabled(eScopedStyle_Unknown),
|
||||
mPendingFullscreenRequests(0),
|
||||
mCompatMode(eCompatibility_FullStandards),
|
||||
mReadyState(ReadyState::READYSTATE_UNINITIALIZED),
|
||||
mStyleBackendType(StyleBackendType::None),
|
||||
|
@ -1551,7 +1552,6 @@ nsDocument::nsDocument(const char* aContentType)
|
|||
, mCurrentOrientationAngle(0)
|
||||
, mCurrentOrientationType(OrientationType::Portrait_primary)
|
||||
, mReportedUseCounters(false)
|
||||
, mPendingFullscreenRequests(0)
|
||||
, mXMLDeclarationBits(0)
|
||||
, mBoxObjectTable(nullptr)
|
||||
, mOnloadBlockCount(0)
|
||||
|
@ -10513,14 +10513,14 @@ FullscreenRoots::IsEmpty()
|
|||
using mozilla::FullscreenRoots;
|
||||
|
||||
nsIDocument*
|
||||
nsDocument::GetFullscreenRoot()
|
||||
nsIDocument::GetFullscreenRoot()
|
||||
{
|
||||
nsCOMPtr<nsIDocument> root = do_QueryReferent(mFullscreenRoot);
|
||||
return root;
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::SetFullscreenRoot(nsIDocument* aRoot)
|
||||
nsIDocument::SetFullscreenRoot(nsIDocument* aRoot)
|
||||
{
|
||||
mFullscreenRoot = do_GetWeakReference(aRoot);
|
||||
}
|
||||
|
@ -10600,7 +10600,7 @@ CountFullscreenSubDocuments(nsIDocument* aDoc)
|
|||
}
|
||||
|
||||
bool
|
||||
nsDocument::IsFullscreenLeaf()
|
||||
nsIDocument::IsFullscreenLeaf()
|
||||
{
|
||||
// A fullscreen leaf document is fullscreen, and has no fullscreen
|
||||
// subdocuments.
|
||||
|
@ -10616,7 +10616,7 @@ ResetFullScreen(nsIDocument* aDocument, void* aData)
|
|||
if (aDocument->FullScreenStackTop()) {
|
||||
NS_ASSERTION(CountFullscreenSubDocuments(aDocument) <= 1,
|
||||
"Should have at most 1 fullscreen subdocument.");
|
||||
static_cast<nsDocument*>(aDocument)->CleanupFullscreenState();
|
||||
aDocument->CleanupFullscreenState();
|
||||
NS_ASSERTION(!aDocument->FullScreenStackTop(),
|
||||
"Should reset full-screen");
|
||||
auto changed = reinterpret_cast<nsCOMArray<nsIDocument>*>(aData);
|
||||
|
@ -10741,7 +10741,7 @@ GetFullscreenLeaf(nsIDocument* aDoc)
|
|||
}
|
||||
|
||||
void
|
||||
nsDocument::RestorePreviousFullScreenState()
|
||||
nsIDocument::RestorePreviousFullScreenState()
|
||||
{
|
||||
NS_ASSERTION(!FullScreenStackTop() || !FullscreenRoots::IsEmpty(),
|
||||
"Should have at least 1 fullscreen root when fullscreen!");
|
||||
|
@ -10751,21 +10751,20 @@ nsDocument::RestorePreviousFullScreenState()
|
|||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> fullScreenDoc = GetFullscreenLeaf(this);
|
||||
AutoTArray<nsDocument*, 8> exitDocs;
|
||||
AutoTArray<nsIDocument*, 8> exitDocs;
|
||||
|
||||
nsIDocument* doc = fullScreenDoc;
|
||||
// Collect all subdocuments.
|
||||
for (; doc != this; doc = doc->GetParentDocument()) {
|
||||
exitDocs.AppendElement(static_cast<nsDocument*>(doc));
|
||||
exitDocs.AppendElement(doc);
|
||||
}
|
||||
MOZ_ASSERT(doc == this, "Must have reached this doc");
|
||||
// Collect all ancestor documents which we are going to change.
|
||||
for (; doc; doc = doc->GetParentDocument()) {
|
||||
nsDocument* theDoc = static_cast<nsDocument*>(doc);
|
||||
MOZ_ASSERT(!theDoc->mFullScreenStack.IsEmpty(),
|
||||
MOZ_ASSERT(!doc->mFullScreenStack.IsEmpty(),
|
||||
"Ancestor of fullscreen document must also be in fullscreen");
|
||||
if (doc != this) {
|
||||
Element* top = theDoc->FullScreenStackTop();
|
||||
Element* top = doc->FullScreenStackTop();
|
||||
if (top->IsHTMLElement(nsGkAtoms::iframe)) {
|
||||
if (static_cast<HTMLIFrameElement*>(top)->FullscreenFlag()) {
|
||||
// If this is an iframe, and it explicitly requested
|
||||
|
@ -10774,13 +10773,13 @@ nsDocument::RestorePreviousFullScreenState()
|
|||
}
|
||||
}
|
||||
}
|
||||
exitDocs.AppendElement(theDoc);
|
||||
if (theDoc->mFullScreenStack.Length() > 1) {
|
||||
exitDocs.AppendElement(doc);
|
||||
if (doc->mFullScreenStack.Length() > 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nsDocument* lastDoc = exitDocs.LastElement();
|
||||
nsIDocument* lastDoc = exitDocs.LastElement();
|
||||
if (!lastDoc->GetParentDocument() &&
|
||||
lastDoc->mFullScreenStack.Length() == 1) {
|
||||
// If we are fully exiting fullscreen, don't touch anything here,
|
||||
|
@ -10807,7 +10806,7 @@ nsDocument::RestorePreviousFullScreenState()
|
|||
newFullscreenDoc = lastDoc->GetParentDocument();
|
||||
}
|
||||
// Dispatch the fullscreenchange event to all document listed.
|
||||
for (nsDocument* d : exitDocs) {
|
||||
for (nsIDocument* d : exitDocs) {
|
||||
DispatchFullScreenChange(d);
|
||||
}
|
||||
|
||||
|
@ -10845,7 +10844,7 @@ public:
|
|||
};
|
||||
|
||||
void
|
||||
nsDocument::AsyncRequestFullScreen(UniquePtr<FullscreenRequest>&& aRequest)
|
||||
nsIDocument::AsyncRequestFullScreen(UniquePtr<FullscreenRequest>&& aRequest)
|
||||
{
|
||||
if (!aRequest->GetElement()) {
|
||||
MOZ_ASSERT_UNREACHABLE(
|
||||
|
@ -10894,7 +10893,7 @@ ClearFullscreenStateOnElement(Element* aElement)
|
|||
}
|
||||
|
||||
void
|
||||
nsDocument::CleanupFullscreenState()
|
||||
nsIDocument::CleanupFullscreenState()
|
||||
{
|
||||
// Iterate the fullscreen stack and clear the fullscreen states.
|
||||
// Since we also need to clear the fullscreen-ancestor state, and
|
||||
|
@ -10914,7 +10913,7 @@ nsDocument::CleanupFullscreenState()
|
|||
}
|
||||
|
||||
bool
|
||||
nsDocument::FullScreenStackPush(Element* aElement)
|
||||
nsIDocument::FullScreenStackPush(Element* aElement)
|
||||
{
|
||||
NS_ASSERTION(aElement, "Must pass non-null to FullScreenStackPush()");
|
||||
Element* top = FullScreenStackTop();
|
||||
|
@ -10929,7 +10928,7 @@ nsDocument::FullScreenStackPush(Element* aElement)
|
|||
}
|
||||
|
||||
void
|
||||
nsDocument::FullScreenStackPop()
|
||||
nsIDocument::FullScreenStackPop()
|
||||
{
|
||||
if (mFullScreenStack.IsEmpty()) {
|
||||
return;
|
||||
|
@ -10963,7 +10962,7 @@ nsDocument::FullScreenStackPop()
|
|||
}
|
||||
|
||||
Element*
|
||||
nsDocument::FullScreenStackTop()
|
||||
nsIDocument::FullScreenStackTop()
|
||||
{
|
||||
if (mFullScreenStack.IsEmpty()) {
|
||||
return nullptr;
|
||||
|
@ -10976,8 +10975,8 @@ nsDocument::FullScreenStackTop()
|
|||
return element;
|
||||
}
|
||||
|
||||
/* virtual */ nsTArray<Element*>
|
||||
nsDocument::GetFullscreenStack() const
|
||||
nsTArray<Element*>
|
||||
nsIDocument::GetFullscreenStack() const
|
||||
{
|
||||
nsTArray<Element*> elements;
|
||||
for (const nsWeakPtr& ptr : mFullScreenStack) {
|
||||
|
@ -11028,7 +11027,7 @@ IsInActiveTab(nsIDocument* aDoc)
|
|||
return activeWindow == rootWin;
|
||||
}
|
||||
|
||||
nsresult nsDocument::RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement)
|
||||
nsresult nsIDocument::RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement)
|
||||
{
|
||||
// Ensure the frame element is the fullscreen element in this document.
|
||||
// If the frame element is already the fullscreen element in this document,
|
||||
|
@ -11042,7 +11041,7 @@ nsresult nsDocument::RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsDocument::RemoteFrameFullscreenReverted()
|
||||
nsresult nsIDocument::RemoteFrameFullscreenReverted()
|
||||
{
|
||||
RestorePreviousFullScreenState();
|
||||
return NS_OK;
|
||||
|
@ -11091,8 +11090,8 @@ GetFullscreenError(nsIDocument* aDoc, bool aCallerIsChrome)
|
|||
}
|
||||
|
||||
bool
|
||||
nsDocument::FullscreenElementReadyCheck(Element* aElement,
|
||||
bool aWasCallerChrome)
|
||||
nsIDocument::FullscreenElementReadyCheck(Element* aElement,
|
||||
bool aWasCallerChrome)
|
||||
{
|
||||
NS_ASSERTION(aElement,
|
||||
"Must pass non-null element to nsDocument::RequestFullScreen");
|
||||
|
@ -11310,7 +11309,7 @@ ShouldApplyFullscreenDirectly(nsIDocument* aDoc,
|
|||
}
|
||||
|
||||
void
|
||||
nsDocument::RequestFullScreen(UniquePtr<FullscreenRequest>&& aRequest)
|
||||
nsIDocument::RequestFullScreen(UniquePtr<FullscreenRequest>&& aRequest)
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindowOuter> rootWin = GetRootWindow(this);
|
||||
if (!rootWin) {
|
||||
|
@ -11378,7 +11377,7 @@ ClearPendingFullscreenRequests(nsIDocument* aDoc)
|
|||
}
|
||||
|
||||
bool
|
||||
nsDocument::ApplyFullscreen(const FullscreenRequest& aRequest)
|
||||
nsIDocument::ApplyFullscreen(const FullscreenRequest& aRequest)
|
||||
{
|
||||
Element* elem = aRequest.GetElement();
|
||||
if (!FullscreenElementReadyCheck(elem, aRequest.mIsCallerChrome)) {
|
||||
|
@ -11479,7 +11478,7 @@ nsDocument::ApplyFullscreen(const FullscreenRequest& aRequest)
|
|||
}
|
||||
|
||||
bool
|
||||
nsDocument::FullscreenEnabled(CallerType aCallerType)
|
||||
nsIDocument::FullscreenEnabled(CallerType aCallerType)
|
||||
{
|
||||
return !GetFullscreenError(this, aCallerType == CallerType::System);
|
||||
}
|
||||
|
|
|
@ -107,11 +107,11 @@ struct FullscreenRequest : public LinkedListElement<FullscreenRequest>
|
|||
~FullscreenRequest();
|
||||
|
||||
Element* GetElement() const { return mElement; }
|
||||
nsDocument* GetDocument() const { return mDocument; }
|
||||
nsIDocument* GetDocument() const { return mDocument; }
|
||||
|
||||
private:
|
||||
RefPtr<Element> mElement;
|
||||
RefPtr<nsDocument> mDocument;
|
||||
RefPtr<nsIDocument> mDocument;
|
||||
|
||||
public:
|
||||
// This value should be true if the fullscreen request is
|
||||
|
@ -669,18 +669,6 @@ public:
|
|||
|
||||
virtual Element* FindImageMap(const nsAString& aNormalizedMapName) override;
|
||||
|
||||
virtual nsTArray<Element*> GetFullscreenStack() const override;
|
||||
virtual void AsyncRequestFullScreen(
|
||||
mozilla::UniquePtr<FullscreenRequest>&& aRequest) override;
|
||||
virtual void RestorePreviousFullScreenState() override;
|
||||
virtual bool IsFullscreenLeaf() override;
|
||||
virtual nsresult
|
||||
RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement) override;
|
||||
|
||||
virtual nsresult RemoteFrameFullscreenReverted() override;
|
||||
virtual nsIDocument* GetFullscreenRoot() override;
|
||||
virtual void SetFullscreenRoot(nsIDocument* aRoot) override;
|
||||
|
||||
// Returns the size of the mBlockedTrackingNodes array. (nsIDocument.h)
|
||||
//
|
||||
// This array contains nodes that have been blocked to prevent
|
||||
|
@ -707,34 +695,6 @@ public:
|
|||
//
|
||||
already_AddRefed<nsSimpleContentList> BlockedTrackingNodes() const;
|
||||
|
||||
// Do the "fullscreen element ready check" from the fullscreen spec.
|
||||
// It returns true if the given element is allowed to go into fullscreen.
|
||||
bool FullscreenElementReadyCheck(Element* aElement, bool aWasCallerChrome);
|
||||
|
||||
// This is called asynchronously by nsIDocument::AsyncRequestFullScreen()
|
||||
// to move this document into full-screen mode if allowed.
|
||||
void RequestFullScreen(mozilla::UniquePtr<FullscreenRequest>&& aRequest);
|
||||
|
||||
// Removes all elements from the full-screen stack, removing full-scren
|
||||
// styles from the top element in the stack.
|
||||
void CleanupFullscreenState();
|
||||
|
||||
// Pushes aElement onto the full-screen stack, and removes full-screen styles
|
||||
// from the former full-screen stack top, and its ancestors, and applies the
|
||||
// styles to aElement. aElement becomes the new "full-screen element".
|
||||
bool FullScreenStackPush(Element* aElement);
|
||||
|
||||
// Remove the top element from the full-screen stack. Removes the full-screen
|
||||
// styles from the former top element, and applies them to the new top
|
||||
// element, if there is one.
|
||||
void FullScreenStackPop();
|
||||
|
||||
// Returns the top element from the full-screen stack.
|
||||
Element* FullScreenStackTop() override;
|
||||
|
||||
// DOM-exposed fullscreen API
|
||||
bool FullscreenEnabled(mozilla::dom::CallerType aCallerType) override;
|
||||
|
||||
void RequestPointerLock(Element* aElement,
|
||||
mozilla::dom::CallerType aCallerType) override;
|
||||
bool SetPointerLock(Element* aElement, int aCursorStyle);
|
||||
|
@ -820,11 +780,6 @@ protected:
|
|||
|
||||
void EnsureOnloadBlocker();
|
||||
|
||||
// Apply the fullscreen state to the document, and trigger related
|
||||
// events. It returns false if the fullscreen element ready check
|
||||
// fails and nothing gets changed.
|
||||
bool ApplyFullscreen(const FullscreenRequest& aRequest);
|
||||
|
||||
// Array of owning references to all children
|
||||
nsAttrAndChildArray mChildren;
|
||||
|
||||
|
@ -832,15 +787,6 @@ protected:
|
|||
// nullptr until GetOrCreatePendingAnimationTracker is called.
|
||||
RefPtr<mozilla::PendingAnimationTracker> mPendingAnimationTracker;
|
||||
|
||||
// Stack of full-screen elements. When we request full-screen we push the
|
||||
// full-screen element onto this stack, and when we cancel full-screen we
|
||||
// pop one off this stack, restoring the previous full-screen state
|
||||
nsTArray<nsWeakPtr> mFullScreenStack;
|
||||
|
||||
// The root of the doc tree in which this document is in. This is only
|
||||
// non-null when this document is in fullscreen mode.
|
||||
nsWeakPtr mFullscreenRoot;
|
||||
|
||||
public:
|
||||
RefPtr<mozilla::EventListenerManager> mListenerManager;
|
||||
RefPtr<mozilla::dom::ScriptLoader> mScriptLoader;
|
||||
|
@ -874,8 +820,6 @@ public:
|
|||
// that we only report them once for the document.
|
||||
bool mReportedUseCounters:1;
|
||||
|
||||
uint8_t mPendingFullscreenRequests;
|
||||
|
||||
uint8_t mXMLDeclarationBits;
|
||||
|
||||
nsRefPtrHashtable<nsPtrHashKey<nsIContent>, mozilla::dom::BoxObject>* mBoxObjectTable;
|
||||
|
|
|
@ -1611,7 +1611,7 @@ public:
|
|||
/**
|
||||
* Returns all elements in the fullscreen stack in the insertion order.
|
||||
*/
|
||||
virtual nsTArray<Element*> GetFullscreenStack() const = 0;
|
||||
nsTArray<Element*> GetFullscreenStack() const;
|
||||
|
||||
/**
|
||||
* Asynchronously requests that the document make aElement the fullscreen
|
||||
|
@ -1624,8 +1624,29 @@ public:
|
|||
* the <iframe> or <browser> that contains this document is also mode
|
||||
* fullscreen. This happens recursively in all ancestor documents.
|
||||
*/
|
||||
virtual void AsyncRequestFullScreen(
|
||||
mozilla::UniquePtr<FullscreenRequest>&& aRequest) = 0;
|
||||
void AsyncRequestFullScreen(mozilla::UniquePtr<FullscreenRequest>&&);
|
||||
|
||||
// Do the "fullscreen element ready check" from the fullscreen spec.
|
||||
// It returns true if the given element is allowed to go into fullscreen.
|
||||
bool FullscreenElementReadyCheck(Element* aElement, bool aWasCallerChrome);
|
||||
|
||||
// This is called asynchronously by nsIDocument::AsyncRequestFullScreen()
|
||||
// to move this document into full-screen mode if allowed.
|
||||
void RequestFullScreen(mozilla::UniquePtr<FullscreenRequest>&& aRequest);
|
||||
|
||||
// Removes all elements from the full-screen stack, removing full-scren
|
||||
// styles from the top element in the stack.
|
||||
void CleanupFullscreenState();
|
||||
|
||||
// Pushes aElement onto the full-screen stack, and removes full-screen styles
|
||||
// from the former full-screen stack top, and its ancestors, and applies the
|
||||
// styles to aElement. aElement becomes the new "full-screen element".
|
||||
bool FullScreenStackPush(Element* aElement);
|
||||
|
||||
// Remove the top element from the full-screen stack. Removes the full-screen
|
||||
// styles from the former top element, and applies them to the new top
|
||||
// element, if there is one.
|
||||
void FullScreenStackPop();
|
||||
|
||||
/**
|
||||
* Called when a frame in a child process has entered fullscreen or when a
|
||||
|
@ -1633,8 +1654,7 @@ public:
|
|||
* aFrameElement is the frame element which contains the child-process
|
||||
* fullscreen document.
|
||||
*/
|
||||
virtual nsresult
|
||||
RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement) = 0;
|
||||
nsresult RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement);
|
||||
|
||||
/**
|
||||
* Called when a frame in a remote child document has rolled back fullscreen
|
||||
|
@ -1645,33 +1665,33 @@ public:
|
|||
* fullscreen document has a parent and that parent isn't fullscreen. We
|
||||
* preserve this property across process boundaries.
|
||||
*/
|
||||
virtual nsresult RemoteFrameFullscreenReverted() = 0;
|
||||
nsresult RemoteFrameFullscreenReverted();
|
||||
|
||||
/**
|
||||
* Restores the previous full-screen element to full-screen status. If there
|
||||
* is no former full-screen element, this exits full-screen, moving the
|
||||
* top-level browser window out of full-screen mode.
|
||||
*/
|
||||
virtual void RestorePreviousFullScreenState() = 0;
|
||||
void RestorePreviousFullScreenState();
|
||||
|
||||
/**
|
||||
* Returns true if this document is a fullscreen leaf document, i.e. it
|
||||
* is in fullscreen mode and has no fullscreen children.
|
||||
*/
|
||||
virtual bool IsFullscreenLeaf() = 0;
|
||||
bool IsFullscreenLeaf();
|
||||
|
||||
/**
|
||||
* Returns the document which is at the root of this document's branch
|
||||
* in the in-process document tree. Returns nullptr if the document isn't
|
||||
* fullscreen.
|
||||
*/
|
||||
virtual nsIDocument* GetFullscreenRoot() = 0;
|
||||
nsIDocument* GetFullscreenRoot();
|
||||
|
||||
/**
|
||||
* Sets the fullscreen root to aRoot. This stores a weak reference to aRoot
|
||||
* in this document.
|
||||
*/
|
||||
virtual void SetFullscreenRoot(nsIDocument* aRoot) = 0;
|
||||
void SetFullscreenRoot(nsIDocument* aRoot);
|
||||
|
||||
/**
|
||||
* Synchronously cleans up the fullscreen state on the given document.
|
||||
|
@ -3002,8 +3022,8 @@ public:
|
|||
void MozSetImageElement(const nsAString& aImageElementId, Element* aElement);
|
||||
nsIURI* GetDocumentURIObject() const;
|
||||
// Not const because all the full-screen goop is not const
|
||||
virtual bool FullscreenEnabled(mozilla::dom::CallerType aCallerType) = 0;
|
||||
virtual Element* FullScreenStackTop() = 0;
|
||||
bool FullscreenEnabled(mozilla::dom::CallerType aCallerType);
|
||||
Element* FullScreenStackTop();
|
||||
bool Fullscreen()
|
||||
{
|
||||
return !!GetFullscreenElement();
|
||||
|
@ -3344,6 +3364,11 @@ protected:
|
|||
// to notify window when the page was first visited.
|
||||
void MaybeActiveMediaComponents();
|
||||
|
||||
// Apply the fullscreen state to the document, and trigger related
|
||||
// events. It returns false if the fullscreen element ready check
|
||||
// fails and nothing gets changed.
|
||||
bool ApplyFullscreen(const FullscreenRequest& aRequest);
|
||||
|
||||
bool GetUseCounter(mozilla::UseCounter aUseCounter)
|
||||
{
|
||||
return mUseCounters[aUseCounter];
|
||||
|
@ -3781,6 +3806,8 @@ protected:
|
|||
enum { eScopedStyle_Unknown, eScopedStyle_Disabled, eScopedStyle_Enabled };
|
||||
unsigned int mIsScopedStyleEnabled : 2;
|
||||
|
||||
uint8_t mPendingFullscreenRequests;
|
||||
|
||||
// Compatibility mode
|
||||
nsCompatibility mCompatMode;
|
||||
|
||||
|
@ -4016,6 +4043,15 @@ protected:
|
|||
nsTHashtable<nsPtrHashKey<mozilla::dom::DOMIntersectionObserver>>
|
||||
mIntersectionObservers;
|
||||
|
||||
// Stack of full-screen elements. When we request full-screen we push the
|
||||
// full-screen element onto this stack, and when we cancel full-screen we
|
||||
// pop one off this stack, restoring the previous full-screen state
|
||||
nsTArray<nsWeakPtr> mFullScreenStack;
|
||||
|
||||
// The root of the doc tree in which this document is in. This is only
|
||||
// non-null when this document is in fullscreen mode.
|
||||
nsWeakPtr mFullscreenRoot;
|
||||
|
||||
nsTArray<RefPtr<mozilla::StyleSheet>> mOnDemandBuiltInUASheets;
|
||||
nsTArray<RefPtr<mozilla::StyleSheet>> mAdditionalSheets[AdditionalSheetTypeCount];
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче