dom/plugins/ipc/PluginModuleChild.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
michael@0 2 /* vim: set sw=4 ts=4 et : */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #ifdef MOZ_WIDGET_QT
michael@0 8 #include <unistd.h> // for _exit()
michael@0 9 #include <QtCore/QTimer>
michael@0 10 #include "nsQAppInstance.h"
michael@0 11 #include "NestedLoopTimer.h"
michael@0 12 #endif
michael@0 13
michael@0 14 #include "mozilla/plugins/PluginModuleChild.h"
michael@0 15
michael@0 16 /* This must occur *after* plugins/PluginModuleChild.h to avoid typedefs conflicts. */
michael@0 17 #include "mozilla/ArrayUtils.h"
michael@0 18
michael@0 19 #include "mozilla/ipc/MessageChannel.h"
michael@0 20
michael@0 21 #ifdef MOZ_WIDGET_GTK
michael@0 22 #include <gtk/gtk.h>
michael@0 23 #if (MOZ_WIDGET_GTK == 3)
michael@0 24 #include <gtk/gtkx.h>
michael@0 25 #endif
michael@0 26 #endif
michael@0 27
michael@0 28 #include "nsIFile.h"
michael@0 29
michael@0 30 #include "pratom.h"
michael@0 31 #include "nsDebug.h"
michael@0 32 #include "nsCOMPtr.h"
michael@0 33 #include "nsPluginsDir.h"
michael@0 34 #include "nsXULAppAPI.h"
michael@0 35
michael@0 36 #ifdef MOZ_X11
michael@0 37 # include "mozilla/X11Util.h"
michael@0 38 #endif
michael@0 39 #include "mozilla/plugins/PluginInstanceChild.h"
michael@0 40 #include "mozilla/plugins/StreamNotifyChild.h"
michael@0 41 #include "mozilla/plugins/BrowserStreamChild.h"
michael@0 42 #include "mozilla/plugins/PluginStreamChild.h"
michael@0 43 #include "PluginIdentifierChild.h"
michael@0 44 #include "mozilla/dom/CrashReporterChild.h"
michael@0 45
michael@0 46 #include "nsNPAPIPlugin.h"
michael@0 47
michael@0 48 #ifdef XP_WIN
michael@0 49 #include "COMMessageFilter.h"
michael@0 50 #include "nsWindowsDllInterceptor.h"
michael@0 51 #include "mozilla/widget/AudioSession.h"
michael@0 52 #endif
michael@0 53
michael@0 54 #ifdef MOZ_WIDGET_COCOA
michael@0 55 #include "PluginInterposeOSX.h"
michael@0 56 #include "PluginUtilsOSX.h"
michael@0 57 #endif
michael@0 58
michael@0 59 #include "GeckoProfiler.h"
michael@0 60
michael@0 61 using namespace mozilla;
michael@0 62 using namespace mozilla::plugins;
michael@0 63 using mozilla::dom::CrashReporterChild;
michael@0 64 using mozilla::dom::PCrashReporterChild;
michael@0 65
michael@0 66 #if defined(XP_WIN)
michael@0 67 const wchar_t * kFlashFullscreenClass = L"ShockwaveFlashFullScreen";
michael@0 68 const wchar_t * kMozillaWindowClass = L"MozillaWindowClass";
michael@0 69 #endif
michael@0 70
michael@0 71 namespace {
michael@0 72 PluginModuleChild* gInstance = nullptr;
michael@0 73 }
michael@0 74
michael@0 75 #ifdef MOZ_WIDGET_QT
michael@0 76 typedef void (*_gtk_init_fn)(int argc, char **argv);
michael@0 77 static _gtk_init_fn s_gtk_init = nullptr;
michael@0 78 static PRLibrary *sGtkLib = nullptr;
michael@0 79 #endif
michael@0 80
michael@0 81 #ifdef XP_WIN
michael@0 82 // Used with fix for flash fullscreen window loosing focus.
michael@0 83 static bool gDelayFlashFocusReplyUntilEval = false;
michael@0 84 // Used to fix GetWindowInfo problems with internal flash settings dialogs
michael@0 85 static WindowsDllInterceptor sUser32Intercept;
michael@0 86 typedef BOOL (WINAPI *GetWindowInfoPtr)(HWND hwnd, PWINDOWINFO pwi);
michael@0 87 static GetWindowInfoPtr sGetWindowInfoPtrStub = nullptr;
michael@0 88 static HWND sBrowserHwnd = nullptr;
michael@0 89 #endif
michael@0 90
michael@0 91 PluginModuleChild::PluginModuleChild()
michael@0 92 : mLibrary(0)
michael@0 93 , mPluginFilename("")
michael@0 94 , mQuirks(QUIRKS_NOT_INITIALIZED)
michael@0 95 , mShutdownFunc(0)
michael@0 96 , mInitializeFunc(0)
michael@0 97 #if defined(OS_WIN) || defined(OS_MACOSX)
michael@0 98 , mGetEntryPointsFunc(0)
michael@0 99 #elif defined(MOZ_WIDGET_GTK)
michael@0 100 , mNestedLoopTimerId(0)
michael@0 101 #elif defined(MOZ_WIDGET_QT)
michael@0 102 , mNestedLoopTimerObject(0)
michael@0 103 #endif
michael@0 104 #ifdef OS_WIN
michael@0 105 , mNestedEventHook(nullptr)
michael@0 106 , mGlobalCallWndProcHook(nullptr)
michael@0 107 #endif
michael@0 108 {
michael@0 109 NS_ASSERTION(!gInstance, "Something terribly wrong here!");
michael@0 110 memset(&mFunctions, 0, sizeof(mFunctions));
michael@0 111 memset(&mSavedData, 0, sizeof(mSavedData));
michael@0 112 gInstance = this;
michael@0 113 mUserAgent.SetIsVoid(true);
michael@0 114 #ifdef XP_MACOSX
michael@0 115 mac_plugin_interposing::child::SetUpCocoaInterposing();
michael@0 116 #endif
michael@0 117 }
michael@0 118
michael@0 119 PluginModuleChild::~PluginModuleChild()
michael@0 120 {
michael@0 121 NS_ASSERTION(gInstance == this, "Something terribly wrong here!");
michael@0 122
michael@0 123 // We don't unload the plugin library in case it uses atexit handlers or
michael@0 124 // other similar hooks.
michael@0 125
michael@0 126 DeinitGraphics();
michael@0 127
michael@0 128 gInstance = nullptr;
michael@0 129 }
michael@0 130
michael@0 131 // static
michael@0 132 PluginModuleChild*
michael@0 133 PluginModuleChild::current()
michael@0 134 {
michael@0 135 NS_ASSERTION(gInstance, "Null instance!");
michael@0 136 return gInstance;
michael@0 137 }
michael@0 138
michael@0 139 bool
michael@0 140 PluginModuleChild::Init(const std::string& aPluginFilename,
michael@0 141 base::ProcessHandle aParentProcessHandle,
michael@0 142 MessageLoop* aIOLoop,
michael@0 143 IPC::Channel* aChannel)
michael@0 144 {
michael@0 145 PLUGIN_LOG_DEBUG_METHOD;
michael@0 146
michael@0 147 GetIPCChannel()->SetAbortOnError(true);
michael@0 148
michael@0 149 // Request Windows message deferral behavior on our channel. This
michael@0 150 // applies to the top level and all sub plugin protocols since they
michael@0 151 // all share the same channel.
michael@0 152 GetIPCChannel()->SetChannelFlags(MessageChannel::REQUIRE_DEFERRED_MESSAGE_PROTECTION);
michael@0 153
michael@0 154 #ifdef XP_WIN
michael@0 155 COMMessageFilter::Initialize(this);
michael@0 156 #endif
michael@0 157
michael@0 158 NS_ASSERTION(aChannel, "need a channel");
michael@0 159
michael@0 160 if (!InitGraphics())
michael@0 161 return false;
michael@0 162
michael@0 163 mPluginFilename = aPluginFilename.c_str();
michael@0 164 nsCOMPtr<nsIFile> localFile;
michael@0 165 NS_NewLocalFile(NS_ConvertUTF8toUTF16(mPluginFilename),
michael@0 166 true,
michael@0 167 getter_AddRefs(localFile));
michael@0 168
michael@0 169 bool exists;
michael@0 170 localFile->Exists(&exists);
michael@0 171 NS_ASSERTION(exists, "plugin file ain't there");
michael@0 172
michael@0 173 nsPluginFile pluginFile(localFile);
michael@0 174
michael@0 175 #if defined(MOZ_X11) || defined(OS_MACOSX)
michael@0 176 nsPluginInfo info = nsPluginInfo();
michael@0 177 if (NS_FAILED(pluginFile.GetPluginInfo(info, &mLibrary))) {
michael@0 178 return false;
michael@0 179 }
michael@0 180
michael@0 181 #if defined(MOZ_X11)
michael@0 182 NS_NAMED_LITERAL_CSTRING(flash10Head, "Shockwave Flash 10.");
michael@0 183 if (StringBeginsWith(nsDependentCString(info.fDescription), flash10Head)) {
michael@0 184 AddQuirk(QUIRK_FLASH_EXPOSE_COORD_TRANSLATION);
michael@0 185 }
michael@0 186 #else // defined(OS_MACOSX)
michael@0 187 mozilla::plugins::PluginUtilsOSX::SetProcessName(info.fName);
michael@0 188 #endif
michael@0 189
michael@0 190 pluginFile.FreePluginInfo(info);
michael@0 191
michael@0 192 if (!mLibrary)
michael@0 193 #endif
michael@0 194 {
michael@0 195 nsresult rv = pluginFile.LoadPlugin(&mLibrary);
michael@0 196 if (NS_FAILED(rv))
michael@0 197 return false;
michael@0 198 }
michael@0 199 NS_ASSERTION(mLibrary, "couldn't open shared object");
michael@0 200
michael@0 201 if (!Open(aChannel, aParentProcessHandle, aIOLoop))
michael@0 202 return false;
michael@0 203
michael@0 204 memset((void*) &mFunctions, 0, sizeof(mFunctions));
michael@0 205 mFunctions.size = sizeof(mFunctions);
michael@0 206 mFunctions.version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
michael@0 207
michael@0 208 // TODO: use PluginPRLibrary here
michael@0 209
michael@0 210 #if defined(OS_LINUX) || defined(OS_BSD)
michael@0 211 mShutdownFunc =
michael@0 212 (NP_PLUGINSHUTDOWN) PR_FindFunctionSymbol(mLibrary, "NP_Shutdown");
michael@0 213
michael@0 214 // create the new plugin handler
michael@0 215
michael@0 216 mInitializeFunc =
michael@0 217 (NP_PLUGINUNIXINIT) PR_FindFunctionSymbol(mLibrary, "NP_Initialize");
michael@0 218 NS_ASSERTION(mInitializeFunc, "couldn't find NP_Initialize()");
michael@0 219
michael@0 220 #elif defined(OS_WIN) || defined(OS_MACOSX)
michael@0 221 mShutdownFunc =
michael@0 222 (NP_PLUGINSHUTDOWN)PR_FindFunctionSymbol(mLibrary, "NP_Shutdown");
michael@0 223
michael@0 224 mGetEntryPointsFunc =
michael@0 225 (NP_GETENTRYPOINTS)PR_FindSymbol(mLibrary, "NP_GetEntryPoints");
michael@0 226 NS_ENSURE_TRUE(mGetEntryPointsFunc, false);
michael@0 227
michael@0 228 mInitializeFunc =
michael@0 229 (NP_PLUGININIT)PR_FindFunctionSymbol(mLibrary, "NP_Initialize");
michael@0 230 NS_ENSURE_TRUE(mInitializeFunc, false);
michael@0 231 #else
michael@0 232
michael@0 233 # error Please copy the initialization code from nsNPAPIPlugin.cpp
michael@0 234
michael@0 235 #endif
michael@0 236
michael@0 237 return true;
michael@0 238 }
michael@0 239
michael@0 240 #if defined(MOZ_WIDGET_GTK)
michael@0 241 typedef void (*GObjectDisposeFn)(GObject*);
michael@0 242 typedef gboolean (*GtkWidgetScrollEventFn)(GtkWidget*, GdkEventScroll*);
michael@0 243 typedef void (*GtkPlugEmbeddedFn)(GtkPlug*);
michael@0 244
michael@0 245 static GObjectDisposeFn real_gtk_plug_dispose;
michael@0 246 static GtkPlugEmbeddedFn real_gtk_plug_embedded;
michael@0 247
michael@0 248 static void
michael@0 249 undo_bogus_unref(gpointer data, GObject* object, gboolean is_last_ref) {
michael@0 250 if (!is_last_ref) // recursion in g_object_ref
michael@0 251 return;
michael@0 252
michael@0 253 g_object_ref(object);
michael@0 254 }
michael@0 255
michael@0 256 static void
michael@0 257 wrap_gtk_plug_dispose(GObject* object) {
michael@0 258 // Work around Flash Player bug described in bug 538914.
michael@0 259 //
michael@0 260 // This function is called during gtk_widget_destroy and/or before
michael@0 261 // the object's last reference is removed. A reference to the
michael@0 262 // object is held during the call so the ref count should not drop
michael@0 263 // to zero. However, Flash Player tries to destroy the GtkPlug
michael@0 264 // using g_object_unref instead of gtk_widget_destroy. The
michael@0 265 // reference that Flash is removing actually belongs to the
michael@0 266 // GtkPlug. During real_gtk_plug_dispose, the GtkPlug removes its
michael@0 267 // reference.
michael@0 268 //
michael@0 269 // A toggle ref is added to prevent premature deletion of the object
michael@0 270 // caused by Flash Player's extra unref, and to detect when there are
michael@0 271 // unexpectedly no other references.
michael@0 272 g_object_add_toggle_ref(object, undo_bogus_unref, nullptr);
michael@0 273 (*real_gtk_plug_dispose)(object);
michael@0 274 g_object_remove_toggle_ref(object, undo_bogus_unref, nullptr);
michael@0 275 }
michael@0 276
michael@0 277 static gboolean
michael@0 278 gtk_plug_scroll_event(GtkWidget *widget, GdkEventScroll *gdk_event)
michael@0 279 {
michael@0 280 if (!gtk_widget_is_toplevel(widget)) // in same process as its GtkSocket
michael@0 281 return FALSE; // event not handled; propagate to GtkSocket
michael@0 282
michael@0 283 GdkWindow* socket_window = gtk_plug_get_socket_window(GTK_PLUG(widget));
michael@0 284 if (!socket_window)
michael@0 285 return FALSE;
michael@0 286
michael@0 287 // Propagate the event to the embedder.
michael@0 288 GdkScreen* screen = gdk_window_get_screen(socket_window);
michael@0 289 GdkWindow* plug_window = gtk_widget_get_window(widget);
michael@0 290 GdkWindow* event_window = gdk_event->window;
michael@0 291 gint x = gdk_event->x;
michael@0 292 gint y = gdk_event->y;
michael@0 293 unsigned int button;
michael@0 294 unsigned int button_mask = 0;
michael@0 295 XEvent xevent;
michael@0 296 Display* dpy = GDK_WINDOW_XDISPLAY(socket_window);
michael@0 297
michael@0 298 /* Translate the event coordinates to the plug window,
michael@0 299 * which should be aligned with the socket window.
michael@0 300 */
michael@0 301 while (event_window != plug_window)
michael@0 302 {
michael@0 303 gint dx, dy;
michael@0 304
michael@0 305 gdk_window_get_position(event_window, &dx, &dy);
michael@0 306 x += dx;
michael@0 307 y += dy;
michael@0 308
michael@0 309 event_window = gdk_window_get_parent(event_window);
michael@0 310 if (!event_window)
michael@0 311 return FALSE;
michael@0 312 }
michael@0 313
michael@0 314 switch (gdk_event->direction) {
michael@0 315 case GDK_SCROLL_UP:
michael@0 316 button = 4;
michael@0 317 button_mask = Button4Mask;
michael@0 318 break;
michael@0 319 case GDK_SCROLL_DOWN:
michael@0 320 button = 5;
michael@0 321 button_mask = Button5Mask;
michael@0 322 break;
michael@0 323 case GDK_SCROLL_LEFT:
michael@0 324 button = 6;
michael@0 325 break;
michael@0 326 case GDK_SCROLL_RIGHT:
michael@0 327 button = 7;
michael@0 328 break;
michael@0 329 default:
michael@0 330 return FALSE; // unknown GdkScrollDirection
michael@0 331 }
michael@0 332
michael@0 333 memset(&xevent, 0, sizeof(xevent));
michael@0 334 xevent.xbutton.type = ButtonPress;
michael@0 335 xevent.xbutton.window = gdk_x11_window_get_xid(socket_window);
michael@0 336 xevent.xbutton.root = gdk_x11_window_get_xid(gdk_screen_get_root_window(screen));
michael@0 337 xevent.xbutton.subwindow = gdk_x11_window_get_xid(plug_window);
michael@0 338 xevent.xbutton.time = gdk_event->time;
michael@0 339 xevent.xbutton.x = x;
michael@0 340 xevent.xbutton.y = y;
michael@0 341 xevent.xbutton.x_root = gdk_event->x_root;
michael@0 342 xevent.xbutton.y_root = gdk_event->y_root;
michael@0 343 xevent.xbutton.state = gdk_event->state;
michael@0 344 xevent.xbutton.button = button;
michael@0 345 xevent.xbutton.same_screen = True;
michael@0 346
michael@0 347 gdk_error_trap_push();
michael@0 348
michael@0 349 XSendEvent(dpy, xevent.xbutton.window,
michael@0 350 True, ButtonPressMask, &xevent);
michael@0 351
michael@0 352 xevent.xbutton.type = ButtonRelease;
michael@0 353 xevent.xbutton.state |= button_mask;
michael@0 354 XSendEvent(dpy, xevent.xbutton.window,
michael@0 355 True, ButtonReleaseMask, &xevent);
michael@0 356
michael@0 357 gdk_display_sync(gdk_screen_get_display(screen));
michael@0 358 gdk_error_trap_pop();
michael@0 359
michael@0 360 return TRUE; // event handled
michael@0 361 }
michael@0 362
michael@0 363 static void
michael@0 364 wrap_gtk_plug_embedded(GtkPlug* plug) {
michael@0 365 GdkWindow* socket_window = gtk_plug_get_socket_window(plug);
michael@0 366 if (socket_window) {
michael@0 367 if (gtk_check_version(2,18,7) != nullptr // older
michael@0 368 && g_object_get_data(G_OBJECT(socket_window),
michael@0 369 "moz-existed-before-set-window")) {
michael@0 370 // Add missing reference for
michael@0 371 // https://bugzilla.gnome.org/show_bug.cgi?id=607061
michael@0 372 g_object_ref(socket_window);
michael@0 373 }
michael@0 374
michael@0 375 // Ensure the window exists to make this GtkPlug behave like an
michael@0 376 // in-process GtkPlug for Flash Player. (Bugs 561308 and 539138).
michael@0 377 gtk_widget_realize(GTK_WIDGET(plug));
michael@0 378 }
michael@0 379
michael@0 380 if (*real_gtk_plug_embedded) {
michael@0 381 (*real_gtk_plug_embedded)(plug);
michael@0 382 }
michael@0 383 }
michael@0 384
michael@0 385 //
michael@0 386 // The next four constants are knobs that can be tuned. They trade
michael@0 387 // off potential UI lag from delayed event processing with CPU time.
michael@0 388 //
michael@0 389 static const gint kNestedLoopDetectorPriority = G_PRIORITY_HIGH_IDLE;
michael@0 390 // 90ms so that we can hopefully break livelocks before the user
michael@0 391 // notices UI lag (100ms)
michael@0 392 static const guint kNestedLoopDetectorIntervalMs = 90;
michael@0 393
michael@0 394 static const gint kBrowserEventPriority = G_PRIORITY_HIGH_IDLE;
michael@0 395 static const guint kBrowserEventIntervalMs = 10;
michael@0 396
michael@0 397 // static
michael@0 398 gboolean
michael@0 399 PluginModuleChild::DetectNestedEventLoop(gpointer data)
michael@0 400 {
michael@0 401 PluginModuleChild* pmc = static_cast<PluginModuleChild*>(data);
michael@0 402
michael@0 403 NS_ABORT_IF_FALSE(0 != pmc->mNestedLoopTimerId,
michael@0 404 "callback after descheduling");
michael@0 405 NS_ABORT_IF_FALSE(pmc->mTopLoopDepth < g_main_depth(),
michael@0 406 "not canceled before returning to main event loop!");
michael@0 407
michael@0 408 PLUGIN_LOG_DEBUG(("Detected nested glib event loop"));
michael@0 409
michael@0 410 // just detected a nested loop; start a timer that will
michael@0 411 // periodically rpc-call back into the browser and process some
michael@0 412 // events
michael@0 413 pmc->mNestedLoopTimerId =
michael@0 414 g_timeout_add_full(kBrowserEventPriority,
michael@0 415 kBrowserEventIntervalMs,
michael@0 416 PluginModuleChild::ProcessBrowserEvents,
michael@0 417 data,
michael@0 418 nullptr);
michael@0 419 // cancel the nested-loop detection timer
michael@0 420 return FALSE;
michael@0 421 }
michael@0 422
michael@0 423 // static
michael@0 424 gboolean
michael@0 425 PluginModuleChild::ProcessBrowserEvents(gpointer data)
michael@0 426 {
michael@0 427 PluginModuleChild* pmc = static_cast<PluginModuleChild*>(data);
michael@0 428
michael@0 429 NS_ABORT_IF_FALSE(pmc->mTopLoopDepth < g_main_depth(),
michael@0 430 "not canceled before returning to main event loop!");
michael@0 431
michael@0 432 pmc->CallProcessSomeEvents();
michael@0 433
michael@0 434 return TRUE;
michael@0 435 }
michael@0 436
michael@0 437 void
michael@0 438 PluginModuleChild::EnteredCxxStack()
michael@0 439 {
michael@0 440 NS_ABORT_IF_FALSE(0 == mNestedLoopTimerId,
michael@0 441 "previous timer not descheduled");
michael@0 442
michael@0 443 mNestedLoopTimerId =
michael@0 444 g_timeout_add_full(kNestedLoopDetectorPriority,
michael@0 445 kNestedLoopDetectorIntervalMs,
michael@0 446 PluginModuleChild::DetectNestedEventLoop,
michael@0 447 this,
michael@0 448 nullptr);
michael@0 449
michael@0 450 #ifdef DEBUG
michael@0 451 mTopLoopDepth = g_main_depth();
michael@0 452 #endif
michael@0 453 }
michael@0 454
michael@0 455 void
michael@0 456 PluginModuleChild::ExitedCxxStack()
michael@0 457 {
michael@0 458 NS_ABORT_IF_FALSE(0 < mNestedLoopTimerId,
michael@0 459 "nested loop timeout not scheduled");
michael@0 460
michael@0 461 g_source_remove(mNestedLoopTimerId);
michael@0 462 mNestedLoopTimerId = 0;
michael@0 463 }
michael@0 464 #elif defined (MOZ_WIDGET_QT)
michael@0 465
michael@0 466 void
michael@0 467 PluginModuleChild::EnteredCxxStack()
michael@0 468 {
michael@0 469 NS_ABORT_IF_FALSE(mNestedLoopTimerObject == nullptr,
michael@0 470 "previous timer not descheduled");
michael@0 471 mNestedLoopTimerObject = new NestedLoopTimer(this);
michael@0 472 QTimer::singleShot(kNestedLoopDetectorIntervalMs,
michael@0 473 mNestedLoopTimerObject, SLOT(timeOut()));
michael@0 474 }
michael@0 475
michael@0 476 void
michael@0 477 PluginModuleChild::ExitedCxxStack()
michael@0 478 {
michael@0 479 NS_ABORT_IF_FALSE(mNestedLoopTimerObject != nullptr,
michael@0 480 "nested loop timeout not scheduled");
michael@0 481 delete mNestedLoopTimerObject;
michael@0 482 mNestedLoopTimerObject = nullptr;
michael@0 483 }
michael@0 484
michael@0 485 #endif
michael@0 486
michael@0 487 bool
michael@0 488 PluginModuleChild::RecvSetParentHangTimeout(const uint32_t& aSeconds)
michael@0 489 {
michael@0 490 #ifdef XP_WIN
michael@0 491 SetReplyTimeoutMs(((aSeconds > 0) ? (1000 * aSeconds) : 0));
michael@0 492 #endif
michael@0 493 return true;
michael@0 494 }
michael@0 495
michael@0 496 bool
michael@0 497 PluginModuleChild::ShouldContinueFromReplyTimeout()
michael@0 498 {
michael@0 499 #ifdef XP_WIN
michael@0 500 NS_RUNTIMEABORT("terminating child process");
michael@0 501 #endif
michael@0 502 return true;
michael@0 503 }
michael@0 504
michael@0 505 bool
michael@0 506 PluginModuleChild::InitGraphics()
michael@0 507 {
michael@0 508 #if defined(MOZ_WIDGET_GTK)
michael@0 509 // Work around plugins that don't interact well with GDK
michael@0 510 // client-side windows.
michael@0 511 PR_SetEnv("GDK_NATIVE_WINDOWS=1");
michael@0 512
michael@0 513 gtk_init(0, 0);
michael@0 514
michael@0 515 // GtkPlug is a static class so will leak anyway but this ref makes sure.
michael@0 516 gpointer gtk_plug_class = g_type_class_ref(GTK_TYPE_PLUG);
michael@0 517
michael@0 518 // The dispose method is a good place to hook into the destruction process
michael@0 519 // because the reference count should be 1 the last time dispose is
michael@0 520 // called. (Toggle references wouldn't detect if the reference count
michael@0 521 // might be higher.)
michael@0 522 GObjectDisposeFn* dispose = &G_OBJECT_CLASS(gtk_plug_class)->dispose;
michael@0 523 NS_ABORT_IF_FALSE(*dispose != wrap_gtk_plug_dispose,
michael@0 524 "InitGraphics called twice");
michael@0 525 real_gtk_plug_dispose = *dispose;
michael@0 526 *dispose = wrap_gtk_plug_dispose;
michael@0 527
michael@0 528 // If we ever stop setting GDK_NATIVE_WINDOWS, we'll also need to
michael@0 529 // gtk_widget_add_events GDK_SCROLL_MASK or GDK client-side windows will
michael@0 530 // not tell us about the scroll events that it intercepts. With native
michael@0 531 // windows, this is called when GDK intercepts the events; if GDK doesn't
michael@0 532 // intercept the events, then the X server will instead send them directly
michael@0 533 // to an ancestor (embedder) window.
michael@0 534 GtkWidgetScrollEventFn* scroll_event =
michael@0 535 &GTK_WIDGET_CLASS(gtk_plug_class)->scroll_event;
michael@0 536 if (!*scroll_event) {
michael@0 537 *scroll_event = gtk_plug_scroll_event;
michael@0 538 }
michael@0 539
michael@0 540 GtkPlugEmbeddedFn* embedded = &GTK_PLUG_CLASS(gtk_plug_class)->embedded;
michael@0 541 real_gtk_plug_embedded = *embedded;
michael@0 542 *embedded = wrap_gtk_plug_embedded;
michael@0 543
michael@0 544 #elif defined(MOZ_WIDGET_QT)
michael@0 545 nsQAppInstance::AddRef();
michael@0 546 // Work around plugins that don't interact well without gtk initialized
michael@0 547 // see bug 566845
michael@0 548 #if defined(MOZ_X11)
michael@0 549 if (!sGtkLib)
michael@0 550 sGtkLib = PR_LoadLibrary("libgtk-x11-2.0.so.0");
michael@0 551 #endif
michael@0 552 if (sGtkLib) {
michael@0 553 s_gtk_init = (_gtk_init_fn)PR_FindFunctionSymbol(sGtkLib, "gtk_init");
michael@0 554 if (s_gtk_init)
michael@0 555 s_gtk_init(0, 0);
michael@0 556 }
michael@0 557 #else
michael@0 558 // may not be necessary on all platforms
michael@0 559 #endif
michael@0 560 #ifdef MOZ_X11
michael@0 561 // Do this after initializing GDK, or GDK will install its own handler.
michael@0 562 XRE_InstallX11ErrorHandler();
michael@0 563 #endif
michael@0 564 return true;
michael@0 565 }
michael@0 566
michael@0 567 void
michael@0 568 PluginModuleChild::DeinitGraphics()
michael@0 569 {
michael@0 570 #ifdef MOZ_WIDGET_QT
michael@0 571 nsQAppInstance::Release();
michael@0 572 if (sGtkLib) {
michael@0 573 PR_UnloadLibrary(sGtkLib);
michael@0 574 sGtkLib = nullptr;
michael@0 575 s_gtk_init = nullptr;
michael@0 576 }
michael@0 577 #endif
michael@0 578
michael@0 579 #if defined(MOZ_X11) && defined(NS_FREE_PERMANENT_DATA)
michael@0 580 // We free some data off of XDisplay close hooks, ensure they're
michael@0 581 // run. Closing the display is pretty scary, so we only do it to
michael@0 582 // silence leak checkers.
michael@0 583 XCloseDisplay(DefaultXDisplay());
michael@0 584 #endif
michael@0 585 }
michael@0 586
michael@0 587 bool
michael@0 588 PluginModuleChild::AnswerNP_Shutdown(NPError *rv)
michael@0 589 {
michael@0 590 AssertPluginThread();
michael@0 591
michael@0 592 #if defined XP_WIN
michael@0 593 mozilla::widget::StopAudioSession();
michael@0 594 #endif
michael@0 595
michael@0 596 // the PluginModuleParent shuts down this process after this interrupt
michael@0 597 // call pops off its stack
michael@0 598
michael@0 599 *rv = mShutdownFunc ? mShutdownFunc() : NPERR_NO_ERROR;
michael@0 600
michael@0 601 // weakly guard against re-entry after NP_Shutdown
michael@0 602 memset(&mFunctions, 0, sizeof(mFunctions));
michael@0 603
michael@0 604 #ifdef OS_WIN
michael@0 605 ResetEventHooks();
michael@0 606 #endif
michael@0 607
michael@0 608 GetIPCChannel()->SetAbortOnError(false);
michael@0 609
michael@0 610 return true;
michael@0 611 }
michael@0 612
michael@0 613 bool
michael@0 614 PluginModuleChild::AnswerOptionalFunctionsSupported(bool *aURLRedirectNotify,
michael@0 615 bool *aClearSiteData,
michael@0 616 bool *aGetSitesWithData)
michael@0 617 {
michael@0 618 *aURLRedirectNotify = !!mFunctions.urlredirectnotify;
michael@0 619 *aClearSiteData = !!mFunctions.clearsitedata;
michael@0 620 *aGetSitesWithData = !!mFunctions.getsiteswithdata;
michael@0 621 return true;
michael@0 622 }
michael@0 623
michael@0 624 bool
michael@0 625 PluginModuleChild::AnswerNPP_ClearSiteData(const nsCString& aSite,
michael@0 626 const uint64_t& aFlags,
michael@0 627 const uint64_t& aMaxAge,
michael@0 628 NPError* aResult)
michael@0 629 {
michael@0 630 *aResult =
michael@0 631 mFunctions.clearsitedata(NullableStringGet(aSite), aFlags, aMaxAge);
michael@0 632 return true;
michael@0 633 }
michael@0 634
michael@0 635 bool
michael@0 636 PluginModuleChild::AnswerNPP_GetSitesWithData(InfallibleTArray<nsCString>* aResult)
michael@0 637 {
michael@0 638 char** result = mFunctions.getsiteswithdata();
michael@0 639 if (!result)
michael@0 640 return true;
michael@0 641
michael@0 642 char** iterator = result;
michael@0 643 while (*iterator) {
michael@0 644 aResult->AppendElement(*iterator);
michael@0 645 NS_Free(*iterator);
michael@0 646 ++iterator;
michael@0 647 }
michael@0 648 NS_Free(result);
michael@0 649
michael@0 650 return true;
michael@0 651 }
michael@0 652
michael@0 653 bool
michael@0 654 PluginModuleChild::RecvSetAudioSessionData(const nsID& aId,
michael@0 655 const nsString& aDisplayName,
michael@0 656 const nsString& aIconPath)
michael@0 657 {
michael@0 658 #if !defined XP_WIN
michael@0 659 NS_RUNTIMEABORT("Not Reached!");
michael@0 660 return false;
michael@0 661 #else
michael@0 662 nsresult rv = mozilla::widget::RecvAudioSessionData(aId, aDisplayName, aIconPath);
michael@0 663 NS_ENSURE_SUCCESS(rv, true); // Bail early if this fails
michael@0 664
michael@0 665 // Ignore failures here; we can't really do anything about them
michael@0 666 mozilla::widget::StartAudioSession();
michael@0 667 return true;
michael@0 668 #endif
michael@0 669 }
michael@0 670
michael@0 671 void
michael@0 672 PluginModuleChild::QuickExit()
michael@0 673 {
michael@0 674 NS_WARNING("plugin process _exit()ing");
michael@0 675 _exit(0);
michael@0 676 }
michael@0 677
michael@0 678 PCrashReporterChild*
michael@0 679 PluginModuleChild::AllocPCrashReporterChild(mozilla::dom::NativeThreadId* id,
michael@0 680 uint32_t* processType)
michael@0 681 {
michael@0 682 return new CrashReporterChild();
michael@0 683 }
michael@0 684
michael@0 685 bool
michael@0 686 PluginModuleChild::DeallocPCrashReporterChild(PCrashReporterChild* actor)
michael@0 687 {
michael@0 688 delete actor;
michael@0 689 return true;
michael@0 690 }
michael@0 691
michael@0 692 bool
michael@0 693 PluginModuleChild::AnswerPCrashReporterConstructor(
michael@0 694 PCrashReporterChild* actor,
michael@0 695 mozilla::dom::NativeThreadId* id,
michael@0 696 uint32_t* processType)
michael@0 697 {
michael@0 698 #ifdef MOZ_CRASHREPORTER
michael@0 699 *id = CrashReporter::CurrentThreadId();
michael@0 700 *processType = XRE_GetProcessType();
michael@0 701 #endif
michael@0 702 return true;
michael@0 703 }
michael@0 704
michael@0 705 void
michael@0 706 PluginModuleChild::ActorDestroy(ActorDestroyReason why)
michael@0 707 {
michael@0 708 if (AbnormalShutdown == why) {
michael@0 709 NS_WARNING("shutting down early because of crash!");
michael@0 710 QuickExit();
michael@0 711 }
michael@0 712
michael@0 713 // doesn't matter why we're being destroyed; it's up to us to
michael@0 714 // initiate (clean) shutdown
michael@0 715 XRE_ShutdownChildProcess();
michael@0 716 }
michael@0 717
michael@0 718 void
michael@0 719 PluginModuleChild::CleanUp()
michael@0 720 {
michael@0 721 }
michael@0 722
michael@0 723 const char*
michael@0 724 PluginModuleChild::GetUserAgent()
michael@0 725 {
michael@0 726 if (mUserAgent.IsVoid() && !CallNPN_UserAgent(&mUserAgent))
michael@0 727 return nullptr;
michael@0 728
michael@0 729 return NullableStringGet(mUserAgent);
michael@0 730 }
michael@0 731
michael@0 732 bool
michael@0 733 PluginModuleChild::RegisterActorForNPObject(NPObject* aObject,
michael@0 734 PluginScriptableObjectChild* aActor)
michael@0 735 {
michael@0 736 AssertPluginThread();
michael@0 737 NS_ASSERTION(aObject && aActor, "Null pointer!");
michael@0 738
michael@0 739 NPObjectData* d = mObjectMap.GetEntry(aObject);
michael@0 740 if (!d) {
michael@0 741 NS_ERROR("NPObject not in object table");
michael@0 742 return false;
michael@0 743 }
michael@0 744
michael@0 745 d->actor = aActor;
michael@0 746 return true;
michael@0 747 }
michael@0 748
michael@0 749 void
michael@0 750 PluginModuleChild::UnregisterActorForNPObject(NPObject* aObject)
michael@0 751 {
michael@0 752 AssertPluginThread();
michael@0 753 NS_ASSERTION(aObject, "Null pointer!");
michael@0 754
michael@0 755 NPObjectData* d = mObjectMap.GetEntry(aObject);
michael@0 756 NS_ASSERTION(d, "NPObject not in object table");
michael@0 757 if (d) {
michael@0 758 d->actor = nullptr;
michael@0 759 }
michael@0 760 }
michael@0 761
michael@0 762 PluginScriptableObjectChild*
michael@0 763 PluginModuleChild::GetActorForNPObject(NPObject* aObject)
michael@0 764 {
michael@0 765 AssertPluginThread();
michael@0 766 NS_ASSERTION(aObject, "Null pointer!");
michael@0 767
michael@0 768 NPObjectData* d = mObjectMap.GetEntry(aObject);
michael@0 769 if (!d) {
michael@0 770 NS_ERROR("Plugin using object not created with NPN_CreateObject?");
michael@0 771 return nullptr;
michael@0 772 }
michael@0 773
michael@0 774 return d->actor;
michael@0 775 }
michael@0 776
michael@0 777 #ifdef DEBUG
michael@0 778 bool
michael@0 779 PluginModuleChild::NPObjectIsRegistered(NPObject* aObject)
michael@0 780 {
michael@0 781 return !!mObjectMap.GetEntry(aObject);
michael@0 782 }
michael@0 783 #endif
michael@0 784
michael@0 785 //-----------------------------------------------------------------------------
michael@0 786 // FIXME/cjones: just getting this out of the way for the moment ...
michael@0 787
michael@0 788 namespace mozilla {
michael@0 789 namespace plugins {
michael@0 790 namespace child {
michael@0 791
michael@0 792 static NPError
michael@0 793 _requestread(NPStream *pstream, NPByteRange *rangeList);
michael@0 794
michael@0 795 static NPError
michael@0 796 _geturlnotify(NPP aNPP, const char* relativeURL, const char* target,
michael@0 797 void* notifyData);
michael@0 798
michael@0 799 static NPError
michael@0 800 _getvalue(NPP aNPP, NPNVariable variable, void *r_value);
michael@0 801
michael@0 802 static NPError
michael@0 803 _setvalue(NPP aNPP, NPPVariable variable, void *r_value);
michael@0 804
michael@0 805 static NPError
michael@0 806 _geturl(NPP aNPP, const char* relativeURL, const char* target);
michael@0 807
michael@0 808 static NPError
michael@0 809 _posturlnotify(NPP aNPP, const char* relativeURL, const char *target,
michael@0 810 uint32_t len, const char *buf, NPBool file, void* notifyData);
michael@0 811
michael@0 812 static NPError
michael@0 813 _posturl(NPP aNPP, const char* relativeURL, const char *target, uint32_t len,
michael@0 814 const char *buf, NPBool file);
michael@0 815
michael@0 816 static NPError
michael@0 817 _newstream(NPP aNPP, NPMIMEType type, const char* window, NPStream** pstream);
michael@0 818
michael@0 819 static int32_t
michael@0 820 _write(NPP aNPP, NPStream *pstream, int32_t len, void *buffer);
michael@0 821
michael@0 822 static NPError
michael@0 823 _destroystream(NPP aNPP, NPStream *pstream, NPError reason);
michael@0 824
michael@0 825 static void
michael@0 826 _status(NPP aNPP, const char *message);
michael@0 827
michael@0 828 static void
michael@0 829 _memfree (void *ptr);
michael@0 830
michael@0 831 static uint32_t
michael@0 832 _memflush(uint32_t size);
michael@0 833
michael@0 834 static void
michael@0 835 _reloadplugins(NPBool reloadPages);
michael@0 836
michael@0 837 static void
michael@0 838 _invalidaterect(NPP aNPP, NPRect *invalidRect);
michael@0 839
michael@0 840 static void
michael@0 841 _invalidateregion(NPP aNPP, NPRegion invalidRegion);
michael@0 842
michael@0 843 static void
michael@0 844 _forceredraw(NPP aNPP);
michael@0 845
michael@0 846 static const char*
michael@0 847 _useragent(NPP aNPP);
michael@0 848
michael@0 849 static void*
michael@0 850 _memalloc (uint32_t size);
michael@0 851
michael@0 852 // Deprecated entry points for the old Java plugin.
michael@0 853 static void* /* OJI type: JRIEnv* */
michael@0 854 _getjavaenv(void);
michael@0 855
michael@0 856 // Deprecated entry points for the old Java plugin.
michael@0 857 static void* /* OJI type: jref */
michael@0 858 _getjavapeer(NPP aNPP);
michael@0 859
michael@0 860 static bool
michael@0 861 _invoke(NPP aNPP, NPObject* npobj, NPIdentifier method, const NPVariant *args,
michael@0 862 uint32_t argCount, NPVariant *result);
michael@0 863
michael@0 864 static bool
michael@0 865 _invokedefault(NPP aNPP, NPObject* npobj, const NPVariant *args,
michael@0 866 uint32_t argCount, NPVariant *result);
michael@0 867
michael@0 868 static bool
michael@0 869 _evaluate(NPP aNPP, NPObject* npobj, NPString *script, NPVariant *result);
michael@0 870
michael@0 871 static bool
michael@0 872 _getproperty(NPP aNPP, NPObject* npobj, NPIdentifier property,
michael@0 873 NPVariant *result);
michael@0 874
michael@0 875 static bool
michael@0 876 _setproperty(NPP aNPP, NPObject* npobj, NPIdentifier property,
michael@0 877 const NPVariant *value);
michael@0 878
michael@0 879 static bool
michael@0 880 _removeproperty(NPP aNPP, NPObject* npobj, NPIdentifier property);
michael@0 881
michael@0 882 static bool
michael@0 883 _hasproperty(NPP aNPP, NPObject* npobj, NPIdentifier propertyName);
michael@0 884
michael@0 885 static bool
michael@0 886 _hasmethod(NPP aNPP, NPObject* npobj, NPIdentifier methodName);
michael@0 887
michael@0 888 static bool
michael@0 889 _enumerate(NPP aNPP, NPObject *npobj, NPIdentifier **identifier,
michael@0 890 uint32_t *count);
michael@0 891
michael@0 892 static bool
michael@0 893 _construct(NPP aNPP, NPObject* npobj, const NPVariant *args,
michael@0 894 uint32_t argCount, NPVariant *result);
michael@0 895
michael@0 896 static void
michael@0 897 _releasevariantvalue(NPVariant *variant);
michael@0 898
michael@0 899 static void
michael@0 900 _setexception(NPObject* npobj, const NPUTF8 *message);
michael@0 901
michael@0 902 static void
michael@0 903 _pushpopupsenabledstate(NPP aNPP, NPBool enabled);
michael@0 904
michael@0 905 static void
michael@0 906 _poppopupsenabledstate(NPP aNPP);
michael@0 907
michael@0 908 static void
michael@0 909 _pluginthreadasynccall(NPP instance, PluginThreadCallback func,
michael@0 910 void *userData);
michael@0 911
michael@0 912 static NPError
michael@0 913 _getvalueforurl(NPP npp, NPNURLVariable variable, const char *url,
michael@0 914 char **value, uint32_t *len);
michael@0 915
michael@0 916 static NPError
michael@0 917 _setvalueforurl(NPP npp, NPNURLVariable variable, const char *url,
michael@0 918 const char *value, uint32_t len);
michael@0 919
michael@0 920 static NPError
michael@0 921 _getauthenticationinfo(NPP npp, const char *protocol,
michael@0 922 const char *host, int32_t port,
michael@0 923 const char *scheme, const char *realm,
michael@0 924 char **username, uint32_t *ulen,
michael@0 925 char **password, uint32_t *plen);
michael@0 926
michael@0 927 static uint32_t
michael@0 928 _scheduletimer(NPP instance, uint32_t interval, NPBool repeat,
michael@0 929 void (*timerFunc)(NPP npp, uint32_t timerID));
michael@0 930
michael@0 931 static void
michael@0 932 _unscheduletimer(NPP instance, uint32_t timerID);
michael@0 933
michael@0 934 static NPError
michael@0 935 _popupcontextmenu(NPP instance, NPMenu* menu);
michael@0 936
michael@0 937 static NPBool
michael@0 938 _convertpoint(NPP instance,
michael@0 939 double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
michael@0 940 double *destX, double *destY, NPCoordinateSpace destSpace);
michael@0 941
michael@0 942 static void
michael@0 943 _urlredirectresponse(NPP instance, void* notifyData, NPBool allow);
michael@0 944
michael@0 945 static NPError
michael@0 946 _initasyncsurface(NPP instance, NPSize *size,
michael@0 947 NPImageFormat format, void *initData,
michael@0 948 NPAsyncSurface *surface);
michael@0 949
michael@0 950 static NPError
michael@0 951 _finalizeasyncsurface(NPP instance, NPAsyncSurface *surface);
michael@0 952
michael@0 953 static void
michael@0 954 _setcurrentasyncsurface(NPP instance, NPAsyncSurface *surface, NPRect *changed);
michael@0 955
michael@0 956 } /* namespace child */
michael@0 957 } /* namespace plugins */
michael@0 958 } /* namespace mozilla */
michael@0 959
michael@0 960 const NPNetscapeFuncs PluginModuleChild::sBrowserFuncs = {
michael@0 961 sizeof(sBrowserFuncs),
michael@0 962 (NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR,
michael@0 963 mozilla::plugins::child::_geturl,
michael@0 964 mozilla::plugins::child::_posturl,
michael@0 965 mozilla::plugins::child::_requestread,
michael@0 966 mozilla::plugins::child::_newstream,
michael@0 967 mozilla::plugins::child::_write,
michael@0 968 mozilla::plugins::child::_destroystream,
michael@0 969 mozilla::plugins::child::_status,
michael@0 970 mozilla::plugins::child::_useragent,
michael@0 971 mozilla::plugins::child::_memalloc,
michael@0 972 mozilla::plugins::child::_memfree,
michael@0 973 mozilla::plugins::child::_memflush,
michael@0 974 mozilla::plugins::child::_reloadplugins,
michael@0 975 mozilla::plugins::child::_getjavaenv,
michael@0 976 mozilla::plugins::child::_getjavapeer,
michael@0 977 mozilla::plugins::child::_geturlnotify,
michael@0 978 mozilla::plugins::child::_posturlnotify,
michael@0 979 mozilla::plugins::child::_getvalue,
michael@0 980 mozilla::plugins::child::_setvalue,
michael@0 981 mozilla::plugins::child::_invalidaterect,
michael@0 982 mozilla::plugins::child::_invalidateregion,
michael@0 983 mozilla::plugins::child::_forceredraw,
michael@0 984 PluginModuleChild::NPN_GetStringIdentifier,
michael@0 985 PluginModuleChild::NPN_GetStringIdentifiers,
michael@0 986 PluginModuleChild::NPN_GetIntIdentifier,
michael@0 987 PluginModuleChild::NPN_IdentifierIsString,
michael@0 988 PluginModuleChild::NPN_UTF8FromIdentifier,
michael@0 989 PluginModuleChild::NPN_IntFromIdentifier,
michael@0 990 PluginModuleChild::NPN_CreateObject,
michael@0 991 PluginModuleChild::NPN_RetainObject,
michael@0 992 PluginModuleChild::NPN_ReleaseObject,
michael@0 993 mozilla::plugins::child::_invoke,
michael@0 994 mozilla::plugins::child::_invokedefault,
michael@0 995 mozilla::plugins::child::_evaluate,
michael@0 996 mozilla::plugins::child::_getproperty,
michael@0 997 mozilla::plugins::child::_setproperty,
michael@0 998 mozilla::plugins::child::_removeproperty,
michael@0 999 mozilla::plugins::child::_hasproperty,
michael@0 1000 mozilla::plugins::child::_hasmethod,
michael@0 1001 mozilla::plugins::child::_releasevariantvalue,
michael@0 1002 mozilla::plugins::child::_setexception,
michael@0 1003 mozilla::plugins::child::_pushpopupsenabledstate,
michael@0 1004 mozilla::plugins::child::_poppopupsenabledstate,
michael@0 1005 mozilla::plugins::child::_enumerate,
michael@0 1006 mozilla::plugins::child::_pluginthreadasynccall,
michael@0 1007 mozilla::plugins::child::_construct,
michael@0 1008 mozilla::plugins::child::_getvalueforurl,
michael@0 1009 mozilla::plugins::child::_setvalueforurl,
michael@0 1010 mozilla::plugins::child::_getauthenticationinfo,
michael@0 1011 mozilla::plugins::child::_scheduletimer,
michael@0 1012 mozilla::plugins::child::_unscheduletimer,
michael@0 1013 mozilla::plugins::child::_popupcontextmenu,
michael@0 1014 mozilla::plugins::child::_convertpoint,
michael@0 1015 nullptr, // handleevent, unimplemented
michael@0 1016 nullptr, // unfocusinstance, unimplemented
michael@0 1017 mozilla::plugins::child::_urlredirectresponse,
michael@0 1018 mozilla::plugins::child::_initasyncsurface,
michael@0 1019 mozilla::plugins::child::_finalizeasyncsurface,
michael@0 1020 mozilla::plugins::child::_setcurrentasyncsurface
michael@0 1021 };
michael@0 1022
michael@0 1023 PluginInstanceChild*
michael@0 1024 InstCast(NPP aNPP)
michael@0 1025 {
michael@0 1026 NS_ABORT_IF_FALSE(!!(aNPP->ndata), "nil instance");
michael@0 1027 return static_cast<PluginInstanceChild*>(aNPP->ndata);
michael@0 1028 }
michael@0 1029
michael@0 1030 namespace mozilla {
michael@0 1031 namespace plugins {
michael@0 1032 namespace child {
michael@0 1033
michael@0 1034 NPError
michael@0 1035 _requestread(NPStream* aStream,
michael@0 1036 NPByteRange* aRangeList)
michael@0 1037 {
michael@0 1038 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1039 ENSURE_PLUGIN_THREAD(NPERR_INVALID_PARAM);
michael@0 1040
michael@0 1041 BrowserStreamChild* bs =
michael@0 1042 static_cast<BrowserStreamChild*>(static_cast<AStream*>(aStream->ndata));
michael@0 1043 bs->EnsureCorrectStream(aStream);
michael@0 1044 return bs->NPN_RequestRead(aRangeList);
michael@0 1045 }
michael@0 1046
michael@0 1047 NPError
michael@0 1048 _geturlnotify(NPP aNPP,
michael@0 1049 const char* aRelativeURL,
michael@0 1050 const char* aTarget,
michael@0 1051 void* aNotifyData)
michael@0 1052 {
michael@0 1053 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1054 ENSURE_PLUGIN_THREAD(NPERR_INVALID_PARAM);
michael@0 1055
michael@0 1056 if (!aNPP) // nullptr check for nspluginwrapper (bug 561690)
michael@0 1057 return NPERR_INVALID_INSTANCE_ERROR;
michael@0 1058
michael@0 1059 nsCString url = NullableString(aRelativeURL);
michael@0 1060 StreamNotifyChild* sn = new StreamNotifyChild(url);
michael@0 1061
michael@0 1062 NPError err;
michael@0 1063 InstCast(aNPP)->CallPStreamNotifyConstructor(
michael@0 1064 sn, url, NullableString(aTarget), false, nsCString(), false, &err);
michael@0 1065
michael@0 1066 if (NPERR_NO_ERROR == err) {
michael@0 1067 // If NPN_PostURLNotify fails, the parent will immediately send us
michael@0 1068 // a PStreamNotifyDestructor, which should not call NPP_URLNotify.
michael@0 1069 sn->SetValid(aNotifyData);
michael@0 1070 }
michael@0 1071
michael@0 1072 return err;
michael@0 1073 }
michael@0 1074
michael@0 1075 NPError
michael@0 1076 _getvalue(NPP aNPP,
michael@0 1077 NPNVariable aVariable,
michael@0 1078 void* aValue)
michael@0 1079 {
michael@0 1080 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1081 ENSURE_PLUGIN_THREAD(NPERR_INVALID_PARAM);
michael@0 1082
michael@0 1083 switch (aVariable) {
michael@0 1084 // Copied from nsNPAPIPlugin.cpp
michael@0 1085 case NPNVToolkit:
michael@0 1086 #if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_QT)
michael@0 1087 *static_cast<NPNToolkitType*>(aValue) = NPNVGtk2;
michael@0 1088 return NPERR_NO_ERROR;
michael@0 1089 #endif
michael@0 1090 return NPERR_GENERIC_ERROR;
michael@0 1091
michael@0 1092 case NPNVjavascriptEnabledBool: // Intentional fall-through
michael@0 1093 case NPNVasdEnabledBool: // Intentional fall-through
michael@0 1094 case NPNVisOfflineBool: // Intentional fall-through
michael@0 1095 case NPNVSupportsXEmbedBool: // Intentional fall-through
michael@0 1096 case NPNVSupportsWindowless: { // Intentional fall-through
michael@0 1097 NPError result;
michael@0 1098 bool value;
michael@0 1099 PluginModuleChild::current()->
michael@0 1100 CallNPN_GetValue_WithBoolReturn(aVariable, &result, &value);
michael@0 1101 *(NPBool*)aValue = value ? true : false;
michael@0 1102 return result;
michael@0 1103 }
michael@0 1104 #if (MOZ_WIDGET_GTK == 2)
michael@0 1105 case NPNVxDisplay: {
michael@0 1106 if (aNPP) {
michael@0 1107 return InstCast(aNPP)->NPN_GetValue(aVariable, aValue);
michael@0 1108 }
michael@0 1109 else {
michael@0 1110 *(void **)aValue = xt_client_get_display();
michael@0 1111 }
michael@0 1112 return NPERR_NO_ERROR;
michael@0 1113 }
michael@0 1114 case NPNVxtAppContext:
michael@0 1115 return NPERR_GENERIC_ERROR;
michael@0 1116 #endif
michael@0 1117 default: {
michael@0 1118 if (aNPP) {
michael@0 1119 return InstCast(aNPP)->NPN_GetValue(aVariable, aValue);
michael@0 1120 }
michael@0 1121
michael@0 1122 NS_WARNING("Null NPP!");
michael@0 1123 return NPERR_INVALID_INSTANCE_ERROR;
michael@0 1124 }
michael@0 1125 }
michael@0 1126
michael@0 1127 NS_NOTREACHED("Shouldn't get here!");
michael@0 1128 return NPERR_GENERIC_ERROR;
michael@0 1129 }
michael@0 1130
michael@0 1131 NPError
michael@0 1132 _setvalue(NPP aNPP,
michael@0 1133 NPPVariable aVariable,
michael@0 1134 void* aValue)
michael@0 1135 {
michael@0 1136 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1137 ENSURE_PLUGIN_THREAD(NPERR_INVALID_PARAM);
michael@0 1138 return InstCast(aNPP)->NPN_SetValue(aVariable, aValue);
michael@0 1139 }
michael@0 1140
michael@0 1141 NPError
michael@0 1142 _geturl(NPP aNPP,
michael@0 1143 const char* aRelativeURL,
michael@0 1144 const char* aTarget)
michael@0 1145 {
michael@0 1146 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1147 ENSURE_PLUGIN_THREAD(NPERR_INVALID_PARAM);
michael@0 1148
michael@0 1149 NPError err;
michael@0 1150 InstCast(aNPP)->CallNPN_GetURL(NullableString(aRelativeURL),
michael@0 1151 NullableString(aTarget), &err);
michael@0 1152 return err;
michael@0 1153 }
michael@0 1154
michael@0 1155 NPError
michael@0 1156 _posturlnotify(NPP aNPP,
michael@0 1157 const char* aRelativeURL,
michael@0 1158 const char* aTarget,
michael@0 1159 uint32_t aLength,
michael@0 1160 const char* aBuffer,
michael@0 1161 NPBool aIsFile,
michael@0 1162 void* aNotifyData)
michael@0 1163 {
michael@0 1164 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1165 ENSURE_PLUGIN_THREAD(NPERR_INVALID_PARAM);
michael@0 1166
michael@0 1167 if (!aBuffer)
michael@0 1168 return NPERR_INVALID_PARAM;
michael@0 1169
michael@0 1170 nsCString url = NullableString(aRelativeURL);
michael@0 1171 StreamNotifyChild* sn = new StreamNotifyChild(url);
michael@0 1172
michael@0 1173 NPError err;
michael@0 1174 InstCast(aNPP)->CallPStreamNotifyConstructor(
michael@0 1175 sn, url, NullableString(aTarget), true,
michael@0 1176 nsCString(aBuffer, aLength), aIsFile, &err);
michael@0 1177
michael@0 1178 if (NPERR_NO_ERROR == err) {
michael@0 1179 // If NPN_PostURLNotify fails, the parent will immediately send us
michael@0 1180 // a PStreamNotifyDestructor, which should not call NPP_URLNotify.
michael@0 1181 sn->SetValid(aNotifyData);
michael@0 1182 }
michael@0 1183
michael@0 1184 return err;
michael@0 1185 }
michael@0 1186
michael@0 1187 NPError
michael@0 1188 _posturl(NPP aNPP,
michael@0 1189 const char* aRelativeURL,
michael@0 1190 const char* aTarget,
michael@0 1191 uint32_t aLength,
michael@0 1192 const char* aBuffer,
michael@0 1193 NPBool aIsFile)
michael@0 1194 {
michael@0 1195 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1196 ENSURE_PLUGIN_THREAD(NPERR_INVALID_PARAM);
michael@0 1197
michael@0 1198 NPError err;
michael@0 1199 // FIXME what should happen when |aBuffer| is null?
michael@0 1200 InstCast(aNPP)->CallNPN_PostURL(NullableString(aRelativeURL),
michael@0 1201 NullableString(aTarget),
michael@0 1202 nsDependentCString(aBuffer, aLength),
michael@0 1203 aIsFile, &err);
michael@0 1204 return err;
michael@0 1205 }
michael@0 1206
michael@0 1207 NPError
michael@0 1208 _newstream(NPP aNPP,
michael@0 1209 NPMIMEType aMIMEType,
michael@0 1210 const char* aWindow,
michael@0 1211 NPStream** aStream)
michael@0 1212 {
michael@0 1213 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1214 ENSURE_PLUGIN_THREAD(NPERR_INVALID_PARAM);
michael@0 1215 return InstCast(aNPP)->NPN_NewStream(aMIMEType, aWindow, aStream);
michael@0 1216 }
michael@0 1217
michael@0 1218 int32_t
michael@0 1219 _write(NPP aNPP,
michael@0 1220 NPStream* aStream,
michael@0 1221 int32_t aLength,
michael@0 1222 void* aBuffer)
michael@0 1223 {
michael@0 1224 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1225 ENSURE_PLUGIN_THREAD(0);
michael@0 1226
michael@0 1227 PluginStreamChild* ps =
michael@0 1228 static_cast<PluginStreamChild*>(static_cast<AStream*>(aStream->ndata));
michael@0 1229 ps->EnsureCorrectInstance(InstCast(aNPP));
michael@0 1230 ps->EnsureCorrectStream(aStream);
michael@0 1231 return ps->NPN_Write(aLength, aBuffer);
michael@0 1232 }
michael@0 1233
michael@0 1234 NPError
michael@0 1235 _destroystream(NPP aNPP,
michael@0 1236 NPStream* aStream,
michael@0 1237 NPError aReason)
michael@0 1238 {
michael@0 1239 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1240 ENSURE_PLUGIN_THREAD(NPERR_INVALID_PARAM);
michael@0 1241
michael@0 1242 PluginInstanceChild* p = InstCast(aNPP);
michael@0 1243 AStream* s = static_cast<AStream*>(aStream->ndata);
michael@0 1244 if (s->IsBrowserStream()) {
michael@0 1245 BrowserStreamChild* bs = static_cast<BrowserStreamChild*>(s);
michael@0 1246 bs->EnsureCorrectInstance(p);
michael@0 1247 bs->NPN_DestroyStream(aReason);
michael@0 1248 }
michael@0 1249 else {
michael@0 1250 PluginStreamChild* ps = static_cast<PluginStreamChild*>(s);
michael@0 1251 ps->EnsureCorrectInstance(p);
michael@0 1252 PPluginStreamChild::Call__delete__(ps, aReason, false);
michael@0 1253 }
michael@0 1254 return NPERR_NO_ERROR;
michael@0 1255 }
michael@0 1256
michael@0 1257 void
michael@0 1258 _status(NPP aNPP,
michael@0 1259 const char* aMessage)
michael@0 1260 {
michael@0 1261 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1262 ENSURE_PLUGIN_THREAD_VOID();
michael@0 1263 NS_WARNING("Not yet implemented!");
michael@0 1264 }
michael@0 1265
michael@0 1266 void
michael@0 1267 _memfree(void* aPtr)
michael@0 1268 {
michael@0 1269 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1270 // Only assert plugin thread here for consistency with in-process plugins.
michael@0 1271 AssertPluginThread();
michael@0 1272 NS_Free(aPtr);
michael@0 1273 }
michael@0 1274
michael@0 1275 uint32_t
michael@0 1276 _memflush(uint32_t aSize)
michael@0 1277 {
michael@0 1278 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1279 // Only assert plugin thread here for consistency with in-process plugins.
michael@0 1280 AssertPluginThread();
michael@0 1281 return 0;
michael@0 1282 }
michael@0 1283
michael@0 1284 void
michael@0 1285 _reloadplugins(NPBool aReloadPages)
michael@0 1286 {
michael@0 1287 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1288 ENSURE_PLUGIN_THREAD_VOID();
michael@0 1289
michael@0 1290 PluginModuleChild::current()->SendNPN_ReloadPlugins(!!aReloadPages);
michael@0 1291 }
michael@0 1292
michael@0 1293 void
michael@0 1294 _invalidaterect(NPP aNPP,
michael@0 1295 NPRect* aInvalidRect)
michael@0 1296 {
michael@0 1297 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1298 ENSURE_PLUGIN_THREAD_VOID();
michael@0 1299 // nullptr check for nspluginwrapper (bug 548434)
michael@0 1300 if (aNPP) {
michael@0 1301 InstCast(aNPP)->InvalidateRect(aInvalidRect);
michael@0 1302 }
michael@0 1303 }
michael@0 1304
michael@0 1305 void
michael@0 1306 _invalidateregion(NPP aNPP,
michael@0 1307 NPRegion aInvalidRegion)
michael@0 1308 {
michael@0 1309 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1310 ENSURE_PLUGIN_THREAD_VOID();
michael@0 1311 NS_WARNING("Not yet implemented!");
michael@0 1312 }
michael@0 1313
michael@0 1314 void
michael@0 1315 _forceredraw(NPP aNPP)
michael@0 1316 {
michael@0 1317 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1318 ENSURE_PLUGIN_THREAD_VOID();
michael@0 1319
michael@0 1320 // We ignore calls to NPN_ForceRedraw. Such calls should
michael@0 1321 // never be necessary.
michael@0 1322 }
michael@0 1323
michael@0 1324 const char*
michael@0 1325 _useragent(NPP aNPP)
michael@0 1326 {
michael@0 1327 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1328 ENSURE_PLUGIN_THREAD(nullptr);
michael@0 1329 return PluginModuleChild::current()->GetUserAgent();
michael@0 1330 }
michael@0 1331
michael@0 1332 void*
michael@0 1333 _memalloc(uint32_t aSize)
michael@0 1334 {
michael@0 1335 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1336 // Only assert plugin thread here for consistency with in-process plugins.
michael@0 1337 AssertPluginThread();
michael@0 1338 return NS_Alloc(aSize);
michael@0 1339 }
michael@0 1340
michael@0 1341 // Deprecated entry points for the old Java plugin.
michael@0 1342 void* /* OJI type: JRIEnv* */
michael@0 1343 _getjavaenv(void)
michael@0 1344 {
michael@0 1345 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1346 return 0;
michael@0 1347 }
michael@0 1348
michael@0 1349 void* /* OJI type: jref */
michael@0 1350 _getjavapeer(NPP aNPP)
michael@0 1351 {
michael@0 1352 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1353 return 0;
michael@0 1354 }
michael@0 1355
michael@0 1356 bool
michael@0 1357 _invoke(NPP aNPP,
michael@0 1358 NPObject* aNPObj,
michael@0 1359 NPIdentifier aMethod,
michael@0 1360 const NPVariant* aArgs,
michael@0 1361 uint32_t aArgCount,
michael@0 1362 NPVariant* aResult)
michael@0 1363 {
michael@0 1364 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1365 ENSURE_PLUGIN_THREAD(false);
michael@0 1366
michael@0 1367 if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->invoke)
michael@0 1368 return false;
michael@0 1369
michael@0 1370 return aNPObj->_class->invoke(aNPObj, aMethod, aArgs, aArgCount, aResult);
michael@0 1371 }
michael@0 1372
michael@0 1373 bool
michael@0 1374 _invokedefault(NPP aNPP,
michael@0 1375 NPObject* aNPObj,
michael@0 1376 const NPVariant* aArgs,
michael@0 1377 uint32_t aArgCount,
michael@0 1378 NPVariant* aResult)
michael@0 1379 {
michael@0 1380 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1381 ENSURE_PLUGIN_THREAD(false);
michael@0 1382
michael@0 1383 if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->invokeDefault)
michael@0 1384 return false;
michael@0 1385
michael@0 1386 return aNPObj->_class->invokeDefault(aNPObj, aArgs, aArgCount, aResult);
michael@0 1387 }
michael@0 1388
michael@0 1389 bool
michael@0 1390 _evaluate(NPP aNPP,
michael@0 1391 NPObject* aObject,
michael@0 1392 NPString* aScript,
michael@0 1393 NPVariant* aResult)
michael@0 1394 {
michael@0 1395 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1396 ENSURE_PLUGIN_THREAD(false);
michael@0 1397
michael@0 1398 if (!(aNPP && aObject && aScript && aResult)) {
michael@0 1399 NS_ERROR("Bad arguments!");
michael@0 1400 return false;
michael@0 1401 }
michael@0 1402
michael@0 1403 PluginScriptableObjectChild* actor =
michael@0 1404 InstCast(aNPP)->GetActorForNPObject(aObject);
michael@0 1405 if (!actor) {
michael@0 1406 NS_ERROR("Failed to create actor?!");
michael@0 1407 return false;
michael@0 1408 }
michael@0 1409
michael@0 1410 #ifdef XP_WIN
michael@0 1411 if (gDelayFlashFocusReplyUntilEval) {
michael@0 1412 ReplyMessage(0);
michael@0 1413 gDelayFlashFocusReplyUntilEval = false;
michael@0 1414 }
michael@0 1415 #endif
michael@0 1416
michael@0 1417 return actor->Evaluate(aScript, aResult);
michael@0 1418 }
michael@0 1419
michael@0 1420 bool
michael@0 1421 _getproperty(NPP aNPP,
michael@0 1422 NPObject* aNPObj,
michael@0 1423 NPIdentifier aPropertyName,
michael@0 1424 NPVariant* aResult)
michael@0 1425 {
michael@0 1426 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1427 ENSURE_PLUGIN_THREAD(false);
michael@0 1428
michael@0 1429 if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->getProperty)
michael@0 1430 return false;
michael@0 1431
michael@0 1432 return aNPObj->_class->getProperty(aNPObj, aPropertyName, aResult);
michael@0 1433 }
michael@0 1434
michael@0 1435 bool
michael@0 1436 _setproperty(NPP aNPP,
michael@0 1437 NPObject* aNPObj,
michael@0 1438 NPIdentifier aPropertyName,
michael@0 1439 const NPVariant* aValue)
michael@0 1440 {
michael@0 1441 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1442 ENSURE_PLUGIN_THREAD(false);
michael@0 1443
michael@0 1444 if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->setProperty)
michael@0 1445 return false;
michael@0 1446
michael@0 1447 return aNPObj->_class->setProperty(aNPObj, aPropertyName, aValue);
michael@0 1448 }
michael@0 1449
michael@0 1450 bool
michael@0 1451 _removeproperty(NPP aNPP,
michael@0 1452 NPObject* aNPObj,
michael@0 1453 NPIdentifier aPropertyName)
michael@0 1454 {
michael@0 1455 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1456 ENSURE_PLUGIN_THREAD(false);
michael@0 1457
michael@0 1458 if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->removeProperty)
michael@0 1459 return false;
michael@0 1460
michael@0 1461 return aNPObj->_class->removeProperty(aNPObj, aPropertyName);
michael@0 1462 }
michael@0 1463
michael@0 1464 bool
michael@0 1465 _hasproperty(NPP aNPP,
michael@0 1466 NPObject* aNPObj,
michael@0 1467 NPIdentifier aPropertyName)
michael@0 1468 {
michael@0 1469 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1470 ENSURE_PLUGIN_THREAD(false);
michael@0 1471
michael@0 1472 if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->hasProperty)
michael@0 1473 return false;
michael@0 1474
michael@0 1475 return aNPObj->_class->hasProperty(aNPObj, aPropertyName);
michael@0 1476 }
michael@0 1477
michael@0 1478 bool
michael@0 1479 _hasmethod(NPP aNPP,
michael@0 1480 NPObject* aNPObj,
michael@0 1481 NPIdentifier aMethodName)
michael@0 1482 {
michael@0 1483 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1484 ENSURE_PLUGIN_THREAD(false);
michael@0 1485
michael@0 1486 if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->hasMethod)
michael@0 1487 return false;
michael@0 1488
michael@0 1489 return aNPObj->_class->hasMethod(aNPObj, aMethodName);
michael@0 1490 }
michael@0 1491
michael@0 1492 bool
michael@0 1493 _enumerate(NPP aNPP,
michael@0 1494 NPObject* aNPObj,
michael@0 1495 NPIdentifier** aIdentifiers,
michael@0 1496 uint32_t* aCount)
michael@0 1497 {
michael@0 1498 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1499 ENSURE_PLUGIN_THREAD(false);
michael@0 1500
michael@0 1501 if (!aNPP || !aNPObj || !aNPObj->_class)
michael@0 1502 return false;
michael@0 1503
michael@0 1504 if (!NP_CLASS_STRUCT_VERSION_HAS_ENUM(aNPObj->_class) ||
michael@0 1505 !aNPObj->_class->enumerate) {
michael@0 1506 *aIdentifiers = 0;
michael@0 1507 *aCount = 0;
michael@0 1508 return true;
michael@0 1509 }
michael@0 1510
michael@0 1511 return aNPObj->_class->enumerate(aNPObj, aIdentifiers, aCount);
michael@0 1512 }
michael@0 1513
michael@0 1514 bool
michael@0 1515 _construct(NPP aNPP,
michael@0 1516 NPObject* aNPObj,
michael@0 1517 const NPVariant* aArgs,
michael@0 1518 uint32_t aArgCount,
michael@0 1519 NPVariant* aResult)
michael@0 1520 {
michael@0 1521 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1522 ENSURE_PLUGIN_THREAD(false);
michael@0 1523
michael@0 1524 if (!aNPP || !aNPObj || !aNPObj->_class ||
michael@0 1525 !NP_CLASS_STRUCT_VERSION_HAS_CTOR(aNPObj->_class) ||
michael@0 1526 !aNPObj->_class->construct) {
michael@0 1527 return false;
michael@0 1528 }
michael@0 1529
michael@0 1530 return aNPObj->_class->construct(aNPObj, aArgs, aArgCount, aResult);
michael@0 1531 }
michael@0 1532
michael@0 1533 void
michael@0 1534 _releasevariantvalue(NPVariant* aVariant)
michael@0 1535 {
michael@0 1536 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1537 // Only assert plugin thread here for consistency with in-process plugins.
michael@0 1538 AssertPluginThread();
michael@0 1539
michael@0 1540 if (NPVARIANT_IS_STRING(*aVariant)) {
michael@0 1541 NPString str = NPVARIANT_TO_STRING(*aVariant);
michael@0 1542 free(const_cast<NPUTF8*>(str.UTF8Characters));
michael@0 1543 }
michael@0 1544 else if (NPVARIANT_IS_OBJECT(*aVariant)) {
michael@0 1545 NPObject* object = NPVARIANT_TO_OBJECT(*aVariant);
michael@0 1546 if (object) {
michael@0 1547 PluginModuleChild::NPN_ReleaseObject(object);
michael@0 1548 }
michael@0 1549 }
michael@0 1550 VOID_TO_NPVARIANT(*aVariant);
michael@0 1551 }
michael@0 1552
michael@0 1553 void
michael@0 1554 _setexception(NPObject* aNPObj,
michael@0 1555 const NPUTF8* aMessage)
michael@0 1556 {
michael@0 1557 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1558 ENSURE_PLUGIN_THREAD_VOID();
michael@0 1559
michael@0 1560 PluginModuleChild* self = PluginModuleChild::current();
michael@0 1561 PluginScriptableObjectChild* actor = nullptr;
michael@0 1562 if (aNPObj) {
michael@0 1563 actor = self->GetActorForNPObject(aNPObj);
michael@0 1564 if (!actor) {
michael@0 1565 NS_ERROR("Failed to get actor!");
michael@0 1566 return;
michael@0 1567 }
michael@0 1568 }
michael@0 1569
michael@0 1570 self->SendNPN_SetException(static_cast<PPluginScriptableObjectChild*>(actor),
michael@0 1571 NullableString(aMessage));
michael@0 1572 }
michael@0 1573
michael@0 1574 void
michael@0 1575 _pushpopupsenabledstate(NPP aNPP,
michael@0 1576 NPBool aEnabled)
michael@0 1577 {
michael@0 1578 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1579 ENSURE_PLUGIN_THREAD_VOID();
michael@0 1580
michael@0 1581 InstCast(aNPP)->CallNPN_PushPopupsEnabledState(aEnabled ? true : false);
michael@0 1582 }
michael@0 1583
michael@0 1584 void
michael@0 1585 _poppopupsenabledstate(NPP aNPP)
michael@0 1586 {
michael@0 1587 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1588 ENSURE_PLUGIN_THREAD_VOID();
michael@0 1589
michael@0 1590 InstCast(aNPP)->CallNPN_PopPopupsEnabledState();
michael@0 1591 }
michael@0 1592
michael@0 1593 void
michael@0 1594 _pluginthreadasynccall(NPP aNPP,
michael@0 1595 PluginThreadCallback aFunc,
michael@0 1596 void* aUserData)
michael@0 1597 {
michael@0 1598 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1599 if (!aFunc)
michael@0 1600 return;
michael@0 1601
michael@0 1602 InstCast(aNPP)->AsyncCall(aFunc, aUserData);
michael@0 1603 }
michael@0 1604
michael@0 1605 NPError
michael@0 1606 _getvalueforurl(NPP npp, NPNURLVariable variable, const char *url,
michael@0 1607 char **value, uint32_t *len)
michael@0 1608 {
michael@0 1609 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1610 AssertPluginThread();
michael@0 1611
michael@0 1612 if (!url)
michael@0 1613 return NPERR_INVALID_URL;
michael@0 1614
michael@0 1615 if (!npp || !value || !len)
michael@0 1616 return NPERR_INVALID_PARAM;
michael@0 1617
michael@0 1618 switch (variable) {
michael@0 1619 case NPNURLVCookie:
michael@0 1620 case NPNURLVProxy:
michael@0 1621 nsCString v;
michael@0 1622 NPError result;
michael@0 1623 InstCast(npp)->
michael@0 1624 CallNPN_GetValueForURL(variable, nsCString(url), &v, &result);
michael@0 1625 if (NPERR_NO_ERROR == result) {
michael@0 1626 *value = ToNewCString(v);
michael@0 1627 *len = v.Length();
michael@0 1628 }
michael@0 1629 return result;
michael@0 1630 }
michael@0 1631
michael@0 1632 return NPERR_INVALID_PARAM;
michael@0 1633 }
michael@0 1634
michael@0 1635 NPError
michael@0 1636 _setvalueforurl(NPP npp, NPNURLVariable variable, const char *url,
michael@0 1637 const char *value, uint32_t len)
michael@0 1638 {
michael@0 1639 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1640 AssertPluginThread();
michael@0 1641
michael@0 1642 if (!value)
michael@0 1643 return NPERR_INVALID_PARAM;
michael@0 1644
michael@0 1645 if (!url)
michael@0 1646 return NPERR_INVALID_URL;
michael@0 1647
michael@0 1648 switch (variable) {
michael@0 1649 case NPNURLVCookie:
michael@0 1650 case NPNURLVProxy:
michael@0 1651 NPError result;
michael@0 1652 InstCast(npp)->CallNPN_SetValueForURL(variable, nsCString(url),
michael@0 1653 nsDependentCString(value, len),
michael@0 1654 &result);
michael@0 1655 return result;
michael@0 1656 }
michael@0 1657
michael@0 1658 return NPERR_INVALID_PARAM;
michael@0 1659 }
michael@0 1660
michael@0 1661 NPError
michael@0 1662 _getauthenticationinfo(NPP npp, const char *protocol,
michael@0 1663 const char *host, int32_t port,
michael@0 1664 const char *scheme, const char *realm,
michael@0 1665 char **username, uint32_t *ulen,
michael@0 1666 char **password, uint32_t *plen)
michael@0 1667 {
michael@0 1668 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1669 AssertPluginThread();
michael@0 1670
michael@0 1671 if (!protocol || !host || !scheme || !realm || !username || !ulen ||
michael@0 1672 !password || !plen)
michael@0 1673 return NPERR_INVALID_PARAM;
michael@0 1674
michael@0 1675 nsCString u;
michael@0 1676 nsCString p;
michael@0 1677 NPError result;
michael@0 1678 InstCast(npp)->
michael@0 1679 CallNPN_GetAuthenticationInfo(nsDependentCString(protocol),
michael@0 1680 nsDependentCString(host),
michael@0 1681 port,
michael@0 1682 nsDependentCString(scheme),
michael@0 1683 nsDependentCString(realm),
michael@0 1684 &u, &p, &result);
michael@0 1685 if (NPERR_NO_ERROR == result) {
michael@0 1686 *username = ToNewCString(u);
michael@0 1687 *ulen = u.Length();
michael@0 1688 *password = ToNewCString(p);
michael@0 1689 *plen = p.Length();
michael@0 1690 }
michael@0 1691 return result;
michael@0 1692 }
michael@0 1693
michael@0 1694 uint32_t
michael@0 1695 _scheduletimer(NPP npp, uint32_t interval, NPBool repeat,
michael@0 1696 void (*timerFunc)(NPP npp, uint32_t timerID))
michael@0 1697 {
michael@0 1698 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1699 AssertPluginThread();
michael@0 1700 return InstCast(npp)->ScheduleTimer(interval, repeat, timerFunc);
michael@0 1701 }
michael@0 1702
michael@0 1703 void
michael@0 1704 _unscheduletimer(NPP npp, uint32_t timerID)
michael@0 1705 {
michael@0 1706 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1707 AssertPluginThread();
michael@0 1708 InstCast(npp)->UnscheduleTimer(timerID);
michael@0 1709 }
michael@0 1710
michael@0 1711
michael@0 1712 #ifdef OS_MACOSX
michael@0 1713 static void ProcessBrowserEvents(void* pluginModule) {
michael@0 1714 PluginModuleChild* pmc = static_cast<PluginModuleChild*>(pluginModule);
michael@0 1715
michael@0 1716 if (!pmc)
michael@0 1717 return;
michael@0 1718
michael@0 1719 pmc->CallProcessSomeEvents();
michael@0 1720 }
michael@0 1721 #endif
michael@0 1722
michael@0 1723 NPError
michael@0 1724 _popupcontextmenu(NPP instance, NPMenu* menu)
michael@0 1725 {
michael@0 1726 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1727 AssertPluginThread();
michael@0 1728
michael@0 1729 #ifdef MOZ_WIDGET_COCOA
michael@0 1730 double pluginX, pluginY;
michael@0 1731 double screenX, screenY;
michael@0 1732
michael@0 1733 const NPCocoaEvent* currentEvent = InstCast(instance)->getCurrentEvent();
michael@0 1734 if (!currentEvent) {
michael@0 1735 return NPERR_GENERIC_ERROR;
michael@0 1736 }
michael@0 1737
michael@0 1738 // Ensure that the events has an x/y value.
michael@0 1739 if (currentEvent->type != NPCocoaEventMouseDown &&
michael@0 1740 currentEvent->type != NPCocoaEventMouseUp &&
michael@0 1741 currentEvent->type != NPCocoaEventMouseMoved &&
michael@0 1742 currentEvent->type != NPCocoaEventMouseEntered &&
michael@0 1743 currentEvent->type != NPCocoaEventMouseExited &&
michael@0 1744 currentEvent->type != NPCocoaEventMouseDragged) {
michael@0 1745 return NPERR_GENERIC_ERROR;
michael@0 1746 }
michael@0 1747
michael@0 1748 pluginX = currentEvent->data.mouse.pluginX;
michael@0 1749 pluginY = currentEvent->data.mouse.pluginY;
michael@0 1750
michael@0 1751 if ((pluginX < 0.0) || (pluginY < 0.0))
michael@0 1752 return NPERR_GENERIC_ERROR;
michael@0 1753
michael@0 1754 NPBool success = _convertpoint(instance,
michael@0 1755 pluginX, pluginY, NPCoordinateSpacePlugin,
michael@0 1756 &screenX, &screenY, NPCoordinateSpaceScreen);
michael@0 1757
michael@0 1758 if (success) {
michael@0 1759 return mozilla::plugins::PluginUtilsOSX::ShowCocoaContextMenu(menu,
michael@0 1760 screenX, screenY,
michael@0 1761 PluginModuleChild::current(),
michael@0 1762 ProcessBrowserEvents);
michael@0 1763 } else {
michael@0 1764 NS_WARNING("Convertpoint failed, could not created contextmenu.");
michael@0 1765 return NPERR_GENERIC_ERROR;
michael@0 1766 }
michael@0 1767
michael@0 1768 #else
michael@0 1769 NS_WARNING("Not supported on this platform!");
michael@0 1770 return NPERR_GENERIC_ERROR;
michael@0 1771 #endif
michael@0 1772 }
michael@0 1773
michael@0 1774 NPBool
michael@0 1775 _convertpoint(NPP instance,
michael@0 1776 double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
michael@0 1777 double *destX, double *destY, NPCoordinateSpace destSpace)
michael@0 1778 {
michael@0 1779 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 1780 if (!IsPluginThread()) {
michael@0 1781 NS_WARNING("Not running on the plugin's main thread!");
michael@0 1782 return false;
michael@0 1783 }
michael@0 1784
michael@0 1785 double rDestX = 0;
michael@0 1786 bool ignoreDestX = !destX;
michael@0 1787 double rDestY = 0;
michael@0 1788 bool ignoreDestY = !destY;
michael@0 1789 bool result = false;
michael@0 1790 InstCast(instance)->CallNPN_ConvertPoint(sourceX, ignoreDestX, sourceY, ignoreDestY, sourceSpace, destSpace,
michael@0 1791 &rDestX, &rDestY, &result);
michael@0 1792 if (result) {
michael@0 1793 if (destX)
michael@0 1794 *destX = rDestX;
michael@0 1795 if (destY)
michael@0 1796 *destY = rDestY;
michael@0 1797 }
michael@0 1798
michael@0 1799 return result;
michael@0 1800 }
michael@0 1801
michael@0 1802 void
michael@0 1803 _urlredirectresponse(NPP instance, void* notifyData, NPBool allow)
michael@0 1804 {
michael@0 1805 InstCast(instance)->NPN_URLRedirectResponse(notifyData, allow);
michael@0 1806 }
michael@0 1807
michael@0 1808 NPError
michael@0 1809 _initasyncsurface(NPP instance, NPSize *size,
michael@0 1810 NPImageFormat format, void *initData,
michael@0 1811 NPAsyncSurface *surface)
michael@0 1812 {
michael@0 1813 return InstCast(instance)->NPN_InitAsyncSurface(size, format, initData, surface);
michael@0 1814 }
michael@0 1815
michael@0 1816 NPError
michael@0 1817 _finalizeasyncsurface(NPP instance, NPAsyncSurface *surface)
michael@0 1818 {
michael@0 1819 return InstCast(instance)->NPN_FinalizeAsyncSurface(surface);
michael@0 1820 }
michael@0 1821
michael@0 1822 void
michael@0 1823 _setcurrentasyncsurface(NPP instance, NPAsyncSurface *surface, NPRect *changed)
michael@0 1824 {
michael@0 1825 InstCast(instance)->NPN_SetCurrentAsyncSurface(surface, changed);
michael@0 1826 }
michael@0 1827
michael@0 1828 } /* namespace child */
michael@0 1829 } /* namespace plugins */
michael@0 1830 } /* namespace mozilla */
michael@0 1831
michael@0 1832 //-----------------------------------------------------------------------------
michael@0 1833
michael@0 1834 bool
michael@0 1835 PluginModuleChild::AnswerNP_GetEntryPoints(NPError* _retval)
michael@0 1836 {
michael@0 1837 PLUGIN_LOG_DEBUG_METHOD;
michael@0 1838 AssertPluginThread();
michael@0 1839
michael@0 1840 #if defined(OS_LINUX) || defined(OS_BSD)
michael@0 1841 return true;
michael@0 1842 #elif defined(OS_WIN) || defined(OS_MACOSX)
michael@0 1843 *_retval = mGetEntryPointsFunc(&mFunctions);
michael@0 1844 return true;
michael@0 1845 #else
michael@0 1846 # error Please implement me for your platform
michael@0 1847 #endif
michael@0 1848 }
michael@0 1849
michael@0 1850 bool
michael@0 1851 PluginModuleChild::AnswerNP_Initialize(const uint32_t& aFlags, NPError* _retval)
michael@0 1852 {
michael@0 1853 PLUGIN_LOG_DEBUG_METHOD;
michael@0 1854 AssertPluginThread();
michael@0 1855
michael@0 1856 mAsyncDrawingAllowed = aFlags & kAllowAsyncDrawing;
michael@0 1857
michael@0 1858 #ifdef OS_WIN
michael@0 1859 SetEventHooks();
michael@0 1860 #endif
michael@0 1861
michael@0 1862 #ifdef MOZ_X11
michael@0 1863 // Send the parent our X socket to act as a proxy reference for our X
michael@0 1864 // resources.
michael@0 1865 int xSocketFd = ConnectionNumber(DefaultXDisplay());
michael@0 1866 SendBackUpXResources(FileDescriptor(xSocketFd));
michael@0 1867 #endif
michael@0 1868
michael@0 1869 #if defined(OS_LINUX) || defined(OS_BSD)
michael@0 1870 *_retval = mInitializeFunc(&sBrowserFuncs, &mFunctions);
michael@0 1871 return true;
michael@0 1872 #elif defined(OS_WIN) || defined(OS_MACOSX)
michael@0 1873 *_retval = mInitializeFunc(&sBrowserFuncs);
michael@0 1874 return true;
michael@0 1875 #else
michael@0 1876 # error Please implement me for your platform
michael@0 1877 #endif
michael@0 1878 }
michael@0 1879
michael@0 1880 PPluginIdentifierChild*
michael@0 1881 PluginModuleChild::AllocPPluginIdentifierChild(const nsCString& aString,
michael@0 1882 const int32_t& aInt,
michael@0 1883 const bool& aTemporary)
michael@0 1884 {
michael@0 1885 // We cannot call SetPermanent within this function because Manager() isn't
michael@0 1886 // set up yet.
michael@0 1887 if (aString.IsVoid()) {
michael@0 1888 return new PluginIdentifierChildInt(aInt);
michael@0 1889 }
michael@0 1890 return new PluginIdentifierChildString(aString);
michael@0 1891 }
michael@0 1892
michael@0 1893 bool
michael@0 1894 PluginModuleChild::RecvPPluginIdentifierConstructor(PPluginIdentifierChild* actor,
michael@0 1895 const nsCString& aString,
michael@0 1896 const int32_t& aInt,
michael@0 1897 const bool& aTemporary)
michael@0 1898 {
michael@0 1899 if (!aTemporary) {
michael@0 1900 static_cast<PluginIdentifierChild*>(actor)->MakePermanent();
michael@0 1901 }
michael@0 1902 return true;
michael@0 1903 }
michael@0 1904
michael@0 1905 bool
michael@0 1906 PluginModuleChild::DeallocPPluginIdentifierChild(PPluginIdentifierChild* aActor)
michael@0 1907 {
michael@0 1908 delete aActor;
michael@0 1909 return true;
michael@0 1910 }
michael@0 1911
michael@0 1912 #if defined(XP_WIN)
michael@0 1913 BOOL WINAPI
michael@0 1914 PMCGetWindowInfoHook(HWND hWnd, PWINDOWINFO pwi)
michael@0 1915 {
michael@0 1916 if (!pwi)
michael@0 1917 return FALSE;
michael@0 1918
michael@0 1919 if (!sGetWindowInfoPtrStub) {
michael@0 1920 NS_ASSERTION(FALSE, "Something is horribly wrong in PMCGetWindowInfoHook!");
michael@0 1921 return FALSE;
michael@0 1922 }
michael@0 1923
michael@0 1924 if (!sBrowserHwnd) {
michael@0 1925 wchar_t szClass[20];
michael@0 1926 if (GetClassNameW(hWnd, szClass, ArrayLength(szClass)) &&
michael@0 1927 !wcscmp(szClass, kMozillaWindowClass)) {
michael@0 1928 sBrowserHwnd = hWnd;
michael@0 1929 }
michael@0 1930 }
michael@0 1931 // Oddity: flash does strange rect comparisons for mouse input destined for
michael@0 1932 // it's internal settings window. Post removing sub widgets for tabs, touch
michael@0 1933 // this up so they get the rect they expect.
michael@0 1934 // XXX potentially tie this to a specific major version?
michael@0 1935 BOOL result = sGetWindowInfoPtrStub(hWnd, pwi);
michael@0 1936 if (sBrowserHwnd && sBrowserHwnd == hWnd)
michael@0 1937 pwi->rcWindow = pwi->rcClient;
michael@0 1938 return result;
michael@0 1939 }
michael@0 1940 #endif
michael@0 1941
michael@0 1942 PPluginInstanceChild*
michael@0 1943 PluginModuleChild::AllocPPluginInstanceChild(const nsCString& aMimeType,
michael@0 1944 const uint16_t& aMode,
michael@0 1945 const InfallibleTArray<nsCString>& aNames,
michael@0 1946 const InfallibleTArray<nsCString>& aValues,
michael@0 1947 NPError* rv)
michael@0 1948 {
michael@0 1949 PLUGIN_LOG_DEBUG_METHOD;
michael@0 1950 AssertPluginThread();
michael@0 1951
michael@0 1952 InitQuirksModes(aMimeType);
michael@0 1953
michael@0 1954 #ifdef XP_WIN
michael@0 1955 if ((mQuirks & QUIRK_FLASH_HOOK_GETWINDOWINFO) &&
michael@0 1956 !sGetWindowInfoPtrStub) {
michael@0 1957 sUser32Intercept.Init("user32.dll");
michael@0 1958 sUser32Intercept.AddHook("GetWindowInfo", reinterpret_cast<intptr_t>(PMCGetWindowInfoHook),
michael@0 1959 (void**) &sGetWindowInfoPtrStub);
michael@0 1960 }
michael@0 1961 #endif
michael@0 1962
michael@0 1963 return new PluginInstanceChild(&mFunctions);
michael@0 1964 }
michael@0 1965
michael@0 1966 void
michael@0 1967 PluginModuleChild::InitQuirksModes(const nsCString& aMimeType)
michael@0 1968 {
michael@0 1969 if (mQuirks != QUIRKS_NOT_INITIALIZED)
michael@0 1970 return;
michael@0 1971 mQuirks = 0;
michael@0 1972 // application/x-silverlight
michael@0 1973 // application/x-silverlight-2
michael@0 1974 NS_NAMED_LITERAL_CSTRING(silverlight, "application/x-silverlight");
michael@0 1975 if (FindInReadable(silverlight, aMimeType)) {
michael@0 1976 mQuirks |= QUIRK_SILVERLIGHT_DEFAULT_TRANSPARENT;
michael@0 1977 #ifdef OS_WIN
michael@0 1978 mQuirks |= QUIRK_WINLESS_TRACKPOPUP_HOOK;
michael@0 1979 mQuirks |= QUIRK_SILVERLIGHT_FOCUS_CHECK_PARENT;
michael@0 1980 #endif
michael@0 1981 }
michael@0 1982
michael@0 1983 #ifdef OS_WIN
michael@0 1984 // application/x-shockwave-flash
michael@0 1985 NS_NAMED_LITERAL_CSTRING(flash, "application/x-shockwave-flash");
michael@0 1986 if (FindInReadable(flash, aMimeType)) {
michael@0 1987 mQuirks |= QUIRK_WINLESS_TRACKPOPUP_HOOK;
michael@0 1988 mQuirks |= QUIRK_FLASH_THROTTLE_WMUSER_EVENTS;
michael@0 1989 mQuirks |= QUIRK_FLASH_HOOK_SETLONGPTR;
michael@0 1990 mQuirks |= QUIRK_FLASH_HOOK_GETWINDOWINFO;
michael@0 1991 mQuirks |= QUIRK_FLASH_FIXUP_MOUSE_CAPTURE;
michael@0 1992 }
michael@0 1993
michael@0 1994 // QuickTime plugin usually loaded with audio/mpeg mimetype
michael@0 1995 NS_NAMED_LITERAL_CSTRING(quicktime, "npqtplugin");
michael@0 1996 if (FindInReadable(quicktime, mPluginFilename)) {
michael@0 1997 mQuirks |= QUIRK_QUICKTIME_AVOID_SETWINDOW;
michael@0 1998 }
michael@0 1999 #endif
michael@0 2000
michael@0 2001 #ifdef XP_MACOSX
michael@0 2002 // Whitelist Flash and Quicktime to support offline renderer
michael@0 2003 NS_NAMED_LITERAL_CSTRING(flash, "application/x-shockwave-flash");
michael@0 2004 NS_NAMED_LITERAL_CSTRING(quicktime, "QuickTime Plugin.plugin");
michael@0 2005 if (FindInReadable(flash, aMimeType)) {
michael@0 2006 mQuirks |= QUIRK_FLASH_AVOID_CGMODE_CRASHES;
michael@0 2007 }
michael@0 2008 if (FindInReadable(flash, aMimeType) ||
michael@0 2009 FindInReadable(quicktime, mPluginFilename)) {
michael@0 2010 mQuirks |= QUIRK_ALLOW_OFFLINE_RENDERER;
michael@0 2011 }
michael@0 2012 #endif
michael@0 2013 }
michael@0 2014
michael@0 2015 bool
michael@0 2016 PluginModuleChild::AnswerPPluginInstanceConstructor(PPluginInstanceChild* aActor,
michael@0 2017 const nsCString& aMimeType,
michael@0 2018 const uint16_t& aMode,
michael@0 2019 const InfallibleTArray<nsCString>& aNames,
michael@0 2020 const InfallibleTArray<nsCString>& aValues,
michael@0 2021 NPError* rv)
michael@0 2022 {
michael@0 2023 PLUGIN_LOG_DEBUG_METHOD;
michael@0 2024 AssertPluginThread();
michael@0 2025
michael@0 2026 PluginInstanceChild* childInstance =
michael@0 2027 reinterpret_cast<PluginInstanceChild*>(aActor);
michael@0 2028 NS_ASSERTION(childInstance, "Null actor!");
michael@0 2029
michael@0 2030 // unpack the arguments into a C format
michael@0 2031 int argc = aNames.Length();
michael@0 2032 NS_ASSERTION(argc == (int) aValues.Length(),
michael@0 2033 "argn.length != argv.length");
michael@0 2034
michael@0 2035 nsAutoArrayPtr<char*> argn(new char*[1 + argc]);
michael@0 2036 nsAutoArrayPtr<char*> argv(new char*[1 + argc]);
michael@0 2037 argn[argc] = 0;
michael@0 2038 argv[argc] = 0;
michael@0 2039
michael@0 2040 for (int i = 0; i < argc; ++i) {
michael@0 2041 argn[i] = const_cast<char*>(NullableStringGet(aNames[i]));
michael@0 2042 argv[i] = const_cast<char*>(NullableStringGet(aValues[i]));
michael@0 2043 }
michael@0 2044
michael@0 2045 NPP npp = childInstance->GetNPP();
michael@0 2046
michael@0 2047 // FIXME/cjones: use SAFE_CALL stuff
michael@0 2048 *rv = mFunctions.newp((char*)NullableStringGet(aMimeType),
michael@0 2049 npp,
michael@0 2050 aMode,
michael@0 2051 argc,
michael@0 2052 argn,
michael@0 2053 argv,
michael@0 2054 0);
michael@0 2055 if (NPERR_NO_ERROR != *rv) {
michael@0 2056 return true;
michael@0 2057 }
michael@0 2058
michael@0 2059 childInstance->Initialize();
michael@0 2060
michael@0 2061 #if defined(XP_MACOSX) && defined(__i386__)
michael@0 2062 // If an i386 Mac OS X plugin has selected the Carbon event model then
michael@0 2063 // we have to fail. We do not support putting Carbon event model plugins
michael@0 2064 // out of process. Note that Carbon is the default model so out of process
michael@0 2065 // plugins need to actively negotiate something else in order to work
michael@0 2066 // out of process.
michael@0 2067 if (childInstance->EventModel() == NPEventModelCarbon) {
michael@0 2068 // Send notification that a plugin tried to negotiate Carbon NPAPI so that
michael@0 2069 // users can be notified that restarting the browser in i386 mode may allow
michael@0 2070 // them to use the plugin.
michael@0 2071 childInstance->SendNegotiatedCarbon();
michael@0 2072
michael@0 2073 // Fail to instantiate.
michael@0 2074 *rv = NPERR_MODULE_LOAD_FAILED_ERROR;
michael@0 2075 }
michael@0 2076 #endif
michael@0 2077
michael@0 2078 return true;
michael@0 2079 }
michael@0 2080
michael@0 2081 bool
michael@0 2082 PluginModuleChild::DeallocPPluginInstanceChild(PPluginInstanceChild* aActor)
michael@0 2083 {
michael@0 2084 PLUGIN_LOG_DEBUG_METHOD;
michael@0 2085 AssertPluginThread();
michael@0 2086
michael@0 2087 delete aActor;
michael@0 2088
michael@0 2089 return true;
michael@0 2090 }
michael@0 2091
michael@0 2092 NPObject*
michael@0 2093 PluginModuleChild::NPN_CreateObject(NPP aNPP, NPClass* aClass)
michael@0 2094 {
michael@0 2095 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 2096 ENSURE_PLUGIN_THREAD(nullptr);
michael@0 2097
michael@0 2098 PluginInstanceChild* i = InstCast(aNPP);
michael@0 2099 if (i->mDeletingHash) {
michael@0 2100 NS_ERROR("Plugin used NPP after NPP_Destroy");
michael@0 2101 return nullptr;
michael@0 2102 }
michael@0 2103
michael@0 2104 NPObject* newObject;
michael@0 2105 if (aClass && aClass->allocate) {
michael@0 2106 newObject = aClass->allocate(aNPP, aClass);
michael@0 2107 }
michael@0 2108 else {
michael@0 2109 newObject = reinterpret_cast<NPObject*>(child::_memalloc(sizeof(NPObject)));
michael@0 2110 }
michael@0 2111
michael@0 2112 if (newObject) {
michael@0 2113 newObject->_class = aClass;
michael@0 2114 newObject->referenceCount = 1;
michael@0 2115 NS_LOG_ADDREF(newObject, 1, "NPObject", sizeof(NPObject));
michael@0 2116 }
michael@0 2117
michael@0 2118 NPObjectData* d = static_cast<PluginModuleChild*>(i->Manager())
michael@0 2119 ->mObjectMap.PutEntry(newObject);
michael@0 2120 NS_ASSERTION(!d->instance, "New NPObject already mapped?");
michael@0 2121 d->instance = i;
michael@0 2122
michael@0 2123 return newObject;
michael@0 2124 }
michael@0 2125
michael@0 2126 NPObject*
michael@0 2127 PluginModuleChild::NPN_RetainObject(NPObject* aNPObj)
michael@0 2128 {
michael@0 2129 AssertPluginThread();
michael@0 2130
michael@0 2131 #ifdef NS_BUILD_REFCNT_LOGGING
michael@0 2132 int32_t refCnt =
michael@0 2133 #endif
michael@0 2134 PR_ATOMIC_INCREMENT((int32_t*)&aNPObj->referenceCount);
michael@0 2135 NS_LOG_ADDREF(aNPObj, refCnt, "NPObject", sizeof(NPObject));
michael@0 2136
michael@0 2137 return aNPObj;
michael@0 2138 }
michael@0 2139
michael@0 2140 void
michael@0 2141 PluginModuleChild::NPN_ReleaseObject(NPObject* aNPObj)
michael@0 2142 {
michael@0 2143 AssertPluginThread();
michael@0 2144
michael@0 2145 NPObjectData* d = current()->mObjectMap.GetEntry(aNPObj);
michael@0 2146 if (!d) {
michael@0 2147 NS_ERROR("Releasing object not in mObjectMap?");
michael@0 2148 return;
michael@0 2149 }
michael@0 2150
michael@0 2151 DeletingObjectEntry* doe = nullptr;
michael@0 2152 if (d->instance->mDeletingHash) {
michael@0 2153 doe = d->instance->mDeletingHash->GetEntry(aNPObj);
michael@0 2154 if (!doe) {
michael@0 2155 NS_ERROR("An object for a destroyed instance isn't in the instance deletion hash");
michael@0 2156 return;
michael@0 2157 }
michael@0 2158 if (doe->mDeleted)
michael@0 2159 return;
michael@0 2160 }
michael@0 2161
michael@0 2162 int32_t refCnt = PR_ATOMIC_DECREMENT((int32_t*)&aNPObj->referenceCount);
michael@0 2163 NS_LOG_RELEASE(aNPObj, refCnt, "NPObject");
michael@0 2164
michael@0 2165 if (refCnt == 0) {
michael@0 2166 DeallocNPObject(aNPObj);
michael@0 2167 if (doe)
michael@0 2168 doe->mDeleted = true;
michael@0 2169 }
michael@0 2170 return;
michael@0 2171 }
michael@0 2172
michael@0 2173 void
michael@0 2174 PluginModuleChild::DeallocNPObject(NPObject* aNPObj)
michael@0 2175 {
michael@0 2176 if (aNPObj->_class && aNPObj->_class->deallocate) {
michael@0 2177 aNPObj->_class->deallocate(aNPObj);
michael@0 2178 } else {
michael@0 2179 child::_memfree(aNPObj);
michael@0 2180 }
michael@0 2181
michael@0 2182 NPObjectData* d = current()->mObjectMap.GetEntry(aNPObj);
michael@0 2183 if (d->actor)
michael@0 2184 d->actor->NPObjectDestroyed();
michael@0 2185
michael@0 2186 current()->mObjectMap.RemoveEntry(aNPObj);
michael@0 2187 }
michael@0 2188
michael@0 2189 void
michael@0 2190 PluginModuleChild::FindNPObjectsForInstance(PluginInstanceChild* instance)
michael@0 2191 {
michael@0 2192 NS_ASSERTION(instance->mDeletingHash, "filling null mDeletingHash?");
michael@0 2193 mObjectMap.EnumerateEntries(CollectForInstance, instance);
michael@0 2194 }
michael@0 2195
michael@0 2196 PLDHashOperator
michael@0 2197 PluginModuleChild::CollectForInstance(NPObjectData* d, void* userArg)
michael@0 2198 {
michael@0 2199 PluginInstanceChild* instance = static_cast<PluginInstanceChild*>(userArg);
michael@0 2200 if (d->instance == instance) {
michael@0 2201 NPObject* o = d->GetKey();
michael@0 2202 instance->mDeletingHash->PutEntry(o);
michael@0 2203 }
michael@0 2204 return PL_DHASH_NEXT;
michael@0 2205 }
michael@0 2206
michael@0 2207 NPIdentifier
michael@0 2208 PluginModuleChild::NPN_GetStringIdentifier(const NPUTF8* aName)
michael@0 2209 {
michael@0 2210 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 2211 AssertPluginThread();
michael@0 2212
michael@0 2213 if (!aName)
michael@0 2214 return 0;
michael@0 2215
michael@0 2216 PluginModuleChild* self = PluginModuleChild::current();
michael@0 2217 nsDependentCString name(aName);
michael@0 2218
michael@0 2219 PluginIdentifierChildString* ident = self->mStringIdentifiers.Get(name);
michael@0 2220 if (!ident) {
michael@0 2221 nsCString nameCopy(name);
michael@0 2222
michael@0 2223 ident = new PluginIdentifierChildString(nameCopy);
michael@0 2224 self->SendPPluginIdentifierConstructor(ident, nameCopy, -1, false);
michael@0 2225 }
michael@0 2226 ident->MakePermanent();
michael@0 2227 return ident;
michael@0 2228 }
michael@0 2229
michael@0 2230 void
michael@0 2231 PluginModuleChild::NPN_GetStringIdentifiers(const NPUTF8** aNames,
michael@0 2232 int32_t aNameCount,
michael@0 2233 NPIdentifier* aIdentifiers)
michael@0 2234 {
michael@0 2235 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 2236 AssertPluginThread();
michael@0 2237
michael@0 2238 if (!(aNames && aNameCount > 0 && aIdentifiers)) {
michael@0 2239 NS_RUNTIMEABORT("Bad input! Headed for a crash!");
michael@0 2240 }
michael@0 2241
michael@0 2242 PluginModuleChild* self = PluginModuleChild::current();
michael@0 2243
michael@0 2244 for (int32_t index = 0; index < aNameCount; ++index) {
michael@0 2245 if (!aNames[index]) {
michael@0 2246 aIdentifiers[index] = 0;
michael@0 2247 continue;
michael@0 2248 }
michael@0 2249 nsDependentCString name(aNames[index]);
michael@0 2250 PluginIdentifierChildString* ident = self->mStringIdentifiers.Get(name);
michael@0 2251 if (!ident) {
michael@0 2252 nsCString nameCopy(name);
michael@0 2253
michael@0 2254 ident = new PluginIdentifierChildString(nameCopy);
michael@0 2255 self->SendPPluginIdentifierConstructor(ident, nameCopy, -1, false);
michael@0 2256 }
michael@0 2257 ident->MakePermanent();
michael@0 2258 aIdentifiers[index] = ident;
michael@0 2259 }
michael@0 2260 }
michael@0 2261
michael@0 2262 bool
michael@0 2263 PluginModuleChild::NPN_IdentifierIsString(NPIdentifier aIdentifier)
michael@0 2264 {
michael@0 2265 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 2266
michael@0 2267 PluginIdentifierChild* ident =
michael@0 2268 static_cast<PluginIdentifierChild*>(aIdentifier);
michael@0 2269 return ident->IsString();
michael@0 2270 }
michael@0 2271
michael@0 2272 NPIdentifier
michael@0 2273 PluginModuleChild::NPN_GetIntIdentifier(int32_t aIntId)
michael@0 2274 {
michael@0 2275 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 2276 AssertPluginThread();
michael@0 2277
michael@0 2278 PluginModuleChild* self = PluginModuleChild::current();
michael@0 2279
michael@0 2280 PluginIdentifierChildInt* ident = self->mIntIdentifiers.Get(aIntId);
michael@0 2281 if (!ident) {
michael@0 2282 nsCString voidString;
michael@0 2283 voidString.SetIsVoid(true);
michael@0 2284
michael@0 2285 ident = new PluginIdentifierChildInt(aIntId);
michael@0 2286 self->SendPPluginIdentifierConstructor(ident, voidString, aIntId, false);
michael@0 2287 }
michael@0 2288 ident->MakePermanent();
michael@0 2289 return ident;
michael@0 2290 }
michael@0 2291
michael@0 2292 NPUTF8*
michael@0 2293 PluginModuleChild::NPN_UTF8FromIdentifier(NPIdentifier aIdentifier)
michael@0 2294 {
michael@0 2295 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 2296
michael@0 2297 if (static_cast<PluginIdentifierChild*>(aIdentifier)->IsString()) {
michael@0 2298 return static_cast<PluginIdentifierChildString*>(aIdentifier)->ToString();
michael@0 2299 }
michael@0 2300 return nullptr;
michael@0 2301 }
michael@0 2302
michael@0 2303 int32_t
michael@0 2304 PluginModuleChild::NPN_IntFromIdentifier(NPIdentifier aIdentifier)
michael@0 2305 {
michael@0 2306 PLUGIN_LOG_DEBUG_FUNCTION;
michael@0 2307
michael@0 2308 if (!static_cast<PluginIdentifierChild*>(aIdentifier)->IsString()) {
michael@0 2309 return static_cast<PluginIdentifierChildInt*>(aIdentifier)->ToInt();
michael@0 2310 }
michael@0 2311 return INT32_MIN;
michael@0 2312 }
michael@0 2313
michael@0 2314 #ifdef OS_WIN
michael@0 2315 void
michael@0 2316 PluginModuleChild::EnteredCall()
michael@0 2317 {
michael@0 2318 mIncallPumpingStack.AppendElement();
michael@0 2319 }
michael@0 2320
michael@0 2321 void
michael@0 2322 PluginModuleChild::ExitedCall()
michael@0 2323 {
michael@0 2324 NS_ASSERTION(mIncallPumpingStack.Length(), "mismatched entered/exited");
michael@0 2325 uint32_t len = mIncallPumpingStack.Length();
michael@0 2326 const IncallFrame& f = mIncallPumpingStack[len - 1];
michael@0 2327 if (f._spinning)
michael@0 2328 MessageLoop::current()->SetNestableTasksAllowed(f._savedNestableTasksAllowed);
michael@0 2329
michael@0 2330 mIncallPumpingStack.TruncateLength(len - 1);
michael@0 2331 }
michael@0 2332
michael@0 2333 LRESULT CALLBACK
michael@0 2334 PluginModuleChild::CallWindowProcHook(int nCode, WPARAM wParam, LPARAM lParam)
michael@0 2335 {
michael@0 2336 // Trap and reply to anything we recognize as the source of a
michael@0 2337 // potential send message deadlock.
michael@0 2338 if (nCode >= 0 &&
michael@0 2339 (InSendMessageEx(nullptr)&(ISMEX_REPLIED|ISMEX_SEND)) == ISMEX_SEND) {
michael@0 2340 CWPSTRUCT* pCwp = reinterpret_cast<CWPSTRUCT*>(lParam);
michael@0 2341 if (pCwp->message == WM_KILLFOCUS) {
michael@0 2342 // Fix for flash fullscreen window loosing focus. On single
michael@0 2343 // core systems, sync killfocus events need to be handled
michael@0 2344 // after the flash fullscreen window procedure processes this
michael@0 2345 // message, otherwise fullscreen focus will not work correctly.
michael@0 2346 wchar_t szClass[26];
michael@0 2347 if (GetClassNameW(pCwp->hwnd, szClass,
michael@0 2348 sizeof(szClass)/sizeof(char16_t)) &&
michael@0 2349 !wcscmp(szClass, kFlashFullscreenClass)) {
michael@0 2350 gDelayFlashFocusReplyUntilEval = true;
michael@0 2351 }
michael@0 2352 }
michael@0 2353 }
michael@0 2354
michael@0 2355 return CallNextHookEx(nullptr, nCode, wParam, lParam);
michael@0 2356 }
michael@0 2357
michael@0 2358 LRESULT CALLBACK
michael@0 2359 PluginModuleChild::NestedInputEventHook(int nCode, WPARAM wParam, LPARAM lParam)
michael@0 2360 {
michael@0 2361 PluginModuleChild* self = current();
michael@0 2362 uint32_t len = self->mIncallPumpingStack.Length();
michael@0 2363 if (nCode >= 0 && len && !self->mIncallPumpingStack[len - 1]._spinning) {
michael@0 2364 MessageLoop* loop = MessageLoop::current();
michael@0 2365 self->SendProcessNativeEventsInInterruptCall();
michael@0 2366 IncallFrame& f = self->mIncallPumpingStack[len - 1];
michael@0 2367 f._spinning = true;
michael@0 2368 f._savedNestableTasksAllowed = loop->NestableTasksAllowed();
michael@0 2369 loop->SetNestableTasksAllowed(true);
michael@0 2370 loop->set_os_modal_loop(true);
michael@0 2371 }
michael@0 2372
michael@0 2373 return CallNextHookEx(nullptr, nCode, wParam, lParam);
michael@0 2374 }
michael@0 2375
michael@0 2376 void
michael@0 2377 PluginModuleChild::SetEventHooks()
michael@0 2378 {
michael@0 2379 NS_ASSERTION(!mNestedEventHook,
michael@0 2380 "mNestedEventHook already setup in call to SetNestedInputEventHook?");
michael@0 2381 NS_ASSERTION(!mGlobalCallWndProcHook,
michael@0 2382 "mGlobalCallWndProcHook already setup in call to CallWindowProcHook?");
michael@0 2383
michael@0 2384 PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION));
michael@0 2385
michael@0 2386 // WH_MSGFILTER event hook for detecting modal loops in the child.
michael@0 2387 mNestedEventHook = SetWindowsHookEx(WH_MSGFILTER,
michael@0 2388 NestedInputEventHook,
michael@0 2389 nullptr,
michael@0 2390 GetCurrentThreadId());
michael@0 2391
michael@0 2392 // WH_CALLWNDPROC event hook for trapping sync messages sent from
michael@0 2393 // parent that can cause deadlocks.
michael@0 2394 mGlobalCallWndProcHook = SetWindowsHookEx(WH_CALLWNDPROC,
michael@0 2395 CallWindowProcHook,
michael@0 2396 nullptr,
michael@0 2397 GetCurrentThreadId());
michael@0 2398 }
michael@0 2399
michael@0 2400 void
michael@0 2401 PluginModuleChild::ResetEventHooks()
michael@0 2402 {
michael@0 2403 PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION));
michael@0 2404 if (mNestedEventHook)
michael@0 2405 UnhookWindowsHookEx(mNestedEventHook);
michael@0 2406 mNestedEventHook = nullptr;
michael@0 2407 if (mGlobalCallWndProcHook)
michael@0 2408 UnhookWindowsHookEx(mGlobalCallWndProcHook);
michael@0 2409 mGlobalCallWndProcHook = nullptr;
michael@0 2410 }
michael@0 2411 #endif
michael@0 2412
michael@0 2413 bool
michael@0 2414 PluginModuleChild::RecvProcessNativeEventsInInterruptCall()
michael@0 2415 {
michael@0 2416 PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION));
michael@0 2417 #if defined(OS_WIN)
michael@0 2418 ProcessNativeEventsInInterruptCall();
michael@0 2419 return true;
michael@0 2420 #else
michael@0 2421 NS_RUNTIMEABORT(
michael@0 2422 "PluginModuleChild::RecvProcessNativeEventsInInterruptCall not implemented!");
michael@0 2423 return false;
michael@0 2424 #endif
michael@0 2425 }
michael@0 2426
michael@0 2427 #ifdef MOZ_WIDGET_COCOA
michael@0 2428 void
michael@0 2429 PluginModuleChild::ProcessNativeEvents() {
michael@0 2430 CallProcessSomeEvents();
michael@0 2431 }
michael@0 2432 #endif
michael@0 2433
michael@0 2434 bool
michael@0 2435 PluginModuleChild::AnswerGeckoGetProfile(nsCString* aProfile) {
michael@0 2436 char* profile = profiler_get_profile();
michael@0 2437 if (profile != nullptr) {
michael@0 2438 *aProfile = nsCString(profile, strlen(profile));
michael@0 2439 free(profile);
michael@0 2440 } else {
michael@0 2441 *aProfile = nsCString("", 0);
michael@0 2442 }
michael@0 2443 return true;
michael@0 2444 }
michael@0 2445

mercurial