1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #include "mozilla/DebugOnly.h"
7 
8 #ifdef MOZ_WIDGET_ANDROID
9 // For ScreenOrientation.h and Hal.h
10 #include "base/basictypes.h"
11 #endif
12 
13 #include "mozilla/Logging.h"
14 #include "prmem.h"
15 #include "nscore.h"
16 #include "prenv.h"
17 
18 #include "nsNPAPIPluginInstance.h"
19 #include "nsNPAPIPlugin.h"
20 #include "nsNPAPIPluginStreamListener.h"
21 #include "nsPluginHost.h"
22 #include "nsPluginLogging.h"
23 #include "nsContentUtils.h"
24 #include "nsPluginInstanceOwner.h"
25 
26 #include "nsThreadUtils.h"
27 #include "nsIDOMElement.h"
28 #include "nsIDocument.h"
29 #include "nsIDocShell.h"
30 #include "nsIScriptGlobalObject.h"
31 #include "nsIScriptContext.h"
32 #include "nsDirectoryServiceDefs.h"
33 #include "nsJSNPRuntime.h"
34 #include "nsPluginStreamListenerPeer.h"
35 #include "nsSize.h"
36 #include "nsNetCID.h"
37 #include "nsIContent.h"
38 #include "nsVersionComparator.h"
39 #include "mozilla/Preferences.h"
40 #include "mozilla/Unused.h"
41 #include "nsILoadContext.h"
42 #include "mozilla/dom/HTMLObjectElementBinding.h"
43 #include "AudioChannelService.h"
44 
45 using namespace mozilla;
46 using namespace mozilla::dom;
47 
48 #ifdef MOZ_WIDGET_ANDROID
49 #include "ANPBase.h"
50 #include <android/log.h>
51 #include "android_npapi.h"
52 #include "mozilla/Mutex.h"
53 #include "mozilla/CondVar.h"
54 #include "mozilla/dom/ScreenOrientation.h"
55 #include "mozilla/Hal.h"
56 #include "GLContextProvider.h"
57 #include "GLContext.h"
58 #include "TexturePoolOGL.h"
59 #include "SurfaceTypes.h"
60 #include "EGLUtils.h"
61 
62 using namespace mozilla;
63 using namespace mozilla::gl;
64 
65 typedef nsNPAPIPluginInstance::VideoInfo VideoInfo;
66 
67 class PluginEventRunnable : public Runnable
68 {
69 public:
PluginEventRunnable(nsNPAPIPluginInstance * instance,ANPEvent * event)70   PluginEventRunnable(nsNPAPIPluginInstance* instance, ANPEvent* event)
71     : mInstance(instance), mEvent(*event), mCanceled(false) {}
72 
Run()73   virtual nsresult Run() {
74     if (mCanceled)
75       return NS_OK;
76 
77     mInstance->HandleEvent(&mEvent, nullptr);
78     mInstance->PopPostedEvent(this);
79     return NS_OK;
80   }
81 
Cancel()82   void Cancel() { mCanceled = true; }
83 private:
84   nsNPAPIPluginInstance* mInstance;
85   ANPEvent mEvent;
86   bool mCanceled;
87 };
88 
89 static RefPtr<GLContext> sPluginContext = nullptr;
90 
EnsureGLContext()91 static bool EnsureGLContext()
92 {
93   if (!sPluginContext) {
94     const auto flags = CreateContextFlags::REQUIRE_COMPAT_PROFILE;
95     nsCString discardedFailureId;
96     sPluginContext = GLContextProvider::CreateHeadless(flags, &discardedFailureId);
97   }
98 
99   return sPluginContext != nullptr;
100 }
101 
102 static std::map<NPP, nsNPAPIPluginInstance*> sPluginNPPMap;
103 
104 #endif
105 
106 using namespace mozilla;
107 using namespace mozilla::plugins::parent;
108 using namespace mozilla::layers;
109 
110 static NS_DEFINE_IID(kIOutputStreamIID, NS_IOUTPUTSTREAM_IID);
111 
NS_IMPL_ISUPPORTS(nsNPAPIPluginInstance,nsIAudioChannelAgentCallback)112 NS_IMPL_ISUPPORTS(nsNPAPIPluginInstance, nsIAudioChannelAgentCallback)
113 
114 nsNPAPIPluginInstance::nsNPAPIPluginInstance()
115   : mDrawingModel(kDefaultDrawingModel)
116 #ifdef MOZ_WIDGET_ANDROID
117   , mANPDrawingModel(0)
118   , mFullScreenOrientation(dom::eScreenOrientation_LandscapePrimary)
119   , mWakeLocked(false)
120   , mFullScreen(false)
121   , mOriginPos(gl::OriginPos::TopLeft)
122 #endif
123   , mRunning(NOT_STARTED)
124   , mWindowless(false)
125   , mTransparent(false)
126   , mCached(false)
127   , mUsesDOMForCursor(false)
128   , mInPluginInitCall(false)
129   , mPlugin(nullptr)
130   , mMIMEType(nullptr)
131   , mOwner(nullptr)
132 #ifdef XP_MACOSX
133   , mCurrentPluginEvent(nullptr)
134 #endif
135 #ifdef MOZ_WIDGET_ANDROID
136   , mOnScreen(true)
137 #endif
138   , mHaveJavaC2PJSObjectQuirk(false)
139   , mCachedParamLength(0)
140   , mCachedParamNames(nullptr)
141   , mCachedParamValues(nullptr)
142   , mMuted(false)
143 {
144   mNPP.pdata = nullptr;
145   mNPP.ndata = this;
146 
147   PLUGIN_LOG(PLUGIN_LOG_BASIC, ("nsNPAPIPluginInstance ctor: this=%p\n",this));
148 
149 #ifdef MOZ_WIDGET_ANDROID
150   sPluginNPPMap[&mNPP] = this;
151 #endif
152 }
153 
~nsNPAPIPluginInstance()154 nsNPAPIPluginInstance::~nsNPAPIPluginInstance()
155 {
156   PLUGIN_LOG(PLUGIN_LOG_BASIC, ("nsNPAPIPluginInstance dtor: this=%p\n",this));
157 
158 #ifdef MOZ_WIDGET_ANDROID
159   sPluginNPPMap.erase(&mNPP);
160 #endif
161 
162   if (mMIMEType) {
163     PR_Free((void *)mMIMEType);
164     mMIMEType = nullptr;
165   }
166 
167   if (!mCachedParamValues || !mCachedParamNames) {
168     return;
169   }
170   MOZ_ASSERT(mCachedParamValues && mCachedParamNames);
171 
172   for (uint32_t i = 0; i < mCachedParamLength; i++) {
173     if (mCachedParamNames[i]) {
174       free(mCachedParamNames[i]);
175       mCachedParamNames[i] = nullptr;
176     }
177     if (mCachedParamValues[i]) {
178       free(mCachedParamValues[i]);
179       mCachedParamValues[i] = nullptr;
180     }
181   }
182 
183   free(mCachedParamNames);
184   mCachedParamNames = nullptr;
185 
186   free(mCachedParamValues);
187   mCachedParamValues = nullptr;
188 }
189 
190 uint32_t nsNPAPIPluginInstance::gInUnsafePluginCalls = 0;
191 
192 void
Destroy()193 nsNPAPIPluginInstance::Destroy()
194 {
195   Stop();
196   mPlugin = nullptr;
197   mAudioChannelAgent = nullptr;
198 
199 #if MOZ_WIDGET_ANDROID
200   if (mContentSurface)
201     mContentSurface->SetFrameAvailableCallback(nullptr);
202 
203   mContentSurface = nullptr;
204 
205   std::map<void*, VideoInfo*>::iterator it;
206   for (it = mVideos.begin(); it != mVideos.end(); it++) {
207     it->second->mSurfaceTexture->SetFrameAvailableCallback(nullptr);
208     delete it->second;
209   }
210   mVideos.clear();
211   SetWakeLock(false);
212 #endif
213 }
214 
215 TimeStamp
StopTime()216 nsNPAPIPluginInstance::StopTime()
217 {
218   return mStopTime;
219 }
220 
Initialize(nsNPAPIPlugin * aPlugin,nsPluginInstanceOwner * aOwner,const nsACString & aMIMEType)221 nsresult nsNPAPIPluginInstance::Initialize(nsNPAPIPlugin *aPlugin, nsPluginInstanceOwner* aOwner, const nsACString& aMIMEType)
222 {
223   PROFILER_LABEL_FUNC(js::ProfileEntry::Category::OTHER);
224   PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance::Initialize this=%p\n",this));
225 
226   NS_ENSURE_ARG_POINTER(aPlugin);
227   NS_ENSURE_ARG_POINTER(aOwner);
228 
229   mPlugin = aPlugin;
230   mOwner = aOwner;
231 
232   if (!aMIMEType.IsEmpty()) {
233     mMIMEType = ToNewCString(aMIMEType);
234   }
235 
236   return Start();
237 }
238 
Stop()239 nsresult nsNPAPIPluginInstance::Stop()
240 {
241   PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance::Stop this=%p\n",this));
242 
243   // Make sure the plugin didn't leave popups enabled.
244   if (mPopupStates.Length() > 0) {
245     nsCOMPtr<nsPIDOMWindowOuter> window = GetDOMWindow();
246 
247     if (window) {
248       window->PopPopupControlState(openAbused);
249     }
250   }
251 
252   if (RUNNING != mRunning) {
253     return NS_OK;
254   }
255 
256   // clean up all outstanding timers
257   for (uint32_t i = mTimers.Length(); i > 0; i--)
258     UnscheduleTimer(mTimers[i - 1]->id);
259 
260   // If there's code from this plugin instance on the stack, delay the
261   // destroy.
262   if (PluginDestructionGuard::DelayDestroy(this)) {
263     return NS_OK;
264   }
265 
266   // Make sure we lock while we're writing to mRunning after we've
267   // started as other threads might be checking that inside a lock.
268   {
269     AsyncCallbackAutoLock lock;
270     mRunning = DESTROYING;
271     mStopTime = TimeStamp::Now();
272   }
273 
274   OnPluginDestroy(&mNPP);
275 
276   // clean up open streams
277   while (mStreamListeners.Length() > 0) {
278     RefPtr<nsNPAPIPluginStreamListener> currentListener(mStreamListeners[0]);
279     currentListener->CleanUpStream(NPRES_USER_BREAK);
280     mStreamListeners.RemoveElement(currentListener);
281   }
282 
283   if (!mPlugin || !mPlugin->GetLibrary())
284     return NS_ERROR_FAILURE;
285 
286   NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
287 
288   NPError error = NPERR_GENERIC_ERROR;
289   if (pluginFunctions->destroy) {
290     NPSavedData *sdata = 0;
291 
292     NS_TRY_SAFE_CALL_RETURN(error, (*pluginFunctions->destroy)(&mNPP, &sdata), this,
293                             NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
294 
295     NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
296                    ("NPP Destroy called: this=%p, npp=%p, return=%d\n", this, &mNPP, error));
297   }
298   mRunning = DESTROYED;
299 
300 #if MOZ_WIDGET_ANDROID
301   for (uint32_t i = 0; i < mPostedEvents.Length(); i++) {
302     mPostedEvents[i]->Cancel();
303   }
304 
305   mPostedEvents.Clear();
306 #endif
307 
308   nsJSNPRuntime::OnPluginDestroy(&mNPP);
309 
310   if (error != NPERR_NO_ERROR)
311     return NS_ERROR_FAILURE;
312   else
313     return NS_OK;
314 }
315 
316 already_AddRefed<nsPIDOMWindowOuter>
GetDOMWindow()317 nsNPAPIPluginInstance::GetDOMWindow()
318 {
319   if (!mOwner)
320     return nullptr;
321 
322   RefPtr<nsPluginInstanceOwner> kungFuDeathGrip(mOwner);
323 
324   nsCOMPtr<nsIDocument> doc;
325   kungFuDeathGrip->GetDocument(getter_AddRefs(doc));
326   if (!doc)
327     return nullptr;
328 
329   RefPtr<nsPIDOMWindowOuter> window = doc->GetWindow();
330 
331   return window.forget();
332 }
333 
334 nsresult
GetTagType(nsPluginTagType * result)335 nsNPAPIPluginInstance::GetTagType(nsPluginTagType *result)
336 {
337   if (!mOwner) {
338     return NS_ERROR_FAILURE;
339   }
340 
341   return mOwner->GetTagType(result);
342 }
343 
344 nsresult
GetMode(int32_t * result)345 nsNPAPIPluginInstance::GetMode(int32_t *result)
346 {
347   if (mOwner)
348     return mOwner->GetMode(result);
349   else
350     return NS_ERROR_FAILURE;
351 }
352 
353 nsTArray<nsNPAPIPluginStreamListener*>*
StreamListeners()354 nsNPAPIPluginInstance::StreamListeners()
355 {
356   return &mStreamListeners;
357 }
358 
359 nsTArray<nsPluginStreamListenerPeer*>*
FileCachedStreamListeners()360 nsNPAPIPluginInstance::FileCachedStreamListeners()
361 {
362   return &mFileCachedStreamListeners;
363 }
364 
365 nsresult
Start()366 nsNPAPIPluginInstance::Start()
367 {
368   if (mRunning == RUNNING) {
369     return NS_OK;
370   }
371 
372   if (!mOwner) {
373     MOZ_ASSERT(false, "Should not be calling Start() on unowned plugin.");
374     return NS_ERROR_FAILURE;
375   }
376 
377   PluginDestructionGuard guard(this);
378 
379   nsTArray<MozPluginParameter> attributes;
380   nsTArray<MozPluginParameter> params;
381 
382   nsPluginTagType tagtype;
383   nsresult rv = GetTagType(&tagtype);
384   if (NS_SUCCEEDED(rv)) {
385     mOwner->GetAttributes(attributes);
386     mOwner->GetParameters(params);
387   } else {
388     MOZ_ASSERT(false, "Failed to get tag type.");
389   }
390 
391   mCachedParamLength = attributes.Length() + 1 + params.Length();
392 
393   // We add an extra entry "PARAM" as a separator between the attribute
394   // and param values, but we don't count it if there are no <param> entries.
395   // Legacy behavior quirk.
396   uint32_t quirkParamLength = params.Length() ?
397                                 mCachedParamLength : attributes.Length();
398 
399   mCachedParamNames = (char**)moz_xmalloc(sizeof(char*) * mCachedParamLength);
400   mCachedParamValues = (char**)moz_xmalloc(sizeof(char*) * mCachedParamLength);
401 
402   for (uint32_t i = 0; i < attributes.Length(); i++) {
403     mCachedParamNames[i] = ToNewUTF8String(attributes[i].mName);
404     mCachedParamValues[i] = ToNewUTF8String(attributes[i].mValue);
405   }
406 
407   // Android expects and empty string instead of null.
408   mCachedParamNames[attributes.Length()] = ToNewUTF8String(NS_LITERAL_STRING("PARAM"));
409   #ifdef MOZ_WIDGET_ANDROID
410     mCachedParamValues[attributes.Length()] = ToNewUTF8String(NS_LITERAL_STRING(""));
411   #else
412     mCachedParamValues[attributes.Length()] = nullptr;
413   #endif
414 
415   for (uint32_t i = 0, pos = attributes.Length() + 1; i < params.Length(); i ++) {
416     mCachedParamNames[pos] = ToNewUTF8String(params[i].mName);
417     mCachedParamValues[pos] = ToNewUTF8String(params[i].mValue);
418     pos++;
419   }
420 
421   int32_t       mode;
422   const char*   mimetype;
423   NPError       error = NPERR_GENERIC_ERROR;
424 
425   GetMode(&mode);
426   GetMIMEType(&mimetype);
427 
428   CheckJavaC2PJSObjectQuirk(quirkParamLength, mCachedParamNames, mCachedParamValues);
429 
430   bool oldVal = mInPluginInitCall;
431   mInPluginInitCall = true;
432 
433   // Need this on the stack before calling NPP_New otherwise some callbacks that
434   // the plugin may make could fail (NPN_HasProperty, for example).
435   NPPAutoPusher autopush(&mNPP);
436 
437   if (!mPlugin)
438     return NS_ERROR_FAILURE;
439 
440   PluginLibrary* library = mPlugin->GetLibrary();
441   if (!library)
442     return NS_ERROR_FAILURE;
443 
444   // Mark this instance as running before calling NPP_New because the plugin may
445   // call other NPAPI functions, like NPN_GetURLNotify, that assume this is set
446   // before returning. If the plugin returns failure, we'll clear it out below.
447   mRunning = RUNNING;
448 
449   nsresult newResult = library->NPP_New((char*)mimetype, &mNPP, (uint16_t)mode,
450                                         quirkParamLength, mCachedParamNames,
451                                         mCachedParamValues, nullptr, &error);
452   mInPluginInitCall = oldVal;
453 
454   NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
455   ("NPP New called: this=%p, npp=%p, mime=%s, mode=%d, argc=%d, return=%d\n",
456   this, &mNPP, mimetype, mode, quirkParamLength, error));
457 
458   if (NS_FAILED(newResult) || error != NPERR_NO_ERROR) {
459     mRunning = DESTROYED;
460     nsJSNPRuntime::OnPluginDestroy(&mNPP);
461     return NS_ERROR_FAILURE;
462   }
463 
464   return newResult;
465 }
466 
SetWindow(NPWindow * window)467 nsresult nsNPAPIPluginInstance::SetWindow(NPWindow* window)
468 {
469   // NPAPI plugins don't want a SetWindow(nullptr).
470   if (!window || RUNNING != mRunning)
471     return NS_OK;
472 
473 #if MOZ_WIDGET_GTK
474   // bug 108347, flash plugin on linux doesn't like window->width <=
475   // 0, but Java needs wants this call.
476   if (window && window->type == NPWindowTypeWindow &&
477       (window->width <= 0 || window->height <= 0) &&
478       (nsPluginHost::GetSpecialType(nsDependentCString(mMIMEType)) !=
479        nsPluginHost::eSpecialType_Java)) {
480     return NS_OK;
481   }
482 #endif
483 
484   if (!mPlugin || !mPlugin->GetLibrary())
485     return NS_ERROR_FAILURE;
486 
487   NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
488 
489   if (pluginFunctions->setwindow) {
490     PluginDestructionGuard guard(this);
491 
492     // XXX Turns out that NPPluginWindow and NPWindow are structurally
493     // identical (on purpose!), so there's no need to make a copy.
494 
495     PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance::SetWindow (about to call it) this=%p\n",this));
496 
497     bool oldVal = mInPluginInitCall;
498     mInPluginInitCall = true;
499 
500     NPPAutoPusher nppPusher(&mNPP);
501 
502     NPError error;
503     NS_TRY_SAFE_CALL_RETURN(error, (*pluginFunctions->setwindow)(&mNPP, (NPWindow*)window), this,
504                             NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
505     // 'error' is only used if this is a logging-enabled build.
506     // That is somewhat complex to check, so we just use "unused"
507     // to suppress any compiler warnings in build configurations
508     // where the logging is a no-op.
509     mozilla::Unused << error;
510 
511     mInPluginInitCall = oldVal;
512 
513     NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
514     ("NPP SetWindow called: this=%p, [x=%d,y=%d,w=%d,h=%d], clip[t=%d,b=%d,l=%d,r=%d], return=%d\n",
515     this, window->x, window->y, window->width, window->height,
516     window->clipRect.top, window->clipRect.bottom, window->clipRect.left, window->clipRect.right, error));
517   }
518   return NS_OK;
519 }
520 
521 nsresult
NewStreamFromPlugin(const char * type,const char * target,nsIOutputStream ** result)522 nsNPAPIPluginInstance::NewStreamFromPlugin(const char* type, const char* target,
523                                            nsIOutputStream* *result)
524 {
525   nsPluginStreamToFile* stream = new nsPluginStreamToFile(target, mOwner);
526   return stream->QueryInterface(kIOutputStreamIID, (void**)result);
527 }
528 
529 nsresult
NewStreamListener(const char * aURL,void * notifyData,nsNPAPIPluginStreamListener ** listener)530 nsNPAPIPluginInstance::NewStreamListener(const char* aURL, void* notifyData,
531                                          nsNPAPIPluginStreamListener** listener)
532 {
533   RefPtr<nsNPAPIPluginStreamListener> sl = new nsNPAPIPluginStreamListener(this, notifyData, aURL);
534 
535   mStreamListeners.AppendElement(sl);
536 
537   sl.forget(listener);
538 
539   return NS_OK;
540 }
541 
Print(NPPrint * platformPrint)542 nsresult nsNPAPIPluginInstance::Print(NPPrint* platformPrint)
543 {
544   NS_ENSURE_TRUE(platformPrint, NS_ERROR_NULL_POINTER);
545 
546   PluginDestructionGuard guard(this);
547 
548   if (!mPlugin || !mPlugin->GetLibrary())
549     return NS_ERROR_FAILURE;
550 
551   NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
552 
553   NPPrint* thePrint = (NPPrint *)platformPrint;
554 
555   // to be compatible with the older SDK versions and to match what
556   // NPAPI and other browsers do, overwrite |window.type| field with one
557   // more copy of |platformPrint|. See bug 113264
558   uint16_t sdkmajorversion = (pluginFunctions->version & 0xff00)>>8;
559   uint16_t sdkminorversion = pluginFunctions->version & 0x00ff;
560   if ((sdkmajorversion == 0) && (sdkminorversion < 11)) {
561     // Let's copy platformPrint bytes over to where it was supposed to be
562     // in older versions -- four bytes towards the beginning of the struct
563     // but we should be careful about possible misalignments
564     if (sizeof(NPWindowType) >= sizeof(void *)) {
565       void* source = thePrint->print.embedPrint.platformPrint;
566       void** destination = (void **)&(thePrint->print.embedPrint.window.type);
567       *destination = source;
568     } else {
569       NS_ERROR("Incompatible OS for assignment");
570     }
571   }
572 
573   if (pluginFunctions->print)
574       NS_TRY_SAFE_CALL_VOID((*pluginFunctions->print)(&mNPP, thePrint), this,
575                             NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
576 
577   NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
578   ("NPP PrintProc called: this=%p, pDC=%p, [x=%d,y=%d,w=%d,h=%d], clip[t=%d,b=%d,l=%d,r=%d]\n",
579   this,
580   platformPrint->print.embedPrint.platformPrint,
581   platformPrint->print.embedPrint.window.x,
582   platformPrint->print.embedPrint.window.y,
583   platformPrint->print.embedPrint.window.width,
584   platformPrint->print.embedPrint.window.height,
585   platformPrint->print.embedPrint.window.clipRect.top,
586   platformPrint->print.embedPrint.window.clipRect.bottom,
587   platformPrint->print.embedPrint.window.clipRect.left,
588   platformPrint->print.embedPrint.window.clipRect.right));
589 
590   return NS_OK;
591 }
592 
HandleEvent(void * event,int16_t * result,NSPluginCallReentry aSafeToReenterGecko)593 nsresult nsNPAPIPluginInstance::HandleEvent(void* event, int16_t* result,
594                                             NSPluginCallReentry aSafeToReenterGecko)
595 {
596   if (RUNNING != mRunning)
597     return NS_OK;
598 
599   PROFILER_LABEL_FUNC(js::ProfileEntry::Category::OTHER);
600 
601   if (!event)
602     return NS_ERROR_FAILURE;
603 
604   PluginDestructionGuard guard(this);
605 
606   if (!mPlugin || !mPlugin->GetLibrary())
607     return NS_ERROR_FAILURE;
608 
609   NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
610 
611   int16_t tmpResult = kNPEventNotHandled;
612 
613   if (pluginFunctions->event) {
614 #ifdef XP_MACOSX
615     mCurrentPluginEvent = event;
616 #endif
617 #if defined(XP_WIN)
618     NS_TRY_SAFE_CALL_RETURN(tmpResult, (*pluginFunctions->event)(&mNPP, event), this,
619                             aSafeToReenterGecko);
620 #else
621     MAIN_THREAD_JNI_REF_GUARD;
622     tmpResult = (*pluginFunctions->event)(&mNPP, event);
623 #endif
624     NPP_PLUGIN_LOG(PLUGIN_LOG_NOISY,
625       ("NPP HandleEvent called: this=%p, npp=%p, event=%p, return=%d\n",
626       this, &mNPP, event, tmpResult));
627 
628     if (result)
629       *result = tmpResult;
630 #ifdef XP_MACOSX
631     mCurrentPluginEvent = nullptr;
632 #endif
633   }
634 
635   return NS_OK;
636 }
637 
GetValueFromPlugin(NPPVariable variable,void * value)638 nsresult nsNPAPIPluginInstance::GetValueFromPlugin(NPPVariable variable, void* value)
639 {
640   if (!mPlugin || !mPlugin->GetLibrary())
641     return NS_ERROR_FAILURE;
642 
643   NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
644 
645   nsresult rv = NS_ERROR_FAILURE;
646 
647   if (pluginFunctions->getvalue && RUNNING == mRunning) {
648     PluginDestructionGuard guard(this);
649 
650     NPError pluginError = NPERR_GENERIC_ERROR;
651     NS_TRY_SAFE_CALL_RETURN(pluginError, (*pluginFunctions->getvalue)(&mNPP, variable, value), this,
652                             NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
653     NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
654     ("NPP GetValue called: this=%p, npp=%p, var=%d, value=%d, return=%d\n",
655     this, &mNPP, variable, value, pluginError));
656 
657     if (pluginError == NPERR_NO_ERROR) {
658       rv = NS_OK;
659     }
660   }
661 
662   return rv;
663 }
664 
GetPlugin()665 nsNPAPIPlugin* nsNPAPIPluginInstance::GetPlugin()
666 {
667   return mPlugin;
668 }
669 
GetNPP(NPP * aNPP)670 nsresult nsNPAPIPluginInstance::GetNPP(NPP* aNPP)
671 {
672   if (aNPP)
673     *aNPP = &mNPP;
674   else
675     return NS_ERROR_NULL_POINTER;
676 
677   return NS_OK;
678 }
679 
SetWindowless(bool aWindowless)680 NPError nsNPAPIPluginInstance::SetWindowless(bool aWindowless)
681 {
682   mWindowless = aWindowless;
683 
684   if (mMIMEType) {
685     // bug 558434 - Prior to 3.6.4, we assumed windowless was transparent.
686     // Silverlight apparently relied on this quirk, so we default to
687     // transparent unless they specify otherwise after setting the windowless
688     // property. (Last tested version: sl 4.0).
689     // Changes to this code should be matched with changes in
690     // PluginInstanceChild::InitQuirksMode.
691     if (nsPluginHost::GetSpecialType(nsDependentCString(mMIMEType)) ==
692         nsPluginHost::eSpecialType_Silverlight) {
693       mTransparent = true;
694     }
695   }
696 
697   return NPERR_NO_ERROR;
698 }
699 
SetTransparent(bool aTransparent)700 NPError nsNPAPIPluginInstance::SetTransparent(bool aTransparent)
701 {
702   mTransparent = aTransparent;
703   return NPERR_NO_ERROR;
704 }
705 
SetUsesDOMForCursor(bool aUsesDOMForCursor)706 NPError nsNPAPIPluginInstance::SetUsesDOMForCursor(bool aUsesDOMForCursor)
707 {
708   mUsesDOMForCursor = aUsesDOMForCursor;
709   return NPERR_NO_ERROR;
710 }
711 
712 bool
UsesDOMForCursor()713 nsNPAPIPluginInstance::UsesDOMForCursor()
714 {
715   return mUsesDOMForCursor;
716 }
717 
SetDrawingModel(NPDrawingModel aModel)718 void nsNPAPIPluginInstance::SetDrawingModel(NPDrawingModel aModel)
719 {
720   mDrawingModel = aModel;
721 }
722 
RedrawPlugin()723 void nsNPAPIPluginInstance::RedrawPlugin()
724 {
725   mOwner->RedrawPlugin();
726 }
727 
728 #if defined(XP_MACOSX)
SetEventModel(NPEventModel aModel)729 void nsNPAPIPluginInstance::SetEventModel(NPEventModel aModel)
730 {
731   // the event model needs to be set for the object frame immediately
732   if (!mOwner) {
733     NS_WARNING("Trying to set event model without a plugin instance owner!");
734     return;
735   }
736 
737   mOwner->SetEventModel(aModel);
738 }
739 #endif
740 
741 #if defined(MOZ_WIDGET_ANDROID)
742 
SendLifecycleEvent(nsNPAPIPluginInstance * aInstance,uint32_t aAction)743 static void SendLifecycleEvent(nsNPAPIPluginInstance* aInstance, uint32_t aAction)
744 {
745   ANPEvent event;
746   event.inSize = sizeof(ANPEvent);
747   event.eventType = kLifecycle_ANPEventType;
748   event.data.lifecycle.action = aAction;
749   aInstance->HandleEvent(&event, nullptr);
750 }
751 
NotifyForeground(bool aForeground)752 void nsNPAPIPluginInstance::NotifyForeground(bool aForeground)
753 {
754   PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance::SetForeground this=%p\n foreground=%d",this, aForeground));
755   if (RUNNING != mRunning)
756     return;
757 
758   SendLifecycleEvent(this, aForeground ? kResume_ANPLifecycleAction : kPause_ANPLifecycleAction);
759 }
760 
NotifyOnScreen(bool aOnScreen)761 void nsNPAPIPluginInstance::NotifyOnScreen(bool aOnScreen)
762 {
763   PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance::SetOnScreen this=%p\n onScreen=%d",this, aOnScreen));
764   if (RUNNING != mRunning || mOnScreen == aOnScreen)
765     return;
766 
767   mOnScreen = aOnScreen;
768   SendLifecycleEvent(this, aOnScreen ? kOnScreen_ANPLifecycleAction : kOffScreen_ANPLifecycleAction);
769 }
770 
MemoryPressure()771 void nsNPAPIPluginInstance::MemoryPressure()
772 {
773   PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance::MemoryPressure this=%p\n",this));
774   if (RUNNING != mRunning)
775     return;
776 
777   SendLifecycleEvent(this, kFreeMemory_ANPLifecycleAction);
778 }
779 
NotifyFullScreen(bool aFullScreen)780 void nsNPAPIPluginInstance::NotifyFullScreen(bool aFullScreen)
781 {
782   PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance::NotifyFullScreen this=%p\n",this));
783 
784   if (RUNNING != mRunning || mFullScreen == aFullScreen)
785     return;
786 
787   mFullScreen = aFullScreen;
788   SendLifecycleEvent(this, mFullScreen ? kEnterFullScreen_ANPLifecycleAction : kExitFullScreen_ANPLifecycleAction);
789 
790   if (mFullScreen && mFullScreenOrientation != dom::eScreenOrientation_None) {
791     java::GeckoAppShell::LockScreenOrientation(mFullScreenOrientation);
792   }
793 }
794 
NotifySize(nsIntSize size)795 void nsNPAPIPluginInstance::NotifySize(nsIntSize size)
796 {
797   if (kOpenGL_ANPDrawingModel != GetANPDrawingModel() ||
798       size == mCurrentSize)
799     return;
800 
801   mCurrentSize = size;
802 
803   ANPEvent event;
804   event.inSize = sizeof(ANPEvent);
805   event.eventType = kDraw_ANPEventType;
806   event.data.draw.model = kOpenGL_ANPDrawingModel;
807   event.data.draw.data.surfaceSize.width = size.width;
808   event.data.draw.data.surfaceSize.height = size.height;
809 
810   HandleEvent(&event, nullptr);
811 }
812 
SetANPDrawingModel(uint32_t aModel)813 void nsNPAPIPluginInstance::SetANPDrawingModel(uint32_t aModel)
814 {
815   mANPDrawingModel = aModel;
816 }
817 
GetJavaSurface()818 void* nsNPAPIPluginInstance::GetJavaSurface()
819 {
820   void* surface = nullptr;
821   nsresult rv = GetValueFromPlugin(kJavaSurface_ANPGetValue, &surface);
822   if (NS_FAILED(rv))
823     return nullptr;
824 
825   return surface;
826 }
827 
PostEvent(void * event)828 void nsNPAPIPluginInstance::PostEvent(void* event)
829 {
830   PluginEventRunnable *r = new PluginEventRunnable(this, (ANPEvent*)event);
831   mPostedEvents.AppendElement(RefPtr<PluginEventRunnable>(r));
832 
833   NS_DispatchToMainThread(r);
834 }
835 
SetFullScreenOrientation(uint32_t orientation)836 void nsNPAPIPluginInstance::SetFullScreenOrientation(uint32_t orientation)
837 {
838   if (mFullScreenOrientation == orientation)
839     return;
840 
841   uint32_t oldOrientation = mFullScreenOrientation;
842   mFullScreenOrientation = orientation;
843 
844   if (mFullScreen) {
845     // We're already fullscreen so immediately apply the orientation change
846 
847     if (mFullScreenOrientation != dom::eScreenOrientation_None) {
848       java::GeckoAppShell::LockScreenOrientation(mFullScreenOrientation);
849     } else if (oldOrientation != dom::eScreenOrientation_None) {
850       // We applied an orientation when we entered fullscreen, but
851       // we don't want it anymore
852       java::GeckoAppShell::UnlockScreenOrientation();
853     }
854   }
855 }
856 
PopPostedEvent(PluginEventRunnable * r)857 void nsNPAPIPluginInstance::PopPostedEvent(PluginEventRunnable* r)
858 {
859   mPostedEvents.RemoveElement(r);
860 }
861 
SetWakeLock(bool aLocked)862 void nsNPAPIPluginInstance::SetWakeLock(bool aLocked)
863 {
864   if (aLocked == mWakeLocked)
865     return;
866 
867   mWakeLocked = aLocked;
868   hal::ModifyWakeLock(NS_LITERAL_STRING("screen"),
869                       mWakeLocked ? hal::WAKE_LOCK_ADD_ONE : hal::WAKE_LOCK_REMOVE_ONE,
870                       hal::WAKE_LOCK_NO_CHANGE);
871 }
872 
GLContext()873 GLContext* nsNPAPIPluginInstance::GLContext()
874 {
875   if (!EnsureGLContext())
876     return nullptr;
877 
878   return sPluginContext;
879 }
880 
CreateSurfaceTexture()881 already_AddRefed<AndroidSurfaceTexture> nsNPAPIPluginInstance::CreateSurfaceTexture()
882 {
883   if (!EnsureGLContext())
884     return nullptr;
885 
886   GLuint texture = TexturePoolOGL::AcquireTexture();
887   if (!texture)
888     return nullptr;
889 
890   RefPtr<AndroidSurfaceTexture> surface = AndroidSurfaceTexture::Create(TexturePoolOGL::GetGLContext(),
891                                                                         texture);
892   if (!surface) {
893     return nullptr;
894   }
895 
896   nsCOMPtr<nsIRunnable> frameCallback = NewRunnableMethod(this, &nsNPAPIPluginInstance::OnSurfaceTextureFrameAvailable);
897   surface->SetFrameAvailableCallback(frameCallback);
898   return surface.forget();
899 }
900 
OnSurfaceTextureFrameAvailable()901 void nsNPAPIPluginInstance::OnSurfaceTextureFrameAvailable()
902 {
903   if (mRunning == RUNNING && mOwner)
904     mOwner->Recomposite();
905 }
906 
AcquireContentWindow()907 void* nsNPAPIPluginInstance::AcquireContentWindow()
908 {
909   if (!mContentSurface) {
910     mContentSurface = CreateSurfaceTexture();
911 
912     if (!mContentSurface)
913       return nullptr;
914   }
915 
916   return mContentSurface->NativeWindow();
917 }
918 
919 AndroidSurfaceTexture*
AsSurfaceTexture()920 nsNPAPIPluginInstance::AsSurfaceTexture()
921 {
922   if (!mContentSurface)
923     return nullptr;
924 
925   return mContentSurface;
926 }
927 
AcquireVideoWindow()928 void* nsNPAPIPluginInstance::AcquireVideoWindow()
929 {
930   RefPtr<AndroidSurfaceTexture> surface = CreateSurfaceTexture();
931   if (!surface) {
932     return nullptr;
933   }
934 
935   VideoInfo* info = new VideoInfo(surface);
936 
937   void* window = info->mSurfaceTexture->NativeWindow();
938   mVideos.insert(std::pair<void*, VideoInfo*>(window, info));
939 
940   return window;
941 }
942 
ReleaseVideoWindow(void * window)943 void nsNPAPIPluginInstance::ReleaseVideoWindow(void* window)
944 {
945   std::map<void*, VideoInfo*>::iterator it = mVideos.find(window);
946   if (it == mVideos.end())
947     return;
948 
949   delete it->second;
950   mVideos.erase(window);
951 }
952 
SetVideoDimensions(void * window,gfxRect aDimensions)953 void nsNPAPIPluginInstance::SetVideoDimensions(void* window, gfxRect aDimensions)
954 {
955   std::map<void*, VideoInfo*>::iterator it;
956 
957   it = mVideos.find(window);
958   if (it == mVideos.end())
959     return;
960 
961   it->second->mDimensions = aDimensions;
962 }
963 
GetVideos(nsTArray<VideoInfo * > & aVideos)964 void nsNPAPIPluginInstance::GetVideos(nsTArray<VideoInfo*>& aVideos)
965 {
966   std::map<void*, VideoInfo*>::iterator it;
967   for (it = mVideos.begin(); it != mVideos.end(); it++)
968     aVideos.AppendElement(it->second);
969 }
970 
GetFromNPP(NPP npp)971 nsNPAPIPluginInstance* nsNPAPIPluginInstance::GetFromNPP(NPP npp)
972 {
973   std::map<NPP, nsNPAPIPluginInstance*>::iterator it;
974 
975   it = sPluginNPPMap.find(npp);
976   if (it == sPluginNPPMap.end())
977     return nullptr;
978 
979   return it->second;
980 }
981 
982 #endif
983 
GetDrawingModel(int32_t * aModel)984 nsresult nsNPAPIPluginInstance::GetDrawingModel(int32_t* aModel)
985 {
986   *aModel = (int32_t)mDrawingModel;
987   return NS_OK;
988 }
989 
IsRemoteDrawingCoreAnimation(bool * aDrawing)990 nsresult nsNPAPIPluginInstance::IsRemoteDrawingCoreAnimation(bool* aDrawing)
991 {
992 #ifdef XP_MACOSX
993   if (!mPlugin)
994       return NS_ERROR_FAILURE;
995 
996   PluginLibrary* library = mPlugin->GetLibrary();
997   if (!library)
998       return NS_ERROR_FAILURE;
999 
1000   return library->IsRemoteDrawingCoreAnimation(&mNPP, aDrawing);
1001 #else
1002   return NS_ERROR_FAILURE;
1003 #endif
1004 }
1005 
1006 nsresult
ContentsScaleFactorChanged(double aContentsScaleFactor)1007 nsNPAPIPluginInstance::ContentsScaleFactorChanged(double aContentsScaleFactor)
1008 {
1009 #if defined(XP_MACOSX) || defined(XP_WIN)
1010   if (!mPlugin)
1011       return NS_ERROR_FAILURE;
1012 
1013   PluginLibrary* library = mPlugin->GetLibrary();
1014   if (!library)
1015       return NS_ERROR_FAILURE;
1016 
1017   // We only need to call this if the plugin is running OOP.
1018   if (!library->IsOOP())
1019       return NS_OK;
1020 
1021   return library->ContentsScaleFactorChanged(&mNPP, aContentsScaleFactor);
1022 #else
1023   return NS_ERROR_FAILURE;
1024 #endif
1025 }
1026 
1027 nsresult
CSSZoomFactorChanged(float aCSSZoomFactor)1028 nsNPAPIPluginInstance::CSSZoomFactorChanged(float aCSSZoomFactor)
1029 {
1030   if (RUNNING != mRunning)
1031     return NS_OK;
1032 
1033   PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance informing plugin of CSS Zoom Factor change this=%p\n",this));
1034 
1035   if (!mPlugin || !mPlugin->GetLibrary())
1036     return NS_ERROR_FAILURE;
1037 
1038   NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
1039 
1040   if (!pluginFunctions->setvalue)
1041     return NS_ERROR_FAILURE;
1042 
1043   PluginDestructionGuard guard(this);
1044 
1045   NPError error;
1046   double value = static_cast<double>(aCSSZoomFactor);
1047   NS_TRY_SAFE_CALL_RETURN(error, (*pluginFunctions->setvalue)(&mNPP, NPNVCSSZoomFactor, &value), this,
1048                           NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
1049   return (error == NPERR_NO_ERROR) ? NS_OK : NS_ERROR_FAILURE;
1050 }
1051 
1052 nsresult
GetJSObject(JSContext * cx,JSObject ** outObject)1053 nsNPAPIPluginInstance::GetJSObject(JSContext *cx, JSObject** outObject)
1054 {
1055   if (mHaveJavaC2PJSObjectQuirk) {
1056     return NS_ERROR_FAILURE;
1057   }
1058 
1059   NPObject *npobj = nullptr;
1060   nsresult rv = GetValueFromPlugin(NPPVpluginScriptableNPObject, &npobj);
1061   if (NS_FAILED(rv) || !npobj)
1062     return NS_ERROR_FAILURE;
1063 
1064   *outObject = nsNPObjWrapper::GetNewOrUsed(&mNPP, cx, npobj);
1065 
1066   _releaseobject(npobj);
1067 
1068   return NS_OK;
1069 }
1070 
1071 void
SetCached(bool aCache)1072 nsNPAPIPluginInstance::SetCached(bool aCache)
1073 {
1074   mCached = aCache;
1075 }
1076 
1077 bool
ShouldCache()1078 nsNPAPIPluginInstance::ShouldCache()
1079 {
1080   return mCached;
1081 }
1082 
1083 nsresult
IsWindowless(bool * isWindowless)1084 nsNPAPIPluginInstance::IsWindowless(bool* isWindowless)
1085 {
1086 #if defined(MOZ_WIDGET_ANDROID) || defined(XP_MACOSX)
1087   // All OS X plugins are windowless.
1088   // On android, pre-honeycomb, all plugins are treated as windowless.
1089   *isWindowless = true;
1090 #else
1091   *isWindowless = mWindowless;
1092 #endif
1093   return NS_OK;
1094 }
1095 
1096 class MOZ_STACK_CLASS AutoPluginLibraryCall
1097 {
1098 public:
AutoPluginLibraryCall(nsNPAPIPluginInstance * aThis)1099   explicit AutoPluginLibraryCall(nsNPAPIPluginInstance* aThis)
1100     : mThis(aThis), mGuard(aThis), mLibrary(nullptr)
1101   {
1102     nsNPAPIPlugin* plugin = mThis->GetPlugin();
1103     if (plugin)
1104       mLibrary = plugin->GetLibrary();
1105   }
operator bool()1106   explicit operator bool() { return !!mLibrary; }
operator ->()1107   PluginLibrary* operator->() { return mLibrary; }
1108 
1109 private:
1110   nsNPAPIPluginInstance* mThis;
1111   PluginDestructionGuard mGuard;
1112   PluginLibrary* mLibrary;
1113 };
1114 
1115 nsresult
AsyncSetWindow(NPWindow * window)1116 nsNPAPIPluginInstance::AsyncSetWindow(NPWindow* window)
1117 {
1118   if (RUNNING != mRunning)
1119     return NS_OK;
1120 
1121   AutoPluginLibraryCall library(this);
1122   if (!library)
1123     return NS_ERROR_FAILURE;
1124 
1125   return library->AsyncSetWindow(&mNPP, window);
1126 }
1127 
1128 nsresult
GetImageContainer(ImageContainer ** aContainer)1129 nsNPAPIPluginInstance::GetImageContainer(ImageContainer**aContainer)
1130 {
1131   *aContainer = nullptr;
1132 
1133   if (RUNNING != mRunning)
1134     return NS_OK;
1135 
1136   AutoPluginLibraryCall library(this);
1137   return !library ? NS_ERROR_FAILURE : library->GetImageContainer(&mNPP, aContainer);
1138 }
1139 
1140 nsresult
GetImageSize(nsIntSize * aSize)1141 nsNPAPIPluginInstance::GetImageSize(nsIntSize* aSize)
1142 {
1143   *aSize = nsIntSize(0, 0);
1144 
1145   if (RUNNING != mRunning)
1146     return NS_OK;
1147 
1148   AutoPluginLibraryCall library(this);
1149   return !library ? NS_ERROR_FAILURE : library->GetImageSize(&mNPP, aSize);
1150 }
1151 
1152 #if defined(XP_WIN)
1153 nsresult
GetScrollCaptureContainer(ImageContainer ** aContainer)1154 nsNPAPIPluginInstance::GetScrollCaptureContainer(ImageContainer**aContainer)
1155 {
1156   *aContainer = nullptr;
1157 
1158   if (RUNNING != mRunning)
1159     return NS_OK;
1160 
1161   AutoPluginLibraryCall library(this);
1162   return !library ? NS_ERROR_FAILURE : library->GetScrollCaptureContainer(&mNPP, aContainer);
1163 }
1164 #endif
1165 
1166 nsresult
HandledWindowedPluginKeyEvent(const NativeEventData & aKeyEventData,bool aIsConsumed)1167 nsNPAPIPluginInstance::HandledWindowedPluginKeyEvent(
1168                          const NativeEventData& aKeyEventData,
1169                          bool aIsConsumed)
1170 {
1171   if (NS_WARN_IF(!mPlugin)) {
1172     return NS_ERROR_FAILURE;
1173   }
1174 
1175   PluginLibrary* library = mPlugin->GetLibrary();
1176   if (NS_WARN_IF(!library)) {
1177     return NS_ERROR_FAILURE;
1178   }
1179   return library->HandledWindowedPluginKeyEvent(&mNPP, aKeyEventData,
1180                                                 aIsConsumed);
1181 }
1182 
1183 void
DidComposite()1184 nsNPAPIPluginInstance::DidComposite()
1185 {
1186   if (RUNNING != mRunning)
1187     return;
1188 
1189   AutoPluginLibraryCall library(this);
1190   library->DidComposite(&mNPP);
1191 }
1192 
1193 nsresult
NotifyPainted(void)1194 nsNPAPIPluginInstance::NotifyPainted(void)
1195 {
1196   NS_NOTREACHED("Dead code, shouldn't be called.");
1197   return NS_ERROR_NOT_IMPLEMENTED;
1198 }
1199 
1200 nsresult
GetIsOOP(bool * aIsAsync)1201 nsNPAPIPluginInstance::GetIsOOP(bool* aIsAsync)
1202 {
1203   AutoPluginLibraryCall library(this);
1204   if (!library)
1205     return NS_ERROR_FAILURE;
1206 
1207   *aIsAsync = library->IsOOP();
1208   return NS_OK;
1209 }
1210 
1211 nsresult
SetBackgroundUnknown()1212 nsNPAPIPluginInstance::SetBackgroundUnknown()
1213 {
1214   if (RUNNING != mRunning)
1215     return NS_OK;
1216 
1217   AutoPluginLibraryCall library(this);
1218   if (!library)
1219     return NS_ERROR_FAILURE;
1220 
1221   return library->SetBackgroundUnknown(&mNPP);
1222 }
1223 
1224 nsresult
BeginUpdateBackground(nsIntRect * aRect,DrawTarget ** aDrawTarget)1225 nsNPAPIPluginInstance::BeginUpdateBackground(nsIntRect* aRect,
1226                                              DrawTarget** aDrawTarget)
1227 {
1228   if (RUNNING != mRunning)
1229     return NS_OK;
1230 
1231   AutoPluginLibraryCall library(this);
1232   if (!library)
1233     return NS_ERROR_FAILURE;
1234 
1235   return library->BeginUpdateBackground(&mNPP, *aRect, aDrawTarget);
1236 }
1237 
1238 nsresult
EndUpdateBackground(nsIntRect * aRect)1239 nsNPAPIPluginInstance::EndUpdateBackground(nsIntRect* aRect)
1240 {
1241   if (RUNNING != mRunning)
1242     return NS_OK;
1243 
1244   AutoPluginLibraryCall library(this);
1245   if (!library)
1246     return NS_ERROR_FAILURE;
1247 
1248   return library->EndUpdateBackground(&mNPP, *aRect);
1249 }
1250 
1251 nsresult
IsTransparent(bool * isTransparent)1252 nsNPAPIPluginInstance::IsTransparent(bool* isTransparent)
1253 {
1254   *isTransparent = mTransparent;
1255   return NS_OK;
1256 }
1257 
1258 nsresult
GetFormValue(nsAString & aValue)1259 nsNPAPIPluginInstance::GetFormValue(nsAString& aValue)
1260 {
1261   aValue.Truncate();
1262 
1263   char *value = nullptr;
1264   nsresult rv = GetValueFromPlugin(NPPVformValue, &value);
1265   if (NS_FAILED(rv) || !value)
1266     return NS_ERROR_FAILURE;
1267 
1268   CopyUTF8toUTF16(value, aValue);
1269 
1270   // NPPVformValue allocates with NPN_MemAlloc(), which uses
1271   // nsMemory.
1272   free(value);
1273 
1274   return NS_OK;
1275 }
1276 
1277 nsresult
PushPopupsEnabledState(bool aEnabled)1278 nsNPAPIPluginInstance::PushPopupsEnabledState(bool aEnabled)
1279 {
1280   nsCOMPtr<nsPIDOMWindowOuter> window = GetDOMWindow();
1281   if (!window)
1282     return NS_ERROR_FAILURE;
1283 
1284   PopupControlState oldState =
1285     window->PushPopupControlState(aEnabled ? openAllowed : openAbused,
1286                                   true);
1287 
1288   if (!mPopupStates.AppendElement(oldState)) {
1289     // Appending to our state stack failed, pop what we just pushed.
1290     window->PopPopupControlState(oldState);
1291     return NS_ERROR_FAILURE;
1292   }
1293 
1294   return NS_OK;
1295 }
1296 
1297 nsresult
PopPopupsEnabledState()1298 nsNPAPIPluginInstance::PopPopupsEnabledState()
1299 {
1300   int32_t last = mPopupStates.Length() - 1;
1301 
1302   if (last < 0) {
1303     // Nothing to pop.
1304     return NS_OK;
1305   }
1306 
1307   nsCOMPtr<nsPIDOMWindowOuter> window = GetDOMWindow();
1308   if (!window)
1309     return NS_ERROR_FAILURE;
1310 
1311   PopupControlState &oldState = mPopupStates[last];
1312 
1313   window->PopPopupControlState(oldState);
1314 
1315   mPopupStates.RemoveElementAt(last);
1316 
1317   return NS_OK;
1318 }
1319 
1320 nsresult
GetPluginAPIVersion(uint16_t * version)1321 nsNPAPIPluginInstance::GetPluginAPIVersion(uint16_t* version)
1322 {
1323   NS_ENSURE_ARG_POINTER(version);
1324 
1325   if (!mPlugin)
1326     return NS_ERROR_FAILURE;
1327 
1328   if (!mPlugin->GetLibrary())
1329     return NS_ERROR_FAILURE;
1330 
1331   NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
1332 
1333   *version = pluginFunctions->version;
1334 
1335   return NS_OK;
1336 }
1337 
1338 nsresult
PrivateModeStateChanged(bool enabled)1339 nsNPAPIPluginInstance::PrivateModeStateChanged(bool enabled)
1340 {
1341   if (RUNNING != mRunning)
1342     return NS_OK;
1343 
1344   PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance informing plugin of private mode state change this=%p\n",this));
1345 
1346   if (!mPlugin || !mPlugin->GetLibrary())
1347     return NS_ERROR_FAILURE;
1348 
1349   NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
1350 
1351   if (!pluginFunctions->setvalue)
1352     return NS_ERROR_FAILURE;
1353 
1354   PluginDestructionGuard guard(this);
1355 
1356   NPError error;
1357   NPBool value = static_cast<NPBool>(enabled);
1358   NS_TRY_SAFE_CALL_RETURN(error, (*pluginFunctions->setvalue)(&mNPP, NPNVprivateModeBool, &value), this,
1359                           NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
1360   return (error == NPERR_NO_ERROR) ? NS_OK : NS_ERROR_FAILURE;
1361 }
1362 
1363 nsresult
IsPrivateBrowsing(bool * aEnabled)1364 nsNPAPIPluginInstance::IsPrivateBrowsing(bool* aEnabled)
1365 {
1366   if (!mOwner)
1367     return NS_ERROR_FAILURE;
1368 
1369   nsCOMPtr<nsIDocument> doc;
1370   mOwner->GetDocument(getter_AddRefs(doc));
1371   NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
1372 
1373   nsCOMPtr<nsPIDOMWindowOuter> domwindow = doc->GetWindow();
1374   NS_ENSURE_TRUE(domwindow, NS_ERROR_FAILURE);
1375 
1376   nsCOMPtr<nsIDocShell> docShell = domwindow->GetDocShell();
1377   nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);
1378   *aEnabled = (loadContext && loadContext->UsePrivateBrowsing());
1379   return NS_OK;
1380 }
1381 
1382 static void
PluginTimerCallback(nsITimer * aTimer,void * aClosure)1383 PluginTimerCallback(nsITimer *aTimer, void *aClosure)
1384 {
1385   nsNPAPITimer* t = (nsNPAPITimer*)aClosure;
1386   NPP npp = t->npp;
1387   uint32_t id = t->id;
1388 
1389   PLUGIN_LOG(PLUGIN_LOG_NOISY, ("nsNPAPIPluginInstance running plugin timer callback this=%p\n", npp->ndata));
1390 
1391   MAIN_THREAD_JNI_REF_GUARD;
1392   // Some plugins (Flash on Android) calls unscheduletimer
1393   // from this callback.
1394   t->inCallback = true;
1395   (*(t->callback))(npp, id);
1396   t->inCallback = false;
1397 
1398   // Make sure we still have an instance and the timer is still alive
1399   // after the callback.
1400   nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance*)npp->ndata;
1401   if (!inst || !inst->TimerWithID(id, nullptr))
1402     return;
1403 
1404   // use UnscheduleTimer to clean up if this is a one-shot timer
1405   uint32_t timerType;
1406   t->timer->GetType(&timerType);
1407   if (t->needUnschedule || timerType == nsITimer::TYPE_ONE_SHOT)
1408     inst->UnscheduleTimer(id);
1409 }
1410 
1411 nsNPAPITimer*
TimerWithID(uint32_t id,uint32_t * index)1412 nsNPAPIPluginInstance::TimerWithID(uint32_t id, uint32_t* index)
1413 {
1414   uint32_t len = mTimers.Length();
1415   for (uint32_t i = 0; i < len; i++) {
1416     if (mTimers[i]->id == id) {
1417       if (index)
1418         *index = i;
1419       return mTimers[i];
1420     }
1421   }
1422   return nullptr;
1423 }
1424 
1425 uint32_t
ScheduleTimer(uint32_t interval,NPBool repeat,void (* timerFunc)(NPP npp,uint32_t timerID))1426 nsNPAPIPluginInstance::ScheduleTimer(uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID))
1427 {
1428   if (RUNNING != mRunning)
1429     return 0;
1430 
1431   nsNPAPITimer *newTimer = new nsNPAPITimer();
1432 
1433   newTimer->inCallback = newTimer->needUnschedule = false;
1434   newTimer->npp = &mNPP;
1435 
1436   // generate ID that is unique to this instance
1437   uint32_t uniqueID = mTimers.Length();
1438   while ((uniqueID == 0) || TimerWithID(uniqueID, nullptr))
1439     uniqueID++;
1440   newTimer->id = uniqueID;
1441 
1442   // create new xpcom timer, scheduled correctly
1443   nsresult rv;
1444   nsCOMPtr<nsITimer> xpcomTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
1445   if (NS_FAILED(rv)) {
1446     delete newTimer;
1447     return 0;
1448   }
1449   const short timerType = (repeat ? (short)nsITimer::TYPE_REPEATING_SLACK : (short)nsITimer::TYPE_ONE_SHOT);
1450   xpcomTimer->InitWithFuncCallback(PluginTimerCallback, newTimer, interval, timerType);
1451   newTimer->timer = xpcomTimer;
1452 
1453   // save callback function
1454   newTimer->callback = timerFunc;
1455 
1456   // add timer to timers array
1457   mTimers.AppendElement(newTimer);
1458 
1459   return newTimer->id;
1460 }
1461 
1462 void
UnscheduleTimer(uint32_t timerID)1463 nsNPAPIPluginInstance::UnscheduleTimer(uint32_t timerID)
1464 {
1465   // find the timer struct by ID
1466   uint32_t index;
1467   nsNPAPITimer* t = TimerWithID(timerID, &index);
1468   if (!t)
1469     return;
1470 
1471   if (t->inCallback) {
1472     t->needUnschedule = true;
1473     return;
1474   }
1475 
1476   // cancel the timer
1477   t->timer->Cancel();
1478 
1479   // remove timer struct from array
1480   mTimers.RemoveElementAt(index);
1481 
1482   // delete timer
1483   delete t;
1484 }
1485 
1486 NPBool
ConvertPoint(double sourceX,double sourceY,NPCoordinateSpace sourceSpace,double * destX,double * destY,NPCoordinateSpace destSpace)1487 nsNPAPIPluginInstance::ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
1488                                     double *destX, double *destY, NPCoordinateSpace destSpace)
1489 {
1490   if (mOwner) {
1491     return mOwner->ConvertPoint(sourceX, sourceY, sourceSpace, destX, destY, destSpace);
1492   }
1493 
1494   return false;
1495 }
1496 
1497 nsresult
GetDOMElement(nsIDOMElement ** result)1498 nsNPAPIPluginInstance::GetDOMElement(nsIDOMElement* *result)
1499 {
1500   if (!mOwner) {
1501     *result = nullptr;
1502     return NS_ERROR_FAILURE;
1503   }
1504 
1505   return mOwner->GetDOMElement(result);
1506 }
1507 
1508 nsresult
InvalidateRect(NPRect * invalidRect)1509 nsNPAPIPluginInstance::InvalidateRect(NPRect *invalidRect)
1510 {
1511   if (RUNNING != mRunning)
1512     return NS_OK;
1513 
1514   if (!mOwner)
1515     return NS_ERROR_FAILURE;
1516 
1517   return mOwner->InvalidateRect(invalidRect);
1518 }
1519 
1520 nsresult
InvalidateRegion(NPRegion invalidRegion)1521 nsNPAPIPluginInstance::InvalidateRegion(NPRegion invalidRegion)
1522 {
1523   if (RUNNING != mRunning)
1524     return NS_OK;
1525 
1526   if (!mOwner)
1527     return NS_ERROR_FAILURE;
1528 
1529   return mOwner->InvalidateRegion(invalidRegion);
1530 }
1531 
1532 nsresult
GetMIMEType(const char ** result)1533 nsNPAPIPluginInstance::GetMIMEType(const char* *result)
1534 {
1535   if (!mMIMEType)
1536     *result = "";
1537   else
1538     *result = mMIMEType;
1539 
1540   return NS_OK;
1541 }
1542 
1543 nsPluginInstanceOwner*
GetOwner()1544 nsNPAPIPluginInstance::GetOwner()
1545 {
1546   return mOwner;
1547 }
1548 
1549 void
SetOwner(nsPluginInstanceOwner * aOwner)1550 nsNPAPIPluginInstance::SetOwner(nsPluginInstanceOwner *aOwner)
1551 {
1552   mOwner = aOwner;
1553 }
1554 
1555 nsresult
AsyncSetWindow(NPWindow & window)1556 nsNPAPIPluginInstance::AsyncSetWindow(NPWindow& window)
1557 {
1558   return NS_ERROR_NOT_IMPLEMENTED;
1559 }
1560 
1561 void
URLRedirectResponse(void * notifyData,NPBool allow)1562 nsNPAPIPluginInstance::URLRedirectResponse(void* notifyData, NPBool allow)
1563 {
1564   if (!notifyData) {
1565     return;
1566   }
1567 
1568   uint32_t listenerCount = mStreamListeners.Length();
1569   for (uint32_t i = 0; i < listenerCount; i++) {
1570     nsNPAPIPluginStreamListener* currentListener = mStreamListeners[i];
1571     if (currentListener->GetNotifyData() == notifyData) {
1572       currentListener->URLRedirectResponse(allow);
1573     }
1574   }
1575 }
1576 
1577 NPError
InitAsyncSurface(NPSize * size,NPImageFormat format,void * initData,NPAsyncSurface * surface)1578 nsNPAPIPluginInstance::InitAsyncSurface(NPSize *size, NPImageFormat format,
1579                                         void *initData, NPAsyncSurface *surface)
1580 {
1581   if (mOwner) {
1582     return mOwner->InitAsyncSurface(size, format, initData, surface);
1583   }
1584 
1585   return NPERR_GENERIC_ERROR;
1586 }
1587 
1588 NPError
FinalizeAsyncSurface(NPAsyncSurface * surface)1589 nsNPAPIPluginInstance::FinalizeAsyncSurface(NPAsyncSurface *surface)
1590 {
1591   if (mOwner) {
1592     return mOwner->FinalizeAsyncSurface(surface);
1593   }
1594 
1595   return NPERR_GENERIC_ERROR;
1596 }
1597 
1598 void
SetCurrentAsyncSurface(NPAsyncSurface * surface,NPRect * changed)1599 nsNPAPIPluginInstance::SetCurrentAsyncSurface(NPAsyncSurface *surface, NPRect *changed)
1600 {
1601   if (mOwner) {
1602     mOwner->SetCurrentAsyncSurface(surface, changed);
1603   }
1604 }
1605 
1606 class CarbonEventModelFailureEvent : public Runnable {
1607 public:
1608   nsCOMPtr<nsIContent> mContent;
1609 
CarbonEventModelFailureEvent(nsIContent * aContent)1610   explicit CarbonEventModelFailureEvent(nsIContent* aContent)
1611     : mContent(aContent)
1612   {}
1613 
~CarbonEventModelFailureEvent()1614   ~CarbonEventModelFailureEvent() {}
1615 
1616   NS_IMETHOD Run();
1617 };
1618 
1619 NS_IMETHODIMP
Run()1620 CarbonEventModelFailureEvent::Run()
1621 {
1622   nsString type = NS_LITERAL_STRING("npapi-carbon-event-model-failure");
1623   nsContentUtils::DispatchTrustedEvent(mContent->GetComposedDoc(), mContent,
1624                                        type, true, true);
1625   return NS_OK;
1626 }
1627 
1628 void
CarbonNPAPIFailure()1629 nsNPAPIPluginInstance::CarbonNPAPIFailure()
1630 {
1631   nsCOMPtr<nsIDOMElement> element;
1632   GetDOMElement(getter_AddRefs(element));
1633   if (!element) {
1634     return;
1635   }
1636 
1637   nsCOMPtr<nsIContent> content(do_QueryInterface(element));
1638   if (!content) {
1639     return;
1640   }
1641 
1642   nsCOMPtr<nsIRunnable> e = new CarbonEventModelFailureEvent(content);
1643   nsresult rv = NS_DispatchToCurrentThread(e);
1644   if (NS_FAILED(rv)) {
1645     NS_WARNING("Failed to dispatch CarbonEventModelFailureEvent.");
1646   }
1647 }
1648 
1649 static bool
GetJavaVersionFromMimetype(nsPluginTag * pluginTag,nsCString & version)1650 GetJavaVersionFromMimetype(nsPluginTag* pluginTag, nsCString& version)
1651 {
1652   for (uint32_t i = 0; i < pluginTag->MimeTypes().Length(); ++i) {
1653     nsCString type = pluginTag->MimeTypes()[i];
1654     nsAutoCString jpi("application/x-java-applet;jpi-version=");
1655 
1656     int32_t idx = type.Find(jpi, false, 0, -1);
1657     if (idx != 0) {
1658       continue;
1659     }
1660 
1661     type.Cut(0, jpi.Length());
1662     if (type.IsEmpty()) {
1663       continue;
1664     }
1665 
1666     type.ReplaceChar('_', '.');
1667     version = type;
1668     return true;
1669   }
1670 
1671   return false;
1672 }
1673 
1674 void
CheckJavaC2PJSObjectQuirk(uint16_t paramCount,const char * const * paramNames,const char * const * paramValues)1675 nsNPAPIPluginInstance::CheckJavaC2PJSObjectQuirk(uint16_t paramCount,
1676                                                  const char* const* paramNames,
1677                                                  const char* const* paramValues)
1678 {
1679   if (!mMIMEType || !mPlugin) {
1680     return;
1681   }
1682 
1683   nsPluginTagType tagtype;
1684   nsresult rv = GetTagType(&tagtype);
1685   if (NS_FAILED(rv) ||
1686       (tagtype != nsPluginTagType_Applet)) {
1687     return;
1688   }
1689 
1690   RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
1691   if (!pluginHost) {
1692     return;
1693   }
1694 
1695   nsPluginTag* pluginTag = pluginHost->TagForPlugin(mPlugin);
1696   if (!pluginTag ||
1697       !pluginTag->mIsJavaPlugin) {
1698     return;
1699   }
1700 
1701   // check the params for "code" being present and non-empty
1702   bool haveCodeParam = false;
1703   bool isCodeParamEmpty = true;
1704 
1705   for (uint16_t i = paramCount; i > 0; --i) {
1706     if (PL_strcasecmp(paramNames[i - 1], "code") == 0) {
1707       haveCodeParam = true;
1708       if (strlen(paramValues[i - 1]) > 0) {
1709         isCodeParamEmpty = false;
1710       }
1711       break;
1712     }
1713   }
1714 
1715   // Due to the Java version being specified inconsistently across platforms
1716   // check the version via the mimetype for choosing specific Java versions
1717   nsCString javaVersion;
1718   if (!GetJavaVersionFromMimetype(pluginTag, javaVersion)) {
1719     return;
1720   }
1721 
1722   mozilla::Version version(javaVersion.get());
1723 
1724   if (version >= "1.7.0.4") {
1725     return;
1726   }
1727 
1728   if (!haveCodeParam && version >= "1.6.0.34" && version < "1.7") {
1729     return;
1730   }
1731 
1732   if (haveCodeParam && !isCodeParamEmpty) {
1733     return;
1734   }
1735 
1736   mHaveJavaC2PJSObjectQuirk = true;
1737 }
1738 
1739 double
GetContentsScaleFactor()1740 nsNPAPIPluginInstance::GetContentsScaleFactor()
1741 {
1742   double scaleFactor = 1.0;
1743   if (mOwner) {
1744     mOwner->GetContentsScaleFactor(&scaleFactor);
1745   }
1746   return scaleFactor;
1747 }
1748 
1749 float
GetCSSZoomFactor()1750 nsNPAPIPluginInstance::GetCSSZoomFactor()
1751 {
1752   float zoomFactor = 1.0;
1753   if (mOwner) {
1754     mOwner->GetCSSZoomFactor(&zoomFactor);
1755   }
1756   return zoomFactor;
1757 }
1758 
1759 nsresult
GetRunID(uint32_t * aRunID)1760 nsNPAPIPluginInstance::GetRunID(uint32_t* aRunID)
1761 {
1762   if (NS_WARN_IF(!aRunID)) {
1763     return NS_ERROR_INVALID_POINTER;
1764   }
1765 
1766   if (NS_WARN_IF(!mPlugin)) {
1767     return NS_ERROR_FAILURE;
1768   }
1769 
1770   PluginLibrary* library = mPlugin->GetLibrary();
1771   if (!library) {
1772     return NS_ERROR_FAILURE;
1773   }
1774 
1775   return library->GetRunID(aRunID);
1776 }
1777 
1778 nsresult
GetOrCreateAudioChannelAgent(nsIAudioChannelAgent ** aAgent)1779 nsNPAPIPluginInstance::GetOrCreateAudioChannelAgent(nsIAudioChannelAgent** aAgent)
1780 {
1781   if (!mAudioChannelAgent) {
1782     nsresult rv;
1783     mAudioChannelAgent = do_CreateInstance("@mozilla.org/audiochannelagent;1", &rv);
1784     if (NS_WARN_IF(!mAudioChannelAgent)) {
1785       return NS_ERROR_FAILURE;
1786     }
1787 
1788     nsCOMPtr<nsPIDOMWindowOuter> window = GetDOMWindow();
1789     if (NS_WARN_IF(!window)) {
1790       return NS_ERROR_FAILURE;
1791     }
1792 
1793     rv = mAudioChannelAgent->Init(window->GetCurrentInnerWindow(),
1794                                  (int32_t)AudioChannelService::GetDefaultAudioChannel(),
1795                                  this);
1796     if (NS_WARN_IF(NS_FAILED(rv))) {
1797       return rv;
1798     }
1799   }
1800 
1801   nsCOMPtr<nsIAudioChannelAgent> agent = mAudioChannelAgent;
1802   agent.forget(aAgent);
1803   return NS_OK;
1804 }
1805 
1806 NS_IMETHODIMP
WindowVolumeChanged(float aVolume,bool aMuted)1807 nsNPAPIPluginInstance::WindowVolumeChanged(float aVolume, bool aMuted)
1808 {
1809   // We just support mute/unmute
1810   nsresult rv = SetMuted(aMuted);
1811   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "SetMuted failed");
1812   if (mMuted != aMuted) {
1813     mMuted = aMuted;
1814     AudioChannelService::AudibleState audible = aMuted ?
1815       AudioChannelService::AudibleState::eNotAudible :
1816       AudioChannelService::AudibleState::eAudible;
1817     mAudioChannelAgent->NotifyStartedAudible(audible,
1818                                              AudioChannelService::AudibleChangedReasons::eVolumeChanged);
1819   }
1820   return rv;
1821 }
1822 
1823 NS_IMETHODIMP
WindowSuspendChanged(nsSuspendedTypes aSuspend)1824 nsNPAPIPluginInstance::WindowSuspendChanged(nsSuspendedTypes aSuspend)
1825 {
1826   // It doesn't support suspended, so we just do something like mute/unmute.
1827   WindowVolumeChanged(1.0, /* useless */
1828                       aSuspend != nsISuspendedTypes::NONE_SUSPENDED);
1829   return NS_OK;
1830 }
1831 
1832 NS_IMETHODIMP
WindowAudioCaptureChanged(bool aCapture)1833 nsNPAPIPluginInstance::WindowAudioCaptureChanged(bool aCapture)
1834 {
1835   return NS_OK;
1836 }
1837 
1838 nsresult
SetMuted(bool aIsMuted)1839 nsNPAPIPluginInstance::SetMuted(bool aIsMuted)
1840 {
1841   if (RUNNING != mRunning)
1842     return NS_OK;
1843 
1844   PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance informing plugin of mute state change this=%p\n",this));
1845 
1846   if (!mPlugin || !mPlugin->GetLibrary())
1847     return NS_ERROR_FAILURE;
1848 
1849   NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
1850 
1851   if (!pluginFunctions->setvalue)
1852     return NS_ERROR_FAILURE;
1853 
1854   PluginDestructionGuard guard(this);
1855 
1856   NPError error;
1857   NPBool value = static_cast<NPBool>(aIsMuted);
1858   NS_TRY_SAFE_CALL_RETURN(error, (*pluginFunctions->setvalue)(&mNPP, NPNVmuteAudioBool, &value), this,
1859                           NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
1860   return (error == NPERR_NO_ERROR) ? NS_OK : NS_ERROR_FAILURE;
1861 }
1862