2007-03-22 10:30:00 -07:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2009-04-23 00:21:22 -07:00
|
|
|
/* vim: set ts=2 sw=2 et tw=79: */
|
2012-05-21 04:12:37 -07:00
|
|
|
/* 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/. */
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Base class for all element classes; this provides an implementation
|
|
|
|
* of DOM Core's nsIDOMElement, implements nsIContent, provides
|
|
|
|
* utility methods for subclasses, and so forth.
|
|
|
|
*/
|
|
|
|
|
2011-10-10 22:50:08 -07:00
|
|
|
#include "mozilla/Util.h"
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsGenericElement.h"
|
|
|
|
|
|
|
|
#include "nsDOMAttribute.h"
|
|
|
|
#include "nsDOMAttributeMap.h"
|
|
|
|
#include "nsIAtom.h"
|
2012-03-28 22:43:09 -07:00
|
|
|
#include "nsINodeInfo.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsIDocument.h"
|
|
|
|
#include "nsIDOMNodeList.h"
|
|
|
|
#include "nsIDOMDocument.h"
|
|
|
|
#include "nsIContentIterator.h"
|
2011-06-23 19:18:01 -07:00
|
|
|
#include "nsEventListenerManager.h"
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 11:00:39 -07:00
|
|
|
#include "nsFocusManager.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsILinkHandler.h"
|
|
|
|
#include "nsIScriptGlobalObject.h"
|
|
|
|
#include "nsIURL.h"
|
|
|
|
#include "nsNetUtil.h"
|
|
|
|
#include "nsIFrame.h"
|
2010-02-11 09:34:01 -08:00
|
|
|
#include "nsIAnonymousContentCreator.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsIPresShell.h"
|
|
|
|
#include "nsPresContext.h"
|
|
|
|
#include "nsStyleConsts.h"
|
|
|
|
#include "nsString.h"
|
|
|
|
#include "nsUnicharUtils.h"
|
2011-04-21 10:35:52 -07:00
|
|
|
#include "nsEventStateManager.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsIDOMEvent.h"
|
|
|
|
#include "nsDOMCID.h"
|
|
|
|
#include "nsIServiceManager.h"
|
|
|
|
#include "nsIDOMCSSStyleDeclaration.h"
|
2009-09-02 17:28:37 -07:00
|
|
|
#include "nsDOMCSSAttrDeclaration.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsINameSpaceManager.h"
|
|
|
|
#include "nsContentList.h"
|
2009-08-12 01:55:14 -07:00
|
|
|
#include "nsDOMTokenList.h"
|
2011-02-10 23:47:00 -08:00
|
|
|
#include "nsXBLPrototypeBinding.h"
|
2012-07-27 07:03:27 -07:00
|
|
|
#include "nsError.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsDOMString.h"
|
|
|
|
#include "nsIScriptSecurityManager.h"
|
|
|
|
#include "nsIDOMMutationEvent.h"
|
|
|
|
#include "nsMutationEvent.h"
|
|
|
|
#include "nsNodeUtils.h"
|
2012-04-16 21:03:10 -07:00
|
|
|
#include "mozilla/dom/DirectionalityUtils.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsDocument.h"
|
2012-02-13 18:00:56 -08:00
|
|
|
#include "nsAttrValueOrString.h"
|
2007-07-08 17:58:15 -07:00
|
|
|
#ifdef MOZ_XUL
|
2007-05-15 18:13:47 -07:00
|
|
|
#include "nsXULElement.h"
|
2007-07-08 17:58:15 -07:00
|
|
|
#endif /* MOZ_XUL */
|
2007-09-21 02:15:42 -07:00
|
|
|
#include "nsFrameManager.h"
|
2008-02-19 23:40:04 -08:00
|
|
|
#include "nsFrameSelection.h"
|
2011-12-20 01:15:41 -08:00
|
|
|
#ifdef DEBUG
|
2012-01-10 06:19:54 -08:00
|
|
|
#include "nsRange.h"
|
2011-12-20 01:15:41 -08:00
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
#include "nsBindingManager.h"
|
|
|
|
#include "nsXBLBinding.h"
|
|
|
|
#include "nsPIDOMWindow.h"
|
|
|
|
#include "nsPIBoxObject.h"
|
2008-03-11 17:51:12 -07:00
|
|
|
#include "nsClientRect.h"
|
2007-05-30 15:32:54 -07:00
|
|
|
#include "nsSVGUtils.h"
|
|
|
|
#include "nsLayoutUtils.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsGkAtoms.h"
|
|
|
|
#include "nsContentUtils.h"
|
|
|
|
#include "nsIJSContextStack.h"
|
|
|
|
|
|
|
|
#include "nsIDOMEventListener.h"
|
|
|
|
#include "nsIWebNavigation.h"
|
|
|
|
#include "nsIBaseWindow.h"
|
2011-11-27 03:51:53 -08:00
|
|
|
#include "nsIWidget.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
#include "jsapi.h"
|
|
|
|
|
|
|
|
#include "nsNodeInfoManager.h"
|
|
|
|
#include "nsICategoryManager.h"
|
|
|
|
#include "nsIDOMDocumentType.h"
|
|
|
|
#include "nsIDOMUserDataHandler.h"
|
2009-02-10 12:56:51 -08:00
|
|
|
#include "nsGenericHTMLElement.h"
|
2008-02-19 23:40:04 -08:00
|
|
|
#include "nsIEditor.h"
|
2010-05-04 10:40:39 -07:00
|
|
|
#include "nsIEditorIMESupport.h"
|
2008-02-19 23:40:04 -08:00
|
|
|
#include "nsIEditorDocShell.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsEventDispatcher.h"
|
|
|
|
#include "nsContentCreatorFunctions.h"
|
|
|
|
#include "nsIControllers.h"
|
2008-08-15 15:26:37 -07:00
|
|
|
#include "nsIView.h"
|
|
|
|
#include "nsIViewManager.h"
|
|
|
|
#include "nsIScrollableFrame.h"
|
2007-05-21 15:26:48 -07:00
|
|
|
#include "nsXBLInsertionPoint.h"
|
2011-03-10 18:48:57 -08:00
|
|
|
#include "mozilla/css/StyleRule.h" /* For nsCSSSelectorList */
|
2008-07-21 17:55:52 -07:00
|
|
|
#include "nsCSSRuleProcessor.h"
|
2009-08-01 08:53:40 -07:00
|
|
|
#include "nsRuleProcessorData.h"
|
2011-12-16 22:02:05 -08:00
|
|
|
#include "nsAsyncDOMEvent.h"
|
2011-08-15 17:55:20 -07:00
|
|
|
#include "nsTextNode.h"
|
2011-05-23 08:39:52 -07:00
|
|
|
#include "dombindings.h"
|
2008-07-21 17:55:52 -07:00
|
|
|
|
2007-07-08 17:58:15 -07:00
|
|
|
#ifdef MOZ_XUL
|
2007-05-24 17:28:20 -07:00
|
|
|
#include "nsIXULDocument.h"
|
2007-07-08 17:58:15 -07:00
|
|
|
#endif /* MOZ_XUL */
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
#include "nsCycleCollectionParticipant.h"
|
2007-05-10 13:21:12 -07:00
|
|
|
#include "nsCCUncollectableMarker.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2008-04-11 10:29:06 -07:00
|
|
|
#include "mozAutoDocUpdate.h"
|
|
|
|
|
2010-03-02 12:59:32 -08:00
|
|
|
#include "nsCSSParser.h"
|
2010-09-14 21:46:40 -07:00
|
|
|
#include "prprf.h"
|
2012-03-31 09:30:13 -07:00
|
|
|
#include "nsDOMMutationObserver.h"
|
2009-05-07 12:37:33 -07:00
|
|
|
#include "nsSVGFeatures.h"
|
2011-05-26 12:58:35 -07:00
|
|
|
#include "nsWrapperCacheInlines.h"
|
2012-01-30 12:08:13 -08:00
|
|
|
#include "nsCycleCollector.h"
|
2011-08-24 12:49:25 -07:00
|
|
|
#include "xpcpublic.h"
|
2012-05-18 01:29:40 -07:00
|
|
|
#include "nsIScriptError.h"
|
2012-03-01 05:09:00 -08:00
|
|
|
#include "nsLayoutStatics.h"
|
|
|
|
#include "mozilla/Telemetry.h"
|
2011-08-24 12:49:25 -07:00
|
|
|
|
2012-03-10 08:13:51 -08:00
|
|
|
#include "mozilla/CORSMode.h"
|
|
|
|
|
2012-03-21 21:10:51 -07:00
|
|
|
#include "nsStyledElement.h"
|
|
|
|
|
2011-10-10 22:50:08 -07:00
|
|
|
using namespace mozilla;
|
2010-04-30 06:12:05 -07:00
|
|
|
using namespace mozilla::dom;
|
2012-04-16 21:03:10 -07:00
|
|
|
using namespace mozilla::directionality;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2010-10-20 04:26:32 -07:00
|
|
|
nsEventStates
|
2011-05-31 18:46:56 -07:00
|
|
|
Element::IntrinsicState() const
|
2007-06-27 19:48:16 -07:00
|
|
|
{
|
2007-07-11 06:05:05 -07:00
|
|
|
return IsEditable() ? NS_EVENT_STATE_MOZ_READWRITE :
|
|
|
|
NS_EVENT_STATE_MOZ_READONLY;
|
2007-06-27 19:48:16 -07:00
|
|
|
}
|
|
|
|
|
2011-05-31 18:46:56 -07:00
|
|
|
void
|
|
|
|
Element::NotifyStateChange(nsEventStates aStates)
|
|
|
|
{
|
|
|
|
nsIDocument* doc = GetCurrentDoc();
|
|
|
|
if (doc) {
|
|
|
|
nsAutoScriptBlocker scriptBlocker;
|
|
|
|
doc->ContentStateChanged(this, aStates);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-31 18:46:57 -07:00
|
|
|
void
|
|
|
|
Element::UpdateLinkState(nsEventStates aState)
|
|
|
|
{
|
|
|
|
NS_ABORT_IF_FALSE(!aState.HasAtLeastOneOfStates(~(NS_EVENT_STATE_VISITED |
|
|
|
|
NS_EVENT_STATE_UNVISITED)),
|
|
|
|
"Unexpected link state bits");
|
|
|
|
mState =
|
|
|
|
(mState & ~(NS_EVENT_STATE_VISITED | NS_EVENT_STATE_UNVISITED)) |
|
|
|
|
aState;
|
|
|
|
}
|
|
|
|
|
2007-06-27 19:48:16 -07:00
|
|
|
void
|
2011-05-31 18:46:57 -07:00
|
|
|
Element::UpdateState(bool aNotify)
|
2007-06-27 19:48:16 -07:00
|
|
|
{
|
2011-05-31 18:46:57 -07:00
|
|
|
nsEventStates oldState = mState;
|
|
|
|
mState = IntrinsicState() | (oldState & ESM_MANAGED_STATES);
|
|
|
|
if (aNotify) {
|
|
|
|
nsEventStates changedStates = oldState ^ mState;
|
|
|
|
if (!changedStates.IsEmpty()) {
|
|
|
|
nsIDocument* doc = GetCurrentDoc();
|
|
|
|
if (doc) {
|
|
|
|
nsAutoScriptBlocker scriptBlocker;
|
|
|
|
doc->ContentStateChanged(this, changedStates);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2011-09-28 23:19:26 -07:00
|
|
|
nsIContent::UpdateEditableState(bool aNotify)
|
2011-05-31 18:46:57 -07:00
|
|
|
{
|
|
|
|
// Guaranteed to be non-element content
|
|
|
|
NS_ASSERTION(!IsElement(), "What happened here?");
|
2007-06-27 19:48:16 -07:00
|
|
|
nsIContent *parent = GetParent();
|
|
|
|
|
|
|
|
SetEditableFlag(parent && parent->HasFlag(NODE_IS_EDITABLE));
|
|
|
|
}
|
|
|
|
|
2011-05-31 18:46:57 -07:00
|
|
|
void
|
2011-09-28 23:19:26 -07:00
|
|
|
nsGenericElement::UpdateEditableState(bool aNotify)
|
2011-05-31 18:46:57 -07:00
|
|
|
{
|
|
|
|
nsIContent *parent = GetParent();
|
|
|
|
|
|
|
|
SetEditableFlag(parent && parent->HasFlag(NODE_IS_EDITABLE));
|
2011-07-20 12:58:25 -07:00
|
|
|
if (aNotify) {
|
|
|
|
UpdateState(aNotify);
|
|
|
|
} else {
|
|
|
|
// Avoid calling UpdateState in this very common case, because
|
|
|
|
// this gets called for pretty much every single element on
|
|
|
|
// insertion into the document and UpdateState can be slow for
|
|
|
|
// some kinds of elements even when not notifying.
|
|
|
|
if (IsEditable()) {
|
|
|
|
RemoveStatesSilently(NS_EVENT_STATE_MOZ_READONLY);
|
|
|
|
AddStatesSilently(NS_EVENT_STATE_MOZ_READWRITE);
|
2011-05-31 18:46:57 -07:00
|
|
|
} else {
|
2011-07-20 12:58:25 -07:00
|
|
|
RemoveStatesSilently(NS_EVENT_STATE_MOZ_READWRITE);
|
|
|
|
AddStatesSilently(NS_EVENT_STATE_MOZ_READONLY);
|
2011-05-31 18:46:57 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-08 10:42:38 -08:00
|
|
|
nsEventStates
|
|
|
|
Element::StyleStateFromLocks() const
|
|
|
|
{
|
|
|
|
nsEventStates locks = LockedStyleStates();
|
|
|
|
nsEventStates state = mState | locks;
|
|
|
|
|
|
|
|
if (locks.HasState(NS_EVENT_STATE_VISITED)) {
|
|
|
|
return state & ~NS_EVENT_STATE_UNVISITED;
|
|
|
|
}
|
|
|
|
if (locks.HasState(NS_EVENT_STATE_UNVISITED)) {
|
|
|
|
return state & ~NS_EVENT_STATE_VISITED;
|
|
|
|
}
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsEventStates
|
|
|
|
Element::LockedStyleStates() const
|
|
|
|
{
|
|
|
|
nsEventStates *locks =
|
|
|
|
static_cast<nsEventStates*> (GetProperty(nsGkAtoms::lockedStyleStates));
|
|
|
|
if (locks) {
|
|
|
|
return *locks;
|
|
|
|
}
|
|
|
|
return nsEventStates();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
nsEventStatesPropertyDtor(void *aObject, nsIAtom *aProperty,
|
|
|
|
void *aPropertyValue, void *aData)
|
|
|
|
{
|
|
|
|
nsEventStates *states = static_cast<nsEventStates*>(aPropertyValue);
|
|
|
|
delete states;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Element::NotifyStyleStateChange(nsEventStates aStates)
|
|
|
|
{
|
|
|
|
nsIDocument* doc = GetCurrentDoc();
|
|
|
|
if (doc) {
|
|
|
|
nsIPresShell *presShell = doc->GetShell();
|
|
|
|
if (presShell) {
|
|
|
|
nsAutoScriptBlocker scriptBlocker;
|
|
|
|
presShell->ContentStateChanged(doc, this, aStates);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Element::LockStyleStates(nsEventStates aStates)
|
|
|
|
{
|
|
|
|
nsEventStates *locks = new nsEventStates(LockedStyleStates());
|
|
|
|
|
|
|
|
*locks |= aStates;
|
|
|
|
|
|
|
|
if (aStates.HasState(NS_EVENT_STATE_VISITED)) {
|
|
|
|
*locks &= ~NS_EVENT_STATE_UNVISITED;
|
|
|
|
}
|
|
|
|
if (aStates.HasState(NS_EVENT_STATE_UNVISITED)) {
|
|
|
|
*locks &= ~NS_EVENT_STATE_VISITED;
|
|
|
|
}
|
|
|
|
|
|
|
|
SetProperty(nsGkAtoms::lockedStyleStates, locks, nsEventStatesPropertyDtor);
|
|
|
|
SetHasLockedStyleStates();
|
|
|
|
|
|
|
|
NotifyStyleStateChange(aStates);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Element::UnlockStyleStates(nsEventStates aStates)
|
|
|
|
{
|
|
|
|
nsEventStates *locks = new nsEventStates(LockedStyleStates());
|
|
|
|
|
|
|
|
*locks &= ~aStates;
|
|
|
|
|
|
|
|
if (locks->IsEmpty()) {
|
|
|
|
DeleteProperty(nsGkAtoms::lockedStyleStates);
|
|
|
|
ClearHasLockedStyleStates();
|
|
|
|
delete locks;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
SetProperty(nsGkAtoms::lockedStyleStates, locks, nsEventStatesPropertyDtor);
|
|
|
|
}
|
|
|
|
|
|
|
|
NotifyStyleStateChange(aStates);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Element::ClearStyleStateLocks()
|
|
|
|
{
|
|
|
|
nsEventStates locks = LockedStyleStates();
|
|
|
|
|
|
|
|
DeleteProperty(nsGkAtoms::lockedStyleStates);
|
|
|
|
ClearHasLockedStyleStates();
|
|
|
|
|
|
|
|
NotifyStyleStateChange(locks);
|
|
|
|
}
|
|
|
|
|
2010-04-19 08:41:37 -07:00
|
|
|
nsIContent*
|
|
|
|
nsGenericElement::GetFirstElementChild()
|
2008-08-04 17:58:16 -07:00
|
|
|
{
|
2010-04-19 08:41:37 -07:00
|
|
|
nsAttrAndChildArray& children = mAttrsAndChildren;
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t i, count = children.ChildCount();
|
2008-08-04 17:58:16 -07:00
|
|
|
for (i = 0; i < count; ++i) {
|
|
|
|
nsIContent* child = children.ChildAt(i);
|
2010-04-30 06:12:05 -07:00
|
|
|
if (child->IsElement()) {
|
2010-04-19 08:41:37 -07:00
|
|
|
return child;
|
2008-08-04 17:58:16 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-30 07:20:58 -07:00
|
|
|
return nullptr;
|
2008-08-04 17:58:16 -07:00
|
|
|
}
|
|
|
|
|
2010-04-19 08:41:37 -07:00
|
|
|
nsIContent*
|
|
|
|
nsGenericElement::GetLastElementChild()
|
2008-08-04 17:58:16 -07:00
|
|
|
{
|
2010-04-19 08:41:37 -07:00
|
|
|
nsAttrAndChildArray& children = mAttrsAndChildren;
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t i = children.ChildCount();
|
2008-08-04 17:58:16 -07:00
|
|
|
while (i > 0) {
|
|
|
|
nsIContent* child = children.ChildAt(--i);
|
2010-04-30 06:12:05 -07:00
|
|
|
if (child->IsElement()) {
|
2010-04-19 08:41:37 -07:00
|
|
|
return child;
|
2008-08-04 17:58:16 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-30 07:20:58 -07:00
|
|
|
return nullptr;
|
2008-08-04 17:58:16 -07:00
|
|
|
}
|
|
|
|
|
2010-04-19 08:41:37 -07:00
|
|
|
nsIContent*
|
|
|
|
nsGenericElement::GetPreviousElementSibling()
|
2008-08-04 17:58:16 -07:00
|
|
|
{
|
2010-04-19 08:41:37 -07:00
|
|
|
nsIContent* parent = GetParent();
|
2008-08-04 17:58:16 -07:00
|
|
|
if (!parent) {
|
2012-07-30 07:20:58 -07:00
|
|
|
return nullptr;
|
2008-08-04 17:58:16 -07:00
|
|
|
}
|
|
|
|
|
2010-04-30 06:12:05 -07:00
|
|
|
NS_ASSERTION(parent->IsElement() ||
|
2008-08-04 17:58:16 -07:00
|
|
|
parent->IsNodeOfType(nsINode::eDOCUMENT_FRAGMENT),
|
|
|
|
"Parent content must be an element or a doc fragment");
|
|
|
|
|
|
|
|
nsAttrAndChildArray& children =
|
|
|
|
static_cast<nsGenericElement*>(parent)->mAttrsAndChildren;
|
2012-08-22 08:56:38 -07:00
|
|
|
int32_t index = children.IndexOfChild(this);
|
2008-08-04 17:58:16 -07:00
|
|
|
if (index < 0) {
|
2012-07-30 07:20:58 -07:00
|
|
|
return nullptr;
|
2008-08-04 17:58:16 -07:00
|
|
|
}
|
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t i = index;
|
2008-08-04 17:58:16 -07:00
|
|
|
while (i > 0) {
|
2012-08-22 08:56:38 -07:00
|
|
|
nsIContent* child = children.ChildAt((uint32_t)--i);
|
2010-04-30 06:12:05 -07:00
|
|
|
if (child->IsElement()) {
|
2010-04-19 08:41:37 -07:00
|
|
|
return child;
|
2008-08-04 17:58:16 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-30 07:20:58 -07:00
|
|
|
return nullptr;
|
2008-08-04 17:58:16 -07:00
|
|
|
}
|
|
|
|
|
2010-04-19 08:41:37 -07:00
|
|
|
nsIContent*
|
|
|
|
nsGenericElement::GetNextElementSibling()
|
2008-08-04 17:58:16 -07:00
|
|
|
{
|
2010-04-19 08:41:37 -07:00
|
|
|
nsIContent* parent = GetParent();
|
2008-08-04 17:58:16 -07:00
|
|
|
if (!parent) {
|
2012-07-30 07:20:58 -07:00
|
|
|
return nullptr;
|
2008-08-04 17:58:16 -07:00
|
|
|
}
|
|
|
|
|
2010-04-30 06:12:05 -07:00
|
|
|
NS_ASSERTION(parent->IsElement() ||
|
2008-08-04 17:58:16 -07:00
|
|
|
parent->IsNodeOfType(nsINode::eDOCUMENT_FRAGMENT),
|
|
|
|
"Parent content must be an element or a doc fragment");
|
|
|
|
|
|
|
|
nsAttrAndChildArray& children =
|
|
|
|
static_cast<nsGenericElement*>(parent)->mAttrsAndChildren;
|
2012-08-22 08:56:38 -07:00
|
|
|
int32_t index = children.IndexOfChild(this);
|
2008-08-04 17:58:16 -07:00
|
|
|
if (index < 0) {
|
2012-07-30 07:20:58 -07:00
|
|
|
return nullptr;
|
2008-08-04 17:58:16 -07:00
|
|
|
}
|
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t i, count = children.ChildCount();
|
|
|
|
for (i = (uint32_t)index + 1; i < count; ++i) {
|
2008-08-04 17:58:16 -07:00
|
|
|
nsIContent* child = children.ChildAt(i);
|
2010-04-30 06:12:05 -07:00
|
|
|
if (child->IsElement()) {
|
2010-04-19 08:41:37 -07:00
|
|
|
return child;
|
2008-08-04 17:58:16 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-30 07:20:58 -07:00
|
|
|
return nullptr;
|
2010-04-19 08:41:37 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2012-08-22 08:56:38 -07:00
|
|
|
nsGenericElement::GetChildElementCount(uint32_t* aResult)
|
2011-12-18 02:06:23 -08:00
|
|
|
{
|
|
|
|
*aResult = GetChildrenList()->Length(true);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// readonly attribute nsIDOMNodeList children
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsGenericElement::GetChildElements(nsIDOMNodeList** aResult)
|
|
|
|
{
|
|
|
|
NS_ADDREF(*aResult = GetChildrenList());
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsGenericElement::GetFirstElementChild(nsIDOMElement** aResult)
|
2010-04-19 08:41:37 -07:00
|
|
|
{
|
2012-07-30 07:20:58 -07:00
|
|
|
*aResult = nullptr;
|
2010-04-19 08:41:37 -07:00
|
|
|
|
2011-12-18 02:06:23 -08:00
|
|
|
nsIContent *result = GetFirstElementChild();
|
2010-04-19 08:41:37 -07:00
|
|
|
|
|
|
|
return result ? CallQueryInterface(result, aResult) : NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2011-12-18 02:06:23 -08:00
|
|
|
nsGenericElement::GetLastElementChild(nsIDOMElement** aResult)
|
2010-04-19 08:41:37 -07:00
|
|
|
{
|
2012-07-30 07:20:58 -07:00
|
|
|
*aResult = nullptr;
|
2010-04-19 08:41:37 -07:00
|
|
|
|
2011-12-18 02:06:23 -08:00
|
|
|
nsIContent *result = GetLastElementChild();
|
2010-04-19 08:41:37 -07:00
|
|
|
|
|
|
|
return result ? CallQueryInterface(result, aResult) : NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2011-12-18 02:06:23 -08:00
|
|
|
nsGenericElement::GetPreviousElementSibling(nsIDOMElement** aResult)
|
2010-04-19 08:41:37 -07:00
|
|
|
{
|
2012-07-30 07:20:58 -07:00
|
|
|
*aResult = nullptr;
|
2010-04-19 08:41:37 -07:00
|
|
|
|
2011-12-18 02:06:23 -08:00
|
|
|
nsIContent *result = GetPreviousElementSibling();
|
2010-04-19 08:41:37 -07:00
|
|
|
|
|
|
|
return result ? CallQueryInterface(result, aResult) : NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2011-12-18 02:06:23 -08:00
|
|
|
nsGenericElement::GetNextElementSibling(nsIDOMElement** aResult)
|
2010-04-19 08:41:37 -07:00
|
|
|
{
|
2012-07-30 07:20:58 -07:00
|
|
|
*aResult = nullptr;
|
2010-04-19 08:41:37 -07:00
|
|
|
|
2011-12-18 02:06:23 -08:00
|
|
|
nsIContent *result = GetNextElementSibling();
|
2010-04-19 08:41:37 -07:00
|
|
|
|
|
|
|
return result ? CallQueryInterface(result, aResult) : NS_OK;
|
2008-08-04 17:58:16 -07:00
|
|
|
}
|
|
|
|
|
2011-08-22 02:14:13 -07:00
|
|
|
nsDOMTokenList*
|
2010-04-19 08:41:37 -07:00
|
|
|
nsGenericElement::GetClassList(nsresult *aResult)
|
|
|
|
{
|
|
|
|
*aResult = NS_ERROR_OUT_OF_MEMORY;
|
2008-08-04 17:58:16 -07:00
|
|
|
|
2010-12-21 17:04:00 -08:00
|
|
|
nsGenericElement::nsDOMSlots *slots = DOMSlots();
|
2008-08-04 17:58:16 -07:00
|
|
|
|
2010-04-19 08:41:37 -07:00
|
|
|
if (!slots->mClassList) {
|
|
|
|
nsCOMPtr<nsIAtom> classAttr = GetClassAttributeName();
|
|
|
|
if (!classAttr) {
|
|
|
|
*aResult = NS_OK;
|
|
|
|
|
2012-07-30 07:20:58 -07:00
|
|
|
return nullptr;
|
2010-04-19 08:41:37 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
slots->mClassList = new nsDOMTokenList(this, classAttr);
|
|
|
|
}
|
|
|
|
|
|
|
|
*aResult = NS_OK;
|
|
|
|
|
|
|
|
return slots->mClassList;
|
2008-08-04 17:58:16 -07:00
|
|
|
}
|
|
|
|
|
2009-08-12 01:55:14 -07:00
|
|
|
NS_IMETHODIMP
|
2011-12-18 02:06:23 -08:00
|
|
|
nsGenericElement::GetClassList(nsIDOMDOMTokenList** aResult)
|
2009-08-12 01:55:14 -07:00
|
|
|
{
|
2012-07-30 07:20:58 -07:00
|
|
|
*aResult = nullptr;
|
2009-08-12 01:55:14 -07:00
|
|
|
|
2010-04-19 08:41:37 -07:00
|
|
|
nsresult rv;
|
2011-12-18 02:06:23 -08:00
|
|
|
nsIDOMDOMTokenList* list = GetClassList(&rv);
|
2010-04-19 08:41:37 -07:00
|
|
|
NS_ENSURE_TRUE(list, rv);
|
2009-08-12 01:55:14 -07:00
|
|
|
|
2010-04-19 08:41:37 -07:00
|
|
|
NS_ADDREF(*aResult = list);
|
2009-08-12 01:55:14 -07:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-12-18 02:06:23 -08:00
|
|
|
NS_IMETHODIMP
|
2011-09-28 23:19:26 -07:00
|
|
|
nsGenericElement::SetCapture(bool aRetargetToElement)
|
2009-09-13 06:13:16 -07:00
|
|
|
{
|
|
|
|
// If there is already an active capture, ignore this request. This would
|
|
|
|
// occur if a splitter, frame resizer, etc had already captured and we don't
|
|
|
|
// want to override those.
|
2010-05-06 05:32:14 -07:00
|
|
|
if (nsIPresShell::GetCapturingContent())
|
2011-12-18 02:06:23 -08:00
|
|
|
return NS_OK;
|
2009-09-13 06:13:16 -07:00
|
|
|
|
2010-05-06 05:32:14 -07:00
|
|
|
nsIPresShell::SetCapturingContent(this, CAPTURE_PREVENTDRAG |
|
2010-02-02 18:07:08 -08:00
|
|
|
(aRetargetToElement ? CAPTURE_RETARGETTOELEMENT : 0));
|
2010-05-06 05:32:14 -07:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-12-18 02:06:23 -08:00
|
|
|
NS_IMETHODIMP
|
2010-05-06 05:32:14 -07:00
|
|
|
nsGenericElement::ReleaseCapture()
|
2009-09-13 06:13:16 -07:00
|
|
|
{
|
2010-05-06 05:32:14 -07:00
|
|
|
if (nsIPresShell::GetCapturingContent() == this) {
|
2012-07-30 07:20:58 -07:00
|
|
|
nsIPresShell::SetCapturingContent(nullptr, 0);
|
2009-09-13 06:13:16 -07:00
|
|
|
}
|
2010-05-06 05:32:14 -07:00
|
|
|
|
2009-09-13 06:13:16 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2008-08-15 15:26:37 -07:00
|
|
|
nsIFrame*
|
|
|
|
nsGenericElement::GetStyledFrame()
|
|
|
|
{
|
|
|
|
nsIFrame *frame = GetPrimaryFrame(Flush_Layout);
|
2012-07-30 07:20:58 -07:00
|
|
|
return frame ? nsLayoutUtils::GetStyleFrame(frame) : nullptr;
|
2008-08-15 15:26:37 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsGenericElement::GetOffsetRect(nsRect& aRect, nsIContent** aOffsetParent)
|
|
|
|
{
|
2012-07-30 07:20:58 -07:00
|
|
|
*aOffsetParent = nullptr;
|
2008-08-15 15:26:37 -07:00
|
|
|
aRect = nsRect();
|
|
|
|
|
|
|
|
nsIFrame* frame = GetStyledFrame();
|
|
|
|
if (!frame) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsPoint origin = frame->GetPosition();
|
|
|
|
aRect.x = nsPresContext::AppUnitsToIntCSSPixels(origin.x);
|
|
|
|
aRect.y = nsPresContext::AppUnitsToIntCSSPixels(origin.y);
|
|
|
|
|
|
|
|
// Get the union of all rectangles in this and continuation frames.
|
|
|
|
// It doesn't really matter what we use as aRelativeTo here, since
|
|
|
|
// we only care about the size. Using 'parent' might make things
|
|
|
|
// a bit faster by speeding up the internal GetOffsetTo operations.
|
2008-09-06 01:52:56 -07:00
|
|
|
nsIFrame* parent = frame->GetParent() ? frame->GetParent() : frame;
|
|
|
|
nsRect rcFrame = nsLayoutUtils::GetAllInFlowRectsUnion(frame, parent);
|
2008-08-15 15:26:37 -07:00
|
|
|
aRect.width = nsPresContext::AppUnitsToIntCSSPixels(rcFrame.width);
|
|
|
|
aRect.height = nsPresContext::AppUnitsToIntCSSPixels(rcFrame.height);
|
|
|
|
}
|
|
|
|
|
2012-06-21 06:35:31 -07:00
|
|
|
nsIntSize
|
|
|
|
nsGenericElement::GetPaddingRectSize()
|
|
|
|
{
|
|
|
|
nsIFrame* frame = GetStyledFrame();
|
|
|
|
if (!frame) {
|
|
|
|
return nsIntSize(0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_ASSERTION(frame->GetParent(), "Styled frame has no parent");
|
|
|
|
nsRect rcFrame = nsLayoutUtils::GetAllInFlowPaddingRectsUnion(frame, frame->GetParent());
|
|
|
|
return nsIntSize(nsPresContext::AppUnitsToIntCSSPixels(rcFrame.width),
|
|
|
|
nsPresContext::AppUnitsToIntCSSPixels(rcFrame.height));
|
|
|
|
}
|
|
|
|
|
2009-09-02 20:57:36 -07:00
|
|
|
nsIScrollableFrame*
|
2010-04-19 08:41:37 -07:00
|
|
|
nsGenericElement::GetScrollFrame(nsIFrame **aStyledFrame)
|
2008-08-15 15:26:37 -07:00
|
|
|
{
|
|
|
|
// it isn't clear what to return for SVG nodes, so just return nothing
|
2010-04-19 08:41:37 -07:00
|
|
|
if (IsSVG()) {
|
2009-09-02 20:57:36 -07:00
|
|
|
if (aStyledFrame) {
|
2012-07-30 07:20:58 -07:00
|
|
|
*aStyledFrame = nullptr;
|
2009-09-02 20:57:36 -07:00
|
|
|
}
|
2012-07-30 07:20:58 -07:00
|
|
|
return nullptr;
|
2008-08-15 15:26:37 -07:00
|
|
|
}
|
|
|
|
|
2010-04-19 08:41:37 -07:00
|
|
|
nsIFrame* frame = GetStyledFrame();
|
2008-08-15 15:26:37 -07:00
|
|
|
|
2009-09-02 20:57:36 -07:00
|
|
|
if (aStyledFrame) {
|
|
|
|
*aStyledFrame = frame;
|
2008-08-15 15:26:37 -07:00
|
|
|
}
|
|
|
|
if (!frame) {
|
2012-07-30 07:20:58 -07:00
|
|
|
return nullptr;
|
2008-08-15 15:26:37 -07:00
|
|
|
}
|
|
|
|
|
2009-09-02 20:57:36 -07:00
|
|
|
// menu frames implement GetScrollTargetFrame but we don't want
|
2011-10-18 13:17:45 -07:00
|
|
|
// to use it here. Similar for comboboxes.
|
|
|
|
if (frame->GetType() != nsGkAtoms::menuFrame &&
|
|
|
|
frame->GetType() != nsGkAtoms::comboboxControlFrame) {
|
2009-09-02 20:57:36 -07:00
|
|
|
nsIScrollableFrame *scrollFrame = frame->GetScrollTargetFrame();
|
|
|
|
if (scrollFrame)
|
|
|
|
return scrollFrame;
|
|
|
|
}
|
2008-08-15 15:26:37 -07:00
|
|
|
|
2011-10-18 03:53:36 -07:00
|
|
|
nsIDocument* doc = OwnerDoc();
|
2011-09-28 23:19:26 -07:00
|
|
|
bool quirksMode = doc->GetCompatibilityMode() == eCompatibility_NavQuirks;
|
2010-04-30 06:12:05 -07:00
|
|
|
Element* elementWithRootScrollInfo =
|
|
|
|
quirksMode ? doc->GetBodyElement() : doc->GetRootElement();
|
2010-04-19 08:41:37 -07:00
|
|
|
if (this == elementWithRootScrollInfo) {
|
2009-09-02 20:57:36 -07:00
|
|
|
// In quirks mode, the scroll info for the body element should map to the
|
|
|
|
// root scrollable frame.
|
|
|
|
// In strict mode, the scroll info for the root element should map to the
|
|
|
|
// the root scrollable frame.
|
|
|
|
return frame->PresContext()->PresShell()->GetRootScrollFrameAsScrollable();
|
2008-08-15 15:26:37 -07:00
|
|
|
}
|
|
|
|
|
2012-07-30 07:20:58 -07:00
|
|
|
return nullptr;
|
2008-08-15 15:26:37 -07:00
|
|
|
}
|
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
int32_t
|
2010-04-19 08:41:37 -07:00
|
|
|
nsGenericElement::GetScrollTop()
|
2008-08-15 15:26:37 -07:00
|
|
|
{
|
2009-09-02 20:57:36 -07:00
|
|
|
nsIScrollableFrame* sf = GetScrollFrame();
|
2012-08-10 04:17:06 -07:00
|
|
|
return sf ? sf->GetScrollPositionCSSPixels().y : 0;
|
2010-04-19 08:41:37 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2012-08-22 08:56:38 -07:00
|
|
|
nsGenericElement::GetScrollTop(int32_t* aScrollTop)
|
2010-04-19 08:41:37 -07:00
|
|
|
{
|
2011-12-18 02:06:23 -08:00
|
|
|
*aScrollTop = GetScrollTop();
|
2008-08-15 15:26:37 -07:00
|
|
|
|
2009-09-02 20:57:36 -07:00
|
|
|
return NS_OK;
|
2008-08-15 15:26:37 -07:00
|
|
|
}
|
|
|
|
|
2011-12-18 02:06:23 -08:00
|
|
|
NS_IMETHODIMP
|
2012-08-22 08:56:38 -07:00
|
|
|
nsGenericElement::SetScrollTop(int32_t aScrollTop)
|
2008-08-15 15:26:37 -07:00
|
|
|
{
|
2009-09-02 20:57:36 -07:00
|
|
|
nsIScrollableFrame* sf = GetScrollFrame();
|
|
|
|
if (sf) {
|
2012-08-10 04:17:06 -07:00
|
|
|
sf->ScrollToCSSPixels(nsIntPoint(sf->GetScrollPositionCSSPixels().x, aScrollTop));
|
2008-08-15 15:26:37 -07:00
|
|
|
}
|
2009-09-02 20:57:36 -07:00
|
|
|
return NS_OK;
|
2008-08-15 15:26:37 -07:00
|
|
|
}
|
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
int32_t
|
2010-04-19 08:41:37 -07:00
|
|
|
nsGenericElement::GetScrollLeft()
|
2008-08-15 15:26:37 -07:00
|
|
|
{
|
2009-09-02 20:57:36 -07:00
|
|
|
nsIScrollableFrame* sf = GetScrollFrame();
|
2012-08-10 04:17:06 -07:00
|
|
|
return sf ? sf->GetScrollPositionCSSPixels().x : 0;
|
2010-04-19 08:41:37 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2012-08-22 08:56:38 -07:00
|
|
|
nsGenericElement::GetScrollLeft(int32_t* aScrollLeft)
|
2010-04-19 08:41:37 -07:00
|
|
|
{
|
2011-12-18 02:06:23 -08:00
|
|
|
*aScrollLeft = GetScrollLeft();
|
2008-08-15 15:26:37 -07:00
|
|
|
|
2009-09-02 20:57:36 -07:00
|
|
|
return NS_OK;
|
2008-08-15 15:26:37 -07:00
|
|
|
}
|
|
|
|
|
2011-12-18 02:06:23 -08:00
|
|
|
NS_IMETHODIMP
|
2012-08-22 08:56:38 -07:00
|
|
|
nsGenericElement::SetScrollLeft(int32_t aScrollLeft)
|
2008-08-15 15:26:37 -07:00
|
|
|
{
|
2009-09-02 20:57:36 -07:00
|
|
|
nsIScrollableFrame* sf = GetScrollFrame();
|
|
|
|
if (sf) {
|
2012-08-10 04:17:06 -07:00
|
|
|
sf->ScrollToCSSPixels(nsIntPoint(aScrollLeft, sf->GetScrollPositionCSSPixels().y));
|
2008-08-15 15:26:37 -07:00
|
|
|
}
|
2009-09-02 20:57:36 -07:00
|
|
|
return NS_OK;
|
2008-08-15 15:26:37 -07:00
|
|
|
}
|
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
int32_t
|
2010-04-19 08:41:37 -07:00
|
|
|
nsGenericElement::GetScrollHeight()
|
2008-08-15 15:26:37 -07:00
|
|
|
{
|
2010-04-19 08:41:37 -07:00
|
|
|
if (IsSVG())
|
|
|
|
return 0;
|
2008-08-15 15:26:37 -07:00
|
|
|
|
2009-09-02 20:57:36 -07:00
|
|
|
nsIScrollableFrame* sf = GetScrollFrame();
|
|
|
|
if (!sf) {
|
2012-06-21 06:36:57 -07:00
|
|
|
return GetPaddingRectSize().height;
|
2008-08-15 15:26:37 -07:00
|
|
|
}
|
|
|
|
|
2009-09-02 20:57:36 -07:00
|
|
|
nscoord height = sf->GetScrollRange().height + sf->GetScrollPortRect().height;
|
2010-04-19 08:41:37 -07:00
|
|
|
return nsPresContext::AppUnitsToIntCSSPixels(height);
|
2008-08-15 15:26:37 -07:00
|
|
|
}
|
|
|
|
|
2010-04-19 08:41:37 -07:00
|
|
|
NS_IMETHODIMP
|
2012-08-22 08:56:38 -07:00
|
|
|
nsGenericElement::GetScrollHeight(int32_t* aScrollHeight)
|
2008-08-15 15:26:37 -07:00
|
|
|
{
|
2011-12-18 02:06:23 -08:00
|
|
|
*aScrollHeight = GetScrollHeight();
|
2008-08-15 15:26:37 -07:00
|
|
|
|
2010-04-19 08:41:37 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
int32_t
|
2010-04-19 08:41:37 -07:00
|
|
|
nsGenericElement::GetScrollWidth()
|
|
|
|
{
|
|
|
|
if (IsSVG())
|
|
|
|
return 0;
|
2008-08-15 15:26:37 -07:00
|
|
|
|
2009-09-02 20:57:36 -07:00
|
|
|
nsIScrollableFrame* sf = GetScrollFrame();
|
|
|
|
if (!sf) {
|
2012-06-21 06:36:57 -07:00
|
|
|
return GetPaddingRectSize().width;
|
2008-08-15 15:26:37 -07:00
|
|
|
}
|
|
|
|
|
2009-09-02 20:57:36 -07:00
|
|
|
nscoord width = sf->GetScrollRange().width + sf->GetScrollPortRect().width;
|
2010-04-19 08:41:37 -07:00
|
|
|
return nsPresContext::AppUnitsToIntCSSPixels(width);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2012-08-22 08:56:38 -07:00
|
|
|
nsGenericElement::GetScrollWidth(int32_t *aScrollWidth)
|
2010-04-19 08:41:37 -07:00
|
|
|
{
|
2011-12-18 02:06:23 -08:00
|
|
|
*aScrollWidth = GetScrollWidth();
|
2010-04-19 08:41:37 -07:00
|
|
|
|
2009-09-02 20:57:36 -07:00
|
|
|
return NS_OK;
|
2008-08-15 15:26:37 -07:00
|
|
|
}
|
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
int32_t
|
2012-06-26 22:30:14 -07:00
|
|
|
nsGenericElement::GetScrollLeftMax()
|
|
|
|
{
|
|
|
|
nsIScrollableFrame* sf = GetScrollFrame();
|
|
|
|
if (!sf) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nsPresContext::AppUnitsToIntCSSPixels(sf->GetScrollRange().XMost());
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2012-08-22 08:56:38 -07:00
|
|
|
nsGenericElement::GetScrollLeftMax(int32_t *aScrollLeftMax)
|
2012-06-26 22:30:14 -07:00
|
|
|
{
|
|
|
|
*aScrollLeftMax = GetScrollLeftMax();
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
int32_t
|
2012-06-26 22:30:14 -07:00
|
|
|
nsGenericElement::GetScrollTopMax()
|
|
|
|
{
|
|
|
|
nsIScrollableFrame* sf = GetScrollFrame();
|
|
|
|
if (!sf) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nsPresContext::AppUnitsToIntCSSPixels(sf->GetScrollRange().YMost());
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2012-08-22 08:56:38 -07:00
|
|
|
nsGenericElement::GetScrollTopMax(int32_t *aScrollTopMax)
|
2012-06-26 22:30:14 -07:00
|
|
|
{
|
|
|
|
*aScrollTopMax = GetScrollTopMax();
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2008-08-15 15:26:37 -07:00
|
|
|
nsRect
|
2010-04-19 08:41:37 -07:00
|
|
|
nsGenericElement::GetClientAreaRect()
|
2008-08-15 15:26:37 -07:00
|
|
|
{
|
2009-09-02 20:57:36 -07:00
|
|
|
nsIFrame* styledFrame;
|
|
|
|
nsIScrollableFrame* sf = GetScrollFrame(&styledFrame);
|
2008-08-15 15:26:37 -07:00
|
|
|
|
2009-09-02 20:57:36 -07:00
|
|
|
if (sf) {
|
|
|
|
return sf->GetScrollPortRect();
|
2008-08-15 15:26:37 -07:00
|
|
|
}
|
|
|
|
|
2009-09-02 20:57:36 -07:00
|
|
|
if (styledFrame &&
|
|
|
|
(styledFrame->GetStyleDisplay()->mDisplay != NS_STYLE_DISPLAY_INLINE ||
|
|
|
|
styledFrame->IsFrameOfType(nsIFrame::eReplaced))) {
|
2008-08-15 15:26:37 -07:00
|
|
|
// Special case code to make client area work even when there isn't
|
|
|
|
// a scroll view, see bug 180552, bug 227567.
|
2009-09-02 20:57:36 -07:00
|
|
|
return styledFrame->GetPaddingRect() - styledFrame->GetPositionIgnoringScrolling();
|
2008-08-15 15:26:37 -07:00
|
|
|
}
|
|
|
|
|
2009-09-02 20:57:36 -07:00
|
|
|
// SVG nodes reach here and just return 0
|
2008-08-15 15:26:37 -07:00
|
|
|
return nsRect(0, 0, 0, 0);
|
|
|
|
}
|
|
|
|
|
2010-04-19 08:41:37 -07:00
|
|
|
NS_IMETHODIMP
|
2012-08-22 08:56:38 -07:00
|
|
|
nsGenericElement::GetClientTop(int32_t *aClientTop)
|
2008-08-15 15:26:37 -07:00
|
|
|
{
|
2011-12-18 02:06:23 -08:00
|
|
|
*aClientTop = GetClientTop();
|
2008-08-15 15:26:37 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-04-19 08:41:37 -07:00
|
|
|
NS_IMETHODIMP
|
2012-08-22 08:56:38 -07:00
|
|
|
nsGenericElement::GetClientLeft(int32_t *aClientLeft)
|
2008-08-15 15:26:37 -07:00
|
|
|
{
|
2011-12-18 02:06:23 -08:00
|
|
|
*aClientLeft = GetClientLeft();
|
2008-08-15 15:26:37 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-04-19 08:41:37 -07:00
|
|
|
NS_IMETHODIMP
|
2012-08-22 08:56:38 -07:00
|
|
|
nsGenericElement::GetClientHeight(int32_t *aClientHeight)
|
2008-08-15 15:26:37 -07:00
|
|
|
{
|
2011-12-18 02:06:23 -08:00
|
|
|
*aClientHeight = GetClientHeight();
|
2008-08-15 15:26:37 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-04-19 08:41:37 -07:00
|
|
|
NS_IMETHODIMP
|
2012-08-22 08:56:38 -07:00
|
|
|
nsGenericElement::GetClientWidth(int32_t *aClientWidth)
|
2008-08-15 15:26:37 -07:00
|
|
|
{
|
2011-12-18 02:06:23 -08:00
|
|
|
*aClientWidth = GetClientWidth();
|
2008-08-15 15:26:37 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-12-18 02:06:23 -08:00
|
|
|
NS_IMETHODIMP
|
2010-04-19 08:41:37 -07:00
|
|
|
nsGenericElement::GetBoundingClientRect(nsIDOMClientRect** aResult)
|
2007-05-30 15:32:54 -07:00
|
|
|
{
|
|
|
|
// Weak ref, since we addref it below
|
2008-03-11 17:51:12 -07:00
|
|
|
nsClientRect* rect = new nsClientRect();
|
2007-05-30 15:32:54 -07:00
|
|
|
NS_ADDREF(*aResult = rect);
|
|
|
|
|
2010-04-19 08:41:37 -07:00
|
|
|
nsIFrame* frame = GetPrimaryFrame(Flush_Layout);
|
2007-05-30 15:32:54 -07:00
|
|
|
if (!frame) {
|
|
|
|
// display:none, perhaps? Return the empty rect
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2008-02-27 01:26:15 -08:00
|
|
|
|
|
|
|
nsRect r = nsLayoutUtils::GetAllInFlowRectsUnion(frame,
|
2011-12-27 19:26:46 -08:00
|
|
|
nsLayoutUtils::GetContainingBlockForClientRect(frame),
|
|
|
|
nsLayoutUtils::RECTS_ACCOUNT_FOR_TRANSFORMS);
|
2009-09-03 21:49:18 -07:00
|
|
|
rect->SetLayoutRect(r);
|
2007-05-30 15:32:54 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2008-01-28 09:42:52 -08:00
|
|
|
NS_IMETHODIMP
|
2011-08-11 06:29:50 -07:00
|
|
|
nsGenericElement::GetElementsByClassName(const nsAString& aClasses,
|
|
|
|
nsIDOMNodeList** aReturn)
|
|
|
|
{
|
|
|
|
return nsContentUtils::GetElementsByClassName(this, aClasses, aReturn);
|
|
|
|
}
|
|
|
|
|
2011-12-18 02:06:23 -08:00
|
|
|
NS_IMETHODIMP
|
2010-04-19 08:41:37 -07:00
|
|
|
nsGenericElement::GetClientRects(nsIDOMClientRectList** aResult)
|
2008-01-28 09:42:52 -08:00
|
|
|
{
|
2012-07-30 07:20:58 -07:00
|
|
|
*aResult = nullptr;
|
2008-01-28 09:42:52 -08:00
|
|
|
|
2011-08-22 02:14:13 -07:00
|
|
|
nsRefPtr<nsClientRectList> rectList = new nsClientRectList(this);
|
2008-02-27 01:26:15 -08:00
|
|
|
|
2010-04-19 08:41:37 -07:00
|
|
|
nsIFrame* frame = GetPrimaryFrame(Flush_Layout);
|
2008-01-28 09:42:52 -08:00
|
|
|
if (!frame) {
|
|
|
|
// display:none, perhaps? Return an empty list
|
|
|
|
*aResult = rectList.forget().get();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-09-24 14:01:48 -07:00
|
|
|
nsLayoutUtils::RectListBuilder builder(rectList);
|
2008-02-27 01:26:15 -08:00
|
|
|
nsLayoutUtils::GetAllInFlowRects(frame,
|
2011-12-27 19:26:46 -08:00
|
|
|
nsLayoutUtils::GetContainingBlockForClientRect(frame), &builder,
|
|
|
|
nsLayoutUtils::RECTS_ACCOUNT_FOR_TRANSFORMS);
|
2008-02-27 01:26:15 -08:00
|
|
|
if (NS_FAILED(builder.mRV))
|
|
|
|
return builder.mRV;
|
2008-01-28 09:42:52 -08:00
|
|
|
*aResult = rectList.forget().get();
|
2007-05-30 15:32:54 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-04-19 08:41:37 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
nsGenericElement::nsGenericElement(already_AddRefed<nsINodeInfo> aNodeInfo)
|
|
|
|
: Element(aNodeInfo)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2012-07-31 08:36:21 -07:00
|
|
|
NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::ELEMENT_NODE,
|
|
|
|
"Bad NodeType in aNodeInfo");
|
|
|
|
|
|
|
|
SetIsElement();
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2012-07-31 08:36:21 -07:00
|
|
|
nsGenericElement::GetTagName(nsAString& aTagName)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2012-07-31 08:36:21 -07:00
|
|
|
aTagName = NodeName();
|
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
nsresult
|
|
|
|
nsGenericElement::GetAttribute(const nsAString& aName,
|
|
|
|
nsAString& aReturn)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2012-07-31 08:36:21 -07:00
|
|
|
const nsAttrValue* val =
|
|
|
|
mAttrsAndChildren.GetAttr(aName,
|
|
|
|
IsHTML() && IsInHTMLDocument() ?
|
|
|
|
eIgnoreCase : eCaseMatters);
|
|
|
|
if (val) {
|
|
|
|
val->ToString(aReturn);
|
|
|
|
} else {
|
|
|
|
if (IsXUL()) {
|
|
|
|
// XXX should be SetDOMStringToNull(aReturn);
|
|
|
|
// See bug 232598
|
|
|
|
aReturn.Truncate();
|
|
|
|
} else {
|
|
|
|
SetDOMStringToNull(aReturn);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
nsresult
|
|
|
|
nsGenericElement::SetAttribute(const nsAString& aName,
|
|
|
|
const nsAString& aValue)
|
|
|
|
{
|
|
|
|
const nsAttrName* name = InternalGetExistingAttrNameFromQName(aName);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
if (!name) {
|
|
|
|
nsresult rv = nsContentUtils::CheckQName(aName, false);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2008-07-21 17:55:52 -07:00
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aName);
|
|
|
|
NS_ENSURE_TRUE(nameAtom, NS_ERROR_OUT_OF_MEMORY);
|
2008-07-21 17:55:52 -07:00
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
return SetAttr(kNameSpaceID_None, nameAtom, aValue, true);
|
|
|
|
}
|
2008-07-21 17:55:52 -07:00
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
return SetAttr(name->NamespaceID(), name->LocalName(), name->GetPrefix(),
|
|
|
|
aValue, true);
|
2008-07-21 17:55:52 -07:00
|
|
|
}
|
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
nsresult
|
|
|
|
nsGenericElement::RemoveAttribute(const nsAString& aName)
|
2008-07-21 17:55:52 -07:00
|
|
|
{
|
2012-07-31 08:36:21 -07:00
|
|
|
const nsAttrName* name = InternalGetExistingAttrNameFromQName(aName);
|
2008-07-21 17:55:52 -07:00
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
if (!name) {
|
|
|
|
// If there is no canonical nsAttrName for this attribute name, then the
|
|
|
|
// attribute does not exist and we can't get its namespace ID and
|
|
|
|
// local name below, so we return early.
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2011-08-24 12:49:25 -07:00
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
// Hold a strong reference here so that the atom or nodeinfo doesn't go
|
|
|
|
// away during UnsetAttr. If it did UnsetAttr would be left with a
|
|
|
|
// dangling pointer as argument without knowing it.
|
|
|
|
nsAttrName tmp(*name);
|
2011-08-24 12:49:25 -07:00
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
return UnsetAttr(name->NamespaceID(), name->LocalName(), true);
|
|
|
|
}
|
2011-08-24 12:49:25 -07:00
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
nsresult
|
|
|
|
nsGenericElement::GetAttributeNode(const nsAString& aName,
|
|
|
|
nsIDOMAttr** aReturn)
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(aReturn);
|
|
|
|
*aReturn = nullptr;
|
2011-08-24 12:49:25 -07:00
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
nsIDocument* document = OwnerDoc();
|
|
|
|
if (document) {
|
|
|
|
document->WarnOnceAbout(nsIDocument::eGetAttributeNode);
|
|
|
|
}
|
2011-08-24 12:49:25 -07:00
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
nsCOMPtr<nsIDOMNamedNodeMap> map;
|
|
|
|
nsresult rv = GetAttributes(getter_AddRefs(map));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2011-08-24 12:49:25 -07:00
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
nsCOMPtr<nsIDOMNode> node;
|
|
|
|
rv = map->GetNamedItem(aName, getter_AddRefs(node));
|
2011-08-24 12:49:25 -07:00
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
if (NS_SUCCEEDED(rv) && node) {
|
|
|
|
rv = CallQueryInterface(node, aReturn);
|
|
|
|
}
|
2011-08-24 12:49:25 -07:00
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
return rv;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
nsresult
|
|
|
|
nsGenericElement::SetAttributeNode(nsIDOMAttr* aAttribute,
|
|
|
|
nsIDOMAttr** aReturn)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2012-07-31 08:36:21 -07:00
|
|
|
NS_ENSURE_ARG_POINTER(aReturn);
|
|
|
|
NS_ENSURE_ARG_POINTER(aAttribute);
|
2009-08-12 01:55:14 -07:00
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
*aReturn = nullptr;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
OwnerDoc()->WarnOnceAbout(nsIDocument::eSetAttributeNode);
|
2011-08-28 07:07:24 -07:00
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
nsCOMPtr<nsIDOMNamedNodeMap> map;
|
|
|
|
nsresult rv = GetAttributes(getter_AddRefs(map));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2011-08-28 07:07:24 -07:00
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
nsCOMPtr<nsIDOMNode> returnNode;
|
|
|
|
rv = map->SetNamedItem(aAttribute, getter_AddRefs(returnNode));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2011-08-28 07:07:24 -07:00
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
if (returnNode) {
|
|
|
|
rv = CallQueryInterface(returnNode, aReturn);
|
2011-08-28 07:07:24 -07:00
|
|
|
}
|
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
return rv;
|
2011-08-28 07:07:24 -07:00
|
|
|
}
|
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
nsresult
|
|
|
|
nsGenericElement::RemoveAttributeNode(nsIDOMAttr* aAttribute,
|
|
|
|
nsIDOMAttr** aReturn)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(aReturn);
|
|
|
|
NS_ENSURE_ARG_POINTER(aAttribute);
|
|
|
|
|
2012-07-30 07:20:58 -07:00
|
|
|
*aReturn = nullptr;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2011-10-18 04:19:44 -07:00
|
|
|
OwnerDoc()->WarnOnceAbout(nsIDocument::eRemoveAttributeNode);
|
2011-06-23 01:30:48 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsCOMPtr<nsIDOMNamedNodeMap> map;
|
|
|
|
nsresult rv = GetAttributes(getter_AddRefs(map));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
nsAutoString name;
|
|
|
|
|
|
|
|
rv = aAttribute->GetName(name);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
nsCOMPtr<nsIDOMNode> node;
|
|
|
|
rv = map->RemoveNamedItem(name, getter_AddRefs(node));
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv) && node) {
|
|
|
|
rv = CallQueryInterface(node, aReturn);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsGenericElement::GetElementsByTagName(const nsAString& aTagname,
|
|
|
|
nsIDOMNodeList** aReturn)
|
|
|
|
{
|
2010-08-31 19:47:00 -07:00
|
|
|
nsContentList *list = NS_GetContentList(this, kNameSpaceID_Unknown,
|
2010-11-23 11:10:56 -08:00
|
|
|
aTagname).get();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// transfer ref to aReturn
|
|
|
|
*aReturn = list;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsGenericElement::GetAttributeNS(const nsAString& aNamespaceURI,
|
|
|
|
const nsAString& aLocalName,
|
|
|
|
nsAString& aReturn)
|
|
|
|
{
|
2012-08-22 08:56:38 -07:00
|
|
|
int32_t nsid =
|
2007-03-22 10:30:00 -07:00
|
|
|
nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI);
|
|
|
|
|
|
|
|
if (nsid == kNameSpaceID_Unknown) {
|
2012-03-11 00:48:16 -08:00
|
|
|
// Unknown namespace means no attribute.
|
|
|
|
SetDOMStringToNull(aReturn);
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIAtom> name = do_GetAtom(aLocalName);
|
2012-03-11 00:48:16 -08:00
|
|
|
bool hasAttr = GetAttr(nsid, name, aReturn);
|
|
|
|
if (!hasAttr) {
|
|
|
|
SetDOMStringToNull(aReturn);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsGenericElement::SetAttributeNS(const nsAString& aNamespaceURI,
|
|
|
|
const nsAString& aQualifiedName,
|
|
|
|
const nsAString& aValue)
|
|
|
|
{
|
2012-03-28 22:43:09 -07:00
|
|
|
nsCOMPtr<nsINodeInfo> ni;
|
2007-03-22 10:30:00 -07:00
|
|
|
nsresult rv =
|
|
|
|
nsContentUtils::GetNodeInfoFromQName(aNamespaceURI, aQualifiedName,
|
|
|
|
mNodeInfo->NodeInfoManager(),
|
2011-06-14 00:56:49 -07:00
|
|
|
nsIDOMNode::ATTRIBUTE_NODE,
|
2007-03-22 10:30:00 -07:00
|
|
|
getter_AddRefs(ni));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
return SetAttr(ni->NamespaceID(), ni->NameAtom(), ni->GetPrefixAtom(),
|
2011-10-17 07:59:28 -07:00
|
|
|
aValue, true);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsGenericElement::RemoveAttributeNS(const nsAString& aNamespaceURI,
|
|
|
|
const nsAString& aLocalName)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIAtom> name = do_GetAtom(aLocalName);
|
2012-08-22 08:56:38 -07:00
|
|
|
int32_t nsid =
|
2007-03-22 10:30:00 -07:00
|
|
|
nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI);
|
|
|
|
|
|
|
|
if (nsid == kNameSpaceID_Unknown) {
|
2012-03-04 15:38:03 -08:00
|
|
|
// If the namespace ID is unknown, it means there can't possibly be an
|
|
|
|
// existing attribute. We would need a known namespace ID to pass into
|
|
|
|
// UnsetAttr, so we return early if we don't have one.
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-10-17 07:59:28 -07:00
|
|
|
UnsetAttr(nsid, name, true);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsGenericElement::GetAttributeNodeNS(const nsAString& aNamespaceURI,
|
|
|
|
const nsAString& aLocalName,
|
|
|
|
nsIDOMAttr** aReturn)
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(aReturn);
|
2012-07-30 07:20:58 -07:00
|
|
|
*aReturn = nullptr;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2011-10-18 04:19:44 -07:00
|
|
|
OwnerDoc()->WarnOnceAbout(nsIDocument::eGetAttributeNodeNS);
|
2011-06-23 01:30:48 -07:00
|
|
|
|
2012-02-27 15:57:28 -08:00
|
|
|
return GetAttributeNodeNSInternal(aNamespaceURI, aLocalName, aReturn);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsGenericElement::GetAttributeNodeNSInternal(const nsAString& aNamespaceURI,
|
|
|
|
const nsAString& aLocalName,
|
|
|
|
nsIDOMAttr** aReturn)
|
|
|
|
{
|
2007-03-22 10:30:00 -07:00
|
|
|
nsCOMPtr<nsIDOMNamedNodeMap> map;
|
|
|
|
nsresult rv = GetAttributes(getter_AddRefs(map));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMNode> node;
|
|
|
|
rv = map->GetNamedItemNS(aNamespaceURI, aLocalName, getter_AddRefs(node));
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv) && node) {
|
|
|
|
rv = CallQueryInterface(node, aReturn);
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsGenericElement::SetAttributeNodeNS(nsIDOMAttr* aNewAttr,
|
|
|
|
nsIDOMAttr** aReturn)
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(aReturn);
|
|
|
|
NS_ENSURE_ARG_POINTER(aNewAttr);
|
2012-07-30 07:20:58 -07:00
|
|
|
*aReturn = nullptr;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2011-10-18 04:19:44 -07:00
|
|
|
OwnerDoc()->WarnOnceAbout(nsIDocument::eSetAttributeNodeNS);
|
2011-06-23 01:30:48 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsCOMPtr<nsIDOMNamedNodeMap> map;
|
|
|
|
nsresult rv = GetAttributes(getter_AddRefs(map));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMNode> returnNode;
|
|
|
|
rv = map->SetNamedItemNS(aNewAttr, getter_AddRefs(returnNode));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
if (returnNode) {
|
|
|
|
rv = CallQueryInterface(returnNode, aReturn);
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsGenericElement::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
|
|
|
|
const nsAString& aLocalName,
|
|
|
|
nsIDOMNodeList** aReturn)
|
|
|
|
{
|
2012-08-22 08:56:38 -07:00
|
|
|
int32_t nameSpaceId = kNameSpaceID_Wildcard;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
if (!aNamespaceURI.EqualsLiteral("*")) {
|
|
|
|
nsresult rv =
|
|
|
|
nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI,
|
|
|
|
nameSpaceId);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
|
2010-11-23 11:10:56 -08:00
|
|
|
NS_ASSERTION(nameSpaceId != kNameSpaceID_Unknown, "Unexpected namespace ID!");
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2010-11-23 11:10:56 -08:00
|
|
|
nsContentList *list = NS_GetContentList(this, nameSpaceId, aLocalName).get();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// transfer ref to aReturn
|
|
|
|
*aReturn = list;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2011-09-28 23:19:26 -07:00
|
|
|
nsGenericElement::HasAttribute(const nsAString& aName, bool* aReturn)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(aReturn);
|
|
|
|
|
|
|
|
const nsAttrName* name = InternalGetExistingAttrNameFromQName(aName);
|
2012-07-30 07:20:58 -07:00
|
|
|
*aReturn = (name != nullptr);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsGenericElement::HasAttributeNS(const nsAString& aNamespaceURI,
|
|
|
|
const nsAString& aLocalName,
|
2011-09-28 23:19:26 -07:00
|
|
|
bool* aReturn)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(aReturn);
|
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
int32_t nsid =
|
2007-03-22 10:30:00 -07:00
|
|
|
nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI);
|
|
|
|
|
|
|
|
if (nsid == kNameSpaceID_Unknown) {
|
|
|
|
// Unknown namespace means no attr...
|
|
|
|
|
2011-10-17 07:59:28 -07:00
|
|
|
*aReturn = false;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIAtom> name = do_GetAtom(aLocalName);
|
|
|
|
*aReturn = HasAttr(nsid, name);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-05-21 15:26:48 -07:00
|
|
|
static nsXBLBinding*
|
|
|
|
GetFirstBindingWithContent(nsBindingManager* aBmgr, nsIContent* aBoundElem)
|
|
|
|
{
|
|
|
|
nsXBLBinding* binding = aBmgr->GetBinding(aBoundElem);
|
|
|
|
while (binding) {
|
|
|
|
if (binding->GetAnonymousContent()) {
|
|
|
|
return binding;
|
|
|
|
}
|
|
|
|
binding = binding->GetBaseBinding();
|
|
|
|
}
|
|
|
|
|
2012-07-30 07:20:58 -07:00
|
|
|
return nullptr;
|
2007-05-21 15:26:48 -07:00
|
|
|
}
|
|
|
|
|
2007-05-22 15:41:32 -07:00
|
|
|
static nsresult
|
|
|
|
BindNodesInInsertPoints(nsXBLBinding* aBinding, nsIContent* aInsertParent,
|
|
|
|
nsIDocument* aDocument)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aBinding && aInsertParent, "Missing arguments");
|
|
|
|
|
|
|
|
nsresult rv;
|
|
|
|
// These should be refcounted or otherwise protectable.
|
|
|
|
nsInsertionPointList* inserts =
|
|
|
|
aBinding->GetExistingInsertionPointsFor(aInsertParent);
|
|
|
|
if (inserts) {
|
2011-09-28 23:19:26 -07:00
|
|
|
bool allowScripts = aBinding->AllowScripts();
|
2007-07-08 17:58:15 -07:00
|
|
|
#ifdef MOZ_XUL
|
2007-05-24 17:28:20 -07:00
|
|
|
nsCOMPtr<nsIXULDocument> xulDoc = do_QueryInterface(aDocument);
|
2007-07-08 17:58:15 -07:00
|
|
|
#endif
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t i;
|
2007-05-22 15:41:32 -07:00
|
|
|
for (i = 0; i < inserts->Length(); ++i) {
|
|
|
|
nsCOMPtr<nsIContent> insertRoot =
|
|
|
|
inserts->ElementAt(i)->GetDefaultContent();
|
|
|
|
if (insertRoot) {
|
2011-09-27 00:54:58 -07:00
|
|
|
for (nsCOMPtr<nsIContent> child = insertRoot->GetFirstChild();
|
|
|
|
child;
|
|
|
|
child = child->GetNextSibling()) {
|
2007-05-22 15:41:32 -07:00
|
|
|
rv = child->BindToTree(aDocument, aInsertParent,
|
|
|
|
aBinding->GetBoundElement(), allowScripts);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2007-05-24 17:28:20 -07:00
|
|
|
|
2007-07-08 17:58:15 -07:00
|
|
|
#ifdef MOZ_XUL
|
2007-05-24 17:28:20 -07:00
|
|
|
if (xulDoc) {
|
|
|
|
xulDoc->AddSubtreeToDocument(child);
|
|
|
|
}
|
2007-07-08 17:58:15 -07:00
|
|
|
#endif
|
2007-05-22 15:41:32 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsresult
|
|
|
|
nsGenericElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
|
|
|
nsIContent* aBindingParent,
|
2011-09-28 23:19:26 -07:00
|
|
|
bool aCompileEventHandlers)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aParent || aDocument, "Must have document if no parent!");
|
|
|
|
NS_PRECONDITION(HasSameOwnerDoc(NODE_FROM(aParent, aDocument)),
|
|
|
|
"Must have the same owner document");
|
2007-05-15 18:13:47 -07:00
|
|
|
NS_PRECONDITION(!aParent || aDocument == aParent->GetCurrentDoc(),
|
2007-03-22 10:30:00 -07:00
|
|
|
"aDocument must be current doc of aParent");
|
|
|
|
NS_PRECONDITION(!GetCurrentDoc(), "Already have a document. Unbind first!");
|
|
|
|
// Note that as we recurse into the kids, they'll have a non-null parent. So
|
|
|
|
// only assert if our parent is _changing_ while we have a parent.
|
|
|
|
NS_PRECONDITION(!GetParent() || aParent == GetParent(),
|
|
|
|
"Already have a parent. Unbind first!");
|
|
|
|
NS_PRECONDITION(!GetBindingParent() ||
|
|
|
|
aBindingParent == GetBindingParent() ||
|
|
|
|
(!aBindingParent && aParent &&
|
|
|
|
aParent->GetBindingParent() == GetBindingParent()),
|
|
|
|
"Already have a binding parent. Unbind first!");
|
2007-05-21 15:26:48 -07:00
|
|
|
NS_PRECONDITION(!aParent || !aDocument ||
|
|
|
|
!aParent->HasFlag(NODE_FORCE_XBL_BINDINGS),
|
|
|
|
"Parent in document but flagged as forcing XBL");
|
2008-07-22 21:50:20 -07:00
|
|
|
NS_PRECONDITION(aBindingParent != this,
|
|
|
|
"Content must not be its own binding parent");
|
|
|
|
NS_PRECONDITION(!IsRootOfNativeAnonymousSubtree() ||
|
|
|
|
aBindingParent == aParent,
|
|
|
|
"Native anonymous content must have its parent as its "
|
2008-02-26 04:40:18 -08:00
|
|
|
"own binding parent");
|
2012-03-21 21:10:51 -07:00
|
|
|
NS_PRECONDITION(aBindingParent || !aParent ||
|
|
|
|
aBindingParent == aParent->GetBindingParent(),
|
|
|
|
"We should be passed the right binding parent");
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2007-07-08 17:58:15 -07:00
|
|
|
#ifdef MOZ_XUL
|
2007-03-22 10:30:00 -07:00
|
|
|
// First set the binding parent
|
2007-05-15 18:13:47 -07:00
|
|
|
nsXULElement* xulElem = nsXULElement::FromContent(this);
|
|
|
|
if (xulElem) {
|
|
|
|
xulElem->SetXULBindingParent(aBindingParent);
|
|
|
|
}
|
2007-07-08 17:58:15 -07:00
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
2007-05-15 18:13:47 -07:00
|
|
|
if (aBindingParent) {
|
2010-12-21 17:04:00 -08:00
|
|
|
nsDOMSlots *slots = DOMSlots();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2007-05-15 18:13:47 -07:00
|
|
|
slots->mBindingParent = aBindingParent; // Weak, so no addref happens.
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2008-07-22 21:50:20 -07:00
|
|
|
NS_ASSERTION(!aBindingParent || IsRootOfNativeAnonymousSubtree() ||
|
2008-04-11 15:44:48 -07:00
|
|
|
!HasFlag(NODE_IS_IN_ANONYMOUS_SUBTREE) ||
|
2008-12-03 02:18:57 -08:00
|
|
|
(aParent && aParent->IsInNativeAnonymousSubtree()),
|
2008-10-22 17:55:04 -07:00
|
|
|
"Trying to re-bind content from native anonymous subtree to "
|
2008-04-11 15:44:48 -07:00
|
|
|
"non-native anonymous parent!");
|
2009-02-24 10:39:09 -08:00
|
|
|
if (aParent && aParent->IsInNativeAnonymousSubtree()) {
|
2008-04-11 15:44:48 -07:00
|
|
|
SetFlags(NODE_IS_IN_ANONYMOUS_SUBTREE);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool hadForceXBL = HasFlag(NODE_FORCE_XBL_BINDINGS);
|
2007-05-21 15:26:48 -07:00
|
|
|
|
2007-05-15 18:13:47 -07:00
|
|
|
// Now set the parent and set the "Force attach xbl" flag if needed.
|
2007-03-22 10:30:00 -07:00
|
|
|
if (aParent) {
|
2011-07-26 04:11:14 -07:00
|
|
|
if (!GetParent()) {
|
|
|
|
NS_ADDREF(aParent);
|
|
|
|
}
|
2011-04-07 19:29:49 -07:00
|
|
|
mParent = aParent;
|
2007-05-15 18:13:47 -07:00
|
|
|
|
|
|
|
if (aParent->HasFlag(NODE_FORCE_XBL_BINDINGS)) {
|
|
|
|
SetFlags(NODE_FORCE_XBL_BINDINGS);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
else {
|
2011-04-07 19:29:49 -07:00
|
|
|
mParent = aDocument;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2011-04-07 19:29:49 -07:00
|
|
|
SetParentIsContent(aParent);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// XXXbz sXBL/XBL2 issue!
|
|
|
|
|
|
|
|
// Finally, set the document
|
|
|
|
if (aDocument) {
|
|
|
|
// Notify XBL- & nsIAnonymousContentCreator-generated
|
|
|
|
// anonymous content that the document is changing.
|
|
|
|
// XXXbz ordering issues here? Probably not, since ChangeDocumentFor is
|
|
|
|
// just pretty broken anyway.... Need to get it working.
|
|
|
|
// XXXbz XBL doesn't handle this (asserts), and we don't really want
|
|
|
|
// to be doing this during parsing anyway... sort this out.
|
2012-07-30 07:20:58 -07:00
|
|
|
// aDocument->BindingManager()->ChangeDocumentFor(this, nullptr,
|
2007-03-22 10:30:00 -07:00
|
|
|
// aDocument);
|
|
|
|
|
2012-03-14 13:14:02 -07:00
|
|
|
// We no longer need to track the subtree pointer (and in fact we'll assert
|
|
|
|
// if we do this any later).
|
|
|
|
ClearSubtreeRootPointer();
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// Being added to a document.
|
2011-04-07 19:29:49 -07:00
|
|
|
SetInDocument();
|
2007-05-15 18:13:47 -07:00
|
|
|
|
|
|
|
// Unset this flag since we now really are in a document.
|
2010-01-18 01:26:40 -08:00
|
|
|
UnsetFlags(NODE_FORCE_XBL_BINDINGS |
|
|
|
|
// And clear the lazy frame construction bits.
|
2010-06-18 09:23:04 -07:00
|
|
|
NODE_NEEDS_FRAME | NODE_DESCENDANTS_NEED_FRAMES |
|
|
|
|
// And the restyle bits
|
|
|
|
ELEMENT_ALL_RESTYLE_FLAGS);
|
2012-03-14 13:14:02 -07:00
|
|
|
} else {
|
|
|
|
// If we're not in the doc, update our subtree pointer.
|
|
|
|
SetSubtreeRootPointer(aParent->SubtreeRoot());
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2012-04-16 21:03:10 -07:00
|
|
|
// This has to be here, rather than in nsGenericHTMLElement::BindToTree,
|
|
|
|
// because it has to happen after updating the parent pointer, but before
|
|
|
|
// recursively binding the kids.
|
|
|
|
if (IsHTML()) {
|
|
|
|
RecomputeDirectionality(this, false);
|
|
|
|
}
|
|
|
|
|
2007-05-21 15:26:48 -07:00
|
|
|
// If NODE_FORCE_XBL_BINDINGS was set we might have anonymous children
|
|
|
|
// that also need to be told that they are moving.
|
2007-03-22 10:30:00 -07:00
|
|
|
nsresult rv;
|
2007-05-21 15:26:48 -07:00
|
|
|
if (hadForceXBL) {
|
2011-10-18 04:19:44 -07:00
|
|
|
nsBindingManager* bmgr = OwnerDoc()->BindingManager();
|
|
|
|
|
|
|
|
// First check if we have a binding...
|
|
|
|
nsXBLBinding* contBinding =
|
|
|
|
GetFirstBindingWithContent(bmgr, this);
|
|
|
|
if (contBinding) {
|
|
|
|
nsCOMPtr<nsIContent> anonRoot = contBinding->GetAnonymousContent();
|
|
|
|
bool allowScripts = contBinding->AllowScripts();
|
|
|
|
for (nsCOMPtr<nsIContent> child = anonRoot->GetFirstChild();
|
|
|
|
child;
|
|
|
|
child = child->GetNextSibling()) {
|
|
|
|
rv = child->BindToTree(aDocument, this, this, allowScripts);
|
2007-05-22 15:41:32 -07:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2007-05-21 15:26:48 -07:00
|
|
|
}
|
|
|
|
|
2011-10-18 04:19:44 -07:00
|
|
|
// ...then check if we have content in insertion points that are
|
|
|
|
// direct children of the <content>
|
|
|
|
rv = BindNodesInInsertPoints(contBinding, this, aDocument);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ...and finally check if we're in a binding where we have content in
|
|
|
|
// insertion points.
|
|
|
|
if (aBindingParent) {
|
|
|
|
nsXBLBinding* binding = bmgr->GetBinding(aBindingParent);
|
|
|
|
if (binding) {
|
|
|
|
rv = BindNodesInInsertPoints(binding, this, aDocument);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2007-05-21 15:26:48 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-17 07:59:28 -07:00
|
|
|
UpdateEditableState(false);
|
2007-06-27 19:48:16 -07:00
|
|
|
|
2007-05-21 15:26:48 -07:00
|
|
|
// Now recurse into our kids
|
2010-07-27 11:39:13 -07:00
|
|
|
for (nsIContent* child = GetFirstChild(); child;
|
|
|
|
child = child->GetNextSibling()) {
|
2007-03-22 10:30:00 -07:00
|
|
|
rv = child->BindToTree(aDocument, this, aBindingParent,
|
|
|
|
aCompileEventHandlers);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsNodeUtils::ParentChainChanged(this);
|
|
|
|
|
2012-03-21 21:10:51 -07:00
|
|
|
if (aDocument && HasID() && !aBindingParent) {
|
|
|
|
aDocument->AddToIdTable(this, DoGetID());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (MayHaveStyle() && !IsXUL()) {
|
|
|
|
// XXXbz if we already have a style attr parsed, this won't do
|
|
|
|
// anything... need to fix that.
|
|
|
|
// If MayHaveStyle() is true, we must be an nsStyledElement
|
|
|
|
static_cast<nsStyledElement*>(this)->ReparseStyleAttribute(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aDocument) {
|
|
|
|
// If we're in a document now, let our mapped attrs know what their new
|
|
|
|
// sheet is. This is safe to run for non-mapped-attribute elements too;
|
|
|
|
// it'll just do a small bit of unnecessary work. But most elements in
|
|
|
|
// practice are mapped-attribute elements.
|
|
|
|
nsHTMLStyleSheet* sheet = aDocument->GetAttributeStyleSheet();
|
|
|
|
if (sheet) {
|
|
|
|
mAttrsAndChildren.SetMappedAttrStyleSheet(sheet);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// XXXbz script execution during binding can trigger some of these
|
|
|
|
// postcondition asserts.... But we do want that, since things will
|
|
|
|
// generally be quite broken when that happens.
|
|
|
|
NS_POSTCONDITION(aDocument == GetCurrentDoc(), "Bound to wrong document");
|
|
|
|
NS_POSTCONDITION(aParent == GetParent(), "Bound to wrong parent");
|
|
|
|
NS_POSTCONDITION(aBindingParent == GetBindingParent(),
|
|
|
|
"Bound to wrong binding parent");
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-06-11 15:22:26 -07:00
|
|
|
class RemoveFromBindingManagerRunnable : public nsRunnable {
|
|
|
|
public:
|
|
|
|
RemoveFromBindingManagerRunnable(nsBindingManager* aManager,
|
|
|
|
Element* aElement,
|
|
|
|
nsIDocument* aDoc,
|
|
|
|
nsIContent* aBindingParent):
|
|
|
|
mManager(aManager), mElement(aElement), mDoc(aDoc),
|
|
|
|
mBindingParent(aBindingParent)
|
|
|
|
{}
|
|
|
|
|
|
|
|
NS_IMETHOD Run()
|
|
|
|
{
|
|
|
|
mManager->RemovedFromDocumentInternal(mElement, mDoc, mBindingParent);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
nsRefPtr<nsBindingManager> mManager;
|
|
|
|
nsRefPtr<Element> mElement;
|
|
|
|
nsCOMPtr<nsIDocument> mDoc;
|
|
|
|
nsCOMPtr<nsIContent> mBindingParent;
|
|
|
|
};
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
void
|
2011-09-28 23:19:26 -07:00
|
|
|
nsGenericElement::UnbindFromTree(bool aDeep, bool aNullParent)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aDeep || (!GetCurrentDoc() && !GetBindingParent()),
|
|
|
|
"Shallow unbind won't clear document and binding parent on "
|
|
|
|
"kids!");
|
2012-03-21 21:10:51 -07:00
|
|
|
|
|
|
|
RemoveFromIdTable();
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// Make sure to unbind this node before doing the kids
|
2007-09-20 19:05:43 -07:00
|
|
|
nsIDocument *document =
|
2011-10-18 03:53:36 -07:00
|
|
|
HasFlag(NODE_FORCE_XBL_BINDINGS) ? OwnerDoc() : GetCurrentDoc();
|
2009-02-05 01:42:55 -08:00
|
|
|
|
2011-04-07 19:29:49 -07:00
|
|
|
if (aNullParent) {
|
2011-12-06 13:59:39 -08:00
|
|
|
if (IsFullScreenAncestor()) {
|
2011-10-31 22:11:09 -07:00
|
|
|
// The element being removed is an ancestor of the full-screen element,
|
|
|
|
// exit full-screen state.
|
2011-12-15 06:47:03 -08:00
|
|
|
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
|
|
|
"DOM", OwnerDoc(),
|
|
|
|
nsContentUtils::eDOM_PROPERTIES,
|
|
|
|
"RemovedFullScreenElement");
|
2011-12-06 13:59:39 -08:00
|
|
|
// Fully exit full-screen.
|
|
|
|
nsIDocument::ExitFullScreen(false);
|
2011-10-31 22:11:09 -07:00
|
|
|
}
|
2012-04-11 14:55:21 -07:00
|
|
|
if (HasPointerLock()) {
|
|
|
|
nsIDocument::UnlockPointer();
|
|
|
|
}
|
2011-07-26 04:11:14 -07:00
|
|
|
if (GetParent()) {
|
|
|
|
NS_RELEASE(mParent);
|
|
|
|
} else {
|
2012-07-30 07:20:58 -07:00
|
|
|
mParent = nullptr;
|
2011-07-26 04:11:14 -07:00
|
|
|
}
|
2011-04-07 19:29:49 -07:00
|
|
|
SetParentIsContent(false);
|
|
|
|
}
|
|
|
|
ClearInDocument();
|
2009-02-05 01:42:55 -08:00
|
|
|
|
2012-03-14 13:14:02 -07:00
|
|
|
// Begin keeping track of our subtree root.
|
|
|
|
SetSubtreeRootPointer(aNullParent ? this : mParent->SubtreeRoot());
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
if (document) {
|
|
|
|
// Notify XBL- & nsIAnonymousContentCreator-generated
|
|
|
|
// anonymous content that the document is changing.
|
2012-06-11 15:22:26 -07:00
|
|
|
if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
|
|
|
|
nsContentUtils::AddScriptRunner(
|
|
|
|
new RemoveFromBindingManagerRunnable(document->BindingManager(), this,
|
|
|
|
document, GetBindingParent()));
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2008-02-18 14:52:19 -08:00
|
|
|
document->ClearBoxObjectFor(this);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-10-07 20:22:42 -07:00
|
|
|
// Ensure that CSS transitions don't continue on an element at a
|
|
|
|
// different place in the tree (even if reinserted before next
|
|
|
|
// animation refresh).
|
2009-10-15 17:23:19 -07:00
|
|
|
// FIXME (Bug 522599): Need a test for this.
|
2009-10-07 20:22:42 -07:00
|
|
|
if (HasFlag(NODE_HAS_PROPERTIES)) {
|
|
|
|
DeleteProperty(nsGkAtoms::transitionsOfBeforeProperty);
|
|
|
|
DeleteProperty(nsGkAtoms::transitionsOfAfterProperty);
|
|
|
|
DeleteProperty(nsGkAtoms::transitionsProperty);
|
2011-04-11 23:18:44 -07:00
|
|
|
DeleteProperty(nsGkAtoms::animationsOfBeforeProperty);
|
|
|
|
DeleteProperty(nsGkAtoms::animationsOfAfterProperty);
|
|
|
|
DeleteProperty(nsGkAtoms::animationsProperty);
|
2009-10-07 20:22:42 -07:00
|
|
|
}
|
|
|
|
|
2007-05-15 18:13:47 -07:00
|
|
|
// Unset this since that's what the old code effectively did.
|
|
|
|
UnsetFlags(NODE_FORCE_XBL_BINDINGS);
|
2012-02-20 04:54:45 -08:00
|
|
|
|
2007-07-08 17:58:15 -07:00
|
|
|
#ifdef MOZ_XUL
|
2007-05-15 18:13:47 -07:00
|
|
|
nsXULElement* xulElem = nsXULElement::FromContent(this);
|
|
|
|
if (xulElem) {
|
2012-07-30 07:20:58 -07:00
|
|
|
xulElem->SetXULBindingParent(nullptr);
|
2007-05-15 18:13:47 -07:00
|
|
|
}
|
2007-07-08 17:58:15 -07:00
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
2007-05-15 18:13:47 -07:00
|
|
|
nsDOMSlots *slots = GetExistingDOMSlots();
|
|
|
|
if (slots) {
|
2012-07-30 07:20:58 -07:00
|
|
|
slots->mBindingParent = nullptr;
|
2007-05-15 18:13:47 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2012-04-16 21:03:10 -07:00
|
|
|
// This has to be here, rather than in nsGenericHTMLElement::UnbindFromTree,
|
|
|
|
// because it has to happen after unsetting the parent pointer, but before
|
|
|
|
// recursively unbinding the kids.
|
|
|
|
if (IsHTML()) {
|
|
|
|
RecomputeDirectionality(this, false);
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
if (aDeep) {
|
2007-05-15 18:13:47 -07:00
|
|
|
// Do the kids. Don't call GetChildCount() here since that'll force
|
|
|
|
// XUL to generate template children, which there is no need for since
|
|
|
|
// all we're going to do is unbind them anyway.
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t i, n = mAttrsAndChildren.ChildCount();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
for (i = 0; i < n; ++i) {
|
2011-10-17 07:59:28 -07:00
|
|
|
// Note that we pass false for aNullParent here, since we don't want
|
2007-03-22 10:30:00 -07:00
|
|
|
// the kids to forget us. We _do_ want them to forget their binding
|
|
|
|
// parent, though, since this only walks non-anonymous kids.
|
2011-10-17 07:59:28 -07:00
|
|
|
mAttrsAndChildren.ChildAt(i)->UnbindFromTree(true, false);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nsNodeUtils::ParentChainChanged(this);
|
|
|
|
}
|
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
nsICSSDeclaration*
|
|
|
|
nsGenericElement::GetSMILOverrideStyle()
|
2010-02-11 09:34:01 -08:00
|
|
|
{
|
2012-07-31 08:36:21 -07:00
|
|
|
nsGenericElement::nsDOMSlots *slots = DOMSlots();
|
2010-02-11 09:34:01 -08:00
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
if (!slots->mSMILOverrideStyle) {
|
|
|
|
slots->mSMILOverrideStyle = new nsDOMCSSAttributeDeclaration(this, true);
|
2010-02-11 09:34:01 -08:00
|
|
|
}
|
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
return slots->mSMILOverrideStyle;
|
2010-02-11 09:34:01 -08:00
|
|
|
}
|
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
css::StyleRule*
|
|
|
|
nsGenericElement::GetSMILOverrideStyleRule()
|
2008-03-12 03:26:12 -07:00
|
|
|
{
|
2012-07-31 08:36:21 -07:00
|
|
|
nsGenericElement::nsDOMSlots *slots = GetExistingDOMSlots();
|
|
|
|
return slots ? slots->mSMILOverrideStyleRule.get() : nullptr;
|
2008-03-12 03:26:12 -07:00
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsresult
|
2012-07-31 08:36:21 -07:00
|
|
|
nsGenericElement::SetSMILOverrideStyleRule(css::StyleRule* aStyleRule,
|
|
|
|
bool aNotify)
|
2009-09-02 17:28:37 -07:00
|
|
|
{
|
2010-12-21 17:04:00 -08:00
|
|
|
nsGenericElement::nsDOMSlots *slots = DOMSlots();
|
2009-09-02 17:28:37 -07:00
|
|
|
|
|
|
|
slots->mSMILOverrideStyleRule = aStyleRule;
|
|
|
|
|
|
|
|
if (aNotify) {
|
|
|
|
nsIDocument* doc = GetCurrentDoc();
|
2010-03-11 22:03:49 -08:00
|
|
|
// Only need to request a restyle if we're in a document. (We might not
|
2009-10-20 09:54:47 -07:00
|
|
|
// be in a document, if we're clearing animation effects on a target node
|
|
|
|
// that's been detached since the previous animation sample.)
|
|
|
|
if (doc) {
|
2010-06-25 06:59:57 -07:00
|
|
|
nsCOMPtr<nsIPresShell> shell = doc->GetShell();
|
2010-01-07 02:36:11 -08:00
|
|
|
if (shell) {
|
2010-06-30 18:54:29 -07:00
|
|
|
shell->RestyleForAnimation(this, eRestyle_Self);
|
2009-10-20 09:54:47 -07:00
|
|
|
}
|
2009-09-02 17:28:37 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-06-07 11:41:23 -07:00
|
|
|
bool
|
|
|
|
nsGenericElement::IsLabelable() const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-03-10 18:48:57 -08:00
|
|
|
css::StyleRule*
|
2007-03-22 10:30:00 -07:00
|
|
|
nsGenericElement::GetInlineStyleRule()
|
|
|
|
{
|
2012-07-30 07:20:58 -07:00
|
|
|
return nullptr;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2012-04-14 06:09:19 -07:00
|
|
|
nsresult
|
2011-03-10 18:48:57 -08:00
|
|
|
nsGenericElement::SetInlineStyleRule(css::StyleRule* aStyleRule,
|
2012-04-05 10:14:54 -07:00
|
|
|
const nsAString* aSerialized,
|
2011-09-28 23:19:26 -07:00
|
|
|
bool aNotify)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
NS_NOTYETIMPLEMENTED("nsGenericElement::SetInlineStyleRule");
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
NS_IMETHODIMP_(bool)
|
2007-03-22 10:30:00 -07:00
|
|
|
nsGenericElement::IsAttributeMapped(const nsIAtom* aAttribute) const
|
|
|
|
{
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
nsChangeHint
|
|
|
|
nsGenericElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
|
2012-08-22 08:56:38 -07:00
|
|
|
int32_t aModType) const
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
return nsChangeHint(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIAtom *
|
|
|
|
nsGenericElement::GetClassAttributeName() const
|
|
|
|
{
|
2012-07-30 07:20:58 -07:00
|
|
|
return nullptr;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
bool
|
|
|
|
nsGenericElement::FindAttributeDependence(const nsIAtom* aAttribute,
|
|
|
|
const MappedAttributeEntry* const aMaps[],
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t aMapCount)
|
2012-07-31 08:36:21 -07:00
|
|
|
{
|
2012-08-22 08:56:38 -07:00
|
|
|
for (uint32_t mapindex = 0; mapindex < aMapCount; ++mapindex) {
|
2012-07-31 08:36:21 -07:00
|
|
|
for (const MappedAttributeEntry* map = aMaps[mapindex];
|
|
|
|
map->attribute; ++map) {
|
|
|
|
if (aAttribute == *map->attribute) {
|
|
|
|
return true;
|
2012-06-27 15:09:15 -07:00
|
|
|
}
|
|
|
|
}
|
2012-02-10 17:21:26 -08:00
|
|
|
}
|
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
return false;
|
|
|
|
}
|
2012-01-30 12:08:13 -08:00
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
already_AddRefed<nsINodeInfo>
|
|
|
|
nsGenericElement::GetExistingAttrNameFromQName(const nsAString& aStr) const
|
|
|
|
{
|
|
|
|
const nsAttrName* name = InternalGetExistingAttrNameFromQName(aStr);
|
|
|
|
if (!name) {
|
|
|
|
return nullptr;
|
2012-01-30 12:08:13 -08:00
|
|
|
}
|
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
nsINodeInfo* nodeInfo;
|
|
|
|
if (name->IsAtom()) {
|
|
|
|
nodeInfo = mNodeInfo->NodeInfoManager()->
|
|
|
|
GetNodeInfo(name->Atom(), nullptr, kNameSpaceID_None,
|
|
|
|
nsIDOMNode::ATTRIBUTE_NODE).get();
|
2012-01-30 12:08:13 -08:00
|
|
|
}
|
2012-07-31 08:36:21 -07:00
|
|
|
else {
|
|
|
|
NS_ADDREF(nodeInfo = name->NodeInfo());
|
|
|
|
}
|
|
|
|
|
|
|
|
return nodeInfo;
|
2012-01-30 12:08:13 -08:00
|
|
|
}
|
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
// static
|
2012-01-30 12:08:13 -08:00
|
|
|
bool
|
2012-07-31 08:36:21 -07:00
|
|
|
nsGenericElement::ShouldBlur(nsIContent *aContent)
|
2012-01-30 12:08:13 -08:00
|
|
|
{
|
2012-07-31 08:36:21 -07:00
|
|
|
// Determine if the current element is focused, if it is not focused
|
|
|
|
// then we should not try to blur
|
|
|
|
nsIDocument *document = aContent->GetDocument();
|
|
|
|
if (!document)
|
2012-01-30 12:08:13 -08:00
|
|
|
return false;
|
2012-07-31 08:36:21 -07:00
|
|
|
|
|
|
|
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(document->GetWindow());
|
|
|
|
if (!window)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
nsCOMPtr<nsPIDOMWindow> focusedFrame;
|
|
|
|
nsIContent* contentToBlur =
|
|
|
|
nsFocusManager::GetFocusedDescendant(window, false, getter_AddRefs(focusedFrame));
|
|
|
|
if (contentToBlur == aContent)
|
2012-01-30 12:08:13 -08:00
|
|
|
return true;
|
2012-07-31 08:36:21 -07:00
|
|
|
|
|
|
|
// if focus on this element would get redirected, then check the redirected
|
|
|
|
// content as well when blurring.
|
|
|
|
return (contentToBlur && nsFocusManager::GetRedirectedFocus(aContent) == contentToBlur);
|
2012-01-30 12:08:13 -08:00
|
|
|
}
|
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
bool
|
2012-08-22 08:56:38 -07:00
|
|
|
nsGenericElement::IsNodeOfType(uint32_t aFlags) const
|
2012-01-30 12:08:13 -08:00
|
|
|
{
|
2012-07-31 08:36:21 -07:00
|
|
|
return !(aFlags & ~eCONTENT);
|
2012-01-30 12:08:13 -08:00
|
|
|
}
|
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
/* static */
|
|
|
|
nsresult
|
|
|
|
nsGenericElement::DispatchEvent(nsPresContext* aPresContext,
|
|
|
|
nsEvent* aEvent,
|
|
|
|
nsIContent* aTarget,
|
|
|
|
bool aFullDispatch,
|
|
|
|
nsEventStatus* aStatus)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aTarget, "Must have target");
|
|
|
|
NS_PRECONDITION(aEvent, "Must have source event");
|
|
|
|
NS_PRECONDITION(aStatus, "Null out param?");
|
2012-02-11 03:03:54 -08:00
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
if (!aPresContext) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2012-02-11 03:03:54 -08:00
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
nsCOMPtr<nsIPresShell> shell = aPresContext->GetPresShell();
|
|
|
|
if (!shell) {
|
|
|
|
return NS_OK;
|
2009-02-27 06:48:26 -08:00
|
|
|
}
|
2012-07-31 08:36:21 -07:00
|
|
|
|
|
|
|
if (aFullDispatch) {
|
|
|
|
return shell->HandleEventWithTarget(aEvent, nullptr, aTarget, aStatus);
|
2009-02-27 06:48:26 -08:00
|
|
|
}
|
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
return shell->HandleDOMEventWithTarget(aTarget, aEvent, aStatus);
|
|
|
|
}
|
2009-05-12 13:20:42 -07:00
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
/* static */
|
|
|
|
nsresult
|
|
|
|
nsGenericElement::DispatchClickEvent(nsPresContext* aPresContext,
|
|
|
|
nsInputEvent* aSourceEvent,
|
|
|
|
nsIContent* aTarget,
|
|
|
|
bool aFullDispatch,
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t aFlags,
|
2012-07-31 08:36:21 -07:00
|
|
|
nsEventStatus* aStatus)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aTarget, "Must have target");
|
|
|
|
NS_PRECONDITION(aSourceEvent, "Must have source event");
|
|
|
|
NS_PRECONDITION(aStatus, "Null out param?");
|
2007-05-10 13:21:12 -07:00
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
nsMouseEvent event(NS_IS_TRUSTED_EVENT(aSourceEvent), NS_MOUSE_CLICK,
|
|
|
|
aSourceEvent->widget, nsMouseEvent::eReal);
|
|
|
|
event.refPoint = aSourceEvent->refPoint;
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t clickCount = 1;
|
2012-07-31 08:36:21 -07:00
|
|
|
float pressure = 0;
|
2012-08-22 08:56:38 -07:00
|
|
|
uint16_t inputSource = 0;
|
2012-07-31 08:36:21 -07:00
|
|
|
if (aSourceEvent->eventStructType == NS_MOUSE_EVENT) {
|
|
|
|
clickCount = static_cast<nsMouseEvent*>(aSourceEvent)->clickCount;
|
|
|
|
pressure = static_cast<nsMouseEvent*>(aSourceEvent)->pressure;
|
|
|
|
inputSource = static_cast<nsMouseEvent*>(aSourceEvent)->inputSource;
|
|
|
|
} else if (aSourceEvent->eventStructType == NS_KEY_EVENT) {
|
|
|
|
inputSource = nsIDOMMouseEvent::MOZ_SOURCE_KEYBOARD;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2012-07-31 08:36:21 -07:00
|
|
|
event.pressure = pressure;
|
|
|
|
event.clickCount = clickCount;
|
|
|
|
event.inputSource = inputSource;
|
|
|
|
event.modifiers = aSourceEvent->modifiers;
|
|
|
|
event.flags |= aFlags; // Be careful not to overwrite existing flags!
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
return DispatchEvent(aPresContext, &event, aTarget, aFullDispatch, aStatus);
|
|
|
|
}
|
2008-03-28 07:09:00 -07:00
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
nsIFrame*
|
|
|
|
nsGenericElement::GetPrimaryFrame(mozFlushType aType)
|
|
|
|
{
|
|
|
|
nsIDocument* doc = GetCurrentDoc();
|
|
|
|
if (!doc) {
|
|
|
|
return nullptr;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
// Cause a flush, so we get up-to-date frame
|
|
|
|
// information
|
|
|
|
doc->FlushPendingNotifications(aType);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-07-31 08:36:21 -07:00
|
|
|
return GetPrimaryFrame();
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
nsresult
|
|
|
|
nsGenericElement::LeaveLink(nsPresContext* aPresContext)
|
|
|
|
{
|
|
|
|
nsILinkHandler *handler = aPresContext->GetLinkHandler();
|
|
|
|
if (!handler) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
return handler->OnLeaveLink();
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2012-08-30 09:25:10 -07:00
|
|
|
nsGenericElement::SetEventHandler(nsIAtom* aEventName,
|
|
|
|
const nsAString& aValue,
|
|
|
|
bool aDefer)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2011-10-18 03:53:36 -07:00
|
|
|
nsIDocument *ownerDoc = OwnerDoc();
|
2011-10-18 04:19:44 -07:00
|
|
|
if (ownerDoc->IsLoadedAsData()) {
|
2007-07-26 19:49:18 -07:00
|
|
|
// Make this a no-op rather than throwing an error to avoid
|
|
|
|
// the error causing problems setting the attribute.
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_PRECONDITION(aEventName, "Must have event name!");
|
2011-09-28 23:19:26 -07:00
|
|
|
bool defer = true;
|
2011-09-28 08:54:50 -07:00
|
|
|
nsEventListenerManager* manager = GetEventListenerManagerForAttr(aEventName,
|
|
|
|
&defer);
|
2009-09-16 02:09:12 -07:00
|
|
|
if (!manager) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-23 04:23:52 -07:00
|
|
|
defer = defer && aDefer; // only defer if everyone agrees...
|
2012-08-30 09:25:10 -07:00
|
|
|
manager->SetEventHandler(aEventName, aValue,
|
|
|
|
nsIProgrammingLanguage::JAVASCRIPT,
|
|
|
|
defer, !nsContentUtils::IsChromeDoc(ownerDoc));
|
2011-06-23 19:18:02 -07:00
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
|
|
|
const nsAttrName*
|
|
|
|
nsGenericElement::InternalGetExistingAttrNameFromQName(const nsAString& aStr) const
|
|
|
|
{
|
2010-03-08 07:45:00 -08:00
|
|
|
return mAttrsAndChildren.GetExistingAttrNameFromQName(aStr);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool
|
2012-08-22 08:56:38 -07:00
|
|
|
nsGenericElement::MaybeCheckSameAttrVal(int32_t aNamespaceID,
|
2012-02-13 18:00:56 -08:00
|
|
|
nsIAtom* aName,
|
|
|
|
nsIAtom* aPrefix,
|
|
|
|
const nsAttrValueOrString& aValue,
|
|
|
|
bool aNotify,
|
|
|
|
nsAttrValue& aOldValue,
|
2012-08-22 08:56:38 -07:00
|
|
|
uint8_t* aModType,
|
2012-02-13 18:00:56 -08:00
|
|
|
bool* aHasListeners)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2011-09-28 23:19:26 -07:00
|
|
|
bool modification = false;
|
2011-02-01 11:41:50 -08:00
|
|
|
*aHasListeners = aNotify &&
|
2007-03-22 10:30:00 -07:00
|
|
|
nsContentUtils::HasMutationListeners(this,
|
2007-07-04 13:39:10 -07:00
|
|
|
NS_EVENT_BITS_MUTATION_ATTRMODIFIED,
|
|
|
|
this);
|
2011-02-01 11:41:50 -08:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// If we have no listeners and aNotify is false, we are almost certainly
|
|
|
|
// coming from the content sink and will almost certainly have no previous
|
|
|
|
// value. Even if we do, setting the value is cheap when we have no
|
|
|
|
// listeners and don't plan to notify. The check for aNotify here is an
|
2011-02-01 11:41:50 -08:00
|
|
|
// optimization, the check for *aHasListeners is a correctness issue.
|
|
|
|
if (*aHasListeners || aNotify) {
|
2007-03-22 10:30:00 -07:00
|
|
|
nsAttrInfo info(GetAttrInfo(aNamespaceID, aName));
|
|
|
|
if (info.mValue) {
|
|
|
|
// Check whether the old value is the same as the new one. Note that we
|
|
|
|
// only need to actually _get_ the old value if we have listeners.
|
2011-02-01 11:41:50 -08:00
|
|
|
if (*aHasListeners) {
|
2012-02-13 18:00:56 -08:00
|
|
|
// Need to store the old value.
|
|
|
|
//
|
|
|
|
// If the current attribute value contains a pointer to some other data
|
|
|
|
// structure that gets updated in the process of setting the attribute
|
|
|
|
// we'll no longer have the old value of the attribute. Therefore, we
|
|
|
|
// should serialize the attribute value now to keep a snapshot.
|
|
|
|
//
|
|
|
|
// We have to serialize the value anyway in order to create the
|
|
|
|
// mutation event so there's no cost in doing it now.
|
|
|
|
aOldValue.SetToSerialized(*info.mValue);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2012-02-13 18:00:56 -08:00
|
|
|
bool valueMatches = aValue.EqualsAsStrings(*info.mValue);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (valueMatches && aPrefix == info.mName->GetPrefix()) {
|
2012-08-15 03:06:01 -07:00
|
|
|
return true;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2011-10-17 07:59:28 -07:00
|
|
|
modification = true;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
2011-02-01 11:41:50 -08:00
|
|
|
*aModType = modification ?
|
2012-08-22 08:56:38 -07:00
|
|
|
static_cast<uint8_t>(nsIDOMMutationEvent::MODIFICATION) :
|
|
|
|
static_cast<uint8_t>(nsIDOMMutationEvent::ADDITION);
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2011-02-01 11:41:50 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2012-08-22 08:56:38 -07:00
|
|
|
nsGenericElement::SetAttr(int32_t aNamespaceID, nsIAtom* aName,
|
2011-02-01 11:41:50 -08:00
|
|
|
nsIAtom* aPrefix, const nsAString& aValue,
|
2011-09-28 23:19:26 -07:00
|
|
|
bool aNotify)
|
2011-02-01 11:41:50 -08:00
|
|
|
{
|
|
|
|
// Keep this in sync with SetParsedAttr below
|
|
|
|
|
|
|
|
NS_ENSURE_ARG_POINTER(aName);
|
|
|
|
NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown,
|
|
|
|
"Don't call SetAttr with unknown namespace");
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2011-02-01 11:41:50 -08:00
|
|
|
if (!mAttrsAndChildren.CanFitMoreAttrs()) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
uint8_t modType;
|
2011-09-28 23:19:26 -07:00
|
|
|
bool hasListeners;
|
2012-02-13 18:00:56 -08:00
|
|
|
nsAttrValueOrString value(aValue);
|
|
|
|
nsAttrValue oldValue;
|
2011-02-01 11:41:50 -08:00
|
|
|
|
2012-08-15 03:06:01 -07:00
|
|
|
if (OnlyNotifySameValueSet(aNamespaceID, aName, aPrefix, value, aNotify,
|
|
|
|
oldValue, &modType, &hasListeners)) {
|
2011-02-01 11:41:50 -08:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2010-02-23 20:37:47 -08:00
|
|
|
|
2012-02-13 18:00:56 -08:00
|
|
|
nsresult rv = BeforeSetAttr(aNamespaceID, aName, &value, aNotify);
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2011-02-01 11:41:50 -08:00
|
|
|
|
2010-02-23 20:37:47 -08:00
|
|
|
if (aNotify) {
|
|
|
|
nsNodeUtils::AttributeWillChange(this, aNamespaceID, aName, modType);
|
|
|
|
}
|
|
|
|
|
2011-03-01 21:33:56 -08:00
|
|
|
// Hold a script blocker while calling ParseAttribute since that can call
|
|
|
|
// out to id-observers
|
2011-05-25 10:58:23 -07:00
|
|
|
nsAutoScriptBlocker scriptBlocker;
|
2011-03-01 21:33:56 -08:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsAttrValue attrValue;
|
|
|
|
if (!ParseAttribute(aNamespaceID, aName, aValue, attrValue)) {
|
|
|
|
attrValue.SetTo(aValue);
|
|
|
|
}
|
|
|
|
|
2011-03-02 06:36:19 -08:00
|
|
|
return SetAttrAndNotify(aNamespaceID, aName, aPrefix, oldValue,
|
|
|
|
attrValue, modType, hasListeners, aNotify,
|
2012-02-13 18:00:56 -08:00
|
|
|
kCallAfterSetAttr);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2011-02-01 11:41:50 -08:00
|
|
|
|
|
|
|
nsresult
|
2012-08-22 08:56:38 -07:00
|
|
|
nsGenericElement::SetParsedAttr(int32_t aNamespaceID, nsIAtom* aName,
|
2011-02-01 11:41:50 -08:00
|
|
|
nsIAtom* aPrefix, nsAttrValue& aParsedValue,
|
2011-09-28 23:19:26 -07:00
|
|
|
bool aNotify)
|
2011-02-01 11:41:50 -08:00
|
|
|
{
|
|
|
|
// Keep this in sync with SetAttr above
|
|
|
|
|
|
|
|
NS_ENSURE_ARG_POINTER(aName);
|
|
|
|
NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown,
|
|
|
|
"Don't call SetAttr with unknown namespace");
|
|
|
|
|
|
|
|
if (!mAttrsAndChildren.CanFitMoreAttrs()) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
uint8_t modType;
|
2011-09-28 23:19:26 -07:00
|
|
|
bool hasListeners;
|
2012-02-13 18:00:56 -08:00
|
|
|
nsAttrValueOrString value(aParsedValue);
|
|
|
|
nsAttrValue oldValue;
|
2011-02-01 11:41:50 -08:00
|
|
|
|
2012-08-15 03:06:01 -07:00
|
|
|
if (OnlyNotifySameValueSet(aNamespaceID, aName, aPrefix, value, aNotify,
|
|
|
|
oldValue, &modType, &hasListeners)) {
|
2011-02-01 11:41:50 -08:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-02-13 18:00:56 -08:00
|
|
|
nsresult rv = BeforeSetAttr(aNamespaceID, aName, &value, aNotify);
|
2011-02-01 11:41:50 -08:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
if (aNotify) {
|
|
|
|
nsNodeUtils::AttributeWillChange(this, aNamespaceID, aName, modType);
|
|
|
|
}
|
|
|
|
|
|
|
|
return SetAttrAndNotify(aNamespaceID, aName, aPrefix, oldValue,
|
|
|
|
aParsedValue, modType, hasListeners, aNotify,
|
2012-02-13 18:00:56 -08:00
|
|
|
kCallAfterSetAttr);
|
2011-02-01 11:41:50 -08:00
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsresult
|
2012-08-22 08:56:38 -07:00
|
|
|
nsGenericElement::SetAttrAndNotify(int32_t aNamespaceID,
|
2007-03-22 10:30:00 -07:00
|
|
|
nsIAtom* aName,
|
|
|
|
nsIAtom* aPrefix,
|
2012-02-13 18:00:56 -08:00
|
|
|
const nsAttrValue& aOldValue,
|
2007-03-22 10:30:00 -07:00
|
|
|
nsAttrValue& aParsedValue,
|
2012-08-22 08:56:38 -07:00
|
|
|
uint8_t aModType,
|
2011-09-28 23:19:26 -07:00
|
|
|
bool aFireMutation,
|
|
|
|
bool aNotify,
|
2012-02-13 18:00:56 -08:00
|
|
|
bool aCallAfterSetAttr)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
nsIDocument* document = GetCurrentDoc();
|
|
|
|
mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify);
|
2007-07-12 13:05:45 -07:00
|
|
|
|
2010-09-01 15:48:24 -07:00
|
|
|
nsMutationGuard::DidMutate();
|
|
|
|
|
2012-02-13 18:00:56 -08:00
|
|
|
// Copy aParsedValue for later use since it will be lost when we call
|
|
|
|
// SetAndTakeMappedAttr below
|
|
|
|
nsAttrValue aValueForAfterSetAttr;
|
|
|
|
if (aCallAfterSetAttr) {
|
|
|
|
aValueForAfterSetAttr.SetTo(aParsedValue);
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
if (aNamespaceID == kNameSpaceID_None) {
|
|
|
|
// XXXbz Perhaps we should push up the attribute mapping function
|
|
|
|
// stuff to nsGenericElement?
|
|
|
|
if (!IsAttributeMapped(aName) ||
|
|
|
|
!SetMappedAttribute(document, aName, aParsedValue, &rv)) {
|
|
|
|
rv = mAttrsAndChildren.SetAndTakeAttr(aName, aParsedValue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2012-03-28 22:43:09 -07:00
|
|
|
nsCOMPtr<nsINodeInfo> ni;
|
2008-09-12 15:32:18 -07:00
|
|
|
ni = mNodeInfo->NodeInfoManager()->GetNodeInfo(aName, aPrefix,
|
2011-06-14 00:56:49 -07:00
|
|
|
aNamespaceID,
|
|
|
|
nsIDOMNode::ATTRIBUTE_NODE);
|
2008-09-25 15:46:52 -07:00
|
|
|
NS_ENSURE_TRUE(ni, NS_ERROR_OUT_OF_MEMORY);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
rv = mAttrsAndChildren.SetAndTakeAttr(ni, aParsedValue);
|
|
|
|
}
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2008-03-03 17:25:06 -08:00
|
|
|
if (document || HasFlag(NODE_FORCE_XBL_BINDINGS)) {
|
2011-10-18 04:19:44 -07:00
|
|
|
nsRefPtr<nsXBLBinding> binding =
|
|
|
|
OwnerDoc()->BindingManager()->GetBinding(this);
|
|
|
|
if (binding) {
|
|
|
|
binding->AttributeChanged(aName, aNamespaceID, false, aNotify);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-31 18:46:57 -07:00
|
|
|
UpdateState(aNotify);
|
|
|
|
|
2007-07-10 18:14:55 -07:00
|
|
|
if (aNotify) {
|
2010-02-23 20:37:47 -08:00
|
|
|
nsNodeUtils::AttributeChanged(this, aNamespaceID, aName, aModType);
|
2007-07-10 18:14:55 -07:00
|
|
|
}
|
2008-12-03 02:39:21 -08:00
|
|
|
|
|
|
|
if (aNamespaceID == kNameSpaceID_XMLEvents &&
|
|
|
|
aName == nsGkAtoms::event && mNodeInfo->GetDocument()) {
|
|
|
|
mNodeInfo->GetDocument()->AddXMLEventsContent(this);
|
|
|
|
}
|
2012-02-13 18:00:56 -08:00
|
|
|
if (aCallAfterSetAttr) {
|
|
|
|
rv = AfterSetAttr(aNamespaceID, aName, &aValueForAfterSetAttr, aNotify);
|
2008-12-03 02:39:21 -08:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
if (aFireMutation) {
|
2011-10-17 07:59:28 -07:00
|
|
|
nsMutationEvent mutation(true, NS_MUTATION_ATTRMODIFIED);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2008-04-18 10:20:11 -07:00
|
|
|
nsCOMPtr<nsIDOMAttr> attrNode;
|
|
|
|
nsAutoString ns;
|
|
|
|
nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNamespaceID, ns);
|
2012-02-27 15:57:28 -08:00
|
|
|
GetAttributeNodeNSInternal(ns, nsDependentAtomString(aName),
|
|
|
|
getter_AddRefs(attrNode));
|
2008-04-18 10:20:11 -07:00
|
|
|
mutation.mRelatedNode = attrNode;
|
|
|
|
|
|
|
|
mutation.mAttrName = aName;
|
|
|
|
nsAutoString newValue;
|
|
|
|
GetAttr(aNamespaceID, aName, newValue);
|
|
|
|
if (!newValue.IsEmpty()) {
|
|
|
|
mutation.mNewAttrValue = do_GetAtom(newValue);
|
|
|
|
}
|
2012-02-13 18:00:56 -08:00
|
|
|
if (!aOldValue.IsEmptyString()) {
|
|
|
|
mutation.mPrevAttrValue = aOldValue.GetAsAtom();
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2010-02-23 20:37:47 -08:00
|
|
|
mutation.mAttrChange = aModType;
|
2008-04-18 10:20:11 -07:00
|
|
|
|
2011-10-18 03:53:36 -07:00
|
|
|
mozAutoSubtreeModified subtree(OwnerDoc(), this);
|
2011-12-16 22:02:05 -08:00
|
|
|
(new nsAsyncDOMEvent(this, mutation))->RunDOMEventWhenSafe();
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool
|
2012-08-22 08:56:38 -07:00
|
|
|
nsGenericElement::ParseAttribute(int32_t aNamespaceID,
|
2007-03-22 10:30:00 -07:00
|
|
|
nsIAtom* aAttribute,
|
|
|
|
const nsAString& aValue,
|
|
|
|
nsAttrValue& aResult)
|
|
|
|
{
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool
|
2007-03-22 10:30:00 -07:00
|
|
|
nsGenericElement::SetMappedAttribute(nsIDocument* aDocument,
|
|
|
|
nsIAtom* aName,
|
|
|
|
nsAttrValue& aValue,
|
|
|
|
nsresult* aRetval)
|
|
|
|
{
|
|
|
|
*aRetval = NS_OK;
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2011-07-29 12:37:17 -07:00
|
|
|
nsEventListenerManager*
|
2011-09-28 08:54:50 -07:00
|
|
|
nsGenericElement::GetEventListenerManagerForAttr(nsIAtom* aAttrName,
|
2011-09-28 23:19:26 -07:00
|
|
|
bool* aDefer)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2011-10-17 07:59:28 -07:00
|
|
|
*aDefer = true;
|
|
|
|
return GetListenerManager(true);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
nsGenericElement::nsAttrInfo
|
2012-08-22 08:56:38 -07:00
|
|
|
nsGenericElement::GetAttrInfo(int32_t aNamespaceID, nsIAtom* aName) const
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2012-07-30 07:20:58 -07:00
|
|
|
NS_ASSERTION(nullptr != aName, "must have attribute name");
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown,
|
|
|
|
"must have a real namespace ID!");
|
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
int32_t index = mAttrsAndChildren.IndexOfAttr(aName, aNamespaceID);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (index >= 0) {
|
|
|
|
return nsAttrInfo(mAttrsAndChildren.AttrNameAt(index),
|
|
|
|
mAttrsAndChildren.AttrAt(index));
|
|
|
|
}
|
|
|
|
|
2012-07-30 07:20:58 -07:00
|
|
|
return nsAttrInfo(nullptr, nullptr);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool
|
2012-08-22 08:56:38 -07:00
|
|
|
nsGenericElement::GetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
2007-03-22 10:30:00 -07:00
|
|
|
nsAString& aResult) const
|
|
|
|
{
|
2012-07-30 07:20:58 -07:00
|
|
|
NS_ASSERTION(nullptr != aName, "must have attribute name");
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown,
|
|
|
|
"must have a real namespace ID!");
|
|
|
|
|
|
|
|
const nsAttrValue* val = mAttrsAndChildren.GetAttr(aName, aNameSpaceID);
|
|
|
|
if (!val) {
|
|
|
|
// Since we are returning a success code we'd better do
|
|
|
|
// something about the out parameters (someone may have
|
|
|
|
// given us a non-empty string).
|
|
|
|
aResult.Truncate();
|
|
|
|
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
val->ToString(aResult);
|
|
|
|
|
2011-10-17 07:59:28 -07:00
|
|
|
return true;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool
|
2012-08-22 08:56:38 -07:00
|
|
|
nsGenericElement::HasAttr(int32_t aNameSpaceID, nsIAtom* aName) const
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2012-07-30 07:20:58 -07:00
|
|
|
NS_ASSERTION(nullptr != aName, "must have attribute name");
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown,
|
|
|
|
"must have a real namespace ID!");
|
|
|
|
|
|
|
|
return mAttrsAndChildren.IndexOfAttr(aName, aNameSpaceID) >= 0;
|
|
|
|
}
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool
|
2012-08-22 08:56:38 -07:00
|
|
|
nsGenericElement::AttrValueIs(int32_t aNameSpaceID,
|
2007-03-22 10:30:00 -07:00
|
|
|
nsIAtom* aName,
|
|
|
|
const nsAString& aValue,
|
|
|
|
nsCaseTreatment aCaseSensitive) const
|
|
|
|
{
|
|
|
|
NS_ASSERTION(aName, "Must have attr name");
|
|
|
|
NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown, "Must have namespace");
|
|
|
|
|
|
|
|
const nsAttrValue* val = mAttrsAndChildren.GetAttr(aName, aNameSpaceID);
|
|
|
|
return val && val->Equals(aValue, aCaseSensitive);
|
|
|
|
}
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool
|
2012-08-22 08:56:38 -07:00
|
|
|
nsGenericElement::AttrValueIs(int32_t aNameSpaceID,
|
2007-03-22 10:30:00 -07:00
|
|
|
nsIAtom* aName,
|
|
|
|
nsIAtom* aValue,
|
|
|
|
nsCaseTreatment aCaseSensitive) const
|
|
|
|
{
|
|
|
|
NS_ASSERTION(aName, "Must have attr name");
|
|
|
|
NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown, "Must have namespace");
|
|
|
|
NS_ASSERTION(aValue, "Null value atom");
|
|
|
|
|
|
|
|
const nsAttrValue* val = mAttrsAndChildren.GetAttr(aName, aNameSpaceID);
|
|
|
|
return val && val->Equals(aValue, aCaseSensitive);
|
|
|
|
}
|
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
int32_t
|
|
|
|
nsGenericElement::FindAttrValueIn(int32_t aNameSpaceID,
|
2007-03-22 10:30:00 -07:00
|
|
|
nsIAtom* aName,
|
|
|
|
AttrValuesArray* aValues,
|
|
|
|
nsCaseTreatment aCaseSensitive) const
|
|
|
|
{
|
|
|
|
NS_ASSERTION(aName, "Must have attr name");
|
|
|
|
NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown, "Must have namespace");
|
|
|
|
NS_ASSERTION(aValues, "Null value array");
|
|
|
|
|
|
|
|
const nsAttrValue* val = mAttrsAndChildren.GetAttr(aName, aNameSpaceID);
|
|
|
|
if (val) {
|
2012-08-22 08:56:38 -07:00
|
|
|
for (int32_t i = 0; aValues[i]; ++i) {
|
2007-03-22 10:30:00 -07:00
|
|
|
if (val->Equals(*aValues[i], aCaseSensitive)) {
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ATTR_VALUE_NO_MATCH;
|
|
|
|
}
|
|
|
|
return ATTR_MISSING;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2012-08-22 08:56:38 -07:00
|
|
|
nsGenericElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
2011-09-28 23:19:26 -07:00
|
|
|
bool aNotify)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2012-07-30 07:20:58 -07:00
|
|
|
NS_ASSERTION(nullptr != aName, "must have attribute name");
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
int32_t index = mAttrsAndChildren.IndexOfAttr(aName, aNameSpaceID);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (index < 0) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-07-30 07:20:58 -07:00
|
|
|
nsresult rv = BeforeSetAttr(aNameSpaceID, aName, nullptr, aNotify);
|
2007-12-04 08:50:32 -08:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2012-02-13 18:00:56 -08:00
|
|
|
|
|
|
|
nsIDocument *document = GetCurrentDoc();
|
2007-03-22 10:30:00 -07:00
|
|
|
mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify);
|
|
|
|
|
2009-06-29 11:36:25 -07:00
|
|
|
if (aNotify) {
|
|
|
|
nsNodeUtils::AttributeWillChange(this, aNameSpaceID, aName,
|
|
|
|
nsIDOMMutationEvent::REMOVAL);
|
|
|
|
}
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool hasMutationListeners = aNotify &&
|
2007-03-22 10:30:00 -07:00
|
|
|
nsContentUtils::HasMutationListeners(this,
|
2007-07-04 13:39:10 -07:00
|
|
|
NS_EVENT_BITS_MUTATION_ATTRMODIFIED,
|
|
|
|
this);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// Grab the attr node if needed before we remove it from the attr map
|
|
|
|
nsCOMPtr<nsIDOMAttr> attrNode;
|
|
|
|
if (hasMutationListeners) {
|
|
|
|
nsAutoString ns;
|
|
|
|
nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNameSpaceID, ns);
|
2012-02-27 15:57:28 -08:00
|
|
|
GetAttributeNodeNSInternal(ns, nsDependentAtomString(aName),
|
|
|
|
getter_AddRefs(attrNode));
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Clear binding to nsIDOMNamedNodeMap
|
|
|
|
nsDOMSlots *slots = GetExistingDOMSlots();
|
|
|
|
if (slots && slots->mAttributeMap) {
|
|
|
|
slots->mAttributeMap->DropAttribute(aNameSpaceID, aName);
|
|
|
|
}
|
|
|
|
|
2010-09-01 15:48:24 -07:00
|
|
|
// The id-handling code, and in the future possibly other code, need to
|
|
|
|
// react to unexpected attribute changes.
|
|
|
|
nsMutationGuard::DidMutate();
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsAttrValue oldValue;
|
2007-12-04 08:50:32 -08:00
|
|
|
rv = mAttrsAndChildren.RemoveAttrAt(index, oldValue);
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2008-03-03 17:25:06 -08:00
|
|
|
if (document || HasFlag(NODE_FORCE_XBL_BINDINGS)) {
|
2011-10-18 04:19:44 -07:00
|
|
|
nsRefPtr<nsXBLBinding> binding =
|
|
|
|
OwnerDoc()->BindingManager()->GetBinding(this);
|
|
|
|
if (binding) {
|
|
|
|
binding->AttributeChanged(aName, aNameSpaceID, true, aNotify);
|
2008-03-03 17:25:06 -08:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2011-05-31 18:46:57 -07:00
|
|
|
UpdateState(aNotify);
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
if (aNotify) {
|
|
|
|
nsNodeUtils::AttributeChanged(this, aNameSpaceID, aName,
|
2009-12-10 14:36:04 -08:00
|
|
|
nsIDOMMutationEvent::REMOVAL);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2012-07-30 07:20:58 -07:00
|
|
|
rv = AfterSetAttr(aNameSpaceID, aName, nullptr, aNotify);
|
2008-12-03 02:39:21 -08:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
if (hasMutationListeners) {
|
2011-08-30 14:45:31 -07:00
|
|
|
nsCOMPtr<nsIDOMEventTarget> node = do_QueryObject(this);
|
2011-10-17 07:59:28 -07:00
|
|
|
nsMutationEvent mutation(true, NS_MUTATION_ATTRMODIFIED);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2008-04-18 10:20:11 -07:00
|
|
|
mutation.mRelatedNode = attrNode;
|
|
|
|
mutation.mAttrName = aName;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2008-04-18 10:20:11 -07:00
|
|
|
nsAutoString value;
|
|
|
|
oldValue.ToString(value);
|
|
|
|
if (!value.IsEmpty())
|
|
|
|
mutation.mPrevAttrValue = do_GetAtom(value);
|
|
|
|
mutation.mAttrChange = nsIDOMMutationEvent::REMOVAL;
|
2008-03-14 16:08:57 -07:00
|
|
|
|
2011-10-18 03:53:36 -07:00
|
|
|
mozAutoSubtreeModified subtree(OwnerDoc(), this);
|
2011-12-16 22:02:05 -08:00
|
|
|
(new nsAsyncDOMEvent(this, mutation))->RunDOMEventWhenSafe();
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2008-12-03 02:39:21 -08:00
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
const nsAttrName*
|
2012-08-22 08:56:38 -07:00
|
|
|
nsGenericElement::GetAttrNameAt(uint32_t aIndex) const
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
return mAttrsAndChildren.GetSafeAttrNameAt(aIndex);
|
|
|
|
}
|
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t
|
2007-03-22 10:30:00 -07:00
|
|
|
nsGenericElement::GetAttrCount() const
|
|
|
|
{
|
|
|
|
return mAttrsAndChildren.AttrCount();
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
void
|
|
|
|
nsGenericElement::ListAttributes(FILE* out) const
|
|
|
|
{
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t index, count = mAttrsAndChildren.AttrCount();
|
2007-03-22 10:30:00 -07:00
|
|
|
for (index = 0; index < count; index++) {
|
|
|
|
nsAutoString buffer;
|
|
|
|
|
|
|
|
// name
|
|
|
|
mAttrsAndChildren.AttrNameAt(index)->GetQualifiedName(buffer);
|
|
|
|
|
|
|
|
// value
|
|
|
|
buffer.AppendLiteral("=\"");
|
|
|
|
nsAutoString value;
|
|
|
|
mAttrsAndChildren.AttrAt(index)->ToString(value);
|
|
|
|
for (int i = value.Length(); i >= 0; --i) {
|
|
|
|
if (value[i] == PRUnichar('"'))
|
2012-08-22 08:56:38 -07:00
|
|
|
value.Insert(PRUnichar('\\'), uint32_t(i));
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
buffer.Append(value);
|
|
|
|
buffer.AppendLiteral("\"");
|
|
|
|
|
|
|
|
fputs(" ", out);
|
|
|
|
fputs(NS_LossyConvertUTF16toASCII(buffer).get(), out);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-08-22 08:56:38 -07:00
|
|
|
nsGenericElement::List(FILE* out, int32_t aIndent,
|
2007-03-22 10:30:00 -07:00
|
|
|
const nsCString& aPrefix) const
|
|
|
|
{
|
2012-08-22 08:56:38 -07:00
|
|
|
int32_t indent;
|
2007-03-22 10:30:00 -07:00
|
|
|
for (indent = aIndent; --indent >= 0; ) fputs(" ", out);
|
|
|
|
|
|
|
|
fputs(aPrefix.get(), out);
|
|
|
|
|
2011-05-05 09:26:33 -07:00
|
|
|
fputs(NS_LossyConvertUTF16toASCII(mNodeInfo->QualifiedName()).get(), out);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
fprintf(out, "@%p", (void *)this);
|
|
|
|
|
|
|
|
ListAttributes(out);
|
|
|
|
|
2011-05-31 18:46:57 -07:00
|
|
|
fprintf(out, " state=[%llx]", State().GetInternalValue());
|
2010-05-11 17:30:42 -07:00
|
|
|
fprintf(out, " flags=[%08x]", static_cast<unsigned int>(GetFlags()));
|
2011-12-20 01:15:41 -08:00
|
|
|
if (IsCommonAncestorForRangeInSelection()) {
|
2012-01-10 06:19:54 -08:00
|
|
|
nsRange::RangeHashTable* ranges =
|
|
|
|
static_cast<nsRange::RangeHashTable*>(GetProperty(nsGkAtoms::range));
|
2011-12-20 01:15:41 -08:00
|
|
|
fprintf(out, " ranges:%d", ranges ? ranges->Count() : 0);
|
|
|
|
}
|
2010-05-01 11:42:47 -07:00
|
|
|
fprintf(out, " primaryframe=%p", static_cast<void*>(GetPrimaryFrame()));
|
2007-03-22 10:30:00 -07:00
|
|
|
fprintf(out, " refcount=%d<", mRefCnt.get());
|
|
|
|
|
2011-09-27 00:54:58 -07:00
|
|
|
nsIContent* child = GetFirstChild();
|
|
|
|
if (child) {
|
2007-03-22 10:30:00 -07:00
|
|
|
fputs("\n", out);
|
2011-09-27 00:54:58 -07:00
|
|
|
|
|
|
|
for (; child; child = child->GetNextSibling()) {
|
|
|
|
child->List(out, aIndent + 1);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
for (indent = aIndent; --indent >= 0; ) fputs(" ", out);
|
|
|
|
}
|
|
|
|
|
|
|
|
fputs(">\n", out);
|
|
|
|
|
2007-07-08 00:08:04 -07:00
|
|
|
nsGenericElement* nonConstThis = const_cast<nsGenericElement*>(this);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// XXX sXBL/XBL2 issue! Owner or current document?
|
2011-10-18 03:53:36 -07:00
|
|
|
nsIDocument *document = OwnerDoc();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2011-10-18 04:19:44 -07:00
|
|
|
// Note: not listing nsIAnonymousContentCreator-created content...
|
|
|
|
|
|
|
|
nsBindingManager* bindingManager = document->BindingManager();
|
|
|
|
nsCOMPtr<nsIDOMNodeList> anonymousChildren;
|
|
|
|
bindingManager->GetAnonymousNodesFor(nonConstThis,
|
|
|
|
getter_AddRefs(anonymousChildren));
|
|
|
|
|
|
|
|
if (anonymousChildren) {
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t length;
|
2011-10-18 04:19:44 -07:00
|
|
|
anonymousChildren->GetLength(&length);
|
|
|
|
if (length > 0) {
|
|
|
|
for (indent = aIndent; --indent >= 0; ) fputs(" ", out);
|
|
|
|
fputs("anonymous-children<\n", out);
|
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
for (uint32_t i = 0; i < length; ++i) {
|
2011-10-18 04:19:44 -07:00
|
|
|
nsCOMPtr<nsIDOMNode> node;
|
|
|
|
anonymousChildren->Item(i, getter_AddRefs(node));
|
|
|
|
nsCOMPtr<nsIContent> child = do_QueryInterface(node);
|
|
|
|
child->List(out, aIndent + 1);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2011-10-18 04:19:44 -07:00
|
|
|
|
|
|
|
for (indent = aIndent; --indent >= 0; ) fputs(" ", out);
|
|
|
|
fputs(">\n", out);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2011-10-18 04:19:44 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2011-10-18 04:19:44 -07:00
|
|
|
if (bindingManager->HasContentListFor(nonConstThis)) {
|
|
|
|
nsCOMPtr<nsIDOMNodeList> contentList;
|
|
|
|
bindingManager->GetContentListFor(nonConstThis,
|
|
|
|
getter_AddRefs(contentList));
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-07-30 07:20:58 -07:00
|
|
|
NS_ASSERTION(contentList != nullptr, "oops, binding manager lied");
|
2011-10-18 04:19:44 -07:00
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t length;
|
2011-10-18 04:19:44 -07:00
|
|
|
contentList->GetLength(&length);
|
|
|
|
if (length > 0) {
|
|
|
|
for (indent = aIndent; --indent >= 0; ) fputs(" ", out);
|
|
|
|
fputs("content-list<\n", out);
|
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
for (uint32_t i = 0; i < length; ++i) {
|
2011-10-18 04:19:44 -07:00
|
|
|
nsCOMPtr<nsIDOMNode> node;
|
|
|
|
contentList->Item(i, getter_AddRefs(node));
|
|
|
|
nsCOMPtr<nsIContent> child = do_QueryInterface(node);
|
|
|
|
child->List(out, aIndent + 1);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2011-10-18 04:19:44 -07:00
|
|
|
|
|
|
|
for (indent = aIndent; --indent >= 0; ) fputs(" ", out);
|
|
|
|
fputs(">\n", out);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-08-22 08:56:38 -07:00
|
|
|
nsGenericElement::DumpContent(FILE* out, int32_t aIndent,
|
2011-09-28 23:19:26 -07:00
|
|
|
bool aDumpAll) const
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2012-08-22 08:56:38 -07:00
|
|
|
int32_t indent;
|
2007-03-22 10:30:00 -07:00
|
|
|
for (indent = aIndent; --indent >= 0; ) fputs(" ", out);
|
|
|
|
|
2011-05-05 09:26:33 -07:00
|
|
|
const nsString& buf = mNodeInfo->QualifiedName();
|
2007-03-22 10:30:00 -07:00
|
|
|
fputs("<", out);
|
|
|
|
fputs(NS_LossyConvertUTF16toASCII(buf).get(), out);
|
|
|
|
|
|
|
|
if(aDumpAll) ListAttributes(out);
|
|
|
|
|
|
|
|
fputs(">", out);
|
|
|
|
|
|
|
|
if(aIndent) fputs("\n", out);
|
|
|
|
|
2011-09-27 00:54:58 -07:00
|
|
|
for (nsIContent* child = GetFirstChild();
|
|
|
|
child;
|
|
|
|
child = child->GetNextSibling()) {
|
2012-08-22 08:56:38 -07:00
|
|
|
int32_t indent = aIndent ? aIndent + 1 : 0;
|
2011-09-27 00:54:58 -07:00
|
|
|
child->DumpContent(out, indent, aDumpAll);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
for (indent = aIndent; --indent >= 0; ) fputs(" ", out);
|
|
|
|
fputs("</", out);
|
|
|
|
fputs(NS_LossyConvertUTF16toASCII(buf).get(), out);
|
|
|
|
fputs(">", out);
|
|
|
|
|
|
|
|
if(aIndent) fputs("\n", out);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool
|
2007-04-23 00:31:21 -07:00
|
|
|
nsGenericElement::CheckHandleEventForLinksPrecondition(nsEventChainVisitor& aVisitor,
|
|
|
|
nsIURI** aURI) const
|
|
|
|
{
|
|
|
|
if (aVisitor.mEventStatus == nsEventStatus_eConsumeNoDefault ||
|
2011-06-30 04:52:11 -07:00
|
|
|
(!NS_IS_TRUSTED_EVENT(aVisitor.mEvent) &&
|
|
|
|
(aVisitor.mEvent->message != NS_MOUSE_CLICK) &&
|
|
|
|
(aVisitor.mEvent->message != NS_KEY_PRESS) &&
|
|
|
|
(aVisitor.mEvent->message != NS_UI_ACTIVATE)) ||
|
2010-12-27 12:42:10 -08:00
|
|
|
!aVisitor.mPresContext ||
|
2011-07-19 09:19:32 -07:00
|
|
|
(aVisitor.mEvent->flags & NS_EVENT_FLAG_PREVENT_MULTIPLE_ACTIONS)) {
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2007-04-23 00:31:21 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Make sure we actually are a link
|
|
|
|
return IsLink(aURI);
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsresult
|
2007-04-23 00:31:21 -07:00
|
|
|
nsGenericElement::PreHandleEventForLinks(nsEventChainPreVisitor& aVisitor)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
// Optimisation: return early if this event doesn't interest us.
|
|
|
|
// IMPORTANT: this switch and the switch below it must be kept in sync!
|
|
|
|
switch (aVisitor.mEvent->message) {
|
|
|
|
case NS_MOUSE_ENTER_SYNTH:
|
|
|
|
case NS_FOCUS_CONTENT:
|
|
|
|
case NS_MOUSE_EXIT_SYNTH:
|
|
|
|
case NS_BLUR_CONTENT:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-04-23 00:31:21 -07:00
|
|
|
// Make sure we meet the preconditions before continuing
|
|
|
|
nsCOMPtr<nsIURI> absURI;
|
|
|
|
if (!CheckHandleEventForLinksPrecondition(aVisitor, getter_AddRefs(absURI))) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
|
|
|
// We do the status bar updates in PreHandleEvent so that the status bar gets
|
|
|
|
// updated even if the event is consumed before we have a chance to set it.
|
|
|
|
switch (aVisitor.mEvent->message) {
|
2010-10-18 11:12:18 -07:00
|
|
|
// Set the status bar similarly for mouseover and focus
|
2007-04-23 00:31:21 -07:00
|
|
|
case NS_MOUSE_ENTER_SYNTH:
|
|
|
|
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
|
|
|
|
// FALL THROUGH
|
|
|
|
case NS_FOCUS_CONTENT:
|
2010-10-18 11:12:18 -07:00
|
|
|
if (aVisitor.mEvent->eventStructType != NS_FOCUS_EVENT ||
|
|
|
|
!static_cast<nsFocusEvent*>(aVisitor.mEvent)->isRefocus) {
|
2007-04-23 00:31:21 -07:00
|
|
|
nsAutoString target;
|
|
|
|
GetLinkTarget(target);
|
2007-07-11 06:05:05 -07:00
|
|
|
nsContentUtils::TriggerLink(this, aVisitor.mPresContext, absURI, target,
|
2011-10-17 07:59:28 -07:00
|
|
|
false, true, true);
|
2010-12-27 12:42:10 -08:00
|
|
|
// Make sure any ancestor links don't also TriggerLink
|
2011-07-19 09:19:32 -07:00
|
|
|
aVisitor.mEvent->flags |= NS_EVENT_FLAG_PREVENT_MULTIPLE_ACTIONS;
|
2007-04-23 00:31:21 -07:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_MOUSE_EXIT_SYNTH:
|
|
|
|
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
|
|
|
|
// FALL THROUGH
|
|
|
|
case NS_BLUR_CONTENT:
|
|
|
|
rv = LeaveLink(aVisitor.mPresContext);
|
2010-12-27 12:42:10 -08:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2011-07-19 09:19:32 -07:00
|
|
|
aVisitor.mEvent->flags |= NS_EVENT_FLAG_PREVENT_MULTIPLE_ACTIONS;
|
2010-12-27 12:42:10 -08:00
|
|
|
}
|
2007-04-23 00:31:21 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
// switch not in sync with the optimization switch earlier in this function
|
|
|
|
NS_NOTREACHED("switch statements not in sync");
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsGenericElement::PostHandleEventForLinks(nsEventChainPostVisitor& aVisitor)
|
|
|
|
{
|
|
|
|
// Optimisation: return early if this event doesn't interest us.
|
|
|
|
// IMPORTANT: this switch and the switch below it must be kept in sync!
|
|
|
|
switch (aVisitor.mEvent->message) {
|
|
|
|
case NS_MOUSE_BUTTON_DOWN:
|
|
|
|
case NS_MOUSE_CLICK:
|
|
|
|
case NS_UI_ACTIVATE:
|
|
|
|
case NS_KEY_PRESS:
|
|
|
|
break;
|
|
|
|
default:
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-04-23 00:31:21 -07:00
|
|
|
// Make sure we meet the preconditions before continuing
|
2007-03-22 10:30:00 -07:00
|
|
|
nsCOMPtr<nsIURI> absURI;
|
2007-04-23 00:31:21 -07:00
|
|
|
if (!CheckHandleEventForLinksPrecondition(aVisitor, getter_AddRefs(absURI))) {
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
|
|
|
switch (aVisitor.mEvent->message) {
|
|
|
|
case NS_MOUSE_BUTTON_DOWN:
|
|
|
|
{
|
|
|
|
if (aVisitor.mEvent->eventStructType == NS_MOUSE_EVENT &&
|
2007-07-08 00:08:04 -07:00
|
|
|
static_cast<nsMouseEvent*>(aVisitor.mEvent)->button ==
|
2007-03-22 10:30:00 -07:00
|
|
|
nsMouseEvent::eLeftButton) {
|
|
|
|
// don't make the link grab the focus if there is no link handler
|
|
|
|
nsILinkHandler *handler = aVisitor.mPresContext->GetLinkHandler();
|
|
|
|
nsIDocument *document = GetCurrentDoc();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 11:00:39 -07:00
|
|
|
if (handler && document) {
|
|
|
|
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
|
|
|
|
if (fm) {
|
2011-07-19 09:19:32 -07:00
|
|
|
aVisitor.mEvent->flags |= NS_EVENT_FLAG_PREVENT_MULTIPLE_ACTIONS;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 11:00:39 -07:00
|
|
|
nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(this);
|
2009-09-21 08:58:16 -07:00
|
|
|
fm->SetFocus(elem, nsIFocusManager::FLAG_BYMOUSE |
|
|
|
|
nsIFocusManager::FLAG_NOSCROLL);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 11:00:39 -07:00
|
|
|
|
2010-10-28 07:11:15 -07:00
|
|
|
nsEventStateManager::SetActiveManager(
|
2011-04-21 10:35:52 -07:00
|
|
|
aVisitor.mPresContext->EventStateManager(), this);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_MOUSE_CLICK:
|
|
|
|
if (NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent)) {
|
2009-10-13 10:23:48 -07:00
|
|
|
nsInputEvent* inputEvent = static_cast<nsInputEvent*>(aVisitor.mEvent);
|
2012-04-24 20:00:02 -07:00
|
|
|
if (inputEvent->IsControl() || inputEvent->IsMeta() ||
|
|
|
|
inputEvent->IsAlt() ||inputEvent->IsShift()) {
|
2009-10-13 10:23:48 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// The default action is simply to dispatch DOMActivate
|
2007-03-25 22:38:22 -07:00
|
|
|
nsCOMPtr<nsIPresShell> shell = aVisitor.mPresContext->GetPresShell();
|
2007-03-22 10:30:00 -07:00
|
|
|
if (shell) {
|
|
|
|
// single-click
|
|
|
|
nsEventStatus status = nsEventStatus_eIgnore;
|
|
|
|
nsUIEvent actEvent(NS_IS_TRUSTED_EVENT(aVisitor.mEvent),
|
|
|
|
NS_UI_ACTIVATE, 1);
|
|
|
|
|
|
|
|
rv = shell->HandleDOMEventWithTarget(this, &actEvent, &status);
|
2010-12-27 12:42:10 -08:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_UI_ACTIVATE:
|
|
|
|
{
|
2011-01-03 18:46:19 -08:00
|
|
|
if (aVisitor.mEvent->originalTarget == this) {
|
2010-12-27 12:42:10 -08:00
|
|
|
nsAutoString target;
|
|
|
|
GetLinkTarget(target);
|
|
|
|
nsContentUtils::TriggerLink(this, aVisitor.mPresContext, absURI, target,
|
2011-10-17 07:59:28 -07:00
|
|
|
true, true, NS_IS_TRUSTED_EVENT(aVisitor.mEvent));
|
2010-12-27 12:42:10 -08:00
|
|
|
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_KEY_PRESS:
|
|
|
|
{
|
|
|
|
if (aVisitor.mEvent->eventStructType == NS_KEY_EVENT) {
|
2007-07-08 00:08:04 -07:00
|
|
|
nsKeyEvent* keyEvent = static_cast<nsKeyEvent*>(aVisitor.mEvent);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (keyEvent->keyCode == NS_VK_RETURN) {
|
|
|
|
nsEventStatus status = nsEventStatus_eIgnore;
|
|
|
|
rv = DispatchClickEvent(aVisitor.mPresContext, keyEvent, this,
|
2011-10-17 07:59:28 -07:00
|
|
|
false, 0, &status);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
// switch not in sync with the optimization switch earlier in this function
|
|
|
|
NS_NOTREACHED("switch statements not in sync");
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsGenericElement::GetLinkTarget(nsAString& aTarget)
|
|
|
|
{
|
|
|
|
aTarget.Truncate();
|
|
|
|
}
|
|
|
|
|
2008-07-21 17:55:52 -07:00
|
|
|
// NOTE: The aPresContext pointer is NOT addrefed.
|
2009-12-10 23:37:41 -08:00
|
|
|
// *aSelectorList might be null even if NS_OK is returned; this
|
|
|
|
// happens when all the selectors were pseudo-element selectors.
|
2008-07-21 17:55:52 -07:00
|
|
|
static nsresult
|
|
|
|
ParseSelectorList(nsINode* aNode,
|
|
|
|
const nsAString& aSelectorString,
|
2011-03-29 10:29:21 -07:00
|
|
|
nsCSSSelectorList** aSelectorList)
|
2008-07-21 17:55:52 -07:00
|
|
|
{
|
|
|
|
NS_ENSURE_ARG(aNode);
|
|
|
|
|
2011-10-18 03:53:36 -07:00
|
|
|
nsIDocument* doc = aNode->OwnerDoc();
|
2010-03-02 12:59:32 -08:00
|
|
|
nsCSSParser parser(doc->CSSLoader());
|
2008-07-21 17:55:52 -07:00
|
|
|
|
2009-12-10 23:37:41 -08:00
|
|
|
nsCSSSelectorList* selectorList;
|
2010-03-02 12:59:32 -08:00
|
|
|
nsresult rv = parser.ParseSelectorString(aSelectorString,
|
|
|
|
doc->GetDocumentURI(),
|
|
|
|
0, // XXXbz get the line number!
|
|
|
|
&selectorList);
|
2008-07-21 17:55:52 -07:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2009-12-10 23:37:41 -08:00
|
|
|
// Filter out pseudo-element selectors from selectorList
|
|
|
|
nsCSSSelectorList** slot = &selectorList;
|
|
|
|
do {
|
|
|
|
nsCSSSelectorList* cur = *slot;
|
|
|
|
if (cur->mSelectors->IsPseudoElement()) {
|
|
|
|
*slot = cur->mNext;
|
2012-07-30 07:20:58 -07:00
|
|
|
cur->mNext = nullptr;
|
2009-12-10 23:37:41 -08:00
|
|
|
delete cur;
|
|
|
|
} else {
|
|
|
|
slot = &cur->mNext;
|
|
|
|
}
|
|
|
|
} while (*slot);
|
|
|
|
*aSelectorList = selectorList;
|
|
|
|
|
2008-07-21 17:55:52 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-09-30 15:17:14 -07:00
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool
|
2010-10-21 07:09:00 -07:00
|
|
|
nsGenericElement::MozMatchesSelector(const nsAString& aSelector, nsresult* aResult)
|
2009-09-30 15:17:14 -07:00
|
|
|
{
|
|
|
|
nsAutoPtr<nsCSSSelectorList> selectorList;
|
2011-09-28 23:19:26 -07:00
|
|
|
bool matches = false;
|
2009-09-30 15:17:14 -07:00
|
|
|
|
2011-03-29 10:29:21 -07:00
|
|
|
*aResult = ParseSelectorList(this, aSelector, getter_Transfers(selectorList));
|
2010-10-21 07:09:00 -07:00
|
|
|
|
|
|
|
if (NS_SUCCEEDED(*aResult)) {
|
2011-11-13 19:24:41 -08:00
|
|
|
OwnerDoc()->FlushPendingLinkUpdates();
|
2011-10-17 07:59:28 -07:00
|
|
|
TreeMatchContext matchingContext(false,
|
2011-03-29 10:29:21 -07:00
|
|
|
nsRuleWalker::eRelevantLinkUnvisited,
|
2012-06-07 12:19:56 -07:00
|
|
|
OwnerDoc(),
|
|
|
|
TreeMatchContext::eNeverMatchVisited);
|
2011-03-29 10:29:21 -07:00
|
|
|
matches = nsCSSRuleProcessor::SelectorListMatches(this, matchingContext,
|
|
|
|
selectorList);
|
2009-09-30 15:17:14 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return matches;
|
|
|
|
}
|
2010-04-19 08:41:37 -07:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2011-12-18 02:06:23 -08:00
|
|
|
nsGenericElement::MozMatchesSelector(const nsAString& aSelector, bool* aReturn)
|
2010-04-19 08:41:37 -07:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aReturn, "Null out param?");
|
2010-10-21 07:09:00 -07:00
|
|
|
|
|
|
|
nsresult rv;
|
2011-12-18 02:06:23 -08:00
|
|
|
*aReturn = MozMatchesSelector(aSelector, &rv);
|
2010-10-21 07:09:00 -07:00
|
|
|
|
|
|
|
return rv;
|
2010-04-19 08:41:37 -07:00
|
|
|
}
|
2011-08-26 15:39:00 -07:00
|
|
|
|
2012-03-10 08:13:51 -08:00
|
|
|
static const nsAttrValue::EnumTable kCORSAttributeTable[] = {
|
|
|
|
// Order matters here
|
|
|
|
// See ParseCORSValue
|
|
|
|
{ "anonymous", CORS_ANONYMOUS },
|
|
|
|
{ "use-credentials", CORS_USE_CREDENTIALS },
|
|
|
|
{ 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
/* static */ void
|
|
|
|
nsGenericElement::ParseCORSValue(const nsAString& aValue,
|
|
|
|
nsAttrValue& aResult)
|
|
|
|
{
|
|
|
|
DebugOnly<bool> success =
|
|
|
|
aResult.ParseEnumValue(aValue, kCORSAttributeTable, false,
|
|
|
|
// default value is anonymous if aValue is
|
|
|
|
// not a value we understand
|
|
|
|
&kCORSAttributeTable[0]);
|
|
|
|
MOZ_ASSERT(success);
|
|
|
|
}
|
|
|
|
|
2012-03-10 08:13:52 -08:00
|
|
|
/* static */ CORSMode
|
|
|
|
nsGenericElement::StringToCORSMode(const nsAString& aValue)
|
|
|
|
{
|
|
|
|
if (aValue.IsVoid()) {
|
|
|
|
return CORS_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsAttrValue val;
|
|
|
|
nsGenericElement::ParseCORSValue(aValue, val);
|
|
|
|
return CORSMode(val.GetEnumValue());
|
|
|
|
}
|
|
|
|
|
2012-03-10 08:13:52 -08:00
|
|
|
/* static */ CORSMode
|
|
|
|
nsGenericElement::AttrValueToCORSMode(const nsAttrValue* aValue)
|
|
|
|
{
|
|
|
|
if (!aValue) {
|
|
|
|
return CORS_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return CORSMode(aValue->GetEnumValue());
|
|
|
|
}
|
|
|
|
|
2011-12-18 02:06:23 -08:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsGenericElement::GetOnmouseenter(JSContext* cx, JS::Value* vp)
|
|
|
|
{
|
|
|
|
return nsINode::GetOnmouseenter(cx, vp);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsGenericElement::SetOnmouseenter(JSContext* cx, const JS::Value& v)
|
|
|
|
{
|
|
|
|
return nsINode::SetOnmouseenter(cx, v);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsGenericElement::GetOnmouseleave(JSContext* cx, JS::Value* vp)
|
|
|
|
{
|
|
|
|
return nsINode::GetOnmouseleave(cx, vp);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsGenericElement::SetOnmouseleave(JSContext* cx, const JS::Value& v)
|
|
|
|
{
|
|
|
|
return nsINode::SetOnmouseleave(cx, v);
|
|
|
|
}
|
|
|
|
|
2012-04-11 14:55:21 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsGenericElement::MozRequestPointerLock()
|
|
|
|
{
|
|
|
|
OwnerDoc()->RequestPointerLock(this);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-05-08 14:47:18 -07:00
|
|
|
static const char*
|
|
|
|
GetFullScreenError(nsIDocument* aDoc)
|
|
|
|
{
|
2012-06-28 01:54:37 -07:00
|
|
|
nsCOMPtr<nsPIDOMWindow> win = aDoc->GetWindow();
|
2012-08-13 09:58:38 -07:00
|
|
|
if (aDoc->NodePrincipal()->GetAppStatus() >= nsIPrincipal::APP_STATUS_INSTALLED) {
|
2012-07-30 19:09:31 -07:00
|
|
|
// Request is in a web app and in the same origin as the web app.
|
|
|
|
// Don't enforce as strict security checks for web apps, the user
|
|
|
|
// is supposed to have trust in them. However documents cross-origin
|
|
|
|
// to the web app must still confirm to the normal security checks.
|
2012-07-30 07:20:58 -07:00
|
|
|
return nullptr;
|
2012-06-28 01:54:37 -07:00
|
|
|
}
|
|
|
|
|
2012-05-08 14:47:18 -07:00
|
|
|
if (!nsContentUtils::IsRequestFullScreenAllowed()) {
|
|
|
|
return "FullScreenDeniedNotInputDriven";
|
|
|
|
}
|
2012-07-30 19:09:31 -07:00
|
|
|
|
2012-05-08 14:47:18 -07:00
|
|
|
if (nsContentUtils::IsSitePermDeny(aDoc->NodePrincipal(), "fullscreen")) {
|
|
|
|
return "FullScreenDeniedBlocked";
|
|
|
|
}
|
|
|
|
|
2012-07-30 07:20:58 -07:00
|
|
|
return nullptr;
|
2012-05-08 14:47:18 -07:00
|
|
|
}
|
|
|
|
|
2012-03-28 22:37:46 -07:00
|
|
|
nsresult nsGenericElement::MozRequestFullScreen()
|
2012-03-23 21:37:04 -07:00
|
|
|
{
|
|
|
|
// Only grant full-screen requests if this is called from inside a trusted
|
|
|
|
// event handler (i.e. inside an event handler for a user initiated event).
|
|
|
|
// This stops the full-screen from being abused similar to the popups of old,
|
|
|
|
// and it also makes it harder for bad guys' script to go full-screen and
|
|
|
|
// spoof the browser chrome/window and phish logins etc.
|
2012-07-30 19:09:31 -07:00
|
|
|
// Note that requests for fullscreen inside a web app's origin are exempt
|
|
|
|
// from this restriction.
|
2012-05-08 14:47:18 -07:00
|
|
|
const char* error = GetFullScreenError(OwnerDoc());
|
|
|
|
if (error) {
|
2012-03-23 21:37:04 -07:00
|
|
|
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
|
|
|
"DOM", OwnerDoc(),
|
|
|
|
nsContentUtils::eDOM_PROPERTIES,
|
2012-05-08 14:47:18 -07:00
|
|
|
error);
|
2012-03-23 21:37:04 -07:00
|
|
|
nsRefPtr<nsAsyncDOMEvent> e =
|
|
|
|
new nsAsyncDOMEvent(OwnerDoc(),
|
|
|
|
NS_LITERAL_STRING("mozfullscreenerror"),
|
|
|
|
true,
|
|
|
|
false);
|
|
|
|
e->PostDOMEvent();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
OwnerDoc()->AsyncRequestFullScreen(this);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|