mshtml: Added noscript tag handling tests.
[wine] / dlls / mshtml / script.c
1 /*
2  * Copyright 2008 Jacek Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include "config.h"
20
21 #include <stdarg.h>
22 #include <assert.h>
23
24 #define COBJMACROS
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "ole2.h"
30 #include "activscp.h"
31 #include "activdbg.h"
32
33 #include "wine/debug.h"
34
35 #include "mshtml_private.h"
36 #include "pluginhost.h"
37 #include "htmlevent.h"
38 #include "binding.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
41
42 #ifdef _WIN64
43
44 #define CTXARG_T DWORDLONG
45 #define IActiveScriptSiteDebugVtbl IActiveScriptSiteDebug64Vtbl
46
47 #define IActiveScriptParse_Release IActiveScriptParse64_Release
48 #define IActiveScriptParse_InitNew IActiveScriptParse64_InitNew
49 #define IActiveScriptParse_ParseScriptText IActiveScriptParse64_ParseScriptText
50 #define IActiveScriptParseProcedure2_Release IActiveScriptParseProcedure2_64_Release
51 #define IActiveScriptParseProcedure2_ParseProcedureText IActiveScriptParseProcedure2_64_ParseProcedureText
52
53 #else
54
55 #define CTXARG_T DWORD
56 #define IActiveScriptSiteDebugVtbl IActiveScriptSiteDebug32Vtbl
57
58 #define IActiveScriptParse_Release IActiveScriptParse32_Release
59 #define IActiveScriptParse_InitNew IActiveScriptParse32_InitNew
60 #define IActiveScriptParse_ParseScriptText IActiveScriptParse32_ParseScriptText
61 #define IActiveScriptParseProcedure2_Release IActiveScriptParseProcedure2_32_Release
62 #define IActiveScriptParseProcedure2_ParseProcedureText IActiveScriptParseProcedure2_32_ParseProcedureText
63
64 #endif
65
66 static const WCHAR documentW[] = {'d','o','c','u','m','e','n','t',0};
67 static const WCHAR windowW[] = {'w','i','n','d','o','w',0};
68 static const WCHAR script_endW[] = {'<','/','S','C','R','I','P','T','>',0};
69 static const WCHAR emptyW[] = {0};
70
71 struct ScriptHost {
72     IActiveScriptSite              IActiveScriptSite_iface;
73     IActiveScriptSiteInterruptPoll IActiveScriptSiteInterruptPoll_iface;
74     IActiveScriptSiteWindow        IActiveScriptSiteWindow_iface;
75     IActiveScriptSiteUIControl     IActiveScriptSiteUIControl_iface;
76     IActiveScriptSiteDebug         IActiveScriptSiteDebug_iface;
77     IServiceProvider               IServiceProvider_iface;
78
79     LONG ref;
80
81     IActiveScript *script;
82     IActiveScriptParse *parse;
83     IActiveScriptParseProcedure2 *parse_proc;
84
85     SCRIPTSTATE script_state;
86
87     HTMLInnerWindow *window;
88
89     GUID guid;
90     struct list entry;
91 };
92
93 static void set_script_prop(ScriptHost *script_host, DWORD property, VARIANT *val)
94 {
95     IActiveScriptProperty *script_prop;
96     HRESULT hres;
97
98     hres = IActiveScript_QueryInterface(script_host->script, &IID_IActiveScriptProperty,
99             (void**)&script_prop);
100     if(FAILED(hres)) {
101         WARN("Could not get IActiveScriptProperty iface: %08x\n", hres);
102         return;
103     }
104
105     hres = IActiveScriptProperty_SetProperty(script_prop, property, NULL, val);
106     IActiveScriptProperty_Release(script_prop);
107     if(FAILED(hres))
108         WARN("SetProperty(%x) failed: %08x\n", property, hres);
109 }
110
111 static BOOL init_script_engine(ScriptHost *script_host)
112 {
113     IObjectSafety *safety;
114     SCRIPTSTATE state;
115     DWORD supported_opts=0, enabled_opts=0;
116     VARIANT var;
117     HRESULT hres;
118
119     hres = IActiveScript_QueryInterface(script_host->script, &IID_IActiveScriptParse, (void**)&script_host->parse);
120     if(FAILED(hres)) {
121         WARN("Could not get IActiveScriptHost: %08x\n", hres);
122         return FALSE;
123     }
124
125     hres = IActiveScript_QueryInterface(script_host->script, &IID_IObjectSafety, (void**)&safety);
126     if(FAILED(hres)) {
127         FIXME("Could not get IObjectSafety: %08x\n", hres);
128         return FALSE;
129     }
130
131     hres = IObjectSafety_GetInterfaceSafetyOptions(safety, &IID_IActiveScriptParse, &supported_opts, &enabled_opts);
132     if(FAILED(hres)) {
133         FIXME("GetInterfaceSafetyOptions failed: %08x\n", hres);
134     }else if(!(supported_opts & INTERFACE_USES_DISPEX)) {
135         FIXME("INTERFACE_USES_DISPEX is not supported\n");
136     }else {
137         hres = IObjectSafety_SetInterfaceSafetyOptions(safety, &IID_IActiveScriptParse,
138                 INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER,
139                 INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER);
140         if(FAILED(hres))
141             FIXME("SetInterfaceSafetyOptions failed: %08x\n", hres);
142     }
143
144     IObjectSafety_Release(safety);
145     if(FAILED(hres))
146         return FALSE;
147
148     V_VT(&var) = VT_I4;
149     V_I4(&var) = 1;
150     set_script_prop(script_host, SCRIPTPROP_INVOKEVERSIONING, &var);
151
152     V_VT(&var) = VT_BOOL;
153     V_BOOL(&var) = VARIANT_TRUE;
154     set_script_prop(script_host, SCRIPTPROP_HACK_TRIDENTEVENTSINK, &var);
155
156     hres = IActiveScriptParse_InitNew(script_host->parse);
157     if(FAILED(hres)) {
158         WARN("InitNew failed: %08x\n", hres);
159         return FALSE;
160     }
161
162     hres = IActiveScript_SetScriptSite(script_host->script, &script_host->IActiveScriptSite_iface);
163     if(FAILED(hres)) {
164         WARN("SetScriptSite failed: %08x\n", hres);
165         IActiveScript_Close(script_host->script);
166         return FALSE;
167     }
168
169     hres = IActiveScript_GetScriptState(script_host->script, &state);
170     if(FAILED(hres))
171         WARN("GetScriptState failed: %08x\n", hres);
172     else if(state != SCRIPTSTATE_INITIALIZED)
173         FIXME("state = %x\n", state);
174
175     hres = IActiveScript_SetScriptState(script_host->script, SCRIPTSTATE_STARTED);
176     if(FAILED(hres)) {
177         WARN("Starting script failed: %08x\n", hres);
178         return FALSE;
179     }
180
181     hres = IActiveScript_AddNamedItem(script_host->script, windowW,
182             SCRIPTITEM_ISVISIBLE|SCRIPTITEM_ISSOURCE|SCRIPTITEM_GLOBALMEMBERS);
183     if(SUCCEEDED(hres)) {
184         V_VT(&var) = VT_BOOL;
185         V_BOOL(&var) = VARIANT_TRUE;
186         set_script_prop(script_host, SCRIPTPROP_ABBREVIATE_GLOBALNAME_RESOLUTION, &var);
187     }else {
188        WARN("AddNamedItem failed: %08x\n", hres);
189     }
190
191     hres = IActiveScript_QueryInterface(script_host->script, &IID_IActiveScriptParseProcedure2,
192                                         (void**)&script_host->parse_proc);
193     if(FAILED(hres)) {
194         /* FIXME: QI for IActiveScriptParseProcedure */
195         WARN("Could not get IActiveScriptParseProcedure iface: %08x\n", hres);
196     }
197
198     return TRUE;
199 }
200
201 static void release_script_engine(ScriptHost *This)
202 {
203     if(!This->script)
204         return;
205
206     switch(This->script_state) {
207     case SCRIPTSTATE_CONNECTED:
208         IActiveScript_SetScriptState(This->script, SCRIPTSTATE_DISCONNECTED);
209
210     case SCRIPTSTATE_STARTED:
211     case SCRIPTSTATE_DISCONNECTED:
212     case SCRIPTSTATE_INITIALIZED:
213         IActiveScript_Close(This->script);
214
215     default:
216         if(This->parse_proc) {
217             IActiveScriptParseProcedure2_Release(This->parse_proc);
218             This->parse_proc = NULL;
219         }
220
221         if(This->parse) {
222             IActiveScriptParse_Release(This->parse);
223             This->parse = NULL;
224         }
225     }
226
227     IActiveScript_Release(This->script);
228     This->script = NULL;
229     This->script_state = SCRIPTSTATE_UNINITIALIZED;
230 }
231
232 void connect_scripts(HTMLInnerWindow *window)
233 {
234     ScriptHost *iter;
235
236     LIST_FOR_EACH_ENTRY(iter, &window->script_hosts, ScriptHost, entry) {
237         if(iter->script_state == SCRIPTSTATE_STARTED)
238             IActiveScript_SetScriptState(iter->script, SCRIPTSTATE_CONNECTED);
239     }
240 }
241
242 static inline ScriptHost *impl_from_IActiveScriptSite(IActiveScriptSite *iface)
243 {
244     return CONTAINING_RECORD(iface, ScriptHost, IActiveScriptSite_iface);
245 }
246
247 static HRESULT WINAPI ActiveScriptSite_QueryInterface(IActiveScriptSite *iface, REFIID riid, void **ppv)
248 {
249     ScriptHost *This = impl_from_IActiveScriptSite(iface);
250
251     *ppv = NULL;
252
253     if(IsEqualGUID(&IID_IUnknown, riid)) {
254         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
255         *ppv = &This->IActiveScriptSite_iface;
256     }else if(IsEqualGUID(&IID_IActiveScriptSite, riid)) {
257         TRACE("(%p)->(IID_IActiveScriptSite %p)\n", This, ppv);
258         *ppv = &This->IActiveScriptSite_iface;
259     }else if(IsEqualGUID(&IID_IActiveScriptSiteInterruptPoll, riid)) {
260         TRACE("(%p)->(IID_IActiveScriptSiteInterruprtPoll %p)\n", This, ppv);
261         *ppv = &This->IActiveScriptSiteInterruptPoll_iface;
262     }else if(IsEqualGUID(&IID_IActiveScriptSiteWindow, riid)) {
263         TRACE("(%p)->(IID_IActiveScriptSiteWindow %p)\n", This, ppv);
264         *ppv = &This->IActiveScriptSiteWindow_iface;
265     }else if(IsEqualGUID(&IID_IActiveScriptSiteUIControl, riid)) {
266         TRACE("(%p)->(IID_IActiveScriptSiteUIControl %p)\n", This, ppv);
267         *ppv = &This->IActiveScriptSiteUIControl_iface;
268     }else if(IsEqualGUID(&IID_IActiveScriptSiteDebug, riid)) {
269         TRACE("(%p)->(IID_IActiveScriptSiteDebug %p)\n", This, ppv);
270         *ppv = &This->IActiveScriptSiteDebug_iface;
271     }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
272         TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
273         *ppv = &This->IServiceProvider_iface;
274     }else if(IsEqualGUID(&IID_ICanHandleException, riid)) {
275         TRACE("(%p)->(IID_ICanHandleException not supported %p)\n", This, ppv);
276         return E_NOINTERFACE;
277     }else {
278         FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
279         return E_NOINTERFACE;
280     }
281
282     IUnknown_AddRef((IUnknown*)*ppv);
283     return S_OK;
284 }
285
286 static ULONG WINAPI ActiveScriptSite_AddRef(IActiveScriptSite *iface)
287 {
288     ScriptHost *This = impl_from_IActiveScriptSite(iface);
289     LONG ref = InterlockedIncrement(&This->ref);
290
291     TRACE("(%p) ref=%d\n", This, ref);
292
293     return ref;
294 }
295
296 static ULONG WINAPI ActiveScriptSite_Release(IActiveScriptSite *iface)
297 {
298     ScriptHost *This = impl_from_IActiveScriptSite(iface);
299     LONG ref = InterlockedDecrement(&This->ref);
300
301     TRACE("(%p) ref=%d\n", This, ref);
302
303     if(!ref) {
304         release_script_engine(This);
305         if(This->window)
306             list_remove(&This->entry);
307         heap_free(This);
308     }
309
310     return ref;
311 }
312
313 static HRESULT WINAPI ActiveScriptSite_GetLCID(IActiveScriptSite *iface, LCID *plcid)
314 {
315     ScriptHost *This = impl_from_IActiveScriptSite(iface);
316
317     TRACE("(%p)->(%p)\n", This, plcid);
318
319     *plcid = GetUserDefaultLCID();
320     return S_OK;
321 }
322
323 static HRESULT WINAPI ActiveScriptSite_GetItemInfo(IActiveScriptSite *iface, LPCOLESTR pstrName,
324         DWORD dwReturnMask, IUnknown **ppiunkItem, ITypeInfo **ppti)
325 {
326     ScriptHost *This = impl_from_IActiveScriptSite(iface);
327
328     TRACE("(%p)->(%s %x %p %p)\n", This, debugstr_w(pstrName), dwReturnMask, ppiunkItem, ppti);
329
330     if(dwReturnMask != SCRIPTINFO_IUNKNOWN) {
331         FIXME("Unsupported mask %x\n", dwReturnMask);
332         return E_NOTIMPL;
333     }
334
335     *ppiunkItem = NULL;
336
337     if(strcmpW(pstrName, windowW))
338         return DISP_E_MEMBERNOTFOUND;
339
340     if(!This->window)
341         return E_FAIL;
342
343     /* FIXME: Return proxy object */
344     *ppiunkItem = (IUnknown*)&This->window->base.IHTMLWindow2_iface;
345     IUnknown_AddRef(*ppiunkItem);
346
347     return S_OK;
348 }
349
350 static HRESULT WINAPI ActiveScriptSite_GetDocVersionString(IActiveScriptSite *iface, BSTR *pbstrVersion)
351 {
352     ScriptHost *This = impl_from_IActiveScriptSite(iface);
353     FIXME("(%p)->(%p)\n", This, pbstrVersion);
354     return E_NOTIMPL;
355 }
356
357 static HRESULT WINAPI ActiveScriptSite_OnScriptTerminate(IActiveScriptSite *iface,
358         const VARIANT *pvarResult, const EXCEPINFO *pexcepinfo)
359 {
360     ScriptHost *This = impl_from_IActiveScriptSite(iface);
361     FIXME("(%p)->(%p %p)\n", This, pvarResult, pexcepinfo);
362     return E_NOTIMPL;
363 }
364
365 static HRESULT WINAPI ActiveScriptSite_OnStateChange(IActiveScriptSite *iface, SCRIPTSTATE ssScriptState)
366 {
367     ScriptHost *This = impl_from_IActiveScriptSite(iface);
368
369     TRACE("(%p)->(%x)\n", This, ssScriptState);
370
371     This->script_state = ssScriptState;
372     return S_OK;
373 }
374
375 static HRESULT WINAPI ActiveScriptSite_OnScriptError(IActiveScriptSite *iface, IActiveScriptError *pscripterror)
376 {
377     ScriptHost *This = impl_from_IActiveScriptSite(iface);
378     FIXME("(%p)->(%p)\n", This, pscripterror);
379     return E_NOTIMPL;
380 }
381
382 static HRESULT WINAPI ActiveScriptSite_OnEnterScript(IActiveScriptSite *iface)
383 {
384     ScriptHost *This = impl_from_IActiveScriptSite(iface);
385
386     TRACE("(%p)->()\n", This);
387
388     return S_OK;
389 }
390
391 static HRESULT WINAPI ActiveScriptSite_OnLeaveScript(IActiveScriptSite *iface)
392 {
393     ScriptHost *This = impl_from_IActiveScriptSite(iface);
394
395     TRACE("(%p)->()\n", This);
396
397     return S_OK;
398 }
399
400 static const IActiveScriptSiteVtbl ActiveScriptSiteVtbl = {
401     ActiveScriptSite_QueryInterface,
402     ActiveScriptSite_AddRef,
403     ActiveScriptSite_Release,
404     ActiveScriptSite_GetLCID,
405     ActiveScriptSite_GetItemInfo,
406     ActiveScriptSite_GetDocVersionString,
407     ActiveScriptSite_OnScriptTerminate,
408     ActiveScriptSite_OnStateChange,
409     ActiveScriptSite_OnScriptError,
410     ActiveScriptSite_OnEnterScript,
411     ActiveScriptSite_OnLeaveScript
412 };
413
414 static inline ScriptHost *impl_from_IActiveScriptSiteInterruptPoll(IActiveScriptSiteInterruptPoll *iface)
415 {
416     return CONTAINING_RECORD(iface, ScriptHost, IActiveScriptSiteInterruptPoll_iface);
417 }
418
419 static HRESULT WINAPI ActiveScriptSiteInterruptPoll_QueryInterface(IActiveScriptSiteInterruptPoll *iface,
420         REFIID riid, void **ppv)
421 {
422     ScriptHost *This = impl_from_IActiveScriptSiteInterruptPoll(iface);
423     return IActiveScriptSite_QueryInterface(&This->IActiveScriptSite_iface, riid, ppv);
424 }
425
426 static ULONG WINAPI ActiveScriptSiteInterruptPoll_AddRef(IActiveScriptSiteInterruptPoll *iface)
427 {
428     ScriptHost *This = impl_from_IActiveScriptSiteInterruptPoll(iface);
429     return IActiveScriptSite_AddRef(&This->IActiveScriptSite_iface);
430 }
431
432 static ULONG WINAPI ActiveScriptSiteInterruptPoll_Release(IActiveScriptSiteInterruptPoll *iface)
433 {
434     ScriptHost *This = impl_from_IActiveScriptSiteInterruptPoll(iface);
435     return IActiveScriptSite_Release(&This->IActiveScriptSite_iface);
436 }
437
438 static HRESULT WINAPI ActiveScriptSiteInterruptPoll_QueryContinue(IActiveScriptSiteInterruptPoll *iface)
439 {
440     ScriptHost *This = impl_from_IActiveScriptSiteInterruptPoll(iface);
441
442     TRACE("(%p)\n", This);
443
444     return S_OK;
445 }
446
447 static const IActiveScriptSiteInterruptPollVtbl ActiveScriptSiteInterruptPollVtbl = {
448     ActiveScriptSiteInterruptPoll_QueryInterface,
449     ActiveScriptSiteInterruptPoll_AddRef,
450     ActiveScriptSiteInterruptPoll_Release,
451     ActiveScriptSiteInterruptPoll_QueryContinue
452 };
453
454 static inline ScriptHost *impl_from_IActiveScriptSiteWindow(IActiveScriptSiteWindow *iface)
455 {
456     return CONTAINING_RECORD(iface, ScriptHost, IActiveScriptSiteWindow_iface);
457 }
458
459 static HRESULT WINAPI ActiveScriptSiteWindow_QueryInterface(IActiveScriptSiteWindow *iface,
460         REFIID riid, void **ppv)
461 {
462     ScriptHost *This = impl_from_IActiveScriptSiteWindow(iface);
463     return IActiveScriptSite_QueryInterface(&This->IActiveScriptSite_iface, riid, ppv);
464 }
465
466 static ULONG WINAPI ActiveScriptSiteWindow_AddRef(IActiveScriptSiteWindow *iface)
467 {
468     ScriptHost *This = impl_from_IActiveScriptSiteWindow(iface);
469     return IActiveScriptSite_AddRef(&This->IActiveScriptSite_iface);
470 }
471
472 static ULONG WINAPI ActiveScriptSiteWindow_Release(IActiveScriptSiteWindow *iface)
473 {
474     ScriptHost *This = impl_from_IActiveScriptSiteWindow(iface);
475     return IActiveScriptSite_Release(&This->IActiveScriptSite_iface);
476 }
477
478 static HRESULT WINAPI ActiveScriptSiteWindow_GetWindow(IActiveScriptSiteWindow *iface, HWND *phwnd)
479 {
480     ScriptHost *This = impl_from_IActiveScriptSiteWindow(iface);
481
482     TRACE("(%p)->(%p)\n", This, phwnd);
483
484     if(!This->window || !This->window->base.outer_window || !This->window->base.outer_window->doc_obj)
485         return E_UNEXPECTED;
486
487     *phwnd = This->window->base.outer_window->doc_obj->hwnd;
488     return S_OK;
489 }
490
491 static HRESULT WINAPI ActiveScriptSiteWindow_EnableModeless(IActiveScriptSiteWindow *iface, BOOL fEnable)
492 {
493     ScriptHost *This = impl_from_IActiveScriptSiteWindow(iface);
494     FIXME("(%p)->(%x)\n", This, fEnable);
495     return S_OK;
496 }
497
498 static const IActiveScriptSiteWindowVtbl ActiveScriptSiteWindowVtbl = {
499     ActiveScriptSiteWindow_QueryInterface,
500     ActiveScriptSiteWindow_AddRef,
501     ActiveScriptSiteWindow_Release,
502     ActiveScriptSiteWindow_GetWindow,
503     ActiveScriptSiteWindow_EnableModeless
504 };
505
506 static inline ScriptHost *impl_from_IActiveScriptSiteUIControl(IActiveScriptSiteUIControl *iface)
507 {
508     return CONTAINING_RECORD(iface, ScriptHost, IActiveScriptSiteUIControl_iface);
509 }
510
511 static HRESULT WINAPI ActiveScriptSiteUIControl_QueryInterface(IActiveScriptSiteUIControl *iface, REFIID riid, void **ppv)
512 {
513     ScriptHost *This = impl_from_IActiveScriptSiteUIControl(iface);
514     return IActiveScriptSite_QueryInterface(&This->IActiveScriptSite_iface, riid, ppv);
515 }
516
517 static ULONG WINAPI ActiveScriptSiteUIControl_AddRef(IActiveScriptSiteUIControl *iface)
518 {
519     ScriptHost *This = impl_from_IActiveScriptSiteUIControl(iface);
520     return IActiveScriptSite_AddRef(&This->IActiveScriptSite_iface);
521 }
522
523 static ULONG WINAPI ActiveScriptSiteUIControl_Release(IActiveScriptSiteUIControl *iface)
524 {
525     ScriptHost *This = impl_from_IActiveScriptSiteUIControl(iface);
526     return IActiveScriptSite_Release(&This->IActiveScriptSite_iface);
527 }
528
529 static HRESULT WINAPI ActiveScriptSiteUIControl_GetUIBehavior(IActiveScriptSiteUIControl *iface, SCRIPTUICITEM UicItem,
530         SCRIPTUICHANDLING *pUicHandling)
531 {
532     ScriptHost *This = impl_from_IActiveScriptSiteUIControl(iface);
533
534     WARN("(%p)->(%d %p) semi-stub\n", This, UicItem, pUicHandling);
535
536     *pUicHandling = SCRIPTUICHANDLING_ALLOW;
537     return S_OK;
538 }
539
540 static const IActiveScriptSiteUIControlVtbl ActiveScriptSiteUIControlVtbl = {
541     ActiveScriptSiteUIControl_QueryInterface,
542     ActiveScriptSiteUIControl_AddRef,
543     ActiveScriptSiteUIControl_Release,
544     ActiveScriptSiteUIControl_GetUIBehavior
545 };
546
547 static inline ScriptHost *impl_from_IActiveScriptSiteDebug(IActiveScriptSiteDebug *iface)
548 {
549     return CONTAINING_RECORD(iface, ScriptHost, IActiveScriptSiteDebug_iface);
550 }
551
552 static HRESULT WINAPI ActiveScriptSiteDebug_QueryInterface(IActiveScriptSiteDebug *iface,
553         REFIID riid, void **ppv)
554 {
555     ScriptHost *This = impl_from_IActiveScriptSiteDebug(iface);
556     return IActiveScriptSite_QueryInterface(&This->IActiveScriptSite_iface, riid, ppv);
557 }
558
559 static ULONG WINAPI ActiveScriptSiteDebug_AddRef(IActiveScriptSiteDebug *iface)
560 {
561     ScriptHost *This = impl_from_IActiveScriptSiteDebug(iface);
562     return IActiveScriptSite_AddRef(&This->IActiveScriptSite_iface);
563 }
564
565 static ULONG WINAPI ActiveScriptSiteDebug_Release(IActiveScriptSiteDebug *iface)
566 {
567     ScriptHost *This = impl_from_IActiveScriptSiteDebug(iface);
568     return IActiveScriptSite_Release(&This->IActiveScriptSite_iface);
569 }
570
571 static HRESULT WINAPI ActiveScriptSiteDebug_GetDocumentContextFromPosition(IActiveScriptSiteDebug *iface,
572             CTXARG_T dwSourceContext, ULONG uCharacterOffset, ULONG uNumChars, IDebugDocumentContext **ppsc)
573 {
574     ScriptHost *This = impl_from_IActiveScriptSiteDebug(iface);
575     FIXME("(%p)->(%s %u %u %p)\n", This, wine_dbgstr_longlong(dwSourceContext), uCharacterOffset,
576           uNumChars, ppsc);
577     return E_NOTIMPL;
578 }
579
580 static HRESULT WINAPI ActiveScriptSiteDebug_GetApplication(IActiveScriptSiteDebug *iface, IDebugApplication **ppda)
581 {
582     ScriptHost *This = impl_from_IActiveScriptSiteDebug(iface);
583     FIXME("(%p)->(%p)\n", This, ppda);
584     return E_NOTIMPL;
585 }
586
587 static HRESULT WINAPI ActiveScriptSiteDebug_GetRootApplicationNode(IActiveScriptSiteDebug *iface,
588             IDebugApplicationNode **ppdanRoot)
589 {
590     ScriptHost *This = impl_from_IActiveScriptSiteDebug(iface);
591     FIXME("(%p)->(%p)\n", This, ppdanRoot);
592     return E_NOTIMPL;
593 }
594
595 static HRESULT WINAPI ActiveScriptSiteDebug_OnScriptErrorDebug(IActiveScriptSiteDebug *iface,
596             IActiveScriptErrorDebug *pErrorDebug, BOOL *pfEnterDebugger, BOOL *pfCallOnScriptErrorWhenContinuing)
597 {
598     ScriptHost *This = impl_from_IActiveScriptSiteDebug(iface);
599     FIXME("(%p)->(%p %p %p)\n", This, pErrorDebug, pfEnterDebugger, pfCallOnScriptErrorWhenContinuing);
600     return E_NOTIMPL;
601 }
602
603 static const IActiveScriptSiteDebugVtbl ActiveScriptSiteDebugVtbl = {
604     ActiveScriptSiteDebug_QueryInterface,
605     ActiveScriptSiteDebug_AddRef,
606     ActiveScriptSiteDebug_Release,
607     ActiveScriptSiteDebug_GetDocumentContextFromPosition,
608     ActiveScriptSiteDebug_GetApplication,
609     ActiveScriptSiteDebug_GetRootApplicationNode,
610     ActiveScriptSiteDebug_OnScriptErrorDebug
611 };
612
613 static inline ScriptHost *impl_from_IServiceProvider(IServiceProvider *iface)
614 {
615     return CONTAINING_RECORD(iface, ScriptHost, IServiceProvider_iface);
616 }
617
618 static HRESULT WINAPI ASServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
619 {
620     ScriptHost *This = impl_from_IServiceProvider(iface);
621     return IActiveScriptSite_QueryInterface(&This->IActiveScriptSite_iface, riid, ppv);
622 }
623
624 static ULONG WINAPI ASServiceProvider_AddRef(IServiceProvider *iface)
625 {
626     ScriptHost *This = impl_from_IServiceProvider(iface);
627     return IActiveScriptSite_AddRef(&This->IActiveScriptSite_iface);
628 }
629
630 static ULONG WINAPI ASServiceProvider_Release(IServiceProvider *iface)
631 {
632     ScriptHost *This = impl_from_IServiceProvider(iface);
633     return IActiveScriptSite_Release(&This->IActiveScriptSite_iface);
634 }
635
636 static HRESULT WINAPI ASServiceProvider_QueryService(IServiceProvider *iface, REFGUID guidService,
637         REFIID riid, void **ppv)
638 {
639     ScriptHost *This = impl_from_IServiceProvider(iface);
640
641     if(IsEqualGUID(&SID_SInternetHostSecurityManager, guidService)) {
642         TRACE("(%p)->(SID_SInternetHostSecurityManager)\n", This);
643
644         if(!This->window || !This->window->doc)
645             return E_NOINTERFACE;
646
647         return IInternetHostSecurityManager_QueryInterface(&This->window->doc->IInternetHostSecurityManager_iface,
648                 riid, ppv);
649     }
650
651     FIXME("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
652     return E_NOINTERFACE;
653 }
654
655 static const IServiceProviderVtbl ASServiceProviderVtbl = {
656     ASServiceProvider_QueryInterface,
657     ASServiceProvider_AddRef,
658     ASServiceProvider_Release,
659     ASServiceProvider_QueryService
660 };
661
662 static ScriptHost *create_script_host(HTMLInnerWindow *window, const GUID *guid)
663 {
664     ScriptHost *ret;
665     HRESULT hres;
666
667     ret = heap_alloc_zero(sizeof(*ret));
668     ret->IActiveScriptSite_iface.lpVtbl = &ActiveScriptSiteVtbl;
669     ret->IActiveScriptSiteInterruptPoll_iface.lpVtbl = &ActiveScriptSiteInterruptPollVtbl;
670     ret->IActiveScriptSiteWindow_iface.lpVtbl = &ActiveScriptSiteWindowVtbl;
671     ret->IActiveScriptSiteUIControl_iface.lpVtbl = &ActiveScriptSiteUIControlVtbl;
672     ret->IActiveScriptSiteDebug_iface.lpVtbl = &ActiveScriptSiteDebugVtbl;
673     ret->IServiceProvider_iface.lpVtbl = &ASServiceProviderVtbl;
674     ret->ref = 1;
675     ret->window = window;
676     ret->script_state = SCRIPTSTATE_UNINITIALIZED;
677
678     ret->guid = *guid;
679     list_add_tail(&window->script_hosts, &ret->entry);
680
681     hres = CoCreateInstance(&ret->guid, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
682             &IID_IActiveScript, (void**)&ret->script);
683     if(FAILED(hres))
684         WARN("Could not load script engine: %08x\n", hres);
685     else if(!init_script_engine(ret))
686         release_script_engine(ret);
687
688     return ret;
689 }
690
691 static void parse_text(ScriptHost *script_host, LPCWSTR text)
692 {
693     EXCEPINFO excepinfo;
694     VARIANT var;
695     HRESULT hres;
696
697     TRACE("%s\n", debugstr_w(text));
698
699     VariantInit(&var);
700     memset(&excepinfo, 0, sizeof(excepinfo));
701     TRACE(">>>\n");
702     hres = IActiveScriptParse_ParseScriptText(script_host->parse, text, windowW, NULL, script_endW,
703                                               0, 0, SCRIPTTEXT_ISVISIBLE|SCRIPTTEXT_HOSTMANAGESSOURCE,
704                                               &var, &excepinfo);
705     if(SUCCEEDED(hres))
706         TRACE("<<<\n");
707     else
708         WARN("<<< %08x\n", hres);
709
710 }
711
712 static void parse_extern_script(ScriptHost *script_host, LPCWSTR src)
713 {
714     IMoniker *mon;
715     WCHAR *text;
716     HRESULT hres;
717
718     static const WCHAR wine_schemaW[] = {'w','i','n','e',':'};
719
720     if(strlenW(src) > sizeof(wine_schemaW)/sizeof(WCHAR) && !memcmp(src, wine_schemaW, sizeof(wine_schemaW)))
721         src += sizeof(wine_schemaW)/sizeof(WCHAR);
722
723     hres = CreateURLMoniker(NULL, src, &mon);
724     if(FAILED(hres))
725         return;
726
727     hres = bind_mon_to_wstr(script_host->window, mon, &text);
728     IMoniker_Release(mon);
729     if(FAILED(hres))
730         return;
731
732     parse_text(script_host, text);
733
734     heap_free(text);
735 }
736
737 static void parse_inline_script(ScriptHost *script_host, HTMLScriptElement *script_elem)
738 {
739     const PRUnichar *text;
740     nsAString text_str;
741     nsresult nsres;
742
743     nsAString_Init(&text_str, NULL);
744     nsres = nsIDOMHTMLScriptElement_GetText(script_elem->nsscript, &text_str);
745     nsAString_GetData(&text_str, &text);
746
747     if(NS_FAILED(nsres)) {
748         ERR("GetText failed: %08x\n", nsres);
749     }else if(*text) {
750         script_elem->parsed = TRUE;
751         parse_text(script_host, text);
752     }
753
754     nsAString_Finish(&text_str);
755 }
756
757 static void parse_script_elem(ScriptHost *script_host, HTMLScriptElement *script_elem)
758 {
759     nsAString src_str, event_str;
760     const PRUnichar *src;
761     nsresult nsres;
762
763     nsAString_Init(&event_str, NULL);
764     nsres = nsIDOMHTMLScriptElement_GetEvent(script_elem->nsscript, &event_str);
765     if(NS_SUCCEEDED(nsres)) {
766         const PRUnichar *event;
767
768         nsAString_GetData(&event_str, &event);
769         if(*event) {
770             TRACE("deferring event %s script evaluation\n", debugstr_w(event));
771             nsAString_Finish(&event_str);
772             return;
773         }
774     }else {
775         ERR("GetAttribute(event) failed: %08x\n", nsres);
776     }
777     nsAString_Finish(&event_str);
778
779     nsAString_Init(&src_str, NULL);
780     nsres = nsIDOMHTMLScriptElement_GetSrc(script_elem->nsscript, &src_str);
781     nsAString_GetData(&src_str, &src);
782
783     if(NS_FAILED(nsres)) {
784         ERR("GetSrc failed: %08x\n", nsres);
785     }else if(*src) {
786         script_elem->parsed = TRUE;
787         parse_extern_script(script_host, src);
788     }else {
789         parse_inline_script(script_host, script_elem);
790     }
791
792     nsAString_Finish(&src_str);
793 }
794
795 static GUID get_default_script_guid(HTMLInnerWindow *window)
796 {
797     /* If not specified, we should use very first script host that was created for the page (or JScript if none) */
798     return list_empty(&window->script_hosts)
799         ? CLSID_JScript
800         : LIST_ENTRY(list_head(&window->script_hosts), ScriptHost, entry)->guid;
801 }
802
803 static BOOL get_guid_from_type(LPCWSTR type, GUID *guid)
804 {
805     const WCHAR text_javascriptW[] =
806         {'t','e','x','t','/','j','a','v','a','s','c','r','i','p','t',0};
807     const WCHAR text_vbscriptW[] =
808         {'t','e','x','t','/','v','b','s','c','r','i','p','t',0};
809
810     /* FIXME: Handle more types */
811     if(!strcmpiW(type, text_javascriptW)) {
812         *guid = CLSID_JScript;
813     }else if(!strcmpiW(type, text_vbscriptW)) {
814         *guid = CLSID_VBScript;
815     }else {
816         FIXME("Unknown type %s\n", debugstr_w(type));
817         return FALSE;
818     }
819
820     return TRUE;
821 }
822
823 static BOOL get_guid_from_language(LPCWSTR type, GUID *guid)
824 {
825     HRESULT hres;
826
827     hres = CLSIDFromProgID(type, guid);
828     if(FAILED(hres))
829         return FALSE;
830
831     /* FIXME: Check CATID_ActiveScriptParse */
832
833     return TRUE;
834 }
835
836 static BOOL get_script_guid(HTMLInnerWindow *window, nsIDOMHTMLScriptElement *nsscript, GUID *guid)
837 {
838     nsAString attr_str, val_str;
839     BOOL ret = FALSE;
840     nsresult nsres;
841
842     static const PRUnichar languageW[] = {'l','a','n','g','u','a','g','e',0};
843
844     nsAString_Init(&val_str, NULL);
845
846     nsres = nsIDOMHTMLScriptElement_GetType(nsscript, &val_str);
847     if(NS_SUCCEEDED(nsres)) {
848         const PRUnichar *type;
849
850         nsAString_GetData(&val_str, &type);
851         if(*type) {
852             ret = get_guid_from_type(type, guid);
853             nsAString_Finish(&val_str);
854             return ret;
855         }
856     }else {
857         ERR("GetType failed: %08x\n", nsres);
858     }
859
860     nsAString_InitDepend(&attr_str, languageW);
861     nsres = nsIDOMHTMLScriptElement_GetAttribute(nsscript, &attr_str, &val_str);
862     nsAString_Finish(&attr_str);
863     if(NS_SUCCEEDED(nsres)) {
864         const PRUnichar *language;
865
866         nsAString_GetData(&val_str, &language);
867
868         if(*language) {
869             ret = get_guid_from_language(language, guid);
870         }else {
871             *guid = get_default_script_guid(window);
872             ret = TRUE;
873         }
874     }else {
875         ERR("GetAttribute(language) failed: %08x\n", nsres);
876     }
877
878     nsAString_Finish(&val_str);
879
880     return ret;
881 }
882
883 static ScriptHost *get_script_host(HTMLInnerWindow *window, const GUID *guid)
884 {
885     ScriptHost *iter;
886
887     LIST_FOR_EACH_ENTRY(iter, &window->script_hosts, ScriptHost, entry) {
888         if(IsEqualGUID(guid, &iter->guid))
889             return iter;
890     }
891
892     return create_script_host(window, guid);
893 }
894
895 static ScriptHost *get_elem_script_host(HTMLInnerWindow *window, HTMLScriptElement *script_elem)
896 {
897     GUID guid;
898
899     if(!get_script_guid(window, script_elem->nsscript, &guid)) {
900         WARN("Could not find script GUID\n");
901         return NULL;
902     }
903
904     if(IsEqualGUID(&CLSID_JScript, &guid)
905        && (!window->base.outer_window || window->base.outer_window->scriptmode != SCRIPTMODE_ACTIVESCRIPT)) {
906         TRACE("Ignoring JScript\n");
907         return NULL;
908     }
909
910     return get_script_host(window, &guid);
911 }
912
913 void doc_insert_script(HTMLInnerWindow *window, HTMLScriptElement *script_elem)
914 {
915     ScriptHost *script_host;
916
917     script_host = get_elem_script_host(window, script_elem);
918     if(!script_host)
919         return;
920
921     if(script_host->parse)
922         parse_script_elem(script_host, script_elem);
923 }
924
925 IDispatch *script_parse_event(HTMLInnerWindow *window, LPCWSTR text)
926 {
927     ScriptHost *script_host;
928     GUID guid;
929     const WCHAR *ptr;
930     IDispatch *disp;
931     HRESULT hres;
932
933     static const WCHAR delimiterW[] = {'\"',0};
934
935     TRACE("%s\n", debugstr_w(text));
936
937     for(ptr = text; isalnumW(*ptr); ptr++);
938     if(*ptr == ':') {
939         LPWSTR language;
940         BOOL b;
941
942         language = heap_alloc((ptr-text+1)*sizeof(WCHAR));
943         memcpy(language, text, (ptr-text)*sizeof(WCHAR));
944         language[ptr-text] = 0;
945
946         b = get_guid_from_language(language, &guid);
947
948         heap_free(language);
949
950         if(!b) {
951             WARN("Could not find language\n");
952             return NULL;
953         }
954
955         ptr++;
956     }else {
957         ptr = text;
958         guid = get_default_script_guid(window);
959     }
960
961     if(IsEqualGUID(&CLSID_JScript, &guid)
962        && (!window->base.outer_window || window->base.outer_window->scriptmode != SCRIPTMODE_ACTIVESCRIPT)) {
963         TRACE("Ignoring JScript\n");
964         return NULL;
965     }
966
967     script_host = get_script_host(window, &guid);
968     if(!script_host || !script_host->parse_proc)
969         return NULL;
970
971     hres = IActiveScriptParseProcedure2_ParseProcedureText(script_host->parse_proc, ptr, NULL, emptyW,
972             NULL, NULL, delimiterW, 0 /* FIXME */, 0,
973             SCRIPTPROC_HOSTMANAGESSOURCE|SCRIPTPROC_IMPLICIT_THIS|SCRIPTPROC_IMPLICIT_PARENTS, &disp);
974     if(FAILED(hres)) {
975         WARN("ParseProcedureText failed: %08x\n", hres);
976         return NULL;
977     }
978
979     TRACE("ret %p\n", disp);
980     return disp;
981 }
982
983 HRESULT exec_script(HTMLInnerWindow *window, const WCHAR *code, const WCHAR *lang, VARIANT *ret)
984 {
985     ScriptHost *script_host;
986     EXCEPINFO ei;
987     GUID guid;
988     HRESULT hres;
989
990     static const WCHAR delimW[] = {'"',0};
991
992     if(!get_guid_from_language(lang, &guid)) {
993         WARN("Could not find script GUID\n");
994         return CO_E_CLASSSTRING;
995     }
996
997     script_host = get_script_host(window, &guid);
998     if(!script_host) {
999         FIXME("No script host\n");
1000         return E_FAIL;
1001     }
1002
1003     if(!script_host->parse) {
1004         FIXME("script_host->parse == NULL\n");
1005         return E_FAIL;
1006     }
1007
1008     memset(&ei, 0, sizeof(ei));
1009     TRACE(">>>\n");
1010     hres = IActiveScriptParse_ParseScriptText(script_host->parse, code, NULL, NULL, delimW, 0, 0, SCRIPTTEXT_ISVISIBLE, ret, &ei);
1011     if(SUCCEEDED(hres))
1012         TRACE("<<<\n");
1013     else
1014         WARN("<<< %08x\n", hres);
1015
1016     return hres;
1017 }
1018
1019 IDispatch *get_script_disp(ScriptHost *script_host)
1020 {
1021     IDispatch *disp;
1022     HRESULT hres;
1023
1024     if(!script_host->script)
1025         return NULL;
1026
1027     hres = IActiveScript_GetScriptDispatch(script_host->script, windowW, &disp);
1028     if(FAILED(hres))
1029         return NULL;
1030
1031     return disp;
1032 }
1033
1034 static HTMLElement *find_event_target(HTMLDocumentNode *doc, HTMLScriptElement *script_elem)
1035 {
1036     const PRUnichar *target_id;
1037     nsAString target_id_str;
1038     HTMLElement *elem;
1039     nsresult nsres;
1040     HRESULT hres;
1041
1042     nsAString_Init(&target_id_str, NULL);
1043     nsres = nsIDOMHTMLScriptElement_GetHtmlFor(script_elem->nsscript, &target_id_str);
1044     if(NS_FAILED(nsres)) {
1045         ERR("GetScriptFor failed: %08x\n", nsres);
1046         nsAString_Finish(&target_id_str);
1047         return NULL;
1048     }
1049
1050     nsAString_GetData(&target_id_str, &target_id);
1051     if(!*target_id || !strcmpW(target_id, documentW) || !strcmpW(target_id, windowW)) {
1052         FIXME("for %s not supported\n", debugstr_w(target_id));
1053         elem = NULL;
1054     }else {
1055         hres = get_doc_elem_by_id(doc, target_id, &elem);
1056         if(FAILED(hres))
1057             elem = NULL;
1058     }
1059     nsAString_Finish(&target_id_str);
1060
1061     return elem;
1062 }
1063
1064 static BOOL parse_event_str(WCHAR *event, const WCHAR **args)
1065 {
1066     WCHAR *ptr;
1067
1068     TRACE("%s\n", debugstr_w(event));
1069
1070     for(ptr = event; isalnumW(*ptr); ptr++);
1071     if(!*ptr) {
1072         *args = NULL;
1073         return TRUE;
1074     }
1075
1076     if(*ptr != '(')
1077         return FALSE;
1078
1079     *ptr++ = 0;
1080     *args = ptr;
1081     while(isalnumW(*ptr) || isspaceW(*ptr) || *ptr == ',')
1082         ptr++;
1083
1084     if(*ptr != ')')
1085         return FALSE;
1086
1087     *ptr++ = 0;
1088     return !*ptr;
1089 }
1090
1091 static IDispatch *parse_event_elem(HTMLDocumentNode *doc, HTMLScriptElement *script_elem, WCHAR **ret_event)
1092 {
1093     ScriptHost *script_host;
1094     WCHAR *event = NULL;
1095     const WCHAR *args;
1096     nsAString nsstr;
1097     IDispatch *disp;
1098     nsresult nsres;
1099     HRESULT hres;
1100
1101     if(script_elem->parsed)
1102         return NULL;
1103
1104     script_host = get_elem_script_host(doc->window, script_elem);
1105     if(!script_host || !script_host->parse_proc)
1106         return NULL;
1107
1108     nsAString_Init(&nsstr, NULL);
1109     nsres = nsIDOMHTMLScriptElement_GetEvent(script_elem->nsscript, &nsstr);
1110     if(NS_SUCCEEDED(nsres)) {
1111         const PRUnichar *event_val;
1112
1113         nsAString_GetData(&nsstr, &event_val);
1114         event = heap_strdupW(event_val);
1115     }
1116     nsAString_Finish(&nsstr);
1117     if(!event)
1118         return NULL;
1119
1120     if(!parse_event_str(event, &args)) {
1121         WARN("parsing %s failed\n", debugstr_w(event));
1122         heap_free(event);
1123         return NULL;
1124     }
1125
1126     nsAString_Init(&nsstr, NULL);
1127     nsres = nsIDOMHTMLScriptElement_GetText(script_elem->nsscript, &nsstr);
1128     if(NS_SUCCEEDED(nsres)) {
1129         const PRUnichar *text;
1130
1131         nsAString_GetData(&nsstr, &text);
1132         hres = IActiveScriptParseProcedure2_ParseProcedureText(script_host->parse_proc, text, args,
1133                 emptyW, NULL, NULL, script_endW, 0, 0,
1134                 SCRIPTPROC_HOSTMANAGESSOURCE|SCRIPTPROC_IMPLICIT_THIS|SCRIPTPROC_IMPLICIT_PARENTS, &disp);
1135         if(FAILED(hres))
1136             disp = NULL;
1137     }else {
1138         ERR("GetText failed: %08x\n", nsres);
1139         disp = NULL;
1140     }
1141     nsAString_Finish(&nsstr);
1142     if(!disp) {
1143         heap_free(event);
1144         return NULL;
1145     }
1146
1147     *ret_event = event;
1148     return disp;
1149 }
1150
1151 void bind_event_scripts(HTMLDocumentNode *doc)
1152 {
1153     HTMLPluginContainer *plugin_container;
1154     nsIDOMHTMLScriptElement *nsscript;
1155     HTMLScriptElement *script_elem;
1156     HTMLElement *event_target;
1157     nsIDOMNodeList *node_list;
1158     nsIDOMNode *script_node;
1159     nsAString selector_str;
1160     IDispatch *event_disp;
1161     PRUint32 length, i;
1162     WCHAR *event;
1163     nsresult nsres;
1164     HRESULT hres;
1165
1166     static const PRUnichar selectorW[] = {'s','c','r','i','p','t','[','e','v','e','n','t',']',0};
1167
1168     TRACE("%p\n", doc);
1169
1170     if(!doc->nsdoc)
1171         return;
1172
1173     nsAString_InitDepend(&selector_str, selectorW);
1174     nsres = nsIDOMNodeSelector_QuerySelectorAll(doc->nsnode_selector, &selector_str, &node_list);
1175     nsAString_Finish(&selector_str);
1176     if(NS_FAILED(nsres)) {
1177         ERR("QuerySelectorAll failed: %08x\n", nsres);
1178         return;
1179     }
1180
1181     if(!node_list)
1182         return;
1183
1184     nsres = nsIDOMNodeList_GetLength(node_list, &length);
1185     assert(nsres == NS_OK);
1186
1187     for(i=0; i < length; i++) {
1188         nsres = nsIDOMNodeList_Item(node_list, i, &script_node);
1189         if(NS_FAILED(nsres) || !script_node) {
1190             ERR("Item(%d) failed: %08x\n", i, nsres);
1191             continue;
1192         }
1193
1194         nsres = nsIDOMNode_QueryInterface(script_node, &IID_nsIDOMHTMLScriptElement, (void**)&nsscript);
1195         assert(nsres == NS_OK);
1196         nsIDOMNode_Release(script_node);
1197
1198         hres = script_elem_from_nsscript(doc, nsscript, &script_elem);
1199         if(FAILED(hres))
1200             continue;
1201
1202         event_disp = parse_event_elem(doc, script_elem, &event);
1203         if(event_disp) {
1204             event_target = find_event_target(doc, script_elem);
1205             if(event_target) {
1206                 IHTMLElement_QueryInterface(&event_target->IHTMLElement_iface, &IID_HTMLPluginContainer, (void**)&plugin_container);
1207
1208                 if(plugin_container)
1209                     bind_activex_event(doc, plugin_container, event, event_disp);
1210                 else
1211                     bind_elem_event(doc, event_target, event, event_disp);
1212
1213                 IHTMLElement_Release(&event_target->IHTMLElement_iface);
1214             }
1215
1216             heap_free(event);
1217             IDispatch_Release(event_disp);
1218         }
1219
1220         IHTMLScriptElement_Release(&script_elem->IHTMLScriptElement_iface);
1221     }
1222
1223     nsIDOMNodeList_Release(node_list);
1224 }
1225
1226 BOOL find_global_prop(HTMLInnerWindow *window, BSTR name, DWORD flags, ScriptHost **ret_host, DISPID *ret_id)
1227 {
1228     IDispatchEx *dispex;
1229     IDispatch *disp;
1230     ScriptHost *iter;
1231     HRESULT hres;
1232
1233     LIST_FOR_EACH_ENTRY(iter, &window->script_hosts, ScriptHost, entry) {
1234         disp = get_script_disp(iter);
1235         if(!disp)
1236             continue;
1237
1238         hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
1239         if(SUCCEEDED(hres)) {
1240             hres = IDispatchEx_GetDispID(dispex, name, flags & (~fdexNameEnsure), ret_id);
1241             IDispatchEx_Release(dispex);
1242         }else {
1243             FIXME("No IDispatchEx\n");
1244             hres = E_NOTIMPL;
1245         }
1246
1247         IDispatch_Release(disp);
1248         if(SUCCEEDED(hres)) {
1249             *ret_host = iter;
1250             return TRUE;
1251         }
1252     }
1253
1254     return FALSE;
1255 }
1256
1257 static BOOL is_jscript_available(void)
1258 {
1259     static BOOL available, checked;
1260
1261     if(!checked) {
1262         IUnknown *unk;
1263         HRESULT hres = CoGetClassObject(&CLSID_JScript, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
1264
1265         if(SUCCEEDED(hres)) {
1266             available = TRUE;
1267             IUnknown_Release(unk);
1268         }else {
1269             available = FALSE;
1270         }
1271         checked = TRUE;
1272     }
1273
1274     return available;
1275 }
1276
1277 void set_script_mode(HTMLOuterWindow *window, SCRIPTMODE mode)
1278 {
1279     nsIWebBrowserSetup *setup;
1280     nsresult nsres;
1281
1282     if(mode == SCRIPTMODE_ACTIVESCRIPT && !is_jscript_available()) {
1283         TRACE("jscript.dll not available\n");
1284         window->scriptmode = SCRIPTMODE_GECKO;
1285         return;
1286     }
1287
1288     window->scriptmode = mode;
1289
1290     if(!window->doc_obj->nscontainer || !window->doc_obj->nscontainer->webbrowser)
1291         return;
1292
1293     nsres = nsIWebBrowser_QueryInterface(window->doc_obj->nscontainer->webbrowser,
1294             &IID_nsIWebBrowserSetup, (void**)&setup);
1295     if(NS_SUCCEEDED(nsres)) {
1296         nsres = nsIWebBrowserSetup_SetProperty(setup, SETUP_ALLOW_JAVASCRIPT,
1297                 window->scriptmode == SCRIPTMODE_GECKO);
1298
1299         if(NS_SUCCEEDED(nsres))
1300             nsres = nsIWebBrowserSetup_SetProperty(setup, SETUP_DISABLE_NOSCRIPT, TRUE);
1301
1302         nsIWebBrowserSetup_Release(setup);
1303     }
1304
1305     if(NS_FAILED(nsres))
1306         ERR("JavaScript setup failed: %08x\n", nsres);
1307 }
1308
1309 void release_script_hosts(HTMLInnerWindow *window)
1310 {
1311     ScriptHost *iter;
1312
1313     while(!list_empty(&window->script_hosts)) {
1314         iter = LIST_ENTRY(list_head(&window->script_hosts), ScriptHost, entry);
1315
1316         release_script_engine(iter);
1317         list_remove(&iter->entry);
1318         iter->window = NULL;
1319         IActiveScriptSite_Release(&iter->IActiveScriptSite_iface);
1320     }
1321 }