зеркало из https://github.com/mozilla/pjs.git
First cut of XMLSerializer and XMLHttpRequest. This is WIP and not part of the Mozilla/Seamonkey build.
This commit is contained in:
Родитель
f5a493943c
Коммит
e38df119b8
|
@ -0,0 +1,67 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIOutputStream;
|
||||
interface nsIDOMNode;
|
||||
|
||||
/**
|
||||
* The nsIDOMSerializer interface is really a placeholder till the W3C
|
||||
* DOM Working Group defines a mechanism for serializing DOM nodes.
|
||||
* An instance of this interface can be used to serialize a DOM document
|
||||
* or any DOM subtree.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(a6cf9123-15b3-11d2-932e-00805f8add32)]
|
||||
interface nsIDOMSerializer : nsISupports {
|
||||
/**
|
||||
* The subtree rooted by the specified element is serialized to
|
||||
* a string.
|
||||
*
|
||||
* @param root The root of the subtree to be serialized. This could
|
||||
* be any node, including a Document.
|
||||
* @returns The serialized subtree in the form of a Unicode string
|
||||
*/
|
||||
wstring serializeToString(in nsIDOMNode root);
|
||||
|
||||
/**
|
||||
* The subtree rooted by the specified element is serialized to
|
||||
* a byte stream using the character set specified.
|
||||
* @param root The root of the subtree to be serialized. This could
|
||||
* be any node, including a Document.
|
||||
* @param stream The byte stream to which the subtree is serialized.
|
||||
* @param charset The name of the character set to use for the encoding
|
||||
* to a byte stream.
|
||||
*/
|
||||
void serializeToStream(in nsIDOMNode root, in nsIOutputStream stream, in string charset);
|
||||
};
|
||||
|
||||
%{ C++
|
||||
#define NS_XMLSERIALIZER_CID \
|
||||
{ /* a6cf9124-15b3-11d2-932e-00805f8add32 */ \
|
||||
0xa6cf9124, 0x15b3, 0x11d2, \
|
||||
{0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} }
|
||||
#define NS_XMLSERIALIZER_PROGID \
|
||||
"component://netscape/xmlextras/xmlserializer"
|
||||
%}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIDOMDocument;
|
||||
interface nsIDOMEventListener;
|
||||
|
||||
[scriptable, uuid(b7215e70-4157-11d4-9a42-000064657374)]
|
||||
interface nsIXMLHttpRequest : nsISupports {
|
||||
noscript void addEventListener(in string type,
|
||||
in nsIDOMEventListener listener);
|
||||
noscript void removeEventListener(in string type,
|
||||
in nsIDOMEventListener listener);
|
||||
attribute nsISupports onload;
|
||||
attribute nsISupports onerror;
|
||||
readonly attribute nsIDOMDocument responseXML;
|
||||
readonly attribute unsigned long status;
|
||||
readonly attribute string statusText;
|
||||
|
||||
void abort();
|
||||
string getAllResponseHeaders();
|
||||
string getResponseHeader(in string header);
|
||||
noscript void openRequest(in string method,
|
||||
in wstring url,
|
||||
in boolean async,
|
||||
in string user,
|
||||
in string password);
|
||||
void open(in string method, in wstring url);
|
||||
void send(in nsISupports body);
|
||||
void setRequestHeader(in string header, in string value);
|
||||
};
|
||||
|
||||
%{ C++
|
||||
#define NS_XMLHTTPREQUEST_CID \
|
||||
{ /* d164e770-4157-11d4-9a42-000064657374 */ \
|
||||
0xd164e770, 0x4157, 0x11d4, \
|
||||
{0x9a, 0x42, 0x00, 0x00, 0x64, 0x65, 0x73, 0x74} }
|
||||
#define NS_XMLHTTPREQUEST_PROGID \
|
||||
"component://netscape/xmlextras/xmlhttprequest"
|
||||
%}
|
|
@ -0,0 +1,670 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "nsDOMSerializer.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMDocumentType.h"
|
||||
#include "nsIDOMText.h"
|
||||
#include "nsIDOMCDATASection.h"
|
||||
#include "nsIDOMComment.h"
|
||||
#include "nsIDOMProcessingInstruction.h"
|
||||
#include "nsIDOMNamedNodeMap.h"
|
||||
#include "nsIDOMAttr.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIUnicodeEncoder.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsICharsetConverterManager.h"
|
||||
|
||||
#define USE_NSICONTENT
|
||||
#ifdef USE_NSICONTENT
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#endif
|
||||
|
||||
static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
|
||||
|
||||
typedef struct {
|
||||
nsString mPrefix;
|
||||
nsString mURI;
|
||||
nsIDOMElement* mOwner;
|
||||
} NameSpaceDecl;
|
||||
|
||||
nsDOMSerializer::nsDOMSerializer()
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
mPrefixIndex = 0;
|
||||
}
|
||||
|
||||
nsDOMSerializer::~nsDOMSerializer()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsDOMSerializer, nsIDOMSerializer)
|
||||
|
||||
void
|
||||
nsDOMSerializer::SerializeText(nsIDOMText* aText, nsString& aStr)
|
||||
{
|
||||
nsAutoString data;
|
||||
if (aText) {
|
||||
aText->GetData(data);
|
||||
aStr.Append(data);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMSerializer::SerializeCDATASection(nsIDOMCDATASection* aCDATASection,
|
||||
nsString& aStr)
|
||||
{
|
||||
nsAutoString data;
|
||||
if (aCDATASection) {
|
||||
aCDATASection->GetData(data);
|
||||
aStr.AppendWithConversion("<![CDATA[");
|
||||
aStr.Append(data);
|
||||
aStr.AppendWithConversion("]]>");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMSerializer::SerializeProcessingInstruction(nsIDOMProcessingInstruction* aPI,
|
||||
nsString& aStr)
|
||||
{
|
||||
nsAutoString target, data;
|
||||
if (aPI) {
|
||||
aStr.AppendWithConversion("<?");
|
||||
aPI->GetTarget(target);
|
||||
aStr.Append(target);
|
||||
aPI->GetData(data);
|
||||
if (data.Length() > 0) {
|
||||
aStr.AppendWithConversion(" ");
|
||||
aStr.Append(data);
|
||||
}
|
||||
aStr.AppendWithConversion(">");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMSerializer::SerializeComment(nsIDOMComment* aComment,
|
||||
nsString& aStr)
|
||||
{
|
||||
nsAutoString data;
|
||||
if (aComment) {
|
||||
aStr.AppendWithConversion("<!--");
|
||||
aComment->GetData(data);
|
||||
aStr.Append(data);
|
||||
aStr.AppendWithConversion("-->");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMSerializer::SerializeDoctype(nsIDOMDocumentType* aDoctype,
|
||||
nsString& aStr)
|
||||
{
|
||||
if (aDoctype) {
|
||||
nsAutoString name, publicId, systemId, internalSubset;
|
||||
|
||||
aDoctype->GetName(name);
|
||||
aDoctype->GetPublicId(publicId);
|
||||
aDoctype->GetSystemId(publicId);
|
||||
aDoctype->GetInternalSubset(publicId);
|
||||
|
||||
aStr.AppendWithConversion("<!DOCTYPE ");
|
||||
aStr.Append(name);
|
||||
if (publicId.Length() > 0) {
|
||||
aStr.AppendWithConversion(" PUBLIC \"");
|
||||
aStr.Append(publicId);
|
||||
aStr.AppendWithConversion("\" \"");
|
||||
aStr.Append(systemId);
|
||||
aStr.AppendWithConversion("\"");
|
||||
}
|
||||
else if (systemId.Length() > 0) {
|
||||
aStr.AppendWithConversion(" SYSTEM \"");
|
||||
aStr.Append(systemId);
|
||||
aStr.AppendWithConversion("\"");
|
||||
}
|
||||
|
||||
if (internalSubset.Length() > 0) {
|
||||
aStr.AppendWithConversion(" ");
|
||||
aStr.Append(internalSubset);
|
||||
}
|
||||
|
||||
aStr.AppendWithConversion(">");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const char* kXMLNS = "xmlns";
|
||||
|
||||
void
|
||||
nsDOMSerializer::PushNameSpaceDecl(nsString& aPrefix,
|
||||
nsString& aURI,
|
||||
nsIDOMElement* aOwner)
|
||||
{
|
||||
NameSpaceDecl* decl = new NameSpaceDecl();
|
||||
if (decl) {
|
||||
decl->mPrefix.Assign(aPrefix);
|
||||
decl->mURI.Assign(aURI);
|
||||
// Don't addref - this weak reference will be removed when
|
||||
// we pop the stack
|
||||
decl->mOwner = aOwner;
|
||||
|
||||
mNameSpaceStack.AppendElement((void*)decl);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMSerializer::PopNameSpaceDeclsFor(nsIDOMElement* aOwner)
|
||||
{
|
||||
PRInt32 index, count;
|
||||
|
||||
count = mNameSpaceStack.Count();
|
||||
for (index = count; index >= 0; index--) {
|
||||
NameSpaceDecl* decl = (NameSpaceDecl*)mNameSpaceStack.ElementAt(index);
|
||||
if (decl) {
|
||||
if (decl->mOwner != aOwner) {
|
||||
break;
|
||||
}
|
||||
mNameSpaceStack.RemoveElementAt(index);
|
||||
delete decl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsDOMSerializer::ConfirmPrefix(nsString& aPrefix,
|
||||
nsString& aURI)
|
||||
{
|
||||
if (aPrefix.EqualsWithConversion(kXMLNS)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (aURI.Length() == 0) {
|
||||
aPrefix.Truncate();
|
||||
return PR_FALSE;
|
||||
}
|
||||
PRInt32 index, count;
|
||||
nsAutoString closestURIMatch;
|
||||
PRBool uriMatch = PR_FALSE;
|
||||
|
||||
count = mNameSpaceStack.Count();
|
||||
for (index = count; index >= 0; index--) {
|
||||
NameSpaceDecl* decl = (NameSpaceDecl*)mNameSpaceStack.ElementAt(index);
|
||||
if (decl) {
|
||||
// Check if we've found a prefix match
|
||||
if (aPrefix.Equals(decl->mPrefix)) {
|
||||
|
||||
// If the URI's match, we don't have to add a namespace decl
|
||||
if (aURI.Equals(decl->mURI)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
// If they don't, we can't use this prefix
|
||||
else {
|
||||
aPrefix.Truncate();
|
||||
}
|
||||
}
|
||||
// If we've found a URI match, then record the first one
|
||||
else if (!uriMatch && aURI.Equals(decl->mURI)) {
|
||||
uriMatch = PR_TRUE;
|
||||
closestURIMatch.Assign(decl->mPrefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// There are no namespace declarations that match the prefix, uri pair.
|
||||
// If there's another prefix that matches that URI, us it.
|
||||
if (uriMatch) {
|
||||
aPrefix.Assign(closestURIMatch);
|
||||
return PR_FALSE;
|
||||
}
|
||||
// If we don't have a prefix, create one
|
||||
else if (aPrefix.Length() == 0) {
|
||||
aPrefix.AssignWithConversion("a");
|
||||
aPrefix.AppendInt(mPrefixIndex++);
|
||||
}
|
||||
|
||||
// Indicate that we need to create a namespace decl for the
|
||||
// final prefix
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMSerializer::SerializeAttr(nsString& aPrefix,
|
||||
nsString& aName,
|
||||
nsString& aValue,
|
||||
nsString& aStr)
|
||||
{
|
||||
aStr.AppendWithConversion(" ");
|
||||
if (aPrefix.Length() > 0) {
|
||||
aStr.Append(aPrefix);
|
||||
aStr.AppendWithConversion(":");
|
||||
}
|
||||
aStr.Append(aName);
|
||||
|
||||
aStr.AppendWithConversion("=\"");
|
||||
aStr.Append(aValue);
|
||||
aStr.AppendWithConversion("\"");
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMSerializer::SerializeElementStart(nsIDOMElement* aElement, nsString& aStr)
|
||||
{
|
||||
if (aElement) {
|
||||
nsAutoString tagPrefix, tagLocalName, tagNamespaceURI;
|
||||
nsAutoString xmlnsStr, defaultnsStr;
|
||||
xmlnsStr.AssignWithConversion(kXMLNS);
|
||||
defaultnsStr.AssignWithConversion("");
|
||||
|
||||
aElement->GetPrefix(tagPrefix);
|
||||
aElement->GetLocalName(tagLocalName);
|
||||
aElement->GetNamespaceURI(tagNamespaceURI);
|
||||
|
||||
#ifdef USE_NSICONTENT
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
|
||||
PRInt32 index, count;
|
||||
nsAutoString nameStr, prefixStr, uriStr, valueStr;
|
||||
PRInt32 namespaceID;
|
||||
nsCOMPtr<nsIAtom> attrName, attrPrefix;
|
||||
if (content) {
|
||||
content->GetAttributeCount(count);
|
||||
|
||||
// First scan for namespace declarations, pushing each on the stack
|
||||
for (index = 0; index < count; index++) {
|
||||
|
||||
content->GetAttributeNameAt(index,
|
||||
namespaceID,
|
||||
*getter_AddRefs(attrName),
|
||||
*getter_AddRefs(attrPrefix));
|
||||
|
||||
if (attrPrefix) {
|
||||
attrPrefix->ToString(prefixStr);
|
||||
}
|
||||
else {
|
||||
prefixStr.Truncate();
|
||||
}
|
||||
attrName->ToString(nameStr);
|
||||
|
||||
content->GetAttribute(namespaceID, attrName, uriStr);
|
||||
if ((namespaceID == kNameSpaceID_XMLNS) ||
|
||||
prefixStr.EqualsWithConversion(kXMLNS)) {
|
||||
PushNameSpaceDecl(nameStr, uriStr, aElement);
|
||||
}
|
||||
else if (nameStr.EqualsWithConversion(kXMLNS)) {
|
||||
PushNameSpaceDecl(defaultnsStr, uriStr, aElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
PRInt32 index, count;
|
||||
nsAutoString nameStr, prefixStr, uriStr, valueStr;
|
||||
nsCOMPtr<nsIDOMNamedNodeMap> attrMap;
|
||||
nsCOMPtr<nsIDOMNode> attrNode;
|
||||
nsCOMPtr<nsIDOMAttr> attrObj;
|
||||
|
||||
aElement->GetAttributes(getter_AddRefs(attrMap));
|
||||
if (attrMap) {
|
||||
attrMap->GetLength((PRUint32*)&count);
|
||||
|
||||
// First scan for namespace declarations, pushing each on the stack
|
||||
for (index = 0; index < count; index++) {
|
||||
attrMap->Item(index, getter_AddRefs(attrNode));
|
||||
attrObj = do_QueryInterface(attrNode);
|
||||
if (attrObj) {
|
||||
attrObj->GetPrefix(prefixStr);
|
||||
attrObj->GetLocalName(nameStr);
|
||||
attrObj->GetNamespaceURI(uriStr);
|
||||
if (prefixStr.EqualsWithConversion(kXMLNS)) {
|
||||
PushNameSpaceDecl(nameStr, uriStr, aElement);
|
||||
}
|
||||
else if (nameStr.EqualsWithConversion(kXMLNS)) {
|
||||
PushNameSpaceDecl(nsAutoString(), uriStr, aElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
PRBool addNSAttr;
|
||||
|
||||
// Serialize the qualified name of the element
|
||||
addNSAttr = ConfirmPrefix(tagPrefix, tagNamespaceURI);
|
||||
aStr.AppendWithConversion("<");
|
||||
if (tagPrefix.Length() > 0) {
|
||||
aStr.Append(tagPrefix);
|
||||
aStr.AppendWithConversion(":");
|
||||
}
|
||||
aStr.Append(tagLocalName);
|
||||
|
||||
// If we had to add a new namespace declaration, serialize
|
||||
// and push it on the namespace stack
|
||||
if (addNSAttr) {
|
||||
SerializeAttr(xmlnsStr, tagPrefix, tagNamespaceURI, aStr);
|
||||
PushNameSpaceDecl(tagPrefix, tagNamespaceURI, aElement);
|
||||
}
|
||||
|
||||
#ifdef USE_NSICONTENT
|
||||
if (content) {
|
||||
// Now serialize each of the attributes
|
||||
// XXX Unfortunately we need a namespace manager to get
|
||||
// attribute URIs.
|
||||
nsCOMPtr<nsIDocument> document;
|
||||
nsCOMPtr<nsINameSpaceManager> nsmanager;
|
||||
content->GetDocument(*getter_AddRefs(document));
|
||||
if (document) {
|
||||
document->GetNameSpaceManager(*getter_AddRefs(nsmanager));
|
||||
}
|
||||
|
||||
for (index = 0; index < count; index++) {
|
||||
content->GetAttributeNameAt(index,
|
||||
namespaceID,
|
||||
*getter_AddRefs(attrName),
|
||||
*getter_AddRefs(attrPrefix));
|
||||
if (attrPrefix) {
|
||||
attrPrefix->ToString(prefixStr);
|
||||
}
|
||||
else {
|
||||
prefixStr.Truncate();
|
||||
}
|
||||
|
||||
addNSAttr = PR_FALSE;
|
||||
if (kNameSpaceID_XMLNS == namespaceID) {
|
||||
prefixStr.AssignWithConversion(kXMLNS);
|
||||
}
|
||||
else if (nsmanager) {
|
||||
nsmanager->GetNameSpaceURI(namespaceID, uriStr);
|
||||
addNSAttr = ConfirmPrefix(prefixStr, uriStr);
|
||||
}
|
||||
|
||||
content->GetAttribute(namespaceID, attrName, valueStr);
|
||||
attrName->ToString(nameStr);
|
||||
|
||||
SerializeAttr(prefixStr, nameStr, valueStr, aStr);
|
||||
|
||||
if (addNSAttr) {
|
||||
SerializeAttr(xmlnsStr, prefixStr, uriStr, aStr);
|
||||
PushNameSpaceDecl(prefixStr, uriStr, aElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (attrMap) {
|
||||
// Now serialize each of the attributes
|
||||
for (index = 0; index < count; index++) {
|
||||
aStr.AppendWithConversion(" ");
|
||||
attrMap->Item(index, getter_AddRefs(attrNode));
|
||||
attrObj = do_QueryInterface(attrNode);
|
||||
if (attrObj) {
|
||||
attrObj->GetPrefix(prefixStr);
|
||||
attrObj->GetLocalName(nameStr);
|
||||
attrObj->GetNamespaceURI(uriStr);
|
||||
|
||||
addNSAttr = ConfirmPrefix(prefixStr, uriStr);
|
||||
attrObj->GetNodeValue(valueStr);
|
||||
|
||||
SerializeAttr(prefixStr, nameStr, valueStr, aStr);
|
||||
|
||||
if (addNSAttr) {
|
||||
SerializeAttr(xmlnsStr, prefixStr, uriStr, aStr);
|
||||
PushNameSpaceDecl(prefixStr, uriStr, aElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
aStr.AppendWithConversion(">");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMSerializer::SerializeElementEnd(nsIDOMElement* aElement, nsString& aStr)
|
||||
{
|
||||
if (aElement) {
|
||||
nsAutoString tagPrefix, tagLocalName, tagNamespaceURI;
|
||||
|
||||
aElement->GetPrefix(tagPrefix);
|
||||
aElement->GetLocalName(tagLocalName);
|
||||
aElement->GetNamespaceURI(tagNamespaceURI);
|
||||
|
||||
ConfirmPrefix(tagPrefix, tagNamespaceURI);
|
||||
aStr.AppendWithConversion("</");
|
||||
if (tagPrefix.Length() > 0) {
|
||||
aStr.Append(tagPrefix);
|
||||
aStr.AppendWithConversion(":");
|
||||
}
|
||||
aStr.Append(tagLocalName);
|
||||
aStr.AppendWithConversion(">");
|
||||
|
||||
PopNameSpaceDeclsFor(aElement);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsDOMSerializer::SerializeNodeStart(nsIDOMNode* aNode, nsString& aStr)
|
||||
{
|
||||
PRUint16 type;
|
||||
|
||||
aNode->GetNodeType(&type);
|
||||
switch (type) {
|
||||
case nsIDOMNode::ELEMENT_NODE:
|
||||
{
|
||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aNode);
|
||||
SerializeElementStart(element, aStr);
|
||||
break;
|
||||
}
|
||||
case nsIDOMNode::TEXT_NODE:
|
||||
{
|
||||
nsCOMPtr<nsIDOMText> text = do_QueryInterface(aNode);
|
||||
SerializeText(text, aStr);
|
||||
break;
|
||||
}
|
||||
case nsIDOMNode::CDATA_SECTION_NODE:
|
||||
{
|
||||
nsCOMPtr<nsIDOMCDATASection> cdata = do_QueryInterface(aNode);
|
||||
SerializeCDATASection(cdata, aStr);
|
||||
break;
|
||||
}
|
||||
case nsIDOMNode::PROCESSING_INSTRUCTION_NODE:
|
||||
{
|
||||
nsCOMPtr<nsIDOMProcessingInstruction> pi = do_QueryInterface(aNode);
|
||||
SerializeProcessingInstruction(pi, aStr);
|
||||
break;
|
||||
}
|
||||
case nsIDOMNode::COMMENT_NODE:
|
||||
{
|
||||
nsCOMPtr<nsIDOMComment> comment = do_QueryInterface(aNode);
|
||||
SerializeComment(comment, aStr);
|
||||
break;
|
||||
}
|
||||
case nsIDOMNode::DOCUMENT_TYPE_NODE:
|
||||
{
|
||||
nsCOMPtr<nsIDOMDocumentType> doctype = do_QueryInterface(aNode);
|
||||
SerializeDoctype(doctype, aStr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMSerializer::SerializeNodeEnd(nsIDOMNode* aNode, nsString& aStr)
|
||||
{
|
||||
PRUint16 type;
|
||||
|
||||
aNode->GetNodeType(&type);
|
||||
switch (type) {
|
||||
case nsIDOMNode::ELEMENT_NODE:
|
||||
{
|
||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aNode);
|
||||
SerializeElementEnd(element, aStr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMSerializer::SerializeToStringRecursive(nsIDOMNode* aNode, nsString& aStr)
|
||||
{
|
||||
nsresult rv = SerializeNodeStart(aNode, aStr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||
rv = aNode->GetChildNodes(getter_AddRefs(childNodes));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (childNodes) {
|
||||
PRInt32 index, count;
|
||||
|
||||
childNodes->GetLength((PRUint32*)&count);
|
||||
for (index = 0; index < count; index++) {
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
|
||||
rv = childNodes->Item(index, getter_AddRefs(child));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = SerializeToStringRecursive(child, aStr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
rv = SerializeNodeEnd(aNode, aStr);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMSerializer::SerializeToString(nsIDOMNode *root, PRUnichar **_retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(root);
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
nsresult rv;
|
||||
nsAutoString str;
|
||||
|
||||
rv = SerializeToStringRecursive(root, str);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
*_retval = str.ToNewUnicode();
|
||||
if (nsnull == *_retval) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
ConvertAndWrite(nsString& aString,
|
||||
nsIOutputStream* aStream,
|
||||
nsIUnicodeEncoder* aEncoder)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aStream);
|
||||
NS_ENSURE_ARG_POINTER(aEncoder);
|
||||
nsresult rv;
|
||||
PRInt32 charLength;
|
||||
PRUnichar* unicodeBuf = (PRUnichar*)aString.GetUnicode();
|
||||
PRInt32 unicodeLength = aString.Length();
|
||||
|
||||
rv = aEncoder->GetMaxLength(unicodeBuf, unicodeLength, &charLength);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCAutoString charXferString;
|
||||
charXferString.SetCapacity(charLength);
|
||||
char* charXferBuf = (char*)charXferString.GetBuffer();
|
||||
|
||||
rv = aEncoder->Convert(unicodeBuf, &unicodeLength, charXferBuf, &charLength);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
PRUint32 written;
|
||||
rv = aStream->Write(charXferBuf, charLength, &written);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMSerializer::SerializeToStreamRecursive(nsIDOMNode* aNode,
|
||||
nsIOutputStream* aStream,
|
||||
nsIUnicodeEncoder* aEncoder)
|
||||
{
|
||||
nsAutoString start;
|
||||
nsresult rv = SerializeNodeStart(aNode, start);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = ConvertAndWrite(start, aStream, aEncoder);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||
rv = aNode->GetChildNodes(getter_AddRefs(childNodes));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (childNodes) {
|
||||
PRInt32 index, count;
|
||||
|
||||
childNodes->GetLength((PRUint32*)&count);
|
||||
for (index = 0; index < count; index++) {
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
|
||||
rv = childNodes->Item(index, getter_AddRefs(child));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = SerializeToStreamRecursive(child, aStream, aEncoder);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoString end;
|
||||
rv = SerializeNodeEnd(aNode, end);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = ConvertAndWrite(end, aStream, aEncoder);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMSerializer::SerializeToStream(nsIDOMNode *root,
|
||||
nsIOutputStream *stream,
|
||||
const char *charset)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(root);
|
||||
NS_ENSURE_ARG_POINTER(stream);
|
||||
NS_ENSURE_ARG_POINTER(charset);
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIUnicodeEncoder> encoder;
|
||||
|
||||
NS_WITH_SERVICE(nsICharsetConverterManager,
|
||||
charsetConv,
|
||||
kCharsetConverterManagerCID,
|
||||
&rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoString charsetStr;
|
||||
charsetStr.AssignWithConversion(charset);
|
||||
rv = charsetConv->GetUnicodeEncoder(&charsetStr,
|
||||
getter_AddRefs(encoder));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = SerializeToStreamRecursive(root, stream, encoder);
|
||||
|
||||
return rv;
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef nsDOMSerializer_h__
|
||||
#define nsDOMSerializer_h__
|
||||
|
||||
#include "nsIDOMSerializer.h"
|
||||
#include "nsISupportsUtils.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsString.h"
|
||||
|
||||
class nsIDOMElement;
|
||||
class nsIDOMDocumentType;
|
||||
class nsIDOMText;
|
||||
class nsIDOMCDATASection;
|
||||
class nsIDOMComment;
|
||||
class nsIDOMProcessingInstruction;
|
||||
class nsIUnicodeEncoder;
|
||||
|
||||
class nsDOMSerializer : public nsIDOMSerializer {
|
||||
public:
|
||||
nsDOMSerializer();
|
||||
virtual ~nsDOMSerializer();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIDOMSerializer
|
||||
NS_IMETHOD SerializeToString(nsIDOMNode *root, PRUnichar **_retval);
|
||||
NS_IMETHOD SerializeToStream(nsIDOMNode *root,
|
||||
nsIOutputStream *stream,
|
||||
const char *charset);
|
||||
|
||||
protected:
|
||||
void SerializeText(nsIDOMText* aText, nsString& aStr);
|
||||
void SerializeCDATASection(nsIDOMCDATASection* aCDATASection, nsString& aStr);
|
||||
void SerializeProcessingInstruction(nsIDOMProcessingInstruction* aPI,
|
||||
nsString& aStr);
|
||||
void SerializeComment(nsIDOMComment* aComment, nsString& aStr);
|
||||
void SerializeDoctype(nsIDOMDocumentType* aDoctype, nsString& aStr);
|
||||
void PushNameSpaceDecl(nsString& aPrefix,
|
||||
nsString& aURI,
|
||||
nsIDOMElement* aOwner);
|
||||
void PopNameSpaceDeclsFor(nsIDOMElement* aOwner);
|
||||
PRBool ConfirmPrefix(nsString& aPrefix,
|
||||
nsString& aURI);
|
||||
void SerializeAttr(nsString& aPrefix,
|
||||
nsString& aName,
|
||||
nsString& aValue,
|
||||
nsString& aStr);
|
||||
void SerializeElementStart(nsIDOMElement* aElement, nsString& aStr);
|
||||
void SerializeElementEnd(nsIDOMElement* aElement, nsString& aStr);
|
||||
nsresult SerializeNodeStart(nsIDOMNode* aNode, nsString& aStr);
|
||||
nsresult SerializeNodeEnd(nsIDOMNode* aNode, nsString& aStr);
|
||||
nsresult SerializeToStringRecursive(nsIDOMNode* aNode, nsString& aStr);
|
||||
nsresult SerializeToStreamRecursive(nsIDOMNode* aNode,
|
||||
nsIOutputStream* aStream,
|
||||
nsIUnicodeEncoder* aEncoder);
|
||||
|
||||
protected:
|
||||
PRInt32 mPrefixIndex;
|
||||
nsVoidArray mNameSpaceStack;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,887 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "nsXMLHttpRequest.h"
|
||||
#include "nsIStreamObserver.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsIHTTPHeader.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsIByteArrayInputStream.h"
|
||||
#include "nsIUnicodeEncoder.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsICharsetConverterManager.h"
|
||||
#include "nsLayoutCID.h"
|
||||
#include "nsIDOMDOMImplementation.h"
|
||||
#include "nsIPrivateDOMImplementation.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsILoadGroup.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsIDOMSerializer.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "prprf.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
#include "nsIJSContextStack.h"
|
||||
|
||||
static const char* kLoadAsData = "loadAsData";
|
||||
static const char* kLoadStr = "load";
|
||||
static const char* kErrorStr = "error";
|
||||
|
||||
static NS_DEFINE_CID(kIDOMDOMImplementationCID, NS_DOM_IMPLEMENTATION_CID);
|
||||
static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
|
||||
|
||||
static JSContext*
|
||||
GetSafeContext()
|
||||
{
|
||||
// Get the "safe" JSContext: our JSContext of last resort
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIJSContextStack, stack, "nsThreadJSContextStack",
|
||||
&rv);
|
||||
if (NS_FAILED(rv))
|
||||
return nsnull;
|
||||
nsCOMPtr<nsIThreadJSContextStack> tcs = do_QueryInterface(stack);
|
||||
JSContext* cx;
|
||||
if (NS_FAILED(tcs->GetSafeJSContext(&cx))) {
|
||||
return nsnull;
|
||||
}
|
||||
return cx;
|
||||
}
|
||||
|
||||
static JSContext*
|
||||
GetCurrentContext()
|
||||
{
|
||||
// Get JSContext from stack.
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIJSContextStack, stack, "nsThreadJSContextStack",
|
||||
&rv);
|
||||
if (NS_FAILED(rv))
|
||||
return nsnull;
|
||||
JSContext *cx;
|
||||
if (NS_FAILED(stack->Peek(&cx)))
|
||||
return nsnull;
|
||||
return cx;
|
||||
}
|
||||
|
||||
nsXMLHttpRequestScriptListener::nsXMLHttpRequestScriptListener(JSObject* aScopeObj, JSObject* aFunctionObj)
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
// We don't have to add a GC root for the scope object
|
||||
// since we'll go away if it goes away
|
||||
mScopeObj = aScopeObj;
|
||||
mFunctionObj = aFunctionObj;
|
||||
JSContext* cx;
|
||||
cx = GetSafeContext();
|
||||
if (cx) {
|
||||
JS_AddNamedRoot(cx, &mFunctionObj, "nsXMLHttpRequest");
|
||||
}
|
||||
}
|
||||
|
||||
nsXMLHttpRequestScriptListener::~nsXMLHttpRequestScriptListener()
|
||||
{
|
||||
JSContext* cx;
|
||||
cx = GetSafeContext();
|
||||
if (cx) {
|
||||
JS_RemoveRoot(cx, &mFunctionObj);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsXMLHttpRequestScriptListener, nsIDOMEventListener, nsIPrivateJSEventListener)
|
||||
|
||||
nsresult
|
||||
nsXMLHttpRequestScriptListener::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
JSContext* cx;
|
||||
cx = GetCurrentContext();
|
||||
if (!cx) {
|
||||
cx = GetSafeContext();
|
||||
}
|
||||
if (cx) {
|
||||
jsval val;
|
||||
|
||||
// Hmmm...we can't pass along the nsIDOMEvent because
|
||||
// we may not have the right type of context (required
|
||||
// to get a JSObject from a nsIScriptObjectOwner)
|
||||
JS_CallFunctionValue(cx, mScopeObj,
|
||||
OBJECT_TO_JSVAL(mFunctionObj),
|
||||
0, nsnull, &val);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequestScriptListener::GetFunctionObj(JSObject** aObj)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aObj);
|
||||
|
||||
*aObj = mFunctionObj;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
/////////////////////////////////////////////
|
||||
|
||||
nsXMLHttpRequest::nsXMLHttpRequest()
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
mComplete = PR_FALSE;
|
||||
}
|
||||
|
||||
nsXMLHttpRequest::~nsXMLHttpRequest()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsXMLHttpRequest, nsIXMLHttpRequest, nsIDOMLoadListener)
|
||||
|
||||
/* noscript void addEventListener (in string type, in nsIDOMEventListener listener); */
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::AddEventListener(const char *type,
|
||||
nsIDOMEventListener *listener)
|
||||
{
|
||||
NS_ENSURE_ARG(type);
|
||||
NS_ENSURE_ARG(listener);
|
||||
nsresult rv;
|
||||
|
||||
// I know, I know - strcmp's. But it's only for a couple of
|
||||
// cases...and they are short strings. :-)
|
||||
if (nsCRT::strcmp(type, kLoadStr) == 0) {
|
||||
if (!mLoadEventListeners) {
|
||||
rv = NS_NewISupportsArray(getter_AddRefs(mLoadEventListeners));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
mLoadEventListeners->AppendElement(listener);
|
||||
}
|
||||
else if (nsCRT::strcmp(type, kErrorStr) == 0) {
|
||||
if (!mErrorEventListeners) {
|
||||
rv = NS_NewISupportsArray(getter_AddRefs(mErrorEventListeners));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
mErrorEventListeners->AppendElement(listener);
|
||||
}
|
||||
else {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* noscript void removeEventListener (in string type, in nsIDOMEventListener listener); */
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::RemoveEventListener(const char *type,
|
||||
nsIDOMEventListener *listener)
|
||||
{
|
||||
NS_ENSURE_ARG(type);
|
||||
NS_ENSURE_ARG(listener);
|
||||
|
||||
if (nsCRT::strcmp(type, kLoadStr) == 0) {
|
||||
if (mLoadEventListeners) {
|
||||
mLoadEventListeners->RemoveElement(listener);
|
||||
}
|
||||
}
|
||||
else if (nsCRT::strcmp(type, kErrorStr) == 0) {
|
||||
if (mErrorEventListeners) {
|
||||
mErrorEventListeners->RemoveElement(listener);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXMLHttpRequest::MakeScriptEventListener(nsISupports* aObject,
|
||||
nsIDOMEventListener** aListener)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
*aListener = nsnull;
|
||||
|
||||
nsCOMPtr<nsIXPCNativeCallContext> cc;
|
||||
NS_WITH_SERVICE(nsIXPConnect, xpc, nsIXPConnect::GetCID(), &rv);
|
||||
if(NS_SUCCEEDED(rv)) {
|
||||
rv = xpc->GetCurrentNativeCallContext(getter_AddRefs(cc));
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv) && cc) {
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> jsobjholder = do_QueryInterface(aObject);
|
||||
if (jsobjholder) {
|
||||
JSObject* funobj;
|
||||
rv = jsobjholder->GetJSObject(&funobj);
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
JSContext* cx;
|
||||
rv = cc->GetJSContext(&cx);
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
JSFunction* fun = JS_ValueToFunction(cx, OBJECT_TO_JSVAL(funobj));
|
||||
if (!fun) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
|
||||
rv = cc->GetCalleeWrapper(getter_AddRefs(wrapper));
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
JSObject* scopeobj;
|
||||
rv = wrapper->GetJSObject(&scopeobj);
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
nsXMLHttpRequestScriptListener* listener = new nsXMLHttpRequestScriptListener(scopeobj, funobj);
|
||||
if (!listener) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
*aListener = listener;
|
||||
NS_ADDREF(*aListener);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static PRBool
|
||||
CheckForScriptListener(nsISupports* aElement, void *aData)
|
||||
{
|
||||
nsCOMPtr<nsIPrivateJSEventListener> jsel = do_QueryInterface(aElement);
|
||||
if (jsel) {
|
||||
nsIDOMEventListener** retval = (nsIDOMEventListener**)aData;
|
||||
|
||||
aElement->QueryInterface(NS_GET_IID(nsIDOMEventListener), (void**)retval);
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
nsXMLHttpRequest::GetScriptEventListener(nsISupportsArray* aList,
|
||||
nsIDOMEventListener** aListener)
|
||||
{
|
||||
aList->EnumerateForwards(CheckForScriptListener, (void*)aListener);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXMLHttpRequest::StuffReturnValue(nsIDOMEventListener* aListener)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIXPCNativeCallContext> cc;
|
||||
NS_WITH_SERVICE(nsIXPConnect, xpc, nsIXPConnect::GetCID(), &rv);
|
||||
if(NS_SUCCEEDED(rv)) {
|
||||
rv = xpc->GetCurrentNativeCallContext(getter_AddRefs(cc));
|
||||
}
|
||||
|
||||
// If we're being called through JS, stuff the return value
|
||||
if (NS_SUCCEEDED(rv) && cc) {
|
||||
jsval* val;
|
||||
rv = cc->GetRetValPtr(&val);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
JSObject* obj;
|
||||
nsCOMPtr<nsIPrivateJSEventListener> jsel = do_QueryInterface(aListener);
|
||||
if (jsel) {
|
||||
jsel->GetFunctionObj(&obj);
|
||||
*val = OBJECT_TO_JSVAL(obj);
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
/* attribute nsIDOMEventListener onload; */
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::GetOnload(nsISupports * *aOnLoad)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aOnLoad);
|
||||
|
||||
*aOnLoad = nsnull;
|
||||
if (mLoadEventListeners) {
|
||||
nsCOMPtr<nsIDOMEventListener> listener;
|
||||
|
||||
GetScriptEventListener(mLoadEventListeners, getter_AddRefs(listener));
|
||||
if (listener) {
|
||||
StuffReturnValue(listener);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::SetOnload(nsISupports * aOnLoad)
|
||||
{
|
||||
NS_ENSURE_ARG(aOnLoad);
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIDOMEventListener> listener;
|
||||
|
||||
rv = MakeScriptEventListener(aOnLoad, getter_AddRefs(listener));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (listener) {
|
||||
nsCOMPtr<nsIDOMEventListener> oldListener;
|
||||
|
||||
// Remove any old script event listener that exists since
|
||||
// we can only have one
|
||||
if (mLoadEventListeners) {
|
||||
GetScriptEventListener(mLoadEventListeners, getter_AddRefs(oldListener));
|
||||
RemoveEventListener(kLoadStr, oldListener);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// If it's not a script event listener, try to directly QI it to
|
||||
// an actual event listener
|
||||
listener = do_QueryInterface(aOnLoad);
|
||||
if (!listener) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
return AddEventListener(kLoadStr, listener);
|
||||
}
|
||||
|
||||
/* attribute nsIDOMEventListener onerror; */
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::GetOnerror(nsISupports * *aOnerror)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aOnerror);
|
||||
|
||||
*aOnerror = nsnull;
|
||||
if (mErrorEventListeners) {
|
||||
nsCOMPtr<nsIDOMEventListener> listener;
|
||||
|
||||
GetScriptEventListener(mErrorEventListeners, getter_AddRefs(listener));
|
||||
if (listener) {
|
||||
StuffReturnValue(listener);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::SetOnerror(nsISupports * aOnerror)
|
||||
{
|
||||
NS_ENSURE_ARG(aOnerror);
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIDOMEventListener> listener;
|
||||
|
||||
rv = MakeScriptEventListener(aOnerror, getter_AddRefs(listener));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (listener) {
|
||||
nsCOMPtr<nsIDOMEventListener> oldListener;
|
||||
|
||||
// Remove any old script event listener that exists since
|
||||
// we can only have one
|
||||
if (mErrorEventListeners) {
|
||||
GetScriptEventListener(mErrorEventListeners,
|
||||
getter_AddRefs(oldListener));
|
||||
RemoveEventListener(kErrorStr, oldListener);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// If it's not a script event listener, try to directly QI it to
|
||||
// an actual event listener
|
||||
listener = do_QueryInterface(aOnerror);
|
||||
if (!listener) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
return AddEventListener(kErrorStr, listener);
|
||||
}
|
||||
|
||||
/* readonly attribute nsIDOMDocument responseXML; */
|
||||
NS_IMETHODIMP nsXMLHttpRequest::GetResponseXML(nsIDOMDocument **aResponseXML)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aResponseXML);
|
||||
*aResponseXML = nsnull;
|
||||
if (mComplete && mDocument) {
|
||||
*aResponseXML = mDocument;
|
||||
NS_ADDREF(*aResponseXML);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute unsigned long status; */
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::GetStatus(PRUint32 *aStatus)
|
||||
{
|
||||
if (mChannel) {
|
||||
return mChannel->GetResponseStatus(aStatus);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute string statusText; */
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::GetStatusText(char * *aStatusText)
|
||||
{
|
||||
if (mChannel) {
|
||||
return mChannel->GetResponseString(aStatusText);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void abort (); */
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::Abort()
|
||||
{
|
||||
if (mChannel) {
|
||||
return mChannel->Cancel(NS_BINDING_ABORTED);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* string getAllResponseHeaders (); */
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::GetAllResponseHeaders(char **_retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
if (mChannel) {
|
||||
nsCOMPtr<nsISimpleEnumerator> enumerator;
|
||||
nsCAutoString headers;
|
||||
|
||||
nsresult rv = mChannel->GetResponseHeaderEnumerator(getter_AddRefs(enumerator));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRBool hasMore;
|
||||
while(NS_SUCCEEDED(enumerator->HasMoreElements(&hasMore)) && hasMore) {
|
||||
nsCOMPtr<nsISupports> isup;
|
||||
|
||||
rv = enumerator->GetNext(getter_AddRefs(isup));
|
||||
if (NS_FAILED(rv)) {
|
||||
break;
|
||||
}
|
||||
nsCOMPtr<nsIHTTPHeader> header = do_QueryInterface(isup);
|
||||
if (header) {
|
||||
nsXPIDLCString name, value;
|
||||
header->GetFieldName(getter_Copies(name));
|
||||
header->GetValue(getter_Copies(value));
|
||||
headers.Append((const char*)name);
|
||||
headers.Append(": ");
|
||||
headers.Append((const char*)value);
|
||||
headers.Append("\n");
|
||||
}
|
||||
}
|
||||
*_retval = headers.ToNewCString();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* string getResponseHeader (in string header); */
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::GetResponseHeader(const char *header, char **_retval)
|
||||
{
|
||||
NS_ENSURE_ARG(header);
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
|
||||
if (mChannel) {
|
||||
nsCOMPtr<nsIAtom> headerAtom = dont_AddRef(NS_NewAtom(header));
|
||||
return mChannel->GetResponseHeader(headerAtom, _retval);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* noscript void openRequest (in string method, in wstring url, in boolean async, in string user, in string password); */
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::OpenRequest(const char *method,
|
||||
const PRUnichar *url,
|
||||
PRBool async,
|
||||
const char *user,
|
||||
const char *password)
|
||||
{
|
||||
NS_ENSURE_ARG(method);
|
||||
NS_ENSURE_ARG(url);
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIURI> uri, baseURI;
|
||||
nsCOMPtr<nsILoadGroup> loadGroup;
|
||||
PRBool authp = PR_FALSE;
|
||||
|
||||
mAsync = async;
|
||||
|
||||
// If we have a base document, use it for the base URL and loadgroup
|
||||
if (mBaseDocument) {
|
||||
baseURI = dont_AddRef(mBaseDocument->GetDocumentURL());
|
||||
rv = mBaseDocument->GetDocumentLoadGroup(getter_AddRefs(loadGroup));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
nsAutoString urlStr(url);
|
||||
rv = NS_NewURI(getter_AddRefs(uri), urlStr, baseURI);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Only http URLs are allowed
|
||||
nsXPIDLCString protocol;
|
||||
uri->GetScheme(getter_Copies(protocol));
|
||||
if (nsCRT::strcmp("http", (const char*)protocol) != 0) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (user) {
|
||||
nsCAutoString prehost;
|
||||
prehost.Assign(user);
|
||||
if (password) {
|
||||
prehost.Append(":");
|
||||
prehost.Append(password);
|
||||
}
|
||||
uri->SetPreHost(prehost.GetBuffer());
|
||||
authp = PR_TRUE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
rv = NS_OpenURI(getter_AddRefs(channel), uri, nsnull, loadGroup);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mChannel = do_QueryInterface(channel);
|
||||
if (!mChannel) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
mChannel->SetAuthTriedWithPrehost(authp);
|
||||
nsCOMPtr<nsIAtom> methodAtom = dont_AddRef(NS_NewAtom(method));
|
||||
if (methodAtom) {
|
||||
rv = mChannel->SetRequestMethod(methodAtom);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* void open (in string method, in wstring url); */
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::Open(const char *method, const PRUnichar *url)
|
||||
{
|
||||
nsresult rv;
|
||||
PRBool async = PR_TRUE;
|
||||
char* user = nsnull;
|
||||
char* password = nsnull;
|
||||
|
||||
nsCOMPtr<nsIXPCNativeCallContext> cc;
|
||||
NS_WITH_SERVICE(nsIXPConnect, xpc, nsIXPConnect::GetCID(), &rv);
|
||||
if(NS_SUCCEEDED(rv)) {
|
||||
rv = xpc->GetCurrentNativeCallContext(getter_AddRefs(cc));
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv) && cc) {
|
||||
PRUint32 argc;
|
||||
rv = cc->GetArgc(&argc);
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
jsval* argv;
|
||||
rv = cc->GetArgvPtr(&argv);
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
JSContext* cx;
|
||||
rv = cc->GetJSContext(&cx);
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
if (argc > 2) {
|
||||
JSBool bool;
|
||||
JS_ValueToBoolean(cx, argv[2], &bool);
|
||||
async = (PRBool)bool;
|
||||
|
||||
if (argc > 3) {
|
||||
JSString* userStr;
|
||||
|
||||
userStr = JS_ValueToString(cx, argv[3]);
|
||||
if (userStr) {
|
||||
user = JS_GetStringBytes(userStr);
|
||||
}
|
||||
|
||||
if (argc > 4) {
|
||||
JSString* passwordStr;
|
||||
|
||||
passwordStr = JS_ValueToString(cx, argv[4]);
|
||||
if (passwordStr) {
|
||||
password = JS_GetStringBytes(passwordStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return OpenRequest(method, url, async, user, password);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXMLHttpRequest::GetStreamForWString(const PRUnichar* aStr,
|
||||
PRInt32 aLength,
|
||||
nsIInputStream** aStream)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIUnicodeEncoder> encoder;
|
||||
nsAutoString charsetStr;
|
||||
char* postData;
|
||||
|
||||
// We want to encode the string as utf-8, so get the right encoder
|
||||
NS_WITH_SERVICE(nsICharsetConverterManager,
|
||||
charsetConv,
|
||||
kCharsetConverterManagerCID,
|
||||
&rv);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
|
||||
|
||||
charsetStr.AssignWithConversion("UTF-8");
|
||||
rv = charsetConv->GetUnicodeEncoder(&charsetStr,
|
||||
getter_AddRefs(encoder));
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
|
||||
|
||||
// Convert to utf-8
|
||||
PRInt32 charLength;
|
||||
const PRUnichar* unicodeBuf = aStr;
|
||||
PRInt32 unicodeLength = aLength;
|
||||
|
||||
rv = encoder->GetMaxLength(unicodeBuf, unicodeLength, &charLength);
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
#define MAX_HEADER_SIZE 128
|
||||
|
||||
// Allocate extra space for the header and trailing CRLF
|
||||
postData = (char*)nsMemory::Alloc(MAX_HEADER_SIZE + charLength + 3);
|
||||
if (!postData) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
rv = encoder->Convert(unicodeBuf,
|
||||
&unicodeLength, postData+MAX_HEADER_SIZE, &charLength);
|
||||
if (NS_FAILED(rv)) {
|
||||
nsMemory::Free(postData);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Now that we know the real content length we can create the header
|
||||
PR_snprintf(postData,
|
||||
MAX_HEADER_SIZE,
|
||||
"Content-type: text/xml\015\012Content-Length: %d\015\012\015\012",
|
||||
charLength);
|
||||
PRInt32 headerSize = nsCRT::strlen(postData);
|
||||
|
||||
// Copy the post data to immediately follow the header
|
||||
nsCRT::memcpy(postData+headerSize, postData+MAX_HEADER_SIZE, charLength);
|
||||
|
||||
// Shove in the traling CRLF
|
||||
postData[headerSize+charLength] = CR;
|
||||
postData[headerSize+charLength+1] = LF;
|
||||
postData[headerSize+charLength+2] = '\0';
|
||||
|
||||
// The new stream takes ownership of the buffer
|
||||
rv = NS_NewByteArrayInputStream((nsIByteArrayInputStream**)aStream,
|
||||
postData,
|
||||
headerSize+charLength+2);
|
||||
if (NS_FAILED(rv)) {
|
||||
nsMemory::Free(postData);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void send (in nsISupports body); */
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::Send(nsISupports *body)
|
||||
{
|
||||
NS_ENSURE_ARG(body);
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIInputStream> postDataStream;
|
||||
|
||||
if (!mChannel) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(body);
|
||||
if (doc) {
|
||||
// Get an XML serializer
|
||||
nsCOMPtr<nsIDOMSerializer> serializer = do_CreateInstance(NS_XMLSERIALIZER_PROGID, &rv);
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
// Serialize the current document to string
|
||||
nsXPIDLString serial;
|
||||
rv = serializer->SerializeToString(doc, getter_Copies(serial));
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
// Convert to a byte stream
|
||||
rv = GetStreamForWString((const PRUnichar*)serial,
|
||||
nsCRT::strlen((const PRUnichar*)serial),
|
||||
getter_AddRefs(postDataStream));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<nsIInputStream> stream = do_QueryInterface(body);
|
||||
if (stream) {
|
||||
postDataStream = stream;
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<nsISupportsWString> wstr = do_QueryInterface(body);
|
||||
if (wstr) {
|
||||
nsXPIDLString holder;
|
||||
wstr->GetData(getter_Copies(holder));
|
||||
rv = GetStreamForWString((const PRUnichar*)holder,
|
||||
nsCRT::strlen((const PRUnichar*)holder),
|
||||
getter_AddRefs(postDataStream));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (postDataStream) {
|
||||
rv = mChannel->SetUploadStream(postDataStream);
|
||||
}
|
||||
|
||||
// Get and initialize a DOMImplementation
|
||||
nsCOMPtr<nsIDOMDOMImplementation> implementation = do_CreateInstance(kIDOMDOMImplementationCID, &rv);
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
if (mBaseDocument) {
|
||||
nsCOMPtr<nsIPrivateDOMImplementation> privImpl = do_QueryInterface(implementation);
|
||||
if (privImpl) {
|
||||
privImpl->Init(mBaseDocument);
|
||||
}
|
||||
}
|
||||
|
||||
// Create an empty document from it
|
||||
nsAutoString emptyStr;
|
||||
rv = implementation->CreateDocument(emptyStr,
|
||||
emptyStr,
|
||||
nsnull,
|
||||
getter_AddRefs(mDocument));
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
// Register as a load listener on the document
|
||||
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(mDocument);
|
||||
if (target) {
|
||||
nsAutoString loadStr;
|
||||
loadStr.AssignWithConversion("load");
|
||||
rv = target->AddEventListener(loadStr,
|
||||
NS_STATIC_CAST(nsIDOMEventListener*, this),
|
||||
PR_FALSE);
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Tell the document to start loading
|
||||
nsCOMPtr<nsIStreamListener> listener;
|
||||
nsCOMPtr<nsIDocument> document = do_QueryInterface(mDocument);
|
||||
if (!document) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
rv = document->StartDocumentLoad(kLoadAsData, mChannel,
|
||||
nsnull, nsnull,
|
||||
getter_AddRefs(listener),
|
||||
PR_FALSE);
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
// Start reading from the channel
|
||||
rv = mChannel->AsyncRead(listener, nsnull);
|
||||
if (!mAsync) {
|
||||
// XXX spin an event loop here and wait
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* void setRequestHeader (in string header, in string value); */
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::SetRequestHeader(const char *header, const char *value)
|
||||
{
|
||||
if (mChannel) {
|
||||
nsCOMPtr<nsIAtom> headerAtom = dont_AddRef(NS_NewAtom(header));
|
||||
return mChannel->SetRequestHeader(headerAtom, value);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIDOMEventListener
|
||||
nsresult
|
||||
nsXMLHttpRequest::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// nsIDOMLoadListener
|
||||
nsresult
|
||||
nsXMLHttpRequest::Load(nsIDOMEvent* aEvent)
|
||||
{
|
||||
mComplete = PR_TRUE;
|
||||
if (mLoadEventListeners) {
|
||||
PRUint32 index, count;
|
||||
|
||||
mLoadEventListeners->Count(&count);
|
||||
for (index = 0; index < count; index++) {
|
||||
nsCOMPtr<nsISupports> current = dont_AddRef(mLoadEventListeners->ElementAt(index));
|
||||
if (current) {
|
||||
nsCOMPtr<nsIDOMEventListener> listener = do_QueryInterface(current);
|
||||
if (listener) {
|
||||
listener->HandleEvent(aEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXMLHttpRequest::Unload(nsIDOMEvent* aEvent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXMLHttpRequest::Abort(nsIDOMEvent* aEvent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXMLHttpRequest::Error(nsIDOMEvent* aEvent)
|
||||
{
|
||||
if (mErrorEventListeners) {
|
||||
PRUint32 index, count;
|
||||
|
||||
mErrorEventListeners->Count(&count);
|
||||
for (index = 0; index < count; index++) {
|
||||
nsCOMPtr<nsISupports> current = dont_AddRef(mErrorEventListeners->ElementAt(index));
|
||||
if (current) {
|
||||
nsCOMPtr<nsIDOMEventListener> listener = do_QueryInterface(current);
|
||||
if (listener) {
|
||||
listener->HandleEvent(aEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef nsXMLHttpRequest_h__
|
||||
#define nsXMLHttpRequest_h__
|
||||
|
||||
#include "nsIXMLHttpRequest.h"
|
||||
#include "nsISupportsUtils.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIDOMLoadListener.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIHTTPChannel.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "jsapi.h"
|
||||
|
||||
class nsXMLHttpRequest : public nsIXMLHttpRequest,
|
||||
public nsIDOMLoadListener
|
||||
{
|
||||
public:
|
||||
nsXMLHttpRequest();
|
||||
virtual ~nsXMLHttpRequest();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIXMLHttpRequest
|
||||
NS_DECL_NSIXMLHTTPREQUEST
|
||||
|
||||
// nsIDOMEventListener
|
||||
virtual nsresult HandleEvent(nsIDOMEvent* aEvent);
|
||||
|
||||
// nsIDOMLoadListener
|
||||
virtual nsresult Load(nsIDOMEvent* aEvent);
|
||||
virtual nsresult Unload(nsIDOMEvent* aEvent);
|
||||
virtual nsresult Abort(nsIDOMEvent* aEvent);
|
||||
virtual nsresult Error(nsIDOMEvent* aEvent);
|
||||
|
||||
protected:
|
||||
nsresult MakeScriptEventListener(nsISupports* aObject,
|
||||
nsIDOMEventListener** aListener);
|
||||
void GetScriptEventListener(nsISupportsArray* aList,
|
||||
nsIDOMEventListener** aListener);
|
||||
PRBool StuffReturnValue(nsIDOMEventListener* aListener);
|
||||
|
||||
|
||||
nsresult GetStreamForWString(const PRUnichar* aStr,
|
||||
PRInt32 aLength,
|
||||
nsIInputStream** aStream);
|
||||
|
||||
nsCOMPtr<nsIHTTPChannel> mChannel;
|
||||
nsCOMPtr<nsIDOMDocument> mDocument;
|
||||
nsCOMPtr<nsIDocument> mBaseDocument;
|
||||
nsCOMPtr<nsISupportsArray> mLoadEventListeners;
|
||||
nsCOMPtr<nsISupportsArray> mErrorEventListeners;
|
||||
PRBool mComplete;
|
||||
PRBool mAsync;
|
||||
};
|
||||
|
||||
#define NS_IPRIVATEJSEVENTLISTENER_IID \
|
||||
{ /* d47a6550-4327-11d4-9a45-000064657374 */ \
|
||||
0xd47a6550, 0x4327, 0x11d4, \
|
||||
{0x9a, 0x45, 0x00, 0x00, 0x64, 0x65, 0x73, 0x74} }
|
||||
|
||||
class nsIPrivateJSEventListener : public nsISupports {
|
||||
public:
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IPRIVATEJSEVENTLISTENER_IID)
|
||||
|
||||
NS_IMETHOD GetFunctionObj(JSObject** aObj) = 0;
|
||||
};
|
||||
|
||||
class nsXMLHttpRequestScriptListener : public nsIDOMEventListener,
|
||||
public nsIPrivateJSEventListener
|
||||
{
|
||||
public:
|
||||
nsXMLHttpRequestScriptListener(JSObject* aScopeObj, JSObject* aFunctionObj);
|
||||
virtual ~nsXMLHttpRequestScriptListener();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIDOMEventListener
|
||||
virtual nsresult HandleEvent(nsIDOMEvent* aEvent);
|
||||
|
||||
// nsIPrivateJSEventListener
|
||||
NS_IMETHOD GetFunctionObj(JSObject** aObj);
|
||||
|
||||
protected:
|
||||
JSObject* mScopeObj;
|
||||
JSObject* mFunctionObj;
|
||||
};
|
||||
|
||||
#endif
|
Загрузка…
Ссылка в новой задаче