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