1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Tim Copperfield <timecop@network.email.ne.jp>
24 : * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either the GNU General Public License Version 2 or later (the "GPL"), or
28 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #include "prlog.h"
41 : #include "prmem.h"
42 : #include "nscore.h"
43 : #include "prenv.h"
44 :
45 : #include "nsNPAPIPluginInstance.h"
46 : #include "nsNPAPIPlugin.h"
47 : #include "nsNPAPIPluginStreamListener.h"
48 : #include "nsPluginHost.h"
49 : #include "nsPluginSafety.h"
50 : #include "nsPluginLogging.h"
51 : #include "nsIPrivateBrowsingService.h"
52 : #include "nsContentUtils.h"
53 :
54 : #include "nsIDocument.h"
55 : #include "nsIScriptGlobalObject.h"
56 : #include "nsIScriptContext.h"
57 : #include "nsDirectoryServiceDefs.h"
58 : #include "nsJSNPRuntime.h"
59 : #include "nsPluginStreamListenerPeer.h"
60 : #include "nsSize.h"
61 : #include "nsNetCID.h"
62 : #include "nsIContent.h"
63 :
64 : #ifdef MOZ_WIDGET_ANDROID
65 : #include "ANPBase.h"
66 : #include <android/log.h>
67 : #include "android_npapi.h"
68 : #include "mozilla/Mutex.h"
69 : #include "mozilla/CondVar.h"
70 : #include "AndroidBridge.h"
71 : #endif
72 :
73 : using namespace mozilla;
74 : using namespace mozilla::plugins::parent;
75 :
76 : static NS_DEFINE_IID(kIOutputStreamIID, NS_IOUTPUTSTREAM_IID);
77 : static NS_DEFINE_IID(kIPluginStreamListenerIID, NS_IPLUGINSTREAMLISTENER_IID);
78 :
79 0 : NS_IMPL_THREADSAFE_ISUPPORTS0(nsNPAPIPluginInstance)
80 :
81 0 : nsNPAPIPluginInstance::nsNPAPIPluginInstance(nsNPAPIPlugin* plugin)
82 : :
83 : mDrawingModel(kDefaultDrawingModel),
84 : #ifdef MOZ_WIDGET_ANDROID
85 : mSurface(nsnull),
86 : mANPDrawingModel(0),
87 : mOnScreen(true),
88 : #endif
89 : mRunning(NOT_STARTED),
90 : mWindowless(false),
91 : mTransparent(false),
92 : mCached(false),
93 : mUsesDOMForCursor(false),
94 : mInPluginInitCall(false),
95 : mPlugin(plugin),
96 : mMIMEType(nsnull),
97 : mOwner(nsnull),
98 : mCurrentPluginEvent(nsnull),
99 : #if defined(MOZ_X11) || defined(XP_WIN) || defined(XP_MACOSX)
100 0 : mUsePluginLayersPref(true)
101 : #else
102 : mUsePluginLayersPref(false)
103 : #endif
104 : {
105 0 : NS_ASSERTION(mPlugin != NULL, "Plugin is required when creating an instance.");
106 :
107 : // Initialize the NPP structure.
108 :
109 0 : mNPP.pdata = NULL;
110 0 : mNPP.ndata = this;
111 :
112 0 : nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
113 0 : if (prefs) {
114 : bool useLayersPref;
115 0 : nsresult rv = prefs->GetBoolPref("plugins.use_layers", &useLayersPref);
116 0 : if (NS_SUCCEEDED(rv))
117 0 : mUsePluginLayersPref = useLayersPref;
118 : }
119 :
120 0 : PLUGIN_LOG(PLUGIN_LOG_BASIC, ("nsNPAPIPluginInstance ctor: this=%p\n",this));
121 0 : }
122 :
123 0 : nsNPAPIPluginInstance::~nsNPAPIPluginInstance()
124 : {
125 0 : PLUGIN_LOG(PLUGIN_LOG_BASIC, ("nsNPAPIPluginInstance dtor: this=%p\n",this));
126 :
127 0 : if (mMIMEType) {
128 0 : PR_Free((void *)mMIMEType);
129 0 : mMIMEType = nsnull;
130 : }
131 0 : }
132 :
133 : void
134 0 : nsNPAPIPluginInstance::Destroy()
135 : {
136 0 : Stop();
137 0 : mPlugin = nsnull;
138 0 : }
139 :
140 : TimeStamp
141 0 : nsNPAPIPluginInstance::StopTime()
142 : {
143 0 : return mStopTime;
144 : }
145 :
146 0 : nsresult nsNPAPIPluginInstance::Initialize(nsIPluginInstanceOwner* aOwner, const char* aMIMEType)
147 : {
148 0 : PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance::Initialize this=%p\n",this));
149 :
150 0 : mOwner = aOwner;
151 :
152 0 : if (aMIMEType) {
153 0 : mMIMEType = (char*)PR_Malloc(PL_strlen(aMIMEType) + 1);
154 :
155 0 : if (mMIMEType)
156 0 : PL_strcpy(mMIMEType, aMIMEType);
157 : }
158 :
159 0 : return InitializePlugin();
160 : }
161 :
162 0 : nsresult nsNPAPIPluginInstance::Start()
163 : {
164 0 : PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance::Start this=%p\n",this));
165 :
166 0 : if (RUNNING == mRunning)
167 0 : return NS_OK;
168 :
169 0 : return InitializePlugin();
170 : }
171 :
172 0 : nsresult nsNPAPIPluginInstance::Stop()
173 : {
174 0 : PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance::Stop this=%p\n",this));
175 :
176 : // Make sure the plugin didn't leave popups enabled.
177 0 : if (mPopupStates.Length() > 0) {
178 0 : nsCOMPtr<nsPIDOMWindow> window = GetDOMWindow();
179 :
180 0 : if (window) {
181 0 : window->PopPopupControlState(openAbused);
182 : }
183 : }
184 :
185 0 : if (RUNNING != mRunning) {
186 0 : return NS_OK;
187 : }
188 :
189 : // clean up all outstanding timers
190 0 : for (PRUint32 i = mTimers.Length(); i > 0; i--)
191 0 : UnscheduleTimer(mTimers[i - 1]->id);
192 :
193 : // If there's code from this plugin instance on the stack, delay the
194 : // destroy.
195 0 : if (PluginDestructionGuard::DelayDestroy(this)) {
196 0 : return NS_OK;
197 : }
198 :
199 : // Make sure we lock while we're writing to mRunning after we've
200 : // started as other threads might be checking that inside a lock.
201 : {
202 0 : AsyncCallbackAutoLock lock;
203 0 : mRunning = DESTROYING;
204 0 : mStopTime = TimeStamp::Now();
205 : }
206 :
207 0 : OnPluginDestroy(&mNPP);
208 :
209 : // clean up open streams
210 0 : while (mStreamListeners.Length() > 0) {
211 0 : nsRefPtr<nsNPAPIPluginStreamListener> currentListener(mStreamListeners[0]);
212 0 : currentListener->CleanUpStream(NPRES_USER_BREAK);
213 0 : mStreamListeners.RemoveElement(currentListener);
214 : }
215 :
216 0 : if (!mPlugin || !mPlugin->GetLibrary())
217 0 : return NS_ERROR_FAILURE;
218 :
219 0 : NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
220 :
221 0 : NPError error = NPERR_GENERIC_ERROR;
222 0 : if (pluginFunctions->destroy) {
223 0 : NPSavedData *sdata = 0;
224 :
225 0 : NS_TRY_SAFE_CALL_RETURN(error, (*pluginFunctions->destroy)(&mNPP, &sdata), this);
226 :
227 0 : NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
228 : ("NPP Destroy called: this=%p, npp=%p, return=%d\n", this, &mNPP, error));
229 : }
230 0 : mRunning = DESTROYED;
231 :
232 0 : nsJSNPRuntime::OnPluginDestroy(&mNPP);
233 :
234 0 : if (error != NPERR_NO_ERROR)
235 0 : return NS_ERROR_FAILURE;
236 : else
237 0 : return NS_OK;
238 : }
239 :
240 : already_AddRefed<nsPIDOMWindow>
241 0 : nsNPAPIPluginInstance::GetDOMWindow()
242 : {
243 0 : nsCOMPtr<nsIPluginInstanceOwner> owner;
244 0 : GetOwner(getter_AddRefs(owner));
245 0 : if (!owner)
246 0 : return nsnull;
247 :
248 0 : nsCOMPtr<nsIDocument> doc;
249 0 : owner->GetDocument(getter_AddRefs(doc));
250 0 : if (!doc)
251 0 : return nsnull;
252 :
253 0 : nsPIDOMWindow *window = doc->GetWindow();
254 0 : NS_IF_ADDREF(window);
255 :
256 0 : return window;
257 : }
258 :
259 : nsresult
260 0 : nsNPAPIPluginInstance::GetTagType(nsPluginTagType *result)
261 : {
262 0 : if (mOwner) {
263 0 : nsCOMPtr<nsIPluginTagInfo> tinfo(do_QueryInterface(mOwner));
264 0 : if (tinfo)
265 0 : return tinfo->GetTagType(result);
266 : }
267 :
268 0 : return NS_ERROR_FAILURE;
269 : }
270 :
271 : nsresult
272 0 : nsNPAPIPluginInstance::GetAttributes(PRUint16& n, const char*const*& names,
273 : const char*const*& values)
274 : {
275 0 : if (mOwner) {
276 0 : nsCOMPtr<nsIPluginTagInfo> tinfo(do_QueryInterface(mOwner));
277 0 : if (tinfo)
278 0 : return tinfo->GetAttributes(n, names, values);
279 : }
280 :
281 0 : return NS_ERROR_FAILURE;
282 : }
283 :
284 : nsresult
285 0 : nsNPAPIPluginInstance::GetParameters(PRUint16& n, const char*const*& names,
286 : const char*const*& values)
287 : {
288 0 : if (mOwner) {
289 0 : nsCOMPtr<nsIPluginTagInfo> tinfo(do_QueryInterface(mOwner));
290 0 : if (tinfo)
291 0 : return tinfo->GetParameters(n, names, values);
292 : }
293 :
294 0 : return NS_ERROR_FAILURE;
295 : }
296 :
297 : nsresult
298 0 : nsNPAPIPluginInstance::GetMode(PRInt32 *result)
299 : {
300 0 : if (mOwner)
301 0 : return mOwner->GetMode(result);
302 : else
303 0 : return NS_ERROR_FAILURE;
304 : }
305 :
306 : nsTArray<nsNPAPIPluginStreamListener*>*
307 0 : nsNPAPIPluginInstance::StreamListeners()
308 : {
309 0 : return &mStreamListeners;
310 : }
311 :
312 : nsTArray<nsPluginStreamListenerPeer*>*
313 0 : nsNPAPIPluginInstance::FileCachedStreamListeners()
314 : {
315 0 : return &mFileCachedStreamListeners;
316 : }
317 :
318 : nsresult
319 0 : nsNPAPIPluginInstance::InitializePlugin()
320 : {
321 0 : PluginDestructionGuard guard(this);
322 :
323 0 : PRUint16 count = 0;
324 0 : const char* const* names = nsnull;
325 0 : const char* const* values = nsnull;
326 : nsPluginTagType tagtype;
327 0 : nsresult rv = GetTagType(&tagtype);
328 0 : if (NS_SUCCEEDED(rv)) {
329 : // Note: If we failed to get the tag type, we may be a full page plugin, so no arguments
330 0 : rv = GetAttributes(count, names, values);
331 0 : NS_ENSURE_SUCCESS(rv, rv);
332 :
333 : // nsPluginTagType_Object or Applet may also have PARAM tags
334 : // Note: The arrays handed back by GetParameters() are
335 : // crafted specially to be directly behind the arrays from GetAttributes()
336 : // with a null entry as a separator. This is for 4.x backwards compatibility!
337 : // see bug 111008 for details
338 0 : if (tagtype != nsPluginTagType_Embed) {
339 0 : PRUint16 pcount = 0;
340 0 : const char* const* pnames = nsnull;
341 0 : const char* const* pvalues = nsnull;
342 0 : if (NS_SUCCEEDED(GetParameters(pcount, pnames, pvalues))) {
343 : // Android expects an empty string as the separator instead of null
344 : #ifdef MOZ_WIDGET_ANDROID
345 : NS_ASSERTION(PL_strcmp(values[count], "") == 0, "attribute/parameter array not setup correctly for Android NPAPI plugins");
346 : #else
347 0 : NS_ASSERTION(!values[count], "attribute/parameter array not setup correctly for NPAPI plugins");
348 : #endif
349 0 : if (pcount)
350 0 : count += ++pcount; // if it's all setup correctly, then all we need is to
351 : // change the count (attrs + PARAM/blank + params)
352 : }
353 : }
354 : }
355 :
356 : PRInt32 mode;
357 : const char* mimetype;
358 0 : NPError error = NPERR_GENERIC_ERROR;
359 :
360 0 : GetMode(&mode);
361 0 : GetMIMEType(&mimetype);
362 :
363 : // Some older versions of Flash have a bug in them
364 : // that causes the stack to become currupt if we
365 : // pass swliveconnect=1 in the NPP_NewProc arrays.
366 : // See bug 149336 (UNIX), bug 186287 (Mac)
367 : //
368 : // The code below disables the attribute unless
369 : // the environment variable:
370 : // MOZILLA_PLUGIN_DISABLE_FLASH_SWLIVECONNECT_HACK
371 : // is set.
372 : //
373 : // It is okay to disable this attribute because
374 : // back in 4.x, scripting required liveconnect to
375 : // start Java which was slow. Scripting no longer
376 : // requires starting Java and is quick plus controled
377 : // from the browser, so Flash now ignores this attribute.
378 : //
379 : // This code can not be put at the time of creating
380 : // the array because we may need to examine the
381 : // stream header to determine we want Flash.
382 :
383 : static const char flashMimeType[] = "application/x-shockwave-flash";
384 : static const char blockedParam[] = "swliveconnect";
385 0 : if (count && !PL_strcasecmp(mimetype, flashMimeType)) {
386 : static int cachedDisableHack = 0;
387 0 : if (!cachedDisableHack) {
388 0 : if (PR_GetEnv("MOZILLA_PLUGIN_DISABLE_FLASH_SWLIVECONNECT_HACK"))
389 0 : cachedDisableHack = -1;
390 : else
391 0 : cachedDisableHack = 1;
392 : }
393 0 : if (cachedDisableHack > 0) {
394 0 : for (PRUint16 i=0; i<count; i++) {
395 0 : if (!PL_strcasecmp(names[i], blockedParam)) {
396 : // BIG FAT WARNIG:
397 : // I'm ugly casting |const char*| to |char*| and altering it
398 : // because I know we do malloc it values in
399 : // http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/layout/html/base/src/nsObjectFrame.cpp&rev=1.349&root=/cvsroot#3020
400 : // and free it at line #2096, so it couldn't be a const ptr to string literal
401 0 : char *val = (char*) values[i];
402 0 : if (val && *val) {
403 : // we cannot just *val=0, it won't be free properly in such case
404 0 : val[0] = '0';
405 0 : val[1] = 0;
406 : }
407 0 : break;
408 : }
409 : }
410 : }
411 : }
412 :
413 0 : bool oldVal = mInPluginInitCall;
414 0 : mInPluginInitCall = true;
415 :
416 : // Need this on the stack before calling NPP_New otherwise some callbacks that
417 : // the plugin may make could fail (NPN_HasProperty, for example).
418 0 : NPPAutoPusher autopush(&mNPP);
419 :
420 0 : if (!mPlugin)
421 0 : return NS_ERROR_FAILURE;
422 :
423 0 : PluginLibrary* library = mPlugin->GetLibrary();
424 0 : if (!library)
425 0 : return NS_ERROR_FAILURE;
426 :
427 : // Mark this instance as running before calling NPP_New because the plugin may
428 : // call other NPAPI functions, like NPN_GetURLNotify, that assume this is set
429 : // before returning. If the plugin returns failure, we'll clear it out below.
430 0 : mRunning = RUNNING;
431 :
432 0 : nsresult newResult = library->NPP_New((char*)mimetype, &mNPP, (PRUint16)mode, count, (char**)names, (char**)values, NULL, &error);
433 0 : mInPluginInitCall = oldVal;
434 :
435 0 : NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
436 : ("NPP New called: this=%p, npp=%p, mime=%s, mode=%d, argc=%d, return=%d\n",
437 : this, &mNPP, mimetype, mode, count, error));
438 :
439 0 : if (NS_FAILED(newResult) || error != NPERR_NO_ERROR) {
440 0 : mRunning = DESTROYED;
441 0 : nsJSNPRuntime::OnPluginDestroy(&mNPP);
442 0 : return NS_ERROR_FAILURE;
443 : }
444 :
445 0 : return NS_OK;
446 : }
447 :
448 0 : nsresult nsNPAPIPluginInstance::SetWindow(NPWindow* window)
449 : {
450 : // NPAPI plugins don't want a SetWindow(NULL).
451 0 : if (!window || RUNNING != mRunning)
452 0 : return NS_OK;
453 :
454 : #if defined(MOZ_WIDGET_GTK2)
455 : // bug 108347, flash plugin on linux doesn't like window->width <=
456 : // 0, but Java needs wants this call.
457 0 : if (!nsPluginHost::IsJavaMIMEType(mMIMEType) && window->type == NPWindowTypeWindow &&
458 : (window->width <= 0 || window->height <= 0)) {
459 0 : return NS_OK;
460 : }
461 : #endif
462 :
463 0 : if (!mPlugin || !mPlugin->GetLibrary())
464 0 : return NS_ERROR_FAILURE;
465 :
466 0 : NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
467 :
468 0 : if (pluginFunctions->setwindow) {
469 0 : PluginDestructionGuard guard(this);
470 :
471 : // XXX Turns out that NPPluginWindow and NPWindow are structurally
472 : // identical (on purpose!), so there's no need to make a copy.
473 :
474 0 : PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance::SetWindow (about to call it) this=%p\n",this));
475 :
476 0 : bool oldVal = mInPluginInitCall;
477 0 : mInPluginInitCall = true;
478 :
479 0 : NPPAutoPusher nppPusher(&mNPP);
480 :
481 : NPError error;
482 0 : NS_TRY_SAFE_CALL_RETURN(error, (*pluginFunctions->setwindow)(&mNPP, (NPWindow*)window), this);
483 :
484 0 : mInPluginInitCall = oldVal;
485 :
486 0 : NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
487 : ("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",
488 : this, window->x, window->y, window->width, window->height,
489 : window->clipRect.top, window->clipRect.bottom, window->clipRect.left, window->clipRect.right, error));
490 : }
491 0 : return NS_OK;
492 : }
493 :
494 : nsresult
495 0 : nsNPAPIPluginInstance::NewStreamFromPlugin(const char* type, const char* target,
496 : nsIOutputStream* *result)
497 : {
498 0 : nsPluginStreamToFile* stream = new nsPluginStreamToFile(target, mOwner);
499 0 : if (!stream)
500 0 : return NS_ERROR_OUT_OF_MEMORY;
501 :
502 0 : return stream->QueryInterface(kIOutputStreamIID, (void**)result);
503 : }
504 :
505 : nsresult
506 0 : nsNPAPIPluginInstance::NewStreamListener(const char* aURL, void* notifyData,
507 : nsIPluginStreamListener** listener)
508 : {
509 0 : nsNPAPIPluginStreamListener* stream = new nsNPAPIPluginStreamListener(this, notifyData, aURL);
510 0 : NS_ENSURE_TRUE(stream, NS_ERROR_OUT_OF_MEMORY);
511 :
512 0 : mStreamListeners.AppendElement(stream);
513 :
514 0 : return stream->QueryInterface(kIPluginStreamListenerIID, (void**)listener);
515 : }
516 :
517 0 : nsresult nsNPAPIPluginInstance::Print(NPPrint* platformPrint)
518 : {
519 0 : NS_ENSURE_TRUE(platformPrint, NS_ERROR_NULL_POINTER);
520 :
521 0 : PluginDestructionGuard guard(this);
522 :
523 0 : if (!mPlugin || !mPlugin->GetLibrary())
524 0 : return NS_ERROR_FAILURE;
525 :
526 0 : NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
527 :
528 0 : NPPrint* thePrint = (NPPrint *)platformPrint;
529 :
530 : // to be compatible with the older SDK versions and to match what
531 : // NPAPI and other browsers do, overwrite |window.type| field with one
532 : // more copy of |platformPrint|. See bug 113264
533 0 : PRUint16 sdkmajorversion = (pluginFunctions->version & 0xff00)>>8;
534 0 : PRUint16 sdkminorversion = pluginFunctions->version & 0x00ff;
535 0 : if ((sdkmajorversion == 0) && (sdkminorversion < 11)) {
536 : // Let's copy platformPrint bytes over to where it was supposed to be
537 : // in older versions -- four bytes towards the beginning of the struct
538 : // but we should be careful about possible misalignments
539 : if (sizeof(NPWindowType) >= sizeof(void *)) {
540 0 : void* source = thePrint->print.embedPrint.platformPrint;
541 0 : void** destination = (void **)&(thePrint->print.embedPrint.window.type);
542 0 : *destination = source;
543 : } else {
544 : NS_ERROR("Incompatible OS for assignment");
545 : }
546 : }
547 :
548 0 : if (pluginFunctions->print)
549 0 : NS_TRY_SAFE_CALL_VOID((*pluginFunctions->print)(&mNPP, thePrint), this);
550 :
551 0 : NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
552 : ("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",
553 : this,
554 : platformPrint->print.embedPrint.platformPrint,
555 : platformPrint->print.embedPrint.window.x,
556 : platformPrint->print.embedPrint.window.y,
557 : platformPrint->print.embedPrint.window.width,
558 : platformPrint->print.embedPrint.window.height,
559 : platformPrint->print.embedPrint.window.clipRect.top,
560 : platformPrint->print.embedPrint.window.clipRect.bottom,
561 : platformPrint->print.embedPrint.window.clipRect.left,
562 : platformPrint->print.embedPrint.window.clipRect.right));
563 :
564 0 : return NS_OK;
565 : }
566 :
567 0 : nsresult nsNPAPIPluginInstance::HandleEvent(void* event, PRInt16* result)
568 : {
569 0 : if (RUNNING != mRunning)
570 0 : return NS_OK;
571 :
572 0 : if (!event)
573 0 : return NS_ERROR_FAILURE;
574 :
575 0 : PluginDestructionGuard guard(this);
576 :
577 0 : if (!mPlugin || !mPlugin->GetLibrary())
578 0 : return NS_ERROR_FAILURE;
579 :
580 0 : NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
581 :
582 0 : PRInt16 tmpResult = kNPEventNotHandled;
583 :
584 0 : if (pluginFunctions->event) {
585 0 : mCurrentPluginEvent = event;
586 : #if defined(XP_WIN) || defined(XP_OS2)
587 : NS_TRY_SAFE_CALL_RETURN(tmpResult, (*pluginFunctions->event)(&mNPP, event), this);
588 : #else
589 0 : tmpResult = (*pluginFunctions->event)(&mNPP, event);
590 : #endif
591 0 : NPP_PLUGIN_LOG(PLUGIN_LOG_NOISY,
592 : ("NPP HandleEvent called: this=%p, npp=%p, event=%p, return=%d\n",
593 : this, &mNPP, event, tmpResult));
594 :
595 0 : if (result)
596 0 : *result = tmpResult;
597 0 : mCurrentPluginEvent = nsnull;
598 : }
599 :
600 0 : return NS_OK;
601 : }
602 :
603 0 : nsresult nsNPAPIPluginInstance::GetValueFromPlugin(NPPVariable variable, void* value)
604 : {
605 0 : if (!mPlugin || !mPlugin->GetLibrary())
606 0 : return NS_ERROR_FAILURE;
607 :
608 0 : NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
609 :
610 0 : nsresult rv = NS_ERROR_FAILURE;
611 :
612 0 : if (pluginFunctions->getvalue && RUNNING == mRunning) {
613 0 : PluginDestructionGuard guard(this);
614 :
615 0 : NPError pluginError = NPERR_GENERIC_ERROR;
616 0 : NS_TRY_SAFE_CALL_RETURN(pluginError, (*pluginFunctions->getvalue)(&mNPP, variable, value), this);
617 0 : NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
618 : ("NPP GetValue called: this=%p, npp=%p, var=%d, value=%d, return=%d\n",
619 : this, &mNPP, variable, value, pluginError));
620 :
621 0 : if (pluginError == NPERR_NO_ERROR) {
622 0 : rv = NS_OK;
623 : }
624 : }
625 :
626 0 : return rv;
627 : }
628 :
629 0 : nsNPAPIPlugin* nsNPAPIPluginInstance::GetPlugin()
630 : {
631 0 : return mPlugin;
632 : }
633 :
634 0 : nsresult nsNPAPIPluginInstance::GetNPP(NPP* aNPP)
635 : {
636 0 : if (aNPP)
637 0 : *aNPP = &mNPP;
638 : else
639 0 : return NS_ERROR_NULL_POINTER;
640 :
641 0 : return NS_OK;
642 : }
643 :
644 0 : NPError nsNPAPIPluginInstance::SetWindowless(bool aWindowless)
645 : {
646 0 : mWindowless = aWindowless;
647 :
648 0 : if (mMIMEType) {
649 : // bug 558434 - Prior to 3.6.4, we assumed windowless was transparent.
650 : // Silverlight apparently relied on this quirk, so we default to
651 : // transparent unless they specify otherwise after setting the windowless
652 : // property. (Last tested version: sl 4.0).
653 : // Changes to this code should be matched with changes in
654 : // PluginInstanceChild::InitQuirksMode.
655 0 : NS_NAMED_LITERAL_CSTRING(silverlight, "application/x-silverlight");
656 0 : if (!PL_strncasecmp(mMIMEType, silverlight.get(), silverlight.Length())) {
657 0 : mTransparent = true;
658 : }
659 : }
660 :
661 0 : return NPERR_NO_ERROR;
662 : }
663 :
664 0 : NPError nsNPAPIPluginInstance::SetTransparent(bool aTransparent)
665 : {
666 0 : mTransparent = aTransparent;
667 0 : return NPERR_NO_ERROR;
668 : }
669 :
670 0 : NPError nsNPAPIPluginInstance::SetUsesDOMForCursor(bool aUsesDOMForCursor)
671 : {
672 0 : mUsesDOMForCursor = aUsesDOMForCursor;
673 0 : return NPERR_NO_ERROR;
674 : }
675 :
676 : bool
677 0 : nsNPAPIPluginInstance::UsesDOMForCursor()
678 : {
679 0 : return mUsesDOMForCursor;
680 : }
681 :
682 0 : void nsNPAPIPluginInstance::SetDrawingModel(NPDrawingModel aModel)
683 : {
684 0 : mDrawingModel = aModel;
685 0 : }
686 :
687 0 : void nsNPAPIPluginInstance::RedrawPlugin()
688 : {
689 0 : mOwner->RedrawPlugin();
690 0 : }
691 :
692 : #if defined(XP_MACOSX)
693 : void nsNPAPIPluginInstance::SetEventModel(NPEventModel aModel)
694 : {
695 : // the event model needs to be set for the object frame immediately
696 : nsCOMPtr<nsIPluginInstanceOwner> owner;
697 : GetOwner(getter_AddRefs(owner));
698 : if (!owner) {
699 : NS_WARNING("Trying to set event model without a plugin instance owner!");
700 : return;
701 : }
702 :
703 : owner->SetEventModel(aModel);
704 : }
705 : #endif
706 :
707 : #if defined(MOZ_WIDGET_ANDROID)
708 :
709 : static void SendLifecycleEvent(nsNPAPIPluginInstance* aInstance, PRUint32 aAction)
710 : {
711 : ANPEvent event;
712 : event.inSize = sizeof(ANPEvent);
713 : event.eventType = kLifecycle_ANPEventType;
714 : event.data.lifecycle.action = aAction;
715 : aInstance->HandleEvent(&event, nsnull);
716 : }
717 :
718 : void nsNPAPIPluginInstance::NotifyForeground(bool aForeground)
719 : {
720 : PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance::SetForeground this=%p\n foreground=%d",this, aForeground));
721 : if (RUNNING != mRunning)
722 : return;
723 :
724 : SendLifecycleEvent(this, aForeground ? kResume_ANPLifecycleAction : kPause_ANPLifecycleAction);
725 : }
726 :
727 : void nsNPAPIPluginInstance::NotifyOnScreen(bool aOnScreen)
728 : {
729 : PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance::SetOnScreen this=%p\n onScreen=%d",this, aOnScreen));
730 : if (RUNNING != mRunning || mOnScreen == aOnScreen)
731 : return;
732 :
733 : mOnScreen = aOnScreen;
734 : SendLifecycleEvent(this, aOnScreen ? kOnScreen_ANPLifecycleAction : kOffScreen_ANPLifecycleAction);
735 : }
736 :
737 : void nsNPAPIPluginInstance::MemoryPressure()
738 : {
739 : PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance::MemoryPressure this=%p\n",this));
740 : if (RUNNING != mRunning)
741 : return;
742 :
743 : SendLifecycleEvent(this, kFreeMemory_ANPLifecycleAction);
744 : }
745 :
746 : void nsNPAPIPluginInstance::SetANPDrawingModel(PRUint32 aModel)
747 : {
748 : mANPDrawingModel = aModel;
749 : }
750 :
751 : class SurfaceGetter : public nsRunnable {
752 : public:
753 : SurfaceGetter(nsNPAPIPluginInstance* aInstance, NPPluginFuncs* aPluginFunctions, NPP_t aNPP) :
754 : mInstance(aInstance), mPluginFunctions(aPluginFunctions), mNPP(aNPP) {
755 : }
756 : ~SurfaceGetter() {
757 : }
758 : nsresult Run() {
759 : void* surface;
760 : (*mPluginFunctions->getvalue)(&mNPP, kJavaSurface_ANPGetValue, &surface);
761 : mInstance->SetJavaSurface(surface);
762 : return NS_OK;
763 : }
764 : void RequestSurface() {
765 : JNIEnv* env = GetJNIForThread();
766 : if (!env)
767 : return;
768 :
769 : if (!mozilla::AndroidBridge::Bridge()) {
770 : PLUGIN_LOG(PLUGIN_LOG_BASIC, ("nsNPAPIPluginInstance null AndroidBridge"));
771 : return;
772 : }
773 : mozilla::AndroidBridge::Bridge()->PostToJavaThread(env, this);
774 : }
775 : private:
776 : nsNPAPIPluginInstance* mInstance;
777 : NPP_t mNPP;
778 : NPPluginFuncs* mPluginFunctions;
779 : };
780 :
781 :
782 : void* nsNPAPIPluginInstance::GetJavaSurface()
783 : {
784 : if (mANPDrawingModel != kSurface_ANPDrawingModel)
785 : return nsnull;
786 :
787 : return mSurface;
788 : }
789 :
790 : void nsNPAPIPluginInstance::SetJavaSurface(void* aSurface)
791 : {
792 : mSurface = aSurface;
793 : }
794 :
795 : void nsNPAPIPluginInstance::RequestJavaSurface()
796 : {
797 : if (mSurfaceGetter.get())
798 : return;
799 :
800 : mSurfaceGetter = new SurfaceGetter(this, mPlugin->PluginFuncs(), mNPP);
801 :
802 : ((SurfaceGetter*)mSurfaceGetter.get())->RequestSurface();
803 : }
804 :
805 : #endif
806 :
807 0 : nsresult nsNPAPIPluginInstance::GetDrawingModel(PRInt32* aModel)
808 : {
809 : #if defined(XP_MACOSX)
810 : *aModel = (PRInt32)mDrawingModel;
811 : return NS_OK;
812 : #else
813 0 : return NS_ERROR_FAILURE;
814 : #endif
815 : }
816 :
817 0 : nsresult nsNPAPIPluginInstance::IsRemoteDrawingCoreAnimation(bool* aDrawing)
818 : {
819 : #ifdef XP_MACOSX
820 : if (!mPlugin)
821 : return NS_ERROR_FAILURE;
822 :
823 : PluginLibrary* library = mPlugin->GetLibrary();
824 : if (!library)
825 : return NS_ERROR_FAILURE;
826 :
827 : return library->IsRemoteDrawingCoreAnimation(&mNPP, aDrawing);
828 : #else
829 0 : return NS_ERROR_FAILURE;
830 : #endif
831 : }
832 :
833 : nsresult
834 0 : nsNPAPIPluginInstance::GetJSObject(JSContext *cx, JSObject** outObject)
835 : {
836 0 : NPObject *npobj = nsnull;
837 0 : nsresult rv = GetValueFromPlugin(NPPVpluginScriptableNPObject, &npobj);
838 0 : if (NS_FAILED(rv) || !npobj)
839 0 : return NS_ERROR_FAILURE;
840 :
841 0 : *outObject = nsNPObjWrapper::GetNewOrUsed(&mNPP, cx, npobj);
842 :
843 0 : _releaseobject(npobj);
844 :
845 0 : return NS_OK;
846 : }
847 :
848 : nsresult
849 0 : nsNPAPIPluginInstance::DefineJavaProperties()
850 : {
851 0 : NPObject *plugin_obj = nsnull;
852 :
853 : // The dummy Java plugin's scriptable object is what we want to
854 : // expose as window.Packages. And Window.Packages.java will be
855 : // exposed as window.java.
856 :
857 : // Get the scriptable plugin object.
858 0 : nsresult rv = GetValueFromPlugin(NPPVpluginScriptableNPObject, &plugin_obj);
859 :
860 0 : if (NS_FAILED(rv) || !plugin_obj) {
861 0 : return NS_ERROR_FAILURE;
862 : }
863 :
864 : // Get the NPObject wrapper for window.
865 0 : NPObject *window_obj = _getwindowobject(&mNPP);
866 :
867 0 : if (!window_obj) {
868 0 : _releaseobject(plugin_obj);
869 :
870 0 : return NS_ERROR_FAILURE;
871 : }
872 :
873 0 : NPIdentifier java_id = _getstringidentifier("java");
874 0 : NPIdentifier packages_id = _getstringidentifier("Packages");
875 :
876 0 : NPObject *java_obj = nsnull;
877 : NPVariant v;
878 0 : OBJECT_TO_NPVARIANT(plugin_obj, v);
879 :
880 : // Define the properties.
881 :
882 0 : bool ok = _setproperty(&mNPP, window_obj, packages_id, &v);
883 0 : if (ok) {
884 0 : ok = _getproperty(&mNPP, plugin_obj, java_id, &v);
885 :
886 0 : if (ok && NPVARIANT_IS_OBJECT(v)) {
887 : // Set java_obj so that we properly release it at the end of
888 : // this function.
889 0 : java_obj = NPVARIANT_TO_OBJECT(v);
890 :
891 0 : ok = _setproperty(&mNPP, window_obj, java_id, &v);
892 : }
893 : }
894 :
895 0 : _releaseobject(window_obj);
896 0 : _releaseobject(plugin_obj);
897 0 : _releaseobject(java_obj);
898 :
899 0 : if (!ok)
900 0 : return NS_ERROR_FAILURE;
901 :
902 0 : return NS_OK;
903 : }
904 :
905 : nsresult
906 0 : nsNPAPIPluginInstance::SetCached(bool aCache)
907 : {
908 0 : mCached = aCache;
909 0 : return NS_OK;
910 : }
911 :
912 : bool
913 0 : nsNPAPIPluginInstance::ShouldCache()
914 : {
915 0 : return mCached;
916 : }
917 :
918 : nsresult
919 0 : nsNPAPIPluginInstance::IsWindowless(bool* isWindowless)
920 : {
921 : #ifdef MOZ_WIDGET_ANDROID
922 : // On android, pre-honeycomb, all plugins are treated as windowless.
923 : *isWindowless = true;
924 : #else
925 0 : *isWindowless = mWindowless;
926 : #endif
927 0 : return NS_OK;
928 : }
929 :
930 : class NS_STACK_CLASS AutoPluginLibraryCall
931 0 : {
932 : public:
933 0 : AutoPluginLibraryCall(nsNPAPIPluginInstance* aThis)
934 0 : : mThis(aThis), mGuard(aThis), mLibrary(nsnull)
935 : {
936 0 : nsNPAPIPlugin* plugin = mThis->GetPlugin();
937 0 : if (plugin)
938 0 : mLibrary = plugin->GetLibrary();
939 0 : }
940 0 : operator bool() { return !!mLibrary; }
941 0 : PluginLibrary* operator->() { return mLibrary; }
942 :
943 : private:
944 : nsNPAPIPluginInstance* mThis;
945 : PluginDestructionGuard mGuard;
946 : PluginLibrary* mLibrary;
947 : };
948 :
949 : nsresult
950 0 : nsNPAPIPluginInstance::AsyncSetWindow(NPWindow* window)
951 : {
952 0 : if (RUNNING != mRunning)
953 0 : return NS_OK;
954 :
955 0 : AutoPluginLibraryCall library(this);
956 0 : if (!library)
957 0 : return NS_ERROR_FAILURE;
958 :
959 0 : return library->AsyncSetWindow(&mNPP, window);
960 : }
961 :
962 : #if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
963 : nsresult
964 : nsNPAPIPluginInstance::HandleGUIEvent(const nsGUIEvent& anEvent, bool* handled)
965 : {
966 : if (RUNNING != mRunning) {
967 : *handled = false;
968 : return NS_OK;
969 : }
970 :
971 : AutoPluginLibraryCall library(this);
972 : if (!library)
973 : return NS_ERROR_FAILURE;
974 :
975 : return library->HandleGUIEvent(&mNPP, anEvent, handled);
976 : }
977 : #endif
978 :
979 : nsresult
980 0 : nsNPAPIPluginInstance::GetImageContainer(ImageContainer**aContainer)
981 : {
982 0 : *aContainer = nsnull;
983 :
984 0 : if (RUNNING != mRunning)
985 0 : return NS_OK;
986 :
987 0 : AutoPluginLibraryCall library(this);
988 0 : return !library ? NS_ERROR_FAILURE : library->GetImageContainer(&mNPP, aContainer);
989 : }
990 :
991 : nsresult
992 0 : nsNPAPIPluginInstance::GetImageSize(nsIntSize* aSize)
993 : {
994 0 : *aSize = nsIntSize(0, 0);
995 :
996 0 : if (RUNNING != mRunning)
997 0 : return NS_OK;
998 :
999 0 : AutoPluginLibraryCall library(this);
1000 0 : return !library ? NS_ERROR_FAILURE : library->GetImageSize(&mNPP, aSize);
1001 : }
1002 :
1003 : nsresult
1004 0 : nsNPAPIPluginInstance::NotifyPainted(void)
1005 : {
1006 0 : NS_NOTREACHED("Dead code, shouldn't be called.");
1007 0 : return NS_ERROR_NOT_IMPLEMENTED;
1008 : }
1009 :
1010 : nsresult
1011 0 : nsNPAPIPluginInstance::UseAsyncPainting(bool* aIsAsync)
1012 : {
1013 0 : if (!mUsePluginLayersPref) {
1014 0 : *aIsAsync = mUsePluginLayersPref;
1015 0 : return NS_OK;
1016 : }
1017 :
1018 0 : AutoPluginLibraryCall library(this);
1019 0 : if (!library)
1020 0 : return NS_ERROR_FAILURE;
1021 :
1022 0 : *aIsAsync = library->UseAsyncPainting();
1023 0 : return NS_OK;
1024 : }
1025 :
1026 : nsresult
1027 0 : nsNPAPIPluginInstance::SetBackgroundUnknown()
1028 : {
1029 0 : if (RUNNING != mRunning)
1030 0 : return NS_OK;
1031 :
1032 0 : AutoPluginLibraryCall library(this);
1033 0 : if (!library)
1034 0 : return NS_ERROR_FAILURE;
1035 :
1036 0 : return library->SetBackgroundUnknown(&mNPP);
1037 : }
1038 :
1039 : nsresult
1040 0 : nsNPAPIPluginInstance::BeginUpdateBackground(nsIntRect* aRect,
1041 : gfxContext** aContext)
1042 : {
1043 0 : if (RUNNING != mRunning)
1044 0 : return NS_OK;
1045 :
1046 0 : AutoPluginLibraryCall library(this);
1047 0 : if (!library)
1048 0 : return NS_ERROR_FAILURE;
1049 :
1050 0 : return library->BeginUpdateBackground(&mNPP, *aRect, aContext);
1051 : }
1052 :
1053 : nsresult
1054 0 : nsNPAPIPluginInstance::EndUpdateBackground(gfxContext* aContext,
1055 : nsIntRect* aRect)
1056 : {
1057 0 : if (RUNNING != mRunning)
1058 0 : return NS_OK;
1059 :
1060 0 : AutoPluginLibraryCall library(this);
1061 0 : if (!library)
1062 0 : return NS_ERROR_FAILURE;
1063 :
1064 0 : return library->EndUpdateBackground(&mNPP, aContext, *aRect);
1065 : }
1066 :
1067 : nsresult
1068 0 : nsNPAPIPluginInstance::IsTransparent(bool* isTransparent)
1069 : {
1070 0 : *isTransparent = mTransparent;
1071 0 : return NS_OK;
1072 : }
1073 :
1074 : nsresult
1075 0 : nsNPAPIPluginInstance::GetFormValue(nsAString& aValue)
1076 : {
1077 0 : aValue.Truncate();
1078 :
1079 0 : char *value = nsnull;
1080 0 : nsresult rv = GetValueFromPlugin(NPPVformValue, &value);
1081 0 : if (NS_FAILED(rv) || !value)
1082 0 : return NS_ERROR_FAILURE;
1083 :
1084 0 : CopyUTF8toUTF16(value, aValue);
1085 :
1086 : // NPPVformValue allocates with NPN_MemAlloc(), which uses
1087 : // nsMemory.
1088 0 : nsMemory::Free(value);
1089 :
1090 0 : return NS_OK;
1091 : }
1092 :
1093 : nsresult
1094 0 : nsNPAPIPluginInstance::PushPopupsEnabledState(bool aEnabled)
1095 : {
1096 0 : nsCOMPtr<nsPIDOMWindow> window = GetDOMWindow();
1097 0 : if (!window)
1098 0 : return NS_ERROR_FAILURE;
1099 :
1100 : PopupControlState oldState =
1101 0 : window->PushPopupControlState(aEnabled ? openAllowed : openAbused,
1102 0 : true);
1103 :
1104 0 : if (!mPopupStates.AppendElement(oldState)) {
1105 : // Appending to our state stack failed, pop what we just pushed.
1106 0 : window->PopPopupControlState(oldState);
1107 0 : return NS_ERROR_FAILURE;
1108 : }
1109 :
1110 0 : return NS_OK;
1111 : }
1112 :
1113 : nsresult
1114 0 : nsNPAPIPluginInstance::PopPopupsEnabledState()
1115 : {
1116 0 : PRInt32 last = mPopupStates.Length() - 1;
1117 :
1118 0 : if (last < 0) {
1119 : // Nothing to pop.
1120 0 : return NS_OK;
1121 : }
1122 :
1123 0 : nsCOMPtr<nsPIDOMWindow> window = GetDOMWindow();
1124 0 : if (!window)
1125 0 : return NS_ERROR_FAILURE;
1126 :
1127 0 : PopupControlState &oldState = mPopupStates[last];
1128 :
1129 0 : window->PopPopupControlState(oldState);
1130 :
1131 0 : mPopupStates.RemoveElementAt(last);
1132 :
1133 0 : return NS_OK;
1134 : }
1135 :
1136 : nsresult
1137 0 : nsNPAPIPluginInstance::GetPluginAPIVersion(PRUint16* version)
1138 : {
1139 0 : NS_ENSURE_ARG_POINTER(version);
1140 :
1141 0 : if (!mPlugin)
1142 0 : return NS_ERROR_FAILURE;
1143 :
1144 0 : if (!mPlugin->GetLibrary())
1145 0 : return NS_ERROR_FAILURE;
1146 :
1147 0 : NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
1148 :
1149 0 : *version = pluginFunctions->version;
1150 :
1151 0 : return NS_OK;
1152 : }
1153 :
1154 : nsresult
1155 0 : nsNPAPIPluginInstance::PrivateModeStateChanged()
1156 : {
1157 0 : if (RUNNING != mRunning)
1158 0 : return NS_OK;
1159 :
1160 0 : PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance informing plugin of private mode state change this=%p\n",this));
1161 :
1162 0 : if (!mPlugin || !mPlugin->GetLibrary())
1163 0 : return NS_ERROR_FAILURE;
1164 :
1165 0 : NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
1166 :
1167 0 : if (pluginFunctions->setvalue) {
1168 0 : PluginDestructionGuard guard(this);
1169 :
1170 0 : nsCOMPtr<nsIPrivateBrowsingService> pbs = do_GetService(NS_PRIVATE_BROWSING_SERVICE_CONTRACTID);
1171 0 : if (pbs) {
1172 0 : bool pme = false;
1173 0 : nsresult rv = pbs->GetPrivateBrowsingEnabled(&pme);
1174 0 : if (NS_FAILED(rv))
1175 0 : return rv;
1176 :
1177 : NPError error;
1178 0 : NPBool value = static_cast<NPBool>(pme);
1179 0 : NS_TRY_SAFE_CALL_RETURN(error, (*pluginFunctions->setvalue)(&mNPP, NPNVprivateModeBool, &value), this);
1180 0 : return (error == NPERR_NO_ERROR) ? NS_OK : NS_ERROR_FAILURE;
1181 : }
1182 : }
1183 0 : return NS_ERROR_FAILURE;
1184 : }
1185 :
1186 : class DelayUnscheduleEvent : public nsRunnable {
1187 : public:
1188 : nsRefPtr<nsNPAPIPluginInstance> mInstance;
1189 : uint32_t mTimerID;
1190 0 : DelayUnscheduleEvent(nsNPAPIPluginInstance* aInstance, uint32_t aTimerId)
1191 : : mInstance(aInstance)
1192 0 : , mTimerID(aTimerId)
1193 0 : {}
1194 :
1195 0 : ~DelayUnscheduleEvent() {}
1196 :
1197 : NS_IMETHOD Run();
1198 : };
1199 :
1200 : NS_IMETHODIMP
1201 0 : DelayUnscheduleEvent::Run()
1202 : {
1203 0 : mInstance->UnscheduleTimer(mTimerID);
1204 0 : return NS_OK;
1205 : }
1206 :
1207 :
1208 : static void
1209 0 : PluginTimerCallback(nsITimer *aTimer, void *aClosure)
1210 : {
1211 0 : nsNPAPITimer* t = (nsNPAPITimer*)aClosure;
1212 0 : NPP npp = t->npp;
1213 0 : uint32_t id = t->id;
1214 :
1215 : // Some plugins (Flash on Android) calls unscheduletimer
1216 : // from this callback.
1217 0 : t->inCallback = true;
1218 0 : (*(t->callback))(npp, id);
1219 0 : t->inCallback = false;
1220 :
1221 : // Make sure we still have an instance and the timer is still alive
1222 : // after the callback.
1223 0 : nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance*)npp->ndata;
1224 0 : if (!inst || !inst->TimerWithID(id, NULL))
1225 0 : return;
1226 :
1227 : // use UnscheduleTimer to clean up if this is a one-shot timer
1228 : PRUint32 timerType;
1229 0 : t->timer->GetType(&timerType);
1230 0 : if (timerType == nsITimer::TYPE_ONE_SHOT)
1231 0 : inst->UnscheduleTimer(id);
1232 : }
1233 :
1234 : nsNPAPITimer*
1235 0 : nsNPAPIPluginInstance::TimerWithID(uint32_t id, PRUint32* index)
1236 : {
1237 0 : PRUint32 len = mTimers.Length();
1238 0 : for (PRUint32 i = 0; i < len; i++) {
1239 0 : if (mTimers[i]->id == id) {
1240 0 : if (index)
1241 0 : *index = i;
1242 0 : return mTimers[i];
1243 : }
1244 : }
1245 0 : return nsnull;
1246 : }
1247 :
1248 : uint32_t
1249 0 : nsNPAPIPluginInstance::ScheduleTimer(uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID))
1250 : {
1251 0 : nsNPAPITimer *newTimer = new nsNPAPITimer();
1252 :
1253 0 : newTimer->inCallback = false;
1254 0 : newTimer->npp = &mNPP;
1255 :
1256 : // generate ID that is unique to this instance
1257 0 : uint32_t uniqueID = mTimers.Length();
1258 0 : while ((uniqueID == 0) || TimerWithID(uniqueID, NULL))
1259 0 : uniqueID++;
1260 0 : newTimer->id = uniqueID;
1261 :
1262 : // create new xpcom timer, scheduled correctly
1263 : nsresult rv;
1264 0 : nsCOMPtr<nsITimer> xpcomTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
1265 0 : if (NS_FAILED(rv)) {
1266 0 : delete newTimer;
1267 0 : return 0;
1268 : }
1269 0 : const short timerType = (repeat ? (short)nsITimer::TYPE_REPEATING_SLACK : (short)nsITimer::TYPE_ONE_SHOT);
1270 0 : xpcomTimer->InitWithFuncCallback(PluginTimerCallback, newTimer, interval, timerType);
1271 0 : newTimer->timer = xpcomTimer;
1272 :
1273 : // save callback function
1274 0 : newTimer->callback = timerFunc;
1275 :
1276 : // add timer to timers array
1277 0 : mTimers.AppendElement(newTimer);
1278 :
1279 0 : return newTimer->id;
1280 : }
1281 :
1282 : void
1283 0 : nsNPAPIPluginInstance::UnscheduleTimer(uint32_t timerID)
1284 : {
1285 : // find the timer struct by ID
1286 : PRUint32 index;
1287 0 : nsNPAPITimer* t = TimerWithID(timerID, &index);
1288 0 : if (!t)
1289 0 : return;
1290 :
1291 0 : if (t->inCallback) {
1292 0 : nsCOMPtr<nsIRunnable> e = new DelayUnscheduleEvent(this, timerID);
1293 0 : NS_DispatchToCurrentThread(e);
1294 : return;
1295 : }
1296 :
1297 : // cancel the timer
1298 0 : t->timer->Cancel();
1299 :
1300 : // remove timer struct from array
1301 0 : mTimers.RemoveElementAt(index);
1302 :
1303 : // delete timer
1304 0 : delete t;
1305 : }
1306 :
1307 : // Show the context menu at the location for the current event.
1308 : // This can only be called from within an NPP_SendEvent call.
1309 : NPError
1310 0 : nsNPAPIPluginInstance::PopUpContextMenu(NPMenu* menu)
1311 : {
1312 0 : if (mOwner && mCurrentPluginEvent)
1313 0 : return mOwner->ShowNativeContextMenu(menu, mCurrentPluginEvent);
1314 :
1315 0 : return NPERR_GENERIC_ERROR;
1316 : }
1317 :
1318 : NPBool
1319 0 : nsNPAPIPluginInstance::ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
1320 : double *destX, double *destY, NPCoordinateSpace destSpace)
1321 : {
1322 0 : if (mOwner)
1323 0 : return mOwner->ConvertPoint(sourceX, sourceY, sourceSpace, destX, destY, destSpace);
1324 :
1325 0 : return false;
1326 : }
1327 :
1328 : nsresult
1329 0 : nsNPAPIPluginInstance::GetDOMElement(nsIDOMElement* *result)
1330 : {
1331 0 : if (!mOwner) {
1332 0 : *result = nsnull;
1333 0 : return NS_ERROR_FAILURE;
1334 : }
1335 :
1336 0 : nsCOMPtr<nsIPluginTagInfo> tinfo(do_QueryInterface(mOwner));
1337 0 : if (tinfo)
1338 0 : return tinfo->GetDOMElement(result);
1339 :
1340 0 : return NS_ERROR_FAILURE;
1341 : }
1342 :
1343 : nsresult
1344 0 : nsNPAPIPluginInstance::InvalidateRect(NPRect *invalidRect)
1345 : {
1346 0 : if (RUNNING != mRunning)
1347 0 : return NS_OK;
1348 :
1349 0 : nsCOMPtr<nsIPluginInstanceOwner> owner;
1350 0 : GetOwner(getter_AddRefs(owner));
1351 0 : if (!owner)
1352 0 : return NS_ERROR_FAILURE;
1353 :
1354 0 : return owner->InvalidateRect(invalidRect);
1355 : }
1356 :
1357 : nsresult
1358 0 : nsNPAPIPluginInstance::InvalidateRegion(NPRegion invalidRegion)
1359 : {
1360 0 : if (RUNNING != mRunning)
1361 0 : return NS_OK;
1362 :
1363 0 : nsCOMPtr<nsIPluginInstanceOwner> owner;
1364 0 : GetOwner(getter_AddRefs(owner));
1365 0 : if (!owner)
1366 0 : return NS_ERROR_FAILURE;
1367 :
1368 0 : return owner->InvalidateRegion(invalidRegion);
1369 : }
1370 :
1371 : nsresult
1372 0 : nsNPAPIPluginInstance::GetMIMEType(const char* *result)
1373 : {
1374 0 : if (!mMIMEType)
1375 0 : *result = "";
1376 : else
1377 0 : *result = mMIMEType;
1378 :
1379 0 : return NS_OK;
1380 : }
1381 :
1382 : nsresult
1383 0 : nsNPAPIPluginInstance::GetJSContext(JSContext* *outContext)
1384 : {
1385 0 : nsCOMPtr<nsIPluginInstanceOwner> owner;
1386 0 : GetOwner(getter_AddRefs(owner));
1387 0 : if (!owner)
1388 0 : return NS_ERROR_FAILURE;
1389 :
1390 0 : *outContext = NULL;
1391 0 : nsCOMPtr<nsIDocument> document;
1392 :
1393 0 : nsresult rv = owner->GetDocument(getter_AddRefs(document));
1394 :
1395 0 : if (NS_SUCCEEDED(rv) && document) {
1396 0 : nsIScriptGlobalObject *global = document->GetScriptGlobalObject();
1397 :
1398 0 : if (global) {
1399 0 : nsIScriptContext *context = global->GetContext();
1400 :
1401 0 : if (context) {
1402 0 : *outContext = context->GetNativeContext();
1403 : }
1404 : }
1405 : }
1406 :
1407 0 : return rv;
1408 : }
1409 :
1410 : nsresult
1411 0 : nsNPAPIPluginInstance::GetOwner(nsIPluginInstanceOwner **aOwner)
1412 : {
1413 0 : NS_ENSURE_ARG_POINTER(aOwner);
1414 0 : *aOwner = mOwner;
1415 0 : NS_IF_ADDREF(mOwner);
1416 0 : return (mOwner ? NS_OK : NS_ERROR_FAILURE);
1417 : }
1418 :
1419 : nsresult
1420 0 : nsNPAPIPluginInstance::SetOwner(nsIPluginInstanceOwner *aOwner)
1421 : {
1422 0 : mOwner = aOwner;
1423 0 : return NS_OK;
1424 : }
1425 :
1426 : nsresult
1427 0 : nsNPAPIPluginInstance::ShowStatus(const char* message)
1428 : {
1429 0 : if (mOwner)
1430 0 : return mOwner->ShowStatus(message);
1431 :
1432 0 : return NS_ERROR_FAILURE;
1433 : }
1434 :
1435 : nsresult
1436 0 : nsNPAPIPluginInstance::InvalidateOwner()
1437 : {
1438 0 : mOwner = nsnull;
1439 :
1440 0 : return NS_OK;
1441 : }
1442 :
1443 : nsresult
1444 0 : nsNPAPIPluginInstance::AsyncSetWindow(NPWindow& window)
1445 : {
1446 0 : return NS_ERROR_NOT_IMPLEMENTED;
1447 : }
1448 :
1449 : void
1450 0 : nsNPAPIPluginInstance::URLRedirectResponse(void* notifyData, NPBool allow)
1451 : {
1452 0 : if (!notifyData) {
1453 0 : return;
1454 : }
1455 :
1456 0 : PRUint32 listenerCount = mStreamListeners.Length();
1457 0 : for (PRUint32 i = 0; i < listenerCount; i++) {
1458 0 : nsNPAPIPluginStreamListener* currentListener = mStreamListeners[i];
1459 0 : if (currentListener->GetNotifyData() == notifyData) {
1460 0 : currentListener->URLRedirectResponse(allow);
1461 : }
1462 : }
1463 : }
1464 :
1465 : NPError
1466 0 : nsNPAPIPluginInstance::InitAsyncSurface(NPSize *size, NPImageFormat format,
1467 : void *initData, NPAsyncSurface *surface)
1468 : {
1469 0 : if (mOwner)
1470 0 : return mOwner->InitAsyncSurface(size, format, initData, surface);
1471 :
1472 0 : return NPERR_GENERIC_ERROR;
1473 : }
1474 :
1475 : NPError
1476 0 : nsNPAPIPluginInstance::FinalizeAsyncSurface(NPAsyncSurface *surface)
1477 : {
1478 0 : if (mOwner)
1479 0 : return mOwner->FinalizeAsyncSurface(surface);
1480 :
1481 0 : return NPERR_GENERIC_ERROR;
1482 : }
1483 :
1484 : void
1485 0 : nsNPAPIPluginInstance::SetCurrentAsyncSurface(NPAsyncSurface *surface, NPRect *changed)
1486 : {
1487 0 : if (mOwner)
1488 0 : mOwner->SetCurrentAsyncSurface(surface, changed);
1489 0 : }
1490 :
1491 : class CarbonEventModelFailureEvent : public nsRunnable {
1492 : public:
1493 : nsCOMPtr<nsIContent> mContent;
1494 :
1495 0 : CarbonEventModelFailureEvent(nsIContent* aContent)
1496 0 : : mContent(aContent)
1497 0 : {}
1498 :
1499 0 : ~CarbonEventModelFailureEvent() {}
1500 :
1501 : NS_IMETHOD Run();
1502 : };
1503 :
1504 : NS_IMETHODIMP
1505 0 : CarbonEventModelFailureEvent::Run()
1506 : {
1507 0 : nsString type = NS_LITERAL_STRING("npapi-carbon-event-model-failure");
1508 : nsContentUtils::DispatchTrustedEvent(mContent->GetDocument(), mContent,
1509 0 : type, true, true);
1510 0 : return NS_OK;
1511 : }
1512 :
1513 : void
1514 0 : nsNPAPIPluginInstance::CarbonNPAPIFailure()
1515 : {
1516 0 : nsCOMPtr<nsIDOMElement> element;
1517 0 : GetDOMElement(getter_AddRefs(element));
1518 0 : if (!element) {
1519 : return;
1520 : }
1521 :
1522 0 : nsCOMPtr<nsIContent> content(do_QueryInterface(element));
1523 0 : if (!content) {
1524 : return;
1525 : }
1526 :
1527 0 : nsCOMPtr<nsIRunnable> e = new CarbonEventModelFailureEvent(content);
1528 0 : nsresult rv = NS_DispatchToCurrentThread(e);
1529 0 : if (NS_FAILED(rv)) {
1530 0 : NS_WARNING("Failed to dispatch CarbonEventModelFailureEvent.");
1531 : }
1532 : }
|