import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo

This commit is contained in:
Roy Tam 2018-01-19 03:59:58 +08:00
commit dcd9973243
150858 changed files with 23884658 additions and 0 deletions

42
xpfe/appshell/moz.build Normal file
View file

@ -0,0 +1,42 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
XPIDL_SOURCES += [
'nsIAppShellService.idl',
'nsIPopupWindowManager.idl',
'nsIWindowlessBrowser.idl',
'nsIWindowMediator.idl',
'nsIWindowMediatorListener.idl',
'nsIXULBrowserWindow.idl',
'nsIXULWindow.idl',
]
XPIDL_MODULE = 'appshell'
EXPORTS += [
'nsAppShellCID.h',
]
UNIFIED_SOURCES += [
'nsAppShellFactory.cpp',
'nsAppShellService.cpp',
'nsAppShellWindowEnumerator.cpp',
'nsChromeTreeOwner.cpp',
'nsContentTreeOwner.cpp',
'nsWebShellWindow.cpp',
'nsWindowMediator.cpp',
'nsXULWindow.cpp',
]
LOCAL_INCLUDES += [
'/dom/base',
]
FINAL_LIBRARY = 'xul'
include('/ipc/chromium/chromium-config.mozbuild')

View file

@ -0,0 +1,10 @@
/* 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 nsAppShellCID_h__
#define nsAppShellCID_h__
#define NS_APPSHELLSERVICE_CONTRACTID "@mozilla.org/appshell/appShellService;1"
#endif

View file

@ -0,0 +1,56 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "mozilla/ModuleUtils.h"
#include "nscore.h"
#include "nsIWindowMediator.h"
#include "nsIAppShellService.h"
#include "nsAppShellService.h"
#include "nsWindowMediator.h"
#include "nsChromeTreeOwner.h"
#include "nsAppShellCID.h"
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAppShellService)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsWindowMediator, Init)
NS_DEFINE_NAMED_CID(NS_APPSHELLSERVICE_CID);
NS_DEFINE_NAMED_CID(NS_WINDOWMEDIATOR_CID);
static const mozilla::Module::CIDEntry kAppShellCIDs[] = {
{ &kNS_APPSHELLSERVICE_CID, false, nullptr, nsAppShellServiceConstructor },
{ &kNS_WINDOWMEDIATOR_CID, false, nullptr, nsWindowMediatorConstructor },
{ nullptr }
};
static const mozilla::Module::ContractIDEntry kAppShellContracts[] = {
{ NS_APPSHELLSERVICE_CONTRACTID, &kNS_APPSHELLSERVICE_CID },
{ NS_WINDOWMEDIATOR_CONTRACTID, &kNS_WINDOWMEDIATOR_CID },
{ nullptr }
};
static nsresult
nsAppShellModuleConstructor()
{
return nsChromeTreeOwner::InitGlobals();
}
static void
nsAppShellModuleDestructor()
{
nsChromeTreeOwner::FreeGlobals();
}
static const mozilla::Module kAppShellModule = {
mozilla::Module::kVersion,
kAppShellCIDs,
kAppShellContracts,
nullptr,
nullptr,
nsAppShellModuleConstructor,
nsAppShellModuleDestructor
};
NSMODULE_DEFN(appshell) = &kAppShellModule;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,58 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 __nsAppShellService_h
#define __nsAppShellService_h
#include "nsIAppShellService.h"
#include "nsIObserver.h"
//Interfaces Needed
#include "nsWebShellWindow.h"
#include "nsStringFwd.h"
#include "nsAutoPtr.h"
#include "nsITabParent.h"
#include "mozilla/Attributes.h"
// {0099907D-123C-4853-A46A-43098B5FB68C}
#define NS_APPSHELLSERVICE_CID \
{ 0x99907d, 0x123c, 0x4853, { 0xa4, 0x6a, 0x43, 0x9, 0x8b, 0x5f, 0xb6, 0x8c } }
class nsAppShellService final : public nsIAppShellService,
public nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIAPPSHELLSERVICE
NS_DECL_NSIOBSERVER
nsAppShellService();
protected:
~nsAppShellService();
nsresult CreateHiddenWindowHelper(bool aIsPrivate);
void EnsurePrivateHiddenWindow();
nsresult JustCreateTopWindow(nsIXULWindow *aParent,
nsIURI *aUrl,
uint32_t aChromeMask,
int32_t aInitialWidth, int32_t aInitialHeight,
bool aIsHiddenWindow,
nsITabParent *aOpeningTab,
mozIDOMWindowProxy *aOpenerWindow,
nsWebShellWindow **aResult);
uint32_t CalculateWindowZLevel(nsIXULWindow *aParent, uint32_t aChromeMask);
RefPtr<nsWebShellWindow> mHiddenWindow;
RefPtr<nsWebShellWindow> mHiddenPrivateWindow;
bool mXPCOMWillShutDown;
bool mXPCOMShuttingDown;
uint16_t mModalWindowCount;
bool mApplicationProvidedHiddenWindow;
uint32_t mScreenId;
};
#endif

View file

@ -0,0 +1,495 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "nsAppShellWindowEnumerator.h"
#include "nsIContentViewer.h"
#include "nsIDocShell.h"
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
#include "nsIDOMElement.h"
#include "nsIDOMWindow.h"
#include "nsIFactory.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIXULWindow.h"
#include "nsWindowMediator.h"
//
// static helper functions
//
static nsCOMPtr<nsIDOMNode> GetDOMNodeFromDocShell(nsIDocShell *aShell);
static void GetAttribute(nsIXULWindow *inWindow, const nsAString &inAttribute,
nsAString &outValue);
static void GetWindowType(nsIXULWindow* inWindow, nsString &outType);
nsCOMPtr<nsIDOMNode> GetDOMNodeFromDocShell(nsIDocShell *aShell)
{
nsCOMPtr<nsIDOMNode> node;
nsCOMPtr<nsIContentViewer> cv;
aShell->GetContentViewer(getter_AddRefs(cv));
if (cv) {
nsCOMPtr<nsIDOMDocument> domdoc(do_QueryInterface(cv->GetDocument()));
if (domdoc) {
nsCOMPtr<nsIDOMElement> element;
domdoc->GetDocumentElement(getter_AddRefs(element));
if (element)
node = element;
}
}
return node;
}
// generic "retrieve the value of a XUL attribute" function
void GetAttribute(nsIXULWindow *inWindow, const nsAString &inAttribute,
nsAString &outValue)
{
nsCOMPtr<nsIDocShell> shell;
if (inWindow && NS_SUCCEEDED(inWindow->GetDocShell(getter_AddRefs(shell)))) {
nsCOMPtr<nsIDOMNode> node(GetDOMNodeFromDocShell(shell));
if (node) {
nsCOMPtr<nsIDOMElement> webshellElement(do_QueryInterface(node));
if (webshellElement)
webshellElement->GetAttribute(inAttribute, outValue);
}
}
}
// retrieve the window type, stored as the value of a particular
// attribute in its XUL window tag
void GetWindowType(nsIXULWindow* aWindow, nsString &outType)
{
GetAttribute(aWindow, NS_LITERAL_STRING("windowtype"), outType);
}
//
// nsWindowInfo
//
nsWindowInfo::nsWindowInfo(nsIXULWindow* inWindow, int32_t inTimeStamp) :
mWindow(inWindow),mTimeStamp(inTimeStamp),mZLevel(nsIXULWindow::normalZ)
{
ReferenceSelf(true, true);
}
nsWindowInfo::~nsWindowInfo()
{
}
// return true if the window described by this WindowInfo has a type
// equal to the given type
bool nsWindowInfo::TypeEquals(const nsAString &aType)
{
nsAutoString rtnString;
GetWindowType(mWindow, rtnString);
return rtnString == aType;
}
// insert the struct into their two linked lists, in position after the
// given (independent) method arguments
void nsWindowInfo::InsertAfter(nsWindowInfo *inOlder , nsWindowInfo *inHigher)
{
if (inOlder) {
mOlder = inOlder;
mYounger = inOlder->mYounger;
mOlder->mYounger = this;
if (mOlder->mOlder == mOlder)
mOlder->mOlder = this;
mYounger->mOlder = this;
if (mYounger->mYounger == mYounger)
mYounger->mYounger = this;
}
if (inHigher) {
mHigher = inHigher;
mLower = inHigher->mLower;
mHigher->mLower = this;
if (mHigher->mHigher == mHigher)
mHigher->mHigher = this;
mLower->mHigher = this;
if (mLower->mLower == mLower)
mLower->mLower = this;
}
}
// remove the struct from its linked lists
void nsWindowInfo::Unlink(bool inAge, bool inZ)
{
if (inAge) {
mOlder->mYounger = mYounger;
mYounger->mOlder = mOlder;
}
if (inZ) {
mLower->mHigher = mHigher;
mHigher->mLower = mLower;
}
ReferenceSelf(inAge, inZ);
}
// initialize the struct to be a valid linked list of one element
void nsWindowInfo::ReferenceSelf(bool inAge, bool inZ)
{
if (inAge) {
mYounger = this;
mOlder = this;
}
if (inZ) {
mLower = this;
mHigher = this;
}
}
//
// nsAppShellWindowEnumerator
//
NS_IMPL_ISUPPORTS(nsAppShellWindowEnumerator, nsISimpleEnumerator)
nsAppShellWindowEnumerator::nsAppShellWindowEnumerator(
const char16_t* aTypeString,
nsWindowMediator& aMediator) :
mWindowMediator(&aMediator), mType(aTypeString), mCurrentPosition(nullptr)
{
mWindowMediator->AddEnumerator(this);
NS_ADDREF(mWindowMediator);
}
nsAppShellWindowEnumerator::~nsAppShellWindowEnumerator()
{
mWindowMediator->RemoveEnumerator(this);
NS_RELEASE(mWindowMediator);
}
// after mCurrentPosition has been initialized to point to the beginning
// of the appropriate list, adjust it if necessary
void nsAppShellWindowEnumerator::AdjustInitialPosition()
{
if (!mType.IsEmpty() && mCurrentPosition && !mCurrentPosition->TypeEquals(mType))
mCurrentPosition = FindNext();
}
NS_IMETHODIMP nsAppShellWindowEnumerator::HasMoreElements(bool *retval)
{
if (!retval)
return NS_ERROR_INVALID_ARG;
*retval = mCurrentPosition ? true : false;
return NS_OK;
}
// if a window is being removed adjust the iterator's current position
void nsAppShellWindowEnumerator::WindowRemoved(nsWindowInfo *inInfo)
{
if (mCurrentPosition == inInfo)
mCurrentPosition = FindNext();
}
//
// nsASDOMWindowEnumerator
//
nsASDOMWindowEnumerator::nsASDOMWindowEnumerator(
const char16_t* aTypeString,
nsWindowMediator& aMediator) :
nsAppShellWindowEnumerator(aTypeString, aMediator)
{
}
nsASDOMWindowEnumerator::~nsASDOMWindowEnumerator()
{
}
NS_IMETHODIMP nsASDOMWindowEnumerator::GetNext(nsISupports **retval)
{
if (!retval)
return NS_ERROR_INVALID_ARG;
*retval = nullptr;
while (mCurrentPosition) {
nsCOMPtr<nsPIDOMWindowOuter> domWindow;
nsWindowMediator::GetDOMWindow(mCurrentPosition->mWindow, domWindow);
mCurrentPosition = FindNext();
if (domWindow)
return CallQueryInterface(domWindow, retval);
}
return NS_OK;
}
//
// nsASXULWindowEnumerator
//
nsASXULWindowEnumerator::nsASXULWindowEnumerator(
const char16_t* aTypeString,
nsWindowMediator& aMediator) :
nsAppShellWindowEnumerator(aTypeString, aMediator)
{
}
nsASXULWindowEnumerator::~nsASXULWindowEnumerator()
{
}
NS_IMETHODIMP nsASXULWindowEnumerator::GetNext(nsISupports **retval)
{
if (!retval)
return NS_ERROR_INVALID_ARG;
*retval = nullptr;
if (mCurrentPosition) {
CallQueryInterface(mCurrentPosition->mWindow, retval);
mCurrentPosition = FindNext();
}
return NS_OK;
}
//
// nsASDOMWindowEarlyToLateEnumerator
//
nsASDOMWindowEarlyToLateEnumerator::nsASDOMWindowEarlyToLateEnumerator(
const char16_t *aTypeString,
nsWindowMediator &aMediator) :
nsASDOMWindowEnumerator(aTypeString, aMediator)
{
mCurrentPosition = aMediator.mOldestWindow;
AdjustInitialPosition();
}
nsASDOMWindowEarlyToLateEnumerator::~nsASDOMWindowEarlyToLateEnumerator()
{
}
nsWindowInfo *nsASDOMWindowEarlyToLateEnumerator::FindNext()
{
nsWindowInfo *info,
*listEnd;
bool allWindows = mType.IsEmpty();
// see nsXULWindowEarlyToLateEnumerator::FindNext
if (!mCurrentPosition)
return nullptr;
info = mCurrentPosition->mYounger;
listEnd = mWindowMediator->mOldestWindow;
while (info != listEnd) {
if (allWindows || info->TypeEquals(mType))
return info;
info = info->mYounger;
}
return nullptr;
}
//
// nsASXULWindowEarlyToLateEnumerator
//
nsASXULWindowEarlyToLateEnumerator::nsASXULWindowEarlyToLateEnumerator(
const char16_t *aTypeString,
nsWindowMediator &aMediator) :
nsASXULWindowEnumerator(aTypeString, aMediator)
{
mCurrentPosition = aMediator.mOldestWindow;
AdjustInitialPosition();
}
nsASXULWindowEarlyToLateEnumerator::~nsASXULWindowEarlyToLateEnumerator()
{
}
nsWindowInfo *nsASXULWindowEarlyToLateEnumerator::FindNext()
{
nsWindowInfo *info,
*listEnd;
bool allWindows = mType.IsEmpty();
/* mCurrentPosition null is assumed to mean that the enumerator has run
its course and is now basically useless. It could also be interpreted
to mean that it was created at a time when there were no windows. In
that case it would probably be more appropriate to check to see whether
windows have subsequently been added. But it's not guaranteed that we'll
pick up newly added windows anyway (if they occurred previous to our
current position) so we just don't worry about that. */
if (!mCurrentPosition)
return nullptr;
info = mCurrentPosition->mYounger;
listEnd = mWindowMediator->mOldestWindow;
while (info != listEnd) {
if (allWindows || info->TypeEquals(mType))
return info;
info = info->mYounger;
}
return nullptr;
}
//
// nsASDOMWindowFrontToBackEnumerator
//
nsASDOMWindowFrontToBackEnumerator::nsASDOMWindowFrontToBackEnumerator(
const char16_t *aTypeString,
nsWindowMediator &aMediator) :
nsASDOMWindowEnumerator(aTypeString, aMediator)
{
mCurrentPosition = aMediator.mTopmostWindow;
AdjustInitialPosition();
}
nsASDOMWindowFrontToBackEnumerator::~nsASDOMWindowFrontToBackEnumerator()
{
}
nsWindowInfo *nsASDOMWindowFrontToBackEnumerator::FindNext()
{
nsWindowInfo *info,
*listEnd;
bool allWindows = mType.IsEmpty();
// see nsXULWindowEarlyToLateEnumerator::FindNext
if (!mCurrentPosition)
return nullptr;
info = mCurrentPosition->mLower;
listEnd = mWindowMediator->mTopmostWindow;
while (info != listEnd) {
if (allWindows || info->TypeEquals(mType))
return info;
info = info->mLower;
}
return nullptr;
}
//
// nsASXULWindowFrontToBackEnumerator
//
nsASXULWindowFrontToBackEnumerator::nsASXULWindowFrontToBackEnumerator(
const char16_t *aTypeString,
nsWindowMediator &aMediator) :
nsASXULWindowEnumerator(aTypeString, aMediator)
{
mCurrentPosition = aMediator.mTopmostWindow;
AdjustInitialPosition();
}
nsASXULWindowFrontToBackEnumerator::~nsASXULWindowFrontToBackEnumerator()
{
}
nsWindowInfo *nsASXULWindowFrontToBackEnumerator::FindNext()
{
nsWindowInfo *info,
*listEnd;
bool allWindows = mType.IsEmpty();
// see nsXULWindowEarlyToLateEnumerator::FindNext
if (!mCurrentPosition)
return nullptr;
info = mCurrentPosition->mLower;
listEnd = mWindowMediator->mTopmostWindow;
while (info != listEnd) {
if (allWindows || info->TypeEquals(mType))
return info;
info = info->mLower;
}
return nullptr;
}
//
// nsASDOMWindowBackToFrontEnumerator
//
nsASDOMWindowBackToFrontEnumerator::nsASDOMWindowBackToFrontEnumerator(
const char16_t *aTypeString,
nsWindowMediator &aMediator) :
nsASDOMWindowEnumerator(aTypeString, aMediator)
{
mCurrentPosition = aMediator.mTopmostWindow ?
aMediator.mTopmostWindow->mHigher : nullptr;
AdjustInitialPosition();
}
nsASDOMWindowBackToFrontEnumerator::~nsASDOMWindowBackToFrontEnumerator()
{
}
nsWindowInfo *nsASDOMWindowBackToFrontEnumerator::FindNext()
{
nsWindowInfo *info,
*listEnd;
bool allWindows = mType.IsEmpty();
// see nsXULWindowEarlyToLateEnumerator::FindNext
if (!mCurrentPosition)
return nullptr;
info = mCurrentPosition->mHigher;
listEnd = mWindowMediator->mTopmostWindow;
if (listEnd)
listEnd = listEnd->mHigher;
while (info != listEnd) {
if (allWindows || info->TypeEquals(mType))
return info;
info = info->mHigher;
}
return nullptr;
}
//
// nsASXULWindowBackToFrontEnumerator
//
nsASXULWindowBackToFrontEnumerator::nsASXULWindowBackToFrontEnumerator(
const char16_t *aTypeString,
nsWindowMediator &aMediator) :
nsASXULWindowEnumerator(aTypeString, aMediator)
{
mCurrentPosition = aMediator.mTopmostWindow ?
aMediator.mTopmostWindow->mHigher : nullptr;
AdjustInitialPosition();
}
nsASXULWindowBackToFrontEnumerator::~nsASXULWindowBackToFrontEnumerator()
{
}
nsWindowInfo *nsASXULWindowBackToFrontEnumerator::FindNext()
{
nsWindowInfo *info,
*listEnd;
bool allWindows = mType.IsEmpty();
// see nsXULWindowEarlyToLateEnumerator::FindNext
if (!mCurrentPosition)
return nullptr;
info = mCurrentPosition->mHigher;
listEnd = mWindowMediator->mTopmostWindow;
if (listEnd)
listEnd = listEnd->mHigher;
while (info != listEnd) {
if (allWindows || info->TypeEquals(mType))
return info;
info = info->mHigher;
}
return nullptr;
}

View file

@ -0,0 +1,166 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 nsAppShellWindowEnumerator_h
#define nsAppShellWindowEnumerator_h
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsISimpleEnumerator.h"
#include "nsIXULWindow.h"
class nsWindowMediator;
//
// nsWindowInfo
//
struct nsWindowInfo
{
nsWindowInfo(nsIXULWindow* inWindow, int32_t inTimeStamp);
~nsWindowInfo();
nsCOMPtr<nsIXULWindow> mWindow;
int32_t mTimeStamp;
uint32_t mZLevel;
// each struct is in two, independent, circular, doubly-linked lists
nsWindowInfo *mYounger, // next younger in sequence
*mOlder;
nsWindowInfo *mLower, // next lower in z-order
*mHigher;
bool TypeEquals(const nsAString &aType);
void InsertAfter(nsWindowInfo *inOlder, nsWindowInfo *inHigher);
void Unlink(bool inAge, bool inZ);
void ReferenceSelf(bool inAge, bool inZ);
};
//
// virtual enumerators
//
class nsAppShellWindowEnumerator : public nsISimpleEnumerator {
friend class nsWindowMediator;
public:
nsAppShellWindowEnumerator(const char16_t* aTypeString,
nsWindowMediator& inMediator);
NS_IMETHOD GetNext(nsISupports **retval) override = 0;
NS_IMETHOD HasMoreElements(bool *retval) override;
NS_DECL_ISUPPORTS
protected:
virtual ~nsAppShellWindowEnumerator();
void AdjustInitialPosition();
virtual nsWindowInfo *FindNext() = 0;
void WindowRemoved(nsWindowInfo *inInfo);
nsWindowMediator *mWindowMediator;
nsString mType;
nsWindowInfo *mCurrentPosition;
};
class nsASDOMWindowEnumerator : public nsAppShellWindowEnumerator {
public:
nsASDOMWindowEnumerator(const char16_t* aTypeString,
nsWindowMediator& inMediator);
virtual ~nsASDOMWindowEnumerator();
NS_IMETHOD GetNext(nsISupports **retval);
};
class nsASXULWindowEnumerator : public nsAppShellWindowEnumerator {
public:
nsASXULWindowEnumerator(const char16_t* aTypeString,
nsWindowMediator& inMediator);
virtual ~nsASXULWindowEnumerator();
NS_IMETHOD GetNext(nsISupports **retval);
};
//
// concrete enumerators
//
class nsASDOMWindowEarlyToLateEnumerator : public nsASDOMWindowEnumerator {
public:
nsASDOMWindowEarlyToLateEnumerator(const char16_t* aTypeString,
nsWindowMediator& inMediator);
virtual ~nsASDOMWindowEarlyToLateEnumerator();
protected:
virtual nsWindowInfo *FindNext();
};
class nsASXULWindowEarlyToLateEnumerator : public nsASXULWindowEnumerator {
public:
nsASXULWindowEarlyToLateEnumerator(const char16_t* aTypeString,
nsWindowMediator& inMediator);
virtual ~nsASXULWindowEarlyToLateEnumerator();
protected:
virtual nsWindowInfo *FindNext();
};
class nsASDOMWindowFrontToBackEnumerator : public nsASDOMWindowEnumerator {
public:
nsASDOMWindowFrontToBackEnumerator(const char16_t* aTypeString,
nsWindowMediator& inMediator);
virtual ~nsASDOMWindowFrontToBackEnumerator();
protected:
virtual nsWindowInfo *FindNext();
};
class nsASXULWindowFrontToBackEnumerator : public nsASXULWindowEnumerator {
public:
nsASXULWindowFrontToBackEnumerator(const char16_t* aTypeString,
nsWindowMediator& inMediator);
virtual ~nsASXULWindowFrontToBackEnumerator();
protected:
virtual nsWindowInfo *FindNext();
};
class nsASDOMWindowBackToFrontEnumerator : public nsASDOMWindowEnumerator {
public:
nsASDOMWindowBackToFrontEnumerator(const char16_t* aTypeString,
nsWindowMediator& inMediator);
virtual ~nsASDOMWindowBackToFrontEnumerator();
protected:
virtual nsWindowInfo *FindNext();
};
class nsASXULWindowBackToFrontEnumerator : public nsASXULWindowEnumerator {
public:
nsASXULWindowBackToFrontEnumerator(const char16_t* aTypeString,
nsWindowMediator& inMediator);
virtual ~nsASXULWindowBackToFrontEnumerator();
protected:
virtual nsWindowInfo *FindNext();
};
#endif

