Coverage Report

Created: 2018-09-25 14:53

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