Bug 1560400: Part 1 - Support remote frames in Window indexed getters. r=nika

Differential Revision: https://phabricator.services.mozilla.com/D35471

--HG--
extra : rebase_source : b326799f8ced75068f7e7fec6edbd39455cdb9b1
extra : source : 84633034590f2d1a4c336f9653e6c542f3a09039
This commit is contained in:
Kris Maglione 2019-06-20 13:52:55 -07:00
Родитель c98e734fe6
Коммит f180f12646
19 изменённых файлов: 136 добавлений и 304 удалений

Просмотреть файл

@ -16,7 +16,6 @@
#include "nsQueryObject.h"
#include "mozilla/dom/URL.h"
#include "nsDOMWindowList.h"
#include "nsIConsoleService.h"
#include "mozilla/dom/Document.h"
#include "nsIDOMWindow.h"

Просмотреть файл

@ -9,7 +9,6 @@
#include "mozilla/dom/WindowBinding.h"
#include "mozilla/dom/WindowProxyHolder.h"
#include "nsContentUtils.h"
#include "nsDOMWindowList.h"
#include "nsGlobalWindow.h"
#include "nsHTMLDocument.h"
#include "nsJSUtils.h"
@ -18,7 +17,7 @@
namespace mozilla {
namespace dom {
static bool ShouldExposeChildWindow(nsString& aNameBeingResolved,
static bool ShouldExposeChildWindow(const nsString& aNameBeingResolved,
BrowsingContext* aChild) {
nsPIDOMWindowOuter* child = aChild->GetDOMWindow();
Element* e = child->GetFrameElementInternal();
@ -169,23 +168,12 @@ bool WindowNamedPropertiesHandler::ownPropNames(
// The names live on the outer window, which might be null
nsGlobalWindowOuter* outer = win->GetOuterWindowInternal();
if (outer) {
nsDOMWindowList* childWindows = outer->GetFrames();
if (childWindows) {
uint32_t length = childWindows->GetLength();
for (uint32_t i = 0; i < length; ++i) {
nsCOMPtr<nsIDocShellTreeItem> item =
childWindows->GetDocShellTreeItemAt(i);
// This is a bit silly, since we could presumably just do
// item->GetWindow(). But it's not obvious whether this does the same
// thing as GetChildWindow() with the item's name (due to the complexity
// of FindChildWithName). Since GetChildWindow is what we use in
// getOwnPropDescriptor, let's try to be consistent.
nsString name;
item->GetName(name);
if (!names.Contains(name)) {
if (BrowsingContext* bc = outer->GetBrowsingContext()) {
for (const auto& child : bc->GetChildren()) {
const nsString& name = child->Name();
if (!name.IsEmpty() && !names.Contains(name)) {
// Make sure we really would expose it from getOwnPropDescriptor.
RefPtr<BrowsingContext> child = win->GetChildWindow(name);
if (child && ShouldExposeChildWindow(name, child)) {
if (ShouldExposeChildWindow(name, child)) {
names.AppendElement(name);
}
}

Просмотреть файл

@ -336,7 +336,6 @@ UNIFIED_SOURCES += [
'nsDOMNavigationTiming.cpp',
'nsDOMSerializer.cpp',
'nsDOMTokenList.cpp',
'nsDOMWindowList.cpp',
'nsFocusManager.cpp',
'nsFrameLoader.cpp',
'nsFrameLoaderOwner.cpp',

Просмотреть файл

@ -1,82 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsDOMWindowList.h"
#include "FlushType.h"
#include "nsCOMPtr.h"
#include "mozilla/dom/Document.h"
#include "nsIDOMWindow.h"
#include "nsIDocShell.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIScriptGlobalObject.h"
#include "nsIWebNavigation.h"
using namespace mozilla;
nsDOMWindowList::nsDOMWindowList(nsIDocShell* aDocShell) {
SetDocShell(aDocShell);
}
nsDOMWindowList::~nsDOMWindowList() {}
void nsDOMWindowList::SetDocShell(nsIDocShell* aDocShell) {
mDocShellNode = aDocShell; // Weak Reference
}
void nsDOMWindowList::EnsureFresh() {
nsCOMPtr<nsIWebNavigation> shellAsNav = do_QueryInterface(mDocShellNode);
if (shellAsNav) {
nsCOMPtr<dom::Document> doc;
shellAsNav->GetDocument(getter_AddRefs(doc));
if (doc) {
doc->FlushPendingNotifications(FlushType::ContentAndNotify);
}
}
}
uint32_t nsDOMWindowList::GetLength() {
EnsureFresh();
NS_ENSURE_TRUE(mDocShellNode, 0);
int32_t length;
nsresult rv = mDocShellNode->GetChildCount(&length);
NS_ENSURE_SUCCESS(rv, 0);
return uint32_t(length);
}
already_AddRefed<nsPIDOMWindowOuter> nsDOMWindowList::IndexedGetter(
uint32_t aIndex) {
nsCOMPtr<nsIDocShellTreeItem> item = GetDocShellTreeItemAt(aIndex);
if (!item) {
return nullptr;
}
nsCOMPtr<nsPIDOMWindowOuter> window = item->GetWindow();
MOZ_ASSERT(window);
return window.forget();
}
already_AddRefed<nsPIDOMWindowOuter> nsDOMWindowList::NamedItem(
const nsAString& aName) {
EnsureFresh();
if (!mDocShellNode) {
return nullptr;
}
nsCOMPtr<nsIDocShellTreeItem> item;
mDocShellNode->FindChildWithName(aName, false, false, nullptr, nullptr,
getter_AddRefs(item));
nsCOMPtr<nsPIDOMWindowOuter> childWindow(do_GetInterface(item));
return childWindow.forget();
}

Просмотреть файл

@ -1,46 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsDOMWindowList_h___
#define nsDOMWindowList_h___
#include "nsCOMPtr.h"
#include <stdint.h>
#include "nsIDocShell.h"
class nsIDocShell;
class nsIDOMWindow;
class nsDOMWindowList final {
public:
explicit nsDOMWindowList(nsIDocShell* aDocShell);
NS_INLINE_DECL_REFCOUNTING(nsDOMWindowList)
uint32_t GetLength();
already_AddRefed<nsPIDOMWindowOuter> IndexedGetter(uint32_t aIndex);
already_AddRefed<nsPIDOMWindowOuter> NamedItem(const nsAString& aName);
// local methods
void SetDocShell(nsIDocShell* aDocShell);
already_AddRefed<nsIDocShellTreeItem> GetDocShellTreeItemAt(uint32_t aIndex) {
EnsureFresh();
nsCOMPtr<nsIDocShellTreeItem> item;
if (mDocShellNode) {
mDocShellNode->GetChildAt(aIndex, getter_AddRefs(item));
}
return item.forget();
}
protected:
~nsDOMWindowList();
// Note: this function may flush and cause mDocShellNode to become null.
void EnsureFresh();
nsIDocShell* mDocShellNode; // Weak Reference
};
#endif // nsDOMWindowList_h___

Просмотреть файл

@ -50,7 +50,6 @@
#include "nsISizeOfEventTarget.h"
#include "nsDOMJSUtils.h"
#include "nsArrayUtils.h"
#include "nsDOMWindowList.h"
#include "mozilla/dom/WakeLock.h"
#include "mozilla/dom/power/PowerManagerService.h"
#include "nsIContentSecurityPolicy.h"
@ -2708,11 +2707,7 @@ bool nsGlobalWindowInner::GetClosed(ErrorResult& aError) {
FORWARD_TO_OUTER(GetClosedOuter, (), true);
}
nsDOMWindowList* nsGlobalWindowInner::GetFrames() {
FORWARD_TO_OUTER(GetFrames, (), nullptr);
}
already_AddRefed<nsPIDOMWindowOuter> nsGlobalWindowInner::IndexedGetter(
Nullable<WindowProxyHolder> nsGlobalWindowInner::IndexedGetter(
uint32_t aIndex) {
FORWARD_TO_OUTER(IndexedGetterOuter, (aIndex), nullptr);
}

Просмотреть файл

@ -77,7 +77,6 @@ class nsITimeoutHandler;
class nsIWebBrowserChrome;
class mozIDOMWindowProxy;
class nsDOMWindowList;
class nsScreen;
class nsHistory;
class nsGlobalWindowObserver;
@ -381,7 +380,8 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
NS_DECL_NSIINTERFACEREQUESTOR
// WebIDL interface.
already_AddRefed<nsPIDOMWindowOuter> IndexedGetter(uint32_t aIndex);
mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder> IndexedGetter(
uint32_t aIndex);
static bool IsPrivilegedChromeWindow(JSContext* /* unused */, JSObject* aObj);
@ -612,7 +612,6 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
void Focus(mozilla::ErrorResult& aError);
nsresult Focus() override;
void Blur(mozilla::ErrorResult& aError);
nsDOMWindowList* GetFrames() final;
mozilla::dom::BrowsingContext* GetFrames(mozilla::ErrorResult& aError);
uint32_t Length();
mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder> GetTop(

Просмотреть файл

@ -48,7 +48,6 @@
#include "nsISizeOfEventTarget.h"
#include "nsDOMJSUtils.h"
#include "nsArrayUtils.h"
#include "nsDOMWindowList.h"
#include "mozilla/dom/WakeLock.h"
#include "mozilla/dom/power/PowerManagerService.h"
#include "nsIDocShellTreeOwner.h"
@ -510,8 +509,9 @@ class nsOuterWindowProxy : public MaybeCrossOriginObject<js::Wrapper> {
// Returns a non-null window only if id is an index and we have a
// window at that index.
already_AddRefed<nsPIDOMWindowOuter> GetSubframeWindow(
JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id) const;
Nullable<WindowProxyHolder> GetSubframeWindow(JSContext* cx,
JS::Handle<JSObject*> proxy,
JS::Handle<jsid> id) const;
bool AppendIndexedPropertyNames(JSObject* proxy,
JS::MutableHandleVector<jsid> props) const;
@ -784,7 +784,7 @@ bool nsOuterWindowProxy::delete_(JSContext* cx, JS::Handle<JSObject*> proxy,
return ReportCrossOriginDenial(cx, id, NS_LITERAL_CSTRING("delete"));
}
if (nsCOMPtr<nsPIDOMWindowOuter> frame = GetSubframeWindow(cx, proxy, id)) {
if (!GetSubframeWindow(cx, proxy, id).IsNull()) {
// Fail (which means throw if strict, else return false).
return result.failCantDeleteWindowElement();
}
@ -818,7 +818,7 @@ bool nsOuterWindowProxy::has(JSContext* cx, JS::Handle<JSObject*> proxy,
return hasOwn(cx, proxy, id, bp);
}
if (nsCOMPtr<nsPIDOMWindowOuter> frame = GetSubframeWindow(cx, proxy, id)) {
if (!GetSubframeWindow(cx, proxy, id).IsNull()) {
*bp = true;
return true;
}
@ -851,7 +851,7 @@ bool nsOuterWindowProxy::hasOwn(JSContext* cx, JS::Handle<JSObject*> proxy,
return js::BaseProxyHandler::hasOwn(cx, proxy, id, bp);
}
if (nsCOMPtr<nsPIDOMWindowOuter> frame = GetSubframeWindow(cx, proxy, id)) {
if (!GetSubframeWindow(cx, proxy, id).IsNull()) {
*bp = true;
return true;
}
@ -982,28 +982,17 @@ bool nsOuterWindowProxy::GetSubframeWindow(JSContext* cx,
JS::Handle<jsid> id,
JS::MutableHandle<JS::Value> vp,
bool& found) const {
nsCOMPtr<nsPIDOMWindowOuter> frame = GetSubframeWindow(cx, proxy, id);
if (!frame) {
Nullable<WindowProxyHolder> frame = GetSubframeWindow(cx, proxy, id);
if (frame.IsNull()) {
found = false;
return true;
}
found = true;
// Just return the window's global
nsGlobalWindowOuter* global = nsGlobalWindowOuter::Cast(frame);
frame->EnsureInnerWindow();
JSObject* obj = global->GetGlobalJSObject();
// This null check fixes a hard-to-reproduce crash that occurs when we
// get here when we're mid-call to nsDocShell::Destroy. See bug 640904
// comment 105.
if (MOZ_UNLIKELY(!obj)) {
return xpc::Throw(cx, NS_ERROR_FAILURE);
}
vp.setObject(*obj);
return JS_WrapValue(cx, vp);
return WrapObject(cx, frame.Value(), vp);
}
already_AddRefed<nsPIDOMWindowOuter> nsOuterWindowProxy::GetSubframeWindow(
Nullable<WindowProxyHolder> nsOuterWindowProxy::GetSubframeWindow(
JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id) const {
uint32_t index = GetArrayIndexFromId(id);
if (!IsArrayIndex(index)) {
@ -1300,7 +1289,6 @@ void nsGlobalWindowOuter::CleanUp() {
StartDying();
mFrames = nullptr;
mWindowUtils = nullptr;
ClearControllers();
@ -2380,10 +2368,6 @@ void nsGlobalWindowOuter::SetDocShell(nsDocShell* aDocShell) {
mTopLevelOuterContentWindow =
!mIsChrome && GetScriptableTopInternal() == this;
if (mFrames) {
mFrames->SetDocShell(aDocShell);
}
// Get our enclosing chrome shell and retrieve its global window impl, so
// that we can do some forwarding to the chrome document.
RefPtr<EventTarget> chromeEventHandler;
@ -2475,10 +2459,6 @@ void nsGlobalWindowOuter::DetachFromDocShell() {
mDocShell = nullptr;
mBrowsingContext->ClearDocShell();
if (mFrames) {
mFrames->SetDocShell(nullptr);
}
MaybeForgiveSpamCount();
CleanUp();
}
@ -3196,20 +3176,16 @@ bool nsGlobalWindowOuter::GetClosedOuter() {
bool nsGlobalWindowOuter::Closed() { return GetClosedOuter(); }
nsDOMWindowList* nsGlobalWindowOuter::GetFrames() {
if (!mFrames && mDocShell) {
mFrames = new nsDOMWindowList(mDocShell);
}
return mFrames;
}
already_AddRefed<nsPIDOMWindowOuter> nsGlobalWindowOuter::IndexedGetterOuter(
Nullable<WindowProxyHolder> nsGlobalWindowOuter::IndexedGetterOuter(
uint32_t aIndex) {
nsDOMWindowList* windows = GetFrames();
NS_ENSURE_TRUE(windows, nullptr);
BrowsingContext* bc = GetBrowsingContext();
NS_ENSURE_TRUE(bc, nullptr);
return windows->IndexedGetter(aIndex);
const BrowsingContext::Children& children = bc->GetChildren();
if (aIndex < children.Length()) {
return WindowProxyHolder(children[aIndex]);
}
return nullptr;
}
nsIControllers* nsGlobalWindowOuter::GetControllersOuter(ErrorResult& aError) {
@ -3962,9 +3938,8 @@ double nsGlobalWindowOuter::GetScrollXOuter() { return GetScrollXY(false).x; }
double nsGlobalWindowOuter::GetScrollYOuter() { return GetScrollXY(false).y; }
uint32_t nsGlobalWindowOuter::Length() {
nsDOMWindowList* windows = GetFrames();
return windows ? windows->GetLength() : 0;
BrowsingContext* bc = GetBrowsingContext();
return bc ? bc->GetChildren().Length() : 0;
}
Nullable<WindowProxyHolder> nsGlobalWindowOuter::GetTopOuter() {

Просмотреть файл

@ -74,7 +74,6 @@ class nsIWebBrowserChrome;
class mozIDOMWindowProxy;
class nsDocShellLoadState;
class nsDOMWindowList;
class nsScreen;
class nsHistory;
class nsGlobalWindowObserver;
@ -354,7 +353,8 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
// nsIObserver
NS_DECL_NSIOBSERVER
already_AddRefed<nsPIDOMWindowOuter> IndexedGetterOuter(uint32_t aIndex);
mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder> IndexedGetterOuter(
uint32_t aIndex);
already_AddRefed<nsPIDOMWindowOuter> GetTop() override;
// Similar to GetTop() except that it stops at content frames that an
@ -535,7 +535,6 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
nsresult Focus() override;
void BlurOuter();
mozilla::dom::BrowsingContext* GetFramesOuter();
nsDOMWindowList* GetFrames() final;
uint32_t Length();
mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder> GetTopOuter();
@ -918,8 +917,8 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
virtual bool ShouldShowFocusRing() override;
virtual void SetKeyboardIndicators(UIStateChangeType aShowFocusRings)
override;
virtual void SetKeyboardIndicators(
UIStateChangeType aShowFocusRings) override;
public:
virtual already_AddRefed<nsPIWindowRoot> GetTopWindowRoot() override;
@ -1099,7 +1098,6 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
// For |window.arguments|, via |openDialog|.
nsCOMPtr<nsIArray> mArguments;
RefPtr<nsDOMWindowList> mFrames;
RefPtr<nsDOMWindowUtils> mWindowUtils;
nsString mStatus;

Просмотреть файл

@ -25,7 +25,6 @@
#define DOM_WINDOW_THAWED_TOPIC "dom-window-thawed"
class nsDOMOfflineResourceList;
class nsDOMWindowList;
class nsGlobalWindowInner;
class nsGlobalWindowOuter;
class nsIArray;
@ -546,8 +545,6 @@ class nsPIDOMWindowInner : public mozIDOMWindow {
virtual nsresult GetControllers(nsIControllers** aControllers) = 0;
virtual nsDOMWindowList* GetFrames() = 0;
virtual nsresult GetInnerWidth(int32_t* aWidth) = 0;
virtual nsresult GetInnerHeight(int32_t* aHeight) = 0;
@ -1045,8 +1042,6 @@ class nsPIDOMWindowOuter : public mozIDOMWindowProxy {
virtual already_AddRefed<mozilla::dom::Selection> GetSelection() = 0;
virtual already_AddRefed<nsPIDOMWindowOuter> GetOpener() = 0;
virtual nsDOMWindowList* GetFrames() = 0;
// aLoadState will be passed on through to the windowwatcher.
// aForceNoOpener will act just like a "noopener" feature in aOptions except
// will not affect any other window features.

Просмотреть файл

@ -7,13 +7,14 @@
#include "nsWindowMemoryReporter.h"
#include "nsWindowSizes.h"
#include "nsGlobalWindow.h"
#include "mozilla/dom/BrowsingContext.h"
#include "mozilla/dom/Document.h"
#include "nsDOMWindowList.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/Telemetry.h"
#include "mozilla/ResultExtensions.h"
#include "nsNetCID.h"
#include "nsPrintfCString.h"
#include "XPCJSMemoryReporter.h"
@ -61,19 +62,16 @@ static nsresult AddNonJSSizeOfWindowAndItsDescendents(
windowSizes.addToTabSizes(aSizes);
nsDOMWindowList* frames = aWindow->GetFrames();
uint32_t length = frames->GetLength();
BrowsingContext* bc = aWindow->GetBrowsingContext();
if (!bc) {
return NS_OK;
}
// Measure this window's descendents.
for (uint32_t i = 0; i < length; i++) {
nsCOMPtr<nsPIDOMWindowOuter> child = frames->IndexedGetter(i);
NS_ENSURE_STATE(child);
nsGlobalWindowOuter* childWin = nsGlobalWindowOuter::Cast(child);
nsresult rv = AddNonJSSizeOfWindowAndItsDescendents(childWin, aSizes);
NS_ENSURE_SUCCESS(rv, rv);
for (const auto& frame : bc->GetChildren()) {
if (auto* childWin = nsGlobalWindowOuter::Cast(frame->GetDOMWindow())) {
MOZ_TRY(AddNonJSSizeOfWindowAndItsDescendents(childWin, aSizes));
}
}
return NS_OK;
}

Просмотреть файл

@ -11,7 +11,9 @@
var SimpleTest = opener.wrappedJSObject.SimpleTest;
var ok = opener.wrappedJSObject.ok;
var doc = frames[0].document;
// Note: We can't use frames[0] here because the type="content" attribute
// isolates it into a separate browsing context hierarchy.
var doc = document.querySelector("iframe").contentDocument;
ok(doc.createElement("body") instanceof HTMLBodyElement,
"Should be instance of HTMLBodyElement");
ok(doc.createElement("div") instanceof HTMLDivElement,

Просмотреть файл

@ -7,7 +7,6 @@
#include "AccessCheck.h"
#include "nsJSPrincipals.h"
#include "nsDOMWindowList.h"
#include "nsGlobalWindow.h"
#include "XPCWrapper.h"

Просмотреть файл

@ -1648,16 +1648,12 @@ bool DOMXrayTraits::resolveOwnProperty(JSContext* cx, HandleObject wrapper,
nsGlobalWindowInner* win = AsWindow(cx, wrapper);
// Note: As() unwraps outer windows to get to the inner window.
if (win) {
nsCOMPtr<nsPIDOMWindowOuter> subframe = win->IndexedGetter(index);
if (subframe) {
subframe->EnsureInnerWindow();
nsGlobalWindowOuter* global = nsGlobalWindowOuter::Cast(subframe);
JSObject* obj = global->GetGlobalJSObject();
if (MOZ_UNLIKELY(!obj)) {
Nullable<WindowProxyHolder> subframe = win->IndexedGetter(index);
if (!subframe.IsNull()) {
if (MOZ_UNLIKELY(!WrapObject(cx, subframe.Value(), desc.value()))) {
// It's gone?
return xpc::Throw(cx, NS_ERROR_FAILURE);
}
desc.value().setObject(*obj);
FillPropertyDescriptor(desc, wrapper, true);
return JS_WrapPropertyDescriptor(cx, desc);
}

Просмотреть файл

@ -11,13 +11,17 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=396024
<iframe src="about:blank" type="content"></iframe>
<script type="application/javascript">
<![CDATA[
// Note: We can't use window.frames directly here because the type="content"
// attributes isolate the frames into their own BrowsingContext hierarchies.
let frameElts = document.getElementsByTagName("iframe");
var is = window.opener.wrappedJSObject.is;
var ok = window.opener.wrappedJSObject.ok;
var todo = window.opener.wrappedJSObject.todo;
var SimpleTest = window.opener.wrappedJSObject.SimpleTest;
var gWbp;
function printpreview() {
gWbp = window.frames[1].docShell.initOrReusePrintPreviewViewer();
gWbp = frameElts[1].contentWindow.docShell.initOrReusePrintPreviewViewer();
var listener = {
onLocationChange: function(webProgress, request, location, flags) { },
onProgressChange: function(webProgress, request, curSelfProgress,
@ -39,12 +43,12 @@ function printpreview() {
prefs.setBoolPref('print.show_print_progress', false);
//XXX I would have thought this would work, instead I'm forced to use prefs service
gWbp.globalPrintSettings.showPrintProgress = false;
gWbp.printPreview(gWbp.globalPrintSettings, window.frames[0], listener);
gWbp.printPreview(gWbp.globalPrintSettings, frameElts[0].contentWindow, listener);
prefs.clearUserPref('print.show_print_progress');
}
function exitprintpreview() {
window.frames[1].docShell.exitPrintPreview();
frameElts[1].contentWindow.docShell.exitPrintPreview();
}
function finish() {
@ -86,11 +90,11 @@ function run2() {
setTimeout(run3, 0);
};
document.getElementById("i").addEventListener("load", loadhandler, true);
window.frames[0].location.reload();
frameElts[0].contentWindow.location.reload();
}
function run3() {
gWbp = window.frames[1].docShell.initOrReusePrintPreviewViewer();
gWbp = frameElts[1].contentWindow.docShell.initOrReusePrintPreviewViewer();
ok(gWbp.doingPrintPreview, "Should be doing print preview");
exitprintpreview();
setTimeout(run4, 0);
@ -109,7 +113,7 @@ function run4() {
}
function run5() {
gWbp = window.frames[1].docShell.initOrReusePrintPreviewViewer();
gWbp = frameElts[1].contentWindow.docShell.initOrReusePrintPreviewViewer();
ok(!gWbp.doingPrintPreview, "Should not be doing print preview anymore2");
//XXX this shouldn't be necessary, see bug 405555

Просмотреть файл

@ -11,13 +11,17 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=482976
<iframe src="about:blank" type="content"></iframe>
<script type="application/javascript">
<![CDATA[
// Note: We can't use window.frames directly here because the type="content"
// attributes isolate the frames into their own BrowsingContext hierarchies.
let frameElts = document.getElementsByTagName("iframe");
var is = window.opener.wrappedJSObject.is;
var ok = window.opener.wrappedJSObject.ok;
var todo = window.opener.wrappedJSObject.todo;
var SimpleTest = window.opener.wrappedJSObject.SimpleTest;
var gWbp;
function printpreview() {
gWbp = window.frames[1].docShell.initOrReusePrintPreviewViewer();
gWbp = frameElts[1].contentWindow.docShell.initOrReusePrintPreviewViewer();
var listener = {
onLocationChange: function(webProgress, request, location, flags) { },
onProgressChange: function(webProgress, request, curSelfProgress,
@ -39,12 +43,12 @@ function printpreview() {
prefs.setBoolPref('print.show_print_progress', false);
//XXX I would have thought this would work, instead I'm forced to use prefs service
gWbp.globalPrintSettings.showPrintProgress = false;
gWbp.printPreview(gWbp.globalPrintSettings, window.frames[0], listener);
gWbp.printPreview(gWbp.globalPrintSettings, frameElts[0].contentWindow, listener);
prefs.clearUserPref('print.show_print_progress');
}
function exitprintpreview() {
window.frames[1].docShell.exitPrintPreview();
frameElts[1].contentWindow.docShell.exitPrintPreview();
}
function finish() {

Просмотреть файл

@ -8,6 +8,10 @@
<iframe height="200" width="600" type="content"></iframe>
<script type="application/javascript">
<![CDATA[
// Note: We can't use window.frames directly here because the type="content"
// attributes isolate the frames into their own BrowsingContext hierarchies.
let frameElts = document.getElementsByTagName("iframe");
var is = window.opener.wrappedJSObject.is;
var isnot = window.opener.wrappedJSObject.isnot;
var ok = window.opener.wrappedJSObject.ok;
@ -24,7 +28,7 @@ var file = Cc["@mozilla.org/file/directory_service;1"]
filePath = file.path;
function printpreview(hasMozPrintCallback) {
gWbp = window.frames[1].docShell.initOrReusePrintPreviewViewer();
gWbp = frameElts[1].docShell.initOrReusePrintPreviewViewer();
var listener = {
onLocationChange: function(webProgress, request, location, flags) { },
onProgressChange: function(webProgress, request, curSelfProgress,
@ -50,22 +54,22 @@ function printpreview(hasMozPrintCallback) {
var after = 0;
function beforeprint() { ++before; }
function afterprint() { ++after; }
window.frames[0].addEventListener("beforeprint", beforeprint, true);
window.frames[0].addEventListener("afterprint", afterprint, true);
gWbp.printPreview(gWbp.globalPrintSettings, window.frames[0], listener);
frameElts[0].contentWindow.addEventListener("beforeprint", beforeprint, true);
frameElts[0].contentWindow.addEventListener("afterprint", afterprint, true);
gWbp.printPreview(gWbp.globalPrintSettings, frameElts[0].contentWindow, listener);
is(before, 1, "Should have called beforeprint listener!");
if (!hasMozPrintCallback) {
// If there's a mozPrintCallback the after print event won't fire until
// later.
is(after, 1, "Should have called afterprint listener!");
}
window.frames[0].removeEventListener("beforeprint", beforeprint, true);
window.frames[0].removeEventListener("afterprint", afterprint, true);
frameElts[0].contentWindow.removeEventListener("beforeprint", beforeprint, true);
frameElts[0].contentWindow.removeEventListener("afterprint", afterprint, true);
prefs.clearUserPref('print.show_print_progress');
}
function exitprintpreview() {
window.frames[1].docShell.exitPrintPreview();
frameElts[1].contentWindow.docShell.exitPrintPreview();
}
function finish() {
@ -117,45 +121,45 @@ function addHTMLContent(parent) {
function startTest1() {
ctx1 = document.getElementsByTagName("canvas")[0].getContext("2d");
ctx2 = document.getElementsByTagName("canvas")[1].getContext("2d");
window.frames[0].document.body.innerHTML = "<div> </div><div>" + counter + " timers</div><div> </div>";
frameElts[0].contentDocument.body.innerHTML = "<div> </div><div>" + counter + " timers</div><div> </div>";
// Note this timeout is needed so that we can check that timers run
// after print preview, but not during it.
window.frames[0].wrappedJSObject.counter = counter;
window.frames[0].counterTimeout = "document.body.firstChild.nextSibling.innerHTML = ++counter + ' timers';" +
frameElts[0].contentWindow.wrappedJSObject.counter = counter;
frameElts[0].contentWindow.counterTimeout = "document.body.firstChild.nextSibling.innerHTML = ++counter + ' timers';" +
"window.setTimeout(counterTimeout, 0);";
window.frames[0].setTimeout(window.frames[0].counterTimeout, 0);
window.frames[0].document.body.firstChild.innerHTML = "Print preview";
frameElts[0].contentWindow.setTimeout(frameElts[0].contentWindow.counterTimeout, 0);
frameElts[0].contentDocument.body.firstChild.innerHTML = "Print preview";
printpreview();
ctx1.drawWindow(window.frames[1], 0, 0, 400, 400, "rgb(256,256,256)");
window.frames[0].document.body.firstChild.innerHTML = "Galley presentation";
ctx1.drawWindow(frameElts[1].contentWindow, 0, 0, 400, 400, "rgb(256,256,256)");
frameElts[0].contentDocument.body.firstChild.innerHTML = "Galley presentation";
// Add some elements.
addHTMLContent(window.frames[0].document.body.lastChild);
addHTMLContent(frameElts[0].contentDocument.body.lastChild);
// Delete them.
window.frames[0].document.body.lastChild.innerHTML = "";
frameElts[0].contentDocument.body.lastChild.innerHTML = "";
// And readd.
addHTMLContent(window.frames[0].document.body.lastChild);
addHTMLContent(frameElts[0].contentDocument.body.lastChild);
setTimeout(finalizeTest1, 1000);
}
function finalizeTest1() {
ctx2.drawWindow(window.frames[1], 0, 0, 400, 400, "rgb(256,256,256)");
ctx2.drawWindow(frameElts[1].contentWindow, 0, 0, 400, 400, "rgb(256,256,256)");
exitprintpreview();
ok(compareCanvases(), "Canvas should be the same!");
counter = window.frames[0].counter;
counter = frameElts[0].contentWindow.counter;
// This timeout is needed so that we can check that timers do run after
// print preview.
setTimeout(runTest2, 1000);
}
function runTest2() {
isnot(window.frames[0].document.body.firstChild.nextSibling.textContent, "0 timers", "Timers should have run!");
isnot(window.frames[0].counter, 0, "Timers should have run!");
counter = window.frames[0].counter;
window.frames[0].counterTimeout = "";
isnot(frameElts[0].contentDocument.body.firstChild.nextSibling.textContent, "0 timers", "Timers should have run!");
isnot(frameElts[0].contentWindow.counter, 0, "Timers should have run!");
counter = frameElts[0].contentWindow.counter;
frameElts[0].contentWindow.counterTimeout = "";
setTimeout(runTest3, 0);
}
@ -208,17 +212,17 @@ function runTest3() {
}
function compareFormElementPrint(el1, el2, equals) {
window.frames[0].document.body.innerHTML = el1;
window.frames[0].document.body.firstChild.value =
window.frames[0].document.body.firstChild.getAttribute('value');
frameElts[0].contentDocument.body.innerHTML = el1;
frameElts[0].contentDocument.body.firstChild.value =
frameElts[0].contentDocument.body.firstChild.getAttribute('value');
printpreview();
ctx1.drawWindow(window.frames[1], 0, 0, 400, 400, "rgb(256,256,256)");
ctx1.drawWindow(frameElts[1].contentWindow, 0, 0, 400, 400, "rgb(256,256,256)");
exitprintpreview();
window.frames[0].document.body.innerHTML = el2;
window.frames[0].document.body.firstChild.value =
window.frames[0].document.body.firstChild.getAttribute('value');
frameElts[0].contentDocument.body.innerHTML = el2;
frameElts[0].contentDocument.body.firstChild.value =
frameElts[0].contentDocument.body.firstChild.getAttribute('value');
printpreview();
ctx2.drawWindow(window.frames[1], 0, 0, 400, 400, "rgb(256,256,256)");
ctx2.drawWindow(frameElts[1].contentWindow, 0, 0, 400, 400, "rgb(256,256,256)");
exitprintpreview();
is(compareCanvases(), equals,
"Comparing print preview didn't succeed [" + el1 + " : " + el2 + "]");
@ -227,7 +231,7 @@ function compareFormElementPrint(el1, el2, equals) {
// This is a crash test for bug 539060.
function runTest4() {
window.frames[0].document.body.innerHTML =
frameElts[0].contentDocument.body.innerHTML =
"<iframe style='display: none;' src='data:text/html,<iframe>'></iframe>";
setTimeout(runTest4end, 500);
}
@ -241,7 +245,7 @@ function runTest4end() {
// This is a crash test for bug 595337
function runTest5() {
window.frames[0].document.body.innerHTML =
frameElts[0].contentDocument.body.innerHTML =
'<iframe style="position: fixed; visibility: hidden; bottom: 10em;"></iframe>' +
'<input contenteditable="true" style="display: table; page-break-before: left; width: 10000px;">';
printpreview();
@ -252,7 +256,7 @@ function runTest5() {
// Crash test for bug 878037
function runTest6() {
window.frames[0].document.body.innerHTML =
frameElts[0].contentDocument.body.innerHTML =
'<style> li { list-style-image: url("animated.gif"); } </style>' +
'<li>Firefox will crash if you try and print this page</li>';
@ -269,19 +273,19 @@ function runTest6end() {
function runTest7() {
var contentText = "<a href='#'>mozilla</a><input>test<select><option>option1</option></select>";
// Create normal content
window.frames[0].document.body.innerHTML =
frameElts[0].contentDocument.body.innerHTML =
"<div>" + contentText + "</div>";
window.frames[0].document.body.firstChild.value =
window.frames[0].document.body.firstChild.getAttribute('value');
frameElts[0].contentDocument.body.firstChild.value =
frameElts[0].contentDocument.body.firstChild.getAttribute('value');
printpreview();
ctx1.drawWindow(window.frames[1], 0, 0, 400, 400, "rgb(255,255,255)");
ctx1.drawWindow(frameElts[1].contentWindow, 0, 0, 400, 400, "rgb(255,255,255)");
exitprintpreview();
window.frames[0].document.body.innerHTML = "<div></div>";
var sr = window.frames[0].document.body.firstChild.attachShadow({mode: "open"});
frameElts[0].contentDocument.body.innerHTML = "<div></div>";
var sr = frameElts[0].contentDocument.body.firstChild.attachShadow({mode: "open"});
sr.innerHTML = contentText;
printpreview();
ctx2.drawWindow(window.frames[1], 0, 0, 400, 400, "rgb(255,255,255)");
ctx2.drawWindow(frameElts[1].contentWindow, 0, 0, 400, 400, "rgb(255,255,255)");
exitprintpreview();
ok(compareCanvases(), "Printing light DOM and shadow DOM should create same output");
@ -298,7 +302,7 @@ async function runTest8() {
iframeElement.setAttribute("src", "printpreview_font_api_ref.html");
});
printpreview();
ctx1.drawWindow(window.frames[1], 0, 0, 400, 400, "rgb(255,255,255)");
ctx1.drawWindow(frameElts[1].contentWindow, 0, 0, 400, 400, "rgb(255,255,255)");
exitprintpreview();
// Second, snapshot the page with font loaded in JS.
@ -307,7 +311,7 @@ async function runTest8() {
iframeElement.setAttribute("src", "printpreview_font_api.html");
});
printpreview();
ctx2.drawWindow(window.frames[1], 0, 0, 400, 400, "rgb(255,255,255)");
ctx2.drawWindow(frameElts[1].contentWindow, 0, 0, 400, 400, "rgb(255,255,255)");
exitprintpreview();
ok(compareCanvases(), "Printing pages with fonts loaded from CSS and JS should be the same.");
@ -316,17 +320,17 @@ async function runTest8() {
// Test for bug 1487649
async function runTest9() {
window.frames[0].document.body.innerHTML = `
frameElts[0].contentDocument.body.innerHTML = `
<svg width="100" height="100">
<rect width='100' height='100' fill='lime'/>
</svg>
`;
printpreview();
ctx1.drawWindow(window.frames[1], 0, 0, 400, 400, "rgb(255,255,255)");
ctx1.drawWindow(frameElts[1].contentWindow, 0, 0, 400, 400, "rgb(255,255,255)");
exitprintpreview();
window.frames[0].document.body.innerHTML = `
frameElts[0].contentDocument.body.innerHTML = `
<svg width="100" height="100">
<defs>
<g id="useme">
@ -339,13 +343,13 @@ async function runTest9() {
// Set the attribute explicitly because this is a chrome document, and the
// href attribute would get sanitized.
window.frames[0].document.querySelector("use").setAttribute("href", "#useme");
frameElts[0].contentDocument.querySelector("use").setAttribute("href", "#useme");
// Ensure the <use> shadow tree is created so we test what we want to test.
window.frames[0].document.body.offsetTop;
frameElts[0].contentDocument.body.offsetTop;
printpreview();
ctx2.drawWindow(window.frames[1], 0, 0, 400, 400, "rgb(255,255,255)");
ctx2.drawWindow(frameElts[1].contentWindow, 0, 0, 400, 400, "rgb(255,255,255)");
exitprintpreview();
ok(compareCanvases(), "Printing <use> subtrees should create same output");
@ -368,7 +372,7 @@ async function runTest10() {
});
printpreview(true);
await mozPrintCallbackDone;
ctx1.drawWindow(window.frames[1], 0, 0, 400, 400, "rgb(255,255,255)");
ctx1.drawWindow(frameElts[1].contentWindow, 0, 0, 400, 400, "rgb(255,255,255)");
exitprintpreview();
// Second, snapshot the page with font loaded in JS.
@ -382,7 +386,7 @@ async function runTest10() {
printpreview(true);
// Wait for the mozprintcallback to finish.
await mozPrintCallbackDone;
ctx2.drawWindow(window.frames[1], 0, 0, 400, 400, "rgb(255,255,255)");
ctx2.drawWindow(frameElts[1].contentWindow, 0, 0, 400, 400, "rgb(255,255,255)");
exitprintpreview();
ok(compareCanvases(), "Printing pages with fonts loaded from a mozPrintCallback should be the same.");

Просмотреть файл

@ -524,7 +524,11 @@ function FlushRendering(aFlushMode) {
}
for (var i = 0; i < win.frames.length; ++i) {
flushWindow(win.frames[i]);
try {
flushWindow(win.frames[i]);
} catch (e) {
Cu.reportError(e);
}
}
}

Просмотреть файл

@ -6,6 +6,7 @@
#include "nsThreadUtils.h"
#include "mozilla/PerformanceUtils.h"
#include "mozilla/ResultExtensions.h"
#include "mozilla/dom/DocGroup.h"
#include "mozilla/dom/BrowserChild.h"
#include "mozilla/dom/WorkerDebugger.h"
@ -16,7 +17,6 @@
#include "jsfriendapi.h"
#include "js/MemoryMetrics.h"
#include "nsWindowMemoryReporter.h"
#include "nsDOMWindowList.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -93,15 +93,16 @@ nsresult GetTabSizes(nsGlobalWindowOuter* aWindow, nsTabSizes* aSizes) {
// Add the window (and inner window) sizes. Might be cached.
AddWindowTabSizes(aWindow, aSizes);
nsDOMWindowList* frames = aWindow->GetFrames();
uint32_t length = frames->GetLength();
BrowsingContext* bc = aWindow->GetBrowsingContext();
if (!bc) {
return NS_OK;
}
// Measure this window's descendents.
for (uint32_t i = 0; i < length; i++) {
nsCOMPtr<nsPIDOMWindowOuter> child = frames->IndexedGetter(i);
NS_ENSURE_STATE(child);
nsGlobalWindowOuter* childWin = nsGlobalWindowOuter::Cast(child);
nsresult rv = GetTabSizes(childWin, aSizes);
NS_ENSURE_SUCCESS(rv, rv);
for (const auto& frame : bc->GetChildren()) {
if (auto* childWin = nsGlobalWindowOuter::Cast(frame->GetDOMWindow())) {
MOZ_TRY(GetTabSizes(childWin, aSizes));
}
}
return NS_OK;
}