diff --git a/browser/base/content/pageinfo/pageInfo.js b/browser/base/content/pageinfo/pageInfo.js
index 3959278f3072..f31246e1ded1 100644
--- a/browser/base/content/pageinfo/pageInfo.js
+++ b/browser/base/content/pageinfo/pageInfo.js
@@ -149,7 +149,10 @@ pageInfoTreeView.prototype = {
return 0;
},
getImageSrc(row, column) {},
- getCellValue(row, column) {},
+ getCellValue(row, column) {
+ let col = column != null ? column : this.copycol;
+ return row < 0 || col < 0 ? "" : this.data[row][col] || "";
+ },
toggleOpenState(index) {},
cycleHeader(col) {},
selectionChanged() {},
@@ -269,6 +272,19 @@ const nsIPermissionManager = Ci.nsIPermissionManager;
const nsICertificateDialogs = Ci.nsICertificateDialogs;
const CERTIFICATEDIALOGS_CONTRACTID = "@mozilla.org/nsCertificateDialogs;1";
+// clipboard helper
+function getClipboardHelper() {
+ try {
+ return Cc["@mozilla.org/widget/clipboardhelper;1"].getService(
+ Ci.nsIClipboardHelper
+ );
+ } catch (e) {
+ // do nothing, later code will handle the error
+ return null;
+ }
+}
+const gClipboardHelper = getClipboardHelper();
+
// namespaces, don't need all of these yet...
const XLinkNS = "http://www.w3.org/1999/xlink";
const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
@@ -1175,6 +1191,37 @@ function formatDate(datestr, unknown) {
return dateTimeFormatter.format(date);
}
+function doCopy() {
+ if (!gClipboardHelper) {
+ return;
+ }
+
+ var elem = document.commandDispatcher.focusedElement;
+
+ if (elem && elem.localName == "tree") {
+ var view = elem.view;
+ var selection = view.selection;
+ var text = [],
+ tmp = "";
+ var min = {},
+ max = {};
+
+ var count = selection.getRangeCount();
+
+ for (var i = 0; i < count; i++) {
+ selection.getRangeAt(i, min, max);
+
+ for (var row = min.value; row <= max.value; row++) {
+ tmp = view.getCellValue(row, null);
+ if (tmp) {
+ text.push(tmp);
+ }
+ }
+ }
+ gClipboardHelper.copyString(text.join("\n"));
+ }
+}
+
function doSelectAllMedia() {
var tree = document.getElementById("imagetree");
diff --git a/browser/base/content/pageinfo/pageInfo.xul b/browser/base/content/pageinfo/pageInfo.xul
index 3f703915d92e..b627afd527f8 100644
--- a/browser/base/content/pageinfo/pageInfo.xul
+++ b/browser/base/content/pageinfo/pageInfo.xul
@@ -47,6 +47,7 @@
+
@@ -58,12 +59,14 @@
#else
#endif
+
+
diff --git a/browser/base/content/test/permissions/browser_temporary_permissions.js b/browser/base/content/test/permissions/browser_temporary_permissions.js
index bbc9c026ac59..66d09a79df8b 100644
--- a/browser/base/content/test/permissions/browser_temporary_permissions.js
+++ b/browser/base/content/test/permissions/browser_temporary_permissions.js
@@ -72,7 +72,7 @@ add_task(async function testTempPermissionSubframes() {
// FIXME(Fission): The load event fires before cross-origin iframes have
// loaded (bug 1559841).
if (content.SpecialPowers.useRemoteSubframes) {
- for (let i = 0; i < 200; i++) {
+ for (let i = 0; i < 800; i++) {
await new Promise(resolve => content.setTimeout(resolve, 0));
}
}
diff --git a/browser/locales/en-US/browser/pageInfo.ftl b/browser/locales/en-US/browser/pageInfo.ftl
index 33256ef1d338..c45dc3c3b51a 100644
--- a/browser/locales/en-US/browser/pageInfo.ftl
+++ b/browser/locales/en-US/browser/pageInfo.ftl
@@ -5,6 +5,12 @@
page-info-window =
.style = width: 600px; min-height: 550px;
+copy =
+ .key = C
+menu-copy =
+ .label = Copy
+ .accesskey = C
+
select-all =
.key = A
menu-select-all =
diff --git a/docshell/base/BrowsingContext.cpp b/docshell/base/BrowsingContext.cpp
index 3cdb775f6d9a..0e211f459be0 100644
--- a/docshell/base/BrowsingContext.cpp
+++ b/docshell/base/BrowsingContext.cpp
@@ -132,7 +132,10 @@ already_AddRefed BrowsingContext::Create(
// The name and opener fields need to be explicitly initialized. Don't bother
// using transactions to set them, as we haven't been attached yet.
context->mName = aName;
- context->mOpenerId = aOpener ? aOpener->Id() : 0;
+ if (aOpener) {
+ context->mOpenerId = aOpener->Id();
+ context->mHadOriginalOpener = true;
+ }
context->mEmbedderPolicy = nsILoadInfo::EMBEDDER_POLICY_NULL;
BrowsingContext* inherit = aParent ? aParent : aOpener;
diff --git a/docshell/base/BrowsingContext.h b/docshell/base/BrowsingContext.h
index 8dc103373d40..67a796548116 100644
--- a/docshell/base/BrowsingContext.h
+++ b/docshell/base/BrowsingContext.h
@@ -209,13 +209,22 @@ class BrowsingContext : public nsWrapperCache, public BrowsingContextBase {
BrowsingContext* Top();
- already_AddRefed GetOpener() const { return Get(mOpenerId); }
+ already_AddRefed GetOpener() const {
+ RefPtr opener(Get(mOpenerId));
+ if (!mIsDiscarded && opener && !opener->mIsDiscarded) {
+ return opener.forget();
+ }
+ return nullptr;
+ }
void SetOpener(BrowsingContext* aOpener) {
+ MOZ_DIAGNOSTIC_ASSERT(!aOpener || aOpener->Group() == Group());
SetOpenerId(aOpener ? aOpener->Id() : 0);
}
bool HasOpener() const;
+ bool HadOriginalOpener() const { return mHadOriginalOpener; }
+
/**
* When a new browsing context is opened by a sandboxed document, it needs to
* keep track of the browsing context that opened it, so that it can be
@@ -481,9 +490,7 @@ class BrowsingContext : public nsWrapperCache, public BrowsingContextBase {
uintptr_t(this) - offsetof(BrowsingContext, mLocation));
}
- already_AddRefed GetDocShell() override {
- return nullptr;
- }
+ already_AddRefed GetDocShell() override { return nullptr; }
};
// Ensure that opener is in the same BrowsingContextGroup.
diff --git a/docshell/base/BrowsingContextFieldList.h b/docshell/base/BrowsingContextFieldList.h
index 15c1e9c8e21d..8b522aad7c07 100644
--- a/docshell/base/BrowsingContextFieldList.h
+++ b/docshell/base/BrowsingContextFieldList.h
@@ -21,6 +21,8 @@ MOZ_BC_FIELD(OpenerId, uint64_t)
MOZ_BC_FIELD(OnePermittedSandboxedNavigatorId, uint64_t)
+MOZ_BC_FIELD(HadOriginalOpener, bool)
+
// Toplevel browsing contexts only. This field controls whether the browsing
// context is currently considered to be activated by a gesture.
MOZ_BC_FIELD(IsActivatedByUserGesture, bool)
diff --git a/docshell/base/nsDSURIContentListener.cpp b/docshell/base/nsDSURIContentListener.cpp
index c46da4f57e68..a5b0ddfa7990 100644
--- a/docshell/base/nsDSURIContentListener.cpp
+++ b/docshell/base/nsDSURIContentListener.cpp
@@ -16,6 +16,7 @@
#include "nsError.h"
#include "nsContentSecurityManager.h"
#include "nsDocShellLoadTypes.h"
+#include "nsGlobalWindowOuter.h"
#include "nsIInterfaceRequestor.h"
#include "nsIMultiPartChannel.h"
@@ -48,10 +49,11 @@ nsIInterfaceRequestor* MaybeCloseWindowHelper::MaybeCloseWindow() {
if (mShouldCloseWindow) {
// Reset the window context to the opener window so that the dependent
// dialogs have a parent
- nsCOMPtr opener = window->GetOpener();
+ nsCOMPtr opener =
+ nsGlobalWindowOuter::Cast(window)->GetSameProcessOpener();
if (opener && !opener->Closed()) {
- mContentContext = do_GetInterface(opener);
+ mContentContext = do_QueryInterface(opener);
// Now close the old window. Do it on a timer so that we don't run
// into issues trying to close the window before it has fully opened.
diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp
index 90b219210e00..d34acc6a15ad 100644
--- a/dom/base/Document.cpp
+++ b/dom/base/Document.cpp
@@ -14863,12 +14863,12 @@ void Document::MaybeAllowStorageForOpenerAfterUserInteraction() {
return;
}
- nsCOMPtr outer = inner->GetOuterWindow();
+ auto* outer = nsGlobalWindowOuter::Cast(inner->GetOuterWindow());
if (NS_WARN_IF(!outer)) {
return;
}
- nsCOMPtr outerOpener = outer->GetOpener();
+ nsCOMPtr outerOpener = outer->GetSameProcessOpener();
if (!outerOpener) {
return;
}
diff --git a/dom/base/nsFrameLoader.cpp b/dom/base/nsFrameLoader.cpp
index e0687c7089d2..decf687055a9 100644
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -2084,12 +2084,6 @@ nsresult nsFrameLoader::MaybeCreateDocShell() {
newWindow->SetFrameElementInternal(mOwnerContent);
- // TODO(farre): Remove this when nsGlobalWindowOuter::GetOpenerWindowOuter
- // starts using BrowsingContext::GetOpener.
- if (RefPtr opener = mBrowsingContext->GetOpener()) {
- newWindow->SetOpenerWindow(opener->GetDOMWindow(), true);
- }
-
// Allow scripts to close the docshell if specified.
if (mOwnerContent->IsXULElement(nsGkAtoms::browser) &&
mOwnerContent->AttrValueIs(kNameSpaceID_None,
diff --git a/dom/base/nsGlobalWindowInner.cpp b/dom/base/nsGlobalWindowInner.cpp
index a13a455d78c4..65c7dbcc4e10 100644
--- a/dom/base/nsGlobalWindowInner.cpp
+++ b/dom/base/nsGlobalWindowInner.cpp
@@ -3034,27 +3034,33 @@ nsresult nsGlobalWindowInner::GetControllers(nsIControllers** aResult) {
return rv.StealNSResult();
}
-nsPIDOMWindowOuter* nsGlobalWindowInner::GetOpenerWindow(ErrorResult& aError) {
+Nullable nsGlobalWindowInner::GetOpenerWindow(
+ ErrorResult& aError) {
FORWARD_TO_OUTER_OR_THROW(GetOpenerWindowOuter, (), aError, nullptr);
}
void nsGlobalWindowInner::GetOpener(JSContext* aCx,
JS::MutableHandle aRetval,
ErrorResult& aError) {
- nsCOMPtr opener = GetOpenerWindow(aError);
- if (aError.Failed() || !opener) {
+ Nullable opener = GetOpenerWindow(aError);
+ if (aError.Failed() || opener.IsNull()) {
aRetval.setNull();
return;
}
- aError = nsContentUtils::WrapNative(aCx, opener, aRetval);
+ if (!ToJSValue(aCx, opener.Value(), aRetval)) {
+ aError.NoteJSContextException(aCx);
+ }
}
void nsGlobalWindowInner::SetOpener(JSContext* aCx,
JS::Handle aOpener,
ErrorResult& aError) {
if (aOpener.isNull()) {
- FORWARD_TO_OUTER_VOID(SetOpenerWindow, (nullptr, false));
+ RefPtr bc(GetBrowsingContext());
+ if (!bc->IsDiscarded()) {
+ bc->SetOpener(nullptr);
+ }
return;
}
diff --git a/dom/base/nsGlobalWindowInner.h b/dom/base/nsGlobalWindowInner.h
index 32029b6f3597..f35c31ba55db 100644
--- a/dom/base/nsGlobalWindowInner.h
+++ b/dom/base/nsGlobalWindowInner.h
@@ -622,7 +622,8 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
void InitWasOffline();
public:
- nsPIDOMWindowOuter* GetOpenerWindow(mozilla::ErrorResult& aError);
+ mozilla::dom::Nullable GetOpenerWindow(
+ mozilla::ErrorResult& aError);
void GetOpener(JSContext* aCx, JS::MutableHandle aRetval,
mozilla::ErrorResult& aError);
void SetOpener(JSContext* aCx, JS::Handle aOpener,
diff --git a/dom/base/nsGlobalWindowOuter.cpp b/dom/base/nsGlobalWindowOuter.cpp
index ff5274f71d35..8735e91149d5 100644
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -1095,7 +1095,6 @@ nsGlobalWindowOuter::nsGlobalWindowOuter(uint64_t aWindowID)
mIsClosed(false),
mInClose(false),
mHavePendingClose(false),
- mHadOriginalOpener(false),
mIsPopupSpam(false),
mBlockScriptedClosingFlag(false),
mWasOffline(false),
@@ -1298,10 +1297,7 @@ void nsGlobalWindowOuter::CleanUp() {
ClearControllers();
- mOpener = nullptr; // Forces Release
- if (mContext) {
- mContext = nullptr; // Forces Release
- }
+ mContext = nullptr; // Forces Release
mChromeEventHandler = nullptr; // Forces Release
mParentTarget = nullptr;
mMessageManager = nullptr;
@@ -2518,70 +2514,6 @@ void nsGlobalWindowOuter::DetachFromDocShell() {
CleanUp();
}
-void nsGlobalWindowOuter::SetOpenerWindow(nsPIDOMWindowOuter* aOpener,
- bool aOriginalOpener) {
- nsWeakPtr opener = do_GetWeakReference(aOpener);
- if (opener == mOpener) {
- MOZ_DIAGNOSTIC_ASSERT(!aOpener || !aOpener->GetDocShell() ||
- (GetBrowsingContext() &&
- aOpener->GetBrowsingContext() &&
- aOpener->GetBrowsingContext()->Id() ==
- GetBrowsingContext()->GetOpenerId()));
- return;
- }
-
- NS_ASSERTION(!aOriginalOpener || !mSetOpenerWindowCalled,
- "aOriginalOpener is true, but not first call to "
- "SetOpenerWindow!");
- NS_ASSERTION(aOpener || !aOriginalOpener,
- "Shouldn't set mHadOriginalOpener if aOpener is null");
-
- mOpener = opener.forget();
- NS_ASSERTION(mOpener || !aOpener, "Opener must support weak references!");
-
- if (mDocShell) {
- MOZ_DIAGNOSTIC_ASSERT(
- !aOriginalOpener || !aOpener ||
- // TODO(farre): Allowing to set a closed or closing window as
- // opener is not ideal, since it won't have a docshell and
- // therefore no browsing context. This means that we're
- // effectively setting the browsing context opener to null and
- // the window opener to a closed window. This needs to be
- // cleaned up, see Bug 1511353.
- nsGlobalWindowOuter::Cast(aOpener)->IsClosedOrClosing() ||
- // TODO(farre): Allowing to set an opener on a closed window is
- // not ideal either, but we need to allow it for now. Bug 1543056.
- IsClosedOrClosing() ||
- aOpener->GetBrowsingContext()->Id() ==
- GetBrowsingContext()->GetOpenerId());
- // TODO(farre): Here we really wish to only consider the case
- // where 'aOriginalOpener'. See bug 1509016.
- GetBrowsingContext()->SetOpener(aOpener ? aOpener->GetBrowsingContext()
- : nullptr);
- }
-
- // Check that the js visible opener matches! We currently don't depend on this
- // being true outside of nightly, so we disable the assertion in optimized
- // release / beta builds.
- nsPIDOMWindowOuter* contentOpener = GetSanitizedOpener(aOpener);
-
- // contentOpener is not used when the DIAGNOSTIC_ASSERT is compiled out.
- mozilla::Unused << contentOpener;
- MOZ_DIAGNOSTIC_ASSERT(
- !contentOpener || !mTabGroup ||
- mTabGroup == nsGlobalWindowOuter::Cast(contentOpener)->mTabGroup);
-
- if (aOriginalOpener) {
- MOZ_ASSERT(!mHadOriginalOpener,
- "Probably too late to call ComputeIsSecureContext again");
- mHadOriginalOpener = true;
- }
-
-#ifdef DEBUG
- mSetOpenerWindowCalled = true;
-#endif
-}
-
void nsGlobalWindowOuter::UpdateParentTarget() {
// NOTE: This method is nearly identical to
// nsGlobalWindowInner::UpdateParentTarget(). IF YOU UPDATE THIS METHOD,
@@ -3290,63 +3222,44 @@ nsresult nsGlobalWindowOuter::GetControllers(nsIControllers** aResult) {
FORWARD_TO_INNER(GetControllers, (aResult), NS_ERROR_UNEXPECTED);
}
-nsPIDOMWindowOuter* nsGlobalWindowOuter::GetSanitizedOpener(
- nsPIDOMWindowOuter* aOpener) {
- if (!aOpener) {
+already_AddRefed
+nsGlobalWindowOuter::GetOpenerBrowsingContext() {
+ RefPtr opener = GetBrowsingContext()->GetOpener();
+ MOZ_DIAGNOSTIC_ASSERT(!opener ||
+ opener->Group() == GetBrowsingContext()->Group());
+ if (!opener || opener->Group() != GetBrowsingContext()->Group()) {
return nullptr;
}
- nsGlobalWindowOuter* win = nsGlobalWindowOuter::Cast(aOpener);
-
- // First, ensure that we're not handing back a chrome window to content:
- if (win->IsChromeWindow()) {
- return nullptr;
- }
-
- // We don't want to reveal the opener if the opener is a mail window,
- // because opener can be used to spoof the contents of a message (bug 105050).
- // So, we look in the opener's root docshell to see if it's a mail window.
- nsCOMPtr openerDocShell = aOpener->GetDocShell();
-
- if (openerDocShell) {
- nsCOMPtr openerRootItem;
- openerDocShell->GetInProcessRootTreeItem(getter_AddRefs(openerRootItem));
- nsCOMPtr openerRootDocShell(do_QueryInterface(openerRootItem));
- if (openerRootDocShell) {
- nsIDocShell::AppType appType = openerRootDocShell->GetAppType();
- if (appType != nsIDocShell::APP_TYPE_MAIL) {
- return aOpener;
- }
+ // Catch the case where we're chrome but the opener is not...
+ if (nsContentUtils::LegacyIsCallerChromeOrNativeCode() &&
+ GetPrincipal() == nsContentUtils::GetSystemPrincipal()) {
+ auto* openerWin = nsGlobalWindowOuter::Cast(opener->GetDOMWindow());
+ if (!openerWin ||
+ openerWin->GetPrincipal() != nsContentUtils::GetSystemPrincipal()) {
+ return nullptr;
}
}
+ return opener.forget();
+}
+
+nsPIDOMWindowOuter* nsGlobalWindowOuter::GetSameProcessOpener() {
+ if (RefPtr opener = GetOpenerBrowsingContext()) {
+ return opener->GetDOMWindow();
+ }
return nullptr;
}
-nsPIDOMWindowOuter* nsGlobalWindowOuter::GetOpenerWindowOuter() {
- nsCOMPtr opener = do_QueryReferent(mOpener);
-
- if (!opener) {
- return nullptr;
+Nullable nsGlobalWindowOuter::GetOpenerWindowOuter() {
+ if (RefPtr opener = GetOpenerBrowsingContext()) {
+ return WindowProxyHolder(opener.forget());
}
-
- // First, check if we were called from a privileged chrome script
- if (nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
- // Catch the case where we're chrome but the opener is not...
- if (GetPrincipal() == nsContentUtils::GetSystemPrincipal() &&
- nsGlobalWindowOuter::Cast(opener)->GetPrincipal() !=
- nsContentUtils::GetSystemPrincipal()) {
- return nullptr;
- }
- return opener;
- }
-
- return GetSanitizedOpener(opener);
+ return nullptr;
}
-already_AddRefed nsGlobalWindowOuter::GetOpener() {
- nsCOMPtr opener = GetOpenerWindowOuter();
- return opener.forget();
+Nullable nsGlobalWindowOuter::GetOpener() {
+ return GetOpenerWindowOuter();
}
void nsGlobalWindowOuter::GetStatusOuter(nsAString& aStatus) {
@@ -4740,7 +4653,7 @@ bool nsGlobalWindowOuter::CanMoveResizeWindows(CallerType aCallerType) {
if (aCallerType != CallerType::System) {
// Don't allow scripts to move or resize windows that were not opened by a
// script.
- if (!mHadOriginalOpener) {
+ if (!HadOriginalOpener()) {
return false;
}
@@ -4972,13 +4885,15 @@ void nsGlobalWindowOuter::FocusOuter() {
nsCOMPtr caller = do_QueryInterface(GetEntryGlobal());
nsPIDOMWindowOuter* callerOuter = caller ? caller->GetOuterWindow() : nullptr;
- nsCOMPtr opener = GetOpener();
+ BrowsingContext* callerBC =
+ callerOuter ? callerOuter->GetBrowsingContext() : nullptr;
+ RefPtr openerBC = GetOpenerBrowsingContext();
// Enforce dom.disable_window_flip (for non-chrome), but still allow the
// window which opened us to raise us at times when popups are allowed
// (bugs 355482 and 369306).
bool canFocus = CanSetProperty("dom.disable_window_flip") ||
- (opener == callerOuter &&
+ (openerBC == callerBC &&
RevisePopupAbuseLevel(PopupBlocker::GetPopupControlState()) <
PopupBlocker::openBlocked);
@@ -6283,7 +6198,7 @@ void nsGlobalWindowOuter::CloseOuter(bool aTrustedCaller) {
NS_ENSURE_SUCCESS_VOID(rv);
if (!StringBeginsWith(url, NS_LITERAL_STRING("about:neterror")) &&
- !mHadOriginalOpener && !aTrustedCaller) {
+ !HadOriginalOpener() && !aTrustedCaller) {
bool allowClose =
mAllowScriptsToClose ||
Preferences::GetBool("dom.allow_scripts_to_close_windows", true);
@@ -7781,11 +7696,11 @@ mozilla::dom::TabGroup* nsGlobalWindowOuter::TabGroupOuter() {
// because a document is getting its NodePrincipal, and asking for the
// TabGroup to determine its DocGroup.
if (!mTabGroup) {
- // Get mOpener ourselves, instead of relying on GetOpenerWindowOuter,
+ // Get the opener ourselves, instead of relying on GetOpenerWindowOuter,
// because that way we dodge the LegacyIsCallerChromeOrNativeCode() call
// which we want to return false.
- nsCOMPtr piOpener = do_QueryReferent(mOpener);
- nsPIDOMWindowOuter* opener = GetSanitizedOpener(piOpener);
+ RefPtr openerBC = GetBrowsingContext()->GetOpener();
+ nsPIDOMWindowOuter* opener = openerBC ? openerBC->GetDOMWindow() : nullptr;
nsPIDOMWindowOuter* parent = GetInProcessScriptableParentOrNull();
MOZ_ASSERT(!parent || !opener,
"Only one of parent and opener may be provided");
@@ -7823,9 +7738,11 @@ mozilla::dom::TabGroup* nsGlobalWindowOuter::TabGroupOuter() {
// Sanity check that our tabgroup matches our opener or parent.
RefPtr parent = GetInProcessScriptableParentOrNull();
MOZ_ASSERT_IF(parent, parent->TabGroup() == mTabGroup);
- nsCOMPtr piOpener = do_QueryReferent(mOpener);
- nsPIDOMWindowOuter* opener = GetSanitizedOpener(piOpener);
- MOZ_ASSERT_IF(opener && nsGlobalWindowOuter::Cast(opener) != this,
+
+ RefPtr openerBC = GetBrowsingContext()->GetOpener();
+ nsPIDOMWindowOuter* opener =
+ openerBC ? openerBC->GetDOMWindow() : nullptr;
+ MOZ_ASSERT_IF(opener && Cast(opener) != this,
opener->TabGroup() == mTabGroup);
}
mIsValidatingTabGroup = false;
diff --git a/dom/base/nsGlobalWindowOuter.h b/dom/base/nsGlobalWindowOuter.h
index 4aa373e05b43..5a3add271c6e 100644
--- a/dom/base/nsGlobalWindowOuter.h
+++ b/dom/base/nsGlobalWindowOuter.h
@@ -323,9 +323,6 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
// Outer windows only.
void DispatchDOMWindowCreated();
- virtual void SetOpenerWindow(nsPIDOMWindowOuter* aOpener,
- bool aOriginalOpener) override;
-
// Outer windows only.
virtual void EnsureSizeAndPositionUpToDate() override;
@@ -456,7 +453,9 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
bool IsCleanedUp() const { return mCleanedUp; }
- bool HadOriginalOpener() const { return mHadOriginalOpener; }
+ bool HadOriginalOpener() const {
+ return GetBrowsingContext()->HadOriginalOpener();
+ }
bool IsTopLevelWindow();
@@ -548,14 +547,15 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
RefPtr mPostMessageEventQueue;
protected:
- nsPIDOMWindowOuter* GetOpenerWindowOuter();
+ mozilla::dom::Nullable
+ GetOpenerWindowOuter();
// Initializes the mWasOffline member variable
void InitWasOffline();
public:
- nsPIDOMWindowOuter* GetSanitizedOpener(nsPIDOMWindowOuter* aOpener);
-
- already_AddRefed GetOpener() override;
+ nsPIDOMWindowOuter* GetSameProcessOpener();
+ already_AddRefed GetOpenerBrowsingContext();
+ mozilla::dom::Nullable GetOpener() override;
mozilla::dom::Nullable GetParentOuter();
already_AddRefed GetInProcessParent() override;
nsPIDOMWindowOuter* GetInProcessScriptableParent() override;
@@ -1074,7 +1074,6 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
// close us when the JS stops executing or that we have a close
// event posted. If this is set, just ignore window.close() calls.
bool mHavePendingClose : 1;
- bool mHadOriginalOpener : 1;
bool mIsPopupSpam : 1;
// Indicates whether scripts are allowed to close this window.
@@ -1100,7 +1099,6 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
bool mHasStorageAccess : 1;
nsCOMPtr mContext;
- nsWeakPtr mOpener;
nsCOMPtr mControllers;
// For |window.arguments|, via |openDialog|.
diff --git a/dom/base/nsPIDOMWindow.h b/dom/base/nsPIDOMWindow.h
index 25516939d09d..251aca82b294 100644
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -885,16 +885,6 @@ class nsPIDOMWindowOuter : public mozIDOMWindowProxy {
Document* aDocument, nsISupports* aState, bool aForceReuseInnerWindow,
mozilla::dom::WindowGlobalChild* aActor = nullptr) = 0;
- /**
- * Set the opener window. aOriginalOpener is true if and only if this is the
- * original opener for the window. That is, it can only be true at most once
- * during the life cycle of a window, and then only the first time
- * SetOpenerWindow is called. It might never be true, of course, if the
- * window does not have an opener when it's created.
- */
- virtual void SetOpenerWindow(nsPIDOMWindowOuter* aOpener,
- bool aOriginalOpener) = 0;
-
/**
* Ensure the size and position of this window are up-to-date by doing
* a layout flush in the parent (which will in turn, do a layout flush
@@ -1047,7 +1037,8 @@ class nsPIDOMWindowOuter : public mozIDOMWindowProxy {
virtual nsresult GetPrompter(nsIPrompt** aPrompt) = 0;
virtual nsresult GetControllers(nsIControllers** aControllers) = 0;
virtual already_AddRefed GetSelection() = 0;
- virtual already_AddRefed GetOpener() = 0;
+ virtual mozilla::dom::Nullable
+ GetOpener() = 0;
// aLoadState will be passed on through to the windowwatcher.
// aForceNoOpener will act just like a "noopener" feature in aOptions except
diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp
index 6045dbe3fcf9..364db76ba4ba 100644
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -962,16 +962,17 @@ nsresult ContentChild::ProvideWindowCommon(
// parent. Otherwise, the parent could send messages to us before we have a
// proper TabGroup for that actor.
RefPtr tabGroup;
+ RefPtr openerBC;
if (aTabOpener && !aForceNoOpener) {
// The new actor will use the same tab group as the opener.
tabGroup = aTabOpener->TabGroup();
+ if (aParent) {
+ openerBC = nsPIDOMWindowOuter::From(aParent)->GetBrowsingContext();
+ }
} else {
tabGroup = new TabGroup();
}
- RefPtr openerBC =
- aParent ? nsPIDOMWindowOuter::From(aParent)->GetBrowsingContext()
- : nullptr;
RefPtr browsingContext = BrowsingContext::Create(
nullptr, openerBC, aName, BrowsingContext::Type::Content);
@@ -1099,17 +1100,25 @@ nsresult ContentChild::ProvideWindowCommon(
newChild->SetMaxTouchPoints(maxTouchPoints);
newChild->SetHasSiblings(hasSiblings);
- // Set the opener window for this window before we start loading the
- // document inside of it. We have to do this before loading the remote
- // scripts, because they can poke at the document and cause the Document
- // to be created before the openerwindow
- nsCOMPtr windowProxy =
- do_GetInterface(newChild->WebNavigation());
- if (!aForceNoOpener && windowProxy && aParent) {
- nsPIDOMWindowOuter* outer = nsPIDOMWindowOuter::From(windowProxy);
- nsPIDOMWindowOuter* parent = nsPIDOMWindowOuter::From(aParent);
- outer->SetOpenerWindow(parent, *aWindowIsNew);
+#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
+ if (nsCOMPtr outer =
+ do_GetInterface(newChild->WebNavigation())) {
+ BrowsingContext* bc = outer->GetBrowsingContext();
+ auto parentBC =
+ aParent
+ ? nsPIDOMWindowOuter::From(aParent)->GetBrowsingContext()->Id()
+ : 0;
+
+ if (aForceNoOpener) {
+ MOZ_DIAGNOSTIC_ASSERT(!*aWindowIsNew || !bc->HadOriginalOpener());
+ MOZ_DIAGNOSTIC_ASSERT(bc->GetOpenerId() == 0);
+ } else {
+ MOZ_DIAGNOSTIC_ASSERT(!*aWindowIsNew ||
+ bc->HadOriginalOpener() == !!parentBC);
+ MOZ_DIAGNOSTIC_ASSERT(bc->GetOpenerId() == parentBC);
+ }
}
+#endif
// Unfortunately we don't get a window unless we've shown the frame. That's
// pretty bogus; see bug 763602.
diff --git a/dom/tests/mochitest/bugs/mochitest.ini b/dom/tests/mochitest/bugs/mochitest.ini
index 786558a97061..4dc5f9bc8ef6 100644
--- a/dom/tests/mochitest/bugs/mochitest.ini
+++ b/dom/tests/mochitest/bugs/mochitest.ini
@@ -38,6 +38,8 @@ support-files =
test2_bug622361.html
file1_bug414291.html
file2_bug414291.html
+prefs =
+ fission.rebuild_frameloaders_on_remoteness_change=true
[test_DOMWindowCreated_chromeonly.html]
[test_bug132255.html]
diff --git a/dom/tests/mochitest/localstorage/mochitest.ini b/dom/tests/mochitest/localstorage/mochitest.ini
index 1a5ea9589926..fb0850bb9467 100644
--- a/dom/tests/mochitest/localstorage/mochitest.ini
+++ b/dom/tests/mochitest/localstorage/mochitest.ini
@@ -18,6 +18,8 @@ support-files =
frameLocalStorageSessionOnly.html
file_tryAccessSessionStorage.html
windowProxy.html
+prefs =
+ fission.rebuild_frameloaders_on_remoteness_change=true
[test_brokenUTF-16.html]
[test_bug600307-DBOps.html]
@@ -53,6 +55,5 @@ skip-if = toolkit == 'android' || (verify && (os == 'linux' || os == 'mac' || os
[test_localStorageQuotaSessionOnly2.html]
skip-if = true # bug 1347690
[test_localStorageReplace.html]
-fail-if = fission
skip-if = toolkit == 'android'
[test_storageConstructor.html]
diff --git a/dom/tests/mochitest/sessionstorage/mochitest.ini b/dom/tests/mochitest/sessionstorage/mochitest.ini
index b129824718b6..33a9b1643f45 100644
--- a/dom/tests/mochitest/sessionstorage/mochitest.ini
+++ b/dom/tests/mochitest/sessionstorage/mochitest.ini
@@ -7,11 +7,12 @@ support-files =
frameReplace.html
interOriginSlave.js
interOriginTest.js
+prefs =
+ fission.rebuild_frameloaders_on_remoteness_change=true
[test_sessionStorageBase.html]
[test_sessionStorageBaseSessionOnly.html]
[test_sessionStorageClone.html]
-fail-if = fission
skip-if = toolkit == 'android'
[test_sessionStorageHttpHttps.html]
skip-if = toolkit == 'android' #TIMED_OUT
diff --git a/dom/tests/mochitest/whatwg/mochitest.ini b/dom/tests/mochitest/whatwg/mochitest.ini
index bd7dfe998685..8eb1ef709873 100644
--- a/dom/tests/mochitest/whatwg/mochitest.ini
+++ b/dom/tests/mochitest/whatwg/mochitest.ini
@@ -15,6 +15,8 @@ support-files =
postMessage_throw_helper.html
postMessage_transfer_helper.html
postMessage_userpass_helper.html
+prefs =
+ fission.rebuild_frameloaders_on_remoteness_change=true
[test_bug477323.html]
[test_document_scripts.html]
@@ -31,17 +33,14 @@ skip-if = fission # Timeouts
[test_postMessage_joined.html]
skip-if = fission # Timeouts
[test_postMessage_onOther.html]
-skip-if = fission #Bug 1571273
[test_postMessage_origin.xhtml]
skip-if = fission # Timeouts
[test_postMessage_override.html]
skip-if = fission
[test_postMessage_special.xhtml]
[test_postMessage_structured_clone.html]
-skip-if = fission #Bug 1570918
[test_postMessage_throw.html]
[test_postMessage_transfer.html]
-skip-if = fission #Bug 1571208
[test_postMessage_userpass.html]
skip-if = fission # Timeouts
[test_bug500328.html]
diff --git a/dom/websocket/WebSocket.cpp b/dom/websocket/WebSocket.cpp
index 490b1c8eb207..d0fd8e417ebb 100644
--- a/dom/websocket/WebSocket.cpp
+++ b/dom/websocket/WebSocket.cpp
@@ -2701,14 +2701,8 @@ nsresult WebSocketImpl::GetLoadingPrincipal(nsIPrincipal** aPrincipal) {
// We are at the top. Let's see if we have an opener window.
if (innerWindow == currentInnerWindow) {
- ErrorResult error;
- parentWindow =
- nsGlobalWindowInner::Cast(innerWindow)->GetOpenerWindow(error);
- if (NS_WARN_IF(error.Failed())) {
- error.SuppressException();
- return NS_ERROR_DOM_SECURITY_ERR;
- }
-
+ parentWindow = nsGlobalWindowOuter::Cast(innerWindow->GetOuterWindow())
+ ->GetSameProcessOpener();
if (!parentWindow) {
break;
}
diff --git a/js/src/jit-test/tests/ctypes/conversion-to-number.js b/js/src/jit-test/tests/ctypes/conversion-to-number.js
new file mode 100644
index 000000000000..6a334ecf3aeb
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/conversion-to-number.js
@@ -0,0 +1,98 @@
+// Type conversion to number should use ECMA-style semantics.
+
+load(libdir + 'asserts.js');
+
+function test() {
+ function checkValue(type, provided, expected) {
+ assertEq(ctypes[type](provided).value, expected,
+ `ctypes.${type}(${provided}) contains unexpected value`);
+ }
+
+ function checkCantConvert(type, value) {
+ var ctor = ctypes[type];
+ assertTypeErrorMessage(() => ctor(value),
+ /can't convert the number/);
+ }
+
+ let testInt8 = checkValue.bind(undefined, "int8_t");
+ let testInt8Throws = checkCantConvert.bind(undefined, "int8_t");
+ testInt8(1e100, 0);
+ testInt8Throws(-129);
+ testInt8(-128, -128);
+ testInt8(-1, -1);
+ testInt8(0, 0);
+ testInt8(1, 1);
+ testInt8(127, 127);
+ testInt8Throws(128);
+
+ let testUint8 = checkValue.bind(undefined, "uint8_t");
+ let testUint8Throws = checkCantConvert.bind(undefined, "uint8_t");
+ testUint8(1e100, 0);
+ testUint8Throws(-1);
+ testUint8(0, 0);
+ testUint8(1, 1);
+ testUint8(127, 127);
+ testUint8(128, 128);
+ testUint8(255, 255);
+ testUint8Throws(256);
+
+ let testInt16 = checkValue.bind(undefined, "int16_t");
+ let testInt16Throws = checkCantConvert.bind(undefined, "int16_t");
+ testInt16(1e100, 0);
+ testInt16Throws(-32769);
+ testInt16(-32768, -32768);
+ testInt16(-1, -1);
+ testInt16(0, 0);
+ testInt16(1, 1);
+ testInt16(32767, 32767);
+ testInt16Throws(32768);
+
+ let testUint16 = checkValue.bind(undefined, "uint16_t");
+ let testUint16Throws = checkCantConvert.bind(undefined, "uint16_t");
+ testUint16(1e100, 0);
+ testUint16Throws(-1);
+ testUint16(0, 0);
+ testUint16(1, 1);
+ testUint16(32767, 32767);
+ testUint16(32768, 32768);
+ testUint16(65535, 65535);
+ testUint16Throws(65536);
+
+ let testInt32 = checkValue.bind(undefined, "int32_t");
+ let testInt32Throws = checkCantConvert.bind(undefined, "int32_t");
+ testInt32(1e100, 0);
+ // This probably should pass, but right now doubles fall into a different
+ // code path where no error occurs. ctypes is probably/hopefully declining in
+ // use now, so just don't bother with this test.
+ //testInt32Throws(-2147483649);
+ testInt32(-2147483648, -2147483648);
+ testInt32(-1, -1);
+ testInt32(0, 0);
+ testInt32(1, 1);
+ testInt32(2147483647, 2147483647);
+ // This probably should pass, but right now doubles fall into a different
+ // code path where no error occurs. ctypes is probably/hopefully declining in
+ // use now, so just don't bother with this test.
+ //testInt32Throws(2147483648);
+
+ let testUint32 = checkValue.bind(undefined, "uint32_t");
+ let testUint32Throws = checkCantConvert.bind(undefined, "uint32_t");
+ testUint32(1e100, 0);
+ testUint32Throws(-1);
+ // This probably should pass, but right now doubles fall into a different
+ // code path where no error occurs. ctypes is probably/hopefully declining in
+ // use now, so just don't bother with this test.
+ //testUint32Throws(-1 * Math.cos(Math.PI)); // -1.0 encoded as a double
+ testUint32(0, 0);
+ testUint32(1, 1);
+ testUint32(2147483647, 2147483647);
+ testUint32(2147483648, 2147483648);
+ testUint32(4294967295, 4294967295);
+ // This probably should pass, but right now doubles fall into a different
+ // code path where no error occurs. ctypes is probably/hopefully declining in
+ // use now, so just don't bother with this test.
+ //testUint32Throws(4294967296);
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/toolkit/components/extensions/test/mochitest/mochitest-common.ini b/toolkit/components/extensions/test/mochitest/mochitest-common.ini
index f991466a5161..b4d30d71e017 100644
--- a/toolkit/components/extensions/test/mochitest/mochitest-common.ini
+++ b/toolkit/components/extensions/test/mochitest/mochitest-common.ini
@@ -85,7 +85,6 @@ skip-if = (!debug && android_version == '18') #Bug 1523193
skip-if = os == 'android' # Android does not support multiple windows.
[test_ext_contentscript_permission.html]
[test_ext_cookies.html]
-fail-if = fission
[test_ext_cookies_containers.html]
[test_ext_cookies_expiry.html]
[test_ext_cookies_first_party.html]
diff --git a/toolkit/components/windowwatcher/nsWindowWatcher.cpp b/toolkit/components/windowwatcher/nsWindowWatcher.cpp
index 2b9175b55e58..ed6fb81336d9 100644
--- a/toolkit/components/windowwatcher/nsWindowWatcher.cpp
+++ b/toolkit/components/windowwatcher/nsWindowWatcher.cpp
@@ -951,10 +951,19 @@ nsresult nsWindowWatcher::OpenWindowInternal(
newDocShell->SetSandboxFlags(activeDocsSandboxFlags);
}
- nsCOMPtr win(newBC->GetDOMWindow());
+ RefPtr win(
+ nsGlobalWindowOuter::Cast(newBC->GetDOMWindow()));
if (win) {
if (!aForceNoOpener) {
- win->SetOpenerWindow(parentWindow, windowIsNew);
+ if (windowIsNew) {
+ // If this is a new window, its opener should have been set when its
+ // BrowsingContext was created. If not, we need to set it ourselves.
+ MOZ_DIAGNOSTIC_ASSERT(newBC->GetOpenerId() ==
+ (parentBC ? parentBC->Id() : 0));
+ MOZ_DIAGNOSTIC_ASSERT(!!parentBC == newBC->HadOriginalOpener());
+ } else {
+ newBC->SetOpener(parentBC);
+ }
} else if (parentWindow && parentWindow != win) {
MOZ_ASSERT(
win->TabGroup() != parentWindow->TabGroup(),
@@ -1069,7 +1078,7 @@ nsresult nsWindowWatcher::OpenWindowInternal(
// SetInitialPrincipalToSubject is safe to call multiple times.
if (win) {
nsCOMPtr cspToInheritForAboutBlank;
- nsCOMPtr targetOpener = win->GetOpener();
+ nsCOMPtr targetOpener = win->GetSameProcessOpener();
nsCOMPtr openerDocShell(do_GetInterface(targetOpener));
if (openerDocShell) {
RefPtr openerDoc =
@@ -1079,13 +1088,12 @@ nsresult nsWindowWatcher::OpenWindowInternal(
win->SetInitialPrincipalToSubject(cspToInheritForAboutBlank);
if (aIsPopupSpam) {
- auto* globalWin = nsGlobalWindowOuter::Cast(win);
- MOZ_ASSERT(!globalWin->IsPopupSpamWindow(),
+ MOZ_ASSERT(!win->IsPopupSpamWindow(),
"Who marked it as popup spam already???");
- if (!globalWin->IsPopupSpamWindow()) { // Make sure we don't mess up
- // our counter even if the above
- // assert fails.
- globalWin->SetIsPopupSpamWindow(true);
+ if (!win->IsPopupSpamWindow()) { // Make sure we don't mess up
+ // our counter even if the above
+ // assert fails.
+ win->SetIsPopupSpamWindow(true);
}
}
}
@@ -1162,7 +1170,8 @@ nsresult nsWindowWatcher::OpenWindowInternal(
nsCOMPtr obsSvc =
mozilla::services::GetObserverService();
if (obsSvc) {
- obsSvc->NotifyObservers(win, "toplevel-window-ready", nullptr);
+ obsSvc->NotifyObservers(ToSupports(win), "toplevel-window-ready",
+ nullptr);
}
}
diff --git a/widget/gtk/WindowSurfaceWayland.cpp b/widget/gtk/WindowSurfaceWayland.cpp
index 91c6589b7409..db17a3a84fea 100644
--- a/widget/gtk/WindowSurfaceWayland.cpp
+++ b/widget/gtk/WindowSurfaceWayland.cpp
@@ -189,7 +189,7 @@ It owns wl_buffer object, owns WaylandDMABufSurface
(which provides the DMA Buffer) and ties them together.
WindowBackBufferDMABuf backend is used only when WaylandDMABufSurface is
-available and gfx.wayland_dmabuf_backend.enabled preference is set.
+available and widget.wayland_dmabuf_backend.enabled preference is set.
*/
@@ -504,6 +504,8 @@ WindowSurfaceWayland::WindowSurfaceWayland(nsWindow* aWindow)
mIsMainThread(NS_IsMainThread()),
mNeedScaleFactorUpdate(true) {
for (int i = 0; i < BACK_BUFFER_NUM; i++) mBackupBuffer[i] = nullptr;
+ mRenderingCacheMode = static_cast(
+ mWaylandDisplay->GetRenderingCacheModePref());
}
WindowSurfaceWayland::~WindowSurfaceWayland() {
@@ -810,10 +812,12 @@ already_AddRefed WindowSurfaceWayland::Lock(
mBufferScreenRect = lockedScreenRect;
}
- if (mWholeWindowBufferDamage) {
+ if (mWholeWindowBufferDamage || mRenderingCacheMode != CACHE_ALL) {
// We can lock/commit entire buffer direcly.
mDrawToWaylandBufferDirectly = true;
+ }
+ if (mDrawToWaylandBufferDirectly) {
// If there's any pending image commit scratch them as we're going
// to redraw the whole sceen anyway.
mDelayedImageCommits.Clear();
@@ -821,10 +825,29 @@ already_AddRefed WindowSurfaceWayland::Lock(
RefPtr dt = LockWaylandBuffer(
/* aCanSwitchBuffer */ mWholeWindowBufferDamage);
if (dt) {
+ // TODO: Try to set clip regions according to given area provided by
+ // compositor, not sure it has any effect. Also disable when drawing
+ // without any cache to speed up rendering.
+ if (!mWholeWindowBufferDamage && mRenderingCacheMode != CACHE_NONE) {
+ uint32_t numRects = aRegion.GetNumRects();
+ if (numRects != 1) {
+ AutoTArray rects;
+ rects.SetCapacity(numRects);
+ for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) {
+ rects.AppendElement(iter.Get().ToUnknownRect());
+ }
+ dt->PushDeviceSpaceClipRects(rects.Elements(), rects.Length());
+ }
+ }
return dt.forget();
}
}
+ // Any caching is disabled and we don't have any back buffer available.
+ if (mRenderingCacheMode == CACHE_NONE) {
+ return nullptr;
+ }
+
// We do indirect drawing due to:
//
// 1) We don't have any front buffer available. Try indirect drawing
diff --git a/widget/gtk/WindowSurfaceWayland.h b/widget/gtk/WindowSurfaceWayland.h
index a0c5f1889a62..cab054f93770 100644
--- a/widget/gtk/WindowSurfaceWayland.h
+++ b/widget/gtk/WindowSurfaceWayland.h
@@ -175,6 +175,21 @@ class WindowSurfaceWayland : public WindowSurface {
void FrameCallbackHandler();
void DelayedCommitHandler();
+ // Image cache mode can be set by widget.wayland_cache_mode
+ typedef enum {
+ // Cache and clip all drawings, default. It's slowest
+ // but also without any rendered artifacts.
+ CACHE_ALL = 0,
+ // Cache drawing only when back buffer is missing. May produce
+ // some rendering artifacts and flickering when partial screen update
+ // is rendered.
+ CACHE_MISSING = 1,
+ // Don't cache anything, draw only when back buffer is available.
+ // Suitable for fullscreen content only like fullscreen video playback and
+ // may work well with dmabuf backend.
+ CACHE_NONE = 2
+ } RenderingCacheMode;
+
private:
WindowBackBuffer* CreateWaylandBuffer(int aWidth, int aHeight);
WindowBackBuffer* GetWaylandBufferToDraw(bool aCanSwitchBuffer);
@@ -215,6 +230,7 @@ class WindowSurfaceWayland : public WindowSurface {
bool mBufferNeedsClear;
bool mIsMainThread;
bool mNeedScaleFactorUpdate;
+ RenderingCacheMode mRenderingCacheMode;
static bool UseDMABufBackend();
static bool mUseDMABufInitialized;
diff --git a/widget/gtk/nsWaylandDisplay.cpp b/widget/gtk/nsWaylandDisplay.cpp
index c76a304da21c..74a52845adcd 100644
--- a/widget/gtk/nsWaylandDisplay.cpp
+++ b/widget/gtk/nsWaylandDisplay.cpp
@@ -13,10 +13,15 @@ namespace widget {
#define GBMLIB_NAME "libgbm.so.1"
#define DRMLIB_NAME "libdrm.so.2"
+#define DMABUF_PREF "widget.wayland_dmabuf_backend.enabled"
+// See WindowSurfaceWayland::RenderingCacheMode for details.
+#define CACHE_MODE_PREF "widget.wayland_cache_mode"
+
bool nsWaylandDisplay::mIsDMABufEnabled = false;
// -1 mean the pref was not loaded yet
int nsWaylandDisplay::mIsDMABufPrefState = -1;
bool nsWaylandDisplay::mIsDMABufConfigured = false;
+int nsWaylandDisplay::mRenderingCacheModePref = -1;
wl_display* WaylandDisplayGetWLDisplay(GdkDisplay* aGdkDisplay) {
if (!aGdkDisplay) {
@@ -317,14 +322,15 @@ nsWaylandDisplay::nsWaylandDisplay(wl_display* aDisplay)
wl_registry_add_listener(mRegistry, ®istry_listener, this);
if (NS_IsMainThread()) {
- // We can't load the preference from compositor/render thread,
- // only from main one. So we can't call it directly from
- // nsWaylandDisplay::IsDMABufEnabled() as it can be called from various
- // threads.
+ // We can't load the preference from compositor/render thread
+ // so load all Wayland prefs here.
if (mIsDMABufPrefState == -1) {
- mIsDMABufPrefState =
- Preferences::GetBool("widget.wayland_dmabuf_backend.enabled", false);
+ mIsDMABufPrefState = Preferences::GetBool(DMABUF_PREF, false);
}
+ if (mRenderingCacheModePref == -1) {
+ mRenderingCacheModePref = Preferences::GetInt(CACHE_MODE_PREF, 0);
+ }
+
// Use default event queue in main thread operated by Gtk+.
mEventQueue = nullptr;
wl_display_roundtrip(mDisplay);
diff --git a/widget/gtk/nsWaylandDisplay.h b/widget/gtk/nsWaylandDisplay.h
index aae01bc168eb..ecf530608d26 100644
--- a/widget/gtk/nsWaylandDisplay.h
+++ b/widget/gtk/nsWaylandDisplay.h
@@ -77,6 +77,9 @@ class nsWaylandDisplay {
uint32_t mModifierLo);
static bool IsDMABufEnabled();
+ // See WindowSurfaceWayland::CacheMode for details.
+ int GetRenderingCacheModePref() { return mRenderingCacheModePref; };
+
private:
bool ConfigureGbm();
@@ -100,6 +103,7 @@ class nsWaylandDisplay {
static bool mIsDMABufEnabled;
static int mIsDMABufPrefState;
static bool mIsDMABufConfigured;
+ static int mRenderingCacheModePref;
};
void WaylandDispatchDisplays();
diff --git a/xpfe/appshell/nsWebShellWindow.cpp b/xpfe/appshell/nsWebShellWindow.cpp
index 492dea155bd0..06d082b2980f 100644
--- a/xpfe/appshell/nsWebShellWindow.cpp
+++ b/xpfe/appshell/nsWebShellWindow.cpp
@@ -210,11 +210,15 @@ nsresult nsWebShellWindow::Initialize(
nsIWebProgress::NOTIFY_STATE_NETWORK);
}
+#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
if (aOpenerWindow) {
- nsPIDOMWindowOuter* window = mDocShell->GetWindow();
- MOZ_ASSERT(window);
- window->SetOpenerWindow(nsPIDOMWindowOuter::From(aOpenerWindow), true);
+ BrowsingContext* bc = mDocShell->GetBrowsingContext();
+ BrowsingContext* openerBC =
+ nsPIDOMWindowOuter::From(aOpenerWindow)->GetBrowsingContext();
+ MOZ_DIAGNOSTIC_ASSERT(bc->GetOpenerId() == openerBC->Id());
+ MOZ_DIAGNOSTIC_ASSERT(bc->HadOriginalOpener());
}
+#endif
// Eagerly create an about:blank content viewer with the right principal here,
// rather than letting it happening in the upcoming call to