зеркало из https://github.com/mozilla/gecko-dev.git
Bug 682305 - nsXMLHttpRequest::Send fails with mChannel being implemented in JS. r=sicking
This commit is contained in:
Родитель
94c4150fb9
Коммит
b74038af93
|
@ -1,4 +1,5 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 sw=2 et tw=80: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
|
@ -109,6 +110,7 @@
|
|||
#include "nsIDOMFormData.h"
|
||||
|
||||
#include "nsWrapperCacheInlines.h"
|
||||
#include "nsStreamListenerWrapper.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
@ -3046,9 +3048,6 @@ nsXMLHttpRequest::Send(JSContext *aCx, nsIVariant* aVariant, const Nullable<Requ
|
|||
if (mState & XML_HTTP_REQUEST_MULTIPART) {
|
||||
Telemetry::Accumulate(Telemetry::MULTIPART_XHR_RESPONSE, 1);
|
||||
listener = new nsMultipartProxyListener(listener);
|
||||
if (!listener) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
} else {
|
||||
Telemetry::Accumulate(Telemetry::MULTIPART_XHR_RESPONSE, 0);
|
||||
}
|
||||
|
@ -3062,9 +3061,18 @@ nsXMLHttpRequest::Send(JSContext *aCx, nsIVariant* aVariant, const Nullable<Requ
|
|||
// a same-origin request right now, since it could be redirected.
|
||||
listener = new nsCORSListenerProxy(listener, mPrincipal, mChannel,
|
||||
withCredentials, true, &rv);
|
||||
NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
else {
|
||||
// Because of bug 682305, we can't let listener be the XHR object itself
|
||||
// because JS wouldn't be able to use it. So if we haven't otherwise
|
||||
// created a listener around 'this', do so now.
|
||||
|
||||
listener = new nsStreamListenerWrapper(listener);
|
||||
}
|
||||
|
||||
NS_ASSERTION(listener != this,
|
||||
"Using an object as a listener that can't be exposed to JS");
|
||||
|
||||
// Bypass the network cache in cases where it makes no sense:
|
||||
// 1) Multipart responses are very large and would likely be doomed by the
|
||||
|
|
|
@ -75,6 +75,7 @@ _CHROME_FILES = \
|
|||
test_bug650784.html \
|
||||
test_bug752226-3.xul \
|
||||
test_bug752226-4.xul \
|
||||
test_bug682305.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=682305
|
||||
-->
|
||||
<head>
|
||||
<title>XMLHttpRequest send and channel implemented in JS</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/ChromeUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=682305">Mozilla Bug 682305</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="application/javascript;version=1.8">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
/*
|
||||
* Register a custom nsIProtocolHandler service
|
||||
* in order to be able to implement *and use* an
|
||||
* nsIChannel component written in Javascript.
|
||||
*/
|
||||
|
||||
var Cc = Components.classes;
|
||||
var Ci = Components.interfaces;
|
||||
var Cr = Components.results;
|
||||
var Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
var SimpleURI = Cc["@mozilla.org/network/simple-uri;1"];
|
||||
var ios = Cc["@mozilla.org/network/io-service;1"]
|
||||
.getService(Ci.nsIIOService);
|
||||
|
||||
var PROTOCOL_SCHEME = "jsproto";
|
||||
|
||||
|
||||
function CustomChannel(uri) {
|
||||
this.URI = this.originalURI = uri;
|
||||
}
|
||||
CustomChannel.prototype = {
|
||||
URI: null,
|
||||
originalURI: null,
|
||||
contentCharset: "utf-8",
|
||||
contentLength: 0,
|
||||
contentType: "text/plain",
|
||||
owner: Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal),
|
||||
securityInfo: null,
|
||||
notificationCallbacks: null,
|
||||
loadFlags: 0,
|
||||
loadGroup: null,
|
||||
name: null,
|
||||
status: Cr.NS_OK,
|
||||
asyncOpen: function(listener, context) {
|
||||
let stream = this.open();
|
||||
try {
|
||||
listener.onStartRequest(this, context);
|
||||
} catch(e) {}
|
||||
try {
|
||||
listener.onDataAvailable(this, context, stream, 0, stream.available());
|
||||
} catch(e) {}
|
||||
try {
|
||||
listener.onStopRequest(this, context, Cr.NS_OK);
|
||||
} catch(e) {}
|
||||
},
|
||||
open: function() {
|
||||
let data = "bar";
|
||||
let stream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(Ci.nsIStringInputStream);
|
||||
stream.setData(data, data.length);
|
||||
return stream;
|
||||
},
|
||||
isPending: function() {
|
||||
return false;
|
||||
},
|
||||
cancel: function() {
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
suspend: function() {
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
resume: function() {
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIChannel, Ci.nsIRequest])
|
||||
};
|
||||
|
||||
|
||||
function CustomProtocol() {}
|
||||
CustomProtocol.prototype = {
|
||||
get scheme() {
|
||||
return PROTOCOL_SCHEME;
|
||||
},
|
||||
get protocolFlags() {
|
||||
return (Ci.nsIProtocolHandler.URI_NORELATIVE |
|
||||
Ci.nsIProtocolHandler.URI_IS_LOCAL_RESOURCE |
|
||||
Ci.nsIProtocolHandler.URI_DANGEROUS_TO_LOAD);
|
||||
},
|
||||
get defaultPort() {
|
||||
return -1;
|
||||
},
|
||||
allowPort: function allowPort() {
|
||||
return false;
|
||||
},
|
||||
newURI: function newURI(spec, charset, baseURI) {
|
||||
var uri = SimpleURI.createInstance(Ci.nsIURI)
|
||||
uri.spec = spec;
|
||||
return uri.QueryInterface(Ci.nsIURI);
|
||||
},
|
||||
newChannel: function newChannel(URI) {
|
||||
return new CustomChannel(URI);
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
|
||||
Ci.nsISupportsWeakReference,
|
||||
Ci.nsIProtocolHandler])
|
||||
};
|
||||
|
||||
var gFactory = {
|
||||
register: function() {
|
||||
var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
|
||||
var classID = Components.ID("{ed064287-1e76-49ba-a28d-dc74394a8334}");
|
||||
var description = PROTOCOL_SCHEME + ": protocol";
|
||||
var contractID = "@mozilla.org/network/protocol;1?name=" + PROTOCOL_SCHEME;
|
||||
var factory = XPCOMUtils._getFactory(CustomProtocol);
|
||||
|
||||
registrar.registerFactory(classID, description, contractID, factory);
|
||||
|
||||
this.unregister = function() {
|
||||
registrar.unregisterFactory(classID, factory);
|
||||
delete this.unregister;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// Register the custom procotol handler
|
||||
gFactory.register();
|
||||
|
||||
// Then, checks if XHR works with it
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", PROTOCOL_SCHEME + ":foo", true);
|
||||
xhr.onload = function () {
|
||||
is(xhr.responseText, "bar", "protocol doesn't work");
|
||||
gFactory.unregister();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
try {
|
||||
xhr.send(null);
|
||||
} catch(e) {
|
||||
ok(false, e);
|
||||
}
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -165,6 +165,7 @@ EXPORTS = \
|
|||
nsReadLine.h \
|
||||
nsASocketHandler.h \
|
||||
nsAsyncRedirectVerifyHelper.h \
|
||||
nsStreamListenerWrapper.h \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsStreamListenerWrapper_h__
|
||||
#define nsStreamListenerWrapper_h__
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIRequestObserver.h"
|
||||
|
||||
// Wrapper class to make replacement of nsHttpChannel's listener
|
||||
// from JavaScript possible. It is workaround for bug 433711 and 682305.
|
||||
class nsStreamListenerWrapper : public nsIStreamListener
|
||||
{
|
||||
public:
|
||||
nsStreamListenerWrapper(nsIStreamListener *listener)
|
||||
: mListener(listener)
|
||||
{
|
||||
NS_ASSERTION(mListener, "no stream listener specified");
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_FORWARD_NSIREQUESTOBSERVER(mListener->)
|
||||
NS_FORWARD_NSISTREAMLISTENER(mListener->)
|
||||
|
||||
private:
|
||||
~nsStreamListenerWrapper() {}
|
||||
nsCOMPtr<nsIStreamListener> mListener;
|
||||
};
|
||||
|
||||
#endif // nsStreamListenerWrapper_h__
|
||||
|
|
@ -93,6 +93,7 @@ CPPSRCS = \
|
|||
nsDNSPrefetch.cpp \
|
||||
RedirectChannelRegistrar.cpp \
|
||||
nsPreloadedStream.cpp \
|
||||
nsStreamListenerWrapper.cpp \
|
||||
$(NULL)
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsStreamListenerWrapper.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsStreamListenerWrapper,
|
||||
nsIStreamListener,
|
||||
nsIRequestObserver)
|
||||
|
|
@ -53,6 +53,7 @@
|
|||
#include "nsIResumableChannel.h"
|
||||
#include "nsIApplicationCacheChannel.h"
|
||||
#include "nsEscape.h"
|
||||
#include "nsStreamListenerWrapper.h"
|
||||
|
||||
#include "prnetdb.h"
|
||||
|
||||
|
@ -1427,36 +1428,6 @@ HttpBaseChannel::GetEntityID(nsACString& aEntityID)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsStreamListenerWrapper <private>
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Wrapper class to make replacement of nsHttpChannel's listener
|
||||
// from JavaScript possible. It is workaround for bug 433711.
|
||||
class nsStreamListenerWrapper : public nsIStreamListener
|
||||
{
|
||||
public:
|
||||
nsStreamListenerWrapper(nsIStreamListener *listener);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_FORWARD_NSIREQUESTOBSERVER(mListener->)
|
||||
NS_FORWARD_NSISTREAMLISTENER(mListener->)
|
||||
|
||||
private:
|
||||
~nsStreamListenerWrapper() {}
|
||||
nsCOMPtr<nsIStreamListener> mListener;
|
||||
};
|
||||
|
||||
nsStreamListenerWrapper::nsStreamListenerWrapper(nsIStreamListener *listener)
|
||||
: mListener(listener)
|
||||
{
|
||||
NS_ASSERTION(mListener, "no stream listener specified");
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsStreamListenerWrapper,
|
||||
nsIStreamListener,
|
||||
nsIRequestObserver)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsHttpChannel::nsITraceableChannel
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
Загрузка…
Ссылка в новой задаче