LCOV - code coverage report
Current view: directory - content/html/content/src - nsGenericHTMLElement.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 1471 142 9.7 %
Date: 2012-06-02 Functions: 172 28 16.3 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* vim:set tw=80 expandtab softtabstop=2 ts=2 sw=2: */
       3                 : /* ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is Mozilla Communicator client code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Netscape Communications Corporation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Mats Palmgren <matspal@gmail.com>
      25                 :  *   Ms2ger <ms2ger@gmail.com>
      26                 :  *
      27                 :  * Alternatively, the contents of this file may be used under the terms of
      28                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      29                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      31                 :  * of those above. If you wish to allow use of your version of this file only
      32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      33                 :  * use your version of this file under the terms of the MPL, indicate your
      34                 :  * decision by deleting the provisions above and replace them with the notice
      35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      36                 :  * the provisions above, a recipient may use your version of this file under
      37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      38                 :  *
      39                 :  * ***** END LICENSE BLOCK ***** */
      40                 : 
      41                 : #include "mozilla/Util.h"
      42                 : 
      43                 : #include "nscore.h"
      44                 : #include "nsGenericHTMLElement.h"
      45                 : #include "nsCOMPtr.h"
      46                 : #include "nsIAtom.h"
      47                 : #include "nsIContentViewer.h"
      48                 : #include "mozilla/css/StyleRule.h"
      49                 : #include "nsIDocument.h"
      50                 : #include "nsIDocumentEncoder.h"
      51                 : #include "nsIDOMHTMLBodyElement.h"
      52                 : #include "nsIDOMHTMLDocument.h"
      53                 : #include "nsIDOMAttr.h"
      54                 : #include "nsIDOMDocumentFragment.h"
      55                 : #include "nsIDOMHTMLElement.h"
      56                 : #include "nsIDOMHTMLMenuElement.h"
      57                 : #include "nsIDOMElementCSSInlineStyle.h"
      58                 : #include "nsIDOMWindow.h"
      59                 : #include "nsIDOMDocument.h"
      60                 : #include "nsEventListenerManager.h"
      61                 : #include "nsMappedAttributes.h"
      62                 : #include "nsHTMLStyleSheet.h"
      63                 : #include "nsIHTMLDocument.h"
      64                 : #include "nsILink.h"
      65                 : #include "nsPIDOMWindow.h"
      66                 : #include "nsIStyleRule.h"
      67                 : #include "nsIURL.h"
      68                 : #include "nsNetUtil.h"
      69                 : #include "nsEscape.h"
      70                 : #include "nsIFrame.h"
      71                 : #include "nsIScrollableFrame.h"
      72                 : #include "nsIView.h"
      73                 : #include "nsIViewManager.h"
      74                 : #include "nsIWidget.h"
      75                 : #include "nsRange.h"
      76                 : #include "nsIPresShell.h"
      77                 : #include "nsPresContext.h"
      78                 : #include "nsIDocShell.h"
      79                 : #include "nsIDocShellTreeItem.h"
      80                 : #include "nsINameSpaceManager.h"
      81                 : #include "nsDOMError.h"
      82                 : #include "nsScriptLoader.h"
      83                 : #include "nsRuleData.h"
      84                 : 
      85                 : #include "nsPresState.h"
      86                 : #include "nsILayoutHistoryState.h"
      87                 : 
      88                 : #include "nsHTMLParts.h"
      89                 : #include "nsContentUtils.h"
      90                 : #include "nsString.h"
      91                 : #include "nsUnicharUtils.h"
      92                 : #include "nsGkAtoms.h"
      93                 : #include "nsEventStateManager.h"
      94                 : #include "nsIDOMEvent.h"
      95                 : #include "nsIDOMNSEvent.h"
      96                 : #include "nsDOMCSSDeclaration.h"
      97                 : #include "nsITextControlFrame.h"
      98                 : #include "nsIForm.h"
      99                 : #include "nsIFormControl.h"
     100                 : #include "nsIDOMHTMLFormElement.h"
     101                 : #include "nsHTMLFormElement.h"
     102                 : #include "nsFocusManager.h"
     103                 : 
     104                 : #include "nsMutationEvent.h"
     105                 : 
     106                 : #include "nsContentCID.h"
     107                 : 
     108                 : #include "nsDOMStringMap.h"
     109                 : 
     110                 : #include "nsIEditor.h"
     111                 : #include "nsIEditorIMESupport.h"
     112                 : #include "nsEventDispatcher.h"
     113                 : #include "nsLayoutUtils.h"
     114                 : #include "nsContentCreatorFunctions.h"
     115                 : #include "mozAutoDocUpdate.h"
     116                 : #include "nsHtml5Module.h"
     117                 : #include "nsITextControlElement.h"
     118                 : #include "mozilla/dom/Element.h"
     119                 : #include "nsHTMLFieldSetElement.h"
     120                 : #include "nsHTMLMenuElement.h"
     121                 : #include "nsAsyncDOMEvent.h"
     122                 : #include "nsIScriptError.h"
     123                 : 
     124                 : #include "mozilla/Preferences.h"
     125                 : #include "mozilla/dom/FromParser.h"
     126                 : 
     127                 : using namespace mozilla;
     128                 : using namespace mozilla::dom;
     129                 : 
     130                 : #include "nsThreadUtils.h"
     131                 : 
     132                 : class nsINodeInfo;
     133                 : class nsIDOMNodeList;
     134                 : class nsRuleWalker;
     135                 : 
     136                 : // XXX todo: add in missing out-of-memory checks
     137                 : 
     138                 : //----------------------------------------------------------------------
     139                 : 
     140                 : #ifdef GATHER_ELEMENT_USEAGE_STATISTICS
     141                 : 
     142                 : // static objects that have constructors are kinda bad, but we don't
     143                 : // care here, this is only debugging code!
     144                 : 
     145                 : static nsHashtable sGEUS_ElementCounts;
     146                 : 
     147                 : void GEUS_ElementCreated(nsINodeInfo *aNodeInfo)
     148                 : {
     149                 :   nsAutoString name;
     150                 :   aNodeInfo->GetName(name);
     151                 : 
     152                 :   nsStringKey key(name);
     153                 : 
     154                 :   PRInt32 count = (PRInt32)sGEUS_ElementCounts.Get(&key);
     155                 : 
     156                 :   count++;
     157                 : 
     158                 :   sGEUS_ElementCounts.Put(&key, (void *)count);
     159                 : }
     160                 : 
     161                 : bool GEUS_enum_func(nsHashKey *aKey, void *aData, void *aClosure)
     162                 : {
     163                 :   const PRUnichar *name_chars = ((nsStringKey *)aKey)->GetString();
     164                 :   NS_ConvertUTF16toUTF8 name(name_chars);
     165                 : 
     166                 :   printf ("%s %d\n", name.get(), aData);
     167                 : 
     168                 :   return true;
     169                 : }
     170                 : 
     171                 : void GEUS_DumpElementCounts()
     172                 : {
     173                 :   printf ("Element count statistics:\n");
     174                 : 
     175                 :   sGEUS_ElementCounts.Enumerate(GEUS_enum_func, nsnull);
     176                 : 
     177                 :   printf ("End of element count statistics:\n");
     178                 : }
     179                 : 
     180                 : nsresult
     181                 : nsGenericHTMLElement::Init(nsINodeInfo *aNodeInfo)
     182                 : {
     183                 :   GEUS_ElementCreated(aNodeInfo);
     184                 : 
     185                 :   return nsGenericHTMLElementBase::Init(aNodeInfo);
     186                 : }
     187                 : 
     188                 : #endif
     189                 : 
     190                 : /**
     191                 :  * nsAutoFocusEvent is used to dispatch a focus event when a
     192                 :  * nsGenericHTMLFormElement is binded to the tree with the autofocus attribute
     193                 :  * enabled.
     194                 :  */
     195                 : class nsAutoFocusEvent : public nsRunnable
     196               0 : {
     197                 : public:
     198               0 :   nsAutoFocusEvent(nsGenericHTMLFormElement* aElement) : mElement(aElement) {}
     199                 : 
     200               0 :   NS_IMETHOD Run() {
     201               0 :     nsFocusManager* fm = nsFocusManager::GetFocusManager();
     202               0 :     if (!fm) {
     203               0 :       return NS_ERROR_NULL_POINTER;
     204                 :     }
     205                 : 
     206               0 :     nsIDocument* document = mElement->OwnerDoc();
     207                 : 
     208               0 :     nsPIDOMWindow* window = document->GetWindow();
     209               0 :     if (!window) {
     210               0 :       return NS_OK;
     211                 :     }
     212                 : 
     213                 :     // Trying to found the top window (equivalent to window.top).
     214               0 :     nsCOMPtr<nsIDOMWindow> top;
     215               0 :     window->GetTop(getter_AddRefs(top));
     216               0 :     if (top) {
     217               0 :       window = static_cast<nsPIDOMWindow*>(top.get());
     218                 :     }
     219                 : 
     220               0 :     if (window->GetFocusedNode()) {
     221               0 :       return NS_OK;
     222                 :     }
     223                 : 
     224               0 :     nsCOMPtr<nsIDocument> topDoc = do_QueryInterface(window->GetExtantDocument());
     225               0 :     if (topDoc && topDoc->GetReadyStateEnum() == nsIDocument::READYSTATE_COMPLETE) {
     226               0 :       return NS_OK;
     227                 :     }
     228                 : 
     229                 :     // If something is focused in the same document, ignore autofocus.
     230               0 :     if (!fm->GetFocusedContent() ||
     231               0 :         fm->GetFocusedContent()->OwnerDoc() != document) {
     232               0 :       return mElement->Focus();
     233                 :     }
     234                 : 
     235               0 :     return NS_OK;
     236                 :   }
     237                 : private:
     238                 :   // NOTE: nsGenericHTMLFormElement is saved as a nsGenericHTMLElement
     239                 :   // because AddRef/Release are ambiguous with nsGenericHTMLFormElement
     240                 :   // and Focus() is declared (and defined) in nsGenericHTMLElement class.
     241                 :   nsRefPtr<nsGenericHTMLElement> mElement;
     242                 : };
     243                 : 
     244                 : class nsGenericHTMLElementTearoff : public nsIDOMElementCSSInlineStyle
     245                 : {
     246               0 :   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     247                 : 
     248               0 :   nsGenericHTMLElementTearoff(nsGenericHTMLElement *aElement)
     249               0 :     : mElement(aElement)
     250                 :   {
     251               0 :   }
     252                 : 
     253               0 :   virtual ~nsGenericHTMLElementTearoff()
     254               0 :   {
     255               0 :   }
     256                 : 
     257               0 :   NS_IMETHOD GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
     258                 :   {
     259                 :     nsresult rv;
     260               0 :     *aStyle = mElement->GetStyle(&rv);
     261               0 :     NS_ENSURE_SUCCESS(rv, rv);
     262               0 :     NS_ADDREF(*aStyle);
     263               0 :     return NS_OK;
     264                 :   }
     265                 : 
     266            1464 :   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsGenericHTMLElementTearoff,
     267                 :                                            nsIDOMElementCSSInlineStyle)
     268                 : 
     269                 : private:
     270                 :   nsRefPtr<nsGenericHTMLElement> mElement;
     271                 : };
     272                 : 
     273            1464 : NS_IMPL_CYCLE_COLLECTION_1(nsGenericHTMLElementTearoff, mElement)
     274                 : 
     275               0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsGenericHTMLElementTearoff)
     276               0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsGenericHTMLElementTearoff)
     277                 : 
     278               0 : NS_INTERFACE_TABLE_HEAD(nsGenericHTMLElementTearoff)
     279               0 :   NS_INTERFACE_TABLE_INHERITED1(nsGenericHTMLElementTearoff,
     280                 :                                 nsIDOMElementCSSInlineStyle)
     281               0 :   NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsGenericHTMLElementTearoff)
     282               0 : NS_INTERFACE_MAP_END_AGGREGATED(mElement)
     283                 : 
     284                 : 
     285               0 : NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsGenericHTMLElement, TabIndex, tabindex, -1)
     286               0 : NS_IMPL_BOOL_ATTR(nsGenericHTMLElement, Hidden, hidden)
     287                 : 
     288                 : nsresult
     289             548 : nsGenericHTMLElement::DOMQueryInterface(nsIDOMHTMLElement *aElement,
     290                 :                                         REFNSIID aIID, void **aInstancePtr)
     291                 : {
     292             548 :   NS_PRECONDITION(aInstancePtr, "null out param");
     293                 : 
     294             548 :   nsresult rv = NS_ERROR_FAILURE;
     295                 : 
     296                 :   NS_INTERFACE_TABLE_BEGIN
     297                 :     NS_INTERFACE_TABLE_ENTRY(nsIDOMHTMLElement, nsIDOMNode)
     298                 :     NS_INTERFACE_TABLE_ENTRY(nsIDOMHTMLElement, nsIDOMElement)
     299                 :     NS_INTERFACE_TABLE_ENTRY(nsIDOMHTMLElement, nsIDOMHTMLElement)
     300             548 :   NS_INTERFACE_TABLE_END_WITH_PTR(aElement)
     301                 : 
     302             548 :   NS_INTERFACE_TABLE_TO_MAP_SEGUE
     303             470 :   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMElementCSSInlineStyle,
     304                 :                                  new nsGenericHTMLElementTearoff(this))
     305             470 :   NS_INTERFACE_MAP_END
     306                 : 
     307                 : // No closing bracket, because NS_INTERFACE_MAP_END does that for us.
     308                 : 
     309                 : nsresult
     310               0 : nsGenericHTMLElement::CopyInnerTo(nsGenericElement* aDst) const
     311                 : {
     312                 :   nsresult rv;
     313               0 :   PRInt32 i, count = GetAttrCount();
     314               0 :   for (i = 0; i < count; ++i) {
     315               0 :     const nsAttrName *name = mAttrsAndChildren.AttrNameAt(i);
     316               0 :     const nsAttrValue *value = mAttrsAndChildren.AttrAt(i);
     317               0 :     if (name->Equals(nsGkAtoms::style, kNameSpaceID_None) &&
     318               0 :         value->Type() == nsAttrValue::eCSSStyleRule) {
     319                 :       // We can't just set this as a string, because that will fail
     320                 :       // to reparse the string into style data until the node is
     321                 :       // inserted into the document.  Clone the Rule instead.
     322               0 :       nsRefPtr<mozilla::css::Rule> ruleClone = value->GetCSSStyleRuleValue()->Clone();
     323               0 :       nsRefPtr<mozilla::css::StyleRule> styleRule = do_QueryObject(ruleClone);
     324               0 :       NS_ENSURE_TRUE(styleRule, NS_ERROR_UNEXPECTED);
     325                 : 
     326               0 :       rv = aDst->SetInlineStyleRule(styleRule, false);
     327               0 :       NS_ENSURE_SUCCESS(rv, rv);
     328                 : 
     329               0 :       continue;
     330                 :     }
     331                 : 
     332               0 :     nsAutoString valStr;
     333               0 :     value->ToString(valStr);
     334                 :     rv = aDst->SetAttr(name->NamespaceID(), name->LocalName(),
     335               0 :                        name->GetPrefix(), valStr, false);
     336               0 :     NS_ENSURE_SUCCESS(rv, rv);
     337                 :   }
     338                 : 
     339               0 :   return NS_OK;
     340                 : }
     341                 : 
     342                 : NS_IMETHODIMP
     343               0 : nsGenericHTMLElement::SetAttribute(const nsAString& aName,
     344                 :                                    const nsAString& aValue)
     345                 : {
     346               0 :   const nsAttrName* name = InternalGetExistingAttrNameFromQName(aName);
     347                 : 
     348               0 :   if (!name) {
     349               0 :     nsresult rv = nsContentUtils::CheckQName(aName, false);
     350               0 :     NS_ENSURE_SUCCESS(rv, rv);
     351                 : 
     352               0 :     nsCOMPtr<nsIAtom> nameAtom;
     353               0 :     if (IsInHTMLDocument()) {
     354               0 :       nsAutoString lower;
     355               0 :       rv = nsContentUtils::ASCIIToLower(aName, lower);
     356               0 :       if (NS_SUCCEEDED(rv)) {
     357               0 :         nameAtom = do_GetAtom(lower);
     358                 :       }
     359                 :     }
     360                 :     else {
     361               0 :       nameAtom = do_GetAtom(aName);
     362                 :     }
     363               0 :     NS_ENSURE_TRUE(nameAtom, NS_ERROR_OUT_OF_MEMORY);
     364                 : 
     365               0 :     return SetAttr(kNameSpaceID_None, nameAtom, aValue, true);
     366                 :   }
     367                 : 
     368                 :   return SetAttr(name->NamespaceID(), name->LocalName(), name->GetPrefix(),
     369               0 :                  aValue, true);
     370                 : }
     371                 : 
     372                 : nsresult
     373               0 : nsGenericHTMLElement::GetDataset(nsIDOMDOMStringMap** aDataset)
     374                 : {
     375               0 :   nsDOMSlots *slots = DOMSlots();
     376                 : 
     377               0 :   if (!slots->mDataset) {
     378                 :     // mDataset is a weak reference so assignment will not AddRef.
     379                 :     // AddRef is called before assigning to out parameter.
     380               0 :     slots->mDataset = new nsDOMStringMap(this);
     381                 :   }
     382                 : 
     383               0 :   NS_ADDREF(*aDataset = slots->mDataset);
     384               0 :   return NS_OK;
     385                 : }
     386                 : 
     387                 : nsresult
     388               0 : nsGenericHTMLElement::ClearDataset()
     389                 : {
     390               0 :   nsDOMSlots *slots = GetExistingDOMSlots();
     391                 : 
     392               0 :   NS_ASSERTION(slots && slots->mDataset,
     393                 :                "Slots should exist and dataset should not be null.");
     394               0 :   slots->mDataset = nsnull;
     395                 : 
     396               0 :   return NS_OK;
     397                 : }
     398                 : 
     399                 : // Implementation for nsIDOMHTMLElement
     400                 : nsresult
     401               0 : nsGenericHTMLElement::GetId(nsAString& aId)
     402                 : {
     403               0 :   GetAttr(kNameSpaceID_None, nsGkAtoms::id, aId);
     404               0 :   return NS_OK;
     405                 : }
     406                 : 
     407                 : nsresult
     408               0 : nsGenericHTMLElement::SetId(const nsAString& aId)
     409                 : {
     410               0 :   SetAttr(kNameSpaceID_None, nsGkAtoms::id, aId, true);
     411               0 :   return NS_OK;
     412                 : }
     413                 : 
     414                 : nsresult
     415               0 : nsGenericHTMLElement::GetTitle(nsAString& aTitle)
     416                 : {
     417               0 :   GetAttr(kNameSpaceID_None, nsGkAtoms::title, aTitle);
     418               0 :   return NS_OK;
     419                 : }
     420                 : 
     421                 : nsresult
     422               0 : nsGenericHTMLElement::SetTitle(const nsAString& aTitle)
     423                 : {
     424               0 :   SetAttr(kNameSpaceID_None, nsGkAtoms::title, aTitle, true);
     425               0 :   return NS_OK;
     426                 : }
     427                 : 
     428                 : nsresult
     429               0 : nsGenericHTMLElement::GetLang(nsAString& aLang)
     430                 : {
     431               0 :   GetAttr(kNameSpaceID_None, nsGkAtoms::lang, aLang);
     432               0 :   return NS_OK;
     433                 : }
     434                 : 
     435                 : nsresult
     436               0 : nsGenericHTMLElement::SetLang(const nsAString& aLang)
     437                 : {
     438               0 :   SetAttr(kNameSpaceID_None, nsGkAtoms::lang, aLang, true);
     439               0 :   return NS_OK;
     440                 : }
     441                 : 
     442                 : static const nsAttrValue::EnumTable kDirTable[] = {
     443                 :   { "ltr", NS_STYLE_DIRECTION_LTR },
     444                 :   { "rtl", NS_STYLE_DIRECTION_RTL },
     445                 :   { 0 }
     446                 : };
     447                 : 
     448               0 : NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsGenericHTMLElement, Dir, dir, NULL)
     449                 : 
     450                 : nsresult
     451               0 : nsGenericHTMLElement::GetClassName(nsAString& aClassName)
     452                 : {
     453               0 :   GetAttr(kNameSpaceID_None, nsGkAtoms::_class, aClassName);
     454               0 :   return NS_OK;
     455                 : }
     456                 : 
     457                 : nsresult
     458               0 : nsGenericHTMLElement::SetClassName(const nsAString& aClassName)
     459                 : {
     460               0 :   SetAttr(kNameSpaceID_None, nsGkAtoms::_class, aClassName, true);
     461               0 :   return NS_OK;
     462                 : }
     463                 : 
     464               0 : NS_IMPL_STRING_ATTR(nsGenericHTMLElement, AccessKey, accesskey)
     465                 : 
     466                 : NS_IMETHODIMP
     467               0 : nsGenericHTMLElement::GetAccessKeyLabel(nsAString& aLabel)
     468                 : {
     469               0 :   nsPresContext *presContext = GetPresContext();
     470                 : 
     471               0 :   if (presContext &&
     472               0 :     presContext->EventStateManager()->GetAccessKeyLabelPrefix(aLabel)) {
     473               0 :       nsAutoString suffix;
     474               0 :       GetAccessKey(suffix);
     475               0 :       aLabel.Append(suffix);
     476                 :   }
     477                 : 
     478               0 :   return NS_OK;
     479                 : }
     480                 : 
     481               0 : static bool IS_TABLE_CELL(nsIAtom* frameType) {
     482                 :   return nsGkAtoms::tableCellFrame == frameType ||
     483               0 :     nsGkAtoms::bcTableCellFrame == frameType;
     484                 : }
     485                 : 
     486                 : static bool
     487               0 : IsOffsetParent(nsIFrame* aFrame)
     488                 : {
     489               0 :   nsIAtom* frameType = aFrame->GetType();
     490               0 :   return (IS_TABLE_CELL(frameType) ||
     491               0 :           frameType == nsGkAtoms::tableFrame);
     492                 : }
     493                 : 
     494                 : void
     495               0 : nsGenericHTMLElement::GetOffsetRect(nsRect& aRect, nsIContent** aOffsetParent)
     496                 : {
     497               0 :   *aOffsetParent = nsnull;
     498               0 :   aRect = nsRect();
     499                 : 
     500               0 :   nsIFrame* frame = GetStyledFrame();
     501               0 :   if (!frame) {
     502               0 :     return;
     503                 :   }
     504                 : 
     505               0 :   nsIFrame* parent = frame->GetParent();
     506               0 :   nsPoint origin(0, 0);
     507                 : 
     508               0 :   if (parent && parent->GetType() == nsGkAtoms::tableOuterFrame &&
     509               0 :       frame->GetType() == nsGkAtoms::tableFrame) {
     510               0 :     origin = parent->GetPositionIgnoringScrolling();
     511               0 :     parent = parent->GetParent();
     512                 :   }
     513                 : 
     514               0 :   Element* docElement = GetCurrentDoc()->GetRootElement();
     515               0 :   nsIContent* content = frame->GetContent();
     516                 : 
     517               0 :   if (content && (content->IsHTML(nsGkAtoms::body) || content == docElement)) {
     518               0 :     parent = frame;
     519                 :   }
     520                 :   else {
     521               0 :     const bool isPositioned = frame->GetStyleDisplay()->IsPositioned();
     522                 :     const bool isAbsolutelyPositioned =
     523               0 :       frame->GetStyleDisplay()->IsAbsolutelyPositioned();
     524               0 :     origin += frame->GetPositionIgnoringScrolling();
     525                 : 
     526               0 :     for ( ; parent ; parent = parent->GetParent()) {
     527               0 :       content = parent->GetContent();
     528                 : 
     529                 :       // Stop at the first ancestor that is positioned.
     530               0 :       if (parent->GetStyleDisplay()->IsPositioned()) {
     531               0 :         *aOffsetParent = content;
     532               0 :         NS_IF_ADDREF(*aOffsetParent);
     533               0 :         break;
     534                 :       }
     535                 : 
     536                 :       // Add the parent's origin to our own to get to the
     537                 :       // right coordinate system.
     538               0 :       const bool isOffsetParent = !isPositioned && IsOffsetParent(parent);
     539               0 :       if (!isAbsolutelyPositioned && !isOffsetParent) {
     540               0 :         origin += parent->GetPositionIgnoringScrolling();
     541                 :       }
     542                 : 
     543               0 :       if (content) {
     544                 :         // If we've hit the document element, break here.
     545               0 :         if (content == docElement) {
     546               0 :           break;
     547                 :         }
     548                 : 
     549                 :         // Break if the ancestor frame type makes it suitable as offset parent
     550                 :         // and this element is *not* positioned or if we found the body element.
     551               0 :         if (isOffsetParent || content->IsHTML(nsGkAtoms::body)) {
     552               0 :           *aOffsetParent = content;
     553               0 :           NS_ADDREF(*aOffsetParent);
     554               0 :           break;
     555                 :         }
     556                 :       }
     557                 :     }
     558                 : 
     559               0 :     if (isAbsolutelyPositioned && !*aOffsetParent) {
     560                 :       // If this element is absolutely positioned, but we don't have
     561                 :       // an offset parent it means this element is an absolutely
     562                 :       // positioned child that's not nested inside another positioned
     563                 :       // element, in this case the element's frame's parent is the
     564                 :       // frame for the HTML element so we fail to find the body in the
     565                 :       // parent chain. We want the offset parent in this case to be
     566                 :       // the body, so we just get the body element from the document.
     567                 : 
     568               0 :       nsCOMPtr<nsIDOMHTMLDocument> html_doc(do_QueryInterface(GetCurrentDoc()));
     569                 : 
     570               0 :       if (html_doc) {
     571               0 :         nsCOMPtr<nsIDOMHTMLElement> html_element;
     572               0 :         html_doc->GetBody(getter_AddRefs(html_element));
     573               0 :         if (html_element) {
     574               0 :           CallQueryInterface(html_element, aOffsetParent);
     575                 :         }
     576                 :       }
     577                 :     }
     578                 :   }
     579                 : 
     580                 :   // Subtract the parent border unless it uses border-box sizing.
     581               0 :   if (parent &&
     582               0 :       parent->GetStylePosition()->mBoxSizing != NS_STYLE_BOX_SIZING_BORDER) {
     583               0 :     const nsStyleBorder* border = parent->GetStyleBorder();
     584               0 :     origin.x -= border->GetActualBorderWidth(NS_SIDE_LEFT);
     585               0 :     origin.y -= border->GetActualBorderWidth(NS_SIDE_TOP);
     586                 :   }
     587                 : 
     588                 :   // XXX We should really consider subtracting out padding for
     589                 :   // content-box sizing, but we should see what IE does....
     590                 : 
     591                 :   // Convert to pixels.
     592               0 :   aRect.x = nsPresContext::AppUnitsToIntCSSPixels(origin.x);
     593               0 :   aRect.y = nsPresContext::AppUnitsToIntCSSPixels(origin.y);
     594                 : 
     595                 :   // Get the union of all rectangles in this and continuation frames.
     596                 :   // It doesn't really matter what we use as aRelativeTo here, since
     597                 :   // we only care about the size. We just have to use something non-null.
     598               0 :   nsRect rcFrame = nsLayoutUtils::GetAllInFlowRectsUnion(frame, frame);
     599               0 :   aRect.width = nsPresContext::AppUnitsToIntCSSPixels(rcFrame.width);
     600               0 :   aRect.height = nsPresContext::AppUnitsToIntCSSPixels(rcFrame.height);
     601                 : }
     602                 : 
     603                 : nsresult
     604               0 : nsGenericHTMLElement::GetOffsetTop(PRInt32* aOffsetTop)
     605                 : {
     606               0 :   nsRect rcFrame;
     607               0 :   nsCOMPtr<nsIContent> parent;
     608               0 :   GetOffsetRect(rcFrame, getter_AddRefs(parent));
     609                 : 
     610               0 :   *aOffsetTop = rcFrame.y;
     611                 : 
     612               0 :   return NS_OK;
     613                 : }
     614                 : 
     615                 : nsresult
     616               0 : nsGenericHTMLElement::GetOffsetLeft(PRInt32* aOffsetLeft)
     617                 : {
     618               0 :   nsRect rcFrame;
     619               0 :   nsCOMPtr<nsIContent> parent;
     620               0 :   GetOffsetRect(rcFrame, getter_AddRefs(parent));
     621                 : 
     622               0 :   *aOffsetLeft = rcFrame.x;
     623                 : 
     624               0 :   return NS_OK;
     625                 : }
     626                 : 
     627                 : nsresult
     628               0 : nsGenericHTMLElement::GetOffsetWidth(PRInt32* aOffsetWidth)
     629                 : {
     630               0 :   nsRect rcFrame;
     631               0 :   nsCOMPtr<nsIContent> parent;
     632               0 :   GetOffsetRect(rcFrame, getter_AddRefs(parent));
     633                 : 
     634               0 :   *aOffsetWidth = rcFrame.width;
     635                 : 
     636               0 :   return NS_OK;
     637                 : }
     638                 : 
     639                 : nsresult
     640               0 : nsGenericHTMLElement::GetOffsetHeight(PRInt32* aOffsetHeight)
     641                 : {
     642               0 :   nsRect rcFrame;
     643               0 :   nsCOMPtr<nsIContent> parent;
     644               0 :   GetOffsetRect(rcFrame, getter_AddRefs(parent));
     645                 : 
     646               0 :   *aOffsetHeight = rcFrame.height;
     647                 : 
     648               0 :   return NS_OK;
     649                 : }
     650                 : 
     651                 : nsresult
     652               0 : nsGenericHTMLElement::GetOffsetParent(nsIDOMElement** aOffsetParent)
     653                 : {
     654               0 :   nsRect rcFrame;
     655               0 :   nsCOMPtr<nsIContent> parent;
     656               0 :   GetOffsetRect(rcFrame, getter_AddRefs(parent));
     657                 : 
     658               0 :   if (parent) {
     659               0 :     CallQueryInterface(parent, aOffsetParent);
     660                 :   } else {
     661               0 :     *aOffsetParent = nsnull;
     662                 :   }
     663                 : 
     664               0 :   return NS_OK;
     665                 : }
     666                 : 
     667                 : nsresult
     668               0 : nsGenericHTMLElement::GetMarkup(bool aIncludeSelf, nsAString& aMarkup)
     669                 : {
     670               0 :   aMarkup.Truncate();
     671                 : 
     672               0 :   nsIDocument* doc = OwnerDoc();
     673                 : 
     674               0 :   nsAutoString contentType;
     675               0 :   if (IsInHTMLDocument()) {
     676               0 :     contentType.AssignLiteral("text/html");
     677                 :   } else {
     678               0 :     doc->GetContentType(contentType);
     679                 :   }
     680                 : 
     681               0 :   nsCOMPtr<nsIDocumentEncoder> docEncoder = doc->GetCachedEncoder();
     682               0 :   if (!docEncoder) {
     683                 :     docEncoder =
     684                 :       do_CreateInstance(PromiseFlatCString(
     685               0 :         nsDependentCString(NS_DOC_ENCODER_CONTRACTID_BASE) +
     686               0 :         NS_ConvertUTF16toUTF8(contentType)
     687               0 :       ).get());
     688                 :   }
     689               0 :   if (!(docEncoder || doc->IsHTML())) {
     690                 :     // This could be some type for which we create a synthetic document.  Try
     691                 :     // again as XML
     692               0 :     contentType.AssignLiteral("application/xml");
     693               0 :     docEncoder = do_CreateInstance(NS_DOC_ENCODER_CONTRACTID_BASE "application/xml");
     694                 :   }
     695                 : 
     696               0 :   NS_ENSURE_TRUE(docEncoder, NS_ERROR_FAILURE);
     697                 : 
     698               0 :   nsresult rv = docEncoder->NativeInit(doc, contentType,
     699                 :                                        nsIDocumentEncoder::OutputEncodeBasicEntities |
     700                 :                                        // Output DOM-standard newlines
     701                 :                                        nsIDocumentEncoder::OutputLFLineBreak |
     702                 :                                        // Don't do linebreaking that's not present in
     703                 :                                        // the source
     704               0 :                                        nsIDocumentEncoder::OutputRaw);
     705               0 :   NS_ENSURE_SUCCESS(rv, rv);
     706                 : 
     707               0 :   if (aIncludeSelf) {
     708               0 :     docEncoder->SetNativeNode(this);
     709                 :   } else {
     710               0 :     docEncoder->SetNativeContainerNode(this);
     711                 :   }
     712               0 :   rv = docEncoder->EncodeToString(aMarkup);
     713               0 :   if (!aIncludeSelf) {
     714               0 :     doc->SetCachedEncoder(docEncoder.forget());
     715                 :   }
     716               0 :   return rv;
     717                 : }
     718                 : 
     719                 : nsresult
     720               0 : nsGenericHTMLElement::GetInnerHTML(nsAString& aInnerHTML) {
     721               0 :   return GetMarkup(false, aInnerHTML);
     722                 : }
     723                 : 
     724                 : NS_IMETHODIMP
     725               0 : nsGenericHTMLElement::GetOuterHTML(nsAString& aOuterHTML) {
     726               0 :   return GetMarkup(true, aOuterHTML);
     727                 : }
     728                 : 
     729                 : void
     730               0 : nsGenericHTMLElement::FireMutationEventsForDirectParsing(nsIDocument* aDoc,
     731                 :                                                          nsIContent* aDest,
     732                 :                                                          PRInt32 aOldChildCount)
     733                 : {
     734                 :   // Fire mutation events. Optimize for the case when there are no listeners
     735               0 :   PRInt32 newChildCount = aDest->GetChildCount();
     736               0 :   if (newChildCount && nsContentUtils::
     737               0 :         HasMutationListeners(aDoc, NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
     738               0 :     nsAutoTArray<nsCOMPtr<nsIContent>, 50> childNodes;
     739               0 :     NS_ASSERTION(newChildCount - aOldChildCount >= 0,
     740                 :                  "What, some unexpected dom mutation has happened?");
     741               0 :     childNodes.SetCapacity(newChildCount - aOldChildCount);
     742               0 :     for (nsIContent* child = aDest->GetFirstChild();
     743                 :          child;
     744               0 :          child = child->GetNextSibling()) {
     745               0 :       childNodes.AppendElement(child);
     746                 :     }
     747               0 :     nsGenericElement::FireNodeInserted(aDoc, aDest, childNodes);
     748                 :   }
     749               0 : }
     750                 : 
     751                 : NS_IMETHODIMP
     752               0 : nsGenericHTMLElement::SetInnerHTML(const nsAString& aInnerHTML)
     753                 : {
     754               0 :   nsIDocument* doc = OwnerDoc();
     755                 : 
     756                 :   // Batch possible DOMSubtreeModified events.
     757               0 :   mozAutoSubtreeModified subtree(doc, nsnull);
     758                 : 
     759               0 :   FireNodeRemovedForChildren();
     760                 : 
     761                 :   // Needed when innerHTML is used in combination with contenteditable
     762               0 :   mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, true);
     763                 : 
     764                 :   // Remove childnodes.
     765               0 :   PRUint32 childCount = GetChildCount();
     766               0 :   for (PRUint32 i = 0; i < childCount; ++i) {
     767               0 :     RemoveChildAt(0, true);
     768                 :   }
     769                 : 
     770               0 :   nsAutoScriptLoaderDisabler sld(doc);
     771                 :   
     772               0 :   nsresult rv = NS_OK;
     773               0 :   if (doc->IsHTML()) {
     774               0 :     PRInt32 oldChildCount = GetChildCount();
     775                 :     rv = nsContentUtils::ParseFragmentHTML(aInnerHTML,
     776                 :                                            this,
     777                 :                                            Tag(),
     778                 :                                            GetNameSpaceID(),
     779               0 :                                            doc->GetCompatibilityMode() ==
     780                 :                                              eCompatibility_NavQuirks,
     781               0 :                                            true);
     782                 :     // HTML5 parser has notified, but not fired mutation events.
     783               0 :     FireMutationEventsForDirectParsing(doc, this, oldChildCount);
     784                 :   } else {
     785               0 :     nsCOMPtr<nsIDOMDocumentFragment> df;
     786                 :     rv = nsContentUtils::CreateContextualFragment(this, aInnerHTML,
     787                 :                                                   true,
     788               0 :                                                   getter_AddRefs(df));
     789               0 :     nsCOMPtr<nsINode> fragment = do_QueryInterface(df);
     790               0 :     if (NS_SUCCEEDED(rv)) {
     791                 :       // Suppress assertion about node removal mutation events that can't have
     792                 :       // listeners anyway, because no one has had the chance to register mutation
     793                 :       // listeners on the fragment that comes from the parser.
     794               0 :       nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
     795                 : 
     796               0 :       static_cast<nsINode*>(this)->AppendChild(fragment, &rv);
     797                 :     }
     798                 :   }
     799                 : 
     800               0 :   return rv;
     801                 : }
     802                 : 
     803                 : NS_IMETHODIMP
     804               0 : nsGenericHTMLElement::SetOuterHTML(const nsAString& aOuterHTML)
     805                 : {
     806               0 :   nsCOMPtr<nsINode> parent = GetNodeParent();
     807               0 :   if (!parent) {
     808               0 :     return NS_OK;
     809                 :   }
     810                 : 
     811               0 :   if (parent->NodeType() == nsIDOMNode::DOCUMENT_NODE) {
     812               0 :     return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
     813                 :   }
     814                 : 
     815               0 :   if (OwnerDoc()->IsHTML()) {
     816                 :     nsIAtom* localName;
     817                 :     PRInt32 namespaceID;
     818               0 :     if (parent->IsElement()) {
     819               0 :       localName = static_cast<nsIContent*>(parent.get())->Tag();
     820               0 :       namespaceID = static_cast<nsIContent*>(parent.get())->GetNameSpaceID();
     821                 :     } else {
     822               0 :       NS_ASSERTION(parent->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE,
     823                 :         "How come the parent isn't a document, a fragment or an element?");
     824               0 :       localName = nsGkAtoms::body;
     825               0 :       namespaceID = kNameSpaceID_XHTML;
     826                 :     }
     827               0 :     nsCOMPtr<nsIDOMDocumentFragment> df;
     828               0 :     nsresult rv = NS_NewDocumentFragment(getter_AddRefs(df),
     829               0 :                                          OwnerDoc()->NodeInfoManager());
     830               0 :     NS_ENSURE_SUCCESS(rv, rv);
     831               0 :     nsCOMPtr<nsIContent> fragment = do_QueryInterface(df);
     832                 :     nsContentUtils::ParseFragmentHTML(aOuterHTML,
     833                 :                                       fragment,
     834                 :                                       localName,
     835                 :                                       namespaceID,
     836               0 :                                       OwnerDoc()->GetCompatibilityMode() ==
     837                 :                                         eCompatibility_NavQuirks,
     838               0 :                                       true);
     839               0 :     parent->ReplaceChild(fragment, this, &rv);
     840               0 :     return rv;
     841                 :   }
     842                 : 
     843               0 :   nsCOMPtr<nsINode> context;
     844               0 :   if (parent->IsElement()) {
     845               0 :     context = parent;
     846                 :   } else {
     847               0 :     NS_ASSERTION(parent->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE,
     848                 :       "How come the parent isn't a document, a fragment or an element?");
     849                 :     nsCOMPtr<nsINodeInfo> info =
     850                 :       OwnerDoc()->NodeInfoManager()->GetNodeInfo(nsGkAtoms::body,
     851                 :                                                  nsnull,
     852                 :                                                  kNameSpaceID_XHTML,
     853               0 :                                                  nsIDOMNode::ELEMENT_NODE);
     854               0 :     context = NS_NewHTMLBodyElement(info.forget(), FROM_PARSER_FRAGMENT);
     855                 :   }
     856                 : 
     857               0 :   nsCOMPtr<nsIDOMDocumentFragment> df;
     858                 :   nsresult rv = nsContentUtils::CreateContextualFragment(context,
     859                 :                                                          aOuterHTML,
     860                 :                                                          true,
     861               0 :                                                          getter_AddRefs(df));
     862               0 :   NS_ENSURE_SUCCESS(rv, rv);
     863               0 :   nsCOMPtr<nsINode> fragment = do_QueryInterface(df);
     864               0 :   parent->ReplaceChild(fragment, this, &rv);
     865               0 :   return rv;
     866                 : }
     867                 : 
     868                 : enum nsAdjacentPosition {
     869                 :   eBeforeBegin,
     870                 :   eAfterBegin,
     871                 :   eBeforeEnd,
     872                 :   eAfterEnd
     873                 : };
     874                 : 
     875                 : NS_IMETHODIMP
     876               0 : nsGenericHTMLElement::InsertAdjacentHTML(const nsAString& aPosition,
     877                 :                                          const nsAString& aText)
     878                 : {
     879                 :   nsAdjacentPosition position;
     880               0 :   if (aPosition.LowerCaseEqualsLiteral("beforebegin")) {
     881               0 :     position = eBeforeBegin;
     882               0 :   } else if (aPosition.LowerCaseEqualsLiteral("afterbegin")) {
     883               0 :     position = eAfterBegin;
     884               0 :   } else if (aPosition.LowerCaseEqualsLiteral("beforeend")) {
     885               0 :     position = eBeforeEnd;
     886               0 :   } else if (aPosition.LowerCaseEqualsLiteral("afterend")) {
     887               0 :     position = eAfterEnd;
     888                 :   } else {
     889               0 :     return NS_ERROR_DOM_SYNTAX_ERR;
     890                 :   }
     891                 : 
     892               0 :   nsCOMPtr<nsIContent> destination;
     893               0 :   if (position == eBeforeBegin || position == eAfterEnd) {
     894               0 :     destination = GetParent();
     895               0 :     if (!destination) {
     896               0 :       return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
     897                 :     }
     898                 :   } else {
     899               0 :     destination = this;
     900                 :   }
     901                 : 
     902               0 :   nsIDocument* doc = OwnerDoc();
     903                 : 
     904                 :   // Needed when insertAdjacentHTML is used in combination with contenteditable
     905               0 :   mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, true);
     906               0 :   nsAutoScriptLoaderDisabler sld(doc);
     907                 :   
     908                 :   // Batch possible DOMSubtreeModified events.
     909               0 :   mozAutoSubtreeModified subtree(doc, nsnull);
     910                 : 
     911                 :   nsresult rv;
     912                 :   // Parse directly into destination if possible
     913               0 :   if (doc->IsHTML() &&
     914                 :       (position == eBeforeEnd ||
     915               0 :        (position == eAfterEnd && !GetNextSibling()) ||
     916               0 :        (position == eAfterBegin && !GetFirstChild()))) {
     917               0 :     PRInt32 oldChildCount = destination->GetChildCount();
     918               0 :     PRInt32 contextNs = destination->GetNameSpaceID();
     919               0 :     nsIAtom* contextLocal = destination->Tag();
     920               0 :     if (contextLocal == nsGkAtoms::html && contextNs == kNameSpaceID_XHTML) {
     921                 :       // For compat with IE6 through IE9. Willful violation of HTML5 as of
     922                 :       // 2011-04-06. CreateContextualFragment does the same already.
     923                 :       // Spec bug: http://www.w3.org/Bugs/Public/show_bug.cgi?id=12434
     924               0 :       contextLocal = nsGkAtoms::body;
     925                 :     }
     926                 :     rv = nsContentUtils::ParseFragmentHTML(aText,
     927                 :                                            destination,
     928                 :                                            contextLocal,
     929                 :                                            contextNs,
     930               0 :                                            doc->GetCompatibilityMode() ==
     931                 :                                              eCompatibility_NavQuirks,
     932               0 :                                            true);
     933                 :     // HTML5 parser has notified, but not fired mutation events.
     934               0 :     FireMutationEventsForDirectParsing(doc, destination, oldChildCount);
     935               0 :     return rv;
     936                 :   }
     937                 : 
     938                 :   // couldn't parse directly
     939               0 :   nsCOMPtr<nsIDOMDocumentFragment> df;
     940                 :   rv = nsContentUtils::CreateContextualFragment(destination,
     941                 :                                                 aText,
     942                 :                                                 true,
     943               0 :                                                 getter_AddRefs(df));
     944               0 :   nsCOMPtr<nsINode> fragment = do_QueryInterface(df);
     945               0 :   NS_ENSURE_SUCCESS(rv, rv);
     946                 : 
     947                 :   // Suppress assertion about node removal mutation events that can't have
     948                 :   // listeners anyway, because no one has had the chance to register mutation
     949                 :   // listeners on the fragment that comes from the parser.
     950               0 :   nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
     951                 : 
     952               0 :   switch (position) {
     953                 :     case eBeforeBegin:
     954               0 :       destination->InsertBefore(fragment, this, &rv);
     955               0 :       break;
     956                 :     case eAfterBegin:
     957               0 :       static_cast<nsINode*>(this)->InsertBefore(fragment, GetFirstChild(), &rv);
     958               0 :       break;
     959                 :     case eBeforeEnd:
     960               0 :       static_cast<nsINode*>(this)->AppendChild(fragment, &rv);
     961               0 :       break;
     962                 :     case eAfterEnd:
     963               0 :       destination->InsertBefore(fragment, GetNextSibling(), &rv);
     964               0 :       break;
     965                 :   }
     966               0 :   return rv;
     967                 : }
     968                 : 
     969                 : nsresult
     970               0 : nsGenericHTMLElement::ScrollIntoView(bool aTop, PRUint8 optional_argc)
     971                 : {
     972               0 :   nsIDocument *document = GetCurrentDoc();
     973                 : 
     974               0 :   if (!document) {
     975               0 :     return NS_OK;
     976                 :   }
     977                 : 
     978                 :   // Get the presentation shell
     979               0 :   nsCOMPtr<nsIPresShell> presShell = document->GetShell();
     980               0 :   if (!presShell) {
     981               0 :     return NS_OK;
     982                 :   }
     983                 : 
     984               0 :   if (!optional_argc) {
     985               0 :     aTop = true;
     986                 :   }
     987                 : 
     988                 :   PRIntn vpercent = aTop ? NS_PRESSHELL_SCROLL_TOP :
     989               0 :     NS_PRESSHELL_SCROLL_BOTTOM;
     990                 : 
     991               0 :   presShell->ScrollContentIntoView(this, vpercent,
     992                 :                                    NS_PRESSHELL_SCROLL_ANYWHERE,
     993               0 :                                    nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
     994                 : 
     995               0 :   return NS_OK;
     996                 : }
     997                 : 
     998                 : NS_IMETHODIMP
     999               0 : nsGenericHTMLElement::GetSpellcheck(bool* aSpellcheck)
    1000                 : {
    1001               0 :   NS_ENSURE_ARG_POINTER(aSpellcheck);
    1002               0 :   *aSpellcheck = false;              // Default answer is to not spellcheck
    1003                 : 
    1004                 :   // Has the state has been explicitly set?
    1005                 :   nsIContent* node;
    1006               0 :   for (node = this; node; node = node->GetParent()) {
    1007               0 :     if (node->IsHTML()) {
    1008                 :       static nsIContent::AttrValuesArray strings[] =
    1009                 :         {&nsGkAtoms::_true, &nsGkAtoms::_false, nsnull};
    1010               0 :       switch (node->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::spellcheck,
    1011               0 :                                     strings, eCaseMatters)) {
    1012                 :         case 0:                         // spellcheck = "true"
    1013               0 :           *aSpellcheck = true;
    1014                 :           // Fall through
    1015                 :         case 1:                         // spellcheck = "false"
    1016               0 :           return NS_OK;
    1017                 :       }
    1018                 :     }
    1019                 :   }
    1020                 : 
    1021                 :   // Is this a chrome element?
    1022               0 :   if (nsContentUtils::IsChromeDoc(OwnerDoc())) {
    1023               0 :     return NS_OK;                       // Not spellchecked by default
    1024                 :   }
    1025                 : 
    1026               0 :   if (IsCurrentBodyElement()) {
    1027               0 :     nsCOMPtr<nsIHTMLDocument> doc = do_QueryInterface(GetCurrentDoc());
    1028               0 :     if (doc) {
    1029               0 :       *aSpellcheck = doc->IsEditingOn();
    1030                 :     }
    1031                 : 
    1032               0 :     return NS_OK;
    1033                 :   }
    1034                 : 
    1035                 :   // Is this element editable?
    1036               0 :   nsCOMPtr<nsIFormControl> formControl = do_QueryInterface(this);
    1037               0 :   if (!formControl) {
    1038               0 :     return NS_OK;                       // Not spellchecked by default
    1039                 :   }
    1040                 : 
    1041                 :   // Is this a multiline plaintext input?
    1042               0 :   PRInt32 controlType = formControl->GetType();
    1043               0 :   if (controlType == NS_FORM_TEXTAREA) {
    1044               0 :     *aSpellcheck = true;             // Spellchecked by default
    1045               0 :     return NS_OK;
    1046                 :   }
    1047                 : 
    1048                 :   // Is this anything other than an input text?
    1049                 :   // Other inputs are not spellchecked.
    1050               0 :   if (controlType != NS_FORM_INPUT_TEXT) {
    1051               0 :     return NS_OK;                       // Not spellchecked by default
    1052                 :   }
    1053                 : 
    1054                 :   // Does the user want input text spellchecked by default?
    1055                 :   // NOTE: Do not reflect a pref value of 0 back to the DOM getter.
    1056                 :   // The web page should not know if the user has disabled spellchecking.
    1057                 :   // We'll catch this in the editor itself.
    1058               0 :   PRInt32 spellcheckLevel = Preferences::GetInt("layout.spellcheckDefault", 1);
    1059               0 :   if (spellcheckLevel == 2) {           // "Spellcheck multi- and single-line"
    1060               0 :     *aSpellcheck = true;             // Spellchecked by default
    1061                 :   }
    1062                 : 
    1063               0 :   return NS_OK;
    1064                 : }
    1065                 : 
    1066                 : NS_IMETHODIMP
    1067               0 : nsGenericHTMLElement::SetSpellcheck(bool aSpellcheck)
    1068                 : {
    1069               0 :   if (aSpellcheck) {
    1070               0 :     return SetAttrHelper(nsGkAtoms::spellcheck, NS_LITERAL_STRING("true"));
    1071                 :   }
    1072                 : 
    1073               0 :   return SetAttrHelper(nsGkAtoms::spellcheck, NS_LITERAL_STRING("false"));
    1074                 : }
    1075                 : 
    1076                 : NS_IMETHODIMP
    1077               0 : nsGenericHTMLElement::GetDraggable(bool* aDraggable)
    1078                 : {
    1079                 :   *aDraggable = AttrValueIs(kNameSpaceID_None, nsGkAtoms::draggable,
    1080               0 :                              nsGkAtoms::_true, eIgnoreCase);
    1081               0 :   return NS_OK;
    1082                 : }
    1083                 : 
    1084                 : NS_IMETHODIMP
    1085               0 : nsGenericHTMLElement::SetDraggable(bool aDraggable)
    1086                 : {
    1087                 :   return SetAttrHelper(nsGkAtoms::draggable,
    1088               0 :                        aDraggable ? NS_LITERAL_STRING("true")
    1089               0 :                                   : NS_LITERAL_STRING("false"));
    1090                 : }
    1091                 : 
    1092                 : bool
    1093               0 : nsGenericHTMLElement::InNavQuirksMode(nsIDocument* aDoc)
    1094                 : {
    1095               0 :   return aDoc && aDoc->GetCompatibilityMode() == eCompatibility_NavQuirks;
    1096                 : }
    1097                 : 
    1098                 : void
    1099             789 : nsGenericHTMLElement::UpdateEditableState(bool aNotify)
    1100                 : {
    1101                 :   // XXX Should we do this only when in a document?
    1102             789 :   ContentEditableTristate value = GetContentEditableValue();
    1103             789 :   if (value != eInherit) {
    1104               0 :     DoSetEditableFlag(!!value, aNotify);
    1105               0 :     return;
    1106                 :   }
    1107                 : 
    1108             789 :   nsStyledElement::UpdateEditableState(aNotify);
    1109                 : }
    1110                 : 
    1111                 : nsresult
    1112             790 : nsGenericHTMLElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
    1113                 :                                  nsIContent* aBindingParent,
    1114                 :                                  bool aCompileEventHandlers)
    1115                 : {
    1116                 :   nsresult rv = nsGenericHTMLElementBase::BindToTree(aDocument, aParent,
    1117                 :                                                      aBindingParent,
    1118             790 :                                                      aCompileEventHandlers);
    1119             790 :   NS_ENSURE_SUCCESS(rv, rv);
    1120                 : 
    1121             790 :   if (aDocument) {
    1122             789 :     RegAccessKey();
    1123             789 :     if (HasName()) {
    1124                 :       aDocument->
    1125               0 :         AddToNameTable(this, GetParsedAttr(nsGkAtoms::name)->GetAtomValue());
    1126                 :     }
    1127             789 :     if (HasFlag(NODE_IS_EDITABLE) && GetContentEditableValue() == eTrue) {
    1128               0 :       nsCOMPtr<nsIHTMLDocument> htmlDocument = do_QueryInterface(aDocument);
    1129               0 :       if (htmlDocument) {
    1130               0 :         htmlDocument->ChangeContentEditableCount(this, +1);
    1131                 :       }
    1132                 :     }
    1133                 :   }
    1134                 : 
    1135             790 :   return rv;
    1136                 : }
    1137                 : 
    1138                 : void
    1139            1249 : nsGenericHTMLElement::UnbindFromTree(bool aDeep, bool aNullParent)
    1140                 : {
    1141            1249 :   if (IsInDoc()) {
    1142             789 :     UnregAccessKey();
    1143                 :   }
    1144                 : 
    1145            1249 :   RemoveFromNameTable();
    1146                 : 
    1147            1249 :   if (GetContentEditableValue() == eTrue) {
    1148               0 :     nsCOMPtr<nsIHTMLDocument> htmlDocument = do_QueryInterface(GetCurrentDoc());
    1149               0 :     if (htmlDocument) {
    1150               0 :       htmlDocument->ChangeContentEditableCount(this, -1);
    1151                 :     }
    1152                 :   }
    1153                 : 
    1154            1249 :   nsStyledElement::UnbindFromTree(aDeep, aNullParent);
    1155            1249 : }
    1156                 : 
    1157                 : nsHTMLFormElement*
    1158               1 : nsGenericHTMLElement::FindAncestorForm(nsHTMLFormElement* aCurrentForm)
    1159                 : {
    1160               1 :   NS_ASSERTION(!HasAttr(kNameSpaceID_None, nsGkAtoms::form),
    1161                 :                "FindAncestorForm should not be called if @form is set!");
    1162                 : 
    1163                 :   // Make sure we don't end up finding a form that's anonymous from
    1164                 :   // our point of view.
    1165               1 :   nsIContent* bindingParent = GetBindingParent();
    1166                 : 
    1167               1 :   nsIContent* content = this;
    1168               5 :   while (content != bindingParent && content) {
    1169                 :     // If the current ancestor is a form, return it as our form
    1170               3 :     if (content->IsHTML(nsGkAtoms::form)) {
    1171                 : #ifdef DEBUG
    1172               0 :       if (!nsContentUtils::IsInSameAnonymousTree(this, content)) {
    1173                 :         // It's possible that we started unbinding at |content| or
    1174                 :         // some ancestor of it, and |content| and |this| used to all be
    1175                 :         // anonymous.  Check for this the hard way.
    1176               0 :         for (nsIContent* child = this; child != content;
    1177               0 :              child = child->GetParent()) {
    1178               0 :           NS_ASSERTION(child->GetParent()->IndexOf(child) != -1,
    1179                 :                        "Walked too far?");
    1180                 :         }
    1181                 :       }
    1182                 : #endif
    1183               0 :       return static_cast<nsHTMLFormElement*>(content);
    1184                 :     }
    1185                 : 
    1186               3 :     nsIContent *prevContent = content;
    1187               3 :     content = prevContent->GetParent();
    1188                 : 
    1189               3 :     if (!content && aCurrentForm) {
    1190                 :       // We got to the root of the subtree we're in, and we're being removed
    1191                 :       // from the DOM (the only time we get into this method with a non-null
    1192                 :       // aCurrentForm).  Check whether aCurrentForm is in the same subtree.  If
    1193                 :       // it is, we want to return aCurrentForm, since this case means that
    1194                 :       // we're one of those inputs-in-a-table that have a hacked mForm pointer
    1195                 :       // and a subtree containing both us and the form got removed from the
    1196                 :       // DOM.
    1197               0 :       if (nsContentUtils::ContentIsDescendantOf(aCurrentForm, prevContent)) {
    1198               0 :         return aCurrentForm;
    1199                 :       }
    1200                 :     }
    1201                 :   }
    1202                 : 
    1203               1 :   return nsnull;
    1204                 : }
    1205                 : 
    1206                 : static bool
    1207               0 : IsArea(nsIContent *aContent)
    1208                 : {
    1209               0 :   return (aContent->Tag() == nsGkAtoms::area &&
    1210               0 :           aContent->IsHTML());
    1211                 : }
    1212                 : 
    1213                 : bool
    1214               0 : nsGenericHTMLElement::CheckHandleEventForAnchorsPreconditions(nsEventChainVisitor& aVisitor)
    1215                 : {
    1216               0 :   NS_PRECONDITION(nsCOMPtr<nsILink>(do_QueryInterface(this)),
    1217                 :                   "should be called only when |this| implements |nsILink|");
    1218                 : 
    1219               0 :   if (!aVisitor.mPresContext) {
    1220                 :     // We need a pres context to do link stuff. Some events (e.g. mutation
    1221                 :     // events) don't have one.
    1222                 :     // XXX: ideally, shouldn't we be able to do what we need without one?
    1223               0 :     return false; 
    1224                 :   }
    1225                 : 
    1226                 :   //Need to check if we hit an imagemap area and if so see if we're handling
    1227                 :   //the event on that map or on a link farther up the tree.  If we're on a
    1228                 :   //link farther up, do nothing.
    1229                 :   nsCOMPtr<nsIContent> target = aVisitor.mPresContext->EventStateManager()->
    1230               0 :     GetEventTargetContent(aVisitor.mEvent);
    1231                 : 
    1232               0 :   return !target || !IsArea(target) || IsArea(this);
    1233                 : }
    1234                 : 
    1235                 : nsresult
    1236               0 : nsGenericHTMLElement::PreHandleEventForAnchors(nsEventChainPreVisitor& aVisitor)
    1237                 : {
    1238               0 :   nsresult rv = nsGenericHTMLElementBase::PreHandleEvent(aVisitor);
    1239               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1240                 : 
    1241               0 :   if (!CheckHandleEventForAnchorsPreconditions(aVisitor)) {
    1242               0 :     return NS_OK;
    1243                 :   }
    1244                 : 
    1245               0 :   return PreHandleEventForLinks(aVisitor);
    1246                 : }
    1247                 : 
    1248                 : nsresult
    1249               0 : nsGenericHTMLElement::PostHandleEventForAnchors(nsEventChainPostVisitor& aVisitor)
    1250                 : {
    1251               0 :   if (!CheckHandleEventForAnchorsPreconditions(aVisitor)) {
    1252               0 :     return NS_OK;
    1253                 :   }
    1254                 : 
    1255               0 :   return PostHandleEventForLinks(aVisitor);
    1256                 : }
    1257                 : 
    1258                 : bool
    1259               0 : nsGenericHTMLElement::IsHTMLLink(nsIURI** aURI) const
    1260                 : {
    1261               0 :   NS_PRECONDITION(aURI, "Must provide aURI out param");
    1262                 : 
    1263               0 :   *aURI = GetHrefURIForAnchors().get();
    1264                 :   // We promise out param is non-null if we return true, so base rv on it
    1265               0 :   return *aURI != nsnull;
    1266                 : }
    1267                 : 
    1268                 : already_AddRefed<nsIURI>
    1269               0 : nsGenericHTMLElement::GetHrefURIForAnchors() const
    1270                 : {
    1271                 :   // This is used by the three nsILink implementations and
    1272                 :   // nsHTMLStyleElement.
    1273                 : 
    1274                 :   // Get href= attribute (relative URI).
    1275                 : 
    1276                 :   // We use the nsAttrValue's copy of the URI string to avoid copying.
    1277               0 :   nsCOMPtr<nsIURI> uri;
    1278               0 :   GetURIAttr(nsGkAtoms::href, nsnull, getter_AddRefs(uri));
    1279                 : 
    1280               0 :   return uri.forget();
    1281                 : }
    1282                 : 
    1283                 : nsresult
    1284              11 : nsGenericHTMLElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
    1285                 :                                    const nsAttrValue* aValue, bool aNotify)
    1286                 : {
    1287              11 :   if (aNamespaceID == kNameSpaceID_None) {
    1288               0 :     if (nsContentUtils::IsEventAttributeName(aName, EventNameType_HTML) &&
    1289                 :         aValue) {
    1290               0 :       NS_ABORT_IF_FALSE(aValue->Type() == nsAttrValue::eString,
    1291                 :         "Expected string value for script body");
    1292               0 :       nsresult rv = AddScriptEventListener(aName, aValue->GetStringValue());
    1293               0 :       NS_ENSURE_SUCCESS(rv, rv);
    1294                 :     }
    1295               0 :     else if (aNotify && aName == nsGkAtoms::spellcheck) {
    1296               0 :       SyncEditorsOnSubtree(this);
    1297                 :     }
    1298                 :   }
    1299                 : 
    1300                 :   return nsGenericHTMLElementBase::AfterSetAttr(aNamespaceID, aName,
    1301              11 :                                                 aValue, aNotify);
    1302                 : }
    1303                 : 
    1304                 : nsEventListenerManager*
    1305               0 : nsGenericHTMLElement::GetEventListenerManagerForAttr(nsIAtom* aAttrName,
    1306                 :                                                      bool* aDefer)
    1307                 : {
    1308                 :   // Attributes on the body and frameset tags get set on the global object
    1309               0 :   if ((mNodeInfo->Equals(nsGkAtoms::body) ||
    1310               0 :        mNodeInfo->Equals(nsGkAtoms::frameset)) &&
    1311                 :       // We only forward some event attributes from body/frameset to window
    1312                 :       (0
    1313                 : #define EVENT(name_, id_, type_, struct_) /* nothing */
    1314                 : #define FORWARDED_EVENT(name_, id_, type_, struct_) \
    1315                 :        || nsGkAtoms::on##name_ == aAttrName
    1316                 : #define WINDOW_EVENT FORWARDED_EVENT
    1317                 : #include "nsEventNameList.h"
    1318                 : #undef WINDOW_EVENT
    1319                 : #undef FORWARDED_EVENT
    1320                 : #undef EVENT
    1321                 :        )
    1322                 :       ) {
    1323                 :     nsPIDOMWindow *win;
    1324                 : 
    1325                 :     // If we have a document, and it has a window, add the event
    1326                 :     // listener on the window (the inner window). If not, proceed as
    1327                 :     // normal.
    1328                 :     // XXXbz sXBL/XBL2 issue: should we instead use GetCurrentDoc() here,
    1329                 :     // override BindToTree for those classes and munge event listeners there?
    1330               0 :     nsIDocument *document = OwnerDoc();
    1331                 : 
    1332                 :     // FIXME (https://bugzilla.mozilla.org/show_bug.cgi?id=431767)
    1333                 :     // nsDocument::GetInnerWindow can return an outer window in some cases,
    1334                 :     // we don't want to stick an event listener on an outer window, so
    1335                 :     // bail if it does.  See similar code in nsHTMLBodyElement and
    1336                 :     // nsHTMLFramesetElement
    1337               0 :     *aDefer = false;
    1338               0 :     if ((win = document->GetInnerWindow()) && win->IsInnerWindow()) {
    1339               0 :       nsCOMPtr<nsIDOMEventTarget> piTarget(do_QueryInterface(win));
    1340                 : 
    1341               0 :       return piTarget->GetListenerManager(true);
    1342                 :     }
    1343                 : 
    1344               0 :     return nsnull;
    1345                 :   }
    1346                 : 
    1347                 :   return nsGenericHTMLElementBase::GetEventListenerManagerForAttr(aAttrName,
    1348               0 :                                                                   aDefer);
    1349                 : }
    1350                 : 
    1351                 : nsresult
    1352              11 : nsGenericHTMLElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
    1353                 :                               nsIAtom* aPrefix, const nsAString& aValue,
    1354                 :                               bool aNotify)
    1355                 : {
    1356                 :   bool contentEditable = aNameSpaceID == kNameSpaceID_None &&
    1357              11 :                            aName == nsGkAtoms::contenteditable;
    1358                 :   bool accessKey = aName == nsGkAtoms::accesskey && 
    1359              11 :                      aNameSpaceID == kNameSpaceID_None;
    1360                 : 
    1361              11 :   PRInt32 change = 0;
    1362              11 :   if (contentEditable) {
    1363               0 :     change = GetContentEditableValue() == eTrue ? -1 : 0;
    1364               0 :     SetMayHaveContentEditableAttr();
    1365                 :   }
    1366                 : 
    1367              11 :   if (accessKey) {
    1368               0 :     UnregAccessKey();
    1369                 :   }
    1370                 : 
    1371                 :   nsresult rv = nsStyledElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue,
    1372              11 :                                          aNotify);
    1373              11 :   NS_ENSURE_SUCCESS(rv, rv);
    1374                 : 
    1375              11 :   if (contentEditable) {
    1376               0 :     if (aValue.IsEmpty() || aValue.LowerCaseEqualsLiteral("true")) {
    1377               0 :       change += 1;
    1378                 :     }
    1379                 : 
    1380               0 :     ChangeEditableState(change);
    1381                 :   }
    1382                 : 
    1383              11 :   if (accessKey && !aValue.IsEmpty()) {
    1384               0 :     SetFlags(NODE_HAS_ACCESSKEY);
    1385               0 :     RegAccessKey();
    1386                 :   }
    1387                 : 
    1388              11 :   return NS_OK;
    1389                 : }
    1390                 : 
    1391                 : nsresult
    1392               0 : nsGenericHTMLElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
    1393                 :                                 bool aNotify)
    1394                 : {
    1395               0 :   bool contentEditable = false;
    1396               0 :   PRInt32 contentEditableChange = 0;
    1397                 : 
    1398                 :   // Check for event handlers
    1399               0 :   if (aNameSpaceID == kNameSpaceID_None) {
    1400               0 :     if (aAttribute == nsGkAtoms::name) {
    1401                 :       // Have to do this before clearing flag. See RemoveFromNameTable
    1402               0 :       RemoveFromNameTable();
    1403               0 :       ClearHasName();
    1404                 :     }
    1405               0 :     else if (aAttribute == nsGkAtoms::contenteditable) {
    1406               0 :       contentEditable = true;
    1407               0 :       contentEditableChange = GetContentEditableValue() == eTrue ? -1 : 0;
    1408                 :     }
    1409               0 :     else if (aAttribute == nsGkAtoms::accesskey) {
    1410                 :       // Have to unregister before clearing flag. See UnregAccessKey
    1411               0 :       UnregAccessKey();
    1412               0 :       UnsetFlags(NODE_HAS_ACCESSKEY);
    1413                 :     }
    1414               0 :     else if (nsContentUtils::IsEventAttributeName(aAttribute,
    1415                 :                                                   EventNameType_HTML)) {
    1416               0 :       nsEventListenerManager* manager = GetListenerManager(false);
    1417               0 :       if (manager) {
    1418               0 :         manager->RemoveScriptEventListener(aAttribute);
    1419                 :       }
    1420                 :     }
    1421                 : 
    1422                 :     // Remove dataset property if necessary.
    1423               0 :     nsDOMSlots *slots = GetExistingDOMSlots();
    1424               0 :     if (slots && slots->mDataset) {
    1425               0 :       slots->mDataset->RemoveProp(aAttribute);
    1426                 :     }
    1427                 :   }
    1428                 : 
    1429                 :   nsresult rv = nsGenericHTMLElementBase::UnsetAttr(aNameSpaceID, aAttribute,
    1430               0 :                                                     aNotify);
    1431               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1432                 : 
    1433               0 :   if (contentEditable) {
    1434               0 :     ChangeEditableState(contentEditableChange);
    1435                 :   }
    1436                 : 
    1437               0 :   return NS_OK;
    1438                 : }
    1439                 : 
    1440                 : void
    1441               0 : nsGenericHTMLElement::GetBaseTarget(nsAString& aBaseTarget) const
    1442                 : {
    1443               0 :   OwnerDoc()->GetBaseTarget(aBaseTarget);
    1444               0 : }
    1445                 : 
    1446                 : //----------------------------------------------------------------------
    1447                 : 
    1448                 : static bool
    1449               0 : CanHaveName(nsIAtom* aTag)
    1450                 : {
    1451                 :   return aTag == nsGkAtoms::img ||
    1452                 :          aTag == nsGkAtoms::form ||
    1453                 :          aTag == nsGkAtoms::applet ||
    1454                 :          aTag == nsGkAtoms::embed ||
    1455               0 :          aTag == nsGkAtoms::object;
    1456                 : }
    1457                 : 
    1458                 : bool
    1459              11 : nsGenericHTMLElement::ParseAttribute(PRInt32 aNamespaceID,
    1460                 :                                      nsIAtom* aAttribute,
    1461                 :                                      const nsAString& aValue,
    1462                 :                                      nsAttrValue& aResult)
    1463                 : {
    1464              11 :   if (aNamespaceID == kNameSpaceID_None) {
    1465               0 :     if (aAttribute == nsGkAtoms::dir) {
    1466               0 :       return aResult.ParseEnumValue(aValue, kDirTable, false);
    1467                 :     }
    1468                 :   
    1469               0 :     if (aAttribute == nsGkAtoms::tabindex) {
    1470               0 :       return aResult.ParseIntWithBounds(aValue, -32768, 32767);
    1471                 :     }
    1472                 : 
    1473               0 :     if (aAttribute == nsGkAtoms::name) {
    1474                 :       // Store name as an atom.  name="" means that the element has no name,
    1475                 :       // not that it has an emptystring as the name.
    1476               0 :       RemoveFromNameTable();
    1477               0 :       if (aValue.IsEmpty()) {
    1478               0 :         ClearHasName();
    1479               0 :         return false;
    1480                 :       }
    1481                 : 
    1482               0 :       aResult.ParseAtom(aValue);
    1483                 : 
    1484               0 :       if (CanHaveName(Tag())) {
    1485               0 :         SetHasName();
    1486               0 :         AddToNameTable(aResult.GetAtomValue());
    1487                 :       }
    1488                 :       
    1489               0 :       return true;
    1490                 :     }
    1491                 : 
    1492               0 :     if (aAttribute == nsGkAtoms::contenteditable) {
    1493               0 :       aResult.ParseAtom(aValue);
    1494               0 :       return true;
    1495                 :     }
    1496                 :   }
    1497                 : 
    1498                 :   return nsGenericHTMLElementBase::ParseAttribute(aNamespaceID, aAttribute,
    1499              11 :                                                   aValue, aResult);
    1500                 : }
    1501                 : 
    1502                 : bool
    1503               0 : nsGenericHTMLElement::IsAttributeMapped(const nsIAtom* aAttribute) const
    1504                 : {
    1505                 :   static const MappedAttributeEntry* const map[] = {
    1506                 :     sCommonAttributeMap
    1507                 :   };
    1508                 :   
    1509               0 :   return FindAttributeDependence(aAttribute, map);
    1510                 : }
    1511                 : 
    1512                 : nsMapRuleToAttributesFunc
    1513               0 : nsGenericHTMLElement::GetAttributeMappingFunction() const
    1514                 : {
    1515               0 :   return &MapCommonAttributesInto;
    1516                 : }
    1517                 : 
    1518                 : nsIFormControlFrame*
    1519               0 : nsGenericHTMLElement::GetFormControlFrame(bool aFlushFrames)
    1520                 : {
    1521               0 :   if (aFlushFrames && IsInDoc()) {
    1522                 :     // Cause a flush of the frames, so we get up-to-date frame information
    1523               0 :     GetCurrentDoc()->FlushPendingNotifications(Flush_Frames);
    1524                 :   }
    1525               0 :   nsIFrame* frame = GetPrimaryFrame();
    1526               0 :   if (frame) {
    1527               0 :     nsIFormControlFrame* form_frame = do_QueryFrame(frame);
    1528               0 :     if (form_frame) {
    1529               0 :       return form_frame;
    1530                 :     }
    1531                 : 
    1532                 :     // If we have generated content, the primary frame will be a
    1533                 :     // wrapper frame..  out real frame will be in its child list.
    1534               0 :     for (frame = frame->GetFirstPrincipalChild();
    1535                 :          frame;
    1536                 :          frame = frame->GetNextSibling()) {
    1537               0 :       form_frame = do_QueryFrame(frame);
    1538               0 :       if (form_frame) {
    1539               0 :         return form_frame;
    1540                 :       }
    1541                 :     }
    1542                 :   }
    1543                 : 
    1544               0 :   return nsnull;
    1545                 : }
    1546                 : 
    1547                 : /* static */ nsresult
    1548               0 : nsGenericHTMLElement::GetPrimaryPresState(nsGenericHTMLElement* aContent,
    1549                 :                                           nsPresState** aPresState)
    1550                 : {
    1551               0 :   NS_ENSURE_ARG_POINTER(aPresState);
    1552               0 :   *aPresState = nsnull;
    1553                 : 
    1554               0 :   nsresult result = NS_OK;
    1555                 : 
    1556               0 :   nsCAutoString key;
    1557               0 :   nsCOMPtr<nsILayoutHistoryState> history = GetLayoutHistoryAndKey(aContent, false, key);
    1558                 : 
    1559               0 :   if (history) {
    1560                 :     // Get the pres state for this key, if it doesn't exist, create one
    1561               0 :     result = history->GetState(key, aPresState);
    1562               0 :     if (!*aPresState) {
    1563               0 :       *aPresState = new nsPresState();
    1564               0 :       result = history->AddState(key, *aPresState);
    1565                 :     }
    1566                 :   }
    1567                 : 
    1568               0 :   return result;
    1569                 : }
    1570                 : 
    1571                 : 
    1572                 : already_AddRefed<nsILayoutHistoryState>
    1573               1 : nsGenericHTMLElement::GetLayoutHistoryAndKey(nsGenericHTMLElement* aContent,
    1574                 :                                              bool aRead,
    1575                 :                                              nsACString& aKey)
    1576                 : {
    1577                 :   //
    1578                 :   // Get the pres shell
    1579                 :   //
    1580               2 :   nsCOMPtr<nsIDocument> doc = aContent->GetDocument();
    1581               1 :   if (!doc) {
    1582               0 :     return nsnull;
    1583                 :   }
    1584                 : 
    1585                 :   //
    1586                 :   // Get the history (don't bother with the key if the history is not there)
    1587                 :   //
    1588               2 :   nsCOMPtr<nsILayoutHistoryState> history = doc->GetLayoutHistoryState();
    1589               1 :   if (!history) {
    1590               1 :     return nsnull;
    1591                 :   }
    1592                 : 
    1593               0 :   if (aRead && !history->HasStates()) {
    1594               0 :     return nsnull;
    1595                 :   }
    1596                 : 
    1597                 :   //
    1598                 :   // Get the state key
    1599                 :   //
    1600                 :   nsresult rv = nsContentUtils::GenerateStateKey(aContent, doc,
    1601                 :                                                  nsIStatefulFrame::eNoID,
    1602               0 :                                                  aKey);
    1603               0 :   if (NS_FAILED(rv)) {
    1604               0 :     return nsnull;
    1605                 :   }
    1606                 : 
    1607                 :   // If the state key is blank, this is anonymous content or for
    1608                 :   // whatever reason we are not supposed to save/restore state.
    1609               0 :   if (aKey.IsEmpty()) {
    1610               0 :     return nsnull;
    1611                 :   }
    1612                 : 
    1613                 :   // Add something unique to content so layout doesn't muck us up
    1614               0 :   aKey += "-C";
    1615                 : 
    1616               0 :   return history.forget();
    1617                 : }
    1618                 : 
    1619                 : bool
    1620               1 : nsGenericHTMLElement::RestoreFormControlState(nsGenericHTMLElement* aContent,
    1621                 :                                               nsIFormControl* aControl)
    1622                 : {
    1623               2 :   nsCAutoString key;
    1624               2 :   nsCOMPtr<nsILayoutHistoryState> history = GetLayoutHistoryAndKey(aContent, true, key);
    1625               1 :   if (!history) {
    1626               1 :     return false;
    1627                 :   }
    1628                 : 
    1629                 :   nsPresState *state;
    1630                 :   // Get the pres state for this key
    1631               0 :   nsresult rv = history->GetState(key, &state);
    1632               0 :   if (NS_SUCCEEDED(rv) && state) {
    1633               0 :     bool result = aControl->RestoreState(state);
    1634               0 :     history->RemoveState(key);
    1635               0 :     return result;
    1636                 :   }
    1637                 : 
    1638               0 :   return false;
    1639                 : }
    1640                 : 
    1641                 : // XXX This creates a dependency between content and frames
    1642                 : nsPresContext*
    1643               0 : nsGenericHTMLElement::GetPresContext()
    1644                 : {
    1645                 :   // Get the document
    1646               0 :   nsIDocument* doc = GetDocument();
    1647               0 :   if (doc) {
    1648                 :     // Get presentation shell.
    1649               0 :     nsIPresShell *presShell = doc->GetShell();
    1650               0 :     if (presShell) {
    1651               0 :       return presShell->GetPresContext();
    1652                 :     }
    1653                 :   }
    1654                 : 
    1655               0 :   return nsnull;
    1656                 : }
    1657                 : 
    1658                 : static const nsAttrValue::EnumTable kAlignTable[] = {
    1659                 :   { "left",      NS_STYLE_TEXT_ALIGN_LEFT },
    1660                 :   { "right",     NS_STYLE_TEXT_ALIGN_RIGHT },
    1661                 : 
    1662                 :   { "top",       NS_STYLE_VERTICAL_ALIGN_TOP },
    1663                 :   { "middle",    NS_STYLE_VERTICAL_ALIGN_MIDDLE_WITH_BASELINE },
    1664                 :   { "bottom",    NS_STYLE_VERTICAL_ALIGN_BASELINE },
    1665                 : 
    1666                 :   { "center",    NS_STYLE_VERTICAL_ALIGN_MIDDLE_WITH_BASELINE },
    1667                 :   { "baseline",  NS_STYLE_VERTICAL_ALIGN_BASELINE },
    1668                 : 
    1669                 :   { "texttop",   NS_STYLE_VERTICAL_ALIGN_TEXT_TOP },
    1670                 :   { "absmiddle", NS_STYLE_VERTICAL_ALIGN_MIDDLE },
    1671                 :   { "abscenter", NS_STYLE_VERTICAL_ALIGN_MIDDLE },
    1672                 :   { "absbottom", NS_STYLE_VERTICAL_ALIGN_BOTTOM },
    1673                 :   { 0 }
    1674                 : };
    1675                 : 
    1676                 : static const nsAttrValue::EnumTable kDivAlignTable[] = {
    1677                 :   { "left", NS_STYLE_TEXT_ALIGN_MOZ_LEFT },
    1678                 :   { "right", NS_STYLE_TEXT_ALIGN_MOZ_RIGHT },
    1679                 :   { "center", NS_STYLE_TEXT_ALIGN_MOZ_CENTER },
    1680                 :   { "middle", NS_STYLE_TEXT_ALIGN_MOZ_CENTER },
    1681                 :   { "justify", NS_STYLE_TEXT_ALIGN_JUSTIFY },
    1682                 :   { 0 }
    1683                 : };
    1684                 : 
    1685                 : static const nsAttrValue::EnumTable kFrameborderTable[] = {
    1686                 :   { "yes", NS_STYLE_FRAME_YES },
    1687                 :   { "no", NS_STYLE_FRAME_NO },
    1688                 :   { "1", NS_STYLE_FRAME_1 },
    1689                 :   { "0", NS_STYLE_FRAME_0 },
    1690                 :   { 0 }
    1691                 : };
    1692                 : 
    1693                 : static const nsAttrValue::EnumTable kScrollingTable[] = {
    1694                 :   { "yes", NS_STYLE_FRAME_YES },
    1695                 :   { "no", NS_STYLE_FRAME_NO },
    1696                 :   { "on", NS_STYLE_FRAME_ON },
    1697                 :   { "off", NS_STYLE_FRAME_OFF },
    1698                 :   { "scroll", NS_STYLE_FRAME_SCROLL },
    1699                 :   { "noscroll", NS_STYLE_FRAME_NOSCROLL },
    1700                 :   { "auto", NS_STYLE_FRAME_AUTO },
    1701                 :   { 0 }
    1702                 : };
    1703                 : 
    1704                 : static const nsAttrValue::EnumTable kTableVAlignTable[] = {
    1705                 :   { "top",     NS_STYLE_VERTICAL_ALIGN_TOP },
    1706                 :   { "middle",  NS_STYLE_VERTICAL_ALIGN_MIDDLE },
    1707                 :   { "bottom",  NS_STYLE_VERTICAL_ALIGN_BOTTOM },
    1708                 :   { "baseline",NS_STYLE_VERTICAL_ALIGN_BASELINE },
    1709                 :   { 0 }
    1710                 : };
    1711                 : 
    1712                 : bool
    1713               0 : nsGenericHTMLElement::ParseAlignValue(const nsAString& aString,
    1714                 :                                       nsAttrValue& aResult)
    1715                 : {
    1716               0 :   return aResult.ParseEnumValue(aString, kAlignTable, false);
    1717                 : }
    1718                 : 
    1719                 : //----------------------------------------
    1720                 : 
    1721                 : static const nsAttrValue::EnumTable kTableHAlignTable[] = {
    1722                 :   { "left",   NS_STYLE_TEXT_ALIGN_LEFT },
    1723                 :   { "right",  NS_STYLE_TEXT_ALIGN_RIGHT },
    1724                 :   { "center", NS_STYLE_TEXT_ALIGN_CENTER },
    1725                 :   { "char",   NS_STYLE_TEXT_ALIGN_CHAR },
    1726                 :   { "justify",NS_STYLE_TEXT_ALIGN_JUSTIFY },
    1727                 :   { 0 }
    1728                 : };
    1729                 : 
    1730                 : bool
    1731               0 : nsGenericHTMLElement::ParseTableHAlignValue(const nsAString& aString,
    1732                 :                                             nsAttrValue& aResult)
    1733                 : {
    1734               0 :   return aResult.ParseEnumValue(aString, kTableHAlignTable, false);
    1735                 : }
    1736                 : 
    1737                 : //----------------------------------------
    1738                 : 
    1739                 : // This table is used for td, th, tr, col, thead, tbody and tfoot.
    1740                 : static const nsAttrValue::EnumTable kTableCellHAlignTable[] = {
    1741                 :   { "left",   NS_STYLE_TEXT_ALIGN_MOZ_LEFT },
    1742                 :   { "right",  NS_STYLE_TEXT_ALIGN_MOZ_RIGHT },
    1743                 :   { "center", NS_STYLE_TEXT_ALIGN_MOZ_CENTER },
    1744                 :   { "char",   NS_STYLE_TEXT_ALIGN_CHAR },
    1745                 :   { "justify",NS_STYLE_TEXT_ALIGN_JUSTIFY },
    1746                 :   { "middle", NS_STYLE_TEXT_ALIGN_MOZ_CENTER },
    1747                 :   { "absmiddle", NS_STYLE_TEXT_ALIGN_CENTER },
    1748                 :   { 0 }
    1749                 : };
    1750                 : 
    1751                 : bool
    1752               0 : nsGenericHTMLElement::ParseTableCellHAlignValue(const nsAString& aString,
    1753                 :                                                 nsAttrValue& aResult)
    1754                 : {
    1755               0 :   return aResult.ParseEnumValue(aString, kTableCellHAlignTable, false);
    1756                 : }
    1757                 : 
    1758                 : //----------------------------------------
    1759                 : 
    1760                 : bool
    1761               0 : nsGenericHTMLElement::ParseTableVAlignValue(const nsAString& aString,
    1762                 :                                             nsAttrValue& aResult)
    1763                 : {
    1764               0 :   return aResult.ParseEnumValue(aString, kTableVAlignTable, false);
    1765                 : }
    1766                 : 
    1767                 : bool
    1768               0 : nsGenericHTMLElement::ParseDivAlignValue(const nsAString& aString,
    1769                 :                                          nsAttrValue& aResult)
    1770                 : {
    1771               0 :   return aResult.ParseEnumValue(aString, kDivAlignTable, false);
    1772                 : }
    1773                 : 
    1774                 : bool
    1775               0 : nsGenericHTMLElement::ParseImageAttribute(nsIAtom* aAttribute,
    1776                 :                                           const nsAString& aString,
    1777                 :                                           nsAttrValue& aResult)
    1778                 : {
    1779               0 :   if ((aAttribute == nsGkAtoms::width) ||
    1780                 :       (aAttribute == nsGkAtoms::height)) {
    1781               0 :     return aResult.ParseSpecialIntValue(aString);
    1782                 :   }
    1783               0 :   if ((aAttribute == nsGkAtoms::hspace) ||
    1784                 :       (aAttribute == nsGkAtoms::vspace) ||
    1785                 :       (aAttribute == nsGkAtoms::border)) {
    1786               0 :     return aResult.ParseIntWithBounds(aString, 0);
    1787                 :   }
    1788               0 :   return false;
    1789                 : }
    1790                 : 
    1791                 : bool
    1792               0 : nsGenericHTMLElement::ParseFrameborderValue(const nsAString& aString,
    1793                 :                                             nsAttrValue& aResult)
    1794                 : {
    1795               0 :   return aResult.ParseEnumValue(aString, kFrameborderTable, false);
    1796                 : }
    1797                 : 
    1798                 : bool
    1799               0 : nsGenericHTMLElement::ParseScrollingValue(const nsAString& aString,
    1800                 :                                           nsAttrValue& aResult)
    1801                 : {
    1802               0 :   return aResult.ParseEnumValue(aString, kScrollingTable, false);
    1803                 : }
    1804                 : 
    1805                 : /**
    1806                 :  * Handle attributes common to all html elements
    1807                 :  */
    1808                 : void
    1809               0 : nsGenericHTMLElement::MapCommonAttributesExceptHiddenInto(const nsMappedAttributes* aAttributes,
    1810                 :                                                           nsRuleData* aData)
    1811                 : {
    1812               0 :   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(UserInterface)) {
    1813               0 :     nsCSSValue* userModify = aData->ValueForUserModify();
    1814               0 :     if (userModify->GetUnit() == eCSSUnit_Null) {
    1815                 :       const nsAttrValue* value =
    1816               0 :         aAttributes->GetAttr(nsGkAtoms::contenteditable);
    1817               0 :       if (value) {
    1818               0 :         if (value->Equals(nsGkAtoms::_empty, eCaseMatters) ||
    1819               0 :             value->Equals(nsGkAtoms::_true, eIgnoreCase)) {
    1820                 :           userModify->SetIntValue(NS_STYLE_USER_MODIFY_READ_WRITE,
    1821               0 :                                   eCSSUnit_Enumerated);
    1822                 :         }
    1823               0 :         else if (value->Equals(nsGkAtoms::_false, eIgnoreCase)) {
    1824                 :             userModify->SetIntValue(NS_STYLE_USER_MODIFY_READ_ONLY,
    1825               0 :                                     eCSSUnit_Enumerated);
    1826                 :         }
    1827                 :       }
    1828                 :     }
    1829                 :   }
    1830                 : 
    1831               0 :   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Font)) {
    1832               0 :     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::lang);
    1833               0 :     if (value && value->Type() == nsAttrValue::eString) {
    1834               0 :       aData->ValueForLang()->SetStringValue(value->GetStringValue(),
    1835               0 :                                             eCSSUnit_Ident);
    1836                 :     }
    1837                 :   }
    1838               0 : }
    1839                 : 
    1840                 : void
    1841               0 : nsGenericHTMLElement::MapCommonAttributesInto(const nsMappedAttributes* aAttributes,
    1842                 :                                               nsRuleData* aData)
    1843                 : {
    1844               0 :   nsGenericHTMLElement::MapCommonAttributesExceptHiddenInto(aAttributes, aData);
    1845                 : 
    1846               0 :   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Display)) {
    1847               0 :     nsCSSValue* display = aData->ValueForDisplay();
    1848               0 :     if (display->GetUnit() == eCSSUnit_Null) {
    1849               0 :       if (aAttributes->IndexOfAttr(nsGkAtoms::hidden, kNameSpaceID_None) >= 0) {
    1850               0 :         display->SetIntValue(NS_STYLE_DISPLAY_NONE, eCSSUnit_Enumerated);
    1851                 :       }
    1852                 :     }
    1853                 :   }
    1854               0 : }
    1855                 : 
    1856                 : void
    1857               1 : nsGenericHTMLFormElement::UpdateEditableFormControlState(bool aNotify)
    1858                 : {
    1859                 :   // nsCSSFrameConstructor::MaybeConstructLazily is based on the logic of this
    1860                 :   // function, so should be kept in sync with that.
    1861                 : 
    1862               1 :   ContentEditableTristate value = GetContentEditableValue();
    1863               1 :   if (value != eInherit) {
    1864               0 :     DoSetEditableFlag(!!value, aNotify);
    1865               0 :     return;
    1866                 :   }
    1867                 : 
    1868               1 :   nsIContent *parent = GetParent();
    1869                 : 
    1870               1 :   if (parent && parent->HasFlag(NODE_IS_EDITABLE)) {
    1871               0 :     DoSetEditableFlag(true, aNotify);
    1872               0 :     return;
    1873                 :   }
    1874                 : 
    1875               1 :   if (!IsTextControl(false)) {
    1876               0 :     DoSetEditableFlag(false, aNotify);
    1877               0 :     return;
    1878                 :   }
    1879                 : 
    1880                 :   // If not contentEditable we still need to check the readonly attribute.
    1881                 :   bool roState;
    1882               1 :   GetBoolAttr(nsGkAtoms::readonly, &roState);
    1883                 : 
    1884               1 :   DoSetEditableFlag(!roState, aNotify);
    1885                 : }
    1886                 : 
    1887                 : 
    1888                 : /* static */ const nsGenericHTMLElement::MappedAttributeEntry
    1889                 : nsGenericHTMLElement::sCommonAttributeMap[] = {
    1890                 :   { &nsGkAtoms::contenteditable },
    1891                 :   { &nsGkAtoms::lang },
    1892                 :   { &nsGkAtoms::hidden },
    1893                 :   { nsnull }
    1894                 : };
    1895                 : 
    1896                 : /* static */ const nsGenericElement::MappedAttributeEntry
    1897                 : nsGenericHTMLElement::sImageMarginSizeAttributeMap[] = {
    1898                 :   { &nsGkAtoms::width },
    1899                 :   { &nsGkAtoms::height },
    1900                 :   { &nsGkAtoms::hspace },
    1901                 :   { &nsGkAtoms::vspace },
    1902                 :   { nsnull }
    1903                 : };
    1904                 : 
    1905                 : /* static */ const nsGenericElement::MappedAttributeEntry
    1906                 : nsGenericHTMLElement::sImageAlignAttributeMap[] = {
    1907                 :   { &nsGkAtoms::align },
    1908                 :   { nsnull }
    1909                 : };
    1910                 : 
    1911                 : /* static */ const nsGenericElement::MappedAttributeEntry
    1912                 : nsGenericHTMLElement::sDivAlignAttributeMap[] = {
    1913                 :   { &nsGkAtoms::align },
    1914                 :   { nsnull }
    1915                 : };
    1916                 : 
    1917                 : /* static */ const nsGenericElement::MappedAttributeEntry
    1918                 : nsGenericHTMLElement::sImageBorderAttributeMap[] = {
    1919                 :   { &nsGkAtoms::border },
    1920                 :   { nsnull }
    1921                 : };
    1922                 : 
    1923                 : /* static */ const nsGenericElement::MappedAttributeEntry
    1924                 : nsGenericHTMLElement::sBackgroundAttributeMap[] = {
    1925                 :   { &nsGkAtoms::background },
    1926                 :   { &nsGkAtoms::bgcolor },
    1927                 :   { nsnull }
    1928                 : };
    1929                 : 
    1930                 : /* static */ const nsGenericElement::MappedAttributeEntry
    1931                 : nsGenericHTMLElement::sBackgroundColorAttributeMap[] = {
    1932                 :   { &nsGkAtoms::bgcolor },
    1933                 :   { nsnull }
    1934                 : };
    1935                 : 
    1936                 : /* static */ const nsGenericElement::MappedAttributeEntry
    1937                 : nsGenericHTMLElement::sScrollingAttributeMap[] = {
    1938                 :   { &nsGkAtoms::scrolling },
    1939                 :   { nsnull }
    1940                 : };
    1941                 : 
    1942                 : void
    1943               0 : nsGenericHTMLElement::MapImageAlignAttributeInto(const nsMappedAttributes* aAttributes,
    1944                 :                                                  nsRuleData* aRuleData)
    1945                 : {
    1946               0 :   if (aRuleData->mSIDs & (NS_STYLE_INHERIT_BIT(Display) |
    1947                 :                           NS_STYLE_INHERIT_BIT(TextReset))) {
    1948               0 :     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align);
    1949               0 :     if (value && value->Type() == nsAttrValue::eEnum) {
    1950               0 :       PRInt32 align = value->GetEnumValue();
    1951               0 :       if (aRuleData->mSIDs & NS_STYLE_INHERIT_BIT(Display)) {
    1952               0 :         nsCSSValue* cssFloat = aRuleData->ValueForCssFloat();
    1953               0 :         if (cssFloat->GetUnit() == eCSSUnit_Null) {
    1954               0 :           if (align == NS_STYLE_TEXT_ALIGN_LEFT) {
    1955               0 :             cssFloat->SetIntValue(NS_STYLE_FLOAT_LEFT, eCSSUnit_Enumerated);
    1956               0 :           } else if (align == NS_STYLE_TEXT_ALIGN_RIGHT) {
    1957               0 :             cssFloat->SetIntValue(NS_STYLE_FLOAT_RIGHT, eCSSUnit_Enumerated);
    1958                 :           }
    1959                 :         }
    1960                 :       }
    1961               0 :       if (aRuleData->mSIDs & NS_STYLE_INHERIT_BIT(TextReset)) {
    1962               0 :         nsCSSValue* verticalAlign = aRuleData->ValueForVerticalAlign();
    1963               0 :         if (verticalAlign->GetUnit() == eCSSUnit_Null) {
    1964               0 :           switch (align) {
    1965                 :           case NS_STYLE_TEXT_ALIGN_LEFT:
    1966                 :           case NS_STYLE_TEXT_ALIGN_RIGHT:
    1967               0 :             break;
    1968                 :           default:
    1969               0 :             verticalAlign->SetIntValue(align, eCSSUnit_Enumerated);
    1970               0 :             break;
    1971                 :           }
    1972                 :         }
    1973                 :       }
    1974                 :     }
    1975                 :   }
    1976               0 : }
    1977                 : 
    1978                 : void
    1979               0 : nsGenericHTMLElement::MapDivAlignAttributeInto(const nsMappedAttributes* aAttributes,
    1980                 :                                                nsRuleData* aRuleData)
    1981                 : {
    1982               0 :   if (aRuleData->mSIDs & NS_STYLE_INHERIT_BIT(Text)) {
    1983               0 :     nsCSSValue* textAlign = aRuleData->ValueForTextAlign();
    1984               0 :     if (textAlign->GetUnit() == eCSSUnit_Null) {
    1985                 :       // align: enum
    1986               0 :       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align);
    1987               0 :       if (value && value->Type() == nsAttrValue::eEnum)
    1988               0 :         textAlign->SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated);
    1989                 :     }
    1990                 :   }
    1991               0 : }
    1992                 : 
    1993                 : 
    1994                 : void
    1995               0 : nsGenericHTMLElement::MapImageMarginAttributeInto(const nsMappedAttributes* aAttributes,
    1996                 :                                                   nsRuleData* aData)
    1997                 : {
    1998               0 :   if (!(aData->mSIDs & NS_STYLE_INHERIT_BIT(Margin)))
    1999               0 :     return;
    2000                 : 
    2001                 :   const nsAttrValue* value;
    2002                 : 
    2003                 :   // hspace: value
    2004               0 :   value = aAttributes->GetAttr(nsGkAtoms::hspace);
    2005               0 :   if (value) {
    2006               0 :     nsCSSValue hval;
    2007               0 :     if (value->Type() == nsAttrValue::eInteger)
    2008               0 :       hval.SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
    2009               0 :     else if (value->Type() == nsAttrValue::ePercent)
    2010               0 :       hval.SetPercentValue(value->GetPercentValue());
    2011                 : 
    2012               0 :     if (hval.GetUnit() != eCSSUnit_Null) {
    2013               0 :       nsCSSValue* left = aData->ValueForMarginLeftValue();
    2014               0 :       if (left->GetUnit() == eCSSUnit_Null)
    2015               0 :         *left = hval;
    2016               0 :       nsCSSValue* right = aData->ValueForMarginRightValue();
    2017               0 :       if (right->GetUnit() == eCSSUnit_Null)
    2018               0 :         *right = hval;
    2019                 :     }
    2020                 :   }
    2021                 : 
    2022                 :   // vspace: value
    2023               0 :   value = aAttributes->GetAttr(nsGkAtoms::vspace);
    2024               0 :   if (value) {
    2025               0 :     nsCSSValue vval;
    2026               0 :     if (value->Type() == nsAttrValue::eInteger)
    2027               0 :       vval.SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
    2028               0 :     else if (value->Type() == nsAttrValue::ePercent)
    2029               0 :       vval.SetPercentValue(value->GetPercentValue());
    2030                 :   
    2031               0 :     if (vval.GetUnit() != eCSSUnit_Null) {
    2032               0 :       nsCSSValue* top = aData->ValueForMarginTop();
    2033               0 :       if (top->GetUnit() == eCSSUnit_Null)
    2034               0 :         *top = vval;
    2035               0 :       nsCSSValue* bottom = aData->ValueForMarginBottom();
    2036               0 :       if (bottom->GetUnit() == eCSSUnit_Null)
    2037               0 :         *bottom = vval;
    2038                 :     }
    2039                 :   }
    2040                 : }
    2041                 : 
    2042                 : void
    2043               0 : nsGenericHTMLElement::MapImageSizeAttributesInto(const nsMappedAttributes* aAttributes,
    2044                 :                                                  nsRuleData* aData)
    2045                 : {
    2046               0 :   if (!(aData->mSIDs & NS_STYLE_INHERIT_BIT(Position)))
    2047               0 :     return;
    2048                 : 
    2049                 :   // width: value
    2050               0 :   nsCSSValue* width = aData->ValueForWidth();
    2051               0 :   if (width->GetUnit() == eCSSUnit_Null) {
    2052               0 :     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
    2053               0 :     if (value && value->Type() == nsAttrValue::eInteger)
    2054               0 :       width->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
    2055               0 :     else if (value && value->Type() == nsAttrValue::ePercent)
    2056               0 :       width->SetPercentValue(value->GetPercentValue());
    2057                 :   }
    2058                 : 
    2059                 :   // height: value
    2060               0 :   nsCSSValue* height = aData->ValueForHeight();
    2061               0 :   if (height->GetUnit() == eCSSUnit_Null) {
    2062               0 :     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::height);
    2063               0 :     if (value && value->Type() == nsAttrValue::eInteger)
    2064               0 :       height->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel); 
    2065               0 :     else if (value && value->Type() == nsAttrValue::ePercent)
    2066               0 :       height->SetPercentValue(value->GetPercentValue());
    2067                 :   }
    2068                 : }
    2069                 : 
    2070                 : void
    2071               0 : nsGenericHTMLElement::MapImageBorderAttributeInto(const nsMappedAttributes* aAttributes,
    2072                 :                                                   nsRuleData* aData)
    2073                 : {
    2074               0 :   if (!(aData->mSIDs & NS_STYLE_INHERIT_BIT(Border)))
    2075               0 :     return;
    2076                 : 
    2077                 :   // border: pixels
    2078               0 :   const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::border);
    2079               0 :   if (!value)
    2080               0 :     return;
    2081                 :   
    2082               0 :   nscoord val = 0;
    2083               0 :   if (value->Type() == nsAttrValue::eInteger)
    2084               0 :     val = value->GetIntegerValue();
    2085                 : 
    2086               0 :   nsCSSValue* borderLeftWidth = aData->ValueForBorderLeftWidthValue();
    2087               0 :   if (borderLeftWidth->GetUnit() == eCSSUnit_Null)
    2088               0 :     borderLeftWidth->SetFloatValue((float)val, eCSSUnit_Pixel);
    2089               0 :   nsCSSValue* borderTopWidth = aData->ValueForBorderTopWidth();
    2090               0 :   if (borderTopWidth->GetUnit() == eCSSUnit_Null)
    2091               0 :     borderTopWidth->SetFloatValue((float)val, eCSSUnit_Pixel);
    2092               0 :   nsCSSValue* borderRightWidth = aData->ValueForBorderRightWidthValue();
    2093               0 :   if (borderRightWidth->GetUnit() == eCSSUnit_Null)
    2094               0 :     borderRightWidth->SetFloatValue((float)val, eCSSUnit_Pixel);
    2095               0 :   nsCSSValue* borderBottomWidth = aData->ValueForBorderBottomWidth();
    2096               0 :   if (borderBottomWidth->GetUnit() == eCSSUnit_Null)
    2097               0 :     borderBottomWidth->SetFloatValue((float)val, eCSSUnit_Pixel);
    2098                 : 
    2099               0 :   nsCSSValue* borderLeftStyle = aData->ValueForBorderLeftStyleValue();
    2100               0 :   if (borderLeftStyle->GetUnit() == eCSSUnit_Null)
    2101               0 :     borderLeftStyle->SetIntValue(NS_STYLE_BORDER_STYLE_SOLID, eCSSUnit_Enumerated);
    2102               0 :   nsCSSValue* borderTopStyle = aData->ValueForBorderTopStyle();
    2103               0 :   if (borderTopStyle->GetUnit() == eCSSUnit_Null)
    2104               0 :     borderTopStyle->SetIntValue(NS_STYLE_BORDER_STYLE_SOLID, eCSSUnit_Enumerated);
    2105               0 :   nsCSSValue* borderRightStyle = aData->ValueForBorderRightStyleValue();
    2106               0 :   if (borderRightStyle->GetUnit() == eCSSUnit_Null)
    2107               0 :     borderRightStyle->SetIntValue(NS_STYLE_BORDER_STYLE_SOLID, eCSSUnit_Enumerated);
    2108               0 :   nsCSSValue* borderBottomStyle = aData->ValueForBorderBottomStyle();
    2109               0 :   if (borderBottomStyle->GetUnit() == eCSSUnit_Null)
    2110               0 :     borderBottomStyle->SetIntValue(NS_STYLE_BORDER_STYLE_SOLID, eCSSUnit_Enumerated);
    2111                 : 
    2112               0 :   nsCSSValue* borderLeftColor = aData->ValueForBorderLeftColorValue();
    2113               0 :   if (borderLeftColor->GetUnit() == eCSSUnit_Null)
    2114               0 :     borderLeftColor->SetIntValue(NS_STYLE_COLOR_MOZ_USE_TEXT_COLOR, eCSSUnit_Enumerated);
    2115               0 :   nsCSSValue* borderTopColor = aData->ValueForBorderTopColor();
    2116               0 :   if (borderTopColor->GetUnit() == eCSSUnit_Null)
    2117               0 :     borderTopColor->SetIntValue(NS_STYLE_COLOR_MOZ_USE_TEXT_COLOR, eCSSUnit_Enumerated);
    2118               0 :   nsCSSValue* borderRightColor = aData->ValueForBorderRightColorValue();
    2119               0 :   if (borderRightColor->GetUnit() == eCSSUnit_Null)
    2120               0 :     borderRightColor->SetIntValue(NS_STYLE_COLOR_MOZ_USE_TEXT_COLOR, eCSSUnit_Enumerated);
    2121               0 :   nsCSSValue* borderBottomColor = aData->ValueForBorderBottomColor();
    2122               0 :   if (borderBottomColor->GetUnit() == eCSSUnit_Null)
    2123               0 :     borderBottomColor->SetIntValue(NS_STYLE_COLOR_MOZ_USE_TEXT_COLOR, eCSSUnit_Enumerated);
    2124                 : }
    2125                 : 
    2126                 : void
    2127               0 : nsGenericHTMLElement::MapBackgroundInto(const nsMappedAttributes* aAttributes,
    2128                 :                                         nsRuleData* aData)
    2129                 : {
    2130               0 :   if (!(aData->mSIDs & NS_STYLE_INHERIT_BIT(Background)))
    2131               0 :     return;
    2132                 : 
    2133               0 :   nsPresContext* presContext = aData->mPresContext;
    2134               0 :   nsCSSValue* backImage = aData->ValueForBackgroundImage();
    2135               0 :   if (backImage->GetUnit() == eCSSUnit_Null &&
    2136               0 :       presContext->UseDocumentColors()) {
    2137                 :     // background
    2138               0 :     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::background);
    2139               0 :     if (value && value->Type() == nsAttrValue::eString) {
    2140               0 :       const nsString& spec = value->GetStringValue();
    2141               0 :       if (!spec.IsEmpty()) {
    2142                 :         // Resolve url to an absolute url
    2143                 :         // XXX this breaks if the HTML element has an xml:base
    2144                 :         // attribute (the xml:base will not be taken into account)
    2145                 :         // as well as elements with _baseHref set. We need to be able
    2146                 :         // to get to the element somehow, or store the base URI in the
    2147                 :         // attributes.
    2148               0 :         nsIDocument* doc = presContext->Document();
    2149               0 :         nsCOMPtr<nsIURI> uri;
    2150                 :         nsresult rv = nsContentUtils::NewURIWithDocumentCharset(
    2151               0 :             getter_AddRefs(uri), spec, doc, doc->GetDocBaseURI());
    2152               0 :         if (NS_SUCCEEDED(rv)) {
    2153                 :           // Note that this should generally succeed here, due to the way
    2154                 :           // |spec| is created.  Maybe we should just add an nsStringBuffer
    2155                 :           // accessor on nsAttrValue?
    2156               0 :           nsRefPtr<nsStringBuffer> buffer = nsCSSValue::BufferFromString(spec);
    2157               0 :           if (NS_LIKELY(buffer)) {
    2158                 :             // XXXbz it would be nice to assert that doc->NodePrincipal() is
    2159                 :             // the same as the principal of the node (which we'd need to store
    2160                 :             // in the mapped attrs or something?)
    2161                 :             nsCSSValue::Image *img =
    2162                 :               new nsCSSValue::Image(uri, buffer, doc->GetDocumentURI(),
    2163               0 :                                     doc->NodePrincipal(), doc);
    2164               0 :             if (NS_LIKELY(img)) {
    2165               0 :               nsCSSValueList* list = backImage->SetListValue();
    2166               0 :               list->mValue.SetImageValue(img);
    2167                 :             }
    2168                 :           }
    2169                 :         }
    2170                 :       }
    2171               0 :       else if (presContext->CompatibilityMode() == eCompatibility_NavQuirks) {
    2172                 :         // in NavQuirks mode, allow the empty string to set the
    2173                 :         // background to empty
    2174               0 :         nsCSSValueList* list = backImage->SetListValue();
    2175               0 :         list->mValue.SetNoneValue();
    2176                 :       }
    2177                 :     }
    2178                 :   }
    2179                 : }
    2180                 : 
    2181                 : void
    2182               0 : nsGenericHTMLElement::MapBGColorInto(const nsMappedAttributes* aAttributes,
    2183                 :                                      nsRuleData* aData)
    2184                 : {
    2185               0 :   if (!(aData->mSIDs & NS_STYLE_INHERIT_BIT(Background)))
    2186               0 :     return;
    2187                 : 
    2188               0 :   nsCSSValue* backColor = aData->ValueForBackgroundColor();
    2189               0 :   if (backColor->GetUnit() == eCSSUnit_Null &&
    2190               0 :       aData->mPresContext->UseDocumentColors()) {
    2191               0 :     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::bgcolor);
    2192                 :     nscolor color;
    2193               0 :     if (value && value->GetColorValue(color)) {
    2194               0 :       backColor->SetColorValue(color);
    2195                 :     }
    2196                 :   }
    2197                 : }
    2198                 : 
    2199                 : void
    2200               0 : nsGenericHTMLElement::MapBackgroundAttributesInto(const nsMappedAttributes* aAttributes,
    2201                 :                                                   nsRuleData* aData)
    2202                 : {
    2203               0 :   MapBackgroundInto(aAttributes, aData);
    2204               0 :   MapBGColorInto(aAttributes, aData);
    2205               0 : }
    2206                 : 
    2207                 : void
    2208               0 : nsGenericHTMLElement::MapScrollingAttributeInto(const nsMappedAttributes* aAttributes,
    2209                 :                                                 nsRuleData* aData)
    2210                 : {
    2211               0 :   if (!(aData->mSIDs & NS_STYLE_INHERIT_BIT(Display)))
    2212               0 :     return;
    2213                 : 
    2214                 :   // scrolling
    2215                 :   nsCSSValue* overflowValues[2] = {
    2216               0 :     aData->ValueForOverflowX(),
    2217               0 :     aData->ValueForOverflowY(),
    2218               0 :   };
    2219               0 :   for (PRUint32 i = 0; i < ArrayLength(overflowValues); ++i) {
    2220               0 :     if (overflowValues[i]->GetUnit() == eCSSUnit_Null) {
    2221               0 :       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::scrolling);
    2222               0 :       if (value && value->Type() == nsAttrValue::eEnum) {
    2223                 :         PRInt32 mappedValue;
    2224               0 :         switch (value->GetEnumValue()) {
    2225                 :           case NS_STYLE_FRAME_ON:
    2226                 :           case NS_STYLE_FRAME_SCROLL:
    2227                 :           case NS_STYLE_FRAME_YES:
    2228               0 :             mappedValue = NS_STYLE_OVERFLOW_SCROLL;
    2229               0 :             break;
    2230                 : 
    2231                 :           case NS_STYLE_FRAME_OFF:
    2232                 :           case NS_STYLE_FRAME_NOSCROLL:
    2233                 :           case NS_STYLE_FRAME_NO:
    2234               0 :             mappedValue = NS_STYLE_OVERFLOW_HIDDEN;
    2235               0 :             break;
    2236                 :         
    2237                 :           case NS_STYLE_FRAME_AUTO:
    2238               0 :             mappedValue = NS_STYLE_OVERFLOW_AUTO;
    2239               0 :             break;
    2240                 : 
    2241                 :           default:
    2242               0 :             NS_NOTREACHED("unexpected value");
    2243               0 :             mappedValue = NS_STYLE_OVERFLOW_AUTO;
    2244               0 :             break;
    2245                 :         }
    2246               0 :         overflowValues[i]->SetIntValue(mappedValue, eCSSUnit_Enumerated);
    2247                 :       }
    2248                 :     }
    2249                 :   }
    2250                 : }
    2251                 : 
    2252                 : //----------------------------------------------------------------------
    2253                 : 
    2254                 : nsresult
    2255               1 : nsGenericHTMLElement::GetAttrHelper(nsIAtom* aAttr, nsAString& aValue)
    2256                 : {
    2257               1 :   GetAttr(kNameSpaceID_None, aAttr, aValue);
    2258               1 :   return NS_OK;
    2259                 : }
    2260                 : 
    2261                 : nsresult
    2262               0 : nsGenericHTMLElement::SetAttrHelper(nsIAtom* aAttr, const nsAString& aValue)
    2263                 : {
    2264               0 :   return SetAttr(kNameSpaceID_None, aAttr, aValue, true);
    2265                 : }
    2266                 : 
    2267                 : nsresult
    2268               0 : nsGenericHTMLElement::SetBoolAttr(nsIAtom* aAttr, bool aValue)
    2269                 : {
    2270               0 :   if (aValue) {
    2271               0 :     return SetAttr(kNameSpaceID_None, aAttr, EmptyString(), true);
    2272                 :   }
    2273                 : 
    2274               0 :   return UnsetAttr(kNameSpaceID_None, aAttr, true);
    2275                 : }
    2276                 : 
    2277                 : nsresult
    2278               1 : nsGenericHTMLElement::GetBoolAttr(nsIAtom* aAttr, bool* aValue) const
    2279                 : {
    2280               1 :   *aValue = HasAttr(kNameSpaceID_None, aAttr);
    2281               1 :   return NS_OK;
    2282                 : }
    2283                 : 
    2284                 : nsresult
    2285               0 : nsGenericHTMLElement::GetIntAttr(nsIAtom* aAttr, PRInt32 aDefault, PRInt32* aResult)
    2286                 : {
    2287               0 :   const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(aAttr);
    2288               0 :   if (attrVal && attrVal->Type() == nsAttrValue::eInteger) {
    2289               0 :     *aResult = attrVal->GetIntegerValue();
    2290                 :   }
    2291                 :   else {
    2292               0 :     *aResult = aDefault;
    2293                 :   }
    2294               0 :   return NS_OK;
    2295                 : }
    2296                 : 
    2297                 : nsresult
    2298               0 : nsGenericHTMLElement::SetIntAttr(nsIAtom* aAttr, PRInt32 aValue)
    2299                 : {
    2300               0 :   nsAutoString value;
    2301               0 :   value.AppendInt(aValue);
    2302                 : 
    2303               0 :   return SetAttr(kNameSpaceID_None, aAttr, value, true);
    2304                 : }
    2305                 : 
    2306                 : nsresult
    2307               0 : nsGenericHTMLElement::GetUnsignedIntAttr(nsIAtom* aAttr, PRUint32 aDefault,
    2308                 :                                          PRUint32* aResult)
    2309                 : {
    2310               0 :   const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(aAttr);
    2311               0 :   if (attrVal && attrVal->Type() == nsAttrValue::eInteger) {
    2312               0 :     *aResult = attrVal->GetIntegerValue();
    2313                 :   }
    2314                 :   else {
    2315               0 :     *aResult = aDefault;
    2316                 :   }
    2317               0 :   return NS_OK;
    2318                 : }
    2319                 : 
    2320                 : nsresult
    2321               0 : nsGenericHTMLElement::SetUnsignedIntAttr(nsIAtom* aAttr, PRUint32 aValue)
    2322                 : {
    2323               0 :   nsAutoString value;
    2324               0 :   value.AppendInt(aValue);
    2325                 : 
    2326               0 :   return SetAttr(kNameSpaceID_None, aAttr, value, true);
    2327                 : }
    2328                 : 
    2329                 : nsresult
    2330               0 : nsGenericHTMLElement::GetDoubleAttr(nsIAtom* aAttr, double aDefault, double* aResult)
    2331                 : {
    2332               0 :   const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(aAttr);
    2333               0 :   if (attrVal && attrVal->Type() == nsAttrValue::eDoubleValue) {
    2334               0 :     *aResult = attrVal->GetDoubleValue();
    2335                 :   }
    2336                 :   else {
    2337               0 :     *aResult = aDefault;
    2338                 :   }
    2339               0 :   return NS_OK;
    2340                 : }
    2341                 : 
    2342                 : nsresult
    2343               0 : nsGenericHTMLElement::SetDoubleAttr(nsIAtom* aAttr, double aValue)
    2344                 : {
    2345               0 :   nsAutoString value;
    2346               0 :   value.AppendFloat(aValue);
    2347                 : 
    2348               0 :   return SetAttr(kNameSpaceID_None, aAttr, value, true);
    2349                 : }
    2350                 : 
    2351                 : nsresult
    2352               0 : nsGenericHTMLElement::GetURIAttr(nsIAtom* aAttr, nsIAtom* aBaseAttr, nsAString& aResult)
    2353                 : {
    2354               0 :   nsCOMPtr<nsIURI> uri;
    2355               0 :   bool hadAttr = GetURIAttr(aAttr, aBaseAttr, getter_AddRefs(uri));
    2356               0 :   if (!hadAttr) {
    2357               0 :     aResult.Truncate();
    2358               0 :     return NS_OK;
    2359                 :   }
    2360                 : 
    2361               0 :   if (!uri) {
    2362                 :     // Just return the attr value
    2363               0 :     GetAttr(kNameSpaceID_None, aAttr, aResult);
    2364               0 :     return NS_OK;
    2365                 :   }
    2366                 : 
    2367               0 :   nsCAutoString spec;
    2368               0 :   uri->GetSpec(spec);
    2369               0 :   CopyUTF8toUTF16(spec, aResult);
    2370               0 :   return NS_OK;
    2371                 : }
    2372                 : 
    2373                 : bool
    2374               0 : nsGenericHTMLElement::GetURIAttr(nsIAtom* aAttr, nsIAtom* aBaseAttr, nsIURI** aURI) const
    2375                 : {
    2376               0 :   *aURI = nsnull;
    2377                 : 
    2378               0 :   const nsAttrValue* attr = mAttrsAndChildren.GetAttr(aAttr);
    2379               0 :   if (!attr) {
    2380               0 :     return false;
    2381                 :   }
    2382                 : 
    2383               0 :   nsCOMPtr<nsIURI> baseURI = GetBaseURI();
    2384                 : 
    2385               0 :   if (aBaseAttr) {
    2386               0 :     nsAutoString baseAttrValue;
    2387               0 :     if (GetAttr(kNameSpaceID_None, aBaseAttr, baseAttrValue)) {
    2388               0 :       nsCOMPtr<nsIURI> baseAttrURI;
    2389                 :       nsresult rv =
    2390               0 :         nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(baseAttrURI),
    2391                 :                                                   baseAttrValue, OwnerDoc(),
    2392               0 :                                                   baseURI);
    2393               0 :       if (NS_FAILED(rv)) {
    2394               0 :         return true;
    2395                 :       }
    2396               0 :       baseURI.swap(baseAttrURI);
    2397                 :     }
    2398                 :   }
    2399                 : 
    2400                 :   // Don't care about return value.  If it fails, we still want to
    2401                 :   // return true, and *aURI will be null.
    2402                 :   nsContentUtils::NewURIWithDocumentCharset(aURI,
    2403               0 :                                             attr->GetStringValue(),
    2404               0 :                                             OwnerDoc(), baseURI);
    2405               0 :   return true;
    2406                 : }
    2407                 : 
    2408                 : nsresult
    2409               0 : nsGenericHTMLElement::GetURIListAttr(nsIAtom* aAttr, nsAString& aResult)
    2410                 : {
    2411               0 :   aResult.Truncate();
    2412                 : 
    2413               0 :   nsAutoString value;
    2414               0 :   if (!GetAttr(kNameSpaceID_None, aAttr, value))
    2415               0 :     return NS_OK;
    2416                 : 
    2417               0 :   nsIDocument* doc = OwnerDoc(); 
    2418               0 :   nsCOMPtr<nsIURI> baseURI = GetBaseURI();
    2419                 : 
    2420                 :   // Value contains relative URIs split on spaces (U+0020)
    2421               0 :   const PRUnichar *start = value.BeginReading();
    2422               0 :   const PRUnichar *end   = value.EndReading();
    2423               0 :   const PRUnichar *iter  = start;
    2424               0 :   for (;;) {
    2425               0 :     if (iter < end && *iter != ' ') {
    2426               0 :       ++iter;
    2427                 :     } else {  // iter is pointing at either end or a space
    2428               0 :       while (*start == ' ' && start < iter)
    2429               0 :         ++start;
    2430               0 :       if (iter != start) {
    2431               0 :         if (!aResult.IsEmpty())
    2432               0 :           aResult.Append(PRUnichar(' '));
    2433               0 :         const nsSubstring& uriPart = Substring(start, iter);
    2434               0 :         nsCOMPtr<nsIURI> attrURI;
    2435               0 :         nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(attrURI),
    2436               0 :                                                   uriPart, doc, baseURI);
    2437               0 :         if (attrURI) {
    2438               0 :           nsCAutoString spec;
    2439               0 :           attrURI->GetSpec(spec);
    2440               0 :           AppendUTF8toUTF16(spec, aResult);
    2441                 :         } else {
    2442               0 :           aResult.Append(uriPart);
    2443                 :         }
    2444                 :       }
    2445               0 :       start = iter = iter + 1;
    2446               0 :       if (iter >= end)
    2447                 :         break;
    2448                 :     }
    2449                 :   }
    2450                 : 
    2451               0 :   return NS_OK;
    2452                 : }
    2453                 : 
    2454                 : nsresult
    2455               0 : nsGenericHTMLElement::GetEnumAttr(nsIAtom* aAttr,
    2456                 :                                   const char* aDefault,
    2457                 :                                   nsAString& aResult)
    2458                 : {
    2459               0 :   const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(aAttr);
    2460                 : 
    2461               0 :   aResult.Truncate();
    2462                 : 
    2463               0 :   if (attrVal && attrVal->Type() == nsAttrValue::eEnum) {
    2464               0 :     attrVal->GetEnumString(aResult, true);
    2465               0 :   } else if (aDefault) {
    2466               0 :     AppendASCIItoUTF16(nsDependentCString(aDefault), aResult);
    2467                 :   }
    2468                 : 
    2469               0 :   return NS_OK;
    2470                 : }
    2471                 : 
    2472                 : nsresult
    2473               0 : nsGenericHTMLElement::GetContentEditable(nsAString& aContentEditable)
    2474                 : {
    2475               0 :   ContentEditableTristate value = GetContentEditableValue();
    2476                 : 
    2477               0 :   if (value == eTrue) {
    2478               0 :     aContentEditable.AssignLiteral("true");
    2479                 :   }
    2480               0 :   else if (value == eFalse) {
    2481               0 :     aContentEditable.AssignLiteral("false");
    2482                 :   }
    2483                 :   else {
    2484               0 :     aContentEditable.AssignLiteral("inherit");
    2485                 :   }
    2486                 : 
    2487               0 :   return NS_OK;
    2488                 : }
    2489                 : 
    2490                 : nsresult
    2491               0 : nsGenericHTMLElement::SetContentEditable(const nsAString& aContentEditable)
    2492                 : {
    2493               0 :   if (nsContentUtils::EqualsLiteralIgnoreASCIICase(aContentEditable, "inherit")) {
    2494               0 :     UnsetAttr(kNameSpaceID_None, nsGkAtoms::contenteditable, true);
    2495                 : 
    2496               0 :     return NS_OK;
    2497                 :   }
    2498                 : 
    2499               0 :   if (nsContentUtils::EqualsLiteralIgnoreASCIICase(aContentEditable, "true")) {
    2500               0 :     SetAttr(kNameSpaceID_None, nsGkAtoms::contenteditable, NS_LITERAL_STRING("true"), true);
    2501                 :     
    2502               0 :     return NS_OK;
    2503                 :   }
    2504                 :   
    2505               0 :   if (nsContentUtils::EqualsLiteralIgnoreASCIICase(aContentEditable, "false")) {
    2506               0 :     SetAttr(kNameSpaceID_None, nsGkAtoms::contenteditable, NS_LITERAL_STRING("false"), true);
    2507                 : 
    2508               0 :     return NS_OK;
    2509                 :   }
    2510                 : 
    2511               0 :   return NS_ERROR_DOM_SYNTAX_ERR;
    2512                 : }
    2513                 : 
    2514                 : nsresult
    2515               0 : nsGenericHTMLElement::GetIsContentEditable(bool* aContentEditable)
    2516                 : {
    2517               0 :   NS_ENSURE_ARG_POINTER(aContentEditable);
    2518                 : 
    2519               0 :   for (nsIContent* node = this; node; node = node->GetParent()) {
    2520               0 :     nsGenericHTMLElement* element = FromContent(node);
    2521               0 :     if (element) {
    2522               0 :       ContentEditableTristate value = element->GetContentEditableValue();
    2523               0 :       if (value != eInherit) {
    2524               0 :         *aContentEditable = value == eTrue;
    2525               0 :         return NS_OK;
    2526                 :       }
    2527                 :     }
    2528                 :   }
    2529                 : 
    2530               0 :   *aContentEditable = false;
    2531               0 :   return NS_OK;
    2532                 : }
    2533                 : 
    2534                 : nsresult
    2535               0 : nsGenericHTMLElement::GetContextMenu(nsIDOMHTMLMenuElement** aContextMenu)
    2536                 : {
    2537               0 :   *aContextMenu = nsnull;
    2538                 : 
    2539               0 :   nsAutoString value;
    2540               0 :   GetAttr(kNameSpaceID_None, nsGkAtoms::contextmenu, value);
    2541                 : 
    2542               0 :   if (value.IsEmpty()) {
    2543               0 :     return NS_OK;
    2544                 :   }
    2545                 : 
    2546               0 :   nsIDocument* doc = GetCurrentDoc();
    2547               0 :   if (doc) {
    2548                 :     nsRefPtr<nsHTMLMenuElement> element =
    2549               0 :       nsHTMLMenuElement::FromContent(doc->GetElementById(value));
    2550               0 :     element.forget(aContextMenu);
    2551                 :   }
    2552                 : 
    2553               0 :   return NS_OK;
    2554                 : }
    2555                 : 
    2556                 : //----------------------------------------------------------------------
    2557                 : 
    2558               1 : nsGenericHTMLFormElement::nsGenericHTMLFormElement(already_AddRefed<nsINodeInfo> aNodeInfo)
    2559                 :   : nsGenericHTMLElement(aNodeInfo)
    2560                 :   , mForm(nsnull)
    2561               1 :   , mFieldSet(nsnull)
    2562                 : {
    2563                 :   // We should add the NS_EVENT_STATE_ENABLED bit here as needed, but
    2564                 :   // that depends on our type, which is not initialized yet.  So we
    2565                 :   // have to do this in subclasses.
    2566               1 : }
    2567                 : 
    2568               2 : nsGenericHTMLFormElement::~nsGenericHTMLFormElement()
    2569                 : {
    2570               1 :   if (mFieldSet) {
    2571               0 :     mFieldSet->RemoveElement(this);
    2572                 :   }
    2573                 : 
    2574                 :   // Check that this element doesn't know anything about its form at this point.
    2575               1 :   NS_ASSERTION(!mForm, "mForm should be null at this point!");
    2576               2 : }
    2577                 : 
    2578              23 : NS_IMPL_QUERY_INTERFACE_INHERITED1(nsGenericHTMLFormElement,
    2579                 :                                    nsGenericHTMLElement,
    2580                 :                                    nsIFormControl)
    2581                 : 
    2582                 : bool
    2583               6 : nsGenericHTMLFormElement::IsNodeOfType(PRUint32 aFlags) const
    2584                 : {
    2585               6 :   return !(aFlags & ~(eCONTENT | eHTML_FORM_CONTROL));
    2586                 : }
    2587                 : 
    2588                 : void
    2589               0 : nsGenericHTMLFormElement::SaveSubtreeState()
    2590                 : {
    2591               0 :   SaveState();
    2592                 : 
    2593               0 :   nsGenericHTMLElement::SaveSubtreeState();
    2594               0 : }
    2595                 : 
    2596                 : void
    2597               0 : nsGenericHTMLFormElement::SetForm(nsIDOMHTMLFormElement* aForm)
    2598                 : {
    2599               0 :   NS_PRECONDITION(aForm, "Don't pass null here");
    2600               0 :   NS_ASSERTION(!mForm,
    2601                 :                "We don't support switching from one non-null form to another.");
    2602                 : 
    2603                 :   // keep a *weak* ref to the form here
    2604               0 :   mForm = static_cast<nsHTMLFormElement*>(aForm);
    2605               0 : }
    2606                 : 
    2607                 : void
    2608               0 : nsGenericHTMLFormElement::ClearForm(bool aRemoveFromForm)
    2609                 : {
    2610               0 :   NS_ASSERTION((mForm != nsnull) == HasFlag(ADDED_TO_FORM),
    2611                 :                "Form control should have had flag set correctly");
    2612                 : 
    2613               0 :   if (!mForm) {
    2614               0 :     return;
    2615                 :   }
    2616                 :   
    2617               0 :   if (aRemoveFromForm) {
    2618               0 :     nsAutoString nameVal, idVal;
    2619               0 :     GetAttr(kNameSpaceID_None, nsGkAtoms::name, nameVal);
    2620               0 :     GetAttr(kNameSpaceID_None, nsGkAtoms::id, idVal);
    2621                 : 
    2622               0 :     mForm->RemoveElement(this, true);
    2623                 : 
    2624               0 :     if (!nameVal.IsEmpty()) {
    2625               0 :       mForm->RemoveElementFromTable(this, nameVal);
    2626                 :     }
    2627                 : 
    2628               0 :     if (!idVal.IsEmpty()) {
    2629               0 :       mForm->RemoveElementFromTable(this, idVal);
    2630                 :     }
    2631                 :   }
    2632                 : 
    2633               0 :   UnsetFlags(ADDED_TO_FORM);
    2634               0 :   mForm = nsnull;
    2635                 : }
    2636                 : 
    2637                 : Element*
    2638               1 : nsGenericHTMLFormElement::GetFormElement()
    2639                 : {
    2640               1 :   return mForm;
    2641                 : }
    2642                 : 
    2643                 : nsresult
    2644               0 : nsGenericHTMLFormElement::GetForm(nsIDOMHTMLFormElement** aForm)
    2645                 : {
    2646               0 :   NS_ENSURE_ARG_POINTER(aForm);
    2647               0 :   NS_IF_ADDREF(*aForm = mForm);
    2648               0 :   return NS_OK;
    2649                 : }
    2650                 : 
    2651                 : nsIContent::IMEState
    2652               0 : nsGenericHTMLFormElement::GetDesiredIMEState()
    2653                 : {
    2654               0 :   nsCOMPtr<nsIEditor> editor = nsnull;
    2655               0 :   nsresult rv = GetEditorInternal(getter_AddRefs(editor));
    2656               0 :   if (NS_FAILED(rv) || !editor)
    2657               0 :     return nsGenericHTMLElement::GetDesiredIMEState();
    2658               0 :   nsCOMPtr<nsIEditorIMESupport> imeEditor = do_QueryInterface(editor);
    2659               0 :   if (!imeEditor)
    2660               0 :     return nsGenericHTMLElement::GetDesiredIMEState();
    2661               0 :   IMEState state;
    2662               0 :   rv = imeEditor->GetPreferredIMEState(&state);
    2663               0 :   if (NS_FAILED(rv))
    2664               0 :     return nsGenericHTMLElement::GetDesiredIMEState();
    2665               0 :   return state;
    2666                 : }
    2667                 : 
    2668                 : nsresult
    2669               1 : nsGenericHTMLFormElement::BindToTree(nsIDocument* aDocument,
    2670                 :                                      nsIContent* aParent,
    2671                 :                                      nsIContent* aBindingParent,
    2672                 :                                      bool aCompileEventHandlers)
    2673                 : {
    2674                 :   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
    2675                 :                                                  aBindingParent,
    2676               1 :                                                  aCompileEventHandlers);
    2677               1 :   NS_ENSURE_SUCCESS(rv, rv);
    2678                 : 
    2679                 :   // An autofocus event has to be launched if the autofocus attribute is
    2680                 :   // specified and the element accept the autofocus attribute. In addition,
    2681                 :   // the document should not be already loaded and the "browser.autofocus"
    2682                 :   // preference should be 'true'.
    2683               1 :   if (IsAutofocusable() && HasAttr(kNameSpaceID_None, nsGkAtoms::autofocus) &&
    2684               0 :       Preferences::GetBool("browser.autofocus", true)) {
    2685               0 :     nsCOMPtr<nsIRunnable> event = new nsAutoFocusEvent(this);
    2686               0 :     rv = NS_DispatchToCurrentThread(event);
    2687               0 :     NS_ENSURE_SUCCESS(rv, rv);
    2688                 :   }
    2689                 : 
    2690                 :   // If @form is set, the element *has* to be in a document, otherwise it
    2691                 :   // wouldn't be possible to find an element with the corresponding id.
    2692                 :   // If @form isn't set, the element *has* to have a parent, otherwise it
    2693                 :   // wouldn't be possible to find a form ancestor.
    2694                 :   // We should not call UpdateFormOwner if none of these conditions are
    2695                 :   // fulfilled.
    2696               1 :   if (HasAttr(kNameSpaceID_None, nsGkAtoms::form) ? !!GetCurrentDoc()
    2697                 :                                                   : !!aParent) {
    2698               1 :     UpdateFormOwner(true, nsnull);
    2699                 :   }
    2700                 : 
    2701                 :   // Set parent fieldset which should be used for the disabled state.
    2702               1 :   UpdateFieldSet(false);
    2703                 : 
    2704               1 :   return NS_OK;
    2705                 : }
    2706                 : 
    2707                 : void
    2708               3 : nsGenericHTMLFormElement::UnbindFromTree(bool aDeep, bool aNullParent)
    2709                 : {
    2710                 :   // Save state before doing anything
    2711               3 :   SaveState();
    2712                 :   
    2713               3 :   if (mForm) {
    2714                 :     // Might need to unset mForm
    2715               0 :     if (aNullParent) {
    2716                 :       // No more parent means no more form
    2717               0 :       ClearForm(true);
    2718                 :     } else {
    2719                 :       // Recheck whether we should still have an mForm.
    2720               0 :       if (HasAttr(kNameSpaceID_None, nsGkAtoms::form) ||
    2721               0 :           !FindAncestorForm(mForm)) {
    2722               0 :         ClearForm(true);
    2723                 :       } else {
    2724               0 :         UnsetFlags(MAYBE_ORPHAN_FORM_ELEMENT);
    2725                 :       }
    2726                 :     }
    2727                 : 
    2728               0 :     if (!mForm) {
    2729                 :       // Our novalidate state might have changed
    2730               0 :       UpdateState(false);
    2731                 :     }
    2732                 :   }
    2733                 : 
    2734                 :   // We have to remove the form id observer if there was one.
    2735                 :   // We will re-add one later if needed (during bind to tree).
    2736               3 :   if (nsContentUtils::HasNonEmptyAttr(this, kNameSpaceID_None,
    2737               3 :                                       nsGkAtoms::form)) {
    2738               0 :     RemoveFormIdObserver();
    2739                 :   }
    2740                 : 
    2741               3 :   nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
    2742                 : 
    2743                 :   // The element might not have a fieldset anymore.
    2744               3 :   UpdateFieldSet(false);
    2745               3 : }
    2746                 : 
    2747                 : nsresult
    2748               0 : nsGenericHTMLFormElement::BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
    2749                 :                                         const nsAttrValueOrString* aValue,
    2750                 :                                         bool aNotify)
    2751                 : {
    2752               0 :   if (aNameSpaceID == kNameSpaceID_None) {
    2753               0 :     nsAutoString tmp;
    2754                 : 
    2755                 :     // remove the control from the hashtable as needed
    2756                 : 
    2757               0 :     if (mForm && (aName == nsGkAtoms::name || aName == nsGkAtoms::id)) {
    2758               0 :       GetAttr(kNameSpaceID_None, aName, tmp);
    2759                 : 
    2760               0 :       if (!tmp.IsEmpty()) {
    2761               0 :         mForm->RemoveElementFromTable(this, tmp);
    2762                 :       }
    2763                 :     }
    2764                 : 
    2765               0 :     if (mForm && aName == nsGkAtoms::type) {
    2766               0 :       GetAttr(kNameSpaceID_None, nsGkAtoms::name, tmp);
    2767                 : 
    2768               0 :       if (!tmp.IsEmpty()) {
    2769               0 :         mForm->RemoveElementFromTable(this, tmp);
    2770                 :       }
    2771                 : 
    2772               0 :       GetAttr(kNameSpaceID_None, nsGkAtoms::id, tmp);
    2773                 : 
    2774               0 :       if (!tmp.IsEmpty()) {
    2775               0 :         mForm->RemoveElementFromTable(this, tmp);
    2776                 :       }
    2777                 : 
    2778               0 :       mForm->RemoveElement(this, false);
    2779                 : 
    2780                 :       // Removing the element from the form can make it not be the default
    2781                 :       // control anymore.  Go ahead and notify on that change, though we might
    2782                 :       // end up readding and becoming the default control again in
    2783                 :       // AfterSetAttr.
    2784                 :       // FIXME: Bug 656197
    2785               0 :       UpdateState(aNotify);
    2786                 :     }
    2787                 : 
    2788               0 :     if (aName == nsGkAtoms::form) {
    2789                 :       // If @form isn't set or set to the empty string, there were no observer
    2790                 :       // so we don't have to remove it.
    2791               0 :       if (nsContentUtils::HasNonEmptyAttr(this, kNameSpaceID_None,
    2792               0 :                                           nsGkAtoms::form)) {
    2793                 :         // The current form id observer is no longer needed.
    2794                 :         // A new one may be added in AfterSetAttr.
    2795               0 :         RemoveFormIdObserver();
    2796                 :       }
    2797                 :     }
    2798                 :   }
    2799                 : 
    2800                 :   return nsGenericHTMLElement::BeforeSetAttr(aNameSpaceID, aName,
    2801               0 :                                              aValue, aNotify);
    2802                 : }
    2803                 : 
    2804                 : nsresult
    2805               0 : nsGenericHTMLFormElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
    2806                 :                                        const nsAttrValue* aValue, bool aNotify)
    2807                 : {
    2808               0 :   if (aNameSpaceID == kNameSpaceID_None) {
    2809                 :     // add the control to the hashtable as needed
    2810                 : 
    2811               0 :     if (mForm && (aName == nsGkAtoms::name || aName == nsGkAtoms::id) &&
    2812               0 :         aValue && !aValue->IsEmptyString()) {
    2813               0 :       NS_ABORT_IF_FALSE(aValue->Type() == nsAttrValue::eAtom,
    2814                 :         "Expected atom value for name/id");
    2815                 :       mForm->AddElementToTable(this,
    2816               0 :         nsDependentAtomString(aValue->GetAtomValue()));
    2817                 :     }
    2818                 : 
    2819               0 :     if (mForm && aName == nsGkAtoms::type) {
    2820               0 :       nsAutoString tmp;
    2821                 : 
    2822               0 :       GetAttr(kNameSpaceID_None, nsGkAtoms::name, tmp);
    2823                 : 
    2824               0 :       if (!tmp.IsEmpty()) {
    2825               0 :         mForm->AddElementToTable(this, tmp);
    2826                 :       }
    2827                 : 
    2828               0 :       GetAttr(kNameSpaceID_None, nsGkAtoms::id, tmp);
    2829                 : 
    2830               0 :       if (!tmp.IsEmpty()) {
    2831               0 :         mForm->AddElementToTable(this, tmp);
    2832                 :       }
    2833                 : 
    2834               0 :       mForm->AddElement(this, false, aNotify);
    2835                 : 
    2836                 :       // Adding the element to the form can make it be the default control .
    2837                 :       // Go ahead and notify on that change.
    2838                 :       // Note: no need to notify on CanBeDisabled(), since type attr
    2839                 :       // changes can't affect that.
    2840               0 :       UpdateState(aNotify);
    2841                 :     }
    2842                 : 
    2843               0 :     if (aName == nsGkAtoms::form) {
    2844                 :       // We need a new form id observer.
    2845               0 :       nsIDocument* doc = GetCurrentDoc();
    2846               0 :       if (doc) {
    2847               0 :         Element* formIdElement = nsnull;
    2848               0 :         if (aValue && !aValue->IsEmptyString()) {
    2849               0 :           formIdElement = AddFormIdObserver();
    2850                 :         }
    2851                 : 
    2852                 :         // Because we have a new @form value (or no more @form), we have to
    2853                 :         // update our form owner.
    2854               0 :         UpdateFormOwner(false, formIdElement);
    2855                 :       }
    2856                 :     }
    2857                 :   }
    2858                 : 
    2859                 :   return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName,
    2860               0 :                                             aValue, aNotify);
    2861                 : }
    2862                 : 
    2863                 : nsresult
    2864               0 : nsGenericHTMLFormElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
    2865                 : {
    2866               0 :   if (NS_IS_TRUSTED_EVENT(aVisitor.mEvent)) {
    2867               0 :     switch (aVisitor.mEvent->message) {
    2868                 :       case NS_FOCUS_CONTENT:
    2869                 :       {
    2870                 :         // Check to see if focus has bubbled up from a form control's
    2871                 :         // child textfield or button.  If that's the case, don't focus
    2872                 :         // this parent file control -- leave focus on the child.
    2873               0 :         nsIFormControlFrame* formControlFrame = GetFormControlFrame(true);
    2874               0 :         if (formControlFrame &&
    2875               0 :             aVisitor.mEvent->originalTarget == static_cast<nsINode*>(this))
    2876               0 :           formControlFrame->SetFocus(true, true);
    2877               0 :         break;
    2878                 :       }
    2879                 :       case NS_BLUR_CONTENT:
    2880                 :       {
    2881               0 :         nsIFormControlFrame* formControlFrame = GetFormControlFrame(true);
    2882               0 :         if (formControlFrame)
    2883               0 :           formControlFrame->SetFocus(false, false);
    2884               0 :         break;
    2885                 :       }
    2886                 :     }
    2887                 :   }
    2888                 : 
    2889               0 :   return nsGenericHTMLElement::PreHandleEvent(aVisitor);
    2890                 : }
    2891                 : 
    2892                 : /* virtual */
    2893                 : bool
    2894               9 : nsGenericHTMLFormElement::IsDisabled() const
    2895                 : {
    2896               9 :   return HasAttr(kNameSpaceID_None, nsGkAtoms::disabled) ||
    2897               9 :          (mFieldSet && mFieldSet->IsDisabled());
    2898                 : }
    2899                 : 
    2900                 : void
    2901               0 : nsGenericHTMLFormElement::ForgetFieldSet(nsIContent* aFieldset)
    2902                 : {
    2903               0 :   if (mFieldSet == aFieldset) {
    2904               0 :     mFieldSet = nsnull;
    2905                 :   }
    2906               0 : }
    2907                 : 
    2908                 : bool
    2909               5 : nsGenericHTMLFormElement::CanBeDisabled() const
    2910                 : {
    2911               5 :   PRInt32 type = GetType();
    2912                 :   // It's easier to test the types that _cannot_ be disabled
    2913                 :   return
    2914                 :     type != NS_FORM_LABEL &&
    2915                 :     type != NS_FORM_OBJECT &&
    2916                 :     type != NS_FORM_OUTPUT &&
    2917               5 :     type != NS_FORM_PROGRESS;
    2918                 : }
    2919                 : 
    2920                 : bool
    2921               0 : nsGenericHTMLFormElement::IsHTMLFocusable(bool aWithMouse,
    2922                 :                                           bool* aIsFocusable,
    2923                 :                                           PRInt32* aTabIndex)
    2924                 : {
    2925               0 :   if (nsGenericHTMLElement::IsHTMLFocusable(aWithMouse, aIsFocusable, aTabIndex)) {
    2926               0 :     return true;
    2927                 :   }
    2928                 : 
    2929                 : #ifdef XP_MACOSX
    2930                 :   *aIsFocusable =
    2931                 :     (!aWithMouse || nsFocusManager::sMouseFocusesFormControl) && *aIsFocusable;
    2932                 : #endif
    2933               0 :   return false;
    2934                 : }
    2935                 : 
    2936                 : nsEventStates
    2937               5 : nsGenericHTMLFormElement::IntrinsicState() const
    2938                 : {
    2939                 :   // If you add attribute-dependent states here, you need to add them them to
    2940                 :   // AfterSetAttr too.  And add them to AfterSetAttr for all subclasses that
    2941                 :   // implement IntrinsicState() and are affected by that attribute.
    2942               5 :   nsEventStates state = nsGenericHTMLElement::IntrinsicState();
    2943                 : 
    2944               5 :   if (CanBeDisabled()) {
    2945                 :     // :enabled/:disabled
    2946               5 :     if (IsDisabled()) {
    2947               0 :       state |= NS_EVENT_STATE_DISABLED;
    2948               0 :       state &= ~NS_EVENT_STATE_ENABLED;
    2949                 :     } else {
    2950               5 :       state &= ~NS_EVENT_STATE_DISABLED;
    2951               5 :       state |= NS_EVENT_STATE_ENABLED;
    2952                 :     }
    2953                 :   }
    2954                 :   
    2955               5 :   if (mForm && mForm->IsDefaultSubmitElement(this)) {
    2956               0 :       NS_ASSERTION(IsSubmitControl(),
    2957                 :                    "Default submit element that isn't a submit control.");
    2958                 :       // We are the default submit element (:default)
    2959               0 :       state |= NS_EVENT_STATE_DEFAULT;
    2960                 :   }
    2961                 : 
    2962                 :   return state;
    2963                 : }
    2964                 : 
    2965                 : nsGenericHTMLFormElement::FocusTristate
    2966               0 : nsGenericHTMLFormElement::FocusState()
    2967                 : {
    2968                 :   // We can't be focused if we aren't in a document
    2969               0 :   nsIDocument* doc = GetCurrentDoc();
    2970               0 :   if (!doc)
    2971               0 :     return eUnfocusable;
    2972                 : 
    2973                 :   // first see if we are disabled or not. If disabled then do nothing.
    2974               0 :   if (IsDisabled()) {
    2975               0 :     return eUnfocusable;
    2976                 :   }
    2977                 : 
    2978                 :   // If the window is not active, do not allow the focus to bring the
    2979                 :   // window to the front.  We update the focus controller, but do
    2980                 :   // nothing else.
    2981               0 :   nsPIDOMWindow* win = doc->GetWindow();
    2982               0 :   if (win) {
    2983               0 :     nsCOMPtr<nsIDOMWindow> rootWindow = do_QueryInterface(win->GetPrivateRoot());
    2984                 : 
    2985               0 :     nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
    2986               0 :     if (fm && rootWindow) {
    2987               0 :       nsCOMPtr<nsIDOMWindow> activeWindow;
    2988               0 :       fm->GetActiveWindow(getter_AddRefs(activeWindow));
    2989               0 :       if (activeWindow == rootWindow) {
    2990               0 :         return eActiveWindow;
    2991                 :       }
    2992                 :     }
    2993                 :   }
    2994                 : 
    2995               0 :   return eInactiveWindow;
    2996                 : }
    2997                 : 
    2998                 : Element*
    2999               0 : nsGenericHTMLFormElement::AddFormIdObserver()
    3000                 : {
    3001               0 :   NS_ASSERTION(GetCurrentDoc(), "When adding a form id observer, "
    3002                 :                                 "we should be in a document!");
    3003                 : 
    3004               0 :   nsAutoString formId;
    3005               0 :   nsIDocument* doc = OwnerDoc();
    3006               0 :   GetAttr(kNameSpaceID_None, nsGkAtoms::form, formId);
    3007               0 :   NS_ASSERTION(!formId.IsEmpty(),
    3008                 :                "@form value should not be the empty string!");
    3009               0 :   nsCOMPtr<nsIAtom> atom = do_GetAtom(formId);
    3010                 : 
    3011               0 :   return doc->AddIDTargetObserver(atom, FormIdUpdated, this, false);
    3012                 : }
    3013                 : 
    3014                 : void
    3015               0 : nsGenericHTMLFormElement::RemoveFormIdObserver()
    3016                 : {
    3017                 :   /**
    3018                 :    * We are using OwnerDoc() because we don't really care about having the
    3019                 :    * element actually being in the tree. If it is not and @form value changes,
    3020                 :    * this method will be called for nothing but removing an observer which does
    3021                 :    * not exist doesn't cost so much (no entry in the hash table) so having a
    3022                 :    * boolean for GetCurrentDoc()/GetOwnerDoc() would make everything look more
    3023                 :    * complex for nothing.
    3024                 :    */
    3025                 : 
    3026               0 :   nsIDocument* doc = OwnerDoc();
    3027                 : 
    3028                 :   // At this point, we may not have a document anymore. In that case, we can't
    3029                 :   // remove the observer. The document did that for us.
    3030               0 :   if (!doc) {
    3031               0 :     return;
    3032                 :   }
    3033                 : 
    3034               0 :   nsAutoString formId;
    3035               0 :   GetAttr(kNameSpaceID_None, nsGkAtoms::form, formId);
    3036               0 :   NS_ASSERTION(!formId.IsEmpty(),
    3037                 :                "@form value should not be the empty string!");
    3038               0 :   nsCOMPtr<nsIAtom> atom = do_GetAtom(formId);
    3039                 : 
    3040               0 :   doc->RemoveIDTargetObserver(atom, FormIdUpdated, this, false);
    3041                 : }
    3042                 : 
    3043                 : 
    3044                 : /* static */
    3045                 : bool
    3046               0 : nsGenericHTMLFormElement::FormIdUpdated(Element* aOldElement,
    3047                 :                                         Element* aNewElement,
    3048                 :                                         void* aData)
    3049                 : {
    3050                 :   nsGenericHTMLFormElement* element =
    3051               0 :     static_cast<nsGenericHTMLFormElement*>(aData);
    3052                 : 
    3053               0 :   NS_ASSERTION(element->IsHTML(), "aData should be an HTML element");
    3054                 : 
    3055               0 :   element->UpdateFormOwner(false, aNewElement);
    3056                 : 
    3057               0 :   return true;
    3058                 : }
    3059                 : 
    3060                 : bool 
    3061               0 : nsGenericHTMLFormElement::IsElementDisabledForEvents(PRUint32 aMessage, 
    3062                 :                                                     nsIFrame* aFrame)
    3063                 : {
    3064               0 :   bool disabled = IsDisabled();
    3065               0 :   if (!disabled && aFrame) {
    3066               0 :     const nsStyleUserInterface* uiStyle = aFrame->GetStyleUserInterface();
    3067                 :     disabled = uiStyle->mUserInput == NS_STYLE_USER_INPUT_NONE ||
    3068               0 :       uiStyle->mUserInput == NS_STYLE_USER_INPUT_DISABLED;
    3069                 : 
    3070                 :   }
    3071               0 :   return disabled && aMessage != NS_MOUSE_MOVE;
    3072                 : }
    3073                 : 
    3074                 : void
    3075               1 : nsGenericHTMLFormElement::UpdateFormOwner(bool aBindToTree,
    3076                 :                                           Element* aFormIdElement)
    3077                 : {
    3078               1 :   NS_PRECONDITION(!aBindToTree || !aFormIdElement,
    3079                 :                   "aFormIdElement shouldn't be set if aBindToTree is true!");
    3080                 : 
    3081               1 :   bool needStateUpdate = false;
    3082               1 :   if (!aBindToTree) {
    3083               0 :     needStateUpdate = mForm && mForm->IsDefaultSubmitElement(this);
    3084               0 :     ClearForm(true);
    3085                 :   }
    3086                 : 
    3087               1 :   nsHTMLFormElement *oldForm = mForm;
    3088                 : 
    3089               1 :   if (!mForm) {
    3090                 :     // If @form is set, we have to use that to find the form.
    3091               2 :     nsAutoString formId;
    3092               1 :     if (GetAttr(kNameSpaceID_None, nsGkAtoms::form, formId)) {
    3093               0 :       if (!formId.IsEmpty()) {
    3094               0 :         Element* element = nsnull;
    3095                 : 
    3096               0 :         if (aBindToTree) {
    3097               0 :           element = AddFormIdObserver();
    3098                 :         } else {
    3099               0 :           element = aFormIdElement;
    3100                 :         }
    3101                 : 
    3102               0 :         NS_ASSERTION(GetCurrentDoc(), "The element should be in a document "
    3103                 :                                       "when UpdateFormOwner is called!");
    3104               0 :         NS_ASSERTION(!GetCurrentDoc() ||
    3105                 :                      element == GetCurrentDoc()->GetElementById(formId),
    3106                 :                      "element should be equals to the current element "
    3107                 :                      "associated with the id in @form!");
    3108                 : 
    3109               0 :         if (element && element->IsHTML(nsGkAtoms::form)) {
    3110               0 :           mForm = static_cast<nsHTMLFormElement*>(element);
    3111                 :         }
    3112                 :       }
    3113                 :      } else {
    3114                 :       // We now have a parent, so we may have picked up an ancestor form.  Search
    3115                 :       // for it.  Note that if mForm is already set we don't want to do this,
    3116                 :       // because that means someone (probably the content sink) has already set
    3117                 :       // it to the right value.  Also note that even if being bound here didn't
    3118                 :       // change our parent, we still need to search, since our parent chain
    3119                 :       // probably changed _somewhere_.
    3120               1 :       mForm = FindAncestorForm();
    3121                 :     }
    3122                 :   }
    3123                 : 
    3124               1 :   if (mForm && !HasFlag(ADDED_TO_FORM)) {
    3125                 :     // Now we need to add ourselves to the form
    3126               0 :     nsAutoString nameVal, idVal;
    3127               0 :     GetAttr(kNameSpaceID_None, nsGkAtoms::name, nameVal);
    3128               0 :     GetAttr(kNameSpaceID_None, nsGkAtoms::id, idVal);
    3129                 : 
    3130               0 :     SetFlags(ADDED_TO_FORM);
    3131                 : 
    3132                 :     // Notify only if we just found this mForm.
    3133               0 :     mForm->AddElement(this, true, oldForm == nsnull);
    3134                 : 
    3135               0 :     if (!nameVal.IsEmpty()) {
    3136               0 :       mForm->AddElementToTable(this, nameVal);
    3137                 :     }
    3138                 : 
    3139               0 :     if (!idVal.IsEmpty()) {
    3140               0 :       mForm->AddElementToTable(this, idVal);
    3141                 :     }
    3142                 :   }
    3143                 : 
    3144               1 :   if (mForm != oldForm || needStateUpdate) {
    3145               0 :     UpdateState(true);
    3146                 :   }
    3147               1 : }
    3148                 : 
    3149                 : void
    3150               4 : nsGenericHTMLFormElement::UpdateFieldSet(bool aNotify)
    3151                 : {
    3152               4 :   nsIContent* parent = nsnull;
    3153               4 :   nsIContent* prev = nsnull;
    3154                 : 
    3155              14 :   for (parent = GetParent(); parent;
    3156               5 :        prev = parent, parent = parent->GetParent()) {
    3157                 :     nsHTMLFieldSetElement* fieldset =
    3158               5 :       nsHTMLFieldSetElement::FromContent(parent);
    3159               5 :     if (fieldset &&
    3160               0 :         (!prev || fieldset->GetFirstLegend() != prev)) {
    3161               0 :       if (mFieldSet == fieldset) {
    3162                 :         // We already have the right fieldset;
    3163               0 :         return;
    3164                 :       }
    3165                 : 
    3166               0 :       if (mFieldSet) {
    3167               0 :         mFieldSet->RemoveElement(this);
    3168                 :       }
    3169               0 :       mFieldSet = fieldset;
    3170               0 :       fieldset->AddElement(this);
    3171                 : 
    3172                 :       // The disabled state may have changed
    3173               0 :       FieldSetDisabledChanged(aNotify);
    3174               0 :       return;
    3175                 :     }
    3176                 :   }
    3177                 : 
    3178                 :   // No fieldset found.
    3179               4 :   if (mFieldSet) {
    3180               0 :     mFieldSet->RemoveElement(this);
    3181               0 :     mFieldSet = nsnull;
    3182                 :     // The disabled state may have changed
    3183               0 :     FieldSetDisabledChanged(aNotify);
    3184                 :   }
    3185                 : }
    3186                 : 
    3187                 : void
    3188               0 : nsGenericHTMLFormElement::FieldSetDisabledChanged(bool aNotify)
    3189                 : {
    3190               0 :   UpdateState(aNotify);
    3191               0 : }
    3192                 : 
    3193                 : //----------------------------------------------------------------------
    3194                 : 
    3195                 : nsresult
    3196               0 : nsGenericHTMLElement::Blur()
    3197                 : {
    3198               0 :   if (!ShouldBlur(this)) {
    3199               0 :     return NS_OK;
    3200                 :   }
    3201                 : 
    3202               0 :   nsIDocument* doc = GetCurrentDoc();
    3203               0 :   if (!doc) {
    3204               0 :     return NS_OK;
    3205                 :   }
    3206                 : 
    3207               0 :   nsIDOMWindow* win = doc->GetWindow();
    3208               0 :   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
    3209               0 :   return (win && fm) ? fm->ClearFocus(win) : NS_OK;
    3210                 : }
    3211                 : 
    3212                 : nsresult
    3213               0 : nsGenericHTMLElement::Focus()
    3214                 : {
    3215               0 :   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
    3216               0 :   nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(this);
    3217               0 :   return fm ? fm->SetFocus(elem, 0) : NS_OK;
    3218                 : }
    3219                 : 
    3220               0 : nsresult nsGenericHTMLElement::MozRequestFullScreen()
    3221                 : {
    3222                 :   // Only grant full-screen requests if this is called from inside a trusted
    3223                 :   // event handler (i.e. inside an event handler for a user initiated event).
    3224                 :   // This stops the full-screen from being abused similar to the popups of old,
    3225                 :   // and it also makes it harder for bad guys' script to go full-screen and
    3226                 :   // spoof the browser chrome/window and phish logins etc.
    3227               0 :   if (!nsContentUtils::IsRequestFullScreenAllowed()) {
    3228                 :     nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
    3229                 :                                     "DOM", OwnerDoc(),
    3230                 :                                     nsContentUtils::eDOM_PROPERTIES,
    3231               0 :                                     "FullScreenDeniedNotInputDriven");
    3232                 :     nsRefPtr<nsAsyncDOMEvent> e =
    3233               0 :       new nsAsyncDOMEvent(OwnerDoc(),
    3234               0 :                           NS_LITERAL_STRING("mozfullscreenerror"),
    3235                 :                           true,
    3236               0 :                           false);
    3237               0 :     e->PostDOMEvent();
    3238               0 :     return NS_OK;
    3239                 :   }
    3240                 : 
    3241               0 :   OwnerDoc()->AsyncRequestFullScreen(this);
    3242                 : 
    3243               0 :   return NS_OK;
    3244                 : }
    3245                 : 
    3246               0 : nsresult nsGenericHTMLElement::Click()
    3247                 : {
    3248               0 :   if (HasFlag(NODE_HANDLING_CLICK))
    3249               0 :     return NS_OK;
    3250                 : 
    3251                 :   // Strong in case the event kills it
    3252               0 :   nsCOMPtr<nsIDocument> doc = GetCurrentDoc();
    3253                 : 
    3254               0 :   nsCOMPtr<nsIPresShell> shell;
    3255               0 :   nsRefPtr<nsPresContext> context;
    3256               0 :   if (doc) {
    3257               0 :     shell = doc->GetShell();
    3258               0 :     if (shell) {
    3259               0 :       context = shell->GetPresContext();
    3260                 :     }
    3261                 :   }
    3262                 : 
    3263               0 :   SetFlags(NODE_HANDLING_CLICK);
    3264                 : 
    3265                 :   // Click() is never called from native code, but it may be
    3266                 :   // called from chrome JS. Mark this event trusted if Click()
    3267                 :   // is called from chrome code.
    3268               0 :   nsMouseEvent event(nsContentUtils::IsCallerChrome(),
    3269               0 :                      NS_MOUSE_CLICK, nsnull, nsMouseEvent::eReal);
    3270               0 :   event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN;
    3271                 : 
    3272               0 :   nsEventDispatcher::Dispatch(this, context, &event);
    3273                 : 
    3274               0 :   UnsetFlags(NODE_HANDLING_CLICK);
    3275               0 :   return NS_OK;
    3276                 : }
    3277                 : 
    3278                 : bool
    3279               0 : nsGenericHTMLElement::IsHTMLFocusable(bool aWithMouse,
    3280                 :                                       bool *aIsFocusable,
    3281                 :                                       PRInt32 *aTabIndex)
    3282                 : {
    3283               0 :   nsIDocument *doc = GetCurrentDoc();
    3284               0 :   if (!doc || doc->HasFlag(NODE_IS_EDITABLE)) {
    3285                 :     // In designMode documents we only allow focusing the document.
    3286               0 :     if (aTabIndex) {
    3287               0 :       *aTabIndex = -1;
    3288                 :     }
    3289                 : 
    3290               0 :     *aIsFocusable = false;
    3291                 : 
    3292               0 :     return true;
    3293                 :   }
    3294                 : 
    3295               0 :   PRInt32 tabIndex = 0;   // Default value for non HTML elements with -moz-user-focus
    3296               0 :   GetTabIndex(&tabIndex);
    3297                 : 
    3298               0 :   bool override, disabled = false;
    3299               0 :   if (IsEditableRoot()) {
    3300                 :     // Editable roots should always be focusable.
    3301               0 :     override = true;
    3302                 : 
    3303                 :     // Ignore the disabled attribute in editable contentEditable/designMode
    3304                 :     // roots.
    3305               0 :     if (!HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex)) {
    3306                 :       // The default value for tabindex should be 0 for editable
    3307                 :       // contentEditable roots.
    3308               0 :       tabIndex = 0;
    3309                 :     }
    3310                 :   }
    3311                 :   else {
    3312               0 :     override = false;
    3313                 : 
    3314                 :     // Just check for disabled attribute on form controls
    3315               0 :     disabled = IsDisabled();
    3316               0 :     if (disabled) {
    3317               0 :       tabIndex = -1;
    3318                 :     }
    3319                 :   }
    3320                 : 
    3321               0 :   if (aTabIndex) {
    3322               0 :     *aTabIndex = tabIndex;
    3323                 :   }
    3324                 : 
    3325                 :   // If a tabindex is specified at all, or the default tabindex is 0, we're focusable
    3326                 :   *aIsFocusable = 
    3327               0 :     (tabIndex >= 0 || (!disabled && HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex)));
    3328                 : 
    3329               0 :   return override;
    3330                 : }
    3331                 : 
    3332                 : void
    3333               0 : nsGenericHTMLElement::RegUnRegAccessKey(bool aDoReg)
    3334                 : {
    3335                 :   // first check to see if we have an access key
    3336               0 :   nsAutoString accessKey;
    3337               0 :   GetAttr(kNameSpaceID_None, nsGkAtoms::accesskey, accessKey);
    3338               0 :   if (accessKey.IsEmpty()) {
    3339                 :     return;
    3340                 :   }
    3341                 : 
    3342                 :   // We have an access key, so get the ESM from the pres context.
    3343               0 :   nsPresContext *presContext = GetPresContext();
    3344                 : 
    3345               0 :   if (presContext) {
    3346               0 :     nsEventStateManager *esm = presContext->EventStateManager();
    3347                 : 
    3348                 :     // Register or unregister as appropriate.
    3349               0 :     if (aDoReg) {
    3350               0 :       esm->RegisterAccessKey(this, (PRUint32)accessKey.First());
    3351                 :     } else {
    3352               0 :       esm->UnregisterAccessKey(this, (PRUint32)accessKey.First());
    3353                 :     }
    3354                 :   }
    3355                 : }
    3356                 : 
    3357                 : void
    3358               0 : nsGenericHTMLElement::PerformAccesskey(bool aKeyCausesActivation,
    3359                 :                                        bool aIsTrustedEvent)
    3360                 : {
    3361               0 :   nsPresContext *presContext = GetPresContext();
    3362               0 :   if (!presContext)
    3363               0 :     return;
    3364                 : 
    3365                 :   // It's hard to say what HTML4 wants us to do in all cases.
    3366               0 :   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
    3367               0 :   if (fm) {
    3368               0 :     nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(this);
    3369               0 :     fm->SetFocus(elem, nsIFocusManager::FLAG_BYKEY);
    3370                 :   }
    3371                 : 
    3372               0 :   if (aKeyCausesActivation) {
    3373                 :     // Click on it if the users prefs indicate to do so.
    3374                 :     nsMouseEvent event(aIsTrustedEvent, NS_MOUSE_CLICK,
    3375               0 :                        nsnull, nsMouseEvent::eReal);
    3376               0 :     event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_KEYBOARD;
    3377                 : 
    3378                 :     nsAutoPopupStatePusher popupStatePusher(aIsTrustedEvent ?
    3379               0 :                                             openAllowed : openAbused);
    3380                 : 
    3381               0 :     nsEventDispatcher::Dispatch(this, presContext, &event);
    3382                 :   }
    3383                 : }
    3384                 : 
    3385                 : const nsAttrName*
    3386               0 : nsGenericHTMLElement::InternalGetExistingAttrNameFromQName(const nsAString& aStr) const
    3387                 : {
    3388               0 :   if (IsInHTMLDocument()) {
    3389               0 :     nsAutoString lower;
    3390               0 :     nsContentUtils::ASCIIToLower(aStr, lower);
    3391               0 :     return mAttrsAndChildren.GetExistingAttrNameFromQName(lower);
    3392                 :   }
    3393                 : 
    3394               0 :   return mAttrsAndChildren.GetExistingAttrNameFromQName(aStr);
    3395                 : }
    3396                 : 
    3397                 : nsresult
    3398               0 : nsGenericHTMLElement::GetEditor(nsIEditor** aEditor)
    3399                 : {
    3400               0 :   *aEditor = nsnull;
    3401                 : 
    3402               0 :   if (!nsContentUtils::IsCallerTrustedForWrite()) {
    3403               0 :     return NS_ERROR_DOM_SECURITY_ERR;
    3404                 :   }
    3405                 : 
    3406               0 :   return GetEditorInternal(aEditor);
    3407                 : }
    3408                 : 
    3409                 : nsresult
    3410               0 : nsGenericHTMLElement::GetEditorInternal(nsIEditor** aEditor)
    3411                 : {
    3412               0 :   *aEditor = nsnull;
    3413                 : 
    3414               0 :   nsCOMPtr<nsITextControlElement> textCtrl = do_QueryInterface(this);
    3415               0 :   if (textCtrl) {
    3416               0 :     *aEditor = textCtrl->GetTextEditor();
    3417               0 :     NS_IF_ADDREF(*aEditor);
    3418                 :   }
    3419                 : 
    3420               0 :   return NS_OK;
    3421                 : }
    3422                 : 
    3423                 : already_AddRefed<nsIEditor>
    3424               0 : nsGenericHTMLElement::GetAssociatedEditor()
    3425                 : {
    3426                 :   // If contenteditable is ever implemented, it might need to do something different here?
    3427                 : 
    3428               0 :   nsIEditor* editor = nsnull;
    3429               0 :   GetEditorInternal(&editor);
    3430               0 :   return editor;
    3431                 : }
    3432                 : 
    3433                 : bool
    3434               0 : nsGenericHTMLElement::IsCurrentBodyElement()
    3435                 : {
    3436                 :   // TODO Bug 698498: Should this handle the case where GetBody returns a
    3437                 :   //                  frameset?
    3438               0 :   nsCOMPtr<nsIDOMHTMLBodyElement> bodyElement = do_QueryInterface(this);
    3439               0 :   if (!bodyElement) {
    3440               0 :     return false;
    3441                 :   }
    3442                 : 
    3443                 :   nsCOMPtr<nsIDOMHTMLDocument> htmlDocument =
    3444               0 :     do_QueryInterface(GetCurrentDoc());
    3445               0 :   if (!htmlDocument) {
    3446               0 :     return false;
    3447                 :   }
    3448                 : 
    3449               0 :   nsCOMPtr<nsIDOMHTMLElement> htmlElement;
    3450               0 :   htmlDocument->GetBody(getter_AddRefs(htmlElement));
    3451               0 :   return htmlElement == bodyElement;
    3452                 : }
    3453                 : 
    3454                 : // static
    3455                 : void
    3456               0 : nsGenericHTMLElement::SyncEditorsOnSubtree(nsIContent* content)
    3457                 : {
    3458                 :   /* Sync this node */
    3459               0 :   nsGenericHTMLElement* element = FromContent(content);
    3460               0 :   if (element) {
    3461               0 :     nsCOMPtr<nsIEditor> editor = element->GetAssociatedEditor();
    3462               0 :     if (editor) {
    3463               0 :       editor->SyncRealTimeSpell();
    3464                 :     }
    3465                 :   }
    3466                 : 
    3467                 :   /* Sync all children */
    3468               0 :   for (nsIContent* child = content->GetFirstChild();
    3469                 :        child;
    3470               0 :        child = child->GetNextSibling()) {
    3471               0 :     SyncEditorsOnSubtree(child);
    3472                 :   }
    3473               0 : }
    3474                 : 
    3475                 : void
    3476               0 : nsGenericHTMLElement::RecompileScriptEventListeners()
    3477                 : {
    3478               0 :     PRInt32 i, count = mAttrsAndChildren.AttrCount();
    3479               0 :     for (i = 0; i < count; ++i) {
    3480               0 :         const nsAttrName *name = mAttrsAndChildren.AttrNameAt(i);
    3481                 : 
    3482                 :         // Eventlistenener-attributes are always in the null namespace
    3483               0 :         if (!name->IsAtom()) {
    3484               0 :             continue;
    3485                 :         }
    3486                 : 
    3487               0 :         nsIAtom *attr = name->Atom();
    3488               0 :         if (!nsContentUtils::IsEventAttributeName(attr, EventNameType_HTML)) {
    3489               0 :             continue;
    3490                 :         }
    3491                 : 
    3492               0 :         nsAutoString value;
    3493               0 :         GetAttr(kNameSpaceID_None, attr, value);
    3494               0 :         AddScriptEventListener(attr, value, true);
    3495                 :     }
    3496               0 : }
    3497                 : 
    3498                 : bool
    3499               0 : nsGenericHTMLElement::IsEditableRoot() const
    3500                 : {
    3501               0 :   nsIDocument *document = GetCurrentDoc();
    3502               0 :   if (!document) {
    3503               0 :     return false;
    3504                 :   }
    3505                 : 
    3506               0 :   if (document->HasFlag(NODE_IS_EDITABLE)) {
    3507               0 :     return false;
    3508                 :   }
    3509                 : 
    3510               0 :   if (GetContentEditableValue() != eTrue) {
    3511               0 :     return false;
    3512                 :   }
    3513                 : 
    3514               0 :   nsIContent *parent = GetParent();
    3515                 : 
    3516               0 :   return !parent || !parent->HasFlag(NODE_IS_EDITABLE);
    3517                 : }
    3518                 : 
    3519                 : static void
    3520               0 : MakeContentDescendantsEditable(nsIContent *aContent, nsIDocument *aDocument)
    3521                 : {
    3522                 :   // If aContent is not an element, we just need to update its
    3523                 :   // internal editable state and don't need to notify anyone about
    3524                 :   // that.  For elements, we need to send a ContentStateChanged
    3525                 :   // notification.
    3526               0 :   if (!aContent->IsElement()) {
    3527               0 :     aContent->UpdateEditableState(false);
    3528               0 :     return;
    3529                 :   }
    3530                 : 
    3531               0 :   Element *element = aContent->AsElement();
    3532                 : 
    3533               0 :   element->UpdateEditableState(true);
    3534                 : 
    3535               0 :   for (nsIContent *child = aContent->GetFirstChild();
    3536                 :        child;
    3537               0 :        child = child->GetNextSibling()) {
    3538               0 :     if (!child->HasAttr(kNameSpaceID_None, nsGkAtoms::contenteditable)) {
    3539               0 :       MakeContentDescendantsEditable(child, aDocument);
    3540                 :     }
    3541                 :   }
    3542                 : }
    3543                 : 
    3544                 : void
    3545               0 : nsGenericHTMLElement::ChangeEditableState(PRInt32 aChange)
    3546                 : {
    3547               0 :   nsIDocument* document = GetCurrentDoc();
    3548               0 :   if (!document) {
    3549               0 :     return;
    3550                 :   }
    3551                 : 
    3552               0 :   if (aChange != 0) {
    3553                 :     nsCOMPtr<nsIHTMLDocument> htmlDocument =
    3554               0 :       do_QueryInterface(document);
    3555               0 :     if (htmlDocument) {
    3556               0 :       htmlDocument->ChangeContentEditableCount(this, aChange);
    3557                 :     }
    3558                 :   }
    3559                 : 
    3560               0 :   if (document->HasFlag(NODE_IS_EDITABLE)) {
    3561               0 :     document = nsnull;
    3562                 :   }
    3563                 : 
    3564                 :   // MakeContentDescendantsEditable is going to call ContentStateChanged for
    3565                 :   // this element and all descendants if editable state has changed.
    3566                 :   // We might as well wrap it all in one script blocker.
    3567               0 :   nsAutoScriptBlocker scriptBlocker;
    3568               0 :   MakeContentDescendantsEditable(this, document);
    3569            4392 : }

Generated by: LCOV version 1.7