2007-03-22 10:30:00 -07:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Mozilla 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/MPL/
|
|
|
|
*
|
|
|
|
* 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 the Initial Developer are Copyright (C) 1998
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
* the provisions above, a recipient may use your version of this file under
|
|
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
|
|
|
|
#include "jsapi.h"
|
|
|
|
#include "nsDOMParser.h"
|
|
|
|
#include "nsIURI.h"
|
|
|
|
#include "nsIChannel.h"
|
|
|
|
#include "nsILoadGroup.h"
|
|
|
|
#include "nsIInputStream.h"
|
|
|
|
#include "nsNetUtil.h"
|
|
|
|
#include "nsStringStream.h"
|
|
|
|
#include "nsIDocument.h"
|
|
|
|
#include "nsIDOMDocument.h"
|
|
|
|
#include "nsIScriptSecurityManager.h"
|
|
|
|
#include "nsIPrincipal.h"
|
|
|
|
#include "nsIDOMClassInfo.h"
|
|
|
|
#include "nsReadableUtils.h"
|
|
|
|
#include "nsCRT.h"
|
|
|
|
#include "nsLoadListenerProxy.h"
|
|
|
|
#include "nsStreamUtils.h"
|
|
|
|
#include "nsThreadUtils.h"
|
|
|
|
#include "nsNetCID.h"
|
|
|
|
#include "nsContentUtils.h"
|
|
|
|
#include "nsDOMJSUtils.h"
|
|
|
|
#include "nsDOMError.h"
|
2007-12-12 00:33:32 -08:00
|
|
|
#include "nsIDOMWindow.h"
|
|
|
|
#include "nsPIDOMWindow.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// nsIDOMEventListener
|
|
|
|
nsresult
|
|
|
|
nsDOMParser::HandleEvent(nsIDOMEvent* aEvent)
|
|
|
|
{
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// nsIDOMLoadListener
|
|
|
|
nsresult
|
|
|
|
nsDOMParser::Load(nsIDOMEvent* aEvent)
|
|
|
|
{
|
|
|
|
mLoopingForSyncLoad = PR_FALSE;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsDOMParser::BeforeUnload(nsIDOMEvent* aEvent)
|
|
|
|
{
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsDOMParser::Unload(nsIDOMEvent* aEvent)
|
|
|
|
{
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsDOMParser::Abort(nsIDOMEvent* aEvent)
|
|
|
|
{
|
|
|
|
mLoopingForSyncLoad = PR_FALSE;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsDOMParser::Error(nsIDOMEvent* aEvent)
|
|
|
|
{
|
|
|
|
mLoopingForSyncLoad = PR_FALSE;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsDOMParser::nsDOMParser()
|
|
|
|
: mLoopingForSyncLoad(PR_FALSE),
|
|
|
|
mAttemptedInit(PR_FALSE)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
nsDOMParser::~nsDOMParser()
|
|
|
|
{
|
|
|
|
NS_ABORT_IF_FALSE(!mLoopingForSyncLoad, "we rather crash than hang");
|
|
|
|
mLoopingForSyncLoad = PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// QueryInterface implementation for nsDOMParser
|
|
|
|
NS_INTERFACE_MAP_BEGIN(nsDOMParser)
|
|
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMParser)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMParser)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMParserJS)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMLoadListener)
|
2008-04-06 05:28:34 -07:00
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
|
2010-03-17 08:09:05 -07:00
|
|
|
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DOMParser)
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_INTERFACE_MAP_END
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMPL_ADDREF(nsDOMParser)
|
|
|
|
NS_IMPL_RELEASE(nsDOMParser)
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDOMParser::ParseFromString(const PRUnichar *str,
|
|
|
|
const char *contentType,
|
|
|
|
nsIDOMDocument **aResult)
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG(str);
|
|
|
|
NS_ENSURE_ARG_POINTER(aResult);
|
|
|
|
|
|
|
|
NS_ConvertUTF16toUTF8 data(str);
|
|
|
|
|
|
|
|
// The new stream holds a reference to the buffer
|
|
|
|
nsCOMPtr<nsIInputStream> stream;
|
|
|
|
nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
|
|
|
|
data.get(), data.Length(),
|
|
|
|
NS_ASSIGNMENT_DEPEND);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
return ParseFromStream(stream, "UTF-8", data.Length(), contentType, aResult);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDOMParser::ParseFromBuffer(const PRUint8 *buf,
|
|
|
|
PRUint32 bufLen,
|
|
|
|
const char *contentType,
|
|
|
|
nsIDOMDocument **aResult)
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(buf);
|
|
|
|
NS_ENSURE_ARG_POINTER(aResult);
|
|
|
|
|
|
|
|
// The new stream holds a reference to the buffer
|
|
|
|
nsCOMPtr<nsIInputStream> stream;
|
|
|
|
nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
|
2007-07-08 00:08:04 -07:00
|
|
|
reinterpret_cast<const char *>(buf),
|
2007-03-22 10:30:00 -07:00
|
|
|
bufLen, NS_ASSIGNMENT_DEPEND);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
return ParseFromStream(stream, nsnull, bufLen, contentType, aResult);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDOMParser::ParseFromStream(nsIInputStream *stream,
|
|
|
|
const char *charset,
|
|
|
|
PRInt32 contentLength,
|
|
|
|
const char *contentType,
|
|
|
|
nsIDOMDocument **aResult)
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG(stream);
|
|
|
|
NS_ENSURE_ARG(contentType);
|
|
|
|
NS_ENSURE_ARG_POINTER(aResult);
|
|
|
|
*aResult = nsnull;
|
|
|
|
|
|
|
|
// For now, we can only create XML documents.
|
|
|
|
if ((nsCRT::strcmp(contentType, "text/xml") != 0) &&
|
|
|
|
(nsCRT::strcmp(contentType, "application/xml") != 0) &&
|
|
|
|
(nsCRT::strcmp(contentType, "application/xhtml+xml") != 0))
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
|
2007-10-01 03:02:32 -07:00
|
|
|
nsCOMPtr<nsIScriptGlobalObject> scriptHandlingObject =
|
|
|
|
do_QueryReferent(mScriptHandlingObject);
|
2007-03-22 10:30:00 -07:00
|
|
|
nsresult rv;
|
|
|
|
if (!mPrincipal) {
|
|
|
|
NS_ENSURE_TRUE(!mAttemptedInit, NS_ERROR_NOT_INITIALIZED);
|
|
|
|
AttemptedInitMarker marker(&mAttemptedInit);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIPrincipal> prin =
|
|
|
|
do_CreateInstance("@mozilla.org/nullprincipal;1", &rv);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2007-10-01 03:02:32 -07:00
|
|
|
rv = Init(prin, nsnull, nsnull, scriptHandlingObject);
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_ASSERTION(mPrincipal, "Must have principal by now");
|
|
|
|
NS_ASSERTION(mDocumentURI, "Must have document URI by now");
|
|
|
|
|
|
|
|
// Put the nsCOMPtr out here so we hold a ref to the stream as needed
|
|
|
|
nsCOMPtr<nsIInputStream> bufferedStream;
|
|
|
|
if (!NS_InputStreamIsBuffered(stream)) {
|
|
|
|
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), stream,
|
|
|
|
4096);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
stream = bufferedStream;
|
|
|
|
}
|
2007-10-01 03:02:32 -07:00
|
|
|
|
2008-03-27 20:46:15 -07:00
|
|
|
// Here we have to cheat a little bit... Setting the base URI won't
|
|
|
|
// work if the document has a null principal, so use
|
|
|
|
// mOriginalPrincipal when creating the document, then reset the
|
|
|
|
// principal.
|
2007-03-22 10:30:00 -07:00
|
|
|
nsCOMPtr<nsIDOMDocument> domDocument;
|
|
|
|
rv = nsContentUtils::CreateDocument(EmptyString(), EmptyString(), nsnull,
|
2008-03-27 20:46:15 -07:00
|
|
|
mDocumentURI, mBaseURI,
|
|
|
|
mOriginalPrincipal,
|
2007-10-01 03:02:32 -07:00
|
|
|
scriptHandlingObject,
|
2007-03-22 10:30:00 -07:00
|
|
|
getter_AddRefs(domDocument));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
// Register as a load listener on the document
|
2007-05-14 02:11:38 -07:00
|
|
|
nsCOMPtr<nsPIDOMEventTarget> target(do_QueryInterface(domDocument));
|
2007-03-22 10:30:00 -07:00
|
|
|
if (target) {
|
2007-07-08 00:08:04 -07:00
|
|
|
nsWeakPtr requestWeak(do_GetWeakReference(static_cast<nsIDOMParser*>(this)));
|
2007-03-22 10:30:00 -07:00
|
|
|
nsLoadListenerProxy* proxy = new nsLoadListenerProxy(requestWeak);
|
|
|
|
if (!proxy) return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
|
|
|
// This will addref the proxy
|
2007-07-08 00:08:04 -07:00
|
|
|
rv = target->AddEventListenerByIID(static_cast<nsIDOMEventListener*>(proxy),
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_GET_IID(nsIDOMLoadListener));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a fake channel
|
|
|
|
nsCOMPtr<nsIChannel> parserChannel;
|
|
|
|
NS_NewInputStreamChannel(getter_AddRefs(parserChannel), mDocumentURI, nsnull,
|
|
|
|
nsDependentCString(contentType), nsnull);
|
|
|
|
NS_ENSURE_STATE(parserChannel);
|
|
|
|
|
2008-04-24 14:54:42 -07:00
|
|
|
// More principal-faking here
|
|
|
|
parserChannel->SetOwner(mOriginalPrincipal);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
if (charset) {
|
|
|
|
parserChannel->SetContentCharset(nsDependentCString(charset));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Tell the document to start loading
|
|
|
|
nsCOMPtr<nsIStreamListener> listener;
|
|
|
|
|
|
|
|
mLoopingForSyncLoad = PR_TRUE;
|
|
|
|
|
|
|
|
// Have to pass PR_FALSE for reset here, else the reset will remove
|
|
|
|
// our event listener. Should that listener addition move to later
|
|
|
|
// than this call? Then we wouldn't need to mess around with
|
|
|
|
// SetPrincipal, etc, probably!
|
2008-04-24 14:54:42 -07:00
|
|
|
nsCOMPtr<nsIDocument> document(do_QueryInterface(domDocument));
|
|
|
|
if (!document) return NS_ERROR_FAILURE;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
rv = document->StartDocumentLoad(kLoadAsData, parserChannel,
|
|
|
|
nsnull, nsnull,
|
|
|
|
getter_AddRefs(listener),
|
|
|
|
PR_FALSE);
|
|
|
|
|
2008-04-24 14:54:42 -07:00
|
|
|
// Make sure to give this document the right base URI
|
2007-03-22 10:30:00 -07:00
|
|
|
document->SetBaseURI(mBaseURI);
|
|
|
|
|
2008-04-24 14:54:42 -07:00
|
|
|
// And the right principal
|
|
|
|
document->SetPrincipal(mPrincipal);
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_FAILED(rv) || !listener) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now start pumping data to the listener
|
|
|
|
nsresult status;
|
|
|
|
|
|
|
|
rv = listener->OnStartRequest(parserChannel, nsnull);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
parserChannel->Cancel(rv);
|
|
|
|
parserChannel->GetStatus(&status);
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(status)) {
|
|
|
|
rv = listener->OnDataAvailable(parserChannel, nsnull, stream, 0,
|
|
|
|
contentLength);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
parserChannel->Cancel(rv);
|
|
|
|
parserChannel->GetStatus(&status);
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = listener->OnStopRequest(parserChannel, nsnull, status);
|
|
|
|
// Failure returned from OnStopRequest does not affect the final status of
|
|
|
|
// the channel, so we do not need to call Cancel(rv) as we do above.
|
|
|
|
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Process events until we receive a load, abort, or error event for the
|
|
|
|
// document object. That event may have already fired.
|
|
|
|
|
|
|
|
nsIThread *thread = NS_GetCurrentThread();
|
|
|
|
while (mLoopingForSyncLoad) {
|
|
|
|
if (!NS_ProcessNextEvent(thread))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
domDocument.swap(*aResult);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDOMParser::Init(nsIPrincipal* principal, nsIURI* documentURI,
|
2007-10-01 03:02:32 -07:00
|
|
|
nsIURI* baseURI, nsIScriptGlobalObject* aScriptObject)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
NS_ENSURE_STATE(!mAttemptedInit);
|
|
|
|
mAttemptedInit = PR_TRUE;
|
|
|
|
|
|
|
|
NS_ENSURE_ARG(principal || documentURI);
|
|
|
|
|
|
|
|
mDocumentURI = documentURI;
|
|
|
|
if (!mDocumentURI) {
|
|
|
|
principal->GetURI(getter_AddRefs(mDocumentURI));
|
|
|
|
if (!mDocumentURI) {
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-01 03:02:32 -07:00
|
|
|
mScriptHandlingObject = do_GetWeakReference(aScriptObject);
|
2007-03-22 10:30:00 -07:00
|
|
|
mPrincipal = principal;
|
2008-03-27 20:46:15 -07:00
|
|
|
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
|
|
|
|
NS_ENSURE_TRUE(secMan, NS_ERROR_NOT_AVAILABLE);
|
|
|
|
nsresult rv;
|
2007-03-22 10:30:00 -07:00
|
|
|
if (!mPrincipal) {
|
2008-03-27 20:46:15 -07:00
|
|
|
rv =
|
2007-03-22 10:30:00 -07:00
|
|
|
secMan->GetCodebasePrincipal(mDocumentURI, getter_AddRefs(mPrincipal));
|
2008-03-27 20:46:15 -07:00
|
|
|
mOriginalPrincipal = mPrincipal;
|
|
|
|
} else {
|
|
|
|
mOriginalPrincipal = principal;
|
|
|
|
PRBool isSystem;
|
|
|
|
rv = secMan->IsSystemPrincipal(mPrincipal, &isSystem);
|
|
|
|
if (NS_FAILED(rv) || isSystem) {
|
|
|
|
// Don't give DOMParsers the system principal. Use a null
|
|
|
|
// principal instead.
|
|
|
|
mPrincipal = do_CreateInstance("@mozilla.org/nullprincipal;1", &rv);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2008-03-27 20:46:15 -07:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
mBaseURI = baseURI;
|
|
|
|
// Note: if mBaseURI is null, fine. Leave it like that; that will use the
|
|
|
|
// documentURI as the base. Otherwise for null principals we'll get
|
|
|
|
// nsDocument::SetBaseURI giving errors.
|
|
|
|
|
|
|
|
NS_POSTCONDITION(mPrincipal, "Must have principal");
|
2008-03-27 20:46:15 -07:00
|
|
|
NS_POSTCONDITION(mOriginalPrincipal, "Must have original principal");
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_POSTCONDITION(mDocumentURI, "Must have document URI");
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static nsQueryInterface
|
|
|
|
JSvalToInterface(JSContext* cx, jsval val, nsIXPConnect* xpc, PRBool* wasNull)
|
|
|
|
{
|
|
|
|
if (val == JSVAL_NULL) {
|
|
|
|
*wasNull = PR_TRUE;
|
|
|
|
return nsQueryInterface(nsnull);
|
|
|
|
}
|
|
|
|
|
|
|
|
*wasNull = PR_FALSE;
|
|
|
|
if (JSVAL_IS_OBJECT(val)) {
|
|
|
|
JSObject* arg = JSVAL_TO_OBJECT(val);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIXPConnectWrappedNative> native;
|
|
|
|
xpc->GetWrappedNativeOfJSObject(cx, arg, getter_AddRefs(native));
|
|
|
|
|
|
|
|
// do_QueryWrappedNative is not null-safe
|
|
|
|
if (native) {
|
|
|
|
return do_QueryWrappedNative(native);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nsQueryInterface(nsnull);
|
|
|
|
}
|
|
|
|
|
|
|
|
static nsresult
|
|
|
|
GetInitArgs(JSContext *cx, PRUint32 argc, jsval *argv,
|
|
|
|
nsIPrincipal** aPrincipal, nsIURI** aDocumentURI,
|
|
|
|
nsIURI** aBaseURI)
|
|
|
|
{
|
|
|
|
// Only proceed if the caller has UniversalXPConnect.
|
|
|
|
PRBool haveUniversalXPConnect;
|
|
|
|
nsresult rv = nsContentUtils::GetSecurityManager()->
|
|
|
|
IsCapabilityEnabled("UniversalXPConnect", &haveUniversalXPConnect);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
if (!haveUniversalXPConnect) {
|
|
|
|
return NS_ERROR_DOM_SECURITY_ERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIXPConnect* xpc = nsContentUtils::XPConnect();
|
|
|
|
|
|
|
|
// First arg is our principal. If someone passes something that's
|
|
|
|
// not a principal and not null, die to prevent privilege escalation.
|
|
|
|
PRBool wasNull;
|
|
|
|
nsCOMPtr<nsIPrincipal> prin = JSvalToInterface(cx, argv[0], xpc, &wasNull);
|
|
|
|
if (!prin && !wasNull) {
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> documentURI;
|
|
|
|
nsCOMPtr<nsIURI> baseURI;
|
|
|
|
if (argc > 1) {
|
|
|
|
// Grab our document URI too. Again, if it's something unexpected bail
|
|
|
|
// out.
|
|
|
|
documentURI = JSvalToInterface(cx, argv[1], xpc, &wasNull);
|
|
|
|
if (!documentURI && !wasNull) {
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argc > 2) {
|
|
|
|
// Grab our base URI as well
|
|
|
|
baseURI = JSvalToInterface(cx, argv[2], xpc, &wasNull);
|
|
|
|
if (!baseURI && !wasNull) {
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IF_ADDREF(*aPrincipal = prin);
|
|
|
|
NS_IF_ADDREF(*aDocumentURI = documentURI);
|
|
|
|
NS_IF_ADDREF(*aBaseURI = baseURI);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2007-12-12 00:33:32 -08:00
|
|
|
nsDOMParser::Initialize(nsISupports* aOwner, JSContext* cx, JSObject* obj,
|
2007-03-22 10:30:00 -07:00
|
|
|
PRUint32 argc, jsval *argv)
|
|
|
|
{
|
|
|
|
AttemptedInitMarker marker(&mAttemptedInit);
|
|
|
|
nsCOMPtr<nsIPrincipal> prin;
|
|
|
|
nsCOMPtr<nsIURI> documentURI;
|
|
|
|
nsCOMPtr<nsIURI> baseURI;
|
|
|
|
if (argc > 0) {
|
|
|
|
nsresult rv = GetInitArgs(cx, argc, argv, getter_AddRefs(prin),
|
|
|
|
getter_AddRefs(documentURI),
|
|
|
|
getter_AddRefs(baseURI));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
} else {
|
|
|
|
// No arguments; use the subject principal
|
|
|
|
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
|
|
|
|
NS_ENSURE_TRUE(secMan, NS_ERROR_UNEXPECTED);
|
|
|
|
|
|
|
|
secMan->GetSubjectPrincipal(getter_AddRefs(prin));
|
|
|
|
|
|
|
|
// We're called from JS; there better be a subject principal, really.
|
|
|
|
NS_ENSURE_TRUE(prin, NS_ERROR_UNEXPECTED);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_ASSERTION(prin, "Must have principal by now");
|
|
|
|
|
|
|
|
if (!documentURI) {
|
|
|
|
// No explicit documentURI; grab document and base URIs off the window our
|
|
|
|
// constructor was called on. Error out if anything untoward happens.
|
|
|
|
|
|
|
|
// Note that this is a behavior change as far as I can tell -- we're now
|
|
|
|
// using the base URI and document URI of the window off of which the
|
|
|
|
// DOMParser is created, not the window in which parse*() is called.
|
|
|
|
// Does that matter?
|
|
|
|
|
|
|
|
// Also note that |cx| matches what GetDocumentFromContext() would return,
|
|
|
|
// while GetDocumentFromCaller() gives us the window that the DOMParser()
|
|
|
|
// call was made on.
|
2007-12-12 00:33:32 -08:00
|
|
|
|
|
|
|
nsCOMPtr<nsIDocument> doc;
|
|
|
|
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aOwner);
|
|
|
|
if (aOwner) {
|
|
|
|
nsCOMPtr<nsIDOMDocument> domdoc = window->GetExtantDocument();
|
|
|
|
doc = do_QueryInterface(domdoc);
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
if (!doc) {
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
baseURI = doc->GetBaseURI();
|
|
|
|
documentURI = doc->GetDocumentURI();
|
|
|
|
}
|
|
|
|
|
2007-12-12 00:33:32 -08:00
|
|
|
nsCOMPtr<nsIScriptGlobalObject> scriptglobal = do_QueryInterface(aOwner);
|
|
|
|
return Init(prin, documentURI, baseURI, scriptglobal);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2008-09-05 14:54:53 -07:00
|
|
|
nsDOMParser::Init(nsIPrincipal *principal, nsIURI *documentURI, nsIURI *baseURI)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
AttemptedInitMarker marker(&mAttemptedInit);
|
|
|
|
|
2008-09-05 14:54:53 -07:00
|
|
|
JSContext *cx = nsContentUtils::GetCurrentJSContext();
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ENSURE_TRUE(cx, NS_ERROR_UNEXPECTED);
|
|
|
|
|
2007-10-01 03:02:32 -07:00
|
|
|
nsIScriptContext* scriptContext = GetScriptContextFromJSContext(cx);
|
2008-09-05 14:54:53 -07:00
|
|
|
return Init(principal, documentURI, baseURI,
|
2007-10-01 03:02:32 -07:00
|
|
|
scriptContext ? scriptContext->GetGlobalObject() : nsnull);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|