Make CreateContextualFragment know what document the fragment is destined for.

Fixes some issues with images and innerHTML.  Bugs 198486, 198989, 201865.
r=jfrancis, sr=jst
This commit is contained in:
bzbarsky%mit.edu 2003-04-15 01:09:09 +00:00
Родитель 0831c7e659
Коммит 5df3b30a3b
8 изменённых файлов: 124 добавлений и 70 удалений

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

@ -365,14 +365,12 @@ nsImageLoadingContent::ImageURIChanged(const nsACString& aNewURI)
nsresult rv; // XXXbz Should failures in this method fire onerror?
// First, get a document (needed for security checks, base URI and the like)
// Even if we do not have a document, we want to keep going here. The
// reason is that nodes created by the HTMLFragmentContentSink have no
// document (not even in the nodeinfo) and are used when cutting and
// pasting, as well as for drag&drop. So if we are to have composer sorta
// working.... Once bug 198486 is fixed, we can go back to just bailing on
// a null document.
nsCOMPtr<nsIDocument> doc;
rv = GetOurDocument(getter_AddRefs(doc));
if (!doc) {
// No reason to bother, I think...
return rv;
}
nsCOMPtr<nsIURI> imageURI;
rv = StringToURI(aNewURI, doc, getter_AddRefs(imageURI));
@ -390,11 +388,7 @@ nsImageLoadingContent::ImageURIChanged(const nsACString& aNewURI)
// not to show the broken image icon. If the load is blocked by the
// content policy or security manager, we will want to cancel with
// the error code from those.
nsresult cancelResult = NS_OK;
if (doc) {
// Can't do security or content policy checks without a document
cancelResult = CanLoadImage(imageURI, doc);
}
nsresult cancelResult = CanLoadImage(imageURI, doc);
if (NS_SUCCEEDED(cancelResult)) {
cancelResult = NS_ERROR_IMAGE_SRC_CHANGED;
}
@ -409,15 +403,11 @@ nsImageLoadingContent::ImageURIChanged(const nsACString& aNewURI)
}
nsCOMPtr<nsILoadGroup> loadGroup;
if (doc) {
doc->GetDocumentLoadGroup(getter_AddRefs(loadGroup));
NS_WARN_IF_FALSE(loadGroup, "Could not get loadgroup; onload may fire too early");
}
doc->GetDocumentLoadGroup(getter_AddRefs(loadGroup));
NS_WARN_IF_FALSE(loadGroup, "Could not get loadgroup; onload may fire too early");
nsCOMPtr<nsIURI> documentURI;
if (doc) {
doc->GetDocumentURL(getter_AddRefs(documentURI));
}
doc->GetDocumentURL(getter_AddRefs(documentURI));
nsCOMPtr<imgIRequest> & req = mCurrentRequest ? mPendingRequest : mCurrentRequest;
@ -513,18 +503,17 @@ nsImageLoadingContent::StringToURI(const nsACString& aSpec,
nsIDocument* aDocument,
nsIURI** aURI)
{
// XXXbz Commented out precondition pending fix for bug 198486
// NS_PRECONDITION(aDocument, "Must have a document");
NS_PRECONDITION(aDocument, "Must have a document");
NS_PRECONDITION(aURI, "Null out param");
nsresult rv = NS_OK;
nsresult rv;
// (1) Get the base URI
nsCOMPtr<nsIURI> baseURL;
nsCOMPtr<nsIHTMLContent> thisContent = do_QueryInterface(this);
if (thisContent) {
rv = thisContent->GetBaseURL(*getter_AddRefs(baseURL));
} else if (aDocument) {
} else {
rv = aDocument->GetBaseURL(*getter_AddRefs(baseURL));
if (!baseURL) {
rv = aDocument->GetDocumentURL(getter_AddRefs(baseURL));
@ -534,9 +523,7 @@ nsImageLoadingContent::StringToURI(const nsACString& aSpec,
// (2) Get the charset
nsAutoString charset;
if (aDocument) {
aDocument->GetDocumentCharacterSet(charset);
}
aDocument->GetDocumentCharacterSet(charset);
// (3) Construct the silly thing
return NS_NewURI(aURI,
@ -549,13 +536,22 @@ nsImageLoadingContent::StringToURI(const nsACString& aSpec,
/**
* Struct used to dispatch events
*/
MOZ_DECL_CTOR_COUNTER(ImageEvent)
struct ImageEvent : PLEvent {
ImageEvent(nsIPresContext* aPresContext, nsIContent* aContent,
const nsAString& aMessage)
: mPresContext(aPresContext),
mContent(aContent),
mMessage(aMessage)
{}
{
MOZ_COUNT_CTOR(ImageEvent);
}
~ImageEvent()
{
MOZ_COUNT_DTOR(ImageEvent);
}
nsCOMPtr<nsIPresContext> mPresContext;
nsCOMPtr<nsIContent> mContent;
nsString mMessage;
@ -610,11 +606,6 @@ nsImageLoadingContent::FireEvent(const nsAString& aEventType)
nsCOMPtr<nsIDocument> document;
rv = GetOurDocument(getter_AddRefs(document));
if (!document) {
// no use to fire events if there is no document....
return rv;
}
nsCOMPtr<nsIPresShell> shell;
document->GetShellAt(0, getter_AddRefs(shell));
NS_ENSURE_TRUE(shell, NS_ERROR_FAILURE);

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

@ -85,11 +85,19 @@ private:
* Struct used to manage the image observers.
*/
struct ImageObserver {
MOZ_DECL_CTOR_COUNTER(ImageObserver)
ImageObserver(imgIDecoderObserver* aObserver) :
mObserver(aObserver),
mNext(nsnull)
{}
~ImageObserver() { delete mNext; }
{
MOZ_COUNT_CTOR(ImageObserver);
}
~ImageObserver()
{
MOZ_COUNT_DTOR(ImageObserver);
delete mNext;
}
nsCOMPtr<imgIDecoderObserver> mObserver;
ImageObserver* mNext;

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

@ -971,7 +971,7 @@ nsresult nsRange::GetStartContainer(nsIDOMNode** aStartParent)
return NS_ERROR_NOT_INITIALIZED;
if (!aStartParent)
return NS_ERROR_NULL_POINTER;
//NS_IF_RELEASE(*aStartParent); don't think we should be doing this
*aStartParent = mStartParent;
NS_IF_ADDREF(*aStartParent);
return NS_OK;
@ -2532,15 +2532,12 @@ nsRange::CreateContextualFragment(const nsAString& aFragment,
nsCOMPtr<nsIParser> parser = do_CreateInstance(kCParserCID, &result);
NS_ENSURE_SUCCESS(result, result);
nsCOMPtr<nsIContent> content = do_QueryInterface(mStartParent, &result);
NS_ENSURE_SUCCESS(result, result);
nsCOMPtr<nsIDocument> document;
nsCOMPtr<nsIDOMDocument> domDocument;
result = content->GetDocument(*getter_AddRefs(document));
if (document && NS_SUCCEEDED(result)) {
domDocument = do_QueryInterface(document, &result);
result = mStartParent->GetOwnerDocument(getter_AddRefs(domDocument));
if (domDocument && NS_SUCCEEDED(result)) {
document = do_QueryInterface(domDocument, &result);
}
nsVoidArray tagStack;
@ -2577,6 +2574,7 @@ nsRange::CreateContextualFragment(const nsAString& aFragment,
result = NS_NewHTMLFragmentContentSink(getter_AddRefs(sink));
if (NS_SUCCEEDED(result)) {
sink->SetTargetDocument(document);
parser->SetContentSink(sink);
nsCOMPtr<nsIDOMNSDocument> domnsDocument(do_QueryInterface(document));
if (domnsDocument) {
@ -2631,9 +2629,7 @@ nsRange::CreateContextualFragment(const nsAString& aFragment,
}
nsDTDMode mode = eDTDMode_autodetect;
nsCOMPtr<nsIDOMDocument> ownerDoc;
mStartParent->GetOwnerDocument(getter_AddRefs(ownerDoc));
nsCOMPtr<nsIHTMLDocument> htmlDoc(do_QueryInterface(ownerDoc));
nsCOMPtr<nsIHTMLDocument> htmlDoc(do_QueryInterface(domDocument));
if (htmlDoc) {
nsCompatibility compatMode;
htmlDoc->GetCompatibilityMode(compatMode);

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

@ -117,6 +117,7 @@ public:
// nsIHTMLFragmentContentSink
NS_IMETHOD GetFragment(nsIDOMDocumentFragment** aFragment);
NS_IMETHOD SetTargetDocument(nsIDocument* aDocument);
nsIContent* GetCurrentContent();
PRInt32 PushContent(nsIContent *aContent);
@ -167,31 +168,27 @@ public:
nsresult
NS_NewHTMLFragmentContentSink2(nsIHTMLFragmentContentSink** aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
NS_PRECONDITION(aResult, "Null out ptr");
nsCOMPtr<nsHTMLFragmentContentSink2> it;
NS_NEWXPCOM(it, nsHTMLFragmentContentSink2);
NS_ENSURE_TRUE(it, NS_ERROR_OUT_OF_MEMORY);
*aResult = new nsHTMLFragmentContentSink2();
NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
nsresult rv = it->Init();
NS_ENSURE_SUCCESS(rv, rv);
NS_ADDREF(*aResult);
return CallQueryInterface(it, aResult);
return NS_OK;
}
nsresult
NS_NewHTMLFragmentContentSink(nsIHTMLFragmentContentSink** aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
NS_PRECONDITION(aResult, "Null out ptr");
nsCOMPtr<nsHTMLFragmentContentSink> it;
NS_NEWXPCOM(it, nsHTMLFragmentContentSink);
NS_ENSURE_TRUE(it, NS_ERROR_OUT_OF_MEMORY);
*aResult = new nsHTMLFragmentContentSink();
NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
nsresult rv = it->Init();
NS_ENSURE_SUCCESS(rv, rv);
NS_ADDREF(*aResult);
return CallQueryInterface(it, aResult);
return NS_OK;
}
nsHTMLFragmentContentSink::nsHTMLFragmentContentSink()
@ -271,15 +268,6 @@ nsHTMLFragmentContentSink::QueryInterface(REFNSIID aIID, void** aInstancePtr)
}
nsresult nsHTMLFragmentContentSink::Init()
{
nsresult rv = NS_NewNodeInfoManager(getter_AddRefs(mNodeInfoManager));
NS_ENSURE_SUCCESS(rv, rv);
return mNodeInfoManager->Init(nsnull);
}
NS_IMETHODIMP
nsHTMLFragmentContentSink::WillBuildModel(void)
{
@ -343,6 +331,8 @@ nsHTMLFragmentContentSink::EndContext(PRInt32 aID)
NS_IMETHODIMP
nsHTMLFragmentContentSink::SetTitle(const nsString& aValue)
{
NS_ENSURE_TRUE(mNodeInfoManager, NS_ERROR_NOT_INITIALIZED);
nsresult result=NS_OK;
nsCOMPtr<nsINodeInfo> nodeInfo;
@ -481,6 +471,8 @@ static const char kSentinelStr[] = "endnote";
NS_IMETHODIMP
nsHTMLFragmentContentSink::OpenContainer(const nsIParserNode& aNode)
{
NS_ENSURE_TRUE(mNodeInfoManager, NS_ERROR_NOT_INITIALIZED);
nsAutoString tag;
nsresult result = NS_OK;
@ -571,6 +563,8 @@ nsHTMLFragmentContentSink::AddHeadContent(const nsIParserNode& aNode)
NS_IMETHODIMP
nsHTMLFragmentContentSink::AddLeaf(const nsIParserNode& aNode)
{
NS_ENSURE_TRUE(mNodeInfoManager, NS_ERROR_NOT_INITIALIZED);
nsresult result = NS_OK;
switch (aNode.GetTokenType()) {
@ -730,6 +724,28 @@ nsHTMLFragmentContentSink::GetFragment(nsIDOMDocumentFragment** aFragment)
return NS_OK;
}
NS_IMETHODIMP
nsHTMLFragmentContentSink::SetTargetDocument(nsIDocument* aTargetDocument)
{
if (aTargetDocument) {
aTargetDocument->GetNodeInfoManager(*getter_AddRefs(mNodeInfoManager));
}
if (mNodeInfoManager) {
return NS_OK;
}
nsresult rv = NS_NewNodeInfoManager(getter_AddRefs(mNodeInfoManager));
NS_ENSURE_SUCCESS(rv, rv);
rv = mNodeInfoManager->Init(nsnull);
if (NS_FAILED(rv)) {
mNodeInfoManager = nsnull;
}
return rv;
}
nsIContent*
nsHTMLFragmentContentSink::GetCurrentContent()
{

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

@ -2133,6 +2133,16 @@ nsresult nsHTMLEditor::CreateDOMFragmentFromPaste(nsIDOMNSRange *aNSRange,
nsCOMPtr<nsIDOMDocumentFragment> docfrag;
nsCOMPtr<nsIDOMNode> contextAsNode, tmp;
nsresult res = NS_OK;
nsCOMPtr<nsIDOMElement> rootElement;
GetRootElement(getter_AddRefs(rootElement));
nsCOMPtr<nsIDocument> doc;
if (rootElement) {
nsCOMPtr<nsIDOMDocument> domDoc;
rootElement->GetOwnerDocument(getter_AddRefs(domDoc));
doc = do_QueryInterface(domDoc);
}
// if we have context info, create a fragment for that
nsVoidArray tagStack;
@ -2141,7 +2151,7 @@ nsresult nsHTMLEditor::CreateDOMFragmentFromPaste(nsIDOMNSRange *aNSRange,
PRInt32 contextDepth = 0;
if (aContextStr.Length())
{
res = ParseFragment(aContextStr, tagStack, address_of(contextAsNode));
res = ParseFragment(aContextStr, tagStack, doc, address_of(contextAsNode));
NS_ENSURE_SUCCESS(res, res);
NS_ENSURE_TRUE(contextAsNode, NS_ERROR_FAILURE);
@ -2168,7 +2178,7 @@ nsresult nsHTMLEditor::CreateDOMFragmentFromPaste(nsIDOMNSRange *aNSRange,
return res;
}
// create fragment for pasted html
res = ParseFragment(aInputString, tagStack, outFragNode);
res = ParseFragment(aInputString, tagStack, doc, outFragNode);
FreeTagStackStrings(tagStack);
NS_ENSURE_SUCCESS(res, res);
NS_ENSURE_TRUE(*outFragNode, NS_ERROR_FAILURE);
@ -2207,7 +2217,10 @@ nsresult nsHTMLEditor::CreateDOMFragmentFromPaste(nsIDOMNSRange *aNSRange,
}
nsresult nsHTMLEditor::ParseFragment(const nsAString & aFragStr, nsVoidArray &aTagStack, nsCOMPtr<nsIDOMNode> *outNode)
nsresult nsHTMLEditor::ParseFragment(const nsAString & aFragStr,
nsVoidArray &aTagStack,
nsIDocument* aTargetDocument,
nsCOMPtr<nsIDOMNode> *outNode)
{
// figure out if we are parsing full context or not
PRBool bContext = (aTagStack.Count()==0);
@ -2230,6 +2243,8 @@ nsresult nsHTMLEditor::ParseFragment(const nsAString & aFragStr, nsVoidArray &aT
nsCOMPtr<nsIHTMLFragmentContentSink> fragSink(do_QueryInterface(sink));
NS_ENSURE_TRUE(fragSink, NS_ERROR_FAILURE);
fragSink->SetTargetDocument(aTargetDocument);
// parse the fragment
parser->SetContentSink(sink);
if (bContext)

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

@ -683,7 +683,9 @@ protected:
nsCOMPtr<nsIDOMNode> *outFragNode,
PRInt32 *outRangeStartHint,
PRInt32 *outRangeEndHint);
nsresult ParseFragment(const nsAString & aStr, nsVoidArray &aTagStack, nsCOMPtr<nsIDOMNode> *outNode);
nsresult ParseFragment(const nsAString & aStr, nsVoidArray &aTagStack,
nsIDocument* aTargetDoc,
nsCOMPtr<nsIDOMNode> *outNode);
nsresult CreateListOfNodesToPaste(nsIDOMNode *aFragmentAsNode,
nsCOMArray<nsIDOMNode>& outNodeList,
PRInt32 aRangeStartHint,

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

@ -44,6 +44,7 @@
#define NS_HTMLFRAGMENTSINK2_CONTRACTID "@mozilla.org/layout/htmlfragmentsink;2"
class nsIDOMDocumentFragment;
class nsIDocument;
#define NS_IHTML_FRAGMENT_CONTENT_SINK_IID \
{0xa6cf9102, 0x15b3, 0x11d2, \
@ -58,6 +59,18 @@ public:
*
*/
NS_IMETHOD GetFragment(nsIDOMDocumentFragment** aFragment) = 0;
/**
* This method is used to set the target document for this fragment
* sink. This document's nodeinfo manager will be used to create
* the content objects. This MUST be called before the sink is used.
*
* If aDocument is null or has no nodeinfo manager, the sink will
* create a brand-new nodeinfo manager.
*
* @param aDocument the document the new nodes will belong to
*/
NS_IMETHOD SetTargetDocument(nsIDocument* aDocument) = 0;
};
#endif

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

@ -44,6 +44,7 @@
#define NS_HTMLFRAGMENTSINK2_CONTRACTID "@mozilla.org/layout/htmlfragmentsink;2"
class nsIDOMDocumentFragment;
class nsIDocument;
#define NS_IHTML_FRAGMENT_CONTENT_SINK_IID \
{0xa6cf9102, 0x15b3, 0x11d2, \
@ -58,6 +59,18 @@ public:
*
*/
NS_IMETHOD GetFragment(nsIDOMDocumentFragment** aFragment) = 0;
/**
* This method is used to set the target document for this fragment
* sink. This document's nodeinfo manager will be used to create
* the content objects. This MUST be called before the sink is used.
*
* If aDocument is null or has no nodeinfo manager, the sink will
* create a brand-new nodeinfo manager.
*
* @param aDocument the document the new nodes will belong to
*/
NS_IMETHOD SetTargetDocument(nsIDocument* aDocument) = 0;
};
#endif