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