mirror of
https://github.com/reactos/wine.git
synced 2025-02-17 19:39:00 +00:00
mshtml: Added support for script 'for' and 'event' attributes.
This commit is contained in:
parent
4503edd614
commit
d40b1ae8dc
@ -36,7 +36,7 @@
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
|
||||
|
||||
static HRESULT get_doc_elem_by_id(HTMLDocumentNode *doc, const WCHAR *id, HTMLElement **ret)
|
||||
HRESULT get_doc_elem_by_id(HTMLDocumentNode *doc, const WCHAR *id, HTMLElement **ret)
|
||||
{
|
||||
nsIDOMNodeList *nsnode_list;
|
||||
nsIDOMElement *nselem;
|
||||
|
@ -1443,6 +1443,21 @@ HRESULT detach_event(event_target_t *event_target, HTMLDocument *doc, BSTR name,
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void bind_elem_event(HTMLDocumentNode *doc, HTMLElement *elem, const WCHAR *event, IDispatch *disp)
|
||||
{
|
||||
eventid_t eid;
|
||||
|
||||
TRACE("(%p %p %s %p)\n", doc, elem, debugstr_w(event), disp);
|
||||
|
||||
eid = attr_to_eid(event);
|
||||
if(eid == EVENTID_LAST) {
|
||||
WARN("Unsupported event %s\n", debugstr_w(event));
|
||||
return;
|
||||
}
|
||||
|
||||
set_event_handler_disp(&elem->node.event_target, elem->node.nsnode, doc, eid, disp);
|
||||
}
|
||||
|
||||
void update_cp_events(HTMLInnerWindow *window, event_target_t **event_target_ptr, cp_static_data_t *cp, nsIDOMNode *nsnode)
|
||||
{
|
||||
event_target_t *event_target;
|
||||
|
@ -61,6 +61,7 @@ void update_cp_events(HTMLInnerWindow*,event_target_t**,cp_static_data_t*,nsIDOM
|
||||
HRESULT doc_init_events(HTMLDocumentNode*) DECLSPEC_HIDDEN;
|
||||
void detach_events(HTMLDocumentNode *doc) DECLSPEC_HIDDEN;
|
||||
HRESULT create_event_obj(IHTMLEventObj**) DECLSPEC_HIDDEN;
|
||||
void bind_elem_event(HTMLDocumentNode*,HTMLElement*,const WCHAR*,IDispatch*) DECLSPEC_HIDDEN;
|
||||
|
||||
void init_nsevents(HTMLDocumentNode*) DECLSPEC_HIDDEN;
|
||||
void release_nsevents(HTMLDocumentNode*) DECLSPEC_HIDDEN;
|
||||
|
@ -751,6 +751,7 @@ typedef struct {
|
||||
} HTMLScriptElement;
|
||||
|
||||
HRESULT script_elem_from_nsscript(HTMLDocumentNode*,nsIDOMHTMLScriptElement*,HTMLScriptElement**) DECLSPEC_HIDDEN;
|
||||
void bind_event_scripts(HTMLDocumentNode*) DECLSPEC_HIDDEN;
|
||||
|
||||
HRESULT HTMLCurrentStyle_Create(HTMLElement*,IHTMLCurrentStyle**) DECLSPEC_HIDDEN;
|
||||
|
||||
@ -923,6 +924,7 @@ BOOL find_global_prop(HTMLInnerWindow*,BSTR,DWORD,ScriptHost**,DISPID*) DECLSPEC
|
||||
IDispatch *get_script_disp(ScriptHost*) DECLSPEC_HIDDEN;
|
||||
HRESULT search_window_props(HTMLInnerWindow*,BSTR,DWORD,DISPID*) DECLSPEC_HIDDEN;
|
||||
HRESULT get_frame_by_name(HTMLOuterWindow*,const WCHAR*,BOOL,HTMLOuterWindow**) DECLSPEC_HIDDEN;
|
||||
HRESULT get_doc_elem_by_id(HTMLDocumentNode*,const WCHAR*,HTMLElement**) DECLSPEC_HIDDEN;
|
||||
|
||||
HRESULT wrap_iface(IUnknown*,IUnknown*,IUnknown**) DECLSPEC_HIDDEN;
|
||||
|
||||
|
@ -287,6 +287,7 @@ static nsresult run_end_load(HTMLDocumentNode *This, nsISupports *arg1, nsISuppo
|
||||
parse_complete(This->basedoc.doc_obj);
|
||||
}
|
||||
|
||||
bind_event_scripts(This);
|
||||
set_ready_state(This->basedoc.window, READYSTATE_INTERACTIVE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define COBJMACROS
|
||||
|
||||
@ -32,6 +33,8 @@
|
||||
#include "wine/debug.h"
|
||||
|
||||
#include "mshtml_private.h"
|
||||
#include "pluginhost.h"
|
||||
#include "htmlevent.h"
|
||||
#include "binding.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
|
||||
@ -60,7 +63,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
|
||||
|
||||
#endif
|
||||
|
||||
static const WCHAR documentW[] = {'d','o','c','u','m','e','n','t',0};
|
||||
static const WCHAR windowW[] = {'w','i','n','d','o','w',0};
|
||||
static const WCHAR script_endW[] = {'<','/','S','C','R','I','P','T','>',0};
|
||||
static const WCHAR emptyW[] = {0};
|
||||
|
||||
struct ScriptHost {
|
||||
@ -689,8 +694,6 @@ static void parse_text(ScriptHost *script_host, LPCWSTR text)
|
||||
VARIANT var;
|
||||
HRESULT hres;
|
||||
|
||||
static const WCHAR script_endW[] = {'<','/','S','C','R','I','P','T','>',0};
|
||||
|
||||
TRACE("%s\n", debugstr_w(text));
|
||||
|
||||
VariantInit(&var);
|
||||
@ -889,23 +892,29 @@ static ScriptHost *get_script_host(HTMLInnerWindow *window, const GUID *guid)
|
||||
return create_script_host(window, guid);
|
||||
}
|
||||
|
||||
void doc_insert_script(HTMLInnerWindow *window, HTMLScriptElement *script_elem)
|
||||
static ScriptHost *get_elem_script_host(HTMLInnerWindow *window, HTMLScriptElement *script_elem)
|
||||
{
|
||||
ScriptHost *script_host;
|
||||
GUID guid;
|
||||
|
||||
if(!get_script_guid(window, script_elem->nsscript, &guid)) {
|
||||
WARN("Could not find script GUID\n");
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(IsEqualGUID(&CLSID_JScript, &guid)
|
||||
&& (!window->base.outer_window || window->base.outer_window->scriptmode != SCRIPTMODE_ACTIVESCRIPT)) {
|
||||
TRACE("Ignoring JScript\n");
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
script_host = get_script_host(window, &guid);
|
||||
return get_script_host(window, &guid);
|
||||
}
|
||||
|
||||
void doc_insert_script(HTMLInnerWindow *window, HTMLScriptElement *script_elem)
|
||||
{
|
||||
ScriptHost *script_host;
|
||||
|
||||
script_host = get_elem_script_host(window, script_elem);
|
||||
if(!script_host)
|
||||
return;
|
||||
|
||||
@ -1022,6 +1031,195 @@ IDispatch *get_script_disp(ScriptHost *script_host)
|
||||
return disp;
|
||||
}
|
||||
|
||||
static HTMLElement *find_event_target(HTMLDocumentNode *doc, HTMLScriptElement *script_elem)
|
||||
{
|
||||
const PRUnichar *target_id;
|
||||
nsAString target_id_str;
|
||||
HTMLElement *elem;
|
||||
nsresult nsres;
|
||||
HRESULT hres;
|
||||
|
||||
nsAString_Init(&target_id_str, NULL);
|
||||
nsres = nsIDOMHTMLScriptElement_GetHtmlFor(script_elem->nsscript, &target_id_str);
|
||||
if(NS_FAILED(nsres)) {
|
||||
ERR("GetScriptFor failed: %08x\n", nsres);
|
||||
nsAString_Finish(&target_id_str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nsAString_GetData(&target_id_str, &target_id);
|
||||
if(!*target_id || !strcmpW(target_id, documentW) || !strcmpW(target_id, windowW)) {
|
||||
FIXME("for %s not supported\n", debugstr_w(target_id));
|
||||
elem = NULL;
|
||||
}else {
|
||||
hres = get_doc_elem_by_id(doc, target_id, &elem);
|
||||
if(FAILED(hres))
|
||||
elem = NULL;
|
||||
}
|
||||
nsAString_Finish(&target_id_str);
|
||||
|
||||
return elem;
|
||||
}
|
||||
|
||||
static BOOL parse_event_str(WCHAR *event, const WCHAR **args)
|
||||
{
|
||||
WCHAR *ptr;
|
||||
|
||||
for(ptr = event; isalnumW(*ptr); ptr++);
|
||||
if(!*ptr) {
|
||||
*args = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if(*ptr != '(')
|
||||
return FALSE;
|
||||
|
||||
*ptr++ = 0;
|
||||
*args = ptr;
|
||||
while(isalnumW(*ptr) || isspaceW(*ptr) || *ptr == ',')
|
||||
ptr++;
|
||||
|
||||
if(*ptr++ != ')')
|
||||
return FALSE;
|
||||
*ptr++ = 0;
|
||||
return !*ptr;
|
||||
}
|
||||
|
||||
static IDispatch *parse_event_elem(HTMLDocumentNode *doc, HTMLScriptElement *script_elem, WCHAR **ret_event)
|
||||
{
|
||||
ScriptHost *script_host;
|
||||
WCHAR *event = NULL;
|
||||
const WCHAR *args;
|
||||
nsAString nsstr;
|
||||
IDispatch *disp;
|
||||
nsresult nsres;
|
||||
HRESULT hres;
|
||||
|
||||
if(script_elem->parsed)
|
||||
return NULL;
|
||||
|
||||
script_host = get_elem_script_host(doc->window, script_elem);
|
||||
if(!script_host || !script_host->parse_proc)
|
||||
return NULL;
|
||||
|
||||
nsAString_Init(&nsstr, NULL);
|
||||
nsres = nsIDOMHTMLScriptElement_GetEvent(script_elem->nsscript, &nsstr);
|
||||
if(NS_SUCCEEDED(nsres)) {
|
||||
const PRUnichar *event_val;
|
||||
|
||||
nsAString_GetData(&nsstr, &event_val);
|
||||
event = heap_strdupW(event_val);
|
||||
}
|
||||
nsAString_Finish(&nsstr);
|
||||
if(!event)
|
||||
return NULL;
|
||||
|
||||
if(!parse_event_str(event, &args)) {
|
||||
WARN("parsing %s failed\n", debugstr_w(event));
|
||||
heap_free(event);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nsAString_Init(&nsstr, NULL);
|
||||
nsres = nsIDOMHTMLScriptElement_GetText(script_elem->nsscript, &nsstr);
|
||||
if(NS_SUCCEEDED(nsres)) {
|
||||
const PRUnichar *text;
|
||||
|
||||
nsAString_GetData(&nsstr, &text);
|
||||
hres = IActiveScriptParseProcedure_ParseProcedureText(script_host->parse_proc, text, args,
|
||||
emptyW, NULL, NULL, script_endW, 0, 0,
|
||||
SCRIPTPROC_HOSTMANAGESSOURCE|SCRIPTPROC_IMPLICIT_THIS|SCRIPTPROC_IMPLICIT_PARENTS, &disp);
|
||||
if(FAILED(hres))
|
||||
disp = NULL;
|
||||
}else {
|
||||
ERR("GetText failed: %08x\n", nsres);
|
||||
disp = NULL;
|
||||
}
|
||||
nsAString_Finish(&nsstr);
|
||||
if(!disp) {
|
||||
heap_free(event);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*ret_event = event;
|
||||
return disp;
|
||||
}
|
||||
|
||||
void bind_event_scripts(HTMLDocumentNode *doc)
|
||||
{
|
||||
HTMLPluginContainer *plugin_container;
|
||||
nsIDOMHTMLScriptElement *nsscript;
|
||||
HTMLScriptElement *script_elem;
|
||||
HTMLElement *event_target;
|
||||
nsIDOMNodeList *node_list;
|
||||
nsIDOMNode *script_node;
|
||||
nsAString selector_str;
|
||||
IDispatch *event_disp;
|
||||
PRUint32 length, i;
|
||||
WCHAR *event;
|
||||
nsresult nsres;
|
||||
HRESULT hres;
|
||||
|
||||
static const PRUnichar selectorW[] = {'s','c','r','i','p','t','[','e','v','e','n','t',']',0};
|
||||
|
||||
TRACE("%p\n", doc);
|
||||
|
||||
if(!doc->nsdoc)
|
||||
return;
|
||||
|
||||
nsAString_InitDepend(&selector_str, selectorW);
|
||||
nsres = nsIDOMNodeSelector_QuerySelectorAll(doc->nsnode_selector, &selector_str, &node_list);
|
||||
nsAString_Finish(&selector_str);
|
||||
if(NS_FAILED(nsres)) {
|
||||
ERR("QuerySelectorAll failed: %08x\n", nsres);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!node_list)
|
||||
return;
|
||||
|
||||
nsres = nsIDOMNodeList_GetLength(node_list, &length);
|
||||
assert(nsres == NS_OK);
|
||||
|
||||
for(i=0; i < length; i++) {
|
||||
nsres = nsIDOMNodeList_Item(node_list, i, &script_node);
|
||||
if(NS_FAILED(nsres) || !script_node) {
|
||||
ERR("Item(%d) failed: %08x\n", i, nsres);
|
||||
continue;
|
||||
}
|
||||
|
||||
nsres = nsIDOMNode_QueryInterface(script_node, &IID_nsIDOMHTMLScriptElement, (void**)&nsscript);
|
||||
assert(nsres == NS_OK);
|
||||
nsIDOMNode_Release(script_node);
|
||||
|
||||
hres = script_elem_from_nsscript(doc, nsscript, &script_elem);
|
||||
if(FAILED(hres))
|
||||
continue;
|
||||
|
||||
event_disp = parse_event_elem(doc, script_elem, &event);
|
||||
if(event_disp) {
|
||||
event_target = find_event_target(doc, script_elem);
|
||||
if(event_target) {
|
||||
IHTMLElement_QueryInterface(&event_target->IHTMLElement_iface, &IID_HTMLPluginContainer, (void**)&plugin_container);
|
||||
|
||||
if(plugin_container)
|
||||
FIXME("ActiveX events not supported\n");
|
||||
else
|
||||
bind_elem_event(doc, event_target, event, event_disp);
|
||||
|
||||
IHTMLElement_Release(&event_target->IHTMLElement_iface);
|
||||
}
|
||||
|
||||
heap_free(event);
|
||||
IDispatch_Release(event_disp);
|
||||
}
|
||||
|
||||
IHTMLScriptElement_Release(&script_elem->IHTMLScriptElement_iface);
|
||||
}
|
||||
|
||||
nsIDOMNodeList_Release(node_list);
|
||||
}
|
||||
|
||||
BOOL find_global_prop(HTMLInnerWindow *window, BSTR name, DWORD flags, ScriptHost **ret_host, DISPID *ret_id)
|
||||
{
|
||||
IDispatchEx *dispex;
|
||||
|
Loading…
x
Reference in New Issue
Block a user