1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
23 * Josh Aas <josh@mozilla.com>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
42 #include "nsAutoLock.h"
43 #include "nsNPAPIPlugin.h"
44 #include "nsNPAPIPluginInstance.h"
45 #include "nsNPAPIPluginStreamListener.h"
46 #include "nsIServiceManager.h"
47 #include "nsThreadUtils.h"
49 #include "nsIPluginStreamListener.h"
50 #include "nsPluginsDir.h"
51 #include "nsPluginSafety.h"
52 #include "nsIPrefService.h"
53 #include "nsIPrefBranch.h"
54 #include "nsPluginLogging.h"
56 #include "nsIPluginInstancePeer2.h"
57 #include "nsIJSContextStack.h"
59 #include "nsPIPluginInstancePeer.h"
60 #include "nsIDOMElement.h"
61 #include "nsIDOMDocument.h"
62 #include "nsPIDOMWindow.h"
63 #include "nsIDocument.h"
64 #include "nsIScriptGlobalObject.h"
65 #include "nsIScriptContext.h"
66 #include "nsDOMJSUtils.h"
67 #include "nsIPrincipal.h"
71 #include "nsIXPConnect.h"
73 #include "nsIObserverService.h"
77 #include <Carbon/Carbon.h>
80 // needed for nppdf plugin
81 #ifdef MOZ_WIDGET_GTK2
84 #include "gtk2xtbin.h"
87 #include "nsJSNPRuntime.h"
89 static PRLock
*sPluginThreadAsyncCallLock
= nsnull
;
90 static PRCList sPendingAsyncCalls
= PR_INIT_STATIC_CLIST(&sPendingAsyncCalls
);
92 // POST/GET stream type
93 enum eNPPStreamTypeInternal
{
94 eNPPStreamTypeInternal_Get
,
95 eNPPStreamTypeInternal_Post
98 static NS_DEFINE_IID(kCPluginManagerCID
, NS_PLUGINMANAGER_CID
);
99 static NS_DEFINE_IID(kPluginManagerCID
, NS_PLUGINMANAGER_CID
);
100 static NS_DEFINE_IID(kMemoryCID
, NS_MEMORY_CID
);
102 // Static stub functions that are exported to the 4.x plugin as entry
103 // points via the CALLBACKS variable.
106 static NPError NP_CALLBACK
107 _requestread(NPStream
*pstream
, NPByteRange
*rangeList
);
109 static NPError NP_CALLBACK
110 _geturlnotify(NPP npp
, const char* relativeURL
, const char* target
,
113 static NPError NP_CALLBACK
114 _getvalue(NPP npp
, NPNVariable variable
, void *r_value
);
116 static NPError NP_CALLBACK
117 _setvalue(NPP npp
, NPPVariable variable
, void *r_value
);
119 static NPError NP_CALLBACK
120 _geturl(NPP npp
, const char* relativeURL
, const char* target
);
122 static NPError NP_CALLBACK
123 _posturlnotify(NPP npp
, const char* relativeURL
, const char *target
,
124 uint32_t len
, const char *buf
, NPBool file
, void* notifyData
);
126 static NPError NP_CALLBACK
127 _posturl(NPP npp
, const char* relativeURL
, const char *target
, uint32_t len
,
128 const char *buf
, NPBool file
);
130 static NPError NP_CALLBACK
131 _newstream(NPP npp
, NPMIMEType type
, const char* window
, NPStream
** pstream
);
133 static int32_t NP_CALLBACK
134 _write(NPP npp
, NPStream
*pstream
, int32_t len
, void *buffer
);
136 static NPError NP_CALLBACK
137 _destroystream(NPP npp
, NPStream
*pstream
, NPError reason
);
139 static void NP_CALLBACK
140 _status(NPP npp
, const char *message
);
142 static void NP_CALLBACK
143 _memfree (void *ptr
);
145 static uint32_t NP_CALLBACK
146 _memflush(uint32_t size
);
148 static void NP_CALLBACK
149 _reloadplugins(NPBool reloadPages
);
151 static void NP_CALLBACK
152 _invalidaterect(NPP npp
, NPRect
*invalidRect
);
154 static void NP_CALLBACK
155 _invalidateregion(NPP npp
, NPRegion invalidRegion
);
157 static void NP_CALLBACK
158 _forceredraw(NPP npp
);
160 static void NP_CALLBACK
161 _pushpopupsenabledstate(NPP npp
, NPBool enabled
);
163 static void NP_CALLBACK
164 _poppopupsenabledstate(NPP npp
);
166 typedef void(*PluginThreadCallback
)(void *);
167 static void NP_CALLBACK
168 _pluginthreadasynccall(NPP instance
, PluginThreadCallback func
,
171 static const char* NP_CALLBACK
174 static void* NP_CALLBACK
175 _memalloc (uint32_t size
);
177 // Deprecated entry points for the old Java plugin.
178 static void* NP_CALLBACK
/* OJI type: JRIEnv* */
180 static void* NP_CALLBACK
/* OJI type: jref */
181 _getJavaPeer(NPP npp
);
185 // This function sends a notification using the observer service to any object
186 // registered to listen to the "experimental-notify-plugin-call" subject.
187 // Each "experimental-notify-plugin-call" notification carries with it the run
188 // time value in milliseconds that the call took to execute.
189 void NS_NotifyPluginCall(PRIntervalTime startTime
)
191 PRIntervalTime endTime
= PR_IntervalNow() - startTime
;
192 nsCOMPtr
<nsIObserverService
> notifyUIService
=
193 do_GetService("@mozilla.org/observer-service;1");
194 float runTimeInSeconds
= float(endTime
) / PR_TicksPerSecond();
195 nsAutoString runTimeString
;
196 runTimeString
.AppendFloat(runTimeInSeconds
);
197 const PRUnichar
* runTime
= runTimeString
.get();
198 notifyUIService
->NotifyObservers(nsnull
, "experimental-notify-plugin-call",
202 NPNetscapeFuncs
nsNPAPIPlugin::CALLBACKS
;
205 nsNPAPIPlugin::CheckClassInitialized(void)
207 static PRBool initialized
= PR_FALSE
;
212 // XXX It'd be nice to make this const and initialize it statically...
213 CALLBACKS
.size
= sizeof(CALLBACKS
);
214 CALLBACKS
.version
= (NP_VERSION_MAJOR
<< 8) + NP_VERSION_MINOR
;
215 CALLBACKS
.geturl
= ((NPN_GetURLProcPtr
)_geturl
);
216 CALLBACKS
.posturl
= ((NPN_PostURLProcPtr
)_posturl
);
217 CALLBACKS
.requestread
= ((NPN_RequestReadProcPtr
)_requestread
);
218 CALLBACKS
.newstream
= ((NPN_NewStreamProcPtr
)_newstream
);
219 CALLBACKS
.write
= ((NPN_WriteProcPtr
)_write
);
220 CALLBACKS
.destroystream
= ((NPN_DestroyStreamProcPtr
)_destroystream
);
221 CALLBACKS
.status
= ((NPN_StatusProcPtr
)_status
);
222 CALLBACKS
.uagent
= ((NPN_UserAgentProcPtr
)_useragent
);
223 CALLBACKS
.memalloc
= ((NPN_MemAllocProcPtr
)_memalloc
);
224 CALLBACKS
.memfree
= ((NPN_MemFreeProcPtr
)_memfree
);
225 CALLBACKS
.memflush
= ((NPN_MemFlushProcPtr
)_memflush
);
226 CALLBACKS
.reloadplugins
= ((NPN_ReloadPluginsProcPtr
)_reloadplugins
);
228 // Deprecated API callbacks.
229 CALLBACKS
.getJavaEnv
= ((NPN_GetJavaEnvProcPtr
)_getJavaEnv
);
230 CALLBACKS
.getJavaPeer
= ((NPN_GetJavaPeerProcPtr
)_getJavaPeer
);
231 CALLBACKS
.geturlnotify
= ((NPN_GetURLNotifyProcPtr
)_geturlnotify
);
232 CALLBACKS
.posturlnotify
= ((NPN_PostURLNotifyProcPtr
)_posturlnotify
);
233 CALLBACKS
.getvalue
= ((NPN_GetValueProcPtr
)_getvalue
);
234 CALLBACKS
.setvalue
= ((NPN_SetValueProcPtr
)_setvalue
);
235 CALLBACKS
.invalidaterect
= ((NPN_InvalidateRectProcPtr
)_invalidaterect
);
236 CALLBACKS
.invalidateregion
= ((NPN_InvalidateRegionProcPtr
)_invalidateregion
);
237 CALLBACKS
.forceredraw
= ((NPN_ForceRedrawProcPtr
)_forceredraw
);
238 CALLBACKS
.getstringidentifier
= ((NPN_GetStringIdentifierProcPtr
)_getstringidentifier
);
239 CALLBACKS
.getstringidentifiers
= ((NPN_GetStringIdentifiersProcPtr
)_getstringidentifiers
);
240 CALLBACKS
.getintidentifier
= ((NPN_GetIntIdentifierProcPtr
)_getintidentifier
);
241 CALLBACKS
.identifierisstring
= ((NPN_IdentifierIsStringProcPtr
)_identifierisstring
);
242 CALLBACKS
.utf8fromidentifier
= ((NPN_UTF8FromIdentifierProcPtr
)_utf8fromidentifier
);
243 CALLBACKS
.intfromidentifier
= ((NPN_IntFromIdentifierProcPtr
)_intfromidentifier
);
244 CALLBACKS
.createobject
= ((NPN_CreateObjectProcPtr
)_createobject
);
245 CALLBACKS
.retainobject
= ((NPN_RetainObjectProcPtr
)_retainobject
);
246 CALLBACKS
.releaseobject
= ((NPN_ReleaseObjectProcPtr
)_releaseobject
);
247 CALLBACKS
.invoke
= ((NPN_InvokeProcPtr
)_invoke
);
248 CALLBACKS
.invokeDefault
= ((NPN_InvokeDefaultProcPtr
)_invokeDefault
);
249 CALLBACKS
.evaluate
= ((NPN_EvaluateProcPtr
)_evaluate
);
250 CALLBACKS
.getproperty
= ((NPN_GetPropertyProcPtr
)_getproperty
);
251 CALLBACKS
.setproperty
= ((NPN_SetPropertyProcPtr
)_setproperty
);
252 CALLBACKS
.removeproperty
= ((NPN_RemovePropertyProcPtr
)_removeproperty
);
253 CALLBACKS
.hasproperty
= ((NPN_HasPropertyProcPtr
)_hasproperty
);
254 CALLBACKS
.hasmethod
= ((NPN_HasMethodProcPtr
)_hasmethod
);
255 CALLBACKS
.enumerate
= ((NPN_EnumerateProcPtr
)_enumerate
);
256 CALLBACKS
.construct
= ((NPN_ConstructProcPtr
)_construct
);
257 CALLBACKS
.releasevariantvalue
= ((NPN_ReleaseVariantValueProcPtr
)_releasevariantvalue
);
258 CALLBACKS
.setexception
= ((NPN_SetExceptionProcPtr
)_setexception
);
259 CALLBACKS
.pushpopupsenabledstate
= ((NPN_PushPopupsEnabledStateProcPtr
)_pushpopupsenabledstate
);
260 CALLBACKS
.poppopupsenabledstate
= ((NPN_PopPopupsEnabledStateProcPtr
)_poppopupsenabledstate
);
261 CALLBACKS
.pluginthreadasynccall
= ((NPN_PluginThreadAsyncCallProcPtr
)_pluginthreadasynccall
);
263 if (!sPluginThreadAsyncCallLock
)
264 sPluginThreadAsyncCallLock
= nsAutoLock::NewLock("sPluginThreadAsyncCallLock");
266 initialized
= PR_TRUE
;
268 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL
,("NPN callbacks initialized\n"));
271 NS_IMPL_ISUPPORTS2(nsNPAPIPlugin
, nsIPlugin
, nsIFactory
)
273 nsNPAPIPlugin::nsNPAPIPlugin(NPPluginFuncs
* callbacks
, PRLibrary
* aLibrary
,
274 NP_PLUGINSHUTDOWN aShutdown
)
276 memset((void*) &fCallbacks
, 0, sizeof(fCallbacks
));
279 #if defined(XP_WIN) || defined(XP_OS2)
280 // On Windows (and Mac) we need to keep a direct reference to the
281 // fCallbacks and NOT just copy the struct. See Bugzilla 85334
283 NP_GETENTRYPOINTS pfnGetEntryPoints
=
284 (NP_GETENTRYPOINTS
)PR_FindSymbol(aLibrary
, "NP_GetEntryPoints");
286 if (!pfnGetEntryPoints
)
289 fCallbacks
.size
= sizeof(fCallbacks
);
291 nsresult result
= pfnGetEntryPoints(&fCallbacks
);
292 NS_ASSERTION(result
== NS_OK
, "Failed to get callbacks");
294 NS_ASSERTION(HIBYTE(fCallbacks
.version
) >= NP_VERSION_MAJOR
,
295 "callback version is less than NP version");
297 fShutdownEntry
= (NP_PLUGINSHUTDOWN
)PR_FindSymbol(aLibrary
, "NP_Shutdown");
298 #elif defined(XP_MACOSX)
299 NPPluginFuncs np_callbacks
;
300 memset((void*) &np_callbacks
, 0, sizeof(np_callbacks
));
301 np_callbacks
.size
= sizeof(np_callbacks
);
303 fShutdownEntry
= (NP_PLUGINSHUTDOWN
)PR_FindSymbol(aLibrary
, "NP_Shutdown");
304 NP_GETENTRYPOINTS pfnGetEntryPoints
= (NP_GETENTRYPOINTS
)PR_FindSymbol(aLibrary
, "NP_GetEntryPoints");
305 NP_PLUGININIT pfnInitialize
= (NP_PLUGININIT
)PR_FindSymbol(aLibrary
, "NP_Initialize");
306 if (!pfnGetEntryPoints
|| !pfnInitialize
|| !fShutdownEntry
) {
307 NS_WARNING("Not all necessary functions exposed by plugin, it will not load.");
311 // we call NP_Initialize before getting function pointers to match
312 // WebKit's behavior. They implemented this first on Mac OS X.
313 if (pfnInitialize(&(nsNPAPIPlugin::CALLBACKS
)) != NPERR_NO_ERROR
)
315 if (pfnGetEntryPoints(&np_callbacks
) != NPERR_NO_ERROR
)
318 fCallbacks
.size
= sizeof(fCallbacks
);
319 fCallbacks
.version
= np_callbacks
.version
;
320 fCallbacks
.newp
= (NPP_NewProcPtr
)np_callbacks
.newp
;
321 fCallbacks
.destroy
= (NPP_DestroyProcPtr
)np_callbacks
.destroy
;
322 fCallbacks
.setwindow
= (NPP_SetWindowProcPtr
)np_callbacks
.setwindow
;
323 fCallbacks
.newstream
= (NPP_NewStreamProcPtr
)np_callbacks
.newstream
;
324 fCallbacks
.destroystream
= (NPP_DestroyStreamProcPtr
)np_callbacks
.destroystream
;
325 fCallbacks
.asfile
= (NPP_StreamAsFileProcPtr
)np_callbacks
.asfile
;
326 fCallbacks
.writeready
= (NPP_WriteReadyProcPtr
)np_callbacks
.writeready
;
327 fCallbacks
.write
= (NPP_WriteProcPtr
)np_callbacks
.write
;
328 fCallbacks
.print
= (NPP_PrintProcPtr
)np_callbacks
.print
;
329 fCallbacks
.event
= (NPP_HandleEventProcPtr
)np_callbacks
.event
;
330 fCallbacks
.urlnotify
= (NPP_URLNotifyProcPtr
)np_callbacks
.urlnotify
;
331 fCallbacks
.getvalue
= (NPP_GetValueProcPtr
)np_callbacks
.getvalue
;
332 fCallbacks
.setvalue
= (NPP_SetValueProcPtr
)np_callbacks
.setvalue
;
333 #else // for everyone else
334 memcpy((void*) &fCallbacks
, (void*) callbacks
, sizeof(fCallbacks
));
335 fShutdownEntry
= aShutdown
;
341 nsNPAPIPlugin::~nsNPAPIPlugin(void)
343 // reset the callbacks list
344 memset((void*) &fCallbacks
, 0, sizeof(fCallbacks
));
348 #if defined(XP_MACOSX)
350 nsNPAPIPlugin::SetPluginRefNum(short aRefNum
)
352 fPluginRefNum
= aRefNum
;
356 // Creates the nsNPAPIPlugin object. One nsNPAPIPlugin object exists per plugin (not instance).
358 nsNPAPIPlugin::CreatePlugin(const char* aFileName
, const char* aFullPath
,
359 PRLibrary
* aLibrary
, nsIPlugin
** aResult
)
361 CheckClassInitialized();
363 #if defined(XP_UNIX) && !defined(XP_MACOSX)
364 nsNPAPIPlugin
*plptr
;
366 NPPluginFuncs callbacks
;
367 memset((void*) &callbacks
, 0, sizeof(callbacks
));
368 callbacks
.size
= sizeof(callbacks
);
370 NP_PLUGINSHUTDOWN pfnShutdown
=
371 (NP_PLUGINSHUTDOWN
)PR_FindFunctionSymbol(aLibrary
, "NP_Shutdown");
373 // create the new plugin handler
375 new nsNPAPIPlugin(&callbacks
, aLibrary
, pfnShutdown
);
377 if (*aResult
== NULL
)
378 return NS_ERROR_OUT_OF_MEMORY
;
382 if (!aFileName
) //do not call NP_Initialize in this case, bug 74938
385 // we must init here because the plugin may call NPN functions
386 // when we call into the NP_Initialize entry point - NPN functions
387 // require that mBrowserManager be set up
390 NP_PLUGINUNIXINIT pfnInitialize
=
391 (NP_PLUGINUNIXINIT
)PR_FindFunctionSymbol(aLibrary
, "NP_Initialize");
394 return NS_ERROR_UNEXPECTED
;
396 if (pfnInitialize(&(nsNPAPIPlugin::CALLBACKS
),&callbacks
) != NS_OK
)
397 return NS_ERROR_UNEXPECTED
;
399 // now copy function table back to nsNPAPIPlugin instance
400 memcpy((void*) &(plptr
->fCallbacks
), (void*)&callbacks
, sizeof(callbacks
));
404 // Note: on Windows, we must use the fCallback because plugins may
405 // change the function table. The Shockwave installer makes changes
406 // in the table while running
407 *aResult
= new nsNPAPIPlugin(nsnull
, aLibrary
, nsnull
);
409 if (*aResult
== NULL
)
410 return NS_ERROR_OUT_OF_MEMORY
;
414 // we must init here because the plugin may call NPN functions
415 // when we call into the NP_Initialize entry point - NPN functions
416 // require that mBrowserManager be set up
417 if (NS_FAILED((*aResult
)->Initialize())) {
418 NS_RELEASE(*aResult
);
419 return NS_ERROR_FAILURE
;
422 NP_PLUGININIT pfnInitialize
=
423 (NP_PLUGININIT
)PR_FindSymbol(aLibrary
, "NP_Initialize");
426 return NS_ERROR_UNEXPECTED
;
428 if (pfnInitialize(&(nsNPAPIPlugin::CALLBACKS
)) != NS_OK
)
429 return NS_ERROR_UNEXPECTED
;
433 // create the new plugin handler
434 *aResult
= new nsNPAPIPlugin(nsnull
, aLibrary
, nsnull
);
436 if (*aResult
== NULL
)
437 return NS_ERROR_OUT_OF_MEMORY
;
441 // we must init here because the plugin may call NPN functions
442 // when we call into the NP_Initialize entry point - NPN functions
443 // require that mBrowserManager be set up
444 if (NS_FAILED((*aResult
)->Initialize())) {
445 NS_RELEASE(*aResult
);
446 return NS_ERROR_FAILURE
;
449 NP_PLUGININIT pfnInitialize
=
450 (NP_PLUGININIT
)PR_FindSymbol(aLibrary
, "NP_Initialize");
453 return NS_ERROR_UNEXPECTED
;
455 // Fixes problem where the OS/2 native multimedia plugins weren't
456 // working on mozilla though did work on 4.x. Problem is that they
457 // expect the current working directory to be the plugins dir.
458 // Since these plugins are no longer maintained and they represent
459 // the majority of the OS/2 plugin contingency, we'll have to make
462 #define MAP_DISKNUM_TO_LETTER(n) ('A' + (n - 1))
463 #define MAP_LETTER_TO_DISKNUM(c) (toupper(c)-'A'+1)
465 unsigned long origDiskNum
, pluginDiskNum
, logicalDisk
;
467 char pluginPath
[CCHMAXPATH
], origPath
[CCHMAXPATH
];
468 strcpy(pluginPath
, aFileName
);
469 char* slash
= strrchr(pluginPath
, '\\');
472 DosQueryCurrentDisk( &origDiskNum
, &logicalDisk
);
473 pluginDiskNum
= MAP_LETTER_TO_DISKNUM(pluginPath
[0]);
475 origPath
[0] = MAP_DISKNUM_TO_LETTER(origDiskNum
);
479 ULONG len
= CCHMAXPATH
-3;
480 APIRET rc
= DosQueryCurrentDir(0, &origPath
[3], &len
);
481 NS_ASSERTION(NO_ERROR
== rc
,"DosQueryCurrentDir failed");
483 BOOL bChangedDir
= FALSE
;
484 BOOL bChangedDisk
= FALSE
;
485 if (pluginDiskNum
!= origDiskNum
) {
486 rc
= DosSetDefaultDisk(pluginDiskNum
);
487 NS_ASSERTION(NO_ERROR
== rc
,"DosSetDefaultDisk failed");
491 if (stricmp(origPath
, pluginPath
) != 0) {
492 rc
= DosSetCurrentDir(pluginPath
);
493 NS_ASSERTION(NO_ERROR
== rc
,"DosSetCurrentDir failed");
497 nsresult rv
= pfnInitialize(&(nsNPAPIPlugin::CALLBACKS
));
500 rc
= DosSetDefaultDisk(origDiskNum
);
501 NS_ASSERTION(NO_ERROR
== rc
,"DosSetDefaultDisk failed");
504 rc
= DosSetCurrentDir(origPath
);
505 NS_ASSERTION(NO_ERROR
== rc
,"DosSetCurrentDir failed");
508 if (!NS_SUCCEEDED(rv
)) {
509 return NS_ERROR_UNEXPECTED
;
513 #if defined(XP_MACOSX)
514 short appRefNum
= ::CurResFile();
517 nsCOMPtr
<nsILocalFile
> pluginPath
;
518 NS_NewNativeLocalFile(nsDependentCString(aFullPath
), PR_TRUE
,
519 getter_AddRefs(pluginPath
));
521 nsPluginFile
pluginFile(pluginPath
);
522 pluginRefNum
= pluginFile
.OpenPluginResource();
524 nsNPAPIPlugin
* plugin
= new nsNPAPIPlugin(nsnull
, aLibrary
, nsnull
);
525 ::UseResFile(appRefNum
);
527 return NS_ERROR_OUT_OF_MEMORY
;
532 if (NS_FAILED((*aResult
)->Initialize())) {
533 NS_RELEASE(*aResult
);
534 return NS_ERROR_FAILURE
;
537 plugin
->SetPluginRefNum(pluginRefNum
);
541 // I just copied UNIX version.
542 // Makoto Hamanaka <VYA04230@nifty.com>
544 nsNPAPIPlugin
*plptr
;
546 NPPluginFuncs callbacks
;
547 memset((void*) &callbacks
, 0, sizeof(callbacks
));
548 callbacks
.size
= sizeof(callbacks
);
550 NP_PLUGINSHUTDOWN pfnShutdown
=
551 (NP_PLUGINSHUTDOWN
)PR_FindSymbol(aLibrary
, "NP_Shutdown");
553 // create the new plugin handler
554 *aResult
= plptr
= new nsNPAPIPlugin(&callbacks
, aLibrary
, pfnShutdown
);
556 if (*aResult
== NULL
)
557 return NS_ERROR_OUT_OF_MEMORY
;
561 // we must init here because the plugin may call NPN functions
562 // when we call into the NP_Initialize entry point - NPN functions
563 // require that mBrowserManager be set up
566 NP_PLUGINUNIXINIT pfnInitialize
=
567 (NP_PLUGINUNIXINIT
)PR_FindSymbol(aLibrary
, "NP_Initialize");
570 return NS_ERROR_FAILURE
;
572 if (pfnInitialize(&(nsNPAPIPlugin::CALLBACKS
),&callbacks
) != NS_OK
)
573 return NS_ERROR_FAILURE
;
575 // now copy function table back to nsNPAPIPlugin instance
576 memcpy((void*) &(plptr
->fCallbacks
), (void*)&callbacks
, sizeof(callbacks
));
583 nsNPAPIPlugin::CreateInstance(nsISupports
*aOuter
, const nsIID
&aIID
,
587 return NS_ERROR_NULL_POINTER
;
591 // XXX This is suspicuous!
592 nsRefPtr
<nsNPAPIPluginInstance
> inst
=
593 new nsNPAPIPluginInstance(&fCallbacks
, fLibrary
);
596 return NS_ERROR_OUT_OF_MEMORY
;
598 return inst
->QueryInterface(aIID
, aResult
);
602 nsNPAPIPlugin::LockFactory(PRBool aLock
)
604 // Not implemented in simplest case.
609 nsNPAPIPlugin::CreatePluginInstance(nsISupports
*aOuter
, REFNSIID aIID
,
610 const char *aPluginMIMEType
, void **aResult
)
612 return CreateInstance(aOuter
, aIID
, aResult
);
616 nsNPAPIPlugin::Initialize(void)
619 return NS_ERROR_FAILURE
;
624 nsNPAPIPlugin::Shutdown(void)
626 NPP_PLUGIN_LOG(PLUGIN_LOG_BASIC
,
627 ("NPP Shutdown to be called: this=%p\n", this));
629 if (fShutdownEntry
) {
630 #if defined(XP_MACOSX)
632 if (fPluginRefNum
> 0)
633 ::CloseResFile(fPluginRefNum
);
635 NS_TRY_SAFE_CALL_VOID(fShutdownEntry(), fLibrary
, nsnull
);
637 fShutdownEntry
= nsnull
;
640 PLUGIN_LOG(PLUGIN_LOG_NORMAL
,
641 ("NPAPIPlugin Shutdown done, this=%p", this));
646 nsNPAPIPlugin::GetMIMEDescription(const char* *resultingDesc
)
648 const char* (*npGetMIMEDescription
)() =
649 (const char* (*)()) PR_FindFunctionSymbol(fLibrary
, "NP_GetMIMEDescription");
651 *resultingDesc
= npGetMIMEDescription
? npGetMIMEDescription() : "";
653 PLUGIN_LOG(PLUGIN_LOG_NORMAL
,
654 ("nsNPAPIPlugin::GetMIMEDescription called: this=%p, result=%s\n",
655 this, *resultingDesc
));
661 nsNPAPIPlugin::GetValue(nsPluginVariable variable
, void *value
)
663 PLUGIN_LOG(PLUGIN_LOG_NORMAL
,
664 ("nsNPAPIPlugin::GetValue called: this=%p, variable=%d\n", this, variable
));
666 NPError (*npGetValue
)(void*, nsPluginVariable
, void*) =
667 (NPError (*)(void*, nsPluginVariable
, void*)) PR_FindFunctionSymbol(fLibrary
,
670 if (npGetValue
&& NPERR_NO_ERROR
== npGetValue(nsnull
, variable
, value
)) {
674 return NS_ERROR_FAILURE
;
677 // Create a new NPP GET or POST (given in the type argument) url
678 // stream that may have a notify callback
680 MakeNewNPAPIStreamInternal(NPP npp
, const char *relativeURL
, const char *target
,
681 eNPPStreamTypeInternal type
,
682 PRBool bDoNotify
= PR_FALSE
,
683 void *notifyData
= nsnull
, uint32_t len
= 0,
684 const char *buf
= nsnull
, NPBool file
= PR_FALSE
)
687 return NPERR_INVALID_INSTANCE_ERROR
;
689 PluginDestructionGuard
guard(npp
);
691 nsIPluginInstance
*inst
= (nsIPluginInstance
*) npp
->ndata
;
693 NS_ASSERTION(inst
, "null instance");
695 return NPERR_INVALID_INSTANCE_ERROR
;
697 nsCOMPtr
<nsIPluginManager
> pm
= do_GetService(kPluginManagerCID
);
698 NS_ASSERTION(pm
, "failed to get plugin manager");
699 if (!pm
) return NPERR_GENERIC_ERROR
;
701 nsCOMPtr
<nsIPluginStreamListener
> listener
;
703 ((nsNPAPIPluginInstance
*)inst
)->NewNotifyStream(getter_AddRefs(listener
),
705 bDoNotify
, relativeURL
);
708 case eNPPStreamTypeInternal_Get
:
710 if (NS_FAILED(pm
->GetURL(inst
, relativeURL
, target
, listener
)))
711 return NPERR_GENERIC_ERROR
;
714 case eNPPStreamTypeInternal_Post
:
716 if (NS_FAILED(pm
->PostURL(inst
, relativeURL
, len
, buf
, file
, target
,
718 return NPERR_GENERIC_ERROR
;
722 NS_ASSERTION(0, "how'd I get here");
725 return NPERR_NO_ERROR
;
729 // Static callbacks that get routed back through the new C++ API
733 _geturl(NPP npp
, const char* relativeURL
, const char* target
)
735 if (!NS_IsMainThread()) {
736 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_geturl called from the wrong thread\n"));
737 return NPERR_INVALID_PARAM
;
740 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL
,
741 ("NPN_GetURL: npp=%p, target=%s, url=%s\n", (void *)npp
, target
,
744 PluginDestructionGuard
guard(npp
);
746 // Block Adobe Acrobat from loading URLs that are not http:, https:,
747 // or ftp: URLs if the given target is null.
748 if (!target
&& relativeURL
&&
749 (strncmp(relativeURL
, "http:", 5) != 0) &&
750 (strncmp(relativeURL
, "https:", 6) != 0) &&
751 (strncmp(relativeURL
, "ftp:", 4) != 0)) {
752 nsNPAPIPluginInstance
*inst
= (nsNPAPIPluginInstance
*) npp
->ndata
;
754 const char *name
= nsPluginHostImpl::GetPluginName(inst
);
756 if (name
&& strstr(name
, "Adobe") && strstr(name
, "Acrobat")) {
757 return NPERR_NO_ERROR
;
761 return MakeNewNPAPIStreamInternal(npp
, relativeURL
, target
,
762 eNPPStreamTypeInternal_Get
);
766 _geturlnotify(NPP npp
, const char* relativeURL
, const char* target
,
769 if (!NS_IsMainThread()) {
770 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_geturlnotify called from the wrong thread\n"));
771 return NPERR_INVALID_PARAM
;
774 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL
,
775 ("NPN_GetURLNotify: npp=%p, target=%s, notify=%p, url=%s\n", (void*)npp
,
776 target
, notifyData
, relativeURL
));
778 PluginDestructionGuard
guard(npp
);
780 return MakeNewNPAPIStreamInternal(npp
, relativeURL
, target
,
781 eNPPStreamTypeInternal_Get
, PR_TRUE
,
786 _posturlnotify(NPP npp
, const char *relativeURL
, const char *target
,
787 uint32_t len
, const char *buf
, NPBool file
, void *notifyData
)
789 if (!NS_IsMainThread()) {
790 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_posturlnotify called from the wrong thread\n"));
791 return NPERR_INVALID_PARAM
;
793 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL
,
794 ("NPN_PostURLNotify: npp=%p, target=%s, len=%d, file=%d, "
795 "notify=%p, url=%s, buf=%s\n",
796 (void*)npp
, target
, len
, file
, notifyData
, relativeURL
,
799 PluginDestructionGuard
guard(npp
);
801 return MakeNewNPAPIStreamInternal(npp
, relativeURL
, target
,
802 eNPPStreamTypeInternal_Post
, PR_TRUE
,
803 notifyData
, len
, buf
, file
);
807 _posturl(NPP npp
, const char *relativeURL
, const char *target
,
808 uint32_t len
, const char *buf
, NPBool file
)
810 if (!NS_IsMainThread()) {
811 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_posturl called from the wrong thread\n"));
812 return NPERR_INVALID_PARAM
;
814 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL
,
815 ("NPN_PostURL: npp=%p, target=%s, file=%d, len=%d, url=%s, "
817 (void*)npp
, target
, file
, len
, relativeURL
, buf
));
819 PluginDestructionGuard
guard(npp
);
821 return MakeNewNPAPIStreamInternal(npp
, relativeURL
, target
,
822 eNPPStreamTypeInternal_Post
, PR_FALSE
, nsnull
,
826 // A little helper class used to wrap up plugin manager streams (that is,
827 // streams from the plugin to the browser).
828 class nsNPAPIStreamWrapper
: nsISupports
834 nsIOutputStream
*fStream
;
838 nsNPAPIStreamWrapper(nsIOutputStream
* stream
);
839 ~nsNPAPIStreamWrapper();
841 void GetStream(nsIOutputStream
* &result
);
842 NPStream
* GetNPStream(void) { return &fNPStream
; }
845 NS_IMPL_ISUPPORTS1(nsNPAPIStreamWrapper
, nsISupports
)
847 nsNPAPIStreamWrapper::nsNPAPIStreamWrapper(nsIOutputStream
* stream
)
850 NS_ASSERTION(stream
, "bad stream");
855 memset(&fNPStream
, 0, sizeof(fNPStream
));
856 fNPStream
.ndata
= (void*) this;
859 nsNPAPIStreamWrapper::~nsNPAPIStreamWrapper(void)
862 NS_IF_RELEASE(fStream
);
866 nsNPAPIStreamWrapper::GetStream(nsIOutputStream
* &result
)
869 NS_IF_ADDREF(fStream
);
873 _newstream(NPP npp
, NPMIMEType type
, const char* target
, NPStream
* *result
)
875 if (!NS_IsMainThread()) {
876 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_newstream called from the wrong thread\n"));
877 return NPERR_INVALID_PARAM
;
879 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL
,
880 ("NPN_NewStream: npp=%p, type=%s, target=%s\n", (void*)npp
,
881 (const char *)type
, target
));
883 NPError err
= NPERR_INVALID_INSTANCE_ERROR
;
884 if (npp
&& npp
->ndata
) {
885 nsIPluginInstance
*inst
= (nsIPluginInstance
*) npp
->ndata
;
887 PluginDestructionGuard
guard(inst
);
889 nsCOMPtr
<nsIOutputStream
> stream
;
890 nsCOMPtr
<nsIPluginInstancePeer
> peer
;
891 if (NS_SUCCEEDED(inst
->GetPeer(getter_AddRefs(peer
))) &&
893 NS_SUCCEEDED(peer
->NewStream((const char*) type
, target
,
894 getter_AddRefs(stream
)))) {
895 nsNPAPIStreamWrapper
* wrapper
= new nsNPAPIStreamWrapper(stream
);
897 (*result
) = wrapper
->GetNPStream();
898 err
= NPERR_NO_ERROR
;
900 err
= NPERR_OUT_OF_MEMORY_ERROR
;
903 err
= NPERR_GENERIC_ERROR
;
910 _write(NPP npp
, NPStream
*pstream
, int32_t len
, void *buffer
)
912 if (!NS_IsMainThread()) {
913 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_write called from the wrong thread\n"));
916 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL
,
917 ("NPN_Write: npp=%p, url=%s, len=%d, buffer=%s\n", (void*)npp
,
918 pstream
->url
, len
, (char*)buffer
));
920 // negative return indicates failure to the plugin
924 PluginDestructionGuard
guard(npp
);
926 nsNPAPIStreamWrapper
* wrapper
= (nsNPAPIStreamWrapper
*) pstream
->ndata
;
927 NS_ASSERTION(wrapper
, "null stream");
931 nsIOutputStream
* stream
;
932 wrapper
->GetStream(stream
);
935 nsresult rv
= stream
->Write((char *)buffer
, len
, &count
);
941 return (int32_t)count
;
945 _destroystream(NPP npp
, NPStream
*pstream
, NPError reason
)
947 if (!NS_IsMainThread()) {
948 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_write called from the wrong thread\n"));
949 return NPERR_INVALID_PARAM
;
951 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL
,
952 ("NPN_DestroyStream: npp=%p, url=%s, reason=%d\n", (void*)npp
,
953 pstream
->url
, (int)reason
));
956 return NPERR_INVALID_INSTANCE_ERROR
;
958 PluginDestructionGuard
guard(npp
);
960 nsCOMPtr
<nsIPluginStreamListener
> listener
=
961 do_QueryInterface((nsISupports
*)pstream
->ndata
);
963 // DestroyStream can kill two kinds of streams: NPP derived and NPN derived.
964 // check to see if they're trying to kill a NPP stream
966 // Tell the stream listner that the stream is now gone.
967 listener
->OnStopBinding(nsnull
, NS_BINDING_ABORTED
);
969 // FIXME: http://bugzilla.mozilla.org/show_bug.cgi?id=240131
971 // Is it ok to leave pstream->ndata set here, and who releases it
972 // (or is it even properly ref counted)? And who closes the stream
975 nsNPAPIStreamWrapper
* wrapper
= (nsNPAPIStreamWrapper
*)pstream
->ndata
;
976 NS_ASSERTION(wrapper
, "null wrapper");
979 return NPERR_INVALID_PARAM
;
981 // This will release the wrapped nsIOutputStream.
983 pstream
->ndata
= nsnull
;
986 return NPERR_NO_ERROR
;
990 _status(NPP npp
, const char *message
)
992 if (!NS_IsMainThread()) {
993 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_status called from the wrong thread\n"));
996 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL
, ("NPN_Status: npp=%p, message=%s\n",
997 (void*)npp
, message
));
999 if (!npp
|| !npp
->ndata
) {
1000 NS_WARNING("_status: npp or npp->ndata == 0");
1004 nsIPluginInstance
*inst
= (nsIPluginInstance
*) npp
->ndata
;
1006 PluginDestructionGuard
guard(inst
);
1008 nsCOMPtr
<nsIPluginInstancePeer
> peer
;
1009 if (NS_SUCCEEDED(inst
->GetPeer(getter_AddRefs(peer
))) && peer
) {
1010 peer
->ShowStatus(message
);
1015 _memfree (void *ptr
)
1017 if (!NS_IsMainThread()) {
1018 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_memfree called from the wrong thread\n"));
1020 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY
, ("NPN_MemFree: ptr=%p\n", ptr
));
1023 nsMemory::Free(ptr
);
1026 uint32_t NP_CALLBACK
1027 _memflush(uint32_t size
)
1029 if (!NS_IsMainThread()) {
1030 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_memflush called from the wrong thread\n"));
1032 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY
, ("NPN_MemFlush: size=%d\n", size
));
1034 nsMemory::HeapMinimize(PR_TRUE
);
1039 _reloadplugins(NPBool reloadPages
)
1041 if (!NS_IsMainThread()) {
1042 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_reloadplugins called from the wrong thread\n"));
1045 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL
,
1046 ("NPN_ReloadPlugins: reloadPages=%d\n", reloadPages
));
1048 nsCOMPtr
<nsIPluginManager
> pm(do_GetService(kPluginManagerCID
));
1052 pm
->ReloadPlugins(reloadPages
);
1056 _invalidaterect(NPP npp
, NPRect
*invalidRect
)
1058 if (!NS_IsMainThread()) {
1059 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_invalidaterect called from the wrong thread\n"));
1062 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL
,
1063 ("NPN_InvalidateRect: npp=%p, top=%d, left=%d, bottom=%d, "
1064 "right=%d\n", (void *)npp
, invalidRect
->top
,
1065 invalidRect
->left
, invalidRect
->bottom
, invalidRect
->right
));
1067 if (!npp
|| !npp
->ndata
) {
1068 NS_WARNING("_invalidaterect: npp or npp->ndata == 0");
1072 nsIPluginInstance
*inst
= (nsIPluginInstance
*) npp
->ndata
;
1074 PluginDestructionGuard
guard(inst
);
1076 nsCOMPtr
<nsIPluginInstancePeer
> peer
;
1077 if (NS_SUCCEEDED(inst
->GetPeer(getter_AddRefs(peer
))) && peer
) {
1078 nsCOMPtr
<nsIWindowlessPluginInstancePeer
> wpeer(do_QueryInterface(peer
));
1080 // XXX nsRect & NPRect are structurally equivalent
1081 wpeer
->InvalidateRect((nsPluginRect
*)invalidRect
);
1087 _invalidateregion(NPP npp
, NPRegion invalidRegion
)
1089 if (!NS_IsMainThread()) {
1090 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_invalidateregion called from the wrong thread\n"));
1093 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL
,
1094 ("NPN_InvalidateRegion: npp=%p, region=%p\n", (void*)npp
,
1095 (void*)invalidRegion
));
1097 if (!npp
|| !npp
->ndata
) {
1098 NS_WARNING("_invalidateregion: npp or npp->ndata == 0");
1102 nsIPluginInstance
*inst
= (nsIPluginInstance
*)npp
->ndata
;
1104 PluginDestructionGuard
guard(inst
);
1106 nsCOMPtr
<nsIPluginInstancePeer
> peer
;
1107 if (NS_SUCCEEDED(inst
->GetPeer(getter_AddRefs(peer
))) && peer
) {
1108 nsCOMPtr
<nsIWindowlessPluginInstancePeer
> wpeer(do_QueryInterface(peer
));
1110 // nsPluginRegion & NPRegion are typedef'd to the same thing
1111 wpeer
->InvalidateRegion((nsPluginRegion
)invalidRegion
);
1117 _forceredraw(NPP npp
)
1119 if (!NS_IsMainThread()) {
1120 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_forceredraw called from the wrong thread\n"));
1123 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL
, ("NPN_ForceDraw: npp=%p\n", (void*)npp
));
1125 if (!npp
|| !npp
->ndata
) {
1126 NS_WARNING("_forceredraw: npp or npp->ndata == 0");
1130 nsIPluginInstance
*inst
= (nsIPluginInstance
*) npp
->ndata
;
1132 PluginDestructionGuard
guard(inst
);
1134 nsCOMPtr
<nsIPluginInstancePeer
> peer
;
1135 if (NS_SUCCEEDED(inst
->GetPeer(getter_AddRefs(peer
))) && peer
) {
1136 nsCOMPtr
<nsIWindowlessPluginInstancePeer
> wpeer(do_QueryInterface(peer
));
1138 wpeer
->ForceRedraw();
1143 static nsIDocument
*
1144 GetDocumentFromNPP(NPP npp
)
1146 NS_ENSURE_TRUE(npp
, nsnull
);
1148 nsNPAPIPluginInstance
*inst
= (nsNPAPIPluginInstance
*)npp
->ndata
;
1149 NS_ENSURE_TRUE(inst
, nsnull
);
1151 PluginDestructionGuard
guard(inst
);
1153 nsCOMPtr
<nsIPluginInstancePeer
> pip
;
1154 inst
->GetPeer(getter_AddRefs(pip
));
1155 nsCOMPtr
<nsPIPluginInstancePeer
> pp(do_QueryInterface(pip
));
1156 NS_ENSURE_TRUE(pp
, nsnull
);
1158 nsCOMPtr
<nsIPluginInstanceOwner
> owner
;
1159 pp
->GetOwner(getter_AddRefs(owner
));
1160 NS_ENSURE_TRUE(owner
, nsnull
);
1162 nsCOMPtr
<nsIDocument
> doc
;
1163 owner
->GetDocument(getter_AddRefs(doc
));
1169 GetJSContextFromDoc(nsIDocument
*doc
)
1171 nsIScriptGlobalObject
*sgo
= doc
->GetScriptGlobalObject();
1172 NS_ENSURE_TRUE(sgo
, nsnull
);
1174 nsIScriptContext
*scx
= sgo
->GetContext();
1175 NS_ENSURE_TRUE(scx
, nsnull
);
1177 return (JSContext
*)scx
->GetNativeContext();
1181 GetJSContextFromNPP(NPP npp
)
1183 nsIDocument
*doc
= GetDocumentFromNPP(npp
);
1184 NS_ENSURE_TRUE(doc
, nsnull
);
1186 return GetJSContextFromDoc(doc
);
1189 NPObject
* NP_CALLBACK
1190 _getwindowobject(NPP npp
)
1192 if (!NS_IsMainThread()) {
1193 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_getwindowobject called from the wrong thread\n"));
1196 JSContext
*cx
= GetJSContextFromNPP(npp
);
1197 NS_ENSURE_TRUE(cx
, nsnull
);
1199 // Using ::JS_GetGlobalObject(cx) is ok here since the window we
1200 // want to return here is the outer window, *not* the inner (since
1201 // we don't know what the plugin will do with it).
1202 return nsJSObjWrapper::GetNewOrUsed(npp
, cx
, ::JS_GetGlobalObject(cx
));
1205 NPObject
* NP_CALLBACK
1206 _getpluginelement(NPP npp
)
1208 if (!NS_IsMainThread()) {
1209 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_getpluginelement called from the wrong thread\n"));
1212 nsIDOMElement
*elementp
= nsnull
;
1213 NPError nperr
= _getvalue(npp
, NPNVDOMElement
, &elementp
);
1215 if (nperr
!= NPERR_NO_ERROR
) {
1219 // Pass ownership of elementp to element
1220 nsCOMPtr
<nsIDOMElement
> element
;
1221 element
.swap(elementp
);
1223 JSContext
*cx
= GetJSContextFromNPP(npp
);
1224 NS_ENSURE_TRUE(cx
, nsnull
);
1226 nsCOMPtr
<nsIXPConnect
> xpc(do_GetService(nsIXPConnect::GetCID()));
1227 NS_ENSURE_TRUE(xpc
, nsnull
);
1229 nsCOMPtr
<nsIXPConnectJSObjectHolder
> holder
;
1230 xpc
->WrapNative(cx
, ::JS_GetGlobalObject(cx
), element
,
1231 NS_GET_IID(nsIDOMElement
),
1232 getter_AddRefs(holder
));
1233 NS_ENSURE_TRUE(holder
, nsnull
);
1235 JSObject
* obj
= nsnull
;
1236 holder
->GetJSObject(&obj
);
1237 NS_ENSURE_TRUE(obj
, nsnull
);
1239 return nsJSObjWrapper::GetNewOrUsed(npp
, cx
, obj
);
1243 doGetIdentifier(JSContext
*cx
, const NPUTF8
* name
)
1245 NS_ConvertUTF8toUTF16
utf16name(name
);
1247 JSString
*str
= ::JS_InternUCStringN(cx
, (jschar
*)utf16name
.get(),
1248 utf16name
.Length());
1253 return (NPIdentifier
)STRING_TO_JSVAL(str
);
1256 NPIdentifier NP_CALLBACK
1257 _getstringidentifier(const NPUTF8
* name
)
1260 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
, ("NPN_getstringidentifier: passed null name"));
1263 if (!NS_IsMainThread()) {
1264 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_getstringidentifier called from the wrong thread\n"));
1267 nsCOMPtr
<nsIThreadJSContextStack
> stack
=
1268 do_GetService("@mozilla.org/js/xpc/ContextStack;1");
1272 JSContext
*cx
= nsnull
;
1273 stack
->GetSafeJSContext(&cx
);
1277 JSAutoRequest
ar(cx
);
1278 return doGetIdentifier(cx
, name
);
1282 _getstringidentifiers(const NPUTF8
** names
, int32_t nameCount
,
1283 NPIdentifier
*identifiers
)
1285 if (!NS_IsMainThread()) {
1286 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_getstringidentifiers called from the wrong thread\n"));
1288 nsCOMPtr
<nsIThreadJSContextStack
> stack
=
1289 do_GetService("@mozilla.org/js/xpc/ContextStack;1");
1293 JSContext
*cx
= nsnull
;
1294 stack
->GetSafeJSContext(&cx
);
1298 JSAutoRequest
ar(cx
);
1300 for (int32_t i
= 0; i
< nameCount
; ++i
) {
1302 identifiers
[i
] = doGetIdentifier(cx
, names
[i
]);
1304 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
, ("NPN_getstringidentifiers: passed null name"));
1305 identifiers
[i
] = NULL
;
1310 NPIdentifier NP_CALLBACK
1311 _getintidentifier(int32_t intid
)
1313 if (!NS_IsMainThread()) {
1314 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_getstringidentifier called from the wrong thread\n"));
1316 return (NPIdentifier
)INT_TO_JSVAL(intid
);
1320 _utf8fromidentifier(NPIdentifier identifier
)
1322 if (!NS_IsMainThread()) {
1323 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_utf8fromidentifier called from the wrong thread\n"));
1328 jsval v
= (jsval
)identifier
;
1330 if (!JSVAL_IS_STRING(v
)) {
1334 JSString
*str
= JSVAL_TO_STRING(v
);
1337 ToNewUTF8String(nsDependentString((PRUnichar
*)::JS_GetStringChars(str
),
1338 ::JS_GetStringLength(str
)));
1342 _intfromidentifier(NPIdentifier identifier
)
1344 if (!NS_IsMainThread()) {
1345 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_intfromidentifier called from the wrong thread\n"));
1347 jsval v
= (jsval
)identifier
;
1349 if (!JSVAL_IS_INT(v
)) {
1350 return PR_INT32_MIN
;
1353 return JSVAL_TO_INT(v
);
1357 _identifierisstring(NPIdentifier identifier
)
1359 if (!NS_IsMainThread()) {
1360 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_identifierisstring called from the wrong thread\n"));
1362 jsval v
= (jsval
)identifier
;
1364 return JSVAL_IS_STRING(v
);
1367 NPObject
* NP_CALLBACK
1368 _createobject(NPP npp
, NPClass
* aClass
)
1370 if (!NS_IsMainThread()) {
1371 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_createobject called from the wrong thread\n"));
1375 NS_ERROR("Null npp passed to _createobject()!");
1380 PluginDestructionGuard
guard(npp
);
1383 NS_ERROR("Null class passed to _createobject()!");
1388 NPPAutoPusher
nppPusher(npp
);
1392 if (aClass
->allocate
) {
1393 npobj
= aClass
->allocate(npp
, aClass
);
1395 npobj
= (NPObject
*)PR_Malloc(sizeof(NPObject
));
1399 npobj
->_class
= aClass
;
1400 npobj
->referenceCount
= 1;
1403 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY
,
1404 ("Created NPObject %p, NPClass %p\n", npobj
, aClass
));
1409 NPObject
* NP_CALLBACK
1410 _retainobject(NPObject
* npobj
)
1412 if (!NS_IsMainThread()) {
1413 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_retainobject called from the wrong thread\n"));
1416 PR_AtomicIncrement((PRInt32
*)&npobj
->referenceCount
);
1423 _releaseobject(NPObject
* npobj
)
1425 if (!NS_IsMainThread()) {
1426 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_releaseobject called from the wrong thread\n"));
1431 int32_t refCnt
= PR_AtomicDecrement((PRInt32
*)&npobj
->referenceCount
);
1434 nsNPObjWrapper::OnDestroy(npobj
);
1436 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY
,
1437 ("Deleting NPObject %p, refcount hit 0\n", npobj
));
1439 if (npobj
->_class
&& npobj
->_class
->deallocate
) {
1440 npobj
->_class
->deallocate(npobj
);
1448 _invoke(NPP npp
, NPObject
* npobj
, NPIdentifier method
, const NPVariant
*args
,
1449 uint32_t argCount
, NPVariant
*result
)
1451 if (!NS_IsMainThread()) {
1452 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_invoke called from the wrong thread\n"));
1455 if (!npp
|| !npobj
|| !npobj
->_class
|| !npobj
->_class
->invoke
)
1458 PluginDestructionGuard
guard(npp
);
1460 NPPExceptionAutoHolder nppExceptionHolder
;
1461 NPPAutoPusher
nppPusher(npp
);
1463 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY
,
1464 ("NPN_Invoke(npp %p, npobj %p, method %p, args %d\n", npp
,
1465 npobj
, method
, argCount
));
1467 return npobj
->_class
->invoke(npobj
, method
, args
, argCount
, result
);
1471 _invokeDefault(NPP npp
, NPObject
* npobj
, const NPVariant
*args
,
1472 uint32_t argCount
, NPVariant
*result
)
1474 if (!NS_IsMainThread()) {
1475 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_invokedefault called from the wrong thread\n"));
1478 if (!npp
|| !npobj
|| !npobj
->_class
|| !npobj
->_class
->invokeDefault
)
1481 NPPExceptionAutoHolder nppExceptionHolder
;
1482 NPPAutoPusher
nppPusher(npp
);
1484 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY
,
1485 ("NPN_InvokeDefault(npp %p, npobj %p, args %d\n", npp
,
1488 return npobj
->_class
->invokeDefault(npobj
, args
, argCount
, result
);
1492 _evaluate(NPP npp
, NPObject
* npobj
, NPString
*script
, NPVariant
*result
)
1494 if (!NS_IsMainThread()) {
1495 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_evaluate called from the wrong thread\n"));
1501 NPPAutoPusher
nppPusher(npp
);
1503 nsIDocument
*doc
= GetDocumentFromNPP(npp
);
1504 NS_ENSURE_TRUE(doc
, false);
1506 JSContext
*cx
= GetJSContextFromDoc(doc
);
1507 NS_ENSURE_TRUE(cx
, false);
1510 nsNPObjWrapper::GetNewOrUsed(npp
, cx
, npobj
);
1516 // Root obj and the rval (below).
1517 jsval vec
[] = { OBJECT_TO_JSVAL(obj
), JSVAL_NULL
};
1518 JSAutoTempValueRooter
tvr(cx
, NS_ARRAY_LENGTH(vec
), vec
);
1519 jsval
*rval
= &vec
[1];
1522 // Initialize the out param to void
1523 VOID_TO_NPVARIANT(*result
);
1526 if (!script
|| !script
->UTF8Length
|| !script
->UTF8Characters
) {
1527 // Nothing to evaluate.
1532 NS_ConvertUTF8toUTF16
utf16script(script
->UTF8Characters
,
1533 script
->UTF8Length
);
1535 nsCOMPtr
<nsIScriptContext
> scx
= GetScriptContextFromJSContext(cx
);
1536 NS_ENSURE_TRUE(scx
, false);
1538 nsIPrincipal
*principal
= doc
->NodePrincipal();
1540 nsCAutoString specStr
;
1543 nsCOMPtr
<nsIURI
> uri
;
1544 principal
->GetURI(getter_AddRefs(uri
));
1547 uri
->GetSpec(specStr
);
1548 spec
= specStr
.get();
1550 // No URI in a principal means it's the system principal. If the
1551 // document URI is a chrome:// URI, pass that in as the URI of the
1552 // script, else pass in null for the filename as there's no way to
1553 // know where this document really came from. Passing in null here
1554 // also means that the script gets treated by XPConnect as if it
1555 // needs additional protection, which is what we want for unknown
1556 // chrome code anyways.
1558 uri
= doc
->GetDocumentURI();
1559 PRBool isChrome
= PR_FALSE
;
1561 if (uri
&& NS_SUCCEEDED(uri
->SchemeIs("chrome", &isChrome
)) && isChrome
) {
1562 uri
->GetSpec(specStr
);
1563 spec
= specStr
.get();
1569 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY
,
1570 ("NPN_Evaluate(npp %p, npobj %p, script <<<%s>>>) called\n",
1571 npp
, npobj
, script
->UTF8Characters
));
1573 nsresult rv
= scx
->EvaluateStringWithValue(utf16script
, obj
, principal
,
1574 spec
, 0, 0, rval
, nsnull
);
1576 return NS_SUCCEEDED(rv
) &&
1577 (!result
|| JSValToNPVariant(npp
, cx
, *rval
, result
));
1581 _getproperty(NPP npp
, NPObject
* npobj
, NPIdentifier property
,
1584 if (!NS_IsMainThread()) {
1585 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_getproperty called from the wrong thread\n"));
1588 if (!npp
|| !npobj
|| !npobj
->_class
|| !npobj
->_class
->getProperty
)
1591 NPPExceptionAutoHolder nppExceptionHolder
;
1592 NPPAutoPusher
nppPusher(npp
);
1594 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY
,
1595 ("NPN_GetProperty(npp %p, npobj %p, property %p) called\n",
1596 npp
, npobj
, property
));
1598 return npobj
->_class
->getProperty(npobj
, property
, result
);
1602 _setproperty(NPP npp
, NPObject
* npobj
, NPIdentifier property
,
1603 const NPVariant
*value
)
1605 if (!NS_IsMainThread()) {
1606 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_setproperty called from the wrong thread\n"));
1609 if (!npp
|| !npobj
|| !npobj
->_class
|| !npobj
->_class
->setProperty
)
1612 NPPExceptionAutoHolder nppExceptionHolder
;
1613 NPPAutoPusher
nppPusher(npp
);
1615 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY
,
1616 ("NPN_SetProperty(npp %p, npobj %p, property %p) called\n",
1617 npp
, npobj
, property
));
1619 return npobj
->_class
->setProperty(npobj
, property
, value
);
1623 _removeproperty(NPP npp
, NPObject
* npobj
, NPIdentifier property
)
1625 if (!NS_IsMainThread()) {
1626 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_removeproperty called from the wrong thread\n"));
1629 if (!npp
|| !npobj
|| !npobj
->_class
|| !npobj
->_class
->removeProperty
)
1632 NPPExceptionAutoHolder nppExceptionHolder
;
1633 NPPAutoPusher
nppPusher(npp
);
1635 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY
,
1636 ("NPN_RemoveProperty(npp %p, npobj %p, property %p) called\n",
1637 npp
, npobj
, property
));
1639 return npobj
->_class
->removeProperty(npobj
, property
);
1643 _hasproperty(NPP npp
, NPObject
* npobj
, NPIdentifier propertyName
)
1645 if (!NS_IsMainThread()) {
1646 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_hasproperty called from the wrong thread\n"));
1649 if (!npp
|| !npobj
|| !npobj
->_class
|| !npobj
->_class
->hasProperty
)
1652 NPPExceptionAutoHolder nppExceptionHolder
;
1653 NPPAutoPusher
nppPusher(npp
);
1655 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY
,
1656 ("NPN_HasProperty(npp %p, npobj %p, property %p) called\n",
1657 npp
, npobj
, propertyName
));
1659 return npobj
->_class
->hasProperty(npobj
, propertyName
);
1663 _hasmethod(NPP npp
, NPObject
* npobj
, NPIdentifier methodName
)
1665 if (!NS_IsMainThread()) {
1666 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_hasmethod called from the wrong thread\n"));
1669 if (!npp
|| !npobj
|| !npobj
->_class
|| !npobj
->_class
->hasMethod
)
1672 NPPExceptionAutoHolder nppExceptionHolder
;
1673 NPPAutoPusher
nppPusher(npp
);
1675 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY
,
1676 ("NPN_HasMethod(npp %p, npobj %p, property %p) called\n",
1677 npp
, npobj
, methodName
));
1679 return npobj
->_class
->hasProperty(npobj
, methodName
);
1683 _enumerate(NPP npp
, NPObject
*npobj
, NPIdentifier
**identifier
,
1686 if (!NS_IsMainThread()) {
1687 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_enumerate called from the wrong thread\n"));
1690 if (!npp
|| !npobj
|| !npobj
->_class
)
1693 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY
,
1694 ("NPN_Enumerate(npp %p, npobj %p) called\n", npp
, npobj
));
1696 if (!NP_CLASS_STRUCT_VERSION_HAS_ENUM(npobj
->_class
) ||
1697 !npobj
->_class
->enumerate
) {
1703 NPPExceptionAutoHolder nppExceptionHolder
;
1704 NPPAutoPusher
nppPusher(npp
);
1706 return npobj
->_class
->enumerate(npobj
, identifier
, count
);
1710 _construct(NPP npp
, NPObject
* npobj
, const NPVariant
*args
,
1711 uint32_t argCount
, NPVariant
*result
)
1713 if (!NS_IsMainThread()) {
1714 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_construct called from the wrong thread\n"));
1717 if (!npp
|| !npobj
|| !npobj
->_class
||
1718 !NP_CLASS_STRUCT_VERSION_HAS_CTOR(npobj
->_class
) ||
1719 !npobj
->_class
->construct
) {
1723 NPPExceptionAutoHolder nppExceptionHolder
;
1724 NPPAutoPusher
nppPusher(npp
);
1726 return npobj
->_class
->construct(npobj
, args
, argCount
, result
);
1729 #ifdef MOZ_MEMORY_WINDOWS
1730 extern "C" size_t malloc_usable_size(const void *ptr
);
1733 InHeap(HANDLE hHeap
, LPVOID lpMem
)
1735 BOOL success
= FALSE
;
1736 PROCESS_HEAP_ENTRY he
;
1738 while (HeapWalk(hHeap
, &he
) != 0) {
1739 if (he
.lpData
== lpMem
) {
1750 _releasevariantvalue(NPVariant
* variant
)
1752 if (!NS_IsMainThread()) {
1753 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_releasevariantvalue called from the wrong thread\n"));
1755 switch (variant
->type
) {
1756 case NPVariantType_Void
:
1757 case NPVariantType_Null
:
1758 case NPVariantType_Bool
:
1759 case NPVariantType_Int32
:
1760 case NPVariantType_Double
:
1762 case NPVariantType_String
:
1764 const NPString
*s
= &NPVARIANT_TO_STRING(*variant
);
1766 if (s
->UTF8Characters
) {
1767 #ifdef MOZ_MEMORY_WINDOWS
1768 if (malloc_usable_size((void *)s
->UTF8Characters
) != 0) {
1769 PR_Free((void *)s
->UTF8Characters
);
1771 void *p
= (void *)s
->UTF8Characters
;
1773 nsAutoTArray
<HANDLE
, 50> heaps
;
1774 nheaps
= GetProcessHeaps(0, heaps
.Elements());
1775 heaps
.AppendElements(nheaps
);
1776 GetProcessHeaps(nheaps
, heaps
.Elements());
1777 for (DWORD i
= 0; i
< nheaps
; i
++) {
1778 if (InHeap(heaps
[i
], p
)) {
1779 HeapFree(heaps
[i
], 0, p
);
1785 PR_Free((void *)s
->UTF8Characters
);
1790 case NPVariantType_Object
:
1792 NPObject
*npobj
= NPVARIANT_TO_OBJECT(*variant
);
1795 _releaseobject(npobj
);
1800 NS_ERROR("Unknown NPVariant type!");
1803 VOID_TO_NPVARIANT(*variant
);
1807 _tostring(NPObject
* npobj
, NPVariant
*result
)
1809 NS_ERROR("Write me!");
1811 if (!NS_IsMainThread()) {
1812 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_tostring called from the wrong thread\n"));
1819 static char *gNPPException
;
1822 _setexception(NPObject
* npobj
, const NPUTF8
*message
)
1824 if (!NS_IsMainThread()) {
1825 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_setexception called from the wrong thread\n"));
1829 if (gNPPException
) {
1830 // If a plugin throws multiple exceptions, we'll only report the
1831 // last one for now.
1832 free(gNPPException
);
1835 gNPPException
= strdup(message
);
1841 return gNPPException
;
1847 NS_ASSERTION(gNPPException
, "Uh, no NPP exception to pop!");
1849 if (gNPPException
) {
1850 free(gNPPException
);
1852 gNPPException
= nsnull
;
1856 NPPExceptionAutoHolder::NPPExceptionAutoHolder()
1857 : mOldException(gNPPException
)
1859 gNPPException
= nsnull
;
1862 NPPExceptionAutoHolder::~NPPExceptionAutoHolder()
1864 NS_ASSERTION(!gNPPException
, "NPP exception not properly cleared!");
1866 gNPPException
= mOldException
;
1870 _getvalue(NPP npp
, NPNVariable variable
, void *result
)
1872 if (!NS_IsMainThread()) {
1873 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_getvalue called from the wrong thread\n"));
1874 return NPERR_INVALID_PARAM
;
1876 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL
, ("NPN_GetValue: npp=%p, var=%d\n",
1877 (void*)npp
, (int)variable
));
1881 PluginDestructionGuard
guard(npp
);
1884 #if defined(XP_UNIX) && !defined(XP_MACOSX)
1885 case NPNVxDisplay
: {
1886 #ifdef MOZ_WIDGET_GTK2
1888 nsNPAPIPluginInstance
*inst
= (nsNPAPIPluginInstance
*) npp
->ndata
;
1889 PRBool windowless
= PR_FALSE
;
1890 inst
->GetValue(nsPluginInstanceVariable_WindowlessBool
, &windowless
);
1891 NPBool needXEmbed
= PR_FALSE
;
1893 inst
->GetValue((nsPluginInstanceVariable
)NPPVpluginNeedsXEmbed
, &needXEmbed
);
1895 if (windowless
|| needXEmbed
) {
1896 (*(Display
**)result
) = GDK_DISPLAY();
1897 return NPERR_NO_ERROR
;
1900 // adobe nppdf calls XtGetApplicationNameAndClass(display,
1901 // &instance, &class) we have to init Xt toolkit before get
1902 // XtDisplay just call gtk_xtbin_new(w,0) once
1903 static GtkWidget
*gtkXtBinHolder
= 0;
1904 if (!gtkXtBinHolder
) {
1905 gtkXtBinHolder
= gtk_xtbin_new(GDK_ROOT_PARENT(),0);
1906 // it crashes on destroy, let it leak
1907 // gtk_widget_destroy(gtkXtBinHolder);
1909 (*(Display
**)result
) = GTK_XTBIN(gtkXtBinHolder
)->xtdisplay
;
1910 return NPERR_NO_ERROR
;
1912 return NPERR_GENERIC_ERROR
;
1915 case NPNVxtAppContext
:
1916 return NPERR_GENERIC_ERROR
;
1919 #if defined(XP_WIN) || defined(XP_OS2) || defined(MOZ_WIDGET_GTK2)
1920 case NPNVnetscapeWindow
: {
1921 if (!npp
|| !npp
->ndata
)
1922 return NPERR_INVALID_INSTANCE_ERROR
;
1924 nsNPAPIPluginInstance
*inst
= (nsNPAPIPluginInstance
*) npp
->ndata
;
1926 nsCOMPtr
<nsIPluginInstancePeer
> peer
;
1927 if (NS_SUCCEEDED(inst
->GetPeer(getter_AddRefs(peer
))) &&
1929 NS_SUCCEEDED(peer
->GetValue(nsPluginInstancePeerVariable_NetscapeWindow
,
1931 return NPERR_NO_ERROR
;
1933 return NPERR_GENERIC_ERROR
;
1937 case NPNVjavascriptEnabledBool
: {
1938 *(NPBool
*)result
= PR_FALSE
;
1939 nsCOMPtr
<nsIPrefBranch
> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID
));
1941 PRBool js
= PR_FALSE
;;
1942 res
= prefs
->GetBoolPref("javascript.enabled", &js
);
1943 if (NS_SUCCEEDED(res
))
1944 *(NPBool
*)result
= js
;
1946 return NPERR_NO_ERROR
;
1949 case NPNVasdEnabledBool
:
1950 *(NPBool
*)result
= PR_FALSE
;
1951 return NPERR_NO_ERROR
;
1953 case NPNVisOfflineBool
: {
1954 PRBool offline
= PR_FALSE
;
1955 nsCOMPtr
<nsIIOService
> ioservice
=
1956 do_GetService(NS_IOSERVICE_CONTRACTID
, &res
);
1957 if (NS_SUCCEEDED(res
))
1958 res
= ioservice
->GetOffline(&offline
);
1960 return NPERR_GENERIC_ERROR
;
1962 *(NPBool
*)result
= offline
;
1963 return NPERR_NO_ERROR
;
1966 case NPNVserviceManager
: {
1967 nsIServiceManager
* sm
;
1968 res
= NS_GetServiceManager(&sm
);
1969 if (NS_SUCCEEDED(res
)) {
1970 *(nsIServiceManager
**)result
= sm
;
1971 return NPERR_NO_ERROR
;
1973 return NPERR_GENERIC_ERROR
;
1977 case NPNVDOMElement
: {
1978 nsNPAPIPluginInstance
*inst
= (nsNPAPIPluginInstance
*) npp
->ndata
;
1979 NS_ENSURE_TRUE(inst
, NPERR_GENERIC_ERROR
);
1981 nsCOMPtr
<nsIPluginInstancePeer
> pip
;
1982 inst
->GetPeer(getter_AddRefs(pip
));
1983 nsCOMPtr
<nsIPluginTagInfo2
> pti2 (do_QueryInterface(pip
));
1985 nsCOMPtr
<nsIDOMElement
> e
;
1986 pti2
->GetDOMElement(getter_AddRefs(e
));
1988 NS_ADDREF(*(nsIDOMElement
**)result
= e
.get());
1989 return NPERR_NO_ERROR
;
1992 return NPERR_GENERIC_ERROR
;
1995 case NPNVDOMWindow
: {
1996 nsNPAPIPluginInstance
*inst
= (nsNPAPIPluginInstance
*)npp
->ndata
;
1997 NS_ENSURE_TRUE(inst
, NPERR_GENERIC_ERROR
);
1999 nsIDOMWindow
*domWindow
= inst
->GetDOMWindow().get();
2002 // Pass over ownership of domWindow to the caller.
2003 (*(nsIDOMWindow
**)result
) = domWindow
;
2005 return NPERR_NO_ERROR
;
2007 return NPERR_GENERIC_ERROR
;
2011 #ifdef MOZ_WIDGET_GTK2
2012 *((NPNToolkitType
*)result
) = NPNVGtk2
;
2015 if (*(NPNToolkitType
*)result
)
2016 return NPERR_NO_ERROR
;
2018 return NPERR_GENERIC_ERROR
;
2021 case NPNVSupportsXEmbedBool
: {
2022 #ifdef MOZ_WIDGET_GTK2
2023 *(NPBool
*)result
= PR_TRUE
;
2025 *(NPBool
*)result
= PR_FALSE
;
2027 return NPERR_NO_ERROR
;
2030 case NPNVWindowNPObject
: {
2031 *(NPObject
**)result
= _getwindowobject(npp
);
2033 return NPERR_NO_ERROR
;
2036 case NPNVPluginElementNPObject
: {
2037 *(NPObject
**)result
= _getpluginelement(npp
);
2039 return NPERR_NO_ERROR
;
2042 case NPNVSupportsWindowless
: {
2043 #if defined(XP_WIN) || defined(XP_MACOSX) || (defined(MOZ_X11) && defined(MOZ_WIDGET_GTK2))
2044 *(NPBool
*)result
= PR_TRUE
;
2046 *(NPBool
*)result
= PR_FALSE
;
2048 return NPERR_NO_ERROR
;
2052 case NPNVpluginDrawingModel
: {
2054 nsNPAPIPluginInstance
*inst
= (nsNPAPIPluginInstance
*)npp
->ndata
;
2056 *(NPDrawingModel
*)result
= inst
->GetDrawingModel();
2057 return NPERR_NO_ERROR
;
2061 return NPERR_GENERIC_ERROR
;
2065 #ifndef NP_NO_QUICKDRAW
2066 case NPNVsupportsQuickDrawBool
: {
2067 *(NPBool
*)result
= PR_TRUE
;
2069 return NPERR_NO_ERROR
;
2073 case NPNVsupportsCoreGraphicsBool
: {
2074 *(NPBool
*)result
= PR_TRUE
;
2076 return NPERR_NO_ERROR
;
2081 return NPERR_GENERIC_ERROR
;
2086 _setvalue(NPP npp
, NPPVariable variable
, void *result
)
2088 if (!NS_IsMainThread()) {
2089 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_setvalue called from the wrong thread\n"));
2090 return NPERR_INVALID_PARAM
;
2092 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL
, ("NPN_SetValue: npp=%p, var=%d\n",
2093 (void*)npp
, (int)variable
));
2096 return NPERR_INVALID_INSTANCE_ERROR
;
2098 nsNPAPIPluginInstance
*inst
= (nsNPAPIPluginInstance
*) npp
->ndata
;
2100 NS_ASSERTION(inst
, "null instance");
2103 return NPERR_INVALID_INSTANCE_ERROR
;
2105 PluginDestructionGuard
guard(inst
);
2109 // we should keep backward compatibility with NPAPI where the
2110 // actual pointer value is checked rather than its content
2111 // when passing booleans
2112 case NPPVpluginWindowBool
: {
2114 // This setting doesn't apply to OS X (only to Windows and Unix/Linux).
2115 // See https://developer.mozilla.org/En/NPN_SetValue#section_5. Return
2116 // NPERR_NO_ERROR here to conform to other browsers' behavior on OS X
2117 // (e.g. Safari and Opera).
2118 return NPERR_NO_ERROR
;
2120 NPBool bWindowless
= (result
== nsnull
);
2121 return inst
->SetWindowless(bWindowless
);
2125 case NPPVpluginTransparentBool
: {
2126 NPBool bTransparent
= (result
!= nsnull
);
2127 return inst
->SetTransparent(bTransparent
);
2130 case NPPVjavascriptPushCallerBool
:
2133 nsCOMPtr
<nsIJSContextStack
> contextStack
=
2134 do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv
);
2135 if (NS_SUCCEEDED(rv
)) {
2136 NPBool bPushCaller
= (result
!= nsnull
);
2139 rv
= NS_ERROR_FAILURE
;
2141 nsCOMPtr
<nsIPluginInstancePeer
> peer
;
2142 if (NS_SUCCEEDED(inst
->GetPeer(getter_AddRefs(peer
))) && peer
) {
2143 nsCOMPtr
<nsIPluginInstancePeer2
> peer2
=
2144 do_QueryInterface(peer
);
2148 rv
= peer2
->GetJSContext(&cx
);
2150 if (NS_SUCCEEDED(rv
))
2151 rv
= contextStack
->Push(cx
);
2155 rv
= contextStack
->Pop(nsnull
);
2158 return NS_SUCCEEDED(rv
) ? NPERR_NO_ERROR
: NPERR_GENERIC_ERROR
;
2161 case NPPVpluginKeepLibraryInMemory
: {
2162 NPBool bCached
= (result
!= nsnull
);
2163 return inst
->SetCached(bCached
);
2166 case NPPVpluginWantsAllNetworkStreams
: {
2167 PRBool bWantsAllNetworkStreams
= (result
!= nsnull
);
2168 return inst
->SetWantsAllNetworkStreams(bWantsAllNetworkStreams
);
2172 case NPPVpluginDrawingModel
: {
2174 int dModelValue
= (int)result
;
2175 inst
->SetDrawingModel((NPDrawingModel
)dModelValue
);
2176 return NPERR_NO_ERROR
;
2179 return NPERR_GENERIC_ERROR
;
2185 return NPERR_NO_ERROR
;
2190 _requestread(NPStream
*pstream
, NPByteRange
*rangeList
)
2192 if (!NS_IsMainThread()) {
2193 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_requestread called from the wrong thread\n"));
2194 return NPERR_INVALID_PARAM
;
2196 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL
, ("NPN_RequestRead: stream=%p\n",
2199 #ifdef PLUGIN_LOGGING
2200 for(NPByteRange
* range
= rangeList
; range
!= nsnull
; range
= range
->next
)
2201 PR_LOG(nsPluginLogging::gNPNLog
,PLUGIN_LOG_NOISY
,
2202 ("%i-%i", range
->offset
, range
->offset
+ range
->length
- 1));
2204 PR_LOG(nsPluginLogging::gNPNLog
,PLUGIN_LOG_NOISY
, ("\n\n"));
2208 if (!pstream
|| !rangeList
|| !pstream
->ndata
)
2209 return NPERR_INVALID_PARAM
;
2211 nsNPAPIPluginStreamListener
* streamlistener
= (nsNPAPIPluginStreamListener
*)pstream
->ndata
;
2213 nsPluginStreamType streamtype
= nsPluginStreamType_Normal
;
2215 streamlistener
->GetStreamType(&streamtype
);
2217 if (streamtype
!= nsPluginStreamType_Seek
)
2218 return NPERR_STREAM_NOT_SEEKABLE
;
2220 if (streamlistener
->mStreamInfo
)
2221 streamlistener
->mStreamInfo
->RequestRead((nsByteRange
*)rangeList
);
2226 // Deprecated, only stubbed out
2227 void* NP_CALLBACK
/* OJI type: JRIEnv* */
2230 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL
, ("NPN_GetJavaEnv\n"));
2234 const char * NP_CALLBACK
2237 if (!NS_IsMainThread()) {
2238 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_useragent called from the wrong thread\n"));
2241 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL
, ("NPN_UserAgent: npp=%p\n", (void*)npp
));
2243 nsCOMPtr
<nsIPluginManager
> pm(do_GetService(kPluginManagerCID
));
2248 nsresult rv
= pm
->UserAgent(&retstr
);
2256 _memalloc (uint32_t size
)
2258 if (!NS_IsMainThread()) {
2259 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL
,("NPN_memalloc called from the wrong thread\n"));
2261 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY
, ("NPN_MemAlloc: size=%d\n", size
));
2262 return nsMemory::Alloc(size
);
2265 // Deprecated, only stubbed out
2266 void* NP_CALLBACK
/* OJI type: jref */
2267 _getJavaPeer(NPP npp
)
2269 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL
, ("NPN_GetJavaPeer: npp=%p\n", (void*)npp
));
2274 _pushpopupsenabledstate(NPP npp
, NPBool enabled
)
2276 if (!NS_IsMainThread()) {
2277 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_pushpopupsenabledstate called from the wrong thread\n"));
2280 nsNPAPIPluginInstance
*inst
= (nsNPAPIPluginInstance
*)npp
->ndata
;
2284 inst
->PushPopupsEnabledState(enabled
);
2288 _poppopupsenabledstate(NPP npp
)
2290 if (!NS_IsMainThread()) {
2291 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS
,("NPN_poppopupsenabledstate called from the wrong thread\n"));
2294 nsNPAPIPluginInstance
*inst
= (nsNPAPIPluginInstance
*)npp
->ndata
;
2298 inst
->PopPopupsEnabledState();
2301 class nsPluginThreadRunnable
: public nsRunnable
,
2305 nsPluginThreadRunnable(NPP instance
, PluginThreadCallback func
,
2307 virtual ~nsPluginThreadRunnable();
2311 PRBool
IsForInstance(NPP instance
)
2313 return (mInstance
== instance
);
2323 return (mFunc
!= nsnull
);
2328 PluginThreadCallback mFunc
;
2332 nsPluginThreadRunnable::nsPluginThreadRunnable(NPP instance
,
2333 PluginThreadCallback func
,
2335 : mInstance(instance
), mFunc(func
), mUserData(userData
)
2337 if (!sPluginThreadAsyncCallLock
) {
2338 // Failed to create lock, not much we can do here then...
2344 PR_INIT_CLIST(this);
2347 nsAutoLock
lock(sPluginThreadAsyncCallLock
);
2349 nsNPAPIPluginInstance
*inst
= (nsNPAPIPluginInstance
*)instance
->ndata
;
2350 if (!inst
|| !inst
->IsStarted()) {
2351 // The plugin was stopped, ignore this async call.
2357 PR_APPEND_LINK(this, &sPendingAsyncCalls
);
2361 nsPluginThreadRunnable::~nsPluginThreadRunnable()
2363 if (!sPluginThreadAsyncCallLock
) {
2368 nsAutoLock
lock(sPluginThreadAsyncCallLock
);
2370 PR_REMOVE_LINK(this);
2375 nsPluginThreadRunnable::Run()
2378 PluginDestructionGuard
guard(mInstance
);
2380 NS_TRY_SAFE_CALL_VOID(mFunc(mUserData
), nsnull
, nsnull
);
2387 _pluginthreadasynccall(NPP instance
, PluginThreadCallback func
, void *userData
)
2389 if (NS_IsMainThread()) {
2390 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY
,("NPN_pluginthreadasynccall called from the main thread\n"));
2392 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY
,("NPN_pluginthreadasynccall called from a non main thread\n"));
2394 nsRefPtr
<nsPluginThreadRunnable
> evt
=
2395 new nsPluginThreadRunnable(instance
, func
, userData
);
2397 if (evt
&& evt
->IsValid()) {
2398 NS_DispatchToMainThread(evt
);
2403 OnPluginDestroy(NPP instance
)
2405 if (!sPluginThreadAsyncCallLock
) {
2410 nsAutoLock
lock(sPluginThreadAsyncCallLock
);
2412 if (PR_CLIST_IS_EMPTY(&sPendingAsyncCalls
)) {
2416 nsPluginThreadRunnable
*r
=
2417 (nsPluginThreadRunnable
*)PR_LIST_HEAD(&sPendingAsyncCalls
);
2420 if (r
->IsForInstance(instance
)) {
2424 r
= (nsPluginThreadRunnable
*)PR_NEXT_LINK(r
);
2425 } while (r
!= &sPendingAsyncCalls
);
2432 NS_ASSERTION(PR_CLIST_IS_EMPTY(&sPendingAsyncCalls
),
2433 "Pending async plugin call list not cleaned up!");
2435 if (sPluginThreadAsyncCallLock
) {
2436 nsAutoLock::DestroyLock(sPluginThreadAsyncCallLock
);
2438 sPluginThreadAsyncCallLock
= nsnull
;
2443 EnterAsyncPluginThreadCallLock()
2445 if (sPluginThreadAsyncCallLock
) {
2446 PR_Lock(sPluginThreadAsyncCallLock
);
2451 ExitAsyncPluginThreadCallLock()
2453 if (sPluginThreadAsyncCallLock
) {
2454 PR_Unlock(sPluginThreadAsyncCallLock
);
2458 NPP
NPPStack::sCurrentNPP
= nsnull
;