LCOV - code coverage report
Current view: directory - content/base/src - nsDocument.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 4099 960 23.4 %
Date: 2012-06-02 Functions: 512 134 26.2 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* vim: set ts=2 sw=2 et tw=78: */
       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.org 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                 :  *   Johnny Stenback <jst@netscape.com>
      25                 :  *   L. David Baron  <dbaron@dbaron.org>
      26                 :  *   Pierre Phaneuf  <pp@ludusdesign.com>
      27                 :  *   Pete Collins    <petejc@collab.net>
      28                 :  *   James Ross      <silver@warwickcompsoc.co.uk>
      29                 :  *   Ryan Jones      <sciguyryan@gmail.com>
      30                 :  *   Ms2ger <ms2ger@gmail.com>
      31                 :  *
      32                 :  * Alternatively, the contents of this file may be used under the terms of
      33                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      34                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      35                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      36                 :  * of those above. If you wish to allow use of your version of this file only
      37                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      38                 :  * use your version of this file under the terms of the MPL, indicate your
      39                 :  * decision by deleting the provisions above and replace them with the notice
      40                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      41                 :  * the provisions above, a recipient may use your version of this file under
      42                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      43                 :  *
      44                 :  * ***** END LICENSE BLOCK ***** */
      45                 : 
      46                 : /*
      47                 :  * Base class for all our document implementations.
      48                 :  */
      49                 : 
      50                 : #include "mozilla/Util.h"
      51                 : 
      52                 : #ifdef MOZ_LOGGING
      53                 : // so we can get logging even in release builds
      54                 : #define FORCE_PR_LOG 1
      55                 : #endif
      56                 : #include "prlog.h"
      57                 : #include "plstr.h"
      58                 : #include "prprf.h"
      59                 : 
      60                 : #include "nsIInterfaceRequestor.h"
      61                 : #include "nsIInterfaceRequestorUtils.h"
      62                 : #include "nsDocument.h"
      63                 : #include "nsUnicharUtils.h"
      64                 : #include "nsIPrivateDOMEvent.h"
      65                 : #include "nsContentList.h"
      66                 : #include "nsIObserver.h"
      67                 : #include "nsIBaseWindow.h"
      68                 : #include "mozilla/css/Loader.h"
      69                 : #include "nsIDocShell.h"
      70                 : #include "nsIDocShellTreeItem.h"
      71                 : #include "nsIScriptRuntime.h"
      72                 : #include "nsCOMArray.h"
      73                 : 
      74                 : #include "nsGUIEvent.h"
      75                 : #include "nsAsyncDOMEvent.h"
      76                 : #include "nsIDOMNodeFilter.h"
      77                 : 
      78                 : #include "nsIDOMStyleSheet.h"
      79                 : #include "nsDOMAttribute.h"
      80                 : #include "nsIDOMDOMStringList.h"
      81                 : #include "nsIDOMDOMImplementation.h"
      82                 : #include "nsIDOMDocumentXBL.h"
      83                 : #include "mozilla/FunctionTimer.h"
      84                 : #include "nsGenericElement.h"
      85                 : #include "nsGenericHTMLElement.h"
      86                 : #include "nsIDOMCDATASection.h"
      87                 : #include "nsIDOMProcessingInstruction.h"
      88                 : #include "nsDOMString.h"
      89                 : #include "nsNodeUtils.h"
      90                 : #include "nsLayoutUtils.h" // for GetFrameForPoint
      91                 : #include "nsIFrame.h"
      92                 : #include "nsITabChild.h"
      93                 : 
      94                 : #include "nsRange.h"
      95                 : #include "nsIDOMText.h"
      96                 : #include "nsIDOMComment.h"
      97                 : #include "nsDOMDocumentType.h"
      98                 : #include "nsNodeIterator.h"
      99                 : #include "nsTreeWalker.h"
     100                 : 
     101                 : #include "nsIServiceManager.h"
     102                 : 
     103                 : #include "nsContentCID.h"
     104                 : #include "nsDOMError.h"
     105                 : #include "nsIPresShell.h"
     106                 : #include "nsPresContext.h"
     107                 : #include "nsIJSON.h"
     108                 : #include "nsThreadUtils.h"
     109                 : #include "nsNodeInfoManager.h"
     110                 : #include "nsIXBLService.h"
     111                 : #include "nsIFileChannel.h"
     112                 : #include "nsIMultiPartChannel.h"
     113                 : #include "nsIRefreshURI.h"
     114                 : #include "nsIWebNavigation.h"
     115                 : #include "nsIScriptError.h"
     116                 : 
     117                 : #include "nsNetUtil.h"     // for NS_MakeAbsoluteURI
     118                 : 
     119                 : #include "nsIScriptSecurityManager.h"
     120                 : #include "nsIPrincipal.h"
     121                 : 
     122                 : #include "nsIDOMWindow.h"
     123                 : #include "nsPIDOMWindow.h"
     124                 : #include "nsIDOMElement.h"
     125                 : #include "nsFocusManager.h"
     126                 : 
     127                 : // for radio group stuff
     128                 : #include "nsIDOMHTMLInputElement.h"
     129                 : #include "nsIRadioVisitor.h"
     130                 : #include "nsIFormControl.h"
     131                 : 
     132                 : #include "nsXMLEventsManager.h"
     133                 : 
     134                 : #include "nsBidiUtils.h"
     135                 : 
     136                 : #include "nsIDOMUserDataHandler.h"
     137                 : #include "nsIDOMXPathEvaluator.h"
     138                 : #include "nsIXPathEvaluatorInternal.h"
     139                 : #include "nsIParserService.h"
     140                 : #include "nsContentCreatorFunctions.h"
     141                 : 
     142                 : #include "nsIScriptContext.h"
     143                 : #include "nsBindingManager.h"
     144                 : #include "nsIDOMHTMLDocument.h"
     145                 : #include "nsIDOMHTMLFormElement.h"
     146                 : #include "nsIRequest.h"
     147                 : #include "nsILink.h"
     148                 : #include "nsBlobProtocolHandler.h"
     149                 : 
     150                 : #include "nsCharsetAlias.h"
     151                 : #include "nsIParser.h"
     152                 : #include "nsIContentSink.h"
     153                 : 
     154                 : #include "nsDateTimeFormatCID.h"
     155                 : #include "nsIDateTimeFormat.h"
     156                 : #include "nsEventDispatcher.h"
     157                 : #include "nsMutationEvent.h"
     158                 : #include "nsIDOMXPathEvaluator.h"
     159                 : #include "nsDOMCID.h"
     160                 : 
     161                 : #include "jsapi.h"
     162                 : #include "nsIJSContextStack.h"
     163                 : #include "nsIXPConnect.h"
     164                 : #include "nsCycleCollector.h"
     165                 : #include "nsCCUncollectableMarker.h"
     166                 : #include "nsIContentPolicy.h"
     167                 : #include "nsContentPolicyUtils.h"
     168                 : #include "nsICategoryManager.h"
     169                 : #include "nsIDocumentLoaderFactory.h"
     170                 : #include "nsIContentViewer.h"
     171                 : #include "nsIXMLContentSink.h"
     172                 : #include "nsContentErrors.h"
     173                 : #include "nsIXULDocument.h"
     174                 : #include "nsIPrompt.h"
     175                 : #include "nsIPropertyBag2.h"
     176                 : #include "nsIDOMPageTransitionEvent.h"
     177                 : #include "nsFrameLoader.h"
     178                 : #include "nsEscape.h"
     179                 : #include "nsObjectLoadingContent.h"
     180                 : #ifdef MOZ_MEDIA
     181                 : #include "nsHTMLMediaElement.h"
     182                 : #endif // MOZ_MEDIA
     183                 : 
     184                 : #include "mozAutoDocUpdate.h"
     185                 : #include "nsGlobalWindow.h"
     186                 : #include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
     187                 : #include "nsDOMNavigationTiming.h"
     188                 : #include "nsEventStateManager.h"
     189                 : 
     190                 : #include "nsSMILAnimationController.h"
     191                 : #include "imgIContainer.h"
     192                 : #include "nsSVGUtils.h"
     193                 : 
     194                 : #include "nsRefreshDriver.h"
     195                 : 
     196                 : // FOR CSP (autogenerated by xpidl)
     197                 : #include "nsIContentSecurityPolicy.h"
     198                 : #include "nsCSPService.h"
     199                 : #include "nsHTMLStyleSheet.h"
     200                 : #include "nsHTMLCSSStyleSheet.h"
     201                 : 
     202                 : #include "mozilla/dom/Link.h"
     203                 : #include "nsIHTMLDocument.h"
     204                 : #include "nsXULAppAPI.h"
     205                 : #include "nsDOMTouchEvent.h"
     206                 : 
     207                 : #include "mozilla/Preferences.h"
     208                 : 
     209                 : #include "imgILoader.h"
     210                 : #include "nsWrapperCacheInlines.h"
     211                 : 
     212                 : using namespace mozilla;
     213                 : using namespace mozilla::dom;
     214                 : 
     215                 : typedef nsTArray<Link*> LinkArray;
     216                 : 
     217                 : // Reference to the document which requested DOM full-screen mode.
     218            1464 : nsWeakPtr nsDocument::sFullScreenDoc = nsnull;
     219                 : 
     220                 : // Reference to the root document of the branch containing the document
     221                 : // which requested DOM full-screen mode.
     222            1464 : nsWeakPtr nsDocument::sFullScreenRootDoc = nsnull;
     223                 : 
     224                 : #ifdef PR_LOGGING
     225                 : static PRLogModuleInfo* gDocumentLeakPRLog;
     226                 : static PRLogModuleInfo* gCspPRLog;
     227                 : #endif
     228                 : 
     229                 : #define NAME_NOT_VALID ((nsSimpleContentList*)1)
     230                 : 
     231             122 : nsIdentifierMapEntry::~nsIdentifierMapEntry()
     232                 : {
     233             122 : }
     234                 : 
     235                 : void
     236             122 : nsIdentifierMapEntry::Traverse(nsCycleCollectionTraversalCallback* aCallback)
     237                 : {
     238             122 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*aCallback,
     239                 :                                      "mIdentifierMap mNameContentList");
     240             122 :   aCallback->NoteXPCOMChild(static_cast<nsIDOMNodeList*>(mNameContentList));
     241                 : 
     242             122 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*aCallback, "mIdentifierMap mDocAllList");
     243             122 :   aCallback->NoteXPCOMChild(static_cast<nsIDOMNodeList*>(mDocAllList));
     244                 : 
     245             122 :   if (mImageElement) {
     246               0 :     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*aCallback,
     247                 :                                        "mIdentifierMap mImageElement element");
     248               0 :     nsIContent* imageElement = mImageElement;
     249               0 :     aCallback->NoteXPCOMChild(imageElement);
     250                 :   }
     251             122 : }
     252                 : 
     253                 : bool
     254             122 : nsIdentifierMapEntry::IsEmpty()
     255                 : {
     256             244 :   return mIdContentList.Count() == 0 && !mNameContentList &&
     257             244 :          !mChangeCallbacks && !mImageElement;
     258                 : }
     259                 : 
     260                 : Element*
     261              78 : nsIdentifierMapEntry::GetIdElement()
     262                 : {
     263              78 :   return static_cast<Element*>(mIdContentList.SafeElementAt(0));
     264                 : }
     265                 : 
     266                 : Element*
     267               0 : nsIdentifierMapEntry::GetImageIdElement()
     268                 : {
     269               0 :   return mImageElement ? mImageElement.get() : GetIdElement();
     270                 : }
     271                 : 
     272                 : void
     273               0 : nsIdentifierMapEntry::AppendAllIdContent(nsCOMArray<nsIContent>* aElements)
     274                 : {
     275               0 :   for (PRInt32 i = 0; i < mIdContentList.Count(); ++i) {
     276               0 :     aElements->AppendObject(static_cast<Element*>(mIdContentList[i]));
     277                 :   }
     278               0 : }
     279                 : 
     280                 : void
     281               0 : nsIdentifierMapEntry::AddContentChangeCallback(nsIDocument::IDTargetObserver aCallback,
     282                 :                                                void* aData, bool aForImage)
     283                 : {
     284               0 :   if (!mChangeCallbacks) {
     285               0 :     mChangeCallbacks = new nsTHashtable<ChangeCallbackEntry>;
     286               0 :     if (!mChangeCallbacks)
     287               0 :       return;
     288               0 :     mChangeCallbacks->Init();
     289                 :   }
     290                 : 
     291               0 :   ChangeCallback cc = { aCallback, aData, aForImage };
     292               0 :   mChangeCallbacks->PutEntry(cc);
     293                 : }
     294                 : 
     295                 : void
     296               0 : nsIdentifierMapEntry::RemoveContentChangeCallback(nsIDocument::IDTargetObserver aCallback,
     297                 :                                                   void* aData, bool aForImage)
     298                 : {
     299               0 :   if (!mChangeCallbacks)
     300               0 :     return;
     301               0 :   ChangeCallback cc = { aCallback, aData, aForImage };
     302               0 :   mChangeCallbacks->RemoveEntry(cc);
     303               0 :   if (mChangeCallbacks->Count() == 0) {
     304               0 :     mChangeCallbacks = nsnull;
     305                 :   }
     306                 : }
     307                 : 
     308                 : struct FireChangeArgs {
     309                 :   Element* mFrom;
     310                 :   Element* mTo;
     311                 :   bool mImageOnly;
     312                 :   bool mHaveImageOverride;
     313                 : };
     314                 : 
     315                 : static PLDHashOperator
     316               0 : FireChangeEnumerator(nsIdentifierMapEntry::ChangeCallbackEntry *aEntry, void *aArg)
     317                 : {
     318               0 :   FireChangeArgs* args = static_cast<FireChangeArgs*>(aArg);
     319                 :   // Don't fire image changes for non-image observers, and don't fire element
     320                 :   // changes for image observers when an image override is active.
     321               0 :   if (aEntry->mKey.mForImage ? (args->mHaveImageOverride && !args->mImageOnly) :
     322                 :                                args->mImageOnly)
     323               0 :     return PL_DHASH_NEXT;
     324               0 :   return aEntry->mKey.mCallback(args->mFrom, args->mTo, aEntry->mKey.mData)
     325               0 :       ? PL_DHASH_NEXT : PL_DHASH_REMOVE;
     326                 : }
     327                 : 
     328                 : void
     329             244 : nsIdentifierMapEntry::FireChangeCallbacks(Element* aOldElement,
     330                 :                                           Element* aNewElement,
     331                 :                                           bool aImageOnly)
     332                 : {
     333             244 :   if (!mChangeCallbacks)
     334             244 :     return;
     335                 : 
     336               0 :   FireChangeArgs args = { aOldElement, aNewElement, aImageOnly, !!mImageElement };
     337               0 :   mChangeCallbacks->EnumerateEntries(FireChangeEnumerator, &args);
     338                 : }
     339                 : 
     340                 : bool
     341             122 : nsIdentifierMapEntry::AddIdElement(Element* aElement)
     342                 : {
     343             122 :   NS_PRECONDITION(aElement, "Must have element");
     344             122 :   NS_PRECONDITION(mIdContentList.IndexOf(nsnull) < 0,
     345                 :                   "Why is null in our list?");
     346                 : 
     347                 : #ifdef DEBUG
     348                 :   Element* currentElement =
     349             122 :     static_cast<Element*>(mIdContentList.SafeElementAt(0));
     350                 : #endif
     351                 : 
     352                 :   // Common case
     353             122 :   if (mIdContentList.Count() == 0) {
     354             122 :     if (!mIdContentList.AppendElement(aElement))
     355               0 :       return false;
     356             122 :     NS_ASSERTION(currentElement == nsnull, "How did that happen?");
     357             122 :     FireChangeCallbacks(nsnull, aElement);
     358             122 :     return true;
     359                 :   }
     360                 : 
     361                 :   // We seem to have multiple content nodes for the same id, or XUL is messing
     362                 :   // with us.  Search for the right place to insert the content.
     363               0 :   PRInt32 start = 0;
     364               0 :   PRInt32 end = mIdContentList.Count();
     365               0 :   do {
     366               0 :     NS_ASSERTION(start < end, "Bogus start/end");
     367                 :     
     368               0 :     PRInt32 cur = (start + end) / 2;
     369               0 :     NS_ASSERTION(cur >= start && cur < end, "What happened here?");
     370                 : 
     371               0 :     Element* curElement = static_cast<Element*>(mIdContentList[cur]);
     372               0 :     if (curElement == aElement) {
     373                 :       // Already in the list, so already in the right spot.  Get out of here.
     374                 :       // XXXbz this only happens because XUL does all sorts of random
     375                 :       // UpdateIdTableEntry calls.  Hate, hate, hate!
     376               0 :       return true;
     377                 :     }
     378                 : 
     379               0 :     if (nsContentUtils::PositionIsBefore(aElement, curElement)) {
     380               0 :       end = cur;
     381                 :     } else {
     382               0 :       start = cur + 1;
     383                 :     }
     384                 :   } while (start != end);
     385                 : 
     386               0 :   if (!mIdContentList.InsertElementAt(aElement, start))
     387               0 :     return false;
     388                 : 
     389               0 :   if (start == 0) {
     390                 :     Element* oldElement =
     391               0 :       static_cast<Element*>(mIdContentList.SafeElementAt(1));
     392               0 :     NS_ASSERTION(currentElement == oldElement, "How did that happen?");
     393               0 :     FireChangeCallbacks(oldElement, aElement);
     394                 :   }
     395               0 :   return true;
     396                 : }
     397                 : 
     398                 : void
     399             122 : nsIdentifierMapEntry::RemoveIdElement(Element* aElement)
     400                 : {
     401             122 :   NS_PRECONDITION(aElement, "Missing element");
     402                 : 
     403                 :   // This should only be called while the document is in an update.
     404                 :   // Assertions near the call to this method guarantee this.
     405                 : 
     406                 :   // This could fire in OOM situations
     407                 :   // Only assert this in HTML documents for now as XUL does all sorts of weird
     408                 :   // crap.
     409             122 :   NS_ASSERTION(!aElement->OwnerDoc()->IsHTML() ||
     410                 :                mIdContentList.IndexOf(aElement) >= 0,
     411                 :                "Removing id entry that doesn't exist");
     412                 : 
     413                 :   // XXXbz should this ever Compact() I guess when all the content is gone
     414                 :   // we'll just get cleaned up in the natural order of things...
     415                 :   Element* currentElement =
     416             122 :     static_cast<Element*>(mIdContentList.SafeElementAt(0));
     417             122 :   mIdContentList.RemoveElement(aElement);
     418             122 :   if (currentElement == aElement) {
     419                 :     FireChangeCallbacks(currentElement,
     420             122 :                         static_cast<Element*>(mIdContentList.SafeElementAt(0)));
     421                 :   }
     422             122 : }
     423                 : 
     424                 : void
     425               0 : nsIdentifierMapEntry::SetImageElement(Element* aElement)
     426                 : {
     427               0 :   Element* oldElement = GetImageIdElement();
     428               0 :   mImageElement = aElement;
     429               0 :   Element* newElement = GetImageIdElement();
     430               0 :   if (oldElement != newElement) {
     431               0 :     FireChangeCallbacks(oldElement, newElement, true);
     432                 :   }
     433               0 : }
     434                 : 
     435                 : void
     436               0 : nsIdentifierMapEntry::AddNameElement(nsIDocument* aDocument, Element* aElement)
     437                 : {
     438               0 :   if (!mNameContentList) {
     439               0 :     mNameContentList = new nsSimpleContentList(aDocument);
     440                 :   }
     441                 : 
     442               0 :   mNameContentList->AppendElement(aElement);
     443               0 : }
     444                 : 
     445                 : void
     446               0 : nsIdentifierMapEntry::RemoveNameElement(Element* aElement)
     447                 : {
     448               0 :   if (mNameContentList) {
     449               0 :     mNameContentList->RemoveElement(aElement);
     450                 :   }
     451               0 : }
     452                 : 
     453                 : // Helper structs for the content->subdoc map
     454                 : 
     455                 : class SubDocMapEntry : public PLDHashEntryHdr
     456                 : {
     457                 : public:
     458                 :   // Both of these are strong references
     459                 :   Element *mKey; // must be first, to look like PLDHashEntryStub
     460                 :   nsIDocument *mSubDocument;
     461                 : };
     462                 : 
     463                 : struct FindContentData
     464                 : {
     465               0 :   FindContentData(nsIDocument *aSubDoc)
     466               0 :     : mSubDocument(aSubDoc), mResult(nsnull)
     467                 :   {
     468               0 :   }
     469                 : 
     470                 :   nsISupports *mSubDocument;
     471                 :   Element *mResult;
     472                 : };
     473                 : 
     474                 : 
     475                 : /**
     476                 :  * A struct that holds all the information about a radio group.
     477                 :  */
     478                 : struct nsRadioGroupStruct
     479               0 : {
     480               0 :   nsRadioGroupStruct()
     481                 :     : mRequiredRadioCount(0)
     482               0 :     , mGroupSuffersFromValueMissing(false)
     483               0 :   {}
     484                 : 
     485                 :   /**
     486                 :    * A strong pointer to the currently selected radio button.
     487                 :    */
     488                 :   nsCOMPtr<nsIDOMHTMLInputElement> mSelectedRadioButton;
     489                 :   nsCOMArray<nsIFormControl> mRadioButtons;
     490                 :   PRUint32 mRequiredRadioCount;
     491                 :   bool mGroupSuffersFromValueMissing;
     492                 : };
     493                 : 
     494                 : 
     495               0 : nsDOMStyleSheetList::nsDOMStyleSheetList(nsIDocument *aDocument)
     496                 : {
     497               0 :   mLength = -1;
     498                 :   // Not reference counted to avoid circular references.
     499                 :   // The document will tell us when its going away.
     500               0 :   mDocument = aDocument;
     501               0 :   mDocument->AddObserver(this);
     502               0 : }
     503                 : 
     504               0 : nsDOMStyleSheetList::~nsDOMStyleSheetList()
     505                 : {
     506               0 :   if (mDocument) {
     507               0 :     mDocument->RemoveObserver(this);
     508                 :   }
     509               0 : }
     510                 : 
     511                 : DOMCI_DATA(StyleSheetList, nsDOMStyleSheetList)
     512                 : 
     513                 : // XXX couldn't we use the GetIIDs method from CSSStyleSheetList here?
     514                 : // QueryInterface implementation for nsDOMStyleSheetList
     515               0 : NS_INTERFACE_TABLE_HEAD(nsDOMStyleSheetList)
     516               0 :   NS_INTERFACE_TABLE3(nsDOMStyleSheetList,
     517                 :                       nsIDOMStyleSheetList,
     518                 :                       nsIDocumentObserver,
     519                 :                       nsIMutationObserver)
     520               0 :   NS_INTERFACE_TABLE_TO_MAP_SEGUE
     521               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(StyleSheetList)
     522               0 : NS_INTERFACE_MAP_END
     523                 : 
     524                 : 
     525               0 : NS_IMPL_ADDREF(nsDOMStyleSheetList)
     526               0 : NS_IMPL_RELEASE(nsDOMStyleSheetList)
     527                 : 
     528                 : 
     529                 : NS_IMETHODIMP
     530               0 : nsDOMStyleSheetList::GetLength(PRUint32* aLength)
     531                 : {
     532               0 :   if (mDocument) {
     533                 :     // XXX Find the number and then cache it. We'll use the
     534                 :     // observer notification to figure out if new ones have
     535                 :     // been added or removed.
     536               0 :     if (-1 == mLength) {
     537               0 :       mLength = mDocument->GetNumberOfStyleSheets();
     538                 : 
     539                 : #ifdef DEBUG
     540                 :       PRInt32 i;
     541               0 :       for (i = 0; i < mLength; i++) {
     542               0 :         nsIStyleSheet *sheet = mDocument->GetStyleSheetAt(i);
     543               0 :         nsCOMPtr<nsIDOMStyleSheet> domss(do_QueryInterface(sheet));
     544               0 :         NS_ASSERTION(domss, "All \"normal\" sheets implement nsIDOMStyleSheet");
     545                 :       }
     546                 : #endif
     547                 :     }
     548               0 :     *aLength = mLength;
     549                 :   }
     550                 :   else {
     551               0 :     *aLength = 0;
     552                 :   }
     553                 : 
     554               0 :   return NS_OK;
     555                 : }
     556                 : 
     557                 : nsIStyleSheet*
     558               0 : nsDOMStyleSheetList::GetItemAt(PRUint32 aIndex)
     559                 : {
     560               0 :   if (!mDocument || aIndex >= (PRUint32)mDocument->GetNumberOfStyleSheets()) {
     561               0 :     return nsnull;
     562                 :   }
     563                 : 
     564               0 :   nsIStyleSheet *sheet = mDocument->GetStyleSheetAt(aIndex);
     565               0 :   NS_ASSERTION(sheet, "Must have a sheet");
     566                 : 
     567               0 :   return sheet;
     568                 : }
     569                 : 
     570                 : NS_IMETHODIMP
     571               0 : nsDOMStyleSheetList::Item(PRUint32 aIndex, nsIDOMStyleSheet** aReturn)
     572                 : {
     573               0 :   nsIStyleSheet *sheet = GetItemAt(aIndex);
     574               0 :   if (!sheet) {
     575               0 :       *aReturn = nsnull;
     576                 : 
     577               0 :       return NS_OK;
     578                 :   }
     579                 : 
     580               0 :   return CallQueryInterface(sheet, aReturn);
     581                 : }
     582                 : 
     583                 : void
     584               0 : nsDOMStyleSheetList::NodeWillBeDestroyed(const nsINode *aNode)
     585                 : {
     586               0 :   mDocument = nsnull;
     587               0 : }
     588                 : 
     589                 : void
     590               0 : nsDOMStyleSheetList::StyleSheetAdded(nsIDocument *aDocument,
     591                 :                                      nsIStyleSheet* aStyleSheet,
     592                 :                                      bool aDocumentSheet)
     593                 : {
     594               0 :   if (aDocumentSheet && -1 != mLength) {
     595               0 :     nsCOMPtr<nsIDOMStyleSheet> domss(do_QueryInterface(aStyleSheet));
     596               0 :     if (domss) {
     597               0 :       mLength++;
     598                 :     }
     599                 :   }
     600               0 : }
     601                 : 
     602                 : void
     603               0 : nsDOMStyleSheetList::StyleSheetRemoved(nsIDocument *aDocument,
     604                 :                                        nsIStyleSheet* aStyleSheet,
     605                 :                                        bool aDocumentSheet)
     606                 : {
     607               0 :   if (aDocumentSheet && -1 != mLength) {
     608               0 :     nsCOMPtr<nsIDOMStyleSheet> domss(do_QueryInterface(aStyleSheet));
     609               0 :     if (domss) {
     610               0 :       mLength--;
     611                 :     }
     612                 :   }
     613               0 : }
     614                 : 
     615                 : // nsOnloadBlocker implementation
     616            9096 : NS_IMPL_ISUPPORTS1(nsOnloadBlocker, nsIRequest)
     617                 : 
     618                 : NS_IMETHODIMP
     619               0 : nsOnloadBlocker::GetName(nsACString &aResult)
     620                 : { 
     621               0 :   aResult.AssignLiteral("about:document-onload-blocker");
     622               0 :   return NS_OK;
     623                 : }
     624                 : 
     625                 : NS_IMETHODIMP
     626               0 : nsOnloadBlocker::IsPending(bool *_retval)
     627                 : {
     628               0 :   *_retval = true;
     629               0 :   return NS_OK;
     630                 : }
     631                 : 
     632                 : NS_IMETHODIMP
     633               0 : nsOnloadBlocker::GetStatus(nsresult *status)
     634                 : {
     635               0 :   *status = NS_OK;
     636               0 :   return NS_OK;
     637                 : } 
     638                 : 
     639                 : NS_IMETHODIMP
     640               0 : nsOnloadBlocker::Cancel(nsresult status)
     641                 : {
     642               0 :   return NS_OK;
     643                 : }
     644                 : NS_IMETHODIMP
     645               0 : nsOnloadBlocker::Suspend(void)
     646                 : {
     647               0 :   return NS_OK;
     648                 : }
     649                 : NS_IMETHODIMP
     650               0 : nsOnloadBlocker::Resume(void)
     651                 : {
     652               0 :   return NS_OK;
     653                 : }
     654                 : 
     655                 : NS_IMETHODIMP
     656               0 : nsOnloadBlocker::GetLoadGroup(nsILoadGroup * *aLoadGroup)
     657                 : {
     658               0 :   *aLoadGroup = nsnull;
     659               0 :   return NS_OK;
     660                 : }
     661                 : 
     662                 : NS_IMETHODIMP
     663               0 : nsOnloadBlocker::SetLoadGroup(nsILoadGroup * aLoadGroup)
     664                 : {
     665               0 :   return NS_OK;
     666                 : }
     667                 : 
     668                 : NS_IMETHODIMP
     669               0 : nsOnloadBlocker::GetLoadFlags(nsLoadFlags *aLoadFlags)
     670                 : {
     671               0 :   *aLoadFlags = nsIRequest::LOAD_NORMAL;
     672               0 :   return NS_OK;
     673                 : }
     674                 : 
     675                 : NS_IMETHODIMP
     676               0 : nsOnloadBlocker::SetLoadFlags(nsLoadFlags aLoadFlags)
     677                 : {
     678               0 :   return NS_OK;
     679                 : }
     680                 : 
     681                 : // ==================================================================
     682                 : 
     683            1273 : nsExternalResourceMap::nsExternalResourceMap()
     684            1273 :   : mHaveShutDown(false)
     685                 : {
     686            1273 :   mMap.Init();
     687            1273 :   mPendingLoads.Init();
     688            1273 : }
     689                 : 
     690                 : nsIDocument*
     691               0 : nsExternalResourceMap::RequestResource(nsIURI* aURI,
     692                 :                                        nsINode* aRequestingNode,
     693                 :                                        nsDocument* aDisplayDocument,
     694                 :                                        ExternalResourceLoad** aPendingLoad)
     695                 : {
     696                 :   // If we ever start allowing non-same-origin loads here, we might need to do
     697                 :   // something interesting with aRequestingPrincipal even for the hashtable
     698                 :   // gets.
     699               0 :   NS_PRECONDITION(aURI, "Must have a URI");
     700               0 :   NS_PRECONDITION(aRequestingNode, "Must have a node");
     701               0 :   *aPendingLoad = nsnull;
     702               0 :   if (mHaveShutDown) {
     703               0 :     return nsnull;
     704                 :   }
     705                 :   
     706                 :   // First, make sure we strip the ref from aURI.
     707               0 :   nsCOMPtr<nsIURI> clone;
     708               0 :   nsresult rv = aURI->CloneIgnoringRef(getter_AddRefs(clone));
     709               0 :   if (NS_FAILED(rv) || !clone) {
     710               0 :     return nsnull;
     711                 :   }
     712                 :   
     713                 :   ExternalResource* resource;
     714               0 :   mMap.Get(clone, &resource);
     715               0 :   if (resource) {
     716               0 :     return resource->mDocument;
     717                 :   }
     718                 : 
     719               0 :   nsRefPtr<PendingLoad> load;
     720               0 :   mPendingLoads.Get(clone, getter_AddRefs(load));
     721               0 :   if (load) {
     722               0 :     load.forget(aPendingLoad);
     723               0 :     return nsnull;
     724                 :   }
     725                 : 
     726               0 :   load = new PendingLoad(aDisplayDocument);
     727                 : 
     728               0 :   if (!mPendingLoads.Put(clone, load)) {
     729               0 :     return nsnull;
     730                 :   }
     731                 : 
     732               0 :   if (NS_FAILED(load->StartLoad(clone, aRequestingNode))) {
     733                 :     // Make sure we don't thrash things by trying this load again, since
     734                 :     // chances are it failed for good reasons (security check, etc).
     735               0 :     AddExternalResource(clone, nsnull, nsnull, aDisplayDocument);
     736                 :   } else {
     737               0 :     load.forget(aPendingLoad);
     738                 :   }
     739                 : 
     740               0 :   return nsnull;
     741                 : }
     742                 : 
     743                 : struct
     744                 : nsExternalResourceEnumArgs
     745                 : {
     746                 :   nsIDocument::nsSubDocEnumFunc callback;
     747                 :   void *data;
     748                 : };
     749                 : 
     750                 : static PLDHashOperator
     751               0 : ExternalResourceEnumerator(nsIURI* aKey,
     752                 :                            nsExternalResourceMap::ExternalResource* aData,
     753                 :                            void* aClosure)
     754                 : {
     755                 :   nsExternalResourceEnumArgs* args =
     756               0 :     static_cast<nsExternalResourceEnumArgs*>(aClosure);
     757                 :   bool next =
     758               0 :     aData->mDocument ? args->callback(aData->mDocument, args->data) : true;
     759               0 :   return next ? PL_DHASH_NEXT : PL_DHASH_STOP;
     760                 : }
     761                 : 
     762                 : void
     763               0 : nsExternalResourceMap::EnumerateResources(nsIDocument::nsSubDocEnumFunc aCallback,
     764                 :                                           void* aData)
     765                 : {
     766               0 :   nsExternalResourceEnumArgs args = { aCallback, aData };
     767               0 :   mMap.EnumerateRead(ExternalResourceEnumerator, &args);
     768               0 : }
     769                 : 
     770                 : static PLDHashOperator
     771               0 : ExternalResourceTraverser(nsIURI* aKey,
     772                 :                           nsExternalResourceMap::ExternalResource* aData,
     773                 :                           void* aClosure)
     774                 : {
     775                 :   nsCycleCollectionTraversalCallback *cb = 
     776               0 :     static_cast<nsCycleCollectionTraversalCallback*>(aClosure);
     777                 : 
     778               0 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
     779                 :                                      "mExternalResourceMap.mMap entry"
     780                 :                                      "->mDocument");
     781               0 :   cb->NoteXPCOMChild(aData->mDocument);
     782                 : 
     783               0 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
     784                 :                                      "mExternalResourceMap.mMap entry"
     785                 :                                      "->mViewer");
     786               0 :   cb->NoteXPCOMChild(aData->mViewer);
     787                 : 
     788               0 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
     789                 :                                      "mExternalResourceMap.mMap entry"
     790                 :                                      "->mLoadGroup");
     791               0 :   cb->NoteXPCOMChild(aData->mLoadGroup);
     792                 : 
     793               0 :   return PL_DHASH_NEXT;
     794                 : }
     795                 : 
     796                 : void
     797            1462 : nsExternalResourceMap::Traverse(nsCycleCollectionTraversalCallback* aCallback) const
     798                 : {
     799                 :   // mPendingLoads will get cleared out as the requests complete, so
     800                 :   // no need to worry about those here.
     801            1462 :   mMap.EnumerateRead(ExternalResourceTraverser, aCallback);
     802            1462 : }
     803                 : 
     804                 : static PLDHashOperator
     805               0 : ExternalResourceHider(nsIURI* aKey,
     806                 :                       nsExternalResourceMap::ExternalResource* aData,
     807                 :                       void* aClosure)
     808                 : {
     809               0 :   if (aData->mViewer) {
     810               0 :     aData->mViewer->Hide();
     811                 :   }
     812               0 :   return PL_DHASH_NEXT;
     813                 : }
     814                 : 
     815                 : void
     816               0 : nsExternalResourceMap::HideViewers()
     817                 : {
     818               0 :   mMap.EnumerateRead(ExternalResourceHider, nsnull);
     819               0 : }
     820                 : 
     821                 : static PLDHashOperator
     822               0 : ExternalResourceShower(nsIURI* aKey,
     823                 :                        nsExternalResourceMap::ExternalResource* aData,
     824                 :                        void* aClosure)
     825                 : {
     826               0 :   if (aData->mViewer) {
     827               0 :     aData->mViewer->Show();
     828                 :   }
     829               0 :   return PL_DHASH_NEXT;
     830                 : }
     831                 : 
     832                 : void
     833               0 : nsExternalResourceMap::ShowViewers()
     834                 : {
     835               0 :   mMap.EnumerateRead(ExternalResourceShower, nsnull);
     836               0 : }
     837                 : 
     838                 : void
     839               0 : TransferZoomLevels(nsIDocument* aFromDoc,
     840                 :                    nsIDocument* aToDoc)
     841                 : {
     842               0 :   NS_ABORT_IF_FALSE(aFromDoc && aToDoc,
     843                 :                     "transferring zoom levels from/to null doc");
     844                 : 
     845               0 :   nsIPresShell* fromShell = aFromDoc->GetShell();
     846               0 :   if (!fromShell)
     847               0 :     return;
     848                 : 
     849               0 :   nsPresContext* fromCtxt = fromShell->GetPresContext();
     850               0 :   if (!fromCtxt)
     851               0 :     return;
     852                 : 
     853               0 :   nsIPresShell* toShell = aToDoc->GetShell();
     854               0 :   if (!toShell)
     855               0 :     return;
     856                 : 
     857               0 :   nsPresContext* toCtxt = toShell->GetPresContext();
     858               0 :   if (!toCtxt)
     859               0 :     return;
     860                 : 
     861               0 :   toCtxt->SetFullZoom(fromCtxt->GetFullZoom());
     862               0 :   toCtxt->SetMinFontSize(fromCtxt->MinFontSize(nsnull));
     863               0 :   toCtxt->SetTextZoom(fromCtxt->TextZoom());
     864                 : }
     865                 : 
     866                 : void
     867               0 : TransferShowingState(nsIDocument* aFromDoc, nsIDocument* aToDoc)
     868                 : {
     869               0 :   NS_ABORT_IF_FALSE(aFromDoc && aToDoc,
     870                 :                     "transferring showing state from/to null doc");
     871                 : 
     872               0 :   if (aFromDoc->IsShowing()) {
     873               0 :     aToDoc->OnPageShow(true, nsnull);
     874                 :   }
     875               0 : }
     876                 : 
     877                 : nsresult
     878               0 : nsExternalResourceMap::AddExternalResource(nsIURI* aURI,
     879                 :                                            nsIContentViewer* aViewer,
     880                 :                                            nsILoadGroup* aLoadGroup,
     881                 :                                            nsIDocument* aDisplayDocument)
     882                 : {
     883               0 :   NS_PRECONDITION(aURI, "Unexpected call");
     884               0 :   NS_PRECONDITION((aViewer && aLoadGroup) || (!aViewer && !aLoadGroup),
     885                 :                   "Must have both or neither");
     886                 :   
     887               0 :   nsRefPtr<PendingLoad> load;
     888               0 :   mPendingLoads.Get(aURI, getter_AddRefs(load));
     889               0 :   mPendingLoads.Remove(aURI);
     890                 : 
     891               0 :   nsresult rv = NS_OK;
     892                 :   
     893               0 :   nsCOMPtr<nsIDocument> doc;
     894               0 :   if (aViewer) {
     895               0 :     doc = aViewer->GetDocument();
     896               0 :     NS_ASSERTION(doc, "Must have a document");
     897                 : 
     898               0 :     nsCOMPtr<nsIXULDocument> xulDoc = do_QueryInterface(doc);
     899               0 :     if (xulDoc) {
     900                 :       // We don't handle XUL stuff here yet.
     901               0 :       rv = NS_ERROR_NOT_AVAILABLE;
     902                 :     } else {
     903               0 :       doc->SetDisplayDocument(aDisplayDocument);
     904                 : 
     905                 :       // Make sure that hiding our viewer will tear down its presentation.
     906               0 :       aViewer->SetSticky(false);
     907                 : 
     908               0 :       rv = aViewer->Init(nsnull, nsIntRect(0, 0, 0, 0));
     909               0 :       if (NS_SUCCEEDED(rv)) {
     910               0 :         rv = aViewer->Open(nsnull, nsnull);
     911                 :       }
     912                 :     }
     913                 :     
     914               0 :     if (NS_FAILED(rv)) {
     915               0 :       doc = nsnull;
     916               0 :       aViewer = nsnull;
     917               0 :       aLoadGroup = nsnull;
     918                 :     }
     919                 :   }
     920                 : 
     921               0 :   ExternalResource* newResource = new ExternalResource();
     922               0 :   if (newResource && !mMap.Put(aURI, newResource)) {
     923               0 :     delete newResource;
     924               0 :     newResource = nsnull;
     925               0 :     if (NS_SUCCEEDED(rv)) {
     926               0 :       rv = NS_ERROR_OUT_OF_MEMORY;
     927                 :     }
     928                 :   }
     929                 : 
     930               0 :   if (newResource) {
     931               0 :     newResource->mDocument = doc;
     932               0 :     newResource->mViewer = aViewer;
     933               0 :     newResource->mLoadGroup = aLoadGroup;
     934               0 :     if (doc) {
     935               0 :       TransferZoomLevels(aDisplayDocument, doc);
     936               0 :       TransferShowingState(aDisplayDocument, doc);
     937                 :     }
     938                 :   }
     939                 : 
     940               0 :   const nsTArray< nsCOMPtr<nsIObserver> > & obs = load->Observers();
     941               0 :   for (PRUint32 i = 0; i < obs.Length(); ++i) {
     942               0 :     obs[i]->Observe(doc, "external-resource-document-created", nsnull);
     943                 :   }
     944                 : 
     945               0 :   return rv;
     946                 : }
     947                 : 
     948               0 : NS_IMPL_ISUPPORTS2(nsExternalResourceMap::PendingLoad,
     949                 :                    nsIStreamListener,
     950                 :                    nsIRequestObserver)
     951                 : 
     952                 : NS_IMETHODIMP
     953               0 : nsExternalResourceMap::PendingLoad::OnStartRequest(nsIRequest *aRequest,
     954                 :                                                    nsISupports *aContext)
     955                 : {
     956               0 :   nsExternalResourceMap& map = mDisplayDocument->ExternalResourceMap();
     957               0 :   if (map.HaveShutDown()) {
     958               0 :     return NS_BINDING_ABORTED;
     959                 :   }
     960                 : 
     961               0 :   nsCOMPtr<nsIContentViewer> viewer;
     962               0 :   nsCOMPtr<nsILoadGroup> loadGroup;
     963               0 :   nsresult rv = SetupViewer(aRequest, getter_AddRefs(viewer),
     964               0 :                             getter_AddRefs(loadGroup));
     965                 : 
     966                 :   // Make sure to do this no matter what
     967                 :   nsresult rv2 = map.AddExternalResource(mURI, viewer, loadGroup,
     968               0 :                                          mDisplayDocument);
     969               0 :   if (NS_FAILED(rv)) {
     970               0 :     return rv;
     971                 :   }
     972               0 :   if (NS_FAILED(rv2)) {
     973               0 :     mTargetListener = nsnull;
     974               0 :     return rv2;
     975                 :   }
     976                 :   
     977               0 :   return mTargetListener->OnStartRequest(aRequest, aContext);
     978                 : }
     979                 : 
     980                 : nsresult
     981               0 : nsExternalResourceMap::PendingLoad::SetupViewer(nsIRequest* aRequest,
     982                 :                                                 nsIContentViewer** aViewer,
     983                 :                                                 nsILoadGroup** aLoadGroup)
     984                 : {
     985               0 :   NS_PRECONDITION(!mTargetListener, "Unexpected call to OnStartRequest");
     986               0 :   *aViewer = nsnull;
     987               0 :   *aLoadGroup = nsnull;
     988                 :   
     989               0 :   nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest));
     990               0 :   NS_ENSURE_TRUE(chan, NS_ERROR_UNEXPECTED);
     991                 : 
     992               0 :   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aRequest));
     993               0 :   if (httpChannel) {
     994                 :     bool requestSucceeded;
     995               0 :     if (NS_FAILED(httpChannel->GetRequestSucceeded(&requestSucceeded)) ||
     996               0 :         !requestSucceeded) {
     997                 :       // Bail out on this load, since it looks like we have an HTTP error page
     998               0 :       return NS_BINDING_ABORTED;
     999                 :     }
    1000                 :   }
    1001                 :  
    1002               0 :   nsCAutoString type;
    1003               0 :   chan->GetContentType(type);
    1004                 : 
    1005               0 :   nsCOMPtr<nsILoadGroup> loadGroup;
    1006               0 :   chan->GetLoadGroup(getter_AddRefs(loadGroup));
    1007                 : 
    1008                 :   // Give this document its own loadgroup
    1009                 :   nsCOMPtr<nsILoadGroup> newLoadGroup =
    1010               0 :         do_CreateInstance(NS_LOADGROUP_CONTRACTID);
    1011               0 :   NS_ENSURE_TRUE(newLoadGroup, NS_ERROR_OUT_OF_MEMORY);
    1012               0 :   newLoadGroup->SetLoadGroup(loadGroup);
    1013                 : 
    1014               0 :   nsCOMPtr<nsIInterfaceRequestor> callbacks;
    1015               0 :   loadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
    1016                 : 
    1017                 :   nsCOMPtr<nsIInterfaceRequestor> newCallbacks =
    1018               0 :     new LoadgroupCallbacks(callbacks);
    1019               0 :   newLoadGroup->SetNotificationCallbacks(newCallbacks);
    1020                 : 
    1021                 :   // This is some serious hackery cribbed from docshell
    1022                 :   nsCOMPtr<nsICategoryManager> catMan =
    1023               0 :     do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
    1024               0 :   NS_ENSURE_TRUE(catMan, NS_ERROR_NOT_AVAILABLE);
    1025               0 :   nsXPIDLCString contractId;
    1026               0 :   nsresult rv = catMan->GetCategoryEntry("Gecko-Content-Viewers", type.get(),
    1027               0 :                                          getter_Copies(contractId));
    1028               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1029                 :   nsCOMPtr<nsIDocumentLoaderFactory> docLoaderFactory =
    1030               0 :     do_GetService(contractId);
    1031               0 :   NS_ENSURE_TRUE(docLoaderFactory, NS_ERROR_NOT_AVAILABLE);
    1032                 : 
    1033               0 :   nsCOMPtr<nsIContentViewer> viewer;
    1034               0 :   nsCOMPtr<nsIStreamListener> listener;
    1035               0 :   rv = docLoaderFactory->CreateInstance("external-resource", chan, newLoadGroup,
    1036                 :                                         type.get(), nsnull, nsnull,
    1037               0 :                                         getter_AddRefs(listener),
    1038               0 :                                         getter_AddRefs(viewer));
    1039               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1040               0 :   NS_ENSURE_TRUE(viewer, NS_ERROR_UNEXPECTED);
    1041                 : 
    1042               0 :   nsCOMPtr<nsIParser> parser = do_QueryInterface(listener);
    1043               0 :   if (!parser) {
    1044                 :     /// We don't want to deal with the various fake documents yet
    1045               0 :     return NS_ERROR_NOT_IMPLEMENTED;
    1046                 :   }
    1047                 : 
    1048                 :   // We can't handle HTML and other weird things here yet.
    1049               0 :   nsIContentSink* sink = parser->GetContentSink();
    1050               0 :   nsCOMPtr<nsIXMLContentSink> xmlSink = do_QueryInterface(sink);
    1051               0 :   if (!xmlSink) {
    1052               0 :     return NS_ERROR_NOT_IMPLEMENTED;
    1053                 :   }
    1054                 : 
    1055               0 :   listener.swap(mTargetListener);
    1056               0 :   viewer.forget(aViewer);
    1057               0 :   newLoadGroup.forget(aLoadGroup);
    1058               0 :   return NS_OK;
    1059                 : }
    1060                 : 
    1061                 : NS_IMETHODIMP
    1062               0 : nsExternalResourceMap::PendingLoad::OnDataAvailable(nsIRequest* aRequest,
    1063                 :                                                     nsISupports* aContext,
    1064                 :                                                     nsIInputStream* aStream,
    1065                 :                                                     PRUint32 aOffset,
    1066                 :                                                     PRUint32 aCount)
    1067                 : {
    1068               0 :   NS_PRECONDITION(mTargetListener, "Shouldn't be getting called!");
    1069               0 :   if (mDisplayDocument->ExternalResourceMap().HaveShutDown()) {
    1070               0 :     return NS_BINDING_ABORTED;
    1071                 :   }
    1072               0 :   return mTargetListener->OnDataAvailable(aRequest, aContext, aStream, aOffset,
    1073               0 :                                           aCount);
    1074                 : }
    1075                 : 
    1076                 : NS_IMETHODIMP
    1077               0 : nsExternalResourceMap::PendingLoad::OnStopRequest(nsIRequest* aRequest,
    1078                 :                                                   nsISupports* aContext,
    1079                 :                                                   nsresult aStatus)
    1080                 : {
    1081                 :   // mTargetListener might be null if SetupViewer or AddExternalResource failed
    1082               0 :   if (mTargetListener) {
    1083               0 :     nsCOMPtr<nsIStreamListener> listener;
    1084               0 :     mTargetListener.swap(listener);
    1085               0 :     return listener->OnStopRequest(aRequest, aContext, aStatus);
    1086                 :   }
    1087                 : 
    1088               0 :   return NS_OK;
    1089                 : }
    1090                 : 
    1091                 : nsresult
    1092               0 : nsExternalResourceMap::PendingLoad::StartLoad(nsIURI* aURI,
    1093                 :                                               nsINode* aRequestingNode)
    1094                 : {
    1095               0 :   NS_PRECONDITION(aURI, "Must have a URI");
    1096               0 :   NS_PRECONDITION(aRequestingNode, "Must have a node");
    1097                 : 
    1098                 :   // Time to start a load.  First, the security checks.
    1099                 : 
    1100               0 :   nsIPrincipal* requestingPrincipal = aRequestingNode->NodePrincipal();
    1101                 : 
    1102               0 :   nsresult rv = nsContentUtils::GetSecurityManager()->
    1103                 :     CheckLoadURIWithPrincipal(requestingPrincipal, aURI,
    1104               0 :                               nsIScriptSecurityManager::STANDARD);
    1105               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1106                 :   
    1107                 :   // Allow data URIs (let them skip the CheckMayLoad call), since we want
    1108                 :   // to allow external resources from data URIs regardless of the difference
    1109                 :   // in URI scheme.
    1110                 :   bool doesInheritSecurityContext;
    1111                 :   rv =
    1112                 :     NS_URIChainHasFlags(aURI,
    1113                 :                         nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
    1114               0 :                         &doesInheritSecurityContext);
    1115               0 :   if (NS_FAILED(rv) || !doesInheritSecurityContext) {
    1116               0 :     rv = requestingPrincipal->CheckMayLoad(aURI, true);
    1117               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1118                 :   }
    1119                 : 
    1120               0 :   PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
    1121                 :   rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_OTHER,
    1122                 :                                  aURI,
    1123                 :                                  requestingPrincipal,
    1124                 :                                  aRequestingNode,
    1125               0 :                                  EmptyCString(), //mime guess
    1126                 :                                  nsnull,         //extra
    1127                 :                                  &shouldLoad,
    1128                 :                                  nsContentUtils::GetContentPolicy(),
    1129               0 :                                  nsContentUtils::GetSecurityManager());
    1130               0 :   if (NS_FAILED(rv)) return rv;
    1131               0 :   if (NS_CP_REJECTED(shouldLoad)) {
    1132                 :     // Disallowed by content policy
    1133               0 :     return NS_ERROR_CONTENT_BLOCKED;
    1134                 :   }
    1135                 : 
    1136               0 :   nsIDocument* doc = aRequestingNode->OwnerDoc();
    1137                 : 
    1138               0 :   nsCOMPtr<nsIInterfaceRequestor> req = nsContentUtils::GetSameOriginChecker();
    1139               0 :   NS_ENSURE_TRUE(req, NS_ERROR_OUT_OF_MEMORY);
    1140                 : 
    1141               0 :   nsCOMPtr<nsILoadGroup> loadGroup = doc->GetDocumentLoadGroup();
    1142               0 :   nsCOMPtr<nsIChannel> channel;
    1143               0 :   rv = NS_NewChannel(getter_AddRefs(channel), aURI, nsnull, loadGroup, req);
    1144               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1145                 : 
    1146               0 :   mURI = aURI;
    1147                 : 
    1148               0 :   return channel->AsyncOpen(this, nsnull);
    1149                 : }
    1150                 : 
    1151               0 : NS_IMPL_ISUPPORTS1(nsExternalResourceMap::LoadgroupCallbacks,
    1152                 :                    nsIInterfaceRequestor)
    1153                 : 
    1154                 : #define IMPL_SHIM(_i) \
    1155                 :   NS_IMPL_ISUPPORTS1(nsExternalResourceMap::LoadgroupCallbacks::_i##Shim, _i)
    1156                 : 
    1157               0 : IMPL_SHIM(nsILoadContext)
    1158               0 : IMPL_SHIM(nsIProgressEventSink)
    1159               0 : IMPL_SHIM(nsIChannelEventSink)
    1160               0 : IMPL_SHIM(nsISecurityEventSink)
    1161               0 : IMPL_SHIM(nsIApplicationCacheContainer)
    1162                 : 
    1163                 : #undef IMPL_SHIM
    1164                 : 
    1165                 : #define IID_IS(_i) aIID.Equals(NS_GET_IID(_i))
    1166                 : 
    1167                 : #define TRY_SHIM(_i)                                                       \
    1168                 :   PR_BEGIN_MACRO                                                           \
    1169                 :     if (IID_IS(_i)) {                                                      \
    1170                 :       nsCOMPtr<_i> real = do_GetInterface(mCallbacks);                     \
    1171                 :       if (!real) {                                                         \
    1172                 :         return NS_NOINTERFACE;                                             \
    1173                 :       }                                                                    \
    1174                 :       nsCOMPtr<_i> shim = new _i##Shim(this, real);                        \
    1175                 :       if (!shim) {                                                         \
    1176                 :         return NS_ERROR_OUT_OF_MEMORY;                                     \
    1177                 :       }                                                                    \
    1178                 :       *aSink = shim.forget().get();                                        \
    1179                 :       return NS_OK;                                                        \
    1180                 :     }                                                                      \
    1181                 :   PR_END_MACRO
    1182                 : 
    1183                 : NS_IMETHODIMP
    1184               0 : nsExternalResourceMap::LoadgroupCallbacks::GetInterface(const nsIID & aIID,
    1185                 :                                                         void **aSink)
    1186                 : {
    1187               0 :   if (mCallbacks &&
    1188               0 :       (IID_IS(nsIPrompt) || IID_IS(nsIAuthPrompt) || IID_IS(nsIAuthPrompt2) ||
    1189               0 :        IID_IS(nsITabChild))) {
    1190               0 :     return mCallbacks->GetInterface(aIID, aSink);
    1191                 :   }
    1192                 : 
    1193               0 :   *aSink = nsnull;
    1194                 : 
    1195               0 :   TRY_SHIM(nsILoadContext);
    1196               0 :   TRY_SHIM(nsIProgressEventSink);
    1197               0 :   TRY_SHIM(nsIChannelEventSink);
    1198               0 :   TRY_SHIM(nsISecurityEventSink);
    1199               0 :   TRY_SHIM(nsIApplicationCacheContainer);
    1200                 :     
    1201               0 :   return NS_NOINTERFACE;
    1202                 : }
    1203                 : 
    1204                 : #undef TRY_SHIM
    1205                 : #undef IID_IS
    1206                 : 
    1207               0 : nsExternalResourceMap::ExternalResource::~ExternalResource()
    1208                 : {
    1209               0 :   if (mViewer) {
    1210               0 :     mViewer->Close(nsnull);
    1211               0 :     mViewer->Destroy();
    1212                 :   }
    1213               0 : }
    1214                 : 
    1215                 : // ==================================================================
    1216                 : // =
    1217                 : // ==================================================================
    1218                 : 
    1219                 : // If we ever have an nsIDocumentObserver notification for stylesheet title
    1220                 : // changes, we could make this inherit from nsDOMStringList instead of
    1221                 : // reimplementing nsIDOMDOMStringList.
    1222                 : class nsDOMStyleSheetSetList : public nsIDOMDOMStringList
    1223                 :                           
    1224                 : {
    1225                 : public:
    1226                 :   NS_DECL_ISUPPORTS
    1227                 : 
    1228                 :   NS_DECL_NSIDOMDOMSTRINGLIST
    1229                 : 
    1230                 :   nsDOMStyleSheetSetList(nsIDocument* aDocument);
    1231                 : 
    1232               0 :   void Disconnect()
    1233                 :   {
    1234               0 :     mDocument = nsnull;
    1235               0 :   }
    1236                 : 
    1237                 : protected:
    1238                 :   // Rebuild our list of style sets
    1239                 :   nsresult GetSets(nsTArray<nsString>& aStyleSets);
    1240                 :   
    1241                 :   nsIDocument* mDocument;  // Our document; weak ref.  It'll let us know if it
    1242                 :                            // dies.
    1243                 : };
    1244                 : 
    1245               0 : NS_IMPL_ADDREF(nsDOMStyleSheetSetList)
    1246               0 : NS_IMPL_RELEASE(nsDOMStyleSheetSetList)
    1247               0 : NS_INTERFACE_TABLE_HEAD(nsDOMStyleSheetSetList)
    1248                 :   NS_OFFSET_AND_INTERFACE_TABLE_BEGIN(nsDOMStyleSheetSetList)
    1249                 :     NS_INTERFACE_TABLE_ENTRY(nsDOMStyleSheetSetList, nsIDOMDOMStringList)
    1250               0 :   NS_OFFSET_AND_INTERFACE_TABLE_END
    1251               0 :   NS_OFFSET_AND_INTERFACE_TABLE_TO_MAP_SEGUE
    1252               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DOMStringList)
    1253               0 : NS_INTERFACE_MAP_END
    1254                 : 
    1255               0 : nsDOMStyleSheetSetList::nsDOMStyleSheetSetList(nsIDocument* aDocument)
    1256               0 :   : mDocument(aDocument)
    1257                 : {
    1258               0 :   NS_ASSERTION(mDocument, "Must have document!");
    1259               0 : }
    1260                 : 
    1261                 : NS_IMETHODIMP
    1262               0 : nsDOMStyleSheetSetList::Item(PRUint32 aIndex, nsAString& aResult)
    1263                 : {
    1264               0 :   nsTArray<nsString> styleSets;
    1265               0 :   nsresult rv = GetSets(styleSets);
    1266               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1267                 :   
    1268               0 :   if (aIndex >= styleSets.Length()) {
    1269               0 :     SetDOMStringToNull(aResult);
    1270                 :   } else {
    1271               0 :     aResult = styleSets[aIndex];
    1272                 :   }
    1273                 : 
    1274               0 :   return NS_OK;
    1275                 : }
    1276                 : 
    1277                 : NS_IMETHODIMP
    1278               0 : nsDOMStyleSheetSetList::GetLength(PRUint32 *aLength)
    1279                 : {
    1280               0 :   nsTArray<nsString> styleSets;
    1281               0 :   nsresult rv = GetSets(styleSets);
    1282               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1283                 :   
    1284               0 :   *aLength = styleSets.Length();
    1285                 : 
    1286               0 :   return NS_OK;
    1287                 : }
    1288                 : 
    1289                 : NS_IMETHODIMP
    1290               0 : nsDOMStyleSheetSetList::Contains(const nsAString& aString, bool *aResult)
    1291                 : {
    1292               0 :   nsTArray<nsString> styleSets;
    1293               0 :   nsresult rv = GetSets(styleSets);
    1294               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1295                 :   
    1296               0 :   *aResult = styleSets.Contains(aString);
    1297                 : 
    1298               0 :   return NS_OK;
    1299                 : }
    1300                 : 
    1301                 : nsresult
    1302               0 : nsDOMStyleSheetSetList::GetSets(nsTArray<nsString>& aStyleSets)
    1303                 : {
    1304               0 :   if (!mDocument) {
    1305               0 :     return NS_OK; // Spec says "no exceptions", and we have no style sets if we
    1306                 :                   // have no document, for sure
    1307                 :   }
    1308                 :   
    1309               0 :   PRInt32 count = mDocument->GetNumberOfStyleSheets();
    1310               0 :   nsAutoString title;
    1311               0 :   nsAutoString temp;
    1312               0 :   for (PRInt32 index = 0; index < count; index++) {
    1313               0 :     nsIStyleSheet* sheet = mDocument->GetStyleSheetAt(index);
    1314               0 :     NS_ASSERTION(sheet, "Null sheet in sheet list!");
    1315               0 :     sheet->GetTitle(title);
    1316               0 :     if (!title.IsEmpty() && !aStyleSets.Contains(title) &&
    1317               0 :         !aStyleSets.AppendElement(title)) {
    1318               0 :       return NS_ERROR_OUT_OF_MEMORY;
    1319                 :     }
    1320                 :   }
    1321                 : 
    1322               0 :   return NS_OK;
    1323                 : }
    1324                 : 
    1325                 : // ==================================================================
    1326                 : // =
    1327                 : // ==================================================================
    1328                 : 
    1329                 : class nsDOMImplementation : public nsIDOMDOMImplementation
    1330                 : {
    1331                 : public:
    1332                 :   nsDOMImplementation(nsIDocument* aOwner,
    1333                 :                       nsIScriptGlobalObject* aScriptObject,
    1334                 :                       nsIURI* aDocumentURI,
    1335                 :                       nsIURI* aBaseURI);
    1336                 :   virtual ~nsDOMImplementation();
    1337                 : 
    1338               1 :   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
    1339            1496 :   NS_DECL_CYCLE_COLLECTION_CLASS(nsDOMImplementation)
    1340                 : 
    1341                 :   // nsIDOMDOMImplementation
    1342                 :   NS_DECL_NSIDOMDOMIMPLEMENTATION
    1343                 : 
    1344                 : protected:
    1345                 :   nsCOMPtr<nsIDocument> mOwner;
    1346                 :   nsWeakPtr mScriptObject;
    1347                 :   nsCOMPtr<nsIURI> mDocumentURI;
    1348                 :   nsCOMPtr<nsIURI> mBaseURI;
    1349                 : };
    1350                 : 
    1351               1 : nsDOMImplementation::nsDOMImplementation(nsIDocument* aOwner,
    1352                 :                                          nsIScriptGlobalObject* aScriptObject,
    1353                 :                                          nsIURI* aDocumentURI,
    1354                 :                                          nsIURI* aBaseURI)
    1355                 :   : mOwner(aOwner),
    1356               1 :     mScriptObject(do_GetWeakReference(aScriptObject)),
    1357                 :     mDocumentURI(aDocumentURI),
    1358               2 :     mBaseURI(aBaseURI)
    1359                 : {
    1360               1 : }
    1361                 : 
    1362               2 : nsDOMImplementation::~nsDOMImplementation()
    1363                 : {
    1364               4 : }
    1365                 : 
    1366                 : DOMCI_DATA(DOMImplementation, nsDOMImplementation)
    1367                 : 
    1368                 : // QueryInterface implementation for nsDOMImplementation
    1369              29 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMImplementation)
    1370              15 :   NS_INTERFACE_MAP_ENTRY(nsIDOMDOMImplementation)
    1371               9 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMDOMImplementation)
    1372               7 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DOMImplementation)
    1373               6 : NS_INTERFACE_MAP_END
    1374                 : 
    1375            1466 : NS_IMPL_CYCLE_COLLECTION_1(nsDOMImplementation, mOwner)
    1376                 : 
    1377              12 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMImplementation)
    1378              12 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMImplementation)
    1379                 : 
    1380                 : 
    1381                 : NS_IMETHODIMP
    1382               0 : nsDOMImplementation::HasFeature(const nsAString& aFeature,
    1383                 :                                 const nsAString& aVersion,
    1384                 :                                 bool* aReturn)
    1385                 : {
    1386                 :   return nsGenericElement::InternalIsSupported(
    1387                 :            static_cast<nsIDOMDOMImplementation*>(this),
    1388               0 :            aFeature, aVersion, aReturn);
    1389                 : }
    1390                 : 
    1391                 : NS_IMETHODIMP
    1392               1 : nsDOMImplementation::CreateDocumentType(const nsAString& aQualifiedName,
    1393                 :                                         const nsAString& aPublicId,
    1394                 :                                         const nsAString& aSystemId,
    1395                 :                                         nsIDOMDocumentType** aReturn)
    1396                 : {
    1397               1 :   *aReturn = nsnull;
    1398               1 :   NS_ENSURE_STATE(mOwner);
    1399                 : 
    1400               1 :   nsresult rv = nsContentUtils::CheckQName(aQualifiedName);
    1401               1 :   NS_ENSURE_SUCCESS(rv, rv);
    1402                 : 
    1403               2 :   nsCOMPtr<nsIAtom> name = do_GetAtom(aQualifiedName);
    1404               1 :   NS_ENSURE_TRUE(name, NS_ERROR_OUT_OF_MEMORY);
    1405                 : 
    1406                 :   // Indicate that there is no internal subset (not just an empty one)
    1407                 :   return NS_NewDOMDocumentType(aReturn, mOwner->NodeInfoManager(),
    1408                 :                                name, aPublicId,
    1409               1 :                                aSystemId, NullString());
    1410                 : }
    1411                 : 
    1412                 : NS_IMETHODIMP
    1413               1 : nsDOMImplementation::CreateDocument(const nsAString& aNamespaceURI,
    1414                 :                                     const nsAString& aQualifiedName,
    1415                 :                                     nsIDOMDocumentType* aDoctype,
    1416                 :                                     nsIDOMDocument** aReturn)
    1417                 : {
    1418               1 :   *aReturn = nsnull;
    1419                 : 
    1420                 :   nsresult rv;
    1421               1 :   if (!aQualifiedName.IsEmpty()) {
    1422               1 :     nsIParserService *parserService = nsContentUtils::GetParserService();
    1423               1 :     NS_ENSURE_TRUE(parserService, NS_ERROR_FAILURE);
    1424                 : 
    1425               2 :     const nsAFlatString& qName = PromiseFlatString(aQualifiedName);
    1426                 :     const PRUnichar *colon;
    1427               1 :     rv = parserService->CheckQName(qName, true, &colon);
    1428               1 :     NS_ENSURE_SUCCESS(rv, rv);
    1429                 : 
    1430               2 :     if (colon &&
    1431               0 :         (DOMStringIsNull(aNamespaceURI) ||
    1432               1 :          (Substring(qName.get(), colon).EqualsLiteral("xml") &&
    1433               0 :           !aNamespaceURI.EqualsLiteral("http://www.w3.org/XML/1998/namespace")))) {
    1434               0 :       return NS_ERROR_DOM_NAMESPACE_ERR;
    1435                 :     }
    1436                 :   }
    1437               0 :   else if (DOMStringIsNull(aQualifiedName) &&
    1438               0 :            !DOMStringIsNull(aNamespaceURI)) {
    1439               0 :     return NS_ERROR_DOM_NAMESPACE_ERR;
    1440                 :   }
    1441                 : 
    1442                 :   nsCOMPtr<nsIScriptGlobalObject> scriptHandlingObject =
    1443               2 :     do_QueryReferent(mScriptObject);
    1444                 :   
    1445               1 :   NS_ENSURE_STATE(!mScriptObject || scriptHandlingObject);
    1446                 : 
    1447                 :   return nsContentUtils::CreateDocument(aNamespaceURI, aQualifiedName, aDoctype,
    1448                 :                                         mDocumentURI, mBaseURI,
    1449               1 :                                         mOwner->NodePrincipal(),
    1450                 :                                         scriptHandlingObject,
    1451                 :                                         DocumentFlavorLegacyGuess,
    1452               2 :                                         aReturn);
    1453                 : }
    1454                 : 
    1455                 : NS_IMETHODIMP
    1456               0 : nsDOMImplementation::CreateHTMLDocument(const nsAString& aTitle,
    1457                 :                                         nsIDOMDocument** aReturn)
    1458                 : {
    1459               0 :   *aReturn = nsnull;
    1460               0 :   NS_ENSURE_STATE(mOwner);
    1461                 : 
    1462               0 :   nsCOMPtr<nsIDOMDocumentType> doctype;
    1463                 :   // Indicate that there is no internal subset (not just an empty one)
    1464               0 :   nsresult rv = NS_NewDOMDocumentType(getter_AddRefs(doctype),
    1465                 :                                       mOwner->NodeInfoManager(),
    1466                 :                                       nsGkAtoms::html, // aName
    1467               0 :                                       EmptyString(), // aPublicId
    1468               0 :                                       EmptyString(), // aSystemId
    1469               0 :                                       NullString()); // aInternalSubset
    1470               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1471                 : 
    1472                 : 
    1473                 :   nsCOMPtr<nsIScriptGlobalObject> scriptHandlingObject =
    1474               0 :     do_QueryReferent(mScriptObject);
    1475                 : 
    1476               0 :   NS_ENSURE_STATE(!mScriptObject || scriptHandlingObject);
    1477                 :                                                        
    1478               0 :   nsCOMPtr<nsIDOMDocument> document;
    1479               0 :   rv = nsContentUtils::CreateDocument(EmptyString(), EmptyString(),
    1480                 :                                       doctype, mDocumentURI, mBaseURI,
    1481               0 :                                       mOwner->NodePrincipal(),
    1482                 :                                       scriptHandlingObject,
    1483                 :                                       DocumentFlavorLegacyGuess,
    1484               0 :                                       getter_AddRefs(document));
    1485               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1486               0 :   nsCOMPtr<nsIDocument> doc = do_QueryInterface(document);
    1487                 : 
    1488               0 :   nsCOMPtr<nsIContent> root;
    1489               0 :   rv = doc->CreateElem(NS_LITERAL_STRING("html"), NULL, kNameSpaceID_XHTML,
    1490               0 :                        getter_AddRefs(root));
    1491               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1492               0 :   rv = doc->AppendChildTo(root, false);
    1493               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1494                 : 
    1495               0 :   nsCOMPtr<nsIContent> head;
    1496               0 :   rv = doc->CreateElem(NS_LITERAL_STRING("head"), NULL, kNameSpaceID_XHTML,
    1497               0 :                        getter_AddRefs(head));
    1498               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1499               0 :   rv = root->AppendChildTo(head, false);
    1500               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1501                 : 
    1502               0 :   nsCOMPtr<nsIContent> title;
    1503               0 :   rv = doc->CreateElem(NS_LITERAL_STRING("title"), NULL, kNameSpaceID_XHTML,
    1504               0 :                        getter_AddRefs(title));
    1505               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1506               0 :   rv = head->AppendChildTo(title, false);
    1507               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1508                 : 
    1509               0 :   nsCOMPtr<nsIContent> titleText;
    1510               0 :   rv = NS_NewTextNode(getter_AddRefs(titleText), doc->NodeInfoManager());
    1511               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1512               0 :   rv = titleText->SetText(aTitle, false);
    1513               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1514               0 :   rv = title->AppendChildTo(titleText, false);
    1515               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1516                 : 
    1517               0 :   nsCOMPtr<nsIContent> body;
    1518               0 :   rv = doc->CreateElem(NS_LITERAL_STRING("body"), NULL, kNameSpaceID_XHTML,
    1519               0 :                        getter_AddRefs(body));
    1520               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1521               0 :   rv = root->AppendChildTo(body, false);
    1522               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1523                 : 
    1524               0 :   document.forget(aReturn);
    1525                 : 
    1526               0 :   return NS_OK;
    1527                 : }
    1528                 : 
    1529                 : // ==================================================================
    1530                 : // =
    1531                 : // ==================================================================
    1532                 : 
    1533                 :   // NOTE! nsDocument::operator new() zeroes out all members, so don't
    1534                 :   // bother initializing members to 0.
    1535                 : 
    1536            1273 : nsDocument::nsDocument(const char* aContentType)
    1537                 :   : nsIDocument()
    1538                 :   , mAnimatingImages(true)
    1539            1273 :   , mVisibilityState(eHidden)
    1540                 : {
    1541            1273 :   SetContentTypeInternal(nsDependentCString(aContentType));
    1542                 :   
    1543                 : #ifdef PR_LOGGING
    1544            1273 :   if (!gDocumentLeakPRLog)
    1545             249 :     gDocumentLeakPRLog = PR_NewLogModule("DocumentLeak");
    1546                 : 
    1547            1273 :   if (gDocumentLeakPRLog)
    1548            1273 :     PR_LOG(gDocumentLeakPRLog, PR_LOG_DEBUG,
    1549                 :            ("DOCUMENT %p created", this));
    1550                 : 
    1551            1273 :   if (!gCspPRLog)
    1552             249 :     gCspPRLog = PR_NewLogModule("CSP");
    1553                 : #endif
    1554                 : 
    1555                 :   // Start out mLastStyleSheetSet as null, per spec
    1556            1273 :   SetDOMStringToNull(mLastStyleSheetSet);
    1557                 :   
    1558            1273 :   mLinksToUpdate.Init();
    1559            1273 : }
    1560                 : 
    1561                 : static PLDHashOperator
    1562               0 : ClearAllBoxObjects(const void* aKey, nsPIBoxObject* aBoxObject, void* aUserArg)
    1563                 : {
    1564               0 :   if (aBoxObject) {
    1565               0 :     aBoxObject->Clear();
    1566                 :   }
    1567               0 :   return PL_DHASH_NEXT;
    1568                 : }
    1569                 : 
    1570            2542 : nsDocument::~nsDocument()
    1571                 : {
    1572                 : #ifdef PR_LOGGING
    1573            1271 :   if (gDocumentLeakPRLog)
    1574            1271 :     PR_LOG(gDocumentLeakPRLog, PR_LOG_DEBUG,
    1575                 :            ("DOCUMENT %p destroyed", this));
    1576                 : #endif
    1577                 : 
    1578                 : #ifdef DEBUG
    1579            1271 :   nsCycleCollector_DEBUG_wasFreed(static_cast<nsIDocument*>(this));
    1580                 : #endif
    1581                 : 
    1582            1271 :   NS_ASSERTION(!mIsShowing, "Destroying a currently-showing document");
    1583                 : 
    1584            1271 :   mInDestructor = true;
    1585            1271 :   mInUnlinkOrDeletion = true;
    1586                 : 
    1587                 :   // Clear mObservers to keep it in sync with the mutationobserver list
    1588            1271 :   mObservers.Clear();
    1589                 : 
    1590            1271 :   if (mStyleSheetSetList) {
    1591               0 :     mStyleSheetSetList->Disconnect();
    1592                 :   }
    1593                 : 
    1594            1271 :   if (mAnimationController) {
    1595               0 :     mAnimationController->Disconnect();
    1596                 :   }
    1597                 : 
    1598            1271 :   mParentDocument = nsnull;
    1599                 : 
    1600                 :   // Kill the subdocument map, doing this will release its strong
    1601                 :   // references, if any.
    1602            1271 :   if (mSubDocuments) {
    1603               0 :     PL_DHashTableDestroy(mSubDocuments);
    1604                 : 
    1605               0 :     mSubDocuments = nsnull;
    1606                 :   }
    1607                 : 
    1608                 :   // Destroy link map now so we don't waste time removing
    1609                 :   // links one by one
    1610            1271 :   DestroyElementMaps();
    1611                 : 
    1612            2542 :   nsAutoScriptBlocker scriptBlocker;
    1613                 : 
    1614                 :   PRInt32 indx; // must be signed
    1615            1271 :   PRUint32 count = mChildren.ChildCount();
    1616            1271 :   for (indx = PRInt32(count) - 1; indx >= 0; --indx) {
    1617               0 :     mChildren.ChildAt(indx)->UnbindFromTree();
    1618               0 :     mChildren.RemoveChildAt(indx);
    1619                 :   }
    1620            1271 :   mFirstChild = nsnull;
    1621            1271 :   mCachedRootElement = nsnull;
    1622                 : 
    1623                 :   // Let the stylesheets know we're going away
    1624            1271 :   indx = mStyleSheets.Count();
    1625            2542 :   while (--indx >= 0) {
    1626               0 :     mStyleSheets[indx]->SetOwningDocument(nsnull);
    1627                 :   }
    1628            1271 :   indx = mCatalogSheets.Count();
    1629            2542 :   while (--indx >= 0) {
    1630               0 :     mCatalogSheets[indx]->SetOwningDocument(nsnull);
    1631                 :   }
    1632            1271 :   if (mAttrStyleSheet)
    1633             469 :     mAttrStyleSheet->SetOwningDocument(nsnull);
    1634            1271 :   if (mStyleAttrStyleSheet)
    1635             469 :     mStyleAttrStyleSheet->SetOwningDocument(nsnull);
    1636                 : 
    1637            1271 :   if (mListenerManager) {
    1638               0 :     mListenerManager->Disconnect();
    1639               0 :     UnsetFlags(NODE_HAS_LISTENERMANAGER);
    1640                 :   }
    1641                 : 
    1642            1271 :   if (mScriptLoader) {
    1643            1271 :     mScriptLoader->DropDocumentReference();
    1644                 :   }
    1645                 : 
    1646            1271 :   if (mCSSLoader) {
    1647                 :     // Could be null here if Init() failed
    1648            1271 :     mCSSLoader->DropDocumentReference();
    1649            1271 :     NS_RELEASE(mCSSLoader);
    1650                 :   }
    1651                 : 
    1652                 :   // XXX Ideally we'd do this cleanup in the nsIDocument destructor.
    1653            1271 :   if (mNodeInfoManager) {
    1654            1271 :     mNodeInfoManager->DropDocumentReference();
    1655                 :   }
    1656                 : 
    1657            1271 :   if (mAttrStyleSheet) {
    1658             469 :     mAttrStyleSheet->SetOwningDocument(nsnull);
    1659                 :   }
    1660                 :   
    1661            1271 :   if (mStyleAttrStyleSheet) {
    1662             469 :     mStyleAttrStyleSheet->SetOwningDocument(nsnull);
    1663                 :   }
    1664                 : 
    1665            1271 :   delete mHeaderData;
    1666                 : 
    1667            1271 :   if (mBoxObjectTable) {
    1668               0 :     mBoxObjectTable->EnumerateRead(ClearAllBoxObjects, nsnull);
    1669               0 :     delete mBoxObjectTable;
    1670                 :   }
    1671                 : 
    1672            1271 :   mPendingTitleChangeEvent.Revoke();
    1673                 : 
    1674            1271 :   for (PRUint32 i = 0; i < mFileDataUris.Length(); ++i) {
    1675               0 :     nsBlobProtocolHandler::RemoveFileDataEntry(mFileDataUris[i]);
    1676                 :   }
    1677                 : 
    1678                 :   // We don't want to leave residual locks on images. Make sure we're in an
    1679                 :   // unlocked state, and then clear the table.
    1680            1271 :   SetImageLockingState(false);
    1681            1271 :   mImageTracker.Clear();
    1682            1271 : }
    1683                 : 
    1684            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsDocument)
    1685                 : 
    1686          154563 : NS_INTERFACE_TABLE_HEAD(nsDocument)
    1687          154563 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
    1688                 :   NS_DOCUMENT_INTERFACE_TABLE_BEGIN(nsDocument)
    1689                 :     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDocument)
    1690                 :     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMDocumentXBL)
    1691                 :     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIScriptObjectPrincipal)
    1692                 :     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMEventTarget)
    1693                 :     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsISupportsWeakReference)
    1694                 :     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIRadioGroupContainer)
    1695                 :     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIMutationObserver)
    1696                 :     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIApplicationCacheContainer)
    1697                 :     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMDocumentTouch)
    1698                 :     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsITouchEventReceiver)
    1699                 :     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIInlineEventHandlers)
    1700          137424 :   NS_OFFSET_AND_INTERFACE_TABLE_END
    1701          137424 :   NS_OFFSET_AND_INTERFACE_TABLE_TO_MAP_SEGUE
    1702          116746 :   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsDocument)
    1703           13842 :   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMXPathNSResolver,
    1704                 :                                  new nsNode3Tearoff(this))
    1705           13842 :   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMNodeSelector,
    1706                 :                                  new nsNodeSelectorTearoff(this))
    1707           27642 :   if (aIID.Equals(NS_GET_IID(nsIDOMXPathEvaluator)) ||
    1708           13800 :       aIID.Equals(NS_GET_IID(nsIXPathEvaluatorInternal))) {
    1709              42 :     if (!mXPathEvaluatorTearoff) {
    1710                 :       nsresult rv;
    1711                 :       mXPathEvaluatorTearoff =
    1712                 :         do_CreateInstance(NS_XPATH_EVALUATOR_CONTRACTID,
    1713               2 :                           static_cast<nsIDocument *>(this), &rv);
    1714               2 :       NS_ENSURE_SUCCESS(rv, rv);
    1715                 :     }
    1716                 : 
    1717              42 :     return mXPathEvaluatorTearoff->QueryInterface(aIID, aInstancePtr);
    1718                 :   }
    1719                 :   else
    1720           13800 : NS_INTERFACE_MAP_END
    1721                 : 
    1722                 : 
    1723          169709 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDocument)
    1724          169705 : NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(nsDocument, 
    1725                 :                                               nsNodeUtils::LastRelease(this))
    1726                 : 
    1727            2237 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsDocument)
    1728            2237 :   return nsGenericElement::CanSkip(tmp, aRemovingAllowed);
    1729                 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
    1730                 : 
    1731            1287 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsDocument)
    1732            1287 :   return nsGenericElement::CanSkipInCC(tmp);
    1733                 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
    1734                 : 
    1735            1317 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsDocument)
    1736            1317 :   return nsGenericElement::CanSkipThis(tmp);
    1737                 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
    1738                 : 
    1739                 : static PLDHashOperator
    1740               0 : SubDocTraverser(PLDHashTable *table, PLDHashEntryHdr *hdr, PRUint32 number,
    1741                 :                 void *arg)
    1742                 : {
    1743               0 :   SubDocMapEntry *entry = static_cast<SubDocMapEntry*>(hdr);
    1744                 :   nsCycleCollectionTraversalCallback *cb = 
    1745               0 :     static_cast<nsCycleCollectionTraversalCallback*>(arg);
    1746                 : 
    1747               0 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mSubDocuments entry->mKey");
    1748               0 :   cb->NoteXPCOMChild(entry->mKey);
    1749               0 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mSubDocuments entry->mSubDocument");
    1750               0 :   cb->NoteXPCOMChild(entry->mSubDocument);
    1751                 : 
    1752               0 :   return PL_DHASH_NEXT;
    1753                 : }
    1754                 : 
    1755                 : static PLDHashOperator
    1756               0 : RadioGroupsTraverser(const nsAString& aKey, nsRadioGroupStruct* aData,
    1757                 :                      void* aClosure)
    1758                 : {
    1759                 :   nsCycleCollectionTraversalCallback *cb = 
    1760               0 :     static_cast<nsCycleCollectionTraversalCallback*>(aClosure);
    1761                 : 
    1762               0 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
    1763                 :                                    "mRadioGroups entry->mSelectedRadioButton");
    1764               0 :   cb->NoteXPCOMChild(aData->mSelectedRadioButton);
    1765                 : 
    1766               0 :   PRUint32 i, count = aData->mRadioButtons.Count();
    1767               0 :   for (i = 0; i < count; ++i) {
    1768               0 :     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
    1769                 :                                        "mRadioGroups entry->mRadioButtons[i]");
    1770               0 :     cb->NoteXPCOMChild(aData->mRadioButtons[i]);
    1771                 :   }
    1772                 : 
    1773               0 :   return PL_DHASH_NEXT;
    1774                 : }
    1775                 : 
    1776                 : static PLDHashOperator
    1777               0 : BoxObjectTraverser(const void* key, nsPIBoxObject* boxObject, void* userArg)
    1778                 : {
    1779                 :   nsCycleCollectionTraversalCallback *cb = 
    1780               0 :     static_cast<nsCycleCollectionTraversalCallback*>(userArg);
    1781                 :  
    1782               0 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mBoxObjectTable entry");
    1783               0 :   cb->NoteXPCOMChild(boxObject);
    1784                 : 
    1785               0 :   return PL_DHASH_NEXT;
    1786                 : }
    1787                 : 
    1788                 : static PLDHashOperator
    1789             122 : IdentifierMapEntryTraverse(nsIdentifierMapEntry *aEntry, void *aArg)
    1790                 : {
    1791                 :   nsCycleCollectionTraversalCallback *cb =
    1792             122 :     static_cast<nsCycleCollectionTraversalCallback*>(aArg);
    1793             122 :   aEntry->Traverse(cb);
    1794             122 :   return PL_DHASH_NEXT;
    1795                 : }
    1796                 : 
    1797                 : static const char* kNSURIs[] = {
    1798                 :   "([none])",
    1799                 :   "(xmlns)",
    1800                 :   "(xml)",
    1801                 :   "(xhtml)",
    1802                 :   "(XLink)",
    1803                 :   "(XSLT)",
    1804                 :   "(XBL)",
    1805                 :   "(MathML)",
    1806                 :   "(RDF)",
    1807                 :   "(XUL)"
    1808                 : };
    1809                 : 
    1810            1462 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument)
    1811            1462 :   if (NS_UNLIKELY(cb.WantDebugInfo())) {
    1812                 :     char name[512];
    1813               0 :     nsCAutoString loadedAsData;
    1814               0 :     if (tmp->IsLoadedAsData()) {
    1815               0 :       loadedAsData.AssignLiteral("data");
    1816                 :     } else {
    1817               0 :       loadedAsData.AssignLiteral("normal");
    1818                 :     }
    1819               0 :     PRUint32 nsid = tmp->GetDefaultNamespaceID();
    1820               0 :     nsCAutoString uri;
    1821               0 :     if (tmp->mDocumentURI)
    1822               0 :       tmp->mDocumentURI->GetSpec(uri);
    1823               0 :     if (nsid < ArrayLength(kNSURIs)) {
    1824                 :       PR_snprintf(name, sizeof(name), "nsDocument %s %s %s",
    1825               0 :                   loadedAsData.get(), kNSURIs[nsid], uri.get());
    1826                 :     }
    1827                 :     else {
    1828                 :       PR_snprintf(name, sizeof(name), "nsDocument %s %s",
    1829               0 :                   loadedAsData.get(), uri.get());
    1830                 :     }
    1831               0 :     cb.DescribeRefCountedNode(tmp->mRefCnt.get(), sizeof(nsDocument), name);
    1832                 :   }
    1833                 :   else {
    1834            1462 :     NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsDocument, tmp->mRefCnt.get())
    1835                 :   }
    1836                 : 
    1837                 :   // Always need to traverse script objects, so do that before we check
    1838                 :   // if we're uncollectable.
    1839            1462 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
    1840                 : 
    1841            1462 :   if (!nsINode::Traverse(tmp, cb)) {
    1842               0 :     return NS_SUCCESS_INTERRUPTED_TRAVERSE;
    1843                 :   }
    1844                 : 
    1845            1462 :   tmp->mIdentifierMap.EnumerateEntries(IdentifierMapEntryTraverse, &cb);
    1846                 : 
    1847            1462 :   tmp->mExternalResourceMap.Traverse(&cb);
    1848                 : 
    1849                 :   // Traverse the mChildren nsAttrAndChildArray.
    1850            3037 :   for (PRInt32 indx = PRInt32(tmp->mChildren.ChildCount()); indx > 0; --indx) {
    1851            1575 :     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mChildren[i]");
    1852            1575 :     cb.NoteXPCOMChild(tmp->mChildren.ChildAt(indx - 1));
    1853                 :   }
    1854                 : 
    1855                 :   // Traverse all nsIDocument pointer members.
    1856            1462 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mSecurityInfo)
    1857            1462 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDisplayDocument)
    1858                 : 
    1859                 :   // Traverse all nsDocument nsCOMPtrs.
    1860            1462 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParser)
    1861            1462 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mScriptGlobalObject)
    1862            1462 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mListenerManager,
    1863                 :                                                   nsEventListenerManager)
    1864            1462 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDOMStyleSheets)
    1865            1462 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mScriptLoader)
    1866                 : 
    1867            1462 :   tmp->mRadioGroups.EnumerateRead(RadioGroupsTraverser, &cb);
    1868                 : 
    1869                 :   // The boxobject for an element will only exist as long as it's in the
    1870                 :   // document, so we'll traverse the table here instead of from the element.
    1871            1462 :   if (tmp->mBoxObjectTable) {
    1872               0 :     tmp->mBoxObjectTable->EnumerateRead(BoxObjectTraverser, &cb);
    1873                 :   }
    1874                 : 
    1875            1462 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChannel)
    1876            1462 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mStyleAttrStyleSheet, nsIStyleSheet)
    1877            1462 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mXPathEvaluatorTearoff)
    1878            1462 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLayoutHistoryState)
    1879            1462 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnloadBlocker)
    1880            1462 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFirstBaseNodeWithHref)
    1881            1462 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDOMImplementation)
    1882            1462 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mImageMaps,
    1883                 :                                                        nsIDOMNodeList)
    1884            1462 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOriginalDocument)
    1885            1462 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCachedEncoder)
    1886            1462 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mStateObjectCached)
    1887                 : 
    1888                 :   // Traverse all our nsCOMArrays.
    1889            1462 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mStyleSheets)
    1890            1462 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mCatalogSheets)
    1891            1462 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mPreloadingImages)
    1892                 : 
    1893            1462 :   for (PRUint32 i = 0; i < tmp->mFrameRequestCallbacks.Length(); ++i) {
    1894               0 :     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mFrameRequestCallbacks[i]");
    1895               0 :     cb.NoteXPCOMChild(tmp->mFrameRequestCallbacks[i]);
    1896                 :   }
    1897                 : 
    1898                 :   // Traverse animation components
    1899            1462 :   if (tmp->mAnimationController) {
    1900               0 :     tmp->mAnimationController->Traverse(&cb);
    1901                 :   }
    1902                 : 
    1903            1462 :   if (tmp->mSubDocuments && tmp->mSubDocuments->ops) {
    1904               0 :     PL_DHashTableEnumerate(tmp->mSubDocuments, SubDocTraverser, &cb);
    1905                 :   }
    1906            1462 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
    1907                 : 
    1908                 : 
    1909            1462 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsDocument)
    1910            1462 :   nsINode::Trace(tmp, aCallback, aClosure);
    1911            1462 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
    1912                 : 
    1913                 : 
    1914            1271 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
    1915            1271 :   tmp->mInUnlinkOrDeletion = true;
    1916                 : 
    1917                 :   // Clear out our external resources
    1918            1271 :   tmp->mExternalResourceMap.Shutdown();
    1919                 : 
    1920            2542 :   nsAutoScriptBlocker scriptBlocker;
    1921                 : 
    1922            1271 :   nsINode::Unlink(tmp);
    1923                 : 
    1924                 :   // Unlink the mChildren nsAttrAndChildArray.
    1925            2644 :   for (PRInt32 indx = PRInt32(tmp->mChildren.ChildCount()) - 1; 
    1926                 :        indx >= 0; --indx) {
    1927            1373 :     tmp->mChildren.ChildAt(indx)->UnbindFromTree();
    1928            1373 :     tmp->mChildren.RemoveChildAt(indx);
    1929                 :   }
    1930            1271 :   tmp->mFirstChild = nsnull;
    1931                 : 
    1932            1271 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mXPathEvaluatorTearoff)
    1933            1271 :   tmp->mCachedRootElement = nsnull; // Avoid a dangling pointer
    1934            1271 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDisplayDocument)
    1935            1271 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFirstBaseNodeWithHref)
    1936            1271 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDOMImplementation)
    1937            1271 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mImageMaps)
    1938            1271 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOriginalDocument)
    1939            1271 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCachedEncoder)
    1940                 : 
    1941            1271 :   tmp->mParentDocument = nsnull;
    1942                 : 
    1943            1271 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mPreloadingImages)
    1944                 : 
    1945                 :   
    1946            1271 :   if (tmp->mBoxObjectTable) {
    1947               0 :    tmp->mBoxObjectTable->EnumerateRead(ClearAllBoxObjects, nsnull);
    1948               0 :    delete tmp->mBoxObjectTable;
    1949               0 :    tmp->mBoxObjectTable = nsnull;
    1950                 :  }
    1951                 : 
    1952            1271 :   if (tmp->mListenerManager) {
    1953               0 :     tmp->mListenerManager->Disconnect();
    1954               0 :     tmp->UnsetFlags(NODE_HAS_LISTENERMANAGER);
    1955               0 :     tmp->mListenerManager = nsnull;
    1956                 :   }
    1957                 : 
    1958            1271 :   if (tmp->mSubDocuments) {
    1959               0 :     PL_DHashTableDestroy(tmp->mSubDocuments);
    1960               0 :     tmp->mSubDocuments = nsnull;
    1961                 :   }
    1962                 : 
    1963            1271 :   tmp->mFrameRequestCallbacks.Clear();
    1964                 : 
    1965            1271 :   tmp->mRadioGroups.Clear();
    1966                 :   
    1967                 :   // nsDocument has a pretty complex destructor, so we're going to
    1968                 :   // assume that *most* cycles you actually want to break somewhere
    1969                 :   // else, and not unlink an awful lot here.
    1970                 : 
    1971            1271 :   tmp->mIdentifierMap.Clear();
    1972                 : 
    1973            1271 :   if (tmp->mAnimationController) {
    1974               0 :     tmp->mAnimationController->Unlink();
    1975                 :   }
    1976                 : 
    1977            1271 :   tmp->mPendingTitleChangeEvent.Revoke();
    1978                 :   
    1979            1271 :   tmp->mInUnlinkOrDeletion = false;
    1980            1271 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
    1981                 : 
    1982                 : 
    1983                 : nsresult
    1984            1273 : nsDocument::Init()
    1985                 : {
    1986            1273 :   if (mCSSLoader || mNodeInfoManager || mScriptLoader) {
    1987               0 :     return NS_ERROR_ALREADY_INITIALIZED;
    1988                 :   }
    1989                 : 
    1990            1273 :   mIdentifierMap.Init();
    1991            1273 :   (void)mStyledLinks.Init();
    1992            1273 :   mRadioGroups.Init();
    1993                 : 
    1994                 :   // Force initialization.
    1995            1273 :   nsINode::nsSlots* slots = GetSlots();
    1996            1273 :   NS_ENSURE_TRUE(slots,NS_ERROR_OUT_OF_MEMORY);
    1997                 : 
    1998                 :   // Prepend self as mutation-observer whether we need it or not (some
    1999                 :   // subclasses currently do, other don't). This is because the code in
    2000                 :   // nsNodeUtils always notifies the first observer first, expecting the
    2001                 :   // first observer to be the document.
    2002            1273 :   NS_ENSURE_TRUE(slots->mMutationObservers.PrependElementUnlessExists(static_cast<nsIMutationObserver*>(this)),
    2003                 :                  NS_ERROR_OUT_OF_MEMORY);
    2004                 : 
    2005                 : 
    2006            1273 :   mOnloadBlocker = new nsOnloadBlocker();
    2007            1273 :   NS_ENSURE_TRUE(mOnloadBlocker, NS_ERROR_OUT_OF_MEMORY);
    2008                 : 
    2009            1273 :   mCSSLoader = new mozilla::css::Loader(this);
    2010            1273 :   NS_ENSURE_TRUE(mCSSLoader, NS_ERROR_OUT_OF_MEMORY);
    2011            1273 :   NS_ADDREF(mCSSLoader);
    2012                 :   // Assume we're not quirky, until we know otherwise
    2013            1273 :   mCSSLoader->SetCompatibilityMode(eCompatibility_FullStandards);
    2014                 : 
    2015            1273 :   mNodeInfoManager = new nsNodeInfoManager();
    2016            1273 :   NS_ENSURE_TRUE(mNodeInfoManager, NS_ERROR_OUT_OF_MEMORY);
    2017                 : 
    2018            1273 :   nsresult  rv = mNodeInfoManager->Init(this);
    2019            1273 :   NS_ENSURE_SUCCESS(rv, rv);
    2020                 : 
    2021                 :   // mNodeInfo keeps NodeInfoManager alive!
    2022            1273 :   mNodeInfo = mNodeInfoManager->GetDocumentNodeInfo();
    2023            1273 :   NS_ENSURE_TRUE(mNodeInfo, NS_ERROR_OUT_OF_MEMORY);
    2024            1273 :   NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_NODE,
    2025                 :                     "Bad NodeType in aNodeInfo");
    2026                 : 
    2027            1273 :   NS_ASSERTION(OwnerDoc() == this, "Our nodeinfo is busted!");
    2028                 : 
    2029            1273 :   mScriptLoader = new nsScriptLoader(this);
    2030            1273 :   NS_ENSURE_TRUE(mScriptLoader, NS_ERROR_OUT_OF_MEMORY);
    2031                 : 
    2032            1273 :   if (!mImageTracker.Init()) {
    2033               0 :     return NS_ERROR_OUT_OF_MEMORY;
    2034                 :   }
    2035                 : 
    2036            1273 :   return NS_OK;
    2037                 : }
    2038                 : 
    2039                 : void 
    2040            1271 : nsIDocument::DeleteAllProperties()
    2041                 : {
    2042            2550 :   for (PRUint32 i = 0; i < GetPropertyTableCount(); ++i) {
    2043            1279 :     PropertyTable(i)->DeleteAllProperties();
    2044                 :   }
    2045            1271 : }
    2046                 : 
    2047                 : void
    2048               0 : nsIDocument::DeleteAllPropertiesFor(nsINode* aNode)
    2049                 : {
    2050               0 :   for (PRUint32 i = 0; i < GetPropertyTableCount(); ++i) {
    2051               0 :     PropertyTable(i)->DeleteAllPropertiesFor(aNode);
    2052                 :   }
    2053               0 : }
    2054                 : 
    2055                 : nsPropertyTable*
    2056             270 : nsIDocument::GetExtraPropertyTable(PRUint16 aCategory)
    2057                 : {
    2058             270 :   NS_ASSERTION(aCategory > 0, "Category 0 should have already been handled");
    2059             548 :   while (aCategory >= mExtraPropertyTables.Length() + 1) {
    2060               8 :     mExtraPropertyTables.AppendElement(new nsPropertyTable());
    2061                 :   }
    2062             270 :   return mExtraPropertyTables[aCategory - 1];
    2063                 : }
    2064                 : 
    2065                 : void
    2066               0 : nsDocument::AddXMLEventsContent(nsIContent *aXMLEventsElement)
    2067                 : {
    2068               0 :   if (!mXMLEventsManager) {
    2069               0 :     mXMLEventsManager = new nsXMLEventsManager();
    2070               0 :     AddObserver(mXMLEventsManager);
    2071                 :   }
    2072               0 :   mXMLEventsManager->AddXMLEventsContent(aXMLEventsElement);
    2073               0 : }
    2074                 : 
    2075                 : void
    2076             469 : nsDocument::Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup)
    2077                 : {
    2078             938 :   nsCOMPtr<nsIURI> uri;
    2079             938 :   nsCOMPtr<nsIPrincipal> principal;
    2080             469 :   if (aChannel) {
    2081                 :     // Note: this code is duplicated in nsXULDocument::StartDocumentLoad and
    2082                 :     // nsScriptSecurityManager::GetChannelPrincipal.    
    2083                 :     // Note: this should match nsDocShell::OnLoadingSite
    2084             469 :     NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
    2085                 : 
    2086                 :     nsIScriptSecurityManager *securityManager =
    2087             469 :       nsContentUtils::GetSecurityManager();
    2088             469 :     if (securityManager) {
    2089                 :       securityManager->GetChannelPrincipal(aChannel,
    2090             469 :                                            getter_AddRefs(principal));
    2091                 :     }
    2092                 :   }
    2093                 : 
    2094             469 :   ResetToURI(uri, aLoadGroup, principal);
    2095                 : 
    2096             938 :   nsCOMPtr<nsIPropertyBag2> bag = do_QueryInterface(aChannel);
    2097             469 :   if (bag) {
    2098             938 :     nsCOMPtr<nsIURI> baseURI;
    2099             938 :     bag->GetPropertyAsInterface(NS_LITERAL_STRING("baseURI"),
    2100             938 :                                 NS_GET_IID(nsIURI), getter_AddRefs(baseURI));
    2101             469 :     if (baseURI) {
    2102               0 :       mDocumentBaseURI = baseURI;
    2103                 :     }
    2104                 :   }
    2105                 : 
    2106             469 :   mChannel = aChannel;
    2107             469 : }
    2108                 : 
    2109                 : void
    2110             469 : nsDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup,
    2111                 :                        nsIPrincipal* aPrincipal)
    2112                 : {
    2113             469 :   NS_PRECONDITION(aURI, "Null URI passed to ResetToURI");
    2114                 : 
    2115                 : #ifdef PR_LOGGING
    2116             469 :   if (gDocumentLeakPRLog && PR_LOG_TEST(gDocumentLeakPRLog, PR_LOG_DEBUG)) {
    2117               0 :     nsCAutoString spec;
    2118               0 :     aURI->GetSpec(spec);
    2119               0 :     PR_LogPrint("DOCUMENT %p ResetToURI %s", this, spec.get());
    2120                 :   }
    2121                 : #endif
    2122                 : 
    2123             469 :   mSecurityInfo = nsnull;
    2124                 : 
    2125             469 :   mDocumentLoadGroup = nsnull;
    2126                 : 
    2127                 :   // Delete references to sub-documents and kill the subdocument map,
    2128                 :   // if any. It holds strong references
    2129             469 :   if (mSubDocuments) {
    2130               0 :     PL_DHashTableDestroy(mSubDocuments);
    2131                 : 
    2132               0 :     mSubDocuments = nsnull;
    2133                 :   }
    2134                 : 
    2135                 :   // Destroy link map now so we don't waste time removing
    2136                 :   // links one by one
    2137             469 :   DestroyElementMaps();
    2138                 : 
    2139             469 :   bool oldVal = mInUnlinkOrDeletion;
    2140             469 :   mInUnlinkOrDeletion = true;
    2141             469 :   PRUint32 count = mChildren.ChildCount();
    2142                 :   { // Scope for update
    2143             938 :     MOZ_AUTO_DOC_UPDATE(this, UPDATE_CONTENT_MODEL, true);    
    2144             469 :     for (PRInt32 i = PRInt32(count) - 1; i >= 0; i--) {
    2145               0 :       nsCOMPtr<nsIContent> content = mChildren.ChildAt(i);
    2146                 : 
    2147               0 :       nsIContent* previousSibling = content->GetPreviousSibling();
    2148                 : 
    2149               0 :       if (nsINode::GetFirstChild() == content) {
    2150               0 :         mFirstChild = content->GetNextSibling();
    2151                 :       }
    2152               0 :       mChildren.RemoveChildAt(i);
    2153               0 :       nsNodeUtils::ContentRemoved(this, content, i, previousSibling);
    2154               0 :       content->UnbindFromTree();
    2155                 :     }
    2156                 :   }
    2157             469 :   mInUnlinkOrDeletion = oldVal;
    2158             469 :   mCachedRootElement = nsnull;
    2159                 : 
    2160                 :   // Reset our stylesheets
    2161             469 :   ResetStylesheetsToURI(aURI);
    2162                 :   
    2163                 :   // Release the listener manager
    2164             469 :   if (mListenerManager) {
    2165               0 :     mListenerManager->Disconnect();
    2166               0 :     mListenerManager = nsnull;
    2167                 :   }
    2168                 : 
    2169                 :   // Release the stylesheets list.
    2170             469 :   mDOMStyleSheets = nsnull;
    2171                 : 
    2172                 :   // Release our principal after tearing down the document, rather than before.
    2173                 :   // This ensures that, during teardown, the document and the dying window (which
    2174                 :   // already nulled out its document pointer and cached the principal) have
    2175                 :   // matching principals.
    2176             469 :   SetPrincipal(nsnull);
    2177                 : 
    2178                 :   // Clear the original URI so SetDocumentURI sets it.
    2179             469 :   mOriginalURI = nsnull;
    2180                 : 
    2181             469 :   SetDocumentURI(aURI);
    2182                 :   // If mDocumentBaseURI is null, nsIDocument::GetBaseURI() returns
    2183                 :   // mDocumentURI.
    2184             469 :   mDocumentBaseURI = nsnull;
    2185                 : 
    2186             469 :   if (aLoadGroup) {
    2187               0 :     mDocumentLoadGroup = do_GetWeakReference(aLoadGroup);
    2188                 :     // there was an assertion here that aLoadGroup was not null.  This
    2189                 :     // is no longer valid: nsDocShell::SetDocument does not create a
    2190                 :     // load group, and it works just fine
    2191                 : 
    2192                 :     // XXXbz what does "just fine" mean exactly?  And given that there
    2193                 :     // is no nsDocShell::SetDocument, what is this talking about?
    2194                 :   }
    2195                 : 
    2196             469 :   mLastModified.Truncate();
    2197                 :   // XXXbz I guess we're assuming that the caller will either pass in
    2198                 :   // a channel with a useful type or call SetContentType?
    2199             469 :   SetContentTypeInternal(EmptyCString());
    2200             469 :   mContentLanguage.Truncate();
    2201             469 :   mBaseTarget.Truncate();
    2202             469 :   mReferrer.Truncate();
    2203                 : 
    2204             469 :   mXMLDeclarationBits = 0;
    2205                 : 
    2206                 :   // Now get our new principal
    2207             469 :   if (aPrincipal) {
    2208             469 :     SetPrincipal(aPrincipal);
    2209                 :   } else {
    2210                 :     nsIScriptSecurityManager *securityManager =
    2211               0 :       nsContentUtils::GetSecurityManager();
    2212               0 :     if (securityManager) {
    2213               0 :       nsCOMPtr<nsIPrincipal> principal;
    2214                 :       nsresult rv =
    2215                 :         securityManager->GetCodebasePrincipal(mDocumentURI,
    2216               0 :                                               getter_AddRefs(principal));
    2217               0 :       if (NS_SUCCEEDED(rv)) {
    2218               0 :         SetPrincipal(principal);
    2219                 :       }
    2220                 :     }
    2221                 :   }
    2222             469 : }
    2223                 : 
    2224                 : nsresult
    2225             469 : nsDocument::ResetStylesheetsToURI(nsIURI* aURI)
    2226                 : {
    2227             469 :   NS_PRECONDITION(aURI, "Null URI passed to ResetStylesheetsToURI");
    2228                 : 
    2229             938 :   mozAutoDocUpdate upd(this, UPDATE_STYLE, true);
    2230                 :   
    2231                 :   // The stylesheets should forget us
    2232             469 :   PRInt32 indx = mStyleSheets.Count();
    2233             938 :   while (--indx >= 0) {
    2234               0 :     nsIStyleSheet* sheet = mStyleSheets[indx];
    2235               0 :     sheet->SetOwningDocument(nsnull);
    2236                 : 
    2237               0 :     if (sheet->IsApplicable()) {
    2238               0 :       RemoveStyleSheetFromStyleSets(sheet);
    2239                 :     }
    2240                 : 
    2241                 :     // XXX Tell observers?
    2242                 :   }
    2243                 : 
    2244             469 :   indx = mCatalogSheets.Count();
    2245             938 :   while (--indx >= 0) {
    2246               0 :     nsIStyleSheet* sheet = mCatalogSheets[indx];
    2247               0 :     sheet->SetOwningDocument(nsnull);
    2248                 : 
    2249               0 :     if (sheet->IsApplicable()) {
    2250               0 :       nsCOMPtr<nsIPresShell> shell = GetShell();
    2251               0 :       if (shell) {
    2252               0 :         shell->StyleSet()->RemoveStyleSheet(nsStyleSet::eAgentSheet, sheet);
    2253                 :       }
    2254                 :     }
    2255                 : 
    2256                 :     // XXX Tell observers?
    2257                 :   }
    2258                 : 
    2259                 : 
    2260                 :   // Release all the sheets
    2261             469 :   mStyleSheets.Clear();
    2262                 :   // NOTE:  We don't release the catalog sheets.  It doesn't really matter
    2263                 :   // now, but it could in the future -- in which case not releasing them
    2264                 :   // is probably the right thing to do.
    2265                 : 
    2266                 :   // Now reset our inline style and attribute sheets.
    2267             469 :   nsresult rv = NS_OK;
    2268             469 :   if (mAttrStyleSheet) {
    2269                 :     // Remove this sheet from all style sets
    2270               0 :     nsCOMPtr<nsIPresShell> shell = GetShell();
    2271               0 :     if (shell) {
    2272                 :       shell->StyleSet()->RemoveStyleSheet(nsStyleSet::ePresHintSheet,
    2273               0 :                                           mAttrStyleSheet);
    2274                 :     }
    2275               0 :     mAttrStyleSheet->Reset(aURI);
    2276                 :   } else {
    2277             469 :     rv = NS_NewHTMLStyleSheet(getter_AddRefs(mAttrStyleSheet), aURI, this);
    2278             469 :     NS_ENSURE_SUCCESS(rv, rv);
    2279                 :   }
    2280                 : 
    2281                 :   // Don't use AddStyleSheet, since it'll put the sheet into style
    2282                 :   // sets in the document level, which is not desirable here.
    2283             469 :   mAttrStyleSheet->SetOwningDocument(this);
    2284                 :   
    2285             469 :   if (mStyleAttrStyleSheet) {
    2286                 :     // Remove this sheet from all style sets
    2287               0 :     nsCOMPtr<nsIPresShell> shell = GetShell();
    2288               0 :     if (shell) {
    2289                 :       shell->StyleSet()->
    2290               0 :         RemoveStyleSheet(nsStyleSet::eStyleAttrSheet, mStyleAttrStyleSheet);
    2291                 :     }
    2292               0 :     mStyleAttrStyleSheet->Reset(aURI);
    2293                 :   } else {
    2294             469 :     mStyleAttrStyleSheet = new nsHTMLCSSStyleSheet();
    2295             469 :     NS_ENSURE_TRUE(mStyleAttrStyleSheet, NS_ERROR_OUT_OF_MEMORY);
    2296             469 :     rv = mStyleAttrStyleSheet->Init(aURI, this);
    2297             469 :     NS_ENSURE_SUCCESS(rv, rv);
    2298                 :   }
    2299                 : 
    2300                 :   // The loop over style sets below will handle putting this sheet
    2301                 :   // into style sets as needed.
    2302             469 :   mStyleAttrStyleSheet->SetOwningDocument(this);
    2303                 : 
    2304                 :   // Now set up our style sets
    2305             938 :   nsCOMPtr<nsIPresShell> shell = GetShell();
    2306             469 :   if (shell) {
    2307               0 :     FillStyleSet(shell->StyleSet());
    2308                 :   }
    2309                 : 
    2310             469 :   return rv;
    2311                 : }
    2312                 : 
    2313                 : void
    2314               0 : nsDocument::FillStyleSet(nsStyleSet* aStyleSet)
    2315                 : {
    2316               0 :   NS_PRECONDITION(aStyleSet, "Must have a style set");
    2317               0 :   NS_PRECONDITION(aStyleSet->SheetCount(nsStyleSet::ePresHintSheet) == 0,
    2318                 :                   "Style set already has a preshint sheet?");
    2319               0 :   NS_PRECONDITION(aStyleSet->SheetCount(nsStyleSet::eDocSheet) == 0,
    2320                 :                   "Style set already has document sheets?");
    2321               0 :   NS_PRECONDITION(aStyleSet->SheetCount(nsStyleSet::eStyleAttrSheet) == 0,
    2322                 :                   "Style set already has style attr sheets?");
    2323               0 :   NS_PRECONDITION(mStyleAttrStyleSheet, "No style attr stylesheet?");
    2324               0 :   NS_PRECONDITION(mAttrStyleSheet, "No attr stylesheet?");
    2325                 :   
    2326               0 :   aStyleSet->AppendStyleSheet(nsStyleSet::ePresHintSheet, mAttrStyleSheet);
    2327                 : 
    2328                 :   aStyleSet->AppendStyleSheet(nsStyleSet::eStyleAttrSheet,
    2329               0 :                               mStyleAttrStyleSheet);
    2330                 : 
    2331                 :   PRInt32 i;
    2332               0 :   for (i = mStyleSheets.Count() - 1; i >= 0; --i) {
    2333               0 :     nsIStyleSheet* sheet = mStyleSheets[i];
    2334               0 :     if (sheet->IsApplicable()) {
    2335               0 :       aStyleSet->AddDocStyleSheet(sheet, this);
    2336                 :     }
    2337                 :   }
    2338                 : 
    2339               0 :   for (i = mCatalogSheets.Count() - 1; i >= 0; --i) {
    2340               0 :     nsIStyleSheet* sheet = mCatalogSheets[i];
    2341               0 :     if (sheet->IsApplicable()) {
    2342               0 :       aStyleSet->AppendStyleSheet(nsStyleSet::eAgentSheet, sheet);
    2343                 :     }
    2344                 :   }
    2345               0 : }
    2346                 : 
    2347                 : nsresult
    2348            1038 : nsDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
    2349                 :                               nsILoadGroup* aLoadGroup,
    2350                 :                               nsISupports* aContainer,
    2351                 :                               nsIStreamListener **aDocListener,
    2352                 :                               bool aReset, nsIContentSink* aSink)
    2353                 : {
    2354                 : #ifdef PR_LOGGING
    2355            1038 :   if (gDocumentLeakPRLog && PR_LOG_TEST(gDocumentLeakPRLog, PR_LOG_DEBUG)) {
    2356               0 :     nsCOMPtr<nsIURI> uri;
    2357               0 :     aChannel->GetURI(getter_AddRefs(uri));
    2358               0 :     nsCAutoString spec;
    2359               0 :     if (uri)
    2360               0 :       uri->GetSpec(spec);
    2361               0 :     PR_LogPrint("DOCUMENT %p StartDocumentLoad %s", this, spec.get());
    2362                 :   }
    2363                 : #endif
    2364                 : 
    2365            1038 :   SetReadyStateInternal(READYSTATE_LOADING);
    2366                 : 
    2367            1038 :   if (nsCRT::strcmp(kLoadAsData, aCommand) == 0) {
    2368            1038 :     mLoadedAsData = true;
    2369                 :     // We need to disable script & style loading in this case.
    2370                 :     // We leave them disabled even in EndLoad(), and let anyone
    2371                 :     // who puts the document on display to worry about enabling.
    2372                 : 
    2373                 :     // Do not load/process scripts when loading as data
    2374            1038 :     ScriptLoader()->SetEnabled(false);
    2375                 : 
    2376                 :     // styles
    2377            1038 :     CSSLoader()->SetEnabled(false); // Do not load/process styles when loading as data
    2378               0 :   } else if (nsCRT::strcmp("external-resource", aCommand) == 0) {
    2379                 :     // Allow CSS, but not scripts
    2380               0 :     ScriptLoader()->SetEnabled(false);
    2381                 :   }
    2382                 : 
    2383            1038 :   mMayStartLayout = false;
    2384                 : 
    2385            1038 :   mHaveInputEncoding = true;
    2386                 : 
    2387            1038 :   if (aReset) {
    2388             469 :     Reset(aChannel, aLoadGroup);
    2389                 :   }
    2390                 : 
    2391            2076 :   nsCAutoString contentType;
    2392            1038 :   if (NS_SUCCEEDED(aChannel->GetContentType(contentType))) {
    2393                 :     // XXX this is only necessary for viewsource:
    2394            1038 :     nsACString::const_iterator start, end, semicolon;
    2395            1038 :     contentType.BeginReading(start);
    2396            1038 :     contentType.EndReading(end);
    2397            1038 :     semicolon = start;
    2398            1038 :     FindCharInReadable(';', semicolon, end);
    2399            1038 :     SetContentTypeInternal(Substring(start, semicolon));
    2400                 :   }
    2401                 : 
    2402            1038 :   RetrieveRelevantHeaders(aChannel);
    2403                 : 
    2404            1038 :   mChannel = aChannel;
    2405                 : 
    2406            1038 :   nsresult rv = InitCSP();
    2407            1038 :   NS_ENSURE_SUCCESS(rv, rv);
    2408                 : 
    2409            1038 :   return NS_OK;
    2410                 : }
    2411                 : 
    2412                 : nsresult
    2413            1038 : nsDocument::InitCSP()
    2414                 : {
    2415            1038 :   if (CSPService::sCSPEnabled) {
    2416            2076 :     nsAutoString cspHeaderValue;
    2417            2076 :     nsAutoString cspROHeaderValue;
    2418                 : 
    2419            1038 :     this->GetHeaderData(nsGkAtoms::headerCSP, cspHeaderValue);
    2420            1038 :     this->GetHeaderData(nsGkAtoms::headerCSPReportOnly, cspROHeaderValue);
    2421                 : 
    2422            1038 :     bool system = false;
    2423            1038 :     nsIScriptSecurityManager *ssm = nsContentUtils::GetSecurityManager();
    2424                 : 
    2425            1038 :     if (NS_SUCCEEDED(ssm->IsSystemPrincipal(NodePrincipal(), &system)) && system) {
    2426                 :       // only makes sense to register new CSP if this document is not priviliged
    2427              70 :       return NS_OK;
    2428                 :     }
    2429                 : 
    2430             968 :     if (cspHeaderValue.IsEmpty() && cspROHeaderValue.IsEmpty()) {
    2431                 :       // no CSP header present, stop processing
    2432             968 :       return NS_OK;
    2433                 :     }
    2434                 : 
    2435                 : #ifdef PR_LOGGING 
    2436               0 :     PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("CSP header specified for document %p", this));
    2437                 : #endif
    2438                 : 
    2439                 :     nsresult rv;
    2440               0 :     nsCOMPtr<nsIContentSecurityPolicy> mCSP;
    2441               0 :     mCSP = do_CreateInstance("@mozilla.org/contentsecuritypolicy;1", &rv);
    2442                 : 
    2443               0 :     if (NS_FAILED(rv)) {
    2444                 : #ifdef PR_LOGGING 
    2445               0 :       PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("Failed to create CSP object: %x", rv));
    2446                 : #endif
    2447               0 :       return rv;
    2448                 :     }
    2449                 : 
    2450                 :     // Store the request context for violation reports
    2451               0 :     nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(mChannel);
    2452               0 :     mCSP->ScanRequestData(httpChannel);
    2453                 : 
    2454                 :     // Start parsing the policy
    2455               0 :     nsCOMPtr<nsIURI> chanURI;
    2456               0 :     mChannel->GetURI(getter_AddRefs(chanURI));
    2457                 : 
    2458                 : #ifdef PR_LOGGING 
    2459               0 :     PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("CSP Loaded"));
    2460                 : #endif
    2461                 : 
    2462                 :     // ReportOnly mode is enabled *only* if there are no regular-strength CSP
    2463                 :     // headers present.  If there are, then we ignore the ReportOnly mode and
    2464                 :     // toss a warning into the error console, proceeding with enforcing the
    2465                 :     // regular-strength CSP.
    2466               0 :     if (cspHeaderValue.IsEmpty()) {
    2467               0 :       mCSP->SetReportOnlyMode(true);
    2468                 : 
    2469                 :       // Need to tokenize the header value since multiple headers could be
    2470                 :       // concatenated into one comma-separated list of policies.
    2471                 :       // See RFC2616 section 4.2 (last paragraph)
    2472               0 :       nsCharSeparatedTokenizer tokenizer(cspROHeaderValue, ',');
    2473               0 :       while (tokenizer.hasMoreTokens()) {
    2474               0 :         const nsSubstring& policy = tokenizer.nextToken();
    2475               0 :         mCSP->RefinePolicy(policy, chanURI);
    2476                 : #ifdef PR_LOGGING
    2477                 :         {
    2478               0 :           PR_LOG(gCspPRLog, PR_LOG_DEBUG,
    2479                 :                   ("CSP (report only) refined with policy: \"%s\"",
    2480                 :                     NS_ConvertUTF16toUTF8(policy).get()));
    2481                 :         }
    2482                 : #endif
    2483                 :       }
    2484                 :     } else {
    2485                 :       //XXX(sstamm): maybe we should post a warning when both read only and regular 
    2486                 :       // CSP headers are present.
    2487                 : 
    2488                 :       // Need to tokenize the header value since multiple headers could be
    2489                 :       // concatenated into one comma-separated list of policies.
    2490                 :       // See RFC2616 section 4.2 (last paragraph)
    2491               0 :       nsCharSeparatedTokenizer tokenizer(cspHeaderValue, ',');
    2492               0 :       while (tokenizer.hasMoreTokens()) {
    2493               0 :         const nsSubstring& policy = tokenizer.nextToken();
    2494               0 :         mCSP->RefinePolicy(policy, chanURI);
    2495                 : #ifdef PR_LOGGING
    2496                 :         {
    2497               0 :           PR_LOG(gCspPRLog, PR_LOG_DEBUG,
    2498                 :                 ("CSP refined with policy: \"%s\"",
    2499                 :                   NS_ConvertUTF16toUTF8(policy).get()));
    2500                 :         }
    2501                 : #endif
    2502                 :       }
    2503                 :     }
    2504                 : 
    2505                 :     // Check for frame-ancestor violation
    2506               0 :     nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocumentContainer);
    2507               0 :     if (docShell) {
    2508               0 :         bool safeAncestry = false;
    2509                 : 
    2510                 :         // PermitsAncestry sends violation reports when necessary
    2511               0 :         rv = mCSP->PermitsAncestry(docShell, &safeAncestry);
    2512               0 :         NS_ENSURE_SUCCESS(rv, rv);
    2513                 : 
    2514               0 :         if (!safeAncestry) {
    2515                 : #ifdef PR_LOGGING
    2516               0 :             PR_LOG(gCspPRLog, PR_LOG_DEBUG, 
    2517                 :                    ("CSP doesn't like frame's ancestry, not loading."));
    2518                 : #endif
    2519                 :             // stop!  ERROR page!
    2520               0 :             mChannel->Cancel(NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION);
    2521                 :         }
    2522                 :     }
    2523                 : 
    2524                 :     //Copy into principal
    2525               0 :     nsIPrincipal* principal = GetPrincipal();
    2526                 : 
    2527               0 :     if (principal) {
    2528               0 :         principal->SetCsp(mCSP);
    2529                 : #ifdef PR_LOGGING
    2530               0 :         PR_LOG(gCspPRLog, PR_LOG_DEBUG, 
    2531                 :                 ("Inserted CSP into principal %p", principal));
    2532                 :     }
    2533                 :     else {
    2534               0 :       PR_LOG(gCspPRLog, PR_LOG_DEBUG, 
    2535                 :               ("Couldn't copy CSP into absent principal %p", principal));
    2536                 : #endif
    2537                 :     }
    2538                 :   }
    2539                 : #ifdef PR_LOGGING
    2540                 :   else { //CSP was not enabled!
    2541               0 :     PR_LOG(gCspPRLog, PR_LOG_DEBUG, 
    2542                 :            ("CSP is disabled, skipping CSP init for document %p", this));
    2543                 :   }
    2544                 : #endif
    2545               0 :   return NS_OK;
    2546                 : }
    2547                 : 
    2548                 : void
    2549               0 : nsDocument::StopDocumentLoad()
    2550                 : {
    2551               0 :   if (mParser) {
    2552               0 :     mParserAborted = true;
    2553               0 :     mParser->Terminate();
    2554                 :   }
    2555               0 : }
    2556                 : 
    2557                 : void
    2558            1742 : nsDocument::SetDocumentURI(nsIURI* aURI)
    2559                 : {
    2560            3484 :   nsCOMPtr<nsIURI> oldBase = GetDocBaseURI();
    2561            1742 :   mDocumentURI = NS_TryToMakeImmutable(aURI);
    2562            1742 :   nsIURI* newBase = GetDocBaseURI();
    2563                 : 
    2564            1742 :   bool equalBases = false;
    2565            1742 :   if (oldBase && newBase) {
    2566               0 :     oldBase->Equals(newBase, &equalBases);
    2567                 :   }
    2568                 :   else {
    2569            1742 :     equalBases = !oldBase && !newBase;
    2570                 :   }
    2571                 : 
    2572                 :   // If this is the first time we're setting the document's URI, set the
    2573                 :   // document's original URI.
    2574            1742 :   if (!mOriginalURI)
    2575            1742 :     mOriginalURI = mDocumentURI;
    2576                 : 
    2577                 :   // If changing the document's URI changed the base URI of the document, we
    2578                 :   // need to refresh the hrefs of all the links on the page.
    2579            1742 :   if (!equalBases) {
    2580            1273 :     RefreshLinkHrefs();
    2581                 :   }
    2582            1742 : }
    2583                 : 
    2584                 : NS_IMETHODIMP
    2585               0 : nsDocument::GetLastModified(nsAString& aLastModified)
    2586                 : {
    2587               0 :   if (!mLastModified.IsEmpty()) {
    2588               0 :     aLastModified.Assign(mLastModified);
    2589                 :   } else {
    2590                 :     // If we for whatever reason failed to find the last modified time
    2591                 :     // (or even the current time), fall back to what NS4.x returned.
    2592               0 :     aLastModified.Assign(NS_LITERAL_STRING("01/01/1970 00:00:00"));
    2593                 :   }
    2594                 : 
    2595               0 :   return NS_OK;
    2596                 : }
    2597                 : 
    2598                 : void
    2599               0 : nsDocument::AddToNameTable(Element *aElement, nsIAtom* aName)
    2600                 : {
    2601                 :   nsIdentifierMapEntry *entry =
    2602               0 :     mIdentifierMap.PutEntry(nsDependentAtomString(aName));
    2603                 : 
    2604                 :   // Null for out-of-memory
    2605               0 :   if (entry) {
    2606               0 :     entry->AddNameElement(this, aElement);
    2607                 :   }
    2608               0 : }
    2609                 : 
    2610                 : void
    2611               0 : nsDocument::RemoveFromNameTable(Element *aElement, nsIAtom* aName)
    2612                 : {
    2613                 :   // Speed up document teardown
    2614               0 :   if (mIdentifierMap.Count() == 0)
    2615               0 :     return;
    2616                 : 
    2617                 :   nsIdentifierMapEntry *entry =
    2618               0 :     mIdentifierMap.GetEntry(nsDependentAtomString(aName));
    2619               0 :   if (!entry) // Could be false if the element was anonymous, hence never added
    2620               0 :     return;
    2621                 : 
    2622               0 :   entry->RemoveNameElement(aElement);
    2623                 : }
    2624                 : 
    2625                 : void
    2626             122 : nsDocument::AddToIdTable(Element *aElement, nsIAtom* aId)
    2627                 : {
    2628                 :   nsIdentifierMapEntry *entry =
    2629             122 :     mIdentifierMap.PutEntry(nsDependentAtomString(aId));
    2630                 : 
    2631             122 :   if (entry) { /* True except on OOM */
    2632             122 :     entry->AddIdElement(aElement);
    2633                 :   }
    2634             122 : }
    2635                 : 
    2636                 : void
    2637             122 : nsDocument::RemoveFromIdTable(Element *aElement, nsIAtom* aId)
    2638                 : {
    2639             122 :   NS_ASSERTION(aId, "huhwhatnow?");
    2640                 : 
    2641                 :   // Speed up document teardown
    2642             122 :   if (mIdentifierMap.Count() == 0) {
    2643               0 :     return;
    2644                 :   }
    2645                 : 
    2646                 :   nsIdentifierMapEntry *entry =
    2647             122 :     mIdentifierMap.GetEntry(nsDependentAtomString(aId));
    2648             122 :   if (!entry) // Can be null for XML elements with changing ids.
    2649               0 :     return;
    2650                 : 
    2651             122 :   entry->RemoveIdElement(aElement);
    2652             122 :   if (entry->IsEmpty()) {
    2653             122 :     mIdentifierMap.RawRemoveEntry(entry);
    2654                 :   }
    2655                 : }
    2656                 : 
    2657                 : nsIPrincipal*
    2658               0 : nsDocument::GetPrincipal()
    2659                 : {
    2660               0 :   return NodePrincipal();
    2661                 : }
    2662                 : 
    2663                 : extern bool sDisablePrefetchHTTPSPref;
    2664                 : 
    2665                 : void
    2666            3249 : nsDocument::SetPrincipal(nsIPrincipal *aNewPrincipal)
    2667                 : {
    2668            3249 :   if (aNewPrincipal && mAllowDNSPrefetch && sDisablePrefetchHTTPSPref) {
    2669            3544 :     nsCOMPtr<nsIURI> uri;
    2670            1772 :     aNewPrincipal->GetURI(getter_AddRefs(uri));
    2671                 :     bool isHTTPS;
    2672            1772 :     if (!uri || NS_FAILED(uri->SchemeIs("https", &isHTTPS)) ||
    2673                 :         isHTTPS) {
    2674             539 :       mAllowDNSPrefetch = false;
    2675                 :     }
    2676                 :   }
    2677            3249 :   mNodeInfoManager->SetDocumentPrincipal(aNewPrincipal);
    2678            3249 : }
    2679                 : 
    2680                 : NS_IMETHODIMP
    2681               0 : nsDocument::GetApplicationCache(nsIApplicationCache **aApplicationCache)
    2682                 : {
    2683               0 :   NS_IF_ADDREF(*aApplicationCache = mApplicationCache);
    2684                 : 
    2685               0 :   return NS_OK;
    2686                 : }
    2687                 : 
    2688                 : NS_IMETHODIMP
    2689               0 : nsDocument::SetApplicationCache(nsIApplicationCache *aApplicationCache)
    2690                 : {
    2691               0 :   mApplicationCache = aApplicationCache;
    2692                 : 
    2693               0 :   return NS_OK;
    2694                 : }
    2695                 : 
    2696                 : NS_IMETHODIMP
    2697               0 : nsDocument::GetContentType(nsAString& aContentType)
    2698                 : {
    2699               0 :   CopyUTF8toUTF16(GetContentTypeInternal(), aContentType);
    2700                 : 
    2701               0 :   return NS_OK;
    2702                 : }
    2703                 : 
    2704                 : void
    2705               0 : nsDocument::SetContentType(const nsAString& aContentType)
    2706                 : {
    2707               0 :   NS_ASSERTION(GetContentTypeInternal().IsEmpty() ||
    2708                 :                GetContentTypeInternal().Equals(NS_ConvertUTF16toUTF8(aContentType)),
    2709                 :                "Do you really want to change the content-type?");
    2710                 : 
    2711               0 :   SetContentTypeInternal(NS_ConvertUTF16toUTF8(aContentType));
    2712               0 : }
    2713                 : 
    2714                 : /* Return true if the document is in the focused top-level window, and is an
    2715                 :  * ancestor of the focused DOMWindow. */
    2716                 : NS_IMETHODIMP
    2717               0 : nsDocument::HasFocus(bool* aResult)
    2718                 : {
    2719               0 :   *aResult = false;
    2720                 : 
    2721               0 :   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
    2722               0 :   if (!fm)
    2723               0 :     return NS_ERROR_NOT_AVAILABLE;
    2724                 : 
    2725                 :   // Is there a focused DOMWindow?
    2726               0 :   nsCOMPtr<nsIDOMWindow> focusedWindow;
    2727               0 :   fm->GetFocusedWindow(getter_AddRefs(focusedWindow));
    2728               0 :   if (!focusedWindow)
    2729               0 :     return NS_OK;
    2730                 : 
    2731                 :   // Are we an ancestor of the focused DOMWindow?
    2732               0 :   nsCOMPtr<nsIDOMDocument> domDocument;
    2733               0 :   focusedWindow->GetDocument(getter_AddRefs(domDocument));
    2734               0 :   nsCOMPtr<nsIDocument> document = do_QueryInterface(domDocument);
    2735                 : 
    2736               0 :   for (nsIDocument* currentDoc = document; currentDoc;
    2737                 :        currentDoc = currentDoc->GetParentDocument()) {
    2738               0 :     if (currentDoc == this) {
    2739                 :       // Yes, we are an ancestor
    2740               0 :       *aResult = true;
    2741               0 :       return NS_OK;
    2742                 :     }
    2743                 :   }
    2744                 : 
    2745               0 :   return NS_OK;
    2746                 : }
    2747                 : 
    2748                 : NS_IMETHODIMP
    2749               0 : nsDocument::GetReferrer(nsAString& aReferrer)
    2750                 : {
    2751               0 :   CopyUTF8toUTF16(mReferrer, aReferrer);
    2752               0 :   return NS_OK;
    2753                 : }
    2754                 : 
    2755                 : NS_IMETHODIMP
    2756               0 : nsDocument::GetActiveElement(nsIDOMElement **aElement)
    2757                 : {
    2758               0 :   *aElement = nsnull;
    2759                 : 
    2760                 :   // Get the focused element.
    2761               0 :   nsCOMPtr<nsPIDOMWindow> window = GetWindow();
    2762               0 :   if (window) {
    2763               0 :     nsCOMPtr<nsPIDOMWindow> focusedWindow;
    2764                 :     nsIContent* focusedContent =
    2765                 :       nsFocusManager::GetFocusedDescendant(window, false,
    2766               0 :                                            getter_AddRefs(focusedWindow));
    2767                 :     // be safe and make sure the element is from this document
    2768               0 :     if (focusedContent && focusedContent->OwnerDoc() == this) {
    2769               0 :       CallQueryInterface(focusedContent, aElement);
    2770               0 :       return NS_OK;
    2771                 :     }
    2772                 :   }
    2773                 : 
    2774                 :   // No focused element anywhere in this document.  Try to get the BODY.
    2775               0 :   nsCOMPtr<nsIDOMHTMLDocument> htmlDoc = do_QueryObject(this);
    2776               0 :   if (htmlDoc) {
    2777               0 :     nsCOMPtr<nsIDOMHTMLElement> bodyElement;
    2778               0 :     htmlDoc->GetBody(getter_AddRefs(bodyElement));
    2779               0 :     if (bodyElement) {
    2780               0 :       *aElement = bodyElement;
    2781               0 :       NS_ADDREF(*aElement);
    2782                 :     }
    2783                 :     // Because of IE compatibility, return null when html document doesn't have
    2784                 :     // a body.
    2785               0 :     return NS_OK;
    2786                 :   }
    2787                 : 
    2788                 :   // If we couldn't get a BODY, return the root element.
    2789               0 :   return GetDocumentElement(aElement);
    2790                 : }
    2791                 : 
    2792                 : NS_IMETHODIMP
    2793               0 : nsDocument::GetCurrentScript(nsIDOMElement **aElement)
    2794                 : {
    2795               0 :   nsIScriptElement* script = mScriptLoader->GetCurrentScript();
    2796               0 :   if (script) {
    2797               0 :     return CallQueryInterface(script, aElement);
    2798                 :   }
    2799                 :   
    2800               0 :   *aElement = nsnull;
    2801                 : 
    2802               0 :   return NS_OK;
    2803                 : }
    2804                 : 
    2805                 : NS_IMETHODIMP
    2806               0 : nsDocument::ElementFromPoint(float aX, float aY, nsIDOMElement** aReturn)
    2807                 : {
    2808               0 :   return ElementFromPointHelper(aX, aY, false, true, aReturn);
    2809                 : }
    2810                 : 
    2811                 : nsresult
    2812               0 : nsDocument::ElementFromPointHelper(float aX, float aY,
    2813                 :                                    bool aIgnoreRootScrollFrame,
    2814                 :                                    bool aFlushLayout,
    2815                 :                                    nsIDOMElement** aReturn)
    2816                 : {
    2817               0 :   NS_ENSURE_ARG_POINTER(aReturn);
    2818               0 :   *aReturn = nsnull;
    2819                 :   // As per the the spec, we return null if either coord is negative
    2820               0 :   if (!aIgnoreRootScrollFrame && (aX < 0 || aY < 0))
    2821               0 :     return NS_OK;
    2822                 : 
    2823               0 :   nscoord x = nsPresContext::CSSPixelsToAppUnits(aX);
    2824               0 :   nscoord y = nsPresContext::CSSPixelsToAppUnits(aY);
    2825               0 :   nsPoint pt(x, y);
    2826                 : 
    2827                 :   // Make sure the layout information we get is up-to-date, and
    2828                 :   // ensure we get a root frame (for everything but XUL)
    2829               0 :   if (aFlushLayout)
    2830               0 :     FlushPendingNotifications(Flush_Layout);
    2831                 : 
    2832               0 :   nsIPresShell *ps = GetShell();
    2833               0 :   NS_ENSURE_STATE(ps);
    2834               0 :   nsIFrame *rootFrame = ps->GetRootFrame();
    2835                 : 
    2836                 :   // XUL docs, unlike HTML, have no frame tree until everything's done loading
    2837               0 :   if (!rootFrame)
    2838               0 :     return NS_OK; // return null to premature XUL callers as a reminder to wait
    2839                 : 
    2840                 :   nsIFrame *ptFrame = nsLayoutUtils::GetFrameForPoint(rootFrame, pt, true,
    2841               0 :                                                       aIgnoreRootScrollFrame);
    2842               0 :   if (!ptFrame)
    2843               0 :     return NS_OK;
    2844                 : 
    2845               0 :   nsIContent* ptContent = ptFrame->GetContent();
    2846               0 :   NS_ENSURE_STATE(ptContent);
    2847                 : 
    2848                 :   // If the content is in a subdocument, try to get the element from |this| doc
    2849               0 :   nsIDocument *currentDoc = ptContent->GetCurrentDoc();
    2850               0 :   if (currentDoc && (currentDoc != this)) {
    2851               0 :     *aReturn = CheckAncestryAndGetFrame(currentDoc).get();
    2852               0 :     return NS_OK;
    2853                 :   }
    2854                 : 
    2855                 :   // If we have an anonymous element (such as an internal div from a textbox),
    2856                 :   // or a node that isn't an element (such as a text frame node),
    2857                 :   // replace it with the first non-anonymous parent node of type element.
    2858               0 :   while (ptContent &&
    2859               0 :          (!ptContent->IsElement() ||
    2860               0 :           ptContent->IsInAnonymousSubtree())) {
    2861                 :     // XXXldb: Faster to jump to GetBindingParent if non-null?
    2862               0 :     ptContent = ptContent->GetParent();
    2863                 :   }
    2864                 :  
    2865               0 :   if (ptContent)
    2866               0 :     CallQueryInterface(ptContent, aReturn);
    2867               0 :   return NS_OK;
    2868                 : }
    2869                 : 
    2870                 : nsresult
    2871               0 : nsDocument::NodesFromRectHelper(float aX, float aY,
    2872                 :                                 float aTopSize, float aRightSize,
    2873                 :                                 float aBottomSize, float aLeftSize,
    2874                 :                                 bool aIgnoreRootScrollFrame,
    2875                 :                                 bool aFlushLayout,
    2876                 :                                 nsIDOMNodeList** aReturn)
    2877                 : {
    2878               0 :   NS_ENSURE_ARG_POINTER(aReturn);
    2879                 :   
    2880               0 :   nsSimpleContentList* elements = new nsSimpleContentList(this);
    2881               0 :   NS_ADDREF(elements);
    2882               0 :   *aReturn = elements;
    2883                 : 
    2884                 :   // Following the same behavior of elementFromPoint,
    2885                 :   // we don't return anything if either coord is negative
    2886               0 :   if (!aIgnoreRootScrollFrame && (aX < 0 || aY < 0))
    2887               0 :     return NS_OK;
    2888                 : 
    2889               0 :   nscoord x = nsPresContext::CSSPixelsToAppUnits(aX - aLeftSize);
    2890               0 :   nscoord y = nsPresContext::CSSPixelsToAppUnits(aY - aTopSize);
    2891               0 :   nscoord w = nsPresContext::CSSPixelsToAppUnits(aLeftSize + aRightSize) + 1;
    2892               0 :   nscoord h = nsPresContext::CSSPixelsToAppUnits(aTopSize + aBottomSize) + 1;
    2893                 : 
    2894               0 :   nsRect rect(x, y, w, h);
    2895                 : 
    2896                 :   // Make sure the layout information we get is up-to-date, and
    2897                 :   // ensure we get a root frame (for everything but XUL)
    2898               0 :   if (aFlushLayout) {
    2899               0 :     FlushPendingNotifications(Flush_Layout);
    2900                 :   }
    2901                 : 
    2902               0 :   nsIPresShell *ps = GetShell();
    2903               0 :   NS_ENSURE_STATE(ps);
    2904               0 :   nsIFrame *rootFrame = ps->GetRootFrame();
    2905                 : 
    2906                 :   // XUL docs, unlike HTML, have no frame tree until everything's done loading
    2907               0 :   if (!rootFrame)
    2908               0 :     return NS_OK; // return nothing to premature XUL callers as a reminder to wait
    2909                 : 
    2910               0 :   nsAutoTArray<nsIFrame*,8> outFrames;
    2911                 :   nsLayoutUtils::GetFramesForArea(rootFrame, rect, outFrames,
    2912               0 :                                   true, aIgnoreRootScrollFrame);
    2913                 : 
    2914               0 :   PRInt32 length = outFrames.Length();
    2915               0 :   if (!length)
    2916               0 :     return NS_OK;
    2917                 : 
    2918                 :   // Used to filter out repeated elements in sequence.
    2919               0 :   nsIContent* lastAdded = nsnull;
    2920                 : 
    2921               0 :   for (PRInt32 i = 0; i < length; i++) {
    2922                 : 
    2923               0 :     nsIContent* ptContent = outFrames.ElementAt(i)->GetContent();
    2924               0 :     NS_ENSURE_STATE(ptContent);
    2925                 : 
    2926                 :     // If the content is in a subdocument, try to get the element from |this| doc
    2927               0 :     nsIDocument *currentDoc = ptContent->GetCurrentDoc();
    2928               0 :     if (currentDoc && (currentDoc != this)) {
    2929                 :       // XXX felipe: I can't get this type right without the intermediate vars
    2930               0 :       nsCOMPtr<nsIDOMElement> x = CheckAncestryAndGetFrame(currentDoc);
    2931               0 :       nsCOMPtr<nsIContent> elementDoc = do_QueryInterface(x);
    2932               0 :       if (elementDoc != lastAdded) {
    2933               0 :         elements->AppendElement(elementDoc);
    2934               0 :         lastAdded = elementDoc;
    2935                 :       }
    2936               0 :       continue;
    2937                 :     }
    2938                 : 
    2939                 :     // If we have an anonymous element (such as an internal div from a textbox),
    2940                 :     // or a node that isn't an element or a text node,
    2941                 :     // replace it with the first non-anonymous parent node.
    2942               0 :     while (ptContent &&
    2943               0 :            (!(ptContent->IsElement() ||
    2944               0 :               ptContent->IsNodeOfType(nsINode::eTEXT)) ||
    2945               0 :             ptContent->IsInAnonymousSubtree())) {
    2946                 :       // XXXldb: Faster to jump to GetBindingParent if non-null?
    2947               0 :       ptContent = ptContent->GetParent();
    2948                 :     }
    2949                 :    
    2950               0 :     if (ptContent && ptContent != lastAdded) {
    2951               0 :       elements->AppendElement(ptContent);
    2952               0 :       lastAdded = ptContent;
    2953                 :     }
    2954                 :   }
    2955               0 :   return NS_OK;
    2956                 : }
    2957                 : 
    2958                 : NS_IMETHODIMP
    2959               0 : nsDocument::GetElementsByClassName(const nsAString& aClasses,
    2960                 :                                    nsIDOMNodeList** aReturn)
    2961                 : {
    2962               0 :   return nsContentUtils::GetElementsByClassName(this, aClasses, aReturn);
    2963                 : }
    2964                 : 
    2965                 : NS_IMETHODIMP
    2966               0 : nsDocument::ReleaseCapture()
    2967                 : {
    2968                 :   // only release the capture if the caller can access it. This prevents a
    2969                 :   // page from stopping a scrollbar grab for example.
    2970               0 :   nsCOMPtr<nsIDOMNode> node = do_QueryInterface(nsIPresShell::GetCapturingContent());
    2971               0 :   if (node && nsContentUtils::CanCallerAccess(node)) {
    2972               0 :     nsIPresShell::SetCapturingContent(nsnull, 0);
    2973                 :   }
    2974               0 :   return NS_OK;
    2975                 : }
    2976                 : 
    2977                 : nsresult
    2978            1842 : nsDocument::SetBaseURI(nsIURI* aURI)
    2979                 : {
    2980            1842 :   if (!aURI && !mDocumentBaseURI) {
    2981            1607 :     return NS_OK;
    2982                 :   }
    2983                 :   
    2984                 :   // Don't do anything if the URI wasn't actually changed.
    2985             235 :   if (aURI && mDocumentBaseURI) {
    2986               0 :     bool equalBases = false;
    2987               0 :     mDocumentBaseURI->Equals(aURI, &equalBases);
    2988               0 :     if (equalBases) {
    2989               0 :       return NS_OK;
    2990                 :     }
    2991                 :   }
    2992                 : 
    2993             235 :   if (aURI) {
    2994             235 :     mDocumentBaseURI = NS_TryToMakeImmutable(aURI);
    2995                 :   } else {
    2996               0 :     mDocumentBaseURI = nsnull;
    2997                 :   }
    2998             235 :   RefreshLinkHrefs();
    2999                 : 
    3000             235 :   return NS_OK;
    3001                 : }
    3002                 : 
    3003                 : void
    3004               0 : nsDocument::GetBaseTarget(nsAString &aBaseTarget)
    3005                 : {
    3006               0 :   aBaseTarget = mBaseTarget;
    3007               0 : }
    3008                 : 
    3009                 : void
    3010            2684 : nsDocument::SetDocumentCharacterSet(const nsACString& aCharSetID)
    3011                 : {
    3012            2684 :   if (!mCharacterSet.Equals(aCharSetID)) {
    3013            1273 :     mCharacterSet = aCharSetID;
    3014                 : 
    3015                 : #ifdef DEBUG
    3016            2546 :     nsCAutoString canonicalName;
    3017            1273 :     nsCharsetAlias::GetPreferred(aCharSetID, canonicalName);
    3018            1273 :     NS_ASSERTION(canonicalName.Equals(aCharSetID),
    3019                 :                  "charset name must be canonical");
    3020                 : #endif
    3021                 : 
    3022            1273 :     PRInt32 n = mCharSetObservers.Length();
    3023                 : 
    3024            1273 :     for (PRInt32 i = 0; i < n; i++) {
    3025               0 :       nsIObserver* observer = mCharSetObservers.ElementAt(i);
    3026                 : 
    3027                 :       observer->Observe(static_cast<nsIDocument *>(this), "charset",
    3028               0 :                         NS_ConvertASCIItoUTF16(aCharSetID).get());
    3029                 :     }
    3030                 :   }
    3031            2684 : }
    3032                 : 
    3033                 : nsresult
    3034               0 : nsDocument::AddCharSetObserver(nsIObserver* aObserver)
    3035                 : {
    3036               0 :   NS_ENSURE_ARG_POINTER(aObserver);
    3037                 : 
    3038               0 :   NS_ENSURE_TRUE(mCharSetObservers.AppendElement(aObserver), NS_ERROR_FAILURE);
    3039                 : 
    3040               0 :   return NS_OK;
    3041                 : }
    3042                 : 
    3043                 : void
    3044               0 : nsDocument::RemoveCharSetObserver(nsIObserver* aObserver)
    3045                 : {
    3046               0 :   mCharSetObservers.RemoveElement(aObserver);
    3047               0 : }
    3048                 : 
    3049                 : void
    3050            3349 : nsDocument::GetHeaderData(nsIAtom* aHeaderField, nsAString& aData) const
    3051                 : {
    3052            3349 :   aData.Truncate();
    3053            3349 :   const nsDocHeaderData* data = mHeaderData;
    3054            6706 :   while (data) {
    3055               8 :     if (data->mField == aHeaderField) {
    3056               0 :       aData = data->mData;
    3057                 : 
    3058               0 :       break;
    3059                 :     }
    3060               8 :     data = data->mNext;
    3061                 :   }
    3062            3349 : }
    3063                 : 
    3064                 : void
    3065               4 : nsDocument::SetHeaderData(nsIAtom* aHeaderField, const nsAString& aData)
    3066                 : {
    3067               4 :   if (!aHeaderField) {
    3068               0 :     NS_ERROR("null headerField");
    3069               0 :     return;
    3070                 :   }
    3071                 : 
    3072               4 :   if (!mHeaderData) {
    3073               4 :     if (!aData.IsEmpty()) { // don't bother storing empty string
    3074               4 :       mHeaderData = new nsDocHeaderData(aHeaderField, aData);
    3075                 :     }
    3076                 :   }
    3077                 :   else {
    3078               0 :     nsDocHeaderData* data = mHeaderData;
    3079               0 :     nsDocHeaderData** lastPtr = &mHeaderData;
    3080               0 :     bool found = false;
    3081               0 :     do {  // look for existing and replace
    3082               0 :       if (data->mField == aHeaderField) {
    3083               0 :         if (!aData.IsEmpty()) {
    3084               0 :           data->mData.Assign(aData);
    3085                 :         }
    3086                 :         else {  // don't store empty string
    3087               0 :           *lastPtr = data->mNext;
    3088               0 :           data->mNext = nsnull;
    3089               0 :           delete data;
    3090                 :         }
    3091               0 :         found = true;
    3092                 : 
    3093               0 :         break;
    3094                 :       }
    3095               0 :       lastPtr = &(data->mNext);
    3096               0 :       data = *lastPtr;
    3097                 :     } while (data);
    3098                 : 
    3099               0 :     if (!aData.IsEmpty() && !found) {
    3100                 :       // didn't find, append
    3101               0 :       *lastPtr = new nsDocHeaderData(aHeaderField, aData);
    3102                 :     }
    3103                 :   }
    3104                 : 
    3105               4 :   if (aHeaderField == nsGkAtoms::headerContentLanguage) {
    3106               0 :     CopyUTF16toUTF8(aData, mContentLanguage);
    3107                 :   }
    3108                 : 
    3109                 :   // Set the default script-type on the root element.
    3110               4 :   if (aHeaderField == nsGkAtoms::headerContentScriptType) {
    3111               0 :     Element *root = GetRootElement();
    3112               0 :     if (root) {
    3113                 :       // Get the script-type ID for this value.
    3114                 :       nsresult rv;
    3115               0 :       nsCOMPtr<nsIScriptRuntime> runtime;
    3116               0 :       rv = NS_GetScriptRuntime(aData, getter_AddRefs(runtime));
    3117               0 :       if (NS_FAILED(rv) || runtime == nsnull) {
    3118               0 :         NS_WARNING("The script-type is unknown");
    3119                 :       } else {
    3120               0 :         root->SetScriptTypeID(runtime->GetScriptTypeID());
    3121                 :       }
    3122                 :     }
    3123                 :   }
    3124                 : 
    3125               4 :   if (aHeaderField == nsGkAtoms::headerDefaultStyle) {
    3126                 :     // Only mess with our stylesheets if we don't have a lastStyleSheetSet, per
    3127                 :     // spec.
    3128               0 :     if (DOMStringIsNull(mLastStyleSheetSet)) {
    3129                 :       // Calling EnableStyleSheetsForSetInternal, not SetSelectedStyleSheetSet,
    3130                 :       // per spec.  The idea here is that we're changing our preferred set and
    3131                 :       // that shouldn't change the value of lastStyleSheetSet.  Also, we're
    3132                 :       // using the Internal version so we can update the CSSLoader and not have
    3133                 :       // to worry about null strings.
    3134               0 :       EnableStyleSheetsForSetInternal(aData, true);
    3135                 :     }
    3136                 :   }
    3137                 : 
    3138               4 :   if (aHeaderField == nsGkAtoms::refresh) {
    3139                 :     // We get into this code before we have a script global yet, so get to
    3140                 :     // our container via mDocumentContainer.
    3141               0 :     nsCOMPtr<nsIRefreshURI> refresher = do_QueryReferent(mDocumentContainer);
    3142               0 :     if (refresher) {
    3143                 :       // Note: using mDocumentURI instead of mBaseURI here, for consistency
    3144                 :       // (used to just use the current URI of our webnavigation, but that
    3145                 :       // should really be the same thing).  Note that this code can run
    3146                 :       // before the current URI of the webnavigation has been updated, so we
    3147                 :       // can't assert equality here.
    3148               0 :       refresher->SetupRefreshURIFromHeader(mDocumentURI,
    3149               0 :                                            NS_ConvertUTF16toUTF8(aData));
    3150                 :     }
    3151                 :   }
    3152                 : 
    3153               4 :   if (aHeaderField == nsGkAtoms::headerDNSPrefetchControl &&
    3154                 :       mAllowDNSPrefetch) {
    3155                 :     // Chromium treats any value other than 'on' (case insensitive) as 'off'.
    3156               0 :     mAllowDNSPrefetch = aData.IsEmpty() || aData.LowerCaseEqualsLiteral("on");
    3157                 :   }
    3158                 : }
    3159                 : 
    3160                 : bool
    3161            1038 : nsDocument::TryChannelCharset(nsIChannel *aChannel,
    3162                 :                               PRInt32& aCharsetSource,
    3163                 :                               nsACString& aCharset)
    3164                 : {
    3165            1038 :   if(kCharsetFromChannel <= aCharsetSource) {
    3166               0 :     return true;
    3167                 :   }
    3168                 : 
    3169            1038 :   if (aChannel) {
    3170            2076 :     nsCAutoString charsetVal;
    3171            1038 :     nsresult rv = aChannel->GetContentCharset(charsetVal);
    3172            1038 :     if (NS_SUCCEEDED(rv)) {
    3173            2076 :       nsCAutoString preferred;
    3174            1038 :       rv = nsCharsetAlias::GetPreferred(charsetVal, preferred);
    3175            1038 :       if(NS_SUCCEEDED(rv)) {
    3176             560 :         aCharset = preferred;
    3177             560 :         aCharsetSource = kCharsetFromChannel;
    3178             560 :         return true;
    3179                 :       }
    3180                 :     }
    3181                 :   }
    3182             478 :   return false;
    3183                 : }
    3184                 : 
    3185                 : nsresult
    3186               0 : nsDocument::CreateShell(nsPresContext* aContext, nsIViewManager* aViewManager,
    3187                 :                         nsStyleSet* aStyleSet,
    3188                 :                         nsIPresShell** aInstancePtrResult)
    3189                 : {
    3190                 :   // Don't add anything here.  Add it to |doCreateShell| instead.
    3191                 :   // This exists so that subclasses can pass other values for the 4th
    3192                 :   // parameter some of the time.
    3193                 :   return doCreateShell(aContext, aViewManager, aStyleSet,
    3194               0 :                        eCompatibility_FullStandards, aInstancePtrResult);
    3195                 : }
    3196                 : 
    3197                 : nsresult
    3198               0 : nsDocument::doCreateShell(nsPresContext* aContext,
    3199                 :                           nsIViewManager* aViewManager, nsStyleSet* aStyleSet,
    3200                 :                           nsCompatibility aCompatMode,
    3201                 :                           nsIPresShell** aInstancePtrResult)
    3202                 : {
    3203               0 :   *aInstancePtrResult = nsnull;
    3204                 : 
    3205               0 :   NS_ASSERTION(!mPresShell, "We have a presshell already!");
    3206                 : 
    3207               0 :   NS_ENSURE_FALSE(GetBFCacheEntry(), NS_ERROR_FAILURE);
    3208                 : 
    3209               0 :   FillStyleSet(aStyleSet);
    3210                 :   
    3211               0 :   nsCOMPtr<nsIPresShell> shell;
    3212               0 :   nsresult rv = NS_NewPresShell(getter_AddRefs(shell));
    3213               0 :   if (NS_FAILED(rv)) {
    3214               0 :     return rv;
    3215                 :   }
    3216                 : 
    3217               0 :   rv = shell->Init(this, aContext, aViewManager, aStyleSet, aCompatMode);
    3218               0 :   NS_ENSURE_SUCCESS(rv, rv);
    3219                 : 
    3220                 :   // Note: we don't hold a ref to the shell (it holds a ref to us)
    3221               0 :   mPresShell = shell;
    3222                 : 
    3223               0 :   mExternalResourceMap.ShowViewers();
    3224                 : 
    3225               0 :   MaybeRescheduleAnimationFrameNotifications();
    3226                 : 
    3227               0 :   shell.swap(*aInstancePtrResult);
    3228                 : 
    3229               0 :   return NS_OK;
    3230                 : }
    3231                 : 
    3232                 : void
    3233               0 : nsDocument::MaybeRescheduleAnimationFrameNotifications()
    3234                 : {
    3235               0 :   if (!mPresShell || !IsEventHandlingEnabled()) {
    3236                 :     // bail out for now, until one of those conditions changes
    3237               0 :     return;
    3238                 :   }
    3239                 : 
    3240               0 :   nsRefreshDriver* rd = mPresShell->GetPresContext()->RefreshDriver();
    3241               0 :   if (!mFrameRequestCallbacks.IsEmpty()) {
    3242               0 :     rd->ScheduleFrameRequestCallbacks(this);
    3243                 :   }
    3244                 : }
    3245                 : 
    3246                 : void
    3247               0 : nsIDocument::TakeFrameRequestCallbacks(FrameRequestCallbackList& aCallbacks)
    3248                 : {
    3249               0 :   aCallbacks.AppendElements(mFrameRequestCallbacks);
    3250               0 :   mFrameRequestCallbacks.Clear();
    3251               0 : }
    3252                 : 
    3253               0 : PLDHashOperator RequestDiscardEnumerator(imgIRequest* aKey,
    3254                 :                                          PRUint32 aData,
    3255                 :                                          void* userArg)
    3256                 : {
    3257               0 :   aKey->RequestDiscard();
    3258               0 :   return PL_DHASH_NEXT;
    3259                 : }
    3260                 : 
    3261                 : void
    3262               0 : nsDocument::DeleteShell()
    3263                 : {
    3264               0 :   mExternalResourceMap.HideViewers();
    3265               0 :   if (IsEventHandlingEnabled()) {
    3266               0 :     RevokeAnimationFrameNotifications();
    3267                 :   }
    3268                 : 
    3269                 :   // When our shell goes away, request that all our images be immediately
    3270                 :   // discarded, so we don't carry around decoded image data for a document we
    3271                 :   // no longer intend to paint.
    3272               0 :   mImageTracker.EnumerateRead(RequestDiscardEnumerator, nsnull);
    3273                 : 
    3274               0 :   mPresShell = nsnull;
    3275               0 : }
    3276                 : 
    3277                 : void
    3278               0 : nsDocument::RevokeAnimationFrameNotifications()
    3279                 : {
    3280               0 :   if (!mFrameRequestCallbacks.IsEmpty()) {
    3281                 :     mPresShell->GetPresContext()->RefreshDriver()->
    3282               0 :       RevokeFrameRequestCallbacks(this);
    3283                 :   }
    3284               0 : }
    3285                 : 
    3286                 : static void
    3287               0 : SubDocClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
    3288                 : {
    3289               0 :   SubDocMapEntry *e = static_cast<SubDocMapEntry *>(entry);
    3290                 : 
    3291               0 :   NS_RELEASE(e->mKey);
    3292               0 :   if (e->mSubDocument) {
    3293               0 :     e->mSubDocument->SetParentDocument(nsnull);
    3294               0 :     NS_RELEASE(e->mSubDocument);
    3295                 :   }
    3296               0 : }
    3297                 : 
    3298                 : static bool
    3299               0 : SubDocInitEntry(PLDHashTable *table, PLDHashEntryHdr *entry, const void *key)
    3300                 : {
    3301                 :   SubDocMapEntry *e =
    3302                 :     const_cast<SubDocMapEntry *>
    3303               0 :               (static_cast<const SubDocMapEntry *>(entry));
    3304                 : 
    3305               0 :   e->mKey = const_cast<Element*>(static_cast<const Element*>(key));
    3306               0 :   NS_ADDREF(e->mKey);
    3307                 : 
    3308               0 :   e->mSubDocument = nsnull;
    3309               0 :   return true;
    3310                 : }
    3311                 : 
    3312                 : nsresult
    3313               0 : nsDocument::SetSubDocumentFor(Element* aElement, nsIDocument* aSubDoc)
    3314                 : {
    3315               0 :   NS_ENSURE_TRUE(aElement, NS_ERROR_UNEXPECTED);
    3316                 : 
    3317               0 :   if (!aSubDoc) {
    3318                 :     // aSubDoc is nsnull, remove the mapping
    3319                 : 
    3320               0 :     if (mSubDocuments) {
    3321                 :       SubDocMapEntry *entry =
    3322                 :         static_cast<SubDocMapEntry*>
    3323                 :                    (PL_DHashTableOperate(mSubDocuments, aElement,
    3324               0 :                                          PL_DHASH_LOOKUP));
    3325                 : 
    3326               0 :       if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
    3327               0 :         PL_DHashTableRawRemove(mSubDocuments, entry);
    3328                 :       }
    3329                 :     }
    3330                 :   } else {
    3331               0 :     if (!mSubDocuments) {
    3332                 :       // Create a new hashtable
    3333                 : 
    3334                 :       static PLDHashTableOps hash_table_ops =
    3335                 :       {
    3336                 :         PL_DHashAllocTable,
    3337                 :         PL_DHashFreeTable,
    3338                 :         PL_DHashVoidPtrKeyStub,
    3339                 :         PL_DHashMatchEntryStub,
    3340                 :         PL_DHashMoveEntryStub,
    3341                 :         SubDocClearEntry,
    3342                 :         PL_DHashFinalizeStub,
    3343                 :         SubDocInitEntry
    3344                 :       };
    3345                 : 
    3346                 :       mSubDocuments = PL_NewDHashTable(&hash_table_ops, nsnull,
    3347               0 :                                        sizeof(SubDocMapEntry), 16);
    3348               0 :       if (!mSubDocuments) {
    3349               0 :         return NS_ERROR_OUT_OF_MEMORY;
    3350                 :       }
    3351                 :     }
    3352                 : 
    3353                 :     // Add a mapping to the hash table
    3354                 :     SubDocMapEntry *entry =
    3355                 :       static_cast<SubDocMapEntry*>
    3356                 :                  (PL_DHashTableOperate(mSubDocuments, aElement,
    3357               0 :                                        PL_DHASH_ADD));
    3358                 : 
    3359               0 :     if (!entry) {
    3360               0 :       return NS_ERROR_OUT_OF_MEMORY;
    3361                 :     }
    3362                 : 
    3363               0 :     if (entry->mSubDocument) {
    3364               0 :       entry->mSubDocument->SetParentDocument(nsnull);
    3365                 : 
    3366                 :       // Release the old sub document
    3367               0 :       NS_RELEASE(entry->mSubDocument);
    3368                 :     }
    3369                 : 
    3370               0 :     entry->mSubDocument = aSubDoc;
    3371               0 :     NS_ADDREF(entry->mSubDocument);
    3372                 : 
    3373               0 :     aSubDoc->SetParentDocument(this);
    3374                 :   }
    3375                 : 
    3376               0 :   return NS_OK;
    3377                 : }
    3378                 : 
    3379                 : nsIDocument*
    3380               0 : nsDocument::GetSubDocumentFor(nsIContent *aContent) const
    3381                 : {
    3382               0 :   if (mSubDocuments && aContent->IsElement()) {
    3383                 :     SubDocMapEntry *entry =
    3384                 :       static_cast<SubDocMapEntry*>
    3385               0 :                  (PL_DHashTableOperate(mSubDocuments, aContent->AsElement(),
    3386               0 :                                        PL_DHASH_LOOKUP));
    3387                 : 
    3388               0 :     if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
    3389               0 :       return entry->mSubDocument;
    3390                 :     }
    3391                 :   }
    3392                 : 
    3393               0 :   return nsnull;
    3394                 : }
    3395                 : 
    3396                 : static PLDHashOperator
    3397               0 : FindContentEnumerator(PLDHashTable *table, PLDHashEntryHdr *hdr,
    3398                 :                       PRUint32 number, void *arg)
    3399                 : {
    3400               0 :   SubDocMapEntry *entry = static_cast<SubDocMapEntry*>(hdr);
    3401               0 :   FindContentData *data = static_cast<FindContentData*>(arg);
    3402                 : 
    3403               0 :   if (entry->mSubDocument == data->mSubDocument) {
    3404               0 :     data->mResult = entry->mKey;
    3405                 : 
    3406               0 :     return PL_DHASH_STOP;
    3407                 :   }
    3408                 : 
    3409               0 :   return PL_DHASH_NEXT;
    3410                 : }
    3411                 : 
    3412                 : Element*
    3413               0 : nsDocument::FindContentForSubDocument(nsIDocument *aDocument) const
    3414                 : {
    3415               0 :   NS_ENSURE_TRUE(aDocument, nsnull);
    3416                 : 
    3417               0 :   if (!mSubDocuments) {
    3418               0 :     return nsnull;
    3419                 :   }
    3420                 : 
    3421               0 :   FindContentData data(aDocument);
    3422               0 :   PL_DHashTableEnumerate(mSubDocuments, FindContentEnumerator, &data);
    3423                 : 
    3424               0 :   return data.mResult;
    3425                 : }
    3426                 : 
    3427                 : bool
    3428           12632 : nsDocument::IsNodeOfType(PRUint32 aFlags) const
    3429                 : {
    3430           12632 :     return !(aFlags & ~eDOCUMENT);
    3431                 : }
    3432                 : 
    3433                 : PRUint16
    3434               0 : nsDocument::NodeType()
    3435                 : {
    3436               0 :     return (PRUint16)nsIDOMNode::DOCUMENT_NODE;
    3437                 : }
    3438                 : 
    3439                 : void
    3440               0 : nsDocument::NodeName(nsAString& aNodeName)
    3441                 : {
    3442               0 :   aNodeName.AssignLiteral("#document");
    3443               0 : }
    3444                 : 
    3445                 : Element*
    3446            5482 : nsIDocument::GetRootElement() const
    3447                 : {
    3448            3160 :   return (mCachedRootElement && mCachedRootElement->GetNodeParent() == this) ?
    3449            8642 :          mCachedRootElement : GetRootElementInternal();
    3450                 : }
    3451                 : 
    3452                 : Element*
    3453            2322 : nsDocument::GetRootElementInternal() const
    3454                 : {
    3455                 :   // Loop backwards because any non-elements, such as doctypes and PIs
    3456                 :   // are likely to appear before the root element.
    3457                 :   PRUint32 i;
    3458            2424 :   for (i = mChildren.ChildCount(); i > 0; --i) {
    3459            1140 :     nsIContent* child = mChildren.ChildAt(i - 1);
    3460            1140 :     if (child->IsElement()) {
    3461            1038 :       const_cast<nsDocument*>(this)->mCachedRootElement = child->AsElement();
    3462            1038 :       return child->AsElement();
    3463                 :     }
    3464                 :   }
    3465                 :   
    3466            1284 :   const_cast<nsDocument*>(this)->mCachedRootElement = nsnull;
    3467            1284 :   return nsnull;
    3468                 : }
    3469                 : 
    3470                 : nsIContent *
    3471              56 : nsDocument::GetChildAt(PRUint32 aIndex) const
    3472                 : {
    3473              56 :   return mChildren.GetSafeChildAt(aIndex);
    3474                 : }
    3475                 : 
    3476                 : PRInt32
    3477              21 : nsDocument::IndexOf(nsINode* aPossibleChild) const
    3478                 : {
    3479              21 :   return mChildren.IndexOfChild(aPossibleChild);
    3480                 : }
    3481                 : 
    3482                 : PRUint32
    3483            1754 : nsDocument::GetChildCount() const
    3484                 : {
    3485            1754 :   return mChildren.ChildCount();
    3486                 : }
    3487                 : 
    3488                 : nsIContent * const *
    3489              72 : nsDocument::GetChildArray(PRUint32* aChildCount) const
    3490                 : {
    3491              72 :   return mChildren.GetChildArray(aChildCount);
    3492                 : }
    3493                 :   
    3494                 : 
    3495                 : nsresult
    3496            1385 : nsDocument::InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
    3497                 :                           bool aNotify)
    3498                 : {
    3499            1385 :   if (aKid->IsElement() && GetRootElement()) {
    3500               0 :     NS_ERROR("Inserting element child when we already have one");
    3501               0 :     return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
    3502                 :   }
    3503                 : 
    3504            1385 :   return doInsertChildAt(aKid, aIndex, aNotify, mChildren);
    3505                 : }
    3506                 : 
    3507                 : nsresult
    3508               0 : nsDocument::AppendChildTo(nsIContent* aKid, bool aNotify)
    3509                 : {
    3510                 :   // Make sure to _not_ call the subclass InsertChildAt here.  If
    3511                 :   // subclasses wanted to hook into this stuff, they would have
    3512                 :   // overridden AppendChildTo.
    3513                 :   // XXXbz maybe this should just be a non-virtual method on nsINode?
    3514                 :   // Feels that way to me...
    3515               0 :   return nsDocument::InsertChildAt(aKid, GetChildCount(), aNotify);
    3516                 : }
    3517                 : 
    3518                 : nsresult
    3519              10 : nsDocument::RemoveChildAt(PRUint32 aIndex, bool aNotify)
    3520                 : {
    3521              20 :   nsCOMPtr<nsIContent> oldKid = GetChildAt(aIndex);
    3522              10 :   if (!oldKid) {
    3523               0 :     return NS_OK;
    3524                 :   }
    3525                 : 
    3526              10 :   if (oldKid->IsElement()) {
    3527                 :     // Destroy the link map up front before we mess with the child list.
    3528              10 :     DestroyElementMaps();
    3529                 :   }
    3530                 : 
    3531                 :   nsresult rv =
    3532              10 :     doRemoveChildAt(aIndex, aNotify, oldKid, mChildren);
    3533              10 :   mCachedRootElement = nsnull;
    3534              10 :   return rv;
    3535                 : }
    3536                 : 
    3537                 : PRInt32
    3538               0 : nsDocument::GetNumberOfStyleSheets() const
    3539                 : {
    3540               0 :   return mStyleSheets.Count();
    3541                 : }
    3542                 : 
    3543                 : nsIStyleSheet*
    3544               0 : nsDocument::GetStyleSheetAt(PRInt32 aIndex) const
    3545                 : {
    3546               0 :   NS_ENSURE_TRUE(0 <= aIndex && aIndex < mStyleSheets.Count(), nsnull);
    3547               0 :   return mStyleSheets[aIndex];
    3548                 : }
    3549                 : 
    3550                 : PRInt32
    3551               0 : nsDocument::GetIndexOfStyleSheet(nsIStyleSheet* aSheet) const
    3552                 : {
    3553               0 :   return mStyleSheets.IndexOf(aSheet);
    3554                 : }
    3555                 : 
    3556                 : void
    3557               0 : nsDocument::AddStyleSheetToStyleSets(nsIStyleSheet* aSheet)
    3558                 : {
    3559               0 :   nsCOMPtr<nsIPresShell> shell = GetShell();
    3560               0 :   if (shell) {
    3561               0 :     shell->StyleSet()->AddDocStyleSheet(aSheet, this);
    3562                 :   }
    3563               0 : }
    3564                 : 
    3565                 : void
    3566               0 : nsDocument::AddStyleSheet(nsIStyleSheet* aSheet)
    3567                 : {
    3568               0 :   NS_PRECONDITION(aSheet, "null arg");
    3569               0 :   mStyleSheets.AppendObject(aSheet);
    3570               0 :   aSheet->SetOwningDocument(this);
    3571                 : 
    3572               0 :   if (aSheet->IsApplicable()) {
    3573               0 :     AddStyleSheetToStyleSets(aSheet);
    3574                 :   }
    3575                 : 
    3576               0 :   NS_DOCUMENT_NOTIFY_OBSERVERS(StyleSheetAdded, (this, aSheet, true));
    3577               0 : }
    3578                 : 
    3579                 : void
    3580               0 : nsDocument::RemoveStyleSheetFromStyleSets(nsIStyleSheet* aSheet)
    3581                 : {
    3582               0 :   nsCOMPtr<nsIPresShell> shell = GetShell();
    3583               0 :   if (shell) {
    3584               0 :     shell->StyleSet()->RemoveStyleSheet(nsStyleSet::eDocSheet, aSheet);
    3585                 :   }
    3586               0 : }
    3587                 : 
    3588                 : void
    3589               0 : nsDocument::RemoveStyleSheet(nsIStyleSheet* aSheet)
    3590                 : {
    3591               0 :   NS_PRECONDITION(aSheet, "null arg");
    3592               0 :   nsCOMPtr<nsIStyleSheet> sheet = aSheet; // hold ref so it won't die too soon
    3593                 : 
    3594               0 :   if (!mStyleSheets.RemoveObject(aSheet)) {
    3595               0 :     NS_NOTREACHED("stylesheet not found");
    3596                 :     return;
    3597                 :   }
    3598                 : 
    3599               0 :   if (!mIsGoingAway) {
    3600               0 :     if (aSheet->IsApplicable()) {
    3601               0 :       RemoveStyleSheetFromStyleSets(aSheet);
    3602                 :     }
    3603                 : 
    3604               0 :     NS_DOCUMENT_NOTIFY_OBSERVERS(StyleSheetRemoved, (this, aSheet, true));
    3605                 :   }
    3606                 : 
    3607               0 :   aSheet->SetOwningDocument(nsnull);
    3608                 : }
    3609                 : 
    3610                 : void
    3611               0 : nsDocument::UpdateStyleSheets(nsCOMArray<nsIStyleSheet>& aOldSheets,
    3612                 :                               nsCOMArray<nsIStyleSheet>& aNewSheets)
    3613                 : {
    3614               0 :   BeginUpdate(UPDATE_STYLE);
    3615                 : 
    3616                 :   // XXX Need to set the sheet on the ownernode, if any
    3617               0 :   NS_PRECONDITION(aOldSheets.Count() == aNewSheets.Count(),
    3618                 :                   "The lists must be the same length!");
    3619               0 :   PRInt32 count = aOldSheets.Count();
    3620                 : 
    3621               0 :   nsCOMPtr<nsIStyleSheet> oldSheet;
    3622                 :   PRInt32 i;
    3623               0 :   for (i = 0; i < count; ++i) {
    3624               0 :     oldSheet = aOldSheets[i];
    3625                 : 
    3626                 :     // First remove the old sheet.
    3627               0 :     NS_ASSERTION(oldSheet, "None of the old sheets should be null");
    3628               0 :     PRInt32 oldIndex = mStyleSheets.IndexOf(oldSheet);
    3629               0 :     RemoveStyleSheet(oldSheet);  // This does the right notifications
    3630                 : 
    3631                 :     // Now put the new one in its place.  If it's null, just ignore it.
    3632               0 :     nsIStyleSheet* newSheet = aNewSheets[i];
    3633               0 :     if (newSheet) {
    3634               0 :       mStyleSheets.InsertObjectAt(newSheet, oldIndex);
    3635               0 :       newSheet->SetOwningDocument(this);
    3636               0 :       if (newSheet->IsApplicable()) {
    3637               0 :         AddStyleSheetToStyleSets(newSheet);
    3638                 :       }
    3639                 : 
    3640               0 :       NS_DOCUMENT_NOTIFY_OBSERVERS(StyleSheetAdded, (this, newSheet, true));
    3641                 :     }
    3642                 :   }
    3643                 : 
    3644               0 :   EndUpdate(UPDATE_STYLE);
    3645               0 : }
    3646                 : 
    3647                 : void
    3648               0 : nsDocument::InsertStyleSheetAt(nsIStyleSheet* aSheet, PRInt32 aIndex)
    3649                 : {
    3650               0 :   NS_PRECONDITION(aSheet, "null ptr");
    3651               0 :   mStyleSheets.InsertObjectAt(aSheet, aIndex);
    3652                 : 
    3653               0 :   aSheet->SetOwningDocument(this);
    3654                 : 
    3655               0 :   if (aSheet->IsApplicable()) {
    3656               0 :     AddStyleSheetToStyleSets(aSheet);
    3657                 :   }
    3658                 : 
    3659               0 :   NS_DOCUMENT_NOTIFY_OBSERVERS(StyleSheetAdded, (this, aSheet, true));
    3660               0 : }
    3661                 : 
    3662                 : 
    3663                 : void
    3664               0 : nsDocument::SetStyleSheetApplicableState(nsIStyleSheet* aSheet,
    3665                 :                                          bool aApplicable)
    3666                 : {
    3667               0 :   NS_PRECONDITION(aSheet, "null arg");
    3668                 : 
    3669                 :   // If we're actually in the document style sheet list
    3670               0 :   if (-1 != mStyleSheets.IndexOf(aSheet)) {
    3671               0 :     if (aApplicable) {
    3672               0 :       AddStyleSheetToStyleSets(aSheet);
    3673                 :     } else {
    3674               0 :       RemoveStyleSheetFromStyleSets(aSheet);
    3675                 :     }
    3676                 :   }
    3677                 : 
    3678                 :   // We have to always notify, since this will be called for sheets
    3679                 :   // that are children of sheets in our style set, as well as some
    3680                 :   // sheets for nsHTMLEditor.
    3681                 : 
    3682               0 :   NS_DOCUMENT_NOTIFY_OBSERVERS(StyleSheetApplicableStateChanged,
    3683                 :                                (this, aSheet, aApplicable));
    3684               0 : }
    3685                 : 
    3686                 : // These three functions are a lot like the implementation of the
    3687                 : // corresponding API for regular stylesheets.
    3688                 : 
    3689                 : PRInt32
    3690               0 : nsDocument::GetNumberOfCatalogStyleSheets() const
    3691                 : {
    3692               0 :   return mCatalogSheets.Count();
    3693                 : }
    3694                 : 
    3695                 : nsIStyleSheet*
    3696               0 : nsDocument::GetCatalogStyleSheetAt(PRInt32 aIndex) const
    3697                 : {
    3698               0 :   NS_ENSURE_TRUE(0 <= aIndex && aIndex < mCatalogSheets.Count(), nsnull);
    3699               0 :   return mCatalogSheets[aIndex];
    3700                 : }
    3701                 : 
    3702                 : void
    3703               0 : nsDocument::AddCatalogStyleSheet(nsIStyleSheet* aSheet)
    3704                 : {
    3705               0 :   mCatalogSheets.AppendObject(aSheet);
    3706               0 :   aSheet->SetOwningDocument(this);
    3707                 : 
    3708               0 :   if (aSheet->IsApplicable()) {
    3709                 :     // This is like |AddStyleSheetToStyleSets|, but for an agent sheet.
    3710               0 :     nsCOMPtr<nsIPresShell> shell = GetShell();
    3711               0 :     if (shell) {
    3712               0 :       shell->StyleSet()->AppendStyleSheet(nsStyleSet::eAgentSheet, aSheet);
    3713                 :     }
    3714                 :   }
    3715                 :                                                                                 
    3716               0 :   NS_DOCUMENT_NOTIFY_OBSERVERS(StyleSheetAdded, (this, aSheet, false));
    3717               0 : }
    3718                 : 
    3719                 : void
    3720               0 : nsDocument::EnsureCatalogStyleSheet(const char *aStyleSheetURI)
    3721                 : {
    3722               0 :   mozilla::css::Loader* cssLoader = CSSLoader();
    3723               0 :   if (cssLoader->GetEnabled()) {
    3724               0 :     PRInt32 sheetCount = GetNumberOfCatalogStyleSheets();
    3725               0 :     for (PRInt32 i = 0; i < sheetCount; i++) {
    3726               0 :       nsIStyleSheet* sheet = GetCatalogStyleSheetAt(i);
    3727               0 :       NS_ASSERTION(sheet, "unexpected null stylesheet in the document");
    3728               0 :       if (sheet) {
    3729               0 :         nsCAutoString uriStr;
    3730               0 :         sheet->GetSheetURI()->GetSpec(uriStr);
    3731               0 :         if (uriStr.Equals(aStyleSheetURI))
    3732                 :           return;
    3733                 :       }
    3734                 :     }
    3735                 : 
    3736               0 :     nsCOMPtr<nsIURI> uri;
    3737               0 :     NS_NewURI(getter_AddRefs(uri), aStyleSheetURI);
    3738               0 :     if (uri) {
    3739               0 :       nsRefPtr<nsCSSStyleSheet> sheet;
    3740               0 :       cssLoader->LoadSheetSync(uri, true, true, getter_AddRefs(sheet));
    3741               0 :       if (sheet) {
    3742               0 :         BeginUpdate(UPDATE_STYLE);
    3743               0 :         AddCatalogStyleSheet(sheet);
    3744               0 :         EndUpdate(UPDATE_STYLE);
    3745                 :       }
    3746                 :     }
    3747                 :   }
    3748                 : }
    3749                 : 
    3750                 : nsIScriptGlobalObject*
    3751            8450 : nsDocument::GetScriptGlobalObject() const
    3752                 : {
    3753                 :    // If we're going away, we've already released the reference to our
    3754                 :    // ScriptGlobalObject.  We can, however, try to obtain it for the
    3755                 :    // caller through our docshell.
    3756                 : 
    3757                 :    // We actually need to start returning the docshell's script global
    3758                 :    // object as soon as nsDocumentViewer::Close has called
    3759                 :    // RemovedFromDocShell on us.
    3760            8450 :    if (mRemovedFromDocShell) {
    3761                 :      nsCOMPtr<nsIInterfaceRequestor> requestor =
    3762               0 :        do_QueryReferent(mDocumentContainer);
    3763               0 :      if (requestor) {
    3764               0 :        nsCOMPtr<nsIScriptGlobalObject> globalObject = do_GetInterface(requestor);
    3765               0 :        return globalObject;
    3766                 :      }
    3767                 :    }
    3768                 : 
    3769            8450 :    return mScriptGlobalObject;
    3770                 : }
    3771                 : 
    3772                 : nsIScriptGlobalObject*
    3773            1924 : nsDocument::GetScopeObject()
    3774                 : {
    3775            3848 :   nsCOMPtr<nsIScriptGlobalObject> scope(do_QueryReferent(mScopeObject));
    3776            1924 :   return scope;
    3777                 : }
    3778                 : 
    3779                 : static void
    3780               0 : NotifyActivityChanged(nsIContent *aContent, void *aUnused)
    3781                 : {
    3782                 : #ifdef MOZ_MEDIA
    3783               0 :   nsCOMPtr<nsIDOMHTMLMediaElement> domMediaElem(do_QueryInterface(aContent));
    3784               0 :   if (domMediaElem) {
    3785               0 :     nsHTMLMediaElement* mediaElem = static_cast<nsHTMLMediaElement*>(aContent);
    3786               0 :     mediaElem->NotifyOwnerDocumentActivityChanged();
    3787                 :   }
    3788                 : #endif
    3789               0 :   nsCOMPtr<nsIObjectLoadingContent> objectLoadingContent(do_QueryInterface(aContent));
    3790               0 :   if (objectLoadingContent) {
    3791               0 :     nsObjectLoadingContent* olc = static_cast<nsObjectLoadingContent*>(objectLoadingContent.get());
    3792               0 :     olc->NotifyOwnerDocumentActivityChanged();
    3793                 :   }
    3794               0 : }
    3795                 : 
    3796                 : void
    3797               0 : nsIDocument::SetContainer(nsISupports* aContainer)
    3798                 : {
    3799               0 :   mDocumentContainer = do_GetWeakReference(aContainer);
    3800               0 :   EnumerateFreezableElements(NotifyActivityChanged, nsnull);
    3801               0 : }
    3802                 : 
    3803                 : void
    3804               0 : nsDocument::SetScriptGlobalObject(nsIScriptGlobalObject *aScriptGlobalObject)
    3805                 : {
    3806                 : #ifdef DEBUG
    3807                 :   {
    3808               0 :     nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(aScriptGlobalObject));
    3809                 : 
    3810               0 :     NS_ASSERTION(!win || win->IsInnerWindow(),
    3811                 :                  "Script global object must be an inner window!");
    3812                 :   }
    3813                 : #endif
    3814               0 :   NS_ABORT_IF_FALSE(aScriptGlobalObject || !mAnimationController ||
    3815                 :                     mAnimationController->IsPausedByType(
    3816                 :                         nsSMILTimeContainer::PAUSE_PAGEHIDE |
    3817                 :                         nsSMILTimeContainer::PAUSE_BEGIN),
    3818                 :                     "Clearing window pointer while animations are unpaused");
    3819                 : 
    3820               0 :   if (mScriptGlobalObject && !aScriptGlobalObject) {
    3821                 :     // We're detaching from the window.  We need to grab a pointer to
    3822                 :     // our layout history state now.
    3823               0 :     mLayoutHistoryState = GetLayoutHistoryState();
    3824                 : 
    3825               0 :     if (mPresShell && !EventHandlingSuppressed()) {
    3826               0 :       RevokeAnimationFrameNotifications();
    3827                 :     }
    3828                 : 
    3829                 :     // Also make sure to remove our onload blocker now if we haven't done it yet
    3830               0 :     if (mOnloadBlockCount != 0) {
    3831               0 :       nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
    3832               0 :       if (loadGroup) {
    3833               0 :         loadGroup->RemoveRequest(mOnloadBlocker, nsnull, NS_OK);
    3834                 :       }
    3835                 :     }
    3836                 :   }
    3837                 : 
    3838               0 :   mScriptGlobalObject = aScriptGlobalObject;
    3839                 : 
    3840               0 :   if (aScriptGlobalObject) {
    3841               0 :     mScriptObject = nsnull;
    3842               0 :     mHasHadScriptHandlingObject = true;
    3843                 :     // Go back to using the docshell for the layout history state
    3844               0 :     mLayoutHistoryState = nsnull;
    3845               0 :     mScopeObject = do_GetWeakReference(aScriptGlobalObject);
    3846                 : 
    3847                 : #ifdef DEBUG
    3848               0 :     if (!mWillReparent) {
    3849                 :       // We really shouldn't have a wrapper here but if we do we need to make sure
    3850                 :       // it has the correct parent.
    3851               0 :       JSObject *obj = GetWrapperPreserveColor();
    3852               0 :       if (obj) {
    3853               0 :         JSObject *newScope = aScriptGlobalObject->GetGlobalJSObject();
    3854               0 :         nsIScriptContext *scx = aScriptGlobalObject->GetContext();
    3855               0 :         JSContext *cx = scx ? scx->GetNativeContext() : nsnull;
    3856               0 :         if (!cx) {
    3857               0 :           nsContentUtils::ThreadJSContextStack()->Peek(&cx);
    3858               0 :           if (!cx) {
    3859               0 :             nsContentUtils::ThreadJSContextStack()->GetSafeJSContext(&cx);
    3860               0 :             NS_ASSERTION(cx, "Uhoh, no context, this is bad!");
    3861                 :           }
    3862                 :         }
    3863               0 :         if (cx) {
    3864               0 :           NS_ASSERTION(JS_GetGlobalForObject(cx, obj) == newScope,
    3865                 :                        "Wrong scope, this is really bad!");
    3866                 :         }
    3867                 :       }
    3868                 :     }
    3869                 : #endif
    3870                 : 
    3871               0 :     if (mAllowDNSPrefetch) {
    3872               0 :       nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocumentContainer);
    3873               0 :       if (docShell) {
    3874                 : #ifdef DEBUG
    3875                 :         nsCOMPtr<nsIWebNavigation> webNav =
    3876               0 :           do_GetInterface(aScriptGlobalObject);
    3877               0 :         NS_ASSERTION(SameCOMIdentity(webNav, docShell),
    3878                 :                      "Unexpected container or script global?");
    3879                 : #endif
    3880                 :         bool allowDNSPrefetch;
    3881               0 :         docShell->GetAllowDNSPrefetch(&allowDNSPrefetch);
    3882               0 :         mAllowDNSPrefetch = allowDNSPrefetch;
    3883                 :       }
    3884                 :     }
    3885                 : 
    3886               0 :     MaybeRescheduleAnimationFrameNotifications();
    3887                 :   }
    3888                 : 
    3889                 :   // Remember the pointer to our window (or lack there of), to avoid
    3890                 :   // having to QI every time it's asked for.
    3891               0 :   nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(mScriptGlobalObject);
    3892               0 :   mWindow = window;
    3893                 : 
    3894                 :   // Set our visibility state, but do not fire the event.  This is correct
    3895                 :   // because either we're coming out of bfcache (in which case IsVisible() will
    3896                 :   // still test false at this point and no state change will happen) or we're
    3897                 :   // doing the initial document load and don't want to fire the event for this
    3898                 :   // change.
    3899               0 :   mVisibilityState = GetVisibilityState();
    3900               0 : }
    3901                 : 
    3902                 : nsIScriptGlobalObject*
    3903           18124 : nsDocument::GetScriptHandlingObjectInternal() const
    3904                 : {
    3905           18124 :   NS_ASSERTION(!mScriptGlobalObject,
    3906                 :                "Do not call this when mScriptGlobalObject is set!");
    3907                 : 
    3908                 :   nsCOMPtr<nsIScriptGlobalObject> scriptHandlingObject =
    3909           36248 :     do_QueryReferent(mScriptObject);
    3910           36248 :   nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(scriptHandlingObject);
    3911           18124 :   if (win) {
    3912               0 :     NS_ASSERTION(win->IsInnerWindow(), "Should have inner window here!");
    3913               0 :     nsPIDOMWindow* outer = win->GetOuterWindow();
    3914               0 :     if (!outer || outer->GetCurrentInnerWindow() != win) {
    3915               0 :       NS_WARNING("Wrong inner/outer window combination!");
    3916               0 :       return nsnull;
    3917                 :     }
    3918                 :   }
    3919           18124 :   return scriptHandlingObject;
    3920                 : }
    3921                 : void
    3922            1273 : nsDocument::SetScriptHandlingObject(nsIScriptGlobalObject* aScriptObject)
    3923                 : {
    3924            1273 :   NS_ASSERTION(!mScriptGlobalObject ||
    3925                 :                mScriptGlobalObject == aScriptObject,
    3926                 :                "Wrong script object!");
    3927            2546 :   nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(aScriptObject);
    3928            1273 :   NS_ASSERTION(!win || win->IsInnerWindow(), "Should have inner window here!");
    3929            1273 :   mScopeObject = mScriptObject = do_GetWeakReference(aScriptObject);
    3930            1273 :   if (aScriptObject) {
    3931               0 :     mHasHadScriptHandlingObject = true;
    3932                 :   }
    3933            1273 : }
    3934                 : 
    3935                 : nsPIDOMWindow *
    3936            7456 : nsDocument::GetWindowInternal() const
    3937                 : {
    3938            7456 :   NS_ASSERTION(!mWindow, "This should not be called when mWindow is not null!");
    3939                 : 
    3940           14912 :   nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(GetScriptGlobalObject()));
    3941                 : 
    3942            7456 :   if (!win) {
    3943            7456 :     return nsnull;
    3944                 :   }
    3945                 : 
    3946               0 :   return win->GetOuterWindow();
    3947                 : }
    3948                 : 
    3949                 : nsPIDOMWindow *
    3950               0 : nsDocument::GetInnerWindowInternal()
    3951                 : {
    3952               0 :   NS_ASSERTION(mRemovedFromDocShell,
    3953                 :                "This document should have been removed from docshell!");
    3954                 : 
    3955               0 :   nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(GetScriptGlobalObject()));
    3956                 : 
    3957               0 :   return win;
    3958                 : }
    3959                 : 
    3960                 : nsScriptLoader*
    3961            2311 : nsDocument::ScriptLoader()
    3962                 : {
    3963            2311 :   return mScriptLoader;
    3964                 : }
    3965                 : 
    3966                 : bool
    3967               0 : nsDocument::InternalAllowXULXBL()
    3968                 : {
    3969               0 :   if (nsContentUtils::AllowXULXBLForPrincipal(NodePrincipal())) {
    3970               0 :     mAllowXULXBL = eTriTrue;
    3971               0 :     return true;
    3972                 :   }
    3973                 : 
    3974               0 :   mAllowXULXBL = eTriFalse;
    3975               0 :   return false;
    3976                 : }
    3977                 : 
    3978                 : // Note: We don't hold a reference to the document observer; we assume
    3979                 : // that it has a live reference to the document.
    3980                 : void
    3981            1038 : nsDocument::AddObserver(nsIDocumentObserver* aObserver)
    3982                 : {
    3983            1038 :   NS_ASSERTION(mObservers.IndexOf(aObserver) == nsTArray<int>::NoIndex,
    3984                 :                "Observer already in the list");
    3985            1038 :   mObservers.AppendElement(aObserver);
    3986            1038 :   AddMutationObserver(aObserver);
    3987            1038 : }
    3988                 : 
    3989                 : bool
    3990            2138 : nsDocument::RemoveObserver(nsIDocumentObserver* aObserver)
    3991                 : {
    3992                 :   // If we're in the process of destroying the document (and we're
    3993                 :   // informing the observers of the destruction), don't remove the
    3994                 :   // observers from the list. This is not a big deal, since we
    3995                 :   // don't hold a live reference to the observers.
    3996            2138 :   if (!mInDestructor) {
    3997            2138 :     RemoveMutationObserver(aObserver);
    3998            2138 :     return mObservers.RemoveElement(aObserver);
    3999                 :   }
    4000                 : 
    4001               0 :   return mObservers.Contains(aObserver);
    4002                 : }
    4003                 : 
    4004                 : void
    4005            6283 : nsDocument::MaybeEndOutermostXBLUpdate()
    4006                 : {
    4007                 :   // Only call BindingManager()->EndOutermostUpdate() when
    4008                 :   // we're not in an update and it is safe to run scripts.
    4009            6283 :   if (mUpdateNestLevel == 0 && mInXBLUpdate) {
    4010            4958 :     if (nsContentUtils::IsSafeToRunScript()) {
    4011            4890 :       mInXBLUpdate = false;
    4012            4890 :       BindingManager()->EndOutermostUpdate();
    4013              68 :     } else if (!mInDestructor) {
    4014                 :       nsContentUtils::AddScriptRunner(
    4015              68 :         NS_NewRunnableMethod(this, &nsDocument::MaybeEndOutermostXBLUpdate));
    4016                 :     }
    4017                 :   }
    4018            6283 : }
    4019                 : 
    4020                 : void
    4021            6215 : nsDocument::BeginUpdate(nsUpdateType aUpdateType)
    4022                 : {
    4023            6215 :   if (mUpdateNestLevel == 0 && !mInXBLUpdate) {
    4024            4890 :     mInXBLUpdate = true;
    4025            4890 :     BindingManager()->BeginOutermostUpdate();
    4026                 :   }
    4027                 :   
    4028            6215 :   ++mUpdateNestLevel;
    4029            6215 :   nsContentUtils::AddScriptBlocker();
    4030            6215 :   NS_DOCUMENT_NOTIFY_OBSERVERS(BeginUpdate, (this, aUpdateType));
    4031            6215 : }
    4032                 : 
    4033                 : void
    4034            6215 : nsDocument::EndUpdate(nsUpdateType aUpdateType)
    4035                 : {
    4036            6215 :   NS_DOCUMENT_NOTIFY_OBSERVERS(EndUpdate, (this, aUpdateType));
    4037                 : 
    4038            6215 :   nsContentUtils::RemoveScriptBlocker();
    4039                 : 
    4040            6215 :   --mUpdateNestLevel;
    4041                 : 
    4042                 :   // This set of updates may have created XBL bindings.  Let the
    4043                 :   // binding manager know we're done.
    4044            6215 :   MaybeEndOutermostXBLUpdate();
    4045                 : 
    4046            6215 :   MaybeInitializeFinalizeFrameLoaders();
    4047            6215 : }
    4048                 : 
    4049                 : void
    4050            1038 : nsDocument::BeginLoad()
    4051                 : {
    4052                 :   // Block onload here to prevent having to deal with blocking and
    4053                 :   // unblocking it while we know the document is loading.
    4054            1038 :   BlockOnload();
    4055                 : 
    4056            1038 :   if (mScriptLoader) {
    4057            1038 :     mScriptLoader->BeginDeferringScripts();
    4058                 :   }
    4059                 : 
    4060            1038 :   NS_DOCUMENT_NOTIFY_OBSERVERS(BeginLoad, (this));
    4061            1038 : }
    4062                 : 
    4063                 : void
    4064               0 : nsDocument::ReportEmptyGetElementByIdArg()
    4065                 : {
    4066                 :   nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
    4067                 :                                   "DOM", this,
    4068                 :                                   nsContentUtils::eDOM_PROPERTIES,
    4069               0 :                                   "EmptyGetElementByIdParam");
    4070               0 : }
    4071                 : 
    4072                 : Element*
    4073              78 : nsDocument::GetElementById(const nsAString& aElementId)
    4074                 : {
    4075              78 :   if (!CheckGetElementByIdArg(aElementId)) {
    4076               0 :     return nsnull;
    4077                 :   }
    4078                 : 
    4079              78 :   nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(aElementId);
    4080              78 :   return entry ? entry->GetIdElement() : nsnull;
    4081                 : }
    4082                 : 
    4083                 : const nsSmallVoidArray*
    4084               0 : nsDocument::GetAllElementsForId(const nsAString& aElementId) const
    4085                 : {
    4086               0 :   if (aElementId.IsEmpty()) {
    4087               0 :     return nsnull;
    4088                 :   }
    4089                 : 
    4090               0 :   nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(aElementId);
    4091               0 :   return entry ? entry->GetIdElements() : nsnull;  
    4092                 : }
    4093                 : 
    4094                 : NS_IMETHODIMP
    4095               0 : nsDocument::GetElementById(const nsAString& aId, nsIDOMElement** aReturn)
    4096                 : {
    4097               0 :   Element *content = GetElementById(aId);
    4098               0 :   if (content) {
    4099               0 :     return CallQueryInterface(content, aReturn);
    4100                 :   }
    4101                 : 
    4102               0 :   *aReturn = nsnull;
    4103                 : 
    4104               0 :   return NS_OK;
    4105                 : }
    4106                 : 
    4107                 : Element*
    4108               0 : nsDocument::AddIDTargetObserver(nsIAtom* aID, IDTargetObserver aObserver,
    4109                 :                                 void* aData, bool aForImage)
    4110                 : {
    4111               0 :   nsDependentAtomString id(aID);
    4112                 : 
    4113               0 :   if (!CheckGetElementByIdArg(id))
    4114               0 :     return nsnull;
    4115                 : 
    4116               0 :   nsIdentifierMapEntry *entry = mIdentifierMap.PutEntry(id);
    4117               0 :   NS_ENSURE_TRUE(entry, nsnull);
    4118                 : 
    4119               0 :   entry->AddContentChangeCallback(aObserver, aData, aForImage);
    4120               0 :   return aForImage ? entry->GetImageIdElement() : entry->GetIdElement();
    4121                 : }
    4122                 : 
    4123                 : void
    4124               0 : nsDocument::RemoveIDTargetObserver(nsIAtom* aID, IDTargetObserver aObserver,
    4125                 :                                    void* aData, bool aForImage)
    4126                 : {
    4127               0 :   nsDependentAtomString id(aID);
    4128                 : 
    4129               0 :   if (!CheckGetElementByIdArg(id))
    4130                 :     return;
    4131                 : 
    4132               0 :   nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(id);
    4133               0 :   if (!entry) {
    4134                 :     return;
    4135                 :   }
    4136                 : 
    4137               0 :   entry->RemoveContentChangeCallback(aObserver, aData, aForImage);
    4138                 : }
    4139                 : 
    4140                 : NS_IMETHODIMP
    4141               0 : nsDocument::MozSetImageElement(const nsAString& aImageElementId,
    4142                 :                                nsIDOMElement* aImageElement)
    4143                 : {
    4144               0 :   if (aImageElementId.IsEmpty())
    4145               0 :     return NS_OK;
    4146                 : 
    4147                 :   // Hold a script blocker while calling SetImageElement since that can call
    4148                 :   // out to id-observers
    4149               0 :   nsAutoScriptBlocker scriptBlocker;
    4150                 : 
    4151               0 :   nsCOMPtr<nsIContent> content = do_QueryInterface(aImageElement);
    4152               0 :   nsIdentifierMapEntry *entry = mIdentifierMap.PutEntry(aImageElementId);
    4153               0 :   if (entry) {
    4154               0 :     entry->SetImageElement(content ? content->AsElement() : nsnull);
    4155               0 :     if (entry->IsEmpty()) {
    4156               0 :       mIdentifierMap.RemoveEntry(aImageElementId);
    4157                 :     }
    4158                 :   }
    4159               0 :   return NS_OK;
    4160                 : }
    4161                 : 
    4162                 : Element*
    4163               0 : nsDocument::LookupImageElement(const nsAString& aId)
    4164                 : {
    4165               0 :   if (aId.IsEmpty())
    4166               0 :     return nsnull;
    4167                 : 
    4168               0 :   nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(aId);
    4169               0 :   return entry ? entry->GetImageIdElement() : nsnull;
    4170                 : }
    4171                 : 
    4172                 : void
    4173            1038 : nsDocument::DispatchContentLoadedEvents()
    4174                 : {
    4175                 :   NS_TIME_FUNCTION;
    4176                 :   // If you add early returns from this method, make sure you're
    4177                 :   // calling UnblockOnload properly.
    4178                 :   
    4179                 :   // Unpin references to preloaded images
    4180            1038 :   mPreloadingImages.Clear();
    4181                 : 
    4182            1038 :   if (mTiming) {
    4183               0 :     mTiming->NotifyDOMContentLoadedStart(nsIDocument::GetDocumentURI());
    4184                 :   }
    4185                 :     
    4186                 :   // Fire a DOM event notifying listeners that this document has been
    4187                 :   // loaded (excluding images and other loads initiated by this
    4188                 :   // document).
    4189                 :   nsContentUtils::DispatchTrustedEvent(this, static_cast<nsIDocument*>(this),
    4190            1038 :                                        NS_LITERAL_STRING("DOMContentLoaded"),
    4191            1038 :                                        true, true);
    4192                 : 
    4193            1038 :   if (mTiming) {
    4194               0 :     mTiming->NotifyDOMContentLoadedEnd(nsIDocument::GetDocumentURI());
    4195                 :   }
    4196                 : 
    4197                 :   // If this document is a [i]frame, fire a DOMFrameContentLoaded
    4198                 :   // event on all parent documents notifying that the HTML (excluding
    4199                 :   // other external files such as images and stylesheets) in a frame
    4200                 :   // has finished loading.
    4201                 : 
    4202                 :   // target_frame is the [i]frame element that will be used as the
    4203                 :   // target for the event. It's the [i]frame whose content is done
    4204                 :   // loading.
    4205            2076 :   nsCOMPtr<nsIDOMEventTarget> target_frame;
    4206                 : 
    4207            1038 :   if (mParentDocument) {
    4208                 :     target_frame =
    4209               0 :       do_QueryInterface(mParentDocument->FindContentForSubDocument(this));
    4210                 :   }
    4211                 : 
    4212            1038 :   if (target_frame) {
    4213               0 :     nsCOMPtr<nsIDocument> parent = mParentDocument;
    4214               0 :     do {
    4215               0 :       nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(parent);
    4216                 : 
    4217               0 :       nsCOMPtr<nsIDOMEvent> event;
    4218               0 :       nsCOMPtr<nsIPrivateDOMEvent> privateEvent;
    4219               0 :       if (domDoc) {
    4220               0 :         domDoc->CreateEvent(NS_LITERAL_STRING("Events"),
    4221               0 :                             getter_AddRefs(event));
    4222                 : 
    4223               0 :         privateEvent = do_QueryInterface(event);
    4224                 :       }
    4225                 : 
    4226               0 :       if (event && privateEvent) {
    4227               0 :         event->InitEvent(NS_LITERAL_STRING("DOMFrameContentLoaded"), true,
    4228               0 :                          true);
    4229                 : 
    4230               0 :         privateEvent->SetTarget(target_frame);
    4231               0 :         privateEvent->SetTrusted(true);
    4232                 : 
    4233                 :         // To dispatch this event we must manually call
    4234                 :         // nsEventDispatcher::Dispatch() on the ancestor document since the
    4235                 :         // target is not in the same document, so the event would never reach
    4236                 :         // the ancestor document if we used the normal event
    4237                 :         // dispatching code.
    4238                 : 
    4239               0 :         nsEvent* innerEvent = privateEvent->GetInternalNSEvent();
    4240               0 :         if (innerEvent) {
    4241               0 :           nsEventStatus status = nsEventStatus_eIgnore;
    4242                 : 
    4243               0 :           nsIPresShell *shell = parent->GetShell();
    4244               0 :           if (shell) {
    4245               0 :             nsRefPtr<nsPresContext> context = shell->GetPresContext();
    4246                 : 
    4247               0 :             if (context) {
    4248                 :               nsEventDispatcher::Dispatch(parent, context, innerEvent, event,
    4249               0 :                                           &status);
    4250                 :             }
    4251                 :           }
    4252                 :         }
    4253                 :       }
    4254                 :       
    4255               0 :       parent = parent->GetParentDocument();
    4256               0 :     } while (parent);
    4257                 :   }
    4258                 : 
    4259                 :   // If the document has a manifest attribute, fire a MozApplicationManifest
    4260                 :   // event.
    4261            1038 :   Element* root = GetRootElement();
    4262            1038 :   if (root && root->HasAttr(kNameSpaceID_None, nsGkAtoms::manifest)) {
    4263                 :     nsContentUtils::DispatchChromeEvent(this, static_cast<nsIDocument*>(this),
    4264               0 :                                         NS_LITERAL_STRING("MozApplicationManifest"),
    4265               0 :                                         true, true);
    4266                 :   }
    4267                 : 
    4268            1038 :   UnblockOnload(true);
    4269            1038 : }
    4270                 : 
    4271                 : void
    4272            1038 : nsDocument::EndLoad()
    4273                 : {
    4274                 :   // Drop the ref to our parser, if any, but keep hold of the sink so that we
    4275                 :   // can flush it from FlushPendingNotifications as needed.  We might have to
    4276                 :   // do that to get a StartLayout() to happen.
    4277            1038 :   if (mParser) {
    4278            1038 :     mWeakSink = do_GetWeakReference(mParser->GetContentSink());
    4279            1038 :     mParser = nsnull;
    4280                 :   }
    4281                 :   
    4282            1038 :   NS_DOCUMENT_NOTIFY_OBSERVERS(EndLoad, (this));
    4283                 :   
    4284            1038 :   if (!mSynchronousDOMContentLoaded) {
    4285                 :     nsRefPtr<nsIRunnable> ev =
    4286               0 :       NS_NewRunnableMethod(this, &nsDocument::DispatchContentLoadedEvents);
    4287               0 :     NS_DispatchToCurrentThread(ev);
    4288                 :   } else {
    4289            1038 :     DispatchContentLoadedEvents();
    4290                 :   }
    4291            1038 : }
    4292                 : 
    4293                 : void
    4294               0 : nsDocument::ContentStateChanged(nsIContent* aContent, nsEventStates aStateMask)
    4295                 : {
    4296               0 :   NS_PRECONDITION(!nsContentUtils::IsSafeToRunScript(),
    4297                 :                   "Someone forgot a scriptblocker");
    4298               0 :   NS_DOCUMENT_NOTIFY_OBSERVERS(ContentStateChanged,
    4299                 :                                (this, aContent, aStateMask));
    4300               0 : }
    4301                 : 
    4302                 : void
    4303               0 : nsDocument::DocumentStatesChanged(nsEventStates aStateMask)
    4304                 : {
    4305                 :   // Invalidate our cached state.
    4306               0 :   mGotDocumentState &= ~aStateMask;
    4307               0 :   mDocumentState &= ~aStateMask;
    4308                 : 
    4309               0 :   NS_DOCUMENT_NOTIFY_OBSERVERS(DocumentStatesChanged, (this, aStateMask));
    4310               0 : }
    4311                 : 
    4312                 : void
    4313               0 : nsDocument::StyleRuleChanged(nsIStyleSheet* aStyleSheet,
    4314                 :                              nsIStyleRule* aOldStyleRule,
    4315                 :                              nsIStyleRule* aNewStyleRule)
    4316                 : {
    4317               0 :   NS_DOCUMENT_NOTIFY_OBSERVERS(StyleRuleChanged,
    4318                 :                                (this, aStyleSheet,
    4319                 :                                 aOldStyleRule, aNewStyleRule));
    4320               0 : }
    4321                 : 
    4322                 : void
    4323               0 : nsDocument::StyleRuleAdded(nsIStyleSheet* aStyleSheet,
    4324                 :                            nsIStyleRule* aStyleRule)
    4325                 : {
    4326               0 :   NS_DOCUMENT_NOTIFY_OBSERVERS(StyleRuleAdded,
    4327                 :                                (this, aStyleSheet, aStyleRule));
    4328               0 : }
    4329                 : 
    4330                 : void
    4331               0 : nsDocument::StyleRuleRemoved(nsIStyleSheet* aStyleSheet,
    4332                 :                              nsIStyleRule* aStyleRule)
    4333                 : {
    4334               0 :   NS_DOCUMENT_NOTIFY_OBSERVERS(StyleRuleRemoved,
    4335                 :                                (this, aStyleSheet, aStyleRule));
    4336               0 : }
    4337                 : 
    4338                 : 
    4339                 : //
    4340                 : // nsIDOMDocument interface
    4341                 : //
    4342                 : NS_IMETHODIMP
    4343               0 : nsDocument::GetDoctype(nsIDOMDocumentType** aDoctype)
    4344                 : {
    4345               0 :   NS_ENSURE_ARG_POINTER(aDoctype);
    4346                 : 
    4347               0 :   *aDoctype = nsnull;
    4348                 :   PRInt32 i, count;
    4349               0 :   count = mChildren.ChildCount();
    4350               0 :   for (i = 0; i < count; i++) {
    4351               0 :     CallQueryInterface(mChildren.ChildAt(i), aDoctype);
    4352                 : 
    4353               0 :     if (*aDoctype) {
    4354               0 :       return NS_OK;
    4355                 :     }
    4356                 :   }
    4357                 : 
    4358               0 :   return NS_OK;
    4359                 : }
    4360                 : 
    4361                 : NS_IMETHODIMP
    4362               2 : nsDocument::GetImplementation(nsIDOMDOMImplementation** aImplementation)
    4363                 : {
    4364               2 :   if (!mDOMImplementation) {
    4365               2 :     nsCOMPtr<nsIURI> uri;
    4366               1 :     NS_NewURI(getter_AddRefs(uri), "about:blank");
    4367               1 :     NS_ENSURE_TRUE(uri, NS_ERROR_OUT_OF_MEMORY);
    4368               1 :     bool hasHadScriptObject = true;
    4369                 :     nsIScriptGlobalObject* scriptObject =
    4370               1 :       GetScriptHandlingObject(hasHadScriptObject);
    4371               1 :     NS_ENSURE_STATE(scriptObject || !hasHadScriptObject);
    4372               2 :     mDOMImplementation = new nsDOMImplementation(this, scriptObject, uri, uri);
    4373               1 :     if (!mDOMImplementation) {
    4374               0 :       return NS_ERROR_OUT_OF_MEMORY;
    4375                 :     }
    4376                 :   }
    4377                 : 
    4378               2 :   NS_ADDREF(*aImplementation = mDOMImplementation);
    4379                 : 
    4380               2 :   return NS_OK;
    4381                 : }
    4382                 : 
    4383                 : NS_IMETHODIMP
    4384            2121 : nsDocument::GetDocumentElement(nsIDOMElement** aDocumentElement)
    4385                 : {
    4386            2121 :   NS_ENSURE_ARG_POINTER(aDocumentElement);
    4387                 : 
    4388            2121 :   Element* root = GetRootElement();
    4389            2121 :   if (root) {
    4390            2121 :     return CallQueryInterface(root, aDocumentElement);
    4391                 :   }
    4392                 : 
    4393               0 :   *aDocumentElement = nsnull;
    4394                 : 
    4395               0 :   return NS_OK;
    4396                 : }
    4397                 : 
    4398                 : NS_IMETHODIMP
    4399               0 : nsDocument::CreateElement(const nsAString& aTagName,
    4400                 :                           nsIDOMElement** aReturn)
    4401                 : {
    4402               0 :   *aReturn = nsnull;
    4403               0 :   nsCOMPtr<nsIContent> content;
    4404               0 :   nsresult rv = CreateElement(aTagName, getter_AddRefs(content));
    4405               0 :   NS_ENSURE_SUCCESS(rv, rv);
    4406               0 :   return CallQueryInterface(content, aReturn);
    4407                 : }
    4408                 : 
    4409               0 : bool IsLowercaseASCII(const nsAString& aValue)
    4410                 : {
    4411               0 :   PRInt32 len = aValue.Length();
    4412               0 :   for (PRInt32 i = 0; i < len; ++i) {
    4413               0 :     PRUnichar c = aValue[i];
    4414               0 :     if (!(0x0061 <= (c) && ((c) <= 0x007a))) {
    4415               0 :       return false;
    4416                 :     }
    4417                 :   }
    4418               0 :   return true;
    4419                 : }
    4420                 : 
    4421                 : nsresult
    4422               8 : nsDocument::CreateElement(const nsAString& aTagName,
    4423                 :                           nsIContent** aReturn)
    4424                 : {
    4425               8 :   *aReturn = nsnull;
    4426                 : 
    4427               8 :   nsresult rv = nsContentUtils::CheckQName(aTagName, false);
    4428               8 :   NS_ENSURE_SUCCESS(rv, rv);
    4429                 : 
    4430               8 :   bool needsLowercase = IsHTML() && !IsLowercaseASCII(aTagName);
    4431              16 :   nsAutoString lcTagName;
    4432               8 :   if (needsLowercase) {
    4433               0 :     nsContentUtils::ASCIIToLower(aTagName, lcTagName);
    4434                 :   }
    4435                 : 
    4436                 :   rv = CreateElem(needsLowercase ? lcTagName : aTagName,
    4437               8 :                   nsnull, mDefaultElementType, aReturn);
    4438               8 :   return rv;
    4439                 : }
    4440                 : 
    4441                 : NS_IMETHODIMP
    4442               1 : nsDocument::CreateElementNS(const nsAString& aNamespaceURI,
    4443                 :                             const nsAString& aQualifiedName,
    4444                 :                             nsIDOMElement** aReturn)
    4445                 : {
    4446               1 :   *aReturn = nsnull;
    4447               2 :   nsCOMPtr<nsIContent> content;
    4448                 :   nsresult rv = CreateElementNS(aNamespaceURI, aQualifiedName,
    4449               1 :                                 getter_AddRefs(content));
    4450               1 :   NS_ENSURE_SUCCESS(rv, rv);
    4451               1 :   return CallQueryInterface(content, aReturn);
    4452                 : }
    4453                 : 
    4454                 : nsresult
    4455             166 : nsDocument::CreateElementNS(const nsAString& aNamespaceURI,
    4456                 :                             const nsAString& aQualifiedName,
    4457                 :                             nsIContent** aReturn)
    4458                 : {
    4459             332 :   nsCOMPtr<nsINodeInfo> nodeInfo;
    4460                 :   nsresult rv = nsContentUtils::GetNodeInfoFromQName(aNamespaceURI,
    4461                 :                                                      aQualifiedName,
    4462                 :                                                      mNodeInfoManager,
    4463                 :                                                      nsIDOMNode::ELEMENT_NODE,
    4464             166 :                                                      getter_AddRefs(nodeInfo));
    4465             166 :   NS_ENSURE_SUCCESS(rv, rv);
    4466                 : 
    4467             166 :   return NS_NewElement(aReturn, nodeInfo.forget(), NOT_FROM_PARSER);
    4468                 : }
    4469                 : 
    4470                 : NS_IMETHODIMP
    4471               0 : nsDocument::CreateTextNode(const nsAString& aData, nsIDOMText** aReturn)
    4472                 : {
    4473               0 :   *aReturn = nsnull;
    4474               0 :   nsCOMPtr<nsIContent> content;
    4475               0 :   nsresult rv = CreateTextNode(aData, getter_AddRefs(content));
    4476               0 :   NS_ENSURE_SUCCESS(rv, rv);
    4477               0 :   return CallQueryInterface(content, aReturn);
    4478                 : }
    4479                 : 
    4480                 : nsresult
    4481              34 : nsDocument::CreateTextNode(const nsAString& aData, nsIContent** aReturn)
    4482                 : {
    4483              34 :   nsresult rv = NS_NewTextNode(aReturn, mNodeInfoManager);
    4484              34 :   if (NS_SUCCEEDED(rv)) {
    4485                 :     // Don't notify; this node is still being created.
    4486              34 :     (*aReturn)->SetText(aData, false);
    4487                 :   }
    4488              34 :   return rv;
    4489                 : }
    4490                 : 
    4491                 : NS_IMETHODIMP
    4492              57 : nsDocument::CreateDocumentFragment(nsIDOMDocumentFragment** aReturn)
    4493                 : {
    4494              57 :   return NS_NewDocumentFragment(aReturn, mNodeInfoManager);
    4495                 : }
    4496                 : 
    4497                 : NS_IMETHODIMP
    4498               1 : nsDocument::CreateComment(const nsAString& aData, nsIDOMComment** aReturn)
    4499                 : {
    4500               1 :   *aReturn = nsnull;
    4501                 : 
    4502                 :   // Make sure the substring "--" is not present in aData.  Otherwise
    4503                 :   // we'll create a document that can't be serialized.
    4504               1 :   if (FindInReadable(NS_LITERAL_STRING("--"), aData)) {
    4505               0 :     return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
    4506                 :   }
    4507                 : 
    4508               2 :   nsCOMPtr<nsIContent> comment;
    4509               1 :   nsresult rv = NS_NewCommentNode(getter_AddRefs(comment), mNodeInfoManager);
    4510                 : 
    4511               1 :   if (NS_SUCCEEDED(rv)) {
    4512                 :     // Don't notify; this node is still being created.
    4513               1 :     comment->SetText(aData, false);
    4514                 : 
    4515               1 :     rv = CallQueryInterface(comment, aReturn);
    4516                 :   }
    4517                 : 
    4518               1 :   return rv;
    4519                 : }
    4520                 : 
    4521                 : NS_IMETHODIMP
    4522               0 : nsDocument::CreateCDATASection(const nsAString& aData,
    4523                 :                                nsIDOMCDATASection** aReturn)
    4524                 : {
    4525               0 :   NS_ENSURE_ARG_POINTER(aReturn);
    4526               0 :   *aReturn = nsnull;
    4527                 : 
    4528               0 :   if (IsHTML()) {
    4529               0 :     return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
    4530                 :   }
    4531                 : 
    4532               0 :   if (FindInReadable(NS_LITERAL_STRING("]]>"), aData)) {
    4533               0 :     return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
    4534                 :   }
    4535                 : 
    4536               0 :   nsCOMPtr<nsIContent> content;
    4537               0 :   nsresult rv = NS_NewXMLCDATASection(getter_AddRefs(content),
    4538               0 :                                       mNodeInfoManager);
    4539                 : 
    4540               0 :   if (NS_SUCCEEDED(rv)) {
    4541                 :     // Don't notify; this node is still being created.
    4542               0 :     content->SetText(aData, false);
    4543                 : 
    4544               0 :     rv = CallQueryInterface(content, aReturn);
    4545                 :   }
    4546                 : 
    4547               0 :   return rv;
    4548                 : }
    4549                 : 
    4550                 : NS_IMETHODIMP
    4551               1 : nsDocument::CreateProcessingInstruction(const nsAString& aTarget,
    4552                 :                                         const nsAString& aData,
    4553                 :                                         nsIDOMProcessingInstruction** aReturn)
    4554                 : {
    4555               1 :   *aReturn = nsnull;
    4556                 : 
    4557               1 :   nsresult rv = nsContentUtils::CheckQName(aTarget, false);
    4558               1 :   NS_ENSURE_SUCCESS(rv, rv);
    4559                 : 
    4560               1 :   if (FindInReadable(NS_LITERAL_STRING("?>"), aData)) {
    4561               0 :     return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
    4562                 :   }
    4563                 : 
    4564               2 :   nsCOMPtr<nsIContent> content;
    4565               1 :   rv = NS_NewXMLProcessingInstruction(getter_AddRefs(content),
    4566               1 :                                       mNodeInfoManager, aTarget, aData);
    4567               1 :   if (NS_FAILED(rv)) {
    4568               0 :     return rv;
    4569                 :   }
    4570                 : 
    4571               1 :   return CallQueryInterface(content, aReturn);
    4572                 : }
    4573                 : 
    4574                 : NS_IMETHODIMP
    4575               4 : nsDocument::CreateAttribute(const nsAString& aName,
    4576                 :                             nsIDOMAttr** aReturn)
    4577                 : {
    4578               4 :   *aReturn = nsnull;
    4579                 : 
    4580               4 :   WarnOnceAbout(eCreateAttribute);
    4581                 : 
    4582               4 :   NS_ENSURE_TRUE(mNodeInfoManager, NS_ERROR_NOT_INITIALIZED);
    4583                 : 
    4584               4 :   nsresult rv = nsContentUtils::CheckQName(aName, false);
    4585               4 :   NS_ENSURE_SUCCESS(rv, rv);
    4586                 : 
    4587               8 :   nsCOMPtr<nsINodeInfo> nodeInfo;
    4588                 :   rv = mNodeInfoManager->GetNodeInfo(aName, nsnull, kNameSpaceID_None,
    4589                 :                                      nsIDOMNode::ATTRIBUTE_NODE,
    4590               4 :                                      getter_AddRefs(nodeInfo));
    4591               4 :   NS_ENSURE_SUCCESS(rv, rv);
    4592                 : 
    4593               8 :   nsAutoString value;
    4594                 :   nsCOMPtr<nsIDOMAttr> attribute =
    4595              12 :     new nsDOMAttribute(nsnull, nodeInfo.forget(), value, false);
    4596               4 :   attribute.forget(aReturn);
    4597               4 :   return NS_OK;
    4598                 : }
    4599                 : 
    4600                 : NS_IMETHODIMP
    4601               1 : nsDocument::CreateAttributeNS(const nsAString & aNamespaceURI,
    4602                 :                               const nsAString & aQualifiedName,
    4603                 :                               nsIDOMAttr **aResult)
    4604                 : {
    4605               1 :   NS_ENSURE_ARG_POINTER(aResult);
    4606               1 :   *aResult = nsnull;
    4607                 : 
    4608               1 :   WarnOnceAbout(eCreateAttributeNS);
    4609                 : 
    4610               2 :   nsCOMPtr<nsINodeInfo> nodeInfo;
    4611                 :   nsresult rv = nsContentUtils::GetNodeInfoFromQName(aNamespaceURI,
    4612                 :                                                      aQualifiedName,
    4613                 :                                                      mNodeInfoManager,
    4614                 :                                                      nsIDOMNode::ATTRIBUTE_NODE,
    4615               1 :                                                      getter_AddRefs(nodeInfo));
    4616               1 :   NS_ENSURE_SUCCESS(rv, rv);
    4617                 : 
    4618               2 :   nsAutoString value;
    4619                 :   nsCOMPtr<nsIDOMAttr> attribute =
    4620               3 :     new nsDOMAttribute(nsnull, nodeInfo.forget(), value, true);
    4621               1 :   attribute.forget(aResult);
    4622               1 :   return NS_OK;
    4623                 : }
    4624                 : 
    4625                 : NS_IMETHODIMP
    4626               0 : nsDocument::GetElementsByTagName(const nsAString& aTagname,
    4627                 :                                  nsIDOMNodeList** aReturn)
    4628                 : {
    4629               0 :   nsRefPtr<nsContentList> list = GetElementsByTagName(aTagname);
    4630               0 :   NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY);
    4631                 : 
    4632                 :   // transfer ref to aReturn
    4633               0 :   *aReturn = list.forget().get();
    4634               0 :   return NS_OK;
    4635                 : }
    4636                 : 
    4637                 : already_AddRefed<nsContentList>
    4638              40 : nsDocument::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
    4639                 :                                    const nsAString& aLocalName)
    4640                 : {
    4641              40 :   PRInt32 nameSpaceId = kNameSpaceID_Wildcard;
    4642                 : 
    4643              40 :   if (!aNamespaceURI.EqualsLiteral("*")) {
    4644                 :     nsresult rv =
    4645              19 :       nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI,
    4646              19 :                                                             nameSpaceId);
    4647              19 :     NS_ENSURE_SUCCESS(rv, nsnull);
    4648                 :   }
    4649                 : 
    4650              40 :   NS_ASSERTION(nameSpaceId != kNameSpaceID_Unknown, "Unexpected namespace ID!");
    4651                 : 
    4652              40 :   return NS_GetContentList(this, nameSpaceId, aLocalName);
    4653                 : }
    4654                 : 
    4655                 : NS_IMETHODIMP
    4656               0 : nsDocument::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
    4657                 :                                    const nsAString& aLocalName,
    4658                 :                                    nsIDOMNodeList** aReturn)
    4659                 : {
    4660                 :   nsRefPtr<nsContentList> list = GetElementsByTagNameNS(aNamespaceURI,
    4661               0 :                                                         aLocalName);
    4662               0 :   NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY);
    4663                 : 
    4664                 :   // transfer ref to aReturn
    4665               0 :   *aReturn = list.forget().get();
    4666               0 :   return NS_OK;
    4667                 : }
    4668                 : 
    4669                 : NS_IMETHODIMP
    4670               0 : nsDocument::GetAsync(bool *aAsync)
    4671                 : {
    4672               0 :   NS_ERROR("nsDocument::GetAsync() should be overriden by subclass!");
    4673                 : 
    4674               0 :   return NS_ERROR_NOT_IMPLEMENTED;
    4675                 : }
    4676                 : 
    4677                 : NS_IMETHODIMP
    4678               0 : nsDocument::SetAsync(bool aAsync)
    4679                 : {
    4680               0 :   NS_ERROR("nsDocument::SetAsync() should be overriden by subclass!");
    4681                 : 
    4682               0 :   return NS_ERROR_NOT_IMPLEMENTED;
    4683                 : }
    4684                 : 
    4685                 : NS_IMETHODIMP
    4686               0 : nsDocument::Load(const nsAString& aUrl, bool *aReturn)
    4687                 : {
    4688               0 :   NS_ERROR("nsDocument::Load() should be overriden by subclass!");
    4689                 : 
    4690               0 :   return NS_ERROR_NOT_IMPLEMENTED;
    4691                 : }
    4692                 : 
    4693                 : NS_IMETHODIMP
    4694               0 : nsDocument::GetStyleSheets(nsIDOMStyleSheetList** aStyleSheets)
    4695                 : {
    4696               0 :   if (!mDOMStyleSheets) {
    4697               0 :     mDOMStyleSheets = new nsDOMStyleSheetList(this);
    4698               0 :     if (!mDOMStyleSheets) {
    4699               0 :       return NS_ERROR_OUT_OF_MEMORY;
    4700                 :     }
    4701                 :   }
    4702                 : 
    4703               0 :   *aStyleSheets = mDOMStyleSheets;
    4704               0 :   NS_ADDREF(*aStyleSheets);
    4705                 : 
    4706               0 :   return NS_OK;
    4707                 : }
    4708                 : 
    4709                 : NS_IMETHODIMP
    4710               0 : nsDocument::GetSelectedStyleSheetSet(nsAString& aSheetSet)
    4711                 : {
    4712               0 :   aSheetSet.Truncate();
    4713                 :   
    4714                 :   // Look through our sheets, find the selected set title
    4715               0 :   PRInt32 count = GetNumberOfStyleSheets();
    4716               0 :   nsAutoString title;
    4717               0 :   for (PRInt32 index = 0; index < count; index++) {
    4718               0 :     nsIStyleSheet* sheet = GetStyleSheetAt(index);
    4719               0 :     NS_ASSERTION(sheet, "Null sheet in sheet list!");
    4720                 : 
    4721               0 :     nsCOMPtr<nsIDOMStyleSheet> domSheet = do_QueryInterface(sheet);
    4722               0 :     NS_ASSERTION(domSheet, "Sheet must QI to nsIDOMStyleSheet");
    4723                 :     bool disabled;
    4724               0 :     domSheet->GetDisabled(&disabled);
    4725               0 :     if (disabled) {
    4726                 :       // Disabled sheets don't affect the currently selected set
    4727               0 :       continue;
    4728                 :     }
    4729                 :     
    4730               0 :     sheet->GetTitle(title);
    4731                 : 
    4732               0 :     if (aSheetSet.IsEmpty()) {
    4733               0 :       aSheetSet = title;
    4734               0 :     } else if (!title.IsEmpty() && !aSheetSet.Equals(title)) {
    4735                 :       // Sheets from multiple sets enabled; return null string, per spec.
    4736               0 :       SetDOMStringToNull(aSheetSet);
    4737                 :       break;
    4738                 :     }
    4739                 :   }
    4740                 : 
    4741               0 :   return NS_OK;
    4742                 : }
    4743                 : 
    4744                 : NS_IMETHODIMP
    4745               0 : nsDocument::SetSelectedStyleSheetSet(const nsAString& aSheetSet)
    4746                 : {
    4747               0 :   if (DOMStringIsNull(aSheetSet)) {
    4748               0 :     return NS_OK;
    4749                 :   }
    4750                 : 
    4751                 :   // Must update mLastStyleSheetSet before doing anything else with stylesheets
    4752                 :   // or CSSLoaders.
    4753               0 :   mLastStyleSheetSet = aSheetSet;
    4754               0 :   EnableStyleSheetsForSetInternal(aSheetSet, true);
    4755               0 :   return NS_OK;
    4756                 : }
    4757                 : 
    4758                 : NS_IMETHODIMP
    4759               0 : nsDocument::GetLastStyleSheetSet(nsAString& aSheetSet)
    4760                 : {
    4761               0 :   aSheetSet = mLastStyleSheetSet;
    4762               0 :   return NS_OK;
    4763                 : }
    4764                 : 
    4765                 : NS_IMETHODIMP
    4766            1273 : nsDocument::GetPreferredStyleSheetSet(nsAString& aSheetSet)
    4767                 : {
    4768            1273 :   GetHeaderData(nsGkAtoms::headerDefaultStyle, aSheetSet);
    4769            1273 :   return NS_OK;
    4770                 : }
    4771                 : 
    4772                 : NS_IMETHODIMP
    4773               0 : nsDocument::GetStyleSheetSets(nsIDOMDOMStringList** aList)
    4774                 : {
    4775               0 :   if (!mStyleSheetSetList) {
    4776               0 :     mStyleSheetSetList = new nsDOMStyleSheetSetList(this);
    4777               0 :     if (!mStyleSheetSetList) {
    4778               0 :       return NS_ERROR_OUT_OF_MEMORY;
    4779                 :     }
    4780                 :   }
    4781                 : 
    4782               0 :   NS_ADDREF(*aList = mStyleSheetSetList);
    4783               0 :   return NS_OK;
    4784                 : }
    4785                 : 
    4786                 : NS_IMETHODIMP
    4787               0 : nsDocument::EnableStyleSheetsForSet(const nsAString& aSheetSet)
    4788                 : {
    4789                 :   // Per spec, passing in null is a no-op.
    4790               0 :   if (!DOMStringIsNull(aSheetSet)) {
    4791                 :     // Note: must make sure to not change the CSSLoader's preferred sheet --
    4792                 :     // that value should be equal to either our lastStyleSheetSet (if that's
    4793                 :     // non-null) or to our preferredStyleSheetSet.  And this method doesn't
    4794                 :     // change either of those.
    4795               0 :     EnableStyleSheetsForSetInternal(aSheetSet, false);
    4796                 :   }
    4797                 : 
    4798               0 :   return NS_OK;
    4799                 : }
    4800                 : 
    4801                 : void
    4802               0 : nsDocument::EnableStyleSheetsForSetInternal(const nsAString& aSheetSet,
    4803                 :                                             bool aUpdateCSSLoader)
    4804                 : {
    4805               0 :   BeginUpdate(UPDATE_STYLE);
    4806               0 :   PRInt32 count = GetNumberOfStyleSheets();
    4807               0 :   nsAutoString title;
    4808               0 :   for (PRInt32 index = 0; index < count; index++) {
    4809               0 :     nsIStyleSheet* sheet = GetStyleSheetAt(index);
    4810               0 :     NS_ASSERTION(sheet, "Null sheet in sheet list!");
    4811               0 :     sheet->GetTitle(title);
    4812               0 :     if (!title.IsEmpty()) {
    4813               0 :       sheet->SetEnabled(title.Equals(aSheetSet));
    4814                 :     }
    4815                 :   }
    4816               0 :   if (aUpdateCSSLoader) {
    4817               0 :     CSSLoader()->SetPreferredSheet(aSheetSet);
    4818                 :   }
    4819               0 :   EndUpdate(UPDATE_STYLE);
    4820               0 : }
    4821                 : 
    4822                 : NS_IMETHODIMP
    4823              28 : nsDocument::GetCharacterSet(nsAString& aCharacterSet)
    4824                 : {
    4825              28 :   CopyASCIItoUTF16(GetDocumentCharacterSet(), aCharacterSet);
    4826              28 :   return NS_OK;
    4827                 : }
    4828                 : 
    4829                 : NS_IMETHODIMP
    4830               0 : nsDocument::ImportNode(nsIDOMNode* aImportedNode,
    4831                 :                        bool aDeep,
    4832                 :                        PRUint8 aArgc,
    4833                 :                        nsIDOMNode** aResult)
    4834                 : {
    4835               0 :   NS_ENSURE_ARG(aImportedNode);
    4836               0 :   if (aArgc == 0) {
    4837               0 :     aDeep = true;
    4838                 :   }
    4839                 : 
    4840               0 :   *aResult = nsnull;
    4841                 : 
    4842               0 :   nsresult rv = nsContentUtils::CheckSameOrigin(this, aImportedNode);
    4843               0 :   if (NS_FAILED(rv)) {
    4844               0 :     return rv;
    4845                 :   }
    4846                 : 
    4847                 :   PRUint16 nodeType;
    4848               0 :   aImportedNode->GetNodeType(&nodeType);
    4849               0 :   switch (nodeType) {
    4850                 :     case nsIDOMNode::ATTRIBUTE_NODE:
    4851                 :     case nsIDOMNode::DOCUMENT_FRAGMENT_NODE:
    4852                 :     case nsIDOMNode::ELEMENT_NODE:
    4853                 :     case nsIDOMNode::PROCESSING_INSTRUCTION_NODE:
    4854                 :     case nsIDOMNode::TEXT_NODE:
    4855                 :     case nsIDOMNode::CDATA_SECTION_NODE:
    4856                 :     case nsIDOMNode::COMMENT_NODE:
    4857                 :     case nsIDOMNode::DOCUMENT_TYPE_NODE:
    4858                 :     {
    4859               0 :       nsCOMPtr<nsINode> imported = do_QueryInterface(aImportedNode);
    4860               0 :       NS_ENSURE_TRUE(imported, NS_ERROR_FAILURE);
    4861                 : 
    4862               0 :       nsCOMPtr<nsIDOMNode> newNode;
    4863               0 :       nsCOMArray<nsINode> nodesWithProperties;
    4864                 :       rv = nsNodeUtils::Clone(imported, aDeep, mNodeInfoManager,
    4865               0 :                               nodesWithProperties, getter_AddRefs(newNode));
    4866               0 :       NS_ENSURE_SUCCESS(rv, rv);
    4867                 : 
    4868               0 :       nsIDocument *ownerDoc = imported->OwnerDoc();
    4869                 :       rv = nsNodeUtils::CallUserDataHandlers(nodesWithProperties, ownerDoc,
    4870                 :                                              nsIDOMUserDataHandler::NODE_IMPORTED,
    4871               0 :                                              true);
    4872               0 :       NS_ENSURE_SUCCESS(rv, rv);
    4873                 : 
    4874               0 :       newNode.swap(*aResult);
    4875                 : 
    4876               0 :       return NS_OK;
    4877                 :     }
    4878                 :     case nsIDOMNode::ENTITY_NODE:
    4879                 :     case nsIDOMNode::ENTITY_REFERENCE_NODE:
    4880                 :     case nsIDOMNode::NOTATION_NODE:
    4881                 :     {
    4882               0 :       return NS_ERROR_NOT_IMPLEMENTED;
    4883                 :     }
    4884                 :     default:
    4885                 :     {
    4886               0 :       NS_WARNING("Don't know how to clone this nodetype for importNode.");
    4887                 : 
    4888               0 :       return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
    4889                 :     }
    4890                 :   }
    4891                 : }
    4892                 : 
    4893                 : NS_IMETHODIMP
    4894               0 : nsDocument::AddBinding(nsIDOMElement* aContent, const nsAString& aURI)
    4895                 : {
    4896               0 :   NS_ENSURE_ARG(aContent);
    4897                 :   
    4898               0 :   nsresult rv = nsContentUtils::CheckSameOrigin(this, aContent);
    4899               0 :   if (NS_FAILED(rv)) {
    4900               0 :     return rv;
    4901                 :   }
    4902                 : 
    4903               0 :   nsCOMPtr<nsIContent> content(do_QueryInterface(aContent));
    4904                 : 
    4905               0 :   nsCOMPtr<nsIURI> uri;
    4906               0 :   rv = NS_NewURI(getter_AddRefs(uri), aURI);
    4907               0 :   if (NS_FAILED(rv)) {
    4908               0 :     return rv;
    4909                 :   }
    4910                 : 
    4911                 :   // Figure out the right principal to use
    4912               0 :   nsCOMPtr<nsIPrincipal> subject;
    4913               0 :   nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
    4914               0 :   if (secMan) {
    4915               0 :     rv = secMan->GetSubjectPrincipal(getter_AddRefs(subject));
    4916               0 :     NS_ENSURE_SUCCESS(rv, rv);
    4917                 :   }
    4918                 : 
    4919               0 :   if (!subject) {
    4920                 :     // Fall back to our principal.  Or should we fall back to the null
    4921                 :     // principal?  The latter would just mean no binding loads....
    4922               0 :     subject = NodePrincipal();
    4923                 :   }
    4924                 :   
    4925               0 :   return BindingManager()->AddLayeredBinding(content, uri, subject);
    4926                 : }
    4927                 : 
    4928                 : NS_IMETHODIMP
    4929               0 : nsDocument::RemoveBinding(nsIDOMElement* aContent, const nsAString& aURI)
    4930                 : {
    4931               0 :   NS_ENSURE_ARG(aContent);
    4932                 : 
    4933               0 :   nsresult rv = nsContentUtils::CheckSameOrigin(this, aContent);
    4934               0 :   if (NS_FAILED(rv)) {
    4935               0 :     return rv;
    4936                 :   }
    4937                 : 
    4938               0 :   nsCOMPtr<nsIURI> uri;
    4939               0 :   rv = NS_NewURI(getter_AddRefs(uri), aURI);
    4940               0 :   if (NS_FAILED(rv)) {
    4941               0 :     return rv;
    4942                 :   }
    4943                 : 
    4944               0 :   nsCOMPtr<nsIContent> content(do_QueryInterface(aContent));
    4945               0 :   return BindingManager()->RemoveLayeredBinding(content, uri);
    4946                 : }
    4947                 : 
    4948                 : NS_IMETHODIMP
    4949               0 : nsDocument::LoadBindingDocument(const nsAString& aURI)
    4950                 : {
    4951               0 :   nsCOMPtr<nsIURI> uri;
    4952               0 :   nsresult rv = NS_NewURI(getter_AddRefs(uri), aURI,
    4953                 :                           mCharacterSet.get(),
    4954               0 :                           GetDocBaseURI());
    4955               0 :   NS_ENSURE_SUCCESS(rv, rv);
    4956                 : 
    4957                 :   // Figure out the right principal to use
    4958               0 :   nsCOMPtr<nsIPrincipal> subject;
    4959               0 :   nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
    4960               0 :   if (secMan) {
    4961               0 :     rv = secMan->GetSubjectPrincipal(getter_AddRefs(subject));
    4962               0 :     NS_ENSURE_SUCCESS(rv, rv);
    4963                 :   }
    4964                 : 
    4965               0 :   if (!subject) {
    4966                 :     // Fall back to our principal.  Or should we fall back to the null
    4967                 :     // principal?  The latter would just mean no binding loads....
    4968               0 :     subject = NodePrincipal();
    4969                 :   }
    4970                 :   
    4971               0 :   BindingManager()->LoadBindingDocument(this, uri, subject);
    4972                 : 
    4973               0 :   return NS_OK;
    4974                 : }
    4975                 : 
    4976                 : NS_IMETHODIMP
    4977               0 : nsDocument::GetBindingParent(nsIDOMNode* aNode, nsIDOMElement** aResult)
    4978                 : {
    4979               0 :   *aResult = nsnull;
    4980               0 :   nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
    4981               0 :   if (!content)
    4982               0 :     return NS_ERROR_FAILURE;
    4983                 : 
    4984               0 :   nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(content->GetBindingParent()));
    4985               0 :   NS_IF_ADDREF(*aResult = elt);
    4986               0 :   return NS_OK;
    4987                 : }
    4988                 : 
    4989                 : static nsresult
    4990               0 : GetElementByAttribute(nsIContent* aContent, nsIAtom* aAttrName,
    4991                 :                       const nsAString& aAttrValue, bool aUniversalMatch,
    4992                 :                       nsIDOMElement** aResult)
    4993                 : {
    4994               0 :   if (aUniversalMatch ? aContent->HasAttr(kNameSpaceID_None, aAttrName) :
    4995                 :                         aContent->AttrValueIs(kNameSpaceID_None, aAttrName,
    4996               0 :                                               aAttrValue, eCaseMatters)) {
    4997               0 :     return CallQueryInterface(aContent, aResult);
    4998                 :   }
    4999                 : 
    5000               0 :   for (nsIContent* child = aContent->GetFirstChild();
    5001                 :        child;
    5002               0 :        child = child->GetNextSibling()) {
    5003                 : 
    5004                 :     GetElementByAttribute(child, aAttrName, aAttrValue, aUniversalMatch,
    5005               0 :                           aResult);
    5006                 : 
    5007               0 :     if (*aResult)
    5008               0 :       return NS_OK;
    5009                 :   }
    5010                 : 
    5011               0 :   return NS_OK;
    5012                 : }
    5013                 : 
    5014                 : NS_IMETHODIMP
    5015               0 : nsDocument::GetAnonymousElementByAttribute(nsIDOMElement* aElement,
    5016                 :                                            const nsAString& aAttrName,
    5017                 :                                            const nsAString& aAttrValue,
    5018                 :                                            nsIDOMElement** aResult)
    5019                 : {
    5020               0 :   *aResult = nsnull;
    5021                 : 
    5022               0 :   nsCOMPtr<nsIDOMNodeList> nodeList;
    5023               0 :   GetAnonymousNodes(aElement, getter_AddRefs(nodeList));
    5024                 : 
    5025               0 :   if (!nodeList)
    5026               0 :     return NS_OK;
    5027                 : 
    5028               0 :   nsCOMPtr<nsIAtom> attribute = do_GetAtom(aAttrName);
    5029                 : 
    5030                 :   PRUint32 length;
    5031               0 :   nodeList->GetLength(&length);
    5032                 : 
    5033               0 :   bool universalMatch = aAttrValue.EqualsLiteral("*");
    5034                 : 
    5035               0 :   for (PRUint32 i = 0; i < length; ++i) {
    5036               0 :     nsCOMPtr<nsIDOMNode> current;
    5037               0 :     nodeList->Item(i, getter_AddRefs(current));
    5038                 : 
    5039               0 :     nsCOMPtr<nsIContent> content(do_QueryInterface(current));
    5040                 : 
    5041                 :     GetElementByAttribute(content, attribute, aAttrValue, universalMatch,
    5042               0 :                           aResult);
    5043               0 :     if (*aResult)
    5044               0 :       return NS_OK;
    5045                 :   }
    5046                 : 
    5047               0 :   return NS_OK;
    5048                 : }
    5049                 : 
    5050                 : 
    5051                 : NS_IMETHODIMP
    5052               0 : nsDocument::GetAnonymousNodes(nsIDOMElement* aElement,
    5053                 :                               nsIDOMNodeList** aResult)
    5054                 : {
    5055               0 :   *aResult = nsnull;
    5056                 : 
    5057               0 :   nsCOMPtr<nsIContent> content(do_QueryInterface(aElement));
    5058               0 :   return BindingManager()->GetAnonymousNodesFor(content, aResult);
    5059                 : }
    5060                 : 
    5061                 : NS_IMETHODIMP
    5062              31 : nsDocument::CreateRange(nsIDOMRange** aReturn)
    5063                 : {
    5064              62 :   nsRefPtr<nsRange> range = new nsRange();
    5065              31 :   nsresult rv = range->Set(this, 0, this, 0);
    5066              31 :   NS_ENSURE_SUCCESS(rv, rv);
    5067                 : 
    5068              31 :   range.forget(aReturn);
    5069              31 :   return NS_OK;
    5070                 : }
    5071                 : 
    5072                 : NS_IMETHODIMP
    5073               0 : nsDocument::CreateNodeIterator(nsIDOMNode *aRoot,
    5074                 :                                PRUint32 aWhatToShow,
    5075                 :                                nsIDOMNodeFilter *aFilter,
    5076                 :                                PRUint8 aOptionalArgc,
    5077                 :                                nsIDOMNodeIterator **_retval)
    5078                 : {
    5079               0 :   *_retval = nsnull;
    5080                 : 
    5081               0 :   if (!aOptionalArgc) {
    5082               0 :     aWhatToShow = nsIDOMNodeFilter::SHOW_ALL;
    5083                 :   }
    5084                 : 
    5085               0 :   if (!aRoot)
    5086               0 :     return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
    5087                 : 
    5088               0 :   nsresult rv = nsContentUtils::CheckSameOrigin(this, aRoot);
    5089               0 :   NS_ENSURE_SUCCESS(rv, rv);
    5090                 : 
    5091               0 :   NS_ENSURE_ARG_POINTER(_retval);
    5092                 : 
    5093               0 :   nsCOMPtr<nsINode> root = do_QueryInterface(aRoot);
    5094               0 :   NS_ENSURE_TRUE(root, NS_ERROR_DOM_NOT_SUPPORTED_ERR);
    5095                 : 
    5096                 :   nsNodeIterator *iterator = new nsNodeIterator(root,
    5097                 :                                                 aWhatToShow,
    5098               0 :                                                 aFilter);
    5099               0 :   NS_ENSURE_TRUE(iterator, NS_ERROR_OUT_OF_MEMORY);
    5100                 : 
    5101               0 :   NS_ADDREF(*_retval = iterator);
    5102                 : 
    5103               0 :   return NS_OK;
    5104                 : }
    5105                 : 
    5106                 : NS_IMETHODIMP
    5107              65 : nsDocument::CreateTreeWalker(nsIDOMNode *aRoot,
    5108                 :                              PRUint32 aWhatToShow,
    5109                 :                              nsIDOMNodeFilter *aFilter,
    5110                 :                              PRUint8 aOptionalArgc,
    5111                 :                              nsIDOMTreeWalker **_retval)
    5112                 : {
    5113              65 :   *_retval = nsnull;
    5114                 : 
    5115              65 :   if (!aOptionalArgc) {
    5116               0 :     aWhatToShow = nsIDOMNodeFilter::SHOW_ALL;
    5117                 :   }
    5118                 : 
    5119              65 :   if (!aRoot)
    5120               0 :     return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
    5121                 : 
    5122              65 :   nsresult rv = nsContentUtils::CheckSameOrigin(this, aRoot);
    5123              65 :   NS_ENSURE_SUCCESS(rv, rv);
    5124                 : 
    5125              65 :   NS_ENSURE_ARG_POINTER(_retval);
    5126                 : 
    5127             130 :   nsCOMPtr<nsINode> root = do_QueryInterface(aRoot);
    5128              65 :   NS_ENSURE_TRUE(root, NS_ERROR_DOM_NOT_SUPPORTED_ERR);
    5129                 : 
    5130                 :   nsTreeWalker* walker = new nsTreeWalker(root,
    5131                 :                                           aWhatToShow,
    5132             130 :                                           aFilter);
    5133              65 :   NS_ENSURE_TRUE(walker, NS_ERROR_OUT_OF_MEMORY);
    5134                 : 
    5135              65 :   NS_ADDREF(*_retval = walker);
    5136                 : 
    5137              65 :   return NS_OK;
    5138                 : }
    5139                 : 
    5140                 : 
    5141                 : NS_IMETHODIMP
    5142               0 : nsDocument::GetDefaultView(nsIDOMWindow** aDefaultView)
    5143                 : {
    5144               0 :   *aDefaultView = nsnull;
    5145               0 :   nsCOMPtr<nsPIDOMWindow> win = GetWindow();
    5146               0 :   win.forget(aDefaultView);
    5147               0 :   return NS_OK;
    5148                 : }
    5149                 : 
    5150                 : NS_IMETHODIMP
    5151               0 : nsDocument::GetLocation(nsIDOMLocation **_retval)
    5152                 : {
    5153               0 :   NS_ENSURE_ARG_POINTER(_retval);
    5154               0 :   *_retval = nsnull;
    5155                 : 
    5156               0 :   nsCOMPtr<nsIDOMWindow> w = do_QueryInterface(mScriptGlobalObject);
    5157                 : 
    5158               0 :   if (!w) {
    5159               0 :     return NS_OK;
    5160                 :   }
    5161                 : 
    5162               0 :   return w->GetLocation(_retval);
    5163                 : }
    5164                 : 
    5165                 : Element*
    5166               0 : nsIDocument::GetHtmlElement()
    5167                 : {
    5168               0 :   Element* rootElement = GetRootElement();
    5169               0 :   if (rootElement && rootElement->IsHTML(nsGkAtoms::html))
    5170               0 :     return rootElement;
    5171               0 :   return nsnull;
    5172                 : }
    5173                 : 
    5174                 : Element*
    5175               0 : nsIDocument::GetHtmlChildElement(nsIAtom* aTag)
    5176                 : {
    5177               0 :   Element* html = GetHtmlElement();
    5178               0 :   if (!html)
    5179               0 :     return nsnull;
    5180                 : 
    5181                 :   // Look for the element with aTag inside html. This needs to run
    5182                 :   // forwards to find the first such element.
    5183               0 :   for (nsIContent* child = html->GetFirstChild();
    5184                 :        child;
    5185               0 :        child = child->GetNextSibling()) {
    5186               0 :     if (child->IsHTML(aTag))
    5187               0 :       return child->AsElement();
    5188                 :   }
    5189               0 :   return nsnull;
    5190                 : }
    5191                 : 
    5192                 : nsIContent*
    5193            1036 : nsDocument::GetTitleContent(PRUint32 aNamespace)
    5194                 : {
    5195                 :   // mMayHaveTitleElement will have been set to true if any HTML or SVG
    5196                 :   // <title> element has been bound to this document. So if it's false,
    5197                 :   // we know there is nothing to do here. This avoids us having to search
    5198                 :   // the whole DOM if someone calls document.title on a large document
    5199                 :   // without a title.
    5200            1036 :   if (!mMayHaveTitleElement)
    5201            1036 :     return nsnull;
    5202                 : 
    5203                 :   nsRefPtr<nsContentList> list =
    5204               0 :     NS_GetContentList(this, aNamespace, NS_LITERAL_STRING("title"));
    5205                 : 
    5206               0 :   return list->Item(0, false);
    5207                 : }
    5208                 : 
    5209                 : void
    5210            1036 : nsDocument::GetTitleFromElement(PRUint32 aNamespace, nsAString& aTitle)
    5211                 : {
    5212            1036 :   nsIContent* title = GetTitleContent(aNamespace);
    5213            1036 :   if (!title)
    5214            1036 :     return;
    5215               0 :   nsContentUtils::GetNodeTextContent(title, false, aTitle);
    5216                 : }
    5217                 : 
    5218                 : NS_IMETHODIMP
    5219            1038 : nsDocument::GetTitle(nsAString& aTitle)
    5220                 : {
    5221            1038 :   aTitle.Truncate();
    5222                 : 
    5223            1038 :   nsIContent *rootElement = GetRootElement();
    5224            1038 :   if (!rootElement)
    5225               0 :     return NS_OK;
    5226                 : 
    5227            2076 :   nsAutoString tmp;
    5228                 : 
    5229            1038 :   switch (rootElement->GetNameSpaceID()) {
    5230                 : #ifdef MOZ_XUL
    5231                 :     case kNameSpaceID_XUL:
    5232               2 :       rootElement->GetAttr(kNameSpaceID_None, nsGkAtoms::title, tmp);
    5233               2 :       break;
    5234                 : #endif
    5235                 :     case kNameSpaceID_SVG:
    5236               0 :       if (rootElement->Tag() == nsGkAtoms::svg) {
    5237               0 :         GetTitleFromElement(kNameSpaceID_SVG, tmp);
    5238               0 :         break;
    5239                 :       } // else fall through
    5240                 :     default:
    5241            1036 :       GetTitleFromElement(kNameSpaceID_XHTML, tmp);
    5242            1036 :       break;
    5243                 :   }
    5244                 : 
    5245            1038 :   tmp.CompressWhitespace();
    5246            1038 :   aTitle = tmp;
    5247            1038 :   return NS_OK;
    5248                 : }
    5249                 : 
    5250                 : NS_IMETHODIMP
    5251               0 : nsDocument::SetTitle(const nsAString& aTitle)
    5252                 : {
    5253               0 :   Element *rootElement = GetRootElement();
    5254               0 :   if (!rootElement)
    5255               0 :     return NS_OK;
    5256                 : 
    5257               0 :   switch (rootElement->GetNameSpaceID()) {
    5258                 :     case kNameSpaceID_SVG:
    5259               0 :       return NS_OK; // SVG doesn't support setting a title
    5260                 : #ifdef MOZ_XUL
    5261                 :     case kNameSpaceID_XUL:
    5262                 :       return rootElement->SetAttr(kNameSpaceID_None, nsGkAtoms::title,
    5263               0 :                                   aTitle, true);
    5264                 : #endif
    5265                 :   }
    5266                 : 
    5267                 :   // Batch updates so that mutation events don't change "the title
    5268                 :   // element" under us
    5269               0 :   mozAutoDocUpdate updateBatch(this, UPDATE_CONTENT_MODEL, true);
    5270                 : 
    5271               0 :   nsIContent* title = GetTitleContent(kNameSpaceID_XHTML);
    5272               0 :   if (!title) {
    5273               0 :     Element *head = GetHeadElement();
    5274               0 :     if (!head)
    5275               0 :       return NS_OK;
    5276                 : 
    5277                 :     {
    5278               0 :       nsCOMPtr<nsINodeInfo> titleInfo;
    5279                 :       titleInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::title, nsnull,
    5280                 :                                                 kNameSpaceID_XHTML,
    5281               0 :                                                 nsIDOMNode::ELEMENT_NODE);
    5282               0 :       if (!titleInfo)
    5283               0 :         return NS_OK;
    5284               0 :       title = NS_NewHTMLTitleElement(titleInfo.forget());
    5285               0 :       if (!title)
    5286               0 :         return NS_OK;
    5287                 :     }
    5288                 : 
    5289               0 :     head->AppendChildTo(title, true);
    5290                 :   }
    5291                 : 
    5292               0 :   return nsContentUtils::SetNodeTextContent(title, aTitle, false);
    5293                 : }
    5294                 : 
    5295                 : void
    5296            1038 : nsDocument::NotifyPossibleTitleChange(bool aBoundTitleElement)
    5297                 : {
    5298            1038 :   NS_ASSERTION(!mInUnlinkOrDeletion || !aBoundTitleElement,
    5299                 :                "Setting a title while unlinking or destroying the element?");
    5300            1038 :   if (mInUnlinkOrDeletion) {
    5301               0 :     return;
    5302                 :   }
    5303                 : 
    5304            1038 :   if (aBoundTitleElement) {
    5305               0 :     mMayHaveTitleElement = true;
    5306                 :   }
    5307            1038 :   if (mPendingTitleChangeEvent.IsPending())
    5308               0 :     return;
    5309                 : 
    5310                 :   nsRefPtr<nsRunnableMethod<nsDocument, void, false> > event =
    5311                 :     NS_NewNonOwningRunnableMethod(this,
    5312            2076 :       &nsDocument::DoNotifyPossibleTitleChange);
    5313            1038 :   nsresult rv = NS_DispatchToCurrentThread(event);
    5314            1038 :   if (NS_SUCCEEDED(rv)) {
    5315            1038 :     mPendingTitleChangeEvent = event;
    5316                 :   }
    5317                 : }
    5318                 : 
    5319                 : void
    5320            1038 : nsDocument::DoNotifyPossibleTitleChange()
    5321                 : {
    5322            1038 :   mPendingTitleChangeEvent.Forget();
    5323            1038 :   mHaveFiredTitleChange = true;
    5324                 : 
    5325            2076 :   nsAutoString title;
    5326            1038 :   GetTitle(title);
    5327                 : 
    5328            2076 :   nsCOMPtr<nsIPresShell> shell = GetShell();
    5329            1038 :   if (shell) {
    5330               0 :     nsCOMPtr<nsISupports> container = shell->GetPresContext()->GetContainer();
    5331               0 :     if (container) {
    5332               0 :       nsCOMPtr<nsIBaseWindow> docShellWin = do_QueryInterface(container);
    5333               0 :       if (docShellWin) {
    5334               0 :         docShellWin->SetTitle(title.get());
    5335                 :       }
    5336                 :     }
    5337                 :   }
    5338                 : 
    5339                 :   // Fire a DOM event for the title change.
    5340                 :   nsContentUtils::DispatchChromeEvent(this, static_cast<nsIDocument*>(this),
    5341            1038 :                                       NS_LITERAL_STRING("DOMTitleChanged"),
    5342            1038 :                                       true, true);
    5343            1038 : }
    5344                 : 
    5345                 : NS_IMETHODIMP
    5346               0 : nsDocument::GetBoxObjectFor(nsIDOMElement* aElement, nsIBoxObject** aResult)
    5347                 : {
    5348               0 :   nsCOMPtr<nsIContent> content(do_QueryInterface(aElement));
    5349               0 :   NS_ENSURE_TRUE(content, NS_ERROR_UNEXPECTED);
    5350                 : 
    5351               0 :   nsIDocument* doc = content->OwnerDoc();
    5352               0 :   NS_ENSURE_TRUE(doc == this, NS_ERROR_DOM_WRONG_DOCUMENT_ERR);
    5353                 : 
    5354               0 :   if (!mHasWarnedAboutBoxObjects && !content->IsXUL()) {
    5355               0 :     mHasWarnedAboutBoxObjects = true;
    5356                 :     nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
    5357                 :                                     "BoxObjects", this,
    5358                 :                                     nsContentUtils::eDOM_PROPERTIES,
    5359               0 :                                     "UseOfGetBoxObjectForWarning");
    5360                 :   }
    5361                 : 
    5362               0 :   *aResult = nsnull;
    5363                 : 
    5364               0 :   if (!mBoxObjectTable) {
    5365               0 :     mBoxObjectTable = new nsInterfaceHashtable<nsVoidPtrHashKey, nsPIBoxObject>;
    5366               0 :     if (mBoxObjectTable && !mBoxObjectTable->Init(12)) {
    5367               0 :       mBoxObjectTable = nsnull;
    5368                 :     }
    5369                 :   } else {
    5370                 :     // Want to use Get(content, aResult); but it's the wrong type
    5371               0 :     *aResult = mBoxObjectTable->GetWeak(content);
    5372               0 :     if (*aResult) {
    5373               0 :       NS_ADDREF(*aResult);
    5374               0 :       return NS_OK;
    5375                 :     }
    5376                 :   }
    5377                 : 
    5378                 :   PRInt32 namespaceID;
    5379               0 :   nsCOMPtr<nsIAtom> tag = BindingManager()->ResolveTag(content, &namespaceID);
    5380                 : 
    5381               0 :   nsCAutoString contractID("@mozilla.org/layout/xul-boxobject");
    5382               0 :   if (namespaceID == kNameSpaceID_XUL) {
    5383               0 :     if (tag == nsGkAtoms::browser ||
    5384               0 :         tag == nsGkAtoms::editor ||
    5385               0 :         tag == nsGkAtoms::iframe)
    5386               0 :       contractID += "-container";
    5387               0 :     else if (tag == nsGkAtoms::menu)
    5388               0 :       contractID += "-menu";
    5389               0 :     else if (tag == nsGkAtoms::popup ||
    5390               0 :              tag == nsGkAtoms::menupopup ||
    5391               0 :              tag == nsGkAtoms::panel ||
    5392               0 :              tag == nsGkAtoms::tooltip)
    5393               0 :       contractID += "-popup";
    5394               0 :     else if (tag == nsGkAtoms::tree)
    5395               0 :       contractID += "-tree";
    5396               0 :     else if (tag == nsGkAtoms::listbox)
    5397               0 :       contractID += "-listbox";
    5398               0 :     else if (tag == nsGkAtoms::scrollbox)
    5399               0 :       contractID += "-scrollbox";
    5400                 :   }
    5401               0 :   contractID += ";1";
    5402                 : 
    5403               0 :   nsCOMPtr<nsPIBoxObject> boxObject(do_CreateInstance(contractID.get()));
    5404               0 :   if (!boxObject)
    5405               0 :     return NS_ERROR_FAILURE;
    5406                 : 
    5407               0 :   boxObject->Init(content);
    5408                 : 
    5409               0 :   if (mBoxObjectTable) {
    5410               0 :     mBoxObjectTable->Put(content, boxObject.get());
    5411                 :   }
    5412                 : 
    5413               0 :   *aResult = boxObject;
    5414               0 :   NS_ADDREF(*aResult);
    5415                 : 
    5416               0 :   return NS_OK;
    5417                 : }
    5418                 : 
    5419                 : void
    5420           75809 : nsDocument::ClearBoxObjectFor(nsIContent* aContent)
    5421                 : {
    5422           75809 :   if (mBoxObjectTable) {
    5423               0 :     nsPIBoxObject *boxObject = mBoxObjectTable->GetWeak(aContent);
    5424               0 :     if (boxObject) {
    5425               0 :       boxObject->Clear();
    5426               0 :       mBoxObjectTable->Remove(aContent);
    5427                 :     }
    5428                 :   }
    5429           75809 : }
    5430                 : 
    5431                 : nsresult
    5432               0 : nsDocument::GetXBLChildNodesFor(nsIContent* aContent, nsIDOMNodeList** aResult)
    5433                 : {
    5434               0 :   return BindingManager()->GetXBLChildNodesFor(aContent, aResult);
    5435                 : }
    5436                 : 
    5437                 : nsresult
    5438               0 : nsDocument::GetContentListFor(nsIContent* aContent, nsIDOMNodeList** aResult)
    5439                 : {
    5440               0 :   return BindingManager()->GetContentListFor(aContent, aResult);
    5441                 : }
    5442                 : 
    5443                 : void
    5444               0 : nsDocument::FlushSkinBindings()
    5445                 : {
    5446               0 :   BindingManager()->FlushSkinBindings();
    5447               0 : }
    5448                 : 
    5449                 : nsresult
    5450               0 : nsDocument::InitializeFrameLoader(nsFrameLoader* aLoader)
    5451                 : {
    5452               0 :   mInitializableFrameLoaders.RemoveElement(aLoader);
    5453                 :   // Don't even try to initialize.
    5454               0 :   if (mInDestructor) {
    5455                 :     NS_WARNING("Trying to initialize a frame loader while"
    5456               0 :                "document is being deleted");
    5457               0 :     return NS_ERROR_FAILURE;
    5458                 :   }
    5459                 : 
    5460               0 :   mInitializableFrameLoaders.AppendElement(aLoader);
    5461               0 :   if (!mFrameLoaderRunner) {
    5462                 :     mFrameLoaderRunner =
    5463               0 :       NS_NewRunnableMethod(this, &nsDocument::MaybeInitializeFinalizeFrameLoaders);
    5464               0 :     NS_ENSURE_TRUE(mFrameLoaderRunner, NS_ERROR_OUT_OF_MEMORY);
    5465               0 :     nsContentUtils::AddScriptRunner(mFrameLoaderRunner);
    5466                 :   }
    5467               0 :   return NS_OK;
    5468                 : }
    5469                 : 
    5470                 : nsresult
    5471               0 : nsDocument::FinalizeFrameLoader(nsFrameLoader* aLoader)
    5472                 : {
    5473               0 :   mInitializableFrameLoaders.RemoveElement(aLoader);
    5474               0 :   if (mInDestructor) {
    5475               0 :     return NS_ERROR_FAILURE;
    5476                 :   }
    5477                 : 
    5478               0 :   mFinalizableFrameLoaders.AppendElement(aLoader);
    5479               0 :   if (!mFrameLoaderRunner) {
    5480                 :     mFrameLoaderRunner =
    5481               0 :       NS_NewRunnableMethod(this, &nsDocument::MaybeInitializeFinalizeFrameLoaders);
    5482               0 :     NS_ENSURE_TRUE(mFrameLoaderRunner, NS_ERROR_OUT_OF_MEMORY);
    5483               0 :     nsContentUtils::AddScriptRunner(mFrameLoaderRunner);
    5484                 :   }
    5485               0 :   return NS_OK;
    5486                 : }
    5487                 : 
    5488                 : void
    5489            6215 : nsDocument::MaybeInitializeFinalizeFrameLoaders()
    5490                 : {
    5491            6215 :   if (mDelayFrameLoaderInitialization || mUpdateNestLevel != 0) {
    5492                 :     // This method will be recalled when mUpdateNestLevel drops to 0,
    5493                 :     // or when !mDelayFrameLoaderInitialization.
    5494            1325 :     mFrameLoaderRunner = nsnull;
    5495            1325 :     return;
    5496                 :   }
    5497                 : 
    5498                 :   // We're not in an update, but it is not safe to run scripts, so
    5499                 :   // postpone frameloader initialization and finalization.
    5500            4890 :   if (!nsContentUtils::IsSafeToRunScript()) {
    5501             204 :     if (!mInDestructor && !mFrameLoaderRunner &&
    5502              68 :         (mInitializableFrameLoaders.Length() ||
    5503              68 :          mFinalizableFrameLoaders.Length())) {
    5504                 :       mFrameLoaderRunner =
    5505               0 :         NS_NewRunnableMethod(this, &nsDocument::MaybeInitializeFinalizeFrameLoaders);
    5506               0 :       nsContentUtils::AddScriptRunner(mFrameLoaderRunner);
    5507                 :     }
    5508              68 :     return;
    5509                 :   }
    5510            4822 :   mFrameLoaderRunner = nsnull;
    5511                 : 
    5512                 :   // Don't use a temporary array for mInitializableFrameLoaders, because
    5513                 :   // loading a frame may cause some other frameloader to be removed from the
    5514                 :   // array. But be careful to keep the loader alive when starting the load!
    5515            9644 :   while (mInitializableFrameLoaders.Length()) {
    5516               0 :     nsRefPtr<nsFrameLoader> loader = mInitializableFrameLoaders[0];
    5517               0 :     mInitializableFrameLoaders.RemoveElementAt(0);
    5518               0 :     NS_ASSERTION(loader, "null frameloader in the array?");
    5519               0 :     loader->ReallyStartLoading();
    5520                 :   }
    5521                 : 
    5522            4822 :   PRUint32 length = mFinalizableFrameLoaders.Length();
    5523            4822 :   if (length > 0) {
    5524               0 :     nsTArray<nsRefPtr<nsFrameLoader> > loaders;
    5525               0 :     mFinalizableFrameLoaders.SwapElements(loaders);
    5526               0 :     for (PRUint32 i = 0; i < length; ++i) {
    5527               0 :       loaders[i]->Finalize();
    5528                 :     }
    5529                 :   }
    5530                 : }
    5531                 : 
    5532                 : void
    5533               0 : nsDocument::TryCancelFrameLoaderInitialization(nsIDocShell* aShell)
    5534                 : {
    5535               0 :   PRUint32 length = mInitializableFrameLoaders.Length();
    5536               0 :   for (PRUint32 i = 0; i < length; ++i) {
    5537               0 :     if (mInitializableFrameLoaders[i]->GetExistingDocShell() == aShell) {
    5538               0 :       mInitializableFrameLoaders.RemoveElementAt(i);
    5539               0 :       return;
    5540                 :     }
    5541                 :   }
    5542                 : }
    5543                 : 
    5544                 : bool
    5545               0 : nsDocument::FrameLoaderScheduledToBeFinalized(nsIDocShell* aShell)
    5546                 : {
    5547               0 :   if (aShell) {
    5548               0 :     PRUint32 length = mFinalizableFrameLoaders.Length();
    5549               0 :     for (PRUint32 i = 0; i < length; ++i) {
    5550               0 :       if (mFinalizableFrameLoaders[i]->GetExistingDocShell() == aShell) {
    5551               0 :         return true;
    5552                 :       }
    5553                 :     }
    5554                 :   }
    5555               0 :   return false;
    5556                 : }
    5557                 : 
    5558                 : nsIDocument*
    5559               0 : nsDocument::RequestExternalResource(nsIURI* aURI,
    5560                 :                                     nsINode* aRequestingNode,
    5561                 :                                     ExternalResourceLoad** aPendingLoad)
    5562                 : {
    5563               0 :   NS_PRECONDITION(aURI, "Must have a URI");
    5564               0 :   NS_PRECONDITION(aRequestingNode, "Must have a node");
    5565               0 :   if (mDisplayDocument) {
    5566               0 :     return mDisplayDocument->RequestExternalResource(aURI,
    5567                 :                                                      aRequestingNode,
    5568               0 :                                                      aPendingLoad);
    5569                 :   }
    5570                 : 
    5571                 :   return mExternalResourceMap.RequestResource(aURI, aRequestingNode,
    5572               0 :                                               this, aPendingLoad);
    5573                 : }
    5574                 : 
    5575                 : void
    5576               0 : nsDocument::EnumerateExternalResources(nsSubDocEnumFunc aCallback, void* aData)
    5577                 : {
    5578               0 :   mExternalResourceMap.EnumerateResources(aCallback, aData);
    5579               0 : }
    5580                 : 
    5581                 : nsSMILAnimationController*
    5582               0 : nsDocument::GetAnimationController()
    5583                 : {
    5584                 :   // We create the animation controller lazily because most documents won't want
    5585                 :   // one and only SVG documents and the like will call this
    5586               0 :   if (mAnimationController)
    5587               0 :     return mAnimationController;
    5588                 :   // Refuse to create an Animation Controller if SMIL is disabled, and also
    5589                 :   // for data documents.
    5590               0 :   if (!NS_SMILEnabled() || mLoadedAsData || mLoadedAsInteractiveData)
    5591               0 :     return nsnull;
    5592                 : 
    5593               0 :   mAnimationController = new nsSMILAnimationController(this);
    5594                 :   
    5595                 :   // If there's a presContext then check the animation mode and pause if
    5596                 :   // necessary.
    5597               0 :   nsIPresShell *shell = GetShell();
    5598               0 :   if (mAnimationController && shell) {
    5599               0 :     nsPresContext *context = shell->GetPresContext();
    5600               0 :     if (context &&
    5601               0 :         context->ImageAnimationMode() == imgIContainer::kDontAnimMode) {
    5602               0 :       mAnimationController->Pause(nsSMILTimeContainer::PAUSE_USERPREF);
    5603                 :     }
    5604                 :   }
    5605                 : 
    5606                 :   // If we're hidden (or being hidden), notify the newly-created animation
    5607                 :   // controller. (Skip this check for SVG-as-an-image documents, though,
    5608                 :   // because they don't get OnPageShow / OnPageHide calls).
    5609               0 :   if (!mIsShowing && !mIsBeingUsedAsImage) {
    5610               0 :     mAnimationController->OnPageHide();
    5611                 :   }
    5612                 : 
    5613               0 :   return mAnimationController;
    5614                 : }
    5615                 : 
    5616                 : struct DirTable {
    5617                 :   const char* mName;
    5618                 :   PRUint8     mValue;
    5619                 : };
    5620                 : 
    5621                 : static const DirTable dirAttributes[] = {
    5622                 :   {"ltr", IBMBIDI_TEXTDIRECTION_LTR},
    5623                 :   {"rtl", IBMBIDI_TEXTDIRECTION_RTL},
    5624                 :   {0}
    5625                 : };
    5626                 : 
    5627                 : /**
    5628                 :  * Retrieve the "direction" property of the document.
    5629                 :  *
    5630                 :  * @lina 01/09/2001
    5631                 :  */
    5632                 : NS_IMETHODIMP
    5633               0 : nsDocument::GetDir(nsAString& aDirection)
    5634                 : {
    5635               0 :   PRUint32 options = GetBidiOptions();
    5636               0 :   for (const DirTable* elt = dirAttributes; elt->mName; elt++) {
    5637               0 :     if (GET_BIDI_OPTION_DIRECTION(options) == elt->mValue) {
    5638               0 :       CopyASCIItoUTF16(elt->mName, aDirection);
    5639               0 :       break;
    5640                 :     }
    5641                 :   }
    5642                 : 
    5643               0 :   return NS_OK;
    5644                 : }
    5645                 : 
    5646                 : /**
    5647                 :  * Set the "direction" property of the document.
    5648                 :  *
    5649                 :  * @lina 01/09/2001
    5650                 :  */
    5651                 : NS_IMETHODIMP
    5652               0 : nsDocument::SetDir(const nsAString& aDirection)
    5653                 : {
    5654               0 :   PRUint32 options = GetBidiOptions();
    5655                 : 
    5656               0 :   for (const DirTable* elt = dirAttributes; elt->mName; elt++) {
    5657               0 :     if (aDirection == NS_ConvertASCIItoUTF16(elt->mName)) {
    5658               0 :       if (GET_BIDI_OPTION_DIRECTION(options) != elt->mValue) {
    5659               0 :         SET_BIDI_OPTION_DIRECTION(options, elt->mValue);
    5660               0 :         nsIPresShell *shell = GetShell();
    5661               0 :         if (shell) {
    5662               0 :           nsPresContext *context = shell->GetPresContext();
    5663               0 :           NS_ENSURE_TRUE(context, NS_ERROR_UNEXPECTED);
    5664               0 :           context->SetBidi(options, true);
    5665                 :         } else {
    5666                 :           // No presentation; just set it on ourselves
    5667               0 :           SetBidiOptions(options);
    5668                 :         }
    5669                 :       }
    5670                 : 
    5671               0 :       break;
    5672                 :     }
    5673                 :   }
    5674                 : 
    5675               0 :   return NS_OK;
    5676                 : }
    5677                 : 
    5678                 : 
    5679                 : //
    5680                 : // nsIDOMNode methods
    5681                 : //
    5682                 : NS_IMETHODIMP
    5683               0 : nsDocument::GetNodeName(nsAString& aNodeName)
    5684                 : {
    5685               0 :   aNodeName.AssignLiteral("#document");
    5686                 : 
    5687               0 :   return NS_OK;
    5688                 : }
    5689                 : 
    5690                 : NS_IMETHODIMP
    5691               0 : nsDocument::GetNodeValue(nsAString& aNodeValue)
    5692                 : {
    5693               0 :   SetDOMStringToNull(aNodeValue);
    5694                 : 
    5695               0 :   return NS_OK;
    5696                 : }
    5697                 : 
    5698                 : NS_IMETHODIMP
    5699               0 : nsDocument::SetNodeValue(const nsAString& aNodeValue)
    5700                 : {
    5701                 :   // The DOM spec says that when nodeValue is defined to be null "setting it
    5702                 :   // has no effect", so we don't throw an exception.
    5703               0 :   return NS_OK;
    5704                 : }
    5705                 : 
    5706                 : NS_IMETHODIMP
    5707              54 : nsDocument::GetNodeType(PRUint16* aNodeType)
    5708                 : {
    5709              54 :   *aNodeType = nsIDOMNode::DOCUMENT_NODE;
    5710                 : 
    5711              54 :   return NS_OK;
    5712                 : }
    5713                 : 
    5714                 : NS_IMETHODIMP
    5715               0 : nsDocument::GetParentNode(nsIDOMNode** aParentNode)
    5716                 : {
    5717               0 :   *aParentNode = nsnull;
    5718                 : 
    5719               0 :   return NS_OK;
    5720                 : }
    5721                 : 
    5722                 : NS_IMETHODIMP
    5723               0 : nsDocument::GetParentElement(nsIDOMElement** aParentElement)
    5724                 : {
    5725               0 :   *aParentElement = nsnull;
    5726               0 :   return NS_OK;
    5727                 : }
    5728                 : 
    5729                 : NS_IMETHODIMP
    5730             109 : nsDocument::GetChildNodes(nsIDOMNodeList** aChildNodes)
    5731                 : {
    5732             109 :   return nsINode::GetChildNodes(aChildNodes);
    5733                 : }
    5734                 : 
    5735                 : NS_IMETHODIMP
    5736               0 : nsDocument::HasChildNodes(bool* aHasChildNodes)
    5737                 : {
    5738               0 :   NS_ENSURE_ARG(aHasChildNodes);
    5739                 : 
    5740               0 :   *aHasChildNodes = (mChildren.ChildCount() != 0);
    5741                 : 
    5742               0 :   return NS_OK;
    5743                 : }
    5744                 : 
    5745                 : NS_IMETHODIMP
    5746               0 : nsDocument::HasAttributes(bool* aHasAttributes)
    5747                 : {
    5748               0 :   NS_ENSURE_ARG(aHasAttributes);
    5749                 : 
    5750               0 :   *aHasAttributes = false;
    5751                 : 
    5752               0 :   return NS_OK;
    5753                 : }
    5754                 : 
    5755                 : NS_IMETHODIMP
    5756               2 : nsDocument::GetFirstChild(nsIDOMNode** aFirstChild)
    5757                 : {
    5758               2 :   return nsINode::GetFirstChild(aFirstChild);
    5759                 : }
    5760                 : 
    5761                 : NS_IMETHODIMP
    5762              72 : nsDocument::GetLastChild(nsIDOMNode** aLastChild)
    5763                 : {
    5764              72 :   return nsINode::GetLastChild(aLastChild);
    5765                 : }
    5766                 : 
    5767                 : NS_IMETHODIMP
    5768               0 : nsDocument::GetPreviousSibling(nsIDOMNode** aPreviousSibling)
    5769                 : {
    5770               0 :   *aPreviousSibling = nsnull;
    5771                 : 
    5772               0 :   return NS_OK;
    5773                 : }
    5774                 : 
    5775                 : NS_IMETHODIMP
    5776               0 : nsDocument::GetNextSibling(nsIDOMNode** aNextSibling)
    5777                 : {
    5778               0 :   *aNextSibling = nsnull;
    5779                 : 
    5780               0 :   return NS_OK;
    5781                 : }
    5782                 : 
    5783                 : NS_IMETHODIMP
    5784               0 : nsDocument::GetAttributes(nsIDOMNamedNodeMap** aAttributes)
    5785                 : {
    5786               0 :   *aAttributes = nsnull;
    5787                 : 
    5788               0 :   return NS_OK;
    5789                 : }
    5790                 : 
    5791                 : NS_IMETHODIMP
    5792               0 : nsDocument::GetNamespaceURI(nsAString& aNamespaceURI)
    5793                 : {
    5794               0 :   SetDOMStringToNull(aNamespaceURI);
    5795                 : 
    5796               0 :   return NS_OK;
    5797                 : }
    5798                 : 
    5799                 : NS_IMETHODIMP
    5800               0 : nsDocument::GetPrefix(nsAString& aPrefix)
    5801                 : {
    5802               0 :   SetDOMStringToNull(aPrefix);
    5803                 : 
    5804               0 :   return NS_OK;
    5805                 : }
    5806                 : 
    5807                 : NS_IMETHODIMP
    5808               0 : nsDocument::GetLocalName(nsAString& aLocalName)
    5809                 : {
    5810               0 :   SetDOMStringToNull(aLocalName);
    5811                 : 
    5812               0 :   return NS_OK;
    5813                 : }
    5814                 : 
    5815                 : NS_IMETHODIMP
    5816               1 : nsDocument::InsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild,
    5817                 :                          nsIDOMNode** aReturn)
    5818                 : {
    5819               1 :   return ReplaceOrInsertBefore(false, aNewChild, aRefChild, aReturn);
    5820                 : }
    5821                 : 
    5822                 : NS_IMETHODIMP
    5823               0 : nsDocument::ReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild,
    5824                 :                          nsIDOMNode** aReturn)
    5825                 : {
    5826               0 :   return ReplaceOrInsertBefore(true, aNewChild, aOldChild, aReturn);
    5827                 : }
    5828                 : 
    5829                 : NS_IMETHODIMP
    5830              10 : nsDocument::RemoveChild(nsIDOMNode* aOldChild, nsIDOMNode** aReturn)
    5831                 : {
    5832              10 :   return nsINode::RemoveChild(aOldChild, aReturn);
    5833                 : }
    5834                 : 
    5835                 : NS_IMETHODIMP
    5836               1 : nsDocument::AppendChild(nsIDOMNode* aNewChild, nsIDOMNode** aReturn)
    5837                 : {
    5838               1 :   return nsDocument::InsertBefore(aNewChild, nsnull, aReturn);
    5839                 : }
    5840                 : 
    5841                 : NS_IMETHODIMP
    5842               0 : nsDocument::CloneNode(bool aDeep, PRUint8 aOptionalArgc, nsIDOMNode** aReturn)
    5843                 : {
    5844               0 :   if (!aOptionalArgc) {
    5845               0 :     aDeep = true;
    5846                 :   }
    5847                 :   
    5848               0 :   return nsNodeUtils::CloneNodeImpl(this, aDeep, !mCreatingStaticClone, aReturn);
    5849                 : }
    5850                 : 
    5851                 : NS_IMETHODIMP
    5852               0 : nsDocument::Normalize()
    5853                 : {
    5854               0 :   return nsIDocument::Normalize();
    5855                 : }
    5856                 : 
    5857                 : NS_IMETHODIMP
    5858               0 : nsDocument::IsSupported(const nsAString& aFeature, const nsAString& aVersion,
    5859                 :                         bool* aReturn)
    5860                 : {
    5861                 :   return nsGenericElement::InternalIsSupported(static_cast<nsIDOMDocument*>(this),
    5862               0 :                                                aFeature, aVersion, aReturn);
    5863                 : }
    5864                 : 
    5865                 : NS_IMETHODIMP
    5866               0 : nsDocument::GetDOMBaseURI(nsAString &aURI)
    5867                 : {
    5868               0 :   return nsIDocument::GetDOMBaseURI(aURI);
    5869                 : }
    5870                 : 
    5871                 : NS_IMETHODIMP
    5872               0 : nsDocument::GetTextContent(nsAString &aTextContent)
    5873                 : {
    5874               0 :   SetDOMStringToNull(aTextContent);
    5875               0 :   return NS_OK;
    5876                 : }
    5877                 : 
    5878                 : NS_IMETHODIMP
    5879               0 : nsDocument::IsEqualNode(nsIDOMNode* aOther, bool* aResult)
    5880                 : {
    5881               0 :   return nsINode::IsEqualNode(aOther, aResult);
    5882                 : }
    5883                 : 
    5884                 : NS_IMETHODIMP
    5885               0 : nsDocument::CompareDocumentPosition(nsIDOMNode *other,
    5886                 :                                    PRUint16 *aResult)
    5887                 : {
    5888               0 :   return nsINode::CompareDocumentPosition(other, aResult);
    5889                 : }
    5890                 : 
    5891                 : NS_IMETHODIMP
    5892               0 : nsDocument::SetTextContent(const nsAString & aTextContent)
    5893                 : {
    5894               0 :   return nsINode::SetTextContent(aTextContent);
    5895                 : }
    5896                 : 
    5897                 : NS_IMETHODIMP
    5898               0 : nsDocument::LookupPrefix(const nsAString & namespaceURI, nsAString & aResult)
    5899                 : {
    5900               0 :   return nsINode::LookupPrefix(namespaceURI, aResult);
    5901                 : }
    5902                 : 
    5903                 : NS_IMETHODIMP
    5904               0 : nsDocument::IsDefaultNamespace(const nsAString & namespaceURI,
    5905                 :                               bool *aResult)
    5906                 : {
    5907               0 :   return nsINode::IsDefaultNamespace(namespaceURI, aResult);
    5908                 : }
    5909                 : 
    5910                 : NS_IMETHODIMP
    5911               0 : nsDocument::LookupNamespaceURI(const nsAString & prefix,
    5912                 :                               nsAString & aResult)
    5913                 : {
    5914               0 :   return nsINode::LookupNamespaceURI(prefix, aResult);
    5915                 : }
    5916                 : 
    5917                 : NS_IMETHODIMP
    5918               0 : nsDocument::SetUserData(const nsAString & key,
    5919                 :                        nsIVariant *data, nsIDOMUserDataHandler *handler,
    5920                 :                        nsIVariant **aResult)
    5921                 : {
    5922               0 :   return nsINode::SetUserData(key, data, handler, aResult);
    5923                 : }
    5924                 : 
    5925                 : NS_IMETHODIMP
    5926               0 : nsDocument::GetUserData(const nsAString & key,
    5927                 :                         nsIVariant **aResult)
    5928                 : {
    5929               0 :   return nsINode::GetUserData(key, aResult);
    5930                 : }
    5931                 : 
    5932                 : NS_IMETHODIMP
    5933               0 : nsDocument::Contains(nsIDOMNode* aOther, bool* aReturn)
    5934                 : {
    5935               0 :   return nsINode::Contains(aOther, aReturn);
    5936                 : }
    5937                 : 
    5938                 : NS_IMETHODIMP
    5939               0 : nsDocument::GetInputEncoding(nsAString& aInputEncoding)
    5940                 : {
    5941               0 :   WarnOnceAbout(eInputEncoding);
    5942               0 :   if (mHaveInputEncoding) {
    5943               0 :     return GetCharacterSet(aInputEncoding);
    5944                 :   }
    5945                 : 
    5946               0 :   SetDOMStringToNull(aInputEncoding);
    5947               0 :   return NS_OK;
    5948                 : }
    5949                 : 
    5950                 : NS_IMETHODIMP
    5951               0 : nsDocument::GetMozSyntheticDocument(bool *aSyntheticDocument)
    5952                 : {
    5953               0 :   *aSyntheticDocument = mIsSyntheticDocument;
    5954               0 :   return NS_OK;
    5955                 : }
    5956                 : 
    5957                 : NS_IMETHODIMP
    5958               0 : nsDocument::GetDocumentURI(nsAString& aDocumentURI)
    5959                 : {
    5960               0 :   if (mDocumentURI) {
    5961               0 :     nsCAutoString uri;
    5962               0 :     mDocumentURI->GetSpec(uri);
    5963               0 :     CopyUTF8toUTF16(uri, aDocumentURI);
    5964                 :   } else {
    5965               0 :     SetDOMStringToNull(aDocumentURI);
    5966                 :   }
    5967                 : 
    5968               0 :   return NS_OK;
    5969                 : }
    5970                 : 
    5971                 : static void BlastSubtreeToPieces(nsINode *aNode);
    5972                 : 
    5973                 : PLDHashOperator
    5974               0 : BlastFunc(nsAttrHashKey::KeyType aKey, nsDOMAttribute *aData, void* aUserArg)
    5975                 : {
    5976                 :   nsCOMPtr<nsIAttribute> *attr =
    5977               0 :     static_cast<nsCOMPtr<nsIAttribute>*>(aUserArg);
    5978                 : 
    5979               0 :   *attr = aData;
    5980                 : 
    5981               0 :   NS_ASSERTION(attr->get(),
    5982                 :                "non-nsIAttribute somehow made it into the hashmap?!");
    5983                 : 
    5984               0 :   return PL_DHASH_STOP;
    5985                 : }
    5986                 : 
    5987                 : static void
    5988               0 : BlastSubtreeToPieces(nsINode *aNode)
    5989                 : {
    5990                 :   PRUint32 i, count;
    5991               0 :   if (aNode->IsElement()) {
    5992               0 :     nsGenericElement *element = static_cast<nsGenericElement*>(aNode);
    5993               0 :     const nsDOMAttributeMap *map = element->GetAttributeMap();
    5994               0 :     if (map) {
    5995               0 :       nsCOMPtr<nsIAttribute> attr;
    5996               0 :       while (map->Enumerate(BlastFunc, &attr) > 0) {
    5997               0 :         BlastSubtreeToPieces(attr);
    5998                 : 
    5999                 : #ifdef DEBUG
    6000                 :         nsresult rv =
    6001                 : #endif
    6002                 :           element->UnsetAttr(attr->NodeInfo()->NamespaceID(),
    6003                 :                              attr->NodeInfo()->NameAtom(),
    6004               0 :                              false);
    6005                 : 
    6006                 :         // XXX Should we abort here?
    6007               0 :         NS_ASSERTION(NS_SUCCEEDED(rv), "Uhoh, UnsetAttr shouldn't fail!");
    6008                 :       }
    6009                 :     }
    6010                 :   }
    6011                 : 
    6012               0 :   count = aNode->GetChildCount();
    6013               0 :   for (i = 0; i < count; ++i) {
    6014               0 :     BlastSubtreeToPieces(aNode->GetFirstChild());
    6015                 : #ifdef DEBUG
    6016                 :     nsresult rv =
    6017                 : #endif
    6018               0 :       aNode->RemoveChildAt(0, false);
    6019                 : 
    6020                 :     // XXX Should we abort here?
    6021               0 :     NS_ASSERTION(NS_SUCCEEDED(rv), "Uhoh, RemoveChildAt shouldn't fail!");
    6022                 :   }
    6023               0 : }
    6024                 : 
    6025                 : 
    6026                 : class nsUserDataCaller : public nsRunnable
    6027               0 : {
    6028                 : public:
    6029               0 :   nsUserDataCaller(nsCOMArray<nsINode>& aNodesWithProperties,
    6030                 :                    nsIDocument* aOwnerDoc)
    6031                 :     : mNodesWithProperties(aNodesWithProperties),
    6032               0 :       mOwnerDoc(aOwnerDoc)
    6033                 :   {
    6034               0 :   }
    6035                 : 
    6036               0 :   NS_IMETHOD Run()
    6037                 :   {
    6038                 :     nsNodeUtils::CallUserDataHandlers(mNodesWithProperties, mOwnerDoc,
    6039                 :                                       nsIDOMUserDataHandler::NODE_ADOPTED,
    6040               0 :                                       false);
    6041               0 :     return NS_OK;
    6042                 :   }
    6043                 : 
    6044                 : private:
    6045                 :   nsCOMArray<nsINode> mNodesWithProperties;
    6046                 :   nsCOMPtr<nsIDocument> mOwnerDoc;
    6047                 : };
    6048                 : 
    6049                 : NS_IMETHODIMP
    6050               0 : nsDocument::AdoptNode(nsIDOMNode *aAdoptedNode, nsIDOMNode **aResult)
    6051                 : {
    6052               0 :   NS_ENSURE_ARG(aAdoptedNode);
    6053                 : 
    6054               0 :   *aResult = nsnull;
    6055                 : 
    6056               0 :   nsresult rv = nsContentUtils::CheckSameOrigin(this, aAdoptedNode);
    6057               0 :   NS_ENSURE_SUCCESS(rv, rv);
    6058                 : 
    6059               0 :   nsCOMPtr<nsINode> adoptedNode = do_QueryInterface(aAdoptedNode);
    6060                 : 
    6061                 :   // Scope firing mutation events so that we don't carry any state that
    6062                 :   // might be stale
    6063                 :   {
    6064               0 :     nsINode* parent = adoptedNode->GetNodeParent();
    6065               0 :     if (parent) {
    6066                 :       nsContentUtils::MaybeFireNodeRemoved(adoptedNode, parent,
    6067               0 :                                            adoptedNode->OwnerDoc());
    6068                 :     }
    6069                 :   }
    6070                 : 
    6071               0 :   nsAutoScriptBlocker scriptBlocker;
    6072                 : 
    6073                 :   PRUint16 nodeType;
    6074               0 :   aAdoptedNode->GetNodeType(&nodeType);
    6075               0 :   switch (nodeType) {
    6076                 :     case nsIDOMNode::ATTRIBUTE_NODE:
    6077                 :     {
    6078                 :       // Remove from ownerElement.
    6079               0 :       nsCOMPtr<nsIDOMAttr> adoptedAttr = do_QueryInterface(aAdoptedNode);
    6080               0 :       NS_ASSERTION(adoptedAttr, "Attribute not implementing nsIDOMAttr");
    6081                 : 
    6082               0 :       nsCOMPtr<nsIDOMElement> ownerElement;
    6083               0 :       rv = adoptedAttr->GetOwnerElement(getter_AddRefs(ownerElement));
    6084               0 :       NS_ENSURE_SUCCESS(rv, rv);
    6085                 : 
    6086               0 :       if (ownerElement) {
    6087               0 :         nsCOMPtr<nsIDOMAttr> newAttr;
    6088               0 :         rv = ownerElement->RemoveAttributeNode(adoptedAttr,
    6089               0 :                                                getter_AddRefs(newAttr));
    6090               0 :         NS_ENSURE_SUCCESS(rv, rv);
    6091                 : 
    6092               0 :         newAttr.swap(adoptedAttr);
    6093                 :       }
    6094                 : 
    6095               0 :       break;
    6096                 :     }
    6097                 :     case nsIDOMNode::DOCUMENT_FRAGMENT_NODE:
    6098                 :     case nsIDOMNode::ELEMENT_NODE:
    6099                 :     case nsIDOMNode::PROCESSING_INSTRUCTION_NODE:
    6100                 :     case nsIDOMNode::TEXT_NODE:
    6101                 :     case nsIDOMNode::CDATA_SECTION_NODE:
    6102                 :     case nsIDOMNode::COMMENT_NODE:
    6103                 :     case nsIDOMNode::DOCUMENT_TYPE_NODE:
    6104                 :     {
    6105                 :       // We don't want to adopt an element into its own contentDocument or into
    6106                 :       // a descendant contentDocument, so we check if the frameElement of this
    6107                 :       // document or any of its parents is the adopted node or one of its
    6108                 :       // descendants.
    6109               0 :       nsIDocument *doc = this;
    6110               0 :       do {
    6111               0 :         nsPIDOMWindow *win = doc->GetWindow();
    6112               0 :         if (win) {
    6113                 :           nsCOMPtr<nsINode> node =
    6114               0 :             do_QueryInterface(win->GetFrameElementInternal());
    6115               0 :           if (node &&
    6116               0 :               nsContentUtils::ContentIsDescendantOf(node, adoptedNode)) {
    6117               0 :             return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
    6118                 :           }
    6119                 :         }
    6120                 :       } while ((doc = doc->GetParentDocument()));
    6121                 : 
    6122                 :       // Remove from parent.
    6123               0 :       nsCOMPtr<nsINode> parent = adoptedNode->GetNodeParent();
    6124               0 :       if (parent) {
    6125               0 :         rv = parent->RemoveChildAt(parent->IndexOf(adoptedNode), true);
    6126               0 :         NS_ENSURE_SUCCESS(rv, rv);
    6127                 :       }
    6128                 : 
    6129               0 :       break;
    6130                 :     }
    6131                 :     case nsIDOMNode::ENTITY_REFERENCE_NODE:
    6132                 :     {
    6133               0 :       return NS_ERROR_NOT_IMPLEMENTED;
    6134                 :     }
    6135                 :     case nsIDOMNode::DOCUMENT_NODE:
    6136                 :     case nsIDOMNode::ENTITY_NODE:
    6137                 :     case nsIDOMNode::NOTATION_NODE:
    6138                 :     {
    6139               0 :       return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
    6140                 :     }
    6141                 :     default:
    6142                 :     {
    6143               0 :       NS_WARNING("Don't know how to adopt this nodetype for adoptNode.");
    6144                 : 
    6145               0 :       return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
    6146                 :     }
    6147                 :   }
    6148                 : 
    6149               0 :   nsIDocument *oldDocument = adoptedNode->OwnerDoc();
    6150               0 :   bool sameDocument = oldDocument == this;
    6151                 : 
    6152               0 :   JSContext *cx = nsnull;
    6153               0 :   JSObject *newScope = nsnull;
    6154               0 :   if (!sameDocument) {
    6155               0 :     rv = nsContentUtils::GetContextAndScope(oldDocument, this, &cx, &newScope);
    6156               0 :     NS_ENSURE_SUCCESS(rv, rv);
    6157                 :   }
    6158                 : 
    6159               0 :   nsCOMArray<nsINode> nodesWithProperties;
    6160                 :   rv = nsNodeUtils::Adopt(adoptedNode, sameDocument ? nsnull : mNodeInfoManager,
    6161               0 :                           cx, newScope, nodesWithProperties);
    6162               0 :   if (NS_FAILED(rv)) {
    6163                 :     // Disconnect all nodes from their parents, since some have the old document
    6164                 :     // as their ownerDocument and some have this as their ownerDocument.
    6165               0 :     BlastSubtreeToPieces(adoptedNode);
    6166                 : 
    6167               0 :     if (!sameDocument && oldDocument) {
    6168               0 :       PRUint32 count = nodesWithProperties.Count();
    6169               0 :       for (PRUint32 j = 0; j < oldDocument->GetPropertyTableCount(); ++j) {
    6170               0 :         for (PRUint32 i = 0; i < count; ++i) {
    6171                 :           // Remove all properties.
    6172                 :           oldDocument->PropertyTable(j)->
    6173               0 :             DeleteAllPropertiesFor(nodesWithProperties[i]);
    6174                 :         }
    6175                 :       }
    6176                 :     }
    6177                 : 
    6178               0 :     return rv;
    6179                 :   }
    6180                 : 
    6181               0 :   PRUint32 count = nodesWithProperties.Count();
    6182               0 :   if (!sameDocument && oldDocument) {
    6183               0 :     for (PRUint32 j = 0; j < oldDocument->GetPropertyTableCount(); ++j) {
    6184               0 :       nsPropertyTable *oldTable = oldDocument->PropertyTable(j);
    6185               0 :       nsPropertyTable *newTable = PropertyTable(j);
    6186               0 :       for (PRUint32 i = 0; i < count; ++i) {
    6187               0 :         if (NS_SUCCEEDED(rv)) {
    6188               0 :           rv = oldTable->TransferOrDeleteAllPropertiesFor(nodesWithProperties[i],
    6189               0 :                                                           newTable);
    6190                 :         } else {
    6191               0 :           oldTable->DeleteAllPropertiesFor(nodesWithProperties[i]);
    6192                 :         }
    6193                 :       }
    6194                 :     }
    6195                 : 
    6196               0 :     if (NS_FAILED(rv)) {
    6197                 :       // Disconnect all nodes from their parents.
    6198               0 :       BlastSubtreeToPieces(adoptedNode);
    6199                 : 
    6200               0 :       return rv;
    6201                 :     }
    6202                 :   }
    6203                 : 
    6204               0 :   if (nodesWithProperties.Count()) {
    6205                 :     nsContentUtils::AddScriptRunner(new nsUserDataCaller(nodesWithProperties,
    6206               0 :                                                          this));
    6207                 :   }
    6208                 : 
    6209               0 :   NS_ASSERTION(adoptedNode->OwnerDoc() == this,
    6210                 :                "Should still be in the document we just got adopted into");
    6211                 : 
    6212               0 :   return CallQueryInterface(adoptedNode, aResult);
    6213                 : }
    6214                 : 
    6215                 : NS_IMETHODIMP
    6216               0 : nsDocument::GetOwnerDocument(nsIDOMDocument** aOwnerDocument)
    6217                 : {
    6218               0 :   return nsINode::GetOwnerDocument(aOwnerDocument);
    6219                 : }
    6220                 : 
    6221                 : nsEventListenerManager*
    6222           14600 : nsDocument::GetListenerManager(bool aCreateIfNotFound)
    6223                 : {
    6224           14600 :   if (!mListenerManager && aCreateIfNotFound) {
    6225                 :     mListenerManager =
    6226               0 :       new nsEventListenerManager(static_cast<nsIDOMEventTarget*>(this));
    6227               0 :     SetFlags(NODE_HAS_LISTENERMANAGER);
    6228                 :   }
    6229                 : 
    6230           14600 :   return mListenerManager;
    6231                 : }
    6232                 : 
    6233                 : nsresult
    6234            6409 : nsDocument::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
    6235                 : {
    6236            6409 :   aVisitor.mCanHandle = true;
    6237                 :    // FIXME! This is a hack to make middle mouse paste working also in Editor.
    6238                 :    // Bug 329119
    6239            6409 :   aVisitor.mForceContentDispatch = true;
    6240                 : 
    6241                 :   // Load events must not propagate to |window| object, see bug 335251.
    6242            6409 :   if (aVisitor.mEvent->message != NS_LOAD) {
    6243            5371 :     nsGlobalWindow* window = static_cast<nsGlobalWindow*>(GetWindow());
    6244            5371 :     aVisitor.mParentTarget = static_cast<nsIDOMEventTarget*>(window);
    6245                 :   }
    6246            6409 :   return NS_OK;
    6247                 : }
    6248                 : 
    6249                 : NS_IMETHODIMP
    6250            6403 : nsDocument::CreateEvent(const nsAString& aEventType, nsIDOMEvent** aReturn)
    6251                 : {
    6252            6403 :   NS_ENSURE_ARG_POINTER(aReturn);
    6253            6403 :   *aReturn = nsnull;
    6254                 : 
    6255                 :   // Obtain a presentation shell
    6256                 : 
    6257            6403 :   nsIPresShell *shell = GetShell();
    6258                 : 
    6259            6403 :   nsPresContext *presContext = nsnull;
    6260                 : 
    6261            6403 :   if (shell) {
    6262                 :     // Retrieve the context
    6263               0 :     presContext = shell->GetPresContext();
    6264                 :   }
    6265                 : 
    6266                 :   // Create event even without presContext.
    6267                 :   return nsEventDispatcher::CreateEvent(presContext, nsnull,
    6268            6403 :                                         aEventType, aReturn);
    6269                 : }
    6270                 : 
    6271                 : void
    6272            7331 : nsDocument::FlushPendingNotifications(mozFlushType aType)
    6273                 : {
    6274                 :   // We need to flush the sink for non-HTML documents (because the XML
    6275                 :   // parser still does insertion with deferred notifications).  We
    6276                 :   // also need to flush the sink if this is a layout-related flush, to
    6277                 :   // make sure that layout is started as needed.  But we can skip that
    6278                 :   // part if we have no presshell or if it's already done an initial
    6279                 :   // reflow.
    6280           21993 :   if ((!IsHTML() ||
    6281                 :        (aType > Flush_ContentAndNotify && mPresShell &&
    6282               0 :         !mPresShell->DidInitialReflow())) &&
    6283           14662 :       (mParser || mWeakSink)) {
    6284             160 :     nsCOMPtr<nsIContentSink> sink;
    6285              80 :     if (mParser) {
    6286               0 :       sink = mParser->GetContentSink();
    6287                 :     } else {
    6288              80 :       sink = do_QueryReferent(mWeakSink);
    6289              80 :       if (!sink) {
    6290              80 :         mWeakSink = nsnull;
    6291                 :       }
    6292                 :     }
    6293                 :     // Determine if it is safe to flush the sink notifications
    6294                 :     // by determining if it safe to flush all the presshells.
    6295              80 :     if (sink && (aType == Flush_Content || IsSafeToFlush())) {
    6296               0 :       sink->FlushPendingNotifications(aType);
    6297                 :     }
    6298                 :   }
    6299                 : 
    6300                 :   // Should we be flushing pending binding constructors in here?
    6301                 : 
    6302            7331 :   if (aType <= Flush_ContentAndNotify) {
    6303                 :     // Nothing to do here
    6304            7331 :     return;
    6305                 :   }
    6306                 : 
    6307                 :   // If we have a parent we must flush the parent too to ensure that our
    6308                 :   // container is reflowed if its size was changed.  But if it's not safe to
    6309                 :   // flush ourselves, then don't flush the parent, since that can cause things
    6310                 :   // like resizes of our frame's widget, which we can't handle while flushing
    6311                 :   // is unsafe.
    6312                 :   // Since media queries mean that a size change of our container can
    6313                 :   // affect style, we need to promote a style flush on ourself to a
    6314                 :   // layout flush on our parent, since we need our container to be the
    6315                 :   // correct size to determine the correct style.
    6316               0 :   if (mParentDocument && IsSafeToFlush()) {
    6317               0 :     mozFlushType parentType = aType;
    6318               0 :     if (aType >= Flush_Style)
    6319               0 :       parentType = NS_MAX(Flush_Layout, aType);
    6320               0 :     mParentDocument->FlushPendingNotifications(parentType);
    6321                 :   }
    6322                 : 
    6323                 :   // We can optimize away getting our presshell and calling
    6324                 :   // FlushPendingNotifications on it if we don't need a flush of the sort we're
    6325                 :   // looking at.  The one exception is if mInFlush is true, because in that
    6326                 :   // case we might have set mNeedStyleFlush and mNeedLayoutFlush to false
    6327                 :   // already but the presshell hasn't actually done the corresponding work yet.
    6328                 :   // So if mInFlush and reentering this code, we need to flush the presshell.
    6329               0 :   if (mNeedStyleFlush ||
    6330                 :       (mNeedLayoutFlush && aType >= Flush_InterruptibleLayout) ||
    6331                 :       aType >= Flush_Display ||
    6332                 :       mInFlush) {
    6333               0 :     nsCOMPtr<nsIPresShell> shell = GetShell();
    6334               0 :     if (shell) {
    6335               0 :       mNeedStyleFlush = false;
    6336               0 :       mNeedLayoutFlush = mNeedLayoutFlush && (aType < Flush_InterruptibleLayout);
    6337                 :       // mInFlush is a bitfield, so can't us AutoRestore here.  But we
    6338                 :       // need to keep track of multi-level reentry correctly, so need
    6339                 :       // to restore the old mInFlush value.
    6340               0 :       bool oldInFlush = mInFlush;
    6341               0 :       mInFlush = true;
    6342               0 :       shell->FlushPendingNotifications(aType);
    6343               0 :       mInFlush = oldInFlush;
    6344                 :     }
    6345                 :   }
    6346                 : }
    6347                 : 
    6348                 : static bool
    6349               0 : Flush(nsIDocument* aDocument, void* aData)
    6350                 : {
    6351               0 :   const mozFlushType* type = static_cast<const mozFlushType*>(aData);
    6352               0 :   aDocument->FlushPendingNotifications(*type);
    6353               0 :   return true;
    6354                 : }
    6355                 : 
    6356                 : void
    6357               0 : nsDocument::FlushExternalResources(mozFlushType aType)
    6358                 : {
    6359               0 :   NS_ASSERTION(aType >= Flush_Style,
    6360                 :     "should only need to flush for style or higher in external resources");
    6361                 : 
    6362               0 :   if (GetDisplayDocument()) {
    6363               0 :     return;
    6364                 :   }
    6365               0 :   EnumerateExternalResources(Flush, &aType);
    6366                 : }
    6367                 : 
    6368                 : void
    6369             825 : nsDocument::SetXMLDeclaration(const PRUnichar *aVersion,
    6370                 :                               const PRUnichar *aEncoding,
    6371                 :                               const PRInt32 aStandalone)
    6372                 : {
    6373             825 :   if (!aVersion || *aVersion == '\0') {
    6374               0 :     mXMLDeclarationBits = 0;
    6375               0 :     return;
    6376                 :   }
    6377                 : 
    6378             825 :   mXMLDeclarationBits = XML_DECLARATION_BITS_DECLARATION_EXISTS;
    6379                 : 
    6380             825 :   if (aEncoding && *aEncoding != '\0') {
    6381             630 :     mXMLDeclarationBits |= XML_DECLARATION_BITS_ENCODING_EXISTS;
    6382                 :   }
    6383                 : 
    6384             825 :   if (aStandalone == 1) {
    6385                 :     mXMLDeclarationBits |= XML_DECLARATION_BITS_STANDALONE_EXISTS |
    6386               0 :                            XML_DECLARATION_BITS_STANDALONE_YES;
    6387                 :   }
    6388             825 :   else if (aStandalone == 0) {
    6389               0 :     mXMLDeclarationBits |= XML_DECLARATION_BITS_STANDALONE_EXISTS;
    6390                 :   }
    6391                 : }
    6392                 : 
    6393                 : void
    6394              75 : nsDocument::GetXMLDeclaration(nsAString& aVersion, nsAString& aEncoding,
    6395                 :                               nsAString& aStandalone)
    6396                 : {
    6397              75 :   aVersion.Truncate();
    6398              75 :   aEncoding.Truncate();
    6399              75 :   aStandalone.Truncate();
    6400                 : 
    6401              75 :   if (!(mXMLDeclarationBits & XML_DECLARATION_BITS_DECLARATION_EXISTS)) {
    6402              46 :     return;
    6403                 :   }
    6404                 : 
    6405                 :   // always until we start supporting 1.1 etc.
    6406              29 :   aVersion.AssignLiteral("1.0");
    6407                 : 
    6408              29 :   if (mXMLDeclarationBits & XML_DECLARATION_BITS_ENCODING_EXISTS) {
    6409                 :     // This is what we have stored, not necessarily what was written
    6410                 :     // in the original
    6411              28 :     GetCharacterSet(aEncoding);
    6412                 :   }
    6413                 : 
    6414              29 :   if (mXMLDeclarationBits & XML_DECLARATION_BITS_STANDALONE_EXISTS) {
    6415               0 :     if (mXMLDeclarationBits & XML_DECLARATION_BITS_STANDALONE_YES) {
    6416               0 :       aStandalone.AssignLiteral("yes");
    6417                 :     } else {
    6418               0 :       aStandalone.AssignLiteral("no");
    6419                 :     }
    6420                 :   }
    6421                 : }
    6422                 : 
    6423                 : bool
    6424               0 : nsDocument::IsScriptEnabled()
    6425                 : {
    6426               0 :   nsCOMPtr<nsIScriptSecurityManager> sm(do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID));
    6427               0 :   NS_ENSURE_TRUE(sm, false);
    6428                 : 
    6429               0 :   nsIScriptGlobalObject* globalObject = GetScriptGlobalObject();
    6430               0 :   NS_ENSURE_TRUE(globalObject, false);
    6431                 : 
    6432               0 :   nsIScriptContext *scriptContext = globalObject->GetContext();
    6433               0 :   NS_ENSURE_TRUE(scriptContext, false);
    6434                 : 
    6435               0 :   JSContext* cx = scriptContext->GetNativeContext();
    6436               0 :   NS_ENSURE_TRUE(cx, false);
    6437                 : 
    6438                 :   bool enabled;
    6439               0 :   nsresult rv = sm->CanExecuteScripts(cx, NodePrincipal(), &enabled);
    6440               0 :   NS_ENSURE_SUCCESS(rv, false);
    6441               0 :   return enabled;
    6442                 : }
    6443                 : 
    6444                 : nsresult
    6445               0 : nsDocument::GetRadioGroup(const nsAString& aName,
    6446                 :                           nsRadioGroupStruct **aRadioGroup)
    6447                 : {
    6448               0 :   nsAutoString tmKey(aName);
    6449               0 :   if(IsHTML())
    6450               0 :      ToLowerCase(tmKey); //should case-insensitive.
    6451               0 :   if (mRadioGroups.Get(tmKey, aRadioGroup))
    6452               0 :     return NS_OK;
    6453                 : 
    6454               0 :   nsAutoPtr<nsRadioGroupStruct> radioGroup(new nsRadioGroupStruct());
    6455               0 :   NS_ENSURE_TRUE(radioGroup, NS_ERROR_OUT_OF_MEMORY);
    6456               0 :   NS_ENSURE_TRUE(mRadioGroups.Put(tmKey, radioGroup), NS_ERROR_OUT_OF_MEMORY);
    6457                 : 
    6458               0 :   *aRadioGroup = radioGroup;
    6459               0 :   radioGroup.forget();
    6460                 : 
    6461               0 :   return NS_OK;
    6462                 : }
    6463                 : 
    6464                 : NS_IMETHODIMP
    6465               0 : nsDocument::SetCurrentRadioButton(const nsAString& aName,
    6466                 :                                   nsIDOMHTMLInputElement* aRadio)
    6467                 : {
    6468               0 :   nsRadioGroupStruct* radioGroup = nsnull;
    6469               0 :   GetRadioGroup(aName, &radioGroup);
    6470               0 :   if (radioGroup) {
    6471               0 :     radioGroup->mSelectedRadioButton = aRadio;
    6472                 :   }
    6473                 : 
    6474               0 :   return NS_OK;
    6475                 : }
    6476                 : 
    6477                 : NS_IMETHODIMP
    6478               0 : nsDocument::GetCurrentRadioButton(const nsAString& aName,
    6479                 :                                   nsIDOMHTMLInputElement** aRadio)
    6480                 : {
    6481               0 :   nsRadioGroupStruct* radioGroup = nsnull;
    6482               0 :   GetRadioGroup(aName, &radioGroup);
    6483               0 :   if (radioGroup) {
    6484               0 :     *aRadio = radioGroup->mSelectedRadioButton;
    6485               0 :     NS_IF_ADDREF(*aRadio);
    6486                 :   }
    6487                 : 
    6488               0 :   return NS_OK;
    6489                 : }
    6490                 : 
    6491                 : NS_IMETHODIMP
    6492               0 : nsDocument::GetPositionInGroup(nsIDOMHTMLInputElement *aRadio,
    6493                 :                                PRInt32 *aPositionIndex,
    6494                 :                                PRInt32 *aItemsInGroup)
    6495                 : {
    6496               0 :   *aPositionIndex = 0;
    6497               0 :   *aItemsInGroup = 1;
    6498               0 :   nsAutoString name;
    6499               0 :   aRadio->GetName(name);
    6500               0 :   if (name.IsEmpty()) {
    6501               0 :     return NS_OK;
    6502                 :   }
    6503                 : 
    6504               0 :   nsRadioGroupStruct* radioGroup = nsnull;
    6505               0 :   nsresult rv = GetRadioGroup(name, &radioGroup);
    6506               0 :   NS_ENSURE_SUCCESS(rv, rv);
    6507                 : 
    6508               0 :   nsCOMPtr<nsIFormControl> radioControl(do_QueryInterface(aRadio));
    6509               0 :   NS_ASSERTION(radioControl, "Radio button should implement nsIFormControl");
    6510               0 :   *aPositionIndex = radioGroup->mRadioButtons.IndexOf(radioControl);
    6511               0 :   NS_ASSERTION(*aPositionIndex >= 0, "Radio button not found in its own group");
    6512               0 :   *aItemsInGroup = radioGroup->mRadioButtons.Count();
    6513                 : 
    6514               0 :   return NS_OK;
    6515                 : }
    6516                 : 
    6517                 : NS_IMETHODIMP
    6518               0 : nsDocument::GetNextRadioButton(const nsAString& aName,
    6519                 :                                const bool aPrevious,
    6520                 :                                nsIDOMHTMLInputElement*  aFocusedRadio,
    6521                 :                                nsIDOMHTMLInputElement** aRadioOut)
    6522                 : {
    6523                 :   // XXX Can we combine the HTML radio button method impls of 
    6524                 :   //     nsDocument and nsHTMLFormControl?
    6525                 :   // XXX Why is HTML radio button stuff in nsDocument, as 
    6526                 :   //     opposed to nsHTMLDocument?
    6527               0 :   *aRadioOut = nsnull;
    6528                 : 
    6529               0 :   nsRadioGroupStruct* radioGroup = nsnull;
    6530               0 :   GetRadioGroup(aName, &radioGroup);
    6531               0 :   if (!radioGroup) {
    6532               0 :     return NS_ERROR_FAILURE;
    6533                 :   }
    6534                 : 
    6535                 :   // Return the radio button relative to the focused radio button.
    6536                 :   // If no radio is focused, get the radio relative to the selected one.
    6537               0 :   nsCOMPtr<nsIDOMHTMLInputElement> currentRadio;
    6538               0 :   if (aFocusedRadio) {
    6539               0 :     currentRadio = aFocusedRadio;
    6540                 :   }
    6541                 :   else {
    6542               0 :     currentRadio = radioGroup->mSelectedRadioButton;
    6543               0 :     if (!currentRadio) {
    6544               0 :       return NS_ERROR_FAILURE;
    6545                 :     }
    6546                 :   }
    6547               0 :   nsCOMPtr<nsIFormControl> radioControl(do_QueryInterface(currentRadio));
    6548               0 :   PRInt32 index = radioGroup->mRadioButtons.IndexOf(radioControl);
    6549               0 :   if (index < 0) {
    6550               0 :     return NS_ERROR_FAILURE;
    6551                 :   }
    6552                 : 
    6553               0 :   PRInt32 numRadios = radioGroup->mRadioButtons.Count();
    6554                 :   bool disabled;
    6555               0 :   nsCOMPtr<nsIDOMHTMLInputElement> radio;
    6556               0 :   do {
    6557               0 :     if (aPrevious) {
    6558               0 :       if (--index < 0) {
    6559               0 :         index = numRadios -1;
    6560                 :       }
    6561                 :     }
    6562               0 :     else if (++index >= numRadios) {
    6563               0 :       index = 0;
    6564                 :     }
    6565               0 :     radio = do_QueryInterface(radioGroup->mRadioButtons[index]);
    6566               0 :     NS_ASSERTION(radio, "mRadioButtons holding a non-radio button");
    6567               0 :     radio->GetDisabled(&disabled);
    6568               0 :   } while (disabled && radio != currentRadio);
    6569                 : 
    6570               0 :   NS_IF_ADDREF(*aRadioOut = radio);
    6571               0 :   return NS_OK;
    6572                 : }
    6573                 : 
    6574                 : NS_IMETHODIMP
    6575               0 : nsDocument::AddToRadioGroup(const nsAString& aName,
    6576                 :                             nsIFormControl* aRadio)
    6577                 : {
    6578               0 :   nsRadioGroupStruct* radioGroup = nsnull;
    6579               0 :   GetRadioGroup(aName, &radioGroup);
    6580               0 :   if (radioGroup) {
    6581               0 :     radioGroup->mRadioButtons.AppendObject(aRadio);
    6582                 : 
    6583               0 :     nsCOMPtr<nsIContent> element = do_QueryInterface(aRadio);
    6584               0 :     NS_ASSERTION(element, "radio controls have to be content elements");
    6585               0 :     if (element->HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
    6586               0 :       radioGroup->mRequiredRadioCount++;
    6587                 :     }
    6588                 :   }
    6589                 : 
    6590               0 :   return NS_OK;
    6591                 : }
    6592                 : 
    6593                 : NS_IMETHODIMP
    6594               0 : nsDocument::RemoveFromRadioGroup(const nsAString& aName,
    6595                 :                                  nsIFormControl* aRadio)
    6596                 : {
    6597               0 :   nsRadioGroupStruct* radioGroup = nsnull;
    6598               0 :   GetRadioGroup(aName, &radioGroup);
    6599               0 :   if (radioGroup) {
    6600               0 :     radioGroup->mRadioButtons.RemoveObject(aRadio);
    6601                 : 
    6602               0 :     nsCOMPtr<nsIContent> element = do_QueryInterface(aRadio);
    6603               0 :     NS_ASSERTION(element, "radio controls have to be content elements");
    6604               0 :     if (element->HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
    6605               0 :       radioGroup->mRequiredRadioCount--;
    6606                 :       NS_ASSERTION(radioGroup->mRequiredRadioCount >= 0,
    6607                 :                    "mRequiredRadioCount shouldn't be negative!");
    6608                 :     }
    6609                 :   }
    6610                 : 
    6611               0 :   return NS_OK;
    6612                 : }
    6613                 : 
    6614                 : NS_IMETHODIMP
    6615               0 : nsDocument::WalkRadioGroup(const nsAString& aName,
    6616                 :                            nsIRadioVisitor* aVisitor,
    6617                 :                            bool aFlushContent)
    6618                 : {
    6619               0 :   nsRadioGroupStruct* radioGroup = nsnull;
    6620               0 :   GetRadioGroup(aName, &radioGroup);
    6621               0 :   if (!radioGroup) {
    6622               0 :     return NS_OK;
    6623                 :   }
    6624                 : 
    6625               0 :   for (int i = 0; i < radioGroup->mRadioButtons.Count(); i++) {
    6626               0 :     if (!aVisitor->Visit(radioGroup->mRadioButtons[i])) {
    6627               0 :       return NS_OK;
    6628                 :     }
    6629                 :   }
    6630                 : 
    6631               0 :   return NS_OK;
    6632                 : }
    6633                 : 
    6634                 : PRUint32
    6635               0 : nsDocument::GetRequiredRadioCount(const nsAString& aName) const
    6636                 : {
    6637               0 :   nsRadioGroupStruct* radioGroup = nsnull;
    6638                 :   // TODO: we should call GetRadioGroup here (and make it const) but for that
    6639                 :   // we would need to have an explicit CreateRadioGroup() instead of create
    6640                 :   // one when GetRadioGroup is called. See bug 636123.
    6641               0 :   nsAutoString tmKey(aName);
    6642               0 :   if (IsHTML())
    6643               0 :      ToLowerCase(tmKey); //should case-insensitive.
    6644               0 :   mRadioGroups.Get(tmKey, &radioGroup);
    6645                 : 
    6646               0 :   return radioGroup ? radioGroup->mRequiredRadioCount : 0;
    6647                 : }
    6648                 : 
    6649                 : void
    6650               0 : nsDocument::RadioRequiredChanged(const nsAString& aName, nsIFormControl* aRadio)
    6651                 : {
    6652               0 :   nsRadioGroupStruct* radioGroup = nsnull;
    6653               0 :   GetRadioGroup(aName, &radioGroup);
    6654                 : 
    6655               0 :   if (!radioGroup) {
    6656               0 :     return;
    6657                 :   }
    6658                 : 
    6659               0 :   nsCOMPtr<nsIContent> element = do_QueryInterface(aRadio);
    6660               0 :   NS_ASSERTION(element, "radio controls have to be content elements");
    6661               0 :   if (element->HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
    6662               0 :     radioGroup->mRequiredRadioCount++;
    6663                 :   } else {
    6664               0 :     radioGroup->mRequiredRadioCount--;
    6665                 :     NS_ASSERTION(radioGroup->mRequiredRadioCount >= 0,
    6666                 :                  "mRequiredRadioCount shouldn't be negative!");
    6667                 :   }
    6668                 : }
    6669                 : 
    6670                 : bool
    6671               0 : nsDocument::GetValueMissingState(const nsAString& aName) const
    6672                 : {
    6673               0 :   nsRadioGroupStruct* radioGroup = nsnull;
    6674                 :   // TODO: we should call GetRadioGroup here (and make it const) but for that
    6675                 :   // we would need to have an explicit CreateRadioGroup() instead of create
    6676                 :   // one when GetRadioGroup is called. See bug 636123.
    6677               0 :   nsAutoString tmKey(aName);
    6678               0 :   if (IsHTML())
    6679               0 :      ToLowerCase(tmKey); //should case-insensitive.
    6680               0 :   mRadioGroups.Get(tmKey, &radioGroup);
    6681                 : 
    6682               0 :   return radioGroup && radioGroup->mGroupSuffersFromValueMissing;
    6683                 : }
    6684                 : 
    6685                 : void
    6686               0 : nsDocument::SetValueMissingState(const nsAString& aName, bool aValue)
    6687                 : {
    6688               0 :   nsRadioGroupStruct* radioGroup = nsnull;
    6689               0 :   GetRadioGroup(aName, &radioGroup);
    6690                 : 
    6691               0 :   if (!radioGroup) {
    6692               0 :     return;
    6693                 :   }
    6694                 : 
    6695               0 :   radioGroup->mGroupSuffersFromValueMissing = aValue;
    6696                 : }
    6697                 : 
    6698                 : void
    6699            1038 : nsDocument::RetrieveRelevantHeaders(nsIChannel *aChannel)
    6700                 : {
    6701            2076 :   nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
    6702            1038 :   PRTime modDate = LL_ZERO;
    6703                 :   nsresult rv;
    6704                 : 
    6705            1038 :   if (httpChannel) {
    6706             934 :     nsCAutoString tmp;
    6707             934 :     rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("last-modified"),
    6708             467 :                                         tmp);
    6709                 : 
    6710             467 :     if (NS_SUCCEEDED(rv)) {
    6711                 :       PRTime time;
    6712             361 :       PRStatus st = PR_ParseTimeString(tmp.get(), true, &time);
    6713             361 :       if (st == PR_SUCCESS) {
    6714             361 :         modDate = time;
    6715                 :       }
    6716                 :     }
    6717                 : 
    6718                 :     // The misspelled key 'referer' is as per the HTTP spec
    6719             934 :     rv = httpChannel->GetRequestHeader(NS_LITERAL_CSTRING("referer"),
    6720             467 :                                        mReferrer);
    6721             467 :     if (NS_FAILED(rv)) {
    6722             467 :       mReferrer.Truncate();
    6723                 :     }
    6724                 : 
    6725                 :     static const char *const headers[] = {
    6726                 :       "default-style",
    6727                 :       "content-style-type",
    6728                 :       "content-language",
    6729                 :       "content-disposition",
    6730                 :       "refresh",
    6731                 :       "x-dns-prefetch-control",
    6732                 :       "x-content-security-policy",
    6733                 :       "x-content-security-policy-report-only",
    6734                 :       "x-frame-options",
    6735                 :       // add more http headers if you need
    6736                 :       // XXXbz don't add content-location support without reading bug
    6737                 :       // 238654 and its dependencies/dups first.
    6738                 :       0
    6739                 :     };
    6740                 :     
    6741             934 :     nsCAutoString headerVal;
    6742             467 :     const char *const *name = headers;
    6743            5137 :     while (*name) {
    6744                 :       rv =
    6745            4203 :         httpChannel->GetResponseHeader(nsDependentCString(*name), headerVal);
    6746            4203 :       if (NS_SUCCEEDED(rv) && !headerVal.IsEmpty()) {
    6747               8 :         nsCOMPtr<nsIAtom> key = do_GetAtom(*name);
    6748               4 :         SetHeaderData(key, NS_ConvertASCIItoUTF16(headerVal));
    6749                 :       }
    6750            4203 :       ++name;
    6751                 :     }
    6752                 :   } else {
    6753            1142 :     nsCOMPtr<nsIFileChannel> fileChannel = do_QueryInterface(aChannel);
    6754             571 :     if (fileChannel) {
    6755               0 :       nsCOMPtr<nsIFile> file;
    6756               0 :       fileChannel->GetFile(getter_AddRefs(file));
    6757               0 :       if (file) {
    6758                 :         PRTime msecs;
    6759               0 :         rv = file->GetLastModifiedTime(&msecs);
    6760                 : 
    6761               0 :         if (NS_SUCCEEDED(rv)) {
    6762                 :           PRInt64 intermediateValue;
    6763               0 :           LL_I2L(intermediateValue, PR_USEC_PER_MSEC);
    6764               0 :           LL_MUL(modDate, msecs, intermediateValue);
    6765                 :         }
    6766                 :       }
    6767                 :     } else {
    6768            1142 :       nsCAutoString contentDisp;
    6769             571 :       rv = aChannel->GetContentDispositionHeader(contentDisp);
    6770             571 :       if (NS_SUCCEEDED(rv)) {
    6771                 :         SetHeaderData(nsGkAtoms::headerContentDisposition,
    6772               0 :                       NS_ConvertASCIItoUTF16(contentDisp));
    6773                 :       }
    6774                 :     }
    6775                 :   }
    6776                 : 
    6777            1038 :   if (LL_IS_ZERO(modDate)) {
    6778                 :     // We got nothing from our attempt to ask nsIFileChannel and
    6779                 :     // nsIHttpChannel for the last modified time. Return the current
    6780                 :     // time.
    6781             677 :     modDate = PR_Now();
    6782                 :   }
    6783                 : 
    6784            1038 :   mLastModified.Truncate();
    6785            1038 :   if (LL_NE(modDate, LL_ZERO)) {
    6786                 :     PRExplodedTime prtime;
    6787            1038 :     PR_ExplodeTime(modDate, PR_LocalTimeParameters, &prtime);
    6788                 :     // "MM/DD/YYYY hh:mm:ss"
    6789                 :     char formatedTime[24];
    6790            1038 :     if (PR_snprintf(formatedTime, sizeof(formatedTime),
    6791                 :                     "%02ld/%02ld/%04hd %02ld:%02ld:%02ld",
    6792                 :                     prtime.tm_month + 1, prtime.tm_mday, prtime.tm_year,
    6793            1038 :                     prtime.tm_hour     ,  prtime.tm_min,  prtime.tm_sec)) {
    6794            1038 :       CopyASCIItoUTF16(nsDependentCString(formatedTime), mLastModified);
    6795                 :     }
    6796                 :   }
    6797            1038 : }
    6798                 : 
    6799                 : nsresult
    6800               8 : nsDocument::CreateElem(const nsAString& aName, nsIAtom *aPrefix, PRInt32 aNamespaceID,
    6801                 :                        nsIContent **aResult)
    6802                 : {
    6803                 : #ifdef DEBUG
    6804              16 :   nsAutoString qName;
    6805               8 :   if (aPrefix) {
    6806               0 :     aPrefix->ToString(qName);
    6807               0 :     qName.Append(':');
    6808                 :   }
    6809               8 :   qName.Append(aName);
    6810                 : 
    6811                 :   // Note: "a:b:c" is a valid name in non-namespaces XML, and
    6812                 :   // nsDocument::CreateElement can call us with such a name and no prefix,
    6813                 :   // which would cause an error if we just used true here.
    6814               8 :   bool nsAware = aPrefix != nsnull || aNamespaceID != GetDefaultNamespaceID();
    6815               8 :   NS_ASSERTION(NS_SUCCEEDED(nsContentUtils::CheckQName(qName, nsAware)),
    6816                 :                "Don't pass invalid prefixes to nsDocument::CreateElem, "
    6817                 :                "check caller.");
    6818                 : #endif
    6819                 : 
    6820               8 :   *aResult = nsnull;
    6821                 :   
    6822              16 :   nsCOMPtr<nsINodeInfo> nodeInfo;
    6823                 :   mNodeInfoManager->GetNodeInfo(aName, aPrefix, aNamespaceID,
    6824                 :                                 nsIDOMNode::ELEMENT_NODE,
    6825               8 :                                 getter_AddRefs(nodeInfo));
    6826               8 :   NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
    6827                 : 
    6828               8 :   return NS_NewElement(aResult, nodeInfo.forget(), NOT_FROM_PARSER);
    6829                 : }
    6830                 : 
    6831                 : bool
    6832               0 : nsDocument::IsSafeToFlush() const
    6833                 : {
    6834               0 :   nsIPresShell* shell = GetShell();
    6835               0 :   if (!shell)
    6836               0 :     return true;
    6837                 : 
    6838               0 :   return shell->IsSafeToFlush();
    6839                 : }
    6840                 : 
    6841                 : nsresult
    6842               0 : nsDocument::Sanitize()
    6843                 : {
    6844                 :   // Sanitize the document by resetting all password fields and any form
    6845                 :   // fields with autocomplete=off to their default values.  We do this now,
    6846                 :   // instead of when the presentation is restored, to offer some protection
    6847                 :   // in case there is ever an exploit that allows a cached document to be
    6848                 :   // accessed from a different document.
    6849                 : 
    6850                 :   // First locate all input elements, regardless of whether they are
    6851                 :   // in a form, and reset the password and autocomplete=off elements.
    6852                 : 
    6853               0 :   nsCOMPtr<nsIDOMNodeList> nodes;
    6854               0 :   nsresult rv = GetElementsByTagName(NS_LITERAL_STRING("input"),
    6855               0 :                                      getter_AddRefs(nodes));
    6856               0 :   NS_ENSURE_SUCCESS(rv, rv);
    6857                 : 
    6858               0 :   PRUint32 length = 0;
    6859               0 :   if (nodes)
    6860               0 :     nodes->GetLength(&length);
    6861                 : 
    6862               0 :   nsCOMPtr<nsIDOMNode> item;
    6863               0 :   nsAutoString value;
    6864                 :   PRUint32 i;
    6865                 : 
    6866               0 :   for (i = 0; i < length; ++i) {
    6867               0 :     nodes->Item(i, getter_AddRefs(item));
    6868               0 :     NS_ASSERTION(item, "null item in node list!");
    6869                 : 
    6870               0 :     nsCOMPtr<nsIDOMHTMLInputElement> input = do_QueryInterface(item);
    6871               0 :     if (!input)
    6872               0 :       continue;
    6873                 : 
    6874               0 :     bool resetValue = false;
    6875                 : 
    6876               0 :     input->GetAttribute(NS_LITERAL_STRING("autocomplete"), value);
    6877               0 :     if (value.LowerCaseEqualsLiteral("off")) {
    6878               0 :       resetValue = true;
    6879                 :     } else {
    6880               0 :       input->GetType(value);
    6881               0 :       if (value.LowerCaseEqualsLiteral("password"))
    6882               0 :         resetValue = true;
    6883                 :     }
    6884                 : 
    6885               0 :     if (resetValue) {
    6886               0 :       nsCOMPtr<nsIFormControl> fc = do_QueryInterface(input);
    6887               0 :       fc->Reset();
    6888                 :     }
    6889                 :   }
    6890                 : 
    6891                 :   // Now locate all _form_ elements that have autocomplete=off and reset them
    6892               0 :   rv = GetElementsByTagName(NS_LITERAL_STRING("form"), getter_AddRefs(nodes));
    6893               0 :   NS_ENSURE_SUCCESS(rv, rv);
    6894                 : 
    6895               0 :   length = 0;
    6896               0 :   if (nodes)
    6897               0 :     nodes->GetLength(&length);
    6898                 : 
    6899               0 :   for (i = 0; i < length; ++i) {
    6900               0 :     nodes->Item(i, getter_AddRefs(item));
    6901               0 :     NS_ASSERTION(item, "null item in nodelist");
    6902                 : 
    6903               0 :     nsCOMPtr<nsIDOMHTMLFormElement> form = do_QueryInterface(item);
    6904               0 :     if (!form)
    6905               0 :       continue;
    6906                 : 
    6907               0 :     form->GetAttribute(NS_LITERAL_STRING("autocomplete"), value);
    6908               0 :     if (value.LowerCaseEqualsLiteral("off"))
    6909               0 :       form->Reset();
    6910                 :   }
    6911                 : 
    6912               0 :   return NS_OK;
    6913                 : }
    6914                 : 
    6915                 : struct SubDocEnumArgs
    6916                 : {
    6917                 :   nsIDocument::nsSubDocEnumFunc callback;
    6918                 :   void *data;
    6919                 : };
    6920                 : 
    6921                 : static PLDHashOperator
    6922               0 : SubDocHashEnum(PLDHashTable *table, PLDHashEntryHdr *hdr,
    6923                 :                PRUint32 number, void *arg)
    6924                 : {
    6925               0 :   SubDocMapEntry *entry = static_cast<SubDocMapEntry*>(hdr);
    6926               0 :   SubDocEnumArgs *args = static_cast<SubDocEnumArgs*>(arg);
    6927                 : 
    6928               0 :   nsIDocument *subdoc = entry->mSubDocument;
    6929               0 :   bool next = subdoc ? args->callback(subdoc, args->data) : true;
    6930                 : 
    6931               0 :   return next ? PL_DHASH_NEXT : PL_DHASH_STOP;
    6932                 : }
    6933                 : 
    6934                 : void
    6935               0 : nsDocument::EnumerateSubDocuments(nsSubDocEnumFunc aCallback, void *aData)
    6936                 : {
    6937               0 :   if (mSubDocuments) {
    6938               0 :     SubDocEnumArgs args = { aCallback, aData };
    6939               0 :     PL_DHashTableEnumerate(mSubDocuments, SubDocHashEnum, &args);
    6940                 :   }
    6941               0 : }
    6942                 : 
    6943                 : static PLDHashOperator
    6944               0 : CanCacheSubDocument(PLDHashTable *table, PLDHashEntryHdr *hdr,
    6945                 :                     PRUint32 number, void *arg)
    6946                 : {
    6947               0 :   SubDocMapEntry *entry = static_cast<SubDocMapEntry*>(hdr);
    6948               0 :   bool *canCacheArg = static_cast<bool*>(arg);
    6949                 : 
    6950               0 :   nsIDocument *subdoc = entry->mSubDocument;
    6951                 : 
    6952                 :   // The aIgnoreRequest we were passed is only for us, so don't pass it on.
    6953               0 :   bool canCache = subdoc ? subdoc->CanSavePresentation(nsnull) : false;
    6954               0 :   if (!canCache) {
    6955               0 :     *canCacheArg = false;
    6956               0 :     return PL_DHASH_STOP;
    6957                 :   }
    6958                 : 
    6959               0 :   return PL_DHASH_NEXT;
    6960                 : }
    6961                 : 
    6962                 : #ifdef DEBUG_bryner
    6963                 : #define DEBUG_PAGE_CACHE
    6964                 : #endif
    6965                 : 
    6966                 : bool
    6967               0 : nsDocument::CanSavePresentation(nsIRequest *aNewRequest)
    6968                 : {
    6969               0 :   if (EventHandlingSuppressed()) {
    6970               0 :     return false;
    6971                 :   }
    6972                 : 
    6973               0 :   nsPIDOMWindow* win = GetInnerWindow();
    6974               0 :   if (win && win->TimeoutSuspendCount()) {
    6975               0 :     return false;
    6976                 :   }
    6977                 : 
    6978                 :   // Check our event listener manager for unload/beforeunload listeners.
    6979               0 :   nsCOMPtr<nsIDOMEventTarget> piTarget = do_QueryInterface(mScriptGlobalObject);
    6980               0 :   if (piTarget) {
    6981                 :     nsEventListenerManager* manager =
    6982               0 :       piTarget->GetListenerManager(false);
    6983               0 :     if (manager && manager->HasUnloadListeners()) {
    6984               0 :       return false;
    6985                 :     }
    6986                 :   }
    6987                 : 
    6988                 :   // Check if we have pending network requests
    6989               0 :   nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
    6990               0 :   if (loadGroup) {
    6991               0 :     nsCOMPtr<nsISimpleEnumerator> requests;
    6992               0 :     loadGroup->GetRequests(getter_AddRefs(requests));
    6993                 : 
    6994               0 :     bool hasMore = false;
    6995                 : 
    6996                 :     // We want to bail out if we have any requests other than aNewRequest (or
    6997                 :     // in the case when aNewRequest is a part of a multipart response the base
    6998                 :     // channel the multipart response is coming in on).
    6999               0 :     nsCOMPtr<nsIChannel> baseChannel;
    7000               0 :     nsCOMPtr<nsIMultiPartChannel> part(do_QueryInterface(aNewRequest));
    7001               0 :     if (part) {
    7002               0 :       part->GetBaseChannel(getter_AddRefs(baseChannel));
    7003                 :     }
    7004                 : 
    7005               0 :     while (NS_SUCCEEDED(requests->HasMoreElements(&hasMore)) && hasMore) {
    7006               0 :       nsCOMPtr<nsISupports> elem;
    7007               0 :       requests->GetNext(getter_AddRefs(elem));
    7008                 : 
    7009               0 :       nsCOMPtr<nsIRequest> request = do_QueryInterface(elem);
    7010               0 :       if (request && request != aNewRequest && request != baseChannel) {
    7011                 : #ifdef DEBUG_PAGE_CACHE
    7012                 :         nsCAutoString requestName, docSpec;
    7013                 :         request->GetName(requestName);
    7014                 :         if (mDocumentURI)
    7015                 :           mDocumentURI->GetSpec(docSpec);
    7016                 : 
    7017                 :         printf("document %s has request %s\n",
    7018                 :                docSpec.get(), requestName.get());
    7019                 : #endif
    7020               0 :         return false;
    7021                 :       }
    7022                 :     }
    7023                 :   }
    7024                 : 
    7025                 :   // Check if we have running IndexedDB transactions
    7026                 :   indexedDB::IndexedDatabaseManager* idbManager =
    7027               0 :     indexedDB::IndexedDatabaseManager::Get();
    7028               0 :   if (idbManager && idbManager->HasOpenTransactions(win)) {
    7029               0 :     return false;
    7030                 :   }
    7031                 : 
    7032               0 :   bool canCache = true;
    7033               0 :   if (mSubDocuments)
    7034               0 :     PL_DHashTableEnumerate(mSubDocuments, CanCacheSubDocument, &canCache);
    7035                 : 
    7036               0 :   return canCache;
    7037                 : }
    7038                 : 
    7039                 : void
    7040               0 : nsDocument::Destroy()
    7041                 : {
    7042                 :   // The ContentViewer wants to release the document now.  So, tell our content
    7043                 :   // to drop any references to the document so that it can be destroyed.
    7044               0 :   if (mIsGoingAway)
    7045               0 :     return;
    7046                 : 
    7047               0 :   mIsGoingAway = true;
    7048                 : 
    7049               0 :   RemovedFromDocShell();
    7050                 : 
    7051               0 :   bool oldVal = mInUnlinkOrDeletion;
    7052               0 :   mInUnlinkOrDeletion = true;
    7053               0 :   PRUint32 i, count = mChildren.ChildCount();
    7054               0 :   for (i = 0; i < count; ++i) {
    7055               0 :     mChildren.ChildAt(i)->DestroyContent();
    7056                 :   }
    7057               0 :   mInUnlinkOrDeletion = oldVal;
    7058                 : 
    7059               0 :   mLayoutHistoryState = nsnull;
    7060                 : 
    7061                 :   // Shut down our external resource map.  We might not need this for
    7062                 :   // leak-fixing if we fix DocumentViewerImpl to do cycle-collection, but
    7063                 :   // tearing down all those frame trees right now is the right thing to do.
    7064               0 :   mExternalResourceMap.Shutdown();
    7065                 : 
    7066                 :   // XXX We really should let cycle collection do this, but that currently still
    7067                 :   //     leaks (see https://bugzilla.mozilla.org/show_bug.cgi?id=406684).
    7068               0 :   nsContentUtils::ReleaseWrapper(static_cast<nsINode*>(this), this);
    7069                 : }
    7070                 : 
    7071                 : void
    7072               0 : nsDocument::RemovedFromDocShell()
    7073                 : {
    7074               0 :   if (mRemovedFromDocShell)
    7075               0 :     return;
    7076                 : 
    7077               0 :   mRemovedFromDocShell = true;
    7078               0 :   EnumerateFreezableElements(NotifyActivityChanged, nsnull); 
    7079                 : 
    7080               0 :   PRUint32 i, count = mChildren.ChildCount();
    7081               0 :   for (i = 0; i < count; ++i) {
    7082               0 :     mChildren.ChildAt(i)->SaveSubtreeState();
    7083                 :   }
    7084                 : }
    7085                 : 
    7086                 : already_AddRefed<nsILayoutHistoryState>
    7087               1 : nsDocument::GetLayoutHistoryState() const
    7088                 : {
    7089               1 :   nsILayoutHistoryState* state = nsnull;
    7090               1 :   if (!mScriptGlobalObject) {
    7091               1 :     NS_IF_ADDREF(state = mLayoutHistoryState);
    7092                 :   } else {
    7093               0 :     nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocumentContainer));
    7094               0 :     if (docShell) {
    7095               0 :       docShell->GetLayoutHistoryState(&state);
    7096                 :     }
    7097                 :   }
    7098                 : 
    7099               1 :   return state;
    7100                 : }
    7101                 : 
    7102                 : void
    7103               0 : nsDocument::EnsureOnloadBlocker()
    7104                 : {
    7105                 :   // If mScriptGlobalObject is null, we shouldn't be messing with the loadgroup
    7106                 :   // -- it's not ours.
    7107               0 :   if (mOnloadBlockCount != 0 && mScriptGlobalObject) {
    7108               0 :     nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
    7109               0 :     if (loadGroup) {
    7110                 :       // Check first to see if mOnloadBlocker is in the loadgroup.
    7111               0 :       nsCOMPtr<nsISimpleEnumerator> requests;
    7112               0 :       loadGroup->GetRequests(getter_AddRefs(requests));
    7113                 : 
    7114               0 :       bool hasMore = false;
    7115               0 :       while (NS_SUCCEEDED(requests->HasMoreElements(&hasMore)) && hasMore) {
    7116               0 :         nsCOMPtr<nsISupports> elem;
    7117               0 :         requests->GetNext(getter_AddRefs(elem));
    7118               0 :         nsCOMPtr<nsIRequest> request = do_QueryInterface(elem);
    7119               0 :         if (request && request == mOnloadBlocker) {
    7120                 :           return;
    7121                 :         }
    7122                 :       }
    7123                 : 
    7124                 :       // Not in the loadgroup, so add it.
    7125               0 :       loadGroup->AddRequest(mOnloadBlocker, nsnull);
    7126                 :     }
    7127                 :   }
    7128                 : }
    7129                 : 
    7130                 : void
    7131               0 : nsDocument::AsyncBlockOnload()
    7132                 : {
    7133               0 :   while (mAsyncOnloadBlockCount) {
    7134               0 :     --mAsyncOnloadBlockCount;
    7135               0 :     BlockOnload();
    7136                 :   }
    7137               0 : }
    7138                 : 
    7139                 : void
    7140            3114 : nsDocument::BlockOnload()
    7141                 : {
    7142            3114 :   if (mDisplayDocument) {
    7143               0 :     mDisplayDocument->BlockOnload();
    7144               0 :     return;
    7145                 :   }
    7146                 :   
    7147                 :   // If mScriptGlobalObject is null, we shouldn't be messing with the loadgroup
    7148                 :   // -- it's not ours.
    7149            3114 :   if (mOnloadBlockCount == 0 && mScriptGlobalObject) {
    7150               0 :     if (!nsContentUtils::IsSafeToRunScript()) {
    7151                 :       // Because AddRequest may lead to OnStateChange calls in chrome,
    7152                 :       // block onload only when there are no script blockers.
    7153               0 :       ++mAsyncOnloadBlockCount;
    7154               0 :       if (mAsyncOnloadBlockCount == 1) {
    7155                 :         bool success = nsContentUtils::AddScriptRunner(
    7156               0 :           NS_NewRunnableMethod(this, &nsDocument::AsyncBlockOnload));
    7157                 : 
    7158                 :         // The script runner shouldn't fail to add. But if somebody broke
    7159                 :         // something and it does, we'll thrash at 100% cpu forever. The best
    7160                 :         // response is just to ignore the onload blocking request. See bug 579535.
    7161               0 :         if (!success) {
    7162               0 :           NS_WARNING("Disaster! Onload blocking script runner failed to add - expect bad things!");
    7163               0 :           mAsyncOnloadBlockCount = 0;
    7164                 :         }
    7165                 :       }
    7166               0 :       return;
    7167                 :     }
    7168               0 :     nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
    7169               0 :     if (loadGroup) {
    7170               0 :       loadGroup->AddRequest(mOnloadBlocker, nsnull);
    7171                 :     }
    7172                 :   }
    7173            3114 :   ++mOnloadBlockCount;      
    7174                 : }
    7175                 : 
    7176                 : void
    7177            3114 : nsDocument::UnblockOnload(bool aFireSync)
    7178                 : {
    7179            3114 :   if (mDisplayDocument) {
    7180               0 :     mDisplayDocument->UnblockOnload(aFireSync);
    7181               0 :     return;
    7182                 :   }
    7183                 : 
    7184            3114 :   if (mOnloadBlockCount == 0 && mAsyncOnloadBlockCount == 0) {
    7185               0 :     NS_NOTREACHED("More UnblockOnload() calls than BlockOnload() calls; dropping call");
    7186               0 :     return;
    7187                 :   }
    7188                 : 
    7189            3114 :   --mOnloadBlockCount;
    7190                 : 
    7191                 :   // If mScriptGlobalObject is null, we shouldn't be messing with the loadgroup
    7192                 :   // -- it's not ours.
    7193            3114 :   if (mOnloadBlockCount == 0 && mScriptGlobalObject) {
    7194               0 :     if (aFireSync && mAsyncOnloadBlockCount == 0) {
    7195                 :       // Increment mOnloadBlockCount, since DoUnblockOnload will decrement it
    7196               0 :       ++mOnloadBlockCount;
    7197               0 :       DoUnblockOnload();
    7198                 :     } else {
    7199               0 :       PostUnblockOnloadEvent();
    7200                 :     }
    7201                 :   }
    7202                 : }
    7203                 : 
    7204               0 : class nsUnblockOnloadEvent : public nsRunnable {
    7205                 : public:
    7206               0 :   nsUnblockOnloadEvent(nsDocument *doc) : mDoc(doc) {}
    7207               0 :   NS_IMETHOD Run() {
    7208               0 :     mDoc->DoUnblockOnload();
    7209               0 :     return NS_OK;
    7210                 :   }
    7211                 : private:  
    7212                 :   nsRefPtr<nsDocument> mDoc;
    7213                 : };
    7214                 : 
    7215                 : void
    7216               0 : nsDocument::PostUnblockOnloadEvent()
    7217                 : {
    7218               0 :   nsCOMPtr<nsIRunnable> evt = new nsUnblockOnloadEvent(this);
    7219               0 :   nsresult rv = NS_DispatchToCurrentThread(evt);
    7220               0 :   if (NS_SUCCEEDED(rv)) {
    7221                 :     // Stabilize block count so we don't post more events while this one is up
    7222               0 :     ++mOnloadBlockCount;
    7223                 :   } else {
    7224               0 :     NS_WARNING("failed to dispatch nsUnblockOnloadEvent");
    7225                 :   }
    7226               0 : }
    7227                 : 
    7228                 : void
    7229               0 : nsDocument::DoUnblockOnload()
    7230                 : {
    7231               0 :   NS_PRECONDITION(!mDisplayDocument,
    7232                 :                   "Shouldn't get here for resource document");
    7233               0 :   NS_PRECONDITION(mOnloadBlockCount != 0,
    7234                 :                   "Shouldn't have a count of zero here, since we stabilized in "
    7235                 :                   "PostUnblockOnloadEvent");
    7236                 :   
    7237               0 :   --mOnloadBlockCount;
    7238                 : 
    7239               0 :   if (mOnloadBlockCount != 0) {
    7240                 :     // We blocked again after the last unblock.  Nothing to do here.  We'll
    7241                 :     // post a new event when we unblock again.
    7242               0 :     return;
    7243                 :   }
    7244                 : 
    7245               0 :   if (mAsyncOnloadBlockCount != 0) {
    7246                 :     // We need to wait until the async onload block has been handled.
    7247               0 :     PostUnblockOnloadEvent();
    7248                 :   }
    7249                 : 
    7250                 :   // If mScriptGlobalObject is null, we shouldn't be messing with the loadgroup
    7251                 :   // -- it's not ours.
    7252               0 :   if (mScriptGlobalObject) {
    7253               0 :     nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
    7254               0 :     if (loadGroup) {
    7255               0 :       loadGroup->RemoveRequest(mOnloadBlocker, nsnull, NS_OK);
    7256                 :     }
    7257                 :   }
    7258                 : }
    7259                 : 
    7260                 : /* See if document is a child of this.  If so, return the frame element in this
    7261                 :  * document that holds currentDoc (or an ancestor). */
    7262                 : already_AddRefed<nsIDOMElement>
    7263               0 : nsDocument::CheckAncestryAndGetFrame(nsIDocument* aDocument) const
    7264                 : {
    7265                 :   nsIDocument* parentDoc;
    7266               0 :   for (parentDoc = aDocument->GetParentDocument();
    7267                 :        parentDoc != static_cast<const nsIDocument* const>(this);
    7268                 :        parentDoc = parentDoc->GetParentDocument()) {
    7269               0 :     if (!parentDoc) {
    7270               0 :       return nsnull;
    7271                 :     }
    7272                 : 
    7273               0 :     aDocument = parentDoc;
    7274                 :   }
    7275                 : 
    7276                 :   // In a child document.  Get the appropriate frame.
    7277               0 :   nsPIDOMWindow* currentWindow = aDocument->GetWindow();
    7278               0 :   if (!currentWindow) {
    7279               0 :     return nsnull;
    7280                 :   }
    7281               0 :   nsIDOMElement* frameElement = currentWindow->GetFrameElementInternal();
    7282               0 :   if (!frameElement) {
    7283               0 :     return nsnull;
    7284                 :   }
    7285                 : 
    7286                 :   // Sanity check result
    7287               0 :   nsCOMPtr<nsIDOMDocument> domDocument;
    7288               0 :   frameElement->GetOwnerDocument(getter_AddRefs(domDocument));
    7289               0 :   if (domDocument != this) {
    7290               0 :     NS_ERROR("Child documents should live in windows the parent owns");
    7291               0 :     return nsnull;
    7292                 :   }
    7293                 : 
    7294               0 :   NS_ADDREF(frameElement);
    7295               0 :   return frameElement;
    7296                 : }
    7297                 : 
    7298                 : void
    7299               0 : nsDocument::DispatchPageTransition(nsIDOMEventTarget* aDispatchTarget,
    7300                 :                                    const nsAString& aType,
    7301                 :                                    bool aPersisted)
    7302                 : {
    7303               0 :   if (aDispatchTarget) {
    7304               0 :     nsCOMPtr<nsIDOMEvent> event;
    7305               0 :     CreateEvent(NS_LITERAL_STRING("pagetransition"), getter_AddRefs(event));
    7306               0 :     nsCOMPtr<nsIDOMPageTransitionEvent> ptEvent = do_QueryInterface(event);
    7307               0 :     nsCOMPtr<nsIPrivateDOMEvent> pEvent = do_QueryInterface(ptEvent);
    7308               0 :     if (pEvent && NS_SUCCEEDED(ptEvent->InitPageTransitionEvent(aType, true,
    7309                 :                                                                 true,
    7310                 :                                                                 aPersisted))) {
    7311               0 :       pEvent->SetTrusted(true);
    7312               0 :       pEvent->SetTarget(this);
    7313                 :       nsEventDispatcher::DispatchDOMEvent(aDispatchTarget, nsnull, event,
    7314               0 :                                           nsnull, nsnull);
    7315                 :     }
    7316                 :   }
    7317               0 : }
    7318                 : 
    7319                 : static bool
    7320               0 : NotifyPageShow(nsIDocument* aDocument, void* aData)
    7321                 : {
    7322               0 :   const bool* aPersistedPtr = static_cast<const bool*>(aData);
    7323               0 :   aDocument->OnPageShow(*aPersistedPtr, nsnull);
    7324               0 :   return true;
    7325                 : }
    7326                 : 
    7327                 : void
    7328               0 : nsDocument::OnPageShow(bool aPersisted,
    7329                 :                        nsIDOMEventTarget* aDispatchStartTarget)
    7330                 : {
    7331               0 :   mVisible = true;
    7332                 : 
    7333               0 :   EnumerateFreezableElements(NotifyActivityChanged, nsnull);
    7334               0 :   EnumerateExternalResources(NotifyPageShow, &aPersisted);
    7335                 : 
    7336               0 :   Element* root = GetRootElement();
    7337               0 :   if (aPersisted && root) {
    7338                 :     // Send out notifications that our <link> elements are attached.
    7339                 :     nsRefPtr<nsContentList> links = NS_GetContentList(root,
    7340                 :                                                       kNameSpaceID_Unknown,
    7341               0 :                                                       NS_LITERAL_STRING("link"));
    7342                 : 
    7343               0 :     PRUint32 linkCount = links->Length(true);
    7344               0 :     for (PRUint32 i = 0; i < linkCount; ++i) {
    7345               0 :       nsCOMPtr<nsILink> link = do_QueryInterface(links->Item(i, false));
    7346               0 :       if (link) {
    7347               0 :         link->LinkAdded();
    7348                 :       }
    7349                 :     }
    7350                 :   }
    7351                 : 
    7352                 :   // See nsIDocument
    7353               0 :   if (!aDispatchStartTarget) {
    7354                 :     // Set mIsShowing before firing events, in case those event handlers
    7355                 :     // move us around.
    7356               0 :     mIsShowing = true;
    7357                 :   }
    7358                 :  
    7359               0 :   if (mAnimationController) {
    7360               0 :     mAnimationController->OnPageShow();
    7361                 :   }
    7362                 : 
    7363               0 :   if (aPersisted) {
    7364               0 :     SetImagesNeedAnimating(true);
    7365                 :   }
    7366                 : 
    7367               0 :   UpdateVisibilityState();
    7368                 : 
    7369               0 :   nsCOMPtr<nsIDOMEventTarget> target = aDispatchStartTarget;
    7370               0 :   if (!target) {
    7371               0 :     target = do_QueryInterface(GetWindow());
    7372                 :   }
    7373               0 :   DispatchPageTransition(target, NS_LITERAL_STRING("pageshow"), aPersisted);
    7374               0 : }
    7375                 : 
    7376                 : static bool
    7377               0 : NotifyPageHide(nsIDocument* aDocument, void* aData)
    7378                 : {
    7379               0 :   const bool* aPersistedPtr = static_cast<const bool*>(aData);
    7380               0 :   aDocument->OnPageHide(*aPersistedPtr, nsnull);
    7381               0 :   return true;
    7382                 : }
    7383                 : 
    7384                 : void
    7385               0 : nsDocument::OnPageHide(bool aPersisted,
    7386                 :                        nsIDOMEventTarget* aDispatchStartTarget)
    7387                 : {
    7388                 :   // Send out notifications that our <link> elements are detached,
    7389                 :   // but only if this is not a full unload.
    7390               0 :   Element* root = GetRootElement();
    7391               0 :   if (aPersisted && root) {
    7392                 :     nsRefPtr<nsContentList> links = NS_GetContentList(root,
    7393                 :                                                       kNameSpaceID_Unknown,
    7394               0 :                                                       NS_LITERAL_STRING("link"));
    7395                 : 
    7396               0 :     PRUint32 linkCount = links->Length(true);
    7397               0 :     for (PRUint32 i = 0; i < linkCount; ++i) {
    7398               0 :       nsCOMPtr<nsILink> link = do_QueryInterface(links->Item(i, false));
    7399               0 :       if (link) {
    7400               0 :         link->LinkRemoved();
    7401                 :       }
    7402                 :     }
    7403                 :   }
    7404                 : 
    7405                 :   // See nsIDocument
    7406               0 :   if (!aDispatchStartTarget) {
    7407                 :     // Set mIsShowing before firing events, in case those event handlers
    7408                 :     // move us around.
    7409               0 :     mIsShowing = false;
    7410                 :   }
    7411                 : 
    7412               0 :   if (mAnimationController) {
    7413               0 :     mAnimationController->OnPageHide();
    7414                 :   }
    7415                 :   
    7416               0 :   if (aPersisted) {
    7417               0 :     SetImagesNeedAnimating(false);
    7418                 :   }
    7419                 : 
    7420                 :   // Now send out a PageHide event.
    7421               0 :   nsCOMPtr<nsIDOMEventTarget> target = aDispatchStartTarget;
    7422               0 :   if (!target) {
    7423               0 :     target = do_QueryInterface(GetWindow());
    7424                 :   }
    7425               0 :   DispatchPageTransition(target, NS_LITERAL_STRING("pagehide"), aPersisted);
    7426                 : 
    7427               0 :   mVisible = false;
    7428                 : 
    7429               0 :   UpdateVisibilityState();
    7430                 :   
    7431               0 :   EnumerateExternalResources(NotifyPageHide, &aPersisted);
    7432               0 :   EnumerateFreezableElements(NotifyActivityChanged, nsnull);
    7433                 : 
    7434               0 :   if (IsFullScreenDoc()) {
    7435                 :     // A full-screen doc has been hidden. We need to ensure we exit
    7436                 :     // full-screen, i.e. remove full-screen state from all full-screen
    7437                 :     // documents, and exit the top-level window from full-screen mode.
    7438                 :     // By the time a doc is hidden, it has been removed from the doc tree,
    7439                 :     // so nsIDocument::ExitFullScreen() won't be able to traverse to this
    7440                 :     // document to reset its state, so reset full-screen state in *this*
    7441                 :     // document. OnPageHide() is called in every hidden document, so doing
    7442                 :     // this ensures all hidden documents have their full-screen state reset.
    7443               0 :     ClearFullScreenStack();
    7444                 : 
    7445                 :     // Next reset full-screen state in all visible documents in the doctree.
    7446               0 :     nsIDocument::ExitFullScreen(false);
    7447                 :   }
    7448               0 : }
    7449                 : 
    7450                 : void
    7451              36 : nsDocument::WillDispatchMutationEvent(nsINode* aTarget)
    7452                 : {
    7453              36 :   NS_ASSERTION(mSubtreeModifiedDepth != 0 ||
    7454                 :                mSubtreeModifiedTargets.Count() == 0,
    7455                 :                "mSubtreeModifiedTargets not cleared after dispatching?");
    7456              36 :   ++mSubtreeModifiedDepth;
    7457              36 :   if (aTarget) {
    7458                 :     // MayDispatchMutationEvent is often called just before this method,
    7459                 :     // so it has already appended the node to mSubtreeModifiedTargets.
    7460               2 :     PRInt32 count = mSubtreeModifiedTargets.Count();
    7461               2 :     if (!count || mSubtreeModifiedTargets[count - 1] != aTarget) {
    7462               2 :       mSubtreeModifiedTargets.AppendObject(aTarget);
    7463                 :     }
    7464                 :   }
    7465              36 : }
    7466                 : 
    7467                 : void
    7468              36 : nsDocument::MutationEventDispatched(nsINode* aTarget)
    7469                 : {
    7470              36 :   --mSubtreeModifiedDepth;
    7471              36 :   if (mSubtreeModifiedDepth == 0) {
    7472              36 :     PRInt32 count = mSubtreeModifiedTargets.Count();
    7473              36 :     if (!count) {
    7474               4 :       return;
    7475                 :     }
    7476                 : 
    7477              64 :     nsCOMPtr<nsPIDOMWindow> window;
    7478              32 :     window = do_QueryInterface(GetScriptGlobalObject());
    7479              32 :     if (window &&
    7480              32 :         !window->HasMutationListeners(NS_EVENT_BITS_MUTATION_SUBTREEMODIFIED)) {
    7481               0 :       mSubtreeModifiedTargets.Clear();
    7482                 :       return;
    7483                 :     }
    7484                 : 
    7485              64 :     nsCOMArray<nsINode> realTargets;
    7486             123 :     for (PRInt32 i = 0; i < count; ++i) {
    7487              91 :       nsINode* possibleTarget = mSubtreeModifiedTargets[i];
    7488             182 :       nsCOMPtr<nsIContent> content = do_QueryInterface(possibleTarget);
    7489              91 :       if (content && content->IsInNativeAnonymousSubtree()) {
    7490               0 :         continue;
    7491                 :       }
    7492                 : 
    7493              91 :       nsINode* commonAncestor = nsnull;
    7494              91 :       PRInt32 realTargetCount = realTargets.Count();
    7495             116 :       for (PRInt32 j = 0; j < realTargetCount; ++j) {
    7496                 :         commonAncestor =
    7497              74 :           nsContentUtils::GetCommonAncestor(possibleTarget, realTargets[j]);
    7498              74 :         if (commonAncestor) {
    7499              49 :           realTargets.ReplaceObjectAt(commonAncestor, j);
    7500              49 :           break;
    7501                 :         }
    7502                 :       }
    7503              91 :       if (!commonAncestor) {
    7504              42 :         realTargets.AppendObject(possibleTarget);
    7505                 :       }
    7506                 :     }
    7507                 : 
    7508              32 :     mSubtreeModifiedTargets.Clear();
    7509                 : 
    7510              32 :     PRInt32 realTargetCount = realTargets.Count();
    7511              74 :     for (PRInt32 k = 0; k < realTargetCount; ++k) {
    7512              84 :       nsMutationEvent mutation(true, NS_MUTATION_SUBTREEMODIFIED);
    7513              84 :       (new nsAsyncDOMEvent(realTargets[k], mutation))->RunDOMEventWhenSafe();
    7514                 :     }
    7515                 :   }
    7516                 : }
    7517                 : 
    7518                 : void
    7519               0 : nsDocument::AddStyleRelevantLink(Link* aLink)
    7520                 : {
    7521               0 :   NS_ASSERTION(aLink, "Passing in a null link.  Expect crashes RSN!");
    7522                 : #ifdef DEBUG
    7523               0 :   nsPtrHashKey<Link>* entry = mStyledLinks.GetEntry(aLink);
    7524               0 :   NS_ASSERTION(!entry, "Document already knows about this Link!");
    7525               0 :   mStyledLinksCleared = false;
    7526                 : #endif
    7527               0 :   (void)mStyledLinks.PutEntry(aLink);
    7528               0 : }
    7529                 : 
    7530                 : void
    7531               0 : nsDocument::ForgetLink(Link* aLink)
    7532                 : {
    7533               0 :   NS_ASSERTION(aLink, "Passing in a null link.  Expect crashes RSN!");
    7534                 : #ifdef DEBUG
    7535               0 :   nsPtrHashKey<Link>* entry = mStyledLinks.GetEntry(aLink);
    7536               0 :   NS_ASSERTION(entry || mStyledLinksCleared,
    7537                 :                "Document knows nothing about this Link!");
    7538                 : #endif
    7539               0 :   (void)mStyledLinks.RemoveEntry(aLink);
    7540               0 : }
    7541                 : 
    7542                 : void
    7543            1750 : nsDocument::DestroyElementMaps()
    7544                 : {
    7545                 : #ifdef DEBUG
    7546            1750 :   mStyledLinksCleared = true;
    7547                 : #endif
    7548            1750 :   mStyledLinks.Clear();
    7549            1750 :   mIdentifierMap.Clear();
    7550            1750 : }
    7551                 : 
    7552                 : static
    7553                 : PLDHashOperator
    7554               0 : EnumerateStyledLinks(nsPtrHashKey<Link>* aEntry, void* aArray)
    7555                 : {
    7556               0 :   LinkArray* array = static_cast<LinkArray*>(aArray);
    7557               0 :   (void)array->AppendElement(aEntry->GetKey());
    7558               0 :   return PL_DHASH_NEXT;
    7559                 : }
    7560                 : 
    7561                 : void
    7562            1508 : nsDocument::RefreshLinkHrefs()
    7563                 : {
    7564                 :   // Get a list of all links we know about.  We will reset them, which will
    7565                 :   // remove them from the document, so we need a copy of what is in the
    7566                 :   // hashtable.
    7567            3016 :   LinkArray linksToNotify(mStyledLinks.Count());
    7568            1508 :   (void)mStyledLinks.EnumerateEntries(EnumerateStyledLinks, &linksToNotify);
    7569                 : 
    7570                 :   // Reset all of our styled links.
    7571            3016 :   nsAutoScriptBlocker scriptBlocker;
    7572            1508 :   for (LinkArray::size_type i = 0; i < linksToNotify.Length(); i++) {
    7573               0 :     linksToNotify[i]->ResetLinkState(true);
    7574                 :   }
    7575            1508 : }
    7576                 : 
    7577                 : nsresult
    7578               0 : nsDocument::CloneDocHelper(nsDocument* clone) const
    7579                 : {
    7580               0 :   clone->mIsStaticDocument = mCreatingStaticClone;
    7581                 : 
    7582                 :   // Init document
    7583               0 :   nsresult rv = clone->Init();
    7584               0 :   NS_ENSURE_SUCCESS(rv, rv);
    7585                 : 
    7586                 :   // Set URI/principal
    7587               0 :   clone->nsDocument::SetDocumentURI(nsIDocument::GetDocumentURI());
    7588                 :   // Must set the principal first, since SetBaseURI checks it.
    7589               0 :   clone->SetPrincipal(NodePrincipal());
    7590               0 :   clone->mDocumentBaseURI = mDocumentBaseURI;
    7591                 : 
    7592               0 :   if (mCreatingStaticClone) {
    7593               0 :     nsCOMPtr<nsIChannel> channel = GetChannel();
    7594               0 :     nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
    7595               0 :     if (channel && loadGroup) {
    7596               0 :       clone->Reset(channel, loadGroup);
    7597                 :     } else {
    7598               0 :       nsIURI* uri = static_cast<const nsIDocument*>(this)->GetDocumentURI();
    7599               0 :       if (uri) {
    7600               0 :         clone->ResetToURI(uri, loadGroup, NodePrincipal());
    7601                 :       }
    7602                 :     }
    7603               0 :     nsCOMPtr<nsISupports> container = GetContainer();
    7604               0 :     clone->SetContainer(container);
    7605                 :   }
    7606                 : 
    7607                 :   // Set scripting object
    7608               0 :   bool hasHadScriptObject = true;
    7609                 :   nsIScriptGlobalObject* scriptObject =
    7610               0 :     GetScriptHandlingObject(hasHadScriptObject);
    7611               0 :   NS_ENSURE_STATE(scriptObject || !hasHadScriptObject);
    7612               0 :   clone->SetScriptHandlingObject(scriptObject);
    7613                 : 
    7614                 :   // Make the clone a data document
    7615               0 :   clone->SetLoadedAsData(true);
    7616                 : 
    7617                 :   // Misc state
    7618                 : 
    7619                 :   // State from nsIDocument
    7620               0 :   clone->mCharacterSet = mCharacterSet;
    7621               0 :   clone->mCharacterSetSource = mCharacterSetSource;
    7622               0 :   clone->mCompatMode = mCompatMode;
    7623               0 :   clone->mBidiOptions = mBidiOptions;
    7624               0 :   clone->mContentLanguage = mContentLanguage;
    7625               0 :   clone->SetContentTypeInternal(GetContentTypeInternal());
    7626               0 :   clone->mSecurityInfo = mSecurityInfo;
    7627                 : 
    7628                 :   // State from nsDocument
    7629               0 :   clone->mIsRegularHTML = mIsRegularHTML;
    7630               0 :   clone->mXMLDeclarationBits = mXMLDeclarationBits;
    7631               0 :   clone->mBaseTarget = mBaseTarget;
    7632               0 :   return NS_OK;
    7633                 : }
    7634                 : 
    7635                 : void
    7636            4325 : nsDocument::SetReadyStateInternal(ReadyState rs)
    7637                 : {
    7638            4325 :   mReadyState = rs;
    7639            4325 :   if (mTiming) {
    7640               0 :     switch (rs) {
    7641                 :       case READYSTATE_LOADING:
    7642               0 :         mTiming->NotifyDOMLoading(nsIDocument::GetDocumentURI());
    7643               0 :         break;
    7644                 :       case READYSTATE_INTERACTIVE:
    7645               0 :         mTiming->NotifyDOMInteractive(nsIDocument::GetDocumentURI());
    7646               0 :         break;
    7647                 :       case READYSTATE_COMPLETE:
    7648               0 :         mTiming->NotifyDOMComplete(nsIDocument::GetDocumentURI());
    7649               0 :         break;
    7650                 :       default:
    7651               0 :         NS_WARNING("Unexpected ReadyState value");
    7652               0 :         break;
    7653                 :     }
    7654                 :   }
    7655                 :   // At the time of loading start, we don't have timing object, record time.
    7656            4325 :   if (READYSTATE_LOADING == rs) {
    7657            1038 :     mLoadingTimeStamp = mozilla::TimeStamp::Now();
    7658                 :   }
    7659                 : 
    7660                 :   nsRefPtr<nsAsyncDOMEvent> plevent =
    7661           12975 :     new nsAsyncDOMEvent(this, NS_LITERAL_STRING("readystatechange"), false, false); 
    7662            4325 :   if (plevent) {
    7663            4325 :     plevent->RunDOMEventWhenSafe();
    7664                 :   }
    7665            4325 : }
    7666                 : 
    7667                 : nsIDocument::ReadyState
    7668               0 : nsDocument::GetReadyStateEnum()
    7669                 : {
    7670               0 :   return mReadyState;
    7671                 : }
    7672                 : 
    7673                 : NS_IMETHODIMP
    7674               0 : nsDocument::GetReadyState(nsAString& aReadyState)
    7675                 : {
    7676               0 :   switch(mReadyState) {
    7677                 :   case READYSTATE_LOADING :
    7678               0 :     aReadyState.Assign(NS_LITERAL_STRING("loading"));
    7679               0 :     break;
    7680                 :   case READYSTATE_INTERACTIVE :
    7681               0 :     aReadyState.Assign(NS_LITERAL_STRING("interactive"));
    7682               0 :     break;
    7683                 :   case READYSTATE_COMPLETE :
    7684               0 :     aReadyState.Assign(NS_LITERAL_STRING("complete"));
    7685               0 :     break;  
    7686                 :   default:
    7687               0 :     aReadyState.Assign(NS_LITERAL_STRING("uninitialized"));
    7688                 :   }
    7689               0 :   return NS_OK;
    7690                 : }
    7691                 : 
    7692                 : static bool
    7693               0 : SuppressEventHandlingInDocument(nsIDocument* aDocument, void* aData)
    7694                 : {
    7695               0 :   aDocument->SuppressEventHandling(*static_cast<PRUint32*>(aData));
    7696               0 :   return true;
    7697                 : }
    7698                 : 
    7699                 : void
    7700               0 : nsDocument::SuppressEventHandling(PRUint32 aIncrease)
    7701                 : {
    7702               0 :   if (mEventsSuppressed == 0 && aIncrease != 0 && mPresShell &&
    7703               0 :       mScriptGlobalObject) {
    7704               0 :     RevokeAnimationFrameNotifications();
    7705                 :   }
    7706               0 :   mEventsSuppressed += aIncrease;
    7707               0 :   EnumerateSubDocuments(SuppressEventHandlingInDocument, &aIncrease);
    7708               0 : }
    7709                 : 
    7710                 : static void
    7711               0 : FireOrClearDelayedEvents(nsTArray<nsCOMPtr<nsIDocument> >& aDocuments,
    7712                 :                          bool aFireEvents)
    7713                 : {
    7714               0 :   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
    7715               0 :   if (!fm)
    7716               0 :     return;
    7717                 : 
    7718               0 :   for (PRUint32 i = 0; i < aDocuments.Length(); ++i) {
    7719               0 :     if (!aDocuments[i]->EventHandlingSuppressed()) {
    7720               0 :       fm->FireDelayedEvents(aDocuments[i]);
    7721               0 :       nsCOMPtr<nsIPresShell> shell = aDocuments[i]->GetShell();
    7722               0 :       if (shell) {
    7723               0 :         shell->FireOrClearDelayedEvents(aFireEvents);
    7724                 :       }
    7725                 :     }
    7726                 :   }
    7727                 : }
    7728                 : 
    7729                 : void
    7730               0 : nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr)
    7731                 : {
    7732                 :   // Early exit if the img is already present in the img-cache
    7733                 :   // which indicates that the "real" load has already started and
    7734                 :   // that we shouldn't preload it.
    7735                 :   PRInt16 blockingStatus;
    7736               0 :   if (nsContentUtils::IsImageInCache(uri) ||
    7737                 :       !nsContentUtils::CanLoadImage(uri, static_cast<nsIDocument *>(this),
    7738               0 :                                     this, NodePrincipal(), &blockingStatus)) {
    7739               0 :     return;
    7740                 :   }
    7741                 : 
    7742               0 :   nsLoadFlags loadFlags = nsIRequest::LOAD_NORMAL;
    7743               0 :   switch (nsGenericElement::StringToCORSMode(aCrossOriginAttr)) {
    7744                 :   case CORS_NONE:
    7745                 :     // Nothing to do
    7746               0 :     break;
    7747                 :   case CORS_ANONYMOUS:
    7748               0 :     loadFlags |= imgILoader::LOAD_CORS_ANONYMOUS;
    7749               0 :     break;
    7750                 :   case CORS_USE_CREDENTIALS:
    7751               0 :     loadFlags |= imgILoader::LOAD_CORS_USE_CREDENTIALS;
    7752               0 :     break;
    7753                 :   default:
    7754                 :     /* should never happen */
    7755               0 :     MOZ_NOT_REACHED("Unknown CORS mode!");
    7756                 :   }
    7757                 : 
    7758                 :   // Image not in cache - trigger preload
    7759               0 :   nsCOMPtr<imgIRequest> request;
    7760                 :   nsresult rv =
    7761                 :     nsContentUtils::LoadImage(uri,
    7762                 :                               this,
    7763                 :                               NodePrincipal(),
    7764                 :                               mDocumentURI, // uri of document used as referrer
    7765                 :                               nsnull,       // no observer
    7766                 :                               loadFlags,
    7767               0 :                               getter_AddRefs(request));
    7768                 : 
    7769                 :   // Pin image-reference to avoid evicting it from the img-cache before
    7770                 :   // the "real" load occurs. Unpinned in DispatchContentLoadedEvents and
    7771                 :   // unlink
    7772               0 :   if (NS_SUCCEEDED(rv)) {
    7773               0 :     mPreloadingImages.AppendObject(request);
    7774                 :   }
    7775                 : }
    7776                 : 
    7777                 : nsEventStates
    7778               0 : nsDocument::GetDocumentState()
    7779                 : {
    7780               0 :   if (!mGotDocumentState.HasState(NS_DOCUMENT_STATE_RTL_LOCALE)) {
    7781               0 :     if (IsDocumentRightToLeft()) {
    7782               0 :       mDocumentState |= NS_DOCUMENT_STATE_RTL_LOCALE;
    7783                 :     }
    7784               0 :     mGotDocumentState |= NS_DOCUMENT_STATE_RTL_LOCALE;
    7785                 :   }
    7786               0 :   if (!mGotDocumentState.HasState(NS_DOCUMENT_STATE_WINDOW_INACTIVE)) {
    7787               0 :     nsIPresShell* shell = GetShell();
    7788               0 :     if (shell && shell->GetPresContext() &&
    7789               0 :         shell->GetPresContext()->IsTopLevelWindowInactive()) {
    7790               0 :       mDocumentState |= NS_DOCUMENT_STATE_WINDOW_INACTIVE;
    7791                 :     }
    7792               0 :     mGotDocumentState |= NS_DOCUMENT_STATE_WINDOW_INACTIVE;
    7793                 :   }
    7794               0 :   return mDocumentState;
    7795                 : }
    7796                 : 
    7797                 : namespace {
    7798                 : 
    7799                 : /**
    7800                 :  * Stub for LoadSheet(), since all we want is to get the sheet into
    7801                 :  * the CSSLoader's style cache
    7802                 :  */
    7803               0 : class StubCSSLoaderObserver : public nsICSSLoaderObserver {
    7804                 : public:
    7805                 :   NS_IMETHOD
    7806               0 :   StyleSheetLoaded(nsCSSStyleSheet*, bool, nsresult)
    7807                 :   {
    7808               0 :     return NS_OK;
    7809                 :   }
    7810                 :   NS_DECL_ISUPPORTS
    7811                 : };
    7812               0 : NS_IMPL_ISUPPORTS1(StubCSSLoaderObserver, nsICSSLoaderObserver)
    7813                 : 
    7814                 : }
    7815                 : 
    7816                 : void
    7817               0 : nsDocument::PreloadStyle(nsIURI* uri, const nsAString& charset)
    7818                 : {
    7819                 :   // The CSSLoader will retain this object after we return.
    7820               0 :   nsCOMPtr<nsICSSLoaderObserver> obs = new StubCSSLoaderObserver();
    7821                 : 
    7822                 :   // Charset names are always ASCII.
    7823                 :   CSSLoader()->LoadSheet(uri, NodePrincipal(),
    7824               0 :                          NS_LossyConvertUTF16toASCII(charset),
    7825               0 :                          obs);
    7826               0 : }
    7827                 : 
    7828                 : nsresult
    7829               0 : nsDocument::LoadChromeSheetSync(nsIURI* uri, bool isAgentSheet,
    7830                 :                                 nsCSSStyleSheet** sheet)
    7831                 : {
    7832               0 :   return CSSLoader()->LoadSheetSync(uri, isAgentSheet, isAgentSheet, sheet);
    7833                 : }
    7834                 : 
    7835                 : class nsDelayedEventDispatcher : public nsRunnable
    7836                 : {
    7837                 : public:
    7838               0 :   nsDelayedEventDispatcher(nsTArray<nsCOMPtr<nsIDocument> >& aDocuments)
    7839               0 :   {
    7840               0 :     mDocuments.SwapElements(aDocuments);
    7841               0 :   }
    7842               0 :   virtual ~nsDelayedEventDispatcher() {}
    7843                 : 
    7844               0 :   NS_IMETHOD Run()
    7845                 :   {
    7846               0 :     FireOrClearDelayedEvents(mDocuments, true);
    7847               0 :     return NS_OK;
    7848                 :   }
    7849                 : 
    7850                 : private:
    7851                 :   nsTArray<nsCOMPtr<nsIDocument> > mDocuments;
    7852                 : };
    7853                 : 
    7854                 : static bool
    7855               0 : GetAndUnsuppressSubDocuments(nsIDocument* aDocument, void* aData)
    7856                 : {
    7857               0 :   PRUint32 suppression = aDocument->EventHandlingSuppressed();
    7858               0 :   if (suppression > 0) {
    7859               0 :     static_cast<nsDocument*>(aDocument)->DecreaseEventSuppression();
    7860                 :   }
    7861                 :   nsTArray<nsCOMPtr<nsIDocument> >* docs =
    7862               0 :     static_cast<nsTArray<nsCOMPtr<nsIDocument> >* >(aData);
    7863               0 :   docs->AppendElement(aDocument);
    7864               0 :   aDocument->EnumerateSubDocuments(GetAndUnsuppressSubDocuments, docs);
    7865               0 :   return true;
    7866                 : }
    7867                 : 
    7868                 : void
    7869               0 : nsDocument::UnsuppressEventHandlingAndFireEvents(bool aFireEvents)
    7870                 : {
    7871               0 :   nsTArray<nsCOMPtr<nsIDocument> > documents;
    7872               0 :   GetAndUnsuppressSubDocuments(this, &documents);
    7873                 : 
    7874               0 :   if (aFireEvents) {
    7875               0 :     NS_DispatchToCurrentThread(new nsDelayedEventDispatcher(documents));
    7876                 :   } else {
    7877               0 :     FireOrClearDelayedEvents(documents, false);
    7878                 :   }
    7879               0 : }
    7880                 : 
    7881                 : nsISupports*
    7882               0 : nsDocument::GetCurrentContentSink()
    7883                 : {
    7884               0 :   return mParser ? mParser->GetContentSink() : nsnull;
    7885                 : }
    7886                 : 
    7887                 : void
    7888               0 : nsDocument::RegisterFileDataUri(const nsACString& aUri)
    7889                 : {
    7890               0 :   mFileDataUris.AppendElement(aUri);
    7891               0 : }
    7892                 : 
    7893                 : void
    7894               0 : nsDocument::UnregisterFileDataUri(const nsACString& aUri)
    7895                 : {
    7896               0 :   mFileDataUris.RemoveElement(aUri);
    7897               0 : }
    7898                 : 
    7899                 : void
    7900            1050 : nsDocument::SetScrollToRef(nsIURI *aDocumentURI)
    7901                 : {
    7902            1050 :   if (!aDocumentURI) {
    7903               0 :     return;
    7904                 :   }
    7905                 : 
    7906            2100 :   nsCAutoString ref;
    7907                 : 
    7908                 :   // Since all URI's that pass through here aren't URL's we can't
    7909                 :   // rely on the nsIURI implementation for providing a way for
    7910                 :   // finding the 'ref' part of the URI, we'll haveto revert to
    7911                 :   // string routines for finding the data past '#'
    7912                 : 
    7913            1050 :   aDocumentURI->GetSpec(ref);
    7914                 : 
    7915            1050 :   nsReadingIterator<char> start, end;
    7916                 : 
    7917            1050 :   ref.BeginReading(start);
    7918            1050 :   ref.EndReading(end);
    7919                 : 
    7920            1050 :   if (FindCharInReadable('#', start, end)) {
    7921               0 :     ++start; // Skip over the '#'
    7922                 : 
    7923               0 :     mScrollToRef = Substring(start, end);
    7924                 :   }
    7925                 : }
    7926                 : 
    7927                 : void
    7928            1038 : nsDocument::ScrollToRef()
    7929                 : {
    7930            1038 :   if (mScrolledToRefAlready) {
    7931               0 :     return;
    7932                 :   }
    7933                 : 
    7934            1038 :   if (mScrollToRef.IsEmpty()) {
    7935            1038 :     return;
    7936                 :   }
    7937                 : 
    7938               0 :   char* tmpstr = ToNewCString(mScrollToRef);
    7939               0 :   if (!tmpstr) {
    7940               0 :     return;
    7941                 :   }
    7942                 : 
    7943               0 :   nsUnescape(tmpstr);
    7944               0 :   nsCAutoString unescapedRef;
    7945               0 :   unescapedRef.Assign(tmpstr);
    7946               0 :   nsMemory::Free(tmpstr);
    7947                 : 
    7948               0 :   nsresult rv = NS_ERROR_FAILURE;
    7949                 :   // We assume that the bytes are in UTF-8, as it says in the spec:
    7950                 :   // http://www.w3.org/TR/html4/appendix/notes.html#h-B.2.1
    7951               0 :   NS_ConvertUTF8toUTF16 ref(unescapedRef);
    7952                 : 
    7953               0 :   nsCOMPtr<nsIPresShell> shell = GetShell();
    7954               0 :   if (shell) {
    7955                 :     // Check an empty string which might be caused by the UTF-8 conversion
    7956               0 :     if (!ref.IsEmpty()) {
    7957                 :       // Note that GoToAnchor will handle flushing layout as needed.
    7958               0 :       rv = shell->GoToAnchor(ref, mChangeScrollPosWhenScrollingToRef);
    7959                 :     } else {
    7960               0 :       rv = NS_ERROR_FAILURE;
    7961                 :     }
    7962                 : 
    7963                 :     // If UTF-8 URI failed then try to assume the string as a
    7964                 :     // document's charset.
    7965                 : 
    7966               0 :     if (NS_FAILED(rv)) {
    7967               0 :       const nsACString &docCharset = GetDocumentCharacterSet();
    7968                 : 
    7969               0 :       rv = nsContentUtils::ConvertStringFromCharset(docCharset, unescapedRef, ref);
    7970                 : 
    7971               0 :       if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) {
    7972               0 :         rv = shell->GoToAnchor(ref, mChangeScrollPosWhenScrollingToRef);
    7973                 :       }
    7974                 :     }
    7975               0 :     if (NS_SUCCEEDED(rv)) {
    7976               0 :       mScrolledToRefAlready = true;
    7977                 :     }
    7978                 :   }
    7979                 : }
    7980                 : 
    7981                 : void
    7982            1038 : nsDocument::ResetScrolledToRefAlready()
    7983                 : {
    7984            1038 :   mScrolledToRefAlready = false;
    7985            1038 : }
    7986                 : 
    7987                 : void
    7988               0 : nsDocument::SetChangeScrollPosWhenScrollingToRef(bool aValue)
    7989                 : {
    7990               0 :   mChangeScrollPosWhenScrollingToRef = aValue;
    7991               0 : }
    7992                 : 
    7993                 : void
    7994               0 : nsIDocument::RegisterFreezableElement(nsIContent* aContent)
    7995                 : {
    7996               0 :   if (!mFreezableElements) {
    7997               0 :     mFreezableElements = new nsTHashtable<nsPtrHashKey<nsIContent> >();
    7998               0 :     if (!mFreezableElements)
    7999               0 :       return;
    8000               0 :     mFreezableElements->Init();
    8001                 :   }
    8002               0 :   mFreezableElements->PutEntry(aContent);
    8003                 : }
    8004                 : 
    8005                 : bool
    8006               0 : nsIDocument::UnregisterFreezableElement(nsIContent* aContent)
    8007                 : {
    8008               0 :   if (!mFreezableElements)
    8009               0 :     return false;
    8010               0 :   if (!mFreezableElements->GetEntry(aContent))
    8011               0 :     return false;
    8012               0 :   mFreezableElements->RemoveEntry(aContent);
    8013               0 :   return true;
    8014                 : }
    8015                 : 
    8016                 : struct EnumerateFreezablesData {
    8017                 :   nsIDocument::FreezableElementEnumerator mEnumerator;
    8018                 :   void* mData;
    8019                 : };
    8020                 : 
    8021                 : static PLDHashOperator
    8022               0 : EnumerateFreezables(nsPtrHashKey<nsIContent>* aEntry, void* aData)
    8023                 : {
    8024               0 :   EnumerateFreezablesData* data = static_cast<EnumerateFreezablesData*>(aData);
    8025               0 :   data->mEnumerator(aEntry->GetKey(), data->mData);
    8026               0 :   return PL_DHASH_NEXT;
    8027                 : }
    8028                 : 
    8029                 : void
    8030               0 : nsIDocument::EnumerateFreezableElements(FreezableElementEnumerator aEnumerator,
    8031                 :                                         void* aData)
    8032                 : {
    8033               0 :   if (!mFreezableElements)
    8034               0 :     return;
    8035               0 :   EnumerateFreezablesData data = { aEnumerator, aData };
    8036               0 :   mFreezableElements->EnumerateEntries(EnumerateFreezables, &data);
    8037                 : }
    8038                 : 
    8039                 : void
    8040               0 : nsIDocument::RegisterPendingLinkUpdate(Link* aLink)
    8041                 : {
    8042               0 :   mLinksToUpdate.PutEntry(aLink);
    8043               0 :   mHasLinksToUpdate = true;
    8044               0 : }
    8045                 : 
    8046                 : void
    8047               0 : nsIDocument::UnregisterPendingLinkUpdate(Link* aLink)
    8048                 : {
    8049               0 :   if (!mHasLinksToUpdate)
    8050               0 :     return;
    8051                 :     
    8052               0 :   mLinksToUpdate.RemoveEntry(aLink);
    8053                 : }
    8054                 :   
    8055                 : static PLDHashOperator
    8056               0 : EnumeratePendingLinkUpdates(nsPtrHashKey<Link>* aEntry, void* aData)
    8057                 : {
    8058               0 :   aEntry->GetKey()->GetElement()->UpdateLinkState(aEntry->GetKey()->LinkState());
    8059               0 :   return PL_DHASH_NEXT;
    8060                 : }
    8061                 : 
    8062                 : void
    8063             110 : nsIDocument::FlushPendingLinkUpdates() 
    8064                 : {
    8065             110 :   if (!mHasLinksToUpdate)
    8066             110 :     return;
    8067                 :     
    8068               0 :   nsAutoScriptBlocker scriptBlocker;
    8069               0 :   mLinksToUpdate.EnumerateEntries(EnumeratePendingLinkUpdates, nsnull);
    8070               0 :   mLinksToUpdate.Clear();
    8071               0 :   mHasLinksToUpdate = false;
    8072                 : }
    8073                 : 
    8074                 : already_AddRefed<nsIDocument>
    8075               0 : nsIDocument::CreateStaticClone(nsISupports* aCloneContainer)
    8076                 : {
    8077               0 :   nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(this);
    8078               0 :   NS_ENSURE_TRUE(domDoc, nsnull);
    8079               0 :   mCreatingStaticClone = true;
    8080                 : 
    8081                 :   // Make document use different container during cloning.
    8082               0 :   nsCOMPtr<nsISupports> originalContainer = GetContainer();
    8083               0 :   SetContainer(aCloneContainer);
    8084               0 :   nsCOMPtr<nsIDOMNode> clonedNode;
    8085               0 :   nsresult rv = domDoc->CloneNode(true, 1, getter_AddRefs(clonedNode));
    8086               0 :   SetContainer(originalContainer);
    8087                 : 
    8088               0 :   nsCOMPtr<nsIDocument> clonedDoc;
    8089               0 :   if (NS_SUCCEEDED(rv)) {
    8090               0 :     clonedDoc = do_QueryInterface(clonedNode);
    8091               0 :     if (clonedDoc) {
    8092               0 :       if (IsStaticDocument()) {
    8093               0 :         clonedDoc->mOriginalDocument = mOriginalDocument;
    8094                 :       } else {
    8095               0 :         clonedDoc->mOriginalDocument = this;
    8096                 :       }
    8097               0 :       PRInt32 sheetsCount = GetNumberOfStyleSheets();
    8098               0 :       for (PRInt32 i = 0; i < sheetsCount; ++i) {
    8099               0 :         nsRefPtr<nsCSSStyleSheet> sheet = do_QueryObject(GetStyleSheetAt(i));
    8100               0 :         if (sheet) {
    8101               0 :           if (sheet->IsApplicable()) {
    8102                 :             nsRefPtr<nsCSSStyleSheet> clonedSheet =
    8103               0 :               sheet->Clone(nsnull, nsnull, clonedDoc, nsnull);
    8104               0 :             NS_WARN_IF_FALSE(clonedSheet, "Cloning a stylesheet didn't work!");
    8105               0 :             if (clonedSheet) {
    8106               0 :               clonedDoc->AddStyleSheet(clonedSheet);
    8107                 :             }
    8108                 :           }
    8109                 :         }
    8110                 :       }
    8111                 : 
    8112               0 :       sheetsCount = GetNumberOfCatalogStyleSheets();
    8113               0 :       for (PRInt32 i = 0; i < sheetsCount; ++i) {
    8114                 :         nsRefPtr<nsCSSStyleSheet> sheet =
    8115               0 :           do_QueryObject(GetCatalogStyleSheetAt(i));
    8116               0 :         if (sheet) {
    8117               0 :           if (sheet->IsApplicable()) {
    8118                 :             nsRefPtr<nsCSSStyleSheet> clonedSheet =
    8119               0 :               sheet->Clone(nsnull, nsnull, clonedDoc, nsnull);
    8120               0 :             NS_WARN_IF_FALSE(clonedSheet, "Cloning a stylesheet didn't work!");
    8121               0 :             if (clonedSheet) {
    8122               0 :               clonedDoc->AddCatalogStyleSheet(clonedSheet);
    8123                 :             }
    8124                 :           }
    8125                 :         }
    8126                 :       }
    8127                 :     }
    8128                 :   }
    8129               0 :   mCreatingStaticClone = false;
    8130               0 :   return clonedDoc.forget();
    8131                 : }
    8132                 : 
    8133                 : nsresult
    8134               0 : nsIDocument::ScheduleFrameRequestCallback(nsIFrameRequestCallback* aCallback,
    8135                 :                                           PRInt32 *aHandle)
    8136                 : {
    8137               0 :   if (mFrameRequestCallbackCounter == PR_INT32_MAX) {
    8138                 :     // Can't increment without overflowing; bail out
    8139               0 :     return NS_ERROR_NOT_AVAILABLE;
    8140                 :   }
    8141               0 :   PRInt32 newHandle = ++mFrameRequestCallbackCounter;
    8142                 : 
    8143               0 :   bool alreadyRegistered = !mFrameRequestCallbacks.IsEmpty();
    8144                 :   DebugOnly<FrameRequest*> request =
    8145               0 :     mFrameRequestCallbacks.AppendElement(FrameRequest(aCallback, newHandle));
    8146               0 :   NS_ASSERTION(request, "This is supposed to be infallible!");
    8147               0 :   if (!alreadyRegistered && mPresShell && IsEventHandlingEnabled()) {
    8148                 :     mPresShell->GetPresContext()->RefreshDriver()->
    8149               0 :       ScheduleFrameRequestCallbacks(this);
    8150                 :   }
    8151                 : 
    8152               0 :   *aHandle = newHandle;
    8153               0 :   return NS_OK;
    8154                 : }
    8155                 : 
    8156                 : void
    8157               0 : nsIDocument::CancelFrameRequestCallback(PRInt32 aHandle)
    8158                 : {
    8159                 :   // mFrameRequestCallbacks is stored sorted by handle
    8160               0 :   if (mFrameRequestCallbacks.RemoveElementSorted(aHandle) &&
    8161               0 :       mFrameRequestCallbacks.IsEmpty() &&
    8162               0 :       mPresShell && IsEventHandlingEnabled()) {
    8163                 :     mPresShell->GetPresContext()->RefreshDriver()->
    8164               0 :       RevokeFrameRequestCallbacks(this);
    8165                 :   }
    8166               0 : }
    8167                 : 
    8168                 : nsresult
    8169               0 : nsDocument::GetStateObject(nsIVariant** aState)
    8170                 : {
    8171                 :   // Get the document's current state object. This is the object backing both
    8172                 :   // history.state and popStateEvent.state.
    8173                 :   //
    8174                 :   // mStateObjectContainer may be null; this just means that there's no
    8175                 :   // current state object.
    8176                 : 
    8177               0 :   nsCOMPtr<nsIVariant> stateObj;
    8178               0 :   if (!mStateObjectCached && mStateObjectContainer) {
    8179               0 :     JSContext *cx = nsContentUtils::GetContextFromDocument(this);
    8180               0 :     mStateObjectContainer->
    8181               0 :       DeserializeToVariant(cx, getter_AddRefs(mStateObjectCached));
    8182                 :   }
    8183                 : 
    8184               0 :   NS_IF_ADDREF(*aState = mStateObjectCached);
    8185                 :   
    8186               0 :   return NS_OK;
    8187                 : }
    8188                 : 
    8189                 : nsDOMNavigationTiming*
    8190               0 : nsDocument::GetNavigationTiming() const
    8191                 : {
    8192               0 :   return mTiming;
    8193                 : }
    8194                 : 
    8195                 : nsresult
    8196               0 : nsDocument::SetNavigationTiming(nsDOMNavigationTiming* aTiming)
    8197                 : {
    8198               0 :   mTiming = aTiming;
    8199               0 :   if (!mLoadingTimeStamp.IsNull() && mTiming) {
    8200               0 :     mTiming->SetDOMLoadingTimeStamp(nsIDocument::GetDocumentURI(), mLoadingTimeStamp);
    8201                 :   }
    8202               0 :   return NS_OK;
    8203                 : }
    8204                 : 
    8205                 : Element*
    8206               0 : nsDocument::FindImageMap(const nsAString& aUseMapValue)
    8207                 : {
    8208               0 :   if (aUseMapValue.IsEmpty()) {
    8209               0 :     return nsnull;
    8210                 :   }
    8211                 : 
    8212               0 :   nsAString::const_iterator start, end;
    8213               0 :   aUseMapValue.BeginReading(start);
    8214               0 :   aUseMapValue.EndReading(end);
    8215                 : 
    8216               0 :   PRInt32 hash = aUseMapValue.FindChar('#');
    8217               0 :   if (hash < 0) {
    8218               0 :     return nsnull;
    8219                 :   }
    8220                 :   // aUsemap contains a '#', set start to point right after the '#'
    8221               0 :   start.advance(hash + 1);
    8222                 : 
    8223               0 :   if (start == end) {
    8224               0 :     return nsnull; // aUsemap == "#"
    8225                 :   }
    8226                 : 
    8227               0 :   const nsAString& mapName = Substring(start, end);
    8228                 : 
    8229               0 :   if (!mImageMaps) {
    8230               0 :     mImageMaps = new nsContentList(this, kNameSpaceID_XHTML, nsGkAtoms::map, nsGkAtoms::map);
    8231                 :   }
    8232                 : 
    8233               0 :   PRUint32 i, n = mImageMaps->Length(true);
    8234               0 :   for (i = 0; i < n; ++i) {
    8235               0 :     nsIContent* map = mImageMaps->GetNodeAt(i);
    8236               0 :     if (map->AttrValueIs(kNameSpaceID_None, nsGkAtoms::id, mapName,
    8237               0 :                          eCaseMatters) ||
    8238                 :         map->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name, mapName,
    8239               0 :                          eIgnoreCase)) {
    8240               0 :       return map->AsElement();
    8241                 :     }
    8242                 :   }
    8243                 : 
    8244               0 :   return nsnull;
    8245                 : }
    8246                 : 
    8247                 : #define DEPRECATED_OPERATION(_op) #_op "Warning",
    8248                 : static const char* kWarnings[] = {
    8249                 : #include "nsDeprecatedOperationList.h"
    8250                 :   nsnull
    8251                 : };
    8252                 : #undef DEPRECATED_OPERATION
    8253                 : 
    8254                 : void
    8255             259 : nsIDocument::WarnOnceAbout(DeprecatedOperations aOperation)
    8256                 : {
    8257                 :   PR_STATIC_ASSERT(eDeprecatedOperationCount <= 64);
    8258             259 :   if (mWarnedAbout & (1 << aOperation)) {
    8259             254 :     return;
    8260                 :   }
    8261               5 :   mWarnedAbout |= (1 << aOperation);
    8262                 :   nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
    8263                 :                                   "DOM Core", this,
    8264                 :                                   nsContentUtils::eDOM_PROPERTIES,
    8265               5 :                                   kWarnings[aOperation]);
    8266                 : }
    8267                 : 
    8268                 : nsresult
    8269               0 : nsDocument::AddImage(imgIRequest* aImage)
    8270                 : {
    8271               0 :   NS_ENSURE_ARG_POINTER(aImage);
    8272                 : 
    8273                 :   // See if the image is already in the hashtable. If it is, get the old count.
    8274               0 :   PRUint32 oldCount = 0;
    8275               0 :   mImageTracker.Get(aImage, &oldCount);
    8276                 : 
    8277                 :   // Put the image in the hashtable, with the proper count.
    8278               0 :   bool success = mImageTracker.Put(aImage, oldCount + 1);
    8279               0 :   if (!success)
    8280               0 :     return NS_ERROR_OUT_OF_MEMORY;
    8281                 : 
    8282               0 :   nsresult rv = NS_OK;
    8283                 : 
    8284                 :   // If this is the first insertion and we're locking images, lock this image
    8285                 :   // too.
    8286               0 :   if (oldCount == 0 && mLockingImages) {
    8287               0 :     rv = aImage->LockImage();
    8288               0 :     if (NS_SUCCEEDED(rv))
    8289               0 :       rv = aImage->RequestDecode();
    8290                 :   }
    8291                 : 
    8292                 :   // If this is the first insertion and we're animating images, request
    8293                 :   // that this image be animated too.
    8294               0 :   if (oldCount == 0 && mAnimatingImages) {
    8295               0 :     nsresult rv2 = aImage->IncrementAnimationConsumers();
    8296               0 :     rv = NS_SUCCEEDED(rv) ? rv2 : rv;
    8297                 :   }
    8298                 : 
    8299               0 :   return rv;
    8300                 : }
    8301                 : 
    8302                 : static void
    8303               0 : NotifyAudioAvailableListener(nsIContent *aContent, void *aUnused)
    8304                 : {
    8305                 : #ifdef MOZ_MEDIA
    8306               0 :   nsCOMPtr<nsIDOMHTMLMediaElement> domMediaElem(do_QueryInterface(aContent));
    8307               0 :   if (domMediaElem) {
    8308               0 :     nsHTMLMediaElement* mediaElem = static_cast<nsHTMLMediaElement*>(aContent);
    8309               0 :     mediaElem->NotifyAudioAvailableListener();
    8310                 :   }
    8311                 : #endif
    8312               0 : }
    8313                 : 
    8314                 : void
    8315               0 : nsDocument::NotifyAudioAvailableListener()
    8316                 : {
    8317               0 :   mHasAudioAvailableListener = true;
    8318               0 :   EnumerateFreezableElements(::NotifyAudioAvailableListener, nsnull);
    8319               0 : }
    8320                 : 
    8321                 : nsresult
    8322               0 : nsDocument::RemoveImage(imgIRequest* aImage)
    8323                 : {
    8324               0 :   NS_ENSURE_ARG_POINTER(aImage);
    8325                 : 
    8326                 :   // Get the old count. It should exist and be > 0.
    8327               0 :   PRUint32 count = 0;
    8328               0 :   DebugOnly<bool> found = mImageTracker.Get(aImage, &count);
    8329               0 :   NS_ABORT_IF_FALSE(found, "Removing image that wasn't in the tracker!");
    8330               0 :   NS_ABORT_IF_FALSE(count > 0, "Entry in the cache tracker with count 0!");
    8331                 : 
    8332                 :   // We're removing, so decrement the count.
    8333               0 :   count--;
    8334                 : 
    8335                 :   // If the count is now zero, remove from the tracker.
    8336                 :   // Otherwise, set the new value.
    8337               0 :   if (count != 0) {
    8338               0 :     mImageTracker.Put(aImage, count);
    8339               0 :     return NS_OK;
    8340                 :   }
    8341                 : 
    8342               0 :   mImageTracker.Remove(aImage);
    8343                 : 
    8344               0 :   nsresult rv = NS_OK;
    8345                 : 
    8346                 :   // Now that we're no longer tracking this image, unlock it if we'd
    8347                 :   // previously locked it.
    8348               0 :   if (mLockingImages) {
    8349               0 :     rv = aImage->UnlockImage();
    8350                 :   }
    8351                 : 
    8352                 :   // If we're animating images, remove our request to animate this one.
    8353               0 :   if (mAnimatingImages) {
    8354               0 :     nsresult rv2 = aImage->DecrementAnimationConsumers();
    8355               0 :     rv = NS_SUCCEEDED(rv) ? rv2 : rv;
    8356                 :   }
    8357                 : 
    8358                 :   // Request that the image be discarded if nobody else holds a lock on it.
    8359                 :   // Do this even if !mLockingImages, because even if we didn't just unlock
    8360                 :   // this image, it might still be a candidate for discarding.
    8361               0 :   aImage->RequestDiscard();
    8362                 : 
    8363               0 :   return rv;
    8364                 : }
    8365                 : 
    8366               0 : PLDHashOperator LockEnumerator(imgIRequest* aKey,
    8367                 :                                PRUint32 aData,
    8368                 :                                void*    userArg)
    8369                 : {
    8370               0 :   aKey->LockImage();
    8371               0 :   aKey->RequestDecode();
    8372               0 :   return PL_DHASH_NEXT;
    8373                 : }
    8374                 : 
    8375               0 : PLDHashOperator UnlockEnumerator(imgIRequest* aKey,
    8376                 :                                  PRUint32 aData,
    8377                 :                                  void*    userArg)
    8378                 : {
    8379               0 :   aKey->UnlockImage();
    8380               0 :   return PL_DHASH_NEXT;
    8381                 : }
    8382                 : 
    8383                 : 
    8384                 : nsresult
    8385            1271 : nsDocument::SetImageLockingState(bool aLocked)
    8386                 : {
    8387            1271 :   if (XRE_GetProcessType() == GeckoProcessType_Content &&
    8388               0 :       !Preferences::GetBool("content.image.allow_locking", true)) {
    8389               0 :     return NS_OK;
    8390                 :   }
    8391                 : 
    8392                 :   // If there's no change, there's nothing to do.
    8393            1271 :   if (mLockingImages == aLocked)
    8394            1271 :     return NS_OK;
    8395                 : 
    8396                 :   // Otherwise, iterate over our images and perform the appropriate action.
    8397                 :   mImageTracker.EnumerateRead(aLocked ? LockEnumerator
    8398                 :                                       : UnlockEnumerator,
    8399               0 :                               nsnull);
    8400                 : 
    8401                 :   // Update state.
    8402               0 :   mLockingImages = aLocked;
    8403                 : 
    8404               0 :   return NS_OK;
    8405                 : }
    8406                 : 
    8407               0 : PLDHashOperator IncrementAnimationEnumerator(imgIRequest* aKey,
    8408                 :                                              PRUint32 aData,
    8409                 :                                              void*    userArg)
    8410                 : {
    8411               0 :   aKey->IncrementAnimationConsumers();
    8412               0 :   return PL_DHASH_NEXT;
    8413                 : }
    8414                 : 
    8415               0 : PLDHashOperator DecrementAnimationEnumerator(imgIRequest* aKey,
    8416                 :                                              PRUint32 aData,
    8417                 :                                              void*    userArg)
    8418                 : {
    8419               0 :   aKey->DecrementAnimationConsumers();
    8420               0 :   return PL_DHASH_NEXT;
    8421                 : }
    8422                 : 
    8423                 : void
    8424               0 : nsDocument::SetImagesNeedAnimating(bool aAnimating)
    8425                 : {
    8426                 :   // If there's no change, there's nothing to do.
    8427               0 :   if (mAnimatingImages == aAnimating)
    8428               0 :     return;
    8429                 : 
    8430                 :   // Otherwise, iterate over our images and perform the appropriate action.
    8431                 :   mImageTracker.EnumerateRead(aAnimating ? IncrementAnimationEnumerator
    8432                 :                                          : DecrementAnimationEnumerator,
    8433               0 :                               nsnull);
    8434                 : 
    8435                 :   // Update state.
    8436               0 :   mAnimatingImages = aAnimating;
    8437                 : }
    8438                 : 
    8439                 : NS_IMETHODIMP
    8440               0 : nsDocument::CreateTouch(nsIDOMWindow* aView,
    8441                 :                         nsIDOMEventTarget* aTarget,
    8442                 :                         PRInt32 aIdentifier,
    8443                 :                         PRInt32 aPageX,
    8444                 :                         PRInt32 aPageY,
    8445                 :                         PRInt32 aScreenX,
    8446                 :                         PRInt32 aScreenY,
    8447                 :                         PRInt32 aClientX,
    8448                 :                         PRInt32 aClientY,
    8449                 :                         PRInt32 aRadiusX,
    8450                 :                         PRInt32 aRadiusY,
    8451                 :                         float aRotationAngle,
    8452                 :                         float aForce,
    8453                 :                         nsIDOMTouch** aRetVal)
    8454                 : {
    8455               0 :   NS_ADDREF(*aRetVal = new nsDOMTouch(aTarget,
    8456                 :                                       aIdentifier,
    8457                 :                                       aPageX,
    8458                 :                                       aPageY,
    8459                 :                                       aScreenX,
    8460                 :                                       aScreenY,
    8461                 :                                       aClientX,
    8462                 :                                       aClientY,
    8463                 :                                       aRadiusX,
    8464                 :                                       aRadiusY,
    8465                 :                                       aRotationAngle,
    8466               0 :                                       aForce));
    8467               0 :   return NS_OK;
    8468                 : }
    8469                 : 
    8470                 : NS_IMETHODIMP
    8471               0 : nsDocument::CreateTouchList(nsIVariant* aPoints,
    8472                 :                             nsIDOMTouchList** aRetVal)
    8473                 : {
    8474               0 :   nsRefPtr<nsDOMTouchList> retval = new nsDOMTouchList();
    8475               0 :   if (aPoints) {
    8476                 :     PRUint16 type;
    8477               0 :     aPoints->GetDataType(&type);
    8478               0 :     if (type == nsIDataType::VTYPE_INTERFACE ||
    8479                 :         type == nsIDataType::VTYPE_INTERFACE_IS) {
    8480               0 :       nsCOMPtr<nsISupports> data;
    8481               0 :       aPoints->GetAsISupports(getter_AddRefs(data));
    8482               0 :       nsCOMPtr<nsIDOMTouch> point = do_QueryInterface(data);
    8483               0 :       if (point) {
    8484               0 :         retval->Append(point);
    8485               0 :       }
    8486               0 :     } else if (type == nsIDataType::VTYPE_ARRAY) {
    8487                 :       PRUint16 valueType;
    8488                 :       nsIID iid;
    8489                 :       PRUint32 valueCount;
    8490                 :       void* rawArray;
    8491               0 :       aPoints->GetAsArray(&valueType, &iid, &valueCount, &rawArray);
    8492               0 :       if (valueType == nsIDataType::VTYPE_INTERFACE ||
    8493                 :           valueType == nsIDataType::VTYPE_INTERFACE_IS) {
    8494               0 :         nsISupports** values = static_cast<nsISupports**>(rawArray);
    8495               0 :         for (PRUint32 i = 0; i < valueCount; ++i) {
    8496               0 :           nsCOMPtr<nsISupports> supports = dont_AddRef(values[i]);
    8497               0 :           nsCOMPtr<nsIDOMTouch> point = do_QueryInterface(supports);
    8498               0 :           if (point) {
    8499               0 :             retval->Append(point);
    8500                 :           }
    8501                 :         }
    8502                 :       }
    8503               0 :       nsMemory::Free(rawArray);
    8504                 :     }
    8505                 :   }
    8506                 : 
    8507               0 :   *aRetVal = retval.forget().get();
    8508               0 :   return NS_OK;
    8509                 : }
    8510                 : 
    8511                 : static void
    8512               0 : DispatchFullScreenChange(nsIDocument* aTarget)
    8513                 : {
    8514                 :   nsRefPtr<nsAsyncDOMEvent> e =
    8515                 :     new nsAsyncDOMEvent(aTarget,
    8516               0 :                         NS_LITERAL_STRING("mozfullscreenchange"),
    8517                 :                         true,
    8518               0 :                         false);
    8519               0 :   e->PostDOMEvent();
    8520               0 : }
    8521                 : 
    8522                 : NS_IMETHODIMP
    8523               0 : nsDocument::MozCancelFullScreen()
    8524                 : {
    8525               0 :   if (!nsContentUtils::IsRequestFullScreenAllowed()) {
    8526               0 :     return NS_OK;
    8527                 :   }
    8528               0 :   RestorePreviousFullScreenState();
    8529               0 :   return NS_OK;
    8530                 : }
    8531                 : 
    8532                 : // Runnable to set window full-screen mode. Used as a script runner
    8533                 : // to ensure we only call nsGlobalWindow::SetFullScreen() when it's safe to 
    8534                 : // run script. nsGlobalWindow::SetFullScreen() dispatches a synchronous event
    8535                 : // (handled in chome code) which is unsafe to run if this is called in
    8536                 : // nsGenericElement::UnbindFromTree().
    8537               0 : class nsSetWindowFullScreen : public nsRunnable {
    8538                 : public:
    8539               0 :   nsSetWindowFullScreen(nsIDocument* aDoc, bool aValue)
    8540               0 :     : mDoc(aDoc), mValue(aValue) {}
    8541                 : 
    8542               0 :   NS_IMETHOD Run()
    8543                 :   {
    8544               0 :     if (mDoc->GetWindow()) {
    8545               0 :       mDoc->GetWindow()->SetFullScreenInternal(mValue, false);
    8546                 :     }
    8547               0 :     return NS_OK;
    8548                 :   }
    8549                 : 
    8550                 : private:
    8551                 :   nsCOMPtr<nsIDocument> mDoc;
    8552                 :   bool mValue;
    8553                 : };
    8554                 : 
    8555                 : static void
    8556               0 : SetWindowFullScreen(nsIDocument* aDoc, bool aValue)
    8557                 : {
    8558               0 :   nsContentUtils::AddScriptRunner(new nsSetWindowFullScreen(aDoc, aValue));
    8559               0 : }
    8560                 : 
    8561               0 : class nsCallExitFullScreen : public nsRunnable {
    8562                 : public:
    8563               0 :   NS_IMETHOD Run()
    8564                 :   {
    8565               0 :     nsDocument::ExitFullScreen();
    8566               0 :     return NS_OK;
    8567                 :   }
    8568                 : };
    8569                 : 
    8570                 : /* static */
    8571                 : void
    8572               0 : nsIDocument::ExitFullScreen(bool aRunAsync)
    8573                 : {
    8574               0 :   if (aRunAsync) {
    8575               0 :     NS_DispatchToCurrentThread(new nsCallExitFullScreen());
    8576               0 :     return;
    8577                 :   }
    8578               0 :   nsDocument::ExitFullScreen();
    8579                 : }
    8580                 : 
    8581                 : static bool
    8582               0 : ResetFullScreen(nsIDocument* aDocument, void* aData) {
    8583               0 :   if (aDocument->IsFullScreenDoc()) {
    8584               0 :     static_cast<nsDocument*>(aDocument)->ClearFullScreenStack();
    8585               0 :     NS_ASSERTION(!aDocument->IsFullScreenDoc(), "Should reset full-screen");
    8586               0 :     nsTArray<nsIDocument*>* changed = reinterpret_cast<nsTArray<nsIDocument*>*>(aData);
    8587               0 :     changed->AppendElement(aDocument);
    8588               0 :     aDocument->EnumerateSubDocuments(ResetFullScreen, aData);
    8589                 :   }
    8590               0 :   return true;
    8591                 : }
    8592                 : 
    8593                 : /* static */
    8594                 : void
    8595               0 : nsDocument::ExitFullScreen()
    8596                 : {
    8597                 :   // Clear full-screen stacks in all descendant documents.
    8598               0 :   nsCOMPtr<nsIDocument> root(do_QueryReferent(sFullScreenRootDoc));
    8599               0 :   if (!root) {
    8600                 :     // Not in full-screen mode.
    8601                 :     return;
    8602                 :   }
    8603               0 :   NS_ASSERTION(root->IsFullScreenDoc(),
    8604                 :     "Full-screen root should be a full-screen doc...");
    8605                 : 
    8606                 :   // Stores a list of documents to which we must dispatch "mozfullscreenchange".
    8607                 :   // We're required by the spec to dispatch the events in leaf-to-root
    8608                 :   // order when exiting full-screen, but we traverse the doctree in a
    8609                 :   // root-to-leaf order, so we save references to the documents we must
    8610                 :   // dispatch to so that we dispatch in the specified order.
    8611               0 :   nsAutoTArray<nsIDocument*, 8> changed;
    8612                 : 
    8613                 :   // Walk the tree of full-screen documents, and reset their full-screen state.
    8614               0 :   ResetFullScreen(root, static_cast<void*>(&changed));
    8615                 : 
    8616                 :   // Dispatch "mozfullscreenchange" events. Note this loop is in reverse
    8617                 :   // order so that the events for the leaf document arrives before the root
    8618                 :   // document, as required by the spec.
    8619               0 :   for (PRUint32 i = 0; i < changed.Length(); ++i) {
    8620               0 :     DispatchFullScreenChange(changed[changed.Length() - i - 1]);
    8621                 :   }
    8622                 : 
    8623                 :   // Reset global state. Do this before we move the window out of full-screen
    8624                 :   // mode, as that calls nsGlobalWindow::SetFullScreen() which calls back into
    8625                 :   // nsIDocument::ExitFullScreen().
    8626               0 :   sFullScreenRootDoc = nsnull;
    8627               0 :   sFullScreenDoc = nsnull;
    8628                 : 
    8629                 :   // Move the top-level window out of full-screen mode.
    8630               0 :   SetWindowFullScreen(root, false);
    8631                 : }
    8632                 : 
    8633                 : void
    8634               0 : nsDocument::RestorePreviousFullScreenState()
    8635                 : {
    8636               0 :   NS_ASSERTION(!IsFullScreenDoc() || sFullScreenDoc != nsnull,
    8637                 :                "Should have a full-screen doc when full-screen!");
    8638                 : 
    8639               0 :   if (!IsFullScreenDoc() || !GetWindow() || !sFullScreenDoc) {
    8640               0 :     return;
    8641                 :   }
    8642                 : 
    8643                 :   // Clear full-screen stacks in all descendant documents, bottom up.
    8644               0 :   nsCOMPtr<nsIDocument> fullScreenDoc(do_QueryReferent(sFullScreenDoc));
    8645               0 :   nsIDocument* doc = fullScreenDoc;
    8646               0 :   while (doc != this) {
    8647               0 :     NS_ASSERTION(doc->IsFullScreenDoc(), "Should be full-screen doc");
    8648               0 :     static_cast<nsDocument*>(doc)->ClearFullScreenStack();
    8649               0 :     DispatchFullScreenChange(doc);
    8650               0 :     doc = doc->GetParentDocument();
    8651                 :   }
    8652                 : 
    8653                 :   // Roll-back full-screen state to previous full-screen element.
    8654               0 :   NS_ASSERTION(doc == this, "Must have reached this doc.");
    8655               0 :   while (doc != nsnull) {
    8656               0 :     static_cast<nsDocument*>(doc)->FullScreenStackPop();
    8657               0 :     DispatchFullScreenChange(doc);
    8658               0 :     if (static_cast<nsDocument*>(doc)->mFullScreenStack.IsEmpty()) {
    8659                 :       // Full-screen stack in document is empty. Go back up to the parent
    8660                 :       // document. We'll pop the containing element off its stack, and use
    8661                 :       // its next full-screen element as the full-screen element.
    8662               0 :       doc = doc->GetParentDocument();
    8663                 :     } else {
    8664                 :       // Else we popped the top of the stack, and there's still another
    8665                 :       // element in there, so that will become the full-screen element.
    8666               0 :       sFullScreenDoc = do_GetWeakReference(doc);
    8667               0 :       break;
    8668                 :     }
    8669                 :   }
    8670                 : 
    8671               0 :   if (doc == nsnull) {
    8672                 :     // We moved all documents out of full-screen mode, reset global full-screen
    8673                 :     // state and move the top-level window out of full-screen mode.
    8674               0 :     DebugOnly< nsCOMPtr<nsIDocument> > root(do_QueryReferent(sFullScreenRootDoc));
    8675               0 :     NS_ASSERTION(!root->IsFullScreenDoc(), "Should have cleared all docs' stacks");
    8676               0 :     sFullScreenDoc = nsnull;
    8677               0 :     sFullScreenRootDoc = nsnull;
    8678               0 :     SetWindowFullScreen(this, false);
    8679                 :   }
    8680                 : }
    8681                 : 
    8682                 : bool
    8683               0 : nsDocument::IsFullScreenDoc()
    8684                 : {
    8685               0 :   return GetFullScreenElement() != nsnull;
    8686                 : }
    8687                 : 
    8688                 : class nsCallRequestFullScreen : public nsRunnable
    8689               0 : {
    8690                 : public:
    8691               0 :   nsCallRequestFullScreen(Element* aElement)
    8692                 :     : mElement(aElement),
    8693                 :       mDoc(aElement->OwnerDoc()),
    8694               0 :       mWasCallerChrome(nsContentUtils::IsCallerChrome())
    8695                 :   {
    8696               0 :   }
    8697                 : 
    8698               0 :   NS_IMETHOD Run()
    8699                 :   {
    8700               0 :     nsDocument* doc = static_cast<nsDocument*>(mDoc.get());
    8701               0 :     doc->RequestFullScreen(mElement, mWasCallerChrome);
    8702               0 :     return NS_OK;
    8703                 :   }
    8704                 : 
    8705                 :   nsRefPtr<Element> mElement;
    8706                 :   nsCOMPtr<nsIDocument> mDoc;
    8707                 :   bool mWasCallerChrome;
    8708                 : };
    8709                 : 
    8710                 : void
    8711               0 : nsDocument::AsyncRequestFullScreen(Element* aElement)
    8712                 : {
    8713               0 :   NS_ASSERTION(aElement,
    8714                 :     "Must pass non-null element to nsDocument::AsyncRequestFullScreen");
    8715               0 :   if (!aElement) {
    8716               0 :     return;
    8717                 :   }
    8718                 :   // Request full-screen asynchronously.
    8719               0 :   nsCOMPtr<nsIRunnable> event(new nsCallRequestFullScreen(aElement));
    8720               0 :   NS_DispatchToCurrentThread(event);
    8721                 : }
    8722                 : 
    8723                 : static void
    8724               0 : LogFullScreenDenied(bool aLogFailure, const char* aMessage, nsIDocument* aDoc)
    8725                 : {
    8726               0 :   if (!aLogFailure) {
    8727               0 :     return;
    8728                 :   }
    8729                 :   nsRefPtr<nsAsyncDOMEvent> e =
    8730                 :     new nsAsyncDOMEvent(aDoc,
    8731               0 :                         NS_LITERAL_STRING("mozfullscreenerror"),
    8732                 :                         true,
    8733               0 :                         false);
    8734               0 :   e->PostDOMEvent();
    8735                 :   nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
    8736                 :                                   "DOM", aDoc,
    8737                 :                                   nsContentUtils::eDOM_PROPERTIES,
    8738               0 :                                   aMessage);
    8739                 : }
    8740                 : 
    8741                 : void
    8742               0 : nsDocument::ClearFullScreenStack()
    8743                 : {
    8744               0 :   if (mFullScreenStack.IsEmpty()) {
    8745               0 :     return;
    8746                 :   }
    8747                 :   // The top element in the full-screen stack will have full-screen
    8748                 :   // style bits set on it and its ancestors. Remove the style bits.
    8749                 :   // Note the non-top elements won't have the style bits set.
    8750               0 :   Element* top = FullScreenStackTop();
    8751               0 :   NS_ASSERTION(top, "Should have a top when full-screen stack isn't empty");
    8752               0 :   if (top) {
    8753               0 :     nsEventStateManager::SetFullScreenState(top, false);
    8754                 :   }
    8755               0 :   mFullScreenStack.Clear();
    8756                 : }
    8757                 : 
    8758                 : bool
    8759               0 : nsDocument::FullScreenStackPush(Element* aElement)
    8760                 : {
    8761               0 :   NS_ASSERTION(aElement, "Must pass non-null to FullScreenStackPush()");
    8762               0 :   Element* top = FullScreenStackTop();
    8763               0 :   if (top == aElement || !aElement) {
    8764               0 :     return false;
    8765                 :   }
    8766               0 :   if (top) {
    8767                 :     // We're pushing a new element onto the full-screen stack, so we must
    8768                 :     // remove the ancestor and full-screen styles from the former top of the
    8769                 :     // stack.
    8770               0 :     nsEventStateManager::SetFullScreenState(top, false);
    8771                 :   }
    8772               0 :   nsEventStateManager::SetFullScreenState(aElement, true);
    8773               0 :   mFullScreenStack.AppendElement(do_GetWeakReference(aElement));
    8774               0 :   NS_ASSERTION(GetFullScreenElement() == aElement, "Should match");
    8775               0 :   return true;
    8776                 : }
    8777                 : 
    8778                 : void
    8779               0 : nsDocument::FullScreenStackPop()
    8780                 : {
    8781               0 :   if (mFullScreenStack.IsEmpty()) {
    8782               0 :     return;
    8783                 :   }
    8784                 : 
    8785                 :   // Remove styles from existing top element.
    8786               0 :   Element* top = FullScreenStackTop();
    8787               0 :   nsEventStateManager::SetFullScreenState(top, false);
    8788                 : 
    8789                 :   // Remove top element. Note the remaining top element in the stack
    8790                 :   // will not have full-screen style bits set, so we will need to restore
    8791                 :   // them on the new top element before returning.
    8792               0 :   PRUint32 last = mFullScreenStack.Length() - 1;
    8793               0 :   mFullScreenStack.RemoveElementAt(last);
    8794                 : 
    8795                 :   // Pop from the stack null elements (references to elements which have
    8796                 :   // been GC'd since they were added to the stack) and elements which are
    8797                 :   // no longer in this document.
    8798               0 :   while (!mFullScreenStack.IsEmpty()) {
    8799               0 :     Element* element = FullScreenStackTop();
    8800               0 :     if (!element || !element->IsInDoc() || element->OwnerDoc() != this) {
    8801               0 :       NS_ASSERTION(!element->IsFullScreenAncestor(),
    8802                 :                    "Should have already removed full-screen styles");
    8803               0 :       PRUint32 last = mFullScreenStack.Length() - 1;
    8804               0 :       mFullScreenStack.RemoveElementAt(last);
    8805                 :     } else {
    8806                 :       // The top element of the stack is now an in-doc element. Apply the
    8807                 :       // full-screen styles and return.
    8808               0 :       nsEventStateManager::SetFullScreenState(element, true);
    8809               0 :       break;
    8810                 :     }
    8811                 :   }
    8812                 : }
    8813                 : 
    8814                 : Element*
    8815               0 : nsDocument::FullScreenStackTop()
    8816                 : {
    8817               0 :   if (mFullScreenStack.IsEmpty()) {
    8818               0 :     return nsnull;
    8819                 :   }
    8820               0 :   PRUint32 last = mFullScreenStack.Length() - 1;
    8821               0 :   nsCOMPtr<Element> element(do_QueryReferent(mFullScreenStack[last]));
    8822               0 :   NS_ASSERTION(element, "Should have full-screen element!");
    8823               0 :   NS_ASSERTION(element->IsInDoc(), "Full-screen element should be in doc");
    8824               0 :   NS_ASSERTION(element->OwnerDoc() == this, "Full-screen element should be in this doc");
    8825               0 :   return element;
    8826                 : }
    8827                 : 
    8828                 : // Returns true if aDoc is in the focused tab in the active window.
    8829                 : static bool
    8830               0 : IsInActiveTab(nsIDocument* aDoc)
    8831                 : {
    8832               0 :   nsCOMPtr<nsISupports> container = aDoc->GetContainer();
    8833               0 :   nsCOMPtr<nsIDocShell> docshell = do_QueryInterface(container);
    8834               0 :   if (!docshell) {
    8835               0 :     return false;
    8836                 :   }
    8837                 : 
    8838               0 :   bool isActive = false;
    8839               0 :   docshell->GetIsActive(&isActive);
    8840               0 :   if (!isActive) {
    8841               0 :     return false;
    8842                 :   }
    8843                 :   
    8844               0 :   nsCOMPtr<nsIDocShellTreeItem> dsti = do_QueryInterface(container);
    8845               0 :   if (!dsti) {
    8846               0 :     return false;
    8847                 :   }
    8848               0 :   nsCOMPtr<nsIDocShellTreeItem> rootItem;
    8849               0 :   dsti->GetRootTreeItem(getter_AddRefs(rootItem));
    8850               0 :   if (!rootItem) {
    8851               0 :     return false;
    8852                 :   }
    8853               0 :   nsCOMPtr<nsIDOMWindow> rootWin = do_GetInterface(rootItem);
    8854               0 :   if (!rootWin) {
    8855               0 :     return false;
    8856                 :   }
    8857                 : 
    8858               0 :   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
    8859               0 :   if (!fm) {
    8860               0 :     return false;
    8861                 :   }
    8862                 : 
    8863               0 :   nsCOMPtr<nsIDOMWindow> activeWindow;
    8864               0 :   fm->GetActiveWindow(getter_AddRefs(activeWindow));
    8865               0 :   if (!activeWindow) {
    8866               0 :     return false;
    8867                 :   }
    8868                 : 
    8869               0 :   return activeWindow == rootWin;
    8870                 : }
    8871                 : 
    8872                 : void
    8873               0 : nsDocument::RequestFullScreen(Element* aElement, bool aWasCallerChrome)
    8874                 : {
    8875               0 :   NS_ASSERTION(aElement,
    8876                 :     "Must pass non-null element to nsDocument::RequestFullScreen");
    8877               0 :   if (!aElement || aElement == GetFullScreenElement()) {
    8878               0 :     return;
    8879                 :   }
    8880               0 :   if (!aElement->IsInDoc()) {
    8881               0 :     LogFullScreenDenied(true, "FullScreenDeniedNotInDocument", this);
    8882               0 :     return;
    8883                 :   }
    8884               0 :   if (aElement->OwnerDoc() != this) {
    8885               0 :     LogFullScreenDenied(true, "FullScreenDeniedMovedDocument", this);
    8886               0 :     return;
    8887                 :   }
    8888               0 :   if (!GetWindow()) {
    8889               0 :     LogFullScreenDenied(true, "FullScreenDeniedLostWindow", this);
    8890               0 :     return;
    8891                 :   }
    8892               0 :   if (!IsFullScreenEnabled(aWasCallerChrome, true)) {
    8893                 :     // IsFullScreenEnabled calls LogFullScreenDenied, no need to log.
    8894               0 :     return;
    8895                 :   }
    8896               0 :   if (GetFullScreenElement() &&
    8897               0 :       !nsContentUtils::ContentIsDescendantOf(aElement, GetFullScreenElement())) {
    8898                 :     // If this document is full-screen, only grant full-screen requests from 
    8899                 :     // a descendent of the current full-screen element.
    8900               0 :     LogFullScreenDenied(true, "FullScreenDeniedNotDescendant", this);
    8901               0 :     return;
    8902                 :   }
    8903               0 :   if (!nsContentUtils::IsChromeDoc(this) && !IsInActiveTab(this)) {
    8904               0 :     LogFullScreenDenied(true, "FullScreenDeniedNotFocusedTab", this);
    8905               0 :     return;
    8906                 :   }
    8907                 :   // Deny requests when a windowed plugin is focused.
    8908               0 :   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
    8909               0 :   if (!fm) {
    8910               0 :     NS_WARNING("Failed to retrieve focus manager in full-screen request.");
    8911               0 :     return;
    8912                 :   }
    8913               0 :   nsCOMPtr<nsIDOMElement> focusedElement;
    8914               0 :   fm->GetFocusedElement(getter_AddRefs(focusedElement));
    8915               0 :   if (focusedElement) {
    8916               0 :     nsCOMPtr<nsIContent> content = do_QueryInterface(focusedElement);
    8917               0 :     if (nsContentUtils::HasPluginWithUncontrolledEventDispatch(content)) {
    8918               0 :       LogFullScreenDenied(true, "FullScreenDeniedFocusedPlugin", this);
    8919                 :       return;
    8920                 :     }
    8921                 :   }
    8922                 : 
    8923                 :   // Stores a list of documents which we must dispatch "mozfullscreenchange"
    8924                 :   // too. We're required by the spec to dispatch the events in root-to-leaf
    8925                 :   // order, but we traverse the doctree in a leaf-to-root order, so we save
    8926                 :   // references to the documents we must dispatch to so that we get the order
    8927                 :   // as specified.
    8928               0 :   nsAutoTArray<nsIDocument*, 8> changed;
    8929                 : 
    8930                 :   // Remember the root document, so that if a full-screen document is hidden
    8931                 :   // we can reset full-screen state in the remaining visible full-screen documents.
    8932               0 :   sFullScreenRootDoc = do_GetWeakReference(nsContentUtils::GetRootDocument(this));
    8933                 : 
    8934                 :   // Set the full-screen element. This sets the full-screen style on the
    8935                 :   // element, and the full-screen-ancestor styles on ancestors of the element
    8936                 :   // in this document.
    8937               0 :   DebugOnly<bool> x = FullScreenStackPush(aElement);
    8938               0 :   NS_ASSERTION(x, "Full-screen state of requesting doc should always change!");
    8939               0 :   changed.AppendElement(this);
    8940                 :   
    8941                 :   // Propagate up the document hierarchy, setting the full-screen element as
    8942                 :   // the element's container in ancestor documents. This also sets the
    8943                 :   // appropriate css styles as well. Note we don't propagate down the
    8944                 :   // document hierarchy, the full-screen element (or its container) is not
    8945                 :   // visible there.  
    8946               0 :   nsIDocument* child = this;
    8947                 :   nsIDocument* parent;
    8948               0 :   while ((parent = child->GetParentDocument())) {
    8949               0 :     Element* element = parent->FindContentForSubDocument(child)->AsElement();
    8950               0 :     if (static_cast<nsDocument*>(parent)->FullScreenStackPush(element)) {
    8951               0 :       changed.AppendElement(parent);
    8952               0 :       child = parent;
    8953                 :     } else {
    8954                 :       // We've reached either the root, or a point in the doctree where the
    8955                 :       // new full-screen element container is the same as the previous
    8956                 :       // full-screen element's container. No more changes need to be made
    8957                 :       // to the full-screen stacks of documents further up the tree.
    8958               0 :       break;
    8959                 :     }
    8960                 :   }
    8961                 : 
    8962                 :   // Dispatch "mozfullscreenchange" events. Note this loop is in reverse
    8963                 :   // order so that the events for the root document arrives before the leaf
    8964                 :   // document, as required by the spec.
    8965               0 :   for (PRUint32 i = 0; i < changed.Length(); ++i) {
    8966               0 :     DispatchFullScreenChange(changed[changed.Length() - i - 1]);
    8967                 :   }
    8968                 : 
    8969                 :   // Remember this is the requesting full-screen document.
    8970               0 :   sFullScreenDoc = do_GetWeakReference(static_cast<nsIDocument*>(this));
    8971                 : 
    8972                 : #ifdef DEBUG
    8973                 :   // Note assertions must run before SetWindowFullScreen() as that does
    8974                 :   // synchronous event dispatch which can run script which exits full-screen!
    8975               0 :   NS_ASSERTION(GetFullScreenElement() == aElement,
    8976                 :                "Full-screen element should be the requested element!");
    8977               0 :   NS_ASSERTION(IsFullScreenDoc(), "Should be full-screen doc");
    8978               0 :   nsCOMPtr<nsIDOMHTMLElement> fse;
    8979               0 :   GetMozFullScreenElement(getter_AddRefs(fse));
    8980               0 :   nsCOMPtr<nsIContent> c(do_QueryInterface(fse));
    8981               0 :   NS_ASSERTION(c->AsElement() == aElement,
    8982                 :     "GetMozFullScreenElement should match GetFullScreenElement()");
    8983                 : #endif
    8984                 : 
    8985                 :   // Make the window full-screen. Note we must make the state changes above
    8986                 :   // before making the window full-screen, as then the document reports as
    8987                 :   // being in full-screen mode when the chrome "fullscreen" event fires,
    8988                 :   // enabling chrome to distinguish between browser and dom full-screen
    8989                 :   // modes. Also note that nsGlobalWindow::SetFullScreen() (which
    8990                 :   // SetWindowFullScreen() calls) proxies to the root window in its hierarchy,
    8991                 :   // and does not operate on the a per-nsIDOMWindow basis.
    8992               0 :   SetWindowFullScreen(this, true);
    8993                 : }
    8994                 : 
    8995                 : NS_IMETHODIMP
    8996               0 : nsDocument::GetMozFullScreenElement(nsIDOMHTMLElement **aFullScreenElement)
    8997                 : {
    8998               0 :   NS_ENSURE_ARG_POINTER(aFullScreenElement);
    8999               0 :   *aFullScreenElement = nsnull;
    9000               0 :   if (IsFullScreenDoc()) {
    9001                 :     // Must have a full-screen element while in full-screen mode.
    9002               0 :     NS_ENSURE_STATE(GetFullScreenElement());
    9003               0 :     CallQueryInterface(GetFullScreenElement(), aFullScreenElement);
    9004                 :   }
    9005               0 :   return NS_OK;
    9006                 : }
    9007                 : 
    9008                 : Element*
    9009               0 : nsDocument::GetFullScreenElement()
    9010                 : {
    9011               0 :   Element* element = FullScreenStackTop();
    9012               0 :   NS_ASSERTION(!element || element->IsFullScreenAncestor(),
    9013                 :     "Should have full-screen styles applied!");
    9014               0 :   return element;
    9015                 : }
    9016                 : 
    9017                 : NS_IMETHODIMP
    9018               0 : nsDocument::GetMozFullScreen(bool *aFullScreen)
    9019                 : {
    9020               0 :   NS_ENSURE_ARG_POINTER(aFullScreen);
    9021               0 :   *aFullScreen = IsFullScreenDoc();
    9022               0 :   return NS_OK;
    9023                 : }
    9024                 : 
    9025                 : NS_IMETHODIMP
    9026               0 : nsDocument::GetMozFullScreenEnabled(bool *aFullScreen)
    9027                 : {
    9028               0 :   NS_ENSURE_ARG_POINTER(aFullScreen);
    9029               0 :   *aFullScreen = IsFullScreenEnabled(nsContentUtils::IsCallerChrome(), false);
    9030               0 :   return NS_OK;
    9031                 : }
    9032                 : 
    9033                 : static bool
    9034               0 : HasFullScreenSubDocument(nsIDocument* aDoc, void* aData)
    9035                 : {
    9036               0 :   if (aDoc->IsFullScreenDoc()) {
    9037                 :     // This subdocument is full-screen. Set result and return false to
    9038                 :     // stop iteration.
    9039               0 :     *static_cast<bool*>(aData) = true;
    9040               0 :     return false;
    9041                 :   }
    9042               0 :   return true;
    9043                 : }
    9044                 : 
    9045                 : static bool
    9046               0 : HasFullScreenSubDocument(nsIDocument* aDoc)
    9047                 : {
    9048               0 :   bool result = false;
    9049               0 :   aDoc->EnumerateSubDocuments(&HasFullScreenSubDocument, static_cast<void*>(&result));
    9050               0 :   return result;
    9051                 : }
    9052                 : 
    9053                 : bool
    9054               0 : nsDocument::IsFullScreenEnabled(bool aCallerIsChrome, bool aLogFailure)
    9055                 : {
    9056               0 :   if (nsContentUtils::IsFullScreenApiEnabled() && aCallerIsChrome) {
    9057                 :     // Chrome code can always use the full-screen API, provided it's not
    9058                 :     // explicitly disabled. Note IsCallerChrome() returns true when running
    9059                 :     // in an nsRunnable, so don't use GetMozFullScreenEnabled() from an
    9060                 :     // nsRunnable!
    9061               0 :     return true;
    9062                 :   }
    9063                 : 
    9064               0 :   if (!nsContentUtils::IsFullScreenApiEnabled()) {
    9065               0 :     LogFullScreenDenied(aLogFailure, "FullScreenDeniedDisabled", this);
    9066               0 :     return false;
    9067                 :   }
    9068               0 :   if (!IsVisible()) {
    9069               0 :     LogFullScreenDenied(aLogFailure, "FullScreenDeniedHidden", this);
    9070               0 :     return false;
    9071                 :   }
    9072               0 :   if (HasFullScreenSubDocument(this)) {
    9073               0 :     LogFullScreenDenied(aLogFailure, "FullScreenDeniedSubDocFullScreen", this);
    9074               0 :     return false;
    9075                 :   }
    9076                 : 
    9077                 :   // Ensure that all ancestor <iframe> elements have the mozallowfullscreen
    9078                 :   // boolean attribute set.
    9079               0 :   nsINode* node = static_cast<nsINode*>(this);
    9080               0 :   do {
    9081               0 :     nsIContent* content = static_cast<nsIContent*>(node);
    9082               0 :     if (content->IsHTML(nsGkAtoms::iframe) &&
    9083               0 :         !content->HasAttr(kNameSpaceID_None, nsGkAtoms::mozallowfullscreen)) {
    9084                 :       // The node requesting fullscreen, or one of its crossdoc ancestors,
    9085                 :       // is an iframe which doesn't have the "mozalllowfullscreen" attribute.
    9086                 :       // This request is not authorized by the parent document.
    9087               0 :       LogFullScreenDenied(aLogFailure, "FullScreenDeniedIframeDisallowed", this);
    9088               0 :       return false;
    9089                 :     }
    9090               0 :     node = nsContentUtils::GetCrossDocParentNode(node);
    9091                 :   } while (node);
    9092                 : 
    9093               0 :   return true;
    9094                 : }
    9095                 : 
    9096                 : #define EVENT(name_, id_, type_, struct_)                                 \
    9097                 :   NS_IMETHODIMP nsDocument::GetOn##name_(JSContext *cx, jsval *vp) {      \
    9098                 :     return nsINode::GetOn##name_(cx, vp);                                 \
    9099                 :   }                                                                       \
    9100                 :   NS_IMETHODIMP nsDocument::SetOn##name_(JSContext *cx, const jsval &v) { \
    9101                 :     return nsINode::SetOn##name_(cx, v);                                  \
    9102                 :   }
    9103                 : #define TOUCH_EVENT EVENT
    9104                 : #define DOCUMENT_ONLY_EVENT EVENT
    9105                 : #include "nsEventNameList.h"
    9106                 : #undef DOCUMENT_ONLY_EVENT
    9107                 : #undef TOUCH_EVENT
    9108                 : #undef EVENT
    9109                 : 
    9110                 : void
    9111               0 : nsDocument::UpdateVisibilityState()
    9112                 : {
    9113               0 :   VisibilityState oldState = mVisibilityState;
    9114               0 :   mVisibilityState = GetVisibilityState();
    9115               0 :   if (oldState != mVisibilityState) {
    9116                 :     nsContentUtils::DispatchTrustedEvent(this, static_cast<nsIDocument*>(this),
    9117               0 :                                          NS_LITERAL_STRING("mozvisibilitychange"),
    9118               0 :                                          false, false);
    9119                 :   }
    9120               0 : }
    9121                 : 
    9122                 : nsDocument::VisibilityState
    9123               0 : nsDocument::GetVisibilityState() const
    9124                 : {
    9125                 :   // We have to check a few pieces of information here:
    9126                 :   // 1)  Are we in bfcache (!IsVisible())?  If so, nothing else matters.
    9127                 :   // 2)  Do we have an outer window?  If not, we're hidden.  Note that we don't
    9128                 :   //     want to use GetWindow here because it does weird groveling for windows
    9129                 :   //     in some cases.
    9130                 :   // 3)  Is our outer window background?  If so, we're hidden.
    9131                 :   // Otherwise, we're visible.
    9132               0 :   if (!IsVisible() || !mWindow || !mWindow->GetOuterWindow() ||
    9133               0 :       mWindow->GetOuterWindow()->IsBackground()) {
    9134               0 :     return eHidden;
    9135                 :   }
    9136                 : 
    9137               0 :   return eVisible;
    9138                 : }
    9139                 : 
    9140                 : /* virtual */ void
    9141               0 : nsDocument::PostVisibilityUpdateEvent()
    9142                 : {
    9143                 :   nsCOMPtr<nsIRunnable> event =
    9144               0 :     NS_NewRunnableMethod(this, &nsDocument::UpdateVisibilityState);
    9145               0 :   NS_DispatchToMainThread(event);
    9146               0 : }
    9147                 : 
    9148                 : NS_IMETHODIMP
    9149               0 : nsDocument::GetMozHidden(bool* aHidden)
    9150                 : {
    9151               0 :   *aHidden = mVisibilityState != eVisible;
    9152               0 :   return NS_OK;
    9153                 : }
    9154                 : 
    9155                 : NS_IMETHODIMP
    9156               0 : nsDocument::GetMozVisibilityState(nsAString& aState)
    9157                 : {
    9158                 :   // This needs to stay in sync with the VisibilityState enum.
    9159                 :   static const char states[][8] = {
    9160                 :     "hidden",
    9161                 :     "visible"
    9162                 :   };
    9163                 :   PR_STATIC_ASSERT(NS_ARRAY_LENGTH(states) == eVisibilityStateCount);
    9164               0 :   aState.AssignASCII(states[mVisibilityState]);
    9165               0 :   return NS_OK;
    9166                 : }
    9167                 : 
    9168                 : /* virtual */ void
    9169               0 : nsIDocument::DocSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
    9170                 : {
    9171                 :   aWindowSizes->mDOM +=
    9172               0 :     nsINode::SizeOfExcludingThis(aWindowSizes->mMallocSizeOf);
    9173                 : 
    9174               0 :   if (mPresShell) {
    9175                 :     mPresShell->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf,
    9176                 :                                     &aWindowSizes->mLayoutArenas,
    9177                 :                                     &aWindowSizes->mLayoutStyleSets,
    9178               0 :                                     &aWindowSizes->mLayoutTextRuns);
    9179                 :   }
    9180                 : 
    9181                 :   // Measurement of the following members may be added later if DMD finds it
    9182                 :   // is worthwhile:
    9183                 :   // - many!
    9184               0 : }
    9185                 : 
    9186                 : void
    9187               0 : nsIDocument::DocSizeOfIncludingThis(nsWindowSizes* aWindowSizes) const
    9188                 : {
    9189               0 :   aWindowSizes->mDOM += aWindowSizes->mMallocSizeOf(this);
    9190               0 :   DocSizeOfExcludingThis(aWindowSizes);
    9191               0 : }
    9192                 : 
    9193                 : static size_t
    9194               0 : SizeOfStyleSheetsElementIncludingThis(nsIStyleSheet* aStyleSheet,
    9195                 :                                       nsMallocSizeOfFun aMallocSizeOf,
    9196                 :                                       void* aData)
    9197                 : {
    9198               0 :   return aStyleSheet->SizeOfIncludingThis(aMallocSizeOf);
    9199                 : }
    9200                 : 
    9201                 : size_t
    9202               0 : nsDocument::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
    9203                 : {
    9204                 :   // This SizeOfExcludingThis() overrides the one from nsINode.  But
    9205                 :   // nsDocuments can only appear at the top of the DOM tree, and we use the
    9206                 :   // specialized DocSizeOfExcludingThis() in that case.  So this should never
    9207                 :   // be called.
    9208               0 :   MOZ_NOT_REACHED("nsDocument::SizeOfExcludingThis");
    9209                 :   return 0;
    9210                 : }
    9211                 : 
    9212                 : void
    9213               0 : nsDocument::DocSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
    9214                 : {
    9215               0 :   nsIDocument::DocSizeOfExcludingThis(aWindowSizes);
    9216                 : 
    9217               0 :   for (nsIContent* node = nsINode::GetFirstChild();
    9218                 :        node;
    9219               0 :        node = node->GetNextNode(this))
    9220                 :   {
    9221                 :     aWindowSizes->mDOM +=
    9222               0 :       node->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf);
    9223                 :   }
    9224                 : 
    9225                 :   aWindowSizes->mStyleSheets +=
    9226                 :     mStyleSheets.SizeOfExcludingThis(SizeOfStyleSheetsElementIncludingThis,
    9227               0 :                                      aWindowSizes->mMallocSizeOf); 
    9228                 :   aWindowSizes->mDOM +=
    9229                 :     mAttrStyleSheet ?
    9230               0 :     mAttrStyleSheet->DOMSizeOfIncludingThis(aWindowSizes->mMallocSizeOf) :
    9231               0 :     0;
    9232                 : 
    9233                 :   // Measurement of the following members may be added later if DMD finds it
    9234                 :   // is worthwhile:
    9235                 :   // - many!
    9236            4392 : }

Generated by: LCOV version 1.7