зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-inbound to mozilla-central. a=merge
This commit is contained in:
Коммит
e8f334670d
|
@ -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");
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
<commandset id="pageInfoCommandSet">
|
||||
<command id="cmd_close" oncommand="window.close();"/>
|
||||
<command id="cmd_help" oncommand="doHelpButton();"/>
|
||||
<command id="cmd_copy" oncommand="doCopy();"/>
|
||||
<command id="cmd_selectall" oncommand="doSelectAll();"/>
|
||||
</commandset>
|
||||
|
||||
|
@ -58,12 +59,14 @@
|
|||
#else
|
||||
<key keycode="VK_F1" command="cmd_help"/>
|
||||
#endif
|
||||
<key data-l10n-id="copy" data-l10n-attrs="key" modifiers="accel" command="cmd_copy"/>
|
||||
<key data-l10n-id="select-all" data-l10n-attrs="key" modifiers="accel" command="cmd_selectall"/>
|
||||
<key data-l10n-id="select-all" data-l10n-attrs="key" modifiers="alt" command="cmd_selectall"/>
|
||||
</keyset>
|
||||
|
||||
<menupopup id="picontext">
|
||||
<menuitem id="menu_selectall" data-l10n-id="menu-select-all" command="cmd_selectall"/>
|
||||
<menuitem id="menu_copy" data-l10n-id="menu-copy" command="cmd_copy"/>
|
||||
</menupopup>
|
||||
|
||||
<vbox id="topBar">
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -132,7 +132,10 @@ already_AddRefed<BrowsingContext> 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;
|
||||
|
|
|
@ -209,13 +209,22 @@ class BrowsingContext : public nsWrapperCache, public BrowsingContextBase {
|
|||
|
||||
BrowsingContext* Top();
|
||||
|
||||
already_AddRefed<BrowsingContext> GetOpener() const { return Get(mOpenerId); }
|
||||
already_AddRefed<BrowsingContext> GetOpener() const {
|
||||
RefPtr<BrowsingContext> 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<nsIDocShell> GetDocShell() override {
|
||||
return nullptr;
|
||||
}
|
||||
already_AddRefed<nsIDocShell> GetDocShell() override { return nullptr; }
|
||||
};
|
||||
|
||||
// Ensure that opener is in the same BrowsingContextGroup.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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<nsPIDOMWindowOuter> opener = window->GetOpener();
|
||||
nsCOMPtr<nsPIDOMWindowOuter> 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.
|
||||
|
|
|
@ -14863,12 +14863,12 @@ void Document::MaybeAllowStorageForOpenerAfterUserInteraction() {
|
|||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowOuter> outer = inner->GetOuterWindow();
|
||||
auto* outer = nsGlobalWindowOuter::Cast(inner->GetOuterWindow());
|
||||
if (NS_WARN_IF(!outer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowOuter> outerOpener = outer->GetOpener();
|
||||
nsCOMPtr<nsPIDOMWindowOuter> outerOpener = outer->GetSameProcessOpener();
|
||||
if (!outerOpener) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -2084,12 +2084,6 @@ nsresult nsFrameLoader::MaybeCreateDocShell() {
|
|||
|
||||
newWindow->SetFrameElementInternal(mOwnerContent);
|
||||
|
||||
// TODO(farre): Remove this when nsGlobalWindowOuter::GetOpenerWindowOuter
|
||||
// starts using BrowsingContext::GetOpener.
|
||||
if (RefPtr<BrowsingContext> 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,
|
||||
|
|
|
@ -3034,27 +3034,33 @@ nsresult nsGlobalWindowInner::GetControllers(nsIControllers** aResult) {
|
|||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
nsPIDOMWindowOuter* nsGlobalWindowInner::GetOpenerWindow(ErrorResult& aError) {
|
||||
Nullable<WindowProxyHolder> nsGlobalWindowInner::GetOpenerWindow(
|
||||
ErrorResult& aError) {
|
||||
FORWARD_TO_OUTER_OR_THROW(GetOpenerWindowOuter, (), aError, nullptr);
|
||||
}
|
||||
|
||||
void nsGlobalWindowInner::GetOpener(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aRetval,
|
||||
ErrorResult& aError) {
|
||||
nsCOMPtr<nsPIDOMWindowOuter> opener = GetOpenerWindow(aError);
|
||||
if (aError.Failed() || !opener) {
|
||||
Nullable<WindowProxyHolder> 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<JS::Value> aOpener,
|
||||
ErrorResult& aError) {
|
||||
if (aOpener.isNull()) {
|
||||
FORWARD_TO_OUTER_VOID(SetOpenerWindow, (nullptr, false));
|
||||
RefPtr<BrowsingContext> bc(GetBrowsingContext());
|
||||
if (!bc->IsDiscarded()) {
|
||||
bc->SetOpener(nullptr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -622,7 +622,8 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
|
|||
void InitWasOffline();
|
||||
|
||||
public:
|
||||
nsPIDOMWindowOuter* GetOpenerWindow(mozilla::ErrorResult& aError);
|
||||
mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder> GetOpenerWindow(
|
||||
mozilla::ErrorResult& aError);
|
||||
void GetOpener(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval,
|
||||
mozilla::ErrorResult& aError);
|
||||
void SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
|
||||
|
|
|
@ -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<BrowsingContext>
|
||||
nsGlobalWindowOuter::GetOpenerBrowsingContext() {
|
||||
RefPtr<BrowsingContext> 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<nsIDocShell> openerDocShell = aOpener->GetDocShell();
|
||||
|
||||
if (openerDocShell) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> openerRootItem;
|
||||
openerDocShell->GetInProcessRootTreeItem(getter_AddRefs(openerRootItem));
|
||||
nsCOMPtr<nsIDocShell> 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<BrowsingContext> opener = GetOpenerBrowsingContext()) {
|
||||
return opener->GetDOMWindow();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsPIDOMWindowOuter* nsGlobalWindowOuter::GetOpenerWindowOuter() {
|
||||
nsCOMPtr<nsPIDOMWindowOuter> opener = do_QueryReferent(mOpener);
|
||||
|
||||
if (!opener) {
|
||||
return nullptr;
|
||||
Nullable<WindowProxyHolder> nsGlobalWindowOuter::GetOpenerWindowOuter() {
|
||||
if (RefPtr<BrowsingContext> 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<nsPIDOMWindowOuter> nsGlobalWindowOuter::GetOpener() {
|
||||
nsCOMPtr<nsPIDOMWindowOuter> opener = GetOpenerWindowOuter();
|
||||
return opener.forget();
|
||||
Nullable<WindowProxyHolder> 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<nsPIDOMWindowInner> caller = do_QueryInterface(GetEntryGlobal());
|
||||
nsPIDOMWindowOuter* callerOuter = caller ? caller->GetOuterWindow() : nullptr;
|
||||
nsCOMPtr<nsPIDOMWindowOuter> opener = GetOpener();
|
||||
BrowsingContext* callerBC =
|
||||
callerOuter ? callerOuter->GetBrowsingContext() : nullptr;
|
||||
RefPtr<BrowsingContext> 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<nsPIDOMWindowOuter> piOpener = do_QueryReferent(mOpener);
|
||||
nsPIDOMWindowOuter* opener = GetSanitizedOpener(piOpener);
|
||||
RefPtr<BrowsingContext> 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<nsPIDOMWindowOuter> parent = GetInProcessScriptableParentOrNull();
|
||||
MOZ_ASSERT_IF(parent, parent->TabGroup() == mTabGroup);
|
||||
nsCOMPtr<nsPIDOMWindowOuter> piOpener = do_QueryReferent(mOpener);
|
||||
nsPIDOMWindowOuter* opener = GetSanitizedOpener(piOpener);
|
||||
MOZ_ASSERT_IF(opener && nsGlobalWindowOuter::Cast(opener) != this,
|
||||
|
||||
RefPtr<BrowsingContext> openerBC = GetBrowsingContext()->GetOpener();
|
||||
nsPIDOMWindowOuter* opener =
|
||||
openerBC ? openerBC->GetDOMWindow() : nullptr;
|
||||
MOZ_ASSERT_IF(opener && Cast(opener) != this,
|
||||
opener->TabGroup() == mTabGroup);
|
||||
}
|
||||
mIsValidatingTabGroup = false;
|
||||
|
|
|
@ -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<mozilla::ThrottledEventQueue> mPostMessageEventQueue;
|
||||
|
||||
protected:
|
||||
nsPIDOMWindowOuter* GetOpenerWindowOuter();
|
||||
mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder>
|
||||
GetOpenerWindowOuter();
|
||||
// Initializes the mWasOffline member variable
|
||||
void InitWasOffline();
|
||||
|
||||
public:
|
||||
nsPIDOMWindowOuter* GetSanitizedOpener(nsPIDOMWindowOuter* aOpener);
|
||||
|
||||
already_AddRefed<nsPIDOMWindowOuter> GetOpener() override;
|
||||
nsPIDOMWindowOuter* GetSameProcessOpener();
|
||||
already_AddRefed<mozilla::dom::BrowsingContext> GetOpenerBrowsingContext();
|
||||
mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder> GetOpener() override;
|
||||
mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder> GetParentOuter();
|
||||
already_AddRefed<nsPIDOMWindowOuter> 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<nsIScriptContext> mContext;
|
||||
nsWeakPtr mOpener;
|
||||
nsCOMPtr<nsIControllers> mControllers;
|
||||
|
||||
// For |window.arguments|, via |openDialog|.
|
||||
|
|
|
@ -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<mozilla::dom::Selection> GetSelection() = 0;
|
||||
virtual already_AddRefed<nsPIDOMWindowOuter> GetOpener() = 0;
|
||||
virtual mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder>
|
||||
GetOpener() = 0;
|
||||
|
||||
// aLoadState will be passed on through to the windowwatcher.
|
||||
// aForceNoOpener will act just like a "noopener" feature in aOptions except
|
||||
|
|
|
@ -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> tabGroup;
|
||||
RefPtr<BrowsingContext> 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<BrowsingContext> openerBC =
|
||||
aParent ? nsPIDOMWindowOuter::From(aParent)->GetBrowsingContext()
|
||||
: nullptr;
|
||||
RefPtr<BrowsingContext> 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<mozIDOMWindowProxy> 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<nsPIDOMWindowOuter> 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.
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
|
@ -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]
|
||||
|
|
|
@ -951,10 +951,19 @@ nsresult nsWindowWatcher::OpenWindowInternal(
|
|||
newDocShell->SetSandboxFlags(activeDocsSandboxFlags);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowOuter> win(newBC->GetDOMWindow());
|
||||
RefPtr<nsGlobalWindowOuter> 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<nsIContentSecurityPolicy> cspToInheritForAboutBlank;
|
||||
nsCOMPtr<mozIDOMWindowProxy> targetOpener = win->GetOpener();
|
||||
nsCOMPtr<mozIDOMWindowProxy> targetOpener = win->GetSameProcessOpener();
|
||||
nsCOMPtr<nsIDocShell> openerDocShell(do_GetInterface(targetOpener));
|
||||
if (openerDocShell) {
|
||||
RefPtr<Document> 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<nsIObserverService> obsSvc =
|
||||
mozilla::services::GetObserverService();
|
||||
if (obsSvc) {
|
||||
obsSvc->NotifyObservers(win, "toplevel-window-ready", nullptr);
|
||||
obsSvc->NotifyObservers(ToSupports(win), "toplevel-window-ready",
|
||||
nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<RenderingCacheMode>(
|
||||
mWaylandDisplay->GetRenderingCacheModePref());
|
||||
}
|
||||
|
||||
WindowSurfaceWayland::~WindowSurfaceWayland() {
|
||||
|
@ -810,10 +812,12 @@ already_AddRefed<gfx::DrawTarget> 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<gfx::DrawTarget> WindowSurfaceWayland::Lock(
|
|||
RefPtr<gfx::DrawTarget> 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<IntRect, 32> 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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче