2009-06-30 22:51:05 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
|
|
* vim: sw=4 ts=4 et :
|
2012-05-21 15:12:37 +04:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2009-06-30 22:51:05 +04:00
|
|
|
|
2011-02-17 01:43:31 +03:00
|
|
|
#include "PluginBackgroundDestroyer.h"
|
2009-09-09 10:31:35 +04:00
|
|
|
#include "PluginInstanceChild.h"
|
2009-09-18 02:15:12 +04:00
|
|
|
#include "PluginModuleChild.h"
|
2009-09-09 18:04:09 +04:00
|
|
|
#include "BrowserStreamChild.h"
|
2009-09-09 01:22:50 +04:00
|
|
|
#include "StreamNotifyChild.h"
|
2010-05-11 08:18:00 +04:00
|
|
|
#include "PluginProcessChild.h"
|
2010-09-15 20:02:49 +04:00
|
|
|
#include "gfxASurface.h"
|
2014-06-06 13:24:24 +04:00
|
|
|
#include "gfxPlatform.h"
|
|
|
|
#include "gfx2DGlue.h"
|
2012-02-16 07:24:38 +04:00
|
|
|
#include "nsNPAPIPluginInstance.h"
|
2014-06-06 13:24:24 +04:00
|
|
|
#include "mozilla/gfx/2D.h"
|
2010-09-15 20:02:49 +04:00
|
|
|
#ifdef MOZ_X11
|
|
|
|
#include "gfxXlibSurface.h"
|
|
|
|
#endif
|
2010-10-25 21:57:13 +04:00
|
|
|
#ifdef XP_WIN
|
2015-12-02 22:31:17 +03:00
|
|
|
#include "mozilla/D3DMessageUtils.h"
|
2010-10-25 21:57:13 +04:00
|
|
|
#include "mozilla/gfx/SharedDIBSurface.h"
|
2011-02-15 15:30:58 +03:00
|
|
|
#include "nsCrashOnException.h"
|
2015-12-02 22:31:17 +03:00
|
|
|
#include "gfxWindowsPlatform.h"
|
2013-12-04 16:19:38 +04:00
|
|
|
extern const wchar_t* kFlashFullscreenClass;
|
2010-10-25 21:57:13 +04:00
|
|
|
using mozilla::gfx::SharedDIBSurface;
|
|
|
|
#endif
|
2010-09-15 20:02:49 +04:00
|
|
|
#include "gfxSharedImageSurface.h"
|
|
|
|
#include "gfxUtils.h"
|
|
|
|
#include "gfxAlphaRecovery.h"
|
2009-07-02 20:54:22 +04:00
|
|
|
|
2013-12-09 06:52:54 +04:00
|
|
|
#include "mozilla/ArrayUtils.h"
|
Bug 1257759 part.5 PluginInstanceChild should post received native key event to chrome process if the key combination may be a shortcut key r=jimm
When PluginInstanceChild receives native key events, it should post the events to the chrome process first for checking if the key combination is reserved. However, posting all key events to the chrome process may make damage to the performance of text input. Therefore, this patch starts to post a key event whose key combination may be a shortcut key. However, for avoiding to shuffle the event order, it posts following key events until all posted key events are handled by the chrome process.
For receiving response from widget, this patch defines nsIKeyEventInPluginCallback. It's specified by nsIWidget::OnWindowedPluginKeyEvent() for ensuring the caller will receive the reply. Basically, the caller of nsIWidget::OnWindowedPluginKeyEvent() should reply to the child process. However, if the widget is a PuppetWidget, it cannot return the result synchronously. Therefore, PuppetWidget::OnWindowedPluginKeyEvent() returns NS_SUCCESS_EVENT_HANDLED_ASYNCHRONOUSLY and stores the callback to mKeyEventInPluginCallbacks. Then, TabParent::HandledWindowedPluginKeyEvent() will call PuppetWidget::HandledWindowedPluginKeyEvent().
MozReview-Commit-ID: G6brOU26NwQ
--HG--
extra : rebase_source : 8140456de278956d2d594e85c7b397ae366b4962
2016-04-19 14:09:37 +03:00
|
|
|
#include "mozilla/BasicEvents.h"
|
2013-09-28 05:42:08 +04:00
|
|
|
#include "mozilla/ipc/MessageChannel.h"
|
2011-07-27 16:17:50 +04:00
|
|
|
#include "mozilla/AutoRestore.h"
|
2015-05-20 22:13:16 +03:00
|
|
|
#include "mozilla/StaticPtr.h"
|
2015-10-28 16:44:19 +03:00
|
|
|
#include "mozilla/UniquePtr.h"
|
2013-10-02 04:57:50 +04:00
|
|
|
#include "ImageContainer.h"
|
2009-11-07 01:33:12 +03:00
|
|
|
|
2011-10-11 09:50:08 +04:00
|
|
|
using namespace mozilla;
|
2010-05-11 08:18:00 +04:00
|
|
|
using mozilla::ipc::ProcessChild;
|
2009-09-18 02:15:12 +04:00
|
|
|
using namespace mozilla::plugins;
|
2012-11-10 19:45:52 +04:00
|
|
|
using namespace mozilla::layers;
|
2013-12-31 13:06:12 +04:00
|
|
|
using namespace mozilla::gfx;
|
Bug 1257759 part.5 PluginInstanceChild should post received native key event to chrome process if the key combination may be a shortcut key r=jimm
When PluginInstanceChild receives native key events, it should post the events to the chrome process first for checking if the key combination is reserved. However, posting all key events to the chrome process may make damage to the performance of text input. Therefore, this patch starts to post a key event whose key combination may be a shortcut key. However, for avoiding to shuffle the event order, it posts following key events until all posted key events are handled by the chrome process.
For receiving response from widget, this patch defines nsIKeyEventInPluginCallback. It's specified by nsIWidget::OnWindowedPluginKeyEvent() for ensuring the caller will receive the reply. Basically, the caller of nsIWidget::OnWindowedPluginKeyEvent() should reply to the child process. However, if the widget is a PuppetWidget, it cannot return the result synchronously. Therefore, PuppetWidget::OnWindowedPluginKeyEvent() returns NS_SUCCESS_EVENT_HANDLED_ASYNCHRONOUSLY and stores the callback to mKeyEventInPluginCallbacks. Then, TabParent::HandledWindowedPluginKeyEvent() will call PuppetWidget::HandledWindowedPluginKeyEvent().
MozReview-Commit-ID: G6brOU26NwQ
--HG--
extra : rebase_source : 8140456de278956d2d594e85c7b397ae366b4962
2016-04-19 14:09:37 +03:00
|
|
|
using namespace mozilla::widget;
|
2012-02-16 07:30:22 +04:00
|
|
|
using namespace std;
|
2009-09-18 02:15:12 +04:00
|
|
|
|
2012-06-28 04:15:32 +04:00
|
|
|
#ifdef MOZ_WIDGET_GTK
|
2009-07-02 01:19:32 +04:00
|
|
|
|
2009-06-30 22:51:05 +04:00
|
|
|
#include <gtk/gtk.h>
|
|
|
|
#include <gdk/gdkx.h>
|
|
|
|
#include <gdk/gdk.h>
|
|
|
|
#include "gtk2xtbin.h"
|
2009-07-02 01:19:32 +04:00
|
|
|
|
|
|
|
#elif defined(OS_WIN)
|
2010-02-10 01:34:38 +03:00
|
|
|
|
2016-04-09 09:15:31 +03:00
|
|
|
#include <windows.h>
|
|
|
|
#include <windowsx.h>
|
|
|
|
|
|
|
|
#include "mozilla/widget/WinMessages.h"
|
Bug 1257759 part.5 PluginInstanceChild should post received native key event to chrome process if the key combination may be a shortcut key r=jimm
When PluginInstanceChild receives native key events, it should post the events to the chrome process first for checking if the key combination is reserved. However, posting all key events to the chrome process may make damage to the performance of text input. Therefore, this patch starts to post a key event whose key combination may be a shortcut key. However, for avoiding to shuffle the event order, it posts following key events until all posted key events are handled by the chrome process.
For receiving response from widget, this patch defines nsIKeyEventInPluginCallback. It's specified by nsIWidget::OnWindowedPluginKeyEvent() for ensuring the caller will receive the reply. Basically, the caller of nsIWidget::OnWindowedPluginKeyEvent() should reply to the child process. However, if the widget is a PuppetWidget, it cannot return the result synchronously. Therefore, PuppetWidget::OnWindowedPluginKeyEvent() returns NS_SUCCESS_EVENT_HANDLED_ASYNCHRONOUSLY and stores the callback to mKeyEventInPluginCallbacks. Then, TabParent::HandledWindowedPluginKeyEvent() will call PuppetWidget::HandledWindowedPluginKeyEvent().
MozReview-Commit-ID: G6brOU26NwQ
--HG--
extra : rebase_source : 8140456de278956d2d594e85c7b397ae366b4962
2016-04-19 14:09:37 +03:00
|
|
|
#include "mozilla/widget/WinModifierKeyState.h"
|
|
|
|
#include "mozilla/widget/WinNativeEventData.h"
|
2010-03-23 06:06:35 +03:00
|
|
|
#include "nsWindowsDllInterceptor.h"
|
2016-09-03 21:46:58 +03:00
|
|
|
#include "X11UndefineNone.h"
|
2010-03-23 06:06:35 +03:00
|
|
|
|
|
|
|
typedef BOOL (WINAPI *User32TrackPopupMenu)(HMENU hMenu,
|
|
|
|
UINT uFlags,
|
|
|
|
int x,
|
|
|
|
int y,
|
|
|
|
int nReserved,
|
|
|
|
HWND hWnd,
|
|
|
|
CONST RECT *prcRect);
|
|
|
|
static WindowsDllInterceptor sUser32Intercept;
|
2013-10-24 00:34:46 +04:00
|
|
|
static HWND sWinlessPopupSurrogateHWND = nullptr;
|
2018-06-27 20:50:50 +03:00
|
|
|
static WindowsDllInterceptor::FuncHookType<User32TrackPopupMenu> sUser32TrackPopupMenuStub;
|
2010-03-23 06:06:35 +03:00
|
|
|
|
2015-12-29 16:57:38 +03:00
|
|
|
static WindowsDllInterceptor sImm32Intercept;
|
2018-06-27 20:50:50 +03:00
|
|
|
static WindowsDllInterceptor::FuncHookType<decltype(&ImmGetContext)> sImm32ImmGetContextStub;
|
|
|
|
static WindowsDllInterceptor::FuncHookType<decltype(&ImmGetCompositionStringW)> sImm32ImmGetCompositionStringStub;
|
|
|
|
static WindowsDllInterceptor::FuncHookType<decltype(&ImmSetCandidateWindow)> sImm32ImmSetCandidateWindowStub;
|
|
|
|
static WindowsDllInterceptor::FuncHookType<decltype(&ImmNotifyIME)> sImm32ImmNotifyIME;
|
|
|
|
static WindowsDllInterceptor::FuncHookType<decltype(&ImmAssociateContextEx)> sImm32ImmAssociateContextExStub;
|
|
|
|
|
2015-12-29 16:57:38 +03:00
|
|
|
static PluginInstanceChild* sCurrentPluginInstance = nullptr;
|
|
|
|
static const HIMC sHookIMC = (const HIMC)0xefefefef;
|
|
|
|
|
2009-12-02 02:33:51 +03:00
|
|
|
using mozilla::gfx::SharedDIB;
|
2009-07-02 01:19:32 +04:00
|
|
|
|
2010-04-26 20:29:11 +04:00
|
|
|
// Flash WM_USER message delay time for PostDelayedTask. Borrowed
|
|
|
|
// from Chromium's web plugin delegate src. See 'flash msg throttling
|
|
|
|
// helpers' section for details.
|
|
|
|
const int kFlashWMUSERMessageThrottleDelayMs = 5;
|
|
|
|
|
2010-10-22 01:52:48 +04:00
|
|
|
static const TCHAR kPluginIgnoreSubclassProperty[] = TEXT("PluginIgnoreSubclassProperty");
|
|
|
|
|
2010-03-26 23:07:37 +03:00
|
|
|
#elif defined(XP_MACOSX)
|
|
|
|
#include <ApplicationServices/ApplicationServices.h>
|
2011-05-20 01:08:14 +04:00
|
|
|
#include "PluginUtilsOSX.h"
|
2010-03-26 23:07:37 +03:00
|
|
|
#endif // defined(XP_MACOSX)
|
2009-06-30 22:51:05 +04:00
|
|
|
|
2014-06-06 13:24:24 +04:00
|
|
|
/**
|
|
|
|
* We can't use gfxPlatform::CreateDrawTargetForSurface() because calling
|
|
|
|
* gfxPlatform::GetPlatform() instantiates the prefs service, and that's not
|
|
|
|
* allowed from processes other than the main process. So we have our own
|
|
|
|
* version here.
|
|
|
|
*/
|
2015-10-18 08:24:48 +03:00
|
|
|
static RefPtr<DrawTarget>
|
2014-06-06 13:24:24 +04:00
|
|
|
CreateDrawTargetForSurface(gfxASurface *aSurface)
|
|
|
|
{
|
2015-08-26 01:28:03 +03:00
|
|
|
SurfaceFormat format = aSurface->GetSurfaceFormat();
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTarget> drawTarget =
|
2014-06-06 13:24:24 +04:00
|
|
|
Factory::CreateDrawTargetForCairoSurface(aSurface->CairoSurface(),
|
2015-04-07 17:08:57 +03:00
|
|
|
aSurface->GetSize(),
|
2014-06-06 13:24:24 +04:00
|
|
|
&format);
|
2015-08-26 01:28:03 +03:00
|
|
|
if (!drawTarget) {
|
2016-12-03 00:46:53 +03:00
|
|
|
MOZ_CRASH("CreateDrawTargetForSurface failed in plugin");
|
2015-08-26 01:28:03 +03:00
|
|
|
}
|
2014-06-06 13:24:24 +04:00
|
|
|
return drawTarget;
|
|
|
|
}
|
|
|
|
|
2016-04-14 11:28:49 +03:00
|
|
|
bool PluginInstanceChild::sIsIMEComposing = false;
|
|
|
|
|
2018-04-13 16:01:28 +03:00
|
|
|
PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface,
|
|
|
|
const nsCString& aMimeType,
|
|
|
|
const InfallibleTArray<nsCString>& aNames,
|
|
|
|
const InfallibleTArray<nsCString>& aValues)
|
|
|
|
: mPluginIface(aPluginIface)
|
|
|
|
, mMimeType(aMimeType)
|
|
|
|
, mNames(aNames)
|
|
|
|
, mValues(aValues)
|
2015-09-17 23:31:34 +03:00
|
|
|
#if defined(XP_DARWIN) || defined (XP_WIN)
|
2018-04-13 16:01:28 +03:00
|
|
|
, mContentsScaleFactor(1.0)
|
2012-10-02 23:48:05 +04:00
|
|
|
#endif
|
2018-06-14 08:38:21 +03:00
|
|
|
, mCSSZoomFactor(0.0)
|
2018-04-13 16:01:28 +03:00
|
|
|
, mPostingKeyEvents(0)
|
|
|
|
, mPostingKeyEventsOutdated(0)
|
|
|
|
, mDrawingModel(kDefaultDrawingModel)
|
|
|
|
, mCurrentDirectSurface(nullptr)
|
|
|
|
, mAsyncInvalidateMutex("PluginInstanceChild::mAsyncInvalidateMutex")
|
|
|
|
, mAsyncInvalidateTask(0)
|
|
|
|
, mCachedWindowActor(nullptr)
|
|
|
|
, mCachedElementActor(nullptr)
|
2009-10-12 03:54:49 +04:00
|
|
|
#if defined(OS_WIN)
|
2018-04-13 16:01:28 +03:00
|
|
|
, mPluginWindowHWND(0)
|
|
|
|
, mPluginWndProc(0)
|
|
|
|
, mPluginParentHWND(0)
|
|
|
|
, mCachedWinlessPluginHWND(0)
|
|
|
|
, mWinlessPopupSurrogateHWND(0)
|
|
|
|
, mWinlessThrottleOldWndProc(0)
|
|
|
|
, mWinlessHiddenMsgHWND(0)
|
2010-01-15 23:35:57 +03:00
|
|
|
#endif // OS_WIN
|
2011-06-25 19:25:03 +04:00
|
|
|
#if defined(MOZ_WIDGET_COCOA)
|
2011-02-15 21:30:09 +03:00
|
|
|
#if defined(__i386__)
|
2018-04-13 16:01:28 +03:00
|
|
|
, mEventModel(NPEventModelCarbon)
|
2010-09-23 09:27:59 +04:00
|
|
|
#endif
|
2018-04-13 16:01:28 +03:00
|
|
|
, mShColorSpace(nullptr)
|
|
|
|
, mShContext(nullptr)
|
|
|
|
, mCGLayer(nullptr)
|
2018-06-14 08:38:21 +03:00
|
|
|
, mCARefreshTimer(0)
|
2018-04-13 16:01:28 +03:00
|
|
|
, mCurrentEvent(nullptr)
|
2010-09-15 20:02:49 +04:00
|
|
|
#endif
|
2018-04-13 16:01:28 +03:00
|
|
|
, mLayersRendering(false)
|
2011-01-28 01:37:00 +03:00
|
|
|
#ifdef XP_WIN
|
2018-04-13 16:01:28 +03:00
|
|
|
, mCurrentSurfaceActor(nullptr)
|
|
|
|
, mBackSurfaceActor(nullptr)
|
2011-01-28 01:37:00 +03:00
|
|
|
#endif
|
2018-04-13 16:01:28 +03:00
|
|
|
, mAccumulatedInvalidRect(0,0,0,0)
|
|
|
|
, mIsTransparent(false)
|
|
|
|
, mSurfaceType(gfxSurfaceType::Max)
|
|
|
|
, mPendingPluginCall(false)
|
|
|
|
, mDoAlphaExtraction(false)
|
|
|
|
, mHasPainted(false)
|
|
|
|
, mSurfaceDifferenceRect(0,0,0,0)
|
|
|
|
, mDestroyed(false)
|
2016-04-22 08:22:03 +03:00
|
|
|
#ifdef XP_WIN
|
2018-04-13 16:01:28 +03:00
|
|
|
, mLastKeyEventConsumed(false)
|
2018-05-17 08:47:55 +03:00
|
|
|
, mLastEnableIMEState(true)
|
2016-04-22 08:22:03 +03:00
|
|
|
#endif // #ifdef XP_WIN
|
2018-04-13 16:01:28 +03:00
|
|
|
, mStackDepth(0)
|
2010-01-15 23:35:57 +03:00
|
|
|
{
|
|
|
|
memset(&mWindow, 0, sizeof(mWindow));
|
2012-08-02 00:34:08 +04:00
|
|
|
mWindow.type = NPWindowTypeWindow;
|
2010-01-15 23:35:57 +03:00
|
|
|
mData.ndata = (void*) this;
|
2012-07-30 18:20:58 +04:00
|
|
|
mData.pdata = nullptr;
|
2009-10-12 03:54:49 +04:00
|
|
|
#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
|
2010-01-15 23:35:57 +03:00
|
|
|
mWindow.ws_info = &mWsInfo;
|
|
|
|
memset(&mWsInfo, 0, sizeof(mWsInfo));
|
2014-05-28 12:23:00 +04:00
|
|
|
#ifdef MOZ_WIDGET_GTK
|
2013-10-24 00:34:46 +04:00
|
|
|
mWsInfo.display = nullptr;
|
2012-08-02 00:34:08 +04:00
|
|
|
#else
|
2010-06-22 00:35:49 +04:00
|
|
|
mWsInfo.display = DefaultXDisplay();
|
2012-08-02 00:34:08 +04:00
|
|
|
#endif
|
2010-01-15 23:35:57 +03:00
|
|
|
#endif // MOZ_X11 && XP_UNIX && !XP_MACOSX
|
2010-03-23 06:06:35 +03:00
|
|
|
#if defined(OS_WIN)
|
|
|
|
InitPopupMenuHook();
|
2015-12-29 16:57:38 +03:00
|
|
|
InitImm32Hook();
|
2010-03-23 06:06:35 +03:00
|
|
|
#endif // OS_WIN
|
2010-01-15 23:35:57 +03:00
|
|
|
}
|
2009-10-12 03:54:49 +04:00
|
|
|
|
2009-09-09 10:31:35 +04:00
|
|
|
PluginInstanceChild::~PluginInstanceChild()
|
2009-07-02 01:19:32 +04:00
|
|
|
{
|
|
|
|
#if defined(OS_WIN)
|
2010-12-09 17:54:26 +03:00
|
|
|
NS_ASSERTION(!mPluginWindowHWND, "Destroying PluginInstanceChild without NPP_Destroy?");
|
2016-09-20 00:05:41 +03:00
|
|
|
// In the event that we registered for audio device changes, stop.
|
2016-11-29 09:52:18 +03:00
|
|
|
PluginModuleChild* chromeInstance = PluginModuleChild::GetChrome();
|
|
|
|
if (chromeInstance) {
|
2017-08-24 19:52:36 +03:00
|
|
|
chromeInstance->PluginRequiresAudioDeviceChanges(this, false);
|
2016-09-20 00:05:41 +03:00
|
|
|
}
|
2009-07-02 01:19:32 +04:00
|
|
|
#endif
|
2011-06-25 19:25:03 +04:00
|
|
|
#if defined(MOZ_WIDGET_COCOA)
|
2010-04-02 01:53:56 +04:00
|
|
|
if (mShColorSpace) {
|
|
|
|
::CGColorSpaceRelease(mShColorSpace);
|
|
|
|
}
|
|
|
|
if (mShContext) {
|
|
|
|
::CGContextRelease(mShContext);
|
|
|
|
}
|
2011-05-20 01:08:14 +04:00
|
|
|
if (mCGLayer) {
|
2011-07-12 18:31:18 +04:00
|
|
|
PluginUtilsOSX::ReleaseCGLayer(mCGLayer);
|
2011-05-20 01:08:14 +04:00
|
|
|
}
|
2011-10-14 22:00:44 +04:00
|
|
|
if (mDrawingModel == NPDrawingModelCoreAnimation) {
|
|
|
|
UnscheduleTimer(mCARefreshTimer);
|
|
|
|
}
|
2010-04-02 01:53:56 +04:00
|
|
|
#endif
|
2009-07-02 01:19:32 +04:00
|
|
|
}
|
|
|
|
|
2014-12-30 02:13:09 +03:00
|
|
|
NPError
|
|
|
|
PluginInstanceChild::DoNPP_New()
|
|
|
|
{
|
|
|
|
// unpack the arguments into a C format
|
|
|
|
int argc = mNames.Length();
|
|
|
|
NS_ASSERTION(argc == (int) mValues.Length(),
|
|
|
|
"argn.length != argv.length");
|
|
|
|
|
2015-10-28 16:44:19 +03:00
|
|
|
UniquePtr<char*[]> argn(new char*[1 + argc]);
|
|
|
|
UniquePtr<char*[]> argv(new char*[1 + argc]);
|
2014-12-30 02:13:09 +03:00
|
|
|
argn[argc] = 0;
|
|
|
|
argv[argc] = 0;
|
|
|
|
|
|
|
|
for (int i = 0; i < argc; ++i) {
|
|
|
|
argn[i] = const_cast<char*>(NullableStringGet(mNames[i]));
|
|
|
|
argv[i] = const_cast<char*>(NullableStringGet(mValues[i]));
|
|
|
|
}
|
|
|
|
|
|
|
|
NPP npp = GetNPP();
|
|
|
|
|
|
|
|
NPError rv = mPluginIface->newp((char*)NullableStringGet(mMimeType), npp,
|
2017-02-23 20:37:42 +03:00
|
|
|
NP_EMBED, argc, argn.get(), argv.get(), 0);
|
2014-12-30 02:13:09 +03:00
|
|
|
if (NPERR_NO_ERROR != rv) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2017-02-08 22:27:49 +03:00
|
|
|
if (!Initialize()) {
|
|
|
|
rv = NPERR_MODULE_LOAD_FAILED_ERROR;
|
2014-12-30 02:13:09 +03:00
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2010-12-07 03:50:47 +03:00
|
|
|
int
|
|
|
|
PluginInstanceChild::GetQuirks()
|
2010-02-25 03:13:48 +03:00
|
|
|
{
|
2014-10-29 18:05:36 +03:00
|
|
|
return PluginModuleChild::GetChrome()->GetQuirks();
|
2010-02-25 03:13:48 +03:00
|
|
|
}
|
|
|
|
|
2010-02-21 00:59:40 +03:00
|
|
|
NPError
|
|
|
|
PluginInstanceChild::InternalGetNPObjectForValue(NPNVariable aValue,
|
|
|
|
NPObject** aObject)
|
|
|
|
{
|
2013-10-24 00:34:46 +04:00
|
|
|
PluginScriptableObjectChild* actor = nullptr;
|
2010-02-21 00:59:40 +03:00
|
|
|
NPError result = NPERR_NO_ERROR;
|
|
|
|
|
|
|
|
switch (aValue) {
|
|
|
|
case NPNVWindowNPObject:
|
|
|
|
if (!(actor = mCachedWindowActor)) {
|
|
|
|
PPluginScriptableObjectChild* actorProtocol;
|
|
|
|
CallNPN_GetValue_NPNVWindowNPObject(&actorProtocol, &result);
|
|
|
|
if (result == NPERR_NO_ERROR) {
|
|
|
|
actor = mCachedWindowActor =
|
|
|
|
static_cast<PluginScriptableObjectChild*>(actorProtocol);
|
|
|
|
NS_ASSERTION(actor, "Null actor!");
|
|
|
|
PluginModuleChild::sBrowserFuncs.retainobject(
|
|
|
|
actor->GetObject(false));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NPNVPluginElementNPObject:
|
|
|
|
if (!(actor = mCachedElementActor)) {
|
|
|
|
PPluginScriptableObjectChild* actorProtocol;
|
|
|
|
CallNPN_GetValue_NPNVPluginElementNPObject(&actorProtocol,
|
|
|
|
&result);
|
|
|
|
if (result == NPERR_NO_ERROR) {
|
|
|
|
actor = mCachedElementActor =
|
|
|
|
static_cast<PluginScriptableObjectChild*>(actorProtocol);
|
|
|
|
NS_ASSERTION(actor, "Null actor!");
|
|
|
|
PluginModuleChild::sBrowserFuncs.retainobject(
|
|
|
|
actor->GetObject(false));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2018-06-18 08:43:11 +03:00
|
|
|
MOZ_ASSERT_UNREACHABLE("Don't know what to do with this value "
|
|
|
|
"type!");
|
2010-02-21 00:59:40 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
{
|
|
|
|
NPError currentResult;
|
2012-07-30 18:20:58 +04:00
|
|
|
PPluginScriptableObjectChild* currentActor = nullptr;
|
2010-02-21 00:59:40 +03:00
|
|
|
|
|
|
|
switch (aValue) {
|
|
|
|
case NPNVWindowNPObject:
|
|
|
|
CallNPN_GetValue_NPNVWindowNPObject(¤tActor,
|
|
|
|
¤tResult);
|
|
|
|
break;
|
|
|
|
case NPNVPluginElementNPObject:
|
|
|
|
CallNPN_GetValue_NPNVPluginElementNPObject(¤tActor,
|
|
|
|
¤tResult);
|
|
|
|
break;
|
|
|
|
default:
|
2012-12-27 08:24:59 +04:00
|
|
|
MOZ_ASSERT(false);
|
2010-02-21 00:59:40 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Make sure that the current actor returned by the parent matches our
|
|
|
|
// cached actor!
|
2013-01-04 18:50:43 +04:00
|
|
|
NS_ASSERTION(!currentActor ||
|
|
|
|
static_cast<PluginScriptableObjectChild*>(currentActor) ==
|
2010-02-21 00:59:40 +03:00
|
|
|
actor, "Cached actor is out of date!");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (result != NPERR_NO_ERROR) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
NPObject* object = actor->GetObject(false);
|
|
|
|
NS_ASSERTION(object, "Null object?!");
|
|
|
|
|
|
|
|
*aObject = PluginModuleChild::sBrowserFuncs.retainobject(object);
|
|
|
|
return NPERR_NO_ERROR;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2009-06-30 22:51:05 +04:00
|
|
|
NPError
|
2009-09-09 10:31:35 +04:00
|
|
|
PluginInstanceChild::NPN_GetValue(NPNVariable aVar,
|
|
|
|
void* aValue)
|
2009-06-30 22:51:05 +04:00
|
|
|
{
|
2009-12-19 01:22:51 +03:00
|
|
|
PLUGIN_LOG_DEBUG(("%s (aVar=%i)", FULLFUNCTION, (int) aVar));
|
2009-10-08 23:11:13 +04:00
|
|
|
AssertPluginThread();
|
2016-04-06 23:23:43 +03:00
|
|
|
AutoStackHelper guard(this);
|
2009-06-30 22:51:05 +04:00
|
|
|
|
|
|
|
switch(aVar) {
|
2009-07-02 20:54:22 +04:00
|
|
|
|
2011-06-02 06:27:51 +04:00
|
|
|
#if defined(MOZ_X11)
|
2009-06-30 22:51:05 +04:00
|
|
|
case NPNVToolkit:
|
|
|
|
*((NPNToolkitType*)aValue) = NPNVGtk2;
|
|
|
|
return NPERR_NO_ERROR;
|
|
|
|
|
2012-08-02 00:34:08 +04:00
|
|
|
case NPNVxDisplay:
|
|
|
|
if (!mWsInfo.display) {
|
|
|
|
// We are called before Initialize() so we have to call it now.
|
2017-02-08 22:27:49 +03:00
|
|
|
if (!Initialize()) {
|
|
|
|
return NPERR_GENERIC_ERROR;
|
|
|
|
}
|
2012-08-02 00:34:08 +04:00
|
|
|
NS_ASSERTION(mWsInfo.display, "We should have a valid display!");
|
|
|
|
}
|
|
|
|
*(void **)aValue = mWsInfo.display;
|
|
|
|
return NPERR_NO_ERROR;
|
2017-02-08 22:27:49 +03:00
|
|
|
|
2009-07-02 20:54:22 +04:00
|
|
|
#elif defined(OS_WIN)
|
|
|
|
case NPNVToolkit:
|
|
|
|
return NPERR_GENERIC_ERROR;
|
|
|
|
#endif
|
2009-09-16 00:33:24 +04:00
|
|
|
case NPNVprivateModeBool: {
|
|
|
|
bool v = false;
|
|
|
|
NPError result;
|
2009-09-19 23:24:24 +04:00
|
|
|
if (!CallNPN_GetValue_NPNVprivateModeBool(&v, &result)) {
|
|
|
|
return NPERR_GENERIC_ERROR;
|
|
|
|
}
|
2009-09-16 00:33:24 +04:00
|
|
|
*static_cast<NPBool*>(aValue) = v;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2011-09-14 20:22:27 +04:00
|
|
|
case NPNVdocumentOrigin: {
|
|
|
|
nsCString v;
|
|
|
|
NPError result;
|
|
|
|
if (!CallNPN_GetValue_NPNVdocumentOrigin(&v, &result)) {
|
|
|
|
return NPERR_GENERIC_ERROR;
|
|
|
|
}
|
2015-05-06 10:07:32 +03:00
|
|
|
if (result == NPERR_NO_ERROR ||
|
|
|
|
(GetQuirks() &
|
2015-08-12 18:00:25 +03:00
|
|
|
QUIRK_FLASH_RETURN_EMPTY_DOCUMENT_ORIGIN)) {
|
2011-09-14 20:22:27 +04:00
|
|
|
*static_cast<char**>(aValue) = ToNewCString(v);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2010-02-21 00:59:40 +03:00
|
|
|
case NPNVWindowNPObject: // Intentional fall-through
|
2009-10-08 03:50:48 +04:00
|
|
|
case NPNVPluginElementNPObject: {
|
2010-02-21 00:59:40 +03:00
|
|
|
NPObject* object;
|
|
|
|
NPError result = InternalGetNPObjectForValue(aVar, &object);
|
|
|
|
if (result == NPERR_NO_ERROR) {
|
|
|
|
*((NPObject**)aValue) = object;
|
2009-10-08 03:50:48 +04:00
|
|
|
}
|
2010-02-21 00:59:40 +03:00
|
|
|
return result;
|
2009-10-08 03:50:48 +04:00
|
|
|
}
|
|
|
|
|
2010-01-14 04:47:38 +03:00
|
|
|
case NPNVnetscapeWindow: {
|
|
|
|
#ifdef XP_WIN
|
|
|
|
if (mWindow.type == NPWindowTypeDrawable) {
|
2010-02-10 01:34:38 +03:00
|
|
|
if (mCachedWinlessPluginHWND) {
|
|
|
|
*static_cast<HWND*>(aValue) = mCachedWinlessPluginHWND;
|
|
|
|
return NPERR_NO_ERROR;
|
|
|
|
}
|
2010-01-14 04:47:38 +03:00
|
|
|
NPError result;
|
2010-02-10 01:34:38 +03:00
|
|
|
if (!CallNPN_GetValue_NPNVnetscapeWindow(&mCachedWinlessPluginHWND, &result)) {
|
2010-01-14 04:47:38 +03:00
|
|
|
return NPERR_GENERIC_ERROR;
|
|
|
|
}
|
2010-02-10 01:34:38 +03:00
|
|
|
*static_cast<HWND*>(aValue) = mCachedWinlessPluginHWND;
|
2010-01-14 04:47:38 +03:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
*static_cast<HWND*>(aValue) = mPluginWindowHWND;
|
|
|
|
return NPERR_NO_ERROR;
|
|
|
|
}
|
2010-01-14 18:18:34 +03:00
|
|
|
#elif defined(MOZ_X11)
|
|
|
|
NPError result;
|
|
|
|
CallNPN_GetValue_NPNVnetscapeWindow(static_cast<XID*>(aValue), &result);
|
|
|
|
return result;
|
2010-01-14 04:47:38 +03:00
|
|
|
#else
|
|
|
|
return NPERR_GENERIC_ERROR;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-12-02 22:31:16 +03:00
|
|
|
case NPNVsupportsAsyncBitmapSurfaceBool: {
|
|
|
|
bool value = false;
|
|
|
|
CallNPN_GetValue_SupportsAsyncBitmapSurface(&value);
|
|
|
|
*((NPBool*)aValue) = value;
|
|
|
|
return NPERR_NO_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef XP_WIN
|
|
|
|
case NPNVsupportsAsyncWindowsDXGISurfaceBool: {
|
|
|
|
bool value = false;
|
|
|
|
CallNPN_GetValue_SupportsAsyncDXGISurface(&value);
|
|
|
|
*((NPBool*)aValue) = value;
|
|
|
|
return NPERR_NO_ERROR;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-12-02 22:31:17 +03:00
|
|
|
#ifdef XP_WIN
|
|
|
|
case NPNVpreferredDXGIAdapter: {
|
|
|
|
DxgiAdapterDesc desc;
|
|
|
|
if (!CallNPN_GetValue_PreferredDXGIAdapter(&desc)) {
|
|
|
|
return NPERR_GENERIC_ERROR;
|
|
|
|
}
|
|
|
|
*reinterpret_cast<DXGI_ADAPTER_DESC*>(aValue) = desc.ToDesc();
|
|
|
|
return NPERR_NO_ERROR;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-03-26 23:07:37 +03:00
|
|
|
#ifdef XP_MACOSX
|
|
|
|
case NPNVsupportsCoreGraphicsBool: {
|
|
|
|
*((NPBool*)aValue) = true;
|
|
|
|
return NPERR_NO_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
case NPNVsupportsCoreAnimationBool: {
|
2014-12-11 17:44:07 +03:00
|
|
|
*((NPBool*)aValue) = true;
|
2010-03-26 23:07:37 +03:00
|
|
|
return NPERR_NO_ERROR;
|
|
|
|
}
|
|
|
|
|
2010-06-09 08:11:48 +04:00
|
|
|
case NPNVsupportsInvalidatingCoreAnimationBool: {
|
2014-12-11 17:44:07 +03:00
|
|
|
*((NPBool*)aValue) = true;
|
2010-06-09 08:11:48 +04:00
|
|
|
return NPERR_NO_ERROR;
|
|
|
|
}
|
|
|
|
|
2011-07-31 21:37:06 +04:00
|
|
|
case NPNVsupportsCompositingCoreAnimationPluginsBool: {
|
|
|
|
*((NPBool*)aValue) = true;
|
|
|
|
return NPERR_NO_ERROR;
|
|
|
|
}
|
|
|
|
|
2010-03-26 23:07:37 +03:00
|
|
|
case NPNVsupportsCocoaBool: {
|
|
|
|
*((NPBool*)aValue) = true;
|
|
|
|
return NPERR_NO_ERROR;
|
|
|
|
}
|
2011-01-21 04:08:11 +03:00
|
|
|
|
2011-02-03 00:05:55 +03:00
|
|
|
#ifndef NP_NO_CARBON
|
|
|
|
case NPNVsupportsCarbonBool: {
|
|
|
|
*((NPBool*)aValue) = false;
|
|
|
|
return NPERR_NO_ERROR;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2011-01-21 04:08:11 +03:00
|
|
|
case NPNVsupportsUpdatedCocoaTextInputBool: {
|
|
|
|
*static_cast<NPBool*>(aValue) = true;
|
|
|
|
return NPERR_NO_ERROR;
|
|
|
|
}
|
|
|
|
|
2010-03-26 23:07:37 +03:00
|
|
|
#ifndef NP_NO_QUICKDRAW
|
|
|
|
case NPNVsupportsQuickDrawBool: {
|
|
|
|
*((NPBool*)aValue) = false;
|
|
|
|
return NPERR_NO_ERROR;
|
|
|
|
}
|
2013-01-24 01:55:41 +04:00
|
|
|
#endif /* NP_NO_QUICKDRAW */
|
2015-09-17 23:31:34 +03:00
|
|
|
#endif /* XP_MACOSX */
|
2012-10-02 23:48:05 +04:00
|
|
|
|
2015-09-17 23:31:34 +03:00
|
|
|
#if defined(XP_MACOSX) || defined(XP_WIN)
|
2012-10-02 23:48:05 +04:00
|
|
|
case NPNVcontentsScaleFactor: {
|
2015-02-09 21:10:33 +03:00
|
|
|
*static_cast<double*>(aValue) = mContentsScaleFactor;
|
2012-10-02 23:48:05 +04:00
|
|
|
return NPERR_NO_ERROR;
|
|
|
|
}
|
2015-09-17 23:31:34 +03:00
|
|
|
#endif /* defined(XP_MACOSX) || defined(XP_WIN) */
|
2010-03-26 23:07:37 +03:00
|
|
|
|
2016-03-17 22:00:59 +03:00
|
|
|
case NPNVCSSZoomFactor: {
|
|
|
|
*static_cast<double*>(aValue) = mCSSZoomFactor;
|
|
|
|
return NPERR_NO_ERROR;
|
|
|
|
}
|
2018-06-18 08:43:11 +03:00
|
|
|
|
2012-09-27 04:22:41 +04:00
|
|
|
#ifdef DEBUG
|
|
|
|
case NPNVjavascriptEnabledBool:
|
|
|
|
case NPNVasdEnabledBool:
|
|
|
|
case NPNVisOfflineBool:
|
|
|
|
case NPNVSupportsXEmbedBool:
|
|
|
|
case NPNVSupportsWindowless:
|
2018-06-18 08:43:11 +03:00
|
|
|
MOZ_FALLTHROUGH_ASSERT("NPNVariable should be handled in "
|
|
|
|
"PluginModuleChild.");
|
2012-09-27 04:22:41 +04:00
|
|
|
#endif
|
|
|
|
|
2009-06-30 22:51:05 +04:00
|
|
|
default:
|
2015-06-04 01:25:57 +03:00
|
|
|
MOZ_LOG(GetPluginLog(), LogLevel::Warning,
|
2009-12-19 01:22:51 +03:00
|
|
|
("In PluginInstanceChild::NPN_GetValue: Unhandled NPNVariable %i (%s)",
|
|
|
|
(int) aVar, NPNVariableToString(aVar)));
|
2009-09-25 06:03:59 +04:00
|
|
|
return NPERR_GENERIC_ERROR;
|
2009-06-30 22:51:05 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-14 22:00:44 +04:00
|
|
|
#ifdef MOZ_WIDGET_COCOA
|
|
|
|
#define DEFAULT_REFRESH_MS 20 // CoreAnimation: 50 FPS
|
|
|
|
|
|
|
|
void
|
|
|
|
CAUpdate(NPP npp, uint32_t timerID) {
|
|
|
|
static_cast<PluginInstanceChild*>(npp->ndata)->Invalidate();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PluginInstanceChild::Invalidate()
|
|
|
|
{
|
2011-10-18 05:42:07 +04:00
|
|
|
NPRect windowRect = {0, 0, uint16_t(mWindow.height),
|
|
|
|
uint16_t(mWindow.width)};
|
2011-10-14 22:00:44 +04:00
|
|
|
|
|
|
|
InvalidateRect(&windowRect);
|
|
|
|
}
|
|
|
|
#endif
|
2009-09-25 06:03:59 +04:00
|
|
|
|
|
|
|
NPError
|
|
|
|
PluginInstanceChild::NPN_SetValue(NPPVariable aVar, void* aValue)
|
|
|
|
{
|
2015-06-04 01:25:57 +03:00
|
|
|
MOZ_LOG(GetPluginLog(), LogLevel::Debug, ("%s (aVar=%i, aValue=%p)",
|
2009-12-19 01:22:51 +03:00
|
|
|
FULLFUNCTION, (int) aVar, aValue));
|
|
|
|
|
2009-10-08 23:11:13 +04:00
|
|
|
AssertPluginThread();
|
2009-09-25 06:03:59 +04:00
|
|
|
|
2016-04-06 23:23:43 +03:00
|
|
|
AutoStackHelper guard(this);
|
|
|
|
|
2009-09-25 06:03:59 +04:00
|
|
|
switch (aVar) {
|
|
|
|
case NPPVpluginWindowBool: {
|
|
|
|
NPError rv;
|
|
|
|
bool windowed = (NPBool) (intptr_t) aValue;
|
|
|
|
|
2017-02-09 18:05:00 +03:00
|
|
|
if (windowed) {
|
|
|
|
return NPERR_GENERIC_ERROR;
|
|
|
|
}
|
|
|
|
|
2009-09-25 06:03:59 +04:00
|
|
|
if (!CallNPN_SetValue_NPPVpluginWindow(windowed, &rv))
|
|
|
|
return NPERR_GENERIC_ERROR;
|
|
|
|
|
2017-02-09 18:05:00 +03:00
|
|
|
mWindow.type = NPWindowTypeDrawable;
|
2009-09-25 06:03:59 +04:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
case NPPVpluginTransparentBool: {
|
|
|
|
NPError rv;
|
2010-10-27 17:13:53 +04:00
|
|
|
mIsTransparent = (!!aValue);
|
2009-09-25 06:03:59 +04:00
|
|
|
|
2010-09-15 20:02:49 +04:00
|
|
|
if (!CallNPN_SetValue_NPPVpluginTransparent(mIsTransparent, &rv))
|
2009-09-25 06:03:59 +04:00
|
|
|
return NPERR_GENERIC_ERROR;
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2011-04-08 23:58:04 +04:00
|
|
|
case NPPVpluginUsesDOMForCursorBool: {
|
|
|
|
NPError rv = NPERR_GENERIC_ERROR;
|
|
|
|
if (!CallNPN_SetValue_NPPVpluginUsesDOMForCursor((NPBool)(intptr_t)aValue, &rv)) {
|
|
|
|
return NPERR_GENERIC_ERROR;
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2010-03-26 23:07:37 +03:00
|
|
|
case NPPVpluginDrawingModel: {
|
2011-02-15 21:30:09 +03:00
|
|
|
NPError rv;
|
2012-09-17 12:37:20 +04:00
|
|
|
int drawingModel = (int16_t) (intptr_t) aValue;
|
2010-03-26 23:07:37 +03:00
|
|
|
|
2014-09-25 00:35:00 +04:00
|
|
|
if (!CallNPN_SetValue_NPPVpluginDrawingModel(drawingModel, &rv))
|
2012-02-16 07:30:22 +04:00
|
|
|
return NPERR_GENERIC_ERROR;
|
2012-02-16 07:24:38 +04:00
|
|
|
|
2011-02-15 21:30:09 +03:00
|
|
|
mDrawingModel = drawingModel;
|
2010-03-26 23:07:37 +03:00
|
|
|
|
2012-02-16 07:24:38 +04:00
|
|
|
#ifdef XP_MACOSX
|
2011-10-14 22:00:44 +04:00
|
|
|
if (drawingModel == NPDrawingModelCoreAnimation) {
|
|
|
|
mCARefreshTimer = ScheduleTimer(DEFAULT_REFRESH_MS, true, CAUpdate);
|
|
|
|
}
|
2012-02-16 07:24:38 +04:00
|
|
|
#endif
|
2011-10-14 22:00:44 +04:00
|
|
|
|
2011-05-20 01:08:14 +04:00
|
|
|
PLUGIN_LOG_DEBUG((" Plugin requested drawing model id #%i\n",
|
|
|
|
mDrawingModel));
|
|
|
|
|
2010-03-26 23:07:37 +03:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2012-02-16 07:24:38 +04:00
|
|
|
#ifdef XP_MACOSX
|
2010-03-26 23:07:37 +03:00
|
|
|
case NPPVpluginEventModel: {
|
2011-02-15 21:30:09 +03:00
|
|
|
NPError rv;
|
2012-09-17 12:37:20 +04:00
|
|
|
int eventModel = (int16_t) (intptr_t) aValue;
|
2010-03-26 23:07:37 +03:00
|
|
|
|
|
|
|
if (!CallNPN_SetValue_NPPVpluginEventModel(eventModel, &rv))
|
|
|
|
return NPERR_GENERIC_ERROR;
|
2011-02-15 21:30:09 +03:00
|
|
|
#if defined(__i386__)
|
2010-09-23 09:27:59 +04:00
|
|
|
mEventModel = static_cast<NPEventModel>(eventModel);
|
2011-02-15 21:30:09 +03:00
|
|
|
#endif
|
2010-03-26 23:07:37 +03:00
|
|
|
|
2011-05-20 01:08:14 +04:00
|
|
|
PLUGIN_LOG_DEBUG((" Plugin requested event model id # %i\n",
|
|
|
|
eventModel));
|
|
|
|
|
2010-03-26 23:07:37 +03:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-07-28 23:59:26 +03:00
|
|
|
case NPPVpluginIsPlayingAudio: {
|
|
|
|
NPError rv = NPERR_GENERIC_ERROR;
|
|
|
|
if (!CallNPN_SetValue_NPPVpluginIsPlayingAudio((NPBool)(intptr_t)aValue, &rv)) {
|
|
|
|
return NPERR_GENERIC_ERROR;
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2016-09-20 00:05:41 +03:00
|
|
|
#ifdef XP_WIN
|
|
|
|
case NPPVpluginRequiresAudioDeviceChanges: {
|
|
|
|
// Many other NPN_SetValue variables are forwarded to our
|
|
|
|
// PluginInstanceParent, which runs on a content process. We
|
|
|
|
// instead forward this message to the PluginModuleParent, which runs
|
|
|
|
// on the chrome process. This is because our audio
|
|
|
|
// API calls should run the chrome proc, not content.
|
|
|
|
NPError rv = NPERR_GENERIC_ERROR;
|
2017-03-03 00:08:29 +03:00
|
|
|
PluginModuleChild* chromeInstance = PluginModuleChild::GetChrome();
|
|
|
|
if (chromeInstance) {
|
2016-09-20 00:05:41 +03:00
|
|
|
rv = chromeInstance->PluginRequiresAudioDeviceChanges(this,
|
|
|
|
(NPBool)(intptr_t)aValue);
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-09-25 06:03:59 +04:00
|
|
|
default:
|
2015-06-04 01:25:57 +03:00
|
|
|
MOZ_LOG(GetPluginLog(), LogLevel::Warning,
|
2009-12-19 01:22:51 +03:00
|
|
|
("In PluginInstanceChild::NPN_SetValue: Unhandled NPPVariable %i (%s)",
|
|
|
|
(int) aVar, NPPVariableToString(aVar)));
|
2009-09-25 06:03:59 +04:00
|
|
|
return NPERR_GENERIC_ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2011-06-09 00:20:53 +04:00
|
|
|
PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginWantsAllNetworkStreams(
|
|
|
|
bool* wantsAllStreams, NPError* rv)
|
|
|
|
{
|
|
|
|
AssertPluginThread();
|
2016-04-06 23:23:43 +03:00
|
|
|
AutoStackHelper guard(this);
|
2011-06-09 00:20:53 +04:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t value = 0;
|
2011-06-09 00:20:53 +04:00
|
|
|
if (!mPluginIface->getvalue) {
|
|
|
|
*rv = NPERR_GENERIC_ERROR;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
*rv = mPluginIface->getvalue(GetNPP(), NPPVpluginWantsAllNetworkStreams,
|
|
|
|
&value);
|
|
|
|
}
|
|
|
|
*wantsAllStreams = value;
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2011-06-09 00:20:53 +04:00
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2009-09-18 02:15:12 +04:00
|
|
|
PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginScriptableNPObject(
|
2009-11-13 01:16:54 +03:00
|
|
|
PPluginScriptableObjectChild** aValue,
|
|
|
|
NPError* aResult)
|
2009-07-02 20:54:22 +04:00
|
|
|
{
|
2009-10-08 23:11:13 +04:00
|
|
|
AssertPluginThread();
|
2016-04-06 23:23:43 +03:00
|
|
|
AutoStackHelper guard(this);
|
2009-09-18 02:15:12 +04:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
NPObject* object = nullptr;
|
2010-02-04 03:02:48 +03:00
|
|
|
NPError result = NPERR_GENERIC_ERROR;
|
|
|
|
if (mPluginIface->getvalue) {
|
|
|
|
result = mPluginIface->getvalue(GetNPP(), NPPVpluginScriptableNPObject,
|
|
|
|
&object);
|
|
|
|
}
|
2009-11-13 01:16:54 +03:00
|
|
|
if (result == NPERR_NO_ERROR && object) {
|
|
|
|
PluginScriptableObjectChild* actor = GetActorForNPObject(object);
|
|
|
|
|
|
|
|
// If we get an actor then it has retained. Otherwise we don't need it
|
|
|
|
// any longer.
|
|
|
|
PluginModuleChild::sBrowserFuncs.releaseobject(object);
|
|
|
|
if (actor) {
|
|
|
|
*aValue = actor;
|
|
|
|
*aResult = NPERR_NO_ERROR;
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2009-11-13 01:16:54 +03:00
|
|
|
}
|
2009-10-08 03:50:48 +04:00
|
|
|
|
2009-11-13 01:16:54 +03:00
|
|
|
NS_ERROR("Failed to get actor!");
|
|
|
|
result = NPERR_GENERIC_ERROR;
|
2009-09-18 02:15:12 +04:00
|
|
|
}
|
2010-03-14 02:57:53 +03:00
|
|
|
else {
|
|
|
|
result = NPERR_GENERIC_ERROR;
|
|
|
|
}
|
2009-09-18 02:15:12 +04:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
*aValue = nullptr;
|
2009-11-13 01:16:54 +03:00
|
|
|
*aResult = result;
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2009-07-02 20:54:22 +04:00
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2011-04-27 17:42:18 +04:00
|
|
|
PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginNativeAccessibleAtkPlugId(
|
|
|
|
nsCString* aPlugId,
|
|
|
|
NPError* aResult)
|
|
|
|
{
|
|
|
|
AssertPluginThread();
|
2016-04-06 23:23:43 +03:00
|
|
|
AutoStackHelper guard(this);
|
2011-04-27 17:42:18 +04:00
|
|
|
|
|
|
|
#if MOZ_ACCESSIBILITY_ATK
|
|
|
|
|
2013-10-24 00:34:46 +04:00
|
|
|
char* plugId = nullptr;
|
2011-04-27 17:42:18 +04:00
|
|
|
NPError result = NPERR_GENERIC_ERROR;
|
|
|
|
if (mPluginIface->getvalue) {
|
|
|
|
result = mPluginIface->getvalue(GetNPP(),
|
|
|
|
NPPVpluginNativeAccessibleAtkPlugId,
|
|
|
|
&plugId);
|
|
|
|
}
|
|
|
|
|
|
|
|
*aPlugId = nsCString(plugId);
|
|
|
|
*aResult = result;
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2011-04-27 17:42:18 +04:00
|
|
|
|
|
|
|
#else
|
|
|
|
|
2017-10-25 09:30:31 +03:00
|
|
|
MOZ_CRASH("shouldn't be called on non-ATK platforms");
|
2011-04-27 17:42:18 +04:00
|
|
|
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2010-01-20 06:23:35 +03:00
|
|
|
PluginInstanceChild::AnswerNPP_SetValue_NPNVprivateModeBool(const bool& value,
|
|
|
|
NPError* result)
|
|
|
|
{
|
2010-02-04 01:17:28 +03:00
|
|
|
if (!mPluginIface->setvalue) {
|
|
|
|
*result = NPERR_GENERIC_ERROR;
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2010-02-04 01:17:28 +03:00
|
|
|
}
|
|
|
|
|
2010-03-17 20:17:09 +03:00
|
|
|
NPBool v = value;
|
2010-01-20 06:23:35 +03:00
|
|
|
*result = mPluginIface->setvalue(GetNPP(), NPNVprivateModeBool, &v);
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2010-01-20 06:23:35 +03:00
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2016-03-17 22:00:59 +03:00
|
|
|
PluginInstanceChild::AnswerNPP_SetValue_NPNVCSSZoomFactor(const double& value,
|
|
|
|
NPError* result)
|
|
|
|
{
|
|
|
|
if (!mPluginIface->setvalue) {
|
|
|
|
*result = NPERR_GENERIC_ERROR;
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2016-03-17 22:00:59 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
mCSSZoomFactor = value;
|
|
|
|
double v = value;
|
|
|
|
*result = mPluginIface->setvalue(GetNPP(), NPNVCSSZoomFactor, &v);
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2016-03-17 22:00:59 +03:00
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2015-07-27 07:05:10 +03:00
|
|
|
PluginInstanceChild::AnswerNPP_SetValue_NPNVmuteAudioBool(const bool& value,
|
|
|
|
NPError* result)
|
|
|
|
{
|
|
|
|
if (!mPluginIface->setvalue) {
|
|
|
|
*result = NPERR_GENERIC_ERROR;
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2015-07-27 07:05:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
NPBool v = value;
|
|
|
|
*result = mPluginIface->setvalue(GetNPP(), NPNVmuteAudioBool, &v);
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2015-07-27 07:05:10 +03:00
|
|
|
}
|
|
|
|
|
2016-09-20 00:05:41 +03:00
|
|
|
#if defined(XP_WIN)
|
|
|
|
NPError
|
|
|
|
PluginInstanceChild::DefaultAudioDeviceChanged(NPAudioDeviceChangeDetails& details)
|
|
|
|
{
|
|
|
|
if (!mPluginIface->setvalue) {
|
|
|
|
return NPERR_GENERIC_ERROR;
|
|
|
|
}
|
|
|
|
return mPluginIface->setvalue(GetNPP(), NPNVaudioDeviceChangeDetails, (void*)&details);
|
|
|
|
}
|
|
|
|
|
2018-06-13 23:12:54 +03:00
|
|
|
NPError
|
|
|
|
PluginInstanceChild::AudioDeviceStateChanged(NPAudioDeviceStateChanged& aDeviceState)
|
|
|
|
{
|
|
|
|
if (!mPluginIface->setvalue) {
|
|
|
|
return NPERR_GENERIC_ERROR;
|
|
|
|
}
|
|
|
|
return mPluginIface->setvalue(GetNPP(), NPNVaudioDeviceStateChanged, (void*)&aDeviceState);
|
|
|
|
}
|
|
|
|
#endif
|
2016-09-20 00:05:41 +03:00
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2009-10-27 22:58:33 +03:00
|
|
|
PluginInstanceChild::AnswerNPP_HandleEvent(const NPRemoteEvent& event,
|
2009-09-19 05:19:11 +04:00
|
|
|
int16_t* handled)
|
|
|
|
{
|
2009-12-19 01:22:51 +03:00
|
|
|
PLUGIN_LOG_DEBUG_FUNCTION;
|
2009-10-08 23:11:13 +04:00
|
|
|
AssertPluginThread();
|
2016-04-06 23:23:43 +03:00
|
|
|
AutoStackHelper guard(this);
|
2009-09-25 06:03:59 +04:00
|
|
|
|
2010-07-02 03:41:36 +04:00
|
|
|
#if defined(MOZ_X11) && defined(DEBUG)
|
2009-10-28 00:07:49 +03:00
|
|
|
if (GraphicsExpose == event.event.type)
|
2010-02-11 02:17:33 +03:00
|
|
|
PLUGIN_LOG_DEBUG((" received drawable 0x%lx\n",
|
|
|
|
event.event.xgraphicsexpose.drawable));
|
2009-09-25 06:03:59 +04:00
|
|
|
#endif
|
|
|
|
|
2010-03-26 23:07:37 +03:00
|
|
|
#ifdef XP_MACOSX
|
2010-03-17 21:38:28 +03:00
|
|
|
// Mac OS X does not define an NPEvent structure. It defines more specific types.
|
|
|
|
NPCocoaEvent evcopy = event.event;
|
2010-07-30 02:38:32 +04:00
|
|
|
|
|
|
|
// Make sure we reset mCurrentEvent in case of an exception
|
|
|
|
AutoRestore<const NPCocoaEvent*> savePreviousEvent(mCurrentEvent);
|
|
|
|
|
|
|
|
// Track the current event for NPN_PopUpContextMenu.
|
|
|
|
mCurrentEvent = &event.event;
|
2010-03-17 21:38:28 +03:00
|
|
|
#else
|
2009-12-02 00:05:26 +03:00
|
|
|
// Make a copy since we may modify values.
|
2009-10-27 22:58:33 +03:00
|
|
|
NPEvent evcopy = event.event;
|
2010-03-17 21:38:28 +03:00
|
|
|
#endif
|
2009-12-02 00:05:26 +03:00
|
|
|
|
2015-09-17 23:31:34 +03:00
|
|
|
#if defined(XP_MACOSX) || defined(XP_WIN)
|
|
|
|
// event.contentsScaleFactor <= 0 is a signal we shouldn't use it,
|
|
|
|
// for example when AnswerNPP_HandleEvent() is called from elsewhere
|
|
|
|
// in the child process (not via rpc code from the parent process).
|
|
|
|
if (event.contentsScaleFactor > 0) {
|
|
|
|
mContentsScaleFactor = event.contentsScaleFactor;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-12-02 00:05:26 +03:00
|
|
|
#ifdef OS_WIN
|
2010-05-26 04:41:02 +04:00
|
|
|
// FIXME/bug 567645: temporarily drop the "dummy event" on the floor
|
|
|
|
if (WM_NULL == evcopy.event)
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2010-05-26 04:41:02 +04:00
|
|
|
|
2010-02-10 01:34:38 +03:00
|
|
|
*handled = WinlessHandleEvent(evcopy);
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2009-12-02 00:05:26 +03:00
|
|
|
#endif
|
|
|
|
|
2011-01-07 15:18:29 +03:00
|
|
|
// XXX A previous call to mPluginIface->event might block, e.g. right click
|
|
|
|
// for context menu. Still, we might get here again, calling into the plugin
|
|
|
|
// a second time while it's in the previous call.
|
2010-03-10 18:54:22 +03:00
|
|
|
if (!mPluginIface->event)
|
|
|
|
*handled = false;
|
|
|
|
else
|
|
|
|
*handled = mPluginIface->event(&mData, reinterpret_cast<void*>(&evcopy));
|
2009-10-12 03:54:49 +04:00
|
|
|
|
2010-03-29 23:27:49 +04:00
|
|
|
#ifdef XP_MACOSX
|
|
|
|
// Release any reference counted objects created in the child process.
|
|
|
|
if (evcopy.type == NPCocoaEventKeyDown ||
|
|
|
|
evcopy.type == NPCocoaEventKeyUp) {
|
|
|
|
::CFRelease((CFStringRef)evcopy.data.key.characters);
|
|
|
|
::CFRelease((CFStringRef)evcopy.data.key.charactersIgnoringModifiers);
|
|
|
|
}
|
|
|
|
else if (evcopy.type == NPCocoaEventTextInput) {
|
|
|
|
::CFRelease((CFStringRef)evcopy.data.text.text);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-10-12 03:54:49 +04:00
|
|
|
#ifdef MOZ_X11
|
2009-10-27 23:59:40 +03:00
|
|
|
if (GraphicsExpose == event.event.type) {
|
2009-10-12 03:54:49 +04:00
|
|
|
// Make sure the X server completes the drawing before the parent
|
|
|
|
// draws on top and destroys the Drawable.
|
|
|
|
//
|
|
|
|
// XSync() waits for the X server to complete. Really this child
|
|
|
|
// process does not need to wait; the parent is the process that needs
|
|
|
|
// to wait. A possibly-slightly-better alternative would be to send
|
|
|
|
// an X event to the parent that the parent would wait for.
|
|
|
|
XSync(mWsInfo.display, False);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2009-09-19 05:19:11 +04:00
|
|
|
}
|
|
|
|
|
2010-03-26 23:07:37 +03:00
|
|
|
#ifdef XP_MACOSX
|
2010-04-20 18:52:19 +04:00
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2010-03-26 23:07:37 +03:00
|
|
|
PluginInstanceChild::AnswerNPP_HandleEvent_Shmem(const NPRemoteEvent& event,
|
2015-01-16 22:58:52 +03:00
|
|
|
Shmem&& mem,
|
2010-03-26 23:07:37 +03:00
|
|
|
int16_t* handled,
|
|
|
|
Shmem* rtnmem)
|
|
|
|
{
|
|
|
|
PLUGIN_LOG_DEBUG_FUNCTION;
|
|
|
|
AssertPluginThread();
|
2016-04-06 23:23:43 +03:00
|
|
|
AutoStackHelper guard(this);
|
2010-03-26 23:07:37 +03:00
|
|
|
|
2010-06-23 18:18:00 +04:00
|
|
|
PaintTracker pt;
|
|
|
|
|
2010-03-26 23:07:37 +03:00
|
|
|
NPCocoaEvent evcopy = event.event;
|
2012-10-02 23:48:05 +04:00
|
|
|
mContentsScaleFactor = event.contentsScaleFactor;
|
2010-03-26 23:07:37 +03:00
|
|
|
|
|
|
|
if (evcopy.type == NPCocoaEventDrawRect) {
|
2012-10-02 23:48:05 +04:00
|
|
|
int scaleFactor = ceil(mContentsScaleFactor);
|
2010-04-02 01:53:56 +04:00
|
|
|
if (!mShColorSpace) {
|
|
|
|
mShColorSpace = CreateSystemColorSpace();
|
|
|
|
if (!mShColorSpace) {
|
|
|
|
PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace."));
|
|
|
|
*handled = false;
|
|
|
|
*rtnmem = mem;
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2017-07-06 15:00:35 +03:00
|
|
|
}
|
2010-03-26 23:07:37 +03:00
|
|
|
}
|
2010-04-02 01:53:56 +04:00
|
|
|
if (!mShContext) {
|
|
|
|
void* cgContextByte = mem.get<char>();
|
2017-07-06 15:00:35 +03:00
|
|
|
mShContext = ::CGBitmapContextCreate(cgContextByte,
|
2012-10-02 23:48:05 +04:00
|
|
|
mWindow.width * scaleFactor,
|
2017-07-06 15:00:35 +03:00
|
|
|
mWindow.height * scaleFactor, 8,
|
|
|
|
mWindow.width * 4 * scaleFactor, mShColorSpace,
|
2010-04-02 01:53:56 +04:00
|
|
|
kCGImageAlphaPremultipliedFirst |
|
|
|
|
kCGBitmapByteOrder32Host);
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2010-04-02 01:53:56 +04:00
|
|
|
if (!mShContext) {
|
|
|
|
PLUGIN_LOG_DEBUG(("Could not allocate CGBitmapContext."));
|
|
|
|
*handled = false;
|
|
|
|
*rtnmem = mem;
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2010-04-02 01:53:56 +04:00
|
|
|
}
|
|
|
|
}
|
2010-04-06 23:02:54 +04:00
|
|
|
CGRect clearRect = ::CGRectMake(0, 0, mWindow.width, mWindow.height);
|
|
|
|
::CGContextClearRect(mShContext, clearRect);
|
2017-07-06 15:00:35 +03:00
|
|
|
evcopy.data.draw.context = mShContext;
|
2010-03-26 23:07:37 +03:00
|
|
|
} else {
|
|
|
|
PLUGIN_LOG_DEBUG(("Invalid event type for AnswerNNP_HandleEvent_Shmem."));
|
|
|
|
*handled = false;
|
|
|
|
*rtnmem = mem;
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2017-07-06 15:00:35 +03:00
|
|
|
}
|
2010-03-26 23:07:37 +03:00
|
|
|
|
|
|
|
if (!mPluginIface->event) {
|
|
|
|
*handled = false;
|
|
|
|
} else {
|
2010-05-20 23:22:57 +04:00
|
|
|
::CGContextSaveGState(evcopy.data.draw.context);
|
2010-03-26 23:07:37 +03:00
|
|
|
*handled = mPluginIface->event(&mData, reinterpret_cast<void*>(&evcopy));
|
2010-05-20 23:22:57 +04:00
|
|
|
::CGContextRestoreGState(evcopy.data.draw.context);
|
2010-03-26 23:07:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
*rtnmem = mem;
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2010-03-26 23:07:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2010-03-26 23:07:37 +03:00
|
|
|
PluginInstanceChild::AnswerNPP_HandleEvent_Shmem(const NPRemoteEvent& event,
|
2015-01-16 22:58:52 +03:00
|
|
|
Shmem&& mem,
|
2010-03-26 23:07:37 +03:00
|
|
|
int16_t* handled,
|
|
|
|
Shmem* rtnmem)
|
|
|
|
{
|
2016-12-03 00:46:53 +03:00
|
|
|
MOZ_CRASH("not reached.");
|
2010-03-26 23:07:37 +03:00
|
|
|
*rtnmem = mem;
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2010-03-26 23:07:37 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-04-20 18:52:19 +04:00
|
|
|
#ifdef XP_MACOSX
|
2011-05-20 01:08:14 +04:00
|
|
|
|
|
|
|
void CallCGDraw(CGContextRef ref, void* aPluginInstance, nsIntRect aUpdateRect) {
|
|
|
|
PluginInstanceChild* pluginInstance = (PluginInstanceChild*)aPluginInstance;
|
|
|
|
|
|
|
|
pluginInstance->CGDraw(ref, aUpdateRect);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
PluginInstanceChild::CGDraw(CGContextRef ref, nsIntRect aUpdateRect) {
|
|
|
|
|
|
|
|
NPCocoaEvent drawEvent;
|
|
|
|
drawEvent.type = NPCocoaEventDrawRect;
|
|
|
|
drawEvent.version = 0;
|
|
|
|
drawEvent.data.draw.x = aUpdateRect.x;
|
|
|
|
drawEvent.data.draw.y = aUpdateRect.y;
|
|
|
|
drawEvent.data.draw.width = aUpdateRect.width;
|
|
|
|
drawEvent.data.draw.height = aUpdateRect.height;
|
|
|
|
drawEvent.data.draw.context = ref;
|
|
|
|
|
|
|
|
NPRemoteEvent remoteDrawEvent = {drawEvent};
|
2012-10-02 23:48:05 +04:00
|
|
|
// Signal to AnswerNPP_HandleEvent() not to use this value
|
|
|
|
remoteDrawEvent.contentsScaleFactor = -1.0;
|
2011-05-20 01:08:14 +04:00
|
|
|
|
|
|
|
int16_t handled;
|
|
|
|
AnswerNPP_HandleEvent(remoteDrawEvent, &handled);
|
|
|
|
return handled == true;
|
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2010-04-20 18:52:19 +04:00
|
|
|
PluginInstanceChild::AnswerNPP_HandleEvent_IOSurface(const NPRemoteEvent& event,
|
|
|
|
const uint32_t &surfaceid,
|
|
|
|
int16_t* handled)
|
|
|
|
{
|
|
|
|
PLUGIN_LOG_DEBUG_FUNCTION;
|
|
|
|
AssertPluginThread();
|
2016-04-06 23:23:43 +03:00
|
|
|
AutoStackHelper guard(this);
|
2010-04-20 18:52:19 +04:00
|
|
|
|
2010-06-23 18:18:00 +04:00
|
|
|
PaintTracker pt;
|
|
|
|
|
2010-04-20 18:52:19 +04:00
|
|
|
NPCocoaEvent evcopy = event.event;
|
2012-10-02 23:48:05 +04:00
|
|
|
mContentsScaleFactor = event.contentsScaleFactor;
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<MacIOSurface> surf = MacIOSurface::LookupSurface(surfaceid,
|
2012-10-02 23:48:05 +04:00
|
|
|
mContentsScaleFactor);
|
2010-04-20 18:52:19 +04:00
|
|
|
if (!surf) {
|
2010-06-18 00:28:38 +04:00
|
|
|
NS_ERROR("Invalid IOSurface.");
|
2010-04-20 18:52:19 +04:00
|
|
|
*handled = false;
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_FAIL_NO_REASON(this);
|
2010-04-20 18:52:19 +04:00
|
|
|
}
|
|
|
|
|
2012-07-31 19:11:57 +04:00
|
|
|
if (!mCARenderer) {
|
|
|
|
mCARenderer = new nsCARenderer();
|
|
|
|
}
|
|
|
|
|
2010-04-20 18:52:19 +04:00
|
|
|
if (evcopy.type == NPCocoaEventDrawRect) {
|
2012-07-31 19:11:57 +04:00
|
|
|
mCARenderer->AttachIOSurface(surf);
|
|
|
|
if (!mCARenderer->isInit()) {
|
2012-07-30 18:20:58 +04:00
|
|
|
void *caLayer = nullptr;
|
2017-07-06 15:00:35 +03:00
|
|
|
NPError result = mPluginIface->getvalue(GetNPP(),
|
2010-04-20 18:52:19 +04:00
|
|
|
NPPVpluginCoreAnimationLayer,
|
|
|
|
&caLayer);
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2010-04-20 18:52:19 +04:00
|
|
|
if (result != NPERR_NO_ERROR || !caLayer) {
|
|
|
|
PLUGIN_LOG_DEBUG(("Plugin requested CoreAnimation but did not "
|
|
|
|
"provide CALayer."));
|
|
|
|
*handled = false;
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_FAIL_NO_REASON(this);
|
2010-04-20 18:52:19 +04:00
|
|
|
}
|
2011-05-20 01:08:14 +04:00
|
|
|
|
2012-07-31 19:11:57 +04:00
|
|
|
mCARenderer->SetupRenderer(caLayer, mWindow.width, mWindow.height,
|
2012-10-02 23:48:05 +04:00
|
|
|
mContentsScaleFactor,
|
2015-08-12 18:00:25 +03:00
|
|
|
GetQuirks() & QUIRK_ALLOW_OFFLINE_RENDERER ?
|
2011-10-21 00:32:38 +04:00
|
|
|
ALLOW_OFFLINE_RENDERER : DISALLOW_OFFLINE_RENDERER);
|
2011-05-20 01:08:14 +04:00
|
|
|
|
2010-04-20 18:52:19 +04:00
|
|
|
// Flash needs to have the window set again after this step
|
|
|
|
if (mPluginIface->setwindow)
|
|
|
|
(void) mPluginIface->setwindow(&mData, &mWindow);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
PLUGIN_LOG_DEBUG(("Invalid event type for "
|
|
|
|
"AnswerNNP_HandleEvent_IOSurface."));
|
|
|
|
*handled = false;
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_FAIL_NO_REASON(this);
|
2017-07-06 15:00:35 +03:00
|
|
|
}
|
2010-04-20 18:52:19 +04:00
|
|
|
|
2012-10-02 23:48:05 +04:00
|
|
|
mCARenderer->Render(mWindow.width, mWindow.height,
|
|
|
|
mContentsScaleFactor, nullptr);
|
2010-04-20 18:52:19 +04:00
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2010-04-20 18:52:19 +04:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2010-04-20 18:52:19 +04:00
|
|
|
PluginInstanceChild::AnswerNPP_HandleEvent_IOSurface(const NPRemoteEvent& event,
|
|
|
|
const uint32_t &surfaceid,
|
|
|
|
int16_t* handled)
|
|
|
|
{
|
2017-10-25 09:30:31 +03:00
|
|
|
MOZ_CRASH("NPP_HandleEvent_IOSurface is a OSX-only message");
|
2010-04-20 18:52:19 +04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2010-03-23 01:35:15 +03:00
|
|
|
PluginInstanceChild::RecvWindowPosChanged(const NPRemoteEvent& event)
|
|
|
|
{
|
2010-12-06 00:57:33 +03:00
|
|
|
NS_ASSERTION(!mLayersRendering && !mPendingPluginCall,
|
|
|
|
"Shouldn't be receiving WindowPosChanged with layer rendering");
|
|
|
|
|
2010-03-23 01:35:15 +03:00
|
|
|
#ifdef OS_WIN
|
|
|
|
int16_t dontcare;
|
|
|
|
return AnswerNPP_HandleEvent(event, &dontcare);
|
|
|
|
#else
|
2017-10-25 09:30:31 +03:00
|
|
|
MOZ_CRASH("WindowPosChanged is a windows-only message");
|
2010-03-23 01:35:15 +03:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2012-10-16 23:41:21 +04:00
|
|
|
PluginInstanceChild::RecvContentsScaleFactorChanged(const double& aContentsScaleFactor)
|
|
|
|
{
|
2015-09-17 23:31:34 +03:00
|
|
|
#if defined(XP_MACOSX) || defined(XP_WIN)
|
2012-10-16 23:41:21 +04:00
|
|
|
mContentsScaleFactor = aContentsScaleFactor;
|
2015-09-17 23:31:34 +03:00
|
|
|
#if defined(XP_MACOSX)
|
2012-10-16 23:41:21 +04:00
|
|
|
if (mShContext) {
|
|
|
|
// Release the shared context so that it is reallocated
|
2017-07-06 15:00:35 +03:00
|
|
|
// with the new size.
|
2012-10-16 23:41:21 +04:00
|
|
|
::CGContextRelease(mShContext);
|
|
|
|
mShContext = nullptr;
|
|
|
|
}
|
2015-09-17 23:31:34 +03:00
|
|
|
#endif
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2012-10-16 23:41:21 +04:00
|
|
|
#else
|
2017-10-25 09:30:31 +03:00
|
|
|
MOZ_CRASH("ContentsScaleFactorChanged is an Windows or OSX only message");
|
2012-10-16 23:41:21 +04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2015-08-12 18:00:26 +03:00
|
|
|
PluginInstanceChild::AnswerCreateChildPluginWindow(NativeWindowHandle* aChildPluginWindow)
|
2015-08-07 10:48:16 +03:00
|
|
|
{
|
|
|
|
#if defined(XP_WIN)
|
|
|
|
MOZ_ASSERT(!mPluginWindowHWND);
|
|
|
|
|
|
|
|
if (!CreatePluginWindow()) {
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_FAIL_NO_REASON(this);
|
2015-08-07 10:48:16 +03:00
|
|
|
}
|
|
|
|
|
2015-08-12 18:00:26 +03:00
|
|
|
MOZ_ASSERT(mPluginWindowHWND);
|
|
|
|
|
|
|
|
*aChildPluginWindow = mPluginWindowHWND;
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2015-08-12 18:00:26 +03:00
|
|
|
#else
|
2018-06-18 08:43:11 +03:00
|
|
|
MOZ_ASSERT_UNREACHABLE("CreateChildPluginWindow not implemented!");
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_FAIL_NO_REASON(this);
|
2015-08-12 18:00:26 +03:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2015-08-12 18:00:26 +03:00
|
|
|
PluginInstanceChild::RecvCreateChildPopupSurrogate(const NativeWindowHandle& aNetscapeWindow)
|
|
|
|
{
|
|
|
|
#if defined(XP_WIN)
|
|
|
|
mCachedWinlessPluginHWND = aNetscapeWindow;
|
|
|
|
CreateWinlessPopupSurrogate();
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2015-08-07 10:48:16 +03:00
|
|
|
#else
|
2018-06-18 08:43:11 +03:00
|
|
|
MOZ_ASSERT_UNREACHABLE("CreateChildPluginWindow not implemented!");
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_FAIL_NO_REASON(this);
|
2015-08-07 10:48:16 +03:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2015-08-07 10:48:16 +03:00
|
|
|
PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow)
|
2009-06-30 22:51:05 +04:00
|
|
|
{
|
2016-12-16 06:16:31 +03:00
|
|
|
PLUGIN_LOG_DEBUG(("%s (aWindow=<window: 0x%" PRIx64 ", x: %d, y: %d, width: %d, height: %d>)",
|
2009-12-19 01:22:51 +03:00
|
|
|
FULLFUNCTION,
|
|
|
|
aWindow.window,
|
|
|
|
aWindow.x, aWindow.y,
|
|
|
|
aWindow.width, aWindow.height));
|
2010-12-06 00:57:33 +03:00
|
|
|
NS_ASSERTION(!mLayersRendering && !mPendingPluginCall,
|
|
|
|
"Shouldn't be receiving NPP_SetWindow with layer rendering");
|
2009-10-08 23:11:13 +04:00
|
|
|
AssertPluginThread();
|
2016-04-06 23:23:43 +03:00
|
|
|
AutoStackHelper guard(this);
|
2009-06-30 22:51:05 +04:00
|
|
|
|
2009-10-01 01:36:14 +04:00
|
|
|
#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
|
2012-08-02 00:34:08 +04:00
|
|
|
NS_ASSERTION(mWsInfo.display, "We should have a valid display!");
|
|
|
|
|
2009-10-01 01:36:14 +04:00
|
|
|
// The minimum info is sent over IPC to allow this
|
|
|
|
// code to determine the rest.
|
2009-06-30 22:51:05 +04:00
|
|
|
|
2009-10-01 01:36:14 +04:00
|
|
|
mWindow.x = aWindow.x;
|
|
|
|
mWindow.y = aWindow.y;
|
|
|
|
mWindow.width = aWindow.width;
|
|
|
|
mWindow.height = aWindow.height;
|
|
|
|
mWindow.clipRect = aWindow.clipRect;
|
|
|
|
mWindow.type = aWindow.type;
|
2009-07-02 20:54:22 +04:00
|
|
|
|
2009-10-01 01:36:14 +04:00
|
|
|
mWsInfo.colormap = aWindow.colormap;
|
2012-08-20 08:20:37 +04:00
|
|
|
int depth;
|
|
|
|
FindVisualAndDepth(mWsInfo.display, aWindow.visualID,
|
|
|
|
&mWsInfo.visual, &depth);
|
|
|
|
mWsInfo.depth = depth;
|
2009-06-30 22:51:05 +04:00
|
|
|
|
2011-02-17 01:43:31 +03:00
|
|
|
PLUGIN_LOG_DEBUG(
|
|
|
|
("[InstanceChild][%p] Answer_SetWindow w=<x=%d,y=%d, w=%d,h=%d>, clip=<l=%d,t=%d,r=%d,b=%d>",
|
|
|
|
this, mWindow.x, mWindow.y, mWindow.width, mWindow.height,
|
|
|
|
mWindow.clipRect.left, mWindow.clipRect.top, mWindow.clipRect.right, mWindow.clipRect.bottom));
|
|
|
|
|
2010-03-10 18:54:22 +03:00
|
|
|
if (mPluginIface->setwindow)
|
|
|
|
(void) mPluginIface->setwindow(&mData, &mWindow);
|
2009-07-02 01:19:32 +04:00
|
|
|
|
2009-07-02 20:54:22 +04:00
|
|
|
#elif defined(OS_WIN)
|
2009-12-02 00:05:26 +03:00
|
|
|
switch (aWindow.type) {
|
|
|
|
case NPWindowTypeWindow:
|
|
|
|
{
|
2015-08-07 10:48:16 +03:00
|
|
|
MOZ_ASSERT(mPluginWindowHWND,
|
|
|
|
"Child plugin window must exist before call to SetWindow");
|
2009-12-02 00:05:26 +03:00
|
|
|
|
2015-08-07 10:48:16 +03:00
|
|
|
HWND parentHWND = reinterpret_cast<HWND>(aWindow.window);
|
|
|
|
if (mPluginWindowHWND != parentHWND) {
|
|
|
|
mPluginParentHWND = parentHWND;
|
2015-06-15 18:08:51 +03:00
|
|
|
ShowWindow(mPluginWindowHWND, SW_SHOWNA);
|
|
|
|
}
|
|
|
|
|
2015-08-07 10:48:16 +03:00
|
|
|
SizePluginWindow(aWindow.width, aWindow.height);
|
|
|
|
|
2009-12-02 00:05:26 +03:00
|
|
|
mWindow.window = (void*)mPluginWindowHWND;
|
|
|
|
mWindow.x = aWindow.x;
|
|
|
|
mWindow.y = aWindow.y;
|
|
|
|
mWindow.width = aWindow.width;
|
|
|
|
mWindow.height = aWindow.height;
|
|
|
|
mWindow.type = aWindow.type;
|
2015-09-17 23:31:34 +03:00
|
|
|
mContentsScaleFactor = aWindow.contentsScaleFactor;
|
2009-12-02 00:05:26 +03:00
|
|
|
|
2010-03-10 18:54:22 +03:00
|
|
|
if (mPluginIface->setwindow) {
|
2010-10-22 01:52:48 +04:00
|
|
|
SetProp(mPluginWindowHWND, kPluginIgnoreSubclassProperty, (HANDLE)1);
|
2010-03-10 18:54:22 +03:00
|
|
|
(void) mPluginIface->setwindow(&mData, &mWindow);
|
2009-12-02 00:05:26 +03:00
|
|
|
WNDPROC wndProc = reinterpret_cast<WNDPROC>(
|
|
|
|
GetWindowLongPtr(mPluginWindowHWND, GWLP_WNDPROC));
|
|
|
|
if (wndProc != PluginWindowProc) {
|
|
|
|
mPluginWndProc = reinterpret_cast<WNDPROC>(
|
|
|
|
SetWindowLongPtr(mPluginWindowHWND, GWLP_WNDPROC,
|
2010-07-12 08:49:12 +04:00
|
|
|
reinterpret_cast<LONG_PTR>(PluginWindowProc)));
|
2011-02-10 01:49:15 +03:00
|
|
|
NS_ASSERTION(mPluginWndProc != PluginWindowProc, "WTF?");
|
2009-12-02 00:05:26 +03:00
|
|
|
}
|
2010-10-22 01:52:48 +04:00
|
|
|
RemoveProp(mPluginWindowHWND, kPluginIgnoreSubclassProperty);
|
|
|
|
HookSetWindowLongPtr();
|
2009-12-02 00:05:26 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2018-06-18 08:43:11 +03:00
|
|
|
MOZ_ASSERT_UNREACHABLE("Bad plugin window type.");
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_FAIL_NO_REASON(this);
|
2009-12-02 00:05:26 +03:00
|
|
|
break;
|
2009-07-02 01:19:32 +04:00
|
|
|
}
|
|
|
|
|
2010-03-26 23:07:37 +03:00
|
|
|
#elif defined(XP_MACOSX)
|
2010-03-17 21:38:28 +03:00
|
|
|
|
|
|
|
mWindow.x = aWindow.x;
|
|
|
|
mWindow.y = aWindow.y;
|
|
|
|
mWindow.width = aWindow.width;
|
|
|
|
mWindow.height = aWindow.height;
|
|
|
|
mWindow.clipRect = aWindow.clipRect;
|
|
|
|
mWindow.type = aWindow.type;
|
2012-10-02 23:48:05 +04:00
|
|
|
mContentsScaleFactor = aWindow.contentsScaleFactor;
|
2009-11-11 05:25:10 +03:00
|
|
|
|
2010-04-02 01:53:56 +04:00
|
|
|
if (mShContext) {
|
|
|
|
// Release the shared context so that it is reallocated
|
2017-07-06 15:00:35 +03:00
|
|
|
// with the new size.
|
2010-04-02 01:53:56 +04:00
|
|
|
::CGContextRelease(mShContext);
|
2012-07-30 18:20:58 +04:00
|
|
|
mShContext = nullptr;
|
2010-04-02 01:53:56 +04:00
|
|
|
}
|
|
|
|
|
2010-03-26 23:07:37 +03:00
|
|
|
if (mPluginIface->setwindow)
|
|
|
|
(void) mPluginIface->setwindow(&mData, &mWindow);
|
|
|
|
|
2010-06-26 00:24:50 +04:00
|
|
|
#elif defined(ANDROID)
|
2012-08-07 11:06:29 +04:00
|
|
|
// TODO: Need Android impl
|
2015-06-12 15:46:43 +03:00
|
|
|
#elif defined(MOZ_WIDGET_UIKIT)
|
|
|
|
// Don't care
|
2009-06-30 22:51:05 +04:00
|
|
|
#else
|
|
|
|
# error Implement me for your OS
|
|
|
|
#endif
|
2009-07-02 20:54:22 +04:00
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2009-06-30 22:51:05 +04:00
|
|
|
}
|
|
|
|
|
2009-07-02 01:19:32 +04:00
|
|
|
bool
|
2009-09-09 10:31:35 +04:00
|
|
|
PluginInstanceChild::Initialize()
|
2009-07-02 01:19:32 +04:00
|
|
|
{
|
2014-05-28 12:23:00 +04:00
|
|
|
#ifdef MOZ_WIDGET_GTK
|
2012-08-02 00:34:08 +04:00
|
|
|
if (mWsInfo.display) {
|
|
|
|
// Already initialized
|
2017-02-08 22:27:49 +03:00
|
|
|
return true;
|
2012-08-02 00:34:08 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Request for windowless plugins is set in newp(), before this call.
|
|
|
|
if (mWindow.type == NPWindowTypeWindow) {
|
2017-02-09 18:05:00 +03:00
|
|
|
return false;
|
2012-08-02 00:34:08 +04:00
|
|
|
}
|
|
|
|
|
2017-02-09 18:05:00 +03:00
|
|
|
mWsInfo.display = DefaultXDisplay();
|
2017-02-08 22:27:49 +03:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(XP_MACOSX) && defined(__i386__)
|
|
|
|
// If an i386 Mac OS X plugin has selected the Carbon event model then
|
|
|
|
// we have to fail. We do not support putting Carbon event model plugins
|
|
|
|
// out of process. Note that Carbon is the default model so out of process
|
|
|
|
// plugins need to actively negotiate something else in order to work
|
|
|
|
// out of process.
|
|
|
|
if (EventModel() == NPEventModelCarbon) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
#endif
|
2012-08-02 00:34:08 +04:00
|
|
|
|
2009-10-08 03:50:48 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
Bug 1257759 part.5 PluginInstanceChild should post received native key event to chrome process if the key combination may be a shortcut key r=jimm
When PluginInstanceChild receives native key events, it should post the events to the chrome process first for checking if the key combination is reserved. However, posting all key events to the chrome process may make damage to the performance of text input. Therefore, this patch starts to post a key event whose key combination may be a shortcut key. However, for avoiding to shuffle the event order, it posts following key events until all posted key events are handled by the chrome process.
For receiving response from widget, this patch defines nsIKeyEventInPluginCallback. It's specified by nsIWidget::OnWindowedPluginKeyEvent() for ensuring the caller will receive the reply. Basically, the caller of nsIWidget::OnWindowedPluginKeyEvent() should reply to the child process. However, if the widget is a PuppetWidget, it cannot return the result synchronously. Therefore, PuppetWidget::OnWindowedPluginKeyEvent() returns NS_SUCCESS_EVENT_HANDLED_ASYNCHRONOUSLY and stores the callback to mKeyEventInPluginCallbacks. Then, TabParent::HandledWindowedPluginKeyEvent() will call PuppetWidget::HandledWindowedPluginKeyEvent().
MozReview-Commit-ID: G6brOU26NwQ
--HG--
extra : rebase_source : 8140456de278956d2d594e85c7b397ae366b4962
2016-04-19 14:09:37 +03:00
|
|
|
PluginInstanceChild::RecvHandledWindowedPluginKeyEvent(
|
|
|
|
const NativeEventData& aKeyEventData,
|
|
|
|
const bool& aIsConsumed)
|
|
|
|
{
|
2016-04-22 08:22:03 +03:00
|
|
|
#if defined(OS_WIN)
|
|
|
|
const WinNativeKeyEventData* eventData =
|
|
|
|
static_cast<const WinNativeKeyEventData*>(aKeyEventData);
|
|
|
|
switch (eventData->mMessage) {
|
|
|
|
case WM_KEYDOWN:
|
|
|
|
case WM_SYSKEYDOWN:
|
|
|
|
case WM_KEYUP:
|
|
|
|
case WM_SYSKEYUP:
|
|
|
|
mLastKeyEventConsumed = aIsConsumed;
|
|
|
|
break;
|
|
|
|
case WM_CHAR:
|
|
|
|
case WM_SYSCHAR:
|
|
|
|
case WM_DEADCHAR:
|
|
|
|
case WM_SYSDEADCHAR:
|
|
|
|
// If preceding keydown or keyup event is consumed by the chrome
|
|
|
|
// process, we should consume WM_*CHAR messages too.
|
|
|
|
if (mLastKeyEventConsumed) {
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2016-04-22 08:22:03 +03:00
|
|
|
}
|
|
|
|
default:
|
|
|
|
MOZ_CRASH("Needs to handle all messages posted to the parent");
|
|
|
|
}
|
|
|
|
#endif // #if defined(OS_WIN)
|
|
|
|
|
Bug 1257759 part.5 PluginInstanceChild should post received native key event to chrome process if the key combination may be a shortcut key r=jimm
When PluginInstanceChild receives native key events, it should post the events to the chrome process first for checking if the key combination is reserved. However, posting all key events to the chrome process may make damage to the performance of text input. Therefore, this patch starts to post a key event whose key combination may be a shortcut key. However, for avoiding to shuffle the event order, it posts following key events until all posted key events are handled by the chrome process.
For receiving response from widget, this patch defines nsIKeyEventInPluginCallback. It's specified by nsIWidget::OnWindowedPluginKeyEvent() for ensuring the caller will receive the reply. Basically, the caller of nsIWidget::OnWindowedPluginKeyEvent() should reply to the child process. However, if the widget is a PuppetWidget, it cannot return the result synchronously. Therefore, PuppetWidget::OnWindowedPluginKeyEvent() returns NS_SUCCESS_EVENT_HANDLED_ASYNCHRONOUSLY and stores the callback to mKeyEventInPluginCallbacks. Then, TabParent::HandledWindowedPluginKeyEvent() will call PuppetWidget::HandledWindowedPluginKeyEvent().
MozReview-Commit-ID: G6brOU26NwQ
--HG--
extra : rebase_source : 8140456de278956d2d594e85c7b397ae366b4962
2016-04-19 14:09:37 +03:00
|
|
|
// Unknown key input shouldn't be sent to plugin for security.
|
|
|
|
// XXX Is this possible if a plugin process which posted the message
|
|
|
|
// already crashed and this plugin process is recreated?
|
2016-04-14 11:28:49 +03:00
|
|
|
if (NS_WARN_IF(!mPostingKeyEvents && !mPostingKeyEventsOutdated)) {
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2016-04-14 11:28:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// If there is outdated posting key events, we should consume the key
|
|
|
|
// events.
|
|
|
|
if (mPostingKeyEventsOutdated) {
|
|
|
|
mPostingKeyEventsOutdated--;
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
Bug 1257759 part.5 PluginInstanceChild should post received native key event to chrome process if the key combination may be a shortcut key r=jimm
When PluginInstanceChild receives native key events, it should post the events to the chrome process first for checking if the key combination is reserved. However, posting all key events to the chrome process may make damage to the performance of text input. Therefore, this patch starts to post a key event whose key combination may be a shortcut key. However, for avoiding to shuffle the event order, it posts following key events until all posted key events are handled by the chrome process.
For receiving response from widget, this patch defines nsIKeyEventInPluginCallback. It's specified by nsIWidget::OnWindowedPluginKeyEvent() for ensuring the caller will receive the reply. Basically, the caller of nsIWidget::OnWindowedPluginKeyEvent() should reply to the child process. However, if the widget is a PuppetWidget, it cannot return the result synchronously. Therefore, PuppetWidget::OnWindowedPluginKeyEvent() returns NS_SUCCESS_EVENT_HANDLED_ASYNCHRONOUSLY and stores the callback to mKeyEventInPluginCallbacks. Then, TabParent::HandledWindowedPluginKeyEvent() will call PuppetWidget::HandledWindowedPluginKeyEvent().
MozReview-Commit-ID: G6brOU26NwQ
--HG--
extra : rebase_source : 8140456de278956d2d594e85c7b397ae366b4962
2016-04-19 14:09:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
mPostingKeyEvents--;
|
2016-04-14 11:28:49 +03:00
|
|
|
|
|
|
|
// If composition has been started after posting the key event,
|
|
|
|
// we should discard the event since if we send the event to plugin,
|
|
|
|
// the plugin may be confused and the result may be broken because
|
|
|
|
// the event order is shuffled.
|
|
|
|
if (aIsConsumed || sIsIMEComposing) {
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
Bug 1257759 part.5 PluginInstanceChild should post received native key event to chrome process if the key combination may be a shortcut key r=jimm
When PluginInstanceChild receives native key events, it should post the events to the chrome process first for checking if the key combination is reserved. However, posting all key events to the chrome process may make damage to the performance of text input. Therefore, this patch starts to post a key event whose key combination may be a shortcut key. However, for avoiding to shuffle the event order, it posts following key events until all posted key events are handled by the chrome process.
For receiving response from widget, this patch defines nsIKeyEventInPluginCallback. It's specified by nsIWidget::OnWindowedPluginKeyEvent() for ensuring the caller will receive the reply. Basically, the caller of nsIWidget::OnWindowedPluginKeyEvent() should reply to the child process. However, if the widget is a PuppetWidget, it cannot return the result synchronously. Therefore, PuppetWidget::OnWindowedPluginKeyEvent() returns NS_SUCCESS_EVENT_HANDLED_ASYNCHRONOUSLY and stores the callback to mKeyEventInPluginCallbacks. Then, TabParent::HandledWindowedPluginKeyEvent() will call PuppetWidget::HandledWindowedPluginKeyEvent().
MozReview-Commit-ID: G6brOU26NwQ
--HG--
extra : rebase_source : 8140456de278956d2d594e85c7b397ae366b4962
2016-04-19 14:09:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(OS_WIN)
|
|
|
|
UINT message = 0;
|
|
|
|
switch (eventData->mMessage) {
|
|
|
|
case WM_KEYDOWN:
|
|
|
|
message = MOZ_WM_KEYDOWN;
|
|
|
|
break;
|
|
|
|
case WM_SYSKEYDOWN:
|
|
|
|
message = MOZ_WM_SYSKEYDOWN;
|
|
|
|
break;
|
|
|
|
case WM_KEYUP:
|
|
|
|
message = MOZ_WM_KEYUP;
|
|
|
|
break;
|
|
|
|
case WM_SYSKEYUP:
|
|
|
|
message = MOZ_WM_SYSKEYUP;
|
|
|
|
break;
|
|
|
|
case WM_CHAR:
|
|
|
|
message = MOZ_WM_CHAR;
|
|
|
|
break;
|
|
|
|
case WM_SYSCHAR:
|
|
|
|
message = MOZ_WM_SYSCHAR;
|
|
|
|
break;
|
|
|
|
case WM_DEADCHAR:
|
|
|
|
message = MOZ_WM_DEADCHAR;
|
|
|
|
break;
|
|
|
|
case WM_SYSDEADCHAR:
|
|
|
|
message = MOZ_WM_SYSDEADCHAR;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
MOZ_CRASH("Needs to handle all messages posted to the parent");
|
|
|
|
}
|
|
|
|
PluginWindowProcInternal(mPluginWindowHWND, message,
|
|
|
|
eventData->mWParam, eventData->mLParam);
|
|
|
|
#endif
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
Bug 1257759 part.5 PluginInstanceChild should post received native key event to chrome process if the key combination may be a shortcut key r=jimm
When PluginInstanceChild receives native key events, it should post the events to the chrome process first for checking if the key combination is reserved. However, posting all key events to the chrome process may make damage to the performance of text input. Therefore, this patch starts to post a key event whose key combination may be a shortcut key. However, for avoiding to shuffle the event order, it posts following key events until all posted key events are handled by the chrome process.
For receiving response from widget, this patch defines nsIKeyEventInPluginCallback. It's specified by nsIWidget::OnWindowedPluginKeyEvent() for ensuring the caller will receive the reply. Basically, the caller of nsIWidget::OnWindowedPluginKeyEvent() should reply to the child process. However, if the widget is a PuppetWidget, it cannot return the result synchronously. Therefore, PuppetWidget::OnWindowedPluginKeyEvent() returns NS_SUCCESS_EVENT_HANDLED_ASYNCHRONOUSLY and stores the callback to mKeyEventInPluginCallbacks. Then, TabParent::HandledWindowedPluginKeyEvent() will call PuppetWidget::HandledWindowedPluginKeyEvent().
MozReview-Commit-ID: G6brOU26NwQ
--HG--
extra : rebase_source : 8140456de278956d2d594e85c7b397ae366b4962
2016-04-19 14:09:37 +03:00
|
|
|
}
|
|
|
|
|
2009-07-02 01:19:32 +04:00
|
|
|
#if defined(OS_WIN)
|
|
|
|
|
|
|
|
static const TCHAR kWindowClassName[] = TEXT("GeckoPluginWindow");
|
2009-09-09 10:31:35 +04:00
|
|
|
static const TCHAR kPluginInstanceChildProperty[] = TEXT("PluginInstanceChildProperty");
|
2010-10-22 01:52:48 +04:00
|
|
|
static const TCHAR kFlashThrottleProperty[] = TEXT("MozillaFlashThrottleProperty");
|
2009-07-02 01:19:32 +04:00
|
|
|
|
|
|
|
// static
|
|
|
|
bool
|
2009-09-09 10:31:35 +04:00
|
|
|
PluginInstanceChild::RegisterWindowClass()
|
2009-07-02 01:19:32 +04:00
|
|
|
{
|
|
|
|
static bool alreadyRegistered = false;
|
|
|
|
if (alreadyRegistered)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
alreadyRegistered = true;
|
|
|
|
|
|
|
|
WNDCLASSEX wcex;
|
|
|
|
wcex.cbSize = sizeof(WNDCLASSEX);
|
|
|
|
wcex.style = CS_DBLCLKS;
|
|
|
|
wcex.lpfnWndProc = DummyWindowProc;
|
|
|
|
wcex.cbClsExtra = 0;
|
|
|
|
wcex.cbWndExtra = 0;
|
2013-10-24 00:34:46 +04:00
|
|
|
wcex.hInstance = GetModuleHandle(nullptr);
|
2009-07-02 01:19:32 +04:00
|
|
|
wcex.hIcon = 0;
|
|
|
|
wcex.hCursor = 0;
|
2009-07-03 00:48:33 +04:00
|
|
|
wcex.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1);
|
2009-07-02 01:19:32 +04:00
|
|
|
wcex.lpszMenuName = 0;
|
|
|
|
wcex.lpszClassName = kWindowClassName;
|
|
|
|
wcex.hIconSm = 0;
|
|
|
|
|
|
|
|
return RegisterClassEx(&wcex) ? true : false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2009-09-09 10:31:35 +04:00
|
|
|
PluginInstanceChild::CreatePluginWindow()
|
2009-07-02 01:19:32 +04:00
|
|
|
{
|
2009-12-02 00:05:26 +03:00
|
|
|
// already initialized
|
|
|
|
if (mPluginWindowHWND)
|
|
|
|
return true;
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2009-07-02 01:19:32 +04:00
|
|
|
if (!RegisterWindowClass())
|
|
|
|
return false;
|
|
|
|
|
2009-12-02 00:05:26 +03:00
|
|
|
mPluginWindowHWND =
|
|
|
|
CreateWindowEx(WS_EX_LEFT | WS_EX_LTRREADING |
|
|
|
|
WS_EX_NOPARENTNOTIFY | // XXXbent Get rid of this!
|
|
|
|
WS_EX_RIGHTSCROLLBAR,
|
|
|
|
kWindowClassName, 0,
|
|
|
|
WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 0,
|
2013-10-24 00:34:46 +04:00
|
|
|
0, 0, nullptr, 0, GetModuleHandle(nullptr), 0);
|
2009-12-02 00:05:26 +03:00
|
|
|
if (!mPluginWindowHWND)
|
|
|
|
return false;
|
|
|
|
if (!SetProp(mPluginWindowHWND, kPluginInstanceChildProperty, this))
|
|
|
|
return false;
|
2009-07-02 01:19:32 +04:00
|
|
|
|
2009-12-02 00:05:26 +03:00
|
|
|
// Apparently some plugins require an ASCII WndProc.
|
|
|
|
SetWindowLongPtrA(mPluginWindowHWND, GWLP_WNDPROC,
|
2010-07-12 08:49:12 +04:00
|
|
|
reinterpret_cast<LONG_PTR>(DefWindowProcA));
|
2009-07-02 01:19:32 +04:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-09-09 10:31:35 +04:00
|
|
|
PluginInstanceChild::DestroyPluginWindow()
|
2009-07-02 01:19:32 +04:00
|
|
|
{
|
|
|
|
if (mPluginWindowHWND) {
|
|
|
|
// Unsubclass the window.
|
|
|
|
WNDPROC wndProc = reinterpret_cast<WNDPROC>(
|
|
|
|
GetWindowLongPtr(mPluginWindowHWND, GWLP_WNDPROC));
|
2010-10-22 01:52:48 +04:00
|
|
|
// Removed prior to SetWindowLongPtr, see HookSetWindowLongPtr.
|
|
|
|
RemoveProp(mPluginWindowHWND, kPluginInstanceChildProperty);
|
2009-07-02 01:19:32 +04:00
|
|
|
if (wndProc == PluginWindowProc) {
|
|
|
|
NS_ASSERTION(mPluginWndProc, "Should have old proc here!");
|
|
|
|
SetWindowLongPtr(mPluginWindowHWND, GWLP_WNDPROC,
|
2010-07-12 08:49:12 +04:00
|
|
|
reinterpret_cast<LONG_PTR>(mPluginWndProc));
|
2009-07-02 01:19:32 +04:00
|
|
|
mPluginWndProc = 0;
|
|
|
|
}
|
|
|
|
DestroyWindow(mPluginWindowHWND);
|
|
|
|
mPluginWindowHWND = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-09-09 10:31:35 +04:00
|
|
|
PluginInstanceChild::SizePluginWindow(int width,
|
|
|
|
int height)
|
2009-07-02 01:19:32 +04:00
|
|
|
{
|
|
|
|
if (mPluginWindowHWND) {
|
2010-02-18 23:20:25 +03:00
|
|
|
mPluginSize.x = width;
|
|
|
|
mPluginSize.y = height;
|
2015-08-07 10:48:16 +03:00
|
|
|
SetWindowPos(mPluginWindowHWND, nullptr, 0, 0, width, height,
|
|
|
|
SWP_NOZORDER | SWP_NOREPOSITION);
|
2009-07-02 01:19:32 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// See chromium's webplugin_delegate_impl.cc for explanation of this function.
|
|
|
|
// static
|
|
|
|
LRESULT CALLBACK
|
2009-09-09 10:31:35 +04:00
|
|
|
PluginInstanceChild::DummyWindowProc(HWND hWnd,
|
|
|
|
UINT message,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam)
|
2009-07-02 01:19:32 +04:00
|
|
|
{
|
|
|
|
return CallWindowProc(DefWindowProc, hWnd, message, wParam, lParam);
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
LRESULT CALLBACK
|
2009-09-09 10:31:35 +04:00
|
|
|
PluginInstanceChild::PluginWindowProc(HWND hWnd,
|
|
|
|
UINT message,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam)
|
2011-02-12 04:56:11 +03:00
|
|
|
{
|
|
|
|
return mozilla::CallWindowProcCrashProtected(PluginWindowProcInternal, hWnd, message, wParam, lParam);
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
LRESULT CALLBACK
|
|
|
|
PluginInstanceChild::PluginWindowProcInternal(HWND hWnd,
|
|
|
|
UINT message,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam)
|
2009-07-02 01:19:32 +04:00
|
|
|
{
|
2013-09-28 05:42:08 +04:00
|
|
|
NS_ASSERTION(!mozilla::ipc::MessageChannel::IsPumpingMessages(),
|
2009-11-07 01:33:12 +03:00
|
|
|
"Failed to prevent a nonqueued message from running!");
|
2009-09-09 10:31:35 +04:00
|
|
|
PluginInstanceChild* self = reinterpret_cast<PluginInstanceChild*>(
|
|
|
|
GetProp(hWnd, kPluginInstanceChildProperty));
|
2009-07-02 01:19:32 +04:00
|
|
|
if (!self) {
|
2018-06-18 08:43:11 +03:00
|
|
|
MOZ_ASSERT_UNREACHABLE("Badness!");
|
2009-07-02 01:19:32 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_ASSERTION(self->mPluginWindowHWND == hWnd, "Wrong window!");
|
2011-02-10 01:49:15 +03:00
|
|
|
NS_ASSERTION(self->mPluginWndProc != PluginWindowProc, "Self-referential windowproc. Infinite recursion will happen soon.");
|
2009-07-02 01:19:32 +04:00
|
|
|
|
2016-04-14 11:28:49 +03:00
|
|
|
bool isIMECompositionMessage = false;
|
2016-03-18 10:39:42 +03:00
|
|
|
switch (message) {
|
|
|
|
// Adobe's shockwave positions the plugin window relative to the browser
|
|
|
|
// frame when it initializes. With oopp disabled, this wouldn't have an
|
|
|
|
// effect. With oopp, GeckoPluginWindow is a child of the parent plugin
|
|
|
|
// window, so the move offsets the child within the parent. Generally
|
|
|
|
// we don't want plugins moving or sizing our window, so we prevent
|
|
|
|
// these changes here.
|
|
|
|
case WM_WINDOWPOSCHANGING: {
|
|
|
|
WINDOWPOS* pos = reinterpret_cast<WINDOWPOS*>(lParam);
|
|
|
|
if (pos &&
|
|
|
|
(!(pos->flags & SWP_NOMOVE) || !(pos->flags & SWP_NOSIZE))) {
|
|
|
|
pos->x = pos->y = 0;
|
|
|
|
pos->cx = self->mPluginSize.x;
|
|
|
|
pos->cy = self->mPluginSize.y;
|
|
|
|
LRESULT res = CallWindowProc(self->mPluginWndProc,
|
|
|
|
hWnd, message, wParam, lParam);
|
|
|
|
pos->x = pos->y = 0;
|
|
|
|
pos->cx = self->mPluginSize.x;
|
|
|
|
pos->cy = self->mPluginSize.y;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2010-02-18 23:20:25 +03:00
|
|
|
|
Bug 1257759 part.5 PluginInstanceChild should post received native key event to chrome process if the key combination may be a shortcut key r=jimm
When PluginInstanceChild receives native key events, it should post the events to the chrome process first for checking if the key combination is reserved. However, posting all key events to the chrome process may make damage to the performance of text input. Therefore, this patch starts to post a key event whose key combination may be a shortcut key. However, for avoiding to shuffle the event order, it posts following key events until all posted key events are handled by the chrome process.
For receiving response from widget, this patch defines nsIKeyEventInPluginCallback. It's specified by nsIWidget::OnWindowedPluginKeyEvent() for ensuring the caller will receive the reply. Basically, the caller of nsIWidget::OnWindowedPluginKeyEvent() should reply to the child process. However, if the widget is a PuppetWidget, it cannot return the result synchronously. Therefore, PuppetWidget::OnWindowedPluginKeyEvent() returns NS_SUCCESS_EVENT_HANDLED_ASYNCHRONOUSLY and stores the callback to mKeyEventInPluginCallbacks. Then, TabParent::HandledWindowedPluginKeyEvent() will call PuppetWidget::HandledWindowedPluginKeyEvent().
MozReview-Commit-ID: G6brOU26NwQ
--HG--
extra : rebase_source : 8140456de278956d2d594e85c7b397ae366b4962
2016-04-19 14:09:37 +03:00
|
|
|
case WM_SETFOCUS:
|
|
|
|
// If this gets focus, ensure that there is no pending key events.
|
|
|
|
// Even if there were, we should ignore them for performance reason.
|
|
|
|
// Although, such case shouldn't occur.
|
2016-09-02 10:12:24 +03:00
|
|
|
NS_WARNING_ASSERTION(self->mPostingKeyEvents == 0,
|
|
|
|
"pending events");
|
Bug 1257759 part.5 PluginInstanceChild should post received native key event to chrome process if the key combination may be a shortcut key r=jimm
When PluginInstanceChild receives native key events, it should post the events to the chrome process first for checking if the key combination is reserved. However, posting all key events to the chrome process may make damage to the performance of text input. Therefore, this patch starts to post a key event whose key combination may be a shortcut key. However, for avoiding to shuffle the event order, it posts following key events until all posted key events are handled by the chrome process.
For receiving response from widget, this patch defines nsIKeyEventInPluginCallback. It's specified by nsIWidget::OnWindowedPluginKeyEvent() for ensuring the caller will receive the reply. Basically, the caller of nsIWidget::OnWindowedPluginKeyEvent() should reply to the child process. However, if the widget is a PuppetWidget, it cannot return the result synchronously. Therefore, PuppetWidget::OnWindowedPluginKeyEvent() returns NS_SUCCESS_EVENT_HANDLED_ASYNCHRONOUSLY and stores the callback to mKeyEventInPluginCallbacks. Then, TabParent::HandledWindowedPluginKeyEvent() will call PuppetWidget::HandledWindowedPluginKeyEvent().
MozReview-Commit-ID: G6brOU26NwQ
--HG--
extra : rebase_source : 8140456de278956d2d594e85c7b397ae366b4962
2016-04-19 14:09:37 +03:00
|
|
|
self->mPostingKeyEvents = 0;
|
2016-04-22 08:22:03 +03:00
|
|
|
self->mLastKeyEventConsumed = false;
|
Bug 1257759 part.5 PluginInstanceChild should post received native key event to chrome process if the key combination may be a shortcut key r=jimm
When PluginInstanceChild receives native key events, it should post the events to the chrome process first for checking if the key combination is reserved. However, posting all key events to the chrome process may make damage to the performance of text input. Therefore, this patch starts to post a key event whose key combination may be a shortcut key. However, for avoiding to shuffle the event order, it posts following key events until all posted key events are handled by the chrome process.
For receiving response from widget, this patch defines nsIKeyEventInPluginCallback. It's specified by nsIWidget::OnWindowedPluginKeyEvent() for ensuring the caller will receive the reply. Basically, the caller of nsIWidget::OnWindowedPluginKeyEvent() should reply to the child process. However, if the widget is a PuppetWidget, it cannot return the result synchronously. Therefore, PuppetWidget::OnWindowedPluginKeyEvent() returns NS_SUCCESS_EVENT_HANDLED_ASYNCHRONOUSLY and stores the callback to mKeyEventInPluginCallbacks. Then, TabParent::HandledWindowedPluginKeyEvent() will call PuppetWidget::HandledWindowedPluginKeyEvent().
MozReview-Commit-ID: G6brOU26NwQ
--HG--
extra : rebase_source : 8140456de278956d2d594e85c7b397ae366b4962
2016-04-19 14:09:37 +03:00
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_KEYDOWN:
|
|
|
|
case WM_SYSKEYDOWN:
|
|
|
|
case WM_KEYUP:
|
|
|
|
case WM_SYSKEYUP:
|
|
|
|
if (self->MaybePostKeyMessage(message, wParam, lParam)) {
|
|
|
|
// If PreHandleKeyMessage() posts the message to the parent
|
|
|
|
// process, we need to wait RecvOnKeyEventHandledBeforePlugin()
|
|
|
|
// to be called.
|
|
|
|
return 0; // Consume current message temporarily.
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MOZ_WM_KEYDOWN:
|
|
|
|
message = WM_KEYDOWN;
|
|
|
|
break;
|
|
|
|
case MOZ_WM_SYSKEYDOWN:
|
|
|
|
message = WM_SYSKEYDOWN;
|
|
|
|
break;
|
|
|
|
case MOZ_WM_KEYUP:
|
|
|
|
message = WM_KEYUP;
|
|
|
|
break;
|
|
|
|
case MOZ_WM_SYSKEYUP:
|
|
|
|
message = WM_SYSKEYUP;
|
|
|
|
break;
|
|
|
|
case MOZ_WM_CHAR:
|
|
|
|
message = WM_CHAR;
|
|
|
|
break;
|
|
|
|
case MOZ_WM_SYSCHAR:
|
|
|
|
message = WM_SYSCHAR;
|
|
|
|
break;
|
|
|
|
case MOZ_WM_DEADCHAR:
|
|
|
|
message = WM_DEADCHAR;
|
|
|
|
break;
|
|
|
|
case MOZ_WM_SYSDEADCHAR:
|
|
|
|
message = WM_SYSDEADCHAR;
|
|
|
|
break;
|
|
|
|
|
2016-04-14 11:28:49 +03:00
|
|
|
case WM_IME_STARTCOMPOSITION:
|
|
|
|
isIMECompositionMessage = true;
|
|
|
|
sIsIMEComposing = true;
|
|
|
|
break;
|
|
|
|
case WM_IME_ENDCOMPOSITION:
|
|
|
|
isIMECompositionMessage = true;
|
|
|
|
sIsIMEComposing = false;
|
|
|
|
break;
|
|
|
|
case WM_IME_COMPOSITION:
|
|
|
|
isIMECompositionMessage = true;
|
|
|
|
// XXX Some old IME may not send WM_IME_COMPOSITION_START or
|
|
|
|
// WM_IME_COMPSOITION_END properly. So, we need to check
|
|
|
|
// WM_IME_COMPSOITION and if it includes commit string.
|
|
|
|
sIsIMEComposing = !(lParam & GCS_RESULTSTR);
|
|
|
|
break;
|
|
|
|
|
2016-03-18 10:39:42 +03:00
|
|
|
// The plugin received keyboard focus, let the parent know so the dom
|
|
|
|
// is up to date.
|
|
|
|
case WM_MOUSEACTIVATE:
|
|
|
|
self->CallPluginFocusChange(true);
|
|
|
|
break;
|
2015-07-06 20:39:25 +03:00
|
|
|
}
|
2010-01-27 00:40:15 +03:00
|
|
|
|
2016-04-14 11:28:49 +03:00
|
|
|
// When a composition is committed, there may be pending key
|
|
|
|
// events which were posted to the parent process before starting
|
|
|
|
// the composition. Then, we shouldn't handle it since they are
|
|
|
|
// now outdated.
|
|
|
|
if (isIMECompositionMessage && !sIsIMEComposing) {
|
|
|
|
self->mPostingKeyEventsOutdated += self->mPostingKeyEvents;
|
|
|
|
self->mPostingKeyEvents = 0;
|
|
|
|
}
|
|
|
|
|
2010-05-18 22:17:10 +04:00
|
|
|
// Prevent lockups due to plugins making rpc calls when the parent
|
|
|
|
// is making a synchronous SendMessage call to the child window. Add
|
|
|
|
// more messages as needed.
|
2013-10-24 00:34:46 +04:00
|
|
|
if ((InSendMessageEx(nullptr)&(ISMEX_REPLIED|ISMEX_SEND)) == ISMEX_SEND) {
|
2010-05-18 22:17:10 +04:00
|
|
|
switch(message) {
|
2015-07-06 20:39:25 +03:00
|
|
|
case WM_CHILDACTIVATE:
|
2010-05-18 22:17:10 +04:00
|
|
|
case WM_KILLFOCUS:
|
|
|
|
ReplyMessage(0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-06 20:39:25 +03:00
|
|
|
if (message == WM_KILLFOCUS) {
|
2010-09-21 20:03:16 +04:00
|
|
|
self->CallPluginFocusChange(false);
|
2015-07-06 20:39:25 +03:00
|
|
|
}
|
2010-06-23 21:08:56 +04:00
|
|
|
|
2010-04-26 20:29:11 +04:00
|
|
|
if (message == WM_USER+1 &&
|
2015-08-12 18:00:25 +03:00
|
|
|
(self->GetQuirks() & QUIRK_FLASH_THROTTLE_WMUSER_EVENTS)) {
|
2010-04-26 20:29:11 +04:00
|
|
|
self->FlashThrottleMessage(hWnd, message, wParam, lParam, true);
|
|
|
|
return 0;
|
|
|
|
}
|
2010-10-07 11:03:18 +04:00
|
|
|
|
2011-02-16 08:18:02 +03:00
|
|
|
NS_ASSERTION(self->mPluginWndProc != PluginWindowProc,
|
|
|
|
"Self-referential windowproc happened inside our hook proc. "
|
|
|
|
"Infinite recursion will happen soon.");
|
2011-02-10 01:49:15 +03:00
|
|
|
|
2010-12-20 17:45:59 +03:00
|
|
|
LRESULT res = CallWindowProc(self->mPluginWndProc, hWnd, message, wParam,
|
|
|
|
lParam);
|
|
|
|
|
2011-02-06 02:13:20 +03:00
|
|
|
// Make sure capture is released by the child on mouse events. Fixes a
|
|
|
|
// problem with flash full screen mode mouse input. Appears to be
|
|
|
|
// caused by a bug in flash, since we are not setting the capture
|
2011-02-16 08:18:02 +03:00
|
|
|
// on the window.
|
|
|
|
if (message == WM_LBUTTONDOWN &&
|
2015-08-12 18:00:25 +03:00
|
|
|
self->GetQuirks() & QUIRK_FLASH_FIXUP_MOUSE_CAPTURE) {
|
2013-12-04 16:19:38 +04:00
|
|
|
wchar_t szClass[26];
|
2011-02-16 08:18:02 +03:00
|
|
|
HWND hwnd = GetForegroundWindow();
|
|
|
|
if (hwnd && GetClassNameW(hwnd, szClass,
|
2014-01-04 19:02:17 +04:00
|
|
|
sizeof(szClass)/sizeof(char16_t)) &&
|
2011-02-16 08:18:02 +03:00
|
|
|
!wcscmp(szClass, kFlashFullscreenClass)) {
|
|
|
|
ReleaseCapture();
|
|
|
|
SetFocus(hwnd);
|
|
|
|
}
|
2011-02-06 02:13:20 +03:00
|
|
|
}
|
|
|
|
|
2015-07-06 20:39:25 +03:00
|
|
|
if (message == WM_CLOSE) {
|
2009-07-02 01:19:32 +04:00
|
|
|
self->DestroyPluginWindow();
|
2015-07-06 20:39:25 +03:00
|
|
|
}
|
2009-07-02 01:19:32 +04:00
|
|
|
|
2015-07-06 20:39:25 +03:00
|
|
|
if (message == WM_NCDESTROY) {
|
2009-09-09 10:31:35 +04:00
|
|
|
RemoveProp(hWnd, kPluginInstanceChildProperty);
|
2015-07-06 20:39:25 +03:00
|
|
|
}
|
2009-07-02 01:19:32 +04:00
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
Bug 1257759 part.5 PluginInstanceChild should post received native key event to chrome process if the key combination may be a shortcut key r=jimm
When PluginInstanceChild receives native key events, it should post the events to the chrome process first for checking if the key combination is reserved. However, posting all key events to the chrome process may make damage to the performance of text input. Therefore, this patch starts to post a key event whose key combination may be a shortcut key. However, for avoiding to shuffle the event order, it posts following key events until all posted key events are handled by the chrome process.
For receiving response from widget, this patch defines nsIKeyEventInPluginCallback. It's specified by nsIWidget::OnWindowedPluginKeyEvent() for ensuring the caller will receive the reply. Basically, the caller of nsIWidget::OnWindowedPluginKeyEvent() should reply to the child process. However, if the widget is a PuppetWidget, it cannot return the result synchronously. Therefore, PuppetWidget::OnWindowedPluginKeyEvent() returns NS_SUCCESS_EVENT_HANDLED_ASYNCHRONOUSLY and stores the callback to mKeyEventInPluginCallbacks. Then, TabParent::HandledWindowedPluginKeyEvent() will call PuppetWidget::HandledWindowedPluginKeyEvent().
MozReview-Commit-ID: G6brOU26NwQ
--HG--
extra : rebase_source : 8140456de278956d2d594e85c7b397ae366b4962
2016-04-19 14:09:37 +03:00
|
|
|
bool
|
|
|
|
PluginInstanceChild::ShouldPostKeyMessage(UINT message,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam)
|
|
|
|
{
|
2016-04-14 11:28:49 +03:00
|
|
|
// If there is a composition, we shouldn't post the key message to the
|
|
|
|
// parent process because we cannot handle IME messages asynchronously.
|
|
|
|
// Therefore, if we posted key events to the parent process, the event
|
|
|
|
// order of the posted key events and IME events are shuffled.
|
|
|
|
if (sIsIMEComposing) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
Bug 1257759 part.5 PluginInstanceChild should post received native key event to chrome process if the key combination may be a shortcut key r=jimm
When PluginInstanceChild receives native key events, it should post the events to the chrome process first for checking if the key combination is reserved. However, posting all key events to the chrome process may make damage to the performance of text input. Therefore, this patch starts to post a key event whose key combination may be a shortcut key. However, for avoiding to shuffle the event order, it posts following key events until all posted key events are handled by the chrome process.
For receiving response from widget, this patch defines nsIKeyEventInPluginCallback. It's specified by nsIWidget::OnWindowedPluginKeyEvent() for ensuring the caller will receive the reply. Basically, the caller of nsIWidget::OnWindowedPluginKeyEvent() should reply to the child process. However, if the widget is a PuppetWidget, it cannot return the result synchronously. Therefore, PuppetWidget::OnWindowedPluginKeyEvent() returns NS_SUCCESS_EVENT_HANDLED_ASYNCHRONOUSLY and stores the callback to mKeyEventInPluginCallbacks. Then, TabParent::HandledWindowedPluginKeyEvent() will call PuppetWidget::HandledWindowedPluginKeyEvent().
MozReview-Commit-ID: G6brOU26NwQ
--HG--
extra : rebase_source : 8140456de278956d2d594e85c7b397ae366b4962
2016-04-19 14:09:37 +03:00
|
|
|
// If there are some pending keyboard events which are not handled in
|
|
|
|
// the parent process, we should post the message for avoiding to shuffle
|
|
|
|
// the key event order.
|
|
|
|
if (mPostingKeyEvents) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we are not waiting calls of RecvOnKeyEventHandledBeforePlugin(),
|
|
|
|
// we don't need to post WM_*CHAR messages.
|
|
|
|
switch (message) {
|
|
|
|
case WM_CHAR:
|
|
|
|
case WM_SYSCHAR:
|
|
|
|
case WM_DEADCHAR:
|
|
|
|
case WM_SYSDEADCHAR:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, we should post key message which might match with a
|
|
|
|
// shortcut key.
|
|
|
|
ModifierKeyState modifierState;
|
|
|
|
if (!modifierState.MaybeMatchShortcutKey()) {
|
|
|
|
// For better UX, we shouldn't use IPC when user tries to
|
|
|
|
// input character(s).
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ignore modifier key events and keys already handled by IME.
|
|
|
|
switch (wParam) {
|
|
|
|
case VK_SHIFT:
|
|
|
|
case VK_CONTROL:
|
|
|
|
case VK_MENU:
|
|
|
|
case VK_LWIN:
|
|
|
|
case VK_RWIN:
|
|
|
|
case VK_CAPITAL:
|
|
|
|
case VK_NUMLOCK:
|
|
|
|
case VK_SCROLL:
|
|
|
|
// Following virtual keycodes shouldn't come with WM_(SYS)KEY* message
|
|
|
|
// but check it for avoiding unnecessary cross process communication.
|
|
|
|
case VK_LSHIFT:
|
|
|
|
case VK_RSHIFT:
|
|
|
|
case VK_LCONTROL:
|
|
|
|
case VK_RCONTROL:
|
|
|
|
case VK_LMENU:
|
|
|
|
case VK_RMENU:
|
|
|
|
case VK_PROCESSKEY:
|
|
|
|
case VK_PACKET:
|
|
|
|
case 0xFF: // 0xFF could be sent with unidentified key by the layout.
|
|
|
|
return false;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
PluginInstanceChild::MaybePostKeyMessage(UINT message,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam)
|
|
|
|
{
|
|
|
|
if (!ShouldPostKeyMessage(message, wParam, lParam)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
ModifierKeyState modifierState;
|
|
|
|
WinNativeKeyEventData winNativeKeyData(message, wParam, lParam,
|
|
|
|
modifierState);
|
|
|
|
NativeEventData nativeKeyData;
|
|
|
|
nativeKeyData.Copy(winNativeKeyData);
|
|
|
|
if (NS_WARN_IF(!SendOnWindowedPluginKeyEvent(nativeKeyData))) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
mPostingKeyEvents++;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-10-22 01:52:48 +04:00
|
|
|
/* set window long ptr hook for flash */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Flash will reset the subclass of our widget at various times.
|
|
|
|
* (Notably when entering and exiting full screen mode.) This
|
|
|
|
* occurs independent of the main plugin window event procedure.
|
|
|
|
* We trap these subclass calls to prevent our subclass hook from
|
|
|
|
* getting dropped.
|
|
|
|
* Note, ascii versions can be nixed once flash versions < 10.1
|
|
|
|
* are considered obsolete.
|
|
|
|
*/
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2010-10-22 01:52:48 +04:00
|
|
|
#ifdef _WIN64
|
|
|
|
typedef LONG_PTR
|
|
|
|
(WINAPI *User32SetWindowLongPtrA)(HWND hWnd,
|
|
|
|
int nIndex,
|
|
|
|
LONG_PTR dwNewLong);
|
|
|
|
typedef LONG_PTR
|
|
|
|
(WINAPI *User32SetWindowLongPtrW)(HWND hWnd,
|
|
|
|
int nIndex,
|
|
|
|
LONG_PTR dwNewLong);
|
2018-06-27 20:50:50 +03:00
|
|
|
static WindowsDllInterceptor::FuncHookType<User32SetWindowLongPtrA> sUser32SetWindowLongAHookStub;
|
|
|
|
static WindowsDllInterceptor::FuncHookType<User32SetWindowLongPtrW> sUser32SetWindowLongWHookStub;
|
2010-10-22 01:52:48 +04:00
|
|
|
#else
|
|
|
|
typedef LONG
|
|
|
|
(WINAPI *User32SetWindowLongA)(HWND hWnd,
|
|
|
|
int nIndex,
|
|
|
|
LONG dwNewLong);
|
|
|
|
typedef LONG
|
|
|
|
(WINAPI *User32SetWindowLongW)(HWND hWnd,
|
|
|
|
int nIndex,
|
|
|
|
LONG dwNewLong);
|
2018-06-27 20:50:50 +03:00
|
|
|
static WindowsDllInterceptor::FuncHookType<User32SetWindowLongA> sUser32SetWindowLongAHookStub;
|
|
|
|
static WindowsDllInterceptor::FuncHookType<User32SetWindowLongW> sUser32SetWindowLongWHookStub;
|
2010-10-22 01:52:48 +04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
extern LRESULT CALLBACK
|
|
|
|
NeuteredWindowProc(HWND hwnd,
|
|
|
|
UINT uMsg,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam);
|
|
|
|
|
|
|
|
const wchar_t kOldWndProcProp[] = L"MozillaIPCOldWndProc";
|
|
|
|
|
|
|
|
// static
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2010-10-22 01:52:48 +04:00
|
|
|
PluginInstanceChild::SetWindowLongHookCheck(HWND hWnd,
|
|
|
|
int nIndex,
|
|
|
|
LONG_PTR newLong)
|
|
|
|
{
|
|
|
|
// Let this go through if it's not a subclass
|
|
|
|
if (nIndex != GWLP_WNDPROC ||
|
|
|
|
// if it's not a subclassed plugin window
|
|
|
|
!GetProp(hWnd, kPluginInstanceChildProperty) ||
|
|
|
|
// if we're not disabled
|
|
|
|
GetProp(hWnd, kPluginIgnoreSubclassProperty) ||
|
|
|
|
// if the subclass is set to a known procedure
|
|
|
|
newLong == reinterpret_cast<LONG_PTR>(PluginWindowProc) ||
|
|
|
|
newLong == reinterpret_cast<LONG_PTR>(NeuteredWindowProc) ||
|
|
|
|
newLong == reinterpret_cast<LONG_PTR>(DefWindowProcA) ||
|
|
|
|
newLong == reinterpret_cast<LONG_PTR>(DefWindowProcW) ||
|
|
|
|
// if the subclass is a WindowsMessageLoop subclass restore
|
|
|
|
GetProp(hWnd, kOldWndProcProp))
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2010-10-22 01:52:48 +04:00
|
|
|
// prevent the subclass
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2010-10-22 01:52:48 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef _WIN64
|
|
|
|
LONG_PTR WINAPI
|
|
|
|
PluginInstanceChild::SetWindowLongPtrAHook(HWND hWnd,
|
|
|
|
int nIndex,
|
|
|
|
LONG_PTR newLong)
|
|
|
|
#else
|
|
|
|
LONG WINAPI
|
|
|
|
PluginInstanceChild::SetWindowLongAHook(HWND hWnd,
|
|
|
|
int nIndex,
|
|
|
|
LONG newLong)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
if (SetWindowLongHookCheck(hWnd, nIndex, newLong))
|
|
|
|
return sUser32SetWindowLongAHookStub(hWnd, nIndex, newLong);
|
|
|
|
|
2017-07-06 15:00:35 +03:00
|
|
|
// Set flash's new subclass to get the result.
|
2010-10-22 01:52:48 +04:00
|
|
|
LONG_PTR proc = sUser32SetWindowLongAHookStub(hWnd, nIndex, newLong);
|
|
|
|
|
|
|
|
// We already checked this in SetWindowLongHookCheck
|
|
|
|
PluginInstanceChild* self = reinterpret_cast<PluginInstanceChild*>(
|
|
|
|
GetProp(hWnd, kPluginInstanceChildProperty));
|
|
|
|
|
2017-07-06 15:00:35 +03:00
|
|
|
// Hook our subclass back up, just like we do on setwindow.
|
2011-02-04 22:51:27 +03:00
|
|
|
WNDPROC currentProc =
|
|
|
|
reinterpret_cast<WNDPROC>(GetWindowLongPtr(hWnd, GWLP_WNDPROC));
|
|
|
|
if (currentProc != PluginWindowProc) {
|
|
|
|
self->mPluginWndProc =
|
2011-02-10 01:49:15 +03:00
|
|
|
reinterpret_cast<WNDPROC>(sUser32SetWindowLongWHookStub(hWnd, nIndex,
|
2011-02-04 22:51:27 +03:00
|
|
|
reinterpret_cast<LONG_PTR>(PluginWindowProc)));
|
2011-02-10 01:49:15 +03:00
|
|
|
NS_ASSERTION(self->mPluginWndProc != PluginWindowProc, "Infinite recursion coming up!");
|
2011-02-04 22:51:27 +03:00
|
|
|
}
|
2010-10-22 01:52:48 +04:00
|
|
|
return proc;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef _WIN64
|
|
|
|
LONG_PTR WINAPI
|
|
|
|
PluginInstanceChild::SetWindowLongPtrWHook(HWND hWnd,
|
|
|
|
int nIndex,
|
|
|
|
LONG_PTR newLong)
|
|
|
|
#else
|
|
|
|
LONG WINAPI
|
|
|
|
PluginInstanceChild::SetWindowLongWHook(HWND hWnd,
|
|
|
|
int nIndex,
|
|
|
|
LONG newLong)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
if (SetWindowLongHookCheck(hWnd, nIndex, newLong))
|
|
|
|
return sUser32SetWindowLongWHookStub(hWnd, nIndex, newLong);
|
|
|
|
|
2017-07-06 15:00:35 +03:00
|
|
|
// Set flash's new subclass to get the result.
|
2010-10-22 01:52:48 +04:00
|
|
|
LONG_PTR proc = sUser32SetWindowLongWHookStub(hWnd, nIndex, newLong);
|
|
|
|
|
|
|
|
// We already checked this in SetWindowLongHookCheck
|
|
|
|
PluginInstanceChild* self = reinterpret_cast<PluginInstanceChild*>(
|
|
|
|
GetProp(hWnd, kPluginInstanceChildProperty));
|
|
|
|
|
2017-07-06 15:00:35 +03:00
|
|
|
// Hook our subclass back up, just like we do on setwindow.
|
2011-02-04 22:51:27 +03:00
|
|
|
WNDPROC currentProc =
|
|
|
|
reinterpret_cast<WNDPROC>(GetWindowLongPtr(hWnd, GWLP_WNDPROC));
|
|
|
|
if (currentProc != PluginWindowProc) {
|
|
|
|
self->mPluginWndProc =
|
2011-02-10 01:49:15 +03:00
|
|
|
reinterpret_cast<WNDPROC>(sUser32SetWindowLongWHookStub(hWnd, nIndex,
|
2011-02-04 22:51:27 +03:00
|
|
|
reinterpret_cast<LONG_PTR>(PluginWindowProc)));
|
2011-02-10 01:49:15 +03:00
|
|
|
NS_ASSERTION(self->mPluginWndProc != PluginWindowProc, "Infinite recursion coming up!");
|
2011-02-04 22:51:27 +03:00
|
|
|
}
|
2010-10-22 01:52:48 +04:00
|
|
|
return proc;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PluginInstanceChild::HookSetWindowLongPtr()
|
|
|
|
{
|
2018-05-16 21:29:43 +03:00
|
|
|
if (!(GetQuirks() & QUIRK_FLASH_HOOK_SETLONGPTR)) {
|
2010-10-22 01:52:48 +04:00
|
|
|
return;
|
2018-05-16 21:29:43 +03:00
|
|
|
}
|
|
|
|
|
2010-10-22 01:52:48 +04:00
|
|
|
sUser32Intercept.Init("user32.dll");
|
|
|
|
#ifdef _WIN64
|
2018-06-27 20:50:50 +03:00
|
|
|
sUser32SetWindowLongAHookStub.Set(sUser32Intercept, "SetWindowLongPtrA",
|
|
|
|
&SetWindowLongPtrAHook);
|
|
|
|
sUser32SetWindowLongWHookStub.Set(sUser32Intercept, "SetWindowLongPtrW",
|
|
|
|
&SetWindowLongPtrWHook);
|
2010-10-22 01:52:48 +04:00
|
|
|
#else
|
2018-06-27 20:50:50 +03:00
|
|
|
sUser32SetWindowLongAHookStub.Set(sUser32Intercept, "SetWindowLongA",
|
|
|
|
&SetWindowLongAHook);
|
|
|
|
sUser32SetWindowLongWHookStub.Set(sUser32Intercept, "SetWindowLongW",
|
|
|
|
&SetWindowLongWHook);
|
2010-10-22 01:52:48 +04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-12-24 20:44:11 +03:00
|
|
|
/* windowless track popup menu helpers */
|
2010-03-23 06:06:35 +03:00
|
|
|
|
|
|
|
BOOL
|
|
|
|
WINAPI
|
|
|
|
PluginInstanceChild::TrackPopupHookProc(HMENU hMenu,
|
|
|
|
UINT uFlags,
|
|
|
|
int x,
|
|
|
|
int y,
|
|
|
|
int nReserved,
|
|
|
|
HWND hWnd,
|
|
|
|
CONST RECT *prcRect)
|
|
|
|
{
|
|
|
|
if (!sUser32TrackPopupMenuStub) {
|
|
|
|
NS_ERROR("TrackPopupMenu stub isn't set! Badness!");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only change the parent when we know this is a context on the plugin
|
|
|
|
// surface within the browser. Prevents resetting the parent on child ui
|
|
|
|
// displayed by plugins that have working parent-child relationships.
|
2013-12-04 16:19:38 +04:00
|
|
|
wchar_t szClass[21];
|
2011-10-11 09:50:08 +04:00
|
|
|
bool haveClass = GetClassNameW(hWnd, szClass, ArrayLength(szClass));
|
2017-07-06 15:00:35 +03:00
|
|
|
if (!haveClass ||
|
2010-03-23 06:06:35 +03:00
|
|
|
(wcscmp(szClass, L"MozillaWindowClass") &&
|
|
|
|
wcscmp(szClass, L"SWFlash_Placeholder"))) {
|
|
|
|
// Unrecognized parent
|
|
|
|
return sUser32TrackPopupMenuStub(hMenu, uFlags, x, y, nReserved,
|
|
|
|
hWnd, prcRect);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Called on an unexpected event, warn.
|
|
|
|
if (!sWinlessPopupSurrogateHWND) {
|
|
|
|
NS_WARNING(
|
|
|
|
"Untraced TrackPopupHookProc call! Menu might not work right!");
|
|
|
|
return sUser32TrackPopupMenuStub(hMenu, uFlags, x, y, nReserved,
|
|
|
|
hWnd, prcRect);
|
|
|
|
}
|
|
|
|
|
|
|
|
HWND surrogateHwnd = sWinlessPopupSurrogateHWND;
|
2013-10-24 00:34:46 +04:00
|
|
|
sWinlessPopupSurrogateHWND = nullptr;
|
2010-03-23 06:06:35 +03:00
|
|
|
|
|
|
|
// Popups that don't use TPM_RETURNCMD expect a final command message
|
|
|
|
// when an item is selected and the context closes. Since we replace
|
|
|
|
// the parent, we need to forward this back to the real parent so it
|
|
|
|
// can act on the menu item selected.
|
|
|
|
bool isRetCmdCall = (uFlags & TPM_RETURNCMD);
|
|
|
|
|
|
|
|
DWORD res = sUser32TrackPopupMenuStub(hMenu, uFlags|TPM_RETURNCMD, x, y,
|
|
|
|
nReserved, surrogateHwnd, prcRect);
|
|
|
|
|
|
|
|
if (!isRetCmdCall && res) {
|
|
|
|
SendMessage(hWnd, WM_COMMAND, MAKEWPARAM(res, 0), 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PluginInstanceChild::InitPopupMenuHook()
|
|
|
|
{
|
2018-05-16 21:23:43 +03:00
|
|
|
if (!(GetQuirks() & QUIRK_WINLESS_TRACKPOPUP_HOOK)) {
|
2010-03-23 06:06:35 +03:00
|
|
|
return;
|
2018-05-16 21:23:43 +03:00
|
|
|
}
|
|
|
|
|
2010-03-23 06:06:35 +03:00
|
|
|
// Note, once WindowsDllInterceptor is initialized for a module,
|
|
|
|
// it remains initialized for that particular module for it's
|
|
|
|
// lifetime. Additional instances are needed if other modules need
|
|
|
|
// to be hooked.
|
2018-05-16 21:23:43 +03:00
|
|
|
sUser32Intercept.Init("user32.dll");
|
2018-06-27 20:50:50 +03:00
|
|
|
sUser32TrackPopupMenuStub.Set(sUser32Intercept, "TrackPopupMenu",
|
|
|
|
&TrackPopupHookProc);
|
2010-03-23 06:06:35 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PluginInstanceChild::CreateWinlessPopupSurrogate()
|
|
|
|
{
|
|
|
|
// already initialized
|
|
|
|
if (mWinlessPopupSurrogateHWND)
|
|
|
|
return;
|
|
|
|
|
|
|
|
mWinlessPopupSurrogateHWND =
|
2015-08-12 18:00:26 +03:00
|
|
|
CreateWindowEx(WS_EX_NOPARENTNOTIFY, L"Static", nullptr, WS_POPUP,
|
|
|
|
0, 0, 0, 0, nullptr, 0, GetModuleHandle(nullptr), 0);
|
2010-03-23 06:06:35 +03:00
|
|
|
if (!mWinlessPopupSurrogateHWND) {
|
|
|
|
NS_ERROR("CreateWindowEx failed for winless placeholder!");
|
|
|
|
return;
|
|
|
|
}
|
2015-08-12 18:00:26 +03:00
|
|
|
|
|
|
|
SendSetNetscapeWindowAsParent(mWinlessPopupSurrogateHWND);
|
2010-03-23 06:06:35 +03:00
|
|
|
}
|
|
|
|
|
2015-12-29 16:57:38 +03:00
|
|
|
// static
|
|
|
|
HIMC
|
|
|
|
PluginInstanceChild::ImmGetContextProc(HWND aWND)
|
|
|
|
{
|
|
|
|
if (!sCurrentPluginInstance) {
|
|
|
|
return sImm32ImmGetContextStub(aWND);
|
|
|
|
}
|
|
|
|
|
|
|
|
wchar_t szClass[21];
|
|
|
|
int haveClass = GetClassNameW(aWND, szClass, ArrayLength(szClass));
|
|
|
|
if (!haveClass || wcscmp(szClass, L"SWFlash_PlaceholderX")) {
|
|
|
|
NS_WARNING("We cannot recongnize hooked window class");
|
|
|
|
return sImm32ImmGetContextStub(aWND);
|
|
|
|
}
|
|
|
|
|
|
|
|
return sHookIMC;
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
LONG
|
|
|
|
PluginInstanceChild::ImmGetCompositionStringProc(HIMC aIMC, DWORD aIndex,
|
|
|
|
LPVOID aBuf, DWORD aLen)
|
|
|
|
{
|
|
|
|
if (aIMC != sHookIMC) {
|
|
|
|
return sImm32ImmGetCompositionStringStub(aIMC, aIndex, aBuf, aLen);
|
|
|
|
}
|
|
|
|
if (!sCurrentPluginInstance) {
|
|
|
|
return IMM_ERROR_GENERAL;
|
|
|
|
}
|
2016-02-02 18:36:30 +03:00
|
|
|
AutoTArray<uint8_t, 16> dist;
|
2015-12-29 16:57:38 +03:00
|
|
|
int32_t length = 0; // IMM_ERROR_NODATA
|
|
|
|
sCurrentPluginInstance->SendGetCompositionString(aIndex, &dist, &length);
|
|
|
|
if (length == IMM_ERROR_NODATA || length == IMM_ERROR_GENERAL) {
|
|
|
|
return length;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aBuf && aLen >= static_cast<DWORD>(length)) {
|
|
|
|
memcpy(aBuf, dist.Elements(), length);
|
|
|
|
}
|
|
|
|
return length;
|
|
|
|
}
|
|
|
|
|
|
|
|
// staitc
|
|
|
|
BOOL
|
|
|
|
PluginInstanceChild::ImmSetCandidateWindowProc(HIMC aIMC, LPCANDIDATEFORM aForm)
|
|
|
|
{
|
|
|
|
if (aIMC != sHookIMC) {
|
|
|
|
return sImm32ImmSetCandidateWindowStub(aIMC, aForm);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!sCurrentPluginInstance ||
|
2016-02-02 11:05:56 +03:00
|
|
|
aForm->dwIndex != 0) {
|
2015-12-29 16:57:38 +03:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2016-02-02 11:05:56 +03:00
|
|
|
CandidateWindowPosition position;
|
|
|
|
position.mPoint.x = aForm->ptCurrentPos.x;
|
|
|
|
position.mPoint.y = aForm->ptCurrentPos.y;
|
|
|
|
position.mExcludeRect = !!(aForm->dwStyle & CFS_EXCLUDE);
|
|
|
|
if (position.mExcludeRect) {
|
2018-02-19 23:15:23 +03:00
|
|
|
position.mRect.x = aForm->rcArea.left;
|
|
|
|
position.mRect.y = aForm->rcArea.top;
|
|
|
|
position.mRect.width = aForm->rcArea.right - aForm->rcArea.left;
|
|
|
|
position.mRect.height = aForm->rcArea.bottom - aForm->rcArea.top;
|
2016-02-02 11:05:56 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
sCurrentPluginInstance->SendSetCandidateWindow(position);
|
2015-12-29 16:57:38 +03:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
BOOL
|
|
|
|
PluginInstanceChild::ImmNotifyIME(HIMC aIMC, DWORD aAction, DWORD aIndex,
|
|
|
|
DWORD aValue)
|
|
|
|
{
|
|
|
|
if (aIMC != sHookIMC) {
|
|
|
|
return sImm32ImmNotifyIME(aIMC, aAction, aIndex, aValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
// We only supports NI_COMPOSITIONSTR because Flash uses it only
|
|
|
|
if (!sCurrentPluginInstance ||
|
|
|
|
aAction != NI_COMPOSITIONSTR ||
|
|
|
|
(aIndex != CPS_COMPLETE && aIndex != CPS_CANCEL)) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
sCurrentPluginInstance->SendRequestCommitOrCancel(aAction == CPS_COMPLETE);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2018-05-17 08:47:55 +03:00
|
|
|
// static
|
|
|
|
BOOL
|
|
|
|
PluginInstanceChild::ImmAssociateContextExProc(HWND hWND, HIMC hImc,
|
|
|
|
DWORD dwFlags)
|
|
|
|
{
|
|
|
|
PluginInstanceChild* self = sCurrentPluginInstance;
|
|
|
|
if (!self) {
|
|
|
|
// If ImmAssociateContextEx calls unexpected window message,
|
|
|
|
// we can use child instance object from window property if available.
|
|
|
|
self = reinterpret_cast<PluginInstanceChild*>(
|
|
|
|
GetProp(hWND, kFlashThrottleProperty));
|
|
|
|
NS_WARNING_ASSERTION(self, "Cannot find PluginInstanceChild");
|
|
|
|
}
|
|
|
|
|
|
|
|
// HIMC is always nullptr on Flash's windowless
|
|
|
|
if (!hImc && self) {
|
|
|
|
// Store the last IME state since Flash may call ImmAssociateContextEx
|
|
|
|
// before taking focus.
|
|
|
|
self->mLastEnableIMEState = !!(dwFlags & IACE_DEFAULT);
|
|
|
|
self->SendEnableIME(self->mLastEnableIMEState);
|
|
|
|
}
|
|
|
|
return sImm32ImmAssociateContextExStub(hWND, hImc, dwFlags);
|
|
|
|
}
|
|
|
|
|
2015-12-29 16:57:38 +03:00
|
|
|
void
|
|
|
|
PluginInstanceChild::InitImm32Hook()
|
|
|
|
{
|
|
|
|
if (!(GetQuirks() & QUIRK_WINLESS_HOOK_IME)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// When using windowless plugin, IMM API won't work due ot OOP.
|
2018-03-07 05:01:30 +03:00
|
|
|
//
|
|
|
|
// ImmReleaseContext on Windows 7+ just returns TRUE only, so we don't
|
|
|
|
// need to hook this.
|
2015-12-29 16:57:38 +03:00
|
|
|
|
|
|
|
sImm32Intercept.Init("imm32.dll");
|
2018-06-27 20:50:50 +03:00
|
|
|
sImm32ImmGetContextStub.Set(sImm32Intercept, "ImmGetContext",
|
|
|
|
&ImmGetContextProc);
|
|
|
|
sImm32ImmGetCompositionStringStub.Set(sImm32Intercept,
|
|
|
|
"ImmGetCompositionStringW",
|
|
|
|
&ImmGetCompositionStringProc);
|
|
|
|
sImm32ImmSetCandidateWindowStub.Set(sImm32Intercept,
|
|
|
|
"ImmSetCandidateWindow",
|
|
|
|
&ImmSetCandidateWindowProc);
|
|
|
|
sImm32ImmNotifyIME.Set(sImm32Intercept, "ImmNotifyIME", &ImmNotifyIME);
|
|
|
|
sImm32ImmAssociateContextExStub.Set(sImm32Intercept, "ImmAssociateContextEx",
|
|
|
|
&ImmAssociateContextExProc);
|
2015-12-29 16:57:38 +03:00
|
|
|
}
|
|
|
|
|
2010-03-23 06:06:35 +03:00
|
|
|
void
|
|
|
|
PluginInstanceChild::DestroyWinlessPopupSurrogate()
|
|
|
|
{
|
|
|
|
if (mWinlessPopupSurrogateHWND)
|
|
|
|
DestroyWindow(mWinlessPopupSurrogateHWND);
|
2013-10-24 00:34:46 +04:00
|
|
|
mWinlessPopupSurrogateHWND = nullptr;
|
2010-03-23 06:06:35 +03:00
|
|
|
}
|
|
|
|
|
2010-02-10 01:34:38 +03:00
|
|
|
int16_t
|
|
|
|
PluginInstanceChild::WinlessHandleEvent(NPEvent& event)
|
|
|
|
{
|
2010-03-10 18:54:22 +03:00
|
|
|
if (!mPluginIface->event)
|
|
|
|
return false;
|
|
|
|
|
2010-02-25 03:13:48 +03:00
|
|
|
// Events that might generate nested event dispatch loops need
|
|
|
|
// special handling during delivery.
|
|
|
|
int16_t handled;
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2013-10-24 00:34:46 +04:00
|
|
|
HWND focusHwnd = nullptr;
|
2010-02-10 01:34:38 +03:00
|
|
|
|
2010-03-23 06:06:35 +03:00
|
|
|
// TrackPopupMenu will fail if the parent window is not associated with
|
|
|
|
// our ui thread. So we hook TrackPopupMenu so we can hand in a surrogate
|
|
|
|
// parent created in the child process.
|
2015-08-12 18:00:25 +03:00
|
|
|
if ((GetQuirks() & QUIRK_WINLESS_TRACKPOPUP_HOOK) && // XXX turn on by default?
|
2010-03-23 06:06:35 +03:00
|
|
|
(event.event == WM_RBUTTONDOWN || // flash
|
|
|
|
event.event == WM_RBUTTONUP)) { // silverlight
|
|
|
|
sWinlessPopupSurrogateHWND = mWinlessPopupSurrogateHWND;
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2011-07-27 16:17:50 +04:00
|
|
|
// A little trick scrounged from chromium's code - set the focus
|
2017-07-06 15:00:35 +03:00
|
|
|
// to our surrogate parent so keyboard nav events go to the menu.
|
2011-07-27 16:17:50 +04:00
|
|
|
focusHwnd = SetFocus(mWinlessPopupSurrogateHWND);
|
2010-03-23 06:06:35 +03:00
|
|
|
}
|
|
|
|
|
2015-12-29 16:57:38 +03:00
|
|
|
AutoRestore<PluginInstanceChild *> pluginInstance(sCurrentPluginInstance);
|
|
|
|
if (event.event == WM_IME_STARTCOMPOSITION ||
|
|
|
|
event.event == WM_IME_COMPOSITION ||
|
2018-05-17 08:47:55 +03:00
|
|
|
event.event == WM_LBUTTONDOWN ||
|
2015-12-29 16:57:38 +03:00
|
|
|
event.event == WM_KILLFOCUS) {
|
|
|
|
sCurrentPluginInstance = this;
|
|
|
|
}
|
|
|
|
|
2011-07-27 16:17:50 +04:00
|
|
|
MessageLoop* loop = MessageLoop::current();
|
|
|
|
AutoRestore<bool> modalLoop(loop->os_modal_loop());
|
|
|
|
|
2010-02-25 03:13:48 +03:00
|
|
|
handled = mPluginIface->event(&mData, reinterpret_cast<void*>(&event));
|
2010-02-10 01:34:38 +03:00
|
|
|
|
2013-10-24 00:34:46 +04:00
|
|
|
sWinlessPopupSurrogateHWND = nullptr;
|
2010-02-10 01:34:38 +03:00
|
|
|
|
2011-07-27 16:17:50 +04:00
|
|
|
if (IsWindow(focusHwnd)) {
|
|
|
|
SetFocus(focusHwnd);
|
|
|
|
}
|
|
|
|
|
2018-05-17 08:47:55 +03:00
|
|
|
// This is hack of Flash's behaviour.
|
|
|
|
//
|
|
|
|
// When moving focus from chrome to plugin by mouse click, Gecko sends
|
|
|
|
// mouse message (such as WM_LBUTTONDOWN etc) at first, then sends
|
|
|
|
// WM_SETFOCUS. But Flash will call ImmAssociateContextEx on WM_LBUTTONDOWN
|
|
|
|
// even if it doesn't receive WM_SETFOCUS.
|
|
|
|
//
|
|
|
|
// In this situation, after sending mouse message, content process will be
|
|
|
|
// activated and set input context with PLUGIN. So after activating
|
|
|
|
// content process, we have to set current IME state again.
|
|
|
|
|
|
|
|
if (event.event == WM_SETFOCUS) {
|
|
|
|
// When focus is changed from chrome process to plugin process,
|
|
|
|
// Flash may call ImmAssociateContextEx before receiving WM_SETFOCUS.
|
|
|
|
SendEnableIME(mLastEnableIMEState);
|
|
|
|
} else if (event.event == WM_KILLFOCUS) {
|
|
|
|
// Flash always calls ImmAssociateContextEx by taking focus.
|
|
|
|
// Although this flag doesn't have to be reset, I add it for safety.
|
|
|
|
mLastEnableIMEState = true;
|
|
|
|
}
|
|
|
|
|
2010-02-25 03:13:48 +03:00
|
|
|
return handled;
|
2010-02-10 01:34:38 +03:00
|
|
|
}
|
|
|
|
|
2010-04-26 20:29:11 +04:00
|
|
|
/* flash msg throttling helpers */
|
|
|
|
|
|
|
|
// Flash has the unfortunate habit of flooding dispatch loops with custom
|
|
|
|
// windowing events they use for timing. We throttle these by dropping the
|
|
|
|
// delivery priority below any other event, including pending ipc io
|
|
|
|
// notifications. We do this for both windowed and windowless controls.
|
2010-05-06 20:40:26 +04:00
|
|
|
// Note flash's windowless msg window can last longer than our instance,
|
|
|
|
// so we try to unhook when the window is destroyed and in NPP_Destroy.
|
|
|
|
|
|
|
|
void
|
|
|
|
PluginInstanceChild::UnhookWinlessFlashThrottle()
|
|
|
|
{
|
|
|
|
// We may have already unhooked
|
|
|
|
if (!mWinlessThrottleOldWndProc)
|
|
|
|
return;
|
|
|
|
|
|
|
|
WNDPROC tmpProc = mWinlessThrottleOldWndProc;
|
2012-07-30 18:20:58 +04:00
|
|
|
mWinlessThrottleOldWndProc = nullptr;
|
2010-05-06 20:40:26 +04:00
|
|
|
|
|
|
|
NS_ASSERTION(mWinlessHiddenMsgHWND,
|
|
|
|
"Missing mWinlessHiddenMsgHWND w/subclass set??");
|
|
|
|
|
|
|
|
// reset the subclass
|
|
|
|
SetWindowLongPtr(mWinlessHiddenMsgHWND, GWLP_WNDPROC,
|
2010-07-12 08:49:12 +04:00
|
|
|
reinterpret_cast<LONG_PTR>(tmpProc));
|
2010-05-06 20:40:26 +04:00
|
|
|
|
|
|
|
// Remove our instance prop
|
2010-10-22 01:52:48 +04:00
|
|
|
RemoveProp(mWinlessHiddenMsgHWND, kFlashThrottleProperty);
|
2012-07-30 18:20:58 +04:00
|
|
|
mWinlessHiddenMsgHWND = nullptr;
|
2010-05-06 20:40:26 +04:00
|
|
|
}
|
2010-04-26 20:29:11 +04:00
|
|
|
|
|
|
|
// static
|
|
|
|
LRESULT CALLBACK
|
|
|
|
PluginInstanceChild::WinlessHiddenFlashWndProc(HWND hWnd,
|
|
|
|
UINT message,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam)
|
|
|
|
{
|
|
|
|
PluginInstanceChild* self = reinterpret_cast<PluginInstanceChild*>(
|
2010-10-22 01:52:48 +04:00
|
|
|
GetProp(hWnd, kFlashThrottleProperty));
|
2010-04-26 20:29:11 +04:00
|
|
|
if (!self) {
|
2018-06-18 08:43:11 +03:00
|
|
|
MOZ_ASSERT_UNREACHABLE("Badness!");
|
2010-04-26 20:29:11 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_ASSERTION(self->mWinlessThrottleOldWndProc,
|
|
|
|
"Missing subclass procedure!!");
|
|
|
|
|
|
|
|
// Throttle
|
|
|
|
if (message == WM_USER+1) {
|
|
|
|
self->FlashThrottleMessage(hWnd, message, wParam, lParam, false);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Unhook
|
2010-05-06 20:40:26 +04:00
|
|
|
if (message == WM_CLOSE || message == WM_NCDESTROY) {
|
2010-04-26 20:29:11 +04:00
|
|
|
WNDPROC tmpProc = self->mWinlessThrottleOldWndProc;
|
2010-05-06 20:40:26 +04:00
|
|
|
self->UnhookWinlessFlashThrottle();
|
2010-04-26 20:29:11 +04:00
|
|
|
LRESULT res = CallWindowProc(tmpProc, hWnd, message, wParam, lParam);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
return CallWindowProc(self->mWinlessThrottleOldWndProc,
|
|
|
|
hWnd, message, wParam, lParam);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Enumerate all thread windows looking for flash's hidden message window.
|
2017-07-06 15:00:35 +03:00
|
|
|
// Once we find it, sub class it so we can throttle user msgs.
|
2010-04-26 20:29:11 +04:00
|
|
|
// static
|
|
|
|
BOOL CALLBACK
|
|
|
|
PluginInstanceChild::EnumThreadWindowsCallback(HWND hWnd,
|
|
|
|
LPARAM aParam)
|
|
|
|
{
|
|
|
|
PluginInstanceChild* self = reinterpret_cast<PluginInstanceChild*>(aParam);
|
|
|
|
if (!self) {
|
2018-06-18 08:43:11 +03:00
|
|
|
MOZ_ASSERT_UNREACHABLE("Enum befuddled!");
|
2010-04-26 20:29:11 +04:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2013-12-04 16:19:38 +04:00
|
|
|
wchar_t className[64];
|
2014-01-04 19:02:17 +04:00
|
|
|
if (!GetClassNameW(hWnd, className, sizeof(className)/sizeof(char16_t)))
|
2010-04-26 20:29:11 +04:00
|
|
|
return TRUE;
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2010-04-26 20:29:11 +04:00
|
|
|
if (!wcscmp(className, L"SWFlash_PlaceholderX")) {
|
|
|
|
WNDPROC oldWndProc =
|
|
|
|
reinterpret_cast<WNDPROC>(GetWindowLongPtr(hWnd, GWLP_WNDPROC));
|
|
|
|
// Only set this if we haven't already.
|
|
|
|
if (oldWndProc != WinlessHiddenFlashWndProc) {
|
|
|
|
if (self->mWinlessThrottleOldWndProc) {
|
|
|
|
NS_WARNING("mWinlessThrottleWndProc already set???");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
// Subsclass and store self as a property
|
2010-05-06 20:40:26 +04:00
|
|
|
self->mWinlessHiddenMsgHWND = hWnd;
|
2010-04-26 20:29:11 +04:00
|
|
|
self->mWinlessThrottleOldWndProc =
|
|
|
|
reinterpret_cast<WNDPROC>(SetWindowLongPtr(hWnd, GWLP_WNDPROC,
|
2010-07-12 08:49:12 +04:00
|
|
|
reinterpret_cast<LONG_PTR>(WinlessHiddenFlashWndProc)));
|
2010-10-22 01:52:48 +04:00
|
|
|
SetProp(hWnd, kFlashThrottleProperty, self);
|
2010-04-26 20:29:11 +04:00
|
|
|
NS_ASSERTION(self->mWinlessThrottleOldWndProc,
|
|
|
|
"SetWindowLongPtr failed?!");
|
|
|
|
}
|
|
|
|
// Return no matter what once we find the right window.
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PluginInstanceChild::SetupFlashMsgThrottle()
|
|
|
|
{
|
|
|
|
if (mWindow.type == NPWindowTypeDrawable) {
|
|
|
|
// Search for the flash hidden message window and subclass it. Only
|
|
|
|
// search for flash windows belonging to our ui thread!
|
|
|
|
if (mWinlessThrottleOldWndProc)
|
|
|
|
return;
|
|
|
|
EnumThreadWindows(GetCurrentThreadId(), EnumThreadWindowsCallback,
|
|
|
|
reinterpret_cast<LPARAM>(this));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Already setup through quirks and the subclass.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
WNDPROC
|
2017-07-19 10:22:05 +03:00
|
|
|
PluginInstanceChild::FlashThrottleMsg::GetProc()
|
2017-07-06 15:00:35 +03:00
|
|
|
{
|
2010-04-26 20:29:11 +04:00
|
|
|
if (mInstance) {
|
|
|
|
return mWindowed ? mInstance->mPluginWndProc :
|
|
|
|
mInstance->mWinlessThrottleOldWndProc;
|
|
|
|
}
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2010-04-26 20:29:11 +04:00
|
|
|
}
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2016-04-28 03:06:05 +03:00
|
|
|
NS_IMETHODIMP
|
2017-07-19 10:22:05 +03:00
|
|
|
PluginInstanceChild::FlashThrottleMsg::Run()
|
2010-04-26 20:29:11 +04:00
|
|
|
{
|
2017-07-19 10:22:05 +03:00
|
|
|
if (!mInstance) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
mInstance->mPendingFlashThrottleMsgs.RemoveElement(this);
|
2010-04-26 20:29:11 +04:00
|
|
|
|
|
|
|
// GetProc() checks mInstance, and pulls the procedure from
|
|
|
|
// PluginInstanceChild. We don't transport sub-class procedure
|
2017-07-19 10:22:05 +03:00
|
|
|
// ptrs around in FlashThrottleMsg msgs.
|
2010-04-26 20:29:11 +04:00
|
|
|
if (!GetProc())
|
2016-04-28 03:06:05 +03:00
|
|
|
return NS_OK;
|
2017-07-06 15:00:35 +03:00
|
|
|
|
|
|
|
// deliver the event to flash
|
2010-04-26 20:29:11 +04:00
|
|
|
CallWindowProc(GetProc(), GetWnd(), GetMsg(), GetWParam(), GetLParam());
|
2016-04-28 03:06:05 +03:00
|
|
|
return NS_OK;
|
2010-04-26 20:29:11 +04:00
|
|
|
}
|
|
|
|
|
2017-07-19 10:22:05 +03:00
|
|
|
nsresult
|
|
|
|
PluginInstanceChild::FlashThrottleMsg::Cancel()
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mInstance);
|
|
|
|
mInstance = nullptr;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-04-26 20:29:11 +04:00
|
|
|
void
|
|
|
|
PluginInstanceChild::FlashThrottleMessage(HWND aWnd,
|
|
|
|
UINT aMsg,
|
|
|
|
WPARAM aWParam,
|
|
|
|
LPARAM aLParam,
|
|
|
|
bool isWindowed)
|
|
|
|
{
|
2017-07-19 10:22:05 +03:00
|
|
|
// We save a reference to the FlashThrottleMsg so we can cancel it in
|
|
|
|
// Destroy if it's still alive.
|
|
|
|
RefPtr<FlashThrottleMsg> task =
|
|
|
|
new FlashThrottleMsg(this, aWnd, aMsg, aWParam, aLParam, isWindowed);
|
|
|
|
|
|
|
|
mPendingFlashThrottleMsgs.AppendElement(task);
|
|
|
|
|
2016-04-28 03:06:05 +03:00
|
|
|
MessageLoop::current()->PostDelayedTask(task.forget(),
|
|
|
|
kFlashWMUSERMessageThrottleDelayMs);
|
2010-04-26 20:29:11 +04:00
|
|
|
}
|
|
|
|
|
2009-07-02 01:19:32 +04:00
|
|
|
#endif // OS_WIN
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2010-01-27 00:40:15 +03:00
|
|
|
PluginInstanceChild::AnswerSetPluginFocus()
|
|
|
|
{
|
2015-06-04 01:25:57 +03:00
|
|
|
MOZ_LOG(GetPluginLog(), LogLevel::Debug, ("%s", FULLFUNCTION));
|
2010-01-27 00:40:15 +03:00
|
|
|
|
|
|
|
#if defined(OS_WIN)
|
2011-05-13 21:06:51 +04:00
|
|
|
// Parent is letting us know the dom set focus to the plugin. Note,
|
|
|
|
// focus can change during transit in certain edge cases, for example
|
|
|
|
// when a button click brings up a full screen window. Since we send
|
|
|
|
// this in response to a WM_SETFOCUS event on our parent, the parent
|
|
|
|
// should have focus when we receive this. If not, ignore the call.
|
2016-11-29 09:51:45 +03:00
|
|
|
if (::GetFocus() == mPluginWindowHWND)
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2010-01-27 00:40:15 +03:00
|
|
|
::SetFocus(mPluginWindowHWND);
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2010-01-27 00:40:15 +03:00
|
|
|
#else
|
2018-06-18 08:43:11 +03:00
|
|
|
MOZ_ASSERT_UNREACHABLE("AnswerSetPluginFocus not implemented!");
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_FAIL_NO_REASON(this);
|
2010-01-27 00:40:15 +03:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2010-01-27 03:08:39 +03:00
|
|
|
PluginInstanceChild::AnswerUpdateWindow()
|
|
|
|
{
|
2015-06-04 01:25:57 +03:00
|
|
|
MOZ_LOG(GetPluginLog(), LogLevel::Debug, ("%s", FULLFUNCTION));
|
2010-01-27 03:08:39 +03:00
|
|
|
|
|
|
|
#if defined(OS_WIN)
|
2010-04-05 20:43:13 +04:00
|
|
|
if (mPluginWindowHWND) {
|
|
|
|
RECT rect;
|
|
|
|
if (GetUpdateRect(GetParent(mPluginWindowHWND), &rect, FALSE)) {
|
2017-07-06 15:00:35 +03:00
|
|
|
::InvalidateRect(mPluginWindowHWND, &rect, FALSE);
|
2010-04-05 20:43:13 +04:00
|
|
|
}
|
|
|
|
UpdateWindow(mPluginWindowHWND);
|
|
|
|
}
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2010-01-27 03:08:39 +03:00
|
|
|
#else
|
2018-06-18 08:43:11 +03:00
|
|
|
MOZ_ASSERT_UNREACHABLE("AnswerUpdateWindow not implemented!");
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_FAIL_NO_REASON(this);
|
2010-01-27 03:08:39 +03:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2012-02-16 07:30:25 +04:00
|
|
|
PluginInstanceChild::RecvNPP_DidComposite()
|
|
|
|
{
|
|
|
|
if (mPluginIface->didComposite) {
|
|
|
|
mPluginIface->didComposite(GetNPP());
|
|
|
|
}
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2012-02-16 07:30:25 +04:00
|
|
|
}
|
|
|
|
|
2009-09-10 02:59:06 +04:00
|
|
|
PPluginScriptableObjectChild*
|
2013-07-08 19:48:39 +04:00
|
|
|
PluginInstanceChild::AllocPPluginScriptableObjectChild()
|
2009-08-11 03:28:22 +04:00
|
|
|
{
|
2009-10-08 23:11:13 +04:00
|
|
|
AssertPluginThread();
|
2010-01-15 23:35:57 +03:00
|
|
|
return new PluginScriptableObjectChild(Proxy);
|
2009-08-11 03:28:22 +04:00
|
|
|
}
|
|
|
|
|
2009-09-18 03:09:20 +04:00
|
|
|
bool
|
2013-07-08 19:48:39 +04:00
|
|
|
PluginInstanceChild::DeallocPPluginScriptableObjectChild(
|
2009-12-03 11:16:14 +03:00
|
|
|
PPluginScriptableObjectChild* aObject)
|
2009-08-11 03:28:22 +04:00
|
|
|
{
|
2009-10-08 23:11:13 +04:00
|
|
|
AssertPluginThread();
|
2010-01-22 18:06:13 +03:00
|
|
|
delete aObject;
|
2010-01-15 23:35:57 +03:00
|
|
|
return true;
|
2009-08-11 03:28:22 +04:00
|
|
|
}
|
2009-08-19 00:20:03 +04:00
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2010-03-05 00:20:14 +03:00
|
|
|
PluginInstanceChild::RecvPPluginScriptableObjectConstructor(
|
2009-10-08 03:50:48 +04:00
|
|
|
PPluginScriptableObjectChild* aActor)
|
|
|
|
{
|
2009-10-08 23:11:13 +04:00
|
|
|
AssertPluginThread();
|
|
|
|
|
2009-10-08 03:50:48 +04:00
|
|
|
// This is only called in response to the parent process requesting the
|
|
|
|
// creation of an actor. This actor will represent an NPObject that is
|
|
|
|
// created by the browser and returned to the plugin.
|
|
|
|
PluginScriptableObjectChild* actor =
|
|
|
|
static_cast<PluginScriptableObjectChild*>(aActor);
|
2010-01-15 23:35:57 +03:00
|
|
|
NS_ASSERTION(!actor->GetObject(false), "Actor already has an object?!");
|
|
|
|
|
|
|
|
actor->InitializeProxy();
|
|
|
|
NS_ASSERTION(actor->GetObject(false), "Actor should have an object!");
|
2009-10-08 03:50:48 +04:00
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2009-10-08 03:50:48 +04:00
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2014-12-30 02:13:09 +03:00
|
|
|
PluginInstanceChild::RecvPBrowserStreamConstructor(
|
2010-01-13 02:06:18 +03:00
|
|
|
PBrowserStreamChild* aActor,
|
|
|
|
const nsCString& url,
|
|
|
|
const uint32_t& length,
|
|
|
|
const uint32_t& lastmodified,
|
|
|
|
PStreamNotifyChild* notifyData,
|
2014-12-30 02:13:09 +03:00
|
|
|
const nsCString& headers)
|
|
|
|
{
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2014-12-30 02:13:09 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
NPError
|
|
|
|
PluginInstanceChild::DoNPP_NewStream(BrowserStreamChild* actor,
|
|
|
|
const nsCString& mimeType,
|
|
|
|
const bool& seekable,
|
|
|
|
uint16_t* stype)
|
2010-01-13 02:06:18 +03:00
|
|
|
{
|
|
|
|
AssertPluginThread();
|
2016-04-06 23:23:43 +03:00
|
|
|
AutoStackHelper guard(this);
|
2014-12-30 02:13:09 +03:00
|
|
|
NPError rv = actor->StreamConstructed(mimeType, seekable, stype);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2014-12-30 02:13:09 +03:00
|
|
|
PluginInstanceChild::AnswerNPP_NewStream(PBrowserStreamChild* actor,
|
|
|
|
const nsCString& mimeType,
|
|
|
|
const bool& seekable,
|
|
|
|
NPError* rv,
|
|
|
|
uint16_t* stype)
|
|
|
|
{
|
|
|
|
*rv = DoNPP_NewStream(static_cast<BrowserStreamChild*>(actor), mimeType,
|
|
|
|
seekable, stype);
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2014-12-30 02:13:09 +03:00
|
|
|
}
|
|
|
|
|
2009-09-10 02:59:06 +04:00
|
|
|
PBrowserStreamChild*
|
2013-07-08 19:48:39 +04:00
|
|
|
PluginInstanceChild::AllocPBrowserStreamChild(const nsCString& url,
|
|
|
|
const uint32_t& length,
|
|
|
|
const uint32_t& lastmodified,
|
|
|
|
PStreamNotifyChild* notifyData,
|
2014-12-30 02:13:09 +03:00
|
|
|
const nsCString& headers)
|
2009-08-19 00:20:03 +04:00
|
|
|
{
|
2009-10-08 23:11:13 +04:00
|
|
|
AssertPluginThread();
|
2010-03-07 00:03:05 +03:00
|
|
|
return new BrowserStreamChild(this, url, length, lastmodified,
|
|
|
|
static_cast<StreamNotifyChild*>(notifyData),
|
2014-12-30 02:13:09 +03:00
|
|
|
headers);
|
2009-08-19 00:20:03 +04:00
|
|
|
}
|
|
|
|
|
2009-09-21 18:51:35 +04:00
|
|
|
bool
|
2013-07-08 19:48:39 +04:00
|
|
|
PluginInstanceChild::DeallocPBrowserStreamChild(PBrowserStreamChild* stream)
|
2009-08-19 00:20:03 +04:00
|
|
|
{
|
2009-10-08 23:11:13 +04:00
|
|
|
AssertPluginThread();
|
2009-08-19 00:20:03 +04:00
|
|
|
delete stream;
|
2009-09-18 03:09:20 +04:00
|
|
|
return true;
|
2009-08-19 00:20:03 +04:00
|
|
|
}
|
|
|
|
|
2009-09-21 18:51:35 +04:00
|
|
|
|
2009-09-09 01:22:50 +04:00
|
|
|
PStreamNotifyChild*
|
2013-07-08 19:48:39 +04:00
|
|
|
PluginInstanceChild::AllocPStreamNotifyChild(const nsCString& url,
|
|
|
|
const nsCString& target,
|
|
|
|
const bool& post,
|
|
|
|
const nsCString& buffer,
|
|
|
|
const bool& file,
|
|
|
|
NPError* result)
|
2009-09-09 01:22:50 +04:00
|
|
|
{
|
2009-10-08 23:11:13 +04:00
|
|
|
AssertPluginThread();
|
2016-12-03 00:46:53 +03:00
|
|
|
MOZ_CRASH("not reached");
|
2013-10-24 00:34:46 +04:00
|
|
|
return nullptr;
|
2009-09-09 01:22:50 +04:00
|
|
|
}
|
|
|
|
|
2010-03-07 00:03:05 +03:00
|
|
|
void
|
|
|
|
StreamNotifyChild::ActorDestroy(ActorDestroyReason why)
|
2009-09-09 01:22:50 +04:00
|
|
|
{
|
2010-03-07 00:03:05 +03:00
|
|
|
if (AncestorDeletion == why && mBrowserStream) {
|
|
|
|
NS_ERROR("Pending NPP_URLNotify not called when closing an instance.");
|
|
|
|
|
|
|
|
// reclaim responsibility for deleting ourself
|
2013-10-24 00:34:46 +04:00
|
|
|
mBrowserStream->mStreamNotify = nullptr;
|
|
|
|
mBrowserStream = nullptr;
|
2010-03-07 00:03:05 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
StreamNotifyChild::SetAssociatedStream(BrowserStreamChild* bs)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(!mBrowserStream, "Two streams for one streamnotify?");
|
|
|
|
|
|
|
|
mBrowserStream = bs;
|
2009-12-03 11:16:14 +03:00
|
|
|
}
|
2009-10-08 23:11:13 +04:00
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2010-03-07 00:03:05 +03:00
|
|
|
StreamNotifyChild::Recv__delete__(const NPReason& reason)
|
2009-12-03 11:16:14 +03:00
|
|
|
{
|
2010-03-07 00:03:05 +03:00
|
|
|
AssertPluginThread();
|
|
|
|
|
|
|
|
if (mBrowserStream)
|
|
|
|
mBrowserStream->NotifyPending();
|
|
|
|
else
|
|
|
|
NPP_URLNotify(reason);
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2009-11-25 17:26:01 +03:00
|
|
|
}
|
2009-09-09 01:22:50 +04:00
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2011-01-05 22:44:21 +03:00
|
|
|
StreamNotifyChild::RecvRedirectNotify(const nsCString& url, const int32_t& status)
|
|
|
|
{
|
|
|
|
// NPP_URLRedirectNotify requires a non-null closure. Since core logic
|
|
|
|
// assumes that all out-of-process notify streams have non-null closure
|
|
|
|
// data it will assume that the plugin was notified at this point and
|
|
|
|
// expect a response otherwise the redirect will hang indefinitely.
|
|
|
|
if (!mClosure) {
|
|
|
|
SendRedirectNotifyResponse(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
PluginInstanceChild* instance = static_cast<PluginInstanceChild*>(Manager());
|
|
|
|
if (instance->mPluginIface->urlredirectnotify)
|
2011-01-14 04:52:15 +03:00
|
|
|
instance->mPluginIface->urlredirectnotify(instance->GetNPP(), url.get(), status, mClosure);
|
2011-01-05 22:44:21 +03:00
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2011-01-05 22:44:21 +03:00
|
|
|
}
|
|
|
|
|
2010-03-07 00:03:05 +03:00
|
|
|
void
|
|
|
|
StreamNotifyChild::NPP_URLNotify(NPReason reason)
|
|
|
|
{
|
|
|
|
PluginInstanceChild* instance = static_cast<PluginInstanceChild*>(Manager());
|
|
|
|
|
|
|
|
if (mClosure)
|
|
|
|
instance->mPluginIface->urlnotify(instance->GetNPP(), mURL.get(),
|
|
|
|
reason, mClosure);
|
|
|
|
}
|
|
|
|
|
2009-11-25 17:26:01 +03:00
|
|
|
bool
|
2013-07-08 19:48:39 +04:00
|
|
|
PluginInstanceChild::DeallocPStreamNotifyChild(PStreamNotifyChild* notifyData)
|
2009-11-25 17:26:01 +03:00
|
|
|
{
|
2009-12-03 11:16:14 +03:00
|
|
|
AssertPluginThread();
|
2010-03-07 00:03:05 +03:00
|
|
|
|
|
|
|
if (!static_cast<StreamNotifyChild*>(notifyData)->mBrowserStream)
|
|
|
|
delete notifyData;
|
2009-09-18 03:09:20 +04:00
|
|
|
return true;
|
2009-09-09 01:22:50 +04:00
|
|
|
}
|
|
|
|
|
2009-09-18 02:15:12 +04:00
|
|
|
PluginScriptableObjectChild*
|
2009-09-23 11:12:52 +04:00
|
|
|
PluginInstanceChild::GetActorForNPObject(NPObject* aObject)
|
2009-09-18 02:15:12 +04:00
|
|
|
{
|
2009-10-08 23:11:13 +04:00
|
|
|
AssertPluginThread();
|
2010-01-15 23:35:57 +03:00
|
|
|
NS_ASSERTION(aObject, "Null pointer!");
|
|
|
|
|
|
|
|
if (aObject->_class == PluginScriptableObjectChild::GetClass()) {
|
|
|
|
// One of ours! It's a browser-provided object.
|
|
|
|
ChildNPObject* object = static_cast<ChildNPObject*>(aObject);
|
|
|
|
NS_ASSERTION(object->parent, "Null actor!");
|
|
|
|
return object->parent;
|
|
|
|
}
|
2010-01-15 23:35:57 +03:00
|
|
|
|
2010-01-15 23:35:57 +03:00
|
|
|
PluginScriptableObjectChild* actor =
|
2014-10-29 18:04:51 +03:00
|
|
|
PluginScriptableObjectChild::GetActorForNPObject(aObject);
|
2010-01-15 23:35:57 +03:00
|
|
|
if (actor) {
|
|
|
|
// Plugin-provided object that we've previously wrapped.
|
|
|
|
return actor;
|
|
|
|
}
|
|
|
|
|
|
|
|
actor = new PluginScriptableObjectChild(LocalObject);
|
2010-03-05 00:20:14 +03:00
|
|
|
if (!SendPPluginScriptableObjectConstructor(actor)) {
|
2010-01-15 23:35:57 +03:00
|
|
|
NS_ERROR("Failed to send constructor message!");
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2010-01-15 23:35:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
actor->InitializeLocal(aObject);
|
|
|
|
return actor;
|
2009-09-18 02:15:12 +04:00
|
|
|
}
|
2009-09-21 18:51:35 +04:00
|
|
|
|
2011-01-05 22:44:21 +03:00
|
|
|
void
|
|
|
|
PluginInstanceChild::NPN_URLRedirectResponse(void* notifyData, NPBool allow)
|
|
|
|
{
|
|
|
|
if (!notifyData) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
InfallibleTArray<PStreamNotifyChild*> notifyStreams;
|
|
|
|
ManagedPStreamNotifyChild(notifyStreams);
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t notifyStreamCount = notifyStreams.Length();
|
|
|
|
for (uint32_t i = 0; i < notifyStreamCount; i++) {
|
2011-01-05 22:44:21 +03:00
|
|
|
StreamNotifyChild* sn = static_cast<StreamNotifyChild*>(notifyStreams[i]);
|
|
|
|
if (sn->mClosure == notifyData) {
|
|
|
|
sn->SendRedirectNotifyResponse(static_cast<bool>(allow));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2011-10-17 18:59:28 +04:00
|
|
|
NS_ASSERTION(false, "Couldn't find stream for redirect response!");
|
2011-01-05 22:44:21 +03:00
|
|
|
}
|
|
|
|
|
2015-12-02 22:31:16 +03:00
|
|
|
bool
|
|
|
|
PluginInstanceChild::IsUsingDirectDrawing()
|
|
|
|
{
|
|
|
|
return IsDrawingModelDirect(mDrawingModel);
|
|
|
|
}
|
|
|
|
|
2015-12-02 22:31:17 +03:00
|
|
|
PluginInstanceChild::DirectBitmap::DirectBitmap(PluginInstanceChild* aOwner, const Shmem& shmem,
|
|
|
|
const IntSize& size, uint32_t stride, SurfaceFormat format)
|
|
|
|
: mOwner(aOwner),
|
|
|
|
mShmem(shmem),
|
|
|
|
mFormat(format),
|
|
|
|
mSize(size),
|
|
|
|
mStride(stride)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
PluginInstanceChild::DirectBitmap::~DirectBitmap()
|
|
|
|
{
|
|
|
|
mOwner->DeallocShmem(mShmem);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline SurfaceFormat
|
|
|
|
NPImageFormatToSurfaceFormat(NPImageFormat aFormat)
|
|
|
|
{
|
|
|
|
switch (aFormat) {
|
|
|
|
case NPImageFormatBGRA32:
|
|
|
|
return SurfaceFormat::B8G8R8A8;
|
|
|
|
case NPImageFormatBGRX32:
|
|
|
|
return SurfaceFormat::B8G8R8X8;
|
|
|
|
default:
|
|
|
|
MOZ_ASSERT_UNREACHABLE("unknown NPImageFormat");
|
|
|
|
return SurfaceFormat::UNKNOWN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-02 22:31:17 +03:00
|
|
|
static inline gfx::IntRect
|
|
|
|
NPRectToIntRect(const NPRect& in)
|
|
|
|
{
|
|
|
|
return IntRect(in.left, in.top, in.right - in.left, in.bottom - in.top);
|
|
|
|
}
|
|
|
|
|
2015-12-02 22:31:16 +03:00
|
|
|
NPError
|
|
|
|
PluginInstanceChild::NPN_InitAsyncSurface(NPSize *size, NPImageFormat format,
|
|
|
|
void *initData, NPAsyncSurface *surface)
|
|
|
|
{
|
|
|
|
AssertPluginThread();
|
2016-04-06 23:23:43 +03:00
|
|
|
AutoStackHelper guard(this);
|
2015-12-02 22:31:16 +03:00
|
|
|
|
|
|
|
if (!IsUsingDirectDrawing()) {
|
2015-12-02 22:31:17 +03:00
|
|
|
return NPERR_INVALID_PARAM;
|
|
|
|
}
|
|
|
|
if (format != NPImageFormatBGRA32 && format != NPImageFormatBGRX32) {
|
|
|
|
return NPERR_INVALID_PARAM;
|
|
|
|
}
|
|
|
|
|
|
|
|
PodZero(surface);
|
|
|
|
|
|
|
|
// NPAPI guarantees that the SetCurrentAsyncSurface call will release the
|
|
|
|
// previous surface if it was different. However, no functionality exists
|
|
|
|
// within content to synchronize a non-shadow-layers transaction with the
|
|
|
|
// compositor.
|
|
|
|
//
|
|
|
|
// To get around this, we allocate two surfaces: a child copy, which we
|
|
|
|
// hand off to the plugin, and a parent copy, which we will hand off to
|
|
|
|
// the compositor. Each call to SetCurrentAsyncSurface will copy the
|
|
|
|
// invalid region from the child surface to its parent.
|
|
|
|
switch (mDrawingModel) {
|
|
|
|
case NPDrawingModelAsyncBitmapSurface: {
|
|
|
|
// Validate that the caller does not expect initial data to be set.
|
|
|
|
if (initData) {
|
|
|
|
return NPERR_INVALID_PARAM;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Validate that we're not double-allocating a surface.
|
|
|
|
RefPtr<DirectBitmap> holder;
|
|
|
|
if (mDirectBitmaps.Get(surface, getter_AddRefs(holder))) {
|
|
|
|
return NPERR_INVALID_PARAM;
|
|
|
|
}
|
|
|
|
|
|
|
|
SurfaceFormat mozformat = NPImageFormatToSurfaceFormat(format);
|
|
|
|
int32_t bytesPerPixel = BytesPerPixel(mozformat);
|
|
|
|
|
|
|
|
if (size->width <= 0 || size->height <= 0) {
|
|
|
|
return NPERR_INVALID_PARAM;
|
|
|
|
}
|
|
|
|
|
|
|
|
CheckedInt<uint32_t> nbytes = SafeBytesForBitmap(size->width, size->height, bytesPerPixel);
|
|
|
|
if (!nbytes.isValid()) {
|
|
|
|
return NPERR_INVALID_PARAM;
|
|
|
|
}
|
|
|
|
|
|
|
|
Shmem shmem;
|
|
|
|
if (!AllocUnsafeShmem(nbytes.value(), SharedMemory::TYPE_BASIC, &shmem)) {
|
|
|
|
return NPERR_OUT_OF_MEMORY_ERROR;
|
|
|
|
}
|
|
|
|
MOZ_ASSERT(shmem.Size<uint8_t>() == nbytes.value());
|
|
|
|
|
|
|
|
surface->version = 0;
|
|
|
|
surface->size = *size;
|
|
|
|
surface->format = format;
|
|
|
|
surface->bitmap.data = shmem.get<unsigned char>();
|
|
|
|
surface->bitmap.stride = size->width * bytesPerPixel;
|
|
|
|
|
|
|
|
// Hold the shmem alive until Finalize() is called or this actor dies.
|
|
|
|
holder = new DirectBitmap(this, shmem,
|
|
|
|
IntSize(size->width, size->height),
|
|
|
|
surface->bitmap.stride, mozformat);
|
|
|
|
mDirectBitmaps.Put(surface, holder);
|
|
|
|
return NPERR_NO_ERROR;
|
|
|
|
}
|
2015-12-02 22:31:17 +03:00
|
|
|
#if defined(XP_WIN)
|
|
|
|
case NPDrawingModelAsyncWindowsDXGISurface: {
|
|
|
|
// Validate that the caller does not expect initial data to be set.
|
|
|
|
if (initData) {
|
|
|
|
return NPERR_INVALID_PARAM;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Validate that we're not double-allocating a surface.
|
|
|
|
WindowsHandle handle = 0;
|
|
|
|
if (mDxgiSurfaces.Get(surface, &handle)) {
|
|
|
|
return NPERR_INVALID_PARAM;
|
|
|
|
}
|
|
|
|
|
|
|
|
NPError error = NPERR_NO_ERROR;
|
|
|
|
SurfaceFormat mozformat = NPImageFormatToSurfaceFormat(format);
|
|
|
|
if (!SendInitDXGISurface(mozformat,
|
|
|
|
IntSize(size->width, size->height),
|
|
|
|
&handle,
|
|
|
|
&error))
|
|
|
|
{
|
|
|
|
return NPERR_GENERIC_ERROR;
|
|
|
|
}
|
|
|
|
if (error != NPERR_NO_ERROR) {
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
surface->version = 0;
|
|
|
|
surface->size = *size;
|
|
|
|
surface->format = format;
|
|
|
|
surface->sharedHandle = reinterpret_cast<HANDLE>(handle);
|
|
|
|
|
|
|
|
mDxgiSurfaces.Put(surface, handle);
|
|
|
|
return NPERR_NO_ERROR;
|
|
|
|
}
|
|
|
|
#endif
|
2015-12-02 22:31:17 +03:00
|
|
|
default:
|
|
|
|
MOZ_ASSERT_UNREACHABLE("unknown drawing model");
|
2015-12-02 22:31:16 +03:00
|
|
|
}
|
|
|
|
|
2015-12-02 22:31:17 +03:00
|
|
|
return NPERR_INVALID_PARAM;
|
2015-12-02 22:31:16 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
NPError
|
|
|
|
PluginInstanceChild::NPN_FinalizeAsyncSurface(NPAsyncSurface *surface)
|
|
|
|
{
|
|
|
|
AssertPluginThread();
|
|
|
|
|
|
|
|
if (!IsUsingDirectDrawing()) {
|
|
|
|
return NPERR_GENERIC_ERROR;
|
|
|
|
}
|
|
|
|
|
2015-12-02 22:31:17 +03:00
|
|
|
switch (mDrawingModel) {
|
|
|
|
case NPDrawingModelAsyncBitmapSurface: {
|
|
|
|
RefPtr<DirectBitmap> bitmap;
|
|
|
|
if (!mDirectBitmaps.Get(surface, getter_AddRefs(bitmap))) {
|
|
|
|
return NPERR_INVALID_PARAM;
|
|
|
|
}
|
|
|
|
|
|
|
|
PodZero(surface);
|
|
|
|
mDirectBitmaps.Remove(surface);
|
|
|
|
return NPERR_NO_ERROR;
|
|
|
|
}
|
2015-12-02 22:31:17 +03:00
|
|
|
#if defined(XP_WIN)
|
|
|
|
case NPDrawingModelAsyncWindowsDXGISurface: {
|
|
|
|
WindowsHandle handle;
|
|
|
|
if (!mDxgiSurfaces.Get(surface, &handle)) {
|
|
|
|
return NPERR_INVALID_PARAM;
|
|
|
|
}
|
|
|
|
|
|
|
|
SendFinalizeDXGISurface(handle);
|
|
|
|
mDxgiSurfaces.Remove(surface);
|
|
|
|
return NPERR_NO_ERROR;
|
|
|
|
}
|
|
|
|
#endif
|
2015-12-02 22:31:17 +03:00
|
|
|
default:
|
|
|
|
MOZ_ASSERT_UNREACHABLE("unknown drawing model");
|
|
|
|
}
|
|
|
|
|
|
|
|
return NPERR_INVALID_PARAM;
|
2015-12-02 22:31:16 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PluginInstanceChild::NPN_SetCurrentAsyncSurface(NPAsyncSurface *surface, NPRect *changed)
|
|
|
|
{
|
2015-12-02 22:31:17 +03:00
|
|
|
AssertPluginThread();
|
|
|
|
|
2015-12-02 22:31:16 +03:00
|
|
|
if (!IsUsingDirectDrawing()) {
|
|
|
|
return;
|
|
|
|
}
|
2015-12-02 22:31:17 +03:00
|
|
|
|
|
|
|
mCurrentDirectSurface = surface;
|
|
|
|
|
|
|
|
if (!surface) {
|
|
|
|
SendRevokeCurrentDirectSurface();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (mDrawingModel) {
|
|
|
|
case NPDrawingModelAsyncBitmapSurface: {
|
|
|
|
RefPtr<DirectBitmap> bitmap;
|
|
|
|
if (!mDirectBitmaps.Get(surface, getter_AddRefs(bitmap))) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
IntRect dirty = changed
|
2015-12-02 22:31:17 +03:00
|
|
|
? NPRectToIntRect(*changed)
|
2015-12-02 22:31:17 +03:00
|
|
|
: IntRect(IntPoint(0, 0), bitmap->mSize);
|
|
|
|
|
|
|
|
// Need a holder since IPDL zaps the object for mysterious reasons.
|
|
|
|
Shmem shmemHolder = bitmap->mShmem;
|
|
|
|
SendShowDirectBitmap(shmemHolder, bitmap->mFormat, bitmap->mStride, bitmap->mSize, dirty);
|
|
|
|
break;
|
|
|
|
}
|
2015-12-02 22:31:17 +03:00
|
|
|
#if defined(XP_WIN)
|
|
|
|
case NPDrawingModelAsyncWindowsDXGISurface: {
|
|
|
|
WindowsHandle handle;
|
|
|
|
if (!mDxgiSurfaces.Get(surface, &handle)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
IntRect dirty = changed
|
|
|
|
? NPRectToIntRect(*changed)
|
|
|
|
: IntRect(IntPoint(0, 0), IntSize(surface->size.width, surface->size.height));
|
|
|
|
|
|
|
|
SendShowDirectDXGISurface(handle, dirty);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
2015-12-02 22:31:17 +03:00
|
|
|
default:
|
|
|
|
MOZ_ASSERT_UNREACHABLE("unknown drawing model");
|
|
|
|
}
|
2015-12-02 22:31:16 +03:00
|
|
|
}
|
|
|
|
|
2012-02-16 07:30:22 +04:00
|
|
|
void
|
|
|
|
PluginInstanceChild::DoAsyncRedraw()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
MutexAutoLock autoLock(mAsyncInvalidateMutex);
|
2013-10-24 00:34:46 +04:00
|
|
|
mAsyncInvalidateTask = nullptr;
|
2012-02-16 07:30:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
SendRedrawPlugin();
|
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2010-09-15 20:02:44 +04:00
|
|
|
PluginInstanceChild::RecvAsyncSetWindow(const gfxSurfaceType& aSurfaceType,
|
|
|
|
const NPRemoteWindow& aWindow)
|
|
|
|
{
|
2010-09-15 20:02:49 +04:00
|
|
|
AssertPluginThread();
|
|
|
|
|
2016-04-06 23:23:43 +03:00
|
|
|
AutoStackHelper guard(this);
|
2010-11-15 17:41:18 +03:00
|
|
|
NS_ASSERTION(!aWindow.window, "Remote window should be null.");
|
|
|
|
|
2010-12-06 00:57:33 +03:00
|
|
|
if (mCurrentAsyncSetWindowTask) {
|
|
|
|
mCurrentAsyncSetWindowTask->Cancel();
|
2012-07-30 18:20:58 +04:00
|
|
|
mCurrentAsyncSetWindowTask = nullptr;
|
2010-12-06 00:57:33 +03:00
|
|
|
}
|
|
|
|
|
2013-03-18 19:00:21 +04:00
|
|
|
// We shouldn't process this now because it may be received within a nested
|
|
|
|
// RPC call, and both Flash and Java don't expect to receive setwindow calls
|
|
|
|
// at arbitrary times.
|
|
|
|
mCurrentAsyncSetWindowTask =
|
2017-06-12 22:34:10 +03:00
|
|
|
NewNonOwningCancelableRunnableMethod<gfxSurfaceType,
|
|
|
|
NPRemoteWindow,
|
|
|
|
bool>(
|
|
|
|
"plugins::PluginInstanceChild::DoAsyncSetWindow",
|
|
|
|
this,
|
|
|
|
&PluginInstanceChild::DoAsyncSetWindow,
|
|
|
|
aSurfaceType,
|
|
|
|
aWindow,
|
|
|
|
true);
|
2016-04-28 03:06:05 +03:00
|
|
|
RefPtr<Runnable> addrefedTask = mCurrentAsyncSetWindowTask;
|
|
|
|
MessageLoop::current()->PostTask(addrefedTask.forget());
|
2010-12-06 00:57:33 +03:00
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2010-12-06 00:57:33 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PluginInstanceChild::DoAsyncSetWindow(const gfxSurfaceType& aSurfaceType,
|
|
|
|
const NPRemoteWindow& aWindow,
|
|
|
|
bool aIsAsync)
|
|
|
|
{
|
2011-02-17 01:43:31 +03:00
|
|
|
PLUGIN_LOG_DEBUG(
|
|
|
|
("[InstanceChild][%p] AsyncSetWindow to <x=%d,y=%d, w=%d,h=%d>",
|
|
|
|
this, aWindow.x, aWindow.y, aWindow.width, aWindow.height));
|
|
|
|
|
2010-12-06 00:57:33 +03:00
|
|
|
AssertPluginThread();
|
|
|
|
NS_ASSERTION(!aWindow.window, "Remote window should be null.");
|
|
|
|
NS_ASSERTION(!mPendingPluginCall, "Can't do SetWindow during plugin call!");
|
|
|
|
|
|
|
|
if (aIsAsync) {
|
|
|
|
if (!mCurrentAsyncSetWindowTask) {
|
|
|
|
return;
|
|
|
|
}
|
2012-07-30 18:20:58 +04:00
|
|
|
mCurrentAsyncSetWindowTask = nullptr;
|
2010-12-06 00:57:33 +03:00
|
|
|
}
|
|
|
|
|
2013-10-24 00:34:46 +04:00
|
|
|
mWindow.window = nullptr;
|
2011-02-17 01:43:31 +03:00
|
|
|
if (mWindow.width != aWindow.width || mWindow.height != aWindow.height ||
|
|
|
|
mWindow.clipRect.top != aWindow.clipRect.top ||
|
2010-11-05 17:40:55 +03:00
|
|
|
mWindow.clipRect.left != aWindow.clipRect.left ||
|
|
|
|
mWindow.clipRect.bottom != aWindow.clipRect.bottom ||
|
|
|
|
mWindow.clipRect.right != aWindow.clipRect.right)
|
2010-11-09 17:36:33 +03:00
|
|
|
mAccumulatedInvalidRect = nsIntRect(0, 0, aWindow.width, aWindow.height);
|
2010-10-25 21:57:13 +04:00
|
|
|
|
2010-09-15 20:02:49 +04:00
|
|
|
mWindow.x = aWindow.x;
|
|
|
|
mWindow.y = aWindow.y;
|
|
|
|
mWindow.width = aWindow.width;
|
|
|
|
mWindow.height = aWindow.height;
|
|
|
|
mWindow.clipRect = aWindow.clipRect;
|
|
|
|
mWindow.type = aWindow.type;
|
2015-09-17 23:31:34 +03:00
|
|
|
#if defined(XP_MACOSX) || defined(XP_WIN)
|
2012-10-02 23:48:05 +04:00
|
|
|
mContentsScaleFactor = aWindow.contentsScaleFactor;
|
|
|
|
#endif
|
2010-09-15 20:02:49 +04:00
|
|
|
|
2010-09-21 20:03:16 +04:00
|
|
|
mLayersRendering = true;
|
2010-09-15 20:02:49 +04:00
|
|
|
mSurfaceType = aSurfaceType;
|
2010-09-21 20:03:16 +04:00
|
|
|
UpdateWindowAttributes(true);
|
2010-09-15 20:02:49 +04:00
|
|
|
|
2010-10-28 00:56:48 +04:00
|
|
|
#ifdef XP_WIN
|
2015-08-12 18:00:25 +03:00
|
|
|
if (GetQuirks() & QUIRK_FLASH_THROTTLE_WMUSER_EVENTS)
|
2010-10-28 00:56:48 +04:00
|
|
|
SetupFlashMsgThrottle();
|
|
|
|
#endif
|
|
|
|
|
2010-11-05 17:40:55 +03:00
|
|
|
if (!mAccumulatedInvalidRect.IsEmpty()) {
|
|
|
|
AsyncShowPluginFrame();
|
|
|
|
}
|
2010-09-15 20:02:44 +04:00
|
|
|
}
|
|
|
|
|
2010-09-21 20:03:16 +04:00
|
|
|
bool
|
2010-09-15 20:02:49 +04:00
|
|
|
PluginInstanceChild::CreateOptSurface(void)
|
|
|
|
{
|
2015-02-10 01:34:50 +03:00
|
|
|
MOZ_ASSERT(mSurfaceType != gfxSurfaceType::Max,
|
|
|
|
"Need a valid surface type here");
|
2011-01-28 01:37:00 +03:00
|
|
|
NS_ASSERTION(!mCurrentSurface, "mCurrentSurfaceActor can get out of sync.");
|
|
|
|
|
2011-02-17 01:43:31 +03:00
|
|
|
// Use an opaque surface unless we're transparent and *don't* have
|
|
|
|
// a background to source from.
|
2013-09-25 00:45:13 +04:00
|
|
|
gfxImageFormat format =
|
2016-01-08 07:57:38 +03:00
|
|
|
(mIsTransparent && !mBackground) ? SurfaceFormat::A8R8G8B8_UINT32 :
|
|
|
|
SurfaceFormat::X8R8G8B8_UINT32;
|
2010-09-15 20:02:49 +04:00
|
|
|
|
2011-08-24 20:15:58 +04:00
|
|
|
#ifdef MOZ_X11
|
2010-09-15 20:02:49 +04:00
|
|
|
Display* dpy = mWsInfo.display;
|
|
|
|
Screen* screen = DefaultScreenOfDisplay(dpy);
|
2016-01-08 07:57:38 +03:00
|
|
|
if (format == SurfaceFormat::X8R8G8B8_UINT32 &&
|
2010-09-15 20:02:49 +04:00
|
|
|
DefaultDepth(dpy, DefaultScreen(dpy)) == 16) {
|
2016-01-08 07:57:38 +03:00
|
|
|
format = SurfaceFormat::R5G6B5_UINT16;
|
2010-09-15 20:02:49 +04:00
|
|
|
}
|
|
|
|
|
2014-01-23 22:26:40 +04:00
|
|
|
if (mSurfaceType == gfxSurfaceType::Xlib) {
|
2011-06-02 06:27:51 +04:00
|
|
|
if (!mIsTransparent || mBackground) {
|
|
|
|
Visual* defaultVisual = DefaultVisualOfScreen(screen);
|
|
|
|
mCurrentSurface =
|
|
|
|
gfxXlibSurface::Create(screen, defaultVisual,
|
2015-09-23 21:49:05 +03:00
|
|
|
IntSize(mWindow.width, mWindow.height));
|
2012-07-30 18:20:58 +04:00
|
|
|
return mCurrentSurface != nullptr;
|
2011-06-02 06:27:51 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
XRenderPictFormat* xfmt = XRenderFindStandardFormat(dpy, PictStandardARGB32);
|
2010-09-15 20:02:49 +04:00
|
|
|
if (!xfmt) {
|
|
|
|
NS_ERROR("Need X falback surface, but FindRenderFormat failed");
|
2010-09-21 20:03:16 +04:00
|
|
|
return false;
|
2010-09-15 20:02:49 +04:00
|
|
|
}
|
|
|
|
mCurrentSurface =
|
|
|
|
gfxXlibSurface::Create(screen, xfmt,
|
2015-09-23 21:49:05 +03:00
|
|
|
IntSize(mWindow.width, mWindow.height));
|
2012-07-30 18:20:58 +04:00
|
|
|
return mCurrentSurface != nullptr;
|
2010-09-15 20:02:49 +04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-10-25 21:57:13 +04:00
|
|
|
#ifdef XP_WIN
|
2015-07-02 15:02:51 +03:00
|
|
|
if (mSurfaceType == gfxSurfaceType::Win32) {
|
2011-02-17 01:43:31 +03:00
|
|
|
bool willHaveTransparentPixels = mIsTransparent && !mBackground;
|
2010-10-25 21:57:13 +04:00
|
|
|
|
|
|
|
SharedDIBSurface* s = new SharedDIBSurface();
|
|
|
|
if (!s->Create(reinterpret_cast<HDC>(mWindow.window),
|
2011-02-17 01:43:31 +03:00
|
|
|
mWindow.width, mWindow.height,
|
|
|
|
willHaveTransparentPixels))
|
2010-10-25 21:57:13 +04:00
|
|
|
return false;
|
|
|
|
|
|
|
|
mCurrentSurface = s;
|
|
|
|
return true;
|
2010-09-15 20:02:49 +04:00
|
|
|
}
|
|
|
|
|
2016-12-03 00:46:53 +03:00
|
|
|
MOZ_CRASH("Shared-memory drawing not expected on Windows.");
|
2010-10-25 21:57:13 +04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// Make common shmem implementation working for any platform
|
2011-01-04 19:40:54 +03:00
|
|
|
mCurrentSurface =
|
2015-09-23 21:49:05 +03:00
|
|
|
gfxSharedImageSurface::CreateUnsafe(this, IntSize(mWindow.width, mWindow.height), format);
|
2011-01-04 19:40:54 +03:00
|
|
|
return !!mCurrentSurface;
|
2010-09-15 20:02:49 +04:00
|
|
|
}
|
|
|
|
|
2010-09-21 20:03:16 +04:00
|
|
|
bool
|
2010-09-15 20:02:49 +04:00
|
|
|
PluginInstanceChild::MaybeCreatePlatformHelperSurface(void)
|
|
|
|
{
|
|
|
|
if (!mCurrentSurface) {
|
|
|
|
NS_ERROR("Cannot create helper surface without mCurrentSurface");
|
2010-09-21 20:03:16 +04:00
|
|
|
return false;
|
2010-09-15 20:02:49 +04:00
|
|
|
}
|
|
|
|
|
2012-02-22 04:32:06 +04:00
|
|
|
#ifdef MOZ_X11
|
2010-09-21 20:03:16 +04:00
|
|
|
bool supportNonDefaultVisual = false;
|
2010-09-15 20:02:49 +04:00
|
|
|
Screen* screen = DefaultScreenOfDisplay(mWsInfo.display);
|
|
|
|
Visual* defaultVisual = DefaultVisualOfScreen(screen);
|
2012-07-30 18:20:58 +04:00
|
|
|
Visual* visual = nullptr;
|
2010-09-15 20:02:49 +04:00
|
|
|
Colormap colormap = 0;
|
2010-09-21 20:03:16 +04:00
|
|
|
mDoAlphaExtraction = false;
|
|
|
|
bool createHelperSurface = false;
|
2010-09-15 20:02:49 +04:00
|
|
|
|
2014-01-23 22:26:40 +04:00
|
|
|
if (mCurrentSurface->GetType() == gfxSurfaceType::Xlib) {
|
2010-09-15 20:02:49 +04:00
|
|
|
static_cast<gfxXlibSurface*>(mCurrentSurface.get())->
|
|
|
|
GetColormapAndVisual(&colormap, &visual);
|
|
|
|
// Create helper surface if layer surface visual not same as default
|
|
|
|
// and we don't support non-default visual rendering
|
|
|
|
if (!visual || (defaultVisual != visual && !supportNonDefaultVisual)) {
|
2010-09-21 20:03:16 +04:00
|
|
|
createHelperSurface = true;
|
2010-09-15 20:02:49 +04:00
|
|
|
visual = defaultVisual;
|
|
|
|
mDoAlphaExtraction = mIsTransparent;
|
|
|
|
}
|
2014-01-23 22:26:40 +04:00
|
|
|
} else if (mCurrentSurface->GetType() == gfxSurfaceType::Image) {
|
2010-09-15 20:02:49 +04:00
|
|
|
// For image layer surface we should always create helper surface
|
2010-09-21 20:03:16 +04:00
|
|
|
createHelperSurface = true;
|
2010-09-15 20:02:49 +04:00
|
|
|
// Check if we can create helper surface with non-default visual
|
|
|
|
visual = gfxXlibSurface::FindVisual(screen,
|
|
|
|
static_cast<gfxImageSurface*>(mCurrentSurface.get())->Format());
|
2012-01-16 05:31:33 +04:00
|
|
|
if (!visual || (defaultVisual != visual && !supportNonDefaultVisual)) {
|
2010-09-15 20:02:49 +04:00
|
|
|
visual = defaultVisual;
|
|
|
|
mDoAlphaExtraction = mIsTransparent;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (createHelperSurface) {
|
|
|
|
if (!visual) {
|
|
|
|
NS_ERROR("Need X falback surface, but visual failed");
|
2010-09-21 20:03:16 +04:00
|
|
|
return false;
|
2010-09-15 20:02:49 +04:00
|
|
|
}
|
|
|
|
mHelperSurface =
|
|
|
|
gfxXlibSurface::Create(screen, visual,
|
|
|
|
mCurrentSurface->GetSize());
|
|
|
|
if (!mHelperSurface) {
|
|
|
|
NS_WARNING("Fail to create create helper surface");
|
2010-09-21 20:03:16 +04:00
|
|
|
return false;
|
2010-09-15 20:02:49 +04:00
|
|
|
}
|
|
|
|
}
|
2011-02-17 01:43:31 +03:00
|
|
|
#elif defined(XP_WIN)
|
|
|
|
mDoAlphaExtraction = mIsTransparent && !mBackground;
|
2010-09-15 20:02:49 +04:00
|
|
|
#endif
|
|
|
|
|
2010-09-21 20:03:16 +04:00
|
|
|
return true;
|
2010-09-15 20:02:49 +04:00
|
|
|
}
|
|
|
|
|
2010-09-21 20:03:16 +04:00
|
|
|
bool
|
2010-09-15 20:02:49 +04:00
|
|
|
PluginInstanceChild::EnsureCurrentBuffer(void)
|
|
|
|
{
|
2015-06-12 15:46:43 +03:00
|
|
|
#ifndef XP_DARWIN
|
2011-02-17 01:43:31 +03:00
|
|
|
nsIntRect toInvalidate(0, 0, 0, 0);
|
2015-09-23 21:49:05 +03:00
|
|
|
IntSize winSize = IntSize(mWindow.width, mWindow.height);
|
2011-02-17 01:43:31 +03:00
|
|
|
|
|
|
|
if (mBackground && mBackground->GetSize() != winSize) {
|
|
|
|
// It would be nice to keep the old background here, but doing
|
|
|
|
// so can lead to cases in which we permanently keep the old
|
|
|
|
// background size.
|
2012-07-30 18:20:58 +04:00
|
|
|
mBackground = nullptr;
|
2011-02-17 01:43:31 +03:00
|
|
|
toInvalidate.UnionRect(toInvalidate,
|
|
|
|
nsIntRect(0, 0, winSize.width, winSize.height));
|
|
|
|
}
|
|
|
|
|
2010-09-15 20:02:49 +04:00
|
|
|
if (mCurrentSurface) {
|
2015-09-23 21:49:05 +03:00
|
|
|
IntSize surfSize = mCurrentSurface->GetSize();
|
2011-02-17 01:43:31 +03:00
|
|
|
if (winSize != surfSize ||
|
|
|
|
(mBackground && !CanPaintOnBackground()) ||
|
|
|
|
(mBackground &&
|
2014-01-23 22:26:40 +04:00
|
|
|
gfxContentType::COLOR != mCurrentSurface->GetContentType()) ||
|
2011-02-17 01:43:31 +03:00
|
|
|
(!mBackground && mIsTransparent &&
|
2014-01-23 22:26:40 +04:00
|
|
|
gfxContentType::COLOR == mCurrentSurface->GetContentType())) {
|
2011-02-17 01:43:31 +03:00
|
|
|
// Don't try to use an old, invalid DC.
|
2012-07-30 18:20:58 +04:00
|
|
|
mWindow.window = nullptr;
|
2011-02-17 01:43:31 +03:00
|
|
|
ClearCurrentSurface();
|
|
|
|
toInvalidate.UnionRect(toInvalidate,
|
|
|
|
nsIntRect(0, 0, winSize.width, winSize.height));
|
|
|
|
}
|
2010-09-15 20:02:49 +04:00
|
|
|
}
|
|
|
|
|
2011-02-17 01:43:31 +03:00
|
|
|
mAccumulatedInvalidRect.UnionRect(mAccumulatedInvalidRect, toInvalidate);
|
|
|
|
|
|
|
|
if (mCurrentSurface) {
|
2011-05-20 01:08:14 +04:00
|
|
|
return true;
|
2010-09-15 20:02:49 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!CreateOptSurface()) {
|
|
|
|
NS_ERROR("Cannot create optimized surface");
|
2010-09-21 20:03:16 +04:00
|
|
|
return false;
|
2010-09-15 20:02:49 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!MaybeCreatePlatformHelperSurface()) {
|
|
|
|
NS_ERROR("Cannot create helper surface");
|
2010-09-21 20:03:16 +04:00
|
|
|
return false;
|
2010-09-15 20:02:49 +04:00
|
|
|
}
|
2015-06-12 15:46:43 +03:00
|
|
|
#elif defined(XP_MACOSX)
|
2011-05-20 01:08:14 +04:00
|
|
|
|
2011-07-12 18:31:18 +04:00
|
|
|
if (!mDoubleBufferCARenderer.HasCALayer()) {
|
2012-07-30 18:20:58 +04:00
|
|
|
void *caLayer = nullptr;
|
2011-05-20 01:08:14 +04:00
|
|
|
if (mDrawingModel == NPDrawingModelCoreGraphics) {
|
2011-07-12 18:31:18 +04:00
|
|
|
if (!mCGLayer) {
|
2016-07-06 19:34:05 +03:00
|
|
|
caLayer = mozilla::plugins::PluginUtilsOSX::GetCGLayer(CallCGDraw,
|
2016-07-22 21:11:14 +03:00
|
|
|
this,
|
2013-01-24 02:19:15 +04:00
|
|
|
mContentsScaleFactor);
|
2011-05-20 01:08:14 +04:00
|
|
|
|
2011-07-12 18:31:18 +04:00
|
|
|
if (!caLayer) {
|
|
|
|
PLUGIN_LOG_DEBUG(("GetCGLayer failed."));
|
|
|
|
return false;
|
|
|
|
}
|
2011-05-20 01:08:14 +04:00
|
|
|
}
|
|
|
|
mCGLayer = caLayer;
|
|
|
|
} else {
|
|
|
|
NPError result = mPluginIface->getvalue(GetNPP(),
|
|
|
|
NPPVpluginCoreAnimationLayer,
|
|
|
|
&caLayer);
|
|
|
|
if (result != NPERR_NO_ERROR || !caLayer) {
|
|
|
|
PLUGIN_LOG_DEBUG(("Plugin requested CoreAnimation but did not "
|
|
|
|
"provide CALayer."));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2011-07-12 18:31:18 +04:00
|
|
|
mDoubleBufferCARenderer.SetCALayer(caLayer);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mDoubleBufferCARenderer.HasFrontSurface() &&
|
|
|
|
(mDoubleBufferCARenderer.GetFrontSurfaceWidth() != mWindow.width ||
|
2012-10-02 23:48:05 +04:00
|
|
|
mDoubleBufferCARenderer.GetFrontSurfaceHeight() != mWindow.height ||
|
|
|
|
mDoubleBufferCARenderer.GetContentsScaleFactor() != mContentsScaleFactor)) {
|
2011-07-12 18:31:18 +04:00
|
|
|
mDoubleBufferCARenderer.ClearFrontSurface();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mDoubleBufferCARenderer.HasFrontSurface()) {
|
2011-10-21 00:32:38 +04:00
|
|
|
bool allocSurface = mDoubleBufferCARenderer.InitFrontSurface(
|
2012-10-02 23:48:05 +04:00
|
|
|
mWindow.width, mWindow.height, mContentsScaleFactor,
|
2015-08-12 18:00:25 +03:00
|
|
|
GetQuirks() & QUIRK_ALLOW_OFFLINE_RENDERER ?
|
2011-10-21 00:32:38 +04:00
|
|
|
ALLOW_OFFLINE_RENDERER : DISALLOW_OFFLINE_RENDERER);
|
2011-07-12 18:31:18 +04:00
|
|
|
if (!allocSurface) {
|
|
|
|
PLUGIN_LOG_DEBUG(("Fail to allocate front IOSurface"));
|
|
|
|
return false;
|
|
|
|
}
|
2011-05-20 01:08:14 +04:00
|
|
|
|
|
|
|
if (mPluginIface->setwindow)
|
|
|
|
(void) mPluginIface->setwindow(&mData, &mWindow);
|
|
|
|
|
2011-07-12 18:31:18 +04:00
|
|
|
nsIntRect toInvalidate(0, 0, mWindow.width, mWindow.height);
|
|
|
|
mAccumulatedInvalidRect.UnionRect(mAccumulatedInvalidRect, toInvalidate);
|
|
|
|
}
|
2011-05-20 01:08:14 +04:00
|
|
|
#endif
|
2017-08-19 21:05:42 +03:00
|
|
|
|
2015-06-12 15:46:43 +03:00
|
|
|
return true;
|
2010-09-15 20:02:49 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-09-21 20:03:16 +04:00
|
|
|
PluginInstanceChild::UpdateWindowAttributes(bool aForceSetWindow)
|
2010-09-15 20:02:49 +04:00
|
|
|
{
|
2016-08-24 21:09:12 +03:00
|
|
|
#if defined(MOZ_X11) || defined(XP_WIN)
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<gfxASurface> curSurface = mHelperSurface ? mHelperSurface : mCurrentSurface;
|
2016-08-24 21:09:12 +03:00
|
|
|
#endif // Only used within MOZ_X11 or XP_WIN blocks. Unused variable otherwise
|
2010-09-21 20:03:16 +04:00
|
|
|
bool needWindowUpdate = aForceSetWindow;
|
2010-09-15 20:02:49 +04:00
|
|
|
#ifdef MOZ_X11
|
2012-07-30 18:20:58 +04:00
|
|
|
Visual* visual = nullptr;
|
2010-09-15 20:02:49 +04:00
|
|
|
Colormap colormap = 0;
|
2014-01-23 22:26:40 +04:00
|
|
|
if (curSurface && curSurface->GetType() == gfxSurfaceType::Xlib) {
|
2010-09-15 20:02:49 +04:00
|
|
|
static_cast<gfxXlibSurface*>(curSurface.get())->
|
|
|
|
GetColormapAndVisual(&colormap, &visual);
|
|
|
|
if (visual != mWsInfo.visual || colormap != mWsInfo.colormap) {
|
|
|
|
mWsInfo.visual = visual;
|
|
|
|
mWsInfo.colormap = colormap;
|
2010-09-21 20:03:16 +04:00
|
|
|
needWindowUpdate = true;
|
2010-09-15 20:02:49 +04:00
|
|
|
}
|
|
|
|
}
|
2010-10-25 21:57:13 +04:00
|
|
|
#endif // MOZ_X11
|
|
|
|
#ifdef XP_WIN
|
2013-10-24 00:34:46 +04:00
|
|
|
HDC dc = nullptr;
|
2010-10-25 21:57:13 +04:00
|
|
|
|
|
|
|
if (curSurface) {
|
2011-02-17 01:43:30 +03:00
|
|
|
if (!SharedDIBSurface::IsSharedDIBSurface(curSurface))
|
2016-12-03 00:46:53 +03:00
|
|
|
MOZ_CRASH("Expected SharedDIBSurface!");
|
2010-10-25 21:57:13 +04:00
|
|
|
|
|
|
|
SharedDIBSurface* dibsurf = static_cast<SharedDIBSurface*>(curSurface.get());
|
|
|
|
dc = dibsurf->GetHDC();
|
|
|
|
}
|
|
|
|
if (mWindow.window != dc) {
|
|
|
|
mWindow.window = dc;
|
|
|
|
needWindowUpdate = true;
|
|
|
|
}
|
|
|
|
#endif // XP_WIN
|
|
|
|
|
2010-09-15 20:02:49 +04:00
|
|
|
if (!needWindowUpdate) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-06-30 20:46:25 +04:00
|
|
|
#ifndef XP_MACOSX
|
|
|
|
// Adjusting the window isn't needed for OSX
|
2010-10-27 17:09:37 +04:00
|
|
|
#ifndef XP_WIN
|
|
|
|
// On Windows, we translate the device context, in order for the window
|
|
|
|
// origin to be correct.
|
2010-09-15 20:02:49 +04:00
|
|
|
mWindow.x = mWindow.y = 0;
|
2010-10-27 17:09:37 +04:00
|
|
|
#endif
|
|
|
|
|
2010-11-05 17:40:55 +03:00
|
|
|
if (IsVisible()) {
|
|
|
|
// The clip rect is relative to drawable top-left.
|
|
|
|
nsIntRect clipRect;
|
2010-09-15 20:02:49 +04:00
|
|
|
|
2010-11-05 17:40:55 +03:00
|
|
|
// Don't ask the plugin to draw outside the drawable. The clip rect
|
|
|
|
// is in plugin coordinates, not window coordinates.
|
|
|
|
// This also ensures that the unsigned clip rectangle offsets won't be -ve.
|
|
|
|
clipRect.SetRect(0, 0, mWindow.width, mWindow.height);
|
|
|
|
|
|
|
|
mWindow.clipRect.left = 0;
|
|
|
|
mWindow.clipRect.top = 0;
|
|
|
|
mWindow.clipRect.right = clipRect.XMost();
|
|
|
|
mWindow.clipRect.bottom = clipRect.YMost();
|
|
|
|
}
|
2011-06-30 20:46:25 +04:00
|
|
|
#endif // XP_MACOSX
|
2010-09-15 20:02:49 +04:00
|
|
|
|
2010-10-25 21:57:13 +04:00
|
|
|
#ifdef XP_WIN
|
|
|
|
// Windowless plugins on Windows need a WM_WINDOWPOSCHANGED event to update
|
|
|
|
// their location... or at least Flash does: Silverlight uses the
|
|
|
|
// window.x/y passed to NPP_SetWindow
|
|
|
|
|
|
|
|
if (mPluginIface->event) {
|
2017-10-17 20:04:51 +03:00
|
|
|
// width and height are stored as units, but narrow to ints here
|
|
|
|
MOZ_RELEASE_ASSERT(mWindow.width <= INT_MAX);
|
|
|
|
MOZ_RELEASE_ASSERT(mWindow.height <= INT_MAX);
|
|
|
|
|
2010-10-25 21:57:13 +04:00
|
|
|
WINDOWPOS winpos = {
|
|
|
|
0, 0,
|
2010-10-27 17:09:37 +04:00
|
|
|
mWindow.x, mWindow.y,
|
2017-10-17 20:04:51 +03:00
|
|
|
(int32_t)mWindow.width, (int32_t)mWindow.height,
|
2011-01-04 06:56:05 +03:00
|
|
|
0
|
2010-10-25 21:57:13 +04:00
|
|
|
};
|
|
|
|
NPEvent pluginEvent = {
|
|
|
|
WM_WINDOWPOSCHANGED, 0,
|
|
|
|
(LPARAM) &winpos
|
|
|
|
};
|
|
|
|
mPluginIface->event(&mData, &pluginEvent);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2011-02-17 01:43:31 +03:00
|
|
|
PLUGIN_LOG_DEBUG(
|
|
|
|
("[InstanceChild][%p] UpdateWindow w=<x=%d,y=%d, w=%d,h=%d>, clip=<l=%d,t=%d,r=%d,b=%d>",
|
|
|
|
this, mWindow.x, mWindow.y, mWindow.width, mWindow.height,
|
|
|
|
mWindow.clipRect.left, mWindow.clipRect.top, mWindow.clipRect.right, mWindow.clipRect.bottom));
|
|
|
|
|
2010-09-15 20:02:49 +04:00
|
|
|
if (mPluginIface->setwindow) {
|
|
|
|
mPluginIface->setwindow(&mData, &mWindow);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PluginInstanceChild::PaintRectToPlatformSurface(const nsIntRect& aRect,
|
|
|
|
gfxASurface* aSurface)
|
|
|
|
{
|
|
|
|
UpdateWindowAttributes();
|
2011-01-04 06:56:05 +03:00
|
|
|
|
2015-12-02 22:31:16 +03:00
|
|
|
// We should not send an async surface if we're using direct rendering.
|
|
|
|
MOZ_ASSERT(!IsUsingDirectDrawing());
|
|
|
|
|
2010-09-15 20:02:49 +04:00
|
|
|
#ifdef MOZ_X11
|
2011-01-04 06:56:05 +03:00
|
|
|
{
|
2014-01-23 22:26:40 +04:00
|
|
|
NS_ASSERTION(aSurface->GetType() == gfxSurfaceType::Xlib,
|
2011-01-04 06:56:05 +03:00
|
|
|
"Non supported platform surface type");
|
2010-10-25 21:57:13 +04:00
|
|
|
|
2011-01-04 06:56:05 +03:00
|
|
|
NPEvent pluginEvent;
|
|
|
|
XGraphicsExposeEvent& exposeEvent = pluginEvent.xgraphicsexpose;
|
|
|
|
exposeEvent.type = GraphicsExpose;
|
|
|
|
exposeEvent.display = mWsInfo.display;
|
|
|
|
exposeEvent.drawable = static_cast<gfxXlibSurface*>(aSurface)->XDrawable();
|
2018-02-19 23:15:23 +03:00
|
|
|
exposeEvent.x = aRect.x;
|
|
|
|
exposeEvent.y = aRect.y;
|
|
|
|
exposeEvent.width = aRect.width;
|
|
|
|
exposeEvent.height = aRect.height;
|
2011-01-04 06:56:05 +03:00
|
|
|
exposeEvent.count = 0;
|
|
|
|
// information not set:
|
|
|
|
exposeEvent.serial = 0;
|
|
|
|
exposeEvent.send_event = False;
|
|
|
|
exposeEvent.major_code = 0;
|
|
|
|
exposeEvent.minor_code = 0;
|
|
|
|
mPluginIface->event(&mData, reinterpret_cast<void*>(&exposeEvent));
|
|
|
|
}
|
|
|
|
#elif defined(XP_WIN)
|
2010-10-25 21:57:13 +04:00
|
|
|
NS_ASSERTION(SharedDIBSurface::IsSharedDIBSurface(aSurface),
|
|
|
|
"Expected (SharedDIB) image surface.");
|
|
|
|
|
2010-10-27 17:09:37 +04:00
|
|
|
// This rect is in the window coordinate space. aRect is in the plugin
|
|
|
|
// coordinate space.
|
2010-10-25 21:57:13 +04:00
|
|
|
RECT rect = {
|
2018-02-19 23:15:23 +03:00
|
|
|
mWindow.x + aRect.x,
|
|
|
|
mWindow.y + aRect.y,
|
2011-01-18 00:58:24 +03:00
|
|
|
mWindow.x + aRect.XMost(),
|
|
|
|
mWindow.y + aRect.YMost()
|
2010-10-25 21:57:13 +04:00
|
|
|
};
|
|
|
|
NPEvent paintEvent = {
|
|
|
|
WM_PAINT,
|
|
|
|
uintptr_t(mWindow.window),
|
2017-10-17 20:04:51 +03:00
|
|
|
intptr_t(&rect)
|
2010-10-25 21:57:13 +04:00
|
|
|
};
|
2010-10-27 17:09:37 +04:00
|
|
|
|
2013-10-24 00:34:46 +04:00
|
|
|
::SetViewportOrgEx((HDC) mWindow.window, -mWindow.x, -mWindow.y, nullptr);
|
|
|
|
::SelectClipRgn((HDC) mWindow.window, nullptr);
|
2011-01-18 00:58:24 +03:00
|
|
|
::IntersectClipRect((HDC) mWindow.window, rect.left, rect.top, rect.right, rect.bottom);
|
2010-10-25 21:57:13 +04:00
|
|
|
mPluginIface->event(&mData, reinterpret_cast<void*>(&paintEvent));
|
2011-01-04 06:56:05 +03:00
|
|
|
#else
|
2016-12-03 00:46:53 +03:00
|
|
|
MOZ_CRASH("Surface type not implemented.");
|
2010-09-15 20:02:49 +04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PluginInstanceChild::PaintRectToSurface(const nsIntRect& aRect,
|
|
|
|
gfxASurface* aSurface,
|
2015-09-25 04:32:40 +03:00
|
|
|
const Color& aColor)
|
2010-09-15 20:02:49 +04:00
|
|
|
{
|
|
|
|
// Render using temporary X surface, with copy to image surface
|
|
|
|
nsIntRect plPaintRect(aRect);
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<gfxASurface> renderSurface = aSurface;
|
2010-09-15 20:02:49 +04:00
|
|
|
#ifdef MOZ_X11
|
2015-08-12 18:00:25 +03:00
|
|
|
if (mIsTransparent && (GetQuirks() & QUIRK_FLASH_EXPOSE_COORD_TRANSLATION)) {
|
2010-09-15 20:02:49 +04:00
|
|
|
// Work around a bug in Flash up to 10.1 d51 at least, where expose event
|
|
|
|
// top left coordinates within the plugin-rect and not at the drawable
|
|
|
|
// origin are misinterpreted. (We can move the top left coordinate
|
|
|
|
// provided it is within the clipRect.), see bug 574583
|
|
|
|
plPaintRect.SetRect(0, 0, aRect.XMost(), aRect.YMost());
|
|
|
|
}
|
2011-06-02 06:27:51 +04:00
|
|
|
if (mHelperSurface) {
|
2010-09-15 20:02:49 +04:00
|
|
|
// On X11 we can paint to non Xlib surface only with HelperSurface
|
|
|
|
renderSurface = mHelperSurface;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2011-09-14 11:51:24 +04:00
|
|
|
if (mIsTransparent && !CanPaintOnBackground()) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTarget> dt = CreateDrawTargetForSurface(renderSurface);
|
2018-02-19 23:15:23 +03:00
|
|
|
gfx::Rect rect(plPaintRect.x, plPaintRect.y,
|
|
|
|
plPaintRect.width, plPaintRect.height);
|
2014-06-30 06:00:10 +04:00
|
|
|
// Moz2D treats OP_SOURCE operations as unbounded, so we need to
|
|
|
|
// clip to the rect that we want to fill:
|
|
|
|
dt->PushClipRect(rect);
|
2015-09-25 04:32:40 +03:00
|
|
|
dt->FillRect(rect, ColorPattern(aColor), // aColor is already a device color
|
2014-06-30 06:00:10 +04:00
|
|
|
DrawOptions(1.f, CompositionOp::OP_SOURCE));
|
|
|
|
dt->PopClip();
|
|
|
|
dt->Flush();
|
2010-09-15 20:02:49 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
PaintRectToPlatformSurface(plPaintRect, renderSurface);
|
|
|
|
|
|
|
|
if (renderSurface != aSurface) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTarget> dt;
|
2015-08-26 01:28:03 +03:00
|
|
|
if (aSurface == mCurrentSurface &&
|
|
|
|
aSurface->GetType() == gfxSurfaceType::Image &&
|
|
|
|
aSurface->GetSurfaceFormat() == SurfaceFormat::B8G8R8X8) {
|
|
|
|
gfxImageSurface* imageSurface = static_cast<gfxImageSurface*>(aSurface);
|
|
|
|
// Bug 1196927 - Reinterpret target surface as BGRA to fill alpha with opaque.
|
|
|
|
// Certain backends (i.e. Skia) may not truly support BGRX formats, so they must
|
|
|
|
// be emulated by filling the alpha channel opaque as if it was BGRA data. Cairo
|
|
|
|
// leaves the alpha zeroed out for BGRX, so we cause Cairo to fill it as opaque
|
|
|
|
// by handling the copy target as a BGRA surface.
|
|
|
|
dt = Factory::CreateDrawTargetForData(BackendType::CAIRO,
|
|
|
|
imageSurface->Data(),
|
|
|
|
imageSurface->GetSize(),
|
|
|
|
imageSurface->Stride(),
|
|
|
|
SurfaceFormat::B8G8R8A8);
|
|
|
|
} else {
|
2010-09-15 20:02:49 +04:00
|
|
|
// Copy helper surface content to target
|
2015-08-26 01:28:03 +03:00
|
|
|
dt = CreateDrawTargetForSurface(aSurface);
|
|
|
|
}
|
2016-09-15 17:36:21 +03:00
|
|
|
if (dt && dt->IsValid()) {
|
|
|
|
RefPtr<SourceSurface> surface =
|
|
|
|
gfxPlatform::GetSourceSurfaceForSurface(dt, renderSurface);
|
|
|
|
dt->CopySurface(surface, aRect, aRect.TopLeft());
|
|
|
|
} else {
|
|
|
|
gfxWarning() << "PluginInstanceChild::PaintRectToSurface failure";
|
|
|
|
}
|
2010-09-15 20:02:49 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PluginInstanceChild::PaintRectWithAlphaExtraction(const nsIntRect& aRect,
|
|
|
|
gfxASurface* aSurface)
|
|
|
|
{
|
2015-02-10 01:34:50 +03:00
|
|
|
MOZ_ASSERT(aSurface->GetContentType() == gfxContentType::COLOR_ALPHA,
|
|
|
|
"Refusing to pointlessly recover alpha");
|
2011-02-17 01:43:30 +03:00
|
|
|
|
|
|
|
nsIntRect rect(aRect);
|
|
|
|
// If |aSurface| can be used to paint and can have alpha values
|
|
|
|
// recovered directly to it, do that to save a tmp surface and
|
|
|
|
// copy.
|
|
|
|
bool useSurfaceSubimageForBlack = false;
|
2014-01-23 22:26:40 +04:00
|
|
|
if (gfxSurfaceType::Image == aSurface->GetType()) {
|
2011-02-17 01:43:30 +03:00
|
|
|
gfxImageSurface* surfaceAsImage =
|
|
|
|
static_cast<gfxImageSurface*>(aSurface);
|
|
|
|
useSurfaceSubimageForBlack =
|
2016-01-08 07:57:38 +03:00
|
|
|
(surfaceAsImage->Format() == SurfaceFormat::A8R8G8B8_UINT32);
|
2011-02-17 01:43:30 +03:00
|
|
|
// If we're going to use a subimage, nudge the rect so that we
|
|
|
|
// can use optimal alpha recovery. If we're not using a
|
|
|
|
// subimage, the temporaries should automatically get
|
|
|
|
// fast-path alpha recovery so we don't need to do anything.
|
|
|
|
if (useSurfaceSubimageForBlack) {
|
|
|
|
rect =
|
|
|
|
gfxAlphaRecovery::AlignRectForSubimageRecovery(aRect,
|
|
|
|
surfaceAsImage);
|
2010-09-15 20:02:49 +04:00
|
|
|
}
|
|
|
|
}
|
2011-02-17 01:43:30 +03:00
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<gfxImageSurface> whiteImage;
|
|
|
|
RefPtr<gfxImageSurface> blackImage;
|
2018-02-19 23:15:23 +03:00
|
|
|
gfxRect targetRect(rect.x, rect.y, rect.width, rect.height);
|
|
|
|
IntSize targetSize(rect.width, rect.height);
|
2011-04-19 07:07:21 +04:00
|
|
|
gfxPoint deviceOffset = -targetRect.TopLeft();
|
2011-02-17 01:43:30 +03:00
|
|
|
|
|
|
|
// We always use a temporary "white image"
|
2016-01-08 07:57:38 +03:00
|
|
|
whiteImage = new gfxImageSurface(targetSize, SurfaceFormat::X8R8G8B8_UINT32);
|
2011-02-17 01:43:31 +03:00
|
|
|
if (whiteImage->CairoStatus()) {
|
|
|
|
return;
|
|
|
|
}
|
2011-02-17 01:43:30 +03:00
|
|
|
|
|
|
|
#ifdef XP_WIN
|
|
|
|
// On windows, we need an HDC and so can't paint directly to
|
|
|
|
// vanilla image surfaces. Bifurcate this painting code so that
|
|
|
|
// we don't accidentally attempt that.
|
|
|
|
if (!SharedDIBSurface::IsSharedDIBSurface(aSurface))
|
2016-12-03 00:46:53 +03:00
|
|
|
MOZ_CRASH("Expected SharedDIBSurface!");
|
2011-02-17 01:43:30 +03:00
|
|
|
|
|
|
|
// Paint the plugin directly onto the target, with a white
|
|
|
|
// background and copy the result
|
2015-09-25 04:32:40 +03:00
|
|
|
PaintRectToSurface(rect, aSurface, Color(1.f, 1.f, 1.f));
|
2011-02-17 01:43:30 +03:00
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTarget> dt = CreateDrawTargetForSurface(whiteImage);
|
|
|
|
RefPtr<SourceSurface> surface =
|
2014-06-06 13:24:24 +04:00
|
|
|
gfxPlatform::GetSourceSurfaceForSurface(dt, aSurface);
|
2015-04-21 18:22:30 +03:00
|
|
|
dt->CopySurface(surface, rect, IntPoint());
|
2010-09-15 20:02:49 +04:00
|
|
|
}
|
|
|
|
|
2011-02-17 01:43:30 +03:00
|
|
|
// Paint the plugin directly onto the target, with a black
|
|
|
|
// background
|
2015-09-25 04:32:40 +03:00
|
|
|
PaintRectToSurface(rect, aSurface, Color(0.f, 0.f, 0.f));
|
2010-09-15 20:02:49 +04:00
|
|
|
|
2011-02-17 01:43:30 +03:00
|
|
|
// Don't copy the result, just extract a subimage so that we can
|
|
|
|
// recover alpha directly into the target
|
|
|
|
gfxImageSurface *image = static_cast<gfxImageSurface*>(aSurface);
|
|
|
|
blackImage = image->GetSubimage(targetRect);
|
2010-09-15 20:02:49 +04:00
|
|
|
|
2011-02-17 01:43:30 +03:00
|
|
|
#else
|
|
|
|
// Paint onto white background
|
2010-09-15 20:02:49 +04:00
|
|
|
whiteImage->SetDeviceOffset(deviceOffset);
|
2015-09-25 04:32:40 +03:00
|
|
|
PaintRectToSurface(rect, whiteImage, Color(1.f, 1.f, 1.f));
|
2011-02-17 01:43:30 +03:00
|
|
|
|
|
|
|
if (useSurfaceSubimageForBlack) {
|
|
|
|
gfxImageSurface *surface = static_cast<gfxImageSurface*>(aSurface);
|
|
|
|
blackImage = surface->GetSubimage(targetRect);
|
|
|
|
} else {
|
|
|
|
blackImage = new gfxImageSurface(targetSize,
|
2016-01-08 07:57:38 +03:00
|
|
|
SurfaceFormat::A8R8G8B8_UINT32);
|
2011-02-17 01:43:30 +03:00
|
|
|
}
|
2010-09-15 20:02:49 +04:00
|
|
|
|
2011-02-17 01:43:30 +03:00
|
|
|
// Paint onto black background
|
|
|
|
blackImage->SetDeviceOffset(deviceOffset);
|
2015-09-25 04:32:40 +03:00
|
|
|
PaintRectToSurface(rect, blackImage, Color(0.f, 0.f, 0.f));
|
2011-02-17 01:43:30 +03:00
|
|
|
#endif
|
|
|
|
|
2015-02-10 01:34:50 +03:00
|
|
|
MOZ_ASSERT(whiteImage && blackImage, "Didn't paint enough!");
|
2011-02-17 01:43:30 +03:00
|
|
|
|
|
|
|
// Extract alpha from black and white image and store to black
|
|
|
|
// image
|
|
|
|
if (!gfxAlphaRecovery::RecoverAlpha(blackImage, whiteImage)) {
|
2010-09-15 20:02:49 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-02-17 01:43:30 +03:00
|
|
|
// If we had to use a temporary black surface, copy the pixels
|
|
|
|
// with alpha back to the target
|
|
|
|
if (!useSurfaceSubimageForBlack) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTarget> dt = CreateDrawTargetForSurface(aSurface);
|
|
|
|
RefPtr<SourceSurface> surface =
|
2014-06-06 13:24:24 +04:00
|
|
|
gfxPlatform::GetSourceSurfaceForSurface(dt, blackImage);
|
|
|
|
dt->CopySurface(surface,
|
2018-02-19 23:15:23 +03:00
|
|
|
IntRect(0, 0, rect.width, rect.height),
|
2015-04-21 18:22:30 +03:00
|
|
|
rect.TopLeft());
|
2010-09-15 20:02:49 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-17 01:43:31 +03:00
|
|
|
bool
|
|
|
|
PluginInstanceChild::CanPaintOnBackground()
|
|
|
|
{
|
|
|
|
return (mBackground &&
|
|
|
|
mCurrentSurface &&
|
|
|
|
mCurrentSurface->GetSize() == mBackground->GetSize());
|
|
|
|
}
|
|
|
|
|
2010-09-21 20:03:16 +04:00
|
|
|
bool
|
2010-09-15 20:02:49 +04:00
|
|
|
PluginInstanceChild::ShowPluginFrame()
|
|
|
|
{
|
2011-02-17 01:43:31 +03:00
|
|
|
// mLayersRendering can be false if we somehow get here without
|
|
|
|
// receiving AsyncSetWindow() first. mPendingPluginCall is our
|
|
|
|
// re-entrancy guard; we can't paint while nested inside another
|
|
|
|
// paint.
|
|
|
|
if (!mLayersRendering || mPendingPluginCall) {
|
2010-09-21 20:03:16 +04:00
|
|
|
return false;
|
2010-09-15 20:02:49 +04:00
|
|
|
}
|
|
|
|
|
2015-12-02 22:31:16 +03:00
|
|
|
// We should not attempt to asynchronously show the plugin if we're using
|
|
|
|
// direct rendering.
|
|
|
|
MOZ_ASSERT(!IsUsingDirectDrawing());
|
|
|
|
|
2011-01-14 17:37:20 +03:00
|
|
|
AutoRestore<bool> pending(mPendingPluginCall);
|
|
|
|
mPendingPluginCall = true;
|
|
|
|
|
2011-06-30 20:46:25 +04:00
|
|
|
bool temporarilyMakeVisible = !IsVisible() && !mHasPainted;
|
|
|
|
if (temporarilyMakeVisible && mWindow.width && mWindow.height) {
|
|
|
|
mWindow.clipRect.right = mWindow.width;
|
|
|
|
mWindow.clipRect.bottom = mWindow.height;
|
|
|
|
} else if (!IsVisible()) {
|
|
|
|
// If we're not visible, don't bother painting a <0,0,0,0>
|
|
|
|
// rect. If we're eventually made visible, the visibility
|
|
|
|
// change will invalidate our window.
|
|
|
|
ClearCurrentSurface();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!EnsureCurrentBuffer()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-07-12 18:31:18 +04:00
|
|
|
#ifdef MOZ_WIDGET_COCOA
|
2011-05-20 01:08:14 +04:00
|
|
|
// We can't use the thebes code with CoreAnimation so we will
|
|
|
|
// take a different code path.
|
|
|
|
if (mDrawingModel == NPDrawingModelCoreAnimation ||
|
|
|
|
mDrawingModel == NPDrawingModelInvalidatingCoreAnimation ||
|
|
|
|
mDrawingModel == NPDrawingModelCoreGraphics) {
|
|
|
|
|
2011-06-30 20:46:25 +04:00
|
|
|
if (!IsVisible()) {
|
|
|
|
return true;
|
2011-05-20 01:08:14 +04:00
|
|
|
}
|
|
|
|
|
2011-07-12 18:31:18 +04:00
|
|
|
if (!mDoubleBufferCARenderer.HasFrontSurface()) {
|
|
|
|
NS_ERROR("CARenderer not initialized for rendering");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-05-20 01:08:14 +04:00
|
|
|
// Clear accRect here to be able to pass
|
|
|
|
// test_invalidate_during_plugin_paint test
|
|
|
|
nsIntRect rect = mAccumulatedInvalidRect;
|
|
|
|
mAccumulatedInvalidRect.SetEmpty();
|
|
|
|
|
|
|
|
// Fix up old invalidations that might have been made when our
|
|
|
|
// surface was a different size
|
|
|
|
rect.IntersectRect(rect,
|
2017-07-06 15:00:35 +03:00
|
|
|
nsIntRect(0, 0,
|
|
|
|
mDoubleBufferCARenderer.GetFrontSurfaceWidth(),
|
2011-07-12 18:31:18 +04:00
|
|
|
mDoubleBufferCARenderer.GetFrontSurfaceHeight()));
|
2011-05-20 01:08:14 +04:00
|
|
|
|
|
|
|
if (mDrawingModel == NPDrawingModelCoreGraphics) {
|
|
|
|
mozilla::plugins::PluginUtilsOSX::Repaint(mCGLayer, rect);
|
|
|
|
}
|
|
|
|
|
2011-07-12 18:31:18 +04:00
|
|
|
mDoubleBufferCARenderer.Render();
|
2011-05-20 01:08:14 +04:00
|
|
|
|
|
|
|
NPRect r = { (uint16_t)rect.y, (uint16_t)rect.x,
|
|
|
|
(uint16_t)rect.YMost(), (uint16_t)rect.XMost() };
|
|
|
|
SurfaceDescriptor currSurf;
|
2012-10-02 23:48:05 +04:00
|
|
|
currSurf = IOSurfaceDescriptor(mDoubleBufferCARenderer.GetFrontSurfaceID(),
|
|
|
|
mDoubleBufferCARenderer.GetContentsScaleFactor());
|
2011-05-20 01:08:14 +04:00
|
|
|
|
2011-06-30 20:46:25 +04:00
|
|
|
mHasPainted = true;
|
|
|
|
|
2011-05-20 01:08:14 +04:00
|
|
|
SurfaceDescriptor returnSurf;
|
|
|
|
|
|
|
|
if (!SendShow(r, currSurf, &returnSurf)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-07-12 18:31:18 +04:00
|
|
|
SwapSurfaces();
|
2011-05-20 01:08:14 +04:00
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
NS_ERROR("Unsupported drawing model for async layer rendering");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-08-07 11:06:29 +04:00
|
|
|
NS_ASSERTION(mWindow.width == uint32_t(mWindow.clipRect.right - mWindow.clipRect.left) &&
|
|
|
|
mWindow.height == uint32_t(mWindow.clipRect.bottom - mWindow.clipRect.top),
|
2011-02-17 01:43:31 +03:00
|
|
|
"Clip rect should be same size as window when using layers");
|
2010-09-15 20:02:49 +04:00
|
|
|
|
2010-09-21 20:03:16 +04:00
|
|
|
// Clear accRect here to be able to pass
|
|
|
|
// test_invalidate_during_plugin_paint test
|
2010-09-15 20:02:49 +04:00
|
|
|
nsIntRect rect = mAccumulatedInvalidRect;
|
2011-04-19 07:07:23 +04:00
|
|
|
mAccumulatedInvalidRect.SetEmpty();
|
2010-09-15 20:02:49 +04:00
|
|
|
|
2011-02-17 01:43:31 +03:00
|
|
|
// Fix up old invalidations that might have been made when our
|
|
|
|
// surface was a different size
|
2015-09-23 21:49:05 +03:00
|
|
|
IntSize surfaceSize = mCurrentSurface->GetSize();
|
2011-02-17 01:43:31 +03:00
|
|
|
rect.IntersectRect(rect,
|
|
|
|
nsIntRect(0, 0, surfaceSize.width, surfaceSize.height));
|
|
|
|
|
2010-10-27 17:09:15 +04:00
|
|
|
if (!ReadbackDifferenceRect(rect)) {
|
2011-02-17 01:43:31 +03:00
|
|
|
// We couldn't read back the pixels that differ between the
|
|
|
|
// current surface and last, so we have to invalidate the
|
|
|
|
// entire window.
|
2010-09-15 20:02:49 +04:00
|
|
|
rect.SetRect(0, 0, mWindow.width, mWindow.height);
|
|
|
|
}
|
|
|
|
|
2011-02-17 01:43:31 +03:00
|
|
|
bool haveTransparentPixels =
|
2014-01-23 22:26:40 +04:00
|
|
|
gfxContentType::COLOR_ALPHA == mCurrentSurface->GetContentType();
|
2011-02-17 01:43:31 +03:00
|
|
|
PLUGIN_LOG_DEBUG(
|
|
|
|
("[InstanceChild][%p] Painting%s <x=%d,y=%d, w=%d,h=%d> on surface <w=%d,h=%d>",
|
|
|
|
this, haveTransparentPixels ? " with alpha" : "",
|
2018-02-19 23:15:23 +03:00
|
|
|
rect.x, rect.y, rect.width, rect.height,
|
2011-02-17 01:43:31 +03:00
|
|
|
mCurrentSurface->GetSize().width, mCurrentSurface->GetSize().height));
|
|
|
|
|
|
|
|
if (CanPaintOnBackground()) {
|
|
|
|
PLUGIN_LOG_DEBUG((" (on background)"));
|
|
|
|
// Source the background pixels ...
|
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<gfxASurface> surface =
|
2014-07-04 06:36:21 +04:00
|
|
|
mHelperSurface ? mHelperSurface : mCurrentSurface;
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTarget> dt = CreateDrawTargetForSurface(surface);
|
|
|
|
RefPtr<SourceSurface> backgroundSurface =
|
2014-07-04 06:36:21 +04:00
|
|
|
gfxPlatform::GetSourceSurfaceForSurface(dt, mBackground);
|
2015-04-21 18:22:30 +03:00
|
|
|
dt->CopySurface(backgroundSurface, rect, rect.TopLeft());
|
2011-02-17 01:43:31 +03:00
|
|
|
}
|
|
|
|
// ... and hand off to the plugin
|
|
|
|
// BEWARE: mBackground may die during this call
|
2015-09-25 04:32:40 +03:00
|
|
|
PaintRectToSurface(rect, mCurrentSurface, Color());
|
2011-02-17 01:43:31 +03:00
|
|
|
} else if (!temporarilyMakeVisible && mDoAlphaExtraction) {
|
|
|
|
// We don't want to pay the expense of alpha extraction for
|
|
|
|
// phony paints.
|
2011-02-17 01:43:31 +03:00
|
|
|
PLUGIN_LOG_DEBUG((" (with alpha recovery)"));
|
2010-09-15 20:02:49 +04:00
|
|
|
PaintRectWithAlphaExtraction(rect, mCurrentSurface);
|
|
|
|
} else {
|
2011-02-17 01:43:31 +03:00
|
|
|
PLUGIN_LOG_DEBUG((" (onto opaque surface)"));
|
2011-02-17 01:43:31 +03:00
|
|
|
|
|
|
|
// If we're on a platform that needs helper surfaces for
|
|
|
|
// plugins, and we're forcing a throwaway paint of a
|
|
|
|
// wmode=transparent plugin, then make sure to use the helper
|
|
|
|
// surface here.
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<gfxASurface> target =
|
2011-02-17 01:43:31 +03:00
|
|
|
(temporarilyMakeVisible && mHelperSurface) ?
|
|
|
|
mHelperSurface : mCurrentSurface;
|
|
|
|
|
2015-09-25 04:32:40 +03:00
|
|
|
PaintRectToSurface(rect, target, Color());
|
2010-09-15 20:02:49 +04:00
|
|
|
}
|
2011-01-04 06:56:05 +03:00
|
|
|
mHasPainted = true;
|
2010-09-15 20:02:49 +04:00
|
|
|
|
2011-02-17 01:43:31 +03:00
|
|
|
if (temporarilyMakeVisible) {
|
|
|
|
mWindow.clipRect.right = mWindow.clipRect.bottom = 0;
|
|
|
|
|
|
|
|
PLUGIN_LOG_DEBUG(
|
|
|
|
("[InstanceChild][%p] Undoing temporary clipping w=<x=%d,y=%d, w=%d,h=%d>, clip=<l=%d,t=%d,r=%d,b=%d>",
|
|
|
|
this, mWindow.x, mWindow.y, mWindow.width, mWindow.height,
|
|
|
|
mWindow.clipRect.left, mWindow.clipRect.top, mWindow.clipRect.right, mWindow.clipRect.bottom));
|
|
|
|
|
|
|
|
if (mPluginIface->setwindow) {
|
|
|
|
mPluginIface->setwindow(&mData, &mWindow);
|
|
|
|
}
|
2011-02-17 01:43:31 +03:00
|
|
|
|
|
|
|
// Skip forwarding the results of the phony paint to the
|
|
|
|
// browser. We may have painted a transparent plugin using
|
|
|
|
// the opaque-plugin path, which can result in wrong pixels.
|
|
|
|
// We also don't want to pay the expense of forwarding the
|
|
|
|
// surface for plugins that might really be invisible.
|
|
|
|
mAccumulatedInvalidRect.SetRect(0, 0, mWindow.width, mWindow.height);
|
|
|
|
return true;
|
2011-02-17 01:43:31 +03:00
|
|
|
}
|
|
|
|
|
2018-02-19 23:15:23 +03:00
|
|
|
NPRect r = { (uint16_t)rect.y, (uint16_t)rect.x,
|
2010-11-11 11:20:03 +03:00
|
|
|
(uint16_t)rect.YMost(), (uint16_t)rect.XMost() };
|
2010-09-15 20:02:49 +04:00
|
|
|
SurfaceDescriptor currSurf;
|
|
|
|
#ifdef MOZ_X11
|
2014-01-23 22:26:40 +04:00
|
|
|
if (mCurrentSurface->GetType() == gfxSurfaceType::Xlib) {
|
2010-09-15 20:02:49 +04:00
|
|
|
gfxXlibSurface *xsurf = static_cast<gfxXlibSurface*>(mCurrentSurface.get());
|
2012-01-10 14:54:38 +04:00
|
|
|
currSurf = SurfaceDescriptorX11(xsurf);
|
2010-09-15 20:02:49 +04:00
|
|
|
// Need to sync all pending x-paint requests
|
|
|
|
// before giving drawable to another process
|
|
|
|
XSync(mWsInfo.display, False);
|
|
|
|
} else
|
2010-10-25 21:57:13 +04:00
|
|
|
#endif
|
|
|
|
#ifdef XP_WIN
|
|
|
|
if (SharedDIBSurface::IsSharedDIBSurface(mCurrentSurface)) {
|
|
|
|
SharedDIBSurface* s = static_cast<SharedDIBSurface*>(mCurrentSurface.get());
|
2011-01-28 01:37:00 +03:00
|
|
|
if (!mCurrentSurfaceActor) {
|
2013-10-24 00:34:46 +04:00
|
|
|
base::SharedMemoryHandle handle = nullptr;
|
2015-04-01 11:40:35 +03:00
|
|
|
s->ShareToProcess(OtherPid(), &handle);
|
2011-01-28 01:37:00 +03:00
|
|
|
|
|
|
|
mCurrentSurfaceActor =
|
|
|
|
SendPPluginSurfaceConstructor(handle,
|
|
|
|
mCurrentSurface->GetSize(),
|
2011-02-17 01:43:31 +03:00
|
|
|
haveTransparentPixels);
|
2011-01-28 01:37:00 +03:00
|
|
|
}
|
|
|
|
currSurf = mCurrentSurfaceActor;
|
2010-10-25 21:57:13 +04:00
|
|
|
s->Flush();
|
|
|
|
} else
|
2010-09-15 20:02:49 +04:00
|
|
|
#endif
|
|
|
|
if (gfxSharedImageSurface::IsSharedImage(mCurrentSurface)) {
|
|
|
|
currSurf = static_cast<gfxSharedImageSurface*>(mCurrentSurface.get())->GetShmem();
|
|
|
|
} else {
|
2016-12-03 00:46:53 +03:00
|
|
|
MOZ_CRASH("Surface type is not remotable");
|
2010-09-21 20:03:16 +04:00
|
|
|
return false;
|
2010-09-15 20:02:49 +04:00
|
|
|
}
|
2010-10-14 22:14:23 +04:00
|
|
|
|
|
|
|
// Unused, except to possibly return a shmem to us
|
|
|
|
SurfaceDescriptor returnSurf;
|
|
|
|
|
|
|
|
if (!SendShow(r, currSurf, &returnSurf)) {
|
2010-09-21 20:03:16 +04:00
|
|
|
return false;
|
2010-09-15 20:02:49 +04:00
|
|
|
}
|
|
|
|
|
2011-01-28 01:37:00 +03:00
|
|
|
SwapSurfaces();
|
2010-09-15 20:02:49 +04:00
|
|
|
mSurfaceDifferenceRect = rect;
|
2010-09-21 20:03:16 +04:00
|
|
|
return true;
|
2010-09-15 20:02:49 +04:00
|
|
|
}
|
|
|
|
|
2010-10-27 17:09:15 +04:00
|
|
|
bool
|
|
|
|
PluginInstanceChild::ReadbackDifferenceRect(const nsIntRect& rect)
|
|
|
|
{
|
|
|
|
if (!mBackSurface)
|
|
|
|
return false;
|
|
|
|
|
2010-12-10 22:32:52 +03:00
|
|
|
// We can read safely from XSurface,SharedDIBSurface and Unsafe SharedMemory,
|
|
|
|
// because PluginHost is not able to modify that surface
|
2010-10-27 17:09:15 +04:00
|
|
|
#if defined(MOZ_X11)
|
2014-01-23 22:26:40 +04:00
|
|
|
if (mBackSurface->GetType() != gfxSurfaceType::Xlib &&
|
2010-12-10 22:32:52 +03:00
|
|
|
!gfxSharedImageSurface::IsSharedImage(mBackSurface))
|
2010-10-27 17:09:15 +04:00
|
|
|
return false;
|
|
|
|
#elif defined(XP_WIN)
|
|
|
|
if (!SharedDIBSurface::IsSharedDIBSurface(mBackSurface))
|
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
|
2015-06-01 05:39:16 +03:00
|
|
|
#if defined(MOZ_X11) || defined(XP_WIN)
|
2011-02-17 01:43:31 +03:00
|
|
|
if (mCurrentSurface->GetContentType() != mBackSurface->GetContentType())
|
|
|
|
return false;
|
|
|
|
|
2010-10-27 17:09:15 +04:00
|
|
|
if (mSurfaceDifferenceRect.IsEmpty())
|
|
|
|
return true;
|
|
|
|
|
2011-02-17 01:43:31 +03:00
|
|
|
PLUGIN_LOG_DEBUG(
|
|
|
|
("[InstanceChild][%p] Reading back part of <x=%d,y=%d, w=%d,h=%d>",
|
2018-02-19 23:15:23 +03:00
|
|
|
this, mSurfaceDifferenceRect.x, mSurfaceDifferenceRect.y,
|
|
|
|
mSurfaceDifferenceRect.width, mSurfaceDifferenceRect.height));
|
2011-02-17 01:43:31 +03:00
|
|
|
|
2010-10-27 17:09:15 +04:00
|
|
|
// Read back previous content
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTarget> dt = CreateDrawTargetForSurface(mCurrentSurface);
|
|
|
|
RefPtr<SourceSurface> source =
|
2014-07-04 06:36:21 +04:00
|
|
|
gfxPlatform::GetSourceSurfaceForSurface(dt, mBackSurface);
|
2010-10-27 17:09:15 +04:00
|
|
|
// Subtract from mSurfaceDifferenceRect area which is overlapping with rect
|
|
|
|
nsIntRegion result;
|
|
|
|
result.Sub(mSurfaceDifferenceRect, nsIntRegion(rect));
|
2016-01-19 04:20:44 +03:00
|
|
|
for (auto iter = result.RectIter(); !iter.Done(); iter.Next()) {
|
|
|
|
const nsIntRect& r = iter.Get();
|
|
|
|
dt->CopySurface(source, r, r.TopLeft());
|
2010-10-27 17:09:15 +04:00
|
|
|
}
|
2010-10-27 23:27:33 +04:00
|
|
|
|
|
|
|
return true;
|
2015-06-01 05:39:16 +03:00
|
|
|
#else
|
|
|
|
return false;
|
|
|
|
#endif
|
2010-10-27 17:09:15 +04:00
|
|
|
}
|
|
|
|
|
2010-09-15 20:02:49 +04:00
|
|
|
void
|
|
|
|
PluginInstanceChild::InvalidateRectDelayed(void)
|
|
|
|
{
|
2010-11-15 17:18:33 +03:00
|
|
|
if (!mCurrentInvalidateTask) {
|
2010-09-15 20:02:49 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
mCurrentInvalidateTask = nullptr;
|
2017-01-11 04:47:25 +03:00
|
|
|
|
|
|
|
// When this method is run asynchronously, we can end up switching to
|
|
|
|
// direct drawing before while we wait to run. In that case, bail.
|
|
|
|
if (IsUsingDirectDrawing()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-02-17 01:43:31 +03:00
|
|
|
if (mAccumulatedInvalidRect.IsEmpty()) {
|
2010-09-15 20:02:49 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ShowPluginFrame()) {
|
|
|
|
AsyncShowPluginFrame();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PluginInstanceChild::AsyncShowPluginFrame(void)
|
|
|
|
{
|
2011-02-17 01:43:31 +03:00
|
|
|
if (mCurrentInvalidateTask) {
|
2010-09-15 20:02:49 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-12-02 22:31:16 +03:00
|
|
|
// When the plugin is using direct surfaces to draw, it is not driving
|
|
|
|
// paints via paint events - it will drive painting via its own events
|
|
|
|
// and/or DidComposite callbacks.
|
|
|
|
if (IsUsingDirectDrawing()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-06-12 22:34:10 +03:00
|
|
|
mCurrentInvalidateTask = NewNonOwningCancelableRunnableMethod(
|
|
|
|
"plugins::PluginInstanceChild::InvalidateRectDelayed",
|
|
|
|
this,
|
|
|
|
&PluginInstanceChild::InvalidateRectDelayed);
|
2016-04-28 03:06:05 +03:00
|
|
|
RefPtr<Runnable> addrefedTask = mCurrentInvalidateTask;
|
|
|
|
MessageLoop::current()->PostTask(addrefedTask.forget());
|
2010-09-15 20:02:49 +04:00
|
|
|
}
|
|
|
|
|
2010-01-05 00:46:34 +03:00
|
|
|
void
|
|
|
|
PluginInstanceChild::InvalidateRect(NPRect* aInvalidRect)
|
2009-11-13 23:20:03 +03:00
|
|
|
{
|
|
|
|
NS_ASSERTION(aInvalidRect, "Null pointer!");
|
|
|
|
|
|
|
|
#ifdef OS_WIN
|
2009-12-02 00:05:26 +03:00
|
|
|
// Invalidate and draw locally for windowed plugins.
|
|
|
|
if (mWindow.type == NPWindowTypeWindow) {
|
|
|
|
NS_ASSERTION(IsWindow(mPluginWindowHWND), "Bad window?!");
|
|
|
|
RECT rect = { aInvalidRect->left, aInvalidRect->top,
|
|
|
|
aInvalidRect->right, aInvalidRect->bottom };
|
2010-01-05 01:41:34 +03:00
|
|
|
::InvalidateRect(mPluginWindowHWND, &rect, FALSE);
|
2010-01-05 00:46:34 +03:00
|
|
|
return;
|
2009-12-02 00:05:26 +03:00
|
|
|
}
|
2009-11-13 23:20:03 +03:00
|
|
|
#endif
|
2009-11-14 00:19:33 +03:00
|
|
|
|
2015-12-02 22:31:16 +03:00
|
|
|
if (IsUsingDirectDrawing()) {
|
|
|
|
NS_ASSERTION(false, "Should not call InvalidateRect() in direct surface mode!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-09-15 20:02:49 +04:00
|
|
|
if (mLayersRendering) {
|
|
|
|
nsIntRect r(aInvalidRect->left, aInvalidRect->top,
|
|
|
|
aInvalidRect->right - aInvalidRect->left,
|
|
|
|
aInvalidRect->bottom - aInvalidRect->top);
|
|
|
|
|
|
|
|
mAccumulatedInvalidRect.UnionRect(r, mAccumulatedInvalidRect);
|
|
|
|
// If we are able to paint and invalidate sent, then reset
|
|
|
|
// accumulated rectangle
|
|
|
|
AsyncShowPluginFrame();
|
|
|
|
return;
|
|
|
|
}
|
2011-05-20 01:08:14 +04:00
|
|
|
|
2011-02-17 01:43:31 +03:00
|
|
|
// If we were going to use layers rendering but it's not set up
|
|
|
|
// yet, and the plugin happens to call this first, we'll forward
|
|
|
|
// the invalidation to the browser. It's unclear whether
|
|
|
|
// non-layers plugins need this rect forwarded when their window
|
|
|
|
// width or height is 0, which it would be for layers plugins
|
|
|
|
// before their first SetWindow().
|
2010-01-05 00:46:34 +03:00
|
|
|
SendNPN_InvalidateRect(*aInvalidRect);
|
2009-11-13 23:20:03 +03:00
|
|
|
}
|
2010-01-15 23:35:57 +03:00
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2011-02-17 01:43:31 +03:00
|
|
|
PluginInstanceChild::RecvUpdateBackground(const SurfaceDescriptor& aBackground,
|
|
|
|
const nsIntRect& aRect)
|
|
|
|
{
|
2015-02-10 01:34:50 +03:00
|
|
|
MOZ_ASSERT(mIsTransparent, "Only transparent plugins use backgrounds");
|
2011-02-17 01:43:31 +03:00
|
|
|
|
|
|
|
if (!mBackground) {
|
|
|
|
// XXX refactor me
|
|
|
|
switch (aBackground.type()) {
|
|
|
|
#ifdef MOZ_X11
|
|
|
|
case SurfaceDescriptor::TSurfaceDescriptorX11: {
|
2012-01-10 14:54:35 +04:00
|
|
|
mBackground = aBackground.get_SurfaceDescriptorX11().OpenForeign();
|
2011-02-17 01:43:31 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
case SurfaceDescriptor::TShmem: {
|
|
|
|
mBackground = gfxSharedImageSurface::Open(aBackground.get_Shmem());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
2016-12-03 00:46:53 +03:00
|
|
|
MOZ_CRASH("Unexpected background surface descriptor");
|
2011-02-17 01:43:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!mBackground) {
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_FAIL_NO_REASON(this);
|
2011-02-17 01:43:31 +03:00
|
|
|
}
|
|
|
|
|
2015-09-23 21:49:05 +03:00
|
|
|
IntSize bgSize = mBackground->GetSize();
|
2011-02-17 01:43:31 +03:00
|
|
|
mAccumulatedInvalidRect.UnionRect(mAccumulatedInvalidRect,
|
|
|
|
nsIntRect(0, 0, bgSize.width, bgSize.height));
|
|
|
|
AsyncShowPluginFrame();
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2011-02-17 01:43:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// XXX refactor me
|
|
|
|
mAccumulatedInvalidRect.UnionRect(aRect, mAccumulatedInvalidRect);
|
|
|
|
|
2013-03-29 19:53:59 +04:00
|
|
|
// This must be asynchronous, because we may be nested within RPC messages
|
|
|
|
// which do not expect to receiving paint events.
|
|
|
|
AsyncShowPluginFrame();
|
2011-02-17 01:43:31 +03:00
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2011-02-17 01:43:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
PPluginBackgroundDestroyerChild*
|
2013-07-08 19:48:39 +04:00
|
|
|
PluginInstanceChild::AllocPPluginBackgroundDestroyerChild()
|
2011-02-17 01:43:31 +03:00
|
|
|
{
|
|
|
|
return new PluginBackgroundDestroyerChild();
|
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2011-02-17 01:43:31 +03:00
|
|
|
PluginInstanceChild::RecvPPluginBackgroundDestroyerConstructor(
|
|
|
|
PPluginBackgroundDestroyerChild* aActor)
|
|
|
|
{
|
|
|
|
// Our background changed, so we have to invalidate the area
|
|
|
|
// painted with the old background. If the background was
|
|
|
|
// destroyed because we have a new background, then we expect to
|
|
|
|
// be notified of that "soon", before processing the asynchronous
|
|
|
|
// invalidation here. If we're *not* getting a new background,
|
|
|
|
// our current front surface is stale and we want to repaint
|
|
|
|
// "soon" so that we can hand the browser back a surface with
|
|
|
|
// alpha values. (We should be notified of that invalidation soon
|
|
|
|
// too, but we don't assume that here.)
|
|
|
|
if (mBackground) {
|
2015-09-23 21:49:05 +03:00
|
|
|
IntSize bgsize = mBackground->GetSize();
|
2011-02-17 01:43:31 +03:00
|
|
|
mAccumulatedInvalidRect.UnionRect(
|
|
|
|
nsIntRect(0, 0, bgsize.width, bgsize.height), mAccumulatedInvalidRect);
|
|
|
|
|
|
|
|
// NB: we don't have to XSync here because only ShowPluginFrame()
|
|
|
|
// uses mBackground, and it always XSyncs after finishing.
|
2012-07-30 18:20:58 +04:00
|
|
|
mBackground = nullptr;
|
2011-02-17 01:43:31 +03:00
|
|
|
AsyncShowPluginFrame();
|
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
if (!PPluginBackgroundDestroyerChild::Send__delete__(aActor)) {
|
|
|
|
return IPC_FAIL_NO_REASON(this);
|
|
|
|
}
|
|
|
|
return IPC_OK();
|
2011-02-17 01:43:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2013-07-08 19:48:39 +04:00
|
|
|
PluginInstanceChild::DeallocPPluginBackgroundDestroyerChild(
|
2011-02-17 01:43:31 +03:00
|
|
|
PPluginBackgroundDestroyerChild* aActor)
|
|
|
|
{
|
|
|
|
delete aActor;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-01-20 06:13:24 +03:00
|
|
|
uint32_t
|
|
|
|
PluginInstanceChild::ScheduleTimer(uint32_t interval, bool repeat,
|
|
|
|
TimerFunc func)
|
|
|
|
{
|
2016-11-14 12:35:58 +03:00
|
|
|
auto* t = new ChildTimer(this, interval, repeat, func);
|
2010-01-20 06:13:24 +03:00
|
|
|
if (0 == t->ID()) {
|
|
|
|
delete t;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
mTimers.AppendElement(t);
|
|
|
|
return t->ID();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PluginInstanceChild::UnscheduleTimer(uint32_t id)
|
|
|
|
{
|
|
|
|
if (0 == id)
|
|
|
|
return;
|
|
|
|
|
2010-02-04 01:17:09 +03:00
|
|
|
mTimers.RemoveElement(id, ChildTimer::IDComparator());
|
2010-01-20 06:13:24 +03:00
|
|
|
}
|
|
|
|
|
2011-01-28 01:37:00 +03:00
|
|
|
void
|
|
|
|
PluginInstanceChild::SwapSurfaces()
|
2010-01-15 23:35:57 +03:00
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<gfxASurface> tmpsurf = mCurrentSurface;
|
2011-01-28 01:37:00 +03:00
|
|
|
#ifdef XP_WIN
|
|
|
|
PPluginSurfaceChild* tmpactor = mCurrentSurfaceActor;
|
|
|
|
#endif
|
2010-02-25 00:14:13 +03:00
|
|
|
|
2011-01-28 01:37:00 +03:00
|
|
|
mCurrentSurface = mBackSurface;
|
|
|
|
#ifdef XP_WIN
|
|
|
|
mCurrentSurfaceActor = mBackSurfaceActor;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
mBackSurface = tmpsurf;
|
|
|
|
#ifdef XP_WIN
|
|
|
|
mBackSurfaceActor = tmpactor;
|
|
|
|
#endif
|
|
|
|
|
2011-07-12 18:31:18 +04:00
|
|
|
#ifdef MOZ_WIDGET_COCOA
|
|
|
|
mDoubleBufferCARenderer.SwapSurfaces();
|
|
|
|
|
2011-01-28 01:37:00 +03:00
|
|
|
// Outdated back surface... not usable anymore due to changed plugin size.
|
|
|
|
// Dropping obsolete surface
|
2017-07-06 15:00:35 +03:00
|
|
|
if (mDoubleBufferCARenderer.HasFrontSurface() &&
|
2011-07-12 18:31:18 +04:00
|
|
|
mDoubleBufferCARenderer.HasBackSurface() &&
|
2017-07-06 15:00:35 +03:00
|
|
|
(mDoubleBufferCARenderer.GetFrontSurfaceWidth() !=
|
2011-07-12 18:31:18 +04:00
|
|
|
mDoubleBufferCARenderer.GetBackSurfaceWidth() ||
|
2017-07-06 15:00:35 +03:00
|
|
|
mDoubleBufferCARenderer.GetFrontSurfaceHeight() !=
|
2012-10-16 23:41:21 +04:00
|
|
|
mDoubleBufferCARenderer.GetBackSurfaceHeight() ||
|
2017-07-06 15:00:35 +03:00
|
|
|
mDoubleBufferCARenderer.GetFrontSurfaceContentsScaleFactor() !=
|
2012-10-16 23:41:21 +04:00
|
|
|
mDoubleBufferCARenderer.GetBackSurfaceContentsScaleFactor())) {
|
2011-07-12 18:31:18 +04:00
|
|
|
|
|
|
|
mDoubleBufferCARenderer.ClearFrontSurface();
|
2011-01-28 01:37:00 +03:00
|
|
|
}
|
2011-08-10 18:12:25 +04:00
|
|
|
#else
|
|
|
|
if (mCurrentSurface && mBackSurface &&
|
|
|
|
(mCurrentSurface->GetSize() != mBackSurface->GetSize() ||
|
|
|
|
mCurrentSurface->GetContentType() != mBackSurface->GetContentType())) {
|
|
|
|
ClearCurrentSurface();
|
|
|
|
}
|
|
|
|
#endif
|
2011-01-28 01:37:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PluginInstanceChild::ClearCurrentSurface()
|
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
mCurrentSurface = nullptr;
|
2011-07-12 18:31:18 +04:00
|
|
|
#ifdef MOZ_WIDGET_COCOA
|
|
|
|
if (mDoubleBufferCARenderer.HasFrontSurface()) {
|
|
|
|
mDoubleBufferCARenderer.ClearFrontSurface();
|
|
|
|
}
|
|
|
|
#endif
|
2011-01-28 01:37:00 +03:00
|
|
|
#ifdef XP_WIN
|
|
|
|
if (mCurrentSurfaceActor) {
|
|
|
|
PPluginSurfaceChild::Send__delete__(mCurrentSurfaceActor);
|
2013-10-24 00:34:46 +04:00
|
|
|
mCurrentSurfaceActor = nullptr;
|
2011-01-28 01:37:00 +03:00
|
|
|
}
|
2010-10-22 01:52:48 +04:00
|
|
|
#endif
|
2012-07-30 18:20:58 +04:00
|
|
|
mHelperSurface = nullptr;
|
2011-01-28 01:37:00 +03:00
|
|
|
}
|
2010-10-22 01:52:48 +04:00
|
|
|
|
2011-01-28 01:37:00 +03:00
|
|
|
void
|
|
|
|
PluginInstanceChild::ClearAllSurfaces()
|
|
|
|
{
|
2010-09-15 20:02:49 +04:00
|
|
|
if (mBackSurface) {
|
|
|
|
// Get last surface back, and drop it
|
|
|
|
SurfaceDescriptor temp = null_t();
|
|
|
|
NPRect r = { 0, 0, 1, 1 };
|
|
|
|
SendShow(r, temp, &temp);
|
|
|
|
}
|
2011-07-12 18:31:18 +04:00
|
|
|
|
2010-09-15 20:02:49 +04:00
|
|
|
if (gfxSharedImageSurface::IsSharedImage(mCurrentSurface))
|
|
|
|
DeallocShmem(static_cast<gfxSharedImageSurface*>(mCurrentSurface.get())->GetShmem());
|
|
|
|
if (gfxSharedImageSurface::IsSharedImage(mBackSurface))
|
|
|
|
DeallocShmem(static_cast<gfxSharedImageSurface*>(mBackSurface.get())->GetShmem());
|
2012-07-30 18:20:58 +04:00
|
|
|
mCurrentSurface = nullptr;
|
|
|
|
mBackSurface = nullptr;
|
2010-09-15 20:02:49 +04:00
|
|
|
|
2011-01-28 01:37:00 +03:00
|
|
|
#ifdef XP_WIN
|
|
|
|
if (mCurrentSurfaceActor) {
|
|
|
|
PPluginSurfaceChild::Send__delete__(mCurrentSurfaceActor);
|
2013-10-24 00:34:46 +04:00
|
|
|
mCurrentSurfaceActor = nullptr;
|
2011-01-28 01:37:00 +03:00
|
|
|
}
|
|
|
|
if (mBackSurfaceActor) {
|
|
|
|
PPluginSurfaceChild::Send__delete__(mBackSurfaceActor);
|
2013-10-24 00:34:46 +04:00
|
|
|
mBackSurfaceActor = nullptr;
|
2011-01-28 01:37:00 +03:00
|
|
|
}
|
|
|
|
#endif
|
2011-05-20 01:08:14 +04:00
|
|
|
|
2011-07-12 18:31:18 +04:00
|
|
|
#ifdef MOZ_WIDGET_COCOA
|
|
|
|
if (mDoubleBufferCARenderer.HasBackSurface()) {
|
2011-05-20 01:08:14 +04:00
|
|
|
// Get last surface back, and drop it
|
|
|
|
SurfaceDescriptor temp = null_t();
|
|
|
|
NPRect r = { 0, 0, 1, 1 };
|
|
|
|
SendShow(r, temp, &temp);
|
2011-06-30 20:46:25 +04:00
|
|
|
}
|
2011-05-20 01:08:14 +04:00
|
|
|
|
2011-06-30 20:46:25 +04:00
|
|
|
if (mCGLayer) {
|
|
|
|
mozilla::plugins::PluginUtilsOSX::ReleaseCGLayer(mCGLayer);
|
2012-07-30 18:20:58 +04:00
|
|
|
mCGLayer = nullptr;
|
2011-05-20 01:08:14 +04:00
|
|
|
}
|
|
|
|
|
2011-07-12 18:31:18 +04:00
|
|
|
mDoubleBufferCARenderer.ClearFrontSurface();
|
|
|
|
mDoubleBufferCARenderer.ClearBackSurface();
|
2011-05-20 01:08:14 +04:00
|
|
|
#endif
|
2011-01-28 01:37:00 +03:00
|
|
|
}
|
|
|
|
|
2015-07-16 20:55:12 +03:00
|
|
|
static void
|
|
|
|
InvalidateObjects(nsTHashtable<DeletingObjectEntry>& aEntries)
|
|
|
|
{
|
|
|
|
for (auto iter = aEntries.Iter(); !iter.Done(); iter.Next()) {
|
|
|
|
DeletingObjectEntry* e = iter.Get();
|
|
|
|
NPObject* o = e->GetKey();
|
|
|
|
if (!e->mDeleted && o->_class && o->_class->invalidate) {
|
|
|
|
o->_class->invalidate(o);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
DeleteObjects(nsTHashtable<DeletingObjectEntry>& aEntries)
|
|
|
|
{
|
|
|
|
for (auto iter = aEntries.Iter(); !iter.Done(); iter.Next()) {
|
|
|
|
DeletingObjectEntry* e = iter.Get();
|
|
|
|
NPObject* o = e->GetKey();
|
|
|
|
if (!e->mDeleted) {
|
|
|
|
e->mDeleted = true;
|
|
|
|
|
|
|
|
#ifdef NS_BUILD_REFCNT_LOGGING
|
|
|
|
{
|
|
|
|
int32_t refcnt = o->referenceCount;
|
|
|
|
while (refcnt) {
|
|
|
|
--refcnt;
|
|
|
|
NS_LOG_RELEASE(o, refcnt, "NPObject");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
PluginModuleChild::DeallocNPObject(o);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-29 18:05:36 +03:00
|
|
|
void
|
|
|
|
PluginInstanceChild::Destroy()
|
2011-01-28 01:37:00 +03:00
|
|
|
{
|
2014-10-29 18:05:36 +03:00
|
|
|
if (mDestroyed) {
|
|
|
|
return;
|
|
|
|
}
|
2016-04-06 23:23:43 +03:00
|
|
|
if (mStackDepth != 0) {
|
2016-12-03 00:46:53 +03:00
|
|
|
MOZ_CRASH("Destroying plugin instance on the stack.");
|
2016-04-06 23:23:43 +03:00
|
|
|
}
|
2014-10-29 18:05:36 +03:00
|
|
|
mDestroyed = true;
|
2011-01-28 01:37:00 +03:00
|
|
|
|
|
|
|
#if defined(OS_WIN)
|
|
|
|
SetProp(mPluginWindowHWND, kPluginIgnoreSubclassProperty, (HANDLE)1);
|
|
|
|
#endif
|
|
|
|
|
2010-11-09 05:49:00 +03:00
|
|
|
InfallibleTArray<PBrowserStreamChild*> streams;
|
2010-03-07 00:03:05 +03:00
|
|
|
ManagedPBrowserStreamChild(streams);
|
|
|
|
|
|
|
|
// First make sure none of these streams become deleted
|
2012-08-22 19:56:38 +04:00
|
|
|
for (uint32_t i = 0; i < streams.Length(); ) {
|
2010-03-07 00:03:05 +03:00
|
|
|
if (static_cast<BrowserStreamChild*>(streams[i])->InstanceDying())
|
|
|
|
++i;
|
|
|
|
else
|
|
|
|
streams.RemoveElementAt(i);
|
|
|
|
}
|
2012-08-22 19:56:38 +04:00
|
|
|
for (uint32_t i = 0; i < streams.Length(); ++i)
|
2010-03-07 00:03:05 +03:00
|
|
|
static_cast<BrowserStreamChild*>(streams[i])->FinishDelivery();
|
|
|
|
|
2010-02-04 01:17:09 +03:00
|
|
|
mTimers.Clear();
|
2011-03-02 21:29:31 +03:00
|
|
|
|
|
|
|
// NPP_Destroy() should be a synchronization point for plugin threads
|
|
|
|
// calling NPN_AsyncCall: after this function returns, they are no longer
|
|
|
|
// allowed to make async calls on this instance.
|
2014-10-29 18:05:36 +03:00
|
|
|
static_cast<PluginModuleChild *>(Manager())->NPP_Destroy(this);
|
2011-03-02 21:29:31 +03:00
|
|
|
mData.ndata = 0;
|
|
|
|
|
2010-09-15 20:02:49 +04:00
|
|
|
if (mCurrentInvalidateTask) {
|
|
|
|
mCurrentInvalidateTask->Cancel();
|
2012-07-30 18:20:58 +04:00
|
|
|
mCurrentInvalidateTask = nullptr;
|
2010-09-15 20:02:49 +04:00
|
|
|
}
|
2010-12-06 00:57:33 +03:00
|
|
|
if (mCurrentAsyncSetWindowTask) {
|
|
|
|
mCurrentAsyncSetWindowTask->Cancel();
|
2012-07-30 18:20:58 +04:00
|
|
|
mCurrentAsyncSetWindowTask = nullptr;
|
2010-12-06 00:57:33 +03:00
|
|
|
}
|
2012-02-16 07:30:22 +04:00
|
|
|
{
|
|
|
|
MutexAutoLock autoLock(mAsyncInvalidateMutex);
|
|
|
|
if (mAsyncInvalidateTask) {
|
|
|
|
mAsyncInvalidateTask->Cancel();
|
2012-07-30 18:20:58 +04:00
|
|
|
mAsyncInvalidateTask = nullptr;
|
2012-02-16 07:30:22 +04:00
|
|
|
}
|
|
|
|
}
|
2010-01-20 06:13:24 +03:00
|
|
|
|
2011-01-28 01:37:00 +03:00
|
|
|
ClearAllSurfaces();
|
2015-12-02 22:31:17 +03:00
|
|
|
mDirectBitmaps.Clear();
|
2011-01-28 01:37:00 +03:00
|
|
|
|
2010-02-25 00:14:13 +03:00
|
|
|
mDeletingHash = new nsTHashtable<DeletingObjectEntry>;
|
2014-10-29 18:04:51 +03:00
|
|
|
PluginScriptableObjectChild::NotifyOfInstanceShutdown(this);
|
2010-02-25 00:14:13 +03:00
|
|
|
|
2015-07-16 20:55:12 +03:00
|
|
|
InvalidateObjects(*mDeletingHash);
|
|
|
|
DeleteObjects(*mDeletingHash);
|
2010-01-15 23:35:57 +03:00
|
|
|
|
2010-02-21 00:59:40 +03:00
|
|
|
// Null out our cached actors as they should have been killed in the
|
|
|
|
// PluginInstanceDestroyed call above.
|
2012-07-30 18:20:58 +04:00
|
|
|
mCachedWindowActor = nullptr;
|
|
|
|
mCachedElementActor = nullptr;
|
2010-02-21 00:59:40 +03:00
|
|
|
|
2010-01-15 23:35:57 +03:00
|
|
|
#if defined(OS_WIN)
|
2010-03-23 06:06:35 +03:00
|
|
|
DestroyWinlessPopupSurrogate();
|
2010-05-06 20:40:26 +04:00
|
|
|
UnhookWinlessFlashThrottle();
|
2010-12-09 17:54:26 +03:00
|
|
|
DestroyPluginWindow();
|
2017-07-19 10:22:05 +03:00
|
|
|
|
|
|
|
for (uint32_t i = 0; i < mPendingFlashThrottleMsgs.Length(); ++i) {
|
|
|
|
mPendingFlashThrottleMsgs[i]->Cancel();
|
|
|
|
}
|
|
|
|
mPendingFlashThrottleMsgs.Clear();
|
2010-01-15 23:35:57 +03:00
|
|
|
#endif
|
2014-10-29 18:05:36 +03:00
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2014-10-29 18:05:36 +03:00
|
|
|
PluginInstanceChild::AnswerNPP_Destroy(NPError* aResult)
|
|
|
|
{
|
|
|
|
PLUGIN_LOG_DEBUG_METHOD;
|
|
|
|
AssertPluginThread();
|
|
|
|
*aResult = NPERR_NO_ERROR;
|
|
|
|
|
|
|
|
Destroy();
|
2012-08-02 00:34:08 +04:00
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2010-01-15 23:35:57 +03:00
|
|
|
}
|
2014-10-29 18:05:36 +03:00
|
|
|
|
|
|
|
void
|
|
|
|
PluginInstanceChild::ActorDestroy(ActorDestroyReason why)
|
|
|
|
{
|
2016-06-28 02:46:27 +03:00
|
|
|
#ifdef XP_WIN
|
|
|
|
// ClearAllSurfaces() should not try to send anything after ActorDestroy.
|
|
|
|
mCurrentSurfaceActor = nullptr;
|
|
|
|
mBackSurfaceActor = nullptr;
|
|
|
|
#endif
|
|
|
|
|
2014-10-29 18:05:36 +03:00
|
|
|
Destroy();
|
|
|
|
}
|