diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp index aa8aff6ae..06ea7c2c1 100644 --- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -17,6 +17,7 @@ #include "mozilla/HashFunctions.h" #include "mozilla/MathAlgorithms.h" +#include "nsISVGChildFrame.h" #include "nsStyleConsts.h" #include "nsPresContext.h" #include "nsIFrame.h" @@ -4806,8 +4807,13 @@ nsImageRenderer::PrepareImage() mImageElementSurface = nsLayoutUtils::SurfaceFromElement(property->GetReferencedElement()); if (!mImageElementSurface.GetSourceSurface()) { - mPaintServerFrame = property->GetReferencedFrame(); - if (!mPaintServerFrame) { + nsIFrame* paintServerFrame = property->GetReferencedFrame(); + // If there's no referenced frame, or the referenced frame is + // non-displayable SVG, then we have nothing valid to paint. + if (!paintServerFrame || + (paintServerFrame->IsFrameOfType(nsIFrame::eSVG) && + !paintServerFrame->IsFrameOfType(nsIFrame::eSVGPaintServer) && + !static_cast(do_QueryFrame(paintServerFrame)))) { mPrepareResult = DrawResult::BAD_IMAGE; return false; } diff --git a/layout/svg/nsSVGIntegrationUtils.cpp b/layout/svg/nsSVGIntegrationUtils.cpp index 0d88bede3..5dd556792 100644 --- a/layout/svg/nsSVGIntegrationUtils.cpp +++ b/layout/svg/nsSVGIntegrationUtils.cpp @@ -788,6 +788,15 @@ nsSVGIntegrationUtils::DrawableFromPaintServer(nsIFrame* aFrame, return drawable.forget(); } +#if DEBUG + if (aFrame->IsFrameOfType(nsIFrame::eSVG) && + !static_cast(do_QueryFrame(aFrame))) { + MOZ_ASSERT_UNREACHABLE("We should prevent painting of unpaintable SVG " + "before we get here"); + return nullptr; + } +#endif + // We don't want to paint into a surface as long as we don't need to, so we // set up a drawing callback. RefPtr cb = diff --git a/toolkit/components/prompts/src/nsPrompter.js b/toolkit/components/prompts/src/nsPrompter.js index 2fa1b19d2..cb714d82a 100644 --- a/toolkit/components/prompts/src/nsPrompter.js +++ b/toolkit/components/prompts/src/nsPrompter.js @@ -371,6 +371,10 @@ function openTabPrompt(domWin, tabPrompt, args) { .getInterface(Ci.nsIDOMWindowUtils); winUtils.enterModalState(); + let frameMM = docShell.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIContentFrameMessageManager); + frameMM.QueryInterface(Ci.nsIDOMEventTarget); + // We provide a callback so the prompt can close itself. We don't want to // wait for this event loop to return... Otherwise the presence of other // prompts on the call stack would in this dialog appearing unresponsive @@ -384,16 +388,25 @@ function openTabPrompt(domWin, tabPrompt, args) { if (newPrompt) tabPrompt.removePrompt(newPrompt); - domWin.removeEventListener("pagehide", pagehide); + frameMM.removeEventListener("pagehide", pagehide, true); winUtils.leaveModalState(); PromptUtils.fireDialogEvent(domWin, "DOMModalDialogClosed"); } - domWin.addEventListener("pagehide", pagehide); - function pagehide() { - domWin.removeEventListener("pagehide", pagehide); + frameMM.addEventListener("pagehide", pagehide, true); + function pagehide(e) { + // Check whether the event relates to our window or its ancestors + let window = domWin; + let eventWindow = e.target.defaultView; + while (window != eventWindow && window.parent != window) { + window = window.parent; + } + if (window != eventWindow) { + return; + } + frameMM.removeEventListener("pagehide", pagehide, true); if (newPrompt) { newPrompt.abortPrompt(); @@ -442,6 +455,9 @@ function openRemotePrompt(domWin, args, tabPrompt) { winUtils.enterModalState(); let closed = false; + let frameMM = docShell.getInterface(Ci.nsIContentFrameMessageManager); + frameMM.QueryInterface(Ci.nsIDOMEventTarget); + // It should be hard or impossible to cause a window to create multiple // prompts, but just in case, give our prompt an ID. let id = "id" + Cc["@mozilla.org/uuid-generator;1"] @@ -453,7 +469,7 @@ function openRemotePrompt(domWin, args, tabPrompt) { } messageManager.removeMessageListener("Prompt:Close", listener); - domWin.removeEventListener("pagehide", pagehide); + frameMM.removeEventListener("pagehide", pagehide, true); winUtils.leaveModalState(); PromptUtils.fireDialogEvent(domWin, "DOMModalDialogClosed"); @@ -470,9 +486,18 @@ function openRemotePrompt(domWin, args, tabPrompt) { closed = true; }); - domWin.addEventListener("pagehide", pagehide); - function pagehide() { - domWin.removeEventListener("pagehide", pagehide); + frameMM.addEventListener("pagehide", pagehide, true); + function pagehide(e) { + // Check whether the event relates to our window or its ancestors + let window = domWin; + let eventWindow = e.target.defaultView; + while (window != eventWindow && window.parent != window) { + window = window.parent; + } + if (window != eventWindow) { + return; + } + frameMM.removeEventListener("pagehide", pagehide, true); messageManager.sendAsyncMessage("Prompt:ForceClose", { _remoteId: id }); }