mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-10 01:08:21 +00:00
Bug 780529. Make people poking XHR via random XPCOM interfaces actually work as long as they stick to GetInterface. r=peterv
This commit is contained in:
parent
583e8302be
commit
2295217399
@ -350,7 +350,8 @@ nsXMLHttpRequest::nsXMLHttpRequest()
|
||||
mFirstStartRequestSeen(false),
|
||||
mInLoadProgressEvent(false),
|
||||
mResultJSON(JSVAL_VOID),
|
||||
mResultArrayBuffer(nullptr)
|
||||
mResultArrayBuffer(nullptr),
|
||||
mXPCOMifier(nullptr)
|
||||
{
|
||||
nsLayoutStatics::AddRef();
|
||||
|
||||
@ -3695,13 +3696,11 @@ nsXMLHttpRequest::GetInterface(const nsIID & aIID, void **aResult)
|
||||
// need to see these notifications for proper functioning.
|
||||
if (aIID.Equals(NS_GET_IID(nsIChannelEventSink))) {
|
||||
mChannelEventSink = do_GetInterface(mNotificationCallbacks);
|
||||
*aResult = static_cast<nsIChannelEventSink*>(this);
|
||||
NS_ADDREF_THIS();
|
||||
*aResult = static_cast<nsIChannelEventSink*>(EnsureXPCOMifier().get());
|
||||
return NS_OK;
|
||||
} else if (aIID.Equals(NS_GET_IID(nsIProgressEventSink))) {
|
||||
mProgressEventSink = do_GetInterface(mNotificationCallbacks);
|
||||
*aResult = static_cast<nsIProgressEventSink*>(this);
|
||||
NS_ADDREF_THIS();
|
||||
*aResult = static_cast<nsIProgressEventSink*>(EnsureXPCOMifier().get());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -3742,7 +3741,21 @@ nsXMLHttpRequest::GetInterface(const nsIID & aIID, void **aResult)
|
||||
|
||||
return wwatch->GetPrompt(window, aIID,
|
||||
reinterpret_cast<void**>(aResult));
|
||||
|
||||
}
|
||||
// Now check for the various XHR non-DOM interfaces, except
|
||||
// nsIProgressEventSink and nsIChannelEventSink which we already
|
||||
// handled above.
|
||||
else if (aIID.Equals(NS_GET_IID(nsIStreamListener))) {
|
||||
*aResult = static_cast<nsIStreamListener*>(EnsureXPCOMifier().get());
|
||||
return NS_OK;
|
||||
}
|
||||
else if (aIID.Equals(NS_GET_IID(nsIRequestObserver))) {
|
||||
*aResult = static_cast<nsIRequestObserver*>(EnsureXPCOMifier().get());
|
||||
return NS_OK;
|
||||
}
|
||||
else if (aIID.Equals(NS_GET_IID(nsITimerCallback))) {
|
||||
*aResult = static_cast<nsITimerCallback*>(EnsureXPCOMifier().get());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return QueryInterface(aIID, aResult);
|
||||
@ -3860,6 +3873,16 @@ nsXMLHttpRequest::StartProgressEventTimer()
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<nsXMLHttpRequestXPCOMifier>
|
||||
nsXMLHttpRequest::EnsureXPCOMifier()
|
||||
{
|
||||
if (!mXPCOMifier) {
|
||||
mXPCOMifier = new nsXMLHttpRequestXPCOMifier(this);
|
||||
}
|
||||
nsRefPtr<nsXMLHttpRequestXPCOMifier> newRef(mXPCOMifier);
|
||||
return newRef.forget();
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsXMLHttpRequest::nsHeaderVisitor, nsIHttpHeaderVisitor)
|
||||
|
||||
NS_IMETHODIMP nsXMLHttpRequest::
|
||||
@ -3957,3 +3980,47 @@ NS_IMETHODIMP nsXMLHttpProgressEvent::GetTotalSize(uint32_t *aTotalSize)
|
||||
LL_L2UI(*aTotalSize, mMaxProgress);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsXMLHttpRequestXPCOMifier implementation
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXMLHttpRequestXPCOMifier)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIChannelEventSink)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIProgressEventSink)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
|
||||
NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStreamListener)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXMLHttpRequestXPCOMifier)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXMLHttpRequestXPCOMifier)
|
||||
|
||||
// Can't NS_IMPL_CYCLE_COLLECTION_1 because mXHR has ambiguous
|
||||
// inheritance from nsISupports.
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLHttpRequestXPCOMifier)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXMLHttpRequestXPCOMifier)
|
||||
if (tmp->mXHR) {
|
||||
tmp->mXHR->mXPCOMifier = nullptr;
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mXHR)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXMLHttpRequestXPCOMifier)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mXHR, nsIXMLHttpRequest)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequestXPCOMifier::GetInterface(const nsIID & aIID, void **aResult)
|
||||
{
|
||||
// Return ourselves for the things we implement (except
|
||||
// nsIInterfaceRequestor) and the XHR for the rest.
|
||||
if (!aIID.Equals(NS_GET_IID(nsIInterfaceRequestor))) {
|
||||
nsresult rv = QueryInterface(aIID, aResult);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return mXHR->GetInterface(aIID, aResult);
|
||||
}
|
||||
|
@ -114,6 +114,10 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class nsXMLHttpRequestXPCOMifier;
|
||||
|
||||
// Make sure that any non-DOM interfaces added here are also added to
|
||||
// nsXMLHttpRequestXPCOMifier.
|
||||
class nsXMLHttpRequest : public nsXHREventTarget,
|
||||
public nsIXMLHttpRequest,
|
||||
public nsIJSXMLHttpRequest,
|
||||
@ -126,6 +130,8 @@ class nsXMLHttpRequest : public nsXHREventTarget,
|
||||
public nsITimerCallback
|
||||
{
|
||||
friend class nsXHRParseEndListener;
|
||||
friend class nsXMLHttpRequestXPCOMifier;
|
||||
|
||||
public:
|
||||
nsXMLHttpRequest();
|
||||
virtual ~nsXMLHttpRequest();
|
||||
@ -502,6 +508,8 @@ protected:
|
||||
const mozilla::dom::Optional<nsAString>& user,
|
||||
const mozilla::dom::Optional<nsAString>& password);
|
||||
|
||||
already_AddRefed<nsXMLHttpRequestXPCOMifier> EnsureXPCOMifier();
|
||||
|
||||
nsCOMPtr<nsISupports> mContext;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
nsCOMPtr<nsIChannel> mChannel;
|
||||
@ -657,10 +665,49 @@ protected:
|
||||
nsCString value;
|
||||
};
|
||||
nsTArray<RequestHeader> mModifiedRequestHeaders;
|
||||
|
||||
// Helper object to manage our XPCOM scriptability bits
|
||||
nsXMLHttpRequestXPCOMifier* mXPCOMifier;
|
||||
};
|
||||
|
||||
#undef IMPL_EVENT_HANDLER
|
||||
|
||||
// A shim class designed to expose the non-DOM interfaces of
|
||||
// XMLHttpRequest via XPCOM stuff.
|
||||
class nsXMLHttpRequestXPCOMifier MOZ_FINAL : public nsIStreamListener,
|
||||
public nsIChannelEventSink,
|
||||
public nsIProgressEventSink,
|
||||
public nsIInterfaceRequestor,
|
||||
public nsITimerCallback,
|
||||
public nsCycleCollectionParticipant
|
||||
{
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXMLHttpRequestXPCOMifier,
|
||||
nsIStreamListener)
|
||||
|
||||
nsXMLHttpRequestXPCOMifier(nsXMLHttpRequest* aXHR) :
|
||||
mXHR(aXHR)
|
||||
{
|
||||
}
|
||||
|
||||
~nsXMLHttpRequestXPCOMifier() {
|
||||
if (mXHR) {
|
||||
mXHR->mXPCOMifier = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
NS_FORWARD_NSISTREAMLISTENER(mXHR->)
|
||||
NS_FORWARD_NSIREQUESTOBSERVER(mXHR->)
|
||||
NS_FORWARD_NSICHANNELEVENTSINK(mXHR->)
|
||||
NS_FORWARD_NSIPROGRESSEVENTSINK(mXHR->)
|
||||
NS_FORWARD_NSITIMERCALLBACK(mXHR->)
|
||||
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
|
||||
private:
|
||||
nsRefPtr<nsXMLHttpRequest> mXHR;
|
||||
};
|
||||
|
||||
// helper class to expose a progress DOM Event
|
||||
|
||||
class nsXMLHttpProgressEvent : public nsIDOMProgressEvent,
|
||||
|
@ -44,6 +44,7 @@ MOCHITEST_CHROME_FILES = \
|
||||
test_bug752226-4.xul \
|
||||
test_bug682305.html \
|
||||
test_bug780199.xul \
|
||||
test_bug780529.xul \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
40
content/base/test/chrome/test_bug780529.xul
Normal file
40
content/base/test/chrome/test_bug780529.xul
Normal file
@ -0,0 +1,40 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=780529
|
||||
-->
|
||||
<window title="Mozilla Bug 780529"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
|
||||
<!-- test results are displayed in the html:body -->
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=780529"
|
||||
target="_blank">Mozilla Bug 780529</a>
|
||||
</body>
|
||||
|
||||
<!-- test code goes here -->
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
/** Test for Bug 780529 **/
|
||||
var req = new XMLHttpRequest();
|
||||
req.open("GET", "", true);
|
||||
// Have to call send() to get the XHR hooked up as the notification callbacks
|
||||
req.send();
|
||||
var callbacks = req.channel.notificationCallbacks;
|
||||
var sink = callbacks.getInterface(Components.interfaces.nsIChannelEventSink);
|
||||
ok(sink instanceof Components.interfaces.nsIChannelEventSink,
|
||||
"Should be a channel event sink")
|
||||
ok("asyncOnChannelRedirect" in sink,
|
||||
"Should have the right methods for an event sink");
|
||||
|
||||
is(callbacks.getInterface(Components.interfaces.nsIXMLHttpRequest), req,
|
||||
"Should have the right object");
|
||||
sinkReq = sink.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
|
||||
isnot(sinkReq, callbacks, "Sink should not be the XHR object");
|
||||
is(sinkReq.getInterface(Components.interfaces.nsIXMLHttpRequest), req,
|
||||
"Should have the XHR object now");
|
||||
]]>
|
||||
</script>
|
||||
</window>
|
Loading…
x
Reference in New Issue
Block a user