mshtml: Support cycle collection for nsChannel.

This is traversed from the Gecko document, and should be part of the graph
(it refers to gecko objects that participate in it, and which are part of
a cycle).

Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
This commit is contained in:
Gabriel Ivăncescu 2023-04-25 20:29:25 +03:00 committed by Alexandre Julliard
parent 917ec2db66
commit 668d8afd74
2 changed files with 101 additions and 26 deletions

View file

@ -37,7 +37,7 @@ typedef struct {
nsIHttpChannelInternal nsIHttpChannelInternal_iface;
nsICacheInfoChannel nsICacheInfoChannel_iface;
LONG ref;
nsCycleCollectingAutoRefCnt ccref;
nsWineURI *uri;
nsIInputStream *post_data_stream;

View file

@ -45,6 +45,7 @@ static const IID NS_IOSERVICE_CID =
static const IID IID_nsWineURI =
{0x5088272e, 0x900b, 0x11da, {0xc6,0x87, 0x00,0x0f,0xea,0x57,0xf2,0x1a}};
static ExternalCycleCollectionParticipant nschannel_ccp;
static nsIIOService *nsio = NULL;
static const char *request_method_strings[] = {"GET", "PUT", "POST"};
@ -540,6 +541,14 @@ static nsresult NSAPI nsChannel_QueryInterface(nsIHttpChannel *iface, nsIIDRef r
}else if(IsEqualGUID(&IID_nsICacheInfoChannel, riid)) {
TRACE("(%p)->(IID_nsICacheInfoChannel %p)\n", This, result);
*result = is_http_channel(This) ? &This->nsICacheInfoChannel_iface : NULL;
}else if(IsEqualGUID(&IID_nsXPCOMCycleCollectionParticipant, riid)) {
TRACE("(%p)->(IID_nsXPCOMCycleCollectionParticipant %p)\n", This, result);
*result = &nschannel_ccp;
return S_OK;
}else if(IsEqualGUID(&IID_nsCycleCollectionISupports, riid)) {
TRACE("(%p)->(IID_nsCycleCollectionISupports %p)\n", This, result);
*result = &This->nsIHttpChannel_iface;
return S_OK;
}else {
TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result);
*result = NULL;
@ -556,7 +565,7 @@ static nsresult NSAPI nsChannel_QueryInterface(nsIHttpChannel *iface, nsIIDRef r
static nsrefcnt NSAPI nsChannel_AddRef(nsIHttpChannel *iface)
{
nsChannel *This = impl_from_nsIHttpChannel(iface);
nsrefcnt ref = InterlockedIncrement(&This->ref);
nsrefcnt ref = ccref_incr(&This->ccref, (nsISupports*)&This->nsIHttpChannel_iface);
TRACE("(%p) ref=%ld\n", This, ref);
@ -566,30 +575,9 @@ static nsrefcnt NSAPI nsChannel_AddRef(nsIHttpChannel *iface)
static nsrefcnt NSAPI nsChannel_Release(nsIHttpChannel *iface)
{
nsChannel *This = impl_from_nsIHttpChannel(iface);
LONG ref = InterlockedDecrement(&This->ref);
nsrefcnt ref = ccref_decr(&This->ccref, (nsISupports*)&This->nsIHttpChannel_iface, &nschannel_ccp);
if(!ref) {
nsIFileURL_Release(&This->uri->nsIFileURL_iface);
if(This->owner)
nsISupports_Release(This->owner);
if(This->post_data_stream)
nsIInputStream_Release(This->post_data_stream);
if(This->load_group)
nsILoadGroup_Release(This->load_group);
if(This->notif_callback)
nsIInterfaceRequestor_Release(This->notif_callback);
if(This->original_uri)
nsIURI_Release(This->original_uri);
if(This->referrer)
nsIURI_Release(This->referrer);
free_http_headers(&This->response_headers);
free_http_headers(&This->request_headers);
free(This->content_type);
free(This->charset);
free(This);
}
TRACE("(%p) ref=%ld\n", This, ref);
return ref;
}
@ -2263,6 +2251,86 @@ static const nsICacheInfoChannelVtbl nsCacheInfoChannelVtbl = {
nsCacheInfoChannel_SetAllowStaleCacheContent
};
static nsresult NSAPI nsChannel_traverse(void *ccp, void *p, nsCycleCollectionTraversalCallback *cb)
{
nsChannel *This = impl_from_nsIHttpChannel(p);
TRACE("%p\n", This);
describe_cc_node(&This->ccref, "nsChannel", cb);
if(This->owner)
note_cc_edge(This->owner, "owner", cb);
if(This->post_data_stream)
note_cc_edge((nsISupports*)This->post_data_stream, "post_data_stream", cb);
if(This->load_group)
note_cc_edge((nsISupports*)This->load_group, "load_group", cb);
if(This->notif_callback)
note_cc_edge((nsISupports*)This->notif_callback, "notif_callback", cb);
if(This->original_uri)
note_cc_edge((nsISupports*)This->original_uri, "original_uri", cb);
if(This->referrer)
note_cc_edge((nsISupports*)This->referrer, "referrer", cb);
return NS_OK;
}
static nsresult NSAPI nsChannel_unlink(void *p)
{
nsChannel *This = impl_from_nsIHttpChannel(p);
TRACE("%p\n", This);
if(This->owner) {
nsISupports *owner = This->owner;
This->owner = NULL;
nsISupports_Release(owner);
}
if(This->post_data_stream) {
nsIInputStream *post_data_stream = This->post_data_stream;
This->post_data_stream = NULL;
nsIInputStream_Release(post_data_stream);
}
if(This->load_group) {
nsILoadGroup *load_group = This->load_group;
This->load_group = NULL;
nsILoadGroup_Release(load_group);
}
if(This->notif_callback) {
nsIInterfaceRequestor *notif_callback = This->notif_callback;
This->notif_callback = NULL;
nsIInterfaceRequestor_Release(notif_callback);
}
if(This->original_uri) {
nsIURI *original_uri = This->original_uri;
This->original_uri = NULL;
nsIURI_Release(original_uri);
}
if(This->referrer) {
nsIURI *referrer = This->referrer;
This->referrer = NULL;
nsIURI_Release(referrer);
}
return NS_OK;
}
static void NSAPI nsChannel_delete_cycle_collectable(void *p)
{
nsChannel *This = impl_from_nsIHttpChannel(p);
nsChannel_unlink(p);
TRACE("(%p)\n", This);
nsIFileURL_Release(&This->uri->nsIFileURL_iface);
free_http_headers(&This->response_headers);
free_http_headers(&This->request_headers);
free(This->content_type);
free(This->charset);
free(This);
}
static void invalidate_uri(nsWineURI *This)
{
if(This->uri) {
@ -3517,10 +3585,10 @@ static nsresult create_nschannel(nsWineURI *uri, nsChannel **ret)
channel->nsIUploadChannel_iface.lpVtbl = &nsUploadChannelVtbl;
channel->nsIHttpChannelInternal_iface.lpVtbl = &nsHttpChannelInternalVtbl;
channel->nsICacheInfoChannel_iface.lpVtbl = &nsCacheInfoChannelVtbl;
channel->ref = 1;
channel->request_method = METHOD_GET;
list_init(&channel->response_headers);
list_init(&channel->request_headers);
ccref_init(&channel->ccref, 1);
nsIFileURL_AddRef(&uri->nsIFileURL_iface);
channel->uri = uri;
@ -3990,6 +4058,11 @@ static nsIIOServiceHook nsIOServiceHook = { &nsIOServiceHookVtbl };
void init_nsio(nsIComponentManager *component_manager)
{
static const CCObjCallback nschannel_ccp_callback = {
nsChannel_traverse,
nsChannel_unlink,
nsChannel_delete_cycle_collectable
};
nsIFactory *old_factory = NULL;
nsresult nsres;
@ -4009,6 +4082,8 @@ void init_nsio(nsIComponentManager *component_manager)
nsres = nsIIOService_SetHook(nsio, &nsIOServiceHook);
assert(nsres == NS_OK);
ccp_init(&nschannel_ccp, &nschannel_ccp_callback);
}
void release_nsio(void)