Coverage Report

Created: 2018-09-25 14:53

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