View file

@ -0,0 +1,561 @@
/* -*- Mode: C++; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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/. */
// Local Includes
#include "nsChromeTreeOwner.h"
#include "nsXULWindow.h"
// Helper Classes
#include "nsString.h"
#include "nsIEmbeddingSiteWindow.h"
#include "nsIServiceManager.h"
#include "nsIDocShellTreeItem.h"
// Interfaces needed to include
#include "nsIPrompt.h"
#include "nsIAuthPrompt.h"
#include "nsIBrowserDOMWindow.h"
#include "nsIWebProgress.h"
#include "nsIWidget.h"
#include "nsIWindowMediator.h"
#include "nsIDOMChromeWindow.h"
#include "nsIDOMNode.h"
#include "nsIDOMElement.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMXULElement.h"
#include "nsIXULBrowserWindow.h"
#include "mozilla/dom/Element.h"
using namespace mozilla;
//*****************************************************************************
// nsChromeTreeOwner string literals
//*****************************************************************************
struct nsChromeTreeOwnerLiterals
{
const nsLiteralString kPersist;
const nsLiteralString kScreenX;
const nsLiteralString kScreenY;
const nsLiteralString kWidth;
const nsLiteralString kHeight;
const nsLiteralString kSizemode;
const nsLiteralString kSpace;
nsChromeTreeOwnerLiterals()
: NS_LITERAL_STRING_INIT(kPersist,"persist")
, NS_LITERAL_STRING_INIT(kScreenX,"screenX")
, NS_LITERAL_STRING_INIT(kScreenY,"screenY")
, NS_LITERAL_STRING_INIT(kWidth,"width")
, NS_LITERAL_STRING_INIT(kHeight,"height")
, NS_LITERAL_STRING_INIT(kSizemode,"sizemode")
, NS_LITERAL_STRING_INIT(kSpace," ")
{}
};
static nsChromeTreeOwnerLiterals *gLiterals;
nsresult
nsChromeTreeOwner::InitGlobals()
{
NS_ASSERTION(gLiterals == nullptr, "already initialized");
gLiterals = new nsChromeTreeOwnerLiterals();
return NS_OK;
}
void
nsChromeTreeOwner::FreeGlobals()
{
delete gLiterals;
gLiterals = nullptr;
}
//*****************************************************************************
//*** nsChromeTreeOwner: Object Management
//*****************************************************************************
nsChromeTreeOwner::nsChromeTreeOwner() : mXULWindow(nullptr)
{
}
nsChromeTreeOwner::~nsChromeTreeOwner()
{
}
//*****************************************************************************
// nsChromeTreeOwner::nsISupports
//*****************************************************************************
NS_IMPL_ADDREF(nsChromeTreeOwner)
NS_IMPL_RELEASE(nsChromeTreeOwner)
NS_INTERFACE_MAP_BEGIN(nsChromeTreeOwner)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDocShellTreeOwner)
NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeOwner)
NS_INTERFACE_MAP_ENTRY(nsIBaseWindow)
NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_END
//*****************************************************************************
// nsChromeTreeOwner::nsIInterfaceRequestor
//*****************************************************************************
NS_IMETHODIMP nsChromeTreeOwner::GetInterface(const nsIID& aIID, void** aSink)
{
NS_ENSURE_ARG_POINTER(aSink);
if(aIID.Equals(NS_GET_IID(nsIPrompt))) {
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->GetInterface(aIID, aSink);
}
if(aIID.Equals(NS_GET_IID(nsIAuthPrompt))) {
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->GetInterface(aIID, aSink);
}
if(aIID.Equals(NS_GET_IID(nsIWebBrowserChrome))) {
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->GetInterface(aIID, aSink);
}
if (aIID.Equals(NS_GET_IID(nsIEmbeddingSiteWindow))) {
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->GetInterface(aIID, aSink);
}
if (aIID.Equals(NS_GET_IID(nsIXULWindow))) {
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->QueryInterface(aIID, aSink);
}
return QueryInterface(aIID, aSink);
}
//*****************************************************************************
// nsChromeTreeOwner::nsIDocShellTreeOwner
//*****************************************************************************
NS_IMETHODIMP
nsChromeTreeOwner::ContentShellAdded(nsIDocShellTreeItem* aContentShell,
bool aPrimary, bool aTargetable,
const nsAString& aID)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->ContentShellAdded(aContentShell, aPrimary, aTargetable,
aID);
}
NS_IMETHODIMP
nsChromeTreeOwner::ContentShellRemoved(nsIDocShellTreeItem* aContentShell)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->ContentShellRemoved(aContentShell);
}
NS_IMETHODIMP nsChromeTreeOwner::GetPrimaryContentShell(nsIDocShellTreeItem** aShell)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->GetPrimaryContentShell(aShell);
}
NS_IMETHODIMP
nsChromeTreeOwner::TabParentAdded(nsITabParent* aTab, bool aPrimary)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->TabParentAdded(aTab, aPrimary);
}
NS_IMETHODIMP
nsChromeTreeOwner::TabParentRemoved(nsITabParent* aTab)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->TabParentRemoved(aTab);
}
NS_IMETHODIMP
nsChromeTreeOwner::GetPrimaryTabParent(nsITabParent** aTab)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->GetPrimaryTabParent(aTab);
}
NS_IMETHODIMP
nsChromeTreeOwner::GetPrimaryContentSize(int32_t* aWidth,
int32_t* aHeight)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->GetPrimaryContentSize(aWidth, aHeight);
}
NS_IMETHODIMP
nsChromeTreeOwner::SetPrimaryContentSize(int32_t aWidth,
int32_t aHeight)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->SetPrimaryContentSize(aWidth, aHeight);
}
NS_IMETHODIMP
nsChromeTreeOwner::GetRootShellSize(int32_t* aWidth,
int32_t* aHeight)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->GetRootShellSize(aWidth, aHeight);
}
NS_IMETHODIMP
nsChromeTreeOwner::SetRootShellSize(int32_t aWidth,
int32_t aHeight)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->SetRootShellSize(aWidth, aHeight);
}
NS_IMETHODIMP nsChromeTreeOwner::SizeShellTo(nsIDocShellTreeItem* aShellItem,
int32_t aCX, int32_t aCY)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->SizeShellTo(aShellItem, aCX, aCY);
}
NS_IMETHODIMP
nsChromeTreeOwner::SetPersistence(bool aPersistPosition,
bool aPersistSize,
bool aPersistSizeMode)
{
NS_ENSURE_STATE(mXULWindow);
nsCOMPtr<dom::Element> docShellElement = mXULWindow->GetWindowDOMElement();
if (!docShellElement)
return NS_ERROR_FAILURE;
nsAutoString persistString;
docShellElement->GetAttribute(gLiterals->kPersist, persistString);
bool saveString = false;
int32_t index;
#define FIND_PERSIST_STRING(aString, aCond) \
index = persistString.Find(aString); \
if (!aCond && index > kNotFound) { \
persistString.Cut(index, aString.Length()); \
saveString = true; \
} else if (aCond && index == kNotFound) { \
persistString.Append(gLiterals->kSpace + aString); \
saveString = true; \
}
FIND_PERSIST_STRING(gLiterals->kScreenX, aPersistPosition);
FIND_PERSIST_STRING(gLiterals->kScreenY, aPersistPosition);
FIND_PERSIST_STRING(gLiterals->kWidth, aPersistSize);
FIND_PERSIST_STRING(gLiterals->kHeight, aPersistSize);
FIND_PERSIST_STRING(gLiterals->kSizemode, aPersistSizeMode);
ErrorResult rv;
if (saveString) {
docShellElement->SetAttribute(gLiterals->kPersist, persistString, rv);
}
return NS_OK;
}
NS_IMETHODIMP
nsChromeTreeOwner::GetPersistence(bool* aPersistPosition,
bool* aPersistSize,
bool* aPersistSizeMode)
{
NS_ENSURE_STATE(mXULWindow);
nsCOMPtr<dom::Element> docShellElement = mXULWindow->GetWindowDOMElement();
if (!docShellElement)
return NS_ERROR_FAILURE;
nsAutoString persistString;
docShellElement->GetAttribute(gLiterals->kPersist, persistString);
// data structure doesn't quite match the question, but it's close enough
// for what we want (since this method is never actually called...)
if (aPersistPosition)
*aPersistPosition = persistString.Find(gLiterals->kScreenX) > kNotFound ||
persistString.Find(gLiterals->kScreenY) > kNotFound;
if (aPersistSize)
*aPersistSize = persistString.Find(gLiterals->kWidth) > kNotFound ||
persistString.Find(gLiterals->kHeight) > kNotFound;
if (aPersistSizeMode)
*aPersistSizeMode = persistString.Find(gLiterals->kSizemode) > kNotFound;
return NS_OK;
}
NS_IMETHODIMP
nsChromeTreeOwner::GetTargetableShellCount(uint32_t* aResult)
{
*aResult = 0;
return NS_OK;
}
NS_IMETHODIMP
nsChromeTreeOwner::GetHasPrimaryContent(bool* aResult)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->GetHasPrimaryContent(aResult);
}
//*****************************************************************************
// nsChromeTreeOwner::nsIBaseWindow
//*****************************************************************************
NS_IMETHODIMP nsChromeTreeOwner::InitWindow(nativeWindow aParentNativeWindow,
nsIWidget* parentWidget, int32_t x, int32_t y, int32_t cx, int32_t cy)
{
// Ignore widget parents for now. Don't think those are a vaild thing to call.
NS_ENSURE_SUCCESS(SetPositionAndSize(x, y, cx, cy, 0), NS_ERROR_FAILURE);
return NS_OK;
}
NS_IMETHODIMP nsChromeTreeOwner::Create()
{
NS_ASSERTION(false, "You can't call this");
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP nsChromeTreeOwner::Destroy()
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->Destroy();
}
NS_IMETHODIMP nsChromeTreeOwner::GetUnscaledDevicePixelsPerCSSPixel(double *aScale)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->GetUnscaledDevicePixelsPerCSSPixel(aScale);
}
NS_IMETHODIMP nsChromeTreeOwner::GetDevicePixelsPerDesktopPixel(double *aScale)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->GetDevicePixelsPerDesktopPixel(aScale);
}
NS_IMETHODIMP nsChromeTreeOwner::SetPositionDesktopPix(int32_t x, int32_t y)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->SetPositionDesktopPix(x, y);
}
NS_IMETHODIMP nsChromeTreeOwner::SetPosition(int32_t x, int32_t y)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->SetPosition(x, y);
}
NS_IMETHODIMP nsChromeTreeOwner::GetPosition(int32_t* x, int32_t* y)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->GetPosition(x, y);
}
NS_IMETHODIMP nsChromeTreeOwner::SetSize(int32_t cx, int32_t cy, bool fRepaint)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->SetSize(cx, cy, fRepaint);
}
NS_IMETHODIMP nsChromeTreeOwner::GetSize(int32_t* cx, int32_t* cy)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->GetSize(cx, cy);
}
NS_IMETHODIMP nsChromeTreeOwner::SetPositionAndSize(int32_t x, int32_t y, int32_t cx,
int32_t cy, uint32_t aFlags)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->SetPositionAndSize(x, y, cx, cy, aFlags);
}
NS_IMETHODIMP nsChromeTreeOwner::GetPositionAndSize(int32_t* x, int32_t* y, int32_t* cx,
int32_t* cy)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->GetPositionAndSize(x, y, cx, cy);
}
NS_IMETHODIMP nsChromeTreeOwner::Repaint(bool aForce)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->Repaint(aForce);
}
NS_IMETHODIMP nsChromeTreeOwner::GetParentWidget(nsIWidget** aParentWidget)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->GetParentWidget(aParentWidget);
}
NS_IMETHODIMP nsChromeTreeOwner::SetParentWidget(nsIWidget* aParentWidget)
{
NS_ASSERTION(false, "You can't call this");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsChromeTreeOwner::GetParentNativeWindow(nativeWindow* aParentNativeWindow)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->GetParentNativeWindow(aParentNativeWindow);
}
NS_IMETHODIMP nsChromeTreeOwner::SetParentNativeWindow(nativeWindow aParentNativeWindow)
{
NS_ASSERTION(false, "You can't call this");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsChromeTreeOwner::GetNativeHandle(nsAString& aNativeHandle)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->GetNativeHandle(aNativeHandle);
}
NS_IMETHODIMP nsChromeTreeOwner::GetVisibility(bool* aVisibility)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->GetVisibility(aVisibility);
}
NS_IMETHODIMP nsChromeTreeOwner::SetVisibility(bool aVisibility)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->SetVisibility(aVisibility);
}
NS_IMETHODIMP nsChromeTreeOwner::GetEnabled(bool *aEnabled)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->GetEnabled(aEnabled);
}
NS_IMETHODIMP nsChromeTreeOwner::SetEnabled(bool aEnable)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->SetEnabled(aEnable);
}
NS_IMETHODIMP nsChromeTreeOwner::GetMainWidget(nsIWidget** aMainWidget)
{
NS_ENSURE_ARG_POINTER(aMainWidget);
NS_ENSURE_STATE(mXULWindow);
*aMainWidget = mXULWindow->mWindow;
NS_IF_ADDREF(*aMainWidget);
return NS_OK;
}
NS_IMETHODIMP nsChromeTreeOwner::SetFocus()
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->SetFocus();
}
NS_IMETHODIMP nsChromeTreeOwner::GetTitle(char16_t** aTitle)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->GetTitle(aTitle);
}
NS_IMETHODIMP nsChromeTreeOwner::SetTitle(const char16_t* aTitle)
{
NS_ENSURE_STATE(mXULWindow);
return mXULWindow->SetTitle(aTitle);
}
//*****************************************************************************
// nsChromeTreeOwner::nsIWebProgressListener
//*****************************************************************************
NS_IMETHODIMP
nsChromeTreeOwner::OnProgressChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
int32_t aCurSelfProgress,
int32_t aMaxSelfProgress,
int32_t aCurTotalProgress,
int32_t aMaxTotalProgress)
{
return NS_OK;
}
NS_IMETHODIMP
nsChromeTreeOwner::OnStateChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
uint32_t aProgressStateFlags,
nsresult aStatus)
{
return NS_OK;
}
NS_IMETHODIMP nsChromeTreeOwner::OnLocationChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
nsIURI* aLocation,
uint32_t aFlags)
{
bool itsForYou = true;
if (aWebProgress) {
NS_ENSURE_STATE(mXULWindow);
nsCOMPtr<mozIDOMWindowProxy> progressWin;
aWebProgress->GetDOMWindow(getter_AddRefs(progressWin));
nsCOMPtr<nsIDocShell> docshell;
mXULWindow->GetDocShell(getter_AddRefs(docshell));
// XXXkhuey this is totally wrong, bug 1223303.
nsCOMPtr<mozIDOMWindowProxy> ourWin(do_QueryInterface(docshell));
if (ourWin != progressWin)
itsForYou = false;
}
// If loading a new root .xul document, then redo chrome.
if (itsForYou) {
NS_ENSURE_STATE(mXULWindow);
mXULWindow->mChromeLoaded = false;
}
return NS_OK;
}
NS_IMETHODIMP
nsChromeTreeOwner::OnStatusChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
nsresult aStatus,
const char16_t* aMessage)
{
return NS_OK;
}
NS_IMETHODIMP
nsChromeTreeOwner::OnSecurityChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest,
uint32_t state)
{
return NS_OK;
}
//*****************************************************************************
// nsChromeTreeOwner: Helpers
//*****************************************************************************
//*****************************************************************************
// nsChromeTreeOwner: Accessors
//*****************************************************************************
void nsChromeTreeOwner::XULWindow(nsXULWindow* aXULWindow)
{
mXULWindow = aXULWindow;
}
nsXULWindow* nsChromeTreeOwner::XULWindow()
{
return mXULWindow;
}

View file

@ -0,0 +1,53 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 nsChromeTreeOwner_h__
#define nsChromeTreeOwner_h__
// Helper Classes
#include "nsCOMPtr.h"
// Interfaces Needed
#include "nsIBaseWindow.h"
#include "nsIDocShellTreeOwner.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIWebProgressListener.h"
#include "nsWeakReference.h"
class nsXULWindow;
class nsChromeTreeOwner : public nsIDocShellTreeOwner,
public nsIBaseWindow,
public nsIInterfaceRequestor,
public nsIWebProgressListener,
public nsSupportsWeakReference
{
friend class nsXULWindow;
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSIBASEWINDOW
NS_DECL_NSIDOCSHELLTREEOWNER
NS_DECL_NSIWEBPROGRESSLISTENER
static nsresult InitGlobals();
static void FreeGlobals();
protected:
nsChromeTreeOwner();
virtual ~nsChromeTreeOwner();
void XULWindow(nsXULWindow* aXULWindow);
nsXULWindow* XULWindow();
protected:
nsXULWindow* mXULWindow;
};
#endif /* nsChromeTreeOwner_h__ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,63 @@
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 nsContentTreeOwner_h__
#define nsContentTreeOwner_h__
// Helper Classes
#include "nsCOMPtr.h"
#include "nsString.h"
// Interfaces Needed
#include "nsIBaseWindow.h"
#include "nsIDocShellTreeOwner.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIWebBrowserChrome3.h"
#include "nsIWindowProvider.h"
class nsXULWindow;
class nsSiteWindow;
class nsContentTreeOwner final : public nsIDocShellTreeOwner,
public nsIBaseWindow,
public nsIInterfaceRequestor,
public nsIWebBrowserChrome3,
public nsIWindowProvider
{
friend class nsXULWindow;
friend class nsSiteWindow;
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIBASEWINDOW
NS_DECL_NSIDOCSHELLTREEOWNER
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSIWEBBROWSERCHROME
NS_DECL_NSIWEBBROWSERCHROME2
NS_DECL_NSIWEBBROWSERCHROME3
NS_DECL_NSIWINDOWPROVIDER
protected:
explicit nsContentTreeOwner(bool fPrimary);
virtual ~nsContentTreeOwner();
void XULWindow(nsXULWindow* aXULWindow);
nsXULWindow* XULWindow();
protected:
nsXULWindow *mXULWindow;
nsSiteWindow *mSiteWindow;
bool mPrimary;
bool mContentTitleSetting;
nsString mWindowTitleModifier;
nsString mTitleSeparator;
nsString mTitlePreface;
nsString mTitleDefault;
};
#endif /* nsContentTreeOwner_h__ */

View file

@ -0,0 +1,150 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "nsISupports.idl"
interface nsIXULWindow;
interface nsIWindowlessBrowser;
interface nsIURI;
interface mozIDOMWindowProxy;
interface nsIAppShell;
interface nsITabParent;
[ptr] native JSContext(JSContext);
%{C++
#include "js/TypeDecls.h"
%}
[scriptable, uuid(19266025-354c-4bb9-986b-3483b2b1cdef)]
interface nsIAppShellService : nsISupports
{
/**
* Create a window, which will be initially invisible.
* @param aParent the parent window. Can be null.
* @param aUrl the contents of the new window.
* @param aChromeMask chrome flags affecting the kind of OS border
* given to the window. see nsIBrowserWindow for
* bit/flag definitions.
* @param aCallbacks interface providing C++ hooks for window initialization
* before the window is made visible. Can be null.
* Deprecated.
* @param aInitialWidth width, in pixels, of the window. Width of window
* at creation. Can be overridden by the "width"
* tag in the XUL. Set to NS_SIZETOCONTENT to force
* the window to wrap to its contents.
* @param aInitialHeight like aInitialWidth, but subtly different.
* @param aOpeningTab The TabParent that requested that this window be opened.
* Can be left null.
* @param aOpenerWindow The Window Proxy which requested that this window be opened.
* Can be left null.
*/
const long SIZE_TO_CONTENT = -1;
nsIXULWindow createTopLevelWindow(in nsIXULWindow aParent,
in nsIURI aUrl,
in uint32_t aChromeMask,
in long aInitialWidth,
in long aInitialHeight,
in nsITabParent aOpeningTab,
in mozIDOMWindowProxy aOpenerWindow);
/**
* This is the constructor for creating an invisible DocShell.
* It is used to simulate DOM windows without an actual physical
* representation.
* @param aIsChrome Set true if you want to use it for chrome content.
*/
nsIWindowlessBrowser createWindowlessBrowser([optional] in bool aIsChrome);
[noscript]
void createHiddenWindow();
void destroyHiddenWindow();
/**
* B2G multi-screen support. When open another top-level window on b2g,
* a screen ID is needed for identifying which screen this window is
* opened to.
* @param aScreenId Differentiate screens of windows. It is platform-
* specific due to the hardware limitation for now.
*/
[noscript]
void setScreenId(in uint32_t aScreenId);
/**
* Return the (singleton) application hidden window, automatically created
* and maintained by this AppShellService.
* @param aResult the hidden window. Do not unhide hidden window.
* Do not taunt hidden window.
*/
readonly attribute nsIXULWindow hiddenWindow;
/**
* Return the (singleton) application hidden window, automatically created
* and maintained by this AppShellService.
* @param aResult the hidden window. Do not unhide hidden window.
* Do not taunt hidden window.
*/
readonly attribute mozIDOMWindowProxy hiddenDOMWindow;
/**
* Return the (singleton) application hidden private window, automatically
* created and maintained by this AppShellService. This window is created
* in private browsing mode.
* @param aResult the hidden private window. Do not unhide hidden window.
* Do not taunt hidden window.
*/
readonly attribute nsIXULWindow hiddenPrivateWindow;
/**
* Return the (singleton) application hidden private window, automatically
* created and maintained by this AppShellService. This window is created
* in private browsing mode.
* @param aResult the hidden private window. Do not unhide hidden window.
* Do not taunt hidden window.
*/
readonly attribute mozIDOMWindowProxy hiddenPrivateDOMWindow;
/**
* Return true if the application hidden window was provided by the
* application. If it wasn't, the default hidden window was used. This will
* usually be false on all non-mac platforms.
*/
readonly attribute boolean applicationProvidedHiddenWindow;
/**
* Add a window to the application's registry of windows. These windows
* are generally shown in the Windows taskbar, and the application
* knows it can't quit until it's out of registered windows.
* @param aWindow the window to register
* @note When this method is successful, it fires the global notification
* "xul-window-registered"
*/
void registerTopLevelWindow(in nsIXULWindow aWindow);
/**
* Remove a window from the application's window registry. Note that
* this method won't automatically attempt to quit the app when
* the last window is unregistered. For that, see Quit().
* @param aWindow you see the pattern
*/
void unregisterTopLevelWindow(in nsIXULWindow aWindow);
/**
* Whether the hidden private window has been lazily created.
*/
[noscript]
readonly attribute boolean hasHiddenPrivateWindow;
/**
* Start/stop tracking lags in the event loop.
* If the event loop gets unresponsive, a "event-loop-lag" notification
* is sent. Note that calling `startEventLoopLagTracking` when tracking
* is already enabled has no effect.
* @return true if tracking succeeded.
*/
bool startEventLoopLagTracking();
void stopEventLoopLagTracking();
};

View file

@ -0,0 +1,35 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
/**
* This is the interface to the Popup Window Manager: an object which
* maintains popup window permissions by website.
*/
#include "nsISupports.idl"
interface nsIPrincipal;
[scriptable, uuid(66386aa9-2088-4bae-82c7-9f58bc02be64)]
interface nsIPopupWindowManager : nsISupports {
/**
* These values are returned by the testPermission method
*/
const uint32_t ALLOW_POPUP = 1;
const uint32_t DENY_POPUP = 2;
const uint32_t ALLOW_POPUP_WITH_PREJUDICE = 3;
/**
* Test whether a website has permission to show a popup window.
* @param principal is the principal to be tested
* @return one of the enumerated permission actions defined above
*/
uint32_t testPermission(in nsIPrincipal principal);
};
%{ C++
#define NS_POPUPWINDOWMANAGER_CONTRACTID "@mozilla.org/PopupWindowManager;1"
%}

View file

@ -0,0 +1,206 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 "nsISupports.idl"
#include "nsISimpleEnumerator.idl"
%{C++
#define NS_WINDOWMEDIATOR_CID \
{ 0x79a2b7cc, 0xf05b, 0x4605, \
{ 0xbf, 0xa0, 0xfa, 0xc5, 0x4f, 0x27, 0xee, 0xc8 } }
#define NS_WINDOWMEDIATOR_CONTRACTID \
"@mozilla.org/appshell/window-mediator;1"
%}
interface mozIDOMWindow;
interface mozIDOMWindowProxy;
interface nsIXULWindow;
interface nsIWidget;
interface nsIWindowMediatorListener;
[scriptable, uuid(df0da056-357d-427f-bafd-e6cbf19c9381)]
interface nsIWindowMediator: nsISupports
{
/** Return an enumerator which iterates over all windows of type aWindowType
* from the oldest window to the youngest.
* @param aWindowType the returned enumerator will enumerate only
* windows of this type. ("type" is the
* |windowtype| attribute of the XML <window> element.)
* If null, all windows will be enumerated.
* @return an enumerator of nsIDOMWindows. Note that windows close
* asynchronously in many cases, so windows returned from this
* enumerator can have .closed set to true. Caveat enumerator!
*/
nsISimpleEnumerator getEnumerator(in wstring aWindowType);
/** Identical to getEnumerator except:
* @return an enumerator of nsIXULWindows
*/
nsISimpleEnumerator getXULWindowEnumerator(in wstring aWindowType);
/** Return an enumerator which iterates over all windows of type aWindowType
* in their z (front-to-back) order. Note this interface makes
* no requirement that a window couldn't be revisited if windows
* are re-ordered while z-order enumerators are active.
* @param aWindowType the returned enumerator will enumerate only
* windows of this type. ("type" is the
* |windowtype| attribute of the XML <window> element.)
* If null, all windows will be enumerated.
* @param aFrontToBack if true, the enumerator enumerates windows in order
* from front to back. back to front if false.
* @return an enumerator of nsIDOMWindows
*/
nsISimpleEnumerator getZOrderDOMWindowEnumerator(in wstring aWindowType,
in boolean aFrontToBack);
/** Identical to getZOrderDOMWindowEnumerator except:
* @return an enumerator of nsIXULWindows
*/
nsISimpleEnumerator getZOrderXULWindowEnumerator(in wstring aWindowType,
in boolean aFrontToBack);
/** This is a shortcut for simply fetching the first window in
* front to back order.
* @param aWindowType return the topmost window of this type.
* ("type" is the |windowtype| attribute of
* the XML <window> element.)
* If null, return the topmost window of any type.
* @return the topmost window
*/
mozIDOMWindowProxy getMostRecentWindow(in wstring aWindowType);
/**
* Return the outer window with the given ID, if any. Can return null.
*/
mozIDOMWindowProxy getOuterWindowWithId(in unsigned long long aOuterWindowID);
/**
* Return the inner window with the given current window ID, if any.
* Can return null if no inner window with the ID exists or if it's not
* a current inner anymore.
*/
mozIDOMWindow getCurrentInnerWindowWithId(in unsigned long long aInnerWindowID);
/** Add the window to the list of known windows. Listeners (see
* addListener) will be notified through their onOpenWindow method.
* @param aWindow the window to add
*/
[noscript] void registerWindow(in nsIXULWindow aWindow);
/** Remove the window from the list of known windows. Listeners (see
* addListener) will be be notified through their onCloseWindow method.
* @param aWindow the window to remove
*/
[noscript] void unregisterWindow(in nsIXULWindow aWindow);
/** Call this method when a window gains focus. It's a primitive means of
* determining the most recent window. It's no longer necessary and it
* really should be removed.
* @param aWindow the window which has gained focus
*/
[noscript] void updateWindowTimeStamp(in nsIXULWindow aWindow);
/** Call this method when a window's title changes. Listeners (see
* addListener) will be notified through their onWindowTitleChange method.
* @param aWindow the window whose title has changed
* @param inTitle the window's new title
*/
[noscript] void updateWindowTitle(in nsIXULWindow aWindow,
in wstring inTitle );
/* z-ordering: */
const unsigned long zLevelTop = 1;
const unsigned long zLevelBottom = 2;
const unsigned long zLevelBelow = 3; // below some window
/** A window wants to be moved in z-order. Calculate whether and how
* it should be constrained. Note this method is advisory only:
* it changes nothing either in WindowMediator's internal state
* or with the window.
* Note it compares the nsIXULWindow to nsIWidgets. A pure interface
* would use all nsIXULWindows. But we expect this to be called from
* callbacks originating in native window code. They are expected to
* hand us comparison values which are pulled from general storage
* in the native widget, and may not correspond to an nsIWidget at all.
* For that reason this interface requires only objects one step
* removed from the native window (nsIWidgets), and its implementation
* must be very understanding of what may be completely invalid
* pointers in those parameters.
*
* @param inWindow the window in question
* @param inPosition requested position
* values: zLevelTop: topmost window. zLevelBottom: bottom.
* zLevelBelow: below ioBelow. (the value of ioBelow will
* be ignored for zLevelTop and Bottom.)
* @param inBelow if inPosition==zLevelBelow, the window
* below which inWindow wants to be placed. Otherwise this
* variable is ignored.
* @param outPosition constrained position, values like inPosition.
* @param outBelow if outPosition==zLevelBelow, the window
* below which inWindow should be placed. Otherwise this
* this value will be null.
* @return PR_TRUE if the position returned is different from
* the position given.
*/
[noscript] boolean calculateZPosition(in nsIXULWindow inWindow,
in unsigned long inPosition,
in nsIWidget inBelow,
out unsigned long outPosition,
out nsIWidget outBelow);
/** A window has been positioned behind another. Inform WindowMediator
* @param inWindow the window in question
* @param inPosition new position. values:
* zLevelTop: topmost window.
* zLevelBottom: bottom.
* zLevelBelow: below inBelow. (inBelow is ignored
* for other values of inPosition.)
* @param inBelow the window inWindow is behind, if zLevelBelow
*/
[noscript] void setZPosition(in nsIXULWindow inWindow,
in unsigned long inPosition,
in nsIXULWindow inBelow);
/** Return the window's Z level (as defined in nsIXULWindow).
* @param aWindow the window in question
* @return aWindow's z level
*/
[noscript] uint32_t getZLevel(in nsIXULWindow aWindow);
/** Set the window's Z level (as defined in nsIXULWindow). The implementation
* will reposition the window as necessary to match its new Z level.
* The implementation will assume a window's Z level to be
* nsIXULWindow::normalZ until it has been informed of a different level.
* @param aWindow the window in question
* @param aZLevel the window's new Z level
*/
[noscript] void setZLevel(in nsIXULWindow aWindow, in uint32_t aZLevel);
/** Register a listener for window status changes.
* keeps strong ref? (to be decided)
* @param aListener the listener to register
*/
void addListener(in nsIWindowMediatorListener aListener);
/** Unregister a listener of window status changes.
* @param aListener the listener to unregister
*/
void removeListener(in nsIWindowMediatorListener aListener);
};
// XXXcatalinb: This should be merged to nsIWindowMediator. Using this
// to avoid UUID change in aurora.
[scriptable, uuid(b9ed4063-39a2-4302-8e5c-7287eef021fe)]
interface nsIWindowMediator_44 : nsIWindowMediator
{
/**
* Same as getMostRecentWindow, but ignores private browsing
* windows.
*/
mozIDOMWindowProxy getMostRecentNonPBWindow(in wstring aWindowType);
};

View file

@ -0,0 +1,19 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 "nsISupports.idl"
interface nsIXULWindow;
[scriptable, uuid(2F276982-0D60-4377-A595-D350BA516395)]
interface nsIWindowMediatorListener : nsISupports
{
void onWindowTitleChange(in nsIXULWindow window,
in wstring newTitle);
void onOpenWindow(in nsIXULWindow window);
void onCloseWindow(in nsIXULWindow window);
};

View file

@ -0,0 +1,27 @@
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 "nsIWebNavigation.idl"
/**
* This interface represents a nsIWebBrowser instance with no associated OS
* window. Its main function is to manage the lifetimes of those windows.
* A strong reference to this object must be held until the window is
* ready to be destroyed.
*/
[scriptable, uuid(abb46f48-abfc-41bf-aa9a-7feccefcf977)]
interface nsIWindowlessBrowser : nsIWebNavigation
{
/**
* "Closes" the windowless browser and destroys its associated nsIWebBrowser
* and docshell.
*
* This method *must* be called for every windowless browser before its last
* reference is released.
*/
void close();
};

View file

@ -0,0 +1,78 @@
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 "nsISupports.idl"
#include "nsIURI.idl"
#include "nsIDOMNode.idl"
interface nsIRequest;
interface nsIDOMElement;
interface nsIInputStream;
interface nsIDocShell;
interface nsITabParent;
interface mozIDOMWindowProxy;
/**
* The nsIXULBrowserWindow supplies the methods that may be called from the
* internals of the browser area to tell the containing xul window to update
* its ui.
*/
[scriptable, uuid(a8675fa9-c8b4-4350-9803-c38f344a9e38)]
interface nsIXULBrowserWindow : nsISupports
{
/**
* Sets the status according to JS' version of status.
*/
void setJSStatus(in AString status);
/**
* Tells the object implementing this function what link we are currently
* over.
*/
void setOverLink(in AString link, in nsIDOMElement element);
/**
* Determines the appropriate target for a link.
*/
AString onBeforeLinkTraversal(in AString originalTarget,
in nsIURI linkURI,
in nsIDOMNode linkNode,
in boolean isAppTab);
/**
* Find the initial browser of the window and set its remote attribute.
* This can be used to ensure that there is a remote browser in a new
* window when it first spawns.
*
*/
nsITabParent forceInitialBrowserRemote();
void forceInitialBrowserNonRemote(in mozIDOMWindowProxy openerWindow);
/**
* Determines whether a load should continue.
*
* @param aDocShell
* The docshell performing the load.
* @param aURI
* The URI being loaded.
* @param aReferrer
* The referrer of the load.
*/
bool shouldLoadURI(in nsIDocShell aDocShell,
in nsIURI aURI,
in nsIURI aReferrer);
/**
* Show/hide a tooltip (when the user mouses over a link, say).
*/
void showTooltip(in long x, in long y, in AString tooltip, in AString direction);
void hideTooltip();
/**
* Return the number of tabs in this window.
*/
uint32_t getTabCount();
};

View file

@ -0,0 +1,168 @@
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 "nsISupports.idl"
/**
* The nsIXULWindow
*
* When the window is destroyed, it will fire a "xul-window-destroyed"
* notification through the global observer service.
*/
interface nsIDocShell;
interface nsIDocShellTreeItem;
interface nsIXULBrowserWindow;
interface nsITabParent;
interface mozIDOMWindowProxy;
[scriptable, uuid(d6d7a014-e28d-4c9d-8727-1cf6d870619b)]
interface nsIXULWindow : nsISupports
{
/**
* The docshell owning the XUL for this window.
*/
readonly attribute nsIDocShell docShell;
/**
* Indicates if this window is instrinsically sized.
*/
attribute boolean intrinsicallySized;
/**
* The primary content shell.
*
* Note that this is a docshell tree item and therefore can not be assured of
* what object it is. It could be an editor, a docshell, or a browser object.
* Or down the road any other object that supports being a DocShellTreeItem
* Query accordingly to determine the capabilities.
*/
readonly attribute nsIDocShellTreeItem primaryContentShell;
/**
* In multiprocess case we may not have primaryContentShell but
* primaryTabParent.
*/
readonly attribute nsITabParent primaryTabParent;
void tabParentAdded(in nsITabParent aTab, in boolean aPrimary);
void tabParentRemoved(in nsITabParent aTab);
/**
* The content shell specified by the supplied id.
*
* Note that this is a docshell tree item and therefore can not be assured of
* what object it is. It could be an editor, a docshell, or a browser object.
* Or down the road any other object that supports being a DocShellTreeItem
* Query accordingly to determine the capabilities.
*/
nsIDocShellTreeItem getContentShellById(in wstring ID);
/**
* Tell this window that it has picked up a child XUL window
* @param aChild the child window being added
*/
void addChildWindow(in nsIXULWindow aChild);
/**
* Tell this window that it has lost a child XUL window
* @param aChild the child window being removed
*/
void removeChildWindow(in nsIXULWindow aChild);
/**
* Move the window to a centered position.
* @param aRelative If not null, the window relative to which the window is
* moved. See aScreen parameter for details.
* @param aScreen PR_TRUE to center the window relative to the screen
* containing aRelative if aRelative is not null. If
* aRelative is null then relative to the screen of the
* opener window if it was initialized by passing it to
* nsWebShellWindow::Initialize. Failing that relative to
* the main screen.
* PR_FALSE to center it relative to aRelative itself.
* @param aAlert PR_TRUE to move the window to an alert position,
* generally centered horizontally and 1/3 down from the top.
*/
void center(in nsIXULWindow aRelative, in boolean aScreen, in boolean aAlert);
/**
* Shows the window as a modal window. That is, ensures that it is visible
* and runs a local event loop, exiting only once the window has been closed.
*/
void showModal();
const unsigned long lowestZ = 0;
const unsigned long loweredZ = 4; /* "alwaysLowered" attribute */
const unsigned long normalZ = 5;
const unsigned long raisedZ = 6; /* "alwaysRaised" attribute */
const unsigned long highestZ = 9;
attribute unsigned long zLevel;
/**
* contextFlags are from nsIWindowCreator2
*/
attribute uint32_t contextFlags;
attribute uint32_t chromeFlags;
/**
* Begin assuming |chromeFlags| don't change hereafter, and assert
* if they do change. The state change is one-way and idempotent.
*/
void assumeChromeFlagsAreFrozen();
/**
* Create a new window.
* @param aChromeFlags see nsIWebBrowserChrome
* @param aOpeningTab the TabParent that requested this new window be opened.
* Can be left null.
* @param aOpener The window which is requesting that this new window be opened.
* @return the newly minted window
*/
nsIXULWindow createNewWindow(in int32_t aChromeFlags,
in nsITabParent aOpeningTab,
in mozIDOMWindowProxy aOpener);
attribute nsIXULBrowserWindow XULBrowserWindow;
/**
* Back-door method to force application of chrome flags at a particular
* time. Do NOT call this unless you know what you're doing! In particular,
* calling this when this XUL window doesn't yet have a document in its
* docshell could cause problems.
*/
[noscript] void applyChromeFlags();
/**
* Given the dimensions of some content area held within this
* XUL window, and assuming that that content area will change
* its dimensions in linear proportion to the dimensions of this
* XUL window, changes the size of the XUL window so that the
* content area reaches a particular size.
*
* We need to supply the content area dimensions because sometimes
* the child's nsDocShellTreeOwner needs to propagate a SizeShellTo
* call to the parent. But the shellItem argument of the call will
* not be available on the parent side.
*
* Note: this is an internal method, other consumers should never call this.
*
* @param aDesiredWidth
* The desired width of the content area in device pixels.
* @param aDesiredHeight
* The desired height of the content area in device pixels.
* @param shellItemWidth
* The current width of the content area.
* @param shellItemHeight
* The current height of the content area.
*/
[noscript, notxpcom] void sizeShellToWithLimit(in int32_t aDesiredWidth,
in int32_t aDesiredHeight,
in int32_t shellItemWidth,
in int32_t shellItemHeight);
};

View file

@ -0,0 +1,911 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "nsWebShellWindow.h"
#include "nsLayoutCID.h"
#include "nsContentCID.h"
#include "nsIWeakReference.h"
#include "nsIContentViewer.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsIURL.h"
#include "nsIIOService.h"
#include "nsIURL.h"
#include "nsNetCID.h"
#include "nsIStringBundle.h"
#include "nsReadableUtils.h"
#include "nsContentUtils.h"
#include "nsEscape.h"
#include "nsPIDOMWindow.h"
#include "nsIWebNavigation.h"
#include "nsIWindowWatcher.h"
#include "nsIDOMXULElement.h"
#include "nsWidgetInitData.h"
#include "nsWidgetsCID.h"
#include "nsIWidget.h"
#include "nsIWidgetListener.h"
#include "nsIDOMCharacterData.h"
#include "nsIDOMNodeList.h"
#include "nsITimer.h"
#include "nsXULPopupManager.h"
#include "nsIDOMXULDocument.h"
#include "nsFocusManager.h"
#include "nsIWebProgress.h"
#include "nsIWebProgressListener.h"
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
#include "nsIDOMNode.h"
#include "nsIDOMElement.h"
#include "nsIDocumentLoaderFactory.h"
#include "nsIObserverService.h"
#include "prprf.h"
#include "nsIScreenManager.h"
#include "nsIScreen.h"
#include "nsIContent.h" // for menus
#include "nsIScriptSecurityManager.h"
// For calculating size
#include "nsIPresShell.h"
#include "nsPresContext.h"
#include "nsIBaseWindow.h"
#include "nsIDocShellTreeItem.h"
#include "mozilla/Attributes.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/MouseEvents.h"
#include "nsPIWindowRoot.h"
#ifdef XP_MACOSX
#include "nsINativeMenuService.h"
#define USE_NATIVE_MENUS
#endif
using namespace mozilla;
using namespace mozilla::dom;
/* Define Class IDs */
static NS_DEFINE_CID(kWindowCID, NS_WINDOW_CID);
#define SIZE_PERSISTENCE_TIMEOUT 500 // msec
nsWebShellWindow::nsWebShellWindow(uint32_t aChromeFlags)
: nsXULWindow(aChromeFlags)
, mSPTimerLock("nsWebShellWindow.mSPTimerLock")
, mWidgetListenerDelegate(this)
{
}
nsWebShellWindow::~nsWebShellWindow()
{
MutexAutoLock lock(mSPTimerLock);
if (mSPTimer)
mSPTimer->Cancel();
}
NS_IMPL_ADDREF_INHERITED(nsWebShellWindow, nsXULWindow)
NS_IMPL_RELEASE_INHERITED(nsWebShellWindow, nsXULWindow)
NS_INTERFACE_MAP_BEGIN(nsWebShellWindow)
NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
NS_INTERFACE_MAP_END_INHERITING(nsXULWindow)
nsresult nsWebShellWindow::Initialize(nsIXULWindow* aParent,
nsIXULWindow* aOpener,
nsIURI* aUrl,
int32_t aInitialWidth,
int32_t aInitialHeight,
bool aIsHiddenWindow,
nsITabParent *aOpeningTab,
mozIDOMWindowProxy *aOpenerWindow,
nsWidgetInitData& widgetInitData)
{
nsresult rv;
nsCOMPtr<nsIWidget> parentWidget;
mIsHiddenWindow = aIsHiddenWindow;
int32_t initialX = 0, initialY = 0;
nsCOMPtr<nsIBaseWindow> base(do_QueryInterface(aOpener));
if (base) {
rv = base->GetPositionAndSize(&mOpenerScreenRect.x,
&mOpenerScreenRect.y,
&mOpenerScreenRect.width,
&mOpenerScreenRect.height);
if (NS_FAILED(rv)) {
mOpenerScreenRect.SetEmpty();
} else {
double scale;
if (NS_SUCCEEDED(base->GetUnscaledDevicePixelsPerCSSPixel(&scale))) {
mOpenerScreenRect.x = NSToIntRound(mOpenerScreenRect.x / scale);
mOpenerScreenRect.y = NSToIntRound(mOpenerScreenRect.y / scale);
mOpenerScreenRect.width = NSToIntRound(mOpenerScreenRect.width / scale);
mOpenerScreenRect.height = NSToIntRound(mOpenerScreenRect.height / scale);
}
initialX = mOpenerScreenRect.x;
initialY = mOpenerScreenRect.y;
ConstrainToOpenerScreen(&initialX, &initialY);
}
}
// XXX: need to get the default window size from prefs...
// Doesn't come from prefs... will come from CSS/XUL/RDF
DesktopIntRect deskRect(initialX, initialY, aInitialWidth, aInitialHeight);
// Create top level window
mWindow = do_CreateInstance(kWindowCID, &rv);
if (NS_OK != rv) {
return rv;
}
/* This next bit is troublesome. We carry two different versions of a pointer
to our parent window. One is the parent window's widget, which is passed
to our own widget. The other is a weak reference we keep here to our
parent WebShellWindow. The former is useful to the widget, and we can't
trust its treatment of the parent reference because they're platform-
specific. The latter is useful to this class.
A better implementation would be one in which the parent keeps strong
references to its children and closes them before it allows itself
to be closed. This would mimic the behaviour of OSes that support
top-level child windows in OSes that do not. Later.
*/
nsCOMPtr<nsIBaseWindow> parentAsWin(do_QueryInterface(aParent));
if (parentAsWin) {
parentAsWin->GetMainWidget(getter_AddRefs(parentWidget));
mParentWindow = do_GetWeakReference(aParent);
}
mWindow->SetWidgetListener(&mWidgetListenerDelegate);
rv = mWindow->Create((nsIWidget *)parentWidget, // Parent nsIWidget
nullptr, // Native parent widget
deskRect, // Widget dimensions
&widgetInitData); // Widget initialization data
NS_ENSURE_SUCCESS(rv, rv);
LayoutDeviceIntRect r = mWindow->GetClientBounds();
// Match the default background color of content. Important on windows
// since we no longer use content child widgets.
mWindow->SetBackgroundColor(NS_RGB(255,255,255));
// Create web shell
mDocShell = do_CreateInstance("@mozilla.org/docshell;1");
NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
mDocShell->SetOpener(aOpeningTab);
// Make sure to set the item type on the docshell _before_ calling
// Create() so it knows what type it is.
nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell));
NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_FAILURE);
NS_ENSURE_SUCCESS(EnsureChromeTreeOwner(), NS_ERROR_FAILURE);
docShellAsItem->SetTreeOwner(mChromeTreeOwner);
docShellAsItem->SetItemType(nsIDocShellTreeItem::typeChrome);
r.x = r.y = 0;
nsCOMPtr<nsIBaseWindow> docShellAsWin(do_QueryInterface(mDocShell));
NS_ENSURE_SUCCESS(docShellAsWin->InitWindow(nullptr, mWindow,
r.x, r.y, r.width, r.height), NS_ERROR_FAILURE);
NS_ENSURE_SUCCESS(docShellAsWin->Create(), NS_ERROR_FAILURE);
// Attach a WebProgress listener.during initialization...
nsCOMPtr<nsIWebProgress> webProgress(do_GetInterface(mDocShell, &rv));
if (webProgress) {
webProgress->AddProgressListener(this, nsIWebProgress::NOTIFY_STATE_NETWORK);
}
if (aOpenerWindow) {
nsPIDOMWindowOuter* window = mDocShell->GetWindow();
MOZ_ASSERT(window);
window->SetOpenerWindow(nsPIDOMWindowOuter::From(aOpenerWindow), true);
}
// Eagerly create an about:blank content viewer with the right principal here,
// rather than letting it happening in the upcoming call to
// SetInitialPrincipalToSubject. This avoids creating the about:blank document
// and then blowing it away with a second one, which can cause problems for the
// top-level chrome window case. See bug 789773.
// Note that we don't accept expanded principals here, similar to
// SetInitialPrincipalToSubject.
if (nsContentUtils::IsInitialized()) { // Sometimes this happens really early See bug 793370.
MOZ_ASSERT(mDocShell->ItemType() == nsIDocShellTreeItem::typeChrome);
nsCOMPtr<nsIPrincipal> principal = nsContentUtils::SubjectPrincipalOrSystemIfNativeCaller();
if (nsContentUtils::IsExpandedPrincipal(principal)) {
principal = nullptr;
}
rv = mDocShell->CreateAboutBlankContentViewer(principal);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDocument> doc = mDocShell->GetDocument();
NS_ENSURE_TRUE(!!doc, NS_ERROR_FAILURE);
doc->SetIsInitialDocument(true);
}
if (nullptr != aUrl) {
nsCString tmpStr;
rv = aUrl->GetSpec(tmpStr);
if (NS_FAILED(rv)) return rv;
NS_ConvertUTF8toUTF16 urlString(tmpStr);
nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mDocShell));
NS_ENSURE_TRUE(webNav, NS_ERROR_FAILURE);
rv = webNav->LoadURI(urlString.get(),
nsIWebNavigation::LOAD_FLAGS_NONE,
nullptr,
nullptr,
nullptr);
NS_ENSURE_SUCCESS(rv, rv);
}
return rv;
}
nsIPresShell*
nsWebShellWindow::GetPresShell()
{
if (!mDocShell)
return nullptr;
return mDocShell->GetPresShell();
}
bool
nsWebShellWindow::WindowMoved(nsIWidget* aWidget, int32_t x, int32_t y)
{
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
if (pm) {
nsCOMPtr<nsPIDOMWindowOuter> window =
mDocShell ? mDocShell->GetWindow() : nullptr;
pm->AdjustPopupsOnWindowChange(window);
}
// Notify all tabs that the widget moved.
if (mDocShell && mDocShell->GetWindow()) {
nsCOMPtr<EventTarget> eventTarget = mDocShell->GetWindow()->GetTopWindowRoot();
nsContentUtils::DispatchChromeEvent(mDocShell->GetDocument(),
eventTarget,
NS_LITERAL_STRING("MozUpdateWindowPos"),
false, false, nullptr);
}
// Persist position, but not immediately, in case this OS is firing
// repeated move events as the user drags the window
SetPersistenceTimer(PAD_POSITION);
return false;
}
bool
nsWebShellWindow::WindowResized(nsIWidget* aWidget, int32_t aWidth, int32_t aHeight)
{
nsCOMPtr<nsIBaseWindow> shellAsWin(do_QueryInterface(mDocShell));
if (shellAsWin) {
shellAsWin->SetPositionAndSize(0, 0, aWidth, aHeight, 0);
}
// Persist size, but not immediately, in case this OS is firing
// repeated size events as the user drags the sizing handle
if (!IsLocked())
SetPersistenceTimer(PAD_POSITION | PAD_SIZE | PAD_MISC);
return true;
}
bool
nsWebShellWindow::RequestWindowClose(nsIWidget* aWidget)
{
// Maintain a reference to this as it is about to get destroyed.
nsCOMPtr<nsIXULWindow> xulWindow(this);
nsCOMPtr<nsPIDOMWindowOuter> window(mDocShell ? mDocShell->GetWindow() : nullptr);
nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(window);
nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
if (!presShell) {
mozilla::DebugOnly<bool> dying;
MOZ_ASSERT(NS_SUCCEEDED(mDocShell->IsBeingDestroyed(&dying)) && dying,
"No presShell, but window is not being destroyed");
} else if (eventTarget) {
RefPtr<nsPresContext> presContext = presShell->GetPresContext();
nsEventStatus status = nsEventStatus_eIgnore;
WidgetMouseEvent event(true, eWindowClose, nullptr,
WidgetMouseEvent::eReal);
if (NS_SUCCEEDED(eventTarget->DispatchDOMEvent(&event, nullptr, presContext, &status)) &&
status == nsEventStatus_eConsumeNoDefault)
return false;
}
Destroy();
return false;
}
void
nsWebShellWindow::SizeModeChanged(nsSizeMode sizeMode)
{
// An alwaysRaised (or higher) window will hide any newly opened normal
// browser windows, so here we just drop a raised window to the normal
// zlevel if it's maximized. We make no provision for automatically
// re-raising it when restored.
if (sizeMode == nsSizeMode_Maximized || sizeMode == nsSizeMode_Fullscreen) {
uint32_t zLevel;
GetZLevel(&zLevel);
if (zLevel > nsIXULWindow::normalZ)
SetZLevel(nsIXULWindow::normalZ);
}
mWindow->SetSizeMode(sizeMode);
// Persist mode, but not immediately, because in many (all?)
// cases this will merge with the similar call in NS_SIZE and
// write the attribute values only once.
SetPersistenceTimer(PAD_MISC);
nsCOMPtr<nsPIDOMWindowOuter> ourWindow =
mDocShell ? mDocShell->GetWindow() : nullptr;
if (ourWindow) {
MOZ_ASSERT(ourWindow->IsOuterWindow());
// Ensure that the fullscreen state is synchronized between
// the widget and the outer window object.
if (sizeMode == nsSizeMode_Fullscreen) {
ourWindow->SetFullScreen(true);
}
else if (sizeMode != nsSizeMode_Minimized) {
if (ourWindow->GetFullScreen()) {
// The first SetFullscreenInternal call below ensures that we do
// not trigger any fullscreen transition even if the window was
// put in fullscreen only for the Fullscreen API. The second
// SetFullScreen call ensures that the window really exit from
// fullscreen even if it entered fullscreen for both Fullscreen
// Mode and Fullscreen API.
ourWindow->SetFullscreenInternal(FullscreenReason::ForForceExitFullscreen, false);
ourWindow->SetFullScreen(false);
}
}
// And always fire a user-defined sizemodechange event on the window
ourWindow->DispatchCustomEvent(NS_LITERAL_STRING("sizemodechange"));
}
nsIPresShell* presShell;
if ((presShell = GetPresShell())) {
presShell->GetPresContext()->SizeModeChanged(sizeMode);
}
// Note the current implementation of SetSizeMode just stores
// the new state; it doesn't actually resize. So here we store
// the state and pass the event on to the OS. The day is coming
// when we'll handle the event here, and the return result will
// then need to be different.
}
void
nsWebShellWindow::UIResolutionChanged()
{
nsCOMPtr<nsPIDOMWindowOuter> ourWindow =
mDocShell ? mDocShell->GetWindow() : nullptr;
if (ourWindow) {
MOZ_ASSERT(ourWindow->IsOuterWindow());
ourWindow->DispatchCustomEvent(NS_LITERAL_STRING("resolutionchange"));
}
}
void
nsWebShellWindow::FullscreenChanged(bool aInFullscreen)
{
if (mDocShell) {
if (nsCOMPtr<nsPIDOMWindowOuter> ourWindow = mDocShell->GetWindow()) {
ourWindow->FinishFullscreenChange(aInFullscreen);
}
}
}
void
nsWebShellWindow::OSToolbarButtonPressed()
{
// Keep a reference as setting the chrome flags can fire events.
nsCOMPtr<nsIXULWindow> xulWindow(this);
// rjc: don't use "nsIWebBrowserChrome::CHROME_EXTRA"
// due to components with multiple sidebar components
// (such as Mail/News, Addressbook, etc)... and frankly,
// Mac IE, OmniWeb, and other Mac OS X apps all work this way
uint32_t chromeMask = (nsIWebBrowserChrome::CHROME_TOOLBAR |
nsIWebBrowserChrome::CHROME_LOCATIONBAR |
nsIWebBrowserChrome::CHROME_PERSONAL_TOOLBAR);
nsCOMPtr<nsIWebBrowserChrome> wbc(do_GetInterface(xulWindow));
if (!wbc)
return;
uint32_t chromeFlags, newChromeFlags = 0;
wbc->GetChromeFlags(&chromeFlags);
newChromeFlags = chromeFlags & chromeMask;
if (!newChromeFlags) chromeFlags |= chromeMask;
else chromeFlags &= (~newChromeFlags);
wbc->SetChromeFlags(chromeFlags);
}
bool
nsWebShellWindow::ZLevelChanged(bool aImmediate, nsWindowZ *aPlacement,
nsIWidget* aRequestBelow, nsIWidget** aActualBelow)
{
if (aActualBelow)
*aActualBelow = nullptr;
return ConstrainToZLevel(aImmediate, aPlacement, aRequestBelow, aActualBelow);
}
void
nsWebShellWindow::WindowActivated()
{
nsCOMPtr<nsIXULWindow> xulWindow(this);
// focusing the window could cause it to close, so keep a reference to it
nsCOMPtr<nsPIDOMWindowOuter> window = mDocShell ? mDocShell->GetWindow() : nullptr;
nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
if (fm && window)
fm->WindowRaised(window);
if (mChromeLoaded) {
PersistentAttributesDirty(PAD_POSITION | PAD_SIZE | PAD_MISC);
SavePersistentAttributes();
}
}
void
nsWebShellWindow::WindowDeactivated()
{
nsCOMPtr<nsIXULWindow> xulWindow(this);
nsCOMPtr<nsPIDOMWindowOuter> window =
mDocShell ? mDocShell->GetWindow() : nullptr;
nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
if (fm && window)
fm->WindowLowered(window);
}
#ifdef USE_NATIVE_MENUS
static void LoadNativeMenus(nsIDOMDocument *aDOMDoc, nsIWidget *aParentWindow)
{
nsCOMPtr<nsINativeMenuService> nms = do_GetService("@mozilla.org/widget/nativemenuservice;1");
if (!nms) {
return;
}
// Find the menubar tag (if there is more than one, we ignore all but
// the first).
nsCOMPtr<nsIDOMNodeList> menubarElements;
aDOMDoc->GetElementsByTagNameNS(NS_LITERAL_STRING("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"),
NS_LITERAL_STRING("menubar"),
getter_AddRefs(menubarElements));
nsCOMPtr<nsIDOMNode> menubarNode;
if (menubarElements)
menubarElements->Item(0, getter_AddRefs(menubarNode));
if (menubarNode) {
nsCOMPtr<nsIContent> menubarContent(do_QueryInterface(menubarNode));
nms->CreateNativeMenuBar(aParentWindow, menubarContent);
} else {
nms->CreateNativeMenuBar(aParentWindow, nullptr);
}
}
#endif
namespace mozilla {
class WebShellWindowTimerCallback final : public nsITimerCallback
{
public:
explicit WebShellWindowTimerCallback(nsWebShellWindow* aWindow)
: mWindow(aWindow)
{}
NS_DECL_THREADSAFE_ISUPPORTS
NS_IMETHOD Notify(nsITimer* aTimer) override
{
// Although this object participates in a refcount cycle (this -> mWindow
// -> mSPTimer -> this), mSPTimer is a one-shot timer and releases this
// after it fires. So we don't need to release mWindow here.
mWindow->FirePersistenceTimer();
return NS_OK;
}
private:
~WebShellWindowTimerCallback() {}
RefPtr<nsWebShellWindow> mWindow;
};
NS_IMPL_ISUPPORTS(WebShellWindowTimerCallback, nsITimerCallback)
} // namespace mozilla
void
nsWebShellWindow::SetPersistenceTimer(uint32_t aDirtyFlags)
{
MutexAutoLock lock(mSPTimerLock);
if (!mSPTimer) {
mSPTimer = do_CreateInstance("@mozilla.org/timer;1");
if (!mSPTimer) {
NS_WARNING("Couldn't create @mozilla.org/timer;1 instance?");
return;
}
}
RefPtr<WebShellWindowTimerCallback> callback =
new WebShellWindowTimerCallback(this);
mSPTimer->InitWithCallback(callback, SIZE_PERSISTENCE_TIMEOUT,
nsITimer::TYPE_ONE_SHOT);
PersistentAttributesDirty(aDirtyFlags);
}
void
nsWebShellWindow::FirePersistenceTimer()
{
MutexAutoLock lock(mSPTimerLock);
SavePersistentAttributes();
}
//----------------------------------------
// nsIWebProgessListener implementation
//----------------------------------------
NS_IMETHODIMP
nsWebShellWindow::OnProgressChange(nsIWebProgress *aProgress,
nsIRequest *aRequest,
int32_t aCurSelfProgress,
int32_t aMaxSelfProgress,
int32_t aCurTotalProgress,
int32_t aMaxTotalProgress)
{
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
return NS_OK;
}
NS_IMETHODIMP
nsWebShellWindow::OnStateChange(nsIWebProgress *aProgress,
nsIRequest *aRequest,
uint32_t aStateFlags,
nsresult aStatus)
{
// If the notification is not about a document finishing, then just
// ignore it...
if (!(aStateFlags & nsIWebProgressListener::STATE_STOP) ||
!(aStateFlags & nsIWebProgressListener::STATE_IS_NETWORK)) {
return NS_OK;
}
if (mChromeLoaded)
return NS_OK;
// If this document notification is for a frame then ignore it...
nsCOMPtr<mozIDOMWindowProxy> eventWin;
aProgress->GetDOMWindow(getter_AddRefs(eventWin));
auto* eventPWin = nsPIDOMWindowOuter::From(eventWin);
if (eventPWin) {
nsPIDOMWindowOuter *rootPWin = eventPWin->GetPrivateRoot();
if (eventPWin != rootPWin)
return NS_OK;
}
mChromeLoaded = true;
mLockedUntilChromeLoad = false;
#ifdef USE_NATIVE_MENUS
///////////////////////////////
// Find the Menubar DOM and Load the menus, hooking them up to the loaded commands
///////////////////////////////
nsCOMPtr<nsIContentViewer> cv;
mDocShell->GetContentViewer(getter_AddRefs(cv));
if (cv) {
nsCOMPtr<nsIDOMDocument> menubarDOMDoc(do_QueryInterface(cv->GetDocument()));
if (menubarDOMDoc)
LoadNativeMenus(menubarDOMDoc, mWindow);
}
#endif // USE_NATIVE_MENUS
OnChromeLoaded();
LoadContentAreas();
return NS_OK;
}
NS_IMETHODIMP
nsWebShellWindow::OnLocationChange(nsIWebProgress *aProgress,
nsIRequest *aRequest,
nsIURI *aURI,
uint32_t aFlags)
{
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
return NS_OK;
}
NS_IMETHODIMP
nsWebShellWindow::OnStatusChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
nsresult aStatus,
const char16_t* aMessage)
{
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
return NS_OK;
}
NS_IMETHODIMP
nsWebShellWindow::OnSecurityChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest,
uint32_t state)
{
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
return NS_OK;
}
//----------------------------------------
// if the main document URL specified URLs for any content areas, start them loading
void nsWebShellWindow::LoadContentAreas() {
nsAutoString searchSpec;
// fetch the chrome document URL
nsCOMPtr<nsIContentViewer> contentViewer;
// yes, it's possible for the docshell to be null even this early
// see bug 57514.
if (mDocShell)
mDocShell->GetContentViewer(getter_AddRefs(contentViewer));
if (contentViewer) {
nsIDocument* doc = contentViewer->GetDocument();
if (doc) {
nsIURI* mainURL = doc->GetDocumentURI();
nsCOMPtr<nsIURL> url = do_QueryInterface(mainURL);
if (url) {
nsAutoCString search;
url->GetQuery(search);
AppendUTF8toUTF16(search, searchSpec);
}
}
}
// content URLs are specified in the search part of the URL
// as <contentareaID>=<escapedURL>[;(repeat)]
if (!searchSpec.IsEmpty()) {
int32_t begPos,
eqPos,
endPos;
nsString contentAreaID,
contentURL;
char *urlChar;
nsresult rv;
for (endPos = 0; endPos < (int32_t)searchSpec.Length(); ) {
// extract contentAreaID and URL substrings
begPos = endPos;
eqPos = searchSpec.FindChar('=', begPos);
if (eqPos < 0)
break;
endPos = searchSpec.FindChar(';', eqPos);
if (endPos < 0)
endPos = searchSpec.Length();
searchSpec.Mid(contentAreaID, begPos, eqPos-begPos);
searchSpec.Mid(contentURL, eqPos+1, endPos-eqPos-1);
endPos++;
// see if we have a docshell with a matching contentAreaID
nsCOMPtr<nsIDocShellTreeItem> content;
rv = GetContentShellById(contentAreaID.get(), getter_AddRefs(content));
if (NS_SUCCEEDED(rv) && content) {
nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(content));
if (webNav) {
urlChar = ToNewCString(contentURL);
if (urlChar) {
nsUnescape(urlChar);
contentURL.AssignWithConversion(urlChar);
webNav->LoadURI(contentURL.get(),
nsIWebNavigation::LOAD_FLAGS_NONE,
nullptr,
nullptr,
nullptr);
free(urlChar);
}
}
}
}
}
}
/**
* ExecuteCloseHandler - Run the close handler, if any.
* @return true iff we found a close handler to run.
*/
bool nsWebShellWindow::ExecuteCloseHandler()
{
/* If the event handler closes this window -- a likely scenario --
things get deleted out of order without this death grip.
(The problem may be the death grip in nsWindow::windowProc,
which forces this window's widget to remain alive longer
than it otherwise would.) */
nsCOMPtr<nsIXULWindow> kungFuDeathGrip(this);
nsCOMPtr<EventTarget> eventTarget;
if (mDocShell) {
eventTarget = do_QueryInterface(mDocShell->GetWindow());
}
if (eventTarget) {
nsCOMPtr<nsIContentViewer> contentViewer;
mDocShell->GetContentViewer(getter_AddRefs(contentViewer));
if (contentViewer) {
RefPtr<nsPresContext> presContext;
contentViewer->GetPresContext(getter_AddRefs(presContext));
nsEventStatus status = nsEventStatus_eIgnore;
WidgetMouseEvent event(true, eWindowClose, nullptr,
WidgetMouseEvent::eReal);
nsresult rv =
eventTarget->DispatchDOMEvent(&event, nullptr, presContext, &status);
if (NS_SUCCEEDED(rv) && status == nsEventStatus_eConsumeNoDefault)
return true;
// else fall through and return false
}
}
return false;
} // ExecuteCloseHandler
void nsWebShellWindow::ConstrainToOpenerScreen(int32_t* aX, int32_t* aY)
{
if (mOpenerScreenRect.IsEmpty()) {
*aX = *aY = 0;
return;
}
int32_t left, top, width, height;
// Constrain initial positions to the same screen as opener
nsCOMPtr<nsIScreenManager> screenmgr = do_GetService("@mozilla.org/gfx/screenmanager;1");
if (screenmgr) {
nsCOMPtr<nsIScreen> screen;
screenmgr->ScreenForRect(mOpenerScreenRect.x, mOpenerScreenRect.y,
mOpenerScreenRect.width, mOpenerScreenRect.height,
getter_AddRefs(screen));
if (screen) {
screen->GetAvailRectDisplayPix(&left, &top, &width, &height);
if (*aX < left || *aX > left + width) {
*aX = left;
}
if (*aY < top || *aY > top + height) {
*aY = top;
}
}
}
}
// nsIBaseWindow
NS_IMETHODIMP nsWebShellWindow::Destroy()
{
nsresult rv;
nsCOMPtr<nsIWebProgress> webProgress(do_GetInterface(mDocShell, &rv));
if (webProgress) {
webProgress->RemoveProgressListener(this);
}
nsCOMPtr<nsIXULWindow> kungFuDeathGrip(this);
{
MutexAutoLock lock(mSPTimerLock);
if (mSPTimer) {
mSPTimer->Cancel();
SavePersistentAttributes();
mSPTimer = nullptr;
}
}
return nsXULWindow::Destroy();
}
nsIXULWindow*
nsWebShellWindow::WidgetListenerDelegate::GetXULWindow()
{
return mWebShellWindow->GetXULWindow();
}
nsIPresShell*
nsWebShellWindow::WidgetListenerDelegate::GetPresShell()
{
return mWebShellWindow->GetPresShell();
}
bool
nsWebShellWindow::WidgetListenerDelegate::WindowMoved(
nsIWidget* aWidget, int32_t aX, int32_t aY)
{
RefPtr<nsWebShellWindow> holder = mWebShellWindow;
return holder->WindowMoved(aWidget, aX, aY);
}
bool
nsWebShellWindow::WidgetListenerDelegate::WindowResized(
nsIWidget* aWidget, int32_t aWidth, int32_t aHeight)
{
RefPtr<nsWebShellWindow> holder = mWebShellWindow;
return holder->WindowResized(aWidget, aWidth, aHeight);
}
bool
nsWebShellWindow::WidgetListenerDelegate::RequestWindowClose(nsIWidget* aWidget)
{
RefPtr<nsWebShellWindow> holder = mWebShellWindow;
return holder->RequestWindowClose(aWidget);
}
void
nsWebShellWindow::WidgetListenerDelegate::SizeModeChanged(nsSizeMode aSizeMode)
{
RefPtr<nsWebShellWindow> holder = mWebShellWindow;
holder->SizeModeChanged(aSizeMode);
}
void
nsWebShellWindow::WidgetListenerDelegate::UIResolutionChanged()
{
RefPtr<nsWebShellWindow> holder = mWebShellWindow;
holder->UIResolutionChanged();
}
void
nsWebShellWindow::WidgetListenerDelegate::FullscreenChanged(bool aInFullscreen)
{
RefPtr<nsWebShellWindow> holder = mWebShellWindow;
holder->FullscreenChanged(aInFullscreen);
}
void
nsWebShellWindow::WidgetListenerDelegate::OSToolbarButtonPressed()
{
RefPtr<nsWebShellWindow> holder = mWebShellWindow;
holder->OSToolbarButtonPressed();
}
bool
nsWebShellWindow::WidgetListenerDelegate::ZLevelChanged(
bool aImmediate, nsWindowZ *aPlacement, nsIWidget* aRequestBelow,
nsIWidget** aActualBelow)
{
RefPtr<nsWebShellWindow> holder = mWebShellWindow;
return holder->ZLevelChanged(aImmediate,
aPlacement,
aRequestBelow,
aActualBelow);
}
void
nsWebShellWindow::WidgetListenerDelegate::WindowActivated()
{
RefPtr<nsWebShellWindow> holder = mWebShellWindow;
holder->WindowActivated();
}
void
nsWebShellWindow::WidgetListenerDelegate::WindowDeactivated()
{
RefPtr<nsWebShellWindow> holder = mWebShellWindow;
holder->WindowDeactivated();
}

View file

@ -0,0 +1,116 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 nsWebShellWindow_h__
#define nsWebShellWindow_h__
#include "mozilla/Mutex.h"
#include "nsIWebProgressListener.h"
#include "nsITimer.h"
#include "nsCOMPtr.h"
#include "nsXULWindow.h"
#include "nsIWidgetListener.h"
#include "nsITabParent.h"
/* Forward declarations.... */
class nsIURI;
struct nsWidgetInitData;
namespace mozilla {
class WebShellWindowTimerCallback;
} // namespace mozilla
class nsWebShellWindow final : public nsXULWindow,
public nsIWebProgressListener
{
public:
// The implementation of non-refcounted nsIWidgetListener, which would hold a
// strong reference on stack before calling nsWebShellWindow
class WidgetListenerDelegate : public nsIWidgetListener
{
public:
explicit WidgetListenerDelegate(nsWebShellWindow* aWebShellWindow)
: mWebShellWindow(aWebShellWindow) {}
virtual nsIXULWindow* GetXULWindow() override;
virtual nsIPresShell* GetPresShell() override;
virtual bool WindowMoved(nsIWidget* aWidget, int32_t x, int32_t y) override;
virtual bool WindowResized(nsIWidget* aWidget, int32_t aWidth, int32_t aHeight) override;
virtual bool RequestWindowClose(nsIWidget* aWidget) override;
virtual void SizeModeChanged(nsSizeMode sizeMode) override;
virtual void UIResolutionChanged() override;
virtual void FullscreenChanged(bool aInFullscreen) override;
virtual void OSToolbarButtonPressed() override;
virtual bool ZLevelChanged(bool aImmediate,
nsWindowZ *aPlacement,
nsIWidget* aRequestBelow,
nsIWidget** aActualBelow) override;
virtual void WindowActivated() override;
virtual void WindowDeactivated() override;
private:
// The lifetime of WidgetListenerDelegate is bound to nsWebShellWindow so
// we just use a raw pointer here.
nsWebShellWindow* mWebShellWindow;
};
explicit nsWebShellWindow(uint32_t aChromeFlags);
// nsISupports interface...
NS_DECL_ISUPPORTS_INHERITED
// nsWebShellWindow methods...
nsresult Initialize(nsIXULWindow * aParent, nsIXULWindow * aOpener,
nsIURI* aUrl,
int32_t aInitialWidth, int32_t aInitialHeight,
bool aIsHiddenWindow,
nsITabParent *aOpeningTab,
mozIDOMWindowProxy *aOpenerWIndow,
nsWidgetInitData& widgetInitData);
nsresult Toolbar();
// nsIWebProgressListener
NS_DECL_NSIWEBPROGRESSLISTENER
// nsIBaseWindow
NS_IMETHOD Destroy() override;
// nsIWidgetListener
nsIXULWindow* GetXULWindow() { return this; }
nsIPresShell* GetPresShell();
bool WindowMoved(nsIWidget* aWidget, int32_t x, int32_t y);
bool WindowResized(nsIWidget* aWidget, int32_t aWidth, int32_t aHeight);
bool RequestWindowClose(nsIWidget* aWidget);
void SizeModeChanged(nsSizeMode sizeMode);
void UIResolutionChanged();
void FullscreenChanged(bool aInFullscreen);
void OSToolbarButtonPressed();
bool ZLevelChanged(bool aImmediate, nsWindowZ *aPlacement,
nsIWidget* aRequestBelow, nsIWidget** aActualBelow);
void WindowActivated();
void WindowDeactivated();
protected:
friend class mozilla::WebShellWindowTimerCallback;
virtual ~nsWebShellWindow();
void LoadContentAreas();
bool ExecuteCloseHandler();
void ConstrainToOpenerScreen(int32_t* aX, int32_t* aY);
nsCOMPtr<nsITimer> mSPTimer;
mozilla::Mutex mSPTimerLock;
WidgetListenerDelegate mWidgetListenerDelegate;
void SetPersistenceTimer(uint32_t aDirtyFlags);
void FirePersistenceTimer();
};
#endif /* nsWebShellWindow_h__ */

View file

@ -0,0 +1,846 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "nsCOMPtr.h"
#include "nsString.h"
#include "nsReadableUtils.h"
#include "nsUnicharUtils.h"
#include "nsTArray.h"
#include "nsIBaseWindow.h"
#include "nsIWidget.h"
#include "nsIDOMWindow.h"
#include "nsIObserverService.h"
#include "nsIServiceManager.h"
#include "nsISimpleEnumerator.h"
#include "nsAppShellWindowEnumerator.h"
#include "nsWindowMediator.h"
#include "nsIWindowMediatorListener.h"
#include "nsXPIDLString.h"
#include "nsGlobalWindow.h"
#include "nsIDocShell.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIXULWindow.h"
using namespace mozilla;
static bool notifyOpenWindow(nsIWindowMediatorListener *aElement, void* aData);
static bool notifyCloseWindow(nsIWindowMediatorListener *aElement, void* aData);
static bool notifyWindowTitleChange(nsIWindowMediatorListener *aElement, void* aData);
// for notifyWindowTitleChange
struct WindowTitleData {
nsIXULWindow* mWindow;
const char16_t *mTitle;
};
nsresult
nsWindowMediator::GetDOMWindow(nsIXULWindow* inWindow,
nsCOMPtr<nsPIDOMWindowOuter>& outDOMWindow)
{
nsCOMPtr<nsIDocShell> docShell;
outDOMWindow = nullptr;
inWindow->GetDocShell(getter_AddRefs(docShell));
NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
outDOMWindow = docShell->GetWindow();
return outDOMWindow ? NS_OK : NS_ERROR_FAILURE;
}
nsWindowMediator::nsWindowMediator() :
mEnumeratorList(), mOldestWindow(nullptr), mTopmostWindow(nullptr),
mTimeStamp(0), mSortingZOrder(false), mReady(false)
{
}
nsWindowMediator::~nsWindowMediator()
{
while (mOldestWindow)
UnregisterWindow(mOldestWindow);
}
nsresult nsWindowMediator::Init()
{
nsresult rv;
nsCOMPtr<nsIObserverService> obsSvc =
do_GetService("@mozilla.org/observer-service;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = obsSvc->AddObserver(this, "xpcom-shutdown", true);
NS_ENSURE_SUCCESS(rv, rv);
mReady = true;
return NS_OK;
}
NS_IMETHODIMP nsWindowMediator::RegisterWindow(nsIXULWindow* inWindow)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
NS_ENSURE_STATE(mReady);
if (GetInfoFor(inWindow)) {
NS_ERROR("multiple window registration");
return NS_ERROR_FAILURE;
}
mTimeStamp++;
// Create window info struct and add to list of windows
nsWindowInfo* windowInfo = new nsWindowInfo(inWindow, mTimeStamp);
WindowTitleData winData = { inWindow, nullptr };
mListeners.EnumerateForwards(notifyOpenWindow, &winData);
if (mOldestWindow)
windowInfo->InsertAfter(mOldestWindow->mOlder, nullptr);
else
mOldestWindow = windowInfo;
return NS_OK;
}
NS_IMETHODIMP
nsWindowMediator::UnregisterWindow(nsIXULWindow* inWindow)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
NS_ENSURE_STATE(mReady);
nsWindowInfo *info = GetInfoFor(inWindow);
if (info)
return UnregisterWindow(info);
return NS_ERROR_INVALID_ARG;
}
nsresult
nsWindowMediator::UnregisterWindow(nsWindowInfo *inInfo)
{
// Inform the iterators
uint32_t index = 0;
while (index < mEnumeratorList.Length()) {
mEnumeratorList[index]->WindowRemoved(inInfo);
index++;
}
WindowTitleData winData = { inInfo->mWindow.get(), nullptr };
mListeners.EnumerateForwards(notifyCloseWindow, &winData);
// Remove from the lists and free up
if (inInfo == mOldestWindow)
mOldestWindow = inInfo->mYounger;
if (inInfo == mTopmostWindow)
mTopmostWindow = inInfo->mLower;
inInfo->Unlink(true, true);
if (inInfo == mOldestWindow)
mOldestWindow = nullptr;
if (inInfo == mTopmostWindow)
mTopmostWindow = nullptr;
delete inInfo;
return NS_OK;
}
nsWindowInfo*
nsWindowMediator::GetInfoFor(nsIXULWindow *aWindow)
{
nsWindowInfo *info,
*listEnd;
if (!aWindow)
return nullptr;
info = mOldestWindow;
listEnd = nullptr;
while (info != listEnd) {
if (info->mWindow.get() == aWindow)
return info;
info = info->mYounger;
listEnd = mOldestWindow;
}
return nullptr;
}
nsWindowInfo*
nsWindowMediator::GetInfoFor(nsIWidget *aWindow)
{
nsWindowInfo *info,
*listEnd;
if (!aWindow)
return nullptr;
info = mOldestWindow;
listEnd = nullptr;
nsCOMPtr<nsIWidget> scanWidget;
while (info != listEnd) {
nsCOMPtr<nsIBaseWindow> base(do_QueryInterface(info->mWindow));
if (base)
base->GetMainWidget(getter_AddRefs(scanWidget));
if (aWindow == scanWidget.get())
return info;
info = info->mYounger;
listEnd = mOldestWindow;
}
return nullptr;
}
NS_IMETHODIMP
nsWindowMediator::GetEnumerator(const char16_t* inType, nsISimpleEnumerator** outEnumerator)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
NS_ENSURE_ARG_POINTER(outEnumerator);
NS_ENSURE_STATE(mReady);
RefPtr<nsAppShellWindowEnumerator> enumerator = new nsASDOMWindowEarlyToLateEnumerator(inType, *this);
enumerator.forget(outEnumerator);
return NS_OK;
}
NS_IMETHODIMP
nsWindowMediator::GetXULWindowEnumerator(const char16_t* inType, nsISimpleEnumerator** outEnumerator)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
NS_ENSURE_ARG_POINTER(outEnumerator);
NS_ENSURE_STATE(mReady);
RefPtr<nsAppShellWindowEnumerator> enumerator = new nsASXULWindowEarlyToLateEnumerator(inType, *this);
enumerator.forget(outEnumerator);
return NS_OK;
}
NS_IMETHODIMP
nsWindowMediator::GetZOrderDOMWindowEnumerator(
const char16_t *aWindowType, bool aFrontToBack,
nsISimpleEnumerator **_retval)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
NS_ENSURE_ARG_POINTER(_retval);
NS_ENSURE_STATE(mReady);
RefPtr<nsAppShellWindowEnumerator> enumerator;
if (aFrontToBack)
enumerator = new nsASDOMWindowFrontToBackEnumerator(aWindowType, *this);
else
enumerator = new nsASDOMWindowBackToFrontEnumerator(aWindowType, *this);
enumerator.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
nsWindowMediator::GetZOrderXULWindowEnumerator(
const char16_t *aWindowType, bool aFrontToBack,
nsISimpleEnumerator **_retval)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
NS_ENSURE_ARG_POINTER(_retval);
NS_ENSURE_STATE(mReady);
RefPtr<nsAppShellWindowEnumerator> enumerator;
if (aFrontToBack)
enumerator = new nsASXULWindowFrontToBackEnumerator(aWindowType, *this);
else
enumerator = new nsASXULWindowBackToFrontEnumerator(aWindowType, *this);
enumerator.forget(_retval);
return NS_OK;
}
int32_t
nsWindowMediator::AddEnumerator(nsAppShellWindowEnumerator * inEnumerator)
{
return mEnumeratorList.AppendElement(inEnumerator) != nullptr;
}
int32_t
nsWindowMediator::RemoveEnumerator(nsAppShellWindowEnumerator * inEnumerator)
{
return mEnumeratorList.RemoveElement(inEnumerator);
}
// Returns the window of type inType ( if null return any window type ) which has the most recent
// time stamp
NS_IMETHODIMP
nsWindowMediator::GetMostRecentWindow(const char16_t* inType,
mozIDOMWindowProxy** outWindow)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
NS_ENSURE_ARG_POINTER(outWindow);
*outWindow = nullptr;
if (!mReady)
return NS_OK;
// Find the most window with the highest time stamp that matches
// the requested type
nsWindowInfo* info = MostRecentWindowInfo(inType, false);
if (info && info->mWindow) {
nsCOMPtr<nsPIDOMWindowOuter> DOMWindow;
if (NS_SUCCEEDED(GetDOMWindow(info->mWindow, DOMWindow))) {
DOMWindow.forget(outWindow);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
return NS_OK;
}
NS_IMETHODIMP
nsWindowMediator::GetMostRecentNonPBWindow(const char16_t* aType, mozIDOMWindowProxy** aWindow)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
NS_ENSURE_ARG_POINTER(aWindow);
*aWindow = nullptr;
nsWindowInfo *info = MostRecentWindowInfo(aType, true);
nsCOMPtr<nsPIDOMWindowOuter> domWindow;
if (info && info->mWindow) {
GetDOMWindow(info->mWindow, domWindow);
}
if (!domWindow) {
return NS_ERROR_FAILURE;
}
domWindow.forget(aWindow);
return NS_OK;
}
nsWindowInfo*
nsWindowMediator::MostRecentWindowInfo(const char16_t* inType,
bool aSkipPrivateBrowsingOrClosed)
{
int32_t lastTimeStamp = -1;
nsAutoString typeString(inType);
bool allWindows = !inType || typeString.IsEmpty();
// Find the most recent window with the highest time stamp that matches
// the requested type and has the correct browsing mode.
nsWindowInfo* searchInfo = mOldestWindow;
nsWindowInfo* listEnd = nullptr;
nsWindowInfo* foundInfo = nullptr;
for (; searchInfo != listEnd; searchInfo = searchInfo->mYounger) {
listEnd = mOldestWindow;
if (!allWindows && !searchInfo->TypeEquals(typeString)) {
continue;
}
if (searchInfo->mTimeStamp < lastTimeStamp) {
continue;
}
if (!searchInfo->mWindow) {
continue;
}
if (aSkipPrivateBrowsingOrClosed) {
nsCOMPtr<nsIDocShell> docShell;
searchInfo->mWindow->GetDocShell(getter_AddRefs(docShell));
nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);
if (!loadContext || loadContext->UsePrivateBrowsing()) {
continue;
}
nsCOMPtr<nsPIDOMWindowOuter> piwindow = docShell->GetWindow();
if (!piwindow || piwindow->Closed()) {
continue;
}
}
foundInfo = searchInfo;
lastTimeStamp = searchInfo->mTimeStamp;
}
return foundInfo;
}
NS_IMETHODIMP
nsWindowMediator::GetOuterWindowWithId(uint64_t aWindowID,
mozIDOMWindowProxy** aWindow)
{
RefPtr<nsGlobalWindow> window = nsGlobalWindow::GetOuterWindowWithId(aWindowID);
nsCOMPtr<nsPIDOMWindowOuter> outer = window ? window->AsOuter() : nullptr;
outer.forget(aWindow);
return NS_OK;
}
NS_IMETHODIMP
nsWindowMediator::GetCurrentInnerWindowWithId(uint64_t aWindowID,
mozIDOMWindow** aWindow)
{
RefPtr<nsGlobalWindow> window = nsGlobalWindow::GetInnerWindowWithId(aWindowID);
// not found
if (!window)
return NS_OK;
nsCOMPtr<nsPIDOMWindowInner> inner = window->AsInner();
nsCOMPtr<nsPIDOMWindowOuter> outer = inner->GetOuterWindow();
NS_ENSURE_TRUE(outer, NS_ERROR_UNEXPECTED);
// outer is already using another inner, so it's same as not found
if (outer->GetCurrentInnerWindow() != inner)
return NS_OK;
inner.forget(aWindow);
return NS_OK;
}
NS_IMETHODIMP
nsWindowMediator::UpdateWindowTimeStamp(nsIXULWindow* inWindow)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
NS_ENSURE_STATE(mReady);
nsWindowInfo *info = GetInfoFor(inWindow);
if (info) {
// increment the window's time stamp
info->mTimeStamp = ++mTimeStamp;
return NS_OK;
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsWindowMediator::UpdateWindowTitle(nsIXULWindow* inWindow,
const char16_t* inTitle)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
NS_ENSURE_STATE(mReady);
if (GetInfoFor(inWindow)) {
WindowTitleData winData = { inWindow, inTitle };
mListeners.EnumerateForwards(notifyWindowTitleChange, &winData);
}
return NS_OK;
}
/* This method's plan is to intervene only when absolutely necessary.
We will get requests to place our windows behind unknown windows.
For the most part, we need to leave those alone (turning them into
explicit requests to be on top breaks Windows.) So generally we
calculate a change as seldom as possible.
*/
NS_IMETHODIMP
nsWindowMediator::CalculateZPosition(
nsIXULWindow *inWindow,
uint32_t inPosition,
nsIWidget *inBelow,
uint32_t *outPosition,
nsIWidget **outBelow,
bool *outAltered)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
NS_ENSURE_ARG_POINTER(outBelow);
NS_ENSURE_STATE(mReady);
*outBelow = nullptr;
if (!inWindow || !outPosition || !outAltered)
return NS_ERROR_NULL_POINTER;
if (inPosition != nsIWindowMediator::zLevelTop &&
inPosition != nsIWindowMediator::zLevelBottom &&
inPosition != nsIWindowMediator::zLevelBelow)
return NS_ERROR_INVALID_ARG;
nsWindowInfo *info = mTopmostWindow;
nsIXULWindow *belowWindow = nullptr;
bool found = false;
nsresult result = NS_OK;
*outPosition = inPosition;
*outAltered = false;
if (mSortingZOrder) { // don't fight SortZOrder()
*outBelow = inBelow;
NS_IF_ADDREF(*outBelow);
return NS_OK;
}
uint32_t inZ;
GetZLevel(inWindow, &inZ);
if (inPosition == nsIWindowMediator::zLevelBelow) {
// locate inBelow. use topmost if it can't be found or isn't in the
// z-order list
info = GetInfoFor(inBelow);
if (!info || (info->mYounger != info && info->mLower == info))
info = mTopmostWindow;
else
found = true;
if (!found) {
/* Treat unknown windows as a request to be on top.
Not as it should be, but that's what Windows gives us.
Note we change inPosition, but not *outPosition. This forces
us to go through the "on top" calculation just below, without
necessarily changing the output parameters. */
inPosition = nsIWindowMediator::zLevelTop;
}
}
if (inPosition == nsIWindowMediator::zLevelTop) {
if (mTopmostWindow && mTopmostWindow->mZLevel > inZ) {
// asked for topmost, can't have it. locate highest allowed position.
do {
if (info->mZLevel <= inZ)
break;
info = info->mLower;
} while (info != mTopmostWindow);
*outPosition = nsIWindowMediator::zLevelBelow;
belowWindow = info->mHigher->mWindow;
*outAltered = true;
}
} else if (inPosition == nsIWindowMediator::zLevelBottom) {
if (mTopmostWindow && mTopmostWindow->mHigher->mZLevel < inZ) {
// asked for bottommost, can't have it. locate lowest allowed position.
do {
info = info->mHigher;
if (info->mZLevel >= inZ)
break;
} while (info != mTopmostWindow);
*outPosition = nsIWindowMediator::zLevelBelow;
belowWindow = info->mWindow;
*outAltered = true;
}
} else {
unsigned long relativeZ;
// check that we're in the right z-plane
if (found) {
belowWindow = info->mWindow;
relativeZ = info->mZLevel;
if (relativeZ > inZ) {
// might be OK. is lower window, if any, lower?
if (info->mLower != info && info->mLower->mZLevel > inZ) {
do {
if (info->mZLevel <= inZ)
break;
info = info->mLower;
} while (info != mTopmostWindow);
belowWindow = info->mHigher->mWindow;
*outAltered = true;
}
} else if (relativeZ < inZ) {
// nope. look for a higher window to be behind.
do {
info = info->mHigher;
if (info->mZLevel >= inZ)
break;
} while (info != mTopmostWindow);
if (info->mZLevel >= inZ)
belowWindow = info->mWindow;
else
*outPosition = nsIWindowMediator::zLevelTop;
*outAltered = true;
} // else they're equal, so it's OK
}
}
if (NS_SUCCEEDED(result) && belowWindow) {
nsCOMPtr<nsIBaseWindow> base(do_QueryInterface(belowWindow));
if (base)
base->GetMainWidget(outBelow);
else
result = NS_ERROR_NO_INTERFACE;
}
return result;
}
NS_IMETHODIMP
nsWindowMediator::SetZPosition(
nsIXULWindow *inWindow,
uint32_t inPosition,
nsIXULWindow *inBelow)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
nsWindowInfo *inInfo,
*belowInfo;
if ((inPosition != nsIWindowMediator::zLevelTop &&
inPosition != nsIWindowMediator::zLevelBottom &&
inPosition != nsIWindowMediator::zLevelBelow) ||
!inWindow) {
return NS_ERROR_INVALID_ARG;
}
if (mSortingZOrder) // don't fight SortZOrder()
return NS_OK;
NS_ENSURE_STATE(mReady);
/* Locate inWindow and unlink it from the z-order list.
It's important we look for it in the age list, not the z-order list.
This is because the former is guaranteed complete, while
now may be this window's first exposure to the latter. */
inInfo = GetInfoFor(inWindow);
if (!inInfo)
return NS_ERROR_INVALID_ARG;
// locate inBelow, place inWindow behind it
if (inPosition == nsIWindowMediator::zLevelBelow) {
belowInfo = GetInfoFor(inBelow);
// it had better also be in the z-order list
if (belowInfo &&
belowInfo->mYounger != belowInfo && belowInfo->mLower == belowInfo) {
belowInfo = nullptr;
}
if (!belowInfo) {
if (inBelow)
return NS_ERROR_INVALID_ARG;
else
inPosition = nsIWindowMediator::zLevelTop;
}
}
if (inPosition == nsIWindowMediator::zLevelTop ||
inPosition == nsIWindowMediator::zLevelBottom)
belowInfo = mTopmostWindow ? mTopmostWindow->mHigher : nullptr;
if (inInfo != belowInfo) {
inInfo->Unlink(false, true);
inInfo->InsertAfter(nullptr, belowInfo);
}
if (inPosition == nsIWindowMediator::zLevelTop)
mTopmostWindow = inInfo;
return NS_OK;
}
NS_IMETHODIMP
nsWindowMediator::GetZLevel(nsIXULWindow *aWindow, uint32_t *_retval)
{
NS_ENSURE_ARG_POINTER(_retval);
*_retval = nsIXULWindow::normalZ;
nsWindowInfo *info = GetInfoFor(aWindow);
if (info) {
*_retval = info->mZLevel;
} else {
NS_WARNING("getting z level of unregistered window");
// this goes off during window destruction
}
return NS_OK;
}
NS_IMETHODIMP
nsWindowMediator::SetZLevel(nsIXULWindow *aWindow, uint32_t aZLevel)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
NS_ENSURE_STATE(mReady);
nsWindowInfo *info = GetInfoFor(aWindow);
NS_ASSERTION(info, "setting z level of unregistered window");
if (!info)
return NS_ERROR_FAILURE;
if (info->mZLevel != aZLevel) {
bool lowered = info->mZLevel > aZLevel;
info->mZLevel = aZLevel;
if (lowered)
SortZOrderFrontToBack();
else
SortZOrderBackToFront();
}
return NS_OK;
}
/* Fix potentially out-of-order windows by performing an insertion sort
on the z-order list. The method will work no matter how broken the
list, but its assumed usage is immediately after one window's z level
has been changed, so one window is potentially out of place. Such a sort
is most efficiently done in a particular direction. Use this one
if a window's z level has just been reduced, so the sort is most efficiently
done front to back.
Note it's hardly worth going to all the trouble to write two versions
of this method except that if we choose the inefficient sorting direction,
on slow systems windows could visibly bubble around the window that
was moved.
*/
void
nsWindowMediator::SortZOrderFrontToBack()
{
nsWindowInfo *scan, // scans list looking for problems
*search, // searches for correct placement for scan window
*prev, // previous search element
*lowest; // bottom-most window in list
bool finished;
if (!mTopmostWindow) // early during program execution there's no z list yet
return; // there's also only one window, so this is not dangerous
mSortingZOrder = true;
/* Step through the list from top to bottom. If we find a window which
should be moved down in the list, move it to its highest legal position. */
do {
finished = true;
lowest = mTopmostWindow->mHigher;
scan = mTopmostWindow;
while (scan != lowest) {
uint32_t scanZ = scan->mZLevel;
if (scanZ < scan->mLower->mZLevel) { // out of order
search = scan->mLower;
do {
prev = search;
search = search->mLower;
} while (prev != lowest && scanZ < search->mZLevel);
// reposition |scan| within the list
if (scan == mTopmostWindow)
mTopmostWindow = scan->mLower;
scan->Unlink(false, true);
scan->InsertAfter(nullptr, prev);
// fix actual window order
nsCOMPtr<nsIBaseWindow> base;
nsCOMPtr<nsIWidget> scanWidget;
nsCOMPtr<nsIWidget> prevWidget;
base = do_QueryInterface(scan->mWindow);
if (base)
base->GetMainWidget(getter_AddRefs(scanWidget));
base = do_QueryInterface(prev->mWindow);
if (base)
base->GetMainWidget(getter_AddRefs(prevWidget));
if (scanWidget)
scanWidget->PlaceBehind(eZPlacementBelow, prevWidget, false);
finished = false;
break;
}
scan = scan->mLower;
}
} while (!finished);
mSortingZOrder = false;
}
// see comment for SortZOrderFrontToBack
void
nsWindowMediator::SortZOrderBackToFront()
{
nsWindowInfo *scan, // scans list looking for problems
*search, // searches for correct placement for scan window
*lowest; // bottom-most window in list
bool finished;
if (!mTopmostWindow) // early during program execution there's no z list yet
return; // there's also only one window, so this is not dangerous
mSortingZOrder = true;
/* Step through the list from bottom to top. If we find a window which
should be moved up in the list, move it to its lowest legal position. */
do {
finished = true;
lowest = mTopmostWindow->mHigher;
scan = lowest;
while (scan != mTopmostWindow) {
uint32_t scanZ = scan->mZLevel;
if (scanZ > scan->mHigher->mZLevel) { // out of order
search = scan;
do {
search = search->mHigher;
} while (search != lowest && scanZ > search->mZLevel);
// reposition |scan| within the list
if (scan != search && scan != search->mLower) {
scan->Unlink(false, true);
scan->InsertAfter(nullptr, search);
}
if (search == lowest)
mTopmostWindow = scan;
// fix actual window order
nsCOMPtr<nsIBaseWindow> base;
nsCOMPtr<nsIWidget> scanWidget;
nsCOMPtr<nsIWidget> searchWidget;
base = do_QueryInterface(scan->mWindow);
if (base)
base->GetMainWidget(getter_AddRefs(scanWidget));
if (mTopmostWindow != scan) {
base = do_QueryInterface(search->mWindow);
if (base)
base->GetMainWidget(getter_AddRefs(searchWidget));
}
if (scanWidget)
scanWidget->PlaceBehind(eZPlacementBelow, searchWidget, false);
finished = false;
break;
}
scan = scan->mHigher;
}
} while (!finished);
mSortingZOrder = false;
}
NS_IMPL_ISUPPORTS(nsWindowMediator,
nsIWindowMediator_44,
nsIWindowMediator,
nsIObserver,
nsISupportsWeakReference)
NS_IMETHODIMP
nsWindowMediator::AddListener(nsIWindowMediatorListener* aListener)
{
NS_ENSURE_ARG_POINTER(aListener);
mListeners.AppendObject(aListener);
return NS_OK;
}
NS_IMETHODIMP
nsWindowMediator::RemoveListener(nsIWindowMediatorListener* aListener)
{
NS_ENSURE_ARG_POINTER(aListener);
mListeners.RemoveObject(aListener);
return NS_OK;
}
NS_IMETHODIMP
nsWindowMediator::Observe(nsISupports* aSubject,
const char* aTopic,
const char16_t* aData)
{
if (!strcmp(aTopic, "xpcom-shutdown") && mReady) {
MOZ_RELEASE_ASSERT(NS_IsMainThread());
while (mOldestWindow)
UnregisterWindow(mOldestWindow);
mReady = false;
}
return NS_OK;
}
bool
notifyOpenWindow(nsIWindowMediatorListener *aListener, void* aData)
{
WindowTitleData* winData = static_cast<WindowTitleData*>(aData);
aListener->OnOpenWindow(winData->mWindow);
return true;
}
bool
notifyCloseWindow(nsIWindowMediatorListener *aListener, void* aData)
{
WindowTitleData* winData = static_cast<WindowTitleData*>(aData);
aListener->OnCloseWindow(winData->mWindow);
return true;
}
bool
notifyWindowTitleChange(nsIWindowMediatorListener *aListener, void* aData)
{
WindowTitleData* titleData = reinterpret_cast<WindowTitleData*>(aData);
aListener->OnWindowTitleChange(titleData->mWindow, titleData->mTitle);
return true;
}

View file

@ -0,0 +1,78 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 nsWindowMediator_h_
#define nsWindowMediator_h_
#include "nsCOMPtr.h"
#include "nsIWindowMediator.h"
#include "nsIObserver.h"
#include "nsTArray.h"
#include "nsXPIDLString.h"
#include "nsWeakReference.h"
#include "nsCOMArray.h"
class nsAppShellWindowEnumerator;
class nsASXULWindowEarlyToLateEnumerator;
class nsASDOMWindowEarlyToLateEnumerator;
class nsASDOMWindowFrontToBackEnumerator;
class nsASXULWindowFrontToBackEnumerator;
class nsASDOMWindowBackToFrontEnumerator;
class nsASXULWindowBackToFrontEnumerator;
class nsIWindowMediatorListener;
struct nsWindowInfo;
class nsWindowMediator :
public nsIWindowMediator_44,
public nsIObserver,
public nsSupportsWeakReference
{
friend class nsAppShellWindowEnumerator;
friend class nsASXULWindowEarlyToLateEnumerator;
friend class nsASDOMWindowEarlyToLateEnumerator;
friend class nsASDOMWindowFrontToBackEnumerator;
friend class nsASXULWindowFrontToBackEnumerator;
friend class nsASDOMWindowBackToFrontEnumerator;
friend class nsASXULWindowBackToFrontEnumerator;
protected:
virtual ~nsWindowMediator();
public:
nsWindowMediator();
nsresult Init();
NS_DECL_ISUPPORTS
NS_DECL_NSIWINDOWMEDIATOR
NS_DECL_NSIWINDOWMEDIATOR_44
NS_DECL_NSIOBSERVER
static nsresult GetDOMWindow(nsIXULWindow* inWindow,
nsCOMPtr<nsPIDOMWindowOuter>& outDOMWindow);
private:
int32_t AddEnumerator(nsAppShellWindowEnumerator* inEnumerator);
int32_t RemoveEnumerator(nsAppShellWindowEnumerator* inEnumerator);
nsWindowInfo* MostRecentWindowInfo(const char16_t* inType,
bool aSkipPrivateBrowsingOrClosed = false);
nsresult UnregisterWindow(nsWindowInfo *inInfo);
nsWindowInfo *GetInfoFor(nsIXULWindow *aWindow);
nsWindowInfo *GetInfoFor(nsIWidget *aWindow);
void SortZOrderFrontToBack();
void SortZOrderBackToFront();
nsTArray<nsAppShellWindowEnumerator*> mEnumeratorList;
nsWindowInfo *mOldestWindow;
nsWindowInfo *mTopmostWindow;
int32_t mTimeStamp;
bool mSortingZOrder;
bool mReady;
nsCOMArray<nsIWindowMediatorListener> mListeners;
};
#endif

File diff suppressed because it is too large Load diff

199
xpfe/appshell/nsXULWindow.h Normal file
View file

@ -0,0 +1,199 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 nsXULWindow_h__
#define nsXULWindow_h__
// Local Includes
#include "nsChromeTreeOwner.h"
#include "nsContentTreeOwner.h"
// Helper classes
#include "nsCOMPtr.h"
#include "nsTArray.h"
#include "nsString.h"
#include "nsWeakReference.h"
#include "nsCOMArray.h"
#include "nsRect.h"
#include "Units.h"
// Interfaces needed
#include "nsIBaseWindow.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeItem.h"
#include "nsIDOMWindow.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIXULWindow.h"
#include "nsIPrompt.h"
#include "nsIAuthPrompt.h"
#include "nsIXULBrowserWindow.h"
#include "nsIWeakReference.h"
#include "nsIWidgetListener.h"
#include "nsITabParent.h"
namespace mozilla {
namespace dom {
class Element;
} // namespace dom
} // namespace mozilla
// nsXULWindow
#define NS_XULWINDOW_IMPL_CID \
{ /* 8eaec2f3-ed02-4be2-8e0f-342798477298 */ \
0x8eaec2f3, \
0xed02, \
0x4be2, \
{ 0x8e, 0x0f, 0x34, 0x27, 0x98, 0x47, 0x72, 0x98 } \
}
class nsContentShellInfo;
class nsXULWindow : public nsIBaseWindow,
public nsIInterfaceRequestor,
public nsIXULWindow,
public nsSupportsWeakReference
{
friend class nsChromeTreeOwner;
friend class nsContentTreeOwner;
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSIXULWINDOW
NS_DECL_NSIBASEWINDOW
NS_DECLARE_STATIC_IID_ACCESSOR(NS_XULWINDOW_IMPL_CID)
void LockUntilChromeLoad() { mLockedUntilChromeLoad = true; }
bool IsLocked() const { return mLockedUntilChromeLoad; }
void IgnoreXULSizeMode(bool aEnable) { mIgnoreXULSizeMode = aEnable; }
void WasRegistered() { mRegistered = true; }
protected:
enum persistentAttributes {
PAD_MISC = 0x1,
PAD_POSITION = 0x2,
PAD_SIZE = 0x4
};
explicit nsXULWindow(uint32_t aChromeFlags);
virtual ~nsXULWindow();
NS_IMETHOD EnsureChromeTreeOwner();
NS_IMETHOD EnsureContentTreeOwner();
NS_IMETHOD EnsurePrimaryContentTreeOwner();
NS_IMETHOD EnsurePrompter();
NS_IMETHOD EnsureAuthPrompter();
void OnChromeLoaded();
void StaggerPosition(int32_t &aRequestedX, int32_t &aRequestedY,
int32_t aSpecWidth, int32_t aSpecHeight);
bool LoadPositionFromXUL(int32_t aSpecWidth, int32_t aSpecHeight);
bool LoadSizeFromXUL(int32_t& aSpecWidth, int32_t& aSpecHeight);
void SetSpecifiedSize(int32_t aSpecWidth, int32_t aSpecHeight);
bool LoadMiscPersistentAttributesFromXUL();
void SyncAttributesToWidget();
NS_IMETHOD SavePersistentAttributes();
NS_IMETHOD GetWindowDOMWindow(mozIDOMWindowProxy** aDOMWindow);
mozilla::dom::Element* GetWindowDOMElement() const;
// See nsIDocShellTreeOwner for docs on next two methods
nsresult ContentShellAdded(nsIDocShellTreeItem* aContentShell,
bool aPrimary, bool aTargetable,
const nsAString& aID);
nsresult ContentShellRemoved(nsIDocShellTreeItem* aContentShell);
NS_IMETHOD GetPrimaryContentSize(int32_t* aWidth,
int32_t* aHeight);
NS_IMETHOD SetPrimaryContentSize(int32_t aWidth,
int32_t aHeight);
nsresult GetRootShellSize(int32_t* aWidth,
int32_t* aHeight);
nsresult SetRootShellSize(int32_t aWidth,
int32_t aHeight);
NS_IMETHOD SizeShellTo(nsIDocShellTreeItem* aShellItem, int32_t aCX,
int32_t aCY);
NS_IMETHOD ExitModalLoop(nsresult aStatus);
NS_IMETHOD CreateNewChromeWindow(int32_t aChromeFlags, nsITabParent* aOpeningTab, mozIDOMWindowProxy* aOpenerWindow, nsIXULWindow **_retval);
NS_IMETHOD CreateNewContentWindow(int32_t aChromeFlags, nsITabParent* aOpeningTab, mozIDOMWindowProxy* aOpenerWindow, nsIXULWindow **_retval);
NS_IMETHOD GetHasPrimaryContent(bool* aResult);
void EnableParent(bool aEnable);
bool ConstrainToZLevel(bool aImmediate, nsWindowZ *aPlacement,
nsIWidget *aReqBelow, nsIWidget **aActualBelow);
void PlaceWindowLayersBehind(uint32_t aLowLevel, uint32_t aHighLevel,
nsIXULWindow *aBehind);
void SetContentScrollbarVisibility(bool aVisible);
bool GetContentScrollbarVisibility();
void PersistentAttributesDirty(uint32_t aDirtyFlags);
nsChromeTreeOwner* mChromeTreeOwner;
nsContentTreeOwner* mContentTreeOwner;
nsContentTreeOwner* mPrimaryContentTreeOwner;
nsCOMPtr<nsIWidget> mWindow;
nsCOMPtr<nsIDocShell> mDocShell;
nsCOMPtr<nsPIDOMWindowOuter> mDOMWindow;
nsCOMPtr<nsIWeakReference> mParentWindow;
nsCOMPtr<nsIPrompt> mPrompter;
nsCOMPtr<nsIAuthPrompt> mAuthPrompter;
nsCOMPtr<nsIXULBrowserWindow> mXULBrowserWindow;
nsCOMPtr<nsIDocShellTreeItem> mPrimaryContentShell;
nsTArray<nsContentShellInfo*> mContentShells; // array of doc shells by id
nsresult mModalStatus;
bool mContinueModalLoop;
bool mDebuting; // being made visible right now
bool mChromeLoaded; // True when chrome has loaded
bool mShowAfterLoad;
bool mIntrinsicallySized;
bool mCenterAfterLoad;
bool mIsHiddenWindow;
bool mLockedUntilChromeLoad;
bool mIgnoreXULSize;
bool mIgnoreXULPosition;
bool mChromeFlagsFrozen;
bool mIgnoreXULSizeMode;
// mDestroying is used to prevent reentry into into Destroy(), which can
// otherwise happen due to script running as we tear down various things.
bool mDestroying;
bool mRegistered;
uint32_t mContextFlags;
uint32_t mPersistentAttributesDirty; // persistentAttributes
uint32_t mPersistentAttributesMask;
uint32_t mChromeFlags;
nsString mTitle;
nsIntRect mOpenerScreenRect; // the screen rect of the opener
nsCOMArray<nsIWeakReference> mTargetableShells; // targetable shells only
nsCOMPtr<nsITabParent> mPrimaryTabParent;
private:
nsresult GetPrimaryTabParentSize(int32_t* aWidth, int32_t* aHeight);
nsresult GetPrimaryContentShellSize(int32_t* aWidth, int32_t* aHeight);
nsresult SetPrimaryTabParentSize(int32_t aWidth, int32_t aHeight);
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsXULWindow, NS_XULWINDOW_IMPL_CID)
// nsContentShellInfo
// Used to map shell IDs to nsIDocShellTreeItems.
class nsContentShellInfo
{
public:
nsContentShellInfo(const nsAString& aID,
nsIWeakReference* aContentShell);
~nsContentShellInfo();
public:
nsString id; // The identifier of the content shell
nsWeakPtr child; // content shell (weak reference to nsIDocShellTreeItem)
};
#endif /* nsXULWindow_h__ */

View file

@ -0,0 +1,5 @@
[DEFAULT]
skip-if = os == 'android'
[test_hiddenPrivateWindow.xul]
[test_windowlessBrowser.xul]

View file

@ -0,0 +1,45 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=815847
-->
<window title="Mozilla Bug 815847"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=815847">Mozilla Bug 815847</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<script class="testbody" type="application/javascript">
<![CDATA[
var Cu = Components.utils;
Cu.import('resource://gre/modules/Services.jsm');
Cu.import('resource://gre/modules/PrivateBrowsingUtils.jsm');
ok(Services.appShell.hiddenWindow, "hiddenWindow should exist");
ok(Services.appShell.hiddenDOMWindow, "hiddenDOMWindow should exist");
ok(Services.appShell.hiddenPrivateWindow, "hiddenPrivateWindow should exist");
ok(Services.appShell.hiddenPrivateDOMWindow, "hiddenPrivateDOMWindow should exist");
ok(!PrivateBrowsingUtils.isWindowPrivate(Services.appShell.hiddenWindow.docShell), "hiddenWindow should not be private");
ok(!PrivateBrowsingUtils.isWindowPrivate(Services.appShell.hiddenDOMWindow), "hiddenDOMWindow should not be private");
ok(PrivateBrowsingUtils.isWindowPrivate(Services.appShell.hiddenPrivateWindow.docShell), "hiddenPrivateWindow should be private");
ok(PrivateBrowsingUtils.isWindowPrivate(Services.appShell.hiddenPrivateDOMWindow), "hiddenPrivateDOMWindow should be private");
]]>
</script>
</window>

View file

@ -0,0 +1,75 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=815847
-->
<window title="Mozilla Bug 815847"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1214174">Mozilla Bug 1214174</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<script class="testbody" type="application/javascript">
<![CDATA[
var Cu = Components.utils;
var Ci = Components.interfaces;
Cu.import('resource://gre/modules/Services.jsm');
function testWindowlessBrowser(chromePrivileged) {
var webNav = Services.appShell.createWindowlessBrowser(chromePrivileged);
ok(webNav, "createWindowlessBrowser should return a wevNav");
let interfaceRequestor = webNav.QueryInterface(Ci.nsIInterfaceRequestor);
let docShell = interfaceRequestor.getInterface(Ci.nsIDocShell);
ok(docShell, "docShell should be defined");
ok(docShell.contentViewer.DOMDocument.defaultView, "docShell defaultView should be defined");
var win = docShell.contentViewer.DOMDocument.defaultView;
ok(win.screenX == 0, "window.screenX should be 0 in a windowless browser");
ok(win.screenY == 0, "window.screenY should be 0 in a windowless browser");
ok(win.outerWidth == 0, "window.outerWidth should be 0 in a windowless browser");
ok(win.outerHeight == 0, "window.outerHeight should be 0 in a windowless browser");
ok(win.sidebar, "window.sidebar should be defined");
ok(win.external, "window.external should be defined");
var exception;
try {
win.external.AddSearchProvider("http://test-fake.url");
} catch(e) {
exception = e;
}
ok(!exception, "window.external.AddSearchProvider should be ignore withour raising an exception");
webNav.close();
}
info("Test Bug 1214174 on a content privileged windowless browser");
testWindowlessBrowser(false);
info("Test Bug 1214174 on a chrome privileged windowless browser");
testWindowlessBrowser(true);
]]>
</script>
</window>

View file

@ -0,0 +1,9 @@
# 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/.
toolkit.jar:
content/global/autocomplete.xml (resources/content/autocomplete.xml)
comm.jar:
content/communicator/autocomplete.css (resources/content/autocomplete.css)

View file

@ -0,0 +1,7 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
JAR_MANIFESTS += ['jar.mn']

View file

@ -0,0 +1,46 @@
/* 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/. */
.autocomplete-result-popupset {
width: 0 !important;
}
.autocomplete-result-popup {
display: -moz-popup !important;
}
/* the C++ implementation of widgets is too eager to make popups visible.
this causes problems (bug 120155 and others), thus this workaround: */
.autocomplete-result-popup[hidden="true"] {
visibility: hidden;
}
.autocomplete-tree {
-moz-user-focus: ignore;
}
.autocomplete-history-dropmarker {
display: none;
}
.autocomplete-history-dropmarker[enablehistory="true"] {
display: -moz-box;
}
/* The following rule is here to fix bug 96899 (and now 117952).
Somehow trees create a situation
in which a popupset flows itself as if its popup child is directly within it
instead of the placeholder child that should actually be inside the popupset.
This is a stopgap measure, and it does not address the real bug. */
popupset {
max-width: 0px;
width: 0px;
min-width: 0%;
min-height: 0%;
}
treecolpicker {
display: none;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,15 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
SOURCES += [
'nsModule.cpp',
]
FINAL_LIBRARY = 'xul'
LOCAL_INCLUDES += [
'../directory',
]

View file

@ -0,0 +1,44 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 "mozilla/ModuleUtils.h"
#include "nsDirectoryViewer.h"
#include "rdf.h"
#include "nsRDFCID.h"
#include "nsCURILoader.h"
// Factory constructors
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsHTTPIndex, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDirectoryViewerFactory)
NS_DEFINE_NAMED_CID(NS_DIRECTORYVIEWERFACTORY_CID);
NS_DEFINE_NAMED_CID(NS_HTTPINDEX_SERVICE_CID);
static const mozilla::Module::CIDEntry kXPFECIDs[] = {
{ &kNS_DIRECTORYVIEWERFACTORY_CID, false, nullptr, nsDirectoryViewerFactoryConstructor },
{ &kNS_HTTPINDEX_SERVICE_CID, false, nullptr, nsHTTPIndexConstructor },
{ nullptr }
};
static const mozilla::Module::ContractIDEntry kXPFEContracts[] = {
{ "@mozilla.org/xpfe/http-index-format-factory-constructor", &kNS_DIRECTORYVIEWERFACTORY_CID },
{ NS_HTTPINDEX_SERVICE_CONTRACTID, &kNS_HTTPINDEX_SERVICE_CID },
{ NS_HTTPINDEX_DATASOURCE_CONTRACTID, &kNS_HTTPINDEX_SERVICE_CID },
{ nullptr }
};
static const mozilla::Module::CategoryEntry kXPFECategories[] = {
{ "Gecko-Content-Viewers", "application/http-index-format", "@mozilla.org/xpfe/http-index-format-factory-constructor" },
{ nullptr }
};
static const mozilla::Module kXPFEModule = {
mozilla::Module::kVersion,
kXPFECIDs,
kXPFEContracts,
kXPFECategories
};
NSMODULE_DEFN(application) = &kXPFEModule;

View file

@ -0,0 +1,20 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
XPIDL_SOURCES += [
'nsIHTTPIndex.idl',
]
XPIDL_MODULE = 'directory'
SOURCES += [
'nsDirectoryViewer.cpp',
]
FINAL_LIBRARY = 'xul'
if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wno-error=shadow']

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,126 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 nsdirectoryviewer__h____
#define nsdirectoryviewer__h____
#include "nsCOMPtr.h"
#include "nsIStreamListener.h"
#include "nsIContentViewer.h"
#include "nsIHTTPIndex.h"
#include "nsIRDFService.h"
#include "nsIRDFDataSource.h"
#include "nsIRDFLiteral.h"
#include "nsIDocumentLoaderFactory.h"
#include "nsITimer.h"
#include "nsXPIDLString.h"
#include "nsIDirIndexListener.h"
#include "nsIFTPChannel.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIInterfaceRequestor.h"
#include "nsIURI.h"
class nsIMutableArray;
class nsDirectoryViewerFactory : public nsIDocumentLoaderFactory
{
public:
nsDirectoryViewerFactory();
// nsISupports interface
NS_DECL_ISUPPORTS
NS_DECL_NSIDOCUMENTLOADERFACTORY
protected:
virtual ~nsDirectoryViewerFactory();
};
class nsHTTPIndex final : public nsIHTTPIndex,
public nsIRDFDataSource,
public nsIStreamListener,
public nsIDirIndexListener,
public nsIInterfaceRequestor,
public nsIFTPEventSink
{
private:
// note: these are NOT statics due to the native of nsHTTPIndex
// where it may or may not be treated as a singleton
nsCOMPtr<nsIRDFResource> kNC_Child;
nsCOMPtr<nsIRDFResource> kNC_Comment;
nsCOMPtr<nsIRDFResource> kNC_Loading;
nsCOMPtr<nsIRDFResource> kNC_URL;
nsCOMPtr<nsIRDFResource> kNC_Description;
nsCOMPtr<nsIRDFResource> kNC_ContentLength;
nsCOMPtr<nsIRDFResource> kNC_LastModified;
nsCOMPtr<nsIRDFResource> kNC_ContentType;
nsCOMPtr<nsIRDFResource> kNC_FileType;
nsCOMPtr<nsIRDFResource> kNC_IsContainer;
nsCOMPtr<nsIRDFLiteral> kTrueLiteral;
nsCOMPtr<nsIRDFLiteral> kFalseLiteral;
nsCOMPtr<nsIRDFService> mDirRDF;
protected:
// We grab a reference to the content viewer container (which
// indirectly owns us) so that we can insert ourselves as a global
// in the script context _after_ the XUL doc has been embedded into
// content viewer. We'll know that this has happened once we receive
// an OnStartRequest() notification
nsCOMPtr<nsIRDFDataSource> mInner;
nsCOMPtr<nsIMutableArray> mConnectionList;
nsCOMPtr<nsIMutableArray> mNodeList;
nsCOMPtr<nsITimer> mTimer;
nsCOMPtr<nsIDirIndexParser> mParser;
nsCString mBaseURL;
nsCString mEncoding;
bool mBindToGlobalObject;
nsIInterfaceRequestor* mRequestor; // WEAK
nsCOMPtr<nsIRDFResource> mDirectory;
explicit nsHTTPIndex(nsIInterfaceRequestor* aRequestor);
nsresult CommonInit(void);
nsresult Init(nsIURI* aBaseURL);
void GetDestination(nsIRDFResource* r, nsXPIDLCString& dest);
bool isWellknownContainerURI(nsIRDFResource *r);
nsresult AddElement(nsIRDFResource *parent, nsIRDFResource *prop,
nsIRDFNode *child);
static void FireTimer(nsITimer* aTimer, void* aClosure);
virtual ~nsHTTPIndex();
public:
nsHTTPIndex();
nsresult Init(void);
static nsresult Create(nsIURI* aBaseURI, nsIInterfaceRequestor* aContainer,
nsIHTTPIndex** aResult);
// nsIHTTPIndex interface
NS_DECL_NSIHTTPINDEX
// NSIRDFDataSource interface
NS_DECL_NSIRDFDATASOURCE
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIDIRINDEXLISTENER
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSIFTPEVENTSINK
// nsISupports interface
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsHTTPIndex, nsIHTTPIndex)
};
// {82776710-5690-11d3-BE36-00104BDE6048}
#define NS_DIRECTORYVIEWERFACTORY_CID \
{ 0x82776710, 0x5690, 0x11d3, { 0xbe, 0x36, 0x0, 0x10, 0x4b, 0xde, 0x60, 0x48 } }
#endif // nsdirectoryviewer__h____

View file

@ -0,0 +1,50 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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/. */
/*
The interface to an HTTP index
*/
#include "nsISupports.idl"
interface nsIStreamListener;
interface nsIRDFDataSource;
interface nsIRDFNode;
interface nsIRDFResource;
[scriptable, uuid(6F2BDBD0-58C3-11d3-BE36-00104BDE6048)]
interface nsIHTTPIndex : nsISupports
{
/**
* The base URL of the HTTP index
*/
readonly attribute string BaseURL;
/**
* The RDF datasource that contains the HTTP index information.
*/
readonly attribute nsIRDFDataSource DataSource;
/**
* The charset to use for decoding FTP filenames
*/
attribute string encoding;
};
%{C++
// {{2587e382-1324-11d4-a652-eadbb2be3484}
#define NS_HTTPINDEX_SERVICE_CID \
{ 0x2587e382, 0x1324, 0x11d4, { 0xa6, 0x52, 0xea, 0xdb, 0xb2, 0xbe, 0x34, 0x84 } }
#define NS_HTTPINDEX_SERVICE_CONTRACTID \
"@mozilla.org/browser/httpindex-service;1"
#define NS_HTTPINDEX_DATASOURCE_CONTRACTID \
"@mozilla.org/rdf/datasource;1?name=httpindex"
%}

12
xpfe/components/moz.build Normal file
View file

@ -0,0 +1,12 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
DIRS += [
'windowds',
'directory',
'build',
]

View file

@ -0,0 +1,17 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
XPIDL_SOURCES += [
'nsIWindowDataSource.idl',
]
XPIDL_MODULE = 'windowds'
SOURCES += [
'nsWindowDataSource.cpp',
]
FINAL_LIBRARY = 'xul'

View file

@ -0,0 +1,17 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 "nsISupports.idl"
#include "nsIDOMWindow.idl"
// interface for accessing RDF-specific data from the window datasource
[scriptable, uuid(3722A5B9-5323-4ed0-BB1A-8299F27A4E89)]
interface nsIWindowDataSource : nsISupports
{
/**
* for the given resource name, return the window
*/
nsIDOMWindow getWindowForResource(in string inResource);
};

View file

@ -0,0 +1,519 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 "nsWindowDataSource.h"
#include "nsIXULWindow.h"
#include "rdf.h"
#include "nsIRDFContainerUtils.h"
#include "nsIServiceManager.h"
#include "nsReadableUtils.h"
#include "nsIObserverService.h"
#include "nsIWindowMediator.h"
#include "nsXPCOMCID.h"
#include "mozilla/ModuleUtils.h"
#include "nsString.h"
// just to do the reverse-lookup! sheesh.
#include "nsIInterfaceRequestorUtils.h"
#include "nsIDocShell.h"
uint32_t nsWindowDataSource::windowCount = 0;
nsIRDFResource* nsWindowDataSource::kNC_Name = nullptr;
nsIRDFResource* nsWindowDataSource::kNC_WindowRoot = nullptr;
nsIRDFResource* nsWindowDataSource::kNC_KeyIndex = nullptr;
nsIRDFService* nsWindowDataSource::gRDFService = nullptr;
uint32_t nsWindowDataSource::gRefCnt = 0;
#define URINC_WINDOWROOT "NC:WindowMediatorRoot"
#define URINC_NAME NC_NAMESPACE_URI "Name"
#define URINC_KEYINDEX NC_NAMESPACE_URI "KeyIndex"
nsresult
nsWindowDataSource::Init()
{
nsresult rv;
if (gRefCnt++ == 0) {
rv = CallGetService("@mozilla.org/rdf/rdf-service;1", &gRDFService);
if (NS_FAILED(rv)) return rv;
gRDFService->GetResource(NS_LITERAL_CSTRING(URINC_WINDOWROOT), &kNC_WindowRoot);
gRDFService->GetResource(NS_LITERAL_CSTRING(URINC_NAME), &kNC_Name);
gRDFService->GetResource(NS_LITERAL_CSTRING(URINC_KEYINDEX), &kNC_KeyIndex);
}
mInner = do_CreateInstance("@mozilla.org/rdf/datasource;1?name=in-memory-datasource", &rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIRDFContainerUtils> rdfc =
do_GetService("@mozilla.org/rdf/container-utils;1", &rv);
if (NS_FAILED(rv)) return rv;
rv = rdfc->MakeSeq(this, kNC_WindowRoot, getter_AddRefs(mContainer));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIWindowMediator> windowMediator =
do_GetService(NS_WINDOWMEDIATOR_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv;
rv = windowMediator->AddListener(this);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIObserverService> observerService =
do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv)) {
rv = observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID,
false);
}
return NS_OK;
}
nsWindowDataSource::~nsWindowDataSource()
{
if (--gRefCnt == 0) {
NS_IF_RELEASE(kNC_Name);
NS_IF_RELEASE(kNC_KeyIndex);
NS_IF_RELEASE(kNC_WindowRoot);
NS_IF_RELEASE(gRDFService);
}
}
NS_IMETHODIMP
nsWindowDataSource::Observe(nsISupports *aSubject, const char* aTopic, const char16_t *aData)
{
if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
// release these objects so that they release their reference
// to us
mContainer = nullptr;
mInner = nullptr;
}
return NS_OK;
}
NS_IMPL_CYCLE_COLLECTION_CLASS(nsWindowDataSource)
NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsWindowDataSource)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsWindowDataSource)
// XXX mContainer?
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mInner)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsWindowDataSource)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsWindowDataSource)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsWindowDataSource)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_ENTRY(nsIWindowMediatorListener)
NS_INTERFACE_MAP_ENTRY(nsIWindowDataSource)
NS_INTERFACE_MAP_ENTRY(nsIRDFDataSource)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
NS_INTERFACE_MAP_END
// nsIWindowMediatorListener implementation
// handle notifications from the window mediator and reflect them into
// RDF
NS_IMETHODIMP
nsWindowDataSource::OnWindowTitleChange(nsIXULWindow *window,
const char16_t *newTitle)
{
nsresult rv;
nsCOMPtr<nsIRDFResource> windowResource;
mWindowResources.Get(window, getter_AddRefs(windowResource));
// oops, make sure this window is in the hashtable!
if (!windowResource) {
OnOpenWindow(window);
mWindowResources.Get(window, getter_AddRefs(windowResource));
}
NS_ENSURE_TRUE(windowResource, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsIRDFLiteral> newTitleLiteral;
rv = gRDFService->GetLiteral(newTitle, getter_AddRefs(newTitleLiteral));
NS_ENSURE_SUCCESS(rv, rv);
// get the old title
nsCOMPtr<nsIRDFNode> oldTitleNode;
rv = GetTarget(windowResource, kNC_Name, true,
getter_AddRefs(oldTitleNode));
// assert the change
if (NS_SUCCEEDED(rv) && oldTitleNode)
// has an existing window title, update it
rv = Change(windowResource, kNC_Name, oldTitleNode, newTitleLiteral);
else
// removed from the tasklist
rv = Assert(windowResource, kNC_Name, newTitleLiteral, true);
if (rv != NS_RDF_ASSERTION_ACCEPTED)
{
NS_ERROR("unable to set window name");
}
return NS_OK;
}
NS_IMETHODIMP
nsWindowDataSource::OnOpenWindow(nsIXULWindow *window)
{
nsAutoCString windowId(NS_LITERAL_CSTRING("window-"));
windowId.AppendInt(windowCount++, 10);
nsCOMPtr<nsIRDFResource> windowResource;
gRDFService->GetResource(windowId, getter_AddRefs(windowResource));
mWindowResources.Put(window, windowResource);
// assert the new window
if (mContainer)
mContainer->AppendElement(windowResource);
return NS_OK;
}
NS_IMETHODIMP
nsWindowDataSource::OnCloseWindow(nsIXULWindow *window)
{
nsresult rv;
nsCOMPtr<nsIRDFResource> resource;
mWindowResources.Get(window, getter_AddRefs(resource));
if (!resource) {
return NS_ERROR_UNEXPECTED;
}
mWindowResources.Remove(window);
// make sure we're not shutting down
if (!mContainer) return NS_OK;
nsCOMPtr<nsIRDFNode> oldKeyNode;
nsCOMPtr<nsIRDFInt> oldKeyInt;
// get the old keyIndex, if any
rv = GetTarget(resource, kNC_KeyIndex, true,
getter_AddRefs(oldKeyNode));
if (NS_SUCCEEDED(rv) && (rv != NS_RDF_NO_VALUE))
oldKeyInt = do_QueryInterface(oldKeyNode);
// update RDF and keyindex - from this point forward we'll ignore
// errors, because they just indicate some kind of RDF inconsistency
int32_t winIndex = -1;
rv = mContainer->IndexOf(resource, &winIndex);
if (NS_FAILED(rv))
return NS_OK;
// unassert the old window, ignore any error
mContainer->RemoveElement(resource, true);
nsCOMPtr<nsISimpleEnumerator> children;
rv = mContainer->GetElements(getter_AddRefs(children));
if (NS_FAILED(rv))
return NS_OK;
bool more = false;
while (NS_SUCCEEDED(rv = children->HasMoreElements(&more)) && more) {
nsCOMPtr<nsISupports> sup;
rv = children->GetNext(getter_AddRefs(sup));
if (NS_FAILED(rv))
break;
nsCOMPtr<nsIRDFResource> windowResource = do_QueryInterface(sup, &rv);
if (NS_FAILED(rv))
continue;
int32_t currentIndex = -1;
mContainer->IndexOf(windowResource, &currentIndex);
// can skip updating windows with lower indexes
// than the window that was removed
if (currentIndex < winIndex)
continue;
nsCOMPtr<nsIRDFNode> newKeyNode;
nsCOMPtr<nsIRDFInt> newKeyInt;
rv = GetTarget(windowResource, kNC_KeyIndex, true,
getter_AddRefs(newKeyNode));
if (NS_SUCCEEDED(rv) && (rv != NS_RDF_NO_VALUE))
newKeyInt = do_QueryInterface(newKeyNode);
// changing from one key index to another
if (oldKeyInt && newKeyInt)
Change(windowResource, kNC_KeyIndex, oldKeyInt, newKeyInt);
// creating a new keyindex - probably window going
// from (none) to "9"
else if (newKeyInt)
Assert(windowResource, kNC_KeyIndex, newKeyInt, true);
// somehow inserting a window above this one,
// "9" to (none)
else if (oldKeyInt)
Unassert(windowResource, kNC_KeyIndex, oldKeyInt);
}
return NS_OK;
}
// nsIWindowDataSource implementation
NS_IMETHODIMP
nsWindowDataSource::GetWindowForResource(const char *aResourceString,
nsIDOMWindow** aResult)
{
if (NS_WARN_IF(!aResourceString)) {
return NS_ERROR_INVALID_ARG;
}
nsCOMPtr<nsIRDFResource> windowResource;
gRDFService->GetResource(nsDependentCString(aResourceString),
getter_AddRefs(windowResource));
// now reverse-lookup in the hashtable
for (auto iter = mWindowResources.Iter(); !iter.Done(); iter.Next()) {
nsIXULWindow* window = iter.Key();
nsIRDFResource* resource = iter.UserData();
if (resource == windowResource) {
// This sucks, we have to jump through docshell to go from
// nsIXULWindow -> nsIDOMWindow.
nsCOMPtr<nsIDocShell> docShell;
window->GetDocShell(getter_AddRefs(docShell));
if (docShell) {
nsCOMPtr<nsIDOMWindow> result = do_GetInterface(docShell);
*aResult = result;
NS_IF_ADDREF(*aResult);
}
break;
}
}
return NS_OK;
}
// nsIRDFDataSource implementation
// mostly, we just forward to mInner, except:
// GetURI() - need to return "rdf:window-mediator"
// GetTarget() - need to handle kNC_KeyIndex
NS_IMETHODIMP nsWindowDataSource::GetURI(char * *aURI)
{
NS_ENSURE_ARG_POINTER(aURI);
*aURI = ToNewCString(NS_LITERAL_CSTRING("rdf:window-mediator"));
if (!*aURI)
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
NS_IMETHODIMP nsWindowDataSource::GetTarget(nsIRDFResource *aSource, nsIRDFResource *aProperty, bool aTruthValue, nsIRDFNode **_retval)
{
NS_ENSURE_ARG_POINTER(_retval);
// add extra nullptr checking for top-crash bug # 146466
if (!gRDFService) return NS_RDF_NO_VALUE;
if (!mInner) return NS_RDF_NO_VALUE;
if (!mContainer) return NS_RDF_NO_VALUE;
// special case kNC_KeyIndex before we forward to mInner
if (aProperty == kNC_KeyIndex) {
int32_t theIndex = 0;
nsresult rv = mContainer->IndexOf(aSource, &theIndex);
if (NS_FAILED(rv)) return rv;
// only allow the range of 1 to 9 for single key access
if (theIndex < 1 || theIndex > 9) return(NS_RDF_NO_VALUE);
nsCOMPtr<nsIRDFInt> indexInt;
rv = gRDFService->GetIntLiteral(theIndex, getter_AddRefs(indexInt));
if (NS_FAILED(rv)) return(rv);
if (!indexInt) return(NS_ERROR_FAILURE);
indexInt.forget(_retval);
return NS_OK;
}
return mInner->GetTarget(aSource, aProperty, aTruthValue, _retval);
}
NS_IMETHODIMP nsWindowDataSource::GetSource(nsIRDFResource *aProperty, nsIRDFNode *aTarget, bool aTruthValue, nsIRDFResource **_retval)
{
if (mInner)
return mInner->GetSource(aProperty, aTarget, aTruthValue, _retval);
return NS_OK;
}
NS_IMETHODIMP nsWindowDataSource::GetSources(nsIRDFResource *aProperty, nsIRDFNode *aTarget, bool aTruthValue, nsISimpleEnumerator **_retval)
{
if (mInner)
return mInner->GetSources(aProperty, aTarget, aTruthValue, _retval);
return NS_OK;
}
NS_IMETHODIMP nsWindowDataSource::GetTargets(nsIRDFResource *aSource, nsIRDFResource *aProperty, bool aTruthValue, nsISimpleEnumerator **_retval)
{
if (mInner)
return mInner->GetTargets(aSource, aProperty, aTruthValue, _retval);
return NS_OK;
}
NS_IMETHODIMP nsWindowDataSource::Assert(nsIRDFResource *aSource, nsIRDFResource *aProperty, nsIRDFNode *aTarget, bool aTruthValue)
{
if (mInner)
return mInner->Assert(aSource, aProperty, aTarget, aTruthValue);
return NS_OK;
}
NS_IMETHODIMP nsWindowDataSource::Unassert(nsIRDFResource *aSource, nsIRDFResource *aProperty, nsIRDFNode *aTarget)
{
if (mInner)
return mInner->Unassert(aSource, aProperty, aTarget);
return NS_OK;
}
NS_IMETHODIMP nsWindowDataSource::Change(nsIRDFResource *aSource, nsIRDFResource *aProperty, nsIRDFNode *aOldTarget, nsIRDFNode *aNewTarget)
{
if (mInner)
return mInner->Change(aSource, aProperty, aOldTarget, aNewTarget);
return NS_OK;
}
NS_IMETHODIMP nsWindowDataSource::Move(nsIRDFResource *aOldSource, nsIRDFResource *aNewSource, nsIRDFResource *aProperty, nsIRDFNode *aTarget)
{
if (mInner)
return mInner->Move(aOldSource, aNewSource, aProperty, aTarget);
return NS_OK;
}
NS_IMETHODIMP nsWindowDataSource::HasAssertion(nsIRDFResource *aSource, nsIRDFResource *aProperty, nsIRDFNode *aTarget, bool aTruthValue, bool *_retval)
{
if (mInner)
return mInner->HasAssertion(aSource, aProperty, aTarget, aTruthValue, _retval);
return NS_OK;
}
NS_IMETHODIMP nsWindowDataSource::AddObserver(nsIRDFObserver *aObserver)
{
if (mInner)
return mInner->AddObserver(aObserver);
return NS_OK;
}
NS_IMETHODIMP nsWindowDataSource::RemoveObserver(nsIRDFObserver *aObserver)
{
if (mInner)
return mInner->RemoveObserver(aObserver);
return NS_OK;
}
NS_IMETHODIMP nsWindowDataSource::ArcLabelsIn(nsIRDFNode *aNode, nsISimpleEnumerator **_retval)
{
if (mInner)
return mInner->ArcLabelsIn(aNode, _retval);
return NS_OK;
}
NS_IMETHODIMP nsWindowDataSource::ArcLabelsOut(nsIRDFResource *aSource, nsISimpleEnumerator **_retval)
{
if (mInner)
return mInner->ArcLabelsOut(aSource, _retval);
return NS_OK;
}
NS_IMETHODIMP nsWindowDataSource::GetAllResources(nsISimpleEnumerator **_retval)
{
if (mInner)
return mInner->GetAllResources(_retval);
return NS_OK;
}
NS_IMETHODIMP nsWindowDataSource::IsCommandEnabled(nsISupports *aSources, nsIRDFResource *aCommand, nsISupports *aArguments, bool *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsWindowDataSource::DoCommand(nsISupports *aSources, nsIRDFResource *aCommand, nsISupports *aArguments)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsWindowDataSource::GetAllCmds(nsIRDFResource *aSource, nsISimpleEnumerator **_retval)
{
if (mInner)
return mInner->GetAllCmds(aSource, _retval);
return NS_OK;
}
NS_IMETHODIMP nsWindowDataSource::HasArcIn(nsIRDFNode *aNode, nsIRDFResource *aArc, bool *_retval)
{
if (mInner)
return mInner->HasArcIn(aNode, aArc, _retval);
return NS_OK;
}
NS_IMETHODIMP nsWindowDataSource::HasArcOut(nsIRDFResource *aSource, nsIRDFResource *aArc, bool *_retval)
{
if (mInner)
return mInner->HasArcOut(aSource, aArc, _retval);
return NS_OK;
}
NS_IMETHODIMP nsWindowDataSource::BeginUpdateBatch()
{
if (mInner)
return mInner->BeginUpdateBatch();
return NS_OK;
}
NS_IMETHODIMP nsWindowDataSource::EndUpdateBatch()
{
if (mInner)
return mInner->EndUpdateBatch();
return NS_OK;
}
// The module goop
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsWindowDataSource, Init)
NS_DEFINE_NAMED_CID(NS_WINDOWDATASOURCE_CID);
static const mozilla::Module::CIDEntry kWindowDSCIDs[] = {
{ &kNS_WINDOWDATASOURCE_CID, false, nullptr, nsWindowDataSourceConstructor },
{ nullptr }
};
static const mozilla::Module::ContractIDEntry kWindowDSContracts[] = {
{ NS_RDF_DATASOURCE_CONTRACTID_PREFIX "window-mediator", &kNS_WINDOWDATASOURCE_CID },
{ nullptr }
};
static const mozilla::Module::CategoryEntry kWindowDSCategories[] = {
{ "app-startup", "Window Data Source", "service," NS_RDF_DATASOURCE_CONTRACTID_PREFIX "window-mediator" },
{ nullptr }
};
static const mozilla::Module kWindowDSModule = {
mozilla::Module::kVersion,
kWindowDSCIDs,
kWindowDSContracts,
kWindowDSCategories
};
NSMODULE_DEFN(nsWindowDataSourceModule) = &kWindowDSModule;

View file

@ -0,0 +1,59 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 "nsIRDFDataSource.h"
#include "nsIWindowMediatorListener.h"
#include "nsIWindowDataSource.h"
#include "nsIObserver.h"
#include "nsHashKeys.h"
#include "nsIRDFService.h"
#include "nsIRDFContainer.h"
#include "nsInterfaceHashtable.h"
#include "nsCycleCollectionParticipant.h"
// {C744CA3D-840B-460a-8D70-7CE63C51C958}
#define NS_WINDOWDATASOURCE_CID \
{ 0xc744ca3d, 0x840b, 0x460a, \
{ 0x8d, 0x70, 0x7c, 0xe6, 0x3c, 0x51, 0xc9, 0x58 } }
class nsWindowDataSource final : public nsIRDFDataSource,
public nsIObserver,
public nsIWindowMediatorListener,
public nsIWindowDataSource
{
public:
nsWindowDataSource() { }
nsresult Init();
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsWindowDataSource,
nsIRDFDataSource)
NS_DECL_NSIOBSERVER
NS_DECL_NSIWINDOWMEDIATORLISTENER
NS_DECL_NSIWINDOWDATASOURCE
NS_DECL_NSIRDFDATASOURCE
protected:
virtual ~nsWindowDataSource();
private:
// mapping of window -> RDF resource
nsInterfaceHashtable<nsPtrHashKey<nsIXULWindow>, nsIRDFResource> mWindowResources;
static uint32_t windowCount;
static uint32_t gRefCnt;
nsCOMPtr<nsIRDFDataSource> mInner;
nsCOMPtr<nsIRDFContainer> mContainer;
static nsIRDFResource* kNC_Name;
static nsIRDFResource* kNC_KeyIndex;
static nsIRDFResource* kNC_WindowRoot;
static nsIRDFService* gRDFService;
};

View file

@ -0,0 +1,5 @@
<html><body onload="
var gLoadEventTime = (new Date()).getTime();
if (window.opener)
window.setTimeout('window.opener.childIsOpen('+gLoadEventTime+');',1000);
"></body></html>

244
xpfe/test/winopen.js Normal file
View file

@ -0,0 +1,244 @@
// target for window.open()
const KID_URL = "child-window.html";
// formats final results
const SERVER_URL = "http://jrgm.mcom.com/cgi-bin/window-open-2.0/openreport.pl";
// let system settle between each window.open
const OPENER_DELAY = 1000;
// three phases: single open/close; overlapped open/close; open-all/close-all
var PHASE_ONE = 10;
var PHASE_TWO = 0;
var PHASE_THREE = 0;
// keep this many windows concurrently open during overlapped phase
var OVERLAP_COUNT = 3;
// repeat three phases CYCLES times
var CYCLES = 1;
// autoclose flag
var AUTOCLOSE = 1;
// Chrome url for child windows.
var KID_CHROME = null;
var SAVED_CHROME = null;
// URL options and correspnding vars.
const options = [ [ "phase1", "PHASE_ONE", false ],
[ "phase2", "PHASE_TWO", false ],
[ "phase3", "PHASE_THREE", false ],
[ "overlap", "OVERLAP_COUNT", false ],
[ "cycles", "CYCLES", false ],
[ "chrome", "KID_CHROME", true ],
[ "close", "AUTOCLOSE", false ] ];
// Note: You can attach search options to the url for this file to control
// any of the options in the array above. E.g., specifying
// mozilla --chrome "file:///D|/mozilla/xpfe/test/winopen.xul?phase1=16&close=0"
// will run this script with PHASE_ONE=16 and AUTOCLOSE=0.
//
// On Win32, you must enclose the --chrome option in quotes in order pass funny Win32 shell
// characters such as '&' or '|'!
var opts = window.location.search.substring(1).split( '&' );
for ( opt in opts ) {
for ( var i in options ) {
if ( opts[opt].indexOf( options[i][0]+"=" ) == 0 ) {
var newVal = opts[opt].split( '=' )[ 1 ];
// wrap with quotes, if required.
if ( options[i][2] ) {
newVal = '"' + newVal + '"';
}
eval( options[i][1] + "=" + newVal + ";" );
}
}
}
var prefs = null;
if ( KID_CHROME ) {
// Reset browser.chromeURL so it points to KID_CHROME.
// This will cause window.open in openWindow to open that chrome.
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
prefs = Components.classes["@mozilla.org/preferences-service;1"]
.getService( Components.interfaces.nsIPrefBranch );
SAVED_CHROME = prefs.getCharPref( "browser.chromeURL" );
prefs.setCharPref( "browser.chromeURL", KID_CHROME );
}
const CYCLE_SIZE = PHASE_ONE + PHASE_TWO + PHASE_THREE;
const MAX_INDEX = CYCLE_SIZE * CYCLES; // total number of windows to open
var windowList = []; // handles to opened windows
var startingTimes = []; // time that window.open is called
var openingTimes = []; // time that child window took to fire onload
var closingTimes = []; // collect stats for case of closing >1 windows
var currentIndex = 0;
function childIsOpen(aTime) {
openingTimes[currentIndex] = aTime - startingTimes[currentIndex];
updateDisplay(currentIndex, openingTimes[currentIndex]);
reapWindows(currentIndex);
currentIndex++;
if (currentIndex < MAX_INDEX)
scheduleNextWindow();
else
window.setTimeout(reportResults, OPENER_DELAY);
}
function updateDisplay(index, time) {
var formIndex = document.getElementById("formIndex");
if (formIndex)
formIndex.setAttribute("value", index+1);
var formTime = document.getElementById("formTime");
if (formTime)
formTime.setAttribute("value", time);
}
function scheduleNextWindow() {
window.setTimeout(openWindow, OPENER_DELAY);
}
function closeOneWindow(aIndex) {
var win = windowList[aIndex];
// no-op if window is already closed
if (win && !win.closed) {
win.close();
windowList[aIndex] = null;
}
}
function closeAllWindows(aRecordTimeToClose) {
var timeToClose = (new Date()).getTime();
var count = 0;
for (var i = 0; i < windowList.length; i++) {
if (windowList[i])
count++;
closeOneWindow(i);
}
if (aRecordTimeToClose && count > 0) {
timeToClose = (new Date()).getTime() - timeToClose;
closingTimes.push(parseInt(timeToClose/count));
}
}
// close some, none, or all open windows in the list
function reapWindows() {
var modIndex = currentIndex % CYCLE_SIZE;
if (modIndex < PHASE_ONE-1) {
// first phase in each "cycle", are single open/close sequences
closeOneWindow(currentIndex);
}
else if (PHASE_ONE-1 <= modIndex && modIndex < PHASE_ONE+PHASE_TWO-1) {
// next phase in each "cycle", keep N windows concurrently open
closeOneWindow(currentIndex - OVERLAP_COUNT);
}
else if (modIndex == PHASE_ONE+PHASE_TWO-1) {
// end overlapping windows cycle; close all windows
closeAllWindows(false);
}
else if (PHASE_ONE+PHASE_TWO <= modIndex && modIndex < CYCLE_SIZE-1) {
// do nothing; keep adding windows
}
else if (modIndex == CYCLE_SIZE-1) {
// end open-all/close-all phase; close windows, recording time to close
closeAllWindows(true);
}
}
function calcMedian( numbers ) {
if ( numbers.length == 0 ) {
return 0;
} else if ( numbers.length == 1 ) {
return numbers[0];
} else if ( numbers.length == 2 ) {
return ( numbers[0] + numbers[1] ) / 2;
} else {
numbers.sort( function (a,b){ return a-b; } );
var n = Math.floor( numbers.length / 2 );
return numbers.length % 2 ? numbers[n] : ( numbers[n-1] + numbers[n] ) / 2;
}
}
function reportResults() {
//XXX need to create a client-side method to do this?
var opening = openingTimes.join(':'); // times for each window open
var closing = closingTimes.join(':'); // these are for >1 url, as a group
//var ua = escape(navigator.userAgent).replace(/\+/g, "%2B"); // + == ' ', on servers
//var reportURL = SERVER_URL +
// "?opening=" + opening +
// "&closing=" + closing +
// "&maxIndex=" + MAX_INDEX +
// "&cycleSize=" + CYCLE_SIZE +
//"&ua=" + ua;
//window.open(reportURL, "test-results");
var avgOpenTime = 0;
var minOpenTime = 99999;
var maxOpenTime = 0;
var medOpenTime = calcMedian( openingTimes.slice(1) );
// ignore first open
for (i = 1; i < MAX_INDEX; i++) {
avgOpenTime += openingTimes[i];
if ( minOpenTime > openingTimes[i] ) {
minOpenTime = openingTimes[i];
}
if ( maxOpenTime < openingTimes[i] ) {
maxOpenTime = openingTimes[i];
}
}
avgOpenTime = Math.round(avgOpenTime / (MAX_INDEX - 1));
dump("openingTimes="+openingTimes.slice(1)+"\n");
dump("avgOpenTime:" + avgOpenTime + "\n" );
dump("minOpenTime:" + minOpenTime + "\n" );
dump("maxOpenTime:" + maxOpenTime + "\n" );
dump("medOpenTime:" + medOpenTime + "\n" );
dump("__xulWinOpenTime:" + medOpenTime + "\n");
// Close the root window, if required.
if ( AUTOCLOSE ) {
window.close();
} else {
document.getElementById("formTimes").value = openingTimes.slice(1);
document.getElementById("formAvg").value = avgOpenTime;
document.getElementById("formMin").value = minOpenTime;
document.getElementById("formMax").value = maxOpenTime;
document.getElementById("formMed").value = medOpenTime;
document.getElementById("formAgain").setAttribute( "disabled", "false" );
}
}
function tryAgain() {
document.getElementById("formAgain").setAttribute( "disabled", "true" );
windowList = [];
startingTimes = [];
openingTimes = [];
closingTimes = [];
currentIndex = 0;
openWindow();
}
function restoreChromeURL() {
// Restore browser.chromeURL pref.
if ( KID_CHROME && SAVED_CHROME.length ) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
prefs.setCharPref( "browser.chromeURL", SAVED_CHROME );
}
}
function openWindow() {
startingTimes[currentIndex] = (new Date()).getTime();
var path = window.location.pathname.substring( 0, window.location.pathname.lastIndexOf('/') );
var url = window.location.protocol + "//" +
window.location.hostname + path + "/" +
KID_URL;
windowList[currentIndex] = window.open(url, currentIndex);
}

75
xpfe/test/winopen.xul Normal file
View file

@ -0,0 +1,75 @@
<?xml version="1.0"?> <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<window
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
orient="vertical"
height="300"
width="400"
windowtype="opener:test"
onunload="restoreChromeURL();"
onload="scheduleNextWindow();">
<script src="winopen.js" type="application/x-javascript"></script>
<groupbox orient="vertical">
<caption label="Window Opening Test"/>
<html>
This will open a series of browser windows, either "one at a
time" or in a sequence of some form. When this test is complete
a final window will be opened which will report the overall results.
</html>
<separator class="thick"/>
<grid>
<columns><column/><column/></columns>
<rows>
<row align="center">
<text value="Index:"/>
<textbox id="formIndex" size="6" value=""/>
</row>
<row align="center">
<text value="Time:"/>
<textbox id="formTime" size="6" value=""/>
<text value="msec"/>
</row>
</rows>
</grid>
<separator class="thick"/>
</groupbox>
<groupbox orient="vertical">
<caption label="Results"/>
<grid>
<columns>
<column/>
<column/>
</columns>
<rows>
<row align="center">
<text value="Times (ignoring the first):"/>
<textbox id="formTimes" size="45" value=""/>
</row>
<row align="center">
<text value="Txul (median):"/>
<hbox>
<textbox id="formMed" size="6" value=""/>
<spring/>
<button id="formAgain" onclick="tryAgain();" label="Try again" disabled="true"/>
</hbox>
</row>
<row align="center">
<text value="Avg:"/>
<hbox><textbox id="formAvg" size="6" value=""/></hbox>
</row>
<row align="center">
<text value="Min:"/>
<hbox><textbox id="formMin" size="6" value=""/></hbox>
</row>
<row align="center">
<text value="Max:"/>
<hbox><textbox id="formMax" size="6" value=""/></hbox>
</row>
</rows>
</grid>
</groupbox>
</window>