mshtml: Store security manager in HTMLWindow instead of HTMLDocumentNode.
[wine] / dlls / mshtml / npplugin.c
1 /*
2  * Copyright 2010 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
23 #define COBJMACROS
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winuser.h"
28 #include "ole2.h"
29 #include "shlobj.h"
30
31 #include "mshtml_private.h"
32 #include "pluginhost.h"
33
34 #include "wine/debug.h"
35 #include "wine/unicode.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
38
39 /* Parts of npapi.h */
40
41 #define NPERR_BASE                         0
42 #define NPERR_NO_ERROR                    (NPERR_BASE + 0)
43 #define NPERR_GENERIC_ERROR               (NPERR_BASE + 1)
44 #define NPERR_INVALID_INSTANCE_ERROR      (NPERR_BASE + 2)
45 #define NPERR_INVALID_FUNCTABLE_ERROR     (NPERR_BASE + 3)
46 #define NPERR_MODULE_LOAD_FAILED_ERROR    (NPERR_BASE + 4)
47 #define NPERR_OUT_OF_MEMORY_ERROR         (NPERR_BASE + 5)
48 #define NPERR_INVALID_PLUGIN_ERROR        (NPERR_BASE + 6)
49 #define NPERR_INVALID_PLUGIN_DIR_ERROR    (NPERR_BASE + 7)
50 #define NPERR_INCOMPATIBLE_VERSION_ERROR  (NPERR_BASE + 8)
51 #define NPERR_INVALID_PARAM               (NPERR_BASE + 9)
52 #define NPERR_INVALID_URL                 (NPERR_BASE + 10)
53 #define NPERR_FILE_NOT_FOUND              (NPERR_BASE + 11)
54 #define NPERR_NO_DATA                     (NPERR_BASE + 12)
55 #define NPERR_STREAM_NOT_SEEKABLE         (NPERR_BASE + 13)
56
57 /* Parts of npfunctions.h */
58
59 typedef NPError (CDECL *NPP_NewProcPtr)(NPMIMEType,NPP,UINT16,INT16,char**,char**,NPSavedData*);
60 typedef NPError (CDECL *NPP_DestroyProcPtr)(NPP,NPSavedData**);
61 typedef NPError (CDECL *NPP_SetWindowProcPtr)(NPP,NPWindow*);
62 typedef NPError (CDECL *NPP_NewStreamProcPtr)(NPP,NPMIMEType,NPStream*,NPBool,UINT16*);
63 typedef NPError (CDECL *NPP_DestroyStreamProcPtr)(NPP,NPStream*,NPReason);
64 typedef INT32 (CDECL *NPP_WriteReadyProcPtr)(NPP,NPStream*);
65 typedef INT32 (CDECL *NPP_WriteProcPtr)(NPP,NPStream*,INT32,INT32,void*);
66 typedef void (CDECL *NPP_StreamAsFileProcPtr)(NPP,NPStream*,const char*);
67 typedef void (CDECL *NPP_PrintProcPtr)(NPP,NPPrint*);
68 typedef INT16 (CDECL *NPP_HandleEventProcPtr)(NPP,void*);
69 typedef void (CDECL *NPP_URLNotifyProcPtr)(NPP,const char*,NPReason,void*);
70 typedef NPError (CDECL *NPP_GetValueProcPtr)(NPP,NPPVariable,void*);
71 typedef NPError (CDECL *NPP_SetValueProcPtr)(NPP,NPNVariable,void*);
72 typedef NPBool (CDECL *NPP_GotFocusPtr)(NPP,NPFocusDirection);
73 typedef void (CDECL *NPP_LostFocusPtr)(NPP);
74
75 typedef struct _NPPluginFuncs {
76     UINT16 size;
77     UINT16 version;
78     NPP_NewProcPtr newp;
79     NPP_DestroyProcPtr destroy;
80     NPP_SetWindowProcPtr setwindow;
81     NPP_NewStreamProcPtr newstream;
82     NPP_DestroyStreamProcPtr destroystream;
83     NPP_StreamAsFileProcPtr asfile;
84     NPP_WriteReadyProcPtr writeready;
85     NPP_WriteProcPtr write;
86     NPP_PrintProcPtr print;
87     NPP_HandleEventProcPtr event;
88     NPP_URLNotifyProcPtr urlnotify;
89     void *javaClass;
90     NPP_GetValueProcPtr getvalue;
91     NPP_SetValueProcPtr setvalue;
92     NPP_GotFocusPtr gotfocus;
93     NPP_LostFocusPtr lostfocus;
94 } NPPluginFuncs;
95
96 static nsIDOMElement *get_dom_element(NPP instance)
97 {
98     nsISupports *instance_unk = (nsISupports*)instance->ndata;
99     nsIPluginInstance *plugin_instance;
100     nsIPluginInstanceOwner *owner;
101     nsIPluginTagInfo *tag_info;
102     nsIDOMElement *elem;
103     nsresult nsres;
104
105     nsres = nsISupports_QueryInterface(instance_unk, &IID_nsIPluginInstance, (void**)&plugin_instance);
106     if(NS_FAILED(nsres))
107         return NULL;
108
109     nsres = nsIPluginInstance_GetOwner(plugin_instance, &owner);
110     nsIPluginInstance_Release(instance_unk);
111     if(NS_FAILED(nsres) || !owner)
112         return NULL;
113
114     nsres = nsISupports_QueryInterface(owner, &IID_nsIPluginTagInfo, (void**)&tag_info);
115     nsISupports_Release(owner);
116     if(NS_FAILED(nsres))
117         return NULL;
118
119     nsres = nsIPluginTagInfo_GetDOMElement(tag_info, &elem);
120     nsIPluginTagInfo_Release(tag_info);
121     if(NS_FAILED(nsres))
122         return NULL;
123
124     return elem;
125 }
126
127 static HTMLWindow *get_elem_window(nsIDOMElement *elem)
128 {
129     nsIDOMWindow *nswindow;
130     nsIDOMDocument *nsdoc;
131     HTMLWindow *window;
132     nsresult nsres;
133
134     nsres = nsIDOMElement_GetOwnerDocument(elem, &nsdoc);
135     if(NS_FAILED(nsres))
136         return NULL;
137
138     nswindow = get_nsdoc_window(nsdoc);
139     nsIDOMDocument_Release(nsdoc);
140     if(!nswindow)
141         return NULL;
142
143     window = nswindow_to_window(nswindow);
144     nsIDOMWindow_Release(nswindow);
145
146     return window;
147 }
148
149 static BOOL parse_classid(const PRUnichar *classid, CLSID *clsid)
150 {
151     const WCHAR *ptr;
152     unsigned len;
153     HRESULT hres;
154
155     static const PRUnichar clsidW[] = {'c','l','s','i','d',':'};
156
157     if(strncmpiW(classid, clsidW, sizeof(clsidW)/sizeof(WCHAR)))
158         return FALSE;
159
160     ptr = classid + sizeof(clsidW)/sizeof(WCHAR);
161     len = strlenW(ptr);
162
163     if(len == 38) {
164         hres = CLSIDFromString(ptr, clsid);
165     }else if(len == 36) {
166         WCHAR buf[39];
167
168         buf[0] = '{';
169         memcpy(buf+1, ptr, len*sizeof(WCHAR));
170         buf[37] = '}';
171         buf[38] = 0;
172         hres = CLSIDFromString(buf, clsid);
173     }else {
174         return FALSE;
175     }
176
177     return SUCCEEDED(hres);
178 }
179
180 static BOOL get_elem_clsid(nsIDOMElement *elem, CLSID *clsid)
181 {
182     nsAString attr_str, val_str;
183     nsresult nsres;
184     BOOL ret = FALSE;
185
186     static const PRUnichar classidW[] = {'c','l','a','s','s','i','d',0};
187
188     nsAString_InitDepend(&attr_str, classidW);
189     nsAString_Init(&val_str, NULL);
190     nsres = nsIDOMElement_GetAttribute(elem, &attr_str, &val_str);
191     nsAString_Finish(&attr_str);
192     if(NS_SUCCEEDED(nsres)) {
193         const PRUnichar *val;
194
195         nsAString_GetData(&val_str, &val);
196         if(*val)
197             ret = parse_classid(val, clsid);
198     }else {
199         ERR("GetAttribute failed: %08x\n", nsres);
200     }
201
202     nsAString_Finish(&attr_str);
203     return ret;
204 }
205
206 static IUnknown *create_activex_object(HTMLWindow *window, nsIDOMElement *nselem, CLSID *clsid)
207 {
208     IClassFactoryEx *cfex;
209     IClassFactory *cf;
210     IUnknown *obj;
211     DWORD policy;
212     HRESULT hres;
213
214     if(!get_elem_clsid(nselem, clsid)) {
215         WARN("Could not determine element CLSID\n");
216         return NULL;
217     }
218
219     TRACE("clsid %s\n", debugstr_guid(clsid));
220
221     policy = 0;
222     hres = IInternetHostSecurityManager_ProcessUrlAction(&window->doc->IInternetHostSecurityManager_iface,
223             URLACTION_ACTIVEX_RUN, (BYTE*)&policy, sizeof(policy), (BYTE*)clsid, sizeof(GUID), 0, 0);
224     if(FAILED(hres) || policy != URLPOLICY_ALLOW) {
225         WARN("ProcessUrlAction returned %08x %x\n", hres, policy);
226         return NULL;
227     }
228
229     hres = CoGetClassObject(clsid, CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, NULL, &IID_IClassFactory, (void**)&cf);
230     if(FAILED(hres))
231         return NULL;
232
233     hres = IClassFactory_QueryInterface(cf, &IID_IClassFactoryEx, (void**)&cfex);
234     if(SUCCEEDED(hres)) {
235         FIXME("Use IClassFactoryEx\n");
236         IClassFactoryEx_Release(cfex);
237     }
238
239     hres = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void**)&obj);
240     if(FAILED(hres))
241         return NULL;
242
243     return obj;
244 }
245
246 static NPError CDECL NPP_New(NPMIMEType pluginType, NPP instance, UINT16 mode, INT16 argc, char **argn,
247         char **argv, NPSavedData *saved)
248 {
249     nsIDOMElement *nselem;
250     HTMLWindow *window;
251     IUnknown *obj;
252     CLSID clsid;
253     NPError err = NPERR_NO_ERROR;
254
255     TRACE("(%s %p %x %d %p %p %p)\n", debugstr_a(pluginType), instance, mode, argc, argn, argv, saved);
256
257     nselem = get_dom_element(instance);
258     if(!nselem) {
259         ERR("Could not get DOM element\n");
260         return NPERR_GENERIC_ERROR;
261     }
262
263     window = get_elem_window(nselem);
264     if(!window) {
265         ERR("Could not get element's window object\n");
266         nsIDOMElement_Release(nselem);
267         return NPERR_GENERIC_ERROR;
268     }
269
270     obj = create_activex_object(window, nselem, &clsid);
271     if(obj) {
272         PluginHost *host;
273         HRESULT hres;
274
275         hres = create_plugin_host(window->doc, nselem, obj, &clsid, &host);
276         nsIDOMElement_Release(nselem);
277         IUnknown_Release(obj);
278         if(SUCCEEDED(hres))
279             instance->pdata = host;
280         else
281             err = NPERR_GENERIC_ERROR;
282     }else {
283         err = NPERR_GENERIC_ERROR;
284     }
285
286     nsIDOMElement_Release(nselem);
287     return err;
288 }
289
290 static NPError CDECL NPP_Destroy(NPP instance, NPSavedData **save)
291 {
292     PluginHost *host = instance->pdata;
293
294     TRACE("(%p %p)\n", instance, save);
295
296     if(!host)
297         return NPERR_GENERIC_ERROR;
298
299     detach_plugin_host(host);
300     IOleClientSite_Release(&host->IOleClientSite_iface);
301     instance->pdata = NULL;
302     return NPERR_NO_ERROR;
303 }
304
305 static NPError CDECL NPP_SetWindow(NPP instance, NPWindow *window)
306 {
307     PluginHost *host = instance->pdata;
308     RECT pos_rect = {0, 0, window->width, window->height};
309
310     TRACE("(%p %p)\n", instance, window);
311
312     if(!host)
313         return NPERR_GENERIC_ERROR;
314
315     update_plugin_window(host, window->window, &pos_rect);
316     return NPERR_NO_ERROR;
317 }
318
319 static NPError CDECL NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream, NPBool seekable, UINT16 *stype)
320 {
321     TRACE("\n");
322     return NPERR_GENERIC_ERROR;
323 }
324
325 static NPError CDECL NPP_DestroyStream(NPP instance, NPStream *stream, NPReason reason)
326 {
327     TRACE("\n");
328     return NPERR_GENERIC_ERROR;
329 }
330
331 static INT32 CDECL NPP_WriteReady(NPP instance, NPStream *stream)
332 {
333     TRACE("\n");
334     return NPERR_GENERIC_ERROR;
335 }
336
337 static INT32 CDECL NPP_Write(NPP instance, NPStream *stream, INT32 offset, INT32 len, void *buffer)
338 {
339     TRACE("\n");
340     return NPERR_GENERIC_ERROR;
341 }
342
343 static void CDECL NPP_StreamAsFile(NPP instance, NPStream *stream, const char *fname)
344 {
345     TRACE("\n");
346 }
347
348 static void CDECL NPP_Print(NPP instance, NPPrint *platformPrint)
349 {
350     FIXME("\n");
351 }
352
353 static INT16 CDECL NPP_HandleEvent(NPP instance, void *event)
354 {
355     TRACE("\n");
356     return NPERR_GENERIC_ERROR;
357 }
358
359 static void CDECL NPP_URLNotify(NPP instance, const char *url, NPReason reason, void *notifyData)
360 {
361     TRACE("\n");
362 }
363
364 static NPError CDECL NPP_GetValue(NPP instance, NPPVariable variable, void *ret_value)
365 {
366     TRACE("\n");
367     return NPERR_GENERIC_ERROR;
368 }
369
370 static NPError CDECL NPP_SetValue(NPP instance, NPNVariable variable, void *value)
371 {
372     TRACE("\n");
373     return NPERR_GENERIC_ERROR;
374 }
375
376 static NPBool CDECL NPP_GotFocus(NPP instance, NPFocusDirection direction)
377 {
378     FIXME("\n");
379     return NPERR_GENERIC_ERROR;
380 }
381
382 static void CDECL NPP_LostFocus(NPP instance)
383 {
384     FIXME("\n");
385 }
386
387 /***********************************************************************
388  *          NP_GetEntryPoints (mshtml.@)
389  */
390 NPError WINAPI NP_GetEntryPoints(NPPluginFuncs* funcs)
391 {
392     TRACE("(%p)\n", funcs);
393
394     funcs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
395     funcs->newp = NPP_New;
396     funcs->destroy = NPP_Destroy;
397     funcs->setwindow = NPP_SetWindow;
398     funcs->newstream = NPP_NewStream;
399     funcs->destroystream = NPP_DestroyStream;
400     funcs->asfile = NPP_StreamAsFile;
401     funcs->writeready = NPP_WriteReady;
402     funcs->write = NPP_Write;
403     funcs->print = NPP_Print;
404     funcs->event = NPP_HandleEvent;
405     funcs->urlnotify = NPP_URLNotify;
406     funcs->javaClass = NULL;
407     funcs->getvalue = NPP_GetValue;
408     funcs->setvalue = NPP_SetValue;
409     funcs->gotfocus = NPP_GotFocus;
410     funcs->lostfocus = NPP_LostFocus;
411
412     return NPERR_NO_ERROR;
413 }