dom/plugins/base/nsNPAPIPlugin.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "base/basictypes.h"
michael@0 7
michael@0 8 /* This must occur *after* layers/PLayerTransaction.h to avoid typedefs conflicts. */
michael@0 9 #include "mozilla/ArrayUtils.h"
michael@0 10
michael@0 11 #include "pratom.h"
michael@0 12 #include "prmem.h"
michael@0 13 #include "prenv.h"
michael@0 14 #include "prclist.h"
michael@0 15
michael@0 16 #include "jsfriendapi.h"
michael@0 17
michael@0 18 #include "nsPluginHost.h"
michael@0 19 #include "nsNPAPIPlugin.h"
michael@0 20 #include "nsNPAPIPluginInstance.h"
michael@0 21 #include "nsNPAPIPluginStreamListener.h"
michael@0 22 #include "nsPluginStreamListenerPeer.h"
michael@0 23 #include "nsIServiceManager.h"
michael@0 24 #include "nsThreadUtils.h"
michael@0 25 #include "mozilla/Preferences.h"
michael@0 26 #include "nsPluginInstanceOwner.h"
michael@0 27
michael@0 28 #include "nsPluginsDir.h"
michael@0 29 #include "nsPluginLogging.h"
michael@0 30
michael@0 31 #include "nsIDOMElement.h"
michael@0 32 #include "nsPIDOMWindow.h"
michael@0 33 #include "nsGlobalWindow.h"
michael@0 34 #include "nsIDocument.h"
michael@0 35 #include "nsIContent.h"
michael@0 36 #include "nsIScriptGlobalObject.h"
michael@0 37 #include "nsIScriptContext.h"
michael@0 38 #include "nsIUnicodeNormalizer.h"
michael@0 39 #include "nsDOMJSUtils.h"
michael@0 40 #include "nsIPrincipal.h"
michael@0 41 #include "nsWildCard.h"
michael@0 42 #include "nsContentUtils.h"
michael@0 43 #include "nsCxPusher.h"
michael@0 44
michael@0 45 #include "nsIXPConnect.h"
michael@0 46
michael@0 47 #include "nsIObserverService.h"
michael@0 48 #include <prinrval.h>
michael@0 49
michael@0 50 #ifdef MOZ_WIDGET_COCOA
michael@0 51 #include <Carbon/Carbon.h>
michael@0 52 #include <ApplicationServices/ApplicationServices.h>
michael@0 53 #include <OpenGL/OpenGL.h>
michael@0 54 #include "nsCocoaFeatures.h"
michael@0 55 #endif
michael@0 56
michael@0 57 // needed for nppdf plugin
michael@0 58 #if (MOZ_WIDGET_GTK)
michael@0 59 #include <gdk/gdk.h>
michael@0 60 #include <gdk/gdkx.h>
michael@0 61 #if (MOZ_WIDGET_GTK == 2)
michael@0 62 #include "gtk2xtbin.h"
michael@0 63 #endif
michael@0 64 #endif
michael@0 65
michael@0 66 #include "nsJSUtils.h"
michael@0 67 #include "nsJSNPRuntime.h"
michael@0 68 #include "nsIHttpAuthManager.h"
michael@0 69 #include "nsICookieService.h"
michael@0 70 #include "nsILoadContext.h"
michael@0 71 #include "nsIDocShell.h"
michael@0 72
michael@0 73 #include "nsNetUtil.h"
michael@0 74
michael@0 75 #include "mozilla/Mutex.h"
michael@0 76 #include "mozilla/PluginLibrary.h"
michael@0 77 using mozilla::PluginLibrary;
michael@0 78
michael@0 79 #include "mozilla/PluginPRLibrary.h"
michael@0 80 using mozilla::PluginPRLibrary;
michael@0 81
michael@0 82 #include "mozilla/plugins/PluginModuleParent.h"
michael@0 83 using mozilla::plugins::PluginModuleParent;
michael@0 84
michael@0 85 #ifdef MOZ_X11
michael@0 86 #include "mozilla/X11Util.h"
michael@0 87 #endif
michael@0 88
michael@0 89 #ifdef XP_WIN
michael@0 90 #include <windows.h>
michael@0 91 #include "mozilla/WindowsVersion.h"
michael@0 92 #ifdef ACCESSIBILITY
michael@0 93 #include "mozilla/a11y/Compatibility.h"
michael@0 94 #endif
michael@0 95 #endif
michael@0 96
michael@0 97 #ifdef MOZ_WIDGET_ANDROID
michael@0 98 #include <android/log.h>
michael@0 99 #include "android_npapi.h"
michael@0 100 #include "ANPBase.h"
michael@0 101 #include "AndroidBridge.h"
michael@0 102 #undef LOG
michael@0 103 #define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args)
michael@0 104 #endif
michael@0 105
michael@0 106 using namespace mozilla;
michael@0 107 using namespace mozilla::plugins::parent;
michael@0 108
michael@0 109 // We should make this const...
michael@0 110 static NPNetscapeFuncs sBrowserFuncs = {
michael@0 111 sizeof(sBrowserFuncs),
michael@0 112 (NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR,
michael@0 113 _geturl,
michael@0 114 _posturl,
michael@0 115 _requestread,
michael@0 116 _newstream,
michael@0 117 _write,
michael@0 118 _destroystream,
michael@0 119 _status,
michael@0 120 _useragent,
michael@0 121 _memalloc,
michael@0 122 _memfree,
michael@0 123 _memflush,
michael@0 124 _reloadplugins,
michael@0 125 _getJavaEnv,
michael@0 126 _getJavaPeer,
michael@0 127 _geturlnotify,
michael@0 128 _posturlnotify,
michael@0 129 _getvalue,
michael@0 130 _setvalue,
michael@0 131 _invalidaterect,
michael@0 132 _invalidateregion,
michael@0 133 _forceredraw,
michael@0 134 _getstringidentifier,
michael@0 135 _getstringidentifiers,
michael@0 136 _getintidentifier,
michael@0 137 _identifierisstring,
michael@0 138 _utf8fromidentifier,
michael@0 139 _intfromidentifier,
michael@0 140 _createobject,
michael@0 141 _retainobject,
michael@0 142 _releaseobject,
michael@0 143 _invoke,
michael@0 144 _invokeDefault,
michael@0 145 _evaluate,
michael@0 146 _getproperty,
michael@0 147 _setproperty,
michael@0 148 _removeproperty,
michael@0 149 _hasproperty,
michael@0 150 _hasmethod,
michael@0 151 _releasevariantvalue,
michael@0 152 _setexception,
michael@0 153 _pushpopupsenabledstate,
michael@0 154 _poppopupsenabledstate,
michael@0 155 _enumerate,
michael@0 156 _pluginthreadasynccall,
michael@0 157 _construct,
michael@0 158 _getvalueforurl,
michael@0 159 _setvalueforurl,
michael@0 160 _getauthenticationinfo,
michael@0 161 _scheduletimer,
michael@0 162 _unscheduletimer,
michael@0 163 _popupcontextmenu,
michael@0 164 _convertpoint,
michael@0 165 nullptr, // handleevent, unimplemented
michael@0 166 nullptr, // unfocusinstance, unimplemented
michael@0 167 _urlredirectresponse,
michael@0 168 _initasyncsurface,
michael@0 169 _finalizeasyncsurface,
michael@0 170 _setcurrentasyncsurface
michael@0 171 };
michael@0 172
michael@0 173 static Mutex *sPluginThreadAsyncCallLock = nullptr;
michael@0 174 static PRCList sPendingAsyncCalls = PR_INIT_STATIC_CLIST(&sPendingAsyncCalls);
michael@0 175
michael@0 176 // POST/GET stream type
michael@0 177 enum eNPPStreamTypeInternal {
michael@0 178 eNPPStreamTypeInternal_Get,
michael@0 179 eNPPStreamTypeInternal_Post
michael@0 180 };
michael@0 181
michael@0 182 PRIntervalTime NS_NotifyBeginPluginCall(NSPluginCallReentry aReentryState)
michael@0 183 {
michael@0 184 nsNPAPIPluginInstance::BeginPluginCall(aReentryState);
michael@0 185 return PR_IntervalNow();
michael@0 186 }
michael@0 187
michael@0 188 // This function sends a notification using the observer service to any object
michael@0 189 // registered to listen to the "experimental-notify-plugin-call" subject.
michael@0 190 // Each "experimental-notify-plugin-call" notification carries with it the run
michael@0 191 // time value in milliseconds that the call took to execute.
michael@0 192 void NS_NotifyPluginCall(PRIntervalTime startTime, NSPluginCallReentry aReentryState)
michael@0 193 {
michael@0 194 nsNPAPIPluginInstance::EndPluginCall(aReentryState);
michael@0 195
michael@0 196 PRIntervalTime endTime = PR_IntervalNow() - startTime;
michael@0 197 nsCOMPtr<nsIObserverService> notifyUIService =
michael@0 198 mozilla::services::GetObserverService();
michael@0 199 if (!notifyUIService)
michael@0 200 return;
michael@0 201
michael@0 202 float runTimeInSeconds = float(endTime) / PR_TicksPerSecond();
michael@0 203 nsAutoString runTimeString;
michael@0 204 runTimeString.AppendFloat(runTimeInSeconds);
michael@0 205 const char16_t* runTime = runTimeString.get();
michael@0 206 notifyUIService->NotifyObservers(nullptr, "experimental-notify-plugin-call",
michael@0 207 runTime);
michael@0 208 }
michael@0 209
michael@0 210 static void CheckClassInitialized()
michael@0 211 {
michael@0 212 static bool initialized = false;
michael@0 213
michael@0 214 if (initialized)
michael@0 215 return;
michael@0 216
michael@0 217 if (!sPluginThreadAsyncCallLock)
michael@0 218 sPluginThreadAsyncCallLock = new Mutex("nsNPAPIPlugin.sPluginThreadAsyncCallLock");
michael@0 219
michael@0 220 initialized = true;
michael@0 221
michael@0 222 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,("NPN callbacks initialized\n"));
michael@0 223 }
michael@0 224
michael@0 225 NS_IMPL_ISUPPORTS0(nsNPAPIPlugin)
michael@0 226
michael@0 227 nsNPAPIPlugin::nsNPAPIPlugin()
michael@0 228 {
michael@0 229 memset((void*)&mPluginFuncs, 0, sizeof(mPluginFuncs));
michael@0 230 mPluginFuncs.size = sizeof(mPluginFuncs);
michael@0 231 mPluginFuncs.version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
michael@0 232
michael@0 233 mLibrary = nullptr;
michael@0 234 }
michael@0 235
michael@0 236 nsNPAPIPlugin::~nsNPAPIPlugin()
michael@0 237 {
michael@0 238 delete mLibrary;
michael@0 239 mLibrary = nullptr;
michael@0 240 }
michael@0 241
michael@0 242 void
michael@0 243 nsNPAPIPlugin::PluginCrashed(const nsAString& pluginDumpID,
michael@0 244 const nsAString& browserDumpID)
michael@0 245 {
michael@0 246 nsRefPtr<nsPluginHost> host = nsPluginHost::GetInst();
michael@0 247 host->PluginCrashed(this, pluginDumpID, browserDumpID);
michael@0 248 }
michael@0 249
michael@0 250 bool
michael@0 251 nsNPAPIPlugin::RunPluginOOP(const nsPluginTag *aPluginTag)
michael@0 252 {
michael@0 253 if (PR_GetEnv("MOZ_DISABLE_OOP_PLUGINS")) {
michael@0 254 return false;
michael@0 255 }
michael@0 256
michael@0 257 if (!aPluginTag) {
michael@0 258 return false;
michael@0 259 }
michael@0 260
michael@0 261 #ifdef ACCESSIBILITY
michael@0 262 // Certain assistive technologies don't want oop Flash, thus we have a special
michael@0 263 // pref for them to disable oop Flash (refer to bug 785047 for details).
michael@0 264 bool useA11yPref = false;
michael@0 265 #ifdef XP_WIN
michael@0 266 useA11yPref = a11y::Compatibility::IsJAWS();
michael@0 267 #endif
michael@0 268 #endif
michael@0 269
michael@0 270 #ifdef XP_WIN
michael@0 271 // On Windows Vista+, we force Flash to run in OOPP mode because Adobe
michael@0 272 // doesn't test Flash in-process and there are known stability bugs.
michael@0 273 if (aPluginTag->mIsFlashPlugin && IsVistaOrLater()) {
michael@0 274 #ifdef ACCESSIBILITY
michael@0 275 if (!useA11yPref)
michael@0 276 return true;
michael@0 277 #else
michael@0 278 return true;
michael@0 279 #endif
michael@0 280 }
michael@0 281 #endif
michael@0 282
michael@0 283 nsIPrefBranch* prefs = Preferences::GetRootBranch();
michael@0 284 if (!prefs) {
michael@0 285 return false;
michael@0 286 }
michael@0 287
michael@0 288 // Get per-library whitelist/blacklist pref string
michael@0 289 // "dom.ipc.plugins.enabled.filename.dll" and fall back to the default value
michael@0 290 // of "dom.ipc.plugins.enabled"
michael@0 291 // The "filename.dll" part can contain shell wildcard pattern
michael@0 292
michael@0 293 nsAutoCString prefFile(aPluginTag->mFullPath.get());
michael@0 294 int32_t slashPos = prefFile.RFindCharInSet("/\\");
michael@0 295 if (kNotFound == slashPos)
michael@0 296 return false;
michael@0 297 prefFile.Cut(0, slashPos + 1);
michael@0 298 ToLowerCase(prefFile);
michael@0 299
michael@0 300 #ifdef XP_MACOSX
michael@0 301 #if defined(__i386__)
michael@0 302 nsAutoCString prefGroupKey("dom.ipc.plugins.enabled.i386.");
michael@0 303 #elif defined(__x86_64__)
michael@0 304 nsAutoCString prefGroupKey("dom.ipc.plugins.enabled.x86_64.");
michael@0 305 #elif defined(__ppc__)
michael@0 306 nsAutoCString prefGroupKey("dom.ipc.plugins.enabled.ppc.");
michael@0 307 #endif
michael@0 308 #else
michael@0 309 nsAutoCString prefGroupKey("dom.ipc.plugins.enabled.");
michael@0 310 #endif
michael@0 311
michael@0 312 #ifdef ACCESSIBILITY
michael@0 313 if (useA11yPref)
michael@0 314 prefGroupKey.AssignLiteral("dom.ipc.plugins.enabled.a11y.");
michael@0 315 #endif
michael@0 316
michael@0 317 // Java plugins include a number of different file names,
michael@0 318 // so use the mime type (mIsJavaPlugin) and a special pref.
michael@0 319 if (aPluginTag->mIsJavaPlugin &&
michael@0 320 !Preferences::GetBool("dom.ipc.plugins.java.enabled", true)) {
michael@0 321 return false;
michael@0 322 }
michael@0 323
michael@0 324 uint32_t prefCount;
michael@0 325 char** prefNames;
michael@0 326 nsresult rv = prefs->GetChildList(prefGroupKey.get(),
michael@0 327 &prefCount, &prefNames);
michael@0 328
michael@0 329 bool oopPluginsEnabled = false;
michael@0 330 bool prefSet = false;
michael@0 331
michael@0 332 if (NS_SUCCEEDED(rv) && prefCount > 0) {
michael@0 333 uint32_t prefixLength = prefGroupKey.Length();
michael@0 334 for (uint32_t currentPref = 0; currentPref < prefCount; currentPref++) {
michael@0 335 // Get the mask
michael@0 336 const char* maskStart = prefNames[currentPref] + prefixLength;
michael@0 337 bool match = false;
michael@0 338
michael@0 339 int valid = NS_WildCardValid(maskStart);
michael@0 340 if (valid == INVALID_SXP) {
michael@0 341 continue;
michael@0 342 }
michael@0 343 else if(valid == NON_SXP) {
michael@0 344 // mask is not a shell pattern, compare it as normal string
michael@0 345 match = (strcmp(prefFile.get(), maskStart) == 0);
michael@0 346 }
michael@0 347 else {
michael@0 348 match = (NS_WildCardMatch(prefFile.get(), maskStart, 0) == MATCH);
michael@0 349 }
michael@0 350
michael@0 351 if (match && NS_SUCCEEDED(Preferences::GetBool(prefNames[currentPref],
michael@0 352 &oopPluginsEnabled))) {
michael@0 353 prefSet = true;
michael@0 354 break;
michael@0 355 }
michael@0 356 }
michael@0 357 NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(prefCount, prefNames);
michael@0 358 }
michael@0 359
michael@0 360 if (!prefSet) {
michael@0 361 oopPluginsEnabled =
michael@0 362 #ifdef XP_MACOSX
michael@0 363 #if defined(__i386__)
michael@0 364 Preferences::GetBool("dom.ipc.plugins.enabled.i386", false);
michael@0 365 #elif defined(__x86_64__)
michael@0 366 Preferences::GetBool("dom.ipc.plugins.enabled.x86_64", false);
michael@0 367 #elif defined(__ppc__)
michael@0 368 Preferences::GetBool("dom.ipc.plugins.enabled.ppc", false);
michael@0 369 #endif
michael@0 370 #else
michael@0 371 #ifdef ACCESSIBILITY
michael@0 372 useA11yPref ? Preferences::GetBool("dom.ipc.plugins.enabled.a11y", false) :
michael@0 373 #endif
michael@0 374 Preferences::GetBool("dom.ipc.plugins.enabled", false);
michael@0 375 #endif
michael@0 376 }
michael@0 377
michael@0 378 return oopPluginsEnabled;
michael@0 379 }
michael@0 380
michael@0 381 inline PluginLibrary*
michael@0 382 GetNewPluginLibrary(nsPluginTag *aPluginTag)
michael@0 383 {
michael@0 384 if (!aPluginTag) {
michael@0 385 return nullptr;
michael@0 386 }
michael@0 387
michael@0 388 if (nsNPAPIPlugin::RunPluginOOP(aPluginTag)) {
michael@0 389 return PluginModuleParent::LoadModule(aPluginTag->mFullPath.get());
michael@0 390 }
michael@0 391 return new PluginPRLibrary(aPluginTag->mFullPath.get(), aPluginTag->mLibrary);
michael@0 392 }
michael@0 393
michael@0 394 // Creates an nsNPAPIPlugin object. One nsNPAPIPlugin object exists per plugin (not instance).
michael@0 395 nsresult
michael@0 396 nsNPAPIPlugin::CreatePlugin(nsPluginTag *aPluginTag, nsNPAPIPlugin** aResult)
michael@0 397 {
michael@0 398 *aResult = nullptr;
michael@0 399
michael@0 400 if (!aPluginTag) {
michael@0 401 return NS_ERROR_FAILURE;
michael@0 402 }
michael@0 403
michael@0 404 CheckClassInitialized();
michael@0 405
michael@0 406 nsRefPtr<nsNPAPIPlugin> plugin = new nsNPAPIPlugin();
michael@0 407 if (!plugin)
michael@0 408 return NS_ERROR_OUT_OF_MEMORY;
michael@0 409
michael@0 410 PluginLibrary* pluginLib = GetNewPluginLibrary(aPluginTag);
michael@0 411 if (!pluginLib) {
michael@0 412 return NS_ERROR_FAILURE;
michael@0 413 }
michael@0 414
michael@0 415 #if defined(XP_MACOSX) || defined(MOZ_WIDGET_ANDROID)
michael@0 416 if (!pluginLib->HasRequiredFunctions()) {
michael@0 417 NS_WARNING("Not all necessary functions exposed by plugin, it will not load.");
michael@0 418 return NS_ERROR_FAILURE;
michael@0 419 }
michael@0 420 #endif
michael@0 421
michael@0 422 plugin->mLibrary = pluginLib;
michael@0 423 pluginLib->SetPlugin(plugin);
michael@0 424
michael@0 425 NPError pluginCallError;
michael@0 426 nsresult rv;
michael@0 427
michael@0 428 // Exchange NPAPI entry points.
michael@0 429 #if defined(XP_WIN)
michael@0 430 // NP_GetEntryPoints must be called before NP_Initialize on Windows.
michael@0 431 rv = pluginLib->NP_GetEntryPoints(&plugin->mPluginFuncs, &pluginCallError);
michael@0 432 if (rv != NS_OK || pluginCallError != NPERR_NO_ERROR) {
michael@0 433 return NS_ERROR_FAILURE;
michael@0 434 }
michael@0 435
michael@0 436 // NP_Initialize must be called after NP_GetEntryPoints on Windows.
michael@0 437 rv = pluginLib->NP_Initialize(&sBrowserFuncs, &pluginCallError);
michael@0 438 if (rv != NS_OK || pluginCallError != NPERR_NO_ERROR) {
michael@0 439 return NS_ERROR_FAILURE;
michael@0 440 }
michael@0 441 #elif defined(XP_MACOSX)
michael@0 442 // NP_Initialize must be called before NP_GetEntryPoints on Mac OS X.
michael@0 443 // We need to match WebKit's behavior.
michael@0 444 rv = pluginLib->NP_Initialize(&sBrowserFuncs, &pluginCallError);
michael@0 445 if (rv != NS_OK || pluginCallError != NPERR_NO_ERROR) {
michael@0 446 return NS_ERROR_FAILURE;
michael@0 447 }
michael@0 448
michael@0 449 rv = pluginLib->NP_GetEntryPoints(&plugin->mPluginFuncs, &pluginCallError);
michael@0 450 if (rv != NS_OK || pluginCallError != NPERR_NO_ERROR) {
michael@0 451 return NS_ERROR_FAILURE;
michael@0 452 }
michael@0 453 #elif defined(MOZ_WIDGET_GONK)
michael@0 454 #else
michael@0 455 rv = pluginLib->NP_Initialize(&sBrowserFuncs, &plugin->mPluginFuncs, &pluginCallError);
michael@0 456 if (rv != NS_OK || pluginCallError != NPERR_NO_ERROR) {
michael@0 457 return NS_ERROR_FAILURE;
michael@0 458 }
michael@0 459 #endif
michael@0 460
michael@0 461 plugin.forget(aResult);
michael@0 462 return NS_OK;
michael@0 463 }
michael@0 464
michael@0 465 PluginLibrary*
michael@0 466 nsNPAPIPlugin::GetLibrary()
michael@0 467 {
michael@0 468 return mLibrary;
michael@0 469 }
michael@0 470
michael@0 471 NPPluginFuncs*
michael@0 472 nsNPAPIPlugin::PluginFuncs()
michael@0 473 {
michael@0 474 return &mPluginFuncs;
michael@0 475 }
michael@0 476
michael@0 477 nsresult
michael@0 478 nsNPAPIPlugin::Shutdown()
michael@0 479 {
michael@0 480 NPP_PLUGIN_LOG(PLUGIN_LOG_BASIC,
michael@0 481 ("NPP Shutdown to be called: this=%p\n", this));
michael@0 482
michael@0 483 NPError shutdownError;
michael@0 484 mLibrary->NP_Shutdown(&shutdownError);
michael@0 485
michael@0 486 return NS_OK;
michael@0 487 }
michael@0 488
michael@0 489 nsresult
michael@0 490 nsNPAPIPlugin::RetainStream(NPStream *pstream, nsISupports **aRetainedPeer)
michael@0 491 {
michael@0 492 if (!aRetainedPeer)
michael@0 493 return NS_ERROR_NULL_POINTER;
michael@0 494
michael@0 495 *aRetainedPeer = nullptr;
michael@0 496
michael@0 497 if (!pstream || !pstream->ndata)
michael@0 498 return NS_ERROR_NULL_POINTER;
michael@0 499
michael@0 500 nsNPAPIStreamWrapper* streamWrapper = static_cast<nsNPAPIStreamWrapper*>(pstream->ndata);
michael@0 501 nsNPAPIPluginStreamListener* listener = streamWrapper->GetStreamListener();
michael@0 502 if (!listener) {
michael@0 503 return NS_ERROR_NULL_POINTER;
michael@0 504 }
michael@0 505
michael@0 506 nsIStreamListener* streamListener = listener->GetStreamListenerPeer();
michael@0 507 if (!streamListener) {
michael@0 508 return NS_ERROR_NULL_POINTER;
michael@0 509 }
michael@0 510
michael@0 511 *aRetainedPeer = streamListener;
michael@0 512 NS_ADDREF(*aRetainedPeer);
michael@0 513 return NS_OK;
michael@0 514 }
michael@0 515
michael@0 516 // Create a new NPP GET or POST (given in the type argument) url
michael@0 517 // stream that may have a notify callback
michael@0 518 NPError
michael@0 519 MakeNewNPAPIStreamInternal(NPP npp, const char *relativeURL, const char *target,
michael@0 520 eNPPStreamTypeInternal type,
michael@0 521 bool bDoNotify = false,
michael@0 522 void *notifyData = nullptr, uint32_t len = 0,
michael@0 523 const char *buf = nullptr, NPBool file = false)
michael@0 524 {
michael@0 525 if (!npp)
michael@0 526 return NPERR_INVALID_INSTANCE_ERROR;
michael@0 527
michael@0 528 PluginDestructionGuard guard(npp);
michael@0 529
michael@0 530 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *) npp->ndata;
michael@0 531 if (!inst || !inst->IsRunning())
michael@0 532 return NPERR_INVALID_INSTANCE_ERROR;
michael@0 533
michael@0 534 nsCOMPtr<nsIPluginHost> pluginHostCOM = do_GetService(MOZ_PLUGIN_HOST_CONTRACTID);
michael@0 535 nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
michael@0 536 if (!pluginHost) {
michael@0 537 return NPERR_GENERIC_ERROR;
michael@0 538 }
michael@0 539
michael@0 540 nsRefPtr<nsNPAPIPluginStreamListener> listener;
michael@0 541 // Set aCallNotify here to false. If pluginHost->GetURL or PostURL fail,
michael@0 542 // the listener's destructor will do the notification while we are about to
michael@0 543 // return a failure code.
michael@0 544 // Call SetCallNotify(true) below after we are sure we cannot return a failure
michael@0 545 // code.
michael@0 546 if (!target) {
michael@0 547 inst->NewStreamListener(relativeURL, notifyData,
michael@0 548 getter_AddRefs(listener));
michael@0 549 if (listener) {
michael@0 550 listener->SetCallNotify(false);
michael@0 551 }
michael@0 552 }
michael@0 553
michael@0 554 switch (type) {
michael@0 555 case eNPPStreamTypeInternal_Get:
michael@0 556 {
michael@0 557 if (NS_FAILED(pluginHost->GetURL(inst, relativeURL, target, listener,
michael@0 558 nullptr, nullptr, false)))
michael@0 559 return NPERR_GENERIC_ERROR;
michael@0 560 break;
michael@0 561 }
michael@0 562 case eNPPStreamTypeInternal_Post:
michael@0 563 {
michael@0 564 if (NS_FAILED(pluginHost->PostURL(inst, relativeURL, len, buf, file,
michael@0 565 target, listener, nullptr, nullptr,
michael@0 566 false, 0, nullptr)))
michael@0 567 return NPERR_GENERIC_ERROR;
michael@0 568 break;
michael@0 569 }
michael@0 570 default:
michael@0 571 NS_ERROR("how'd I get here");
michael@0 572 }
michael@0 573
michael@0 574 if (listener) {
michael@0 575 // SetCallNotify(bDoNotify) here, see comment above.
michael@0 576 listener->SetCallNotify(bDoNotify);
michael@0 577 }
michael@0 578
michael@0 579 return NPERR_NO_ERROR;
michael@0 580 }
michael@0 581
michael@0 582 #if defined(MOZ_MEMORY_WINDOWS)
michael@0 583 extern "C" size_t malloc_usable_size(const void *ptr);
michael@0 584 #endif
michael@0 585
michael@0 586 namespace {
michael@0 587
michael@0 588 static char *gNPPException;
michael@0 589
michael@0 590 class nsPluginThreadRunnable : public nsRunnable,
michael@0 591 public PRCList
michael@0 592 {
michael@0 593 public:
michael@0 594 nsPluginThreadRunnable(NPP instance, PluginThreadCallback func,
michael@0 595 void *userData);
michael@0 596 virtual ~nsPluginThreadRunnable();
michael@0 597
michael@0 598 NS_IMETHOD Run();
michael@0 599
michael@0 600 bool IsForInstance(NPP instance)
michael@0 601 {
michael@0 602 return (mInstance == instance);
michael@0 603 }
michael@0 604
michael@0 605 void Invalidate()
michael@0 606 {
michael@0 607 mFunc = nullptr;
michael@0 608 }
michael@0 609
michael@0 610 bool IsValid()
michael@0 611 {
michael@0 612 return (mFunc != nullptr);
michael@0 613 }
michael@0 614
michael@0 615 private:
michael@0 616 NPP mInstance;
michael@0 617 PluginThreadCallback mFunc;
michael@0 618 void *mUserData;
michael@0 619 };
michael@0 620
michael@0 621 static nsIDocument *
michael@0 622 GetDocumentFromNPP(NPP npp)
michael@0 623 {
michael@0 624 NS_ENSURE_TRUE(npp, nullptr);
michael@0 625
michael@0 626 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)npp->ndata;
michael@0 627 NS_ENSURE_TRUE(inst, nullptr);
michael@0 628
michael@0 629 PluginDestructionGuard guard(inst);
michael@0 630
michael@0 631 nsRefPtr<nsPluginInstanceOwner> owner = inst->GetOwner();
michael@0 632 NS_ENSURE_TRUE(owner, nullptr);
michael@0 633
michael@0 634 nsCOMPtr<nsIDocument> doc;
michael@0 635 owner->GetDocument(getter_AddRefs(doc));
michael@0 636
michael@0 637 return doc;
michael@0 638 }
michael@0 639
michael@0 640 static JSContext *
michael@0 641 GetJSContextFromDoc(nsIDocument *doc)
michael@0 642 {
michael@0 643 nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(doc->GetWindow());
michael@0 644 NS_ENSURE_TRUE(sgo, nullptr);
michael@0 645
michael@0 646 nsIScriptContext *scx = sgo->GetContext();
michael@0 647 NS_ENSURE_TRUE(scx, nullptr);
michael@0 648
michael@0 649 return scx->GetNativeContext();
michael@0 650 }
michael@0 651
michael@0 652 static JSContext *
michael@0 653 GetJSContextFromNPP(NPP npp)
michael@0 654 {
michael@0 655 nsIDocument *doc = GetDocumentFromNPP(npp);
michael@0 656 NS_ENSURE_TRUE(doc, nullptr);
michael@0 657
michael@0 658 return GetJSContextFromDoc(doc);
michael@0 659 }
michael@0 660
michael@0 661 static already_AddRefed<nsIChannel>
michael@0 662 GetChannelFromNPP(NPP npp)
michael@0 663 {
michael@0 664 nsCOMPtr<nsIDocument> doc = GetDocumentFromNPP(npp);
michael@0 665 if (!doc)
michael@0 666 return nullptr;
michael@0 667 nsCOMPtr<nsPIDOMWindow> domwindow = doc->GetWindow();
michael@0 668 nsCOMPtr<nsIChannel> channel;
michael@0 669 if (domwindow) {
michael@0 670 nsCOMPtr<nsIDocShell> docShell = domwindow->GetDocShell();
michael@0 671 if (docShell) {
michael@0 672 docShell->GetCurrentDocumentChannel(getter_AddRefs(channel));
michael@0 673 }
michael@0 674 }
michael@0 675 return channel.forget();
michael@0 676 }
michael@0 677
michael@0 678 static NPIdentifier
michael@0 679 doGetIdentifier(JSContext *cx, const NPUTF8* name)
michael@0 680 {
michael@0 681 NS_ConvertUTF8toUTF16 utf16name(name);
michael@0 682
michael@0 683 JSString *str = ::JS_InternUCStringN(cx, utf16name.get(), utf16name.Length());
michael@0 684
michael@0 685 if (!str)
michael@0 686 return nullptr;
michael@0 687
michael@0 688 return StringToNPIdentifier(cx, str);
michael@0 689 }
michael@0 690
michael@0 691 #if defined(MOZ_MEMORY_WINDOWS)
michael@0 692 BOOL
michael@0 693 InHeap(HANDLE hHeap, LPVOID lpMem)
michael@0 694 {
michael@0 695 BOOL success = FALSE;
michael@0 696 PROCESS_HEAP_ENTRY he;
michael@0 697 he.lpData = nullptr;
michael@0 698 while (HeapWalk(hHeap, &he) != 0) {
michael@0 699 if (he.lpData == lpMem) {
michael@0 700 success = TRUE;
michael@0 701 break;
michael@0 702 }
michael@0 703 }
michael@0 704 HeapUnlock(hHeap);
michael@0 705 return success;
michael@0 706 }
michael@0 707 #endif
michael@0 708
michael@0 709 } /* anonymous namespace */
michael@0 710
michael@0 711 NPPExceptionAutoHolder::NPPExceptionAutoHolder()
michael@0 712 : mOldException(gNPPException)
michael@0 713 {
michael@0 714 gNPPException = nullptr;
michael@0 715 }
michael@0 716
michael@0 717 NPPExceptionAutoHolder::~NPPExceptionAutoHolder()
michael@0 718 {
michael@0 719 NS_ASSERTION(!gNPPException, "NPP exception not properly cleared!");
michael@0 720
michael@0 721 gNPPException = mOldException;
michael@0 722 }
michael@0 723
michael@0 724 nsPluginThreadRunnable::nsPluginThreadRunnable(NPP instance,
michael@0 725 PluginThreadCallback func,
michael@0 726 void *userData)
michael@0 727 : mInstance(instance), mFunc(func), mUserData(userData)
michael@0 728 {
michael@0 729 if (!sPluginThreadAsyncCallLock) {
michael@0 730 // Failed to create lock, not much we can do here then...
michael@0 731 mFunc = nullptr;
michael@0 732
michael@0 733 return;
michael@0 734 }
michael@0 735
michael@0 736 PR_INIT_CLIST(this);
michael@0 737
michael@0 738 {
michael@0 739 MutexAutoLock lock(*sPluginThreadAsyncCallLock);
michael@0 740
michael@0 741 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
michael@0 742 if (!inst || !inst->IsRunning()) {
michael@0 743 // The plugin was stopped, ignore this async call.
michael@0 744 mFunc = nullptr;
michael@0 745
michael@0 746 return;
michael@0 747 }
michael@0 748
michael@0 749 PR_APPEND_LINK(this, &sPendingAsyncCalls);
michael@0 750 }
michael@0 751 }
michael@0 752
michael@0 753 nsPluginThreadRunnable::~nsPluginThreadRunnable()
michael@0 754 {
michael@0 755 if (!sPluginThreadAsyncCallLock) {
michael@0 756 return;
michael@0 757 }
michael@0 758
michael@0 759 {
michael@0 760 MutexAutoLock lock(*sPluginThreadAsyncCallLock);
michael@0 761
michael@0 762 PR_REMOVE_LINK(this);
michael@0 763 }
michael@0 764 }
michael@0 765
michael@0 766 NS_IMETHODIMP
michael@0 767 nsPluginThreadRunnable::Run()
michael@0 768 {
michael@0 769 if (mFunc) {
michael@0 770 PluginDestructionGuard guard(mInstance);
michael@0 771
michael@0 772 NS_TRY_SAFE_CALL_VOID(mFunc(mUserData), nullptr,
michael@0 773 NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO);
michael@0 774 }
michael@0 775
michael@0 776 return NS_OK;
michael@0 777 }
michael@0 778
michael@0 779 void
michael@0 780 OnPluginDestroy(NPP instance)
michael@0 781 {
michael@0 782 if (!sPluginThreadAsyncCallLock) {
michael@0 783 return;
michael@0 784 }
michael@0 785
michael@0 786 {
michael@0 787 MutexAutoLock lock(*sPluginThreadAsyncCallLock);
michael@0 788
michael@0 789 if (PR_CLIST_IS_EMPTY(&sPendingAsyncCalls)) {
michael@0 790 return;
michael@0 791 }
michael@0 792
michael@0 793 nsPluginThreadRunnable *r =
michael@0 794 (nsPluginThreadRunnable *)PR_LIST_HEAD(&sPendingAsyncCalls);
michael@0 795
michael@0 796 do {
michael@0 797 if (r->IsForInstance(instance)) {
michael@0 798 r->Invalidate();
michael@0 799 }
michael@0 800
michael@0 801 r = (nsPluginThreadRunnable *)PR_NEXT_LINK(r);
michael@0 802 } while (r != &sPendingAsyncCalls);
michael@0 803 }
michael@0 804 }
michael@0 805
michael@0 806 void
michael@0 807 OnShutdown()
michael@0 808 {
michael@0 809 NS_ASSERTION(PR_CLIST_IS_EMPTY(&sPendingAsyncCalls),
michael@0 810 "Pending async plugin call list not cleaned up!");
michael@0 811
michael@0 812 if (sPluginThreadAsyncCallLock) {
michael@0 813 delete sPluginThreadAsyncCallLock;
michael@0 814
michael@0 815 sPluginThreadAsyncCallLock = nullptr;
michael@0 816 }
michael@0 817 }
michael@0 818
michael@0 819 AsyncCallbackAutoLock::AsyncCallbackAutoLock()
michael@0 820 {
michael@0 821 if (sPluginThreadAsyncCallLock) {
michael@0 822 sPluginThreadAsyncCallLock->Lock();
michael@0 823 }
michael@0 824 }
michael@0 825
michael@0 826 AsyncCallbackAutoLock::~AsyncCallbackAutoLock()
michael@0 827 {
michael@0 828 if (sPluginThreadAsyncCallLock) {
michael@0 829 sPluginThreadAsyncCallLock->Unlock();
michael@0 830 }
michael@0 831 }
michael@0 832
michael@0 833
michael@0 834 NPP NPPStack::sCurrentNPP = nullptr;
michael@0 835
michael@0 836 const char *
michael@0 837 PeekException()
michael@0 838 {
michael@0 839 return gNPPException;
michael@0 840 }
michael@0 841
michael@0 842 void
michael@0 843 PopException()
michael@0 844 {
michael@0 845 NS_ASSERTION(gNPPException, "Uh, no NPP exception to pop!");
michael@0 846
michael@0 847 if (gNPPException) {
michael@0 848 free(gNPPException);
michael@0 849
michael@0 850 gNPPException = nullptr;
michael@0 851 }
michael@0 852 }
michael@0 853
michael@0 854 //
michael@0 855 // Static callbacks that get routed back through the new C++ API
michael@0 856 //
michael@0 857
michael@0 858 namespace mozilla {
michael@0 859 namespace plugins {
michael@0 860 namespace parent {
michael@0 861
michael@0 862 NPError
michael@0 863 _geturl(NPP npp, const char* relativeURL, const char* target)
michael@0 864 {
michael@0 865 if (!NS_IsMainThread()) {
michael@0 866 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_geturl called from the wrong thread\n"));
michael@0 867 return NPERR_INVALID_PARAM;
michael@0 868 }
michael@0 869
michael@0 870 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
michael@0 871 ("NPN_GetURL: npp=%p, target=%s, url=%s\n", (void *)npp, target,
michael@0 872 relativeURL));
michael@0 873
michael@0 874 PluginDestructionGuard guard(npp);
michael@0 875
michael@0 876 // Block Adobe Acrobat from loading URLs that are not http:, https:,
michael@0 877 // or ftp: URLs if the given target is null.
michael@0 878 if (!target && relativeURL &&
michael@0 879 (strncmp(relativeURL, "http:", 5) != 0) &&
michael@0 880 (strncmp(relativeURL, "https:", 6) != 0) &&
michael@0 881 (strncmp(relativeURL, "ftp:", 4) != 0)) {
michael@0 882 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *) npp->ndata;
michael@0 883
michael@0 884
michael@0 885 const char *name = nullptr;
michael@0 886 nsRefPtr<nsPluginHost> host = nsPluginHost::GetInst();
michael@0 887 host->GetPluginName(inst, &name);
michael@0 888
michael@0 889 if (name && strstr(name, "Adobe") && strstr(name, "Acrobat")) {
michael@0 890 return NPERR_NO_ERROR;
michael@0 891 }
michael@0 892 }
michael@0 893
michael@0 894 return MakeNewNPAPIStreamInternal(npp, relativeURL, target,
michael@0 895 eNPPStreamTypeInternal_Get);
michael@0 896 }
michael@0 897
michael@0 898 NPError
michael@0 899 _geturlnotify(NPP npp, const char* relativeURL, const char* target,
michael@0 900 void* notifyData)
michael@0 901 {
michael@0 902 if (!NS_IsMainThread()) {
michael@0 903 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_geturlnotify called from the wrong thread\n"));
michael@0 904 return NPERR_INVALID_PARAM;
michael@0 905 }
michael@0 906
michael@0 907 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
michael@0 908 ("NPN_GetURLNotify: npp=%p, target=%s, notify=%p, url=%s\n", (void*)npp,
michael@0 909 target, notifyData, relativeURL));
michael@0 910
michael@0 911 PluginDestructionGuard guard(npp);
michael@0 912
michael@0 913 return MakeNewNPAPIStreamInternal(npp, relativeURL, target,
michael@0 914 eNPPStreamTypeInternal_Get, true,
michael@0 915 notifyData);
michael@0 916 }
michael@0 917
michael@0 918 NPError
michael@0 919 _posturlnotify(NPP npp, const char *relativeURL, const char *target,
michael@0 920 uint32_t len, const char *buf, NPBool file, void *notifyData)
michael@0 921 {
michael@0 922 if (!NS_IsMainThread()) {
michael@0 923 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_posturlnotify called from the wrong thread\n"));
michael@0 924 return NPERR_INVALID_PARAM;
michael@0 925 }
michael@0 926 if (!buf)
michael@0 927 return NPERR_INVALID_PARAM;
michael@0 928
michael@0 929 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
michael@0 930 ("NPN_PostURLNotify: npp=%p, target=%s, len=%d, file=%d, "
michael@0 931 "notify=%p, url=%s, buf=%s\n",
michael@0 932 (void*)npp, target, len, file, notifyData, relativeURL,
michael@0 933 buf));
michael@0 934
michael@0 935 PluginDestructionGuard guard(npp);
michael@0 936
michael@0 937 return MakeNewNPAPIStreamInternal(npp, relativeURL, target,
michael@0 938 eNPPStreamTypeInternal_Post, true,
michael@0 939 notifyData, len, buf, file);
michael@0 940 }
michael@0 941
michael@0 942 NPError
michael@0 943 _posturl(NPP npp, const char *relativeURL, const char *target,
michael@0 944 uint32_t len, const char *buf, NPBool file)
michael@0 945 {
michael@0 946 if (!NS_IsMainThread()) {
michael@0 947 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_posturl called from the wrong thread\n"));
michael@0 948 return NPERR_INVALID_PARAM;
michael@0 949 }
michael@0 950 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
michael@0 951 ("NPN_PostURL: npp=%p, target=%s, file=%d, len=%d, url=%s, "
michael@0 952 "buf=%s\n",
michael@0 953 (void*)npp, target, file, len, relativeURL, buf));
michael@0 954
michael@0 955 PluginDestructionGuard guard(npp);
michael@0 956
michael@0 957 return MakeNewNPAPIStreamInternal(npp, relativeURL, target,
michael@0 958 eNPPStreamTypeInternal_Post, false, nullptr,
michael@0 959 len, buf, file);
michael@0 960 }
michael@0 961
michael@0 962 NPError
michael@0 963 _newstream(NPP npp, NPMIMEType type, const char* target, NPStream* *result)
michael@0 964 {
michael@0 965 if (!NS_IsMainThread()) {
michael@0 966 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_newstream called from the wrong thread\n"));
michael@0 967 return NPERR_INVALID_PARAM;
michael@0 968 }
michael@0 969 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
michael@0 970 ("NPN_NewStream: npp=%p, type=%s, target=%s\n", (void*)npp,
michael@0 971 (const char *)type, target));
michael@0 972
michael@0 973 NPError err = NPERR_INVALID_INSTANCE_ERROR;
michael@0 974 if (npp && npp->ndata) {
michael@0 975 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance*)npp->ndata;
michael@0 976
michael@0 977 PluginDestructionGuard guard(inst);
michael@0 978
michael@0 979 nsCOMPtr<nsIOutputStream> stream;
michael@0 980 if (NS_SUCCEEDED(inst->NewStreamFromPlugin((const char*) type, target,
michael@0 981 getter_AddRefs(stream)))) {
michael@0 982 nsNPAPIStreamWrapper* wrapper = new nsNPAPIStreamWrapper(stream, nullptr);
michael@0 983 if (wrapper) {
michael@0 984 (*result) = &wrapper->mNPStream;
michael@0 985 err = NPERR_NO_ERROR;
michael@0 986 } else {
michael@0 987 err = NPERR_OUT_OF_MEMORY_ERROR;
michael@0 988 }
michael@0 989 } else {
michael@0 990 err = NPERR_GENERIC_ERROR;
michael@0 991 }
michael@0 992 }
michael@0 993 return err;
michael@0 994 }
michael@0 995
michael@0 996 int32_t
michael@0 997 _write(NPP npp, NPStream *pstream, int32_t len, void *buffer)
michael@0 998 {
michael@0 999 if (!NS_IsMainThread()) {
michael@0 1000 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_write called from the wrong thread\n"));
michael@0 1001 return 0;
michael@0 1002 }
michael@0 1003 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
michael@0 1004 ("NPN_Write: npp=%p, url=%s, len=%d, buffer=%s\n", (void*)npp,
michael@0 1005 pstream->url, len, (char*)buffer));
michael@0 1006
michael@0 1007 // negative return indicates failure to the plugin
michael@0 1008 if (!npp)
michael@0 1009 return -1;
michael@0 1010
michael@0 1011 PluginDestructionGuard guard(npp);
michael@0 1012
michael@0 1013 nsNPAPIStreamWrapper* wrapper = static_cast<nsNPAPIStreamWrapper*>(pstream->ndata);
michael@0 1014 if (!wrapper) {
michael@0 1015 return -1;
michael@0 1016 }
michael@0 1017
michael@0 1018 nsIOutputStream* stream = wrapper->GetOutputStream();
michael@0 1019 if (!stream) {
michael@0 1020 return -1;
michael@0 1021 }
michael@0 1022
michael@0 1023 uint32_t count = 0;
michael@0 1024 nsresult rv = stream->Write((char *)buffer, len, &count);
michael@0 1025
michael@0 1026 if (NS_FAILED(rv)) {
michael@0 1027 return -1;
michael@0 1028 }
michael@0 1029
michael@0 1030 return (int32_t)count;
michael@0 1031 }
michael@0 1032
michael@0 1033 NPError
michael@0 1034 _destroystream(NPP npp, NPStream *pstream, NPError reason)
michael@0 1035 {
michael@0 1036 if (!NS_IsMainThread()) {
michael@0 1037 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_write called from the wrong thread\n"));
michael@0 1038 return NPERR_INVALID_PARAM;
michael@0 1039 }
michael@0 1040 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
michael@0 1041 ("NPN_DestroyStream: npp=%p, url=%s, reason=%d\n", (void*)npp,
michael@0 1042 pstream->url, (int)reason));
michael@0 1043
michael@0 1044 if (!npp)
michael@0 1045 return NPERR_INVALID_INSTANCE_ERROR;
michael@0 1046
michael@0 1047 PluginDestructionGuard guard(npp);
michael@0 1048
michael@0 1049 nsNPAPIStreamWrapper *streamWrapper = static_cast<nsNPAPIStreamWrapper*>(pstream->ndata);
michael@0 1050 if (!streamWrapper) {
michael@0 1051 return NPERR_INVALID_PARAM;
michael@0 1052 }
michael@0 1053
michael@0 1054 nsNPAPIPluginStreamListener *listener = streamWrapper->GetStreamListener();
michael@0 1055 if (listener) {
michael@0 1056 // This type of stream is going from the browser to the plugin. It's either the
michael@0 1057 // initial src/data stream or another stream resulting from NPN_GetURL* or
michael@0 1058 // NPN_PostURL*.
michael@0 1059 //
michael@0 1060 // Calling OnStopBinding on the listener may cause it to be deleted due to the
michael@0 1061 // releasing of its last references.
michael@0 1062 listener->OnStopBinding(nullptr, NS_BINDING_ABORTED);
michael@0 1063 } else {
michael@0 1064 // This type of stream (NPStream) was created via NPN_NewStream. The plugin holds
michael@0 1065 // the reference until it is to be deleted here. Deleting the wrapper will
michael@0 1066 // release the wrapped nsIOutputStream.
michael@0 1067 //
michael@0 1068 // The NPStream the plugin references should always be a sub-object of it's own
michael@0 1069 // 'ndata', which is our nsNPAPIStramWrapper. See bug 548441.
michael@0 1070 NS_ASSERTION((char*)streamWrapper <= (char*)pstream &&
michael@0 1071 ((char*)pstream) + sizeof(*pstream)
michael@0 1072 <= ((char*)streamWrapper) + sizeof(*streamWrapper),
michael@0 1073 "pstream is not a subobject of wrapper");
michael@0 1074 delete streamWrapper;
michael@0 1075 }
michael@0 1076
michael@0 1077 // 'listener' and/or 'streamWrapper' may be invalid (deleted) at this point. Don't
michael@0 1078 // touch them again!
michael@0 1079
michael@0 1080 return NPERR_NO_ERROR;
michael@0 1081 }
michael@0 1082
michael@0 1083 void
michael@0 1084 _status(NPP npp, const char *message)
michael@0 1085 {
michael@0 1086 if (!NS_IsMainThread()) {
michael@0 1087 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_status called from the wrong thread\n"));
michael@0 1088 return;
michael@0 1089 }
michael@0 1090 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_Status: npp=%p, message=%s\n",
michael@0 1091 (void*)npp, message));
michael@0 1092
michael@0 1093 if (!npp || !npp->ndata) {
michael@0 1094 NS_WARNING("_status: npp or npp->ndata == 0");
michael@0 1095 return;
michael@0 1096 }
michael@0 1097
michael@0 1098 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance*)npp->ndata;
michael@0 1099
michael@0 1100 PluginDestructionGuard guard(inst);
michael@0 1101
michael@0 1102 inst->ShowStatus(message);
michael@0 1103 }
michael@0 1104
michael@0 1105 void
michael@0 1106 _memfree (void *ptr)
michael@0 1107 {
michael@0 1108 if (!NS_IsMainThread()) {
michael@0 1109 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_memfree called from the wrong thread\n"));
michael@0 1110 }
michael@0 1111 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY, ("NPN_MemFree: ptr=%p\n", ptr));
michael@0 1112
michael@0 1113 if (ptr)
michael@0 1114 nsMemory::Free(ptr);
michael@0 1115 }
michael@0 1116
michael@0 1117 uint32_t
michael@0 1118 _memflush(uint32_t size)
michael@0 1119 {
michael@0 1120 if (!NS_IsMainThread()) {
michael@0 1121 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_memflush called from the wrong thread\n"));
michael@0 1122 }
michael@0 1123 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY, ("NPN_MemFlush: size=%d\n", size));
michael@0 1124
michael@0 1125 nsMemory::HeapMinimize(true);
michael@0 1126 return 0;
michael@0 1127 }
michael@0 1128
michael@0 1129 void
michael@0 1130 _reloadplugins(NPBool reloadPages)
michael@0 1131 {
michael@0 1132 if (!NS_IsMainThread()) {
michael@0 1133 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_reloadplugins called from the wrong thread\n"));
michael@0 1134 return;
michael@0 1135 }
michael@0 1136 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
michael@0 1137 ("NPN_ReloadPlugins: reloadPages=%d\n", reloadPages));
michael@0 1138
michael@0 1139 nsCOMPtr<nsIPluginHost> pluginHost(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
michael@0 1140 if (!pluginHost)
michael@0 1141 return;
michael@0 1142
michael@0 1143 pluginHost->ReloadPlugins();
michael@0 1144 }
michael@0 1145
michael@0 1146 void
michael@0 1147 _invalidaterect(NPP npp, NPRect *invalidRect)
michael@0 1148 {
michael@0 1149 if (!NS_IsMainThread()) {
michael@0 1150 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_invalidaterect called from the wrong thread\n"));
michael@0 1151 return;
michael@0 1152 }
michael@0 1153 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
michael@0 1154 ("NPN_InvalidateRect: npp=%p, top=%d, left=%d, bottom=%d, "
michael@0 1155 "right=%d\n", (void *)npp, invalidRect->top,
michael@0 1156 invalidRect->left, invalidRect->bottom, invalidRect->right));
michael@0 1157
michael@0 1158 if (!npp || !npp->ndata) {
michael@0 1159 NS_WARNING("_invalidaterect: npp or npp->ndata == 0");
michael@0 1160 return;
michael@0 1161 }
michael@0 1162
michael@0 1163 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance*)npp->ndata;
michael@0 1164
michael@0 1165 PluginDestructionGuard guard(inst);
michael@0 1166
michael@0 1167 inst->InvalidateRect((NPRect *)invalidRect);
michael@0 1168 }
michael@0 1169
michael@0 1170 void
michael@0 1171 _invalidateregion(NPP npp, NPRegion invalidRegion)
michael@0 1172 {
michael@0 1173 if (!NS_IsMainThread()) {
michael@0 1174 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_invalidateregion called from the wrong thread\n"));
michael@0 1175 return;
michael@0 1176 }
michael@0 1177 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
michael@0 1178 ("NPN_InvalidateRegion: npp=%p, region=%p\n", (void*)npp,
michael@0 1179 (void*)invalidRegion));
michael@0 1180
michael@0 1181 if (!npp || !npp->ndata) {
michael@0 1182 NS_WARNING("_invalidateregion: npp or npp->ndata == 0");
michael@0 1183 return;
michael@0 1184 }
michael@0 1185
michael@0 1186 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance*)npp->ndata;
michael@0 1187
michael@0 1188 PluginDestructionGuard guard(inst);
michael@0 1189
michael@0 1190 inst->InvalidateRegion((NPRegion)invalidRegion);
michael@0 1191 }
michael@0 1192
michael@0 1193 void
michael@0 1194 _forceredraw(NPP npp)
michael@0 1195 {
michael@0 1196 }
michael@0 1197
michael@0 1198 NPObject*
michael@0 1199 _getwindowobject(NPP npp)
michael@0 1200 {
michael@0 1201 if (!NS_IsMainThread()) {
michael@0 1202 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_getwindowobject called from the wrong thread\n"));
michael@0 1203 return nullptr;
michael@0 1204 }
michael@0 1205
michael@0 1206 // The window want to return here is the outer window, *not* the inner (since
michael@0 1207 // we don't know what the plugin will do with it).
michael@0 1208 nsIDocument* doc = GetDocumentFromNPP(npp);
michael@0 1209 NS_ENSURE_TRUE(doc, nullptr);
michael@0 1210 nsCOMPtr<nsPIDOMWindow> outer = do_QueryInterface(doc->GetWindow());
michael@0 1211 NS_ENSURE_TRUE(outer, nullptr);
michael@0 1212
michael@0 1213 AutoJSContext cx;
michael@0 1214 JS::Rooted<JSObject*> global(cx, static_cast<nsGlobalWindow*>(outer.get())->GetGlobalJSObject());
michael@0 1215 return nsJSObjWrapper::GetNewOrUsed(npp, cx, global);
michael@0 1216 }
michael@0 1217
michael@0 1218 NPObject*
michael@0 1219 _getpluginelement(NPP npp)
michael@0 1220 {
michael@0 1221 if (!NS_IsMainThread()) {
michael@0 1222 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_getpluginelement called from the wrong thread\n"));
michael@0 1223 return nullptr;
michael@0 1224 }
michael@0 1225
michael@0 1226 nsNPAPIPluginInstance* inst = static_cast<nsNPAPIPluginInstance*>(npp->ndata);
michael@0 1227 if (!inst)
michael@0 1228 return nullptr;
michael@0 1229
michael@0 1230 nsCOMPtr<nsIDOMElement> element;
michael@0 1231 inst->GetDOMElement(getter_AddRefs(element));
michael@0 1232
michael@0 1233 if (!element)
michael@0 1234 return nullptr;
michael@0 1235
michael@0 1236 AutoPushJSContext cx(GetJSContextFromNPP(npp));
michael@0 1237 NS_ENSURE_TRUE(cx, nullptr);
michael@0 1238 JSAutoRequest ar(cx); // Unnecessary once bug 868130 lands.
michael@0 1239
michael@0 1240 nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID()));
michael@0 1241 NS_ENSURE_TRUE(xpc, nullptr);
michael@0 1242
michael@0 1243 nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
michael@0 1244 xpc->WrapNative(cx, ::JS::CurrentGlobalOrNull(cx), element,
michael@0 1245 NS_GET_IID(nsIDOMElement),
michael@0 1246 getter_AddRefs(holder));
michael@0 1247 NS_ENSURE_TRUE(holder, nullptr);
michael@0 1248
michael@0 1249 JS::Rooted<JSObject*> obj(cx, holder->GetJSObject());
michael@0 1250 NS_ENSURE_TRUE(obj, nullptr);
michael@0 1251
michael@0 1252 return nsJSObjWrapper::GetNewOrUsed(npp, cx, obj);
michael@0 1253 }
michael@0 1254
michael@0 1255 NPIdentifier
michael@0 1256 _getstringidentifier(const NPUTF8* name)
michael@0 1257 {
michael@0 1258 if (!name) {
michael@0 1259 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS, ("NPN_getstringidentifier: passed null name"));
michael@0 1260 return nullptr;
michael@0 1261 }
michael@0 1262 if (!NS_IsMainThread()) {
michael@0 1263 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_getstringidentifier called from the wrong thread\n"));
michael@0 1264 }
michael@0 1265
michael@0 1266 AutoSafeJSContext cx;
michael@0 1267 return doGetIdentifier(cx, name);
michael@0 1268 }
michael@0 1269
michael@0 1270 void
michael@0 1271 _getstringidentifiers(const NPUTF8** names, int32_t nameCount,
michael@0 1272 NPIdentifier *identifiers)
michael@0 1273 {
michael@0 1274 if (!NS_IsMainThread()) {
michael@0 1275 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_getstringidentifiers called from the wrong thread\n"));
michael@0 1276 }
michael@0 1277
michael@0 1278 AutoSafeJSContext cx;
michael@0 1279
michael@0 1280 for (int32_t i = 0; i < nameCount; ++i) {
michael@0 1281 if (names[i]) {
michael@0 1282 identifiers[i] = doGetIdentifier(cx, names[i]);
michael@0 1283 } else {
michael@0 1284 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS, ("NPN_getstringidentifiers: passed null name"));
michael@0 1285 identifiers[i] = nullptr;
michael@0 1286 }
michael@0 1287 }
michael@0 1288 }
michael@0 1289
michael@0 1290 NPIdentifier
michael@0 1291 _getintidentifier(int32_t intid)
michael@0 1292 {
michael@0 1293 if (!NS_IsMainThread()) {
michael@0 1294 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_getstringidentifier called from the wrong thread\n"));
michael@0 1295 }
michael@0 1296 return IntToNPIdentifier(intid);
michael@0 1297 }
michael@0 1298
michael@0 1299 NPUTF8*
michael@0 1300 _utf8fromidentifier(NPIdentifier id)
michael@0 1301 {
michael@0 1302 if (!NS_IsMainThread()) {
michael@0 1303 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_utf8fromidentifier called from the wrong thread\n"));
michael@0 1304 }
michael@0 1305 if (!id)
michael@0 1306 return nullptr;
michael@0 1307
michael@0 1308 if (!NPIdentifierIsString(id)) {
michael@0 1309 return nullptr;
michael@0 1310 }
michael@0 1311
michael@0 1312 JSString *str = NPIdentifierToString(id);
michael@0 1313
michael@0 1314 return
michael@0 1315 ToNewUTF8String(nsDependentString(::JS_GetInternedStringChars(str),
michael@0 1316 ::JS_GetStringLength(str)));
michael@0 1317 }
michael@0 1318
michael@0 1319 int32_t
michael@0 1320 _intfromidentifier(NPIdentifier id)
michael@0 1321 {
michael@0 1322 if (!NS_IsMainThread()) {
michael@0 1323 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_intfromidentifier called from the wrong thread\n"));
michael@0 1324 }
michael@0 1325
michael@0 1326 if (!NPIdentifierIsInt(id)) {
michael@0 1327 return INT32_MIN;
michael@0 1328 }
michael@0 1329
michael@0 1330 return NPIdentifierToInt(id);
michael@0 1331 }
michael@0 1332
michael@0 1333 bool
michael@0 1334 _identifierisstring(NPIdentifier id)
michael@0 1335 {
michael@0 1336 if (!NS_IsMainThread()) {
michael@0 1337 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_identifierisstring called from the wrong thread\n"));
michael@0 1338 }
michael@0 1339
michael@0 1340 return NPIdentifierIsString(id);
michael@0 1341 }
michael@0 1342
michael@0 1343 NPObject*
michael@0 1344 _createobject(NPP npp, NPClass* aClass)
michael@0 1345 {
michael@0 1346 if (!NS_IsMainThread()) {
michael@0 1347 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_createobject called from the wrong thread\n"));
michael@0 1348 return nullptr;
michael@0 1349 }
michael@0 1350 if (!npp) {
michael@0 1351 NS_ERROR("Null npp passed to _createobject()!");
michael@0 1352
michael@0 1353 return nullptr;
michael@0 1354 }
michael@0 1355
michael@0 1356 PluginDestructionGuard guard(npp);
michael@0 1357
michael@0 1358 if (!aClass) {
michael@0 1359 NS_ERROR("Null class passed to _createobject()!");
michael@0 1360
michael@0 1361 return nullptr;
michael@0 1362 }
michael@0 1363
michael@0 1364 NPPAutoPusher nppPusher(npp);
michael@0 1365
michael@0 1366 NPObject *npobj;
michael@0 1367
michael@0 1368 if (aClass->allocate) {
michael@0 1369 npobj = aClass->allocate(npp, aClass);
michael@0 1370 } else {
michael@0 1371 npobj = (NPObject *)PR_Malloc(sizeof(NPObject));
michael@0 1372 }
michael@0 1373
michael@0 1374 if (npobj) {
michael@0 1375 npobj->_class = aClass;
michael@0 1376 npobj->referenceCount = 1;
michael@0 1377 NS_LOG_ADDREF(npobj, 1, "BrowserNPObject", sizeof(NPObject));
michael@0 1378 }
michael@0 1379
michael@0 1380 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
michael@0 1381 ("Created NPObject %p, NPClass %p\n", npobj, aClass));
michael@0 1382
michael@0 1383 return npobj;
michael@0 1384 }
michael@0 1385
michael@0 1386 NPObject*
michael@0 1387 _retainobject(NPObject* npobj)
michael@0 1388 {
michael@0 1389 if (!NS_IsMainThread()) {
michael@0 1390 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_retainobject called from the wrong thread\n"));
michael@0 1391 }
michael@0 1392 if (npobj) {
michael@0 1393 #ifdef NS_BUILD_REFCNT_LOGGING
michael@0 1394 int32_t refCnt =
michael@0 1395 #endif
michael@0 1396 PR_ATOMIC_INCREMENT((int32_t*)&npobj->referenceCount);
michael@0 1397 NS_LOG_ADDREF(npobj, refCnt, "BrowserNPObject", sizeof(NPObject));
michael@0 1398 }
michael@0 1399
michael@0 1400 return npobj;
michael@0 1401 }
michael@0 1402
michael@0 1403 void
michael@0 1404 _releaseobject(NPObject* npobj)
michael@0 1405 {
michael@0 1406 if (!NS_IsMainThread()) {
michael@0 1407 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_releaseobject called from the wrong thread\n"));
michael@0 1408 }
michael@0 1409 if (!npobj)
michael@0 1410 return;
michael@0 1411
michael@0 1412 int32_t refCnt = PR_ATOMIC_DECREMENT((int32_t*)&npobj->referenceCount);
michael@0 1413 NS_LOG_RELEASE(npobj, refCnt, "BrowserNPObject");
michael@0 1414
michael@0 1415 if (refCnt == 0) {
michael@0 1416 nsNPObjWrapper::OnDestroy(npobj);
michael@0 1417
michael@0 1418 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
michael@0 1419 ("Deleting NPObject %p, refcount hit 0\n", npobj));
michael@0 1420
michael@0 1421 if (npobj->_class && npobj->_class->deallocate) {
michael@0 1422 npobj->_class->deallocate(npobj);
michael@0 1423 } else {
michael@0 1424 PR_Free(npobj);
michael@0 1425 }
michael@0 1426 }
michael@0 1427 }
michael@0 1428
michael@0 1429 bool
michael@0 1430 _invoke(NPP npp, NPObject* npobj, NPIdentifier method, const NPVariant *args,
michael@0 1431 uint32_t argCount, NPVariant *result)
michael@0 1432 {
michael@0 1433 if (!NS_IsMainThread()) {
michael@0 1434 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_invoke called from the wrong thread\n"));
michael@0 1435 return false;
michael@0 1436 }
michael@0 1437 if (!npp || !npobj || !npobj->_class || !npobj->_class->invoke)
michael@0 1438 return false;
michael@0 1439
michael@0 1440 PluginDestructionGuard guard(npp);
michael@0 1441
michael@0 1442 NPPExceptionAutoHolder nppExceptionHolder;
michael@0 1443 NPPAutoPusher nppPusher(npp);
michael@0 1444
michael@0 1445 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
michael@0 1446 ("NPN_Invoke(npp %p, npobj %p, method %p, args %d\n", npp,
michael@0 1447 npobj, method, argCount));
michael@0 1448
michael@0 1449 return npobj->_class->invoke(npobj, method, args, argCount, result);
michael@0 1450 }
michael@0 1451
michael@0 1452 bool
michael@0 1453 _invokeDefault(NPP npp, NPObject* npobj, const NPVariant *args,
michael@0 1454 uint32_t argCount, NPVariant *result)
michael@0 1455 {
michael@0 1456 if (!NS_IsMainThread()) {
michael@0 1457 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_invokedefault called from the wrong thread\n"));
michael@0 1458 return false;
michael@0 1459 }
michael@0 1460 if (!npp || !npobj || !npobj->_class || !npobj->_class->invokeDefault)
michael@0 1461 return false;
michael@0 1462
michael@0 1463 NPPExceptionAutoHolder nppExceptionHolder;
michael@0 1464 NPPAutoPusher nppPusher(npp);
michael@0 1465
michael@0 1466 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
michael@0 1467 ("NPN_InvokeDefault(npp %p, npobj %p, args %d\n", npp,
michael@0 1468 npobj, argCount));
michael@0 1469
michael@0 1470 return npobj->_class->invokeDefault(npobj, args, argCount, result);
michael@0 1471 }
michael@0 1472
michael@0 1473 bool
michael@0 1474 _evaluate(NPP npp, NPObject* npobj, NPString *script, NPVariant *result)
michael@0 1475 {
michael@0 1476 if (!NS_IsMainThread()) {
michael@0 1477 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_evaluate called from the wrong thread\n"));
michael@0 1478 return false;
michael@0 1479 }
michael@0 1480 if (!npp)
michael@0 1481 return false;
michael@0 1482
michael@0 1483 NPPAutoPusher nppPusher(npp);
michael@0 1484
michael@0 1485 nsIDocument *doc = GetDocumentFromNPP(npp);
michael@0 1486 NS_ENSURE_TRUE(doc, false);
michael@0 1487
michael@0 1488 nsGlobalWindow* win = static_cast<nsGlobalWindow*>(doc->GetInnerWindow());
michael@0 1489 if (NS_WARN_IF(!win || !win->FastGetGlobalJSObject())) {
michael@0 1490 return false;
michael@0 1491 }
michael@0 1492
michael@0 1493 AutoSafeJSContext cx;
michael@0 1494 JSAutoCompartment ac(cx, win->FastGetGlobalJSObject());
michael@0 1495
michael@0 1496 JS::Rooted<JSObject*> obj(cx, nsNPObjWrapper::GetNewOrUsed(npp, cx, npobj));
michael@0 1497
michael@0 1498 if (!obj) {
michael@0 1499 return false;
michael@0 1500 }
michael@0 1501
michael@0 1502 obj = JS_ObjectToInnerObject(cx, obj);
michael@0 1503 NS_ABORT_IF_FALSE(obj,
michael@0 1504 "JS_ObjectToInnerObject should never return null with non-null input.");
michael@0 1505
michael@0 1506 if (result) {
michael@0 1507 // Initialize the out param to void
michael@0 1508 VOID_TO_NPVARIANT(*result);
michael@0 1509 }
michael@0 1510
michael@0 1511 if (!script || !script->UTF8Length || !script->UTF8Characters) {
michael@0 1512 // Nothing to evaluate.
michael@0 1513
michael@0 1514 return true;
michael@0 1515 }
michael@0 1516
michael@0 1517 NS_ConvertUTF8toUTF16 utf16script(script->UTF8Characters,
michael@0 1518 script->UTF8Length);
michael@0 1519
michael@0 1520 nsIPrincipal *principal = doc->NodePrincipal();
michael@0 1521
michael@0 1522 nsAutoCString specStr;
michael@0 1523 const char *spec;
michael@0 1524
michael@0 1525 nsCOMPtr<nsIURI> uri;
michael@0 1526 principal->GetURI(getter_AddRefs(uri));
michael@0 1527
michael@0 1528 if (uri) {
michael@0 1529 uri->GetSpec(specStr);
michael@0 1530 spec = specStr.get();
michael@0 1531 } else {
michael@0 1532 // No URI in a principal means it's the system principal. If the
michael@0 1533 // document URI is a chrome:// URI, pass that in as the URI of the
michael@0 1534 // script, else pass in null for the filename as there's no way to
michael@0 1535 // know where this document really came from. Passing in null here
michael@0 1536 // also means that the script gets treated by XPConnect as if it
michael@0 1537 // needs additional protection, which is what we want for unknown
michael@0 1538 // chrome code anyways.
michael@0 1539
michael@0 1540 uri = doc->GetDocumentURI();
michael@0 1541 bool isChrome = false;
michael@0 1542
michael@0 1543 if (uri && NS_SUCCEEDED(uri->SchemeIs("chrome", &isChrome)) && isChrome) {
michael@0 1544 uri->GetSpec(specStr);
michael@0 1545 spec = specStr.get();
michael@0 1546 } else {
michael@0 1547 spec = nullptr;
michael@0 1548 }
michael@0 1549 }
michael@0 1550
michael@0 1551 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
michael@0 1552 ("NPN_Evaluate(npp %p, npobj %p, script <<<%s>>>) called\n",
michael@0 1553 npp, npobj, script->UTF8Characters));
michael@0 1554
michael@0 1555 JS::CompileOptions options(cx);
michael@0 1556 options.setFileAndLine(spec, 0)
michael@0 1557 .setVersion(JSVERSION_DEFAULT);
michael@0 1558 JS::Rooted<JS::Value> rval(cx);
michael@0 1559 nsJSUtils::EvaluateOptions evalOptions;
michael@0 1560 nsresult rv = nsJSUtils::EvaluateString(cx, utf16script, obj, options,
michael@0 1561 evalOptions, &rval);
michael@0 1562
michael@0 1563 return NS_SUCCEEDED(rv) &&
michael@0 1564 (!result || JSValToNPVariant(npp, cx, rval, result));
michael@0 1565 }
michael@0 1566
michael@0 1567 bool
michael@0 1568 _getproperty(NPP npp, NPObject* npobj, NPIdentifier property,
michael@0 1569 NPVariant *result)
michael@0 1570 {
michael@0 1571 if (!NS_IsMainThread()) {
michael@0 1572 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_getproperty called from the wrong thread\n"));
michael@0 1573 return false;
michael@0 1574 }
michael@0 1575 if (!npp || !npobj || !npobj->_class || !npobj->_class->getProperty)
michael@0 1576 return false;
michael@0 1577
michael@0 1578 NPPExceptionAutoHolder nppExceptionHolder;
michael@0 1579 NPPAutoPusher nppPusher(npp);
michael@0 1580
michael@0 1581 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
michael@0 1582 ("NPN_GetProperty(npp %p, npobj %p, property %p) called\n",
michael@0 1583 npp, npobj, property));
michael@0 1584
michael@0 1585 if (!npobj->_class->getProperty(npobj, property, result))
michael@0 1586 return false;
michael@0 1587
michael@0 1588 // If a Java plugin tries to get the document.URL or document.documentURI
michael@0 1589 // property from us, don't pass back a value that Java won't be able to
michael@0 1590 // understand -- one that will make the URL(String) constructor throw a
michael@0 1591 // MalformedURL exception. Passing such a value causes Java Plugin2 to
michael@0 1592 // crash (to throw a RuntimeException in Plugin2Manager.getDocumentBase()).
michael@0 1593 // Also don't pass back a value that Java is likely to mishandle.
michael@0 1594
michael@0 1595 nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*) npp->ndata;
michael@0 1596 if (!inst)
michael@0 1597 return false;
michael@0 1598 nsNPAPIPlugin* plugin = inst->GetPlugin();
michael@0 1599 if (!plugin)
michael@0 1600 return false;
michael@0 1601 nsRefPtr<nsPluginHost> host = nsPluginHost::GetInst();
michael@0 1602 nsPluginTag* pluginTag = host->TagForPlugin(plugin);
michael@0 1603 if (!pluginTag->mIsJavaPlugin)
michael@0 1604 return true;
michael@0 1605
michael@0 1606 if (!NPVARIANT_IS_STRING(*result))
michael@0 1607 return true;
michael@0 1608
michael@0 1609 NPUTF8* propertyName = _utf8fromidentifier(property);
michael@0 1610 if (!propertyName)
michael@0 1611 return true;
michael@0 1612 bool notURL =
michael@0 1613 (PL_strcasecmp(propertyName, "URL") &&
michael@0 1614 PL_strcasecmp(propertyName, "documentURI"));
michael@0 1615 _memfree(propertyName);
michael@0 1616 if (notURL)
michael@0 1617 return true;
michael@0 1618
michael@0 1619 NPObject* window_obj = _getwindowobject(npp);
michael@0 1620 if (!window_obj)
michael@0 1621 return true;
michael@0 1622
michael@0 1623 NPVariant doc_v;
michael@0 1624 NPObject* document_obj = nullptr;
michael@0 1625 NPIdentifier doc_id = _getstringidentifier("document");
michael@0 1626 bool ok = npobj->_class->getProperty(window_obj, doc_id, &doc_v);
michael@0 1627 _releaseobject(window_obj);
michael@0 1628 if (ok) {
michael@0 1629 if (NPVARIANT_IS_OBJECT(doc_v)) {
michael@0 1630 document_obj = NPVARIANT_TO_OBJECT(doc_v);
michael@0 1631 } else {
michael@0 1632 _releasevariantvalue(&doc_v);
michael@0 1633 return true;
michael@0 1634 }
michael@0 1635 } else {
michael@0 1636 return true;
michael@0 1637 }
michael@0 1638 _releaseobject(document_obj);
michael@0 1639 if (document_obj != npobj)
michael@0 1640 return true;
michael@0 1641
michael@0 1642 NPString urlnp = NPVARIANT_TO_STRING(*result);
michael@0 1643 nsXPIDLCString url;
michael@0 1644 url.Assign(urlnp.UTF8Characters, urlnp.UTF8Length);
michael@0 1645
michael@0 1646 bool javaCompatible = false;
michael@0 1647 if (NS_FAILED(NS_CheckIsJavaCompatibleURLString(url, &javaCompatible)))
michael@0 1648 javaCompatible = false;
michael@0 1649 if (javaCompatible)
michael@0 1650 return true;
michael@0 1651
michael@0 1652 // If Java won't be able to interpret the original value of document.URL or
michael@0 1653 // document.documentURI, or is likely to mishandle it, pass back something
michael@0 1654 // that Java will understand but won't be able to use to access the network,
michael@0 1655 // and for which same-origin checks will always fail.
michael@0 1656
michael@0 1657 if (inst->mFakeURL.IsVoid()) {
michael@0 1658 // Abort (do an error return) if NS_MakeRandomInvalidURLString() fails.
michael@0 1659 if (NS_FAILED(NS_MakeRandomInvalidURLString(inst->mFakeURL))) {
michael@0 1660 _releasevariantvalue(result);
michael@0 1661 return false;
michael@0 1662 }
michael@0 1663 }
michael@0 1664
michael@0 1665 _releasevariantvalue(result);
michael@0 1666 char* fakeurl = (char *) _memalloc(inst->mFakeURL.Length() + 1);
michael@0 1667 strcpy(fakeurl, inst->mFakeURL);
michael@0 1668 STRINGZ_TO_NPVARIANT(fakeurl, *result);
michael@0 1669
michael@0 1670 return true;
michael@0 1671 }
michael@0 1672
michael@0 1673 bool
michael@0 1674 _setproperty(NPP npp, NPObject* npobj, NPIdentifier property,
michael@0 1675 const NPVariant *value)
michael@0 1676 {
michael@0 1677 if (!NS_IsMainThread()) {
michael@0 1678 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_setproperty called from the wrong thread\n"));
michael@0 1679 return false;
michael@0 1680 }
michael@0 1681 if (!npp || !npobj || !npobj->_class || !npobj->_class->setProperty)
michael@0 1682 return false;
michael@0 1683
michael@0 1684 NPPExceptionAutoHolder nppExceptionHolder;
michael@0 1685 NPPAutoPusher nppPusher(npp);
michael@0 1686
michael@0 1687 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
michael@0 1688 ("NPN_SetProperty(npp %p, npobj %p, property %p) called\n",
michael@0 1689 npp, npobj, property));
michael@0 1690
michael@0 1691 return npobj->_class->setProperty(npobj, property, value);
michael@0 1692 }
michael@0 1693
michael@0 1694 bool
michael@0 1695 _removeproperty(NPP npp, NPObject* npobj, NPIdentifier property)
michael@0 1696 {
michael@0 1697 if (!NS_IsMainThread()) {
michael@0 1698 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_removeproperty called from the wrong thread\n"));
michael@0 1699 return false;
michael@0 1700 }
michael@0 1701 if (!npp || !npobj || !npobj->_class || !npobj->_class->removeProperty)
michael@0 1702 return false;
michael@0 1703
michael@0 1704 NPPExceptionAutoHolder nppExceptionHolder;
michael@0 1705 NPPAutoPusher nppPusher(npp);
michael@0 1706
michael@0 1707 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
michael@0 1708 ("NPN_RemoveProperty(npp %p, npobj %p, property %p) called\n",
michael@0 1709 npp, npobj, property));
michael@0 1710
michael@0 1711 return npobj->_class->removeProperty(npobj, property);
michael@0 1712 }
michael@0 1713
michael@0 1714 bool
michael@0 1715 _hasproperty(NPP npp, NPObject* npobj, NPIdentifier propertyName)
michael@0 1716 {
michael@0 1717 if (!NS_IsMainThread()) {
michael@0 1718 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_hasproperty called from the wrong thread\n"));
michael@0 1719 return false;
michael@0 1720 }
michael@0 1721 if (!npp || !npobj || !npobj->_class || !npobj->_class->hasProperty)
michael@0 1722 return false;
michael@0 1723
michael@0 1724 NPPExceptionAutoHolder nppExceptionHolder;
michael@0 1725 NPPAutoPusher nppPusher(npp);
michael@0 1726
michael@0 1727 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
michael@0 1728 ("NPN_HasProperty(npp %p, npobj %p, property %p) called\n",
michael@0 1729 npp, npobj, propertyName));
michael@0 1730
michael@0 1731 return npobj->_class->hasProperty(npobj, propertyName);
michael@0 1732 }
michael@0 1733
michael@0 1734 bool
michael@0 1735 _hasmethod(NPP npp, NPObject* npobj, NPIdentifier methodName)
michael@0 1736 {
michael@0 1737 if (!NS_IsMainThread()) {
michael@0 1738 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_hasmethod called from the wrong thread\n"));
michael@0 1739 return false;
michael@0 1740 }
michael@0 1741 if (!npp || !npobj || !npobj->_class || !npobj->_class->hasMethod)
michael@0 1742 return false;
michael@0 1743
michael@0 1744 NPPExceptionAutoHolder nppExceptionHolder;
michael@0 1745 NPPAutoPusher nppPusher(npp);
michael@0 1746
michael@0 1747 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
michael@0 1748 ("NPN_HasMethod(npp %p, npobj %p, property %p) called\n",
michael@0 1749 npp, npobj, methodName));
michael@0 1750
michael@0 1751 return npobj->_class->hasMethod(npobj, methodName);
michael@0 1752 }
michael@0 1753
michael@0 1754 bool
michael@0 1755 _enumerate(NPP npp, NPObject *npobj, NPIdentifier **identifier,
michael@0 1756 uint32_t *count)
michael@0 1757 {
michael@0 1758 if (!NS_IsMainThread()) {
michael@0 1759 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_enumerate called from the wrong thread\n"));
michael@0 1760 return false;
michael@0 1761 }
michael@0 1762 if (!npp || !npobj || !npobj->_class)
michael@0 1763 return false;
michael@0 1764
michael@0 1765 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
michael@0 1766 ("NPN_Enumerate(npp %p, npobj %p) called\n", npp, npobj));
michael@0 1767
michael@0 1768 if (!NP_CLASS_STRUCT_VERSION_HAS_ENUM(npobj->_class) ||
michael@0 1769 !npobj->_class->enumerate) {
michael@0 1770 *identifier = 0;
michael@0 1771 *count = 0;
michael@0 1772 return true;
michael@0 1773 }
michael@0 1774
michael@0 1775 NPPExceptionAutoHolder nppExceptionHolder;
michael@0 1776 NPPAutoPusher nppPusher(npp);
michael@0 1777
michael@0 1778 return npobj->_class->enumerate(npobj, identifier, count);
michael@0 1779 }
michael@0 1780
michael@0 1781 bool
michael@0 1782 _construct(NPP npp, NPObject* npobj, const NPVariant *args,
michael@0 1783 uint32_t argCount, NPVariant *result)
michael@0 1784 {
michael@0 1785 if (!NS_IsMainThread()) {
michael@0 1786 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_construct called from the wrong thread\n"));
michael@0 1787 return false;
michael@0 1788 }
michael@0 1789 if (!npp || !npobj || !npobj->_class ||
michael@0 1790 !NP_CLASS_STRUCT_VERSION_HAS_CTOR(npobj->_class) ||
michael@0 1791 !npobj->_class->construct) {
michael@0 1792 return false;
michael@0 1793 }
michael@0 1794
michael@0 1795 NPPExceptionAutoHolder nppExceptionHolder;
michael@0 1796 NPPAutoPusher nppPusher(npp);
michael@0 1797
michael@0 1798 return npobj->_class->construct(npobj, args, argCount, result);
michael@0 1799 }
michael@0 1800
michael@0 1801 void
michael@0 1802 _releasevariantvalue(NPVariant* variant)
michael@0 1803 {
michael@0 1804 if (!NS_IsMainThread()) {
michael@0 1805 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_releasevariantvalue called from the wrong thread\n"));
michael@0 1806 }
michael@0 1807 switch (variant->type) {
michael@0 1808 case NPVariantType_Void :
michael@0 1809 case NPVariantType_Null :
michael@0 1810 case NPVariantType_Bool :
michael@0 1811 case NPVariantType_Int32 :
michael@0 1812 case NPVariantType_Double :
michael@0 1813 break;
michael@0 1814 case NPVariantType_String :
michael@0 1815 {
michael@0 1816 const NPString *s = &NPVARIANT_TO_STRING(*variant);
michael@0 1817
michael@0 1818 if (s->UTF8Characters) {
michael@0 1819 #if defined(MOZ_MEMORY_WINDOWS)
michael@0 1820 if (malloc_usable_size((void *)s->UTF8Characters) != 0) {
michael@0 1821 PR_Free((void *)s->UTF8Characters);
michael@0 1822 } else {
michael@0 1823 void *p = (void *)s->UTF8Characters;
michael@0 1824 DWORD nheaps = 0;
michael@0 1825 nsAutoTArray<HANDLE, 50> heaps;
michael@0 1826 nheaps = GetProcessHeaps(0, heaps.Elements());
michael@0 1827 heaps.AppendElements(nheaps);
michael@0 1828 GetProcessHeaps(nheaps, heaps.Elements());
michael@0 1829 for (DWORD i = 0; i < nheaps; i++) {
michael@0 1830 if (InHeap(heaps[i], p)) {
michael@0 1831 HeapFree(heaps[i], 0, p);
michael@0 1832 break;
michael@0 1833 }
michael@0 1834 }
michael@0 1835 }
michael@0 1836 #else
michael@0 1837 NS_Free((void *)s->UTF8Characters);
michael@0 1838 #endif
michael@0 1839 }
michael@0 1840 break;
michael@0 1841 }
michael@0 1842 case NPVariantType_Object:
michael@0 1843 {
michael@0 1844 NPObject *npobj = NPVARIANT_TO_OBJECT(*variant);
michael@0 1845
michael@0 1846 if (npobj)
michael@0 1847 _releaseobject(npobj);
michael@0 1848
michael@0 1849 break;
michael@0 1850 }
michael@0 1851 default:
michael@0 1852 NS_ERROR("Unknown NPVariant type!");
michael@0 1853 }
michael@0 1854
michael@0 1855 VOID_TO_NPVARIANT(*variant);
michael@0 1856 }
michael@0 1857
michael@0 1858 void
michael@0 1859 _setexception(NPObject* npobj, const NPUTF8 *message)
michael@0 1860 {
michael@0 1861 if (!NS_IsMainThread()) {
michael@0 1862 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_setexception called from the wrong thread\n"));
michael@0 1863 return;
michael@0 1864 }
michael@0 1865
michael@0 1866 if (!message) return;
michael@0 1867
michael@0 1868 if (gNPPException) {
michael@0 1869 // If a plugin throws multiple exceptions, we'll only report the
michael@0 1870 // last one for now.
michael@0 1871 free(gNPPException);
michael@0 1872 }
michael@0 1873
michael@0 1874 gNPPException = strdup(message);
michael@0 1875 }
michael@0 1876
michael@0 1877 NPError
michael@0 1878 _getvalue(NPP npp, NPNVariable variable, void *result)
michael@0 1879 {
michael@0 1880 if (!NS_IsMainThread()) {
michael@0 1881 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_getvalue called from the wrong thread\n"));
michael@0 1882 return NPERR_INVALID_PARAM;
michael@0 1883 }
michael@0 1884 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_GetValue: npp=%p, var=%d\n",
michael@0 1885 (void*)npp, (int)variable));
michael@0 1886
michael@0 1887 nsresult res;
michael@0 1888
michael@0 1889 PluginDestructionGuard guard(npp);
michael@0 1890
michael@0 1891 switch(variable) {
michael@0 1892 #if defined(XP_UNIX) && !defined(XP_MACOSX)
michael@0 1893 case NPNVxDisplay : {
michael@0 1894 #if defined(MOZ_X11)
michael@0 1895 if (npp) {
michael@0 1896 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *) npp->ndata;
michael@0 1897 bool windowless = false;
michael@0 1898 inst->IsWindowless(&windowless);
michael@0 1899 // The documentation on the types for many variables in NP(N|P)_GetValue
michael@0 1900 // is vague. Often boolean values are NPBool (1 byte), but
michael@0 1901 // https://developer.mozilla.org/en/XEmbed_Extension_for_Mozilla_Plugins
michael@0 1902 // treats NPPVpluginNeedsXEmbed as PRBool (int), and
michael@0 1903 // on x86/32-bit, flash stores to this using |movl 0x1,&needsXEmbed|.
michael@0 1904 // thus we can't use NPBool for needsXEmbed, or the three bytes above
michael@0 1905 // it on the stack would get clobbered. so protect with the larger bool.
michael@0 1906 int needsXEmbed = 0;
michael@0 1907 if (!windowless) {
michael@0 1908 res = inst->GetValueFromPlugin(NPPVpluginNeedsXEmbed, &needsXEmbed);
michael@0 1909 // If the call returned an error code make sure we still use our default value.
michael@0 1910 if (NS_FAILED(res)) {
michael@0 1911 needsXEmbed = 0;
michael@0 1912 }
michael@0 1913 }
michael@0 1914 if (windowless || needsXEmbed) {
michael@0 1915 (*(Display **)result) = mozilla::DefaultXDisplay();
michael@0 1916 return NPERR_NO_ERROR;
michael@0 1917 }
michael@0 1918 }
michael@0 1919 #if (MOZ_WIDGET_GTK == 2)
michael@0 1920 // adobe nppdf calls XtGetApplicationNameAndClass(display,
michael@0 1921 // &instance, &class) we have to init Xt toolkit before get
michael@0 1922 // XtDisplay just call gtk_xtbin_new(w,0) once
michael@0 1923 static GtkWidget *gtkXtBinHolder = 0;
michael@0 1924 if (!gtkXtBinHolder) {
michael@0 1925 gtkXtBinHolder = gtk_xtbin_new(gdk_get_default_root_window(),0);
michael@0 1926 // it crashes on destroy, let it leak
michael@0 1927 // gtk_widget_destroy(gtkXtBinHolder);
michael@0 1928 }
michael@0 1929 (*(Display **)result) = GTK_XTBIN(gtkXtBinHolder)->xtdisplay;
michael@0 1930 return NPERR_NO_ERROR;
michael@0 1931 #endif
michael@0 1932 #endif
michael@0 1933 return NPERR_GENERIC_ERROR;
michael@0 1934 }
michael@0 1935
michael@0 1936 case NPNVxtAppContext:
michael@0 1937 return NPERR_GENERIC_ERROR;
michael@0 1938 #endif
michael@0 1939
michael@0 1940 #if defined(XP_WIN) || (MOZ_WIDGET_GTK == 2) || defined(MOZ_WIDGET_QT)
michael@0 1941 case NPNVnetscapeWindow: {
michael@0 1942 if (!npp || !npp->ndata)
michael@0 1943 return NPERR_INVALID_INSTANCE_ERROR;
michael@0 1944
michael@0 1945 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *) npp->ndata;
michael@0 1946
michael@0 1947 nsRefPtr<nsPluginInstanceOwner> owner = inst->GetOwner();
michael@0 1948 NS_ENSURE_TRUE(owner, NPERR_NO_ERROR);
michael@0 1949
michael@0 1950 if (NS_SUCCEEDED(owner->GetNetscapeWindow(result))) {
michael@0 1951 return NPERR_NO_ERROR;
michael@0 1952 }
michael@0 1953 return NPERR_GENERIC_ERROR;
michael@0 1954 }
michael@0 1955 #endif
michael@0 1956
michael@0 1957 case NPNVjavascriptEnabledBool: {
michael@0 1958 *(NPBool*)result = false;
michael@0 1959 bool js = false;
michael@0 1960 res = Preferences::GetBool("javascript.enabled", &js);
michael@0 1961 if (NS_SUCCEEDED(res)) {
michael@0 1962 *(NPBool*)result = js;
michael@0 1963 }
michael@0 1964 return NPERR_NO_ERROR;
michael@0 1965 }
michael@0 1966
michael@0 1967 case NPNVasdEnabledBool:
michael@0 1968 *(NPBool*)result = false;
michael@0 1969 return NPERR_NO_ERROR;
michael@0 1970
michael@0 1971 case NPNVisOfflineBool: {
michael@0 1972 bool offline = false;
michael@0 1973 nsCOMPtr<nsIIOService> ioservice =
michael@0 1974 do_GetService(NS_IOSERVICE_CONTRACTID, &res);
michael@0 1975 if (NS_SUCCEEDED(res))
michael@0 1976 res = ioservice->GetOffline(&offline);
michael@0 1977 if (NS_FAILED(res))
michael@0 1978 return NPERR_GENERIC_ERROR;
michael@0 1979
michael@0 1980 *(NPBool*)result = offline;
michael@0 1981 return NPERR_NO_ERROR;
michael@0 1982 }
michael@0 1983
michael@0 1984 case NPNVToolkit: {
michael@0 1985 #ifdef MOZ_WIDGET_GTK
michael@0 1986 *((NPNToolkitType*)result) = NPNVGtk2;
michael@0 1987 #endif
michael@0 1988
michael@0 1989 #ifdef MOZ_WIDGET_QT
michael@0 1990 /* Fake toolkit so flash plugin works */
michael@0 1991 *((NPNToolkitType*)result) = NPNVGtk2;
michael@0 1992 #endif
michael@0 1993 if (*(NPNToolkitType*)result)
michael@0 1994 return NPERR_NO_ERROR;
michael@0 1995
michael@0 1996 return NPERR_GENERIC_ERROR;
michael@0 1997 }
michael@0 1998
michael@0 1999 case NPNVSupportsXEmbedBool: {
michael@0 2000 #ifdef MOZ_WIDGET_GTK
michael@0 2001 *(NPBool*)result = true;
michael@0 2002 #elif defined(MOZ_WIDGET_QT)
michael@0 2003 // Desktop Flash fail to initialize if browser does not support NPNVSupportsXEmbedBool
michael@0 2004 // even when wmode!=windowed, lets return fake support
michael@0 2005 fprintf(stderr, "Fake support for XEmbed plugins in Qt port\n");
michael@0 2006 *(NPBool*)result = true;
michael@0 2007 #else
michael@0 2008 *(NPBool*)result = false;
michael@0 2009 #endif
michael@0 2010 return NPERR_NO_ERROR;
michael@0 2011 }
michael@0 2012
michael@0 2013 case NPNVWindowNPObject: {
michael@0 2014 *(NPObject **)result = _getwindowobject(npp);
michael@0 2015
michael@0 2016 return *(NPObject **)result ? NPERR_NO_ERROR : NPERR_GENERIC_ERROR;
michael@0 2017 }
michael@0 2018
michael@0 2019 case NPNVPluginElementNPObject: {
michael@0 2020 *(NPObject **)result = _getpluginelement(npp);
michael@0 2021
michael@0 2022 return *(NPObject **)result ? NPERR_NO_ERROR : NPERR_GENERIC_ERROR;
michael@0 2023 }
michael@0 2024
michael@0 2025 case NPNVSupportsWindowless: {
michael@0 2026 #if defined(XP_WIN) || defined(XP_MACOSX) || \
michael@0 2027 (defined(MOZ_X11) && (defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_QT)))
michael@0 2028 *(NPBool*)result = true;
michael@0 2029 #else
michael@0 2030 *(NPBool*)result = false;
michael@0 2031 #endif
michael@0 2032 return NPERR_NO_ERROR;
michael@0 2033 }
michael@0 2034
michael@0 2035 case NPNVprivateModeBool: {
michael@0 2036 bool privacy;
michael@0 2037 nsNPAPIPluginInstance *inst = static_cast<nsNPAPIPluginInstance*>(npp->ndata);
michael@0 2038 if (!inst)
michael@0 2039 return NPERR_GENERIC_ERROR;
michael@0 2040
michael@0 2041 nsresult rv = inst->IsPrivateBrowsing(&privacy);
michael@0 2042 if (NS_FAILED(rv))
michael@0 2043 return NPERR_GENERIC_ERROR;
michael@0 2044 *(NPBool*)result = (NPBool)privacy;
michael@0 2045 return NPERR_NO_ERROR;
michael@0 2046 }
michael@0 2047
michael@0 2048 case NPNVdocumentOrigin: {
michael@0 2049 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)npp->ndata;
michael@0 2050 if (!inst) {
michael@0 2051 return NPERR_GENERIC_ERROR;
michael@0 2052 }
michael@0 2053
michael@0 2054 nsCOMPtr<nsIDOMElement> element;
michael@0 2055 inst->GetDOMElement(getter_AddRefs(element));
michael@0 2056 if (!element) {
michael@0 2057 return NPERR_GENERIC_ERROR;
michael@0 2058 }
michael@0 2059
michael@0 2060 nsCOMPtr<nsIContent> content(do_QueryInterface(element));
michael@0 2061 if (!content) {
michael@0 2062 return NPERR_GENERIC_ERROR;
michael@0 2063 }
michael@0 2064
michael@0 2065 nsIPrincipal* principal = content->NodePrincipal();
michael@0 2066
michael@0 2067 nsAutoString utf16Origin;
michael@0 2068 res = nsContentUtils::GetUTFOrigin(principal, utf16Origin);
michael@0 2069 if (NS_FAILED(res)) {
michael@0 2070 return NPERR_GENERIC_ERROR;
michael@0 2071 }
michael@0 2072
michael@0 2073 nsCOMPtr<nsIUnicodeNormalizer> normalizer = do_GetService(NS_UNICODE_NORMALIZER_CONTRACTID);
michael@0 2074 if (!normalizer) {
michael@0 2075 return NPERR_GENERIC_ERROR;
michael@0 2076 }
michael@0 2077
michael@0 2078 nsAutoString normalizedUTF16Origin;
michael@0 2079 res = normalizer->NormalizeUnicodeNFKC(utf16Origin, normalizedUTF16Origin);
michael@0 2080 if (NS_FAILED(res)) {
michael@0 2081 return NPERR_GENERIC_ERROR;
michael@0 2082 }
michael@0 2083
michael@0 2084 *(char**)result = ToNewUTF8String(normalizedUTF16Origin);
michael@0 2085 return *(char**)result ? NPERR_NO_ERROR : NPERR_GENERIC_ERROR;
michael@0 2086 }
michael@0 2087
michael@0 2088 #ifdef XP_MACOSX
michael@0 2089 case NPNVpluginDrawingModel: {
michael@0 2090 if (npp) {
michael@0 2091 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance*)npp->ndata;
michael@0 2092 if (inst) {
michael@0 2093 NPDrawingModel drawingModel;
michael@0 2094 inst->GetDrawingModel((int32_t*)&drawingModel);
michael@0 2095 *(NPDrawingModel*)result = drawingModel;
michael@0 2096 return NPERR_NO_ERROR;
michael@0 2097 }
michael@0 2098 }
michael@0 2099 else {
michael@0 2100 return NPERR_GENERIC_ERROR;
michael@0 2101 }
michael@0 2102 }
michael@0 2103
michael@0 2104 #ifndef NP_NO_QUICKDRAW
michael@0 2105 case NPNVsupportsQuickDrawBool: {
michael@0 2106 *(NPBool*)result = false;
michael@0 2107
michael@0 2108 return NPERR_NO_ERROR;
michael@0 2109 }
michael@0 2110 #endif
michael@0 2111
michael@0 2112 case NPNVsupportsCoreGraphicsBool: {
michael@0 2113 *(NPBool*)result = true;
michael@0 2114
michael@0 2115 return NPERR_NO_ERROR;
michael@0 2116 }
michael@0 2117
michael@0 2118 case NPNVsupportsCoreAnimationBool: {
michael@0 2119 *(NPBool*)result = nsCocoaFeatures::SupportCoreAnimationPlugins();
michael@0 2120
michael@0 2121 return NPERR_NO_ERROR;
michael@0 2122 }
michael@0 2123
michael@0 2124 case NPNVsupportsInvalidatingCoreAnimationBool: {
michael@0 2125 *(NPBool*)result = nsCocoaFeatures::SupportCoreAnimationPlugins();
michael@0 2126
michael@0 2127 return NPERR_NO_ERROR;
michael@0 2128 }
michael@0 2129
michael@0 2130 case NPNVsupportsCompositingCoreAnimationPluginsBool: {
michael@0 2131 *(NPBool*)result = PR_TRUE;
michael@0 2132
michael@0 2133 return NPERR_NO_ERROR;
michael@0 2134 }
michael@0 2135
michael@0 2136 #ifndef NP_NO_CARBON
michael@0 2137 case NPNVsupportsCarbonBool: {
michael@0 2138 *(NPBool*)result = false;
michael@0 2139
michael@0 2140 return NPERR_NO_ERROR;
michael@0 2141 }
michael@0 2142 #endif
michael@0 2143 case NPNVsupportsCocoaBool: {
michael@0 2144 *(NPBool*)result = true;
michael@0 2145
michael@0 2146 return NPERR_NO_ERROR;
michael@0 2147 }
michael@0 2148
michael@0 2149 case NPNVsupportsUpdatedCocoaTextInputBool: {
michael@0 2150 *(NPBool*)result = true;
michael@0 2151 return NPERR_NO_ERROR;
michael@0 2152 }
michael@0 2153
michael@0 2154 case NPNVcontentsScaleFactor: {
michael@0 2155 nsNPAPIPluginInstance *inst =
michael@0 2156 (nsNPAPIPluginInstance *) (npp ? npp->ndata : nullptr);
michael@0 2157 double scaleFactor = inst ? inst->GetContentsScaleFactor() : 1.0;
michael@0 2158 *(double*)result = scaleFactor;
michael@0 2159 return NPERR_NO_ERROR;
michael@0 2160 }
michael@0 2161 #endif
michael@0 2162
michael@0 2163 #ifdef MOZ_WIDGET_ANDROID
michael@0 2164 case kLogInterfaceV0_ANPGetValue: {
michael@0 2165 LOG("get log interface");
michael@0 2166 ANPLogInterfaceV0 *i = (ANPLogInterfaceV0 *) result;
michael@0 2167 InitLogInterface(i);
michael@0 2168 return NPERR_NO_ERROR;
michael@0 2169 }
michael@0 2170
michael@0 2171 case kBitmapInterfaceV0_ANPGetValue: {
michael@0 2172 LOG("get bitmap interface");
michael@0 2173 ANPBitmapInterfaceV0 *i = (ANPBitmapInterfaceV0 *) result;
michael@0 2174 InitBitmapInterface(i);
michael@0 2175 return NPERR_NO_ERROR;
michael@0 2176 }
michael@0 2177
michael@0 2178 case kMatrixInterfaceV0_ANPGetValue: {
michael@0 2179 LOG("get matrix interface");
michael@0 2180 ANPMatrixInterfaceV0 *i = (ANPMatrixInterfaceV0 *) result;
michael@0 2181 InitMatrixInterface(i);
michael@0 2182 return NPERR_NO_ERROR;
michael@0 2183 }
michael@0 2184
michael@0 2185 case kPathInterfaceV0_ANPGetValue: {
michael@0 2186 LOG("get path interface");
michael@0 2187 ANPPathInterfaceV0 *i = (ANPPathInterfaceV0 *) result;
michael@0 2188 InitPathInterface(i);
michael@0 2189 return NPERR_NO_ERROR;
michael@0 2190 }
michael@0 2191
michael@0 2192 case kTypefaceInterfaceV0_ANPGetValue: {
michael@0 2193 LOG("get typeface interface");
michael@0 2194 ANPTypefaceInterfaceV0 *i = (ANPTypefaceInterfaceV0 *) result;
michael@0 2195 InitTypeFaceInterface(i);
michael@0 2196 return NPERR_NO_ERROR;
michael@0 2197 }
michael@0 2198
michael@0 2199 case kPaintInterfaceV0_ANPGetValue: {
michael@0 2200 LOG("get paint interface");
michael@0 2201 ANPPaintInterfaceV0 *i = (ANPPaintInterfaceV0 *) result;
michael@0 2202 InitPaintInterface(i);
michael@0 2203 return NPERR_NO_ERROR;
michael@0 2204 }
michael@0 2205
michael@0 2206 case kCanvasInterfaceV0_ANPGetValue: {
michael@0 2207 LOG("get canvas interface");
michael@0 2208 ANPCanvasInterfaceV0 *i = (ANPCanvasInterfaceV0 *) result;
michael@0 2209 InitCanvasInterface(i);
michael@0 2210 return NPERR_NO_ERROR;
michael@0 2211 }
michael@0 2212
michael@0 2213 case kWindowInterfaceV0_ANPGetValue: {
michael@0 2214 LOG("get window interface");
michael@0 2215 ANPWindowInterfaceV0 *i = (ANPWindowInterfaceV0 *) result;
michael@0 2216 InitWindowInterface(i);
michael@0 2217 return NPERR_NO_ERROR;
michael@0 2218 }
michael@0 2219
michael@0 2220 case kAudioTrackInterfaceV0_ANPGetValue: {
michael@0 2221 LOG("get audio interface");
michael@0 2222 ANPAudioTrackInterfaceV0 *i = (ANPAudioTrackInterfaceV0 *) result;
michael@0 2223 InitAudioTrackInterfaceV0(i);
michael@0 2224 return NPERR_NO_ERROR;
michael@0 2225 }
michael@0 2226
michael@0 2227 case kEventInterfaceV0_ANPGetValue: {
michael@0 2228 LOG("get event interface");
michael@0 2229 ANPEventInterfaceV0 *i = (ANPEventInterfaceV0 *) result;
michael@0 2230 InitEventInterface(i);
michael@0 2231 return NPERR_NO_ERROR;
michael@0 2232 }
michael@0 2233
michael@0 2234 case kSystemInterfaceV0_ANPGetValue: {
michael@0 2235 LOG("get system interface");
michael@0 2236 ANPSystemInterfaceV0* i = reinterpret_cast<ANPSystemInterfaceV0*>(result);
michael@0 2237 InitSystemInterface(i);
michael@0 2238 return NPERR_NO_ERROR;
michael@0 2239 }
michael@0 2240
michael@0 2241 case kSurfaceInterfaceV0_ANPGetValue: {
michael@0 2242 LOG("get surface interface");
michael@0 2243 ANPSurfaceInterfaceV0 *i = (ANPSurfaceInterfaceV0 *) result;
michael@0 2244 InitSurfaceInterface(i);
michael@0 2245 return NPERR_NO_ERROR;
michael@0 2246 }
michael@0 2247
michael@0 2248 case kSupportedDrawingModel_ANPGetValue: {
michael@0 2249 LOG("get supported drawing model");
michael@0 2250 uint32_t* bits = reinterpret_cast<uint32_t*>(result);
michael@0 2251 *bits = kBitmap_ANPDrawingModel && kSurface_ANPDrawingModel;
michael@0 2252 return NPERR_NO_ERROR;
michael@0 2253 }
michael@0 2254
michael@0 2255 case kJavaContext_ANPGetValue: {
michael@0 2256 jobject ret = mozilla::widget::android::GeckoAppShell::GetContext();
michael@0 2257 if (!ret)
michael@0 2258 return NPERR_GENERIC_ERROR;
michael@0 2259
michael@0 2260 int32_t* i = reinterpret_cast<int32_t*>(result);
michael@0 2261 *i = reinterpret_cast<int32_t>(ret);
michael@0 2262 return NPERR_NO_ERROR;
michael@0 2263 }
michael@0 2264
michael@0 2265 case kAudioTrackInterfaceV1_ANPGetValue: {
michael@0 2266 LOG("get audio interface v1");
michael@0 2267 ANPAudioTrackInterfaceV1 *i = (ANPAudioTrackInterfaceV1 *) result;
michael@0 2268 InitAudioTrackInterfaceV1(i);
michael@0 2269 return NPERR_NO_ERROR;
michael@0 2270 }
michael@0 2271
michael@0 2272 case kNativeWindowInterfaceV0_ANPGetValue: {
michael@0 2273 LOG("get native window interface v0");
michael@0 2274 ANPNativeWindowInterfaceV0* i = (ANPNativeWindowInterfaceV0 *) result;
michael@0 2275 InitNativeWindowInterface(i);
michael@0 2276 return NPERR_NO_ERROR;
michael@0 2277 }
michael@0 2278
michael@0 2279 case kOpenGLInterfaceV0_ANPGetValue: {
michael@0 2280 LOG("get openGL interface");
michael@0 2281 ANPOpenGLInterfaceV0 *i = (ANPOpenGLInterfaceV0*) result;
michael@0 2282 InitOpenGLInterface(i);
michael@0 2283 return NPERR_NO_ERROR;
michael@0 2284 }
michael@0 2285
michael@0 2286 case kWindowInterfaceV1_ANPGetValue: {
michael@0 2287 LOG("get Window interface V1");
michael@0 2288 ANPWindowInterfaceV1 *i = (ANPWindowInterfaceV1 *) result;
michael@0 2289 InitWindowInterfaceV1(i);
michael@0 2290 return NPERR_NO_ERROR;
michael@0 2291 }
michael@0 2292
michael@0 2293 case kWindowInterfaceV2_ANPGetValue: {
michael@0 2294 LOG("get Window interface V2");
michael@0 2295 ANPWindowInterfaceV2 *i = (ANPWindowInterfaceV2 *) result;
michael@0 2296 InitWindowInterfaceV2(i);
michael@0 2297 return NPERR_NO_ERROR;
michael@0 2298 }
michael@0 2299
michael@0 2300 case kVideoInterfaceV0_ANPGetValue: {
michael@0 2301 LOG("get video interface");
michael@0 2302 ANPVideoInterfaceV0 *i = (ANPVideoInterfaceV0*) result;
michael@0 2303 InitVideoInterfaceV0(i);
michael@0 2304 return NPERR_NO_ERROR;
michael@0 2305 }
michael@0 2306
michael@0 2307 case kVideoInterfaceV1_ANPGetValue: {
michael@0 2308 LOG("get video interface");
michael@0 2309 ANPVideoInterfaceV1 *i = (ANPVideoInterfaceV1*) result;
michael@0 2310 InitVideoInterfaceV1(i);
michael@0 2311 return NPERR_NO_ERROR;
michael@0 2312 }
michael@0 2313
michael@0 2314
michael@0 2315 case kSystemInterfaceV1_ANPGetValue: {
michael@0 2316 LOG("get system interface v1");
michael@0 2317 ANPSystemInterfaceV1* i = reinterpret_cast<ANPSystemInterfaceV1*>(result);
michael@0 2318 InitSystemInterfaceV1(i);
michael@0 2319 return NPERR_NO_ERROR;
michael@0 2320 }
michael@0 2321
michael@0 2322 case kSystemInterfaceV2_ANPGetValue: {
michael@0 2323 LOG("get system interface v2");
michael@0 2324 ANPSystemInterfaceV2* i = reinterpret_cast<ANPSystemInterfaceV2*>(result);
michael@0 2325 InitSystemInterfaceV2(i);
michael@0 2326 return NPERR_NO_ERROR;
michael@0 2327 }
michael@0 2328
michael@0 2329 #endif
michael@0 2330
michael@0 2331 // we no longer hand out any XPCOM objects
michael@0 2332 case NPNVDOMElement:
michael@0 2333 // fall through
michael@0 2334 case NPNVDOMWindow:
michael@0 2335 // fall through
michael@0 2336 case NPNVserviceManager:
michael@0 2337 // old XPCOM objects, no longer supported, but null out the out
michael@0 2338 // param to avoid crashing plugins that still try to use this.
michael@0 2339 *(nsISupports**)result = nullptr;
michael@0 2340 // fall through
michael@0 2341 default:
michael@0 2342 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_getvalue unhandled get value: %d\n", variable));
michael@0 2343 return NPERR_GENERIC_ERROR;
michael@0 2344 }
michael@0 2345 }
michael@0 2346
michael@0 2347 NPError
michael@0 2348 _setvalue(NPP npp, NPPVariable variable, void *result)
michael@0 2349 {
michael@0 2350 if (!NS_IsMainThread()) {
michael@0 2351 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_setvalue called from the wrong thread\n"));
michael@0 2352 return NPERR_INVALID_PARAM;
michael@0 2353 }
michael@0 2354 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_SetValue: npp=%p, var=%d\n",
michael@0 2355 (void*)npp, (int)variable));
michael@0 2356
michael@0 2357 if (!npp)
michael@0 2358 return NPERR_INVALID_INSTANCE_ERROR;
michael@0 2359
michael@0 2360 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *) npp->ndata;
michael@0 2361
michael@0 2362 NS_ASSERTION(inst, "null instance");
michael@0 2363
michael@0 2364 if (!inst)
michael@0 2365 return NPERR_INVALID_INSTANCE_ERROR;
michael@0 2366
michael@0 2367 PluginDestructionGuard guard(inst);
michael@0 2368
michael@0 2369 switch (variable) {
michael@0 2370
michael@0 2371 // we should keep backward compatibility with NPAPI where the
michael@0 2372 // actual pointer value is checked rather than its content
michael@0 2373 // when passing booleans
michael@0 2374 case NPPVpluginWindowBool: {
michael@0 2375 #ifdef XP_MACOSX
michael@0 2376 // This setting doesn't apply to OS X (only to Windows and Unix/Linux).
michael@0 2377 // See https://developer.mozilla.org/En/NPN_SetValue#section_5. Return
michael@0 2378 // NPERR_NO_ERROR here to conform to other browsers' behavior on OS X
michael@0 2379 // (e.g. Safari and Opera).
michael@0 2380 return NPERR_NO_ERROR;
michael@0 2381 #else
michael@0 2382 NPBool bWindowless = (result == nullptr);
michael@0 2383 return inst->SetWindowless(bWindowless);
michael@0 2384 #endif
michael@0 2385 }
michael@0 2386 case NPPVpluginTransparentBool: {
michael@0 2387 NPBool bTransparent = (result != nullptr);
michael@0 2388 return inst->SetTransparent(bTransparent);
michael@0 2389 }
michael@0 2390
michael@0 2391 case NPPVjavascriptPushCallerBool: {
michael@0 2392 return NPERR_NO_ERROR;
michael@0 2393 }
michael@0 2394
michael@0 2395 case NPPVpluginKeepLibraryInMemory: {
michael@0 2396 NPBool bCached = (result != nullptr);
michael@0 2397 inst->SetCached(bCached);
michael@0 2398 return NPERR_NO_ERROR;
michael@0 2399 }
michael@0 2400
michael@0 2401 case NPPVpluginUsesDOMForCursorBool: {
michael@0 2402 bool useDOMForCursor = (result != nullptr);
michael@0 2403 return inst->SetUsesDOMForCursor(useDOMForCursor);
michael@0 2404 }
michael@0 2405
michael@0 2406 #ifndef MOZ_WIDGET_ANDROID
michael@0 2407 // On android, their 'drawing model' uses the same constant!
michael@0 2408 case NPPVpluginDrawingModel: {
michael@0 2409 if (inst) {
michael@0 2410 inst->SetDrawingModel((NPDrawingModel)NS_PTR_TO_INT32(result));
michael@0 2411 return NPERR_NO_ERROR;
michael@0 2412 }
michael@0 2413 else {
michael@0 2414 return NPERR_GENERIC_ERROR;
michael@0 2415 }
michael@0 2416 }
michael@0 2417 #endif
michael@0 2418
michael@0 2419 #ifdef XP_MACOSX
michael@0 2420 case NPPVpluginEventModel: {
michael@0 2421 if (inst) {
michael@0 2422 inst->SetEventModel((NPEventModel)NS_PTR_TO_INT32(result));
michael@0 2423 return NPERR_NO_ERROR;
michael@0 2424 }
michael@0 2425 else {
michael@0 2426 return NPERR_GENERIC_ERROR;
michael@0 2427 }
michael@0 2428 }
michael@0 2429 #endif
michael@0 2430 #ifdef MOZ_WIDGET_ANDROID
michael@0 2431 case kRequestDrawingModel_ANPSetValue:
michael@0 2432 if (inst)
michael@0 2433 inst->SetANPDrawingModel(NS_PTR_TO_INT32(result));
michael@0 2434 return NPERR_NO_ERROR;
michael@0 2435 case kAcceptEvents_ANPSetValue:
michael@0 2436 return NPERR_NO_ERROR;
michael@0 2437 #endif
michael@0 2438 default:
michael@0 2439 return NPERR_GENERIC_ERROR;
michael@0 2440 }
michael@0 2441 }
michael@0 2442
michael@0 2443 NPError
michael@0 2444 _requestread(NPStream *pstream, NPByteRange *rangeList)
michael@0 2445 {
michael@0 2446 if (!NS_IsMainThread()) {
michael@0 2447 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_requestread called from the wrong thread\n"));
michael@0 2448 return NPERR_INVALID_PARAM;
michael@0 2449 }
michael@0 2450 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_RequestRead: stream=%p\n",
michael@0 2451 (void*)pstream));
michael@0 2452
michael@0 2453 #ifdef PLUGIN_LOGGING
michael@0 2454 for(NPByteRange * range = rangeList; range != nullptr; range = range->next)
michael@0 2455 PR_LOG(nsPluginLogging::gNPNLog,PLUGIN_LOG_NOISY,
michael@0 2456 ("%i-%i", range->offset, range->offset + range->length - 1));
michael@0 2457
michael@0 2458 PR_LOG(nsPluginLogging::gNPNLog,PLUGIN_LOG_NOISY, ("\n\n"));
michael@0 2459 PR_LogFlush();
michael@0 2460 #endif
michael@0 2461
michael@0 2462 if (!pstream || !rangeList || !pstream->ndata)
michael@0 2463 return NPERR_INVALID_PARAM;
michael@0 2464
michael@0 2465 nsNPAPIStreamWrapper* streamWrapper = static_cast<nsNPAPIStreamWrapper*>(pstream->ndata);
michael@0 2466 nsNPAPIPluginStreamListener* streamlistener = streamWrapper->GetStreamListener();
michael@0 2467 if (!streamlistener) {
michael@0 2468 return NPERR_GENERIC_ERROR;
michael@0 2469 }
michael@0 2470
michael@0 2471 int32_t streamtype = NP_NORMAL;
michael@0 2472
michael@0 2473 streamlistener->GetStreamType(&streamtype);
michael@0 2474
michael@0 2475 if (streamtype != NP_SEEK)
michael@0 2476 return NPERR_STREAM_NOT_SEEKABLE;
michael@0 2477
michael@0 2478 if (!streamlistener->mStreamListenerPeer)
michael@0 2479 return NPERR_GENERIC_ERROR;
michael@0 2480
michael@0 2481 nsresult rv = streamlistener->mStreamListenerPeer->RequestRead((NPByteRange *)rangeList);
michael@0 2482 if (NS_FAILED(rv))
michael@0 2483 return NPERR_GENERIC_ERROR;
michael@0 2484
michael@0 2485 return NPERR_NO_ERROR;
michael@0 2486 }
michael@0 2487
michael@0 2488 // Deprecated, only stubbed out
michael@0 2489 void* /* OJI type: JRIEnv* */
michael@0 2490 _getJavaEnv()
michael@0 2491 {
michael@0 2492 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_GetJavaEnv\n"));
michael@0 2493 return nullptr;
michael@0 2494 }
michael@0 2495
michael@0 2496 const char *
michael@0 2497 _useragent(NPP npp)
michael@0 2498 {
michael@0 2499 if (!NS_IsMainThread()) {
michael@0 2500 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_useragent called from the wrong thread\n"));
michael@0 2501 return nullptr;
michael@0 2502 }
michael@0 2503 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_UserAgent: npp=%p\n", (void*)npp));
michael@0 2504
michael@0 2505 nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
michael@0 2506 nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
michael@0 2507 if (!pluginHost) {
michael@0 2508 return nullptr;
michael@0 2509 }
michael@0 2510
michael@0 2511 const char *retstr;
michael@0 2512 nsresult rv = pluginHost->UserAgent(&retstr);
michael@0 2513 if (NS_FAILED(rv))
michael@0 2514 return nullptr;
michael@0 2515
michael@0 2516 return retstr;
michael@0 2517 }
michael@0 2518
michael@0 2519 void *
michael@0 2520 _memalloc (uint32_t size)
michael@0 2521 {
michael@0 2522 if (!NS_IsMainThread()) {
michael@0 2523 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,("NPN_memalloc called from the wrong thread\n"));
michael@0 2524 }
michael@0 2525 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY, ("NPN_MemAlloc: size=%d\n", size));
michael@0 2526 return nsMemory::Alloc(size);
michael@0 2527 }
michael@0 2528
michael@0 2529 // Deprecated, only stubbed out
michael@0 2530 void* /* OJI type: jref */
michael@0 2531 _getJavaPeer(NPP npp)
michael@0 2532 {
michael@0 2533 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_GetJavaPeer: npp=%p\n", (void*)npp));
michael@0 2534 return nullptr;
michael@0 2535 }
michael@0 2536
michael@0 2537 void
michael@0 2538 _pushpopupsenabledstate(NPP npp, NPBool enabled)
michael@0 2539 {
michael@0 2540 if (!NS_IsMainThread()) {
michael@0 2541 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_pushpopupsenabledstate called from the wrong thread\n"));
michael@0 2542 return;
michael@0 2543 }
michael@0 2544 nsNPAPIPluginInstance *inst = npp ? (nsNPAPIPluginInstance *)npp->ndata : nullptr;
michael@0 2545 if (!inst)
michael@0 2546 return;
michael@0 2547
michael@0 2548 inst->PushPopupsEnabledState(enabled);
michael@0 2549 }
michael@0 2550
michael@0 2551 void
michael@0 2552 _poppopupsenabledstate(NPP npp)
michael@0 2553 {
michael@0 2554 if (!NS_IsMainThread()) {
michael@0 2555 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_poppopupsenabledstate called from the wrong thread\n"));
michael@0 2556 return;
michael@0 2557 }
michael@0 2558 nsNPAPIPluginInstance *inst = npp ? (nsNPAPIPluginInstance *)npp->ndata : nullptr;
michael@0 2559 if (!inst)
michael@0 2560 return;
michael@0 2561
michael@0 2562 inst->PopPopupsEnabledState();
michael@0 2563 }
michael@0 2564
michael@0 2565 void
michael@0 2566 _pluginthreadasynccall(NPP instance, PluginThreadCallback func, void *userData)
michael@0 2567 {
michael@0 2568 if (NS_IsMainThread()) {
michael@0 2569 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,("NPN_pluginthreadasynccall called from the main thread\n"));
michael@0 2570 } else {
michael@0 2571 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,("NPN_pluginthreadasynccall called from a non main thread\n"));
michael@0 2572 }
michael@0 2573 nsRefPtr<nsPluginThreadRunnable> evt =
michael@0 2574 new nsPluginThreadRunnable(instance, func, userData);
michael@0 2575
michael@0 2576 if (evt && evt->IsValid()) {
michael@0 2577 NS_DispatchToMainThread(evt);
michael@0 2578 }
michael@0 2579 }
michael@0 2580
michael@0 2581 NPError
michael@0 2582 _getvalueforurl(NPP instance, NPNURLVariable variable, const char *url,
michael@0 2583 char **value, uint32_t *len)
michael@0 2584 {
michael@0 2585 if (!instance) {
michael@0 2586 return NPERR_INVALID_PARAM;
michael@0 2587 }
michael@0 2588
michael@0 2589 if (!url || !*url || !len) {
michael@0 2590 return NPERR_INVALID_URL;
michael@0 2591 }
michael@0 2592
michael@0 2593 *len = 0;
michael@0 2594
michael@0 2595 switch (variable) {
michael@0 2596 case NPNURLVProxy:
michael@0 2597 {
michael@0 2598 nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
michael@0 2599 nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
michael@0 2600 if (pluginHost && NS_SUCCEEDED(pluginHost->FindProxyForURL(url, value))) {
michael@0 2601 *len = *value ? strlen(*value) : 0;
michael@0 2602 return NPERR_NO_ERROR;
michael@0 2603 }
michael@0 2604 break;
michael@0 2605 }
michael@0 2606 case NPNURLVCookie:
michael@0 2607 {
michael@0 2608 nsCOMPtr<nsICookieService> cookieService =
michael@0 2609 do_GetService(NS_COOKIESERVICE_CONTRACTID);
michael@0 2610
michael@0 2611 if (!cookieService)
michael@0 2612 return NPERR_GENERIC_ERROR;
michael@0 2613
michael@0 2614 // Make an nsURI from the url argument
michael@0 2615 nsCOMPtr<nsIURI> uri;
michael@0 2616 if (NS_FAILED(NS_NewURI(getter_AddRefs(uri), nsDependentCString(url)))) {
michael@0 2617 return NPERR_GENERIC_ERROR;
michael@0 2618 }
michael@0 2619
michael@0 2620 nsCOMPtr<nsIChannel> channel = GetChannelFromNPP(instance);
michael@0 2621
michael@0 2622 if (NS_FAILED(cookieService->GetCookieString(uri, channel, value)) ||
michael@0 2623 !*value) {
michael@0 2624 return NPERR_GENERIC_ERROR;
michael@0 2625 }
michael@0 2626
michael@0 2627 *len = strlen(*value);
michael@0 2628 return NPERR_NO_ERROR;
michael@0 2629 }
michael@0 2630
michael@0 2631 break;
michael@0 2632 default:
michael@0 2633 // Fall through and return an error...
michael@0 2634 ;
michael@0 2635 }
michael@0 2636
michael@0 2637 return NPERR_GENERIC_ERROR;
michael@0 2638 }
michael@0 2639
michael@0 2640 NPError
michael@0 2641 _setvalueforurl(NPP instance, NPNURLVariable variable, const char *url,
michael@0 2642 const char *value, uint32_t len)
michael@0 2643 {
michael@0 2644 if (!instance) {
michael@0 2645 return NPERR_INVALID_PARAM;
michael@0 2646 }
michael@0 2647
michael@0 2648 if (!url || !*url) {
michael@0 2649 return NPERR_INVALID_URL;
michael@0 2650 }
michael@0 2651
michael@0 2652 switch (variable) {
michael@0 2653 case NPNURLVCookie:
michael@0 2654 {
michael@0 2655 if (!url || !value || (0 >= len))
michael@0 2656 return NPERR_INVALID_PARAM;
michael@0 2657
michael@0 2658 nsresult rv = NS_ERROR_FAILURE;
michael@0 2659 nsCOMPtr<nsIIOService> ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
michael@0 2660 if (NS_FAILED(rv))
michael@0 2661 return NPERR_GENERIC_ERROR;
michael@0 2662
michael@0 2663 nsCOMPtr<nsICookieService> cookieService = do_GetService(NS_COOKIESERVICE_CONTRACTID, &rv);
michael@0 2664 if (NS_FAILED(rv))
michael@0 2665 return NPERR_GENERIC_ERROR;
michael@0 2666
michael@0 2667 nsCOMPtr<nsIURI> uriIn;
michael@0 2668 rv = ioService->NewURI(nsDependentCString(url), nullptr, nullptr, getter_AddRefs(uriIn));
michael@0 2669 if (NS_FAILED(rv))
michael@0 2670 return NPERR_GENERIC_ERROR;
michael@0 2671
michael@0 2672 nsCOMPtr<nsIChannel> channel = GetChannelFromNPP(instance);
michael@0 2673
michael@0 2674 char *cookie = (char*)value;
michael@0 2675 char c = cookie[len];
michael@0 2676 cookie[len] = '\0';
michael@0 2677 rv = cookieService->SetCookieString(uriIn, nullptr, cookie, channel);
michael@0 2678 cookie[len] = c;
michael@0 2679 if (NS_SUCCEEDED(rv))
michael@0 2680 return NPERR_NO_ERROR;
michael@0 2681 }
michael@0 2682
michael@0 2683 break;
michael@0 2684 case NPNURLVProxy:
michael@0 2685 // We don't support setting proxy values, fall through...
michael@0 2686 default:
michael@0 2687 // Fall through and return an error...
michael@0 2688 ;
michael@0 2689 }
michael@0 2690
michael@0 2691 return NPERR_GENERIC_ERROR;
michael@0 2692 }
michael@0 2693
michael@0 2694 NPError
michael@0 2695 _getauthenticationinfo(NPP instance, const char *protocol, const char *host,
michael@0 2696 int32_t port, const char *scheme, const char *realm,
michael@0 2697 char **username, uint32_t *ulen, char **password,
michael@0 2698 uint32_t *plen)
michael@0 2699 {
michael@0 2700 if (!instance || !protocol || !host || !scheme || !realm || !username ||
michael@0 2701 !ulen || !password || !plen)
michael@0 2702 return NPERR_INVALID_PARAM;
michael@0 2703
michael@0 2704 *username = nullptr;
michael@0 2705 *password = nullptr;
michael@0 2706 *ulen = 0;
michael@0 2707 *plen = 0;
michael@0 2708
michael@0 2709 nsDependentCString proto(protocol);
michael@0 2710
michael@0 2711 if (!proto.LowerCaseEqualsLiteral("http") &&
michael@0 2712 !proto.LowerCaseEqualsLiteral("https"))
michael@0 2713 return NPERR_GENERIC_ERROR;
michael@0 2714
michael@0 2715 nsCOMPtr<nsIHttpAuthManager> authManager =
michael@0 2716 do_GetService("@mozilla.org/network/http-auth-manager;1");
michael@0 2717 if (!authManager)
michael@0 2718 return NPERR_GENERIC_ERROR;
michael@0 2719
michael@0 2720 nsNPAPIPluginInstance *inst = static_cast<nsNPAPIPluginInstance*>(instance->ndata);
michael@0 2721 if (!inst)
michael@0 2722 return NPERR_GENERIC_ERROR;
michael@0 2723
michael@0 2724 bool authPrivate = false;
michael@0 2725 if (NS_FAILED(inst->IsPrivateBrowsing(&authPrivate)))
michael@0 2726 return NPERR_GENERIC_ERROR;
michael@0 2727
michael@0 2728 nsIDocument *doc = GetDocumentFromNPP(instance);
michael@0 2729 NS_ENSURE_TRUE(doc, NPERR_GENERIC_ERROR);
michael@0 2730 nsIPrincipal *principal = doc->NodePrincipal();
michael@0 2731
michael@0 2732 nsAutoString unused, uname16, pwd16;
michael@0 2733 if (NS_FAILED(authManager->GetAuthIdentity(proto, nsDependentCString(host),
michael@0 2734 port, nsDependentCString(scheme),
michael@0 2735 nsDependentCString(realm),
michael@0 2736 EmptyCString(), unused, uname16,
michael@0 2737 pwd16, authPrivate, principal))) {
michael@0 2738 return NPERR_GENERIC_ERROR;
michael@0 2739 }
michael@0 2740
michael@0 2741 NS_ConvertUTF16toUTF8 uname8(uname16);
michael@0 2742 NS_ConvertUTF16toUTF8 pwd8(pwd16);
michael@0 2743
michael@0 2744 *username = ToNewCString(uname8);
michael@0 2745 *ulen = *username ? uname8.Length() : 0;
michael@0 2746
michael@0 2747 *password = ToNewCString(pwd8);
michael@0 2748 *plen = *password ? pwd8.Length() : 0;
michael@0 2749
michael@0 2750 return NPERR_NO_ERROR;
michael@0 2751 }
michael@0 2752
michael@0 2753 uint32_t
michael@0 2754 _scheduletimer(NPP instance, uint32_t interval, NPBool repeat, PluginTimerFunc timerFunc)
michael@0 2755 {
michael@0 2756 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
michael@0 2757 if (!inst)
michael@0 2758 return 0;
michael@0 2759
michael@0 2760 return inst->ScheduleTimer(interval, repeat, timerFunc);
michael@0 2761 }
michael@0 2762
michael@0 2763 void
michael@0 2764 _unscheduletimer(NPP instance, uint32_t timerID)
michael@0 2765 {
michael@0 2766 #ifdef MOZ_WIDGET_ANDROID
michael@0 2767 // Sometimes Flash calls this with a dead NPP instance. Ensure the one we have
michael@0 2768 // here is valid and maps to a nsNPAPIPluginInstance.
michael@0 2769 nsNPAPIPluginInstance *inst = nsNPAPIPluginInstance::GetFromNPP(instance);
michael@0 2770 #else
michael@0 2771 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
michael@0 2772 #endif
michael@0 2773 if (!inst)
michael@0 2774 return;
michael@0 2775
michael@0 2776 inst->UnscheduleTimer(timerID);
michael@0 2777 }
michael@0 2778
michael@0 2779 NPError
michael@0 2780 _popupcontextmenu(NPP instance, NPMenu* menu)
michael@0 2781 {
michael@0 2782 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
michael@0 2783 if (!inst)
michael@0 2784 return NPERR_GENERIC_ERROR;
michael@0 2785
michael@0 2786 return inst->PopUpContextMenu(menu);
michael@0 2787 }
michael@0 2788
michael@0 2789 NPError
michael@0 2790 _initasyncsurface(NPP instance, NPSize *size, NPImageFormat format, void *initData, NPAsyncSurface *surface)
michael@0 2791 {
michael@0 2792 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
michael@0 2793 if (!inst)
michael@0 2794 return NPERR_GENERIC_ERROR;
michael@0 2795
michael@0 2796 return inst->InitAsyncSurface(size, format, initData, surface);
michael@0 2797 }
michael@0 2798
michael@0 2799 NPError
michael@0 2800 _finalizeasyncsurface(NPP instance, NPAsyncSurface *surface)
michael@0 2801 {
michael@0 2802 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
michael@0 2803 if (!inst)
michael@0 2804 return NPERR_GENERIC_ERROR;
michael@0 2805
michael@0 2806 return inst->FinalizeAsyncSurface(surface);
michael@0 2807 }
michael@0 2808
michael@0 2809 void
michael@0 2810 _setcurrentasyncsurface(NPP instance, NPAsyncSurface *surface, NPRect *changed)
michael@0 2811 {
michael@0 2812 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
michael@0 2813 if (!inst)
michael@0 2814 return;
michael@0 2815
michael@0 2816 inst->SetCurrentAsyncSurface(surface, changed);
michael@0 2817 }
michael@0 2818
michael@0 2819 NPBool
michael@0 2820 _convertpoint(NPP instance, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace)
michael@0 2821 {
michael@0 2822 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
michael@0 2823 if (!inst)
michael@0 2824 return false;
michael@0 2825
michael@0 2826 return inst->ConvertPoint(sourceX, sourceY, sourceSpace, destX, destY, destSpace);
michael@0 2827 }
michael@0 2828
michael@0 2829 void
michael@0 2830 _urlredirectresponse(NPP instance, void* notifyData, NPBool allow)
michael@0 2831 {
michael@0 2832 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
michael@0 2833 if (!inst) {
michael@0 2834 return;
michael@0 2835 }
michael@0 2836
michael@0 2837 inst->URLRedirectResponse(notifyData, allow);
michael@0 2838 }
michael@0 2839
michael@0 2840 } /* namespace parent */
michael@0 2841 } /* namespace plugins */
michael@0 2842 } /* namespace mozilla */

mercurial