dom/plugins/base/nsNPAPIPluginInstance.cpp

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

mercurial