NS_IMPL_ADDREF(nsDocument) NS_IMPL_RELEASE(nsDocument)  nsresult nsDocument::Init() { if (mNodeInfoManager) { return NS_ERROR_ALREADY_INITIALIZED; }  mNodeInfoManager = new nsNodeInfoManager(); NS_ENSURE_TRUE(mNodeInfoManager, NS_ERROR_OUT_OF_MEMORY);  return mNodeInfoManager->Init(this); }  void nsDocument::Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup) { nsCOMPtr<nsIURI> uri; if (aChannel) { aChannel->GetOriginalURI(getter_AddRefs(uri));  PRBool isChrome = PR_FALSE; PRBool isRes = PR_FALSE; uri->SchemeIs("chrome", &isChrome); uri->SchemeIs("resource", &isRes);  if (!isChrome && !isRes) aChannel->GetURI(getter_AddRefs(uri)); }  ResetToURI(uri, aLoadGroup);  if (aChannel) { nsCOMPtr<nsISupports> owner; aChannel->GetOwner(getter_AddRefs(owner));  mPrincipal = do_QueryInterface(owner); } }  void nsDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup) { NS_PRECONDITION(aURI, "Null URI passed to ResetToURI"); mDocumentTitle.Truncate();  mPrincipal = nsnull; mDocumentLoadGroup = nsnull;    if (mSubDocuments) { PL_DHashTableDestroy(mSubDocuments);  mSubDocuments = nsnull; }  mRootContent = nsnull; PRInt32 count, i; count = mChildren.Count(); for (i = 0; i < count; i++) { nsCOMPtr<nsIContent> content = mChildren[i];  content->SetDocument(nsnull, PR_TRUE, PR_TRUE); ContentRemoved(nsnull, content, i); } mChildren.Clear();   ResetStylesheetsToURI(aURI);   mListenerManager = nsnull;   mDOMStyleSheets = nsnull;  mDocumentURI = aURI; mDocumentBaseURI = mDocumentURI;  if (aLoadGroup) { mDocumentLoadGroup = do_GetWeakReference(aLoadGroup);    }  mLastModified.Truncate(); mContentType.Truncate(); mContentLanguage.Truncate(); mBaseTarget.Truncate(); mReferrer.Truncate();  mXMLDeclarationBits = 0; }  nsresult nsDocument::ResetStylesheetsToURI(nsIURI* aURI) { NS_PRECONDITION(aURI, "Null URI passed to ResetStylesheetsToURI");   PRInt32 indx = mStyleSheets.Count(); while (--indx >= 0) { nsIStyleSheet* sheet = mStyleSheets[indx]; sheet->SetOwningDocument(nsnull);  PRBool applicable; sheet->GetApplicable(applicable); if (applicable) { RemoveStyleSheetFromStyleSets(sheet); }   }   mStyleSheets.Clear();     nsresult rv; if (mAttrStyleSheet) { rv = mAttrStyleSheet->Reset(aURI); } else { rv = NS_NewHTMLStyleSheet(getter_AddRefs(mAttrStyleSheet), aURI, this); } NS_ENSURE_SUCCESS(rv, rv);  AddStyleSheet(mAttrStyleSheet, 0);  if (mStyleAttrStyleSheet) { rv = mStyleAttrStyleSheet->Reset(aURI); } else { rv = NS_NewHTMLCSSStyleSheet(getter_AddRefs(mStyleAttrStyleSheet), aURI, this); } NS_ENSURE_SUCCESS(rv, rv);  AddStyleSheet(mStyleAttrStyleSheet, 0);  return rv; }  nsresult nsDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel, nsILoadGroup* aLoadGroup, nsISupports* aContainer, nsIStreamListener **aDocListener, PRBool aReset, nsIContentSink* aSink) { if (aReset) { Reset(aChannel, aLoadGroup); }  nsCAutoString contentType; if (NS_SUCCEEDED(aChannel->GetContentType(contentType))) {  nsACString::const_iterator start, end, semicolon; contentType.BeginReading(start); contentType.EndReading(end); semicolon = start; FindCharInReadable(';', semicolon, end); mContentType = Substring(start, semicolon); }  RetrieveRelevantHeaders(aChannel);  return NS_OK; }  void nsDocument::StopDocumentLoad() { }  NS_IMETHODIMP nsDocument::GetLastModified(nsAString& aLastModified) { if (!mLastModified.IsEmpty()) { CopyASCIItoUCS2(mLastModified, aLastModified); } else {   CopyASCIItoUCS2(NS_LITERAL_CSTRING("January 1, 1970 GMT"), aLastModified); }  return NS_OK; }  nsIPrincipal* nsDocument::GetPrincipal() { if (!mPrincipal) { nsresult rv; nsCOMPtr<nsIScriptSecurityManager> securityManager = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); if (NS_FAILED(rv)) return nsnull; NS_WARN_IF_FALSE(mDocumentURI, "no URI!"); rv = securityManager->GetCodebasePrincipal(mDocumentURI, getter_AddRefs(mPrincipal));  if (NS_FAILED(rv)) { return nsnull; } }  return mPrincipal; }   NS_IMETHODIMP nsDocument::GetPrincipal(nsIPrincipal **aPrincipal) { NS_IF_ADDREF(*aPrincipal = GetPrincipal()); return *aPrincipal ? NS_OK : NS_ERROR_FAILURE; }  void nsDocument::SetPrincipal(nsIPrincipal *aNewPrincipal) { mPrincipal = aNewPrincipal; }  NS_IMETHODIMP nsDocument::GetContentType(nsAString& aContentType) { CopyUTF8toUTF16(mContentType, aContentType);  return NS_OK; }  void nsDocument::SetContentType(const nsAString& aContentType) { NS_ASSERTION(mContentType.IsEmpty() || mContentType.Equals(NS_ConvertUCS2toUTF8(aContentType)), "Do you really want to change the content-type?");  CopyUTF16toUTF8(aContentType, mContentType); }  NS_IMETHODIMP nsDocument::GetReferrer(nsAString& aReferrer) { CopyUTF8toUTF16(mReferrer, aReferrer); return NS_OK; }  nsresult nsDocument::SetBaseURI(nsIURI* aURI) { nsresult rv = NS_OK;  if (aURI) { nsIScriptSecurityManager* securityManager = nsContentUtils::GetSecurityManager(); rv = securityManager->CheckLoadURI(mDocumentURI, aURI, nsIScriptSecurityManager::STANDARD); if (NS_SUCCEEDED(rv)) { mDocumentBaseURI = aURI; } } else { mDocumentBaseURI = nsnull; }  return rv; }  void nsDocument::GetBaseTarget(nsAString &aBaseTarget) const { aBaseTarget.Assign(mBaseTarget); }  void nsDocument::SetBaseTarget(const nsAString &aBaseTarget) { mBaseTarget.Assign(aBaseTarget); }  void nsDocument::SetDocumentCharacterSet(const nsACString& aCharSetID) { if (!mCharacterSet.Equals(aCharSetID)) { mCharacterSet = aCharSetID;  #ifdef DEBUG nsCOMPtr<nsICharsetAlias> calias(do_GetService(kCharsetAliasCID)); if (calias) { nsCAutoString canonicalName; calias->GetPreferred(aCharSetID, canonicalName); NS_ASSERTION(canonicalName.Equals(aCharSetID), "charset name must be canonical"); } #endif  PRInt32 n = mCharSetObservers.Count();  for (PRInt32 i = 0; i < n; i++) { nsIObserver* observer = NS_STATIC_CAST(nsIObserver *, mCharSetObservers.ElementAt(i));  observer->Observe(NS_STATIC_CAST(nsIDocument *, this), "charset", NS_ConvertASCIItoUCS2(aCharSetID).get()); } } }  nsresult nsDocument::AddCharSetObserver(nsIObserver* aObserver) { NS_ENSURE_ARG_POINTER(aObserver);  NS_ENSURE_TRUE(mCharSetObservers.AppendElement(aObserver), NS_ERROR_FAILURE);  return NS_OK; }  void nsDocument::RemoveCharSetObserver(nsIObserver* aObserver) { mCharSetObservers.RemoveElement(aObserver); }  nsILineBreaker* nsDocument::GetLineBreaker() { if (!mLineBreaker) {  nsresult rv; nsCOMPtr<nsILineBreakerFactory> lbf = do_GetService(NS_LWBRK_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, nsnull);  lbf->GetBreaker(nsString(), getter_AddRefs(mLineBreaker)); NS_ENSURE_TRUE(mLineBreaker, nsnull); }  return mLineBreaker; }  void nsDocument::SetLineBreaker(nsILineBreaker* aLineBreaker) { mLineBreaker = aLineBreaker; }  nsIWordBreaker* nsDocument::GetWordBreaker() { if (!mWordBreaker) {  nsresult rv; nsCOMPtr<nsIWordBreakerFactory> wbf = do_GetService(NS_LWBRK_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, nsnull);  wbf->GetBreaker(nsString(), getter_AddRefs(mWordBreaker)); NS_ENSURE_TRUE(wbf, nsnull); }  return mWordBreaker; }  void nsDocument::SetWordBreaker(nsIWordBreaker* aWordBreaker) { mWordBreaker = aWordBreaker; }  void nsDocument::GetHeaderData(nsIAtom* aHeaderField, nsAString& aData) const { aData.Truncate(); const nsDocHeaderData* data = mHeaderData; while (data) { if (data->mField == aHeaderField) { aData = data->mData;  break; } data = data->mNext; } }  void nsDocument::SetHeaderData(nsIAtom* aHeaderField, const nsAString& aData) { if (!aHeaderField) { NS_ERROR("null headerField"); return; }  if (!mHeaderData) { if (!aData.IsEmpty()) { mHeaderData = new nsDocHeaderData(aHeaderField, aData); } } else { nsDocHeaderData* data = mHeaderData; nsDocHeaderData** lastPtr = &mHeaderData; PRBool found = PR_FALSE; do { if (data->mField == aHeaderField) { if (!aData.IsEmpty()) { data->mData.Assign(aData); } else { *lastPtr = data->mNext; data->mNext = nsnull; delete data; } found = PR_TRUE;  break; } lastPtr = &(data->mNext); data = *lastPtr; } while (data);  if (!aData.IsEmpty() && !found) {  *lastPtr = new nsDocHeaderData(aHeaderField, aData); } }  if (aHeaderField == nsHTMLAtoms::headerDefaultStyle) {  nsAutoString type; nsAutoString title; PRInt32 index;  mCSSLoader->SetPreferredSheet(aData);  PRInt32 count = mStyleSheets.Count(); for (index = 0; index < count; index++) { nsIStyleSheet* sheet = mStyleSheets[index]; sheet->GetType(type); if (!type.Equals(NS_LITERAL_STRING("text/html"))) { sheet->GetTitle(title); if (!title.IsEmpty()) { PRBool enabled = (!aData.IsEmpty() && title.Equals(aData, nsCaseInsensitiveStringComparator()));  sheet->SetEnabled(enabled); } } } } }  nsresult nsDocument::CreateShell(nsIPresContext* aContext, nsIViewManager* aViewManager, nsStyleSet* aStyleSet, nsIPresShell** aInstancePtrResult) {    return doCreateShell(aContext, aViewManager, aStyleSet, eCompatibility_FullStandards, aInstancePtrResult); }  nsresult nsDocument::doCreateShell(nsIPresContext* aContext, nsIViewManager* aViewManager, nsStyleSet* aStyleSet, nsCompatibility aCompatMode, nsIPresShell** aInstancePtrResult) { nsCOMPtr<nsIPresShell> shell; nsresult rv = NS_NewPresShell(getter_AddRefs(shell)); if (NS_FAILED(rv)) { return rv; }  rv = shell->Init(this, aContext, aViewManager, aStyleSet, aCompatMode); NS_ENSURE_SUCCESS(rv, rv);   mPresShells.AppendElement(shell); *aInstancePtrResult = shell.get(); NS_ADDREF(*aInstancePtrResult);  return NS_OK; }  PRBool nsDocument::DeleteShell(nsIPresShell* aShell) { return mPresShells.RemoveElement(aShell); }  PRUint32 nsDocument::GetNumberOfShells() const { return mPresShells.Count(); }  nsIPresShell * nsDocument::GetShellAt(PRUint32 aIndex) const { return (nsIPresShell*)mPresShells.SafeElementAt(aIndex); }  PR_STATIC_CALLBACK(void) SubDocClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry) { SubDocMapEntry *e = NS_STATIC_CAST(SubDocMapEntry *, entry);  NS_RELEASE(e->mKey); NS_IF_RELEASE(e->mSubDocument); }
NS_INTERFACE_MAP_BEGIN(nsDOMImplementation)  NS_INTERFACE_MAP_ENTRY(nsIDOMDOMImplementation)  NS_INTERFACE_MAP_ENTRY(nsIPrivateDOMImplementation)  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMDOMImplementation)  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(DOMImplementation)NS_INTERFACE_MAP_END