зеркало из https://github.com/mozilla/gecko-dev.git
Bug 118704. Get the document title from the DOM instead of storing it as a string in the document. r+sr=jst
This commit is contained in:
Родитель
78a2558a52
Коммит
34de2392a2
|
@ -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,167 @@ 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;
|
||||
|
||||
switch (rootContent->GetNameSpaceID()) {
|
||||
#ifdef MOZ_SVG
|
||||
case kNameSpaceID_SVG:
|
||||
if (rootContent->Tag() == nsGkAtoms::svg) {
|
||||
GetTitleFromElement(nsINode::eSVG, aTitle);
|
||||
return NS_OK;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef MOZ_XUL
|
||||
case kNameSpaceID_XUL:
|
||||
rootContent->GetAttr(kNameSpaceID_None, nsGkAtoms::title, aTitle);
|
||||
return NS_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
GetTitleFromElement(nsINode::eHTML, aTitle);
|
||||
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;
|
||||
|
||||
mPendingTitleChangeEvent = new nsRunnableMethod<nsDocument>(this,
|
||||
&nsDocument::DoNotifyPossibleTitleChange);
|
||||
NS_DispatchToCurrentThread(mPendingTitleChangeEvent.get());
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::DoNotifyPossibleTitleChange()
|
||||
{
|
||||
mPendingTitleChangeEvent.Forget();
|
||||
|
||||
nsAutoString title;
|
||||
GetTitle(title);
|
||||
|
||||
nsPresShellIterator iter(this);
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
while ((shell = iter.GetNextShell())) {
|
||||
|
@ -4322,18 +4468,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)
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Test for titles</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<style type="text/css">
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body onload="runTests()">
|
||||
|
||||
<p id="display"></p>
|
||||
<div style="display:none;">
|
||||
<iframe id="html1" src="data:text/html,<html><head><title id='t'>Test</title></head></html>"></iframe>
|
||||
<iframe id="html2" src="data:text/html,<html><head><title id='t'>Test</title><title>Foo</title></head></html>"></iframe>
|
||||
<iframe id="html3" src="data:text/html,<html></html>"></iframe>
|
||||
<iframe id="xhtml1" src="data:text/xml,<html xmlns='http://www.w3.org/1999/xhtml'><body><title id='t'>Test</title></body></html>"></iframe>
|
||||
<iframe id="xhtml2" src="data:text/xml,<title xmlns='http://www.w3.org/1999/xhtml'>Test</title>"></iframe>
|
||||
<iframe id="xhtml3" src="data:text/xml,<title xmlns='http://www.w3.org/1999/xhtml'>Te<div>bogus</div>st</title>"></iframe>
|
||||
<iframe id="xhtml4" src="data:text/xml,<html xmlns='http://www.w3.org/1999/xhtml'/>"></iframe>
|
||||
<iframe id="xhtml5" src="data:text/xml,<html xmlns='http://www.w3.org/1999/xhtml'><head/></html>"></iframe>
|
||||
<iframe id="xhtml6" src="data:text/xml,<html xmlns='http://www.w3.org/1999/xhtml'><head><style/></head></html>"></iframe>
|
||||
<iframe id="xul1" src="data:application/vnd.mozilla.xul+xml,<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul' title='Test'/>"></iframe>
|
||||
<iframe id="xul2" src="data:application/vnd.mozilla.xul+xml,<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul' title='Test'/>"></iframe>
|
||||
<iframe id="svg1" src="data:text/xml,<svg xmlns='http://www.w3.org/2000/svg'><title id='t'>Test</title></svg>"></iframe>
|
||||
<iframe id="svg2" src="data:text/xml,<svg xmlns='http://www.w3.org/2000/svg'><title id='t'>Test</title></svg>"></iframe>
|
||||
</div>
|
||||
|
||||
<pre id="test">
|
||||
<script>
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function testStatics() {
|
||||
function testStatic(id, expect, description) {
|
||||
is(document.getElementById(id).contentDocument.title, expect, description);
|
||||
}
|
||||
|
||||
testStatic("html1", "Test", "HTML <title>");
|
||||
testStatic("html2", "Test", "choose the first HTML <title>");
|
||||
testStatic("html3", "", "No title");
|
||||
testStatic("xhtml1", "Test", "XHTML <title> in body");
|
||||
testStatic("xhtml2", "Test", "XHTML <title> as root element");
|
||||
testStatic("xhtml3", "Test", "XHTML <title> containing an element");
|
||||
testStatic("xul1", "Test", "XUL <window> title attribute");
|
||||
testStatic("svg1", "Test", "SVG <title>");
|
||||
}
|
||||
|
||||
function testDynamics() {
|
||||
var inProgress = {};
|
||||
function testDynamic(id, expect, description, op, checkDOM) {
|
||||
inProgress[description] = true;
|
||||
var frame = document.getElementById(id);
|
||||
var done = false;
|
||||
|
||||
function listener() {
|
||||
inProgress[description] = false;
|
||||
is(frame.contentDocument.title, expect, "'title': " + description);
|
||||
if (typeof(checkDOM) != undefined) {
|
||||
checkDOM(frame.contentDocument, "DOM: " + description);
|
||||
}
|
||||
}
|
||||
frame.contentDocument.addEventListener("DOMTitleChanged", listener, false);
|
||||
|
||||
op(frame.contentDocument);
|
||||
}
|
||||
|
||||
testDynamic("html1", "Hello", "Setting HTML <title> text contents", function(doc){
|
||||
var t = doc.getElementById("t"); t.textContent = "Hello";
|
||||
});
|
||||
testDynamic("html2", "Foo", "Removing HTML <title>", function(doc){
|
||||
var t = doc.getElementById("t"); t.parentNode.removeChild(t);
|
||||
});
|
||||
testDynamic("html3", "Hello", "Appending HTML <title> element to root element", function(doc){
|
||||
var t = doc.createElement("title"); t.textContent = "Hello"; doc.documentElement.appendChild(t);
|
||||
});
|
||||
testDynamic("xhtml3", "Hello", "Setting 'title' clears existing <title> contents", function(doc){
|
||||
doc.title = "Hello";
|
||||
}, function(doc, desc) {
|
||||
is(doc.documentElement.firstChild.data, "Hello", desc);
|
||||
is(doc.documentElement.firstChild.nextSibling, null, desc);
|
||||
});
|
||||
// This one does nothing and won't fire an event
|
||||
document.getElementById("xhtml4").contentDocument.title = "Hello";
|
||||
is(document.getElementById("xhtml4").contentDocument.title, "", "Setting 'title' does nothing with no <head>");
|
||||
testDynamic("xhtml5", "Hello", "Setting 'title' works with a <head>", function(doc){
|
||||
doc.title = "Hello";
|
||||
}, function(doc, desc) {
|
||||
var head = doc.documentElement.firstChild;
|
||||
var title = head.firstChild;
|
||||
is(title.tagName.toLowerCase(), "title", desc);
|
||||
is(title.firstChild.data, "Hello", desc);
|
||||
is(title.firstChild.nextSibling, null, desc);
|
||||
is(title.nextSibling, null, desc);
|
||||
});
|
||||
testDynamic("xhtml6", "Hello", "Setting 'title' appends to <head>", function(doc){
|
||||
doc.title = "Hello";
|
||||
}, function(doc, desc) {
|
||||
var head = doc.documentElement.firstChild;
|
||||
is(head.firstChild.tagName.toLowerCase(), "style", desc);
|
||||
var title = head.firstChild.nextSibling;
|
||||
is(title.tagName.toLowerCase(), "title", desc);
|
||||
is(title.firstChild.data, "Hello", desc);
|
||||
is(title.firstChild.nextSibling, null, desc);
|
||||
is(title.nextSibling, null, desc);
|
||||
});
|
||||
|
||||
testDynamic("xul1", "Hello", "Setting XUL <window> title attribute", function(doc){
|
||||
doc.documentElement.setAttribute("title", "Hello");
|
||||
});
|
||||
testDynamic("xul2", "Hello", "Setting 'title' in XUL", function(doc){
|
||||
doc.title = "Hello";
|
||||
}, function(doc, desc) {
|
||||
is(doc.documentElement.getAttribute("title"), "Hello", desc);
|
||||
is(doc.documentElement.firstChild, null, desc);
|
||||
});
|
||||
|
||||
testDynamic("svg1", "Hello", "Setting SVG <title> text contents", function(doc){
|
||||
var t = doc.getElementById("t"); t.textContent = "Hello";
|
||||
});
|
||||
testDynamic("svg2", "", "Removing SVG <title>", function(doc){
|
||||
var t = doc.getElementById("t"); t.parentNode.removeChild(t);
|
||||
});
|
||||
|
||||
function end() {
|
||||
for (description in inProgress) {
|
||||
ok(!inProgress[description], description + ": DOMTitleChange not fired");
|
||||
}
|
||||
SimpleTest.finish();
|
||||
}
|
||||
setTimeout(end, 500);
|
||||
}
|
||||
|
||||
function acid() {
|
||||
var doctype = document.implementation.createDocumentType("html", "-//W3C//DTD XHTML 1.0 Strict//EN", "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd");
|
||||
is(doctype.ownerDocument, null, "doctype's ownerDocument was wrong after creation");
|
||||
var doc = document.implementation.createDocument("http://www.w3.org/1999/xhtml", "html", doctype);
|
||||
doc.documentElement.appendChild(doc.createElementNS("http://www.w3.org/1999/xhtml", "head"));
|
||||
doc.documentElement.appendChild(doc.createElementNS("http://www.w3.org/1999/xhtml", "body"));
|
||||
var t = doc.createElementNS("http://www.w3.org/1999/xhtml", "title");
|
||||
doc.documentElement.firstChild.appendChild(t);
|
||||
// ok we have a conforming XHTML1 doc in |doc| now.
|
||||
is(doctype.ownerDocument, doc, "doctype's ownerDocument didn't change when it was assigned to another document");
|
||||
is(doc.title, "", "document had unexpected title");
|
||||
t.textContent = "Sparrow";
|
||||
is(doc.title, "Sparrow", "document.title did not update dynamically");
|
||||
doc.body.appendChild(doc.createElementNS("http://www.w3.org/1999/xhtml", "form"));
|
||||
is(doc.forms.length, 1, "document.forms not updated after inserting a form");
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
testStatics();
|
||||
// acid();
|
||||
testDynamics();
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче