mshtml: Use vtbl to get ConnectionPointContainer from event target.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2017-10-18 16:39:22 +02:00 committed by Alexandre Julliard
parent e5c0759c0c
commit 0c35bf7c8e
6 changed files with 59 additions and 48 deletions

View File

@ -5030,6 +5030,15 @@ static void HTMLDocumentNode_bind_event(DispatchEx *dispex, eventid_t eid)
ensure_doc_nsevent_handler(This, eid);
}
static ConnectionPointContainer *HTMLDocumentNode_get_cp_container(DispatchEx *dispex)
{
HTMLDocumentNode *This = impl_from_DispatchEx(dispex);
ConnectionPointContainer *container = This->basedoc.doc_obj
? &This->basedoc.doc_obj->basedoc.cp_container : &This->basedoc.cp_container;
IConnectionPointContainer_AddRef(&container->IConnectionPointContainer_iface);
return container;
}
static const event_target_vtbl_t HTMLDocumentNode_event_target_vtbl = {
{
NULL,
@ -5038,7 +5047,8 @@ static const event_target_vtbl_t HTMLDocumentNode_event_target_vtbl = {
HTMLDocumentNode_get_compat_mode,
NULL
},
HTMLDocumentNode_bind_event
HTMLDocumentNode_bind_event,
HTMLDocumentNode_get_cp_container
};
static const NodeImplVtbl HTMLDocumentFragmentImplVtbl = {
@ -5138,7 +5148,6 @@ HRESULT create_doc_from_nsdoc(nsIDOMHTMLDocument *nsdoc, HTMLDocumentObj *doc_ob
doc_init_events(doc);
doc->node.vtbl = &HTMLDocumentNodeImplVtbl;
doc->node.cp_container = &doc->basedoc.cp_container;
*ret = doc;
return S_OK;
@ -5156,7 +5165,6 @@ static HRESULT create_document_fragment(nsIDOMNode *nsnode, HTMLDocumentNode *do
HTMLDOMNode_Init(doc_node, &doc_frag->node, nsnode, &HTMLDocumentNode_dispex);
doc_frag->node.vtbl = &HTMLDocumentFragmentImplVtbl;
doc_frag->node.cp_container = &doc_frag->basedoc.cp_container;
*ret = doc_frag;
return S_OK;

View File

@ -5347,6 +5347,13 @@ static void HTMLElement_bind_event(DispatchEx *dispex, eventid_t eid)
}
}
static ConnectionPointContainer *HTMLElement_get_cp_container(DispatchEx *dispex)
{
HTMLElement *This = impl_from_DispatchEx(dispex);
IConnectionPointContainer_AddRef(&This->cp_container.IConnectionPointContainer_iface);
return &This->cp_container;
}
void HTMLElement_init_dispex_info(dispex_data_t *info, compat_mode_t mode)
{
static const DISPID elem2_ie11_blacklist[] = {DISPID_IHTMLELEMENT2_DOSCROLL, DISPID_UNKNOWN};
@ -5377,7 +5384,8 @@ static event_target_vtbl_t HTMLElement_event_target_vtbl = {
NULL,
HTMLElement_populate_props
},
HTMLElement_bind_event
HTMLElement_bind_event,
HTMLElement_get_cp_container
};
static dispex_static_data_t HTMLElement_dispex = {
@ -5410,7 +5418,6 @@ void HTMLElement_Init(HTMLElement *This, HTMLDocumentNode *doc, nsIDOMHTMLElemen
This->nselem = nselem;
}
This->node.cp_container = &This->cp_container;
ConnectionPointContainer_Init(&This->cp_container, (IUnknown*)&This->IHTMLElement_iface, This->node.vtbl->cpc_entries);
}

View File

@ -937,11 +937,12 @@ static BOOL is_cp_event(cp_static_data_t *data, DISPID dispid)
return FALSE;
}
void call_event_handlers(HTMLDocumentNode *doc, HTMLEventObj *event_obj, EventTarget *event_target,
ConnectionPointContainer *cp_container, eventid_t eid, IDispatch *this_obj)
void call_event_handlers(HTMLEventObj *event_obj, EventTarget *event_target, eventid_t eid, IDispatch *this_obj)
{
handler_vector_t *handler_vector = get_handler_vector(event_target, eid, FALSE);
const BOOL cancelable = event_info[eid].flags & EVENT_CANCELABLE;
ConnectionPointContainer *cp_container = NULL;
const event_target_vtbl_t *vtbl;
VARIANT v;
HRESULT hres;
@ -1010,51 +1011,46 @@ void call_event_handlers(HTMLDocumentNode *doc, HTMLEventObj *event_obj, EventTa
}
}
/*
* NOTE: CP events may require doc_obj reference, which we don't own. We make sure that
* it's safe to call event handler by checking nsevent_listener, which is NULL for
* detached documents.
*/
if(cp_container && cp_container->forward_container)
cp_container = cp_container->forward_container;
if(cp_container && cp_container->cps && doc->nsevent_listener) {
ConnectionPoint *cp;
unsigned i, j;
if((vtbl = dispex_get_vtbl(&event_target->dispex)) && vtbl->get_cp_container)
cp_container = vtbl->get_cp_container(&event_target->dispex);
if(cp_container) {
if(cp_container->cps) {
ConnectionPoint *cp;
unsigned i, j;
for(j=0; cp_container->cp_entries[j].riid; j++) {
cp = cp_container->cps + j;
if(!cp->sinks_size || !is_cp_event(cp->data, event_info[eid].dispid))
continue;
for(i=0; doc->nsevent_listener && i < cp->sinks_size; i++) {
if(!cp->sinks[i].disp)
for(j=0; cp_container->cp_entries[j].riid; j++) {
cp = cp_container->cps + j;
if(!cp->sinks_size || !is_cp_event(cp->data, event_info[eid].dispid))
continue;
V_VT(&v) = VT_EMPTY;
for(i=0; i < cp->sinks_size; i++) {
if(!cp->sinks[i].disp)
continue;
TRACE("cp %s [%u] >>>\n", debugstr_w(event_info[eid].name), i);
hres = call_cp_func(cp->sinks[i].disp, event_info[eid].dispid,
cp->data->pass_event_arg ? event_obj : NULL, &v);
if(hres == S_OK) {
TRACE("cp %s [%u] <<<\n", debugstr_w(event_info[eid].name), i);
V_VT(&v) = VT_EMPTY;
if(cancelable) {
if(V_VT(&v) == VT_BOOL) {
if(!V_BOOL(&v))
event_obj->prevent_default = TRUE;
}else if(V_VT(&v) != VT_EMPTY) {
FIXME("unhandled result %s\n", debugstr_variant(&v));
TRACE("cp %s [%u] >>>\n", debugstr_w(event_info[eid].name), i);
hres = call_cp_func(cp->sinks[i].disp, event_info[eid].dispid,
cp->data->pass_event_arg ? event_obj : NULL, &v);
if(hres == S_OK) {
TRACE("cp %s [%u] <<<\n", debugstr_w(event_info[eid].name), i);
if(cancelable) {
if(V_VT(&v) == VT_BOOL) {
if(!V_BOOL(&v))
event_obj->prevent_default = TRUE;
}else if(V_VT(&v) != VT_EMPTY) {
FIXME("unhandled result %s\n", debugstr_variant(&v));
}
}
VariantClear(&v);
}else {
WARN("cp %s [%u] <<< %08x\n", debugstr_w(event_info[eid].name), i, hres);
}
VariantClear(&v);
}else {
WARN("cp %s [%u] <<< %08x\n", debugstr_w(event_info[eid].name), i, hres);
}
}
if(!doc->nsevent_listener)
break;
}
IConnectionPointContainer_Release(&cp_container->IConnectionPointContainer_iface);
}
}
@ -1094,7 +1090,7 @@ static void fire_event_obj(HTMLDocumentNode *doc, eventid_t eid, HTMLEventObj *e
do {
hres = get_node(doc, nsnode, FALSE, &node);
if(SUCCEEDED(hres) && node) {
call_event_handlers(doc, event_obj, &node->event_target, node->cp_container, eid,
call_event_handlers(event_obj, &node->event_target, eid,
script_this ? script_this : (IDispatch*)&node->IHTMLDOMNode_iface);
node_release(node);
}
@ -1116,14 +1112,14 @@ static void fire_event_obj(HTMLDocumentNode *doc, eventid_t eid, HTMLEventObj *e
/* fallthrough */
case DOCUMENT_NODE:
call_event_handlers(doc, event_obj, &doc->node.event_target, &doc->basedoc.cp_container, eid,
call_event_handlers(event_obj, &doc->node.event_target, eid,
script_this ? script_this : (IDispatch*)&doc->basedoc.IHTMLDocument2_iface);
if(!(event_info[eid].flags & EVENT_BUBBLE) || (event_obj && event_obj->cancel_bubble))
break;
/* fallthrough */
default: /* window object */
call_event_handlers(doc, event_obj, &doc->window->event_target, NULL, eid,
call_event_handlers(event_obj, &doc->window->event_target, eid,
script_this ? script_this : (IDispatch*)&doc->window->base.IHTMLWindow2_iface);
}

View File

@ -72,7 +72,7 @@ void bind_target_event(HTMLDocumentNode*,EventTarget*,const WCHAR*,IDispatch*) D
HRESULT ensure_doc_nsevent_handler(HTMLDocumentNode*,eventid_t) DECLSPEC_HIDDEN;
typedef struct HTMLEventObj HTMLEventObj;
void call_event_handlers(HTMLDocumentNode*,HTMLEventObj*,EventTarget*,ConnectionPointContainer*,eventid_t,IDispatch*);
void call_event_handlers(HTMLEventObj*,EventTarget*,eventid_t,IDispatch*);
void init_nsevents(HTMLDocumentNode*) DECLSPEC_HIDDEN;
void release_nsevents(HTMLDocumentNode*) DECLSPEC_HIDDEN;
@ -83,6 +83,7 @@ void detach_nsevent(HTMLDocumentNode*,const WCHAR*) DECLSPEC_HIDDEN;
typedef struct {
dispex_static_data_vtbl_t dispex_vtbl;
void (*bind_event)(DispatchEx*,eventid_t);
ConnectionPointContainer *(*get_cp_container)(DispatchEx*);
} event_target_vtbl_t;
static inline EventTarget *get_node_event_prop_target(HTMLDOMNode *node, eventid_t eid)

View File

@ -736,7 +736,6 @@ struct HTMLDOMNode {
nsIDOMNode *nsnode;
HTMLDocumentNode *doc;
ConnectionPointContainer *cp_container;
};
static inline void node_addref(HTMLDOMNode *node)

View File

@ -190,7 +190,7 @@ static nsresult NSAPI XMLHttpReqEventListener_HandleEvent(nsIDOMEventListener *i
if(!This->xhr)
return NS_OK;
call_event_handlers(NULL, NULL, &This->xhr->event_target, NULL, EVENTID_READYSTATECHANGE,
call_event_handlers(NULL, &This->xhr->event_target, EVENTID_READYSTATECHANGE,
(IDispatch*)&This->xhr->IHTMLXMLHttpRequest_iface);
return NS_OK;
}