68.14.8 - dom

This commit is contained in:
Fedor 2025-04-19 19:12:25 +03:00
parent f9bcc75aaf
commit 4efeab7ecb
709 changed files with 4306 additions and 18728 deletions

View File

@ -44,11 +44,6 @@ const gMozillaSpecificProperties = {
from: "1",
to: "0"
},
"-moz-stack-sizing": {
// https://developer.mozilla.org/en/docs/Web/CSS/-moz-stack-sizing
from: "ignore",
to: "stretch-to-fit"
},
"-moz-text-size-adjust": {
// https://drafts.csswg.org/css-size-adjust/#propdef-text-size-adjust
from: "none",

View File

@ -41,9 +41,6 @@ const testcases = [
property: "-moz-osx-font-smoothing",
pref: "layout.css.osx-font-smoothing.enabled"
},
{
property: "-moz-stack-sizing"
},
{
property: "-moz-text-size-adjust"
},

View File

@ -28,8 +28,6 @@ mozilla::LazyLogModule gAudioChannelLog("AudioChannel");
namespace {
bool sAudioChannelCompeting = false;
bool sAudioChannelCompetingAllAgents = false;
bool sXPCOMShuttingDown = false;
class NotifyChannelActiveRunnable final : public Runnable {
@ -117,20 +115,6 @@ class AudioPlaybackRunnable final : public Runnable {
AudioChannelService::AudibleChangedReasons mReason;
};
bool IsEnableAudioCompetingForAllAgents() {
// In general, the audio competing should only be for audible media and it
// helps user can focus on one media at the same time. However, we hope to
// treat all media as the same in the mobile device. First reason is we have
// media control on fennec and we just want to control one media at once time.
// Second reason is to reduce the bandwidth, avoiding to play any non-audible
// media in background which user doesn't notice about.
#ifdef MOZ_WIDGET_ANDROID
return true;
#else
return sAudioChannelCompetingAllAgents;
#endif
}
} // anonymous namespace
namespace mozilla {
@ -250,12 +234,6 @@ void AudioChannelService::Shutdown() {
}
}
/* static */
bool AudioChannelService::IsEnableAudioCompeting() {
CreateServiceIfNeeded();
return sAudioChannelCompeting;
}
NS_INTERFACE_MAP_BEGIN(AudioChannelService)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
@ -270,11 +248,6 @@ AudioChannelService::AudioChannelService() {
obs->AddObserver(this, "xpcom-shutdown", false);
obs->AddObserver(this, "outer-window-destroyed", false);
}
Preferences::AddBoolVarCache(&sAudioChannelCompeting,
"dom.audiochannel.audioCompeting");
Preferences::AddBoolVarCache(&sAudioChannelCompetingAllAgents,
"dom.audiochannel.audioCompeting.allAgents");
}
AudioChannelService::~AudioChannelService() {}
@ -334,9 +307,6 @@ AudioPlaybackConfig AudioChannelService::GetMediaConfig(
if (winData) {
config.mVolume *= winData->mConfig.mVolume;
config.mMuted = config.mMuted || winData->mConfig.mMuted;
config.mSuspend = winData->mOwningAudioFocus
? config.mSuspend
: nsISuspendedTypes::SUSPENDED_STOP_DISPOSABLE;
config.mCapturedAudio = winData->mIsAudioCaptured;
}
@ -532,20 +502,6 @@ bool AudioChannelService::IsWindowActive(nsPIDOMWindowOuter* aWindow) {
return !winData->mAudibleAgents.IsEmpty();
}
void AudioChannelService::RefreshAgentsAudioFocusChanged(
AudioChannelAgent* aAgent) {
MOZ_ASSERT(aAgent);
nsTObserverArray<nsAutoPtr<AudioChannelWindow>>::ForwardIterator iter(
mWindows);
while (iter.HasMore()) {
AudioChannelWindow* winData = iter.GetNext();
if (winData->mOwningAudioFocus) {
winData->AudioFocusChanged(aAgent);
}
}
}
void AudioChannelService::NotifyMediaResumedFromBlock(
nsPIDOMWindowOuter* aWindow) {
MOZ_ASSERT(aWindow);
@ -563,168 +519,13 @@ void AudioChannelService::NotifyMediaResumedFromBlock(
winData->NotifyMediaBlockStop(aWindow);
}
void AudioChannelService::AudioChannelWindow::RequestAudioFocus(
AudioChannelAgent* aAgent) {
MOZ_ASSERT(aAgent);
// Don't need to check audio focus for window-less agent.
if (!aAgent->Window()) {
return;
}
// We already have the audio focus. No operation is needed.
if (mOwningAudioFocus) {
return;
}
// Only foreground window can request audio focus, but it would still own the
// audio focus even it goes to background. Audio focus would be abandoned
// only when other foreground window starts audio competing.
// One exception is if the pref "media.block-autoplay-until-in-foreground"
// is on and the background page is the non-visited before. Because the media
// in that page would be blocked until the page is going to foreground.
mOwningAudioFocus = (!(aAgent->Window()->IsBackground()) ||
aAgent->Window()->GetMediaSuspend() ==
nsISuspendedTypes::SUSPENDED_BLOCK);
MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
("AudioChannelWindow, RequestAudioFocus, this = %p, "
"agent = %p, owning audio focus = %s\n",
this, aAgent, mOwningAudioFocus ? "true" : "false"));
}
void AudioChannelService::AudioChannelWindow::NotifyAudioCompetingChanged(
AudioChannelAgent* aAgent) {
// This function may be called after RemoveAgentAndReduceAgentsNum(), so the
// agent may be not contained in mAgent. In addition, the agent would still
// be alive because we have kungFuDeathGrip in UnregisterAudioChannelAgent().
MOZ_ASSERT(aAgent);
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
MOZ_ASSERT(service);
if (!service->IsEnableAudioCompeting()) {
return;
}
if (!IsAgentInvolvingInAudioCompeting(aAgent)) {
return;
}
MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
("AudioChannelWindow, NotifyAudioCompetingChanged, this = %p, "
"agent = %p\n",
this, aAgent));
service->RefreshAgentsAudioFocusChanged(aAgent);
}
bool AudioChannelService::AudioChannelWindow::IsAgentInvolvingInAudioCompeting(
AudioChannelAgent* aAgent) const {
MOZ_ASSERT(aAgent);
if (!mOwningAudioFocus) {
return false;
}
if (IsAudioCompetingInSameTab()) {
return false;
}
// TODO : add MediaSession::ambient kind, because it doens't interact with
// other kinds.
return true;
}
bool AudioChannelService::AudioChannelWindow::IsAudioCompetingInSameTab()
const {
bool hasMultipleActiveAgents = IsEnableAudioCompetingForAllAgents()
? mAgents.Length() > 1
: mAudibleAgents.Length() > 1;
return mOwningAudioFocus && hasMultipleActiveAgents;
}
void AudioChannelService::AudioChannelWindow::AudioFocusChanged(
AudioChannelAgent* aNewPlayingAgent) {
// This agent isn't always known for the current window, because it can comes
// from other window.
MOZ_ASSERT(aNewPlayingAgent);
if (IsInactiveWindow()) {
// These would happen in two situations,
// (1) Audio in page A was ended, and another page B want to play audio.
// Page A should abandon its focus.
// (2) Audio was paused by remote-control, page should still own the focus.
mOwningAudioFocus = IsContainingPlayingAgent(aNewPlayingAgent);
} else {
nsTObserverArray<AudioChannelAgent*>::ForwardIterator iter(
IsEnableAudioCompetingForAllAgents() ? mAgents : mAudibleAgents);
while (iter.HasMore()) {
AudioChannelAgent* agent = iter.GetNext();
MOZ_ASSERT(agent);
// Don't need to update the playing state of new playing agent.
if (agent == aNewPlayingAgent) {
continue;
}
uint32_t type = GetCompetingBehavior(agent);
// If window will be suspended, it needs to abandon the audio focus
// because only one window can own audio focus at a time. However, we
// would support multiple audio focus at the same time in the future.
mOwningAudioFocus = (type == nsISuspendedTypes::NONE_SUSPENDED);
// TODO : support other behaviors which are definded in MediaSession API.
switch (type) {
case nsISuspendedTypes::NONE_SUSPENDED:
case nsISuspendedTypes::SUSPENDED_STOP_DISPOSABLE:
agent->WindowSuspendChanged(type);
break;
}
}
}
MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
("AudioChannelWindow, AudioFocusChanged, this = %p, "
"OwningAudioFocus = %s\n",
this, mOwningAudioFocus ? "true" : "false"));
}
bool AudioChannelService::AudioChannelWindow::IsContainingPlayingAgent(
AudioChannelAgent* aAgent) const {
return (aAgent->WindowID() == mWindowID);
}
uint32_t AudioChannelService::AudioChannelWindow::GetCompetingBehavior(
AudioChannelAgent* aAgent) const {
MOZ_ASSERT(aAgent);
MOZ_ASSERT(IsEnableAudioCompetingForAllAgents()
? mAgents.Contains(aAgent)
: mAudibleAgents.Contains(aAgent));
uint32_t competingBehavior = nsISuspendedTypes::SUSPENDED_STOP_DISPOSABLE;
MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
("AudioChannelWindow, GetCompetingBehavior, this = %p, "
"behavior = %s\n",
this, SuspendTypeToStr(competingBehavior)));
return competingBehavior;
}
void AudioChannelService::AudioChannelWindow::AppendAgent(
AudioChannelAgent* aAgent, AudibleState aAudible) {
MOZ_ASSERT(aAgent);
RequestAudioFocus(aAgent);
AppendAgentAndIncreaseAgentsNum(aAgent);
AudioAudibleChanged(aAgent, aAudible,
AudibleChangedReasons::eDataAudibleChanged);
if (IsEnableAudioCompetingForAllAgents() &&
aAudible != AudibleState::eAudible) {
NotifyAudioCompetingChanged(aAgent);
}
}
void AudioChannelService::AudioChannelWindow::RemoveAgent(
@ -794,7 +595,6 @@ void AudioChannelService::AudioChannelWindow::AudioAudibleChanged(
if (aAudible == AudibleState::eAudible) {
AppendAudibleAgentIfNotContained(aAgent, aReason);
NotifyAudioCompetingChanged(aAgent);
} else {
RemoveAudibleAgentIfContained(aAgent, aReason);
}
@ -839,12 +639,6 @@ bool AudioChannelService::AudioChannelWindow::IsLastAudibleAgent() const {
return mAudibleAgents.IsEmpty();
}
bool AudioChannelService::AudioChannelWindow::IsInactiveWindow() const {
return IsEnableAudioCompetingForAllAgents()
? mAudibleAgents.IsEmpty() && mAgents.IsEmpty()
: mAudibleAgents.IsEmpty();
}
void AudioChannelService::AudioChannelWindow::NotifyAudioAudibleChanged(
nsPIDOMWindowOuter* aWindow, AudibleState aAudible,
AudibleChangedReasons aReason) {

View File

@ -183,10 +183,8 @@ class AudioChannelService final : public nsIObserver {
explicit AudioChannelWindow(uint64_t aWindowID)
: mWindowID(aWindowID),
mIsAudioCaptured(false),
mOwningAudioFocus(!AudioChannelService::IsEnableAudioCompeting()),
mShouldSendActiveMediaBlockStopEvent(false) {}
void AudioFocusChanged(AudioChannelAgent* aNewPlayingAgent);
void AudioAudibleChanged(AudioChannelAgent* aAgent, AudibleState aAudible,
AudibleChangedReasons aReason);
@ -203,10 +201,6 @@ class AudioChannelService final : public nsIObserver {
nsTObserverArray<AudioChannelAgent*> mAgents;
nsTObserverArray<AudioChannelAgent*> mAudibleAgents;
// Owning audio focus when the window starts playing audible sound, and
// lose audio focus when other windows starts playing.
bool mOwningAudioFocus;
// If we've dispatched "activeMediaBlockStart" event, we must dispatch
// another event "activeMediablockStop" when the window is resumed from
// suspend-block.
@ -230,18 +224,6 @@ class AudioChannelService final : public nsIObserver {
void NotifyChannelActive(uint64_t aWindowID, bool aActive);
void MaybeNotifyMediaBlockStart(AudioChannelAgent* aAgent);
void RequestAudioFocus(AudioChannelAgent* aAgent);
// We need to do audio competing only when the new incoming agent started.
void NotifyAudioCompetingChanged(AudioChannelAgent* aAgent);
uint32_t GetCompetingBehavior(AudioChannelAgent* aAgent) const;
bool IsAgentInvolvingInAudioCompeting(AudioChannelAgent* aAgent) const;
bool IsAudioCompetingInSameTab() const;
bool IsContainingPlayingAgent(AudioChannelAgent* aAgent) const;
bool IsInactiveWindow() const;
};
AudioChannelWindow* GetOrCreateWindowData(nsPIDOMWindowOuter* aWindow);

View File

@ -7,7 +7,6 @@
#ifndef mozilla_dom_BindContext_h__
#define mozilla_dom_BindContext_h__
#include "nsXBLBinding.h"
#include "mozilla/Attributes.h"
#include "mozilla/AutoRestore.h"
#include "mozilla/dom/Document.h"
@ -46,17 +45,9 @@ struct MOZ_STACK_CLASS BindContext final {
// Whether our subtree root is changing as a result of this operation.
bool SubtreeRootChanges() const { return mSubtreeRootChanges; }
// Returns the binding parent of the subtree to be inserted.
//
// This can be null.
Element* GetBindingParent() const { return mBindingParent; }
// This constructor should be used for regular appends to content.
explicit BindContext(nsINode& aParent)
: mDoc(*aParent.OwnerDoc()),
mBindingParent(aParent.IsContent()
? aParent.AsContent()->GetBindingParent()
: nullptr),
mInComposedDoc(aParent.IsInComposedDoc()),
mInUncomposedDoc(aParent.IsInUncomposedDoc()),
mSubtreeRootChanges(true) {}
@ -69,7 +60,6 @@ struct MOZ_STACK_CLASS BindContext final {
// This constructor is only meant to be used in that situation.
explicit BindContext(ShadowRoot& aShadowRoot)
: mDoc(*aShadowRoot.OwnerDoc()),
mBindingParent(aShadowRoot.Host()),
mInComposedDoc(aShadowRoot.IsInComposedDoc()),
mInUncomposedDoc(false),
mSubtreeRootChanges(false) {}
@ -79,21 +69,12 @@ struct MOZ_STACK_CLASS BindContext final {
enum ForNativeAnonymous { ForNativeAnonymous };
BindContext(Element& aParentElement, enum ForNativeAnonymous)
: mDoc(*aParentElement.OwnerDoc()),
mBindingParent(&aParentElement),
mInComposedDoc(aParentElement.IsInComposedDoc()),
mInUncomposedDoc(aParentElement.IsInUncomposedDoc()),
mSubtreeRootChanges(true) {
MOZ_ASSERT(mInComposedDoc, "Binding NAC in a disconnected subtree?");
}
// This is meant to be used to bind XBL anonymous content.
BindContext(nsXBLBinding& aBinding, Element& aParentElement)
: mDoc(*aParentElement.OwnerDoc()),
mBindingParent(aBinding.GetBoundElement()),
mInComposedDoc(aParentElement.IsInComposedDoc()),
mInUncomposedDoc(aParentElement.IsInUncomposedDoc()),
mSubtreeRootChanges(true) {}
private:
static bool IsLikelyUndisplayed(const nsINode& aParent) {
return aParent.IsAnyOfHTMLElements(nsGkAtoms::style, nsGkAtoms::script);
@ -101,8 +82,6 @@ struct MOZ_STACK_CLASS BindContext final {
Document& mDoc;
Element* const mBindingParent;
const bool mInComposedDoc;
const bool mInUncomposedDoc;

View File

@ -506,7 +506,7 @@ void BodyConsumer::BeginConsumeBodyMainThread(ThreadSafeWorkerRef* aWorkerRef) {
rv = GetBodyLocalFile(getter_AddRefs(file));
if (!NS_WARN_IF(NS_FAILED(rv)) && file) {
ChromeFilePropertyBag bag;
bag.mType = NS_ConvertUTF8toUTF16(mBodyMimeType);
CopyUTF8toUTF16(mBodyMimeType, bag.mType);
ErrorResult error;
RefPtr<Promise> promise =

View File

@ -26,7 +26,6 @@
#include "nsChangeHint.h"
#include "nsCOMArray.h"
#include "mozilla/dom/DirectionalityUtils.h"
#include "nsBindingManager.h"
#include "nsCCUncollectableMarker.h"
#include "mozAutoDocUpdate.h"
#include "nsTextNode.h"
@ -36,6 +35,10 @@
#include "nsWindowSizes.h"
#include "nsWrapperCacheInlines.h"
#if defined(ACCESSIBILITY) && defined(DEBUG)
# include "nsAccessibilityService.h"
#endif
namespace mozilla {
namespace dom {
@ -396,41 +399,16 @@ nsresult CharacterData::BindToTree(BindContext& aContext, nsINode& aParent) {
// only assert if our parent is _changing_ while we have a parent.
MOZ_ASSERT(!GetParentNode() || &aParent == GetParentNode(),
"Already have a parent. Unbind first!");
MOZ_ASSERT(
!GetBindingParent() ||
aContext.GetBindingParent() == GetBindingParent() ||
(!aContext.GetBindingParent() && aParent.IsContent() &&
aParent.AsContent()->GetBindingParent() == GetBindingParent()),
"Already have a binding parent. Unbind first!");
MOZ_ASSERT(!IsRootOfNativeAnonymousSubtree() ||
aContext.GetBindingParent() == &aParent,
"Native anonymous content must have its parent as its "
"own binding parent");
MOZ_ASSERT(aContext.GetBindingParent() || !aParent.IsContent() ||
aContext.GetBindingParent() ==
aParent.AsContent()->GetBindingParent(),
"We should be passed the right binding parent");
// First set the binding parent
if (Element* bindingParent = aContext.GetBindingParent()) {
ExtendedContentSlots()->mBindingParent = bindingParent;
}
const bool hadParent = !!GetParentNode();
NS_ASSERTION(!aContext.GetBindingParent() ||
IsRootOfNativeAnonymousSubtree() ||
!HasFlag(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE) ||
aParent.IsInNativeAnonymousSubtree(),
"Trying to re-bind content from native anonymous subtree to "
"non-native anonymous parent!");
if (aParent.IsInNativeAnonymousSubtree()) {
SetFlags(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE);
}
if (aParent.HasFlag(NODE_HAS_BEEN_IN_UA_WIDGET)) {
SetFlags(NODE_HAS_BEEN_IN_UA_WIDGET);
}
if (HasFlag(NODE_IS_ANONYMOUS_ROOT)) {
if (IsRootOfNativeAnonymousSubtree()) {
aParent.SetMayHaveAnonymousChildren();
}
@ -486,8 +464,6 @@ nsresult CharacterData::BindToTree(BindContext& aContext, nsINode& aParent) {
MOZ_ASSERT(IsInComposedDoc() == aContext.InComposedDoc());
MOZ_ASSERT(IsInUncomposedDoc() == aContext.InUncomposedDoc());
MOZ_ASSERT(&aParent == GetParentNode(), "Bound to wrong parent node");
MOZ_ASSERT(aContext.GetBindingParent() == GetBindingParent(),
"Bound to wrong binding parent");
MOZ_ASSERT(aParent.IsInUncomposedDoc() == IsInUncomposedDoc());
MOZ_ASSERT(aParent.IsInComposedDoc() == IsInComposedDoc());
MOZ_ASSERT(aParent.IsInShadowTree() == IsInShadowTree());
@ -501,8 +477,6 @@ void CharacterData::UnbindFromTree(bool aNullParent) {
HandleShadowDOMRelatedRemovalSteps(aNullParent);
Document* document = GetComposedDoc();
if (aNullParent) {
if (IsRootOfNativeAnonymousSubtree()) {
MutationObservers::NotifyNativeAnonymousChildListChange(this, true);
@ -524,26 +498,18 @@ void CharacterData::UnbindFromTree(bool aNullParent) {
SetSubtreeRootPointer(aNullParent ? this : mParent->SubtreeRoot());
}
if (document && !GetContainingShadow()) {
// Notify XBL- & nsIAnonymousContentCreator-generated
// anonymous content that the document is changing.
// Unlike XBL, bindings for web components shadow DOM
// do not get uninstalled.
if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
nsContentUtils::AddScriptRunner(new RemoveFromBindingManagerRunnable(
document->BindingManager(), this, document));
}
}
nsExtendedContentSlots* slots = GetExistingExtendedContentSlots();
if (slots) {
slots->mBindingParent = nullptr;
if (nsExtendedContentSlots* slots = GetExistingExtendedContentSlots()) {
if (aNullParent || !mParent->IsInShadowTree()) {
slots->mContainingShadow = nullptr;
}
}
MutationObservers::NotifyParentChainChanged(this);
#if defined(ACCESSIBILITY) && defined(DEBUG)
MOZ_ASSERT(!GetAccService() || !GetAccService()->HasAccessible(this),
"An accessible for this element still exists!");
#endif
}
//----------------------------------------------------------------------

View File

@ -167,8 +167,6 @@ class CharacterData : public nsIContent {
void DumpContent(FILE* out, int32_t aIndent, bool aDumpAll) const override {}
#endif
nsXBLBinding* DoGetXBLBinding() const final { return nullptr; }
bool IsNodeOfType(uint32_t aFlags) const override { return false; }
bool IsLink(nsIURI** aURI) const final {

View File

@ -6,7 +6,6 @@
#include "nsContentUtils.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/HTMLSlotElement.h"
#include "mozilla/dom/XBLChildrenElement.h"
#include "mozilla/dom/ShadowRoot.h"
#include "nsIAnonymousContentCreator.h"
#include "nsIFrame.h"
@ -45,17 +44,10 @@ nsIContent* ExplicitChildIterator::GetNextChild() {
return mChild;
}
MOZ_ASSERT(mChild->IsActiveChildrenElement());
auto* childrenElement = static_cast<XBLChildrenElement*>(mChild);
if (mIndexInInserted < childrenElement->InsertedChildrenLength()) {
return childrenElement->InsertedChild(mIndexInInserted++);
}
mIndexInInserted = 0;
mChild = mChild->GetNextSibling();
MOZ_ASSERT_UNREACHABLE("This needs to be revisited");
} else if (mDefaultChild) {
// If we're already in default content, check if there are more nodes there
MOZ_ASSERT(mChild);
MOZ_ASSERT(mChild->IsActiveChildrenElement());
mDefaultChild = mDefaultChild->GetNextSibling();
if (mDefaultChild) {
@ -83,89 +75,23 @@ nsIContent* ExplicitChildIterator::GetNextChild() {
mChild = mChild->GetNextSibling();
}
// Iterate until we find a non-insertion point, or an insertion point with
// content.
while (mChild) {
if (mChild->IsActiveChildrenElement()) {
// If the current child being iterated is a content insertion point
// then the iterator needs to return the nodes distributed into
// the content insertion point.
auto* childrenElement = static_cast<XBLChildrenElement*>(mChild);
if (childrenElement->HasInsertedChildren()) {
// Iterate through elements projected on insertion point.
mIndexInInserted = 1;
return childrenElement->InsertedChild(0);
}
// Insertion points inside fallback/default content
// are considered inactive and do not get assigned nodes.
mDefaultChild = mChild->GetFirstChild();
if (mDefaultChild) {
return mDefaultChild;
}
// If we have an insertion point with no assigned nodes and
// no default content, move on to the next node.
mChild = mChild->GetNextSibling();
} else {
// mChild is not an insertion point, thus it is the next node to
// return from this iterator.
break;
}
}
return mChild;
}
void FlattenedChildIterator::Init(bool aIgnoreXBL) {
if (aIgnoreXBL) {
mXBLInvolved = Some(false);
void FlattenedChildIterator::Init() {
if (!mParent->IsElement()) {
// TODO(emilio): I think it probably makes sense to only allow constructing
// FlattenedChildIterators with Element.
return;
}
// TODO(emilio): I think it probably makes sense to only allow constructing
// FlattenedChildIterators with Element.
if (mParent->IsElement()) {
if (ShadowRoot* shadow = mParent->AsElement()->GetShadowRoot()) {
mParent = shadow;
mXBLInvolved = Some(true);
return;
}
if (ShadowRoot* shadow = mParent->AsElement()->GetShadowRoot()) {
mParent = shadow;
mShadowDOMInvolved = true;
return;
}
nsXBLBinding* binding =
mParent->OwnerDoc()->BindingManager()->GetBindingWithContent(mParent);
if (binding) {
MOZ_ASSERT(binding->GetAnonymousContent());
mParent = binding->GetAnonymousContent();
mXBLInvolved = Some(true);
}
}
bool FlattenedChildIterator::ComputeWhetherXBLIsInvolved() const {
MOZ_ASSERT(mXBLInvolved.isNothing());
// We set mXBLInvolved to true if either the node we're iterating has a
// binding with content attached to it (in which case it is handled in Init),
// the node is generated XBL content and has an <xbl:children> child, or the
// node is a <slot> element.
if (!mParent->GetBindingParent()) {
return false;
}
if (mParentAsSlot) {
return true;
mShadowDOMInvolved = true;
}
for (nsIContent* child = mParent->GetFirstChild(); child;
child = child->GetNextSibling()) {
if (child->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) {
MOZ_ASSERT(child->GetBindingParent());
return true;
}
}
return false;
}
bool ExplicitChildIterator::Seek(const nsIContent* aChildToFind) {
@ -177,7 +103,6 @@ bool ExplicitChildIterator::Seek(const nsIContent* aChildToFind) {
mIndexInInserted = 0;
mDefaultChild = nullptr;
mIsFirst = false;
MOZ_ASSERT(!mChild->IsActiveChildrenElement());
return true;
}
@ -198,9 +123,7 @@ nsIContent* ExplicitChildIterator::Get() const {
}
if (mIndexInInserted) {
MOZ_ASSERT(mChild->IsActiveChildrenElement());
auto* childrenElement = static_cast<XBLChildrenElement*>(mChild);
return childrenElement->InsertedChild(mIndexInInserted - 1);
MOZ_ASSERT_UNREACHABLE("This needs to be revisited");
}
return mDefaultChild ? mDefaultChild : mChild;
@ -223,14 +146,7 @@ nsIContent* ExplicitChildIterator::GetPreviousChild() {
return mChild;
}
// NB: mIndexInInserted points one past the last returned child so we need
// to look *two* indices back in order to return the previous child.
MOZ_ASSERT(mChild->IsActiveChildrenElement());
auto* childrenElement = static_cast<XBLChildrenElement*>(mChild);
if (--mIndexInInserted) {
return childrenElement->InsertedChild(mIndexInInserted - 1);
}
mChild = mChild->GetPreviousSibling();
MOZ_ASSERT_UNREACHABLE("This needs to be revisited");
} else if (mDefaultChild) {
// If we're already in default content, check if there are more nodes there
mDefaultChild = mDefaultChild->GetPreviousSibling();
@ -259,32 +175,6 @@ nsIContent* ExplicitChildIterator::GetPreviousChild() {
mChild = mParent->GetLastChild();
}
// Iterate until we find a non-insertion point, or an insertion point with
// content.
while (mChild) {
if (mChild->IsActiveChildrenElement()) {
// If the current child being iterated is a content insertion point
// then the iterator needs to return the nodes distributed into
// the content insertion point.
auto* childrenElement = static_cast<XBLChildrenElement*>(mChild);
if (childrenElement->HasInsertedChildren()) {
mIndexInInserted = childrenElement->InsertedChildrenLength();
return childrenElement->InsertedChild(mIndexInInserted - 1);
}
mDefaultChild = mChild->GetLastChild();
if (mDefaultChild) {
return mDefaultChild;
}
mChild = mChild->GetPreviousSibling();
} else {
// mChild is not an insertion point, thus it is the next node to
// return from this iterator.
break;
}
}
if (!mChild) {
mIsFirst = true;
}

View File

@ -34,22 +34,6 @@ class ExplicitChildIterator {
explicit ExplicitChildIterator(const nsIContent* aParent,
bool aStartAtBeginning = true);
ExplicitChildIterator(const ExplicitChildIterator& aOther)
: mParent(aOther.mParent),
mParentAsSlot(aOther.mParentAsSlot),
mChild(aOther.mChild),
mDefaultChild(aOther.mDefaultChild),
mIsFirst(aOther.mIsFirst),
mIndexInInserted(aOther.mIndexInInserted) {}
ExplicitChildIterator(ExplicitChildIterator&& aOther)
: mParent(aOther.mParent),
mParentAsSlot(aOther.mParentAsSlot),
mChild(aOther.mChild),
mDefaultChild(aOther.mDefaultChild),
mIsFirst(aOther.mIsFirst),
mIndexInInserted(aOther.mIndexInInserted) {}
nsIContent* GetNextChild();
// Looks for aChildToFind respecting insertion points until aChildToFind is
@ -129,61 +113,30 @@ class FlattenedChildIterator : public ExplicitChildIterator {
bool aStartAtBeginning = true)
: ExplicitChildIterator(aParent, aStartAtBeginning),
mOriginalContent(aParent) {
Init(false);
Init();
}
FlattenedChildIterator(FlattenedChildIterator&& aOther)
: ExplicitChildIterator(std::move(aOther)),
mOriginalContent(aOther.mOriginalContent),
mXBLInvolved(aOther.mXBLInvolved) {}
FlattenedChildIterator(const FlattenedChildIterator& aOther)
: ExplicitChildIterator(aOther),
mOriginalContent(aOther.mOriginalContent),
mXBLInvolved(aOther.mXBLInvolved) {}
bool XBLInvolved() {
if (mXBLInvolved.isNothing()) {
mXBLInvolved = Some(ComputeWhetherXBLIsInvolved());
}
return *mXBLInvolved;
}
bool ShadowDOMInvolved() { return mShadowDOMInvolved; }
const nsIContent* Parent() const { return mOriginalContent; }
private:
bool ComputeWhetherXBLIsInvolved() const;
void Init(bool aIgnoreXBL);
protected:
/**
* This constructor is a hack to help AllChildrenIterator which sometimes
* doesn't want to consider XBL.
*/
FlattenedChildIterator(const nsIContent* aParent, uint32_t aFlags,
bool aStartAtBeginning = true)
: ExplicitChildIterator(aParent, aStartAtBeginning),
mOriginalContent(aParent) {
bool ignoreXBL = aFlags & nsIContent::eAllButXBL;
Init(ignoreXBL);
}
const nsIContent* mOriginalContent;
private:
void Init();
// For certain optimizations, nsCSSFrameConstructor needs to know if the child
// list of the element that we're iterating matches its .childNodes.
//
// This is lazily computed when asked for it.
Maybe<bool> mXBLInvolved;
bool mShadowDOMInvolved = false;
};
/**
* AllChildrenIterator traverses the children of an element including before /
* after content and optionally XBL children. The iterator can be initialized
* to start at the end by providing false for aStartAtBeginning in order to
* start iterating in reverse from the last child.
* after content and shadow DOM. The iterator can be initialized to start at
* the end by providing false for aStartAtBeginning in order to start iterating
* in reverse from the last child.
*
* Note: it assumes that no mutation of the DOM or frame tree takes place during
* iteration, and will break horribly if that is not true.
@ -192,31 +145,22 @@ class AllChildrenIterator : private FlattenedChildIterator {
public:
AllChildrenIterator(const nsIContent* aNode, uint32_t aFlags,
bool aStartAtBeginning = true)
: FlattenedChildIterator(aNode, aFlags, aStartAtBeginning),
: FlattenedChildIterator(aNode, aStartAtBeginning),
mAnonKidsIdx(aStartAtBeginning ? UINT32_MAX : 0),
mFlags(aFlags),
mPhase(aStartAtBeginning ? eAtBegin : eAtEnd) {}
AllChildrenIterator(AllChildrenIterator&& aOther)
: FlattenedChildIterator(std::move(aOther)),
mAnonKids(std::move(aOther.mAnonKids)),
mAnonKidsIdx(aOther.mAnonKidsIdx),
mFlags(aOther.mFlags),
mPhase(aOther.mPhase)
#ifdef DEBUG
,
mMutationGuard(aOther.mMutationGuard)
#endif
{
}
AllChildrenIterator(AllChildrenIterator&&) = default;
AllChildrenIterator& operator=(AllChildrenIterator&& aOther) {
// Explicitly call the destructor to ensure the assertion in the destructor
// is checked.
this->~AllChildrenIterator();
new (this) AllChildrenIterator(std::move(aOther));
return *this;
}
#ifdef DEBUG
~AllChildrenIterator() { MOZ_ASSERT(!mMutationGuard.Mutated(0)); }
#endif
@ -305,10 +249,7 @@ class MOZ_NEEDS_MEMMOVABLE_MEMBERS StyleChildrenIterator
MOZ_COUNT_CTOR(StyleChildrenIterator);
}
StyleChildrenIterator& operator=(StyleChildrenIterator&& aOther) {
AllChildrenIterator::operator=(std::move(aOther));
return *this;
}
StyleChildrenIterator& operator=(StyleChildrenIterator&& aOther) = default;
MOZ_COUNTED_DTOR(StyleChildrenIterator)

View File

@ -385,16 +385,6 @@ class CustomElementRegistry final : public nsISupports, public nsWrapperCache {
};
public:
/**
* Returns whether there's a definition that is likely to match this type
* atom. This is not exact, so should only be used for optimization, but it's
* good enough to prove that the chrome code doesn't need an XBL binding.
*/
bool IsLikelyToBeCustomElement(nsAtom* aTypeAtom) const {
return mCustomDefinitions.GetWeak(aTypeAtom) ||
mElementCreationCallbacks.GetWeak(aTypeAtom);
}
/**
* Looking up a custom element definition.
* https://html.spec.whatwg.org/#look-up-a-custom-element-definition

View File

@ -172,7 +172,6 @@
#include "nsContentCreatorFunctions.h"
#include "nsIScriptContext.h"
#include "nsBindingManager.h"
#include "nsHTMLDocument.h"
#include "nsIRequest.h"
#include "mozilla/dom/BlobURLProtocolHandler.h"
@ -292,17 +291,17 @@
#include "mozilla/dom/SVGSVGElement.h"
#include "mozilla/dom/DocGroup.h"
#include "mozilla/dom/TabGroup.h"
#include "mozilla/dom/ChromeObserver.h"
#ifdef MOZ_XUL
# include "mozilla/dom/XULBroadcastManager.h"
# include "mozilla/dom/XULPersist.h"
# include "nsIXULWindow.h"
# include "nsIAppWindow.h"
# include "nsIChromeRegistry.h"
# include "nsXULPrototypeDocument.h"
# include "nsXULCommandDispatcher.h"
# include "nsXULPopupManager.h"
# include "nsIDocShellTreeOwner.h"
#endif
#include "mozilla/dom/BoxObject.h"
#include "mozilla/DocLoadingTimelineMarker.h"
@ -829,19 +828,14 @@ nsresult ExternalResourceMap::AddExternalResource(nsIURI* aURI,
doc = aViewer->GetDocument();
NS_ASSERTION(doc, "Must have a document");
if (doc->IsXULDocument()) {
// We don't handle XUL stuff here yet.
rv = NS_ERROR_NOT_AVAILABLE;
} else {
doc->SetDisplayDocument(aDisplayDocument);
doc->SetDisplayDocument(aDisplayDocument);
// Make sure that hiding our viewer will tear down its presentation.
aViewer->SetSticky(false);
// Make sure that hiding our viewer will tear down its presentation.
aViewer->SetSticky(false);
rv = aViewer->Init(nullptr, nsIntRect(0, 0, 0, 0));
if (NS_SUCCEEDED(rv)) {
rv = aViewer->Open(nullptr, nullptr);
}
rv = aViewer->Init(nullptr, nsIntRect(0, 0, 0, 0));
if (NS_SUCCEEDED(rv)) {
rv = aViewer->Open(nullptr, nullptr);
}
if (NS_FAILED(rv)) {
@ -1204,7 +1198,6 @@ Document::Document(const char* aContentType)
mIsInitialDocumentInWindow(false),
mIgnoreDocGroupMismatches(false),
mLoadedAsData(false),
mLoadedAsInteractiveData(false),
mMayStartLayout(true),
mHaveFiredTitleChange(false),
mIsShowing(false),
@ -1265,7 +1258,6 @@ Document::Document(const char* aContentType)
mAutoFocusFired(false),
mScrolledToRefAlready(false),
mChangeScrollPosWhenScrollingToRef(false),
mHasWarnedAboutBoxObjects(false),
mDelayFrameLoaderInitialization(false),
mSynchronousDOMContentLoaded(false),
mMaybeServiceWorkerControlled(false),
@ -1325,7 +1317,6 @@ Document::Document(const char* aContentType)
mHeaderData(nullptr),
mScrollAnchorAdjustmentLength(0),
mScrollAnchorAdjustmentCount(0),
mBoxObjectTable(nullptr),
mCurrentOrientationAngle(0),
mCurrentOrientationType(OrientationType::Portrait_primary),
mServoRestyleRootDirtyBits(0),
@ -1357,19 +1348,6 @@ Document::Document(const char* aContentType)
mReferrerInfo = new dom::ReferrerInfo(nullptr);
}
void Document::ClearAllBoxObjects() {
if (mBoxObjectTable) {
for (auto iter = mBoxObjectTable->Iter(); !iter.Done(); iter.Next()) {
nsPIBoxObject* boxObject = iter.UserData();
if (boxObject) {
boxObject->Clear();
}
}
delete mBoxObjectTable;
mBoxObjectTable = nullptr;
}
}
bool Document::IsAboutPage() const {
nsCOMPtr<nsIPrincipal> principal = NodePrincipal();
return principal->SchemeIs("about");
@ -1551,8 +1529,6 @@ Document::~Document() {
delete mHeaderData;
ClearAllBoxObjects();
mPendingTitleChangeEvent.Revoke();
mPlugins.Clear();
@ -1658,13 +1634,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(Document)
return NS_SUCCESS_INTERRUPTED_TRAVERSE;
}
if (tmp->mMaybeEndOutermostXBLUpdateRunner) {
// The cached runnable keeps a reference to the document object..
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(
cb, "mMaybeEndOutermostXBLUpdateRunner.mObj");
cb.NoteXPCOMChild(ToSupports(tmp));
}
tmp->mExternalResourceMap.Traverse(&cb);
// Traverse all Document pointer members.
@ -1683,15 +1652,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(Document)
DocumentOrShadowRoot::Traverse(tmp, cb);
// The boxobject for an element will only exist as long as it's in the
// document, so we'll traverse the table here instead of from the element.
if (tmp->mBoxObjectTable) {
for (auto iter = tmp->mBoxObjectTable->Iter(); !iter.Done(); iter.Next()) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mBoxObjectTable entry");
cb.NoteXPCOMChild(iter.UserData());
}
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChannel)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLayoutHistoryState)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOnloadBlocker)
@ -1802,7 +1762,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Document)
tmp->mCachedRootElement = nullptr; // Avoid a dangling pointer
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDisplayDocument)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mMaybeEndOutermostXBLUpdateRunner)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDOMImplementation)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mImageMaps)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCachedEncoder)
@ -1835,8 +1794,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Document)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIntersectionObservers)
tmp->ClearAllBoxObjects();
if (tmp->mListenerManager) {
tmp->mListenerManager->Disconnect();
tmp->UnsetFlags(NODE_HAS_LISTENERMANAGER);
@ -1974,7 +1931,7 @@ void Document::Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup) {
nsCOMPtr<nsIPrincipal> principal;
nsCOMPtr<nsIPrincipal> storagePrincipal;
if (aChannel) {
// Note: this code is duplicated in XULDocument::StartDocumentLoad and
// Note: this code is duplicated in PrototypeDocumentContentSink::Init and
// nsScriptSecurityManager::GetChannelResultPrincipals.
// Note: this should match nsDocShell::OnLoadingSite
NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
@ -2641,6 +2598,9 @@ nsresult Document::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
IsSynthesized() && XRE_IsContentProcess()) {
ContentChild::UpdateCookieStatus(mChannel);
}
// Store the security info for future use.
mChannel->GetSecurityInfo(getter_AddRefs(mSecurityInfo));
}
// If this document is being loaded by a docshell, copy its sandbox flags
@ -2866,11 +2826,12 @@ nsresult Document::InitCSP(nsIChannel* aChannel) {
// ----- if the doc is an addon, apply its CSP.
if (addonPolicy) {
nsAutoString addonCSP;
Unused << ExtensionPolicyService::GetSingleton().GetBaseCSP(addonCSP);
mCSP->AppendPolicy(addonCSP, false, false);
nsAutoString extensionPageCSP;
Unused << ExtensionPolicyService::GetSingleton().GetBaseCSP(
extensionPageCSP);
mCSP->AppendPolicy(extensionPageCSP, false, false);
mCSP->AppendPolicy(addonPolicy->ContentSecurityPolicy(), false, false);
mCSP->AppendPolicy(addonPolicy->ExtensionPageCSP(), false, false);
// Bug 1548468: Move CSP off ExpandedPrincipal
// Currently the LoadInfo holds the source of truth for every resource load
// because LoadInfo::GetCSP() queries the CSP from an ExpandedPrincipal
@ -3503,7 +3464,7 @@ SVGSVGElement* Document::GetSVGRootElement() const {
/* Return true if the document is in the focused top-level window, and is an
* ancestor of the focused DOMWindow. */
bool Document::HasFocus(ErrorResult& rv) const {
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (!fm) {
rv.Throw(NS_ERROR_NOT_AVAILABLE);
return false;
@ -5390,9 +5351,9 @@ Element* Document::GetActiveElement() {
if (bodyElement) {
return bodyElement;
}
// Special case to handle the transition to browser.xhtml where there is
// currently not a body element, but we need to match the XUL behavior.
// This should be removed when bug 1492582 is resolved.
// Special case to handle the transition to XHTML from XUL documents
// where there currently isn't a body element, but we need to match the
// XUL behavior. This should be removed when bug 1540278 is resolved.
if (nsContentUtils::IsChromeDoc(this)) {
Element* docElement = GetDocumentElement();
if (docElement && docElement->IsXULElement()) {
@ -5604,20 +5565,6 @@ static inline void AssertNoStaleServoDataIn(nsINode& aSubtreeRoot) {
continue;
}
MOZ_ASSERT(!element->HasServoData());
if (nsXBLBinding* binding = element->GetXBLBinding()) {
if (nsXBLBinding* bindingWithContent = binding->GetBindingWithContent()) {
nsIContent* content = bindingWithContent->GetAnonymousContent();
// Need to do this instead of just AssertNoStaleServoDataIn(*content),
// because the parent of the children of the <content> element isn't the
// <content> element, but the bound element, and that confuses
// GetNextNode a lot.
MOZ_ASSERT(!content->AsElement()->HasServoData());
for (nsINode* child = content->GetFirstChild(); child;
child = child->GetNextSibling()) {
AssertNoStaleServoDataIn(*child);
}
}
}
}
#endif
}
@ -6521,24 +6468,6 @@ bool Document::RemoveObserver(nsIDocumentObserver* aObserver) {
return mObservers.Contains(aObserver);
}
void Document::MaybeEndOutermostXBLUpdate() {
// Only call BindingManager()->EndOutermostUpdate() when
// we're not in an update and it is safe to run scripts.
if (mUpdateNestLevel == 0 && mInXBLUpdate) {
if (nsContentUtils::IsSafeToRunScript()) {
mInXBLUpdate = false;
BindingManager()->EndOutermostUpdate();
} else if (!mInDestructor) {
if (!mMaybeEndOutermostXBLUpdateRunner) {
mMaybeEndOutermostXBLUpdateRunner =
NewRunnableMethod("Document::MaybeEndOutermostXBLUpdate", this,
&Document::MaybeEndOutermostXBLUpdate);
}
nsContentUtils::AddScriptRunner(mMaybeEndOutermostXBLUpdateRunner);
}
}
}
void Document::BeginUpdate() {
// If the document is going away, then it's probably okay to do things to it
// in the wrong DocGroup. We're unlikely to run JS or do anything else
@ -6551,11 +6480,6 @@ void Document::BeginUpdate() {
mDocGroup->ValidateAccess();
}
if (mUpdateNestLevel == 0 && !mInXBLUpdate) {
mInXBLUpdate = true;
BindingManager()->BeginOutermostUpdate();
}
++mUpdateNestLevel;
nsContentUtils::AddScriptBlocker();
NS_DOCUMENT_NOTIFY_OBSERVERS(BeginUpdate, (this));
@ -6571,10 +6495,6 @@ void Document::EndUpdate() {
--mUpdateNestLevel;
// This set of updates may have created XBL bindings. Let the
// binding manager know we're done.
MaybeEndOutermostXBLUpdate();
MaybeInitializeFinalizeFrameLoaders();
if (mXULBroadcastManager) {
mXULBroadcastManager->MaybeBroadcast();
@ -6772,10 +6692,9 @@ void Document::EndLoad() {
bool turnOnEditing =
mParser && (HasFlag(NODE_IS_EDITABLE) || mContentEditableCount > 0);
#if defined(DEBUG) && !defined(ANDROID)
#if defined(DEBUG)
// only assert if nothing stopped the load on purpose
// TODO: we probably also want to check XUL documents here too
if (!mParserAborted && !IsXULDocument()) {
if (!mParserAborted) {
nsContentSecurityUtils::AssertAboutPageHasCSP(this);
}
#endif
@ -6799,6 +6718,14 @@ void Document::EndLoad() {
mParser = nullptr;
}
// Update the attributes on the PerformanceNavigationTiming before notifying
// the onload observers.
if (nsPIDOMWindowInner* window = GetInnerWindow()) {
if (RefPtr<Performance> performance = window->GetPerformance()) {
performance->UpdateNavigationTimingEntry();
}
}
NS_DOCUMENT_NOTIFY_OBSERVERS(EndLoad, (this));
// Part 2: Code that only executes when this EndLoad matches a BeginLoad.
@ -7455,85 +7382,6 @@ already_AddRefed<nsINode> Document::ImportNode(nsINode& aNode, bool aDeep,
return nullptr;
}
void Document::LoadBindingDocument(const nsAString& aURI,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& rv) {
nsCOMPtr<nsIURI> uri;
rv = NS_NewURI(getter_AddRefs(uri), aURI, mCharacterSet, GetDocBaseURI());
if (rv.Failed()) {
return;
}
BindingManager()->LoadBindingDocument(this, uri, &aSubjectPrincipal);
}
Element* Document::GetBindingParent(nsINode& aNode) {
nsCOMPtr<nsIContent> content(do_QueryInterface(&aNode));
if (!content) return nullptr;
nsIContent* bindingParent = content->GetBindingParent();
return bindingParent ? bindingParent->AsElement() : nullptr;
}
static Element* GetElementByAttribute(Element* aElement, nsAtom* aAttrName,
const nsAString& aAttrValue,
bool aUniversalMatch) {
if (aUniversalMatch ? aElement->HasAttr(kNameSpaceID_None, aAttrName)
: aElement->AttrValueIs(kNameSpaceID_None, aAttrName,
aAttrValue, eCaseMatters)) {
return aElement;
}
for (nsIContent* child = aElement->GetFirstChild(); child;
child = child->GetNextSibling()) {
if (!child->IsElement()) {
continue;
}
Element* matchedElement = GetElementByAttribute(
child->AsElement(), aAttrName, aAttrValue, aUniversalMatch);
if (matchedElement) return matchedElement;
}
return nullptr;
}
Element* Document::GetAnonymousElementByAttribute(
nsIContent* aElement, nsAtom* aAttrName,
const nsAString& aAttrValue) const {
nsINodeList* nodeList = BindingManager()->GetAnonymousNodesFor(aElement);
if (!nodeList) return nullptr;
uint32_t length = nodeList->Length();
bool universalMatch = aAttrValue.EqualsLiteral("*");
for (uint32_t i = 0; i < length; ++i) {
Element* current = Element::FromNode(nodeList->Item(i));
if (!current) {
continue;
}
Element* matchedElm =
GetElementByAttribute(current, aAttrName, aAttrValue, universalMatch);
if (matchedElm) return matchedElm;
}
return nullptr;
}
Element* Document::GetAnonymousElementByAttribute(Element& aElement,
const nsAString& aAttrName,
const nsAString& aAttrValue) {
RefPtr<nsAtom> attribute = NS_Atomize(aAttrName);
return GetAnonymousElementByAttribute(&aElement, attribute, aAttrValue);
}
nsINodeList* Document::GetAnonymousNodes(Element& aElement) {
return BindingManager()->GetAnonymousNodesFor(&aElement);
}
already_AddRefed<nsRange> Document::CreateRange(ErrorResult& rv) {
return nsRange::Create(this, 0, this, 0, rv);
}
@ -7944,55 +7792,6 @@ void Document::DoNotifyPossibleTitleChange() {
Cancelable::eYes);
}
already_AddRefed<BoxObject> Document::GetBoxObjectFor(Element* aElement,
ErrorResult& aRv) {
if (!aElement) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
Document* doc = aElement->OwnerDoc();
if (doc != this) {
aRv.Throw(NS_ERROR_DOM_WRONG_DOCUMENT_ERR);
return nullptr;
}
if (!mHasWarnedAboutBoxObjects && !aElement->IsXULElement()) {
mHasWarnedAboutBoxObjects = true;
nsContentUtils::ReportToConsole(
nsIScriptError::warningFlag, NS_LITERAL_CSTRING("BoxObjects"), this,
nsContentUtils::eDOM_PROPERTIES, "UseOfGetBoxObjectForWarning");
}
if (!mBoxObjectTable) {
mBoxObjectTable =
new nsRefPtrHashtable<nsPtrHashKey<nsIContent>, BoxObject>(6);
}
RefPtr<BoxObject> boxObject;
auto entry = mBoxObjectTable->LookupForAdd(aElement);
if (entry) {
boxObject = entry.Data();
return boxObject.forget();
}
boxObject = new BoxObject();
boxObject->Init(aElement);
entry.OrInsert([&boxObject]() { return boxObject; });
return boxObject.forget();
}
void Document::ClearBoxObjectFor(nsIContent* aContent) {
if (mBoxObjectTable) {
if (auto entry = mBoxObjectTable->Lookup(aContent)) {
nsPIBoxObject* boxObject = entry.Data();
boxObject->Clear();
entry.Remove();
}
}
}
already_AddRefed<MediaQueryList> Document::MatchMedia(
const nsACString& aMediaQueryList, CallerType aCallerType) {
RefPtr<MediaQueryList> result =
@ -8009,7 +7808,7 @@ void Document::SetMayStartLayout(bool aMayStartLayout) {
// Before starting layout, check whether we're a toplevel chrome
// window. If we are, setup some state so that we don't have to restyle
// the whole tree after StartLayout.
if (nsCOMPtr<nsIXULWindow> win = GetXULWindowIfToplevelChrome()) {
if (nsCOMPtr<nsIAppWindow> win = GetAppWindowIfToplevelChrome()) {
// We're the chrome document!
win->BeforeStartLayout();
}
@ -8117,6 +7916,7 @@ void Document::TryCancelFrameLoaderInitialization(nsIDocShell* aShell) {
void Document::SetPrototypeDocument(nsXULPrototypeDocument* aPrototype) {
mPrototypeDocument = aPrototype;
mSynchronousDOMContentLoaded = true;
}
Document* Document::RequestExternalResource(
@ -8143,7 +7943,7 @@ SMILAnimationController* Document::GetAnimationController() {
// one and only SVG documents and the like will call this
if (mAnimationController) return mAnimationController;
// Refuse to create an Animation Controller for data documents.
if (mLoadedAsData || mLoadedAsInteractiveData) return nullptr;
if (mLoadedAsData) return nullptr;
mAnimationController = new SMILAnimationController(this);
@ -8895,14 +8695,6 @@ nsINode* Document::AdoptNode(nsINode& aAdoptedNode, ErrorResult& rv) {
parent->RemoveChildNode(adoptedNode->AsContent(), true);
} else {
MOZ_ASSERT(!adoptedNode->IsInUncomposedDoc());
// If we're adopting a node that's not in a document, it might still
// have a binding applied. Remove the binding from the element now
// that it's getting adopted into a new document.
// TODO Fully tear down the binding.
if (Element* element = Element::FromNode(adoptedNode)) {
element->SetXBLBinding(nullptr);
}
}
break;
@ -10749,14 +10541,15 @@ void Document::SetReadyStateInternal(ReadyState aReadyState,
}
// At the time of loading start, we don't have timing object, record time.
if (READYSTATE_INTERACTIVE == aReadyState) {
if (NodePrincipal()->IsSystemPrincipal()) {
Element* root = GetRootElement();
if ((root && root->HasAttr(kNameSpaceID_None, nsGkAtoms::mozpersist)) ||
IsXULDocument()) {
mXULPersist = new XULPersist(this);
mXULPersist->Init();
}
if (READYSTATE_INTERACTIVE == aReadyState &&
NodePrincipal()->IsSystemPrincipal()) {
if (!mXULPersist) {
mXULPersist = new XULPersist(this);
mXULPersist->Init();
}
if (!mChromeObserver) {
mChromeObserver = new ChromeObserver(this);
mChromeObserver->Init();
}
}
@ -10802,7 +10595,7 @@ void Document::SuppressEventHandling(uint32_t aIncrease) {
static void FireOrClearDelayedEvents(nsTArray<nsCOMPtr<Document>>& aDocuments,
bool aFireEvents) {
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (!fm) return;
for (uint32_t i = 0; i < aDocuments.Length(); ++i) {
@ -11077,14 +10870,14 @@ RefPtr<StyleSheet> Document::LoadChromeSheetSync(nsIURI* uri) {
}
void Document::ResetDocumentDirection() {
if (!(nsContentUtils::IsChromeDoc(this) || IsXULDocument())) {
if (!nsContentUtils::IsChromeDoc(this)) {
return;
}
UpdateDocumentStates(NS_DOCUMENT_STATE_RTL_LOCALE, true);
}
bool Document::IsDocumentRightToLeft() {
if (!(nsContentUtils::IsChromeDoc(this) || IsXULDocument())) {
if (!nsContentUtils::IsChromeDoc(this)) {
return false;
}
// setting the localedir attribute on the root element forces a
@ -13858,13 +13651,6 @@ void Document::AddSizeOfNodeTree(nsINode& aNode, nsWindowSizes& aWindowSizes) {
if (ShadowRoot* shadow = element->GetShadowRoot()) {
AddSizeOfNodeTree(*shadow, aWindowSizes);
}
for (nsXBLBinding* binding = element->GetXBLBinding(); binding;
binding = binding->GetBaseBinding()) {
if (nsIContent* anonContent = binding->GetAnonymousContent()) {
AddSizeOfNodeTree(*anonContent, aWindowSizes);
}
}
}
}
@ -13933,23 +13719,23 @@ already_AddRefed<XPathResult> Document::Evaluate(
aType, aResult, rv);
}
already_AddRefed<nsIXULWindow> Document::GetXULWindowIfToplevelChrome() const {
already_AddRefed<nsIAppWindow> Document::GetAppWindowIfToplevelChrome() const {
nsCOMPtr<nsIDocShellTreeItem> item = GetDocShell();
if (!item) {
return nullptr;
}
nsCOMPtr<nsIDocShellTreeOwner> owner;
item->GetTreeOwner(getter_AddRefs(owner));
nsCOMPtr<nsIXULWindow> xulWin = do_GetInterface(owner);
if (!xulWin) {
nsCOMPtr<nsIAppWindow> appWin = do_GetInterface(owner);
if (!appWin) {
return nullptr;
}
nsCOMPtr<nsIDocShell> xulWinShell;
xulWin->GetDocShell(getter_AddRefs(xulWinShell));
if (!SameCOMIdentity(xulWinShell, item)) {
nsCOMPtr<nsIDocShell> appWinShell;
appWin->GetDocShell(getter_AddRefs(appWinShell));
if (!SameCOMIdentity(appWinShell, item)) {
return nullptr;
}
return xulWin.forget();
return appWin.forget();
}
Document* Document::GetTopLevelContentDocument() {

View File

@ -79,7 +79,6 @@ class ElementCreationOptionsOrString;
class gfxUserFontSet;
class imgIRequest;
class nsBindingManager;
class nsCachableElementsByNameNodeList;
class nsContentList;
class nsIDocShell;
@ -124,7 +123,7 @@ class nsWindowSizes;
class nsDOMCaretPosition;
class nsViewportInfo;
class nsIGlobalObject;
class nsIXULWindow;
class nsIAppWindow;
class nsXULPrototypeDocument;
class nsXULPrototypeElement;
class PermissionDelegateHandler;
@ -162,9 +161,9 @@ class Rule;
namespace dom {
class AnonymousContent;
class Attr;
class BoxObject;
class XULBroadcastManager;
class XULPersist;
class ChromeObserver;
class ClientInfo;
class ClientState;
class CDATASection;
@ -218,7 +217,6 @@ class XPathEvaluator;
class XPathExpression;
class XPathNSResolver;
class XPathResult;
class XULDocument;
template <typename>
class Sequence;
@ -1019,9 +1017,6 @@ class Document : public nsINode,
}
void SetLoadedAsData(bool aLoadedAsData) { mLoadedAsData = aLoadedAsData; }
void SetLoadedAsInteractiveData(bool aLoadedAsInteractiveData) {
mLoadedAsInteractiveData = aLoadedAsInteractiveData;
}
/**
* Normally we assert if a runnable labeled with one DocGroup touches data
@ -1715,10 +1710,6 @@ class Document : public nsINode,
void DoUnblockOnload();
void ClearAllBoxObjects();
void MaybeEndOutermostXBLUpdate();
void RetrieveRelevantHeaders(nsIChannel* aChannel);
void TryChannelCharset(nsIChannel* aChannel, int32_t& aCharsetSource,
@ -2304,10 +2295,6 @@ class Document : public nsINode,
DoUpdateSVGUseElementShadowTrees();
}
nsBindingManager* BindingManager() const {
return mNodeInfoManager->GetBindingManager();
}
/**
* Only to be used inside Gecko, you can't really do anything with the
* pointer outside Gecko anyway.
@ -2372,14 +2359,8 @@ class Document : public nsINode,
bool IsHTMLOrXHTML() const { return mType == eHTML || mType == eXHTML; }
bool IsXMLDocument() const { return !IsHTMLDocument(); }
bool IsSVGDocument() const { return mType == eSVG; }
bool IsXULDocument() const { return mType == eXUL; }
bool IsUnstyledDocument() {
return IsLoadedAsData() || IsLoadedAsInteractiveData();
}
bool IsUnstyledDocument() { return IsLoadedAsData(); }
bool LoadsFullXULStyleSheetUpFront() {
if (IsXULDocument()) {
return true;
}
if (IsSVGDocument()) {
return false;
}
@ -2618,20 +2599,6 @@ class Document : public nsINode,
// Refreshes the hrefs of all the links in the document.
void RefreshLinkHrefs();
/**
* Resets and removes a box object from the document's box object cache
*
* @param aElement canonical nsIContent pointer of the box object's element
*/
void ClearBoxObjectFor(nsIContent* aContent);
/**
* Get the box object for an element. This is not exposed through a
* scriptable interface except for XUL documents.
*/
already_AddRefed<BoxObject> GetBoxObjectFor(Element* aElement,
ErrorResult& aRv);
/**
* Support for window.matchMedia()
*/
@ -2652,10 +2619,6 @@ class Document : public nsINode,
*/
bool HaveFiredDOMTitleChange() const { return mHaveFiredTitleChange; }
Element* GetAnonymousElementByAttribute(nsIContent* aElement,
nsAtom* aAttrName,
const nsAString& aAttrValue) const;
/**
* To batch DOMSubtreeModified, document needs to be informed when
* a mutation event might be dispatched, even if the event isn't actually
@ -2703,8 +2666,6 @@ class Document : public nsINode,
bool IsLoadedAsData() { return mLoadedAsData; }
bool IsLoadedAsInteractiveData() { return mLoadedAsInteractiveData; }
bool MayStartLayout() { return mMayStartLayout; }
void SetMayStartLayout(bool aMayStartLayout);
@ -3447,9 +3408,9 @@ class Document : public nsINode,
Document* GetTopLevelContentDocument();
const Document* GetTopLevelContentDocument() const;
// Returns the associated XUL window if this is a top-level chrome document,
// Returns the associated app window if this is a top-level chrome document,
// null otherwise.
already_AddRefed<nsIXULWindow> GetXULWindowIfToplevelChrome() const;
already_AddRefed<nsIAppWindow> GetAppWindowIfToplevelChrome() const;
already_AddRefed<Element> CreateElement(
const nsAString& aTagName, const ElementCreationOptionsOrString& aOptions,
@ -3640,13 +3601,7 @@ class Document : public nsINode,
bool IsScrollingElement(Element* aElement);
// QuerySelector and QuerySelectorAll already defined on nsINode
nsINodeList* GetAnonymousNodes(Element& aElement);
Element* GetAnonymousElementByAttribute(Element& aElement,
const nsAString& aAttrName,
const nsAString& aAttrValue);
Element* GetBindingParent(nsINode& aNode);
void LoadBindingDocument(const nsAString& aURI,
nsIPrincipal& aSubjectPrincipal, ErrorResult& rv);
XPathExpression* CreateExpression(const nsAString& aExpression,
XPathNSResolver* aResolver,
ErrorResult& rv);
@ -3726,12 +3681,6 @@ class Document : public nsINode,
inline SVGDocument* AsSVGDocument();
inline const SVGDocument* AsSVGDocument() const;
/**
* Asserts IsXULDocument, and can't return null.
* Defined inline in XULDocument.h
*/
inline XULDocument* AsXULDocument();
/*
* Given a node, get a weak reference to it and append that reference to
* mBlockedNodesByClassifier. Can be used later on to look up a node in it.
@ -4487,11 +4436,6 @@ class Document : public nsINode,
// as scripts and plugins, disabled.
bool mLoadedAsData : 1;
// This flag is only set in XMLDocument, for e.g. documents used in XBL. We
// don't want animations to play in such documents, so we need to store the
// flag here so that we can check it in Document::GetAnimationController.
bool mLoadedAsInteractiveData : 1;
// If true, whoever is creating the document has gotten it to the
// point where it's safe to start layout on it.
bool mMayStartLayout : 1;
@ -4668,8 +4612,6 @@ class Document : public nsINode,
bool mScrolledToRefAlready : 1;
bool mChangeScrollPosWhenScrollingToRef : 1;
bool mHasWarnedAboutBoxObjects : 1;
bool mDelayFrameLoaderInitialization : 1;
bool mSynchronousDOMContentLoaded : 1;
@ -4777,8 +4719,7 @@ class Document : public nsINode,
eHTML,
eXHTML,
eGenericXML,
eSVG,
eXUL
eSVG
};
Type mType;
@ -5046,8 +4987,6 @@ class Document : public nsINode,
RefPtr<dom::ScriptLoader> mScriptLoader;
nsRefPtrHashtable<nsPtrHashKey<nsIContent>, BoxObject>* mBoxObjectTable;
// Tracker for animations that are waiting to start.
// nullptr until GetOrCreatePendingAnimationTracker is called.
RefPtr<PendingAnimationTracker> mPendingAnimationTracker;
@ -5100,7 +5039,6 @@ class Document : public nsINode,
RefPtr<EventListenerManager> mListenerManager;
nsCOMPtr<nsIRunnable> mMaybeEndOutermostXBLUpdateRunner;
nsCOMPtr<nsIRequest> mOnloadBlocker;
// Gecko-internal sheets used for extensions and such.
@ -5147,6 +5085,7 @@ class Document : public nsINode,
RefPtr<XULBroadcastManager> mXULBroadcastManager;
RefPtr<XULPersist> mXULPersist;
RefPtr<ChromeObserver> mChromeObserver;
RefPtr<HTMLAllCollection> mAll;
@ -5308,12 +5247,6 @@ nsresult NS_NewDOMDocument(
nsIURI* aDocumentURI, nsIURI* aBaseURI, nsIPrincipal* aPrincipal,
bool aLoadedAsData, nsIGlobalObject* aEventObject, DocumentFlavor aFlavor);
// This is used only for xbl documents created from the startup cache.
// Non-cached documents are created in the same manner as xml documents.
nsresult NS_NewXBLDocument(mozilla::dom::Document** aInstancePtrResult,
nsIURI* aDocumentURI, nsIURI* aBaseURI,
nsIPrincipal* aPrincipal);
nsresult NS_NewPluginDocument(mozilla::dom::Document** aInstancePtrResult);
inline mozilla::dom::Document* nsINode::GetOwnerDocument() const {

View File

@ -46,7 +46,6 @@
#include "nsContentList.h"
#include "nsVariant.h"
#include "nsDOMTokenList.h"
#include "nsXBLPrototypeBinding.h"
#include "nsError.h"
#include "nsDOMString.h"
#include "mozilla/dom/AnimatableBinding.h"
@ -93,10 +92,7 @@
# include "nsRange.h"
#endif
#include "nsBindingManager.h"
#include "nsXBLBinding.h"
#include "nsPIDOMWindow.h"
#include "nsPIBoxObject.h"
#include "mozilla/dom/DOMRect.h"
#include "nsLayoutUtils.h"
#include "nsGkAtoms.h"
@ -128,7 +124,6 @@
#include "mozilla/dom/NodeListBinding.h"
#include "nsStyledElement.h"
#include "nsXBLService.h"
#include "nsITextControlFrame.h"
#include "nsISupportsImpl.h"
#include "mozilla/dom/CSSPseudoElement.h"
@ -166,6 +161,10 @@
#include "DOMMatrix.h"
#if defined(ACCESSIBILITY) && defined(DEBUG)
# include "nsAccessibilityService.h"
#endif
using mozilla::gfx::Matrix4x4;
namespace mozilla {
@ -255,9 +254,7 @@ Element::QueryInterface(REFNSIID aIID, void** aInstancePtr) {
return NS_OK;
}
// Give the binding manager a chance to get an interface for this element.
return OwnerDoc()->BindingManager()->GetBindingImplementation(this, aIID,
aInstancePtr);
return NS_NOINTERFACE;
}
EventStates Element::IntrinsicState() const {
@ -387,46 +384,6 @@ void Element::SetTabIndex(int32_t aTabIndex, mozilla::ErrorResult& aError) {
SetAttr(nsGkAtoms::tabindex, value, aError);
}
void Element::SetXBLBinding(nsXBLBinding* aBinding,
nsBindingManager* aOldBindingManager) {
nsBindingManager* bindingManager;
if (aOldBindingManager) {
MOZ_ASSERT(!aBinding,
"aOldBindingManager should only be provided "
"when removing a binding.");
bindingManager = aOldBindingManager;
} else {
bindingManager = OwnerDoc()->BindingManager();
}
// After this point, aBinding will be the most-derived binding for aContent.
// If we already have a binding for aContent, make sure to
// remove it from the attached stack. Otherwise we might end up firing its
// constructor twice (if aBinding inherits from it) or firing its constructor
// after aContent has been deleted (if aBinding is null and the content node
// dies before we process mAttachedStack).
RefPtr<nsXBLBinding> oldBinding = GetXBLBinding();
if (oldBinding) {
bindingManager->RemoveFromAttachedQueue(oldBinding);
}
if (aBinding) {
SetFlags(NODE_MAY_BE_IN_BINDING_MNGR);
nsExtendedDOMSlots* slots = ExtendedDOMSlots();
slots->mXBLBinding = aBinding;
bindingManager->AddBoundContent(this);
} else {
nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots) {
slots->mXBLBinding = nullptr;
}
bindingManager->RemoveBoundContent(this);
if (oldBinding) {
oldBinding->SetBoundElement(nullptr);
}
}
}
void Element::SetShadowRoot(ShadowRoot* aShadowRoot) {
nsExtendedDOMSlots* slots = ExtendedDOMSlots();
slots->mShadowRoot = aShadowRoot;
@ -443,7 +400,7 @@ void Element::Blur(mozilla::ErrorResult& aError) {
}
nsPIDOMWindowOuter* win = doc->GetWindow();
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (win && fm) {
aError = fm->ClearFocus(win);
}
@ -535,121 +492,6 @@ void Element::ClearStyleStateLocks() {
NotifyStyleStateChange(locks.mLocks);
}
static bool IsLikelyCustomElement(const nsXULElement& aElement) {
const CustomElementData* data = aElement.GetCustomElementData();
if (!data) {
return false;
}
const CustomElementRegistry* registry =
nsContentUtils::GetCustomElementRegistry(aElement.OwnerDoc());
if (!registry) {
return false;
}
return registry->IsLikelyToBeCustomElement(data->GetCustomElementType());
}
static bool MayNeedToLoadXBLBinding(const Document& aDocument,
const Element& aElement) {
// If we have a frame, the frame has already loaded the binding.
// Otherwise, don't do anything else here unless we're dealing with
// XUL or an HTML element that may have a plugin-related overlay
// (i.e. object or embed).
if (!aDocument.GetPresShell() || aElement.GetPrimaryFrame()) {
return false;
}
if (auto* xulElem = nsXULElement::FromNode(aElement)) {
return !IsLikelyCustomElement(*xulElem);
}
return aElement.IsAnyOfHTMLElements(nsGkAtoms::object, nsGkAtoms::embed);
}
StyleUrlOrNone Element::GetBindingURL(Document* aDocument) {
if (!MayNeedToLoadXBLBinding(*aDocument, *this)) {
return StyleUrlOrNone::None();
}
// Get the computed -moz-binding directly from the ComputedStyle
RefPtr<ComputedStyle> style =
nsComputedDOMStyle::GetComputedStyleNoFlush(this, nullptr);
if (!style) {
return StyleUrlOrNone::None();
}
return style->StyleDisplay()->mBinding;
}
JSObject* Element::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) {
JS::Rooted<JSObject*> obj(aCx, nsINode::WrapObject(aCx, aGivenProto));
if (!obj) {
return nullptr;
}
if (XRE_IsContentProcess() && !NodePrincipal()->IsSystemPrincipal()) {
// We don't use XBL in content privileged content processes.
return obj;
}
Document* doc = GetComposedDoc();
if (!doc) {
// There's no baseclass that cares about this call so we just
// return here.
return obj;
}
// We must ensure that the XBL Binding is installed before we hand
// back this object.
if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR) && GetXBLBinding()) {
// There's already a binding for this element so nothing left to
// be done here.
// In theory we could call ExecuteAttachedHandler here when it's safe to
// run script if we also removed the binding from the PAQ queue, but that
// seems like a scary change that would mosly just add more
// inconsistencies.
return obj;
}
// Make sure the ComputedStyle goes away _before_ we load the binding
// since that can destroy the relevant presshell.
{
StyleUrlOrNone result = GetBindingURL(doc);
if (result.IsUrl()) {
auto& url = result.AsUrl();
nsCOMPtr<nsIURI> uri = url.GetURI();
nsCOMPtr<nsIPrincipal> principal = url.ExtraData().Principal();
// We have a binding that must be installed.
nsXBLService* xblService = nsXBLService::GetInstance();
if (!xblService) {
dom::Throw(aCx, NS_ERROR_NOT_AVAILABLE);
return nullptr;
}
RefPtr<nsXBLBinding> binding;
xblService->LoadBindings(this, uri, principal, getter_AddRefs(binding));
if (binding) {
if (nsContentUtils::IsSafeToRunScript()) {
binding->ExecuteAttachedHandler();
} else {
nsContentUtils::AddScriptRunner(
NewRunnableMethod("nsXBLBinding::ExecuteAttachedHandler", binding,
&nsXBLBinding::ExecuteAttachedHandler));
}
}
}
}
return obj;
}
/* virtual */
nsINode* Element::GetScopeChainParent() const { return OwnerDoc(); }
@ -1165,7 +1007,7 @@ bool Element::CanAttachShadowDOM() const {
* XUL elements.
*/
if (!IsHTMLElement() &&
!(XRE_IsParentProcess() && IsXULElement() &&
!(IsXULElement() &&
nsContentUtils::AllowXULXBLForPrincipal(NodePrincipal()))) {
return false;
}
@ -1238,7 +1080,7 @@ already_AddRefed<ShadowRoot> Element::AttachShadow(const ShadowRootInit& aInit,
* 4. If context object is a shadow host, then throw
* an "NotSupportedError" DOMException.
*/
if (GetShadowRoot() || GetXBLBinding()) {
if (GetShadowRoot()) {
aError.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return nullptr;
}
@ -1259,12 +1101,19 @@ already_AddRefed<ShadowRoot> Element::AttachShadowWithoutNameChecks(
nsGkAtoms::documentFragmentNodeName, nullptr, kNameSpaceID_None,
DOCUMENT_FRAGMENT_NODE);
if (Document* doc = GetComposedDoc()) {
if (PresShell* presShell = doc->GetPresShell()) {
presShell->DestroyFramesForAndRestyle(this);
// If there are no children, the flat tree is not changing due to the presence
// of the shadow root, so we don't need to invalidate style / layout.
//
// This is a minor optimization, but also works around nasty stuff like
// bug 1397876.
if (HasChildren()) {
if (Document* doc = GetComposedDoc()) {
if (PresShell* presShell = doc->GetPresShell()) {
presShell->DestroyFramesForAndRestyle(this);
}
}
MOZ_ASSERT(!GetPrimaryFrame());
}
MOZ_ASSERT(!GetPrimaryFrame());
/**
* 4. Let shadow be a new shadow root whose node document is
@ -1655,50 +1504,16 @@ nsresult Element::BindToTree(BindContext& aContext, nsINode& aParent) {
// only assert if our parent is _changing_ while we have a parent.
MOZ_ASSERT(!GetParentNode() || &aParent == GetParentNode(),
"Already have a parent. Unbind first!");
MOZ_ASSERT(
!GetBindingParent() ||
aContext.GetBindingParent() == GetBindingParent() ||
(!aContext.GetBindingParent() && aParent.IsContent() &&
aParent.AsContent()->GetBindingParent() == GetBindingParent()),
"Already have a binding parent. Unbind first!");
MOZ_ASSERT(aContext.GetBindingParent() != this,
"Content must not be its own binding parent");
MOZ_ASSERT(!IsRootOfNativeAnonymousSubtree() ||
aContext.GetBindingParent() == &aParent,
"Native anonymous content must have its parent as its "
"own binding parent");
MOZ_ASSERT(aContext.GetBindingParent() || !aParent.IsContent() ||
aContext.GetBindingParent() ==
aParent.AsContent()->GetBindingParent(),
"We should be passed the right binding parent");
#ifdef MOZ_XUL
// First set the binding parent
if (nsXULElement* xulElem = nsXULElement::FromNode(this)) {
xulElem->SetXULBindingParent(aContext.GetBindingParent());
} else
#endif
{
if (Element* bindingParent = aContext.GetBindingParent()) {
ExtendedDOMSlots()->mBindingParent = bindingParent;
}
}
const bool hadParent = !!GetParentNode();
NS_ASSERTION(!aContext.GetBindingParent() ||
IsRootOfNativeAnonymousSubtree() ||
!HasFlag(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE) ||
aParent.IsInNativeAnonymousSubtree(),
"Trying to re-bind content from native anonymous subtree to "
"non-native anonymous parent!");
if (aParent.IsInNativeAnonymousSubtree()) {
SetFlags(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE);
}
if (aParent.HasFlag(NODE_HAS_BEEN_IN_UA_WIDGET)) {
SetFlags(NODE_HAS_BEEN_IN_UA_WIDGET);
}
if (HasFlag(NODE_IS_ANONYMOUS_ROOT)) {
if (IsRootOfNativeAnonymousSubtree()) {
aParent.SetMayHaveAnonymousChildren();
}
@ -1758,17 +1573,6 @@ nsresult Element::BindToTree(BindContext& aContext, nsINode& aParent) {
UpdateEditableState(false);
// If we had a pre-existing XBL binding, we might have anonymous children that
// also need to be told that they are moving.
if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
nsXBLBinding* binding =
aContext.OwnerDoc().BindingManager()->GetBindingWithContent(this);
if (binding) {
binding->BindAnonymousContent(binding->GetAnonymousContent(), this);
}
}
// Call BindToTree on shadow root children.
nsresult rv;
if (ShadowRoot* shadowRoot = GetShadowRoot()) {
@ -1839,8 +1643,6 @@ nsresult Element::BindToTree(BindContext& aContext, nsINode& aParent) {
MOZ_ASSERT(IsInComposedDoc() == aContext.InComposedDoc());
MOZ_ASSERT(IsInUncomposedDoc() == aContext.InUncomposedDoc());
MOZ_ASSERT(&aParent == GetParentNode(), "Bound to wrong parent node");
MOZ_ASSERT(aContext.GetBindingParent() == GetBindingParent(),
"Bound to wrong binding parent");
MOZ_ASSERT(aParent.IsInUncomposedDoc() == IsInUncomposedDoc());
MOZ_ASSERT(aParent.IsInComposedDoc() == IsInComposedDoc());
MOZ_ASSERT(aParent.IsInShadowTree() == IsInShadowTree());
@ -1848,32 +1650,6 @@ nsresult Element::BindToTree(BindContext& aContext, nsINode& aParent) {
return NS_OK;
}
RemoveFromBindingManagerRunnable::RemoveFromBindingManagerRunnable(
nsBindingManager* aManager, nsIContent* aContent, Document* aDoc)
: mozilla::Runnable("dom::RemoveFromBindingManagerRunnable"),
mManager(aManager),
mContent(aContent),
mDoc(aDoc) {}
RemoveFromBindingManagerRunnable::~RemoveFromBindingManagerRunnable() {}
NS_IMETHODIMP
RemoveFromBindingManagerRunnable::Run() {
// It may be the case that the element was removed from the
// DOM, causing this runnable to be created, then inserted back
// into the document before the this runnable had a chance to
// tear down the binding. Only tear down the binding if the element
// is still no longer in the DOM. nsXBLService::LoadBinding tears
// down the old binding if the element is inserted back into the
// DOM and loads a different binding.
if (!mContent->IsInComposedDoc()) {
mManager->RemovedFromDocumentInternal(mContent, mDoc,
nsBindingManager::eRunDtor);
}
return NS_OK;
}
bool WillDetachFromShadowOnUnbind(const Element& aElement, bool aNullParent) {
// If our parent still is in a shadow tree by now, and we're not removing
// ourselves from it, then we're still going to be in a shadow tree after
@ -1950,6 +1726,11 @@ void Element::UnbindFromTree(bool aNullParent) {
"propagated scrollbar styles) - that's dangerous...");
}
}
# ifdef ACCESSIBILITY
MOZ_ASSERT(!GetAccService() || !GetAccService()->HasAccessible(this),
"An accessible for this element still exists!");
# endif
#endif
// Ensure that CSS transitions don't continue on an element at a
@ -1997,41 +1778,13 @@ void Element::UnbindFromTree(bool aNullParent) {
SetSubtreeRootPointer(aNullParent ? this : mParent->SubtreeRoot());
}
bool clearBindingParent = true;
#ifdef MOZ_XUL
if (nsXULElement* xulElem = nsXULElement::FromNode(this)) {
xulElem->SetXULBindingParent(nullptr);
clearBindingParent = false;
}
#endif
if (nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots()) {
if (clearBindingParent) {
slots->mBindingParent = nullptr;
}
if (aNullParent || !mParent->IsInShadowTree()) {
slots->mContainingShadow = nullptr;
}
}
if (document) {
if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
// Notify XBL- & nsIAnonymousContentCreator-generated anonymous content
// that the document is changing.
nsContentUtils::AddScriptRunner(new RemoveFromBindingManagerRunnable(
document->BindingManager(), this, document));
nsXBLBinding* binding =
document->BindingManager()->GetBindingWithContent(this);
if (binding) {
nsXBLBinding::UnbindAnonymousContent(document,
binding->GetAnonymousContent(),
/* aNullParent */ false);
}
}
document->ClearBoxObjectFor(this);
// Disconnected must be enqueued whenever a connected custom element becomes
// disconnected.
CustomElementData* data = GetCustomElementData();
@ -2553,13 +2306,6 @@ nsresult Element::SetAttrAndNotify(
oldValue = aOldValue;
}
if (aComposedDocument) {
RefPtr<nsXBLBinding> binding = GetXBLBinding();
if (binding) {
binding->AttributeChanged(aName, aNamespaceID, false, aNotify);
}
}
if (HasElementCreatedFromPrototypeAndHasUnmodifiedL10n() &&
aNamespaceID == kNameSpaceID_None &&
(aName == nsGkAtoms::datal10nid || aName == nsGkAtoms::datal10nargs)) {
@ -2874,13 +2620,6 @@ nsresult Element::UnsetAttr(int32_t aNameSpaceID, nsAtom* aName, bool aNotify) {
PostIdMaybeChange(aNameSpaceID, aName, nullptr);
if (document) {
RefPtr<nsXBLBinding> binding = GetXBLBinding();
if (binding) {
binding->AttributeChanged(aName, aNameSpaceID, true, aNotify);
}
}
const CustomElementData* data = GetCustomElementData();
if (data && data->mState == CustomElementData::State::eCustom) {
CustomElementDefinition* definition = data->GetCustomElementDefinition();
@ -3004,51 +2743,6 @@ void Element::List(FILE* out, int32_t aIndent, const nsCString& aPrefix) const {
}
fputs(">\n", out);
Element* nonConstThis = const_cast<Element*>(this);
// XXX sXBL/XBL2 issue! Owner or current document?
Document* document = OwnerDoc();
// Note: not listing nsIAnonymousContentCreator-created content...
nsBindingManager* bindingManager = document->BindingManager();
nsINodeList* anonymousChildren =
bindingManager->GetAnonymousNodesFor(nonConstThis);
if (anonymousChildren) {
uint32_t length = anonymousChildren->Length();
for (indent = aIndent; --indent >= 0;) fputs(" ", out);
fputs("anonymous-children<\n", out);
for (uint32_t i = 0; i < length; ++i) {
nsIContent* child = anonymousChildren->Item(i);
child->List(out, aIndent + 1);
}
for (indent = aIndent; --indent >= 0;) fputs(" ", out);
fputs(">\n", out);
bool outHeader = false;
ExplicitChildIterator iter(nonConstThis);
for (nsIContent* child = iter.GetNextChild(); child;
child = iter.GetNextChild()) {
if (!outHeader) {
outHeader = true;
for (indent = aIndent; --indent >= 0;) fputs(" ", out);
fputs("content-list<\n", out);
}
child->List(out, aIndent + 1);
}
if (outHeader) {
for (indent = aIndent; --indent >= 0;) fputs(" ", out);
fputs(">\n", out);
}
}
}
void Element::DumpContent(FILE* out, int32_t aIndent, bool aDumpAll) const {
@ -3192,7 +2886,7 @@ nsresult Element::PostHandleEventForLinks(EventChainPostVisitor& aVisitor) {
aVisitor.mEvent->mFlags.mMultipleActionsPrevented = true;
if (IsInComposedDoc()) {
if (nsIFocusManager* fm = nsFocusManager::GetFocusManager()) {
if (nsFocusManager* fm = nsFocusManager::GetFocusManager()) {
RefPtr<Element> kungFuDeathGrip(this);
fm->SetFocus(kungFuDeathGrip, nsIFocusManager::FLAG_BYMOUSE |
nsIFocusManager::FLAG_NOSCROLL);
@ -4099,11 +3793,6 @@ void Element::GetCustomInterface(nsGetterAddRefs<T> aResult) {
return;
}
}
// Otherwise, check the binding manager to see if it implements the interface
// for this element.
OwnerDoc()->BindingManager()->GetBindingImplementation(
this, NS_GET_TEMPLATE_IID(T), aResult);
}
void Element::ClearServoData(Document* aDoc) {

View File

@ -222,22 +222,6 @@ class Element : public FragmentOrElement {
*/
void SetTabIndex(int32_t aTabIndex, mozilla::ErrorResult& aError);
/**
* Sets or unsets an XBL binding for this element. Setting a
* binding on an element that already has a binding will remove the
* old binding.
*
* @param aBinding The binding to bind to this content. If nullptr is
* provided as the argument, then existing binding will be
* removed.
*
* @param aOldBindingManager The old binding manager that contains
* this content if this content was adopted
* to another document.
*/
void SetXBLBinding(nsXBLBinding* aBinding,
nsBindingManager* aOldBindingManager = nullptr);
/**
* Sets the ShadowRoot binding for this element. The contents of the
* binding is rendered in place of this node's children.
@ -456,8 +440,6 @@ class Element : public FragmentOrElement {
}
}
mozilla::StyleUrlOrNone GetBindingURL(Document* aDocument);
Directionality GetComputedDirectionality() const;
static const uint32_t kAllServoDescendantBits =
@ -1444,8 +1426,6 @@ class Element : public FragmentOrElement {
*/
static CORSMode AttrValueToCORSMode(const nsAttrValue* aValue);
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) final;
nsINode* GetScopeChainParent() const override;
/**
@ -1914,20 +1894,6 @@ class Element : public FragmentOrElement {
AttrArray mAttrs;
};
class RemoveFromBindingManagerRunnable : public mozilla::Runnable {
public:
RemoveFromBindingManagerRunnable(nsBindingManager* aManager,
nsIContent* aContent, Document* aDoc);
NS_IMETHOD Run() override;
private:
virtual ~RemoveFromBindingManagerRunnable();
RefPtr<nsBindingManager> mManager;
RefPtr<nsIContent> mContent;
RefPtr<Document> mDoc;
};
NS_DEFINE_STATIC_IID_ACCESSOR(Element, NS_ELEMENT_IID)
inline bool Element::HasAttr(int32_t aNameSpaceID, const nsAtom* aName) const {

View File

@ -49,7 +49,6 @@
#include "nsNameSpaceManager.h"
#include "nsContentList.h"
#include "nsDOMTokenList.h"
#include "nsXBLPrototypeBinding.h"
#include "nsError.h"
#include "nsDOMString.h"
#include "mozilla/InternalMutationEvent.h"
@ -64,11 +63,8 @@
# include "nsRange.h"
#endif
#include "nsBindingManager.h"
#include "nsFrameLoader.h"
#include "nsXBLBinding.h"
#include "nsPIDOMWindow.h"
#include "nsPIBoxObject.h"
#include "nsLayoutUtils.h"
#include "nsGkAtoms.h"
#include "nsContentUtils.h"
@ -154,11 +150,10 @@ NS_IMPL_MAIN_THREAD_ONLY_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE_AND_DESTROY(
nsIContent* nsIContent::FindFirstNonChromeOnlyAccessContent() const {
// This handles also nested native anonymous content.
for (const nsIContent* content = this; content;
content = content->GetBindingParent()) {
content = content->GetChromeOnlyAccessSubtreeRootParent()) {
if (!content->ChromeOnlyAccess()) {
// Oops, this function signature allows casting const to
// non-const. (Then again, so does
// GetChildAt_Deprecated(0)->GetParent().)
// non-const. (Then again, so does GetFirstChild()->GetParent().)
return const_cast<nsIContent*>(content);
}
}
@ -522,28 +517,20 @@ static_assert(sizeof(FragmentOrElement::nsDOMSlots) <= MaxDOMSlotSizeAllowed,
"DOM slots cannot be grown without consideration");
void nsIContent::nsExtendedContentSlots::UnlinkExtendedSlots() {
mBindingParent = nullptr;
mXBLInsertionPoint = nullptr;
mContainingShadow = nullptr;
mAssignedSlot = nullptr;
}
void nsIContent::nsExtendedContentSlots::TraverseExtendedSlots(
nsCycleCollectionTraversalCallback& aCb) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mExtendedSlots->mBindingParent");
aCb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mBindingParent));
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mExtendedSlots->mContainingShadow");
aCb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mContainingShadow));
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mExtendedSlots->mAssignedSlot");
aCb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mAssignedSlot.get()));
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mExtendedSlots->mXBLInsertionPoint");
aCb.NoteXPCOMChild(mXBLInsertionPoint.get());
}
nsIContent::nsExtendedContentSlots::nsExtendedContentSlots() {}
nsIContent::nsExtendedContentSlots::nsExtendedContentSlots() = default;
nsIContent::nsExtendedContentSlots::~nsExtendedContentSlots() = default;
@ -629,13 +616,12 @@ size_t FragmentOrElement::nsDOMSlots::SizeOfIncludingThis(
// The following member are not measured:
// - mControllers: because it is non-owning
// - mBindingParent: because it is some ancestor element.
return n;
}
FragmentOrElement::nsExtendedDOMSlots::nsExtendedDOMSlots() = default;
FragmentOrElement::nsExtendedDOMSlots::~nsExtendedDOMSlots() {}
FragmentOrElement::nsExtendedDOMSlots::~nsExtendedDOMSlots() = default;
void FragmentOrElement::nsExtendedDOMSlots::UnlinkExtendedSlots() {
nsIContent::nsExtendedContentSlots::UnlinkExtendedSlots();
@ -670,10 +656,6 @@ void FragmentOrElement::nsExtendedDOMSlots::TraverseExtendedSlots(
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mExtendedSlots->mShadowRoot");
aCb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mShadowRoot));
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mExtendedSlots->mXBLBinding");
aCb.NoteNativeChild(mXBLBinding,
NS_CYCLE_COLLECTION_PARTICIPANT(nsXBLBinding));
if (mCustomElementData) {
mCustomElementData->Traverse(aCb);
}
@ -707,12 +689,6 @@ size_t FragmentOrElement::nsExtendedDOMSlots::SizeOfExcludingThis(
// mShadowRoot should be handled during normal DOM tree memory reporting, just
// like kids, siblings, etc.
// We don't seem to have memory reporting for nsXBLBinding. At least
// report the memory it's using directly.
if (mXBLBinding) {
n += aMallocSizeOf(mXBLBinding);
}
if (mCustomElementData) {
n += mCustomElementData->SizeOfIncludingThis(aMallocSizeOf);
}
@ -878,23 +854,12 @@ void nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor) {
aVisitor.mEventTargetAtParent = parent;
} else if (parent && aVisitor.mOriginalTargetIsInAnon) {
nsCOMPtr<nsIContent> content(do_QueryInterface(aVisitor.mEvent->mTarget));
if (content && content->GetBindingParent() == parent) {
if (content &&
content->GetClosestNativeAnonymousSubtreeRootParent() == parent) {
aVisitor.mEventTargetAtParent = parent;
}
}
// check for an anonymous parent
// XXX XBL2/sXBL issue
if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
nsIContent* insertionParent = GetXBLInsertionParent();
NS_ASSERTION(!(aVisitor.mEventTargetAtParent && insertionParent &&
aVisitor.mEventTargetAtParent != insertionParent),
"Retargeting and having insertion parent!");
if (insertionParent) {
parent = insertionParent;
}
}
if (!aVisitor.mEvent->mFlags.mComposedInNativeAnonymousContent &&
IsRootOfNativeAnonymousSubtree() && OwnerDoc()->GetWindow()) {
aVisitor.SetParentTarget(OwnerDoc()->GetWindow()->GetParentTarget(), true);
@ -1067,58 +1032,11 @@ bool FragmentOrElement::IsLink(nsIURI** aURI) const {
return false;
}
nsXBLBinding* FragmentOrElement::DoGetXBLBinding() const {
MOZ_ASSERT(HasFlag(NODE_MAY_BE_IN_BINDING_MNGR));
const nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
return slots ? slots->mXBLBinding.get() : nullptr;
}
nsIContent* nsIContent::GetContainingShadowHost() const {
if (mozilla::dom::ShadowRoot* shadow = GetContainingShadow()) {
return shadow->GetHost();
}
return nullptr;
}
void nsIContent::SetAssignedSlot(HTMLSlotElement* aSlot) {
MOZ_ASSERT(aSlot || GetExistingExtendedContentSlots());
ExtendedContentSlots()->mAssignedSlot = aSlot;
}
void nsIContent::SetXBLInsertionPoint(nsIContent* aContent) {
if (aContent) {
nsExtendedContentSlots* slots = ExtendedContentSlots();
SetFlags(NODE_MAY_BE_IN_BINDING_MNGR);
slots->mXBLInsertionPoint = aContent;
} else {
if (nsExtendedContentSlots* slots = GetExistingExtendedContentSlots()) {
slots->mXBLInsertionPoint = nullptr;
}
}
}
#ifdef DEBUG
void nsIContent::AssertAnonymousSubtreeRelatedInvariants() const {
MOZ_ASSERT(!IsRootOfNativeAnonymousSubtree() ||
(GetParent() && GetBindingParent() == GetParent()),
"root of native anonymous subtree must have parent equal "
"to binding parent");
MOZ_ASSERT(!GetParent() || !IsInComposedDoc() ||
((GetBindingParent() == GetParent()) ==
HasFlag(NODE_IS_ANONYMOUS_ROOT)) ||
// Unfortunately default content for XBL insertion points
// is anonymous content that is bound with the parent of
// the insertion point as the parent but the bound element
// for the binding as the binding parent. So we have to
// complicate the assert a bit here.
(GetBindingParent() &&
(GetBindingParent() == GetParent()->GetBindingParent()) ==
HasFlag(NODE_IS_ANONYMOUS_ROOT)),
"For connected nodes, flag and GetBindingParent() check "
"should match");
}
#endif
void FragmentOrElement::GetTextContentInternal(nsAString& aTextContent,
OOMReporter& aError) {
if (!nsContentUtils::GetNodeTextContent(this, true, aTextContent, fallible)) {
@ -1143,12 +1061,6 @@ void FragmentOrElement::DestroyContent() {
AsElement()->ClearServoData();
}
Document* document = OwnerDoc();
document->BindingManager()->RemovedFromDocument(this, document,
nsBindingManager::eRunDtor);
document->ClearBoxObjectFor(this);
#ifdef DEBUG
uint32_t oldChildCount = GetChildCount();
#endif
@ -1354,9 +1266,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(FragmentOrElement)
tmp->ExtendedDOMSlots()->mShadowRoot = nullptr;
}
Document* doc = tmp->OwnerDoc();
doc->BindingManager()->RemovedFromDocument(tmp, doc,
nsBindingManager::eDoNotRunDtor);
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(FragmentOrElement)
@ -1581,10 +1490,6 @@ bool NodeHasActiveFrame(Document* aCurrentDoc, nsINode* aNode) {
aNode->AsElement()->GetPrimaryFrame();
}
bool OwnedByBindingManager(Document* aCurrentDoc, nsINode* aNode) {
return aNode->IsElement() && aNode->AsElement()->GetXBLBinding();
}
// CanSkip checks if aNode is known-live, and if it is, returns true. If aNode
// is in a known-live DOM tree, CanSkip may also remove other objects from
// purple buffer and unmark event listeners and user data. If the root of the
@ -1600,8 +1505,7 @@ bool FragmentOrElement::CanSkip(nsINode* aNode, bool aRemovingAllowed) {
bool unoptimizable = aNode->UnoptimizableCCNode();
Document* currentDoc = aNode->GetComposedDoc();
if (currentDoc && IsCertainlyAliveNode(aNode, currentDoc) &&
(!unoptimizable || NodeHasActiveFrame(currentDoc, aNode) ||
OwnedByBindingManager(currentDoc, aNode))) {
(!unoptimizable || NodeHasActiveFrame(currentDoc, aNode))) {
MarkNodeChildren(aNode);
return true;
}
@ -1779,10 +1683,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(FragmentOrElement)
}
nsAutoCString orphan;
if (!tmp->IsInComposedDoc() &&
// Ignore xbl:content, which is never in the document and hence always
// appears to be orphaned.
!tmp->NodeInfo()->Equals(nsGkAtoms::content, kNameSpaceID_XBL)) {
if (!tmp->IsInComposedDoc()) {
orphan.AppendLiteral(" (orphan)");
}
@ -1800,8 +1701,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(FragmentOrElement)
return NS_SUCCESS_INTERRUPTED_TRAVERSE;
}
tmp->OwnerDoc()->BindingManager()->Traverse(tmp, cb);
// Check that whenever we have effect properties, MayHaveAnimations is set.
#ifdef DEBUG
nsAtom** effectProps = EffectSet::GetEffectSetPropertyAtoms();

View File

@ -18,7 +18,6 @@
#include "nsIContent.h" // base class
#include "nsIHTMLCollection.h"
#include "nsDataHashtable.h"
#include "nsXBLBinding.h"
class ContentUnbinder;
class nsContentList;
@ -97,7 +96,6 @@ class FragmentOrElement : public nsIContent {
virtual uint32_t TextLength() const override;
virtual bool TextIsOnlyWhitespace() override;
virtual bool ThreadSafeTextIsOnlyWhitespace() const override;
virtual nsXBLBinding* DoGetXBLBinding() const override;
virtual bool IsLink(nsIURI** aURI) const override;
virtual void DestroyContent() override;
@ -185,11 +183,6 @@ class FragmentOrElement : public nsIContent {
*/
RefPtr<ShadowRoot> mShadowRoot;
/**
* XBL binding installed on the element.
*/
RefPtr<nsXBLBinding> mXBLBinding;
/**
* Web components custom element data.
*/

View File

@ -88,7 +88,7 @@ class FullscreenRequest : public FullscreenChange {
dom::CallerType::NonSystem, false));
}
~FullscreenRequest() { MOZ_COUNT_DTOR(FullscreenRequest); }
MOZ_COUNTED_DTOR(FullscreenRequest)
dom::Element* Element() const { return mElement; }

View File

@ -8,9 +8,7 @@
#include "nsContentUtils.h"
#include "nsIURI.h"
#include "nsIReferrerInfo.h"
#include "nsBindingManager.h"
#include "nsEscape.h"
#include "nsXBLPrototypeBinding.h"
#include "nsCycleCollectionParticipant.h"
namespace mozilla {
@ -57,52 +55,19 @@ void IDTracker::ResetToURIFragmentID(nsIContent* aFromContent, nsIURI* aURI,
if (NS_FAILED(rv) || ref.IsEmpty()) {
return;
}
rv = NS_OK;
nsIContent* bindingParent = aFromContent->GetBindingParent();
if (bindingParent && !aFromContent->IsInShadowTree()) {
nsXBLBinding* binding = bindingParent->GetXBLBinding();
if (!binding) {
// This happens, for example, if aFromContent is part of the content
// inserted by a call to Document::InsertAnonymousContent, which we
// also want to handle. (It also happens for <use>'s anonymous
// content etc.)
Element* anonRoot =
doc->GetAnonRootIfInAnonymousContentContainer(aFromContent);
if (anonRoot) {
mElement = nsContentUtils::MatchElementId(anonRoot, ref);
// We don't have watching working yet for anonymous content, so bail out
// here.
return;
}
} else {
bool isEqualExceptRef;
rv = aURI->EqualsExceptRef(binding->PrototypeBinding()->DocURI(),
&isEqualExceptRef);
if (NS_SUCCEEDED(rv) && isEqualExceptRef) {
// XXX sXBL/XBL2 issue
// Our content is an anonymous XBL element from a binding inside the
// same document that the referenced URI points to. In order to avoid
// the risk of ID collisions we restrict ourselves to anonymous
// elements from this binding; specifically, URIs that are relative to
// the binding document should resolve to the copy of the target
// element that has been inserted into the bound document.
// If the URI points to a different document we don't need this
// restriction.
nsINodeList* anonymousChildren =
doc->BindingManager()->GetAnonymousNodesFor(bindingParent);
if (anonymousChildren) {
uint32_t length = anonymousChildren->Length();
for (uint32_t i = 0; i < length && !mElement; ++i) {
mElement =
nsContentUtils::MatchElementId(anonymousChildren->Item(i), ref);
}
}
// We don't have watching working yet for XBL, so bail out here.
return;
}
if (aFromContent->IsInNativeAnonymousSubtree()) {
// This happens, for example, if aFromContent is part of the content
// inserted by a call to Document::InsertAnonymousContent, which we
// also want to handle. (It also happens for other native anonymous content
// etc.)
Element* anonRoot =
doc->GetAnonRootIfInAnonymousContentContainer(aFromContent);
if (anonRoot) {
mElement = nsContentUtils::MatchElementId(anonRoot, ref);
// We don't have watching working yet for anonymous content, so bail out
// here.
return;
}
}

View File

@ -43,7 +43,7 @@ Location::Location(nsPIDOMWindowInner* aWindow, nsIDocShell* aDocShell)
mDocShell = do_GetWeakReference(aDocShell);
}
Location::~Location() {}
Location::~Location() = default;
// QueryInterface implementation for Location
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Location)

View File

@ -20,7 +20,6 @@
#ifdef MOZ_XUL
# include "nsXULElement.h"
#endif
#include "nsBindingManager.h"
#include "nsGenericHTMLElement.h"
#include "mozilla/AnimationTarget.h"
#include "mozilla/Assertions.h"
@ -51,6 +50,10 @@ enum class IsRemoveNotification {
# define COMPOSED_DOC_DECL
#endif
#define CALL_BINDING_MANAGER(func_, params_) \
do { \
} while (0)
// This macro expects the ownerDocument of content_ to be in scope as
// |Document* doc|
#define IMPL_MUTATION_NOTIFICATION(func_, content_, params_, remove_) \
@ -67,7 +70,7 @@ enum class IsRemoveNotification {
presShell->func_ params_; \
} \
} \
doc->BindingManager()->func_ params_; \
CALL_BINDING_MANAGER(func_, params_); \
nsINode* last; \
do { \
nsINode::nsSlots* slots = node->GetExistingSlots(); \

View File

@ -19,13 +19,12 @@ static const int32_t kNameSpaceID_None = 0;
#define kNameSpaceID_XHTML 3
#define kNameSpaceID_XLink 4
#define kNameSpaceID_XSLT 5
#define kNameSpaceID_XBL 6
#define kNameSpaceID_MathML 7
#define kNameSpaceID_RDF 8
#define kNameSpaceID_XUL 9
#define kNameSpaceID_SVG 10
#define kNameSpaceID_disabled_MathML 11
#define kNameSpaceID_disabled_SVG 12
#define kNameSpaceID_LastBuiltin 12 // last 'built-in' namespace
#define kNameSpaceID_MathML 6
#define kNameSpaceID_RDF 7
#define kNameSpaceID_XUL 8
#define kNameSpaceID_SVG 9
#define kNameSpaceID_disabled_MathML 10
#define kNameSpaceID_disabled_SVG 11
#define kNameSpaceID_LastBuiltin 11 // last 'built-in' namespace
#endif // mozilla_dom_NameSpaceConstants_h__

View File

@ -0,0 +1,55 @@
/* 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 mozilla_dom_PlacesBookmarkRemoved_h
#define mozilla_dom_PlacesBookmarkRemoved_h
#include "mozilla/dom/PlacesBookmark.h"
namespace mozilla {
namespace dom {
class PlacesBookmarkRemoved final : public PlacesBookmark {
public:
explicit PlacesBookmarkRemoved()
: PlacesBookmark(PlacesEventType::Bookmark_removed) {}
static already_AddRefed<PlacesBookmarkRemoved> Constructor(
const GlobalObject& aGlobal, const PlacesBookmarkRemovedInit& aInitDict) {
RefPtr<PlacesBookmarkRemoved> event = new PlacesBookmarkRemoved();
event->mItemType = aInitDict.mItemType;
event->mId = aInitDict.mId;
event->mParentId = aInitDict.mParentId;
event->mIndex = aInitDict.mIndex;
event->mUrl = aInitDict.mUrl;
event->mGuid = aInitDict.mGuid;
event->mParentGuid = aInitDict.mParentGuid;
event->mSource = aInitDict.mSource;
event->mIsTagging = aInitDict.mIsTagging;
event->mIsDescendantRemoval = aInitDict.mIsDescendantRemoval;
return event.forget();
}
JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override {
return PlacesBookmarkRemoved_Binding::Wrap(aCx, this, aGivenProto);
}
const PlacesBookmarkRemoved* AsPlacesBookmarkRemoved() const override {
return this;
}
int32_t Index() { return mIndex; }
bool IsDescendantRemoval() { return mIsDescendantRemoval; }
int32_t mIndex;
bool mIsDescendantRemoval;
private:
~PlacesBookmarkRemoved() = default;
};
} // namespace dom
} // namespace mozilla
#endif

View File

@ -35,6 +35,9 @@ class PlacesEvent : public nsWrapperCache {
virtual const PlacesBookmarkAddition* AsPlacesBookmarkAddition() const {
return nullptr;
}
virtual const PlacesBookmarkRemoved* AsPlacesBookmarkRemoved() const {
return nullptr;
}
protected:
virtual ~PlacesEvent() = default;

View File

@ -46,7 +46,7 @@ PostMessageEvent::PostMessageEvent(BrowsingContext* aSource,
mCallerDocumentURI(aCallerDocumentURI),
mIsFromPrivateWindow(aIsFromPrivateWindow) {}
PostMessageEvent::~PostMessageEvent() {}
PostMessageEvent::~PostMessageEvent() = default;
NS_IMETHODIMP
PostMessageEvent::Run() {

View File

@ -36,13 +36,15 @@ nsINode* RangeUtils::ComputeRootNode(nsINode* aNode) {
nsIContent* content = aNode->AsContent();
// If the node is in a shadow tree then the ShadowRoot is the root.
//
// FIXME(emilio): Should this be after the NAC check below? We can have NAC
// inside Shadow DOM which will peek this path rather than the one below.
if (ShadowRoot* containingShadow = content->GetContainingShadow()) {
return containingShadow;
}
// If the node has a binding parent, that should be the root.
// XXXbz maybe only for native anonymous content?
if (nsINode* root = content->GetBindingParent()) {
// If the node is in NAC, then the NAC parent should be the root.
if (nsINode* root = content->GetClosestNativeAnonymousSubtreeRootParent()) {
return root;
}
}

View File

@ -2816,7 +2816,7 @@ nsIFrame* Selection::GetSelectionAnchorGeometry(SelectionRegion aRegion,
// make focusRect relative to anchorFrame
focusRect += focusFrame->GetOffsetTo(anchorFrame);
aRect->UnionRectEdges(anchorRect, focusRect);
*aRect = anchorRect.UnionEdges(focusRect);
return anchorFrame;
}

View File

@ -9,7 +9,6 @@
#include "ChildIterator.h"
#include "nsContentUtils.h"
#include "nsWindowSizes.h"
#include "nsXBLPrototypeBinding.h"
#include "mozilla/dom/DirectionalityUtils.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/HTMLSlotElement.h"
@ -60,7 +59,6 @@ ShadowRoot::ShadowRoot(Element* aElement, ShadowRootMode aMode,
SetFlags(NODE_IS_IN_SHADOW_TREE);
Bind();
ExtendedDOMSlots()->mBindingParent = aElement;
ExtendedDOMSlots()->mContainingShadow = this;
}
@ -89,8 +87,8 @@ void ShadowRoot::AddSizeOfExcludingThis(nsWindowSizes& aSizes,
ShadowRootAuthorStylesMallocEnclosingSizeOf, mServoStyles.get());
}
JSObject* ShadowRoot::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) {
JSObject* ShadowRoot::WrapNode(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) {
return mozilla::dom::ShadowRoot_Binding::Wrap(aCx, this, aGivenProto);
}
@ -521,7 +519,7 @@ void ShadowRoot::GetEventTargetParent(EventChainPreVisitor& aVisitor) {
aVisitor.SetParentTarget(shadowHost, false);
nsCOMPtr<nsIContent> content(do_QueryInterface(aVisitor.mEvent->mTarget));
if (content && content->GetBindingParent() == shadowHost) {
if (content && content->GetContainingShadow() == this) {
aVisitor.mEventTargetAtParent = shadowHost;
}
}
@ -667,7 +665,7 @@ void ShadowRoot::MaybeUnslotHostChild(nsIContent& aChild) {
"How did aChild end up assigned to a slot?");
// If the slot is going to start showing fallback content, we need to tell
// layout about it.
if (slot->AssignedNodes().Length() == 1) {
if (slot->AssignedNodes().Length() == 1 && slot->HasChildren()) {
InvalidateStyleAndLayoutOnSubtree(slot);
}
@ -693,7 +691,8 @@ void ShadowRoot::MaybeSlotHostChild(nsIContent& aChild) {
}
// Fallback content will go away, let layout know.
if (assignment.mSlot->AssignedNodes().IsEmpty()) {
if (assignment.mSlot->AssignedNodes().IsEmpty() &&
assignment.mSlot->HasChildren()) {
InvalidateStyleAndLayoutOnSubtree(assignment.mSlot);
}

View File

@ -151,6 +151,10 @@ class ShadowRoot final : public DocumentFragment,
void AddSlot(HTMLSlotElement* aSlot);
void RemoveSlot(HTMLSlotElement* aSlot);
bool HasSlots() const { return !mSlotMap.IsEmpty(); };
HTMLSlotElement* GetDefaultSlot() const {
SlotArray* list = mSlotMap.Get(NS_LITERAL_STRING(""));
return list ? (*list)->ElementAt(0) : nullptr;
}
void PartAdded(const Element&);
void PartRemoved(const Element&);
@ -167,8 +171,7 @@ class ShadowRoot final : public DocumentFragment,
mozilla::ServoStyleRuleMap& ServoStyleRuleMap();
JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
JSObject* WrapNode(JSContext*, JS::Handle<JSObject*> aGivenProto) final;
void NodeInfoChanged(Document* aOldDoc) override {
DocumentFragment::NodeInfoChanged(aOldDoc);

View File

@ -86,15 +86,6 @@ void Text::GetWholeText(nsAString& aWholeText, ErrorResult& aRv) {
return;
}
int32_t index = parent->ComputeIndexOf(this);
NS_WARNING_ASSERTION(index >= 0,
"Trying to use .wholeText with an anonymous"
"text node child of a binding parent?");
if (NS_WARN_IF(index < 0)) {
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return;
}
Text* first = FirstLogicallyAdjacentTextNode(this);
Text* last = LastLogicallyAdjacentTextNode(this);

View File

@ -33,7 +33,7 @@ class TimeoutHandler : public nsISupports {
TimeoutHandler() : mFileName(""), mLineNo(0), mColumn(0) {}
explicit TimeoutHandler(JSContext* aCx);
virtual ~TimeoutHandler() {}
virtual ~TimeoutHandler() = default;
// filename, line number and JS language version string of the
// caller of setTimeout()
@ -60,7 +60,7 @@ class ScriptTimeoutHandler : public TimeoutHandler {
};
protected:
virtual ~ScriptTimeoutHandler() {}
virtual ~ScriptTimeoutHandler() = default;
nsCOMPtr<nsIGlobalObject> mGlobal;
// The expression to evaluate or function to call. If mFunction is non-null

View File

@ -2,7 +2,7 @@
<html>
<head>
<meta charset="UTF-8">
<link rel="import" href="1027461-inner.xul">
<link rel="import" href="1027461-inner.xhtml">
</head>
<body>
</body>

View File

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html>
<body>
<iframe id="iframe" src="1370968-inner.xul"></iframe>
<iframe id="iframe" src="1370968-inner.xhtml"></iframe>
<script>
var io = new IntersectionObserver(function () {
}, { });

View File

@ -1,3 +0,0 @@
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" onload="var button=document.getElementsByTagName('button')[0]; try { button.appendChild(SpecialPowers.unwrap(SpecialPowers.wrap(document).getAnonymousNodes(button))[0]); } catch(e) { }">
<button/>
</window>

View File

@ -1,35 +0,0 @@
<html xmlns="http://www.w3.org/1999/xhtml" class="reftest-wait">
<head>
<script>
function init()
{
var foopy = document.getElementById("foopy");
var emb = document.getElementById("emb");
try {
foopy.appendChild(SpecialPowers.unwrap(SpecialPowers.wrap(document).getAnonymousNodes(emb))[0]);
emb.parentNode.removeChild(emb);
foopy.parentNode.removeChild(foopy);
} catch (e) {
}
document.documentElement.removeAttribute("class");
}
window.addEventListener("load", function() { setTimeout(init, 30); }, false);
</script>
</head>
<body>
<div id="foopy"/>
<embed src="data:foo/bar,baz" id="emb" />
</body>
</html>

View File

@ -4,6 +4,6 @@
setTimeout('document.documentElement.className = ""', 500);
</script>
<body>
<iframe src="384663-1-inner.xul"></iframe>
<iframe src="384663-1-inner.xhtml"></iframe>
</body>
</html>

View File

@ -7,7 +7,6 @@ load 231475-1.html
load 244933-1.html
load 275912-1.html
load 293388-1.html
load 308120-1.xul
load 325730-1.html
load 326618-1.html
load 326646-1.html
@ -16,7 +15,6 @@ load 327571-1.html
load 327694.html
load 327695-1.html
load 329481-1.xhtml
load 330925-1.xhtml
load 336381-1.xhtml
load 336715-1.xhtml
load 338391-1.xhtml
@ -204,9 +202,9 @@ load 1326194-2.html
load 1332939.html
load 1341693.html
load 1352453.html
load 1353529.xul
load chrome://reftest/content/crashtests/dom/base/crashtests/1353529.xhtml
load 1368327.html
load 1369363.xul
load chrome://reftest/content/crashtests/dom/base/crashtests/1369363.xhtml
load 1370072.html
pref(clipboard.autocopy,true) load 1370737.html
load 1370968.html

View File

@ -210,6 +210,7 @@ EXPORTS.mozilla.dom += [
'ParentProcessMessageManager.h',
'PlacesBookmark.h',
'PlacesBookmarkAddition.h',
'PlacesBookmarkRemoved.h',
'PlacesEvent.h',
'PlacesObservers.h',
'PlacesVisit.h',
@ -501,7 +502,6 @@ LOCAL_INCLUDES += [
'/dom/storage',
'/dom/svg',
'/dom/u2f',
'/dom/xbl',
'/dom/xml',
'/dom/xslt/xpath',
'/dom/xul',

View File

@ -8,7 +8,6 @@
#include "nsServiceManagerUtils.h"
#include "nsIContentViewer.h"
#include "mozilla/dom/Document.h"
#include "XULDocument.h"
#include "InProcessBrowserChildMessageManager.h"
#include "nsIWindowMediator.h"
#include "nsPIDOMWindow.h"
@ -17,7 +16,7 @@
#include "nsISHEntry.h"
#include "nsIWindowWatcher.h"
#include "mozilla/Services.h"
#include "nsIXULWindow.h"
#include "nsIAppWindow.h"
#include "nsIAppShellService.h"
#include "nsAppShellCID.h"
#include "nsContentUtils.h"
@ -351,23 +350,12 @@ nsresult nsCCUncollectableMarker::Observe(nsISupports* aSubject,
bool hasHiddenWindow = false;
appShell->GetHasHiddenWindow(&hasHiddenWindow);
if (hasHiddenWindow) {
nsCOMPtr<nsIXULWindow> hw;
nsCOMPtr<nsIAppWindow> hw;
appShell->GetHiddenWindow(getter_AddRefs(hw));
nsCOMPtr<nsIDocShell> shell;
hw->GetDocShell(getter_AddRefs(shell));
MarkDocShell(shell, cleanupJS);
}
bool hasHiddenPrivateWindow = false;
appShell->GetHasHiddenPrivateWindow(&hasHiddenPrivateWindow);
if (hasHiddenPrivateWindow) {
nsCOMPtr<nsIXULWindow> hw;
appShell->GetHiddenPrivateWindow(getter_AddRefs(hw));
if (hw) {
nsCOMPtr<nsIDocShell> shell;
hw->GetDocShell(getter_AddRefs(shell));
MarkDocShell(shell, cleanupJS);
}
}
}
#ifdef MOZ_XUL

View File

@ -285,7 +285,7 @@ nsContentAreaDragDropDataProvider::GetFlavorData(nsITransferable* aTransferable,
NS_ENSURE_SUCCESS(rv, rv);
newFileName.Append(".");
newFileName.Append(primaryExtension);
targetFilename = NS_ConvertUTF8toUTF16(newFileName);
CopyUTF8toUTF16(newFileName, targetFilename);
}
}
}

View File

@ -60,7 +60,7 @@ class nsContentAreaDragDrop {
// during the drop instead of when it is added to the drag data transfer. This
// ensures that the image data is only created when an image drop is allowed.
class nsContentAreaDragDropDataProvider : public nsIFlavorDataProvider {
virtual ~nsContentAreaDragDropDataProvider() {}
virtual ~nsContentAreaDragDropDataProvider() = default;
public:
NS_DECL_ISUPPORTS

View File

@ -98,7 +98,6 @@ inline const char* NS_CP_ContentTypeName(uint32_t contentType) {
CASE_RETURN(TYPE_DOCUMENT);
CASE_RETURN(TYPE_SUBDOCUMENT);
CASE_RETURN(TYPE_REFRESH);
CASE_RETURN(TYPE_XBL);
CASE_RETURN(TYPE_PING);
CASE_RETURN(TYPE_XMLHTTPREQUEST);
CASE_RETURN(TYPE_OBJECT_SUBREQUEST);

View File

@ -52,6 +52,7 @@
#include "mozilla/dom/Document.h"
#include "mozilla/dom/DocumentInlines.h"
#include "mozilla/dom/MessageBroadcaster.h"
#include "mozilla/dom/MessagePort.h"
#include "mozilla/dom/DocumentFragment.h"
#include "mozilla/dom/DOMException.h"
#include "mozilla/dom/DOMExceptionBinding.h"
@ -120,7 +121,6 @@
#include "nsAttrName.h"
#include "nsAttrValue.h"
#include "nsAttrValueInlines.h"
#include "nsBindingManager.h"
#include "nsCanvasFrame.h"
#include "nsCaret.h"
#include "nsCCUncollectableMarker.h"
@ -565,7 +565,7 @@ class nsContentUtils::UserInteractionObserver final
static Atomic<bool> sUserActive;
private:
~UserInteractionObserver() {}
~UserInteractionObserver() = default;
};
/* static */
@ -2101,7 +2101,7 @@ bool nsContentUtils::IsCallerContentXBL() {
return true;
}
return xpc::IsContentXBLScope(realm);
return false;
}
bool nsContentUtils::IsCallerUAWidget() {
@ -2134,9 +2134,7 @@ bool nsContentUtils::ThreadsafeIsSystemCaller(JSContext* aCx) {
bool nsContentUtils::LookupBindingMember(
JSContext* aCx, nsIContent* aContent, JS::Handle<jsid> aId,
JS::MutableHandle<JS::PropertyDescriptor> aDesc) {
nsXBLBinding* binding = aContent->GetXBLBinding();
if (!binding) return true;
return binding->LookupMember(aCx, aId, aDesc);
return true;
}
// static
@ -3551,7 +3549,6 @@ void nsContentUtils::GetEventArgNames(int32_t aNameSpaceID, nsAtom* aEventName,
static const char* gPropertiesFiles[nsContentUtils::PropertiesFile_COUNT] = {
// Must line up with the enum values in |PropertiesFile| enum.
"chrome://global/locale/css.properties",
"chrome://global/locale/xbl.properties",
"chrome://global/locale/xul.properties",
"chrome://global/locale/layout_errors.properties",
"chrome://global/locale/layout/HtmlForm.properties",
@ -4270,7 +4267,7 @@ void nsContentUtils::RequestFrameFocus(Element& aFrameElement, bool aCanRaise) {
return;
}
nsCOMPtr<nsIFocusManager> fm = nsFocusManager::GetFocusManager();
RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager();
if (!fm) {
return;
}
@ -4409,14 +4406,6 @@ bool nsContentUtils::HasMutationListeners(nsINode* aNode, uint32_t aType,
return true;
}
if (aNode->IsContent()) {
nsIContent* insertionPoint = aNode->AsContent()->GetXBLInsertionPoint();
if (insertionPoint) {
aNode = insertionPoint->GetParent();
MOZ_ASSERT(aNode);
continue;
}
}
aNode = aNode->GetParentNode();
}
@ -5173,18 +5162,18 @@ bool nsContentUtils::IsInSameAnonymousTree(const nsINode* aNode,
MOZ_ASSERT(aNode, "Must have a node to work with");
MOZ_ASSERT(aContent, "Must have a content to work with");
if (!aNode->IsContent()) {
/**
* The root isn't an nsIContent, so it's a document or attribute. The only
* nodes in the same anonymous subtree as it will have a null
* bindingParent.
*
* XXXbz strictly speaking, that's not true for attribute nodes.
*/
return aContent->GetBindingParent() == nullptr;
if (aNode->IsInNativeAnonymousSubtree() != aContent->IsInNativeAnonymousSubtree()) {
return false;
}
return aNode->AsContent()->GetBindingParent() == aContent->GetBindingParent();
if (aNode->IsInNativeAnonymousSubtree()) {
return aContent->GetClosestNativeAnonymousSubtreeRoot() ==
aNode->GetClosestNativeAnonymousSubtreeRoot();
}
// FIXME: This doesn't deal with disconnected nodes whatsoever, but it didn't
// use to either. Maybe that's fine.
return aNode->GetContainingShadow() == aContent->GetContainingShadow();
}
/* static */
@ -5937,7 +5926,7 @@ nsresult nsContentUtils::GetUTFOrigin(nsIPrincipal* aPrincipal,
asciiOrigin.AssignLiteral("null");
}
aOrigin = NS_ConvertUTF8toUTF16(asciiOrigin);
CopyUTF8toUTF16(asciiOrigin, aOrigin);
return NS_OK;
}
@ -5963,7 +5952,7 @@ nsresult nsContentUtils::GetUTFOrigin(nsIURI* aURI, nsAString& aOrigin) {
rv = GetASCIIOrigin(aURI, asciiOrigin);
NS_ENSURE_SUCCESS(rv, rv);
aOrigin = NS_ConvertUTF8toUTF16(asciiOrigin);
CopyUTF8toUTF16(asciiOrigin, aOrigin);
return NS_OK;
}
@ -8853,7 +8842,7 @@ void nsContentUtils::GetPresentationURL(nsIDocShell* aDocShell,
nsAutoCString uriStr;
uri->GetSpec(uriStr);
aPresentationUrl = NS_ConvertUTF8toUTF16(uriStr);
CopyUTF8toUTF16(uriStr, aPresentationUrl);
return;
}
@ -9496,11 +9485,8 @@ void nsContentUtils::AppendDocumentLevelNativeAnonymousContentTo(
"scroll frame should always implement nsIAnonymousContentCreator");
creator->AppendAnonymousContentTo(aElements, 0);
}
if (nsCanvasFrame* canvasFrame = presShell->GetCanvasFrame()) {
if (Element* container = canvasFrame->GetCustomContentContainer()) {
aElements.AppendElement(container);
}
canvasFrame->AppendAnonymousContentTo(aElements, 0);
}
}
@ -9660,6 +9646,41 @@ nsresult nsContentUtils::CreateJSValueFromSequenceOfObject(
return NS_OK;
}
/* static */
void nsContentUtils::StructuredClone(JSContext* aCx, nsIGlobalObject* aGlobal,
JS::Handle<JS::Value> aValue,
const StructuredSerializeOptions& aOptions,
JS::MutableHandle<JS::Value> aRetval,
ErrorResult& aError) {
JS::Rooted<JS::Value> transferArray(aCx, JS::UndefinedValue());
aError = nsContentUtils::CreateJSValueFromSequenceOfObject(
aCx, aOptions.mTransfer, &transferArray);
if (NS_WARN_IF(aError.Failed())) {
return;
}
JS::CloneDataPolicy clonePolicy;
//clonePolicy.allowIntraClusterClonableSharedObjects();
//clonePolicy.allowSharedMemoryObjects();
clonePolicy.denySharedArrayBuffer();
StructuredCloneHolder holder(StructuredCloneHolder::CloningSupported,
StructuredCloneHolder::TransferringSupported,
JS::StructuredCloneScope::SameProcess);
holder.Write(aCx, aValue, transferArray, clonePolicy, aError);
if (NS_WARN_IF(aError.Failed())) {
return;
}
holder.Read(aGlobal, aCx, aRetval, aError);
if (NS_WARN_IF(aError.Failed())) {
return;
}
nsTArray<RefPtr<MessagePort>> ports = holder.TakeTransferredPorts();
Unused << ports;
}
/* static */
bool nsContentUtils::ShouldBlockReservedKeys(WidgetKeyboardEvent* aKeyEvent) {
nsCOMPtr<nsIPrincipal> principal;

View File

@ -153,6 +153,7 @@ class MessageBroadcaster;
class NodeInfo;
class Selection;
class StaticRange;
struct StructuredSerializeOptions;
class WorkerPrivate;
} // namespace dom
@ -1118,7 +1119,6 @@ class nsContentUtils {
*/
enum PropertiesFile {
eCSS_PROPERTIES,
eXBL_PROPERTIES,
eXUL_PROPERTIES,
eLAYOUT_PROPERTIES,
eFORMS_PROPERTIES,
@ -3098,6 +3098,15 @@ class nsContentUtils {
JSContext* aCx, const mozilla::dom::Sequence<JSObject*>& aTransfer,
JS::MutableHandle<JS::Value> aValue);
/**
* This implements the structured cloning algorithm as described by
* https://html.spec.whatwg.org/#structured-cloning.
*/
static void StructuredClone(
JSContext* aCx, nsIGlobalObject* aGlobal, JS::Handle<JS::Value> aValue,
const mozilla::dom::StructuredSerializeOptions& aOptions,
JS::MutableHandle<JS::Value> aRetval, mozilla::ErrorResult& aError);
/**
* Returns true if reserved key events should be prevented from being sent
* to their target. Instead, the key event should be handled by chrome only.

View File

@ -117,15 +117,6 @@ static nsresult EncodeForTextUnicode(nsIDocumentEncoder& aEncoder,
rv = aEncoder.GetMimeType(mimeType);
NS_ENSURE_SUCCESS(rv, rv);
if (!selForcedTextPlain && mimeType.EqualsLiteral(kTextMime)) {
// SetSelection and EncodeToString use this case to signal that text/plain
// was forced because the document is either not an HTMLDocument or it's
// XHTML. We want to pretty print XHTML but not non-HTMLDocuments.
if (!aDocument.IsHTMLOrXHTML()) {
selForcedTextPlain = true;
}
}
// The mime type is ultimately text/html if the encoder successfully encoded
// the selection as text/html.
aEncodedAsTextHTMLResult = mimeType.EqualsLiteral(kHTMLMime);

View File

@ -49,8 +49,7 @@ class nsAttrKey {
nsAttrKey(int32_t aNs, nsAtom* aName)
: mNamespaceID(aNs), mLocalName(aName) {}
nsAttrKey(const nsAttrKey& aAttr)
: mNamespaceID(aAttr.mNamespaceID), mLocalName(aAttr.mLocalName) {}
nsAttrKey(const nsAttrKey& aAttr) = default;
};
/**
@ -63,7 +62,7 @@ class nsAttrHashKey : public PLDHashEntryHdr {
explicit nsAttrHashKey(KeyTypePointer aKey) : mKey(*aKey) {}
nsAttrHashKey(const nsAttrHashKey& aCopy) : mKey(aCopy.mKey) {}
~nsAttrHashKey() {}
~nsAttrHashKey() = default;
KeyType GetKey() const { return mKey; }
bool KeyEquals(KeyTypePointer aKey) const {

View File

@ -31,7 +31,7 @@ class nsDOMMutationObserver;
using mozilla::dom::MutationObservingInfo;
class nsDOMMutationRecord final : public nsISupports, public nsWrapperCache {
virtual ~nsDOMMutationRecord() {}
virtual ~nsDOMMutationRecord() = default;
public:
typedef nsTArray<RefPtr<mozilla::dom::Animation>> AnimationArray;
@ -112,7 +112,7 @@ class nsDOMMutationRecord final : public nsISupports, public nsWrapperCache {
// members to make sure we go through getters/setters.
class nsMutationReceiverBase : public nsStubAnimationObserver {
public:
virtual ~nsMutationReceiverBase() {}
virtual ~nsMutationReceiverBase() = default;
nsDOMMutationObserver* Observer();
nsINode* Target() { return mParent ? mParent->Target() : mTarget; }
@ -398,7 +398,7 @@ class nsAnimationReceiver : public nsMutationReceiver {
NS_DECL_NSIANIMATIONOBSERVER_ANIMATIONREMOVED
protected:
virtual ~nsAnimationReceiver() {}
virtual ~nsAnimationReceiver() = default;
nsAnimationReceiver(nsINode* aTarget, nsDOMMutationObserver* aObserver)
: nsMutationReceiver(aTarget, aObserver) {}

View File

@ -21,7 +21,7 @@
#include "nsIWebNavigation.h"
#include "nsCaret.h"
#include "nsIBaseWindow.h"
#include "nsIXULWindow.h"
#include "nsIAppWindow.h"
#include "nsTextControlFrame.h"
#include "nsViewManager.h"
#include "nsFrameSelection.h"
@ -33,7 +33,6 @@
#include "nsIPrincipal.h"
#include "nsIObserverService.h"
#include "nsIObjectFrame.h"
#include "nsBindingManager.h"
#include "BrowserChild.h"
#include "nsFrameLoader.h"
#include "nsHTMLDocument.h"
@ -250,7 +249,9 @@ static nsPIDOMWindowOuter* GetContentWindow(nsIContent* aContent) {
Document* doc = aContent->GetComposedDoc();
if (doc) {
Document* subdoc = doc->GetSubDocumentFor(aContent);
if (subdoc) return subdoc->GetWindow();
if (subdoc) {
return subdoc->GetWindow();
}
}
return nullptr;
@ -319,17 +320,12 @@ Element* nsFocusManager::GetFocusedDescendant(
Element* nsFocusManager::GetRedirectedFocus(nsIContent* aContent) {
#ifdef MOZ_XUL
if (aContent->IsXULElement()) {
if (aContent->IsXULElement(nsGkAtoms::textbox)) {
return aContent->OwnerDoc()->GetAnonymousElementByAttribute(
aContent, nsGkAtoms::anonid, NS_LITERAL_STRING("input"));
} else {
nsCOMPtr<nsIDOMXULMenuListElement> menulist =
aContent->AsElement()->AsXULMenuList();
if (menulist) {
RefPtr<Element> inputField;
menulist->GetInputField(getter_AddRefs(inputField));
return inputField;
}
nsCOMPtr<nsIDOMXULMenuListElement> menulist =
aContent->AsElement()->AsXULMenuList();
if (menulist) {
RefPtr<Element> inputField;
menulist->GetInputField(getter_AddRefs(inputField));
return inputField;
}
}
#endif
@ -408,7 +404,9 @@ NS_IMETHODIMP nsFocusManager::SetFocusedWindow(
}
nsCOMPtr<nsPIDOMWindowOuter> rootWindow = windowToFocus->GetPrivateRoot();
if (rootWindow) RaiseWindow(rootWindow);
if (rootWindow) {
RaiseWindow(rootWindow);
}
LOGFOCUS(("<<SetFocusedWindow end>>"));
@ -430,7 +428,9 @@ nsFocusManager::GetLastFocusMethod(mozIDOMWindowProxy* aWindow,
if (aWindow) {
window = nsPIDOMWindowOuter::From(aWindow);
}
if (!window) window = mFocusedWindow;
if (!window) {
window = mFocusedWindow;
}
*aLastFocusMethod = window ? window->GetFocusMethod() : 0;
@ -559,7 +559,9 @@ nsFocusManager::GetFocusedElementForWindow(mozIDOMWindowProxy* aWindow,
mozIDOMWindowProxy** aFocusedWindow,
Element** aElement) {
*aElement = nullptr;
if (aFocusedWindow) *aFocusedWindow = nullptr;
if (aFocusedWindow) {
*aFocusedWindow = nullptr;
}
NS_ENSURE_TRUE(aWindow, NS_ERROR_INVALID_ARG);
nsCOMPtr<nsPIDOMWindowOuter> window = nsPIDOMWindowOuter::From(aWindow);
@ -573,7 +575,9 @@ nsFocusManager::GetFocusedElementForWindow(mozIDOMWindowProxy* aWindow,
focusedElement.forget(aElement);
if (aFocusedWindow) NS_IF_ADDREF(*aFocusedWindow = focusedWindow);
if (aFocusedWindow) {
NS_IF_ADDREF(*aFocusedWindow = focusedWindow);
}
return NS_OK;
}
@ -590,7 +594,9 @@ nsFocusManager::MoveCaretToFocus(mozIDOMWindowProxy* aWindow) {
// don't move the caret for editable documents
bool isEditable;
docShell->GetEditable(&isEditable);
if (isEditable) return NS_OK;
if (isEditable) {
return NS_OK;
}
RefPtr<PresShell> presShell = docShell->GetPresShell();
NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
@ -606,9 +612,11 @@ nsFocusManager::MoveCaretToFocus(mozIDOMWindowProxy* aWindow) {
return NS_OK;
}
NS_IMETHODIMP
nsFocusManager::WindowRaised(mozIDOMWindowProxy* aWindow) {
NS_ENSURE_TRUE(aWindow, NS_ERROR_INVALID_ARG);
void nsFocusManager::WindowRaised(mozIDOMWindowProxy* aWindow) {
if (!aWindow) {
return;
}
nsCOMPtr<nsPIDOMWindowOuter> window = nsPIDOMWindowOuter::From(aWindow);
if (MOZ_LOG_TEST(gFocusLog, LogLevel::Debug)) {
@ -637,7 +645,7 @@ nsFocusManager::WindowRaised(mozIDOMWindowProxy* aWindow) {
// what the focus manager thinks should be the current widget is actually
// focused.
EnsureCurrentWidgetFocused();
return NS_OK;
return;
}
// lower the existing window, if any. This shouldn't happen usually.
@ -646,7 +654,9 @@ nsFocusManager::WindowRaised(mozIDOMWindowProxy* aWindow) {
nsCOMPtr<nsIDocShellTreeItem> docShellAsItem = window->GetDocShell();
// If there's no docShellAsItem, this window must have been closed,
// in that case there is no tree owner.
NS_ENSURE_TRUE(docShellAsItem, NS_OK);
if (!docShellAsItem) {
return;
}
// set this as the active window
mActiveWindow = window;
@ -658,7 +668,7 @@ nsFocusManager::WindowRaised(mozIDOMWindowProxy* aWindow) {
if (baseWindow) {
bool isEnabled = true;
if (NS_SUCCEEDED(baseWindow->GetEnabled(&isEnabled)) && !isEnabled) {
return NS_ERROR_FAILURE;
return;
}
baseWindow->SetVisibility(true);
@ -680,19 +690,21 @@ nsFocusManager::WindowRaised(mozIDOMWindowProxy* aWindow) {
window, eIncludeAllDescendants, getter_AddRefs(currentWindow));
NS_ASSERTION(currentWindow, "window raised with no window current");
if (!currentWindow) return NS_OK;
if (!currentWindow) {
return;
}
// If there is no nsIXULWindow, then this is an embedded or child process
// If there is no nsIAppWindow, then this is an embedded or child process
// window. Pass false for aWindowRaised so that commands get updated.
nsCOMPtr<nsIXULWindow> xulWin(do_GetInterface(baseWindow));
Focus(currentWindow, currentFocus, 0, true, false, xulWin != nullptr, true);
return NS_OK;
nsCOMPtr<nsIAppWindow> appWin(do_GetInterface(baseWindow));
Focus(currentWindow, currentFocus, 0, true, false, appWin != nullptr, true);
}
NS_IMETHODIMP
nsFocusManager::WindowLowered(mozIDOMWindowProxy* aWindow) {
NS_ENSURE_TRUE(aWindow, NS_ERROR_INVALID_ARG);
void nsFocusManager::WindowLowered(mozIDOMWindowProxy* aWindow) {
if (!aWindow) {
return;
}
nsCOMPtr<nsPIDOMWindowOuter> window = nsPIDOMWindowOuter::From(aWindow);
if (MOZ_LOG_TEST(gFocusLog, LogLevel::Debug)) {
@ -712,7 +724,9 @@ nsFocusManager::WindowLowered(mozIDOMWindowProxy* aWindow) {
}
}
if (mActiveWindow != window) return NS_OK;
if (mActiveWindow != window) {
return;
}
// clear the mouse capture as the active window has changed
PresShell::ReleaseCapturingContent();
@ -742,11 +756,11 @@ nsFocusManager::WindowLowered(mozIDOMWindowProxy* aWindow) {
mWindowBeingLowered = mActiveWindow;
mActiveWindow = nullptr;
if (mFocusedWindow) Blur(nullptr, nullptr, true, true);
if (mFocusedWindow) {
Blur(nullptr, nullptr, true, true);
}
mWindowBeingLowered = nullptr;
return NS_OK;
}
nsresult nsFocusManager::ContentRemoved(Document* aDocument,
@ -755,15 +769,16 @@ nsresult nsFocusManager::ContentRemoved(Document* aDocument,
NS_ENSURE_ARG(aContent);
nsPIDOMWindowOuter* window = aDocument->GetWindow();
if (!window) return NS_OK;
if (!window) {
return NS_OK;
}
// if the content is currently focused in the window, or is an
// shadow-including inclusive ancestor of the currently focused element,
// reset the focus within that window.
nsIContent* content = window->GetFocusedElement();
Element* content = window->GetFocusedElement();
if (content &&
nsContentUtils::ContentIsHostIncludingDescendantOf(content, aContent)) {
bool shouldShowFocusRing = window->ShouldShowFocusRing();
window->SetFocusedElement(nullptr);
// if this window is currently focused, clear the global focused
@ -803,16 +818,19 @@ nsresult nsFocusManager::ContentRemoved(Document* aDocument,
}
}
NotifyFocusStateChange(content, nullptr, shouldShowFocusRing, 0,
/* aGettingFocus = */ false);
NotifyFocusStateChange(content, nullptr, 0, /* aGettingFocus = */ false,
false);
}
return NS_OK;
}
NS_IMETHODIMP
nsFocusManager::WindowShown(mozIDOMWindowProxy* aWindow, bool aNeedsFocus) {
NS_ENSURE_TRUE(aWindow, NS_ERROR_INVALID_ARG);
void nsFocusManager::WindowShown(mozIDOMWindowProxy* aWindow,
bool aNeedsFocus) {
if (!aWindow) {
return;
}
nsCOMPtr<nsPIDOMWindowOuter> window = nsPIDOMWindowOuter::From(aWindow);
if (MOZ_LOG_TEST(gFocusLog, LogLevel::Debug)) {
@ -840,31 +858,34 @@ nsFocusManager::WindowShown(mozIDOMWindowProxy* aWindow, bool aNeedsFocus) {
}
}
if (mFocusedWindow != window) return NS_OK;
if (mFocusedWindow != window) {
return;
}
if (aNeedsFocus) {
nsCOMPtr<nsPIDOMWindowOuter> currentWindow;
RefPtr<Element> currentFocus = GetFocusedDescendant(
window, eIncludeAllDescendants, getter_AddRefs(currentWindow));
if (currentWindow)
if (currentWindow) {
Focus(currentWindow, currentFocus, 0, true, false, false, true);
}
} else {
// Sometimes, an element in a window can be focused before the window is
// visible, which would mean that the widget may not be properly focused.
// When the window becomes visible, make sure the right widget is focused.
EnsureCurrentWidgetFocused();
}
return NS_OK;
}
NS_IMETHODIMP
nsFocusManager::WindowHidden(mozIDOMWindowProxy* aWindow) {
void nsFocusManager::WindowHidden(mozIDOMWindowProxy* aWindow) {
// if there is no window or it is not the same or an ancestor of the
// currently focused window, just return, as the current focus will not
// be affected.
NS_ENSURE_TRUE(aWindow, NS_ERROR_INVALID_ARG);
if (!aWindow) {
return;
}
nsCOMPtr<nsPIDOMWindowOuter> window = nsPIDOMWindowOuter::From(aWindow);
if (MOZ_LOG_TEST(gFocusLog, LogLevel::Debug)) {
@ -894,7 +915,9 @@ nsFocusManager::WindowHidden(mozIDOMWindowProxy* aWindow) {
}
}
if (!IsSameOrAncestor(window, mFocusedWindow)) return NS_OK;
if (!IsSameOrAncestor(window, mFocusedWindow)) {
return;
}
// at this point, we know that the window being hidden is either the focused
// window, or an ancestor of the focused window. Either way, the focus is no
@ -903,11 +926,14 @@ nsFocusManager::WindowHidden(mozIDOMWindowProxy* aWindow) {
RefPtr<Element> oldFocusedElement = std::move(mFocusedElement);
nsCOMPtr<nsIDocShell> focusedDocShell = mFocusedWindow->GetDocShell();
if (!focusedDocShell) {
return;
}
RefPtr<PresShell> presShell = focusedDocShell->GetPresShell();
if (oldFocusedElement && oldFocusedElement->IsInComposedDoc()) {
NotifyFocusStateChange(oldFocusedElement, nullptr,
mFocusedWindow->ShouldShowFocusRing(), 0, false);
NotifyFocusStateChange(oldFocusedElement, nullptr, 0, false, false);
window->UpdateCommands(u"focus"_ns, nullptr, 0);
if (presShell) {
@ -942,11 +968,13 @@ nsFocusManager::WindowHidden(mozIDOMWindowProxy* aWindow) {
// not happen if nsIAppStartup::eForceQuit is used to quit, and can cause
// a leak. So if the active window is being destroyed, call WindowLowered
// directly.
if (mActiveWindow == mFocusedWindow || mActiveWindow == window)
if (mActiveWindow == mFocusedWindow || mActiveWindow == window) {
WindowLowered(mActiveWindow);
else
}
else {
ClearFocus(mActiveWindow);
return NS_OK;
}
return;
}
// if the window being hidden is an ancestor of the focused window, adjust
@ -960,20 +988,19 @@ nsFocusManager::WindowHidden(mozIDOMWindowProxy* aWindow) {
nsCOMPtr<nsIDocShellTreeItem> parentDsti;
dsti->GetInProcessParent(getter_AddRefs(parentDsti));
if (parentDsti) {
if (nsCOMPtr<nsPIDOMWindowOuter> parentWindow = parentDsti->GetWindow())
if (nsCOMPtr<nsPIDOMWindowOuter> parentWindow =
parentDsti->GetWindow()) {
parentWindow->SetFocusedElement(nullptr);
}
}
}
SetFocusedWindowInternal(window);
}
return NS_OK;
}
NS_IMETHODIMP
nsFocusManager::FireDelayedEvents(Document* aDocument) {
NS_ENSURE_ARG(aDocument);
void nsFocusManager::FireDelayedEvents(Document* aDocument) {
MOZ_ASSERT(aDocument);
// fire any delayed focus and blur events in the same order that they were
// added
@ -1000,36 +1027,90 @@ nsFocusManager::FireDelayedEvents(Document* aDocument) {
}
}
}
return NS_OK;
}
NS_IMETHODIMP
nsFocusManager::FocusPlugin(Element* aPlugin) {
nsresult nsFocusManager::FocusPlugin(Element* aPlugin) {
NS_ENSURE_ARG(aPlugin);
SetFocusInner(aPlugin, 0, true, false);
return NS_OK;
}
NS_IMETHODIMP
nsFocusManager::ParentActivated(mozIDOMWindowProxy* aWindow, bool aActive) {
void nsFocusManager::ParentActivated(mozIDOMWindowProxy* aWindow,
bool aActive) {
nsCOMPtr<nsPIDOMWindowOuter> window = nsPIDOMWindowOuter::From(aWindow);
NS_ENSURE_TRUE(window, NS_ERROR_INVALID_ARG);
if (!window) {
return;
}
ActivateOrDeactivate(window, aActive);
return NS_OK;
}
static bool ShouldMatchFocusVisible(const Element& aElement,
int32_t aFocusFlags) {
switch (nsFocusManager::GetFocusMoveActionCause(aFocusFlags)) {
case InputContextAction::CAUSE_UNKNOWN:
case InputContextAction::CAUSE_KEY:
nsFocusManager::BlurredElementInfo::BlurredElementInfo(Element& aElement)
: mElement(aElement),
mHadRing(aElement.State().HasState(NS_EVENT_STATE_FOCUSRING)) {}
nsFocusManager::BlurredElementInfo::~BlurredElementInfo() = default;
// https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo
static bool ShouldMatchFocusVisible(
nsPIDOMWindowOuter* aWindow, const Element& aElement, int32_t aFocusFlags,
const Maybe<nsFocusManager::BlurredElementInfo>& aBlurredElementInfo,
bool aIsRefocus, bool aRefocusedElementUsedToShowOutline) {
// If we were explicitly requested to show the ring, do it.
if (aFocusFlags & nsIFocusManager::FLAG_SHOWRING) {
return true;
}
if (aWindow->ShouldShowFocusRing()) {
// The window decision also trumps any other heuristic.
return true;
}
// Any element which supports keyboard input (such as an input element, or any
// other element which may trigger a virtual keyboard to be shown on focus if
// a physical keyboard is not present) should always match :focus-visible when
// focused.
{
if (aElement.IsHTMLElement(nsGkAtoms::textarea) || aElement.IsEditable()) {
return true;
}
if (auto* input = HTMLInputElement::FromNode(aElement)) {
if (input->IsSingleLineTextControl()) {
return true;
}
}
}
switch (nsFocusManager::GetFocusMoveActionCause(aFocusFlags)) {
case InputContextAction::CAUSE_KEY:
// If the user interacts with the page via the keyboard, the currently
// focused element should match :focus-visible (i.e. keyboard usage may
// change whether this pseudo-class matches even if it doesn't affect
// :focus).
return true;
case InputContextAction::CAUSE_UNKNOWN:
// If the active element matches :focus-visible, and a script causes focus
// to move elsewhere, the newly focused element should match
// :focus-visible.
//
// Conversely, if the active element does not match :focus-visible, and a
// script causes focus to move elsewhere, the newly focused element should
// not match :focus-visible.
//
// There's an special-case here. If this is a refocus, we just keep the
// outline as it was before, the focus isn't moving after all.
if (aIsRefocus) {
return aRefocusedElementUsedToShowOutline;
}
return !aBlurredElementInfo || aBlurredElementInfo->mHadRing;
case InputContextAction::CAUSE_MOUSE:
case InputContextAction::CAUSE_TOUCH:
case InputContextAction::CAUSE_LONGPRESS:
break;
// If the user interacts with the page via a pointing device, such that
// the focus is moved to a new element which does not support user input,
// the newly focused element should not match :focus-visible.
return false;
case InputContextAction::CAUSE_UNKNOWN_CHROME:
case InputContextAction::CAUSE_UNKNOWN_DURING_KEYBOARD_INPUT:
case InputContextAction::CAUSE_UNKNOWN_DURING_NON_KEYBOARD_INPUT:
@ -1044,60 +1125,31 @@ static bool ShouldMatchFocusVisible(const Element& aElement,
return false;
}
// On Windows and Linux, focus rings are only shown when the FLAG_SHOWRING flag
// is used.
static bool ShouldShowFocusRingForElement(Element& aElement, int32_t aFlags) {
if (aFlags & nsIFocusManager::FLAG_SHOWRING) {
return true;
}
#if defined(XP_MACOSX) || defined(ANDROID)
if (aFlags & nsIFocusManager::FLAG_BYMOUSE) {
return !nsContentUtils::ContentIsLink(&aElement) &&
!aElement.IsAnyOfHTMLElements(nsGkAtoms::video, nsGkAtoms::audio);
}
return true;
#else
return false;
#endif
}
/* static */
void nsFocusManager::NotifyFocusStateChange(nsIContent* aContent,
nsIContent* aContentToFocus,
bool aWindowShouldShowFocusRing,
int32_t aFlags,
bool aGettingFocus) {
MOZ_ASSERT_IF(aContentToFocus, !aGettingFocus);
auto* element = Element::FromNode(aContent);
if (!element) {
return;
}
void nsFocusManager::NotifyFocusStateChange(Element* aElement,
Element* aElementToFocus,
int32_t aFlags, bool aGettingFocus,
bool aShouldShowFocusRing) {
MOZ_ASSERT_IF(aElementToFocus, !aGettingFocus);
nsIContent* commonAncestor = nullptr;
if (aContentToFocus && aContentToFocus->IsElement()) {
if (aElementToFocus) {
commonAncestor = nsContentUtils::GetCommonFlattenedTreeAncestor(
aContent, aContentToFocus);
aElement, aElementToFocus);
}
if (aGettingFocus) {
EventStates eventStateToAdd = NS_EVENT_STATE_FOCUS;
if (aWindowShouldShowFocusRing ||
ShouldShowFocusRingForElement(*element, aFlags)) {
if (aShouldShowFocusRing) {
eventStateToAdd |= NS_EVENT_STATE_FOCUSRING;
}
if (aWindowShouldShowFocusRing ||
ShouldMatchFocusVisible(*element, aFlags)) {
eventStateToAdd |= NS_EVENT_STATE_FOCUS_VISIBLE;
}
element->AddStates(eventStateToAdd);
aElement->AddStates(eventStateToAdd);
} else {
EventStates eventStateToRemove = NS_EVENT_STATE_FOCUS |
NS_EVENT_STATE_FOCUSRING |
NS_EVENT_STATE_FOCUS_VISIBLE;
element->RemoveStates(eventStateToRemove);
EventStates eventStateToRemove =
NS_EVENT_STATE_FOCUS | NS_EVENT_STATE_FOCUSRING;
aElement->RemoveStates(eventStateToRemove);
}
for (nsIContent* content = aContent; content && content != commonAncestor;
for (nsIContent* content = aElement; content && content != commonAncestor;
content = content->GetFlattenedTreeParent()) {
Element* element = Element::FromNode(content);
if (!element) {
@ -1169,7 +1221,7 @@ void nsFocusManager::ActivateOrDeactivate(nsPIDOMWindowOuter* aWindow,
}
void nsFocusManager::SetFocusInner(Element* aNewContent, int32_t aFlags,
bool aFocusChanged, bool aAdjustWidget) {
bool aFocusChanged, bool aAdjustWidgets) {
// if the element is not focusable, just return and leave the focus as is
RefPtr<Element> elementToFocus =
FlushAndCheckIfFocusable(aNewContent, aFlags);
@ -1315,7 +1367,10 @@ void nsFocusManager::SetFocusInner(Element* aNewContent, int32_t aFlags,
isElementInActiveWindow, isElementInFocusedWindow, sendFocusEvent));
if (sendFocusEvent) {
RefPtr<Element> oldFocusedElement = mFocusedElement;
Maybe<BlurredElementInfo> blurredInfo;
if (mFocusedElement) {
blurredInfo.emplace(*mFocusedElement);
}
// return if blurring fails or the focus changes during the blur
if (mFocusedWindow) {
// if the focus is being moved to another element in the same document,
@ -1342,14 +1397,14 @@ void nsFocusManager::SetFocusInner(Element* aNewContent, int32_t aFlags,
commonAncestor = GetCommonAncestor(newWindow, mFocusedWindow);
if (!Blur(currentIsSameOrAncestor ? mFocusedWindow.get() : nullptr,
commonAncestor, !isElementInFocusedWindow, aAdjustWidget,
commonAncestor, !isElementInFocusedWindow, aAdjustWidgets,
elementToFocus)) {
return;
}
}
Focus(newWindow, elementToFocus, aFlags, !isElementInFocusedWindow,
aFocusChanged, false, aAdjustWidget, oldFocusedElement);
aFocusChanged, false, aAdjustWidgets, blurredInfo);
} else {
// otherwise, for inactive windows and when the caller cannot steal the
// focus, update the node in the window, and raise the window if desired.
@ -1371,7 +1426,9 @@ void nsFocusManager::SetFocusInner(Element* aNewContent, int32_t aFlags,
// update the commands even when inactive so that the attributes for that
// window are up to date.
if (allowFrameSwitch) newWindow->UpdateCommands(u"focus"_ns, nullptr, 0);
if (allowFrameSwitch) {
newWindow->UpdateCommands(u"focus"_ns, nullptr, 0);
}
if (aFlags & FLAG_RAISE) RaiseWindow(newRootWindow);
}
@ -1475,16 +1532,22 @@ void nsFocusManager::AdjustWindowFocus(nsPIDOMWindowOuter* aWindow,
}
bool nsFocusManager::IsWindowVisible(nsPIDOMWindowOuter* aWindow) {
if (!aWindow || aWindow->IsFrozen()) return false;
if (!aWindow || aWindow->IsFrozen()) {
return false;
}
// Check if the inner window is frozen as well. This can happen when a focus
// change occurs while restoring a previous page.
nsPIDOMWindowInner* innerWindow = aWindow->GetCurrentInnerWindow();
if (!innerWindow || innerWindow->IsFrozen()) return false;
if (!innerWindow || innerWindow->IsFrozen()) {
return false;
}
nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell();
nsCOMPtr<nsIBaseWindow> baseWin(do_QueryInterface(docShell));
if (!baseWin) return false;
if (!baseWin) {
return false;
}
bool visible = false;
baseWin->GetVisibility(&visible);
@ -1509,7 +1572,9 @@ bool nsFocusManager::IsNonFocusableRoot(nsIContent* aContent) {
Element* nsFocusManager::FlushAndCheckIfFocusable(Element* aElement,
uint32_t aFlags) {
if (!aElement) return nullptr;
if (!aElement) {
return nullptr;
}
nsCOMPtr<Document> doc = aElement->GetComposedDoc();
// can't focus elements that are not in documents
@ -1585,7 +1650,7 @@ Element* nsFocusManager::FlushAndCheckIfFocusable(Element* aElement,
bool nsFocusManager::Blur(nsPIDOMWindowOuter* aWindowToClear,
nsPIDOMWindowOuter* aAncestorWindowToFocus,
bool aIsLeavingDocument, bool aAdjustWidgets,
nsIContent* aContentToFocus) {
Element* aElementToFocus) {
LOGFOCUS(("<<Blur begin>>"));
// hold a reference to the focused content, which may be null
@ -1635,7 +1700,6 @@ bool nsFocusManager::Blur(nsPIDOMWindowOuter* aWindowToClear,
// now adjust the actual focus, by clearing the fields in the focus manager
// and in the window.
mFocusedElement = nullptr;
bool shouldShowFocusRing = window->ShouldShowFocusRing();
if (aWindowToClear) aWindowToClear->SetFocusedElement(nullptr);
LOGCONTENT("Element %s has been blurred", element.get());
@ -1645,8 +1709,7 @@ bool nsFocusManager::Blur(nsPIDOMWindowOuter* aWindowToClear,
element && element->IsInComposedDoc() && !IsNonFocusableRoot(element);
if (element) {
if (sendBlurEvent) {
NotifyFocusStateChange(element, aContentToFocus, shouldShowFocusRing, 0,
false);
NotifyFocusStateChange(element, aElementToFocus, 0, false, false);
}
// if an object/plug-in/remote browser is being blurred, move the system
@ -1702,11 +1765,12 @@ bool nsFocusManager::Blur(nsPIDOMWindowOuter* aWindowToClear,
// if there is an active window, update commands. If there isn't an active
// window, then this was a blur caused by the active window being lowered,
// so there is no need to update the commands
if (mActiveWindow)
if (mActiveWindow) {
window->UpdateCommands(u"focus"_ns, nullptr, 0);
}
SendFocusOrBlurEvent(eBlur, presShell, element->GetComposedDoc(), element,
1, false, false, aContentToFocus);
1, false, false, aElementToFocus);
}
// if we are leaving the document or the window was lowered, make the caret
@ -1782,21 +1846,27 @@ void nsFocusManager::ActivateRemoteFrameIfNeeded(Element& aElement) {
}
}
void nsFocusManager::Focus(nsPIDOMWindowOuter* aWindow, Element* aElement,
uint32_t aFlags, bool aIsNewDocument,
bool aFocusChanged, bool aWindowRaised,
bool aAdjustWidgets, nsIContent* aContentLostFocus) {
void nsFocusManager::Focus(
nsPIDOMWindowOuter* aWindow, Element* aElement, uint32_t aFlags,
bool aIsNewDocument, bool aFocusChanged, bool aWindowRaised,
bool aAdjustWidgets, const Maybe<BlurredElementInfo>& aBlurredElementInfo) {
LOGFOCUS(("<<Focus begin>>"));
if (!aWindow) return;
if (aElement && (aElement == mFirstFocusEvent || aElement == mFirstBlurEvent))
if (!aWindow) {
return;
}
if (aElement &&
(aElement == mFirstFocusEvent || aElement == mFirstBlurEvent)) {
return;
}
// Keep a reference to the presShell since dispatching the DOM event may
// cause the document to be destroyed.
nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell();
if (!docShell) return;
if (!docShell) {
return;
}
RefPtr<PresShell> presShell = docShell->GetPresShell();
if (!presShell) {
@ -1848,7 +1918,9 @@ void nsFocusManager::Focus(nsPIDOMWindowOuter* aWindow, Element* aElement,
}
// indicate that the window has taken focus.
if (aWindow->TakeFocus(true, focusMethod)) aIsNewDocument = true;
if (aWindow->TakeFocus(true, focusMethod)) {
aIsNewDocument = true;
}
SetFocusedWindowInternal(aWindow);
@ -1859,7 +1931,9 @@ void nsFocusManager::Focus(nsPIDOMWindowOuter* aWindow, Element* aElement,
if (aElement) {
nsIFrame* contentFrame = aElement->GetPrimaryFrame();
nsIObjectFrame* objectFrame = do_QueryFrame(contentFrame);
if (objectFrame) objectFrameWidget = objectFrame->GetWidget();
if (objectFrame) {
objectFrameWidget = objectFrame->GetWidget();
}
}
if (aAdjustWidgets && !objectFrameWidget && !sTestMode) {
if (nsViewManager* vm = presShell->GetViewManager()) {
@ -1898,21 +1972,26 @@ void nsFocusManager::Focus(nsPIDOMWindowOuter* aWindow, Element* aElement,
mFocusedElement = aElement;
nsIContent* focusedNode = aWindow->GetFocusedElement();
bool isRefocus = focusedNode && focusedNode == aElement;
const bool sendFocusEvent = aElement && aElement->IsInComposedDoc() &&
!IsNonFocusableRoot(aElement);
const bool isRefocus = focusedNode && focusedNode == aElement;
const bool shouldShowFocusRing =
sendFocusEvent &&
ShouldMatchFocusVisible(
aWindow, *aElement, aFlags, aBlurredElementInfo, isRefocus,
isRefocus && aWindow->FocusedElementShowedOutline());
aWindow->SetFocusedElement(aElement, focusMethod);
aWindow->SetFocusedElement(aElement, focusMethod, false,
shouldShowFocusRing);
// if the focused element changed, scroll it into view
if (aElement && aFocusChanged) {
ScrollIntoView(presShell, aElement, aFlags);
}
bool sendFocusEvent = aElement && aElement->IsInComposedDoc() &&
!IsNonFocusableRoot(aElement);
nsPresContext* presContext = presShell->GetPresContext();
if (sendFocusEvent) {
NotifyFocusStateChange(aElement, nullptr, aWindow->ShouldShowFocusRing(),
aFlags, /* aGettingFocus = */ true);
NotifyFocusStateChange(aElement, nullptr, aFlags,
/* aGettingFocus = */ true, shouldShowFocusRing);
// if this is an object/plug-in/remote browser, focus its widget. Note
// that we might no longer be in the same document, due to the events we
@ -1933,12 +2012,15 @@ void nsFocusManager::Focus(nsPIDOMWindowOuter* aWindow, Element* aElement,
// as long as this focus wasn't because a window was raised, update the
// commands
// XXXndeakin P2 someone could adjust the focus during the update
if (!aWindowRaised)
if (!aWindowRaised) {
aWindow->UpdateCommands(u"focus"_ns, nullptr, 0);
}
SendFocusOrBlurEvent(eFocus, presShell, aElement->GetComposedDoc(),
aElement, aFlags & FOCUSMETHOD_MASK, aWindowRaised,
isRefocus, aContentLostFocus);
SendFocusOrBlurEvent(
eFocus, presShell, aElement->GetComposedDoc(), aElement,
aFlags & FOCUSMETHOD_MASK, aWindowRaised, isRefocus,
aBlurredElementInfo ? aBlurredElementInfo->mElement.get()
: nullptr);
} else {
IMEStateManager::OnChangeFocus(presContext, nullptr,
GetFocusMoveActionCause(aFlags));
@ -1969,7 +2051,9 @@ void nsFocusManager::Focus(nsPIDOMWindowOuter* aWindow, Element* aElement,
GetFocusMoveActionCause(aFlags));
}
if (!aWindowRaised) aWindow->UpdateCommands(u"focus"_ns, nullptr, 0);
if (!aWindowRaised) {
aWindow->UpdateCommands(u"focus"_ns, nullptr, 0);
}
}
// update the caret visibility and position to match the newly focused
@ -1982,7 +2066,9 @@ void nsFocusManager::Focus(nsPIDOMWindowOuter* aWindow, Element* aElement,
UpdateCaret(aFocusChanged && !(aFlags & FLAG_BYMOUSE), aIsNewDocument,
mFocusedElement);
if (clearFirstFocusEvent) mFirstFocusEvent = nullptr;
if (clearFirstFocusEvent) {
mFirstFocusEvent = nullptr;
}
}
class FocusBlurEvent : public Runnable {
@ -2217,10 +2303,14 @@ void nsFocusManager::RaiseWindow(nsPIDOMWindowOuter* aWindow) {
nsCOMPtr<nsPIDOMWindowOuter> childWindow;
GetFocusedDescendant(aWindow, eIncludeAllDescendants,
getter_AddRefs(childWindow));
if (!childWindow) childWindow = aWindow;
if (!childWindow) {
childWindow = aWindow;
}
nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell();
if (!docShell) return;
if (!docShell) {
return;
}
PresShell* presShell = docShell->GetPresShell();
if (!presShell) {
@ -2230,7 +2320,9 @@ void nsFocusManager::RaiseWindow(nsPIDOMWindowOuter* aWindow) {
if (nsViewManager* vm = presShell->GetViewManager()) {
nsCOMPtr<nsIWidget> widget;
vm->GetRootWidget(getter_AddRefs(widget));
if (widget) widget->SetFocus(nsIWidget::Raise::Yes);
if (widget) {
widget->SetFocus(nsIWidget::Raise::Yes);
}
}
#else
nsCOMPtr<nsIBaseWindow> treeOwnerAsWin =
@ -2238,7 +2330,9 @@ void nsFocusManager::RaiseWindow(nsPIDOMWindowOuter* aWindow) {
if (treeOwnerAsWin) {
nsCOMPtr<nsIWidget> widget;
treeOwnerAsWin->GetMainWidget(getter_AddRefs(widget));
if (widget) widget->SetFocus(nsIWidget::Raise::Yes);
if (widget) {
widget->SetFocus(nsIWidget::Raise::Yes);
}
}
#endif
}
@ -2251,7 +2345,9 @@ void nsFocusManager::UpdateCaret(bool aMoveCaretToFocus, bool aUpdateVisibility,
nsIContent* aContent) {
LOGFOCUS(("Update Caret: %d %d", aMoveCaretToFocus, aUpdateVisibility));
if (!mFocusedWindow) return;
if (!mFocusedWindow) {
return;
}
// this is called when a document is focused or when the caretbrowsing
// preference is changed
@ -2285,14 +2381,18 @@ void nsFocusManager::UpdateCaret(bool aMoveCaretToFocus, bool aUpdateVisibility,
doc->GetEditingState() == Document::EditingState::eContentEditable;
bool isFocusEditable = aContent && aContent->HasFlag(NODE_IS_EDITABLE);
if (!isContentEditableDoc || isFocusEditable) return;
if (!isContentEditableDoc || isFocusEditable) {
return;
}
}
if (!isEditable && aMoveCaretToFocus) {
MoveCaretToFocus(presShell, aContent);
}
if (!aUpdateVisibility) return;
if (!aUpdateVisibility) {
return;
}
// XXXndeakin this doesn't seem right. It should be checking for this only
// on the nearest ancestor frame which is a chrome frame. But this is
@ -2352,17 +2452,23 @@ nsresult nsFocusManager::SetCaretVisible(PresShell* aPresShell, bool aVisible,
// Return early if there is no caret. This can happen for the testcase
// for bug 308025 where a window is closed in a blur handler.
RefPtr<nsCaret> caret = aPresShell->GetCaret();
if (!caret) return NS_OK;
if (!caret) {
return NS_OK;
}
bool caretVisible = caret->IsVisible();
if (!aVisible && !caretVisible) return NS_OK;
if (!aVisible && !caretVisible) {
return NS_OK;
}
RefPtr<nsFrameSelection> frameSelection;
if (aContent) {
NS_ASSERTION(aContent->GetComposedDoc() == aPresShell->GetDocument(),
"Wrong document?");
nsIFrame* focusFrame = aContent->GetPrimaryFrame();
if (focusFrame) frameSelection = focusFrame->GetFrameSelection();
if (focusFrame) {
frameSelection = focusFrame->GetFrameSelection();
}
}
RefPtr<nsFrameSelection> docFrameSelection = aPresShell->FrameSelection();
@ -2618,19 +2724,22 @@ nsresult nsFocusManager::DetermineElementToMoveFocus(
int32_t tabIndex = forward ? 1 : 0;
if (startContent) {
nsIFrame* frame = startContent->GetPrimaryFrame();
if (startContent->IsHTMLElement(nsGkAtoms::area))
if (startContent->IsHTMLElement(nsGkAtoms::area)) {
startContent->IsFocusable(&tabIndex);
else if (frame)
} else if (frame) {
frame->IsFocusable(&tabIndex, 0);
else
} else {
startContent->IsFocusable(&tabIndex);
}
// if the current element isn't tabbable, ignore the tabindex and just
// look for the next element. The root content won't have a tabindex
// so just treat this as the beginning of the tab order.
if (tabIndex < 0) {
tabIndex = 1;
if (startContent != rootContent) ignoreTabIndex = true;
if (startContent != rootContent) {
ignoreTabIndex = true;
}
}
// check if the focus is currently inside a popup. Elements such as the
@ -2666,7 +2775,9 @@ nsresult nsFocusManager::DetermineElementToMoveFocus(
// if there is no focus, yet a panel is open, focus the first item in
// the panel
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
if (pm) popupFrame = pm->GetTopPopup(ePopupTypePanel);
if (pm) {
popupFrame = pm->GetTopPopup(ePopupTypePanel);
}
}
#endif
if (popupFrame) {
@ -2813,7 +2924,9 @@ nsresult nsFocusManager::DetermineElementToMoveFocus(
ignoreTabIndex = false;
if (aNoParentTraversal) {
if (startContent == rootContent) return NS_OK;
if (startContent == rootContent) {
return NS_OK;
}
startContent = rootContent;
tabIndex = forward ? 1 : 0;
@ -2875,10 +2988,11 @@ nsresult nsFocusManager::DetermineElementToMoveFocus(
// If the tree owner took the focus, blur the current element.
if (tookFocus) {
nsCOMPtr<nsPIDOMWindowOuter> window = docShell->GetWindow();
if (window->GetFocusedElement() == mFocusedElement)
if (window->GetFocusedElement() == mFocusedElement) {
Blur(mFocusedWindow, nullptr, true, true);
else
} else {
window->SetFocusedElement(nullptr);
}
return NS_OK;
}
@ -2911,7 +3025,9 @@ nsresult nsFocusManager::DetermineElementToMoveFocus(
// wrapped all the way around and didn't find anything to move the focus
// to, so just break out
if (startContent == originalStartContent) break;
if (startContent == originalStartContent) {
break;
}
}
return NS_OK;
@ -3604,10 +3720,11 @@ nsresult nsFocusManager::GetNextTabbableContent(
// and the end of the span, and the span would end up getting focused
// again.
do {
if (aForward)
if (aForward) {
frameTraversal->Next();
else
} else {
frameTraversal->Prev();
}
frame = static_cast<nsIFrame*>(frameTraversal->CurrentItem());
} while (frame && frame->GetPrevContinuation());
}
@ -3708,7 +3825,9 @@ nsIContent* nsFocusManager::GetNextTabbableMapArea(bool aForward,
MOZ_ASSERT(imgElement);
nsCOMPtr<nsIContent> mapContent = imgElement->FindImageMap();
if (!mapContent) return nullptr;
if (!mapContent) {
return nullptr;
}
uint32_t count = mapContent->GetChildCount();
// First see if the the start content is in this map
@ -3976,7 +4095,9 @@ void nsFocusManager::GetFocusInSelection(nsPIDOMWindowOuter* aWindow,
continue;
}
if (selectionNode == endSelectionNode) break;
if (selectionNode == endSelectionNode) {
break;
}
testNode = selectionNode->GetNextSibling();
if (testNode) {
selectionNode = testNode;
@ -3997,7 +4118,9 @@ void nsFocusManager::GetFocusInSelection(nsPIDOMWindowOuter* aWindow,
break;
}
selectionNode = testNode->GetNextSibling();
if (selectionNode) break;
if (selectionNode) {
break;
}
selectionNode = testNode;
} while (true);
} while (selectionNode && selectionNode != endSelectionNode);

View File

@ -179,6 +179,53 @@ class nsFocusManager final : public nsIFocusManager,
*/
void ActivateRemoteFrameIfNeeded(mozilla::dom::Element&);
/**
* Raises the top-level window aWindow at the widget level.
*/
void RaiseWindow(nsPIDOMWindowOuter* aWindow);
/**
* Called when a window has been raised.
*/
void WindowRaised(mozIDOMWindowProxy* aWindow);
/**
* Called when a window has been lowered.
*/
void WindowLowered(mozIDOMWindowProxy* aWindow);
/**
* Called when a new document in a window is shown.
*
* If aNeedsFocus is true, then focus events are expected to be fired on the
* window if this window is in the focused window chain.
*/
void WindowShown(mozIDOMWindowProxy* aWindow, bool aNeedsFocus);
/**
* Called when a document in a window has been hidden or otherwise can no
* longer accept focus.
*/
void WindowHidden(mozIDOMWindowProxy* aWindow);
/**
* Fire any events that have been delayed due to synchronized actions.
*/
void FireDelayedEvents(Document* aDocument);
/**
* Used in a child process to indicate that the parent window is now
* active or deactive.
*/
void ParentActivated(mozIDOMWindowProxy* aWindow, bool aActive);
/**
* Indicate that a plugin wishes to take the focus. This is similar to a
* normal focus except that the widget focus is not changed. Updating the
* widget focus state is the responsibility of the caller.
*/
nsresult FocusPlugin(mozilla::dom::Element* aPlugin);
static uint32_t FocusOptionsToFocusManagerFlags(
const mozilla::dom::FocusOptions& aOptions);
@ -203,6 +250,14 @@ class nsFocusManager final : public nsIFocusManager,
static void MarkUncollectableForCCGeneration(uint32_t aGeneration);
struct BlurredElementInfo {
const mozilla::OwningNonNull<mozilla::dom::Element> mElement;
const bool mHadRing;
explicit BlurredElementInfo(mozilla::dom::Element&);
~BlurredElementInfo();
};
protected:
nsFocusManager();
~nsFocusManager();
@ -311,7 +366,7 @@ class nsFocusManager final : public nsIFocusManager,
MOZ_CAN_RUN_SCRIPT_BOUNDARY
bool Blur(nsPIDOMWindowOuter* aWindowToClear,
nsPIDOMWindowOuter* aAncestorWindowToFocus, bool aIsLeavingDocument,
bool aAdjustWidget, nsIContent* aContentToFocus = nullptr);
bool aAdjustWidget, mozilla::dom::Element* aElementToFocus = nullptr);
/**
* Focus an element in the active window and child frame.
@ -343,7 +398,7 @@ class nsFocusManager final : public nsIFocusManager,
void Focus(nsPIDOMWindowOuter* aWindow, mozilla::dom::Element* aContent,
uint32_t aFlags, bool aIsNewDocument, bool aFocusChanged,
bool aWindowRaised, bool aAdjustWidget,
nsIContent* aContentLostFocus = nullptr);
const mozilla::Maybe<BlurredElementInfo>& = mozilla::Nothing());
/**
* Send a focus or blur event at aTarget. It may be added to the delayed
@ -403,11 +458,6 @@ class nsFocusManager final : public nsIFocusManager,
void ScrollIntoView(mozilla::PresShell* aPresShell, nsIContent* aContent,
uint32_t aFlags);
/**
* Raises the top-level window aWindow at the widget level.
*/
void RaiseWindow(nsPIDOMWindowOuter* aWindow);
/**
* Updates the caret positon and visibility to match the focus.
*
@ -616,18 +666,19 @@ class nsFocusManager final : public nsIFocusManager,
nsIContent** aFocusedContent);
private:
// Notify that the focus state of aContent has changed. Note that
// we need to pass in whether the window should show a focus ring
// before the SetFocusedNode call on it happened when losing focus
// and after the SetFocusedNode call when gaining focus, which is
// why that information needs to be an explicit argument instead of
// just passing in the window and asking it whether it should show
// focus rings: in the losing focus case that information could be
// wrong..
static void NotifyFocusStateChange(nsIContent* aContent,
nsIContent* aContentToFocus,
bool aWindowShouldShowFocusRing,
int32_t aFlags, bool aGettingFocus);
// Notify that the focus state of aElement has changed. Note that we need to
// pass in whether the window should show a focus ring before the
// SetFocusedNode call on it happened when losing focus and after the
// SetFocusedNode call when gaining focus, which is why that information needs
// to be an explicit argument instead of just passing in the window and asking
// it whether it should show focus rings: in the losing focus case that
// information could be wrong.
//
// aShouldShowFocusRing is only relevant if aGettingFocus is true.
static void NotifyFocusStateChange(mozilla::dom::Element* aElement,
mozilla::dom::Element* aElementToFocus,
int32_t aFlags, bool aGettingFocus,
bool aShouldShowFocusRing);
void SetFocusedWindowInternal(nsPIDOMWindowOuter* aWindow);

View File

@ -33,7 +33,7 @@
#include "nsIScrollableFrame.h"
#include "nsSubDocumentFrame.h"
#include "nsError.h"
#include "nsIXULWindow.h"
#include "nsIAppWindow.h"
#include "nsIMozBrowserFrame.h"
#include "nsIScriptError.h"
#include "nsGlobalWindow.h"
@ -427,11 +427,6 @@ void nsFrameLoader::LoadFrame(bool aOriginalSrc) {
return;
}
if (doc->IsLoadedAsInteractiveData()) {
// XBL bindings doc shouldn't load sub-documents.
return;
}
nsIURI* base_uri = mOwnerContent->GetBaseURI();
auto encoding = doc->GetDocumentCharacterSet();
@ -494,8 +489,8 @@ nsresult nsFrameLoader::LoadURI(nsIURI* aURI,
void nsFrameLoader::ResumeLoad(uint64_t aPendingSwitchID) {
Document* doc = mOwnerContent->OwnerDoc();
if (doc->IsStaticDocument() || doc->IsLoadedAsInteractiveData()) {
// Static & XBL bindings doc shouldn't load sub-documents.
if (doc->IsStaticDocument()) {
// Static doc shouldn't load sub-documents.
return;
}
@ -2631,7 +2626,7 @@ bool nsFrameLoader::TryRemoteBrowser() {
!parentOwner) {
return false;
}
nsCOMPtr<nsIXULWindow> window(do_GetInterface(parentOwner));
nsCOMPtr<nsIAppWindow> window(do_GetInterface(parentOwner));
if (window && NS_FAILED(window->GetChromeFlags(&chromeFlags))) {
return false;
}

View File

@ -235,7 +235,7 @@ nsresult nsSelectionCommandsBase::GetSelectionControllerFromWindow(
// Helpers for nsSelectMoveScrollCommand and nsPhysicalSelectMoveScrollCommand
static void AdjustFocusAfterCaretMove(nsPIDOMWindowOuter* aWindow) {
// adjust the focus to the new caret position
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm) {
RefPtr<dom::Element> result;
fm->MoveFocus(aWindow, nullptr, nsIFocusManager::MOVEFOCUS_CARET,

View File

@ -294,9 +294,6 @@
# include "nsIWebBrowserPrint.h"
#endif
#include "nsBindingManager.h"
#include "nsXBLService.h"
#ifdef HAVE_SIDEBAR
# include "mozilla/dom/ExternalBinding.h"
#endif
@ -1110,13 +1107,6 @@ void nsGlobalWindowInner::ShutDown() {
sInnerWindowsById = nullptr;
}
// static
void nsGlobalWindowInner::CleanupCachedXBLHandlers() {
if (mCachedXBLPrototypeHandlers && mCachedXBLPrototypeHandlers->Count() > 0) {
mCachedXBLPrototypeHandlers->Clear();
}
}
void nsGlobalWindowInner::FreeInnerObjects() {
if (IsDying()) {
return;
@ -1206,8 +1196,6 @@ void nsGlobalWindowInner::FreeInnerObjects() {
NotifyWindowIDDestroyed("inner-window-destroyed");
CleanupCachedXBLHandlers();
for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
mAudioContexts[i]->Shutdown();
}
@ -1332,12 +1320,6 @@ NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsGlobalWindowInner)
return true;
}
tmp->mCanSkipCCGeneration = nsCCUncollectableMarker::sGeneration;
if (tmp->mCachedXBLPrototypeHandlers) {
for (auto iter = tmp->mCachedXBLPrototypeHandlers->Iter(); !iter.Done();
iter.Next()) {
iter.Data().exposeToActiveJS();
}
}
if (EventListenerManager* elm = tmp->GetExistingListenerManager()) {
elm->MarkForCC();
}
@ -1473,8 +1455,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindowInner)
JS::SetRealmNonLive(js::GetNonCCWObjectRealm(wrapper));
}
tmp->CleanupCachedXBLHandlers();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mNavigator)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPerformance)
@ -1593,12 +1573,6 @@ void nsGlobalWindowInner::RiskyUnlink() {
#endif
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsGlobalWindowInner)
if (tmp->mCachedXBLPrototypeHandlers) {
for (auto iter = tmp->mCachedXBLPrototypeHandlers->Iter(); !iter.Done();
iter.Next()) {
aCallbacks.Trace(&iter.Data(), "Cached XBL prototype handler", aClosure);
}
}
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRACE_END
@ -2021,11 +1995,6 @@ nsresult nsGlobalWindowInner::PostHandleEvent(EventChainPostVisitor& aVisitor) {
}
}
#endif
// Execute bindingdetached handlers before we tear ourselves
// down.
if (mDoc) {
mDoc->BindingManager()->ExecuteDetachedHandlers();
}
mIsDocumentLoaded = false;
} else if (aVisitor.mEvent->mMessage == eLoad &&
aVisitor.mEvent->IsTrusted()) {
@ -3888,25 +3857,6 @@ void nsGlobalWindowInner::NotifyDOMWindowThawed(nsGlobalWindowInner* aWindow) {
}
}
JSObject* nsGlobalWindowInner::GetCachedXBLPrototypeHandler(
nsXBLPrototypeHandler* aKey) {
JS::Rooted<JSObject*> handler(RootingCx());
if (mCachedXBLPrototypeHandlers) {
mCachedXBLPrototypeHandlers->Get(aKey, handler.address());
}
return handler;
}
void nsGlobalWindowInner::CacheXBLPrototypeHandler(
nsXBLPrototypeHandler* aKey, JS::Handle<JSObject*> aHandler) {
if (!mCachedXBLPrototypeHandlers) {
mCachedXBLPrototypeHandlers = MakeUnique<XBLPrototypeHandlerTable>();
PreserveWrapper(ToSupports(this));
}
mCachedXBLPrototypeHandlers->Put(aKey, aHandler);
}
Element* nsGlobalWindowInner::GetFrameElement(nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError) {
FORWARD_TO_OUTER_OR_THROW(GetFrameElementOuter, (aSubjectPrincipal), aError,
@ -4105,7 +4055,8 @@ void nsGlobalWindowInner::StopVRActivity() {
void nsGlobalWindowInner::SetFocusedElement(Element* aElement,
uint32_t aFocusMethod,
bool aNeedsFocus) {
bool aNeedsFocus,
bool aWillShowOutline) {
if (aElement && aElement->GetComposedDoc() != mDoc) {
NS_WARNING("Trying to set focus to a node from a wrong document");
return;
@ -4115,13 +4066,17 @@ void nsGlobalWindowInner::SetFocusedElement(Element* aElement,
NS_ASSERTION(!aElement, "Trying to focus cleaned up window!");
aElement = nullptr;
aNeedsFocus = false;
aWillShowOutline = false;
}
if (mFocusedElement != aElement) {
UpdateCanvasFocus(false, aElement);
mFocusedElement = aElement;
// TODO: Maybe this should be set on refocus too?
mFocusMethod = aFocusMethod & FOCUSMETHOD_MASK;
}
mFocusedElementShowedOutlines = aWillShowOutline;
if (mFocusedElement) {
// if a node was focused by a keypress, turn on focus rings for the
// window.
@ -4130,7 +4085,9 @@ void nsGlobalWindowInner::SetFocusedElement(Element* aElement,
}
}
if (aNeedsFocus) mNeedsFocus = aNeedsFocus;
if (aNeedsFocus) {
mNeedsFocus = aNeedsFocus;
}
}
uint32_t nsGlobalWindowInner::GetFocusMethod() { return mFocusMethod; }
@ -4175,7 +4132,7 @@ void nsGlobalWindowInner::SetReadyForFocus() {
bool oldNeedsFocus = mNeedsFocus;
mNeedsFocus = false;
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm) {
fm->WindowShown(GetOuterWindow(), oldNeedsFocus);
}
@ -4186,7 +4143,7 @@ void nsGlobalWindowInner::PageHidden() {
// no longer valid. Use the persisted field to determine if the document
// is being destroyed.
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm) {
fm->WindowHidden(GetOuterWindow());
}
@ -7020,6 +6977,14 @@ mozilla::dom::TabGroup* nsGlobalWindowInner::TabGroupInner() {
return tabGroup;
}
// https://html.spec.whatwg.org/#structured-cloning
void nsGlobalWindowInner::StructuredClone(
JSContext* aCx, JS::Handle<JS::Value> aValue,
const StructuredSerializeOptions& aOptions,
JS::MutableHandle<JS::Value> aRetval, ErrorResult& aError) {
nsContentUtils::StructuredClone(aCx, this, aValue, aOptions, aRetval, aError);
}
nsresult nsGlobalWindowInner::Dispatch(
TaskCategory aCategory, already_AddRefed<nsIRunnable>&& aRunnable) {
MOZ_RELEASE_ASSERT(NS_IsMainThread());

View File

@ -452,8 +452,6 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
static void ShutDown();
static bool IsCallerChrome();
void CleanupCachedXBLHandlers();
friend class WindowStateHolder;
NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(
@ -465,12 +463,6 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
void RiskyUnlink();
#endif
virtual JSObject* GetCachedXBLPrototypeHandler(
nsXBLPrototypeHandler* aKey) override;
virtual void CacheXBLPrototypeHandler(
nsXBLPrototypeHandler* aKey, JS::Handle<JSObject*> aHandler) override;
virtual bool TakeFocus(bool aFocus, uint32_t aFocusMethod) override;
virtual void SetReadyForFocus() override;
virtual void PageHidden() override;
@ -894,6 +886,11 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
int32_t aSx, int32_t aSy, int32_t aSw, int32_t aSh,
mozilla::ErrorResult& aRv);
void StructuredClone(JSContext* aCx, JS::Handle<JS::Value> aValue,
const mozilla::dom::StructuredSerializeOptions& aOptions,
JS::MutableHandle<JS::Value> aRetval,
mozilla::ErrorResult& aError);
// ChromeWindow bits. Do NOT call these unless your window is in
// fact chrome.
uint16_t WindowState();
@ -1122,13 +1119,13 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
bool IsInModalState();
virtual void SetFocusedElement(mozilla::dom::Element* aElement,
uint32_t aFocusMethod = 0,
bool aNeedsFocus = false) override;
void SetFocusedElement(mozilla::dom::Element* aElement,
uint32_t aFocusMethod = 0, bool aNeedsFocus = false,
bool aWillShowOutline = false) override;
virtual uint32_t GetFocusMethod() override;
uint32_t GetFocusMethod() override;
virtual bool ShouldShowFocusRing() override;
bool ShouldShowFocusRing() override;
// Inner windows only.
void UpdateCanvasFocus(bool aFocusChanged, nsIContent* aNewContent);
@ -1364,7 +1361,7 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
uint32_t mSerial;
#endif
// the method that was used to focus mFocusedNode
// the method that was used to focus mFocusedElement
uint32_t mFocusMethod;
// The current idle request callback handle
@ -1378,10 +1375,6 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
RefPtr<nsDOMOfflineResourceList> mApplicationCache;
using XBLPrototypeHandlerTable =
nsJSThingHashtable<nsPtrHashKey<nsXBLPrototypeHandler>, JSObject*>;
mozilla::UniquePtr<XBLPrototypeHandlerTable> mCachedXBLPrototypeHandlers;
RefPtr<mozilla::dom::IDBFactory> mIndexedDB;
// This counts the number of windows that have been opened in rapid succession
@ -1466,11 +1459,9 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
// Members in the mChromeFields member should only be used in chrome windows.
// All accesses to this field should be guarded by a check of mIsChrome.
struct ChromeFields {
ChromeFields() : mGroupMessageManagers(1) {}
RefPtr<mozilla::dom::ChromeMessageBroadcaster> mMessageManager;
nsRefPtrHashtable<nsStringHashKey, mozilla::dom::ChromeMessageBroadcaster>
mGroupMessageManagers;
mGroupMessageManagers{1};
} mChromeFields;
// These fields are used by the inner and outer windows to prevent

View File

@ -20,6 +20,7 @@
#include "nsISecureBrowserUI.h"
#include "nsIWebProgressListener.h"
#include "mozilla/AntiTrackingCommon.h"
#include "mozilla/dom/BrowserChild.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/BrowsingContextBinding.h"
#include "mozilla/dom/ContentFrameMessageManager.h"
@ -140,6 +141,7 @@
#include "nsDOMWindowUtils.h"
#include "nsIWindowWatcher.h"
#include "nsPIWindowWatcher.h"
#include "nsIAppWindow.h"
#include "nsIContentViewer.h"
#include "nsIScriptError.h"
#include "nsIControllers.h"
@ -153,7 +155,6 @@
#include "mozilla/EventStateManager.h"
#include "nsIObserverService.h"
#include "nsFocusManager.h"
#include "nsIXULWindow.h"
#include "nsServiceManagerUtils.h"
#include "mozilla/dom/CustomEvent.h"
#include "nsIScreenManager.h"
@ -171,11 +172,8 @@
#include "nsNetCID.h"
#include "nsIArray.h"
#include "XULDocument.h"
#include "nsIDOMXULCommandDispatcher.h"
#include "nsBindingManager.h"
#include "nsXBLService.h"
#include "mozilla/GlobalKeyListener.h"
#include "nsIDragService.h"
@ -1766,7 +1764,7 @@ void nsGlobalWindowOuter::SetInitialPrincipalToSubject(
// We should never create windows with an expanded principal.
// If we have a system principal, make sure we're not using it for a content
// docshell.
// NOTE: Please keep this logic in sync with nsWebShellWindow::Initialize().
// NOTE: Please keep this logic in sync with AppWindow::Initialize().
if (nsContentUtils::IsExpandedPrincipal(newWindowPrincipal) ||
(newWindowPrincipal->IsSystemPrincipal() &&
GetDocShell()->ItemType() != nsIDocShellTreeItem::typeChrome)) {
@ -3557,42 +3555,55 @@ void nsGlobalWindowOuter::SetNameOuter(const nsAString& aName,
}
// Helper functions used by many methods below.
int32_t nsGlobalWindowOuter::DevToCSSIntPixels(int32_t px) {
if (!mDocShell) return px; // assume 1:1
RefPtr<nsPresContext> presContext = mDocShell->GetPresContext();
if (!presContext) return px;
return presContext->DevPixelsToIntCSSPixels(px);
int32_t nsGlobalWindowOuter::DevToCSSIntPixelsForBaseWindow(
int32_t aDevicePixels, nsIBaseWindow* aWindow) {
MOZ_ASSERT(aWindow);
double scale;
aWindow->GetUnscaledDevicePixelsPerCSSPixel(&scale);
double zoom = 1.0;
if (mDocShell && mDocShell->GetPresContext()) {
zoom = mDocShell->GetPresContext()->GetFullZoom();
}
return std::floor(aDevicePixels / scale / zoom + 0.5);
}
int32_t nsGlobalWindowOuter::CSSToDevIntPixels(int32_t px) {
if (!mDocShell) return px; // assume 1:1
RefPtr<nsPresContext> presContext = mDocShell->GetPresContext();
if (!presContext) return px;
return presContext->CSSPixelsToDevPixels(px);
nsIntSize nsGlobalWindowOuter::DevToCSSIntPixelsForBaseWindow(
nsIntSize aDeviceSize, nsIBaseWindow* aWindow) {
MOZ_ASSERT(aWindow);
double scale;
aWindow->GetUnscaledDevicePixelsPerCSSPixel(&scale);
double zoom = 1.0;
if (mDocShell && mDocShell->GetPresContext()) {
zoom = mDocShell->GetPresContext()->GetFullZoom();
}
return nsIntSize::Round(
static_cast<float>(aDeviceSize.width / scale / zoom),
static_cast<float>(aDeviceSize.height / scale / zoom));
}
nsIntSize nsGlobalWindowOuter::DevToCSSIntPixels(nsIntSize px) {
if (!mDocShell) return px; // assume 1:1
RefPtr<nsPresContext> presContext = mDocShell->GetPresContext();
if (!presContext) return px;
return nsIntSize(presContext->DevPixelsToIntCSSPixels(px.width),
presContext->DevPixelsToIntCSSPixels(px.height));
int32_t nsGlobalWindowOuter::CSSToDevIntPixelsForBaseWindow(
int32_t aCSSPixels, nsIBaseWindow* aWindow) {
MOZ_ASSERT(aWindow);
double scale;
aWindow->GetUnscaledDevicePixelsPerCSSPixel(&scale);
double zoom = 1.0;
if (mDocShell && mDocShell->GetPresContext()) {
zoom = mDocShell->GetPresContext()->GetFullZoom();
}
return std::floor(aCSSPixels * scale * zoom + 0.5);
}
nsIntSize nsGlobalWindowOuter::CSSToDevIntPixels(nsIntSize px) {
if (!mDocShell) return px; // assume 1:1
RefPtr<nsPresContext> presContext = mDocShell->GetPresContext();
if (!presContext) return px;
return nsIntSize(presContext->CSSPixelsToDevPixels(px.width),
presContext->CSSPixelsToDevPixels(px.height));
nsIntSize nsGlobalWindowOuter::CSSToDevIntPixelsForBaseWindow(
nsIntSize aCSSSize, nsIBaseWindow* aWindow) {
MOZ_ASSERT(aWindow);
double scale;
aWindow->GetUnscaledDevicePixelsPerCSSPixel(&scale);
double zoom = 1.0;
if (mDocShell && mDocShell->GetPresContext()) {
zoom = mDocShell->GetPresContext()->GetFullZoom();
}
return nsIntSize::Round(static_cast<float>(aCSSSize.width * scale * zoom),
static_cast<float>(aCSSSize.height * scale * zoom));
}
nsresult nsGlobalWindowOuter::GetInnerSize(CSSIntSize& aSize) {
@ -3608,12 +3619,6 @@ nsresult nsGlobalWindowOuter::GetInnerSize(CSSIntSize& aSize) {
return NS_OK;
}
// If the visual viewport has been overriden, return that.
if (presShell->IsVisualViewportSizeSet()) {
aSize = CSSIntRect::FromAppUnitsRounded(presShell->GetVisualViewportSize());
return NS_OK;
}
// Whether or not the css viewport has been overridden, we can get the
// correct value by looking at the visible area of the presContext.
RefPtr<nsViewManager> viewManager = presShell->GetViewManager();
@ -3646,24 +3651,8 @@ void nsGlobalWindowOuter::SetInnerWidthOuter(int32_t aInnerWidth,
CheckSecurityWidthAndHeight(&aInnerWidth, nullptr, aCallerType);
RefPtr<PresShell> presShell = mDocShell->GetPresShell();
// Setting inner width should set the visual viewport. Most of the
// time, this is the same as the CSS viewport, and when we set one,
// we implicitly set both of them. But if
// presShell->IsVisualViewportSizeSet() returns true, that means
// that the two diverge. In that case we only set the visual viewport.
// This mirrors the logic in ::GetInnerSize() and ensures that JS
// behaves sanely when setting and then getting the innerWidth.
if (presShell && presShell->IsVisualViewportSizeSet()) {
CSSSize viewportSize =
CSSRect::FromAppUnits(presShell->GetVisualViewportSize());
viewportSize.width = aInnerWidth;
nsLayoutUtils::SetVisualViewportSize(presShell, viewportSize);
return;
}
// We're going to set both viewports. If the css viewport has been
// overridden, change the css viewport override. The visual viewport
// will adopt this value via the logic in ::GetInnerSize().
// Setting inner width should set the CSS viewport. If the CSS viewport
// has been overridden, change the override.
if (presShell && presShell->GetIsViewportOverridden()) {
nscoord height = 0;
@ -3677,14 +3666,14 @@ void nsGlobalWindowOuter::SetInnerWidthOuter(int32_t aInnerWidth,
return;
}
// Nothing has been overriden, so change the docshell itself, which will
// affect both viewports.
// Nothing has been overriden, so change the docshell itself.
int32_t height = 0;
int32_t unused = 0;
nsCOMPtr<nsIBaseWindow> docShellAsWin(do_QueryInterface(mDocShell));
docShellAsWin->GetSize(&unused, &height);
aError = SetDocShellWidthAndHeight(CSSToDevIntPixels(aInnerWidth), height);
aError = SetDocShellWidthAndHeight(
CSSToDevIntPixelsForBaseWindow(aInnerWidth, docShellAsWin), height);
}
int32_t nsGlobalWindowOuter::GetInnerHeightOuter(ErrorResult& aError) {
@ -3708,24 +3697,8 @@ void nsGlobalWindowOuter::SetInnerHeightOuter(int32_t aInnerHeight,
CheckSecurityWidthAndHeight(nullptr, &aInnerHeight, aCallerType);
RefPtr<PresShell> presShell = mDocShell->GetPresShell();
// Setting inner height should set the visual viewport. Most of the
// time, this is the same as the CSS viewport, and when we set one,
// we implicitly set both of them. But if
// presShell->IsVisualViewportSizeSet() returns true, that means
// that the two diverge. In that case we only set the visual viewport.
// This mirrors the logic in ::GetInnerSize() and ensures that JS
// behaves sanely when setting and then getting the innerHeight.
if (presShell && presShell->IsVisualViewportSizeSet()) {
CSSSize viewportSize =
CSSRect::FromAppUnits(presShell->GetVisualViewportSize());
viewportSize.height = aInnerHeight;
nsLayoutUtils::SetVisualViewportSize(presShell, viewportSize);
return;
}
// We're going to set both viewports. If the css viewport has been
// overridden, change the css viewport override. The visual viewport
// will adopt this value via the logic in ::GetInnerSize().
// Setting inner height should set the CSS viewport. If the CSS viewport
// has been overridden, change the override.
if (presShell && presShell->GetIsViewportOverridden()) {
nscoord width = 0;
@ -3739,14 +3712,14 @@ void nsGlobalWindowOuter::SetInnerHeightOuter(int32_t aInnerHeight,
return;
}
// Nothing has been overriden, so change the docshell itself, which will
// affect both viewports.
// Nothing has been overriden, so change the docshell itself.
int32_t height = 0;
int32_t width = 0;
nsCOMPtr<nsIBaseWindow> docShellAsWin(do_QueryInterface(mDocShell));
docShellAsWin->GetSize(&width, &height);
aError = SetDocShellWidthAndHeight(width, CSSToDevIntPixels(aInnerHeight));
aError = SetDocShellWidthAndHeight(
width, CSSToDevIntPixelsForBaseWindow(aInnerHeight, docShellAsWin));
}
nsIntSize nsGlobalWindowOuter::GetOuterSize(CallerType aCallerType,
@ -3757,23 +3730,13 @@ nsIntSize nsGlobalWindowOuter::GetOuterSize(CallerType aCallerType,
return nsIntSize(size.width, size.height);
}
if (mDoc && mDoc->InRDMPane()) {
CSSIntSize size;
aError = GetInnerSize(size);
// Obtain the current zoom of the presentation shell. The zoom value will
// be used to scale the size of the visual viewport to the device browser's
// outer size values. Once RDM no longer relies on the having the page
// content being embedded in a <iframe mozbrowser>, we can do away with
// this approach and retrieve the size of the frame containing the browser
// content.
RefPtr<nsPresContext> presContext = mDocShell->GetPresContext();
if (presContext) {
float zoom = presContext->GetDeviceFullZoom();
int32_t width = std::round(size.width * zoom);
int32_t height = std::round(size.height * zoom);
return nsIntSize(width, height);
// Windows showing documents in RDM panes and any subframes within them
// return the simulated device size.
if (mDoc) {
Maybe<CSSIntSize> deviceSize = GetRDMDeviceSize(*mDoc);
if (deviceSize.isSome()) {
const CSSIntSize& size = deviceSize.value();
return nsIntSize(size.width, size.height);
}
}
@ -3789,7 +3752,7 @@ nsIntSize nsGlobalWindowOuter::GetOuterSize(CallerType aCallerType,
return nsIntSize();
}
return DevToCSSIntPixels(sizeDevPixels);
return DevToCSSIntPixelsForBaseWindow(sizeDevPixels, treeOwnerAsWin);
}
int32_t nsGlobalWindowOuter::GetOuterWidthOuter(CallerType aCallerType,
@ -3821,7 +3784,8 @@ void nsGlobalWindowOuter::SetOuterSize(int32_t aLengthCSSPixels, bool aIsWidth,
return;
}
int32_t lengthDevPixels = CSSToDevIntPixels(aLengthCSSPixels);
int32_t lengthDevPixels =
CSSToDevIntPixelsForBaseWindow(aLengthCSSPixels, treeOwnerAsWin);
if (aIsWidth) {
width = lengthDevPixels;
} else {
@ -3915,6 +3879,41 @@ nsRect nsGlobalWindowOuter::GetInnerScreenRect() {
return rootFrame->GetScreenRectInAppUnits();
}
Maybe<CSSIntSize> nsGlobalWindowOuter::GetRDMDeviceSize(
const Document& aDocument) {
// RDM device size should reflect the simulated device resolution, and
// be independent of any full zoom or resolution zoom applied to the
// content. To get this value, we get the "unscaled" browser child size,
// and divide by the full zoom. "Unscaled" in this case means unscaled
// from device to screen but it has been affected (multipled) by the
// full zoom and we need to compensate for that.
MOZ_RELEASE_ASSERT(NS_IsMainThread());
// Bug 1576256: This does not work for cross-process subframes.
const Document* topInProcessContentDoc =
aDocument.GetTopLevelContentDocument();
if (topInProcessContentDoc && topInProcessContentDoc->InRDMPane()) {
nsIDocShell* docShell = topInProcessContentDoc->GetDocShell();
if (docShell) {
nsPresContext* presContext = docShell->GetPresContext();
if (presContext) {
nsCOMPtr<nsIBrowserChild> child = docShell->GetBrowserChild();
if (child) {
// We intentionally use GetFullZoom here instead of
// GetDeviceFullZoom, because the unscaledInnerSize is based
// on the full zoom and not the device full zoom (which is
// rounded to result in integer device pixels).
float zoom = presContext->GetFullZoom();
BrowserChild* bc = static_cast<BrowserChild*>(child.get());
CSSSize unscaledSize = bc->GetUnscaledInnerSize();
return Some(CSSIntSize(gfx::RoundedToInt(unscaledSize / zoom)));
}
}
}
}
return Nothing();
}
float nsGlobalWindowOuter::GetMozInnerScreenXOuter(CallerType aCallerType) {
// When resisting fingerprinting, always return 0.
if (nsContentUtils::ResistFingerprinting(aCallerType)) {
@ -3990,7 +3989,7 @@ void nsGlobalWindowOuter::SetScreenXOuter(int32_t aScreenX,
}
CheckSecurityLeftAndTop(&aScreenX, nullptr, aCallerType);
x = CSSToDevIntPixels(aScreenX);
x = CSSToDevIntPixelsForBaseWindow(aScreenX, treeOwnerAsWin);
aError = treeOwnerAsWin->SetPosition(x, y);
@ -4018,7 +4017,7 @@ void nsGlobalWindowOuter::SetScreenYOuter(int32_t aScreenY,
}
CheckSecurityLeftAndTop(nullptr, &aScreenY, aCallerType);
y = CSSToDevIntPixels(aScreenY);
y = CSSToDevIntPixelsForBaseWindow(aScreenY, treeOwnerAsWin);
aError = treeOwnerAsWin->SetPosition(x, y);
@ -4105,22 +4104,23 @@ void nsGlobalWindowOuter::CheckSecurityLeftAndTop(int32_t* aLeft, int32_t* aTop,
rootWindow->FlushPendingNotifications(FlushType::Layout);
}
nsCOMPtr<nsIBaseWindow> treeOwner = GetTreeOwnerWindow();
nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
RefPtr<nsScreen> screen = GetScreen();
if (treeOwner && screen) {
if (treeOwnerAsWin && screen) {
int32_t winLeft, winTop, winWidth, winHeight;
// Get the window size
treeOwner->GetPositionAndSize(&winLeft, &winTop, &winWidth, &winHeight);
treeOwnerAsWin->GetPositionAndSize(&winLeft, &winTop, &winWidth,
&winHeight);
// convert those values to CSS pixels
// XXX four separate retrievals of the prescontext
winLeft = DevToCSSIntPixels(winLeft);
winTop = DevToCSSIntPixels(winTop);
winWidth = DevToCSSIntPixels(winWidth);
winHeight = DevToCSSIntPixels(winHeight);
winLeft = DevToCSSIntPixelsForBaseWindow(winLeft, treeOwnerAsWin);
winTop = DevToCSSIntPixelsForBaseWindow(winTop, treeOwnerAsWin);
winWidth = DevToCSSIntPixelsForBaseWindow(winWidth, treeOwnerAsWin);
winHeight = DevToCSSIntPixelsForBaseWindow(winHeight, treeOwnerAsWin);
// Get the screen dimensions
// XXX This should use nsIScreenManager once it's fully fleshed out.
@ -4646,9 +4646,9 @@ nsresult nsGlobalWindowOuter::SetFullscreenInternal(FullscreenReason aReason,
// Prevent chrome documents which are still loading from resizing
// the window after we set fullscreen mode.
nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
nsCOMPtr<nsIXULWindow> xulWin(do_GetInterface(treeOwnerAsWin));
if (aFullscreen && xulWin) {
xulWin->SetIntrinsicallySized(false);
nsCOMPtr<nsIAppWindow> appWin(do_GetInterface(treeOwnerAsWin));
if (aFullscreen && appWin) {
appWin->SetIntrinsicallySized(false);
}
// Set this before so if widget sends an event indicating its
@ -5159,10 +5159,7 @@ void nsGlobalWindowOuter::FocusOuter() {
// if there is no parent, this must be a toplevel window, so raise the
// window if canFocus is true. If this is a child process, the raise
// window request will get forwarded to the parent by the puppet widget.
DebugOnly<nsresult> rv = fm->SetActiveWindow(this);
MOZ_ASSERT(NS_SUCCEEDED(rv),
"SetActiveWindow only fails if passed null or a non-toplevel "
"window, which is not the case here.");
fm->RaiseWindow(this);
}
}
@ -5187,7 +5184,7 @@ void nsGlobalWindowOuter::BlurOuter() {
siteWindow->Blur();
// if the root is focused, clear the focus
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm && mDoc) {
RefPtr<Element> element;
fm->GetFocusedElementForWindow(this, false, nullptr,
@ -5373,14 +5370,15 @@ void nsGlobalWindowOuter::MoveByOuter(int32_t aXDif, int32_t aYDif,
}
// mild abuse of a "size" object so we don't need more helper functions
nsIntSize cssPos(DevToCSSIntPixels(nsIntSize(x, y)));
nsIntSize cssPos(
DevToCSSIntPixelsForBaseWindow(nsIntSize(x, y), treeOwnerAsWin));
cssPos.width += aXDif;
cssPos.height += aYDif;
CheckSecurityLeftAndTop(&cssPos.width, &cssPos.height, aCallerType);
nsIntSize newDevPos(CSSToDevIntPixels(cssPos));
nsIntSize newDevPos(CSSToDevIntPixelsForBaseWindow(cssPos, treeOwnerAsWin));
aError = treeOwnerAsWin->SetPosition(newDevPos.width, newDevPos.height);
@ -5415,7 +5413,7 @@ void nsGlobalWindowOuter::ResizeToOuter(int32_t aWidth, int32_t aHeight,
nsIntSize cssSize(aWidth, aHeight);
CheckSecurityWidthAndHeight(&cssSize.width, &cssSize.height, aCallerType);
nsIntSize devSz(CSSToDevIntPixels(cssSize));
nsIntSize devSz(CSSToDevIntPixelsForBaseWindow(cssSize, treeOwnerAsWin));
aError = treeOwnerAsWin->SetSize(devSz.width, devSz.height, true);
@ -5450,14 +5448,15 @@ void nsGlobalWindowOuter::ResizeByOuter(int32_t aWidthDif, int32_t aHeightDif,
// into CSS pixels, add the arguments, do the security check, and
// then convert back to device pixels for the call to SetSize.
nsIntSize cssSize(DevToCSSIntPixels(nsIntSize(width, height)));
nsIntSize cssSize(
DevToCSSIntPixelsForBaseWindow(nsIntSize(width, height), treeOwnerAsWin));
cssSize.width += aWidthDif;
cssSize.height += aHeightDif;
CheckSecurityWidthAndHeight(&cssSize.width, &cssSize.height, aCallerType);
nsIntSize newDevSize(CSSToDevIntPixels(cssSize));
nsIntSize newDevSize(CSSToDevIntPixelsForBaseWindow(cssSize, treeOwnerAsWin));
aError = treeOwnerAsWin->SetSize(newDevSize.width, newDevSize.height, true);
@ -5488,8 +5487,8 @@ void nsGlobalWindowOuter::SizeToContentOuter(CallerType aCallerType,
return;
}
int32_t width, height;
aError = cv->GetContentSize(&width, &height);
nsIntSize contentSize;
aError = cv->GetContentSize(&contentSize.width, &contentSize.height);
if (aError.Failed()) {
return;
}
@ -5502,10 +5501,21 @@ void nsGlobalWindowOuter::SizeToContentOuter(CallerType aCallerType,
return;
}
nsIntSize cssSize(DevToCSSIntPixels(nsIntSize(width, height)));
// Don't use DevToCSSIntPixelsForBaseWindow() nor
// CSSToDevIntPixelsForBaseWindow() here because contentSize is comes from
// nsIContentViewer::GetContentSize() and it's computed with nsPresContext so
// that we need to work with nsPresContext here too.
RefPtr<nsPresContext> presContext = cv->GetPresContext();
MOZ_ASSERT(
presContext,
"Should be non-nullptr if nsIContentViewer::GetContentSize() succeeded");
nsIntSize cssSize(presContext->DevPixelsToIntCSSPixels(contentSize.width),
presContext->DevPixelsToIntCSSPixels(contentSize.height));
CheckSecurityWidthAndHeight(&cssSize.width, &cssSize.height, aCallerType);
nsIntSize newDevSize(CSSToDevIntPixels(cssSize));
nsIntSize newDevSize(presContext->CSSPixelsToDevPixels(cssSize.width),
presContext->CSSPixelsToDevPixels(cssSize.height));
nsCOMPtr<nsIDocShell> docShell = mDocShell;
aError =
@ -6050,7 +6060,7 @@ bool nsGlobalWindowOuter::GatherPostMessageData(
if (!callerPrin->IsSystemPrincipal()) {
nsAutoCString asciiOrigin;
callerPrin->GetAsciiOrigin(asciiOrigin);
aOrigin = NS_ConvertUTF8toUTF16(asciiOrigin);
CopyUTF8toUTF16(asciiOrigin, aOrigin);
} else if (callerInnerWin) {
if (!*aCallerDocumentURI) {
return false;
@ -6916,10 +6926,10 @@ void nsGlobalWindowOuter::ActivateOrDeactivate(bool aActivate) {
// Get the top level widget's nsGlobalWindowOuter
nsCOMPtr<nsPIDOMWindowOuter> topLevelWindow;
// widgetListener should be a nsXULWindow
// widgetListener should be an AppWindow
nsIWidgetListener* listener = topLevelWidget->GetWidgetListener();
if (listener) {
nsCOMPtr<nsIXULWindow> window = listener->GetXULWindow();
nsCOMPtr<nsIAppWindow> window = listener->GetAppWindow();
nsCOMPtr<nsIInterfaceRequestor> req(do_QueryInterface(window));
topLevelWindow = do_GetInterface(req);
}
@ -7022,9 +7032,10 @@ void nsGlobalWindowOuter::SetChromeEventHandler(
void nsGlobalWindowOuter::SetFocusedElement(Element* aElement,
uint32_t aFocusMethod,
bool aNeedsFocus) {
FORWARD_TO_INNER_VOID(SetFocusedElement,
(aElement, aFocusMethod, aNeedsFocus));
bool aNeedsFocus,
bool aWillShowOutline) {
FORWARD_TO_INNER_VOID(SetFocusedElement, (aElement, aFocusMethod, aNeedsFocus,
aWillShowOutline));
}
uint32_t nsGlobalWindowOuter::GetFocusMethod() {
@ -7625,7 +7636,7 @@ nsresult nsGlobalWindowOuter::RestoreWindowState(nsISupports* aState) {
// it easy to tell which link was last clicked when going back a page.
Element* focusedElement = inner->GetFocusedElement();
if (nsContentUtils::ContentIsLink(focusedElement)) {
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm) {
// XXXbz Do we need the stack strong ref here?
RefPtr<Element> kungFuDeathGrip(focusedElement);

View File

@ -51,6 +51,7 @@
#include "nsCheapSets.h"
#include "mozilla/dom/ImageBitmapSource.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/dom/BrowsingContext.h"
class nsDocShell;
class nsIArray;
@ -85,7 +86,6 @@ class DOMEventTargetHelper;
class ThrottledEventQueue;
namespace dom {
class BarProp;
class BrowsingContext;
struct ChannelPixelLayout;
class Console;
class Crypto;
@ -869,6 +869,7 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
mozilla::dom::CallerType aCallerType,
mozilla::ErrorResult& aError);
nsRect GetInnerScreenRect();
static Maybe<mozilla::CSSIntSize> GetRDMDeviceSize(const Document& aDocument);
bool IsFrame();
@ -890,33 +891,44 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
}
// Convenience functions for the many methods that need to scale
// from device to CSS pixels or vice versa. Note: if a presentation
// context is not available, they will assume a 1:1 ratio.
// from device to CSS pixels. This computes it with cached scale in
// PresContext which may be not recent information of the widget.
// Note: if PresContext is not available, they will assume a 1:1 ratio.
int32_t DevToCSSIntPixels(int32_t px);
int32_t CSSToDevIntPixels(int32_t px);
nsIntSize DevToCSSIntPixels(nsIntSize px);
nsIntSize CSSToDevIntPixels(nsIntSize px);
virtual void SetFocusedElement(mozilla::dom::Element* aElement,
uint32_t aFocusMethod = 0,
bool aNeedsFocus = false) override;
// Convenience functions for the methods which call methods of nsIBaseWindow
// because it takes/returns device pixels. Unfortunately, mPresContext may
// have older scale value for the corresponding widget. Therefore, these
// helper methods convert between CSS pixels and device pixels with aWindow.
int32_t DevToCSSIntPixelsForBaseWindow(int32_t aDevicePixels,
nsIBaseWindow* aWindow);
nsIntSize DevToCSSIntPixelsForBaseWindow(nsIntSize aDeviceSize,
nsIBaseWindow* aWindow);
int32_t CSSToDevIntPixelsForBaseWindow(int32_t aCSSPixels,
nsIBaseWindow* aWindow);
nsIntSize CSSToDevIntPixelsForBaseWindow(nsIntSize aCSSSize,
nsIBaseWindow* aWindow);
virtual uint32_t GetFocusMethod() override;
void SetFocusedElement(mozilla::dom::Element* aElement,
uint32_t aFocusMethod = 0, bool aNeedsFocus = false,
bool aWillShowOutline = false) override;
virtual bool ShouldShowFocusRing() override;
uint32_t GetFocusMethod() override;
virtual void SetKeyboardIndicators(UIStateChangeType aShowFocusRings)
override;
bool ShouldShowFocusRing() override;
void SetKeyboardIndicators(UIStateChangeType aShowFocusRings) override;
public:
virtual already_AddRefed<nsPIWindowRoot> GetTopWindowRoot() override;
already_AddRefed<nsPIWindowRoot> GetTopWindowRoot() override;
protected:
void NotifyWindowIDDestroyed(const char* aTopic);
void ClearStatus();
virtual void UpdateParentTarget() override;
void UpdateParentTarget() override;
void InitializeShowFocusRings();

View File

@ -19,7 +19,6 @@ class nsAttrValue;
class nsAttrName;
class nsTextFragment;
class nsIFrame;
class nsXBLBinding;
namespace mozilla {
class EventChainPreVisitor;
@ -67,6 +66,7 @@ class nsIContent : public nsINode {
explicit nsIContent(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
: nsINode(std::move(aNodeInfo)) {
MOZ_ASSERT(mNodeInfo);
MOZ_ASSERT(static_cast<nsINode*>(this) == reinterpret_cast<nsINode*>(this));
SetNodeIsContent();
}
#endif // MOZILLA_INTERNAL_API
@ -125,48 +125,28 @@ class nsIContent : public nsINode {
*
* @note the result children order is
* 1. :before generated node
* 2. XBL flattened tree children of this node
* 2. Shadow DOM flattened tree children of this node
* 3. native anonymous nodes
* 4. :after generated node
*/
eAllChildren = 0,
/**
* All XBL explicit children of the node (see
* http://www.w3.org/TR/xbl/#explicit3 ), as well as :before and :after
* anonymous content and native anonymous children.
*
* @note the result children order is
* 1. :before generated node
* 2. XBL explicit children of the node
* 3. native anonymous nodes
* 4. :after generated node
* Skip native anonymous content created for placeholder of HTML input.
*/
eAllButXBL = 1,
/**
* Skip native anonymous content created for placeholder of HTML input,
* used in conjunction with eAllChildren or eAllButXBL.
*/
eSkipPlaceholderContent = 2,
eSkipPlaceholderContent = 1 << 0,
/**
* Skip native anonymous content created by ancestor frames of the root
* element's primary frame, such as scrollbar elements created by the root
* scroll frame.
*/
eSkipDocumentLevelNativeAnonymousContent = 4,
eSkipDocumentLevelNativeAnonymousContent = 1 << 1,
};
/**
* Return either the XBL explicit children of the node or the XBL flattened
* tree children of the node, depending on the filter, as well as
* native anonymous children.
*
* @note calling this method with eAllButXBL will return children that are
* also in the eAllButXBL and eAllChildren child lists of other descendants
* of this node in the tree, but those other nodes cannot be reached from the
* eAllButXBL child list.
* Return the flattened tree children of the node, depending on the filter, as
* well as native anonymous children.
*/
virtual already_AddRefed<nsINodeList> GetChildren(uint32_t aFilter) = 0;
@ -175,7 +155,7 @@ class nsIContent : public nsINode {
* @see nsIAnonymousContentCreator
*/
void SetIsNativeAnonymousRoot() {
SetFlags(NODE_IS_ANONYMOUS_ROOT | NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE |
SetFlags(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE |
NODE_IS_NATIVE_ANONYMOUS_ROOT);
}
@ -185,28 +165,16 @@ class nsIContent : public nsINode {
*/
nsIContent* FindFirstNonChromeOnlyAccessContent() const;
#ifdef DEBUG
void AssertAnonymousSubtreeRelatedInvariants() const;
#endif
/**
* Returns true if and only if this node has a parent, but is not in
* its parent's child list.
*
* FIXME(emilio): Remove along nsINode::IsInAnonymousSubtree.
*/
bool IsRootOfAnonymousSubtree() const {
#ifdef DEBUG
AssertAnonymousSubtreeRelatedInvariants();
#endif
return HasFlag(NODE_IS_ANONYMOUS_ROOT);
return IsRootOfNativeAnonymousSubtree();
}
/**
* Returns true if there is NOT a path through child lists
* from the top of this node's parent chain back to this node or
* if the node is in native anonymous subtree without a parent.
*/
inline bool IsInAnonymousSubtree() const;
/**
* Return true iff this node is in an HTML document (in the HTML5 sense of
* the term, i.e. not in an XHTML/XML document).
@ -272,8 +240,6 @@ class nsIContent : public nsINode {
return IsMathMLElement() && IsNodeInternal(aFirst, aArgs...);
}
inline bool IsActiveChildrenElement() const;
bool IsGeneratedContentContainerForBefore() const {
return IsRootOfNativeAnonymousSubtree() &&
mNodeInfo->NameAtom() == nsGkAtoms::mozgeneratedcontentbefore;
@ -380,36 +346,6 @@ class nsIContent : public nsINode {
*/
virtual IMEState GetDesiredIMEState();
/**
* Gets content node with the binding (or native code, possibly on the
* frame) responsible for our construction (and existence). Used by
* anonymous content (both XBL-generated and native-anonymous).
*
* null for all explicit content (i.e., content reachable from the top
* of its GetParent() chain via child lists).
*
* @return the binding parent
*/
virtual mozilla::dom::Element* GetBindingParent() const {
const nsExtendedContentSlots* slots = GetExistingExtendedContentSlots();
return slots ? slots->mBindingParent.get() : nullptr;
}
/**
* Gets the current XBL binding that is bound to this element.
*
* @return the current binding.
*/
nsXBLBinding* GetXBLBinding() const {
if (!HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
return nullptr;
}
return DoGetXBLBinding();
}
virtual nsXBLBinding* DoGetXBLBinding() const = 0;
/**
* Gets the ShadowRoot binding for this element.
*
@ -419,8 +355,6 @@ class nsIContent : public nsINode {
/**
* Gets the root of the node tree for this content if it is in a shadow tree.
* This method is called |GetContainingShadow| instead of |GetRootShadowRoot|
* to avoid confusion with |GetShadowRoot|.
*
* @return The ShadowRoot that is the root of the node tree.
*/
@ -429,14 +363,6 @@ class nsIContent : public nsINode {
return slots ? slots->mContainingShadow.get() : nullptr;
}
/**
* Gets the shadow host if this content is in a shadow tree. That is, the host
* of |GetContainingShadow|, if its not null.
*
* @return The shadow host, if this is in shadow tree, or null.
*/
nsIContent* GetContainingShadowHost() const;
/**
* Gets the assigned slot associated with this content.
*
@ -463,29 +389,6 @@ class nsIContent : public nsINode {
*/
mozilla::dom::HTMLSlotElement* GetAssignedSlotByMode() const;
nsIContent* GetXBLInsertionParent() const {
nsIContent* ip = GetXBLInsertionPoint();
return ip ? ip->GetParent() : nullptr;
}
/**
* Gets the insertion parent element of the XBL binding.
* The insertion parent is our one true parent in the transformed DOM.
*
* @return the insertion parent element.
*/
nsIContent* GetXBLInsertionPoint() const {
const nsExtendedContentSlots* slots = GetExistingExtendedContentSlots();
return slots ? slots->mXBLInsertionPoint.get() : nullptr;
}
/**
* Sets the insertion parent element of the XBL binding.
*
* @param aContent The insertion parent element.
*/
void SetXBLInsertionPoint(nsIContent* aContent);
/**
* Same as GetFlattenedTreeParentNode, but returns null if the parent is
* non-nsIContent.
@ -542,9 +445,8 @@ class nsIContent : public nsINode {
* For container elements, this is called *before* any of the children are
* created or added into the tree.
*
* NOTE: this is currently only called for input and button, in the HTML
* content sink. If you want to call it on your element, modify the content
* sink of your choice to do so. This is an efficiency measure.
* NOTE: this is only called for elements listed in
* RequiresDoneCreatingElement. This is an efficiency measure.
*
* If you also need to determine whether the parser is the one creating your
* element (through createElement() or cloneNode() generally) then add a
@ -565,10 +467,8 @@ class nsIContent : public nsINode {
* This method is called when the parser finishes creating the element's
* children, if any are present.
*
* NOTE: this is currently only called for textarea, select, and object
* elements in the HTML content sink. If you want to call it on your element,
* modify the content sink of your choice to do so. This is an efficiency
* measure.
* NOTE: this is only called for elements listed in
* RequiresDoneAddingChildren. This is an efficiency measure.
*
* If you also need to determine whether the parser is the one creating your
* element (through createElement() or cloneNode() generally) then add a
@ -595,6 +495,47 @@ class nsIContent : public nsINode {
*/
virtual bool IsDoneAddingChildren() { return true; }
/**
* Returns true if an element needs its DoneCreatingElement method to be
* called after it has been created.
* @see nsIContent::DoneCreatingElement
*
* @param aNamespaceID the node's namespace ID
* @param aName the node's tag name
*/
static inline bool RequiresDoneCreatingElement(int32_t aNamespace,
nsAtom* aName) {
if (aNamespace == kNameSpaceID_XHTML &&
(aName == nsGkAtoms::input || aName == nsGkAtoms::button ||
aName == nsGkAtoms::menuitem || aName == nsGkAtoms::audio ||
aName == nsGkAtoms::video)) {
MOZ_ASSERT(
!RequiresDoneAddingChildren(aNamespace, aName),
"Both DoneCreatingElement and DoneAddingChildren on a same element "
"isn't supported.");
return true;
}
return false;
}
/**
* Returns true if an element needs its DoneAddingChildren method to be
* called after all of its children have been added.
* @see nsIContent::DoneAddingChildren
*
* @param aNamespace the node's namespace ID
* @param aName the node's tag name
*/
static inline bool RequiresDoneAddingChildren(int32_t aNamespace,
nsAtom* aName) {
return (aNamespace == kNameSpaceID_XHTML &&
(aName == nsGkAtoms::select || aName == nsGkAtoms::textarea ||
aName == nsGkAtoms::head || aName == nsGkAtoms::title ||
aName == nsGkAtoms::object || aName == nsGkAtoms::output)) ||
(aNamespace == kNameSpaceID_SVG && aName == nsGkAtoms::title) ||
(aNamespace == kNameSpaceID_XUL && aName == nsGkAtoms::linkset);
}
/**
* Get the ID of this content node (the atom corresponding to the
* value of the id attribute). This may be null if there is no ID.
@ -737,18 +678,6 @@ class nsIContent : public nsINode {
virtual size_t SizeOfExcludingThis(
mozilla::MallocSizeOf aMallocSizeOf) const;
/**
* The nearest enclosing content node with a binding that created us.
*
* @see nsIContent::GetBindingParent
*/
RefPtr<mozilla::dom::Element> mBindingParent;
/**
* @see nsIContent::GetXBLInsertionPoint
*/
nsCOMPtr<nsIContent> mXBLInsertionPoint;
/**
* @see nsIContent::GetContainingShadow
*/
@ -887,13 +816,4 @@ class nsIContent : public nsINode {
NS_DEFINE_STATIC_IID_ACCESSOR(nsIContent, NS_ICONTENT_IID)
inline nsIContent* nsINode::AsContent() {
MOZ_ASSERT(IsContent());
return static_cast<nsIContent*>(this);
}
inline const nsIContent* nsINode::AsContent() const {
return const_cast<nsINode*>(this)->AsContent();
}
#endif /* nsIContent_h___ */

View File

@ -7,7 +7,6 @@
#include "nsIContent.h"
#include "mozilla/dom/Document.h"
#include "nsBindingManager.h"
#include "nsContentUtils.h"
#include "nsAtom.h"
#include "nsIFrame.h"
@ -116,23 +115,6 @@ static inline nsINode* GetFlattenedTreeParentNode(const nsINode* aNode) {
}
}
if (content->HasFlag(NODE_MAY_BE_IN_BINDING_MNGR) ||
parent->HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
if (nsIContent* xblInsertionPoint = content->GetXBLInsertionPoint()) {
return xblInsertionPoint->GetParent();
}
if (parent->OwnerDoc()->BindingManager()->GetBindingWithContent(
parentAsContent)) {
// This is an unassigned node child of the bound element, so it isn't part
// of the flat tree.
return nullptr;
}
}
MOZ_ASSERT(!parentAsContent->IsActiveChildrenElement(),
"<xbl:children> isn't in the flattened tree");
// Common case.
return parent;
}
@ -180,45 +162,6 @@ inline bool nsINode::IsEditable() const {
return doc && doc->HasFlag(NODE_IS_EDITABLE);
}
inline bool nsIContent::IsActiveChildrenElement() const {
if (!mNodeInfo->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) {
return false;
}
nsIContent* bindingParent = GetBindingParent();
if (!bindingParent) {
return false;
}
// We reuse the binding parent machinery for Shadow DOM too, so prevent that
// from getting us confused in this case.
return !bindingParent->GetShadowRoot();
}
inline bool nsIContent::IsInAnonymousSubtree() const {
NS_ASSERTION(
!IsInNativeAnonymousSubtree() || GetBindingParent() ||
(!IsInUncomposedDoc() && static_cast<nsIContent*>(SubtreeRoot())
->IsInNativeAnonymousSubtree()),
"Must have binding parent when in native anonymous subtree which is in "
"document.\n"
"Native anonymous subtree which is not in document must have native "
"anonymous root.");
if (IsInNativeAnonymousSubtree()) {
return true;
}
nsIContent* bindingParent = GetBindingParent();
if (!bindingParent) {
return false;
}
// We reuse the binding parent machinery for Shadow DOM too, so prevent that
// from getting us confused in this case.
return !bindingParent->GetShadowRoot();
}
inline void nsIContent::HandleInsertionToOrRemovalFromSlot() {
using mozilla::dom::HTMLSlotElement;

View File

@ -105,11 +105,9 @@ interface nsIContentPolicy : nsISupports
*/
const nsContentPolicyType TYPE_REFRESH = 8;
/**
* Indicates an XBL binding request, triggered either by -moz-binding CSS
* property.
/*
* XXX: nsContentPolicyType = 9 used to inicate an XBL binding request.
*/
const nsContentPolicyType TYPE_XBL = 9;
/**
* Indicates a ping triggered by a click on <A PING="..."> element.

View File

@ -43,7 +43,6 @@
#include "mozilla/dom/L10nOverlays.h"
#include "mozilla/StaticPrefs_layout.h"
#include "nsAttrValueOrString.h"
#include "nsBindingManager.h"
#include "nsCCUncollectableMarker.h"
#include "nsContentCreatorFunctions.h"
#include "nsContentList.h"
@ -78,7 +77,6 @@
#include "nsLayoutUtils.h"
#include "nsNameSpaceManager.h"
#include "nsNodeInfoManager.h"
#include "nsPIBoxObject.h"
#include "nsObjectLoadingContent.h"
#include "nsPIDOMWindow.h"
#include "nsPresContext.h"
@ -88,8 +86,6 @@
#include "nsStyleConsts.h"
#include "nsTextNode.h"
#include "nsUnicharUtils.h"
#include "nsXBLBinding.h"
#include "nsXBLPrototypeBinding.h"
#include "nsWindowSizes.h"
#include "mozilla/Preferences.h"
#include "xpcpublic.h"
@ -497,20 +493,19 @@ static nsIContent* GetRootForContentSubtree(nsIContent* aContent) {
// Special case for ShadowRoot because the ShadowRoot itself is
// the root. This is necessary to prevent selection from crossing
// the ShadowRoot boundary.
ShadowRoot* containingShadow = aContent->GetContainingShadow();
if (containingShadow) {
//
// FIXME(emilio): The NAC check should probably be done before this? We can
// have NAC inside shadow DOM.
if (ShadowRoot* containingShadow = aContent->GetContainingShadow()) {
return containingShadow;
}
nsIContent* stop = aContent->GetBindingParent();
while (aContent) {
nsIContent* parent = aContent->GetParent();
if (parent == stop) {
break;
}
aContent = parent;
if (nsIContent* nativeAnonRoot = aContent->GetClosestNativeAnonymousSubtreeRoot()) {
return nativeAnonRoot;
}
return aContent;
if (Document* doc = aContent->GetUncomposedDoc()) {
return doc->GetRootElement();
}
return nsIContent::FromNode(aContent->SubtreeRoot());
}
nsIContent* nsINode::GetSelectionRootContent(PresShell* aPresShell) {
@ -523,7 +518,7 @@ nsIContent* nsINode::GetSelectionRootContent(PresShell* aPresShell) {
return nullptr;
}
if (static_cast<nsIContent*>(this)->HasIndependentSelection()) {
if (AsContent()->HasIndependentSelection()) {
// This node should be a descendant of input/textarea editor.
nsIContent* content = GetTextEditorRootContent();
if (content) return content;
@ -541,7 +536,7 @@ nsIContent* nsINode::GetSelectionRootContent(PresShell* aPresShell) {
NS_ENSURE_TRUE(editorRoot, nullptr);
return nsContentUtils::IsInSameAnonymousTree(this, editorRoot)
? editorRoot
: GetRootForContentSubtree(static_cast<nsIContent*>(this));
: GetRootForContentSubtree(AsContent());
}
// If the document isn't editable but this is editable, this is in
// contenteditable. Use the editing host element for selection root.
@ -565,7 +560,7 @@ nsIContent* nsINode::GetSelectionRootContent(PresShell* aPresShell) {
// root. Otherwise, we can return the content simply.
NS_ENSURE_TRUE(content, nullptr);
if (!nsContentUtils::IsInSameAnonymousTree(this, content)) {
content = GetRootForContentSubtree(static_cast<nsIContent*>(this));
content = GetRootForContentSubtree(AsContent());
// Fixup for ShadowRoot because the ShadowRoot itself does not have a frame.
// Use the host as the root.
if (ShadowRoot* shadowRoot = ShadowRoot::FromNode(content)) {
@ -680,38 +675,12 @@ void nsINode::LastRelease() {
UnsetFlags(NODE_HAS_LISTENERMANAGER);
}
if (Element* element = Element::FromNode(this)) {
element->OwnerDoc()->ClearBoxObjectFor(element);
NS_ASSERTION(!element->GetXBLBinding(), "Node has binding on destruction");
}
ReleaseWrapper(this);
FragmentOrElement::RemoveBlackMarkedNode(this);
}
#ifdef DEBUG
void nsINode::CheckNotNativeAnonymous() const {
if (!IsContent()) return;
nsIContent* content =
static_cast<const nsIContent*>(this)->GetBindingParent();
while (content) {
if (content->IsRootOfNativeAnonymousSubtree()) {
NS_ERROR("Element not marked to be in native anonymous subtree!");
break;
}
content = content->GetBindingParent();
}
}
#endif
bool nsINode::IsInAnonymousSubtree() const {
if (!IsContent()) {
return false;
}
return AsContent()->IsInAnonymousSubtree();
}
std::ostream& operator<<(std::ostream& aStream, const nsINode& aNode) {
nsAutoString elemDesc;
@ -740,9 +709,23 @@ std::ostream& operator<<(std::ostream& aStream, const nsINode& aNode) {
return aStream << str.get();
}
ShadowRoot* nsINode::GetContainingShadow() const {
if (!IsInShadowTree()) {
return nullptr;
}
return AsContent()->GetContainingShadow();
}
nsIContent* nsINode::GetContainingShadowHost() const {
if (ShadowRoot* shadow = GetContainingShadow()) {
return shadow->GetHost();
}
return nullptr;
}
SVGUseElement* nsINode::DoGetContainingSVGUseShadowHost() const {
MOZ_ASSERT(IsInShadowTree());
return SVGUseElement::FromNodeOrNull(AsContent()->GetContainingShadowHost());
return SVGUseElement::FromNodeOrNull(GetContainingShadowHost());
}
void nsINode::GetNodeValueInternal(nsAString& aNodeValue) {
@ -1344,12 +1327,7 @@ nsIGlobalObject* nsINode::GetOwnerGlobal() const {
}
bool nsINode::UnoptimizableCCNode() const {
const uintptr_t problematicFlags =
(NODE_IS_ANONYMOUS_ROOT | NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE |
NODE_IS_NATIVE_ANONYMOUS_ROOT | NODE_MAY_BE_IN_BINDING_MNGR);
return HasFlag(problematicFlags) || NodeType() == ATTRIBUTE_NODE ||
// For strange cases like xbl:content/xbl:children
(IsElement() && AsElement()->IsInNamespace(kNameSpaceID_XBL));
return IsInNativeAnonymousSubtree() || IsAttr();
}
/* static */
@ -2801,29 +2779,47 @@ bool nsINode::Contains(const nsINode* aOther) const {
if (aOther == this) {
return true;
}
if (!aOther || OwnerDoc() != aOther->OwnerDoc() ||
IsInUncomposedDoc() != aOther->IsInUncomposedDoc() ||
!aOther->IsContent() || !GetFirstChild()) {
!aOther->IsContent() || !HasChildren()) {
return false;
}
const nsIContent* other = static_cast<const nsIContent*>(aOther);
if (this == OwnerDoc()) {
if (IsDocument()) {
// document.contains(aOther) returns true if aOther is in the document,
// but is not in any anonymous subtree.
// IsInUncomposedDoc() check is done already before this.
return !other->IsInAnonymousSubtree();
return !aOther->IsInAnonymousSubtree();
}
if (!IsElement() && !IsDocumentFragment()) {
return false;
}
if (AsContent()->GetBindingParent() != other->GetBindingParent()) {
if (IsInShadowTree() != aOther->IsInShadowTree() ||
IsInNativeAnonymousSubtree() != aOther->IsInNativeAnonymousSubtree()) {
return false;
}
return other->IsInclusiveDescendantOf(this);
if (IsInNativeAnonymousSubtree()) {
if (GetClosestNativeAnonymousSubtreeRoot() !=
aOther->GetClosestNativeAnonymousSubtreeRoot()) {
return false;
}
}
if (IsInShadowTree()) {
ShadowRoot* otherRoot = aOther->GetContainingShadow();
if (IsShadowRoot()) {
return otherRoot == this;
}
if (otherRoot != GetContainingShadow()) {
return false;
}
}
return aOther->IsInclusiveDescendantOf(this);
}
uint32_t nsINode::Length() const {
@ -3174,7 +3170,6 @@ already_AddRefed<nsINode> nsINode::CloneAndAdopt(
bool wasRegistered = false;
if (elem) {
oldDoc->ClearBoxObjectFor(elem);
wasRegistered = oldDoc->UnregisterActivityObserver(elem);
}
@ -3479,21 +3474,3 @@ size_t nsNodeWeakReference::SizeOfOnlyThis(
mozilla::MallocSizeOf aMallocSizeOf) const {
return aMallocSizeOf(this);
}
nsIContent* nsINode::GetClosestNativeAnonymousSubtreeRoot() const {
if (!IsInNativeAnonymousSubtree()) {
return nullptr;
}
MOZ_ASSERT(IsContent(), "How did non-content end up in NAC?");
for (const nsINode* node = this; node; node = node->GetParentNode()) {
if (node->IsRootOfNativeAnonymousSubtree()) {
return const_cast<nsINode*>(node)->AsContent();
}
}
// FIXME(emilio): This should not happen, usually, but editor removes nodes
// in native anonymous subtrees, and we don't clean nodes from the current
// event content stack from ContentRemoved, so it can actually happen, see
// bug 1510208.
NS_WARNING("GetClosestNativeAnonymousSubtreeRoot on disconnected NAC!");
return nullptr;
}

View File

@ -97,6 +97,7 @@ class Optional;
class OwningNodeOrString;
template <typename>
class Sequence;
class ShadowRoot;
class SVGUseElement;
class Text;
class TextOrElementOrDocument;
@ -116,47 +117,35 @@ enum {
// Whether this node has had any properties set on it
NODE_HAS_PROPERTIES = NODE_FLAG_BIT(1),
// Whether this node is the root of an anonymous subtree. Note that this
// need not be a native anonymous subtree. Any anonymous subtree, including
// XBL-generated ones, will do. This flag is set-once: once a node has it,
// it must not be removed.
// NOTE: Should only be used on nsIContent nodes
NODE_IS_ANONYMOUS_ROOT = NODE_FLAG_BIT(2),
// Whether the node has some ancestor, possibly itself, that is native
// anonymous. This includes ancestors crossing XBL scopes, in cases when an
// XBL binding is attached to an element which has a native anonymous
// ancestor. This flag is set-once: once a node has it, it must not be
// removed.
// NOTE: Should only be used on nsIContent nodes
NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE = NODE_FLAG_BIT(3),
NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE = NODE_FLAG_BIT(2),
// Whether this node is the root of a native anonymous (from the perspective
// of its parent) subtree. This flag is set-once: once a node has it, it
// must not be removed.
// NOTE: Should only be used on nsIContent nodes
NODE_IS_NATIVE_ANONYMOUS_ROOT = NODE_FLAG_BIT(4),
NODE_IS_NATIVE_ANONYMOUS_ROOT = NODE_FLAG_BIT(3),
// Whether a binding manager may have a pointer to this
NODE_MAY_BE_IN_BINDING_MNGR = NODE_FLAG_BIT(5),
NODE_IS_EDITABLE = NODE_FLAG_BIT(6),
// Free bit here.
NODE_IS_EDITABLE = NODE_FLAG_BIT(4),
// Whether the node participates in a shadow tree.
NODE_IS_IN_SHADOW_TREE = NODE_FLAG_BIT(8),
NODE_IS_IN_SHADOW_TREE = NODE_FLAG_BIT(5),
// Node has an :empty or :-moz-only-whitespace selector
NODE_HAS_EMPTY_SELECTOR = NODE_FLAG_BIT(9),
NODE_HAS_EMPTY_SELECTOR = NODE_FLAG_BIT(6),
// A child of the node has a selector such that any insertion,
// removal, or appending of children requires restyling the parent.
NODE_HAS_SLOW_SELECTOR = NODE_FLAG_BIT(10),
NODE_HAS_SLOW_SELECTOR = NODE_FLAG_BIT(7),
// A child of the node has a :first-child, :-moz-first-node,
// :only-child, :last-child or :-moz-last-node selector.
NODE_HAS_EDGE_CHILD_SELECTOR = NODE_FLAG_BIT(11),
NODE_HAS_EDGE_CHILD_SELECTOR = NODE_FLAG_BIT(8),
// A child of the node has a selector such that any insertion or
// removal of children requires restyling later siblings of that
@ -165,7 +154,7 @@ enum {
// other content tree changes (e.g., the child changes to or from
// matching :empty due to a grandchild insertion or removal), the
// child's later siblings must also be restyled.
NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS = NODE_FLAG_BIT(12),
NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS = NODE_FLAG_BIT(9),
NODE_ALL_SELECTOR_FLAGS = NODE_HAS_EMPTY_SELECTOR | NODE_HAS_SLOW_SELECTOR |
NODE_HAS_EDGE_CHILD_SELECTOR |
@ -173,32 +162,32 @@ enum {
// This node needs to go through frame construction to get a frame (or
// undisplayed entry).
NODE_NEEDS_FRAME = NODE_FLAG_BIT(13),
NODE_NEEDS_FRAME = NODE_FLAG_BIT(10),
// At least one descendant in the flattened tree has NODE_NEEDS_FRAME set.
// This should be set on every node on the flattened tree path between the
// node(s) with NODE_NEEDS_FRAME and the root content.
NODE_DESCENDANTS_NEED_FRAMES = NODE_FLAG_BIT(14),
NODE_DESCENDANTS_NEED_FRAMES = NODE_FLAG_BIT(11),
// Set if the node has the accesskey attribute set.
NODE_HAS_ACCESSKEY = NODE_FLAG_BIT(15),
NODE_HAS_ACCESSKEY = NODE_FLAG_BIT(12),
// Set if the node has right-to-left directionality
NODE_HAS_DIRECTION_RTL = NODE_FLAG_BIT(16),
NODE_HAS_DIRECTION_RTL = NODE_FLAG_BIT(13),
// Set if the node has left-to-right directionality
NODE_HAS_DIRECTION_LTR = NODE_FLAG_BIT(17),
NODE_HAS_DIRECTION_LTR = NODE_FLAG_BIT(14),
NODE_ALL_DIRECTION_FLAGS = NODE_HAS_DIRECTION_LTR | NODE_HAS_DIRECTION_RTL,
NODE_HAS_BEEN_IN_UA_WIDGET = NODE_FLAG_BIT(18),
NODE_HAS_BEEN_IN_UA_WIDGET = NODE_FLAG_BIT(15),
// Set if the node has a nonce value and a header delivered CSP.
NODE_HAS_NONCE_AND_HEADER_CSP = NODE_FLAG_BIT(19),
NODE_HAS_NONCE_AND_HEADER_CSP = NODE_FLAG_BIT(16),
NODE_KEEPS_DOMARENA = NODE_FLAG_BIT(20),
NODE_KEEPS_DOMARENA = NODE_FLAG_BIT(17),
// Remaining bits are node type specific.
NODE_TYPE_SPECIFIC_BITS_OFFSET = 21
NODE_TYPE_SPECIFIC_BITS_OFFSET = 18
};
// Make sure we have space for our bits
@ -463,8 +452,7 @@ class nsINode : public mozilla::dom::EventTarget {
inline mozilla::dom::DocumentFragment* AsDocumentFragment();
inline const mozilla::dom::DocumentFragment* AsDocumentFragment() const;
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
JSObject* WrapObject(JSContext*, JS::Handle<JSObject*> aGivenProto) final;
/**
* Hook for constructing JS::ubi::Concrete specializations for memory
@ -539,10 +527,18 @@ class nsINode : public mozilla::dom::EventTarget {
/**
* Return this node as nsIContent. Should only be used for nodes for which
* IsContent() is true. This is defined inline in nsIContent.h.
* IsContent() is true.
*
* The assertion in nsIContent's constructor makes this safe.
*/
inline nsIContent* AsContent();
inline const nsIContent* AsContent() const;
nsIContent* AsContent() {
MOZ_ASSERT(IsContent());
return reinterpret_cast<nsIContent*>(this);
}
const nsIContent* AsContent() const {
MOZ_ASSERT(IsContent());
return reinterpret_cast<const nsIContent*>(this);
}
/*
* Return whether the node is a Text node (which might be an actual
@ -957,7 +953,7 @@ class nsINode : public mozilla::dom::EventTarget {
*/
nsIContent* GetParent() const {
return MOZ_LIKELY(GetBoolFlag(ParentIsContent))
? reinterpret_cast<nsIContent*>(mParent)
? mParent->AsContent()
: nullptr;
}
@ -1269,19 +1265,18 @@ class nsINode : public mozilla::dom::EventTarget {
void SetFlags(FlagsType aFlagsToSet) {
NS_ASSERTION(
!(aFlagsToSet &
(NODE_IS_ANONYMOUS_ROOT | NODE_IS_NATIVE_ANONYMOUS_ROOT |
NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE | NODE_DESCENDANTS_NEED_FRAMES |
NODE_NEEDS_FRAME | NODE_HAS_BEEN_IN_UA_WIDGET)) ||
(NODE_IS_NATIVE_ANONYMOUS_ROOT | NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE |
NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME |
NODE_HAS_BEEN_IN_UA_WIDGET)) ||
IsContent(),
"Flag only permitted on nsIContent nodes");
nsWrapperCache::SetFlags(aFlagsToSet);
}
void UnsetFlags(FlagsType aFlagsToUnset) {
NS_ASSERTION(
!(aFlagsToUnset & (NODE_IS_ANONYMOUS_ROOT | NODE_HAS_BEEN_IN_UA_WIDGET |
NODE_IS_NATIVE_ANONYMOUS_ROOT)),
"Trying to unset write-only flags");
NS_ASSERTION(!(aFlagsToUnset & (NODE_HAS_BEEN_IN_UA_WIDGET |
NODE_IS_NATIVE_ANONYMOUS_ROOT)),
"Trying to unset write-only flags");
nsWrapperCache::UnsetFlags(aFlagsToUnset);
}
@ -1299,25 +1294,41 @@ class nsINode : public mozilla::dom::EventTarget {
* Returns true if |this| or any of its ancestors is native anonymous.
*/
bool IsInNativeAnonymousSubtree() const {
#ifdef DEBUG
if (HasFlag(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE)) {
return true;
}
CheckNotNativeAnonymous();
return false;
#else
return HasFlag(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE);
#endif
}
bool IsInAnonymousSubtree() const;
/**
* Returns true if there is NOT a path through child lists
* from the top of this node's parent chain back to this node or
* if the node is in native anonymous subtree without a parent.
*
* TODO(emilio):: Remove this function, and use just
* IsInNativeAnonymousSubtree, or something?
*/
bool IsInAnonymousSubtree() const { return IsInNativeAnonymousSubtree(); }
/**
* If |this| or any ancestor is native anonymous, return the root of the
* native anonymous subtree. Note that in case of nested native anonymous
* content, this returns the innermost root, not the outermost.
*/
nsIContent* GetClosestNativeAnonymousSubtreeRoot() const;
nsIContent* GetClosestNativeAnonymousSubtreeRoot() const {
if (!IsInNativeAnonymousSubtree()) {
return nullptr;
}
MOZ_ASSERT(IsContent(), "How did non-content end up in NAC?");
for (const nsINode* node = this; node; node = node->GetParentNode()) {
if (node->IsRootOfNativeAnonymousSubtree()) {
return const_cast<nsINode*>(node)->AsContent();
}
}
// FIXME(emilio): This should not happen, usually, but editor removes nodes
// in native anonymous subtrees, and we don't clean nodes from the current
// event content stack from ContentRemoved, so it can actually happen, see
// bug 1510208.
NS_WARNING("GetClosestNativeAnonymousSubtreeRoot on disconnected NAC!");
return nullptr;
}
/**
* If |this| or any ancestor is native anonymous, return the parent of the
@ -1334,6 +1345,18 @@ class nsINode : public mozilla::dom::EventTarget {
return reinterpret_cast<const nsINode*>(root)->GetParent();
}
/**
* Gets the root of the node tree for this content if it is in a shadow tree.
*/
mozilla::dom::ShadowRoot* GetContainingShadow() const;
/**
* Gets the shadow host if this content is in a shadow tree. That is, the host
* of |GetContainingShadow|, if its not null.
*
* @return The shadow host, if this is in shadow tree, or null.
*/
nsIContent* GetContainingShadowHost() const;
bool IsInSVGUseShadowTree() const {
return !!GetContainingSVGUseShadowHost();
}
@ -1354,6 +1377,17 @@ class nsINode : public mozilla::dom::EventTarget {
NODE_HAS_BEEN_IN_UA_WIDGET);
}
const nsIContent* GetChromeOnlyAccessSubtreeRootParent() const {
if (!ChromeOnlyAccess()) {
return nullptr;
}
// We can have NAC in UA widgets, but not the other way around.
if (IsInNativeAnonymousSubtree()) {
return GetClosestNativeAnonymousSubtreeRootParent();
}
return GetContainingShadowHost();
}
bool IsInShadowTree() const { return HasFlag(NODE_IS_IN_SHADOW_TREE); }
/**
@ -1362,10 +1396,9 @@ class nsINode : public mozilla::dom::EventTarget {
* @return whether this content is anonymous
*/
bool IsRootOfNativeAnonymousSubtree() const {
NS_ASSERTION(!HasFlag(NODE_IS_NATIVE_ANONYMOUS_ROOT) ||
(HasFlag(NODE_IS_ANONYMOUS_ROOT) &&
HasFlag(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE)),
"Some flags seem to be missing!");
NS_ASSERTION(
!HasFlag(NODE_IS_NATIVE_ANONYMOUS_ROOT) || IsInNativeAnonymousSubtree(),
"Some flags seem to be missing!");
return HasFlag(NODE_IS_NATIVE_ANONYMOUS_ROOT);
}
@ -2108,12 +2141,6 @@ class nsINode : public mozilla::dom::EventTarget {
nsIPrincipal* aSubjectPrincipal,
mozilla::ErrorResult& aError) {}
#ifdef DEBUG
// Note: virtual so that IsInNativeAnonymousSubtree can be called accross
// module boundaries.
virtual void CheckNotNativeAnonymous() const;
#endif
void EnsurePreInsertionValidity1(mozilla::ErrorResult& aError);
void EnsurePreInsertionValidity2(bool aReplace, nsINode& aNewChild,
nsINode* aRefChild,

View File

@ -36,7 +36,6 @@
#include "nsINode.h"
#include "nsString.h"
#include "nsTPromiseFlatString.h"
#include "nsXBLPrototypeBinding.h"
#include "nscore.h"
#if !defined(DEBUG) && !defined(MOZ_ENABLE_JS_DUMP)
@ -218,29 +217,6 @@ bool nsJSUtils::GetScopeChainForElement(
return true;
}
/* static */
bool nsJSUtils::GetScopeChainForXBL(
JSContext* aCx, Element* aElement,
const nsXBLPrototypeBinding& aProtoBinding,
JS::MutableHandleVector<JSObject*> aScopeChain) {
if (!aElement) {
return true;
}
if (!aProtoBinding.SimpleScopeChain()) {
return GetScopeChainForElement(aCx, aElement, aScopeChain);
}
if (!AddScopeChainItem(aCx, aElement, aScopeChain)) {
return false;
}
if (!AddScopeChainItem(aCx, aElement->OwnerDoc(), aScopeChain)) {
return false;
}
return true;
}
/* static */
void nsJSUtils::ResetTimeZone() { JS::ResetTimeZone(); }

View File

@ -100,17 +100,6 @@ class nsJSUtils {
JSContext* aCx, mozilla::dom::Element* aElement,
JS::MutableHandleVector<JSObject*> aScopeChain);
// Returns a scope chain suitable for XBL execution.
//
// This is by default GetScopeChainForElemenet, but will be different if the
// <binding> element had the simpleScopeChain attribute.
//
// This is to prevent footguns like bug 1446342.
static bool GetScopeChainForXBL(
JSContext* aCx, mozilla::dom::Element* aBoundElement,
const nsXBLPrototypeBinding& aProtoBinding,
JS::MutableHandleVector<JSObject*> aScopeChain);
static void ResetTimeZone();
static bool DumpEnabled();

View File

@ -19,7 +19,6 @@
#include "nsString.h"
#include "mozilla/dom/NodeInfo.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/dom/XBLChildrenElement.h"
#include "mozilla/dom/Element.h"
#include "mozilla/Preferences.h"
@ -70,7 +69,6 @@ bool nsNameSpaceManager::Init() {
REGISTER_NAMESPACE(nsGkAtoms::nsuri_xhtml, kNameSpaceID_XHTML);
REGISTER_NAMESPACE(nsGkAtoms::nsuri_xlink, kNameSpaceID_XLink);
REGISTER_NAMESPACE(nsGkAtoms::nsuri_xslt, kNameSpaceID_XSLT);
REGISTER_NAMESPACE(nsGkAtoms::nsuri_xbl, kNameSpaceID_XBL);
REGISTER_NAMESPACE(nsGkAtoms::nsuri_mathml, kNameSpaceID_MathML);
REGISTER_NAMESPACE(nsGkAtoms::nsuri_rdf, kNameSpaceID_RDF);
REGISTER_NAMESPACE(nsGkAtoms::nsuri_xul, kNameSpaceID_XUL);
@ -165,8 +163,8 @@ int32_t nsNameSpaceManager::GetNameSpaceID(nsAtom* aURI, bool aInChromeDoc) {
// static
const char* nsNameSpaceManager::GetNameSpaceDisplayName(uint32_t aNameSpaceID) {
static const char* kNSURIs[] = {"([none])", "(xmlns)", "(xml)", "(xhtml)",
"(XLink)", "(XSLT)", "(XBL)", "(MathML)",
"(RDF)", "(XUL)", "(SVG)"};
"(XLink)", "(XSLT)", "(MathML)", "(RDF)",
"(XUL)", "(SVG)"};
if (aNameSpaceID < ArrayLength(kNSURIs)) {
return kNSURIs[aNameSpaceID];
}
@ -212,12 +210,6 @@ nsresult NS_NewElement(Element** aResult,
ni->NodeType(), ni->GetExtraName());
return NS_NewXMLElement(aResult, genericXMLNI.forget());
}
if (ns == kNameSpaceID_XBL && ni->Equals(nsGkAtoms::children)) {
RefPtr<mozilla::dom::NodeInfo> nodeInfo(ni);
auto* nim = nodeInfo->NodeInfoManager();
NS_ADDREF(*aResult = new (nim) XBLChildrenElement(nodeInfo.forget()));
return NS_OK;
}
return NS_NewXMLElement(aResult, ni.forget());
}

View File

@ -70,7 +70,7 @@ class nsNameSpaceManager final {
const int32_t aNameSpaceID);
nsresult AddDisabledNameSpace(already_AddRefed<nsAtom> aURI,
const int32_t aNameSpaceID);
~nsNameSpaceManager(){};
~nsNameSpaceManager() = default;
nsDataHashtable<nsRefPtrHashKey<nsAtom>, int32_t> mURIToIDTable;
nsDataHashtable<nsRefPtrHashKey<nsAtom>, int32_t> mDisabledURIToIDTable;

View File

@ -25,7 +25,6 @@
#include "nsGkAtoms.h"
#include "nsComponentManagerUtils.h"
#include "nsLayoutStatics.h"
#include "nsBindingManager.h"
#include "nsHashKeys.h"
#include "nsCCUncollectableMarker.h"
#include "nsNameSpaceManager.h"
@ -61,8 +60,6 @@ nsNodeInfoManager::~nsNodeInfoManager() {
mArena = nullptr;
mBindingManager = nullptr;
if (gNodeInfoManagerLeakPRLog)
MOZ_LOG(gNodeInfoManagerLeakPRLog, LogLevel::Debug,
("NODEINFOMANAGER %p destroyed", this));
@ -77,7 +74,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsNodeInfoManager)
if (tmp->mNonDocumentNodeInfos) {
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mDocument)
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBindingManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsNodeInfoManager, AddRef)
@ -109,10 +105,6 @@ nsresult nsNodeInfoManager::Init(mozilla::dom::Document* aDocument) {
mPrincipal = NullPrincipal::CreateWithoutOriginAttributes();
if (aDocument) {
mBindingManager = new nsBindingManager(aDocument);
}
mDefaultPrincipal = mPrincipal;
mDocument = aDocument;
@ -125,10 +117,6 @@ nsresult nsNodeInfoManager::Init(mozilla::dom::Document* aDocument) {
}
void nsNodeInfoManager::DropDocumentReference() {
if (mBindingManager) {
mBindingManager->DropDocumentReference();
}
// This is probably not needed anymore.
for (auto iter = mNodeInfoHash.Iter(); !iter.Done(); iter.Next()) {
iter.Data()->mDocument = nullptr;
@ -414,11 +402,6 @@ bool nsNodeInfoManager::InternalMathMLEnabled() {
void nsNodeInfoManager::AddSizeOfIncludingThis(nsWindowSizes& aSizes) const {
aSizes.mDOMOtherSize += aSizes.mState.mMallocSizeOf(this);
if (mBindingManager) {
aSizes.mBindingsSize +=
mBindingManager->SizeOfIncludingThis(aSizes.mState.mMallocSizeOf);
}
// Measurement of the following members may be added later if DMD finds it
// is worthwhile:
// - mNodeInfoHash

View File

@ -18,7 +18,6 @@
#include "nsDataHashtable.h"
#include "nsStringFwd.h"
class nsBindingManager;
class nsAtom;
class nsIPrincipal;
class nsWindowSizes;
@ -97,8 +96,6 @@ class nsNodeInfoManager final {
void RemoveNodeInfo(mozilla::dom::NodeInfo* aNodeInfo);
nsBindingManager* GetBindingManager() const { return mBindingManager; }
/**
* Returns true if SVG nodes in this document have real SVG semantics.
*/
@ -171,7 +168,6 @@ class nsNodeInfoManager final {
mCommentNodeInfo; // WEAK to avoid circular ownership
mozilla::dom::NodeInfo* MOZ_NON_OWNING_REF
mDocumentNodeInfo; // WEAK to avoid circular ownership
RefPtr<nsBindingManager> mBindingManager;
NodeInfoCache mRecentlyUsedNodeInfos;
mozilla::Maybe<bool> mSVGEnabled; // Lazily initialized.
mozilla::Maybe<bool> mMathMLEnabled; // Lazily initialized.

View File

@ -41,7 +41,6 @@ class nsIURI;
class nsPIDOMWindowInner;
class nsPIDOMWindowOuter;
class nsPIWindowRoot;
class nsXBLPrototypeHandler;
typedef uint32_t SuspendTypes;
@ -439,11 +438,6 @@ class nsPIDOMWindowInner : public mozIDOMWindow {
return mMayHaveSelectionChangeEventListener;
}
virtual JSObject* GetCachedXBLPrototypeHandler(
nsXBLPrototypeHandler* aKey) = 0;
virtual void CacheXBLPrototypeHandler(nsXBLPrototypeHandler* aKey,
JS::Handle<JSObject*> aHandler) = 0;
/*
* Get and set the currently focused element within the document. If
* aNeedsFocus is true, then set mNeedsFocus to true to indicate that a
@ -452,10 +446,22 @@ class nsPIDOMWindowInner : public mozIDOMWindow {
* DO NOT CALL EITHER OF THESE METHODS DIRECTLY. USE THE FOCUS MANAGER
* INSTEAD.
*/
inline mozilla::dom::Element* GetFocusedElement() const;
mozilla::dom::Element* GetFocusedElement() const {
return mFocusedElement.get();
}
virtual void SetFocusedElement(mozilla::dom::Element* aElement,
uint32_t aFocusMethod = 0,
bool aNeedsFocus = false) = 0;
bool aNeedsFocus = false,
bool aWillShowOutline = false) = 0;
/**
* Get whether the focused element did show outlines when it was focused.
*
* Only for the focus manager. Returns false if there was no focused element.
*/
bool FocusedElementShowedOutline() const {
return mFocusedElementShowedOutlines;
}
/**
* Retrieves the method that was used to focus the current node.
@ -647,6 +653,8 @@ class nsPIDOMWindowInner : public mozIDOMWindow {
// notification.
bool mHasNotifiedGlobalCreated;
bool mFocusedElementShowedOutlines = false;
uint32_t mMarkedCCGeneration;
// mTopInnerWindow is used for tab-wise check by timeout throttling. It could
@ -940,9 +948,17 @@ class nsPIDOMWindowOuter : public mozIDOMWindowProxy {
* INSTEAD.
*/
inline mozilla::dom::Element* GetFocusedElement() const;
virtual void SetFocusedElement(mozilla::dom::Element* aElement,
uint32_t aFocusMethod = 0,
bool aNeedsFocus = false) = 0;
bool aNeedsFocus = false,
bool aWillShowOutline = false) = 0;
/**
* Get whether the focused element did show outlines when it was focused.
*
* Only for the focus manager. Returns false if there was no focused element.
*/
bool FocusedElementShowedOutline() const;
/**
* Retrieves the method that was used to focus the current node.

View File

@ -2,7 +2,10 @@
* 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/. */
bool nsPIDOMWindowOuter::IsLoading() const {
#ifndef dom_base_nsPIDOMWindowInlines_h___
#define dom_base_nsPIDOMWindowInlines_h___
inline bool nsPIDOMWindowOuter::IsLoading() const {
auto* win = GetCurrentInnerWindow();
if (!win) {
@ -14,7 +17,7 @@ bool nsPIDOMWindowOuter::IsLoading() const {
return win->IsLoading();
}
bool nsPIDOMWindowInner::IsLoading() const {
inline bool nsPIDOMWindowInner::IsLoading() const {
if (!mOuterWindow) {
NS_ERROR("IsLoading() called on orphan inner window!");
@ -24,7 +27,7 @@ bool nsPIDOMWindowInner::IsLoading() const {
return !mIsDocumentLoaded;
}
bool nsPIDOMWindowOuter::IsHandlingResizeEvent() const {
inline bool nsPIDOMWindowOuter::IsHandlingResizeEvent() const {
auto* win = GetCurrentInnerWindow();
if (!win) {
@ -36,7 +39,7 @@ bool nsPIDOMWindowOuter::IsHandlingResizeEvent() const {
return win->IsHandlingResizeEvent();
}
bool nsPIDOMWindowInner::IsHandlingResizeEvent() const {
inline bool nsPIDOMWindowInner::IsHandlingResizeEvent() const {
if (!mOuterWindow) {
NS_ERROR("IsHandlingResizeEvent() called on orphan inner window!");
@ -46,34 +49,39 @@ bool nsPIDOMWindowInner::IsHandlingResizeEvent() const {
return mIsHandlingResizeEvent;
}
bool nsPIDOMWindowInner::IsCurrentInnerWindow() const {
inline bool nsPIDOMWindowInner::IsCurrentInnerWindow() const {
return mOuterWindow && mOuterWindow->GetCurrentInnerWindow() == this;
}
bool nsPIDOMWindowInner::HasActiveDocument() {
inline bool nsPIDOMWindowInner::HasActiveDocument() {
return IsCurrentInnerWindow() ||
(mOuterWindow && mOuterWindow->GetCurrentInnerWindow() &&
mOuterWindow->GetCurrentInnerWindow()->GetDoc() == mDoc);
}
bool nsPIDOMWindowInner::IsTopInnerWindow() const {
inline bool nsPIDOMWindowInner::IsTopInnerWindow() const {
return mTopInnerWindow == this;
}
nsIDocShell* nsPIDOMWindowOuter::GetDocShell() const { return mDocShell; }
inline nsIDocShell* nsPIDOMWindowOuter::GetDocShell() const {
return mDocShell;
}
nsIDocShell* nsPIDOMWindowInner::GetDocShell() const {
inline nsIDocShell* nsPIDOMWindowInner::GetDocShell() const {
return mOuterWindow ? mOuterWindow->GetDocShell() : nullptr;
}
mozilla::dom::BrowsingContext* nsPIDOMWindowOuter::GetBrowsingContext() const {
inline mozilla::dom::BrowsingContext* nsPIDOMWindowOuter::GetBrowsingContext()
const {
return mBrowsingContext;
}
mozilla::dom::Element* nsPIDOMWindowOuter::GetFocusedElement() const {
inline mozilla::dom::Element* nsPIDOMWindowOuter::GetFocusedElement() const {
return mInnerWindow ? mInnerWindow->GetFocusedElement() : nullptr;
}
mozilla::dom::Element* nsPIDOMWindowInner::GetFocusedElement() const {
return mFocusedElement;
inline bool nsPIDOMWindowOuter::FocusedElementShowedOutline() const {
return mInnerWindow && mInnerWindow->FocusedElementShowedOutline();
}
#endif

View File

@ -856,10 +856,10 @@ void nsRange::DoSetRange(const RangeBoundaryBase<SPT, SRT>& aStartBoundary,
!aRootNode ||
(aStartBoundary.Container()->IsContent() &&
aEndBoundary.Container()->IsContent() &&
aRootNode == static_cast<nsIContent*>(aStartBoundary.Container())
->GetBindingParent() &&
aRootNode == static_cast<nsIContent*>(aEndBoundary.Container())
->GetBindingParent()) ||
aRootNode ==
RangeUtils::ComputeRootNode(aStartBoundary.Container()) &&
aRootNode ==
RangeUtils::ComputeRootNode(aEndBoundary.Container())) ||
(!aRootNode->GetParentNode() &&
(aRootNode->IsDocument() || aRootNode->IsAttr() ||
aRootNode->IsDocumentFragment() ||
@ -1286,7 +1286,7 @@ class MOZ_STACK_CLASS RangeSubtreeIterator {
public:
RangeSubtreeIterator() : mIterState(eDone) {}
~RangeSubtreeIterator() {}
~RangeSubtreeIterator() = default;
nsresult Init(nsRange* aRange);
already_AddRefed<nsINode> GetCurrentNode();

View File

@ -6,7 +6,6 @@
#include "nsScreen.h"
#include "mozilla/dom/Document.h"
#include "nsIDocShell.h"
#include "mozilla/dom/Document.h"
#include "nsPresContext.h"
#include "nsCOMPtr.h"
#include "nsIDocShellTreeItem.h"
@ -84,6 +83,22 @@ nsresult nsScreen::GetRect(nsRect& aRect) {
return GetWindowInnerRect(aRect);
}
// Here we manipulate the value of aRect to represent the screen size,
// if in RDM.
nsCOMPtr<nsPIDOMWindowInner> owner = GetOwner();
if (owner) {
mozilla::dom::Document* doc = owner->GetExtantDoc();
if (doc) {
Maybe<mozilla::CSSIntSize> deviceSize =
nsGlobalWindowOuter::GetRDMDeviceSize(*doc);
if (deviceSize.isSome()) {
const mozilla::CSSIntSize& size = deviceSize.value();
aRect.SetRect(0, 0, size.width, size.height);
return NS_OK;
}
}
}
nsDeviceContext* context = GetDeviceContext();
if (!context) {
@ -111,10 +126,20 @@ nsresult nsScreen::GetAvailRect(nsRect& aRect) {
return GetWindowInnerRect(aRect);
}
// Here we manipulate the value of aRect to represent the screen avail size,
// Here we manipulate the value of aRect to represent the screen size,
// if in RDM.
if (IsInRDMPane()) {
return GetRDMScreenSize(aRect);
nsCOMPtr<nsPIDOMWindowInner> owner = GetOwner();
if (owner) {
mozilla::dom::Document* doc = owner->GetExtantDoc();
if (doc) {
Maybe<mozilla::CSSIntSize> deviceSize =
nsGlobalWindowOuter::GetRDMDeviceSize(*doc);
if (deviceSize.isSome()) {
const mozilla::CSSIntSize& size = deviceSize.value();
aRect.SetRect(0, 0, size.width, size.height);
return NS_OK;
}
}
}
nsDeviceContext* context = GetDeviceContext();
@ -143,29 +168,6 @@ nsresult nsScreen::GetAvailRect(nsRect& aRect) {
return NS_OK;
}
nsresult nsScreen::GetRDMScreenSize(nsRect& aRect) {
GetWindowInnerRect(aRect);
// GetOwner(), GetDocShell(), and GetPresContext() can potentially return
// nullptr, so to be safe let's make sure we check these before proceeding.
nsCOMPtr<nsPIDOMWindowInner> owner = GetOwner();
if (owner) {
nsIDocShell* docShell = owner->GetDocShell();
if (docShell) {
RefPtr<nsPresContext> presContext = docShell->GetPresContext();
if (presContext) {
float zoom = presContext->GetDeviceFullZoom();
int32_t width = std::round(aRect.Width() * zoom);
int32_t height = std::round(aRect.Height() * zoom);
aRect.SetHeight(height);
aRect.SetWidth(width);
return NS_OK;
}
}
}
return NS_ERROR_FAILURE;
}
mozilla::dom::ScreenOrientation* nsScreen::Orientation() const {
return mScreenOrientation;
}
@ -279,16 +281,6 @@ void nsScreen::MozUnlockOrientation() {
mScreenOrientation->UnlockDeviceOrientation();
}
bool nsScreen::IsDeviceSizePageSize() {
if (nsPIDOMWindowInner* owner = GetOwner()) {
nsIDocShell* docShell = owner->GetDocShell();
if (docShell) {
return docShell->GetDeviceSizeIsPageSize();
}
}
return false;
}
/* virtual */
JSObject* nsScreen::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) {
@ -315,15 +307,3 @@ bool nsScreen::ShouldResistFingerprinting() const {
}
return resist;
}
bool nsScreen::IsInRDMPane() const {
bool isInRDM = false;
nsCOMPtr<nsPIDOMWindowInner> owner = GetOwner();
if (owner) {
Document* doc = owner->GetExtantDoc();
isInRDM = doc && doc->InRDMPane();
}
return isInRDM;
}

View File

@ -45,38 +45,12 @@ class nsScreen : public mozilla::DOMEventTargetHelper {
int32_t GetWidth(ErrorResult& aRv) {
nsRect rect;
if (IsDeviceSizePageSize()) {
if (IsInRDMPane()) {
GetRDMScreenSize(rect);
return rect.Width();
}
if (nsCOMPtr<nsPIDOMWindowInner> owner = GetOwner()) {
int32_t innerWidth = 0;
aRv = owner->GetInnerWidth(&innerWidth);
return innerWidth;
}
}
aRv = GetRect(rect);
return rect.Width();
}
int32_t GetHeight(ErrorResult& aRv) {
nsRect rect;
if (IsDeviceSizePageSize()) {
if (IsInRDMPane()) {
GetRDMScreenSize(rect);
return rect.Height();
}
if (nsCOMPtr<nsPIDOMWindowInner> owner = GetOwner()) {
int32_t innerHeight = 0;
aRv = owner->GetInnerHeight(&innerHeight);
return innerHeight;
}
}
aRv = GetRect(rect);
return rect.Height();
}
@ -144,17 +118,14 @@ class nsScreen : public mozilla::DOMEventTargetHelper {
nsresult GetRect(nsRect& aRect);
nsresult GetAvailRect(nsRect& aRect);
nsresult GetWindowInnerRect(nsRect& aRect);
nsresult GetRDMScreenSize(nsRect& aRect);
private:
explicit nsScreen(nsPIDOMWindowInner* aWindow);
virtual ~nsScreen();
bool IsDeviceSizePageSize();
bool ShouldResistFingerprinting() const;
bool IsInRDMPane() const;
mozilla::dom::Document* TopContentDocumentInRDMPane() const;
RefPtr<mozilla::dom::ScreenOrientation> mScreenOrientation;
};

View File

@ -1062,92 +1062,16 @@ bool nsTreeSanitizer::MustPrune(int32_t aNamespace, nsAtom* aLocal,
return false;
}
bool nsTreeSanitizer::SanitizeStyleDeclaration(DeclarationBlock* aDeclaration) {
return aDeclaration->RemovePropertyByID(eCSSProperty__moz_binding);
}
void nsTreeSanitizer::SanitizeStyleSheet(const nsAString& aOriginal,
nsAString& aSanitized,
Document* aDocument,
nsIURI* aBaseURI) {
aSanitized.Truncate();
NS_ConvertUTF16toUTF8 style(aOriginal);
RefPtr<nsIReferrerInfo> referrer =
ReferrerInfo::CreateForInternalCSSResources(aDocument);
if (StaticPrefs::layout_css_moz_binding_content_enabled() ||
aDocument->IsDocumentURISchemeChrome()) {
// aSanitized will hold the permitted CSS text.
// -moz-binding is blacklisted.
bool didSanitize = false;
// Create a sheet to hold the parsed CSS
RefPtr<StyleSheet> sheet = new StyleSheet(mozilla::css::eAuthorSheetFeatures,
CORS_NONE, SRIMetadata());
sheet->SetURIs(aDocument->GetDocumentURI(), nullptr, aBaseURI);
sheet->SetPrincipal(aDocument->NodePrincipal());
sheet->ParseSheetSync(aDocument->CSSLoader(),
NS_ConvertUTF16toUTF8(aOriginal),
/* aLoadData = */ nullptr,
/* aLineNumber = */ 0);
// Mark the sheet as complete.
MOZ_ASSERT(!sheet->HasForcedUniqueInner(),
"should not get a forced unique inner during parsing");
NS_ConvertUTF16toUTF8 style(aOriginal);
sheet->SetComplete();
// Loop through all the rules found in the CSS text
ErrorResult err;
RefPtr<dom::CSSRuleList> rules =
sheet->GetCssRules(*nsContentUtils::GetSystemPrincipal(), err);
err.SuppressException();
if (!rules) {
return;
}
uint32_t ruleCount = rules->Length();
for (uint32_t i = 0; i < ruleCount; ++i) {
mozilla::css::Rule* rule = rules->Item(i);
if (!rule) continue;
switch (rule->Type()) {
default:
didSanitize = true;
// Ignore these rule types.
break;
case StyleCssRuleType::Namespace:
case StyleCssRuleType::FontFace: {
// Append @namespace and @font-face rules verbatim.
nsAutoCString cssText;
rule->GetCssText(cssText);
aSanitized.Append(NS_ConvertUTF8toUTF16(cssText).get());
break;
}
case StyleCssRuleType::Style: {
// For style rules, we will just look for and remove the
// -moz-binding properties.
auto styleRule = static_cast<BindingStyleRule*>(rule);
DeclarationBlock* styleDecl = styleRule->GetDeclarationBlock();
MOZ_ASSERT(styleDecl);
if (SanitizeStyleDeclaration(styleDecl)) {
didSanitize = true;
}
nsAutoCString decl;
styleRule->GetCssText(decl);
aSanitized.Append(NS_ConvertUTF8toUTF16(decl).get());
}
}
}
if (didSanitize) {
if (mLogRemovals) {
LogMessage("Removed some rules and/or properties from stylesheet.",
aDocument);
}
} else {
aSanitized.Assign(aOriginal);
}
return;
}
NS_ConvertUTF16toUTF8 style(aOriginal);
RefPtr<URLExtraData> extraData =
new URLExtraData(aBaseURI, referrer, aDocument->NodePrincipal());
auto sanitizationKind = StyleSanitizationKind::Standard;
auto extraData =
MakeRefPtr<URLExtraData>(aBaseURI, referrer, aDocument->NodePrincipal());
RefPtr<RawServoStyleSheetContents> contents =
Servo_StyleSheet_FromUTF8Bytes(
/* loader = */ nullptr,
@ -1156,9 +1080,8 @@ void nsTreeSanitizer::SanitizeStyleSheet(const nsAString& aOriginal,
css::SheetParsingMode::eAuthorSheetFeatures, extraData.get(),
/* line_number_offset = */ 0, aDocument->GetCompatibilityMode(),
/* reusable_sheets = */ nullptr,
StyleAllowImportRules::Yes,
sanitizationKind, &aSanitized)
.Consume();
StyleAllowImportRules::Yes, StyleSanitizationKind::Standard,
&aSanitized).Consume();
if (mLogRemovals && aSanitized.Length() != aOriginal.Length()) {
LogMessage("Removed some rules and/or properties from stylesheet.",
@ -1194,26 +1117,6 @@ void nsTreeSanitizer::SanitizeAttributes(mozilla::dom::Element* aElement,
if (kNameSpaceID_None == attrNs) {
if (aAllowed.mStyle && nsGkAtoms::style == attrLocal) {
nsAutoString value;
aElement->GetAttr(attrNs, attrLocal, value);
Document* document = aElement->OwnerDoc();
RefPtr<URLExtraData> urlExtra(aElement->GetURLDataForStyleAttr());
RefPtr<DeclarationBlock> decl = DeclarationBlock::FromCssText(
value, urlExtra, document->GetCompatibilityMode(),
document->CSSLoader(), StyleCssRuleType::Style);
if (decl) {
if (SanitizeStyleDeclaration(decl)) {
nsAutoCString cleanValue;
decl->ToString(cleanValue);
aElement->SetAttr(kNameSpaceID_None, nsGkAtoms::style,
NS_ConvertUTF8toUTF16(cleanValue), false);
if (mLogRemovals) {
LogMessage(
"Removed -moz-binding styling from element style attribute.",
aElement->OwnerDoc(), aElement);
}
}
}
continue;
}
if (aAllowed.mDangerousSrc && nsGkAtoms::src == attrLocal) {

View File

@ -76,7 +76,7 @@
* its own sub-tree, even if multiple tabs are showing the same URI.
*
* - <top-uri> is the URI of the top window. Excepting special windows (such
* as browser.xul or hiddenWindow.html) it's what the address bar shows for
* as browser.xhtml or hiddenWindow.html) it's what the address bar shows for
* the tab.
*
*/

View File

@ -57,3 +57,4 @@ skip-if = (os == "win" && processor == "aarch64") # aarch64 due to bug 1536566
[browser_multiple_popups.js]
skip-if = os == 'win' && !debug # Bug 1505235
support-files = browser_multiple_popups.html
[browser_outline_refocus.js]

View File

@ -0,0 +1,65 @@
const URL = `data:text/html,<a target="_blank" href="http://example.com">Click me</a>`;
async function test_browser_outline_refocus(
aMessage,
aShouldFocusBeVisible,
aOpenTabCallback
) {
await BrowserTestUtils.withNewTab(URL, async function(browser) {
let tab = gBrowser.getTabForBrowser(browser);
let newTabPromise = BrowserTestUtils.waitForNewTab(gBrowser);
await aOpenTabCallback(browser);
info("waiting for new tab");
let newTab = await newTabPromise;
is(gBrowser.selectedTab, newTab, "Should've switched to the new tab");
info("switching back");
await BrowserTestUtils.switchTab(gBrowser, tab);
info("checking focus");
let [wasFocused, wasFocusVisible] = await SpecialPowers.spawn(
browser,
[],
() => {
let link = content.document.querySelector("a");
return [link.matches(":focus"), link.matches(":focus-visible")];
}
);
ok(wasFocused, "Link should be refocused");
is(wasFocusVisible, aShouldFocusBeVisible, aMessage);
info("closing tab");
await BrowserTestUtils.removeTab(newTab);
});
}
add_task(async function browser_outline_refocus_mouse() {
await test_browser_outline_refocus(
"Link shouldn't show outlines since it was originally focused by mouse",
false,
function(aBrowser) {
info("clicking on link");
return BrowserTestUtils.synthesizeMouseAtCenter("a", {}, aBrowser);
}
);
});
add_task(async function browser_outline_refocus_key() {
await SpecialPowers.pushPrefEnv({
set: [["accessibility.tabfocus", 7]],
});
await test_browser_outline_refocus(
"Link should show outlines since it was originally focused by keyboard",
true,
function(aBrowser) {
info("Navigating via keyboard");
EventUtils.sendKey("tab");
EventUtils.sendKey("return");
}
);
});

View File

@ -15,7 +15,7 @@ support-files =
referrer_testserver.sjs
!/image/test/mochitest/shaver.png
[test_anonymousContent_xul_window.xul]
[test_anonymousContent_xul_window.xhtml]
[test_blockParsing.html]
[test_blocking_image.html]
[test_bug419527.xhtml]
@ -23,12 +23,11 @@ support-files =
[test_bug1008126.html]
[test_bug1016960.html]
[test_anchor_target_blank_referrer.html]
[test_copypaste.xul]
[test_domrequesthelper.xul]
[test_fragment_sanitization.xul]
[test_domrequesthelper.xhtml]
[test_fragment_sanitization.xhtml]
[test_messagemanager_send_principal.html]
[test_navigator_resolve_identity_xrays.xul]
support-files = file_navigator_resolve_identity_xrays.xul
[test_navigator_resolve_identity_xrays.xhtml]
support-files = file_navigator_resolve_identity_xrays.xhtml
[test_sandboxed_blob_uri.html]
[test_sendQueryContentAndSelectionSetEvent.html]
[test_urgent_start.html]

View File

@ -2,87 +2,83 @@
skip-if = os == 'android'
support-files =
bug418986-1.js
cpows_child.js
cpows_parent.xul
file_bug549682.xul
file_bug616841.xul
file_bug816340.xul
file_bug990812-1.xul
file_bug990812-2.xul
file_bug990812-3.xul
file_bug990812-4.xul
file_bug990812-5.xul
file_bug1139964.xul
file_bug1209621.xul
clonedoc/**
file_bug549682.xhtml
file_bug616841.xhtml
file_bug816340.xhtml
file_bug990812-1.xhtml
file_bug990812-2.xhtml
file_bug990812-3.xhtml
file_bug990812-4.xhtml
file_bug990812-5.xhtml
file_bug1139964.xhtml
file_bug1209621.xhtml
fileconstructor_file.png
frame_bug814638.xul
frame_bug814638.xhtml
frame_custom_element_content.html
custom_element_ep.js
host_bug814638.xul
window_nsITextInputProcessor.xul
title_window.xul
window_swapFrameLoaders.xul
host_bug814638.xhtml
window_nsITextInputProcessor.xhtml
title_window.xhtml
window_swapFrameLoaders.xhtml
[test_bug120684.xul]
[test_bug206691.xul]
[test_bug289714.xul]
[test_bug339494.xul]
[test_bug357450.xul]
[test_bug120684.xhtml]
[test_bug206691.xhtml]
[test_bug289714.xhtml]
[test_bug339494.xhtml]
[test_bug357450.xhtml]
support-files = ../file_bug357450.js
[test_bug380418.html]
[test_bug380418.html^headers^]
[test_bug383430.html]
[test_bug418986-1.xul]
[test_bug421622.xul]
[test_bug429785.xul]
[test_bug430050.xul]
[test_bug467123.xul]
[test_bug473284.xul]
[test_bug549682.xul]
[test_bug418986-1.xhtml]
[test_bug421622.xhtml]
[test_bug429785.xhtml]
[test_bug430050.xhtml]
[test_bug467123.xhtml]
[test_bug473284.xhtml]
[test_bug549682.xhtml]
skip-if = verify
[test_bug571390.xul]
[test_bug1098074_throw_from_ReceiveMessage.xul]
[test_bug616841.xul]
[test_bug635835.xul]
[test_bug571390.xhtml]
[test_bug1098074_throw_from_ReceiveMessage.xhtml]
[test_bug616841.xhtml]
[test_bug635835.xhtml]
[test_bug682305.html]
[test_bug683852.xul]
[test_bug752226-3.xul]
[test_bug752226-4.xul]
[test_bug683852.xhtml]
[test_bug752226-3.xhtml]
[test_bug752226-4.xhtml]
[test_bug765993.html]
[test_bug780199.xul]
[test_bug780529.xul]
[test_bug800386.xul]
[test_bug814638.xul]
[test_bug816340.xul]
[test_bug884693.xul]
[test_bug780199.xhtml]
[test_bug780529.xhtml]
[test_bug800386.xhtml]
[test_bug814638.xhtml]
[test_bug816340.xhtml]
[test_bug884693.xhtml]
[test_bug914381.html]
[test_bug990812.xul]
[test_bug1063837.xul]
[test_bug1139964.xul]
[test_bug1209621.xul]
[test_bug990812.xhtml]
[test_bug1063837.xhtml]
[test_bug1139964.xhtml]
[test_bug1209621.xhtml]
[test_bug1346936.html]
[test_chromeOuterWindowID.xul]
[test_chromeOuterWindowID.xhtml]
support-files =
window_chromeOuterWindowID.xul
[test_cpows.xul]
support-files =
cpows_child.html
window_chromeOuterWindowID.xhtml
[test_getElementsWithGrid.html]
[test_custom_element_content.xul]
[test_custom_element_ep.xul]
[test_document-element-inserted.xul]
[test_custom_element_content.xhtml]
[test_custom_element_ep.xhtml]
[test_document-element-inserted.xhtml]
support-files =
file_document-element-inserted.xul
file_document-element-inserted-inner.xul
[test_domparsing.xul]
[test_fileconstructor.xul]
file_document-element-inserted.xhtml
file_document-element-inserted-inner.xhtml
[test_domparsing.xhtml]
[test_fileconstructor.xhtml]
[test_input_value_set_preserve_undo.xhtml]
[test_nsITextInputProcessor.xul]
[test_permission_isHandlingUserInput.xul]
[test_nsITextInputProcessor.xhtml]
[test_permission_isHandlingUserInput.xhtml]
support-files = ../dummy.html
[test_range_getClientRectsAndTexts.html]
[test_title.xul]
support-files = file_title.xul
[test_windowroot.xul]
[test_swapFrameLoaders.xul]
[test_title.xhtml]
support-files = file_title.xhtml
[test_windowroot.xhtml]
[test_swapFrameLoaders.xhtml]
[test_bug1339722.html]

View File

@ -0,0 +1 @@
content clonedoc content/

View File

@ -0,0 +1,4 @@
<?xml version='1.0' encoding='UTF-8'?>
<something>
<somethinglese/>
</something>

View File

@ -173,7 +173,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=549682
messageManager.removeDelayedFrameScript(toBeRemovedScript);
var oldValue = globalListenerCallCount;
var b = document.createElement("browser");
var b = document.createXULElement("browser");
b.setAttribute("type", "content");
document.documentElement.appendChild(b);
is(globalListenerCallCount, oldValue + 1,

View File

@ -45,7 +45,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=990812
}
});
var browser = document.createElement("browser");
var browser = document.createXULElement("browser");
browser.setAttribute("messagemanagergroup", "test");
browser.setAttribute("src", "about:mozilla");
browser.setAttribute("type", "content");

View File

@ -39,7 +39,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=990812
}
});
var browser = document.createElement("browser");
var browser = document.createXULElement("browser");
browser.setAttribute("messagemanagergroup", "test");
browser.setAttribute("src", "about:mozilla");
browser.setAttribute("type", "content");

View File

@ -1,3 +1,3 @@
<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'>
<iframe src='file_document-element-inserted-inner.xul'></iframe>
<iframe src='file_document-element-inserted-inner.xhtml'></iframe>
</window>

View File

@ -5,5 +5,5 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=814638
-->
<window title="Mozilla Bug 814638"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<iframe flex="1" src="frame_bug814638.xul"/>
<iframe flex="1" src="frame_bug814638.xhtml"/>
</window>

Some files were not shown because too many files have changed in this diff Show More