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 #include "mozilla/Logging.h"
9 #include "nscore.h"
10 #include "prenv.h"
11
12 #include "nsNPAPIPluginInstance.h"
13 #include "nsNPAPIPlugin.h"
14 #include "nsNPAPIPluginStreamListener.h"
15 #include "nsPluginHost.h"
16 #include "nsPluginLogging.h"
17 #include "nsContentUtils.h"
18 #include "nsPluginInstanceOwner.h"
19
20 #include "nsThreadUtils.h"
21 #include "mozilla/dom/Document.h"
22 #include "nsIDocShell.h"
23 #include "nsIScriptGlobalObject.h"
24 #include "nsIScriptContext.h"
25 #include "nsDirectoryServiceDefs.h"
26 #include "nsJSNPRuntime.h"
27 #include "nsPluginStreamListenerPeer.h"
28 #include "nsSize.h"
29 #include "nsNetCID.h"
30 #include "nsIContent.h"
31 #include "nsVersionComparator.h"
32 #include "mozilla/Preferences.h"
33 #include "mozilla/Unused.h"
34 #include "nsILoadContext.h"
35 #include "mozilla/dom/Element.h"
36 #include "mozilla/dom/HTMLObjectElementBinding.h"
37 #include "AudioChannelService.h"
38
39 using namespace mozilla;
40 using namespace mozilla::dom;
41
42 using namespace mozilla;
43 using namespace mozilla::plugins::parent;
44 using namespace mozilla::layers;
45
NS_IMPL_ISUPPORTS(nsNPAPIPluginInstance,nsIAudioChannelAgentCallback)46 NS_IMPL_ISUPPORTS(nsNPAPIPluginInstance, nsIAudioChannelAgentCallback)
47
48 nsNPAPIPluginInstance::nsNPAPIPluginInstance()
49 : mDrawingModel(kDefaultDrawingModel),
50 mRunning(NOT_STARTED),
51 mWindowless(false),
52 mTransparent(false),
53 mCached(false),
54 mUsesDOMForCursor(false),
55 mInPluginInitCall(false),
56 mPlugin(nullptr),
57 mMIMEType(nullptr),
58 mOwner(nullptr)
59 #ifdef XP_MACOSX
60 ,
61 mCurrentPluginEvent(nullptr)
62 #endif
63 ,
64 mCachedParamLength(0),
65 mCachedParamNames(nullptr),
66 mCachedParamValues(nullptr) {
67 mNPP.pdata = nullptr;
68 mNPP.ndata = this;
69
70 PLUGIN_LOG(PLUGIN_LOG_BASIC, ("nsNPAPIPluginInstance ctor: this=%p\n", this));
71 }
72
~nsNPAPIPluginInstance()73 nsNPAPIPluginInstance::~nsNPAPIPluginInstance() {
74 PLUGIN_LOG(PLUGIN_LOG_BASIC, ("nsNPAPIPluginInstance dtor: this=%p\n", this));
75
76 if (mMIMEType) {
77 free(mMIMEType);
78 mMIMEType = nullptr;
79 }
80
81 if (!mCachedParamValues || !mCachedParamNames) {
82 return;
83 }
84 MOZ_ASSERT(mCachedParamValues && mCachedParamNames);
85
86 for (uint32_t i = 0; i < mCachedParamLength; i++) {
87 if (mCachedParamNames[i]) {
88 free(mCachedParamNames[i]);
89 mCachedParamNames[i] = nullptr;
90 }
91 if (mCachedParamValues[i]) {
92 free(mCachedParamValues[i]);
93 mCachedParamValues[i] = nullptr;
94 }
95 }
96
97 free(mCachedParamNames);
98 mCachedParamNames = nullptr;
99
100 free(mCachedParamValues);
101 mCachedParamValues = nullptr;
102 }
103
104 uint32_t nsNPAPIPluginInstance::gInUnsafePluginCalls = 0;
105
Destroy()106 void nsNPAPIPluginInstance::Destroy() {
107 Stop();
108 mPlugin = nullptr;
109 mAudioChannelAgent = nullptr;
110 }
111
StopTime()112 TimeStamp nsNPAPIPluginInstance::StopTime() { return mStopTime; }
113
Initialize(nsNPAPIPlugin * aPlugin,nsPluginInstanceOwner * aOwner,const nsACString & aMIMEType)114 nsresult nsNPAPIPluginInstance::Initialize(nsNPAPIPlugin* aPlugin,
115 nsPluginInstanceOwner* aOwner,
116 const nsACString& aMIMEType) {
117 AUTO_PROFILER_LABEL("nsNPAPIPlugin::Initialize", OTHER);
118 PLUGIN_LOG(PLUGIN_LOG_NORMAL,
119 ("nsNPAPIPluginInstance::Initialize this=%p\n", this));
120
121 NS_ENSURE_ARG_POINTER(aPlugin);
122 NS_ENSURE_ARG_POINTER(aOwner);
123
124 mPlugin = aPlugin;
125 mOwner = aOwner;
126
127 if (!aMIMEType.IsEmpty()) {
128 mMIMEType = ToNewCString(aMIMEType);
129 }
130
131 return Start();
132 }
133
Stop()134 nsresult nsNPAPIPluginInstance::Stop() {
135 PLUGIN_LOG(PLUGIN_LOG_NORMAL,
136 ("nsNPAPIPluginInstance::Stop this=%p\n", this));
137
138 // Make sure the plugin didn't leave popups enabled.
139 if (mPopupStates.Length() > 0) {
140 PopupBlocker::PopPopupControlState(PopupBlocker::openAbused);
141 }
142
143 if (RUNNING != mRunning) {
144 return NS_OK;
145 }
146
147 // clean up all outstanding timers
148 for (uint32_t i = mTimers.Length(); i > 0; i--)
149 UnscheduleTimer(mTimers[i - 1]->id);
150
151 // If there's code from this plugin instance on the stack, delay the
152 // destroy.
153 if (PluginDestructionGuard::DelayDestroy(this)) {
154 return NS_OK;
155 }
156
157 mRunning = DESTROYING;
158 mStopTime = TimeStamp::Now();
159
160 // clean up open streams
161 while (mStreamListeners.Length() > 0) {
162 RefPtr<nsNPAPIPluginStreamListener> currentListener(mStreamListeners[0]);
163 currentListener->CleanUpStream(NPRES_USER_BREAK);
164 mStreamListeners.RemoveElement(currentListener);
165 }
166
167 if (!mPlugin || !mPlugin->GetLibrary()) return NS_ERROR_FAILURE;
168
169 NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
170
171 NPError error = NPERR_GENERIC_ERROR;
172 if (pluginFunctions->destroy) {
173 NPSavedData* sdata = 0;
174
175 NS_TRY_SAFE_CALL_RETURN(error, (*pluginFunctions->destroy)(&mNPP, &sdata),
176 this, NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
177
178 NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
179 ("NPP Destroy called: this=%p, npp=%p, return=%d\n", this,
180 &mNPP, error));
181 }
182 mRunning = DESTROYED;
183
184 nsJSNPRuntime::OnPluginDestroy(&mNPP);
185
186 if (error != NPERR_NO_ERROR)
187 return NS_ERROR_FAILURE;
188 else
189 return NS_OK;
190 }
191
GetDOMWindow()192 already_AddRefed<nsPIDOMWindowOuter> nsNPAPIPluginInstance::GetDOMWindow() {
193 if (!mOwner) return nullptr;
194
195 RefPtr<nsPluginInstanceOwner> kungFuDeathGrip(mOwner);
196
197 nsCOMPtr<Document> doc;
198 kungFuDeathGrip->GetDocument(getter_AddRefs(doc));
199 if (!doc) return nullptr;
200
201 RefPtr<nsPIDOMWindowOuter> window = doc->GetWindow();
202
203 return window.forget();
204 }
205
GetTagType(nsPluginTagType * result)206 nsresult nsNPAPIPluginInstance::GetTagType(nsPluginTagType* result) {
207 if (!mOwner) {
208 return NS_ERROR_FAILURE;
209 }
210
211 return mOwner->GetTagType(result);
212 }
213
214 nsTArray<nsNPAPIPluginStreamListener*>*
StreamListeners()215 nsNPAPIPluginInstance::StreamListeners() {
216 return &mStreamListeners;
217 }
218
219 nsTArray<nsPluginStreamListenerPeer*>*
FileCachedStreamListeners()220 nsNPAPIPluginInstance::FileCachedStreamListeners() {
221 return &mFileCachedStreamListeners;
222 }
223
Start()224 nsresult nsNPAPIPluginInstance::Start() {
225 if (mRunning == RUNNING) {
226 return NS_OK;
227 }
228
229 if (!mOwner) {
230 MOZ_ASSERT(false, "Should not be calling Start() on unowned plugin.");
231 return NS_ERROR_FAILURE;
232 }
233
234 PluginDestructionGuard guard(this);
235
236 nsTArray<MozPluginParameter> attributes;
237 nsTArray<MozPluginParameter> params;
238
239 nsPluginTagType tagtype;
240 nsresult rv = GetTagType(&tagtype);
241 if (NS_SUCCEEDED(rv)) {
242 mOwner->GetAttributes(attributes);
243 mOwner->GetParameters(params);
244 } else {
245 MOZ_ASSERT(false, "Failed to get tag type.");
246 }
247
248 mCachedParamLength = attributes.Length() + 1 + params.Length();
249
250 // We add an extra entry "PARAM" as a separator between the attribute
251 // and param values, but we don't count it if there are no <param> entries.
252 // Legacy behavior quirk.
253 uint32_t quirkParamLength =
254 params.Length() ? mCachedParamLength : attributes.Length();
255
256 mCachedParamNames = (char**)moz_xmalloc(sizeof(char*) * mCachedParamLength);
257 mCachedParamValues = (char**)moz_xmalloc(sizeof(char*) * mCachedParamLength);
258
259 for (uint32_t i = 0; i < attributes.Length(); i++) {
260 mCachedParamNames[i] = ToNewUTF8String(attributes[i].mName);
261 mCachedParamValues[i] = ToNewUTF8String(attributes[i].mValue);
262 }
263
264 mCachedParamNames[attributes.Length()] =
265 ToNewUTF8String(NS_LITERAL_STRING("PARAM"));
266 mCachedParamValues[attributes.Length()] = nullptr;
267
268 for (uint32_t i = 0, pos = attributes.Length() + 1; i < params.Length();
269 i++) {
270 mCachedParamNames[pos] = ToNewUTF8String(params[i].mName);
271 mCachedParamValues[pos] = ToNewUTF8String(params[i].mValue);
272 pos++;
273 }
274
275 const char* mimetype;
276 NPError error = NPERR_GENERIC_ERROR;
277
278 GetMIMEType(&mimetype);
279
280 bool oldVal = mInPluginInitCall;
281 mInPluginInitCall = true;
282
283 // Need this on the stack before calling NPP_New otherwise some callbacks that
284 // the plugin may make could fail (NPN_HasProperty, for example).
285 NPPAutoPusher autopush(&mNPP);
286
287 if (!mPlugin) return NS_ERROR_FAILURE;
288
289 PluginLibrary* library = mPlugin->GetLibrary();
290 if (!library) return NS_ERROR_FAILURE;
291
292 // Mark this instance as running before calling NPP_New because the plugin may
293 // call other NPAPI functions, like NPN_GetURLNotify, that assume this is set
294 // before returning. If the plugin returns failure, we'll clear it out below.
295 mRunning = RUNNING;
296
297 nsresult newResult =
298 library->NPP_New((char*)mimetype, &mNPP, quirkParamLength,
299 mCachedParamNames, mCachedParamValues, nullptr, &error);
300 mInPluginInitCall = oldVal;
301
302 NPP_PLUGIN_LOG(
303 PLUGIN_LOG_NORMAL,
304 ("NPP New called: this=%p, npp=%p, mime=%s, argc=%d, return=%d\n", this,
305 &mNPP, mimetype, quirkParamLength, error));
306
307 if (NS_FAILED(newResult) || error != NPERR_NO_ERROR) {
308 mRunning = DESTROYED;
309 nsJSNPRuntime::OnPluginDestroy(&mNPP);
310 return NS_ERROR_FAILURE;
311 }
312
313 return newResult;
314 }
315
SetWindow(NPWindow * window)316 nsresult nsNPAPIPluginInstance::SetWindow(NPWindow* window) {
317 // NPAPI plugins don't want a SetWindow(nullptr).
318 if (!window || RUNNING != mRunning) return NS_OK;
319
320 #if MOZ_WIDGET_GTK
321 // bug 108347, flash plugin on linux doesn't like window->width <= 0
322 return NS_OK;
323 #endif
324
325 if (!mPlugin || !mPlugin->GetLibrary()) return NS_ERROR_FAILURE;
326
327 NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
328
329 if (pluginFunctions->setwindow) {
330 PluginDestructionGuard guard(this);
331
332 // XXX Turns out that NPPluginWindow and NPWindow are structurally
333 // identical (on purpose!), so there's no need to make a copy.
334
335 PLUGIN_LOG(PLUGIN_LOG_NORMAL,
336 ("nsNPAPIPluginInstance::SetWindow (about to call it) this=%p\n",
337 this));
338
339 bool oldVal = mInPluginInitCall;
340 mInPluginInitCall = true;
341
342 NPPAutoPusher nppPusher(&mNPP);
343
344 NPError error;
345 NS_TRY_SAFE_CALL_RETURN(
346 error, (*pluginFunctions->setwindow)(&mNPP, (NPWindow*)window), this,
347 NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
348 // 'error' is only used if this is a logging-enabled build.
349 // That is somewhat complex to check, so we just use "unused"
350 // to suppress any compiler warnings in build configurations
351 // where the logging is a no-op.
352 mozilla::Unused << error;
353
354 mInPluginInitCall = oldVal;
355
356 NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
357 ("NPP SetWindow called: this=%p, [x=%d,y=%d,w=%d,h=%d], "
358 "clip[t=%d,b=%d,l=%d,r=%d], return=%d\n",
359 this, window->x, window->y, window->width, window->height,
360 window->clipRect.top, window->clipRect.bottom,
361 window->clipRect.left, window->clipRect.right, error));
362 }
363 return NS_OK;
364 }
365
NewStreamListener(const char * aURL,void * notifyData,nsNPAPIPluginStreamListener ** listener)366 nsresult nsNPAPIPluginInstance::NewStreamListener(
367 const char* aURL, void* notifyData,
368 nsNPAPIPluginStreamListener** listener) {
369 RefPtr<nsNPAPIPluginStreamListener> sl =
370 new nsNPAPIPluginStreamListener(this, notifyData, aURL);
371
372 mStreamListeners.AppendElement(sl);
373
374 sl.forget(listener);
375
376 return NS_OK;
377 }
378
Print(NPPrint * platformPrint)379 nsresult nsNPAPIPluginInstance::Print(NPPrint* platformPrint) {
380 NS_ENSURE_TRUE(platformPrint, NS_ERROR_NULL_POINTER);
381
382 PluginDestructionGuard guard(this);
383
384 if (!mPlugin || !mPlugin->GetLibrary()) return NS_ERROR_FAILURE;
385
386 NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
387
388 NPPrint* thePrint = (NPPrint*)platformPrint;
389
390 // to be compatible with the older SDK versions and to match what
391 // NPAPI and other browsers do, overwrite |window.type| field with one
392 // more copy of |platformPrint|. See bug 113264
393 uint16_t sdkmajorversion = (pluginFunctions->version & 0xff00) >> 8;
394 uint16_t sdkminorversion = pluginFunctions->version & 0x00ff;
395 if ((sdkmajorversion == 0) && (sdkminorversion < 11)) {
396 // Let's copy platformPrint bytes over to where it was supposed to be
397 // in older versions -- four bytes towards the beginning of the struct
398 // but we should be careful about possible misalignments
399 if (sizeof(NPWindowType) >= sizeof(void*)) {
400 void* source = thePrint->print.embedPrint.platformPrint;
401 void** destination = (void**)&(thePrint->print.embedPrint.window.type);
402 *destination = source;
403 } else {
404 NS_ERROR("Incompatible OS for assignment");
405 }
406 }
407
408 if (pluginFunctions->print)
409 NS_TRY_SAFE_CALL_VOID((*pluginFunctions->print)(&mNPP, thePrint), this,
410 NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
411
412 NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
413 ("NPP PrintProc called: this=%p, pDC=%p, "
414 "[x=%d,y=%d,w=%d,h=%d], clip[t=%d,b=%d,l=%d,r=%d]\n",
415 this, platformPrint->print.embedPrint.platformPrint,
416 platformPrint->print.embedPrint.window.x,
417 platformPrint->print.embedPrint.window.y,
418 platformPrint->print.embedPrint.window.width,
419 platformPrint->print.embedPrint.window.height,
420 platformPrint->print.embedPrint.window.clipRect.top,
421 platformPrint->print.embedPrint.window.clipRect.bottom,
422 platformPrint->print.embedPrint.window.clipRect.left,
423 platformPrint->print.embedPrint.window.clipRect.right));
424
425 return NS_OK;
426 }
427
HandleEvent(void * event,int16_t * result,NSPluginCallReentry aSafeToReenterGecko)428 nsresult nsNPAPIPluginInstance::HandleEvent(
429 void* event, int16_t* result, NSPluginCallReentry aSafeToReenterGecko) {
430 if (RUNNING != mRunning) return NS_OK;
431
432 AUTO_PROFILER_LABEL("nsNPAPIPluginInstance::HandleEvent", OTHER);
433
434 if (!event) return NS_ERROR_FAILURE;
435
436 PluginDestructionGuard guard(this);
437
438 if (!mPlugin || !mPlugin->GetLibrary()) return NS_ERROR_FAILURE;
439
440 NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
441
442 int16_t tmpResult = kNPEventNotHandled;
443
444 if (pluginFunctions->event) {
445 #ifdef XP_MACOSX
446 mCurrentPluginEvent = event;
447 #endif
448 #if defined(XP_WIN)
449 NS_TRY_SAFE_CALL_RETURN(tmpResult, (*pluginFunctions->event)(&mNPP, event),
450 this, aSafeToReenterGecko);
451 #else
452 tmpResult = (*pluginFunctions->event)(&mNPP, event);
453 #endif
454 NPP_PLUGIN_LOG(
455 PLUGIN_LOG_NOISY,
456 ("NPP HandleEvent called: this=%p, npp=%p, event=%p, return=%d\n", this,
457 &mNPP, event, tmpResult));
458
459 if (result) *result = tmpResult;
460 #ifdef XP_MACOSX
461 mCurrentPluginEvent = nullptr;
462 #endif
463 }
464
465 return NS_OK;
466 }
467
GetValueFromPlugin(NPPVariable variable,void * value)468 nsresult nsNPAPIPluginInstance::GetValueFromPlugin(NPPVariable variable,
469 void* value) {
470 if (!mPlugin || !mPlugin->GetLibrary()) return NS_ERROR_FAILURE;
471
472 NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
473
474 nsresult rv = NS_ERROR_FAILURE;
475
476 if (pluginFunctions->getvalue && RUNNING == mRunning) {
477 PluginDestructionGuard guard(this);
478
479 NPError pluginError = NPERR_GENERIC_ERROR;
480 NS_TRY_SAFE_CALL_RETURN(
481 pluginError, (*pluginFunctions->getvalue)(&mNPP, variable, value), this,
482 NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
483 NPP_PLUGIN_LOG(
484 PLUGIN_LOG_NORMAL,
485 ("NPP GetValue called: this=%p, npp=%p, var=%d, value=%p, return=%d\n",
486 this, &mNPP, variable, value, pluginError));
487
488 if (pluginError == NPERR_NO_ERROR) {
489 rv = NS_OK;
490 }
491 }
492
493 return rv;
494 }
495
GetPlugin()496 nsNPAPIPlugin* nsNPAPIPluginInstance::GetPlugin() { return mPlugin; }
497
GetNPP(NPP * aNPP)498 nsresult nsNPAPIPluginInstance::GetNPP(NPP* aNPP) {
499 if (aNPP)
500 *aNPP = &mNPP;
501 else
502 return NS_ERROR_NULL_POINTER;
503
504 return NS_OK;
505 }
506
SetWindowless(bool aWindowless)507 NPError nsNPAPIPluginInstance::SetWindowless(bool aWindowless) {
508 mWindowless = aWindowless;
509 return NPERR_NO_ERROR;
510 }
511
SetTransparent(bool aTransparent)512 NPError nsNPAPIPluginInstance::SetTransparent(bool aTransparent) {
513 mTransparent = aTransparent;
514 return NPERR_NO_ERROR;
515 }
516
SetUsesDOMForCursor(bool aUsesDOMForCursor)517 NPError nsNPAPIPluginInstance::SetUsesDOMForCursor(bool aUsesDOMForCursor) {
518 mUsesDOMForCursor = aUsesDOMForCursor;
519 return NPERR_NO_ERROR;
520 }
521
UsesDOMForCursor()522 bool nsNPAPIPluginInstance::UsesDOMForCursor() { return mUsesDOMForCursor; }
523
SetDrawingModel(NPDrawingModel aModel)524 void nsNPAPIPluginInstance::SetDrawingModel(NPDrawingModel aModel) {
525 mDrawingModel = aModel;
526 }
527
RedrawPlugin()528 void nsNPAPIPluginInstance::RedrawPlugin() { mOwner->RedrawPlugin(); }
529
530 #if defined(XP_MACOSX)
SetEventModel(NPEventModel aModel)531 void nsNPAPIPluginInstance::SetEventModel(NPEventModel aModel) {
532 // the event model needs to be set for the object frame immediately
533 if (!mOwner) {
534 NS_WARNING("Trying to set event model without a plugin instance owner!");
535 return;
536 }
537
538 mOwner->SetEventModel(aModel);
539 }
540 #endif
541
GetDrawingModel(int32_t * aModel)542 nsresult nsNPAPIPluginInstance::GetDrawingModel(int32_t* aModel) {
543 *aModel = (int32_t)mDrawingModel;
544 return NS_OK;
545 }
546
IsRemoteDrawingCoreAnimation(bool * aDrawing)547 nsresult nsNPAPIPluginInstance::IsRemoteDrawingCoreAnimation(bool* aDrawing) {
548 #ifdef XP_MACOSX
549 if (!mPlugin) return NS_ERROR_FAILURE;
550
551 PluginLibrary* library = mPlugin->GetLibrary();
552 if (!library) return NS_ERROR_FAILURE;
553
554 return library->IsRemoteDrawingCoreAnimation(&mNPP, aDrawing);
555 #else
556 return NS_ERROR_FAILURE;
557 #endif
558 }
559
ContentsScaleFactorChanged(double aContentsScaleFactor)560 nsresult nsNPAPIPluginInstance::ContentsScaleFactorChanged(
561 double aContentsScaleFactor) {
562 #if defined(XP_MACOSX) || defined(XP_WIN)
563 if (!mPlugin) return NS_ERROR_FAILURE;
564
565 PluginLibrary* library = mPlugin->GetLibrary();
566 if (!library) return NS_ERROR_FAILURE;
567
568 // We only need to call this if the plugin is running OOP.
569 if (!library->IsOOP()) return NS_OK;
570
571 return library->ContentsScaleFactorChanged(&mNPP, aContentsScaleFactor);
572 #else
573 return NS_ERROR_FAILURE;
574 #endif
575 }
576
CSSZoomFactorChanged(float aCSSZoomFactor)577 nsresult nsNPAPIPluginInstance::CSSZoomFactorChanged(float aCSSZoomFactor) {
578 if (RUNNING != mRunning) return NS_OK;
579
580 PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance informing plugin of "
581 "CSS Zoom Factor change this=%p\n",
582 this));
583
584 if (!mPlugin || !mPlugin->GetLibrary()) return NS_ERROR_FAILURE;
585
586 NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
587
588 if (!pluginFunctions->setvalue) return NS_ERROR_FAILURE;
589
590 PluginDestructionGuard guard(this);
591
592 NPError error;
593 double value = static_cast<double>(aCSSZoomFactor);
594 NS_TRY_SAFE_CALL_RETURN(
595 error, (*pluginFunctions->setvalue)(&mNPP, NPNVCSSZoomFactor, &value),
596 this, NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
597 return (error == NPERR_NO_ERROR) ? NS_OK : NS_ERROR_FAILURE;
598 }
599
GetJSObject(JSContext * cx,JSObject ** outObject)600 nsresult nsNPAPIPluginInstance::GetJSObject(JSContext* cx,
601 JSObject** outObject) {
602 NPObject* npobj = nullptr;
603 nsresult rv = GetValueFromPlugin(NPPVpluginScriptableNPObject, &npobj);
604 if (NS_FAILED(rv) || !npobj) return NS_ERROR_FAILURE;
605
606 *outObject = nsNPObjWrapper::GetNewOrUsed(&mNPP, cx, npobj);
607
608 _releaseobject(npobj);
609
610 return NS_OK;
611 }
612
SetCached(bool aCache)613 void nsNPAPIPluginInstance::SetCached(bool aCache) { mCached = aCache; }
614
ShouldCache()615 bool nsNPAPIPluginInstance::ShouldCache() { return mCached; }
616
IsWindowless(bool * isWindowless)617 nsresult nsNPAPIPluginInstance::IsWindowless(bool* isWindowless) {
618 #if defined(XP_MACOSX)
619 // All OS X plugins are windowless.
620 *isWindowless = true;
621 #else
622 *isWindowless = mWindowless;
623 #endif
624 return NS_OK;
625 }
626
627 class MOZ_STACK_CLASS AutoPluginLibraryCall {
628 public:
AutoPluginLibraryCall(nsNPAPIPluginInstance * aThis)629 explicit AutoPluginLibraryCall(nsNPAPIPluginInstance* aThis)
630 : mThis(aThis), mGuard(aThis), mLibrary(nullptr) {
631 nsNPAPIPlugin* plugin = mThis->GetPlugin();
632 if (plugin) mLibrary = plugin->GetLibrary();
633 }
operator bool()634 explicit operator bool() { return !!mLibrary; }
operator ->()635 PluginLibrary* operator->() { return mLibrary; }
636
637 private:
638 nsNPAPIPluginInstance* mThis;
639 PluginDestructionGuard mGuard;
640 PluginLibrary* mLibrary;
641 };
642
AsyncSetWindow(NPWindow * window)643 nsresult nsNPAPIPluginInstance::AsyncSetWindow(NPWindow* window) {
644 if (RUNNING != mRunning) return NS_OK;
645
646 AutoPluginLibraryCall library(this);
647 if (!library) return NS_ERROR_FAILURE;
648
649 return library->AsyncSetWindow(&mNPP, window);
650 }
651
GetImageContainer(ImageContainer ** aContainer)652 nsresult nsNPAPIPluginInstance::GetImageContainer(ImageContainer** aContainer) {
653 *aContainer = nullptr;
654
655 if (RUNNING != mRunning) return NS_OK;
656
657 AutoPluginLibraryCall library(this);
658 return !library ? NS_ERROR_FAILURE
659 : library->GetImageContainer(&mNPP, aContainer);
660 }
661
GetImageSize(nsIntSize * aSize)662 nsresult nsNPAPIPluginInstance::GetImageSize(nsIntSize* aSize) {
663 *aSize = nsIntSize(0, 0);
664
665 if (RUNNING != mRunning) return NS_OK;
666
667 AutoPluginLibraryCall library(this);
668 return !library ? NS_ERROR_FAILURE : library->GetImageSize(&mNPP, aSize);
669 }
670
671 #if defined(XP_WIN)
GetScrollCaptureContainer(ImageContainer ** aContainer)672 nsresult nsNPAPIPluginInstance::GetScrollCaptureContainer(
673 ImageContainer** aContainer) {
674 *aContainer = nullptr;
675
676 if (RUNNING != mRunning) return NS_OK;
677
678 AutoPluginLibraryCall library(this);
679 return !library ? NS_ERROR_FAILURE
680 : library->GetScrollCaptureContainer(&mNPP, aContainer);
681 }
682 #endif
683
HandledWindowedPluginKeyEvent(const NativeEventData & aKeyEventData,bool aIsConsumed)684 nsresult nsNPAPIPluginInstance::HandledWindowedPluginKeyEvent(
685 const NativeEventData& aKeyEventData, bool aIsConsumed) {
686 if (NS_WARN_IF(!mPlugin)) {
687 return NS_ERROR_FAILURE;
688 }
689
690 PluginLibrary* library = mPlugin->GetLibrary();
691 if (NS_WARN_IF(!library)) {
692 return NS_ERROR_FAILURE;
693 }
694 return library->HandledWindowedPluginKeyEvent(&mNPP, aKeyEventData,
695 aIsConsumed);
696 }
697
DidComposite()698 void nsNPAPIPluginInstance::DidComposite() {
699 if (RUNNING != mRunning) return;
700
701 AutoPluginLibraryCall library(this);
702 library->DidComposite(&mNPP);
703 }
704
NotifyPainted(void)705 nsresult nsNPAPIPluginInstance::NotifyPainted(void) {
706 MOZ_ASSERT_UNREACHABLE("Dead code, shouldn't be called.");
707 return NS_ERROR_NOT_IMPLEMENTED;
708 }
709
GetIsOOP(bool * aIsAsync)710 nsresult nsNPAPIPluginInstance::GetIsOOP(bool* aIsAsync) {
711 AutoPluginLibraryCall library(this);
712 if (!library) return NS_ERROR_FAILURE;
713
714 *aIsAsync = library->IsOOP();
715 return NS_OK;
716 }
717
SetBackgroundUnknown()718 nsresult nsNPAPIPluginInstance::SetBackgroundUnknown() {
719 if (RUNNING != mRunning) return NS_OK;
720
721 AutoPluginLibraryCall library(this);
722 if (!library) return NS_ERROR_FAILURE;
723
724 return library->SetBackgroundUnknown(&mNPP);
725 }
726
BeginUpdateBackground(nsIntRect * aRect,DrawTarget ** aDrawTarget)727 nsresult nsNPAPIPluginInstance::BeginUpdateBackground(
728 nsIntRect* aRect, DrawTarget** aDrawTarget) {
729 if (RUNNING != mRunning) return NS_OK;
730
731 AutoPluginLibraryCall library(this);
732 if (!library) return NS_ERROR_FAILURE;
733
734 return library->BeginUpdateBackground(&mNPP, *aRect, aDrawTarget);
735 }
736
EndUpdateBackground(nsIntRect * aRect)737 nsresult nsNPAPIPluginInstance::EndUpdateBackground(nsIntRect* aRect) {
738 if (RUNNING != mRunning) return NS_OK;
739
740 AutoPluginLibraryCall library(this);
741 if (!library) return NS_ERROR_FAILURE;
742
743 return library->EndUpdateBackground(&mNPP, *aRect);
744 }
745
IsTransparent(bool * isTransparent)746 nsresult nsNPAPIPluginInstance::IsTransparent(bool* isTransparent) {
747 *isTransparent = mTransparent;
748 return NS_OK;
749 }
750
GetFormValue(nsAString & aValue)751 nsresult nsNPAPIPluginInstance::GetFormValue(nsAString& aValue) {
752 aValue.Truncate();
753
754 char* value = nullptr;
755 nsresult rv = GetValueFromPlugin(NPPVformValue, &value);
756 if (NS_FAILED(rv) || !value) return NS_ERROR_FAILURE;
757
758 CopyUTF8toUTF16(MakeStringSpan(value), aValue);
759
760 // NPPVformValue allocates with NPN_MemAlloc(), which uses
761 // nsMemory.
762 free(value);
763
764 return NS_OK;
765 }
766
PushPopupsEnabledState(bool aEnabled)767 nsresult nsNPAPIPluginInstance::PushPopupsEnabledState(bool aEnabled) {
768 nsCOMPtr<nsPIDOMWindowOuter> window = GetDOMWindow();
769 if (!window) return NS_ERROR_FAILURE;
770
771 PopupBlocker::PopupControlState oldState =
772 PopupBlocker::PushPopupControlState(
773 aEnabled ? PopupBlocker::openAllowed : PopupBlocker::openAbused,
774 true);
775
776 // XXX(Bug 1631371) Check if this should use a fallible operation as it
777 // pretended earlier.
778 mPopupStates.AppendElement(oldState);
779
780 return NS_OK;
781 }
782
PopPopupsEnabledState()783 nsresult nsNPAPIPluginInstance::PopPopupsEnabledState() {
784 int32_t last = mPopupStates.Length() - 1;
785
786 if (last < 0) {
787 // Nothing to pop.
788 return NS_OK;
789 }
790
791 nsCOMPtr<nsPIDOMWindowOuter> window = GetDOMWindow();
792 if (!window) return NS_ERROR_FAILURE;
793
794 PopupBlocker::PopupControlState& oldState = mPopupStates[last];
795
796 PopupBlocker::PopPopupControlState(oldState);
797
798 mPopupStates.RemoveElementAt(last);
799
800 return NS_OK;
801 }
802
GetPluginAPIVersion(uint16_t * version)803 nsresult nsNPAPIPluginInstance::GetPluginAPIVersion(uint16_t* version) {
804 NS_ENSURE_ARG_POINTER(version);
805
806 if (!mPlugin) return NS_ERROR_FAILURE;
807
808 if (!mPlugin->GetLibrary()) return NS_ERROR_FAILURE;
809
810 NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
811
812 *version = pluginFunctions->version;
813
814 return NS_OK;
815 }
816
PrivateModeStateChanged(bool enabled)817 nsresult nsNPAPIPluginInstance::PrivateModeStateChanged(bool enabled) {
818 if (RUNNING != mRunning) return NS_OK;
819
820 PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance informing plugin of "
821 "private mode state change this=%p\n",
822 this));
823
824 if (!mPlugin || !mPlugin->GetLibrary()) return NS_ERROR_FAILURE;
825
826 NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
827
828 if (!pluginFunctions->setvalue) return NS_ERROR_FAILURE;
829
830 PluginDestructionGuard guard(this);
831
832 NPError error;
833 NPBool value = static_cast<NPBool>(enabled);
834 NS_TRY_SAFE_CALL_RETURN(
835 error, (*pluginFunctions->setvalue)(&mNPP, NPNVprivateModeBool, &value),
836 this, NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
837 return (error == NPERR_NO_ERROR) ? NS_OK : NS_ERROR_FAILURE;
838 }
839
IsPrivateBrowsing(bool * aEnabled)840 nsresult nsNPAPIPluginInstance::IsPrivateBrowsing(bool* aEnabled) {
841 if (!mOwner) return NS_ERROR_FAILURE;
842
843 nsCOMPtr<Document> doc;
844 mOwner->GetDocument(getter_AddRefs(doc));
845 NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
846
847 nsCOMPtr<nsPIDOMWindowOuter> domwindow = doc->GetWindow();
848 NS_ENSURE_TRUE(domwindow, NS_ERROR_FAILURE);
849
850 nsCOMPtr<nsIDocShell> docShell = domwindow->GetDocShell();
851 nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);
852 *aEnabled = (loadContext && loadContext->UsePrivateBrowsing());
853 return NS_OK;
854 }
855
PluginTimerCallback(nsITimer * aTimer,void * aClosure)856 static void PluginTimerCallback(nsITimer* aTimer, void* aClosure) {
857 nsNPAPITimer* t = (nsNPAPITimer*)aClosure;
858 NPP npp = t->npp;
859 uint32_t id = t->id;
860
861 PLUGIN_LOG(PLUGIN_LOG_NOISY,
862 ("nsNPAPIPluginInstance running plugin timer callback this=%p\n",
863 npp->ndata));
864
865 // Some plugins (Flash on Android) calls unscheduletimer
866 // from this callback.
867 t->inCallback = true;
868 (*(t->callback))(npp, id);
869 t->inCallback = false;
870
871 // Make sure we still have an instance and the timer is still alive
872 // after the callback.
873 nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)npp->ndata;
874 if (!inst || !inst->TimerWithID(id, nullptr)) return;
875
876 // use UnscheduleTimer to clean up if this is a one-shot timer
877 uint32_t timerType;
878 t->timer->GetType(&timerType);
879 if (t->needUnschedule || timerType == nsITimer::TYPE_ONE_SHOT)
880 inst->UnscheduleTimer(id);
881 }
882
TimerWithID(uint32_t id,uint32_t * index)883 nsNPAPITimer* nsNPAPIPluginInstance::TimerWithID(uint32_t id, uint32_t* index) {
884 uint32_t len = mTimers.Length();
885 for (uint32_t i = 0; i < len; i++) {
886 if (mTimers[i]->id == id) {
887 if (index) *index = i;
888 return mTimers[i];
889 }
890 }
891 return nullptr;
892 }
893
ScheduleTimer(uint32_t interval,NPBool repeat,void (* timerFunc)(NPP npp,uint32_t timerID))894 uint32_t nsNPAPIPluginInstance::ScheduleTimer(
895 uint32_t interval, NPBool repeat,
896 void (*timerFunc)(NPP npp, uint32_t timerID)) {
897 if (RUNNING != mRunning) return 0;
898
899 nsNPAPITimer* newTimer = new nsNPAPITimer();
900
901 newTimer->inCallback = newTimer->needUnschedule = false;
902 newTimer->npp = &mNPP;
903
904 // generate ID that is unique to this instance
905 uint32_t uniqueID = mTimers.Length();
906 while ((uniqueID == 0) || TimerWithID(uniqueID, nullptr)) uniqueID++;
907 newTimer->id = uniqueID;
908
909 // create new xpcom timer, scheduled correctly
910 nsresult rv;
911 const short timerType = (repeat ? (short)nsITimer::TYPE_REPEATING_SLACK
912 : (short)nsITimer::TYPE_ONE_SHOT);
913 rv = NS_NewTimerWithFuncCallback(
914 getter_AddRefs(newTimer->timer), PluginTimerCallback, newTimer, interval,
915 timerType, "nsNPAPIPluginInstance::ScheduleTimer");
916 if (NS_FAILED(rv)) {
917 delete newTimer;
918 return 0;
919 }
920
921 // save callback function
922 newTimer->callback = timerFunc;
923
924 // add timer to timers array
925 mTimers.AppendElement(newTimer);
926
927 return newTimer->id;
928 }
929
UnscheduleTimer(uint32_t timerID)930 void nsNPAPIPluginInstance::UnscheduleTimer(uint32_t timerID) {
931 // find the timer struct by ID
932 uint32_t index;
933 nsNPAPITimer* t = TimerWithID(timerID, &index);
934 if (!t) return;
935
936 if (t->inCallback) {
937 t->needUnschedule = true;
938 return;
939 }
940
941 // cancel the timer
942 t->timer->Cancel();
943
944 // remove timer struct from array
945 mTimers.RemoveElementAt(index);
946
947 // delete timer
948 delete t;
949 }
950
ConvertPoint(double sourceX,double sourceY,NPCoordinateSpace sourceSpace,double * destX,double * destY,NPCoordinateSpace destSpace)951 NPBool nsNPAPIPluginInstance::ConvertPoint(double sourceX, double sourceY,
952 NPCoordinateSpace sourceSpace,
953 double* destX, double* destY,
954 NPCoordinateSpace destSpace) {
955 if (mOwner) {
956 return mOwner->ConvertPoint(sourceX, sourceY, sourceSpace, destX, destY,
957 destSpace);
958 }
959
960 return false;
961 }
962
GetDOMElement(Element ** result)963 nsresult nsNPAPIPluginInstance::GetDOMElement(Element** result) {
964 if (!mOwner) {
965 *result = nullptr;
966 return NS_ERROR_FAILURE;
967 }
968
969 return mOwner->GetDOMElement(result);
970 }
971
InvalidateRect(NPRect * invalidRect)972 nsresult nsNPAPIPluginInstance::InvalidateRect(NPRect* invalidRect) {
973 if (RUNNING != mRunning) return NS_OK;
974
975 if (!mOwner) return NS_ERROR_FAILURE;
976
977 return mOwner->InvalidateRect(invalidRect);
978 }
979
InvalidateRegion(NPRegion invalidRegion)980 nsresult nsNPAPIPluginInstance::InvalidateRegion(NPRegion invalidRegion) {
981 if (RUNNING != mRunning) return NS_OK;
982
983 if (!mOwner) return NS_ERROR_FAILURE;
984
985 return mOwner->InvalidateRegion(invalidRegion);
986 }
987
GetMIMEType(const char ** result)988 nsresult nsNPAPIPluginInstance::GetMIMEType(const char** result) {
989 if (!mMIMEType)
990 *result = "";
991 else
992 *result = mMIMEType;
993
994 return NS_OK;
995 }
996
GetOwner()997 nsPluginInstanceOwner* nsNPAPIPluginInstance::GetOwner() { return mOwner; }
998
SetOwner(nsPluginInstanceOwner * aOwner)999 void nsNPAPIPluginInstance::SetOwner(nsPluginInstanceOwner* aOwner) {
1000 mOwner = aOwner;
1001 }
1002
AsyncSetWindow(NPWindow & window)1003 nsresult nsNPAPIPluginInstance::AsyncSetWindow(NPWindow& window) {
1004 return NS_ERROR_NOT_IMPLEMENTED;
1005 }
1006
URLRedirectResponse(void * notifyData,NPBool allow)1007 void nsNPAPIPluginInstance::URLRedirectResponse(void* notifyData,
1008 NPBool allow) {
1009 if (!notifyData) {
1010 return;
1011 }
1012
1013 uint32_t listenerCount = mStreamListeners.Length();
1014 for (uint32_t i = 0; i < listenerCount; i++) {
1015 nsNPAPIPluginStreamListener* currentListener = mStreamListeners[i];
1016 if (currentListener->GetNotifyData() == notifyData) {
1017 currentListener->URLRedirectResponse(allow);
1018 }
1019 }
1020 }
1021
InitAsyncSurface(NPSize * size,NPImageFormat format,void * initData,NPAsyncSurface * surface)1022 NPError nsNPAPIPluginInstance::InitAsyncSurface(NPSize* size,
1023 NPImageFormat format,
1024 void* initData,
1025 NPAsyncSurface* surface) {
1026 if (mOwner) {
1027 return mOwner->InitAsyncSurface(size, format, initData, surface);
1028 }
1029
1030 return NPERR_GENERIC_ERROR;
1031 }
1032
FinalizeAsyncSurface(NPAsyncSurface * surface)1033 NPError nsNPAPIPluginInstance::FinalizeAsyncSurface(NPAsyncSurface* surface) {
1034 if (mOwner) {
1035 return mOwner->FinalizeAsyncSurface(surface);
1036 }
1037
1038 return NPERR_GENERIC_ERROR;
1039 }
1040
SetCurrentAsyncSurface(NPAsyncSurface * surface,NPRect * changed)1041 void nsNPAPIPluginInstance::SetCurrentAsyncSurface(NPAsyncSurface* surface,
1042 NPRect* changed) {
1043 if (mOwner) {
1044 mOwner->SetCurrentAsyncSurface(surface, changed);
1045 }
1046 }
1047
GetContentsScaleFactor()1048 double nsNPAPIPluginInstance::GetContentsScaleFactor() {
1049 double scaleFactor = 1.0;
1050 if (mOwner) {
1051 mOwner->GetContentsScaleFactor(&scaleFactor);
1052 }
1053 return scaleFactor;
1054 }
1055
GetCSSZoomFactor()1056 float nsNPAPIPluginInstance::GetCSSZoomFactor() {
1057 float zoomFactor = 1.0;
1058 if (mOwner) {
1059 mOwner->GetCSSZoomFactor(&zoomFactor);
1060 }
1061 return zoomFactor;
1062 }
1063
GetRunID(uint32_t * aRunID)1064 nsresult nsNPAPIPluginInstance::GetRunID(uint32_t* aRunID) {
1065 if (NS_WARN_IF(!aRunID)) {
1066 return NS_ERROR_INVALID_POINTER;
1067 }
1068
1069 if (NS_WARN_IF(!mPlugin)) {
1070 return NS_ERROR_FAILURE;
1071 }
1072
1073 PluginLibrary* library = mPlugin->GetLibrary();
1074 if (!library) {
1075 return NS_ERROR_FAILURE;
1076 }
1077
1078 return library->GetRunID(aRunID);
1079 }
1080
CreateAudioChannelAgentIfNeeded()1081 nsresult nsNPAPIPluginInstance::CreateAudioChannelAgentIfNeeded() {
1082 if (mAudioChannelAgent) {
1083 return NS_OK;
1084 }
1085
1086 mAudioChannelAgent = new AudioChannelAgent();
1087
1088 nsCOMPtr<nsPIDOMWindowOuter> window = GetDOMWindow();
1089 if (NS_WARN_IF(!window)) {
1090 return NS_ERROR_FAILURE;
1091 }
1092
1093 nsresult rv = mAudioChannelAgent->Init(window->GetCurrentInnerWindow(), this);
1094 if (NS_WARN_IF(NS_FAILED(rv))) {
1095 return rv;
1096 }
1097 return NS_OK;
1098 }
1099
NotifyStartedPlaying()1100 void nsNPAPIPluginInstance::NotifyStartedPlaying() {
1101 nsresult rv = CreateAudioChannelAgentIfNeeded();
1102 if (NS_WARN_IF(NS_FAILED(rv))) {
1103 return;
1104 }
1105
1106 MOZ_ASSERT(mAudioChannelAgent);
1107 rv = mAudioChannelAgent->NotifyStartedPlaying(
1108 mIsMuted ? AudioChannelService::AudibleState::eNotAudible
1109 : AudioChannelService::AudibleState::eAudible);
1110 if (NS_WARN_IF(NS_FAILED(rv))) {
1111 return;
1112 }
1113
1114 mAudioChannelAgent->PullInitialUpdate();
1115 }
1116
NotifyStoppedPlaying()1117 void nsNPAPIPluginInstance::NotifyStoppedPlaying() {
1118 MOZ_ASSERT(mAudioChannelAgent);
1119 nsresult rv = mAudioChannelAgent->NotifyStoppedPlaying();
1120 if (NS_WARN_IF(NS_FAILED(rv))) {
1121 return;
1122 }
1123 }
1124
1125 NS_IMETHODIMP
WindowVolumeChanged(float aVolume,bool aMuted)1126 nsNPAPIPluginInstance::WindowVolumeChanged(float aVolume, bool aMuted) {
1127 MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
1128 ("nsNPAPIPluginInstance, WindowVolumeChanged, "
1129 "this = %p, aVolume = %f, aMuted = %s\n",
1130 this, aVolume, aMuted ? "true" : "false"));
1131 // We just support mute/unmute
1132 if (mWindowMuted != aMuted) {
1133 mWindowMuted = aMuted;
1134 return UpdateMutedIfNeeded();
1135 }
1136 return NS_OK;
1137 }
1138
1139 NS_IMETHODIMP
WindowSuspendChanged(nsSuspendedTypes aSuspend)1140 nsNPAPIPluginInstance::WindowSuspendChanged(nsSuspendedTypes aSuspend) {
1141 MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
1142 ("nsNPAPIPluginInstance, WindowSuspendChanged, "
1143 "this = %p, aSuspend = %s\n",
1144 this, SuspendTypeToStr(aSuspend)));
1145 const bool isSuspended = aSuspend != nsISuspendedTypes::NONE_SUSPENDED;
1146 if (mWindowSuspended != isSuspended) {
1147 mWindowSuspended = isSuspended;
1148 // It doesn't support suspending, so we just do something like mute/unmute.
1149 return UpdateMutedIfNeeded();
1150 }
1151 return NS_OK;
1152 }
1153
1154 NS_IMETHODIMP
WindowAudioCaptureChanged(bool aCapture)1155 nsNPAPIPluginInstance::WindowAudioCaptureChanged(bool aCapture) {
1156 return NS_OK;
1157 }
1158
NotifyAudibleStateChanged() const1159 void nsNPAPIPluginInstance::NotifyAudibleStateChanged() const {
1160 // This happens when global window destroyed, we would notify agent's callback
1161 // to mute its volume, but the nsNSNPAPI had released the agent before that.
1162 if (!mAudioChannelAgent) {
1163 return;
1164 }
1165 AudioChannelService::AudibleState audibleState =
1166 mIsMuted ? AudioChannelService::AudibleState::eNotAudible
1167 : AudioChannelService::AudibleState::eAudible;
1168 // Because we don't really support suspending nsNPAPI, so all audible changes
1169 // come from changing its volume.
1170 mAudioChannelAgent->NotifyStartedAudible(
1171 audibleState, AudioChannelService::AudibleChangedReasons::eVolumeChanged);
1172 }
1173
UpdateMutedIfNeeded()1174 nsresult nsNPAPIPluginInstance::UpdateMutedIfNeeded() {
1175 const bool shouldMute = mWindowSuspended || mWindowMuted;
1176 if (mIsMuted == shouldMute) {
1177 return NS_OK;
1178 }
1179
1180 mIsMuted = shouldMute;
1181 NotifyAudibleStateChanged();
1182 nsresult rv = SetMuted(mIsMuted);
1183 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "SetMuted failed");
1184 return rv;
1185 }
1186
SetMuted(bool aIsMuted)1187 nsresult nsNPAPIPluginInstance::SetMuted(bool aIsMuted) {
1188 if (RUNNING != mRunning) return NS_OK;
1189
1190 PLUGIN_LOG(
1191 PLUGIN_LOG_NORMAL,
1192 ("nsNPAPIPluginInstance informing plugin of mute state change this=%p\n",
1193 this));
1194
1195 if (!mPlugin || !mPlugin->GetLibrary()) return NS_ERROR_FAILURE;
1196
1197 NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
1198
1199 if (!pluginFunctions->setvalue) return NS_ERROR_FAILURE;
1200
1201 PluginDestructionGuard guard(this);
1202
1203 NPError error;
1204 NPBool value = static_cast<NPBool>(aIsMuted);
1205 NS_TRY_SAFE_CALL_RETURN(
1206 error, (*pluginFunctions->setvalue)(&mNPP, NPNVmuteAudioBool, &value),
1207 this, NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
1208 return (error == NPERR_NO_ERROR) ? NS_OK : NS_ERROR_FAILURE;
1209 }
1210