Bug 118704. Get the document title from the DOM instead of storing it in the document object. Relanding with hopeful leak fix. r+sr=jst

This commit is contained in:
Robert O'Callahan 2008-08-18 14:10:28 +12:00
Родитель 89c80e25b5
Коммит 98eff410d2
26 изменённых файлов: 465 добавлений и 254 удалений

Просмотреть файл

@ -411,11 +411,10 @@ NS_IMETHODIMP nsDocAccessible::GetURL(nsAString& aURL)
NS_IMETHODIMP nsDocAccessible::GetTitle(nsAString& aTitle)
{
if (mDocument) {
aTitle = mDocument->GetDocumentTitle();
return NS_OK;
nsCOMPtr<nsIDOMNSDocument> domnsDocument(do_QueryInterface(mDocument));
if (domnsDocument) {
return domnsDocument->GetTitle(aTitle);
}
return NS_ERROR_FAILURE;
}

Просмотреть файл

@ -97,8 +97,8 @@ class nsFrameLoader;
// IID for the nsIDocument interface
#define NS_IDOCUMENT_IID \
{ 0xc45a4a53, 0x0485, 0x43d5, \
{ 0x85, 0x95, 0x9f, 0x0b, 0xf4, 0x0d, 0xe9, 0x34 } }
{ 0x5f0203a8, 0xd926, 0x4adf, \
{ 0xba, 0x96, 0xe6, 0xc3, 0xe6, 0xbb, 0x1b, 0xe5 } }
// Flag for AddStyleSheet().
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
@ -167,14 +167,13 @@ public:
virtual void StopDocumentLoad() = 0;
/**
* Return the title of the document. This will return a void string
* if there is no title for this document).
* Signal that the document title may have changed
* (see nsDocument::GetTitle).
* @param aBoundTitleElement true if an HTML or SVG <title> element
* has just been bound to the document.
*/
const nsString& GetDocumentTitle() const
{
return mDocumentTitle;
}
virtual void NotifyPossibleTitleChange(PRBool aBoundTitleElement) = 0;
/**
* Return the URI for the document. May return null.
*/
@ -1011,7 +1010,6 @@ protected:
friend class mozAutoSubtreeModified;
friend class nsPresShellIterator;
nsString mDocumentTitle;
nsCOMPtr<nsIURI> mDocumentURI;
nsCOMPtr<nsIURI> mDocumentBaseURI;

Просмотреть файл

@ -1419,11 +1419,6 @@ nsContentSink::EndUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType)
void
nsContentSink::DidBuildModelImpl(void)
{
if (mDocument && mDocument->GetDocumentTitle().IsVoid()) {
nsCOMPtr<nsIDOMNSDocument> dom_doc(do_QueryInterface(mDocument));
dom_doc->SetTitle(EmptyString());
}
// Cancel a timer if we had one out there
if (mNotificationTimer) {
SINK_TRACE(gContentSinkLogModuleInfo, SINK_TRACE_REFLOW,

Просмотреть файл

@ -270,7 +270,6 @@ protected:
PRUint8 mDynamicLowerValue : 1;
PRUint8 mParsing : 1;
PRUint8 mDroppedTimer : 1;
PRUint8 mInTitle : 1;
PRUint8 mChangeScrollPosWhenScrollingToRef : 1;
// If true, we deferred starting layout until sheets load
PRUint8 mDeferredLayoutStart : 1;

Просмотреть файл

@ -26,6 +26,7 @@
* Pierre Phaneuf <pp@ludusdesign.com>
* Pete Collins <petejc@collab.net>
* James Ross <silver@warwickcompsoc.co.uk>
* Ryan Jones <sciguyryan@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -73,6 +74,7 @@
#include "nsIDOMAbstractView.h"
#include "nsIDOMDocumentXBL.h"
#include "nsGenericElement.h"
#include "nsGenericHTMLElement.h"
#include "nsIDOMEventGroup.h"
#include "nsIDOMCDATASection.h"
#include "nsIDOMProcessingInstruction.h"
@ -114,8 +116,6 @@
#include "nsPIDOMWindow.h"
#include "nsIDOMElement.h"
#include "nsGkAtoms.h"
// for radio group stuff
#include "nsIDOMHTMLInputElement.h"
#include "nsIRadioVisitor.h"
@ -1450,7 +1450,6 @@ nsDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup,
}
#endif
mDocumentTitle.SetIsVoid(PR_TRUE);
mIdentifierMap.Clear();
SetPrincipal(nsnull);
@ -4297,20 +4296,176 @@ nsDocument::GetLocation(nsIDOMLocation **_retval)
return w->GetLocation(_retval);
}
nsIContent*
nsDocument::GetHtmlContent()
{
nsIContent* rootContent = GetRootContent();
if (rootContent && rootContent->Tag() == nsGkAtoms::html &&
rootContent->IsNodeOfType(nsINode::eHTML))
return rootContent;
return nsnull;
}
nsIContent*
nsDocument::GetHtmlChildContent(nsIAtom* aTag)
{
nsIContent* html = GetHtmlContent();
if (!html)
return nsnull;
// Look for the element with aTag inside html. This needs to run
// forwards to find the first such element.
for (PRUint32 i = 0; i < html->GetChildCount(); ++i) {
nsIContent* result = html->GetChildAt(i);
if (result->Tag() == aTag && result->IsNodeOfType(nsINode::eHTML))
return result;
}
return nsnull;
}
nsIContent*
nsDocument::GetTitleContent(PRUint32 aNodeType)
{
// mMayHaveTitleElement will have been set to true if any HTML or SVG
// <title> element has been bound to this document. So if it's false,
// we know there is nothing to do here. This avoids us having to search
// the whole DOM if someone calls document.title on a large document
// without a title.
if (!mMayHaveTitleElement)
return nsnull;
nsRefPtr<nsContentList> list =
NS_GetContentList(this, nsGkAtoms::title, kNameSpaceID_Unknown);
if (!list)
return nsnull;
for (PRUint32 i = 0; ; ++i) {
// Avoid calling list->Length --- by calling Item one at a time,
// we can avoid scanning the whole document to build the list of all
// matches
nsIContent* elem = list->Item(i, PR_FALSE);
if (!elem)
return nsnull;
if (elem->IsNodeOfType(aNodeType))
return elem;
}
}
void
nsDocument::GetTitleFromElement(PRUint32 aNodeType, nsAString& aTitle)
{
nsIContent* title = GetTitleContent(aNodeType);
if (!title)
return;
nsContentUtils::GetNodeTextContent(title, PR_FALSE, aTitle);
}
NS_IMETHODIMP
nsDocument::GetTitle(nsAString& aTitle)
{
aTitle.Assign(mDocumentTitle);
// Make sure not to return null from this method even if
// mDocumentTitle is void.
aTitle.SetIsVoid(PR_FALSE);
aTitle.Truncate();
nsIContent *rootContent = GetRootContent();
if (!rootContent)
return NS_OK;
nsAutoString tmp;
switch (rootContent->GetNameSpaceID()) {
#ifdef MOZ_XUL
case kNameSpaceID_XUL:
rootContent->GetAttr(kNameSpaceID_None, nsGkAtoms::title, tmp);
break;
#endif
#ifdef MOZ_SVG
case kNameSpaceID_SVG:
if (rootContent->Tag() == nsGkAtoms::svg) {
GetTitleFromElement(nsINode::eSVG, tmp);
break;
} // else fall through
#endif
default:
GetTitleFromElement(nsINode::eHTML, tmp);
break;
}
tmp.CompressWhitespace();
aTitle = tmp;
return NS_OK;
}
NS_IMETHODIMP
nsDocument::SetTitle(const nsAString& aTitle)
{
nsIContent *rootContent = GetRootContent();
if (!rootContent)
return NS_OK;
switch (rootContent->GetNameSpaceID()) {
#ifdef MOZ_SVG
case kNameSpaceID_SVG:
return NS_OK; // SVG doesn't support setting a title
#endif
#ifdef MOZ_XUL
case kNameSpaceID_XUL:
return rootContent->SetAttr(kNameSpaceID_None, nsGkAtoms::title,
aTitle, PR_TRUE);
#endif
}
// Batch updates so that mutation events don't change "the title
// element" under us
mozAutoDocUpdate updateBatch(this, UPDATE_CONTENT_MODEL, PR_TRUE);
nsIContent* title = GetTitleContent(nsINode::eHTML);
if (!title) {
nsIContent *head = GetHeadContent();
if (!head)
return NS_OK;
{
nsCOMPtr<nsINodeInfo> titleInfo;
mNodeInfoManager->GetNodeInfo(nsGkAtoms::title, nsnull,
kNameSpaceID_None, getter_AddRefs(titleInfo));
if (!titleInfo)
return NS_OK;
title = NS_NewHTMLTitleElement(titleInfo);
if (!title)
return NS_OK;
}
head->AppendChildTo(title, PR_TRUE);
}
return nsContentUtils::SetNodeTextContent(title, aTitle, PR_FALSE);
}
void
nsDocument::NotifyPossibleTitleChange(PRBool aBoundTitleElement)
{
if (aBoundTitleElement) {
mMayHaveTitleElement = PR_TRUE;
}
if (mPendingTitleChangeEvent.IsPending())
return;
nsRefPtr<nsRunnableMethod<nsDocument> > event =
new nsRunnableMethod<nsDocument>(this,
&nsDocument::DoNotifyPossibleTitleChange);
nsresult rv = NS_DispatchToCurrentThread(event);
if (NS_SUCCEEDED(rv)) {
mPendingTitleChangeEvent = event;
}
}
void
nsDocument::DoNotifyPossibleTitleChange()
{
mPendingTitleChangeEvent.Forget();
nsAutoString title;
GetTitle(title);
nsPresShellIterator iter(this);
nsCOMPtr<nsIPresShell> shell;
while ((shell = iter.GetNextShell())) {
@ -4322,18 +4477,13 @@ nsDocument::SetTitle(const nsAString& aTitle)
if (!docShellWin)
continue;
nsresult rv = docShellWin->SetTitle(PromiseFlatString(aTitle).get());
NS_ENSURE_SUCCESS(rv, rv);
docShellWin->SetTitle(PromiseFlatString(title).get());
}
mDocumentTitle.Assign(aTitle);
// Fire a DOM event for the title change.
nsContentUtils::DispatchTrustedEvent(this, static_cast<nsIDocument*>(this),
NS_LITERAL_STRING("DOMTitleChanged"),
PR_TRUE, PR_TRUE);
return NS_OK;
}
NS_IMETHODIMP

Просмотреть файл

@ -92,6 +92,7 @@
#include "nsIChannel.h"
#include "nsCycleCollectionParticipant.h"
#include "nsContentList.h"
#include "nsGkAtoms.h"
// Put these here so all document impls get them automatically
#include "nsHTMLStyleSheet.h"
@ -104,6 +105,7 @@
#include "nsDOMAttributeMap.h"
#include "nsPresShellIterator.h"
#include "nsContentUtils.h"
#include "nsThreadUtils.h"
#define XML_DECLARATION_BITS_DECLARATION_EXISTS (1 << 0)
#define XML_DECLARATION_BITS_ENCODING_EXISTS (1 << 1)
@ -428,6 +430,8 @@ public:
virtual void StopDocumentLoad();
virtual void NotifyPossibleTitleChange(PRBool aBoundTitleElement);
virtual void SetDocumentURI(nsIURI* aURI);
/**
@ -796,6 +800,9 @@ public:
static nsresult GetElementsByClassNameHelper(nsINode* aRootNode,
const nsAString& aClasses,
nsIDOMNodeList** aReturn);
void DoNotifyPossibleTitleChange();
protected:
void RegisterNamedItems(nsIContent *aContent);
@ -828,6 +835,30 @@ protected:
// That will stop us from resolving URIs for all links as they are removed.
void DestroyLinkMap();
// Get the root <html> element, or return null if there isn't one (e.g.
// if the root isn't <html>)
nsIContent* GetHtmlContent();
// Returns the first child of GetHtmlContent which has the given tag,
// or nsnull if that doesn't exist.
nsIContent* GetHtmlChildContent(nsIAtom* aTag);
// Get the canonical <body> element, or return null if there isn't one (e.g.
// if the root isn't <html> or if the <body> isn't there)
nsIContent* GetBodyContent() {
return GetHtmlChildContent(nsGkAtoms::body);
}
// Get the canonical <head> element, or return null if there isn't one (e.g.
// if the root isn't <html> or if the <head> isn't there)
nsIContent* GetHeadContent() {
return GetHtmlChildContent(nsGkAtoms::head);
}
// Get the first <title> element with the given IsNodeOfType type, or
// return null if there isn't one
nsIContent* GetTitleContent(PRUint32 aNodeType);
// Find the first "title" element in the given IsNodeOfType type and
// append the concatenation of its text node children to aTitle. Do
// nothing if there is no such element.
void GetTitleFromElement(PRUint32 aNodeType, nsAString& aTitle);
nsresult doCreateShell(nsPresContext* aContext,
nsIViewManager* aViewManager, nsStyleSet* aStyleSet,
nsCompatibility aCompatMode,
@ -940,6 +971,9 @@ protected:
// XXXbz should this be reset if someone manually calls
// SetContentType() on this document?
PRPackedBool mIsRegularHTML:1;
// True if this document has ever had an HTML or SVG <title> element
// bound to it
PRPackedBool mMayHaveTitleElement:1;
PRPackedBool mHasWarnedAboutBoxObjects:1;
@ -1031,7 +1065,8 @@ private:
nsTArray<nsRefPtr<nsFrameLoader> > mInitializableFrameLoaders;
nsTArray<nsRefPtr<nsFrameLoader> > mFinalizableFrameLoaders;
nsRevocableEventPtr<nsRunnableMethod<nsDocument> > mPendingTitleChangeEvent;
};
#endif /* nsDocument_h___ */

Просмотреть файл

@ -198,6 +198,7 @@ _TEST_FILES = test_bug5141.html \
test_NodeIterator_mutations_2.html \
test_bug28293.html \
file_bug28293.sjs \
test_title.html \
$(NULL)
libs:: $(_TEST_FILES)

Просмотреть файл

@ -20,6 +20,7 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ryan Jones <sciguyryan@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -42,10 +43,12 @@
#include "nsIDOMText.h"
#include "nsIDocument.h"
#include "nsIDOMHTMLDocument.h"
#include "nsContentUtils.h"
#include "nsPLDOMEvent.h"
class nsHTMLTitleElement : public nsGenericHTMLElement,
public nsIDOMHTMLTitleElement
public nsIDOMHTMLTitleElement,
public nsStubMutationObserver
{
public:
nsHTMLTitleElement(nsINodeInfo *aNodeInfo);
@ -66,7 +69,25 @@ public:
// nsIDOMHTMLTitleElement
NS_DECL_NSIDOMHTMLTITLEELEMENT
// nsIMutationObserver
NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
virtual nsresult BindToTree(nsIDocument *aDocument, nsIContent *aParent,
nsIContent *aBindingParent,
PRBool aCompileEventHandlers);
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
PRBool aNullParent = PR_TRUE);
virtual nsresult DoneAddingChildren(PRBool aHaveNotified);
private:
void SendTitleChangeEvent(PRBool aBound);
};
@ -76,6 +97,7 @@ NS_IMPL_NS_NEW_HTML_ELEMENT(Title)
nsHTMLTitleElement::nsHTMLTitleElement(nsINodeInfo *aNodeInfo)
: nsGenericHTMLElement(aNodeInfo)
{
AddMutationObserver(this);
}
nsHTMLTitleElement::~nsHTMLTitleElement()
@ -89,7 +111,9 @@ NS_IMPL_RELEASE_INHERITED(nsHTMLTitleElement, nsGenericElement)
// QueryInterface implementation for nsHTMLTitleElement
NS_HTML_CONTENT_INTERFACE_TABLE_HEAD(nsHTMLTitleElement, nsGenericHTMLElement)
NS_INTERFACE_TABLE_INHERITED1(nsHTMLTitleElement, nsIDOMHTMLTitleElement)
NS_INTERFACE_TABLE_INHERITED2(nsHTMLTitleElement,
nsIDOMHTMLTitleElement,
nsIMutationObserver)
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLTitleElement)
@ -100,18 +124,89 @@ NS_IMETHODIMP
nsHTMLTitleElement::GetText(nsAString& aTitle)
{
nsContentUtils::GetNodeTextContent(this, PR_FALSE, aTitle);
return NS_OK;
}
NS_IMETHODIMP
nsHTMLTitleElement::SetText(const nsAString& aTitle)
{
nsCOMPtr<nsIDOMHTMLDocument> htmlDoc(do_QueryInterface(GetCurrentDoc()));
if (htmlDoc) {
htmlDoc->SetTitle(aTitle);
}
return nsContentUtils::SetNodeTextContent(this, aTitle, PR_TRUE);
}
void
nsHTMLTitleElement::CharacterDataChanged(nsIDocument *aDocument,
nsIContent *aContent,
CharacterDataChangeInfo *aInfo)
{
SendTitleChangeEvent(PR_FALSE);
}
void
nsHTMLTitleElement::ContentAppended(nsIDocument *aDocument,
nsIContent *aContainer,
PRInt32 aNewIndexInContainer)
{
SendTitleChangeEvent(PR_FALSE);
}
void
nsHTMLTitleElement::ContentInserted(nsIDocument *aDocument,
nsIContent *aContainer,
nsIContent *aChild,
PRInt32 aIndexInContainer)
{
SendTitleChangeEvent(PR_FALSE);
}
void
nsHTMLTitleElement::ContentRemoved(nsIDocument *aDocument,
nsIContent *aContainer,
nsIContent *aChild,
PRInt32 aIndexInContainer)
{
SendTitleChangeEvent(PR_FALSE);
}
nsresult
nsHTMLTitleElement::BindToTree(nsIDocument *aDocument,
nsIContent *aParent,
nsIContent *aBindingParent,
PRBool aCompileEventHandlers)
{
// Let this fall through.
nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
SendTitleChangeEvent(PR_TRUE);
return NS_OK;
}
void
nsHTMLTitleElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
{
SendTitleChangeEvent(PR_FALSE);
// Let this fall through.
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
}
nsresult
nsHTMLTitleElement::DoneAddingChildren(PRBool aHaveNotified)
{
if (!aHaveNotified) {
SendTitleChangeEvent(PR_FALSE);
}
return NS_OK;
}
void
nsHTMLTitleElement::SendTitleChangeEvent(PRBool aBound)
{
nsIDocument* doc = GetCurrentDoc();
if (doc) {
doc->NotifyPossibleTitleChange(aBound);
}
}

Просмотреть файл

@ -218,7 +218,6 @@ public:
#endif
protected:
nsresult UpdateDocumentTitle();
// If aCheckIfPresent is true, will only set an attribute in cases
// when it's not already set.
nsresult AddAttributes(const nsIParserNode& aNode, nsIContent* aContent,
@ -245,7 +244,6 @@ protected:
nsRefPtr<nsGenericHTMLElement> mFrameset;
nsGenericHTMLElement* mHead;
nsString mTitleString;
nsRefPtr<nsGenericHTMLElement> mCurrentForm;
nsAutoVoidArray mContextStack;
@ -878,13 +876,6 @@ SinkContext::OpenContainer(const nsIParserNode& aNode)
}
break;
case eHTMLTag_title:
if (mSink->mDocument->GetDocumentTitle().IsVoid()) {
// The first title wins.
mSink->mInTitle = PR_TRUE;
}
break;
case eHTMLTag_button:
content->DoneCreatingElement();
break;
@ -1010,6 +1001,7 @@ SinkContext::CloseContainer(const nsHTMLTag aTag, PRBool aMalformed)
case eHTMLTag_textarea:
case eHTMLTag_object:
case eHTMLTag_applet:
case eHTMLTag_title:
content->DoneAddingChildren(HaveNotifiedForCurrentContent());
break;
@ -1022,13 +1014,6 @@ SinkContext::CloseContainer(const nsHTMLTag aTag, PRBool aMalformed)
result = mSink->ProcessSTYLEEndTag(content);
break;
case eHTMLTag_title:
if (mSink->mInTitle) {
mSink->UpdateDocumentTitle();
mSink->mInTitle = PR_FALSE;
}
break;
default:
break;
}
@ -1294,11 +1279,6 @@ SinkContext::AddText(const nsAString& aText)
return NS_OK;
}
if (mSink->mInTitle) {
// Hang onto the title text specially.
mSink->mTitleString.Append(aText);
}
// Create buffer when we first need it
if (mTextSize == 0) {
mText = new PRUnichar[4096];
@ -2429,33 +2409,6 @@ HTMLContentSink::AddLeaf(const nsIParserNode& aNode)
return rv;
}
nsresult
HTMLContentSink::UpdateDocumentTitle()
{
MOZ_TIMER_DEBUGLOG(("Start: nsHTMLContentSink::UpdateDocumentTitle()\n"));
MOZ_TIMER_START(mWatch);
NS_ASSERTION(mCurrentContext == mHeadContext, "title not in head");
if (!mDocument->GetDocumentTitle().IsVoid()) {
MOZ_TIMER_DEBUGLOG(("Stop: nsHTMLContentSink::UpdateDocumentTitle()\n"));
MOZ_TIMER_STOP(mWatch);
return NS_OK;
}
// Use mTitleString.
mTitleString.CompressWhitespace(PR_TRUE, PR_TRUE);
nsCOMPtr<nsIDOMNSDocument> domDoc(do_QueryInterface(mDocument));
domDoc->SetTitle(mTitleString);
mTitleString.Truncate();
MOZ_TIMER_DEBUGLOG(("Stop: nsHTMLContentSink::UpdateDocumentTitle()\n"));
MOZ_TIMER_STOP(mWatch);
return NS_OK;
}
/**
* This gets called by the parsing system when we find a comment
* @update gess11/9/98

Просмотреть файл

@ -1977,13 +1977,6 @@ nsHTMLDocument::OpenCommon(const nsACString& aContentType, PRBool aReplace)
EditingStateChanged();
}
// Zap the old title -- otherwise it would hang around until document.close()
// (which might never come) if the new document doesn't explicitly set one.
// Void the title to make sure that we actually respect any titles set by the
// new document.
SetTitle(EmptyString());
mDocumentTitle.SetIsVoid(PR_TRUE);
// Store the security info of the caller now that we're done
// resetting the document.
mSecurityInfo = securityInfo;
@ -2936,34 +2929,6 @@ nsHTMLDocument::GetBodyContentExternal()
return GetBodyContent();
}
nsIContent*
nsHTMLDocument::GetHtmlContent()
{
nsIContent* rootContent = GetRootContent();
if (rootContent && rootContent->Tag() == nsGkAtoms::html &&
rootContent->IsNodeOfType(nsINode::eHTML))
return rootContent;
return nsnull;
}
nsIContent*
nsHTMLDocument::GetBodyContent()
{
nsIContent* html = GetHtmlContent();
if (!html)
return nsnull;
// Look for body inside html. This needs to run forwards to find
// the first body element.
for (PRUint32 i = 0; i < html->GetChildCount(); ++i) {
nsIContent* body = html->GetChildAt(i);
if (body->Tag() == nsGkAtoms::body &&
body->IsNodeOfType(nsINode::eHTML))
return body;
}
return nsnull;
}
// forms related stuff
NS_IMETHODIMP

Просмотреть файл

@ -229,13 +229,6 @@ protected:
static void DocumentWriteTerminationFunc(nsISupports *aRef);
// Get the root <html> element, or return null if there isn't one (e.g.
// if the root isn't <html>)
nsIContent* GetHtmlContent();
// Get the canonical <body> element, or return null if there isn't one (e.g.
// if the root isn't <html> or if the <body> isn't there)
nsIContent* GetBodyContent();
void GetDomainURI(nsIURI **uri);
nsresult WriteCommon(const nsAString& aText,

Просмотреть файл

@ -247,6 +247,19 @@ nsMediaDocument::CreateSyntheticDocument()
rv = AppendChildTo(root, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
rv = mNodeInfoManager->GetNodeInfo(nsGkAtoms::head, nsnull,
kNameSpaceID_None,
getter_AddRefs(nodeInfo));
NS_ENSURE_SUCCESS(rv, rv);
// Create a <head> so our title has somewhere to live
nsRefPtr<nsGenericHTMLElement> head = NS_NewHTMLHeadElement(nodeInfo);
if (!head) {
return NS_ERROR_OUT_OF_MEMORY;
}
root->AppendChildTo(head, PR_FALSE);
rv = mNodeInfoManager->GetNodeInfo(nsGkAtoms::body, nsnull,
kNameSpaceID_None,
getter_AddRefs(nodeInfo));

Просмотреть файл

@ -42,7 +42,8 @@
typedef nsSVGStylableElement nsSVGTitleElementBase;
class nsSVGTitleElement : public nsSVGTitleElementBase,
public nsIDOMSVGTitleElement
public nsIDOMSVGTitleElement,
public nsStubMutationObserver
{
protected:
friend nsresult NS_NewSVGTitleElement(nsIContent **aResult,
@ -61,7 +62,25 @@ public:
NS_FORWARD_NSIDOMELEMENT(nsSVGTitleElementBase::)
NS_FORWARD_NSIDOMSVGELEMENT(nsSVGTitleElementBase::)
// nsIMutationObserver
NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
virtual nsresult BindToTree(nsIDocument *aDocument, nsIContent *aParent,
nsIContent *aBindingParent,
PRBool aCompileEventHandlers);
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
PRBool aNullParent = PR_TRUE);
virtual nsresult DoneAddingChildren(PRBool aHaveNotified);
private:
void SendTitleChangeEvent(PRBool aBound);
};
NS_IMPL_NS_NEW_SVG_ELEMENT(Title)
@ -78,6 +97,7 @@ NS_INTERFACE_MAP_BEGIN(nsSVGTitleElement)
NS_INTERFACE_MAP_ENTRY(nsIDOMElement)
NS_INTERFACE_MAP_ENTRY(nsIDOMSVGElement)
NS_INTERFACE_MAP_ENTRY(nsIDOMSVGTitleElement)
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGTitleElement)
NS_INTERFACE_MAP_END_INHERITING(nsSVGTitleElementBase)
@ -88,18 +108,94 @@ NS_INTERFACE_MAP_END_INHERITING(nsSVGTitleElementBase)
nsSVGTitleElement::nsSVGTitleElement(nsINodeInfo *aNodeInfo)
: nsSVGTitleElementBase(aNodeInfo)
{
AddMutationObserver(this);
}
nsresult
nsSVGTitleElement::Init()
{
return nsSVGTitleElementBase::Init();
}
void
nsSVGTitleElement::CharacterDataChanged(nsIDocument *aDocument,
nsIContent *aContent,
CharacterDataChangeInfo *aInfo)
{
SendTitleChangeEvent(PR_FALSE);
}
void
nsSVGTitleElement::ContentAppended(nsIDocument *aDocument,
nsIContent *aContainer,
PRInt32 aNewIndexInContainer)
{
SendTitleChangeEvent(PR_FALSE);
}
void
nsSVGTitleElement::ContentInserted(nsIDocument *aDocument,
nsIContent *aContainer,
nsIContent *aChild,
PRInt32 aIndexInContainer)
{
SendTitleChangeEvent(PR_FALSE);
}
void
nsSVGTitleElement::ContentRemoved(nsIDocument *aDocument,
nsIContent *aContainer,
nsIContent *aChild,
PRInt32 aIndexInContainer)
{
SendTitleChangeEvent(PR_FALSE);
}
nsresult
nsSVGTitleElement::BindToTree(nsIDocument *aDocument,
nsIContent *aParent,
nsIContent *aBindingParent,
PRBool aCompileEventHandlers)
{
// Let this fall through.
nsresult rv = nsSVGTitleElementBase::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
SendTitleChangeEvent(PR_TRUE);
return NS_OK;
}
void
nsSVGTitleElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
{
SendTitleChangeEvent(PR_FALSE);
// Let this fall through.
nsSVGTitleElementBase::UnbindFromTree(aDeep, aNullParent);
}
nsresult
nsSVGTitleElement::DoneAddingChildren(PRBool aHaveNotified)
{
if (!aHaveNotified) {
SendTitleChangeEvent(PR_FALSE);
}
return NS_OK;
}
void
nsSVGTitleElement::SendTitleChangeEvent(PRBool aBound)
{
nsIDocument* doc = GetCurrentDoc();
if (doc) {
doc->NotifyPossibleTitleChange(aBound);
}
}
//----------------------------------------------------------------------
// nsIDOMNode methods
NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGTitleElement)

Просмотреть файл

@ -543,24 +543,9 @@ nsXMLContentSink::CreateElement(const PRUnichar** aAtts, PRUint32 aAttsCount,
}
}
if (aNodeInfo->Equals(nsGkAtoms::title, kNameSpaceID_XHTML)) {
if (mDocument && mDocument->GetDocumentTitle().IsVoid()) {
mInTitle = PR_TRUE; // The first title wins
}
}
#ifdef MOZ_SVG
else if (aNodeInfo->Equals(nsGkAtoms::title, kNameSpaceID_SVG)) {
nsIContent* parent = GetCurrentContent();
if (mDocument && mDocument->GetDocumentTitle().IsVoid() &&
parent && parent == mDocElement &&
parent->NodeInfo()->Equals(nsGkAtoms::svg, kNameSpaceID_SVG)) {
mInTitle = PR_TRUE; // The first title wins
}
}
#endif // MOZ_SVG
else if (aNodeInfo->Equals(nsGkAtoms::link, kNameSpaceID_XHTML) ||
aNodeInfo->Equals(nsGkAtoms::style, kNameSpaceID_XHTML) ||
aNodeInfo->Equals(nsGkAtoms::style, kNameSpaceID_SVG)) {
if (aNodeInfo->Equals(nsGkAtoms::link, kNameSpaceID_XHTML) ||
aNodeInfo->Equals(nsGkAtoms::style, kNameSpaceID_XHTML) ||
aNodeInfo->Equals(nsGkAtoms::style, kNameSpaceID_SVG)) {
nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(content));
if (ssle) {
ssle->InitStyleLinkElement(PR_FALSE);
@ -598,6 +583,7 @@ nsXMLContentSink::CloseElement(nsIContent* aContent)
#ifdef MOZ_XTF
|| nodeInfo->NamespaceID() > kNameSpaceID_LastBuiltin
#endif
|| nodeInfo->NameAtom() == nsGkAtoms::title
) {
aContent->DoneAddingChildren(HaveNotifiedForCurrentContent());
}
@ -643,19 +629,7 @@ nsXMLContentSink::CloseElement(nsIContent* aContent)
return rv;
}
if ((nodeInfo->Equals(nsGkAtoms::title, kNameSpaceID_XHTML)
#ifdef MOZ_SVG
|| nodeInfo->Equals(nsGkAtoms::title, kNameSpaceID_SVG)
#endif // MOZ_SVG
) && mInTitle) {
NS_ASSERTION(mDocument, "How did mInTitle get to be true if mDocument is null?");
// The first title wins
nsCOMPtr<nsIDOMNSDocument> dom_doc(do_QueryInterface(mDocument));
mTitleText.CompressWhitespace();
dom_doc->SetTitle(mTitleText);
mInTitle = PR_FALSE;
}
else if (nodeInfo->Equals(nsGkAtoms::base, kNameSpaceID_XHTML) &&
if (nodeInfo->Equals(nsGkAtoms::base, kNameSpaceID_XHTML) &&
!mHasProcessedBase) {
// The first base wins
rv = ProcessBASETag(aContent);
@ -1214,10 +1188,6 @@ nsXMLContentSink::HandleCDataSection(const PRUnichar *aData,
FlushText();
if (mInTitle) {
mTitleText.Append(aData, aLength);
}
nsCOMPtr<nsIContent> cdata;
nsresult rv = NS_NewXMLCDATASection(getter_AddRefs(cdata), mNodeInfoManager);
if (cdata) {
@ -1557,11 +1527,6 @@ nsresult
nsXMLContentSink::AddText(const PRUnichar* aText,
PRInt32 aLength)
{
if (mInTitle) {
mTitleText.Append(aText,aLength);
}
// Create buffer when we first need it
if (0 == mTextSize) {
mText = (PRUnichar *) PR_MALLOC(sizeof(PRUnichar) * NS_ACCUMULATION_BUFFER_SIZE);

Просмотреть файл

@ -194,8 +194,6 @@ protected:
XMLContentSinkState mState;
nsString mTitleText;
PRInt32 mTextLength;
PRInt32 mTextSize;

Просмотреть файл

@ -176,11 +176,6 @@ txMozillaTextOutput::createResultDocument(nsIDOMDocument* aSourceDocument,
NS_ASSERTION(mDocument, "Need document");
nsCOMPtr<nsIDOMNSDocument> nsDoc = do_QueryInterface(mDocument);
if (nsDoc) {
nsDoc->SetTitle(EmptyString());
}
// Reset and set up document
URIUtils::ResetWithSource(mDocument, aSourceDocument);

Просмотреть файл

@ -86,7 +86,6 @@ txMozillaXMLOutput::txMozillaXMLOutput(const nsSubstring& aRootName,
: mTreeDepth(0),
mBadChildLevel(0),
mTableState(NORMAL),
mHaveTitleElement(PR_FALSE),
mHaveBaseElement(PR_FALSE),
mCreatingNewDocument(PR_TRUE),
mOpenedElementIsHTML(PR_FALSE),
@ -112,7 +111,6 @@ txMozillaXMLOutput::txMozillaXMLOutput(txOutputFormat* aFormat,
: mTreeDepth(0),
mBadChildLevel(0),
mTableState(NORMAL),
mHaveTitleElement(PR_FALSE),
mHaveBaseElement(PR_FALSE),
mCreatingNewDocument(PR_FALSE),
mOpenedElementIsHTML(PR_FALSE),
@ -261,14 +259,6 @@ txMozillaXMLOutput::endDocument(nsresult aResult)
return rv;
}
// This should really be handled by nsIDocument::Reset
if (mCreatingNewDocument && !mHaveTitleElement) {
nsCOMPtr<nsIDOMNSDocument> domDoc = do_QueryInterface(mDocument);
if (domDoc) {
domDoc->SetTitle(EmptyString());
}
}
if (!mRefreshString.IsEmpty()) {
nsCOMPtr<nsIDocument> doc = do_QueryInterface(mDocument);
nsPIDOMWindow *win = doc->GetWindow();
@ -779,22 +769,6 @@ txMozillaXMLOutput::endHTMLElement(nsIContent* aElement)
return NS_OK;
}
// Set document title
else if (mCreatingNewDocument &&
atom == txHTMLAtoms::title && !mHaveTitleElement) {
// The first title wins
mHaveTitleElement = PR_TRUE;
nsCOMPtr<nsIDOMNSDocument> domDoc = do_QueryInterface(mDocument);
nsAutoString title;
nsContentUtils::GetNodeTextContent(aElement, PR_TRUE, title);
if (domDoc) {
title.CompressWhitespace();
domDoc->SetTitle(title);
}
}
else if (mCreatingNewDocument && atom == txHTMLAtoms::base &&
!mHaveBaseElement) {
// The first base wins

Просмотреть файл

@ -153,7 +153,6 @@ private:
txOutputFormat mOutputFormat;
PRPackedBool mHaveTitleElement;
PRPackedBool mHaveBaseElement;
PRPackedBool mCreatingNewDocument;

Просмотреть файл

@ -1154,9 +1154,14 @@ nsXULElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
aValue) {
HideWindowChrome(aValue && NS_LITERAL_STRING("true").Equals(*aValue));
}
nsIDocument *document = GetCurrentDoc();
if (aName == nsGkAtoms::title &&
document && document->GetRootContent() == this) {
document->NotifyPossibleTitleChange(PR_FALSE);
}
// (in)activetitlebarcolor is settable on any root node (windows, dialogs, etc)
nsIDocument *document = GetCurrentDoc();
if ((aName == nsGkAtoms::activetitlebarcolor ||
aName == nsGkAtoms::inactivetitlebarcolor) &&
document && document->GetRootContent() == this) {

Просмотреть файл

@ -441,8 +441,6 @@ nsXULDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
mMayStartLayout = PR_FALSE;
mDocumentLoadGroup = do_GetWeakReference(aLoadGroup);
mDocumentTitle.SetIsVoid(PR_TRUE);
mChannel = aChannel;
mHaveInputEncoding = PR_TRUE;
@ -3116,12 +3114,7 @@ nsXULDocument::DoneWalking()
// happen.
mDocumentLoaded = PR_TRUE;
nsAutoString title;
nsIContent* root = GetRootContent();
if (root) {
root->GetAttr(kNameSpaceID_None, nsGkAtoms::title, title);
}
SetTitle(title);
NotifyPossibleTitleChange(PR_FALSE);
// Before starting layout, check whether we're a toplevel chrome
// window. If we are, set our chrome flags now, so that we don't have

Просмотреть файл

@ -5897,13 +5897,9 @@ nsDocShell::RestoreFromHistory()
rv = privWin->RestoreWindowState(windowState);
NS_ENSURE_SUCCESS(rv, rv);
// Now, dispatch a title change event which would happed as the
// Now, dispatch a title change event which would happen as the
// <head> is parsed.
nsCOMPtr<nsIDOMNSDocument> nsDoc = do_QueryInterface(document);
if (nsDoc) {
const nsAFlatString &title = document->GetDocumentTitle();
nsDoc->SetTitle(title);
}
document->NotifyPossibleTitleChange(PR_FALSE);
// Now we simulate appending child docshells for subframes.
for (i = 0; i < childShells.Count(); ++i) {

Просмотреть файл

@ -66,36 +66,19 @@ NS_IMETHODIMP SetDocTitleTxn::Init(nsIHTMLEditor *aEditor,
NS_IMETHODIMP SetDocTitleTxn::DoTransaction(void)
{
nsresult res = SetDomTitle(mValue);
if (NS_FAILED(res)) return res;
return SetDocTitle(mValue);
return SetDomTitle(mValue);
}
NS_IMETHODIMP SetDocTitleTxn::UndoTransaction(void)
{
return SetDocTitle(mUndoValue);
// No extra work required; the DOM changes alone are enough
return NS_OK;
}
NS_IMETHODIMP SetDocTitleTxn::RedoTransaction(void)
{
return SetDocTitle(mValue);
}
nsresult SetDocTitleTxn::SetDocTitle(const nsAString& aTitle)
{
NS_ASSERTION(mEditor, "bad state");
if (!mEditor) return NS_ERROR_NOT_INITIALIZED;
nsCOMPtr<nsIEditor> editor = do_QueryInterface(mEditor);
if (!editor) return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMDocument> domDoc;
nsresult rv = editor->GetDocument(getter_AddRefs(domDoc));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIDOMHTMLDocument> HTMLDoc = do_QueryInterface(domDoc);
if (!HTMLDoc) return NS_ERROR_FAILURE;
return HTMLDoc->SetTitle(aTitle);
// No extra work required; the DOM changes alone are enough
return NS_OK;
}
nsresult SetDocTitleTxn::SetDomTitle(const nsAString& aTitle)

Просмотреть файл

@ -68,7 +68,6 @@ public:
const nsAString *aValue);
private:
SetDocTitleTxn();
nsresult SetDocTitle(const nsAString& aTitle);
nsresult SetDomTitle(const nsAString& aTitle);
public:

Просмотреть файл

@ -128,9 +128,9 @@ EmbedContextMenuInfo::SetFrameIndex()
if (currentDoc == mCtxDocument) {
mCtxFrameNum = i;
mCtxDomWindow = currentWindow;
nsCOMPtr<nsIDocument> doc = do_QueryInterface(currentDoc);
nsCOMPtr<nsIDOMNSDocument> doc = do_QueryInterface(currentDoc);
if (doc)
mCtxDocTitle = doc->GetDocumentTitle();
doc->GetTitle(mCtxDocTitle);
return NS_OK;
}
}

Просмотреть файл

@ -112,6 +112,7 @@ static const char kPrintingPromptService[] = "@mozilla.org/embedcomp/printingpro
#include "nsISelectionListener.h"
#include "nsISelectionPrivate.h"
#include "nsIDOMHTMLDocument.h"
#include "nsIDOMNSDocument.h"
#include "nsIDOMNSHTMLDocument.h"
#include "nsIDOMHTMLCollection.h"
#include "nsIDOMHTMLElement.h"
@ -1153,7 +1154,9 @@ nsPrintEngine::GetDocumentTitleAndURL(nsIDocument* aDoc,
*aTitle = nsnull;
*aURLStr = nsnull;
const nsAString &docTitle = aDoc->GetDocumentTitle();
nsAutoString docTitle;
nsCOMPtr<nsIDOMNSDocument> doc = do_QueryInterface(aDoc);
doc->GetTitle(docTitle);
if (!docTitle.IsEmpty()) {
*aTitle = ToNewUnicode(docTitle);
}

Просмотреть файл

@ -245,7 +245,8 @@ protected:
#define IMETHOD_VISIBILITY NS_VISIBILITY_HIDDEN
// An event that can be used to call a method on a class. The class type must
// support reference counting.
// support reference counting. This event supports Revoke for use
// with nsRevocableEventPtr.
template <class T>
class nsRunnableMethod : public nsRunnable
{
@ -258,13 +259,19 @@ public:
}
NS_IMETHOD Run() {
if (!mObj)
return NS_OK;
(mObj->*mMethod)();
return NS_OK;
}
void Revoke() {
NS_IF_RELEASE(mObj);
}
private:
virtual ~nsRunnableMethod() {
NS_RELEASE(mObj);
NS_IF_RELEASE(mObj);
}
T *mObj;
@ -364,6 +371,8 @@ public:
PRBool IsPending() {
return mEvent != nsnull;
}
T *get() { return mEvent; }
private:
// Not implemented