зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1480206 - Move XULDocument popup attributes to Document. r=bz
Allows top level non-XUL documents to share this code. Three tests had to be adjusted to account for the attributes being chrome only now and not available to content privilege XUL. In two tests, the values attributes are now simply undefined. The crashtest was converted to a chrome mochitest to preserve what it was testing. MozReview-Commit-ID: 99w9Ax4et3C --HG-- rename : dom/base/crashtests/473284.xul => dom/base/test/chrome/test_bug473284.xul extra : rebase_source : 924d34a88fe8a48d766f78b02e64275f6e7cdc2b
This commit is contained in:
Родитель
20a322176f
Коммит
da472b2bfe
|
@ -74,7 +74,6 @@ skip load 458637-1.html # sporadically times out (bug 473680)
|
|||
load 462947.html
|
||||
load 467392.html
|
||||
load 472593-1.html
|
||||
load 473284.xul
|
||||
load 474041-1.svg
|
||||
load 476526.html
|
||||
load 483818-1.html
|
||||
|
|
|
@ -259,6 +259,7 @@
|
|||
#include "mozilla/dom/MenuBoxObject.h"
|
||||
#include "mozilla/dom/TreeBoxObject.h"
|
||||
#include "nsIXULWindow.h"
|
||||
#include "nsXULPopupManager.h"
|
||||
#include "nsIDocShellTreeOwner.h"
|
||||
#endif
|
||||
#include "nsIPresShellInlines.h"
|
||||
|
@ -10174,6 +10175,112 @@ nsIDocument::MaybeResolveReadyForIdle()
|
|||
}
|
||||
}
|
||||
|
||||
static JSObject*
|
||||
GetScopeObjectOfNode(nsINode* node)
|
||||
{
|
||||
MOZ_ASSERT(node, "Must not be called with null.");
|
||||
|
||||
// Window root occasionally keeps alive a node of a document whose
|
||||
// window is already dead. If in this brief period someone calls
|
||||
// GetPopupNode and we return that node, we can end up creating a
|
||||
// reflector for the node in the wrong global (the current global,
|
||||
// not the document global, because we won't know what the document
|
||||
// global is). Returning an orphan node like that to JS would be a
|
||||
// bug anyway, so to avoid this, let's do the same check as fetching
|
||||
// GetParentObjet() on the document does to determine the scope and
|
||||
// if it returns null let's just return null in XULDocument::GetPopupNode.
|
||||
nsIDocument* doc = node->OwnerDoc();
|
||||
MOZ_ASSERT(doc, "This should never happen.");
|
||||
|
||||
nsIGlobalObject* global = doc->GetScopeObject();
|
||||
return global ? global->GetGlobalJSObject() : nullptr;
|
||||
}
|
||||
|
||||
|
||||
already_AddRefed<nsPIWindowRoot>
|
||||
nsIDocument::GetWindowRoot()
|
||||
{
|
||||
if (!mDocumentContainer) {
|
||||
return nullptr;
|
||||
}
|
||||
// XXX It's unclear why this can't just use GetWindow().
|
||||
nsCOMPtr<nsPIDOMWindowOuter> piWin = mDocumentContainer->GetWindow();
|
||||
return piWin ? piWin->GetTopWindowRoot() : nullptr;
|
||||
}
|
||||
|
||||
already_AddRefed<nsINode>
|
||||
nsIDocument::GetPopupNode()
|
||||
{
|
||||
nsCOMPtr<nsINode> node;
|
||||
nsCOMPtr<nsPIWindowRoot> rootWin = GetWindowRoot();
|
||||
if (rootWin) {
|
||||
node = rootWin->GetPopupNode(); // addref happens here
|
||||
}
|
||||
|
||||
if (!node) {
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
if (pm) {
|
||||
node = pm->GetLastTriggerPopupNode(this);
|
||||
}
|
||||
}
|
||||
|
||||
if (node && GetScopeObjectOfNode(node)) {
|
||||
return node.forget();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
nsIDocument::SetPopupNode(nsINode* aNode)
|
||||
{
|
||||
nsCOMPtr<nsPIWindowRoot> rootWin = GetWindowRoot();
|
||||
if (rootWin) {
|
||||
rootWin->SetPopupNode(aNode);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the rangeOffset element from the XUL Popup Manager. This is for
|
||||
// chrome callers only.
|
||||
nsINode*
|
||||
nsIDocument::GetPopupRangeParent(ErrorResult& aRv)
|
||||
{
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
if (!pm) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return pm->GetMouseLocationParent();
|
||||
}
|
||||
|
||||
// Returns the rangeOffset element from the XUL Popup Manager.
|
||||
int32_t
|
||||
nsIDocument::GetPopupRangeOffset(ErrorResult& aRv)
|
||||
{
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
if (!pm) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pm->MouseLocationOffset();
|
||||
}
|
||||
|
||||
already_AddRefed<nsINode>
|
||||
nsIDocument::GetTooltipNode()
|
||||
{
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
if (pm) {
|
||||
nsCOMPtr<nsINode> node = pm->GetLastTriggerTooltipNode(this);
|
||||
if (node) {
|
||||
return node.forget();
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsIHTMLCollection*
|
||||
nsIDocument::Children()
|
||||
{
|
||||
|
|
|
@ -1383,6 +1383,11 @@ protected:
|
|||
*/
|
||||
void ClearStaleServoData();
|
||||
|
||||
/**
|
||||
* Returns the top window root from the outer window.
|
||||
*/
|
||||
already_AddRefed<nsPIWindowRoot> GetWindowRoot();
|
||||
|
||||
private:
|
||||
class SelectorCacheKey
|
||||
{
|
||||
|
@ -3336,6 +3341,13 @@ public:
|
|||
|
||||
mozilla::dom::Promise* GetDocumentReadyForIdle(mozilla::ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<nsINode> GetPopupNode();
|
||||
void SetPopupNode(nsINode* aNode);
|
||||
nsINode* GetPopupRangeParent(ErrorResult& aRv);
|
||||
int32_t GetPopupRangeOffset(ErrorResult& aRv);
|
||||
already_AddRefed<nsINode> GetTooltipNode();
|
||||
void SetTooltipNode(nsINode* aNode) { /* do nothing */ }
|
||||
|
||||
// ParentNode
|
||||
nsIHTMLCollection* Children();
|
||||
uint32_t ChildElementCount();
|
||||
|
|
|
@ -39,6 +39,7 @@ support-files = ../file_bug357450.js
|
|||
[test_bug429785.xul]
|
||||
[test_bug430050.xul]
|
||||
[test_bug467123.xul]
|
||||
[test_bug473284.xul]
|
||||
[test_bug549682.xul]
|
||||
skip-if = verify
|
||||
[test_bug571390.xul]
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
<?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=473284
|
||||
-->
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
class="reftest-wait"
|
||||
onload="
|
||||
var result = '';
|
||||
try {
|
||||
|
@ -86,8 +92,14 @@ try {
|
|||
result += '.';
|
||||
}
|
||||
|
||||
document.documentElement.textContent = result == '.23.56.89.bc' ? 'PASSED' : 'FAILED';
|
||||
if (document.documentElement.textContent == 'PASSED') {
|
||||
document.documentElement.removeAttribute('class');
|
||||
}
|
||||
"/>
|
||||
is(result, '.23.56.89.bc', 'The correct assignments throw.');
|
||||
">
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<!-- test results are displayed in the html:body -->
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=473284"
|
||||
target="_blank">Mozilla Bug 473284</a>
|
||||
</body>
|
||||
</window>
|
|
@ -406,6 +406,21 @@ partial interface Document {
|
|||
// "document_idle" webextension script injection point.
|
||||
[ChromeOnly, Throws]
|
||||
readonly attribute Promise<Document> documentReadyForIdle;
|
||||
|
||||
[ChromeOnly]
|
||||
attribute Node? popupNode;
|
||||
|
||||
/**
|
||||
* These attributes correspond to rangeParent and rangeOffset. They will help
|
||||
* you find where in the DOM the popup is happening. Can be accessed only
|
||||
* during a popup event. Accessing any other time will be an error.
|
||||
*/
|
||||
[Throws, ChromeOnly]
|
||||
readonly attribute Node? popupRangeParent;
|
||||
[Throws, ChromeOnly]
|
||||
readonly attribute long popupRangeOffset;
|
||||
[ChromeOnly]
|
||||
attribute Node? tooltipNode;
|
||||
};
|
||||
|
||||
dictionary BlockParsingOptions {
|
||||
|
|
|
@ -9,20 +9,6 @@ interface MozObserver;
|
|||
|
||||
[Func="IsChromeOrXBL"]
|
||||
interface XULDocument : Document {
|
||||
attribute Node? popupNode;
|
||||
|
||||
/**
|
||||
* These attributes correspond to trustedGetPopupNode().rangeOffset and
|
||||
* rangeParent. They will help you find where in the DOM the popup is
|
||||
* happening. Can be accessed only during a popup event. Accessing any other
|
||||
* time will be an error.
|
||||
*/
|
||||
[Throws, ChromeOnly]
|
||||
readonly attribute Node? popupRangeParent;
|
||||
[Throws, ChromeOnly]
|
||||
readonly attribute long popupRangeOffset;
|
||||
|
||||
attribute Node? tooltipNode;
|
||||
|
||||
readonly attribute XULCommandDispatcher? commandDispatcher;
|
||||
|
||||
|
|
|
@ -1003,113 +1003,6 @@ XULDocument::Persist(Element* aElement, int32_t aNameSpaceID,
|
|||
mLocalStore->SetValue(uri, id, attrstr, valuestr);
|
||||
}
|
||||
|
||||
static JSObject*
|
||||
GetScopeObjectOfNode(nsINode* node)
|
||||
{
|
||||
MOZ_ASSERT(node, "Must not be called with null.");
|
||||
|
||||
// Window root occasionally keeps alive a node of a document whose
|
||||
// window is already dead. If in this brief period someone calls
|
||||
// GetPopupNode and we return that node, nsNodeSH::PreCreate will throw,
|
||||
// because it will not know which scope this node belongs to. Returning
|
||||
// an orphan node like that to JS would be a bug anyway, so to avoid
|
||||
// this, let's do the same check as nsNodeSH::PreCreate does to
|
||||
// determine the scope and if it fails let's just return null in
|
||||
// XULDocument::GetPopupNode.
|
||||
nsIDocument* doc = node->OwnerDoc();
|
||||
MOZ_ASSERT(doc, "This should never happen.");
|
||||
|
||||
nsIGlobalObject* global = doc->GetScopeObject();
|
||||
return global ? global->GetGlobalJSObject() : nullptr;
|
||||
}
|
||||
|
||||
already_AddRefed<nsINode>
|
||||
XULDocument::GetPopupNode()
|
||||
{
|
||||
nsCOMPtr<nsINode> node;
|
||||
nsCOMPtr<nsPIWindowRoot> rootWin = GetWindowRoot();
|
||||
if (rootWin) {
|
||||
node = rootWin->GetPopupNode(); // addref happens here
|
||||
}
|
||||
|
||||
if (!node) {
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
if (pm) {
|
||||
node = pm->GetLastTriggerPopupNode(this);
|
||||
}
|
||||
}
|
||||
|
||||
if (node && nsContentUtils::CanCallerAccess(node)
|
||||
&& GetScopeObjectOfNode(node)) {
|
||||
return node.forget();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
XULDocument::SetPopupNode(nsINode* aNode)
|
||||
{
|
||||
nsCOMPtr<nsPIWindowRoot> rootWin = GetWindowRoot();
|
||||
if (rootWin) {
|
||||
rootWin->SetPopupNode(aNode);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the rangeOffset element from the XUL Popup Manager. This is for
|
||||
// chrome callers only.
|
||||
nsINode*
|
||||
XULDocument::GetPopupRangeParent(ErrorResult& aRv)
|
||||
{
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
if (!pm) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsINode* rangeParent = pm->GetMouseLocationParent();
|
||||
if (rangeParent && !nsContentUtils::CanCallerAccess(rangeParent)) {
|
||||
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return rangeParent;
|
||||
}
|
||||
|
||||
// Returns the rangeOffset element from the XUL Popup Manager. We check the
|
||||
// rangeParent to determine if the caller has rights to access to the data.
|
||||
int32_t
|
||||
XULDocument::GetPopupRangeOffset(ErrorResult& aRv)
|
||||
{
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
if (!pm) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
nsINode* rangeParent = pm->GetMouseLocationParent();
|
||||
if (rangeParent && !nsContentUtils::CanCallerAccess(rangeParent)) {
|
||||
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pm->MouseLocationOffset();
|
||||
}
|
||||
|
||||
already_AddRefed<nsINode>
|
||||
XULDocument::GetTooltipNode()
|
||||
{
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
if (pm) {
|
||||
nsCOMPtr<nsINode> node = pm->GetLastTriggerTooltipNode(this);
|
||||
if (node && nsContentUtils::CanCallerAccess(node)) {
|
||||
return node.forget();
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsresult
|
||||
XULDocument::AddElementToDocumentPre(Element* aElement)
|
||||
{
|
||||
|
@ -2717,17 +2610,6 @@ XULDocument::CachedChromeStreamListener::OnDataAvailable(nsIRequest *request,
|
|||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
already_AddRefed<nsPIWindowRoot>
|
||||
XULDocument::GetWindowRoot()
|
||||
{
|
||||
if (!mDocumentContainer) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowOuter> piWin = mDocumentContainer->GetWindow();
|
||||
return piWin ? piWin->GetTopWindowRoot() : nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
XULDocument::IsDocumentRightToLeft()
|
||||
{
|
||||
|
|
|
@ -137,12 +137,6 @@ public:
|
|||
void TraceProtos(JSTracer* aTrc);
|
||||
|
||||
// WebIDL API
|
||||
already_AddRefed<nsINode> GetPopupNode();
|
||||
void SetPopupNode(nsINode* aNode);
|
||||
nsINode* GetPopupRangeParent(ErrorResult& aRv);
|
||||
int32_t GetPopupRangeOffset(ErrorResult& aRv);
|
||||
already_AddRefed<nsINode> GetTooltipNode();
|
||||
void SetTooltipNode(nsINode* aNode) { /* do nothing */ }
|
||||
nsIDOMXULCommandDispatcher* GetCommandDispatcher() const
|
||||
{
|
||||
return mCommandDispatcher;
|
||||
|
@ -190,8 +184,6 @@ protected:
|
|||
Element* aListener,
|
||||
nsAtom* aAttr);
|
||||
|
||||
already_AddRefed<nsPIWindowRoot> GetWindowRoot();
|
||||
|
||||
static void DirectionChanged(const char* aPrefName, XULDocument* aData);
|
||||
|
||||
// pseudo constants
|
||||
|
|
|
@ -453,7 +453,7 @@ var popupTests = [
|
|||
var evt = child.createEvent("Event");
|
||||
evt.initEvent("click", true, true);
|
||||
child.documentElement.dispatchEvent(evt);
|
||||
is(child.documentElement.getAttribute("data"), "xnull",
|
||||
is(child.documentElement.getAttribute("data"), "xundefined",
|
||||
"cannot get popupNode from other document");
|
||||
child.documentElement.setAttribute("data", "none");
|
||||
// now try again with document.popupNode set explicitly
|
||||
|
|
|
@ -113,7 +113,7 @@ var popupTests = [
|
|||
var evt = child.createEvent("Event");
|
||||
evt.initEvent("click", true, true);
|
||||
child.documentElement.dispatchEvent(evt);
|
||||
is(child.documentElement.getAttribute("data"), "xnull",
|
||||
is(child.documentElement.getAttribute("data"), "xundefined",
|
||||
"cannot get tooltipNode from other document");
|
||||
|
||||
var buttonrect = document.getElementById("withtooltip").getBoundingClientRect();
|
||||
|
|
Загрузка…
Ссылка в новой задаче