1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/plugins/base/nsPluginInstanceOwner.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,3195 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +// vim:set ts=2 sts=2 sw=2 et cin: 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifdef MOZ_X11 1.11 +#include <cairo-xlib.h> 1.12 +#include "gfxXlibSurface.h" 1.13 +/* X headers suck */ 1.14 +enum { XKeyPress = KeyPress }; 1.15 +#include "mozilla/X11Util.h" 1.16 +using mozilla::DefaultXDisplay; 1.17 +#endif 1.18 + 1.19 +#include "nsPluginInstanceOwner.h" 1.20 +#include "nsIRunnable.h" 1.21 +#include "nsContentUtils.h" 1.22 +#include "nsRect.h" 1.23 +#include "nsSize.h" 1.24 +#include "nsDisplayList.h" 1.25 +#include "ImageLayers.h" 1.26 +#include "SharedTextureImage.h" 1.27 +#include "nsObjectFrame.h" 1.28 +#include "nsIPluginDocument.h" 1.29 +#include "nsIStringStream.h" 1.30 +#include "nsNetUtil.h" 1.31 +#include "mozilla/Preferences.h" 1.32 +#include "nsILinkHandler.h" 1.33 +#include "nsIDocShellTreeItem.h" 1.34 +#include "nsIWebBrowserChrome.h" 1.35 +#include "nsLayoutUtils.h" 1.36 +#include "nsIPluginWidget.h" 1.37 +#include "nsViewManager.h" 1.38 +#include "nsIDocShellTreeOwner.h" 1.39 +#include "nsIDOMHTMLObjectElement.h" 1.40 +#include "nsIAppShell.h" 1.41 +#include "nsIDOMHTMLAppletElement.h" 1.42 +#include "nsIObjectLoadingContent.h" 1.43 +#include "nsAttrName.h" 1.44 +#include "nsIFocusManager.h" 1.45 +#include "nsFocusManager.h" 1.46 +#include "nsIDOMDragEvent.h" 1.47 +#include "nsIScrollableFrame.h" 1.48 +#include "nsIDocShell.h" 1.49 +#include "ImageContainer.h" 1.50 +#include "nsIDOMHTMLCollection.h" 1.51 +#include "GLContext.h" 1.52 +#include "GLSharedHandleHelpers.h" 1.53 +#include "nsIContentInlines.h" 1.54 +#include "mozilla/MiscEvents.h" 1.55 +#include "mozilla/MouseEvents.h" 1.56 +#include "mozilla/TextEvents.h" 1.57 + 1.58 +#include "nsContentCID.h" 1.59 +#include "nsWidgetsCID.h" 1.60 +static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID); 1.61 +static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID); 1.62 + 1.63 +#ifdef XP_WIN 1.64 +#include <wtypes.h> 1.65 +#include <winuser.h> 1.66 +#endif 1.67 + 1.68 +#ifdef XP_MACOSX 1.69 +#include <Carbon/Carbon.h> 1.70 +#include "nsPluginUtilsOSX.h" 1.71 +#endif 1.72 + 1.73 +#if (MOZ_WIDGET_GTK == 2) 1.74 +#include <gdk/gdk.h> 1.75 +#include <gdk/gdkx.h> 1.76 +#include <gtk/gtk.h> 1.77 +#endif 1.78 + 1.79 +#ifdef MOZ_WIDGET_ANDROID 1.80 +#include "ANPBase.h" 1.81 +#include "AndroidBridge.h" 1.82 +#include "nsWindow.h" 1.83 + 1.84 +static nsPluginInstanceOwner* sFullScreenInstance = nullptr; 1.85 + 1.86 +using namespace mozilla::dom; 1.87 + 1.88 +#include <android/log.h> 1.89 +#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args) 1.90 +#endif 1.91 + 1.92 +using namespace mozilla; 1.93 +using namespace mozilla::layers; 1.94 + 1.95 +// special class for handeling DOM context menu events because for 1.96 +// some reason it starves other mouse events if implemented on the 1.97 +// same class 1.98 +class nsPluginDOMContextMenuListener : public nsIDOMEventListener 1.99 +{ 1.100 +public: 1.101 + nsPluginDOMContextMenuListener(nsIContent* aContent); 1.102 + virtual ~nsPluginDOMContextMenuListener(); 1.103 + 1.104 + NS_DECL_ISUPPORTS 1.105 + NS_DECL_NSIDOMEVENTLISTENER 1.106 + 1.107 + void Destroy(nsIContent* aContent); 1.108 + 1.109 + nsEventStatus ProcessEvent(const WidgetGUIEvent& anEvent) 1.110 + { 1.111 + return nsEventStatus_eConsumeNoDefault; 1.112 + } 1.113 +}; 1.114 + 1.115 +class AsyncPaintWaitEvent : public nsRunnable 1.116 +{ 1.117 +public: 1.118 + AsyncPaintWaitEvent(nsIContent* aContent, bool aFinished) : 1.119 + mContent(aContent), mFinished(aFinished) 1.120 + { 1.121 + } 1.122 + 1.123 + NS_IMETHOD Run() 1.124 + { 1.125 + nsContentUtils::DispatchTrustedEvent(mContent->OwnerDoc(), mContent, 1.126 + mFinished ? NS_LITERAL_STRING("MozPaintWaitFinished") : NS_LITERAL_STRING("MozPaintWait"), 1.127 + true, true); 1.128 + return NS_OK; 1.129 + } 1.130 + 1.131 +private: 1.132 + nsCOMPtr<nsIContent> mContent; 1.133 + bool mFinished; 1.134 +}; 1.135 + 1.136 +void 1.137 +nsPluginInstanceOwner::NotifyPaintWaiter(nsDisplayListBuilder* aBuilder) 1.138 +{ 1.139 + // This is notification for reftests about async plugin paint start 1.140 + if (!mWaitingForPaint && !IsUpToDate() && aBuilder->ShouldSyncDecodeImages()) { 1.141 + nsCOMPtr<nsIRunnable> event = new AsyncPaintWaitEvent(mContent, false); 1.142 + // Run this event as soon as it's safe to do so, since listeners need to 1.143 + // receive it immediately 1.144 + mWaitingForPaint = nsContentUtils::AddScriptRunner(event); 1.145 + } 1.146 +} 1.147 + 1.148 +already_AddRefed<ImageContainer> 1.149 +nsPluginInstanceOwner::GetImageContainer() 1.150 +{ 1.151 + if (!mInstance) 1.152 + return nullptr; 1.153 + 1.154 + nsRefPtr<ImageContainer> container; 1.155 + 1.156 +#if MOZ_WIDGET_ANDROID 1.157 + // Right now we only draw with Gecko layers on Honeycomb and higher. See Paint() 1.158 + // for what we do on other versions. 1.159 + if (AndroidBridge::Bridge()->GetAPIVersion() < 11) 1.160 + return nullptr; 1.161 + 1.162 + LayoutDeviceRect r = GetPluginRect(); 1.163 + 1.164 + // NotifySize() causes Flash to do a bunch of stuff like ask for surfaces to render 1.165 + // into, set y-flip flags, etc, so we do this at the beginning. 1.166 + gfxSize resolution = mObjectFrame->PresContext()->PresShell()->GetCumulativeResolution(); 1.167 + ScreenSize screenSize = (r * LayoutDeviceToScreenScale(resolution.width, resolution.height)).Size(); 1.168 + mInstance->NotifySize(nsIntSize(screenSize.width, screenSize.height)); 1.169 + 1.170 + container = LayerManager::CreateImageContainer(); 1.171 + 1.172 + nsRefPtr<Image> img = container->CreateImage(ImageFormat::SHARED_TEXTURE); 1.173 + 1.174 + SharedTextureImage::Data data; 1.175 + data.mSize = gfx::IntSize(r.width, r.height); 1.176 + data.mHandle = mInstance->CreateSharedHandle(); 1.177 + data.mShareType = mozilla::gl::SharedTextureShareType::SameProcess; 1.178 + data.mInverted = mInstance->Inverted(); 1.179 + 1.180 + SharedTextureImage* pluginImage = static_cast<SharedTextureImage*>(img.get()); 1.181 + pluginImage->SetData(data); 1.182 + 1.183 + container->SetCurrentImageInTransaction(img); 1.184 + 1.185 + return container.forget(); 1.186 +#endif 1.187 + 1.188 + mInstance->GetImageContainer(getter_AddRefs(container)); 1.189 + return container.forget(); 1.190 +} 1.191 + 1.192 +void 1.193 +nsPluginInstanceOwner::SetBackgroundUnknown() 1.194 +{ 1.195 + if (mInstance) { 1.196 + mInstance->SetBackgroundUnknown(); 1.197 + } 1.198 +} 1.199 + 1.200 +already_AddRefed<gfxContext> 1.201 +nsPluginInstanceOwner::BeginUpdateBackground(const nsIntRect& aRect) 1.202 +{ 1.203 + nsIntRect rect = aRect; 1.204 + nsRefPtr<gfxContext> ctx; 1.205 + if (mInstance && 1.206 + NS_SUCCEEDED(mInstance->BeginUpdateBackground(&rect, getter_AddRefs(ctx)))) { 1.207 + return ctx.forget(); 1.208 + } 1.209 + return nullptr; 1.210 +} 1.211 + 1.212 +void 1.213 +nsPluginInstanceOwner::EndUpdateBackground(gfxContext* aContext, 1.214 + const nsIntRect& aRect) 1.215 +{ 1.216 + nsIntRect rect = aRect; 1.217 + if (mInstance) { 1.218 + mInstance->EndUpdateBackground(aContext, &rect); 1.219 + } 1.220 +} 1.221 + 1.222 +bool 1.223 +nsPluginInstanceOwner::UseAsyncRendering() 1.224 +{ 1.225 +#ifdef XP_MACOSX 1.226 + if (mUseAsyncRendering) { 1.227 + return true; 1.228 + } 1.229 +#endif 1.230 + 1.231 + bool isOOP; 1.232 + bool result = (mInstance && 1.233 + NS_SUCCEEDED(mInstance->GetIsOOP(&isOOP)) && isOOP 1.234 +#ifndef XP_MACOSX 1.235 + && (!mPluginWindow || 1.236 + mPluginWindow->type == NPWindowTypeDrawable) 1.237 +#endif 1.238 + ); 1.239 + 1.240 +#ifdef XP_MACOSX 1.241 + if (result) { 1.242 + mUseAsyncRendering = true; 1.243 + } 1.244 +#endif 1.245 + 1.246 + return result; 1.247 +} 1.248 + 1.249 +nsIntSize 1.250 +nsPluginInstanceOwner::GetCurrentImageSize() 1.251 +{ 1.252 + nsIntSize size(0,0); 1.253 + if (mInstance) { 1.254 + mInstance->GetImageSize(&size); 1.255 + } 1.256 + return size; 1.257 +} 1.258 + 1.259 +nsPluginInstanceOwner::nsPluginInstanceOwner() 1.260 +{ 1.261 + // create nsPluginNativeWindow object, it is derived from NPWindow 1.262 + // struct and allows to manipulate native window procedure 1.263 + nsCOMPtr<nsIPluginHost> pluginHostCOM = do_GetService(MOZ_PLUGIN_HOST_CONTRACTID); 1.264 + mPluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get()); 1.265 + if (mPluginHost) 1.266 + mPluginHost->NewPluginNativeWindow(&mPluginWindow); 1.267 + else 1.268 + mPluginWindow = nullptr; 1.269 + 1.270 + mObjectFrame = nullptr; 1.271 + mContent = nullptr; 1.272 + mWidgetCreationComplete = false; 1.273 +#ifdef XP_MACOSX 1.274 + memset(&mCGPluginPortCopy, 0, sizeof(NP_CGContext)); 1.275 + mInCGPaintLevel = 0; 1.276 + mSentInitialTopLevelWindowEvent = false; 1.277 + mColorProfile = nullptr; 1.278 + mPluginPortChanged = false; 1.279 +#endif 1.280 + mContentFocused = false; 1.281 + mWidgetVisible = true; 1.282 + mPluginWindowVisible = false; 1.283 + mPluginDocumentActiveState = true; 1.284 + mNumCachedAttrs = 0; 1.285 + mNumCachedParams = 0; 1.286 + mCachedAttrParamNames = nullptr; 1.287 + mCachedAttrParamValues = nullptr; 1.288 + mLastMouseDownButtonType = -1; 1.289 + 1.290 +#ifdef XP_MACOSX 1.291 +#ifndef NP_NO_CARBON 1.292 + // We don't support Carbon, but it is still the default model for i386 NPAPI. 1.293 + mEventModel = NPEventModelCarbon; 1.294 +#else 1.295 + mEventModel = NPEventModelCocoa; 1.296 +#endif 1.297 + mUseAsyncRendering = false; 1.298 +#endif 1.299 + 1.300 + mWaitingForPaint = false; 1.301 + 1.302 +#ifdef MOZ_WIDGET_ANDROID 1.303 + mFullScreen = false; 1.304 + mJavaView = nullptr; 1.305 +#endif 1.306 +} 1.307 + 1.308 +nsPluginInstanceOwner::~nsPluginInstanceOwner() 1.309 +{ 1.310 + int32_t cnt; 1.311 + 1.312 + if (mWaitingForPaint) { 1.313 + // We don't care when the event is dispatched as long as it's "soon", 1.314 + // since whoever needs it will be waiting for it. 1.315 + nsCOMPtr<nsIRunnable> event = new AsyncPaintWaitEvent(mContent, true); 1.316 + NS_DispatchToMainThread(event); 1.317 + } 1.318 + 1.319 + mObjectFrame = nullptr; 1.320 + 1.321 + for (cnt = 0; cnt < (mNumCachedAttrs + 1 + mNumCachedParams); cnt++) { 1.322 + if (mCachedAttrParamNames && mCachedAttrParamNames[cnt]) { 1.323 + NS_Free(mCachedAttrParamNames[cnt]); 1.324 + mCachedAttrParamNames[cnt] = nullptr; 1.325 + } 1.326 + 1.327 + if (mCachedAttrParamValues && mCachedAttrParamValues[cnt]) { 1.328 + NS_Free(mCachedAttrParamValues[cnt]); 1.329 + mCachedAttrParamValues[cnt] = nullptr; 1.330 + } 1.331 + } 1.332 + 1.333 + if (mCachedAttrParamNames) { 1.334 + NS_Free(mCachedAttrParamNames); 1.335 + mCachedAttrParamNames = nullptr; 1.336 + } 1.337 + 1.338 + if (mCachedAttrParamValues) { 1.339 + NS_Free(mCachedAttrParamValues); 1.340 + mCachedAttrParamValues = nullptr; 1.341 + } 1.342 + 1.343 + PLUG_DeletePluginNativeWindow(mPluginWindow); 1.344 + mPluginWindow = nullptr; 1.345 + 1.346 +#ifdef MOZ_WIDGET_ANDROID 1.347 + RemovePluginView(); 1.348 +#endif 1.349 + 1.350 + if (mInstance) { 1.351 + mInstance->SetOwner(nullptr); 1.352 + } 1.353 +} 1.354 + 1.355 +NS_IMPL_ISUPPORTS(nsPluginInstanceOwner, 1.356 + nsIPluginInstanceOwner, 1.357 + nsIDOMEventListener, 1.358 + nsIPrivacyTransitionObserver, 1.359 + nsISupportsWeakReference) 1.360 + 1.361 +nsresult 1.362 +nsPluginInstanceOwner::SetInstance(nsNPAPIPluginInstance *aInstance) 1.363 +{ 1.364 + NS_ASSERTION(!mInstance || !aInstance, "mInstance should only be set or unset!"); 1.365 + 1.366 + // If we're going to null out mInstance after use, be sure to call 1.367 + // mInstance->SetOwner(nullptr) here, since it now won't be called 1.368 + // from our destructor. This fixes bug 613376. 1.369 + if (mInstance && !aInstance) { 1.370 + mInstance->SetOwner(nullptr); 1.371 + 1.372 +#ifdef MOZ_WIDGET_ANDROID 1.373 + RemovePluginView(); 1.374 +#endif 1.375 + } 1.376 + 1.377 + mInstance = aInstance; 1.378 + 1.379 + nsCOMPtr<nsIDocument> doc; 1.380 + GetDocument(getter_AddRefs(doc)); 1.381 + if (doc) { 1.382 + nsCOMPtr<nsPIDOMWindow> domWindow = doc->GetWindow(); 1.383 + if (domWindow) { 1.384 + nsCOMPtr<nsIDocShell> docShell = domWindow->GetDocShell(); 1.385 + if (docShell) 1.386 + docShell->AddWeakPrivacyTransitionObserver(this); 1.387 + } 1.388 + } 1.389 + 1.390 + return NS_OK; 1.391 +} 1.392 + 1.393 +NS_IMETHODIMP nsPluginInstanceOwner::GetWindow(NPWindow *&aWindow) 1.394 +{ 1.395 + NS_ASSERTION(mPluginWindow, "the plugin window object being returned is null"); 1.396 + aWindow = mPluginWindow; 1.397 + return NS_OK; 1.398 +} 1.399 + 1.400 +NS_IMETHODIMP nsPluginInstanceOwner::GetMode(int32_t *aMode) 1.401 +{ 1.402 + nsCOMPtr<nsIDocument> doc; 1.403 + nsresult rv = GetDocument(getter_AddRefs(doc)); 1.404 + nsCOMPtr<nsIPluginDocument> pDoc (do_QueryInterface(doc)); 1.405 + 1.406 + if (pDoc) { 1.407 + *aMode = NP_FULL; 1.408 + } else { 1.409 + *aMode = NP_EMBED; 1.410 + } 1.411 + 1.412 + return rv; 1.413 +} 1.414 + 1.415 +NS_IMETHODIMP nsPluginInstanceOwner::GetAttributes(uint16_t& n, 1.416 + const char*const*& names, 1.417 + const char*const*& values) 1.418 +{ 1.419 + nsresult rv = EnsureCachedAttrParamArrays(); 1.420 + NS_ENSURE_SUCCESS(rv, rv); 1.421 + 1.422 + n = mNumCachedAttrs; 1.423 + names = (const char **)mCachedAttrParamNames; 1.424 + values = (const char **)mCachedAttrParamValues; 1.425 + 1.426 + return rv; 1.427 +} 1.428 + 1.429 +NS_IMETHODIMP nsPluginInstanceOwner::GetAttribute(const char* name, const char* *result) 1.430 +{ 1.431 + NS_ENSURE_ARG_POINTER(name); 1.432 + NS_ENSURE_ARG_POINTER(result); 1.433 + 1.434 + nsresult rv = EnsureCachedAttrParamArrays(); 1.435 + NS_ENSURE_SUCCESS(rv, rv); 1.436 + 1.437 + *result = nullptr; 1.438 + 1.439 + for (int i = 0; i < mNumCachedAttrs; i++) { 1.440 + if (0 == PL_strcasecmp(mCachedAttrParamNames[i], name)) { 1.441 + *result = mCachedAttrParamValues[i]; 1.442 + return NS_OK; 1.443 + } 1.444 + } 1.445 + 1.446 + return NS_ERROR_FAILURE; 1.447 +} 1.448 + 1.449 +NS_IMETHODIMP nsPluginInstanceOwner::GetDOMElement(nsIDOMElement* *result) 1.450 +{ 1.451 + return CallQueryInterface(mContent, result); 1.452 +} 1.453 + 1.454 +nsresult nsPluginInstanceOwner::GetInstance(nsNPAPIPluginInstance **aInstance) 1.455 +{ 1.456 + NS_ENSURE_ARG_POINTER(aInstance); 1.457 + 1.458 + *aInstance = mInstance; 1.459 + NS_IF_ADDREF(*aInstance); 1.460 + return NS_OK; 1.461 +} 1.462 + 1.463 +NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL, 1.464 + const char *aTarget, 1.465 + nsIInputStream *aPostStream, 1.466 + void *aHeadersData, 1.467 + uint32_t aHeadersDataLen) 1.468 +{ 1.469 + NS_ENSURE_TRUE(mContent, NS_ERROR_NULL_POINTER); 1.470 + 1.471 + if (mContent->IsEditable()) { 1.472 + return NS_OK; 1.473 + } 1.474 + 1.475 + nsIDocument *doc = mContent->GetCurrentDoc(); 1.476 + if (!doc) { 1.477 + return NS_ERROR_FAILURE; 1.478 + } 1.479 + 1.480 + nsIPresShell *presShell = doc->GetShell(); 1.481 + if (!presShell) { 1.482 + return NS_ERROR_FAILURE; 1.483 + } 1.484 + 1.485 + nsPresContext *presContext = presShell->GetPresContext(); 1.486 + if (!presContext) { 1.487 + return NS_ERROR_FAILURE; 1.488 + } 1.489 + 1.490 + // the container of the pres context will give us the link handler 1.491 + nsCOMPtr<nsISupports> container = presContext->GetContainerWeak(); 1.492 + NS_ENSURE_TRUE(container,NS_ERROR_FAILURE); 1.493 + nsCOMPtr<nsILinkHandler> lh = do_QueryInterface(container); 1.494 + NS_ENSURE_TRUE(lh, NS_ERROR_FAILURE); 1.495 + 1.496 + nsAutoString unitarget; 1.497 + unitarget.AssignASCII(aTarget); // XXX could this be nonascii? 1.498 + 1.499 + nsCOMPtr<nsIURI> baseURI = GetBaseURI(); 1.500 + 1.501 + // Create an absolute URL 1.502 + nsCOMPtr<nsIURI> uri; 1.503 + nsresult rv = NS_NewURI(getter_AddRefs(uri), aURL, baseURI); 1.504 + 1.505 + NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); 1.506 + 1.507 + nsCOMPtr<nsIInputStream> headersDataStream; 1.508 + if (aPostStream && aHeadersData) { 1.509 + if (!aHeadersDataLen) 1.510 + return NS_ERROR_UNEXPECTED; 1.511 + 1.512 + nsCOMPtr<nsIStringInputStream> sis = do_CreateInstance("@mozilla.org/io/string-input-stream;1"); 1.513 + if (!sis) 1.514 + return NS_ERROR_OUT_OF_MEMORY; 1.515 + 1.516 + rv = sis->SetData((char *)aHeadersData, aHeadersDataLen); 1.517 + NS_ENSURE_SUCCESS(rv, rv); 1.518 + headersDataStream = do_QueryInterface(sis); 1.519 + } 1.520 + 1.521 + int32_t blockPopups = 1.522 + Preferences::GetInt("privacy.popups.disable_from_plugins"); 1.523 + nsAutoPopupStatePusher popupStatePusher((PopupControlState)blockPopups); 1.524 + 1.525 + rv = lh->OnLinkClick(mContent, uri, unitarget.get(), NullString(), 1.526 + aPostStream, headersDataStream, true); 1.527 + 1.528 + return rv; 1.529 +} 1.530 + 1.531 +NS_IMETHODIMP nsPluginInstanceOwner::ShowStatus(const char *aStatusMsg) 1.532 +{ 1.533 + nsresult rv = NS_ERROR_FAILURE; 1.534 + 1.535 + rv = this->ShowStatus(NS_ConvertUTF8toUTF16(aStatusMsg).get()); 1.536 + 1.537 + return rv; 1.538 +} 1.539 + 1.540 +NS_IMETHODIMP nsPluginInstanceOwner::ShowStatus(const char16_t *aStatusMsg) 1.541 +{ 1.542 + nsresult rv = NS_ERROR_FAILURE; 1.543 + 1.544 + if (!mObjectFrame) { 1.545 + return rv; 1.546 + } 1.547 + nsCOMPtr<nsIDocShellTreeItem> docShellItem = mObjectFrame->PresContext()->GetDocShell(); 1.548 + if (NS_FAILED(rv) || !docShellItem) { 1.549 + return rv; 1.550 + } 1.551 + 1.552 + nsCOMPtr<nsIDocShellTreeOwner> treeOwner; 1.553 + rv = docShellItem->GetTreeOwner(getter_AddRefs(treeOwner)); 1.554 + if (NS_FAILED(rv) || !treeOwner) { 1.555 + return rv; 1.556 + } 1.557 + 1.558 + nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(treeOwner, &rv)); 1.559 + if (NS_FAILED(rv) || !browserChrome) { 1.560 + return rv; 1.561 + } 1.562 + rv = browserChrome->SetStatus(nsIWebBrowserChrome::STATUS_SCRIPT, 1.563 + aStatusMsg); 1.564 + 1.565 + return rv; 1.566 +} 1.567 + 1.568 +NS_IMETHODIMP nsPluginInstanceOwner::GetDocument(nsIDocument* *aDocument) 1.569 +{ 1.570 + if (!aDocument) 1.571 + return NS_ERROR_NULL_POINTER; 1.572 + 1.573 + // XXX sXBL/XBL2 issue: current doc or owner doc? 1.574 + // But keep in mind bug 322414 comment 33 1.575 + NS_IF_ADDREF(*aDocument = mContent->OwnerDoc()); 1.576 + return NS_OK; 1.577 +} 1.578 + 1.579 +NS_IMETHODIMP nsPluginInstanceOwner::InvalidateRect(NPRect *invalidRect) 1.580 +{ 1.581 + // If our object frame has gone away, we won't be able to determine 1.582 + // up-to-date-ness, so just fire off the event. 1.583 + if (mWaitingForPaint && (!mObjectFrame || IsUpToDate())) { 1.584 + // We don't care when the event is dispatched as long as it's "soon", 1.585 + // since whoever needs it will be waiting for it. 1.586 + nsCOMPtr<nsIRunnable> event = new AsyncPaintWaitEvent(mContent, true); 1.587 + NS_DispatchToMainThread(event); 1.588 + mWaitingForPaint = false; 1.589 + } 1.590 + 1.591 + if (!mObjectFrame || !invalidRect || !mWidgetVisible) 1.592 + return NS_ERROR_FAILURE; 1.593 + 1.594 +#if defined(XP_MACOSX) || defined(MOZ_WIDGET_ANDROID) 1.595 + // Each time an asynchronously-drawing plugin sends a new surface to display, 1.596 + // the image in the ImageContainer is updated and InvalidateRect is called. 1.597 + // There are different side effects for (sync) Android plugins. 1.598 + nsRefPtr<ImageContainer> container; 1.599 + mInstance->GetImageContainer(getter_AddRefs(container)); 1.600 +#endif 1.601 + 1.602 +#ifndef XP_MACOSX 1.603 + // Windowed plugins should not be calling NPN_InvalidateRect, but 1.604 + // Silverlight does and expects it to "work" 1.605 + if (mWidget) { 1.606 + mWidget->Invalidate(nsIntRect(invalidRect->left, invalidRect->top, 1.607 + invalidRect->right - invalidRect->left, 1.608 + invalidRect->bottom - invalidRect->top)); 1.609 + return NS_OK; 1.610 + } 1.611 +#endif 1.612 + nsIntRect rect(invalidRect->left, 1.613 + invalidRect->top, 1.614 + invalidRect->right - invalidRect->left, 1.615 + invalidRect->bottom - invalidRect->top); 1.616 + // invalidRect is in "display pixels". In non-HiDPI modes "display pixels" 1.617 + // are device pixels. But in HiDPI modes each display pixel corresponds 1.618 + // to more than one device pixel. 1.619 + double scaleFactor = 1.0; 1.620 + GetContentsScaleFactor(&scaleFactor); 1.621 + rect.ScaleRoundOut(scaleFactor); 1.622 + mObjectFrame->InvalidateLayer(nsDisplayItem::TYPE_PLUGIN, &rect); 1.623 + return NS_OK; 1.624 +} 1.625 + 1.626 +NS_IMETHODIMP nsPluginInstanceOwner::InvalidateRegion(NPRegion invalidRegion) 1.627 +{ 1.628 + return NS_ERROR_NOT_IMPLEMENTED; 1.629 +} 1.630 + 1.631 +NS_IMETHODIMP 1.632 +nsPluginInstanceOwner::RedrawPlugin() 1.633 +{ 1.634 + if (mObjectFrame) { 1.635 + mObjectFrame->InvalidateLayer(nsDisplayItem::TYPE_PLUGIN); 1.636 + } 1.637 + return NS_OK; 1.638 +} 1.639 + 1.640 +NS_IMETHODIMP nsPluginInstanceOwner::GetNetscapeWindow(void *value) 1.641 +{ 1.642 + if (!mObjectFrame) { 1.643 + NS_WARNING("plugin owner has no owner in getting doc's window handle"); 1.644 + return NS_ERROR_FAILURE; 1.645 + } 1.646 + 1.647 +#if defined(XP_WIN) 1.648 + void** pvalue = (void**)value; 1.649 + nsViewManager* vm = mObjectFrame->PresContext()->GetPresShell()->GetViewManager(); 1.650 + if (!vm) 1.651 + return NS_ERROR_FAILURE; 1.652 +#if defined(XP_WIN) 1.653 + // This property is provided to allow a "windowless" plugin to determine the window it is drawing 1.654 + // in, so it can translate mouse coordinates it receives directly from the operating system 1.655 + // to coordinates relative to itself. 1.656 + 1.657 + // The original code (outside this #if) returns the document's window, which is OK if the window the "windowless" plugin 1.658 + // is drawing into has the same origin as the document's window, but this is not the case for "windowless" plugins inside of scrolling DIVs etc 1.659 + 1.660 + // To make sure "windowless" plugins always get the right origin for translating mouse coordinates, this code 1.661 + // determines the window handle of the mozilla window containing the "windowless" plugin. 1.662 + 1.663 + // Given that this HWND may not be that of the document's window, there is a slight risk 1.664 + // of confusing a plugin that is using this HWND for illicit purposes, but since the documentation 1.665 + // does not suggest this HWND IS that of the document window, rather that of the window 1.666 + // the plugin is drawn in, this seems like a safe fix. 1.667 + 1.668 + // we only attempt to get the nearest window if this really is a "windowless" plugin so as not 1.669 + // to change any behaviour for the much more common windowed plugins, 1.670 + // though why this method would even be being called for a windowed plugin escapes me. 1.671 + if (mPluginWindow && mPluginWindow->type == NPWindowTypeDrawable) { 1.672 + // it turns out that flash also uses this window for determining focus, and is currently 1.673 + // unable to show a caret correctly if we return the enclosing window. Therefore for 1.674 + // now we only return the enclosing window when there is an actual offset which 1.675 + // would otherwise cause coordinates to be offset incorrectly. (i.e. 1.676 + // if the enclosing window if offset from the document window) 1.677 + // 1.678 + // fixing both the caret and ability to interact issues for a windowless control in a non document aligned windw 1.679 + // does not seem to be possible without a change to the flash plugin 1.680 + 1.681 + nsIWidget* win = mObjectFrame->GetNearestWidget(); 1.682 + if (win) { 1.683 + nsView *view = nsView::GetViewFor(win); 1.684 + NS_ASSERTION(view, "No view for widget"); 1.685 + nsPoint offset = view->GetOffsetTo(nullptr); 1.686 + 1.687 + if (offset.x || offset.y) { 1.688 + // in the case the two windows are offset from eachother, we do go ahead and return the correct enclosing window 1.689 + // so that mouse co-ordinates are not messed up. 1.690 + *pvalue = (void*)win->GetNativeData(NS_NATIVE_WINDOW); 1.691 + if (*pvalue) 1.692 + return NS_OK; 1.693 + } 1.694 + } 1.695 + } 1.696 +#endif 1.697 + // simply return the topmost document window 1.698 + nsCOMPtr<nsIWidget> widget; 1.699 + vm->GetRootWidget(getter_AddRefs(widget)); 1.700 + if (widget) { 1.701 + *pvalue = (void*)widget->GetNativeData(NS_NATIVE_WINDOW); 1.702 + } else { 1.703 + NS_ASSERTION(widget, "couldn't get doc's widget in getting doc's window handle"); 1.704 + } 1.705 + 1.706 + return NS_OK; 1.707 +#elif (defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_QT)) && defined(MOZ_X11) 1.708 + // X11 window managers want the toplevel window for WM_TRANSIENT_FOR. 1.709 + nsIWidget* win = mObjectFrame->GetNearestWidget(); 1.710 + if (!win) 1.711 + return NS_ERROR_FAILURE; 1.712 + *static_cast<Window*>(value) = (long unsigned int)win->GetNativeData(NS_NATIVE_SHAREABLE_WINDOW); 1.713 + return NS_OK; 1.714 +#else 1.715 + return NS_ERROR_NOT_IMPLEMENTED; 1.716 +#endif 1.717 +} 1.718 + 1.719 +NS_IMETHODIMP nsPluginInstanceOwner::SetEventModel(int32_t eventModel) 1.720 +{ 1.721 +#ifdef XP_MACOSX 1.722 + mEventModel = static_cast<NPEventModel>(eventModel); 1.723 + return NS_OK; 1.724 +#else 1.725 + return NS_ERROR_NOT_IMPLEMENTED; 1.726 +#endif 1.727 +} 1.728 + 1.729 +NPError nsPluginInstanceOwner::ShowNativeContextMenu(NPMenu* menu, void* event) 1.730 +{ 1.731 + if (!menu || !event) 1.732 + return NPERR_GENERIC_ERROR; 1.733 + 1.734 +#ifdef XP_MACOSX 1.735 + if (GetEventModel() != NPEventModelCocoa) 1.736 + return NPERR_INCOMPATIBLE_VERSION_ERROR; 1.737 + 1.738 + return NS_NPAPI_ShowCocoaContextMenu(static_cast<void*>(menu), mWidget, 1.739 + static_cast<NPCocoaEvent*>(event)); 1.740 +#else 1.741 + return NPERR_INCOMPATIBLE_VERSION_ERROR; 1.742 +#endif 1.743 +} 1.744 + 1.745 +NPBool nsPluginInstanceOwner::ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace, 1.746 + double *destX, double *destY, NPCoordinateSpace destSpace) 1.747 +{ 1.748 +#ifdef XP_MACOSX 1.749 + if (!mWidget) 1.750 + return false; 1.751 + 1.752 + return NS_NPAPI_ConvertPointCocoa(mWidget->GetNativeData(NS_NATIVE_WIDGET), 1.753 + sourceX, sourceY, sourceSpace, destX, destY, destSpace); 1.754 +#else 1.755 + // we should implement this for all platforms 1.756 + return false; 1.757 +#endif 1.758 +} 1.759 + 1.760 +NPError nsPluginInstanceOwner::InitAsyncSurface(NPSize *size, NPImageFormat format, 1.761 + void *initData, NPAsyncSurface *surface) 1.762 +{ 1.763 + return NPERR_INCOMPATIBLE_VERSION_ERROR; 1.764 +} 1.765 + 1.766 +NPError nsPluginInstanceOwner::FinalizeAsyncSurface(NPAsyncSurface *) 1.767 +{ 1.768 + return NPERR_INCOMPATIBLE_VERSION_ERROR; 1.769 +} 1.770 + 1.771 +void nsPluginInstanceOwner::SetCurrentAsyncSurface(NPAsyncSurface *, NPRect*) 1.772 +{ 1.773 +} 1.774 + 1.775 +NS_IMETHODIMP nsPluginInstanceOwner::GetTagType(nsPluginTagType *result) 1.776 +{ 1.777 + NS_ENSURE_ARG_POINTER(result); 1.778 + 1.779 + *result = nsPluginTagType_Unknown; 1.780 + 1.781 + nsIAtom *atom = mContent->Tag(); 1.782 + 1.783 + if (atom == nsGkAtoms::applet) 1.784 + *result = nsPluginTagType_Applet; 1.785 + else if (atom == nsGkAtoms::embed) 1.786 + *result = nsPluginTagType_Embed; 1.787 + else if (atom == nsGkAtoms::object) 1.788 + *result = nsPluginTagType_Object; 1.789 + 1.790 + return NS_OK; 1.791 +} 1.792 + 1.793 +NS_IMETHODIMP nsPluginInstanceOwner::GetParameters(uint16_t& n, const char*const*& names, const char*const*& values) 1.794 +{ 1.795 + nsresult rv = EnsureCachedAttrParamArrays(); 1.796 + NS_ENSURE_SUCCESS(rv, rv); 1.797 + 1.798 + n = mNumCachedParams; 1.799 + if (n) { 1.800 + names = (const char **)(mCachedAttrParamNames + mNumCachedAttrs + 1); 1.801 + values = (const char **)(mCachedAttrParamValues + mNumCachedAttrs + 1); 1.802 + } else 1.803 + names = values = nullptr; 1.804 + 1.805 + return rv; 1.806 +} 1.807 + 1.808 +NS_IMETHODIMP nsPluginInstanceOwner::GetParameter(const char* name, const char* *result) 1.809 +{ 1.810 + NS_ENSURE_ARG_POINTER(name); 1.811 + NS_ENSURE_ARG_POINTER(result); 1.812 + 1.813 + nsresult rv = EnsureCachedAttrParamArrays(); 1.814 + NS_ENSURE_SUCCESS(rv, rv); 1.815 + 1.816 + *result = nullptr; 1.817 + 1.818 + for (int i = mNumCachedAttrs + 1; i < (mNumCachedParams + 1 + mNumCachedAttrs); i++) { 1.819 + if (0 == PL_strcasecmp(mCachedAttrParamNames[i], name)) { 1.820 + *result = mCachedAttrParamValues[i]; 1.821 + return NS_OK; 1.822 + } 1.823 + } 1.824 + 1.825 + return NS_ERROR_FAILURE; 1.826 +} 1.827 + 1.828 + 1.829 +// Cache the attributes and/or parameters of our tag into a single set 1.830 +// of arrays to be compatible with Netscape 4.x. The attributes go first, 1.831 +// followed by a PARAM/null and then any PARAM tags. Also, hold the 1.832 +// cached array around for the duration of the life of the instance 1.833 +// because Netscape 4.x did. See bug 111008. 1.834 +nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays() 1.835 +{ 1.836 + if (mCachedAttrParamValues) 1.837 + return NS_OK; 1.838 + 1.839 + NS_PRECONDITION(((mNumCachedAttrs + mNumCachedParams) == 0) && 1.840 + !mCachedAttrParamNames, 1.841 + "re-cache of attrs/params not implemented! use the DOM " 1.842 + "node directy instead"); 1.843 + 1.844 + // Convert to a 16-bit count. Subtract 3 in case we add an extra 1.845 + // "src", "wmode", or "codebase" entry below. 1.846 + uint32_t cattrs = mContent->GetAttrCount(); 1.847 + if (cattrs < 0x0000FFFC) { 1.848 + mNumCachedAttrs = static_cast<uint16_t>(cattrs); 1.849 + } else { 1.850 + mNumCachedAttrs = 0xFFFC; 1.851 + } 1.852 + 1.853 + // Check if we are java for special codebase handling 1.854 + const char* mime = nullptr; 1.855 + bool isJava = NS_SUCCEEDED(mInstance->GetMIMEType(&mime)) && mime && 1.856 + nsPluginHost::IsJavaMIMEType(mime); 1.857 + 1.858 + // now, we need to find all the PARAM tags that are children of us 1.859 + // however, be careful not to include any PARAMs that don't have us 1.860 + // as a direct parent. For nested object (or applet) tags, be sure 1.861 + // to only round up the param tags that coorespond with THIS 1.862 + // instance. And also, weed out any bogus tags that may get in the 1.863 + // way, see bug 39609. Then, with any param tag that meet our 1.864 + // qualification, temporarly cache them in an nsCOMArray until 1.865 + // we can figure out what size to make our fixed char* array. 1.866 + nsCOMArray<nsIDOMElement> ourParams; 1.867 + 1.868 + // Get all dependent PARAM tags, even if they are not direct children. 1.869 + nsCOMPtr<nsIDOMElement> mydomElement = do_QueryInterface(mContent); 1.870 + NS_ENSURE_TRUE(mydomElement, NS_ERROR_NO_INTERFACE); 1.871 + 1.872 + // Making DOM method calls can cause our frame to go away. 1.873 + nsCOMPtr<nsIPluginInstanceOwner> kungFuDeathGrip(this); 1.874 + 1.875 + nsCOMPtr<nsIDOMHTMLCollection> allParams; 1.876 + NS_NAMED_LITERAL_STRING(xhtml_ns, "http://www.w3.org/1999/xhtml"); 1.877 + mydomElement->GetElementsByTagNameNS(xhtml_ns, NS_LITERAL_STRING("param"), 1.878 + getter_AddRefs(allParams)); 1.879 + if (allParams) { 1.880 + uint32_t numAllParams; 1.881 + allParams->GetLength(&numAllParams); 1.882 + for (uint32_t i = 0; i < numAllParams; i++) { 1.883 + nsCOMPtr<nsIDOMNode> pnode; 1.884 + allParams->Item(i, getter_AddRefs(pnode)); 1.885 + nsCOMPtr<nsIDOMElement> domelement = do_QueryInterface(pnode); 1.886 + if (domelement) { 1.887 + // Ignore params without a name attribute. 1.888 + nsAutoString name; 1.889 + domelement->GetAttribute(NS_LITERAL_STRING("name"), name); 1.890 + if (!name.IsEmpty()) { 1.891 + // Find the first object or applet parent. 1.892 + nsCOMPtr<nsIDOMNode> parent; 1.893 + nsCOMPtr<nsIDOMHTMLObjectElement> domobject; 1.894 + nsCOMPtr<nsIDOMHTMLAppletElement> domapplet; 1.895 + pnode->GetParentNode(getter_AddRefs(parent)); 1.896 + while (!(domobject || domapplet) && parent) { 1.897 + domobject = do_QueryInterface(parent); 1.898 + domapplet = do_QueryInterface(parent); 1.899 + nsCOMPtr<nsIDOMNode> temp; 1.900 + parent->GetParentNode(getter_AddRefs(temp)); 1.901 + parent = temp; 1.902 + } 1.903 + if (domapplet || domobject) { 1.904 + if (domapplet) { 1.905 + parent = do_QueryInterface(domapplet); 1.906 + } 1.907 + else { 1.908 + parent = do_QueryInterface(domobject); 1.909 + } 1.910 + nsCOMPtr<nsIDOMNode> mydomNode = do_QueryInterface(mydomElement); 1.911 + if (parent == mydomNode) { 1.912 + ourParams.AppendObject(domelement); 1.913 + } 1.914 + } 1.915 + } 1.916 + } 1.917 + } 1.918 + } 1.919 + 1.920 + // Convert to a 16-bit count. 1.921 + uint32_t cparams = ourParams.Count(); 1.922 + if (cparams < 0x0000FFFF) { 1.923 + mNumCachedParams = static_cast<uint16_t>(cparams); 1.924 + } else { 1.925 + mNumCachedParams = 0xFFFF; 1.926 + } 1.927 + 1.928 + uint16_t numRealAttrs = mNumCachedAttrs; 1.929 + 1.930 + // Some plugins were never written to understand the "data" attribute of the OBJECT tag. 1.931 + // Real and WMP will not play unless they find a "src" attribute, see bug 152334. 1.932 + // Nav 4.x would simply replace the "data" with "src". Because some plugins correctly 1.933 + // look for "data", lets instead copy the "data" attribute and add another entry 1.934 + // to the bottom of the array if there isn't already a "src" specified. 1.935 + nsAutoString data; 1.936 + if (mContent->Tag() == nsGkAtoms::object && 1.937 + !mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::src) && 1.938 + mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::data, data) && 1.939 + !data.IsEmpty()) { 1.940 + mNumCachedAttrs++; 1.941 + } 1.942 + 1.943 + // "plugins.force.wmode" forces us to send a specific "wmode" parameter, 1.944 + // used by flash to select a rendering mode. Common values include 1.945 + // "opaque", "transparent", "windowed", "direct" 1.946 + nsCString wmodeType; 1.947 + nsAdoptingCString wmodePref = Preferences::GetCString("plugins.force.wmode"); 1.948 + if (!wmodePref.IsEmpty()) { 1.949 + mNumCachedAttrs++; 1.950 + wmodeType = wmodePref; 1.951 + } 1.952 +#if defined(XP_WIN) || defined(XP_LINUX) 1.953 + // Bug 923745 - Until we support windowed mode plugins in content processes, 1.954 + // force flash to use a windowless rendering mode. This hack should go away 1.955 + // when bug 923746 lands. (OS X plugins always use some native widgets, so 1.956 + // unfortunately this does not help there) 1.957 + else if (XRE_GetProcessType() == GeckoProcessType_Content) { 1.958 + mNumCachedAttrs++; 1.959 + wmodeType.AssignLiteral("transparent"); 1.960 + } 1.961 +#endif 1.962 + 1.963 + // (Bug 738396) java has quirks in its codebase parsing, pass the 1.964 + // absolute codebase URI as content sees it. 1.965 + bool addCodebase = false; 1.966 + nsAutoCString codebaseStr; 1.967 + if (isJava) { 1.968 + nsCOMPtr<nsIObjectLoadingContent> objlc = do_QueryInterface(mContent); 1.969 + NS_ENSURE_TRUE(objlc, NS_ERROR_UNEXPECTED); 1.970 + nsCOMPtr<nsIURI> codebaseURI; 1.971 + nsresult rv = objlc->GetBaseURI(getter_AddRefs(codebaseURI)); 1.972 + NS_ENSURE_SUCCESS(rv, rv); 1.973 + codebaseURI->GetSpec(codebaseStr); 1.974 + if (!mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::codebase)) { 1.975 + mNumCachedAttrs++; 1.976 + addCodebase = true; 1.977 + } 1.978 + } 1.979 + 1.980 + mCachedAttrParamNames = (char**)NS_Alloc(sizeof(char*) * (mNumCachedAttrs + 1 + mNumCachedParams)); 1.981 + NS_ENSURE_TRUE(mCachedAttrParamNames, NS_ERROR_OUT_OF_MEMORY); 1.982 + mCachedAttrParamValues = (char**)NS_Alloc(sizeof(char*) * (mNumCachedAttrs + 1 + mNumCachedParams)); 1.983 + NS_ENSURE_TRUE(mCachedAttrParamValues, NS_ERROR_OUT_OF_MEMORY); 1.984 + 1.985 + // Some plugins (eg Flash, see bug 234675.) are actually sensitive to the 1.986 + // attribute order. So we want to make sure we give the plugin the 1.987 + // attributes in the order they came in in the source, to be compatible with 1.988 + // other browsers. Now in HTML, the storage order is the reverse of the 1.989 + // source order, while in XML and XHTML it's the same as the source order 1.990 + // (see the AddAttributes functions in the HTML and XML content sinks). 1.991 + int32_t start, end, increment; 1.992 + if (mContent->IsHTML() && 1.993 + mContent->IsInHTMLDocument()) { 1.994 + // HTML. Walk attributes in reverse order. 1.995 + start = numRealAttrs - 1; 1.996 + end = -1; 1.997 + increment = -1; 1.998 + } else { 1.999 + // XHTML or XML. Walk attributes in forward order. 1.1000 + start = 0; 1.1001 + end = numRealAttrs; 1.1002 + increment = 1; 1.1003 + } 1.1004 + 1.1005 + // Set to the next slot to fill in name and value cache arrays. 1.1006 + uint32_t nextAttrParamIndex = 0; 1.1007 + 1.1008 + // Whether or not we force the wmode below while traversing 1.1009 + // the name/value pairs. 1.1010 + bool wmodeSet = false; 1.1011 + 1.1012 + // Add attribute name/value pairs. 1.1013 + for (int32_t index = start; index != end; index += increment) { 1.1014 + const nsAttrName* attrName = mContent->GetAttrNameAt(index); 1.1015 + nsIAtom* atom = attrName->LocalName(); 1.1016 + nsAutoString value; 1.1017 + mContent->GetAttr(attrName->NamespaceID(), atom, value); 1.1018 + nsAutoString name; 1.1019 + atom->ToString(name); 1.1020 + 1.1021 + FixUpURLS(name, value); 1.1022 + 1.1023 + mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(name); 1.1024 + if (!wmodeType.IsEmpty() && 1.1025 + 0 == PL_strcasecmp(mCachedAttrParamNames[nextAttrParamIndex], "wmode")) { 1.1026 + mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_ConvertUTF8toUTF16(wmodeType)); 1.1027 + 1.1028 + if (!wmodeSet) { 1.1029 + // We allocated space to add a wmode attr, but we don't need it now. 1.1030 + mNumCachedAttrs--; 1.1031 + wmodeSet = true; 1.1032 + } 1.1033 + } else if (isJava && 0 == PL_strcasecmp(mCachedAttrParamNames[nextAttrParamIndex], "codebase")) { 1.1034 + mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_ConvertUTF8toUTF16(codebaseStr)); 1.1035 + } else { 1.1036 + mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(value); 1.1037 + } 1.1038 + nextAttrParamIndex++; 1.1039 + } 1.1040 + 1.1041 + // Potentially add CODEBASE attribute 1.1042 + if (addCodebase) { 1.1043 + mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("codebase")); 1.1044 + mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_ConvertUTF8toUTF16(codebaseStr)); 1.1045 + nextAttrParamIndex++; 1.1046 + } 1.1047 + 1.1048 + // Potentially add WMODE attribute. 1.1049 + if (!wmodeType.IsEmpty() && !wmodeSet) { 1.1050 + mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("wmode")); 1.1051 + mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_ConvertUTF8toUTF16(wmodeType)); 1.1052 + nextAttrParamIndex++; 1.1053 + } 1.1054 + 1.1055 + // Potentially add SRC attribute. 1.1056 + if (!data.IsEmpty()) { 1.1057 + mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("SRC")); 1.1058 + mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(data); 1.1059 + nextAttrParamIndex++; 1.1060 + } 1.1061 + 1.1062 + // Add PARAM and null separator. 1.1063 + mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("PARAM")); 1.1064 +#ifdef MOZ_WIDGET_ANDROID 1.1065 + // Flash expects an empty string on android 1.1066 + mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("")); 1.1067 +#else 1.1068 + mCachedAttrParamValues[nextAttrParamIndex] = nullptr; 1.1069 +#endif 1.1070 + nextAttrParamIndex++; 1.1071 + 1.1072 + // Add PARAM name/value pairs. 1.1073 + 1.1074 + // We may decrement mNumCachedParams below 1.1075 + uint16_t totalParams = mNumCachedParams; 1.1076 + for (uint16_t i = 0; i < totalParams; i++) { 1.1077 + nsIDOMElement* param = ourParams.ObjectAt(i); 1.1078 + if (!param) { 1.1079 + continue; 1.1080 + } 1.1081 + 1.1082 + nsAutoString name; 1.1083 + nsAutoString value; 1.1084 + param->GetAttribute(NS_LITERAL_STRING("name"), name); // check for empty done above 1.1085 + param->GetAttribute(NS_LITERAL_STRING("value"), value); 1.1086 + 1.1087 + FixUpURLS(name, value); 1.1088 + 1.1089 + /* 1.1090 + * According to the HTML 4.01 spec, at 1.1091 + * http://www.w3.org/TR/html4/types.html#type-cdata 1.1092 + * ''User agents may ignore leading and trailing 1.1093 + * white space in CDATA attribute values (e.g., " 1.1094 + * myval " may be interpreted as "myval"). Authors 1.1095 + * should not declare attribute values with 1.1096 + * leading or trailing white space.'' 1.1097 + * However, do not trim consecutive spaces as in bug 122119 1.1098 + */ 1.1099 + name.Trim(" \n\r\t\b", true, true, false); 1.1100 + value.Trim(" \n\r\t\b", true, true, false); 1.1101 + if (isJava && name.EqualsIgnoreCase("codebase")) { 1.1102 + // We inserted normalized codebase above, don't include other versions in 1.1103 + // params 1.1104 + mNumCachedParams--; 1.1105 + continue; 1.1106 + } 1.1107 + mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(name); 1.1108 + mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(value); 1.1109 + nextAttrParamIndex++; 1.1110 + } 1.1111 + 1.1112 + return NS_OK; 1.1113 +} 1.1114 + 1.1115 +#ifdef XP_MACOSX 1.1116 + 1.1117 +static void InitializeNPCocoaEvent(NPCocoaEvent* event) 1.1118 +{ 1.1119 + memset(event, 0, sizeof(NPCocoaEvent)); 1.1120 +} 1.1121 + 1.1122 +NPDrawingModel nsPluginInstanceOwner::GetDrawingModel() 1.1123 +{ 1.1124 +#ifndef NP_NO_QUICKDRAW 1.1125 + // We don't support the Quickdraw drawing model any more but it's still 1.1126 + // the default model for i386 per NPAPI. 1.1127 + NPDrawingModel drawingModel = NPDrawingModelQuickDraw; 1.1128 +#else 1.1129 + NPDrawingModel drawingModel = NPDrawingModelCoreGraphics; 1.1130 +#endif 1.1131 + 1.1132 + if (!mInstance) 1.1133 + return drawingModel; 1.1134 + 1.1135 + mInstance->GetDrawingModel((int32_t*)&drawingModel); 1.1136 + return drawingModel; 1.1137 +} 1.1138 + 1.1139 +bool nsPluginInstanceOwner::IsRemoteDrawingCoreAnimation() 1.1140 +{ 1.1141 + if (!mInstance) 1.1142 + return false; 1.1143 + 1.1144 + bool coreAnimation; 1.1145 + if (!NS_SUCCEEDED(mInstance->IsRemoteDrawingCoreAnimation(&coreAnimation))) 1.1146 + return false; 1.1147 + 1.1148 + return coreAnimation; 1.1149 +} 1.1150 + 1.1151 +nsresult nsPluginInstanceOwner::ContentsScaleFactorChanged(double aContentsScaleFactor) 1.1152 +{ 1.1153 + if (!mInstance) { 1.1154 + return NS_ERROR_NULL_POINTER; 1.1155 + } 1.1156 + return mInstance->ContentsScaleFactorChanged(aContentsScaleFactor); 1.1157 +} 1.1158 + 1.1159 +NPEventModel nsPluginInstanceOwner::GetEventModel() 1.1160 +{ 1.1161 + return mEventModel; 1.1162 +} 1.1163 + 1.1164 +#define DEFAULT_REFRESH_RATE 20 // 50 FPS 1.1165 + 1.1166 +nsCOMPtr<nsITimer> *nsPluginInstanceOwner::sCATimer = nullptr; 1.1167 +nsTArray<nsPluginInstanceOwner*> *nsPluginInstanceOwner::sCARefreshListeners = nullptr; 1.1168 + 1.1169 +void nsPluginInstanceOwner::CARefresh(nsITimer *aTimer, void *aClosure) { 1.1170 + if (!sCARefreshListeners) { 1.1171 + return; 1.1172 + } 1.1173 + for (size_t i = 0; i < sCARefreshListeners->Length(); i++) { 1.1174 + nsPluginInstanceOwner* instanceOwner = (*sCARefreshListeners)[i]; 1.1175 + NPWindow *window; 1.1176 + instanceOwner->GetWindow(window); 1.1177 + if (!window) { 1.1178 + continue; 1.1179 + } 1.1180 + NPRect r; 1.1181 + r.left = 0; 1.1182 + r.top = 0; 1.1183 + r.right = window->width; 1.1184 + r.bottom = window->height; 1.1185 + instanceOwner->InvalidateRect(&r); 1.1186 + } 1.1187 +} 1.1188 + 1.1189 +void nsPluginInstanceOwner::AddToCARefreshTimer() { 1.1190 + if (!mInstance) { 1.1191 + return; 1.1192 + } 1.1193 + 1.1194 + // Flash invokes InvalidateRect for us. 1.1195 + const char* mime = nullptr; 1.1196 + if (NS_SUCCEEDED(mInstance->GetMIMEType(&mime)) && mime) { 1.1197 + if (strcmp(mime, "application/x-shockwave-flash") == 0) { 1.1198 + return; 1.1199 + } 1.1200 + } 1.1201 + 1.1202 + if (!sCARefreshListeners) { 1.1203 + sCARefreshListeners = new nsTArray<nsPluginInstanceOwner*>(); 1.1204 + if (!sCARefreshListeners) { 1.1205 + return; 1.1206 + } 1.1207 + } 1.1208 + 1.1209 + if (sCARefreshListeners->Contains(this)) { 1.1210 + return; 1.1211 + } 1.1212 + 1.1213 + sCARefreshListeners->AppendElement(this); 1.1214 + 1.1215 + if (!sCATimer) { 1.1216 + sCATimer = new nsCOMPtr<nsITimer>(); 1.1217 + if (!sCATimer) { 1.1218 + return; 1.1219 + } 1.1220 + } 1.1221 + 1.1222 + if (sCARefreshListeners->Length() == 1) { 1.1223 + *sCATimer = do_CreateInstance("@mozilla.org/timer;1"); 1.1224 + (*sCATimer)->InitWithFuncCallback(CARefresh, nullptr, 1.1225 + DEFAULT_REFRESH_RATE, nsITimer::TYPE_REPEATING_SLACK); 1.1226 + } 1.1227 +} 1.1228 + 1.1229 +void nsPluginInstanceOwner::RemoveFromCARefreshTimer() { 1.1230 + if (!sCARefreshListeners || sCARefreshListeners->Contains(this) == false) { 1.1231 + return; 1.1232 + } 1.1233 + 1.1234 + sCARefreshListeners->RemoveElement(this); 1.1235 + 1.1236 + if (sCARefreshListeners->Length() == 0) { 1.1237 + if (sCATimer) { 1.1238 + (*sCATimer)->Cancel(); 1.1239 + delete sCATimer; 1.1240 + sCATimer = nullptr; 1.1241 + } 1.1242 + delete sCARefreshListeners; 1.1243 + sCARefreshListeners = nullptr; 1.1244 + } 1.1245 +} 1.1246 + 1.1247 +void nsPluginInstanceOwner::RenderCoreAnimation(CGContextRef aCGContext, 1.1248 + int aWidth, int aHeight) 1.1249 +{ 1.1250 + if (aWidth == 0 || aHeight == 0) 1.1251 + return; 1.1252 + 1.1253 + if (!mCARenderer) { 1.1254 + mCARenderer = new nsCARenderer(); 1.1255 + } 1.1256 + 1.1257 + // aWidth and aHeight are in "display pixels". In non-HiDPI modes 1.1258 + // "display pixels" are device pixels. But in HiDPI modes each 1.1259 + // display pixel corresponds to more than one device pixel. 1.1260 + double scaleFactor = 1.0; 1.1261 + GetContentsScaleFactor(&scaleFactor); 1.1262 + 1.1263 + if (!mIOSurface || 1.1264 + (mIOSurface->GetWidth() != (size_t)aWidth || 1.1265 + mIOSurface->GetHeight() != (size_t)aHeight || 1.1266 + mIOSurface->GetContentsScaleFactor() != scaleFactor)) { 1.1267 + mIOSurface = nullptr; 1.1268 + 1.1269 + // If the renderer is backed by an IOSurface, resize it as required. 1.1270 + mIOSurface = MacIOSurface::CreateIOSurface(aWidth, aHeight, scaleFactor); 1.1271 + if (mIOSurface) { 1.1272 + RefPtr<MacIOSurface> attachSurface = MacIOSurface::LookupSurface( 1.1273 + mIOSurface->GetIOSurfaceID(), 1.1274 + scaleFactor); 1.1275 + if (attachSurface) { 1.1276 + mCARenderer->AttachIOSurface(attachSurface); 1.1277 + } else { 1.1278 + NS_ERROR("IOSurface attachment failed"); 1.1279 + mIOSurface = nullptr; 1.1280 + } 1.1281 + } 1.1282 + } 1.1283 + 1.1284 + if (!mColorProfile) { 1.1285 + mColorProfile = CreateSystemColorSpace(); 1.1286 + } 1.1287 + 1.1288 + if (mCARenderer->isInit() == false) { 1.1289 + void *caLayer = nullptr; 1.1290 + nsresult rv = mInstance->GetValueFromPlugin(NPPVpluginCoreAnimationLayer, &caLayer); 1.1291 + if (NS_FAILED(rv) || !caLayer) { 1.1292 + return; 1.1293 + } 1.1294 + 1.1295 + // We don't run Flash in-process so we can unconditionally disallow 1.1296 + // the offliner renderer. 1.1297 + mCARenderer->SetupRenderer(caLayer, aWidth, aHeight, scaleFactor, 1.1298 + DISALLOW_OFFLINE_RENDERER); 1.1299 + 1.1300 + // Setting up the CALayer requires resetting the painting otherwise we 1.1301 + // get garbage for the first few frames. 1.1302 + FixUpPluginWindow(ePluginPaintDisable); 1.1303 + FixUpPluginWindow(ePluginPaintEnable); 1.1304 + } 1.1305 + 1.1306 + CGImageRef caImage = nullptr; 1.1307 + nsresult rt = mCARenderer->Render(aWidth, aHeight, scaleFactor, &caImage); 1.1308 + if (rt == NS_OK && mIOSurface && mColorProfile) { 1.1309 + nsCARenderer::DrawSurfaceToCGContext(aCGContext, mIOSurface, mColorProfile, 1.1310 + 0, 0, aWidth, aHeight); 1.1311 + } else if (rt == NS_OK && caImage != nullptr) { 1.1312 + // Significant speed up by resetting the scaling 1.1313 + ::CGContextSetInterpolationQuality(aCGContext, kCGInterpolationNone ); 1.1314 + ::CGContextTranslateCTM(aCGContext, 0, (double) aHeight * scaleFactor); 1.1315 + ::CGContextScaleCTM(aCGContext, scaleFactor, -scaleFactor); 1.1316 + 1.1317 + ::CGContextDrawImage(aCGContext, CGRectMake(0,0,aWidth,aHeight), caImage); 1.1318 + } else { 1.1319 + NS_NOTREACHED("nsCARenderer::Render failure"); 1.1320 + } 1.1321 +} 1.1322 + 1.1323 +void* nsPluginInstanceOwner::GetPluginPortCopy() 1.1324 +{ 1.1325 + if (GetDrawingModel() == NPDrawingModelCoreGraphics || 1.1326 + GetDrawingModel() == NPDrawingModelCoreAnimation || 1.1327 + GetDrawingModel() == NPDrawingModelInvalidatingCoreAnimation) 1.1328 + return &mCGPluginPortCopy; 1.1329 + return nullptr; 1.1330 +} 1.1331 + 1.1332 +// Currently (on OS X in Cocoa widgets) any changes made as a result of 1.1333 +// calling GetPluginPortFromWidget() are immediately reflected in the NPWindow 1.1334 +// structure that has been passed to the plugin via SetWindow(). This is 1.1335 +// because calls to nsChildView::GetNativeData(NS_NATIVE_PLUGIN_PORT_CG) 1.1336 +// always return a pointer to the same internal (private) object, but may 1.1337 +// make changes inside that object. All calls to GetPluginPortFromWidget() made while 1.1338 +// the plugin is active (i.e. excluding those made at our initialization) 1.1339 +// need to take this into account. The easiest way to do so is to replace 1.1340 +// them with calls to SetPluginPortAndDetectChange(). This method keeps track 1.1341 +// of when calls to GetPluginPortFromWidget() result in changes, and sets a flag to make 1.1342 +// sure SetWindow() gets called the next time through FixUpPluginWindow(), so 1.1343 +// that the plugin is notified of these changes. 1.1344 +void* nsPluginInstanceOwner::SetPluginPortAndDetectChange() 1.1345 +{ 1.1346 + if (!mPluginWindow) 1.1347 + return nullptr; 1.1348 + void* pluginPort = GetPluginPortFromWidget(); 1.1349 + if (!pluginPort) 1.1350 + return nullptr; 1.1351 + mPluginWindow->window = pluginPort; 1.1352 + 1.1353 + return mPluginWindow->window; 1.1354 +} 1.1355 + 1.1356 +void nsPluginInstanceOwner::BeginCGPaint() 1.1357 +{ 1.1358 + ++mInCGPaintLevel; 1.1359 +} 1.1360 + 1.1361 +void nsPluginInstanceOwner::EndCGPaint() 1.1362 +{ 1.1363 + --mInCGPaintLevel; 1.1364 + NS_ASSERTION(mInCGPaintLevel >= 0, "Mismatched call to nsPluginInstanceOwner::EndCGPaint()!"); 1.1365 +} 1.1366 + 1.1367 +#endif 1.1368 + 1.1369 +// static 1.1370 +uint32_t 1.1371 +nsPluginInstanceOwner::GetEventloopNestingLevel() 1.1372 +{ 1.1373 + nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID); 1.1374 + uint32_t currentLevel = 0; 1.1375 + if (appShell) { 1.1376 + appShell->GetEventloopNestingLevel(¤tLevel); 1.1377 +#ifdef XP_MACOSX 1.1378 + // Cocoa widget code doesn't process UI events through the normal 1.1379 + // appshell event loop, so it needs an additional count here. 1.1380 + currentLevel++; 1.1381 +#endif 1.1382 + } 1.1383 + 1.1384 + // No idea how this happens... but Linux doesn't consistently 1.1385 + // process UI events through the appshell event loop. If we get a 0 1.1386 + // here on any platform we increment the level just in case so that 1.1387 + // we make sure we always tear the plugin down eventually. 1.1388 + if (!currentLevel) { 1.1389 + currentLevel++; 1.1390 + } 1.1391 + 1.1392 + return currentLevel; 1.1393 +} 1.1394 + 1.1395 +#ifdef MOZ_WIDGET_ANDROID 1.1396 + 1.1397 +// Modified version of nsFrame::GetOffsetToCrossDoc that stops when it 1.1398 +// hits an element with a displayport (or runs out of frames). This is 1.1399 +// not really the right thing to do, but it's better than what was here before. 1.1400 +static nsPoint 1.1401 +GetOffsetRootContent(nsIFrame* aFrame) 1.1402 +{ 1.1403 + // offset will hold the final offset 1.1404 + // docOffset holds the currently accumulated offset at the current APD, it 1.1405 + // will be converted and added to offset when the current APD changes. 1.1406 + nsPoint offset(0, 0), docOffset(0, 0); 1.1407 + const nsIFrame* f = aFrame; 1.1408 + int32_t currAPD = aFrame->PresContext()->AppUnitsPerDevPixel(); 1.1409 + int32_t apd = currAPD; 1.1410 + nsRect displayPort; 1.1411 + while (f) { 1.1412 + if (f->GetContent() && nsLayoutUtils::GetDisplayPort(f->GetContent(), &displayPort)) 1.1413 + break; 1.1414 + 1.1415 + docOffset += f->GetPosition(); 1.1416 + nsIFrame* parent = f->GetParent(); 1.1417 + if (parent) { 1.1418 + f = parent; 1.1419 + } else { 1.1420 + nsPoint newOffset(0, 0); 1.1421 + f = nsLayoutUtils::GetCrossDocParentFrame(f, &newOffset); 1.1422 + int32_t newAPD = f ? f->PresContext()->AppUnitsPerDevPixel() : 0; 1.1423 + if (!f || newAPD != currAPD) { 1.1424 + // Convert docOffset to the right APD and add it to offset. 1.1425 + offset += docOffset.ConvertAppUnits(currAPD, apd); 1.1426 + docOffset.x = docOffset.y = 0; 1.1427 + } 1.1428 + currAPD = newAPD; 1.1429 + docOffset += newOffset; 1.1430 + } 1.1431 + } 1.1432 + 1.1433 + offset += docOffset.ConvertAppUnits(currAPD, apd); 1.1434 + 1.1435 + return offset; 1.1436 +} 1.1437 + 1.1438 +LayoutDeviceRect nsPluginInstanceOwner::GetPluginRect() 1.1439 +{ 1.1440 + // Get the offset of the content relative to the page 1.1441 + nsRect bounds = mObjectFrame->GetContentRectRelativeToSelf() + GetOffsetRootContent(mObjectFrame); 1.1442 + LayoutDeviceIntRect rect = LayoutDeviceIntRect::FromAppUnitsToNearest(bounds, mObjectFrame->PresContext()->AppUnitsPerDevPixel()); 1.1443 + return LayoutDeviceRect(rect); 1.1444 +} 1.1445 + 1.1446 +bool nsPluginInstanceOwner::AddPluginView(const LayoutDeviceRect& aRect /* = LayoutDeviceRect(0, 0, 0, 0) */) 1.1447 +{ 1.1448 + if (!mJavaView) { 1.1449 + mJavaView = mInstance->GetJavaSurface(); 1.1450 + 1.1451 + if (!mJavaView) 1.1452 + return false; 1.1453 + 1.1454 + mJavaView = (void*)AndroidBridge::GetJNIEnv()->NewGlobalRef((jobject)mJavaView); 1.1455 + } 1.1456 + 1.1457 + if (AndroidBridge::Bridge()) 1.1458 + AndroidBridge::Bridge()->AddPluginView((jobject)mJavaView, aRect, mFullScreen); 1.1459 + 1.1460 + if (mFullScreen) 1.1461 + sFullScreenInstance = this; 1.1462 + 1.1463 + return true; 1.1464 +} 1.1465 + 1.1466 +void nsPluginInstanceOwner::RemovePluginView() 1.1467 +{ 1.1468 + if (!mInstance || !mJavaView) 1.1469 + return; 1.1470 + 1.1471 + mozilla::widget::android::GeckoAppShell::RemovePluginView((jobject)mJavaView, mFullScreen); 1.1472 + AndroidBridge::GetJNIEnv()->DeleteGlobalRef((jobject)mJavaView); 1.1473 + mJavaView = nullptr; 1.1474 + 1.1475 + if (mFullScreen) 1.1476 + sFullScreenInstance = nullptr; 1.1477 +} 1.1478 + 1.1479 +void nsPluginInstanceOwner::GetVideos(nsTArray<nsNPAPIPluginInstance::VideoInfo*>& aVideos) 1.1480 +{ 1.1481 + if (!mInstance) 1.1482 + return; 1.1483 + 1.1484 + mInstance->GetVideos(aVideos); 1.1485 +} 1.1486 + 1.1487 +already_AddRefed<ImageContainer> nsPluginInstanceOwner::GetImageContainerForVideo(nsNPAPIPluginInstance::VideoInfo* aVideoInfo) 1.1488 +{ 1.1489 + nsRefPtr<ImageContainer> container = LayerManager::CreateImageContainer(); 1.1490 + 1.1491 + nsRefPtr<Image> img = container->CreateImage(ImageFormat::SHARED_TEXTURE); 1.1492 + 1.1493 + SharedTextureImage::Data data; 1.1494 + 1.1495 + data.mShareType = gl::SharedTextureShareType::SameProcess; 1.1496 + data.mHandle = gl::CreateSharedHandle(mInstance->GLContext(), 1.1497 + data.mShareType, 1.1498 + aVideoInfo->mSurfaceTexture, 1.1499 + gl::SharedTextureBufferType::SurfaceTexture); 1.1500 + 1.1501 + // The logic below for Honeycomb is just a guess, but seems to work. We don't have a separate 1.1502 + // inverted flag for video. 1.1503 + data.mInverted = AndroidBridge::Bridge()->IsHoneycomb() ? true : mInstance->Inverted(); 1.1504 + data.mSize = gfx::IntSize(aVideoInfo->mDimensions.width, aVideoInfo->mDimensions.height); 1.1505 + 1.1506 + SharedTextureImage* pluginImage = static_cast<SharedTextureImage*>(img.get()); 1.1507 + pluginImage->SetData(data); 1.1508 + container->SetCurrentImageInTransaction(img); 1.1509 + 1.1510 + return container.forget(); 1.1511 +} 1.1512 + 1.1513 +void nsPluginInstanceOwner::Invalidate() { 1.1514 + NPRect rect; 1.1515 + rect.left = rect.top = 0; 1.1516 + rect.right = mPluginWindow->width; 1.1517 + rect.bottom = mPluginWindow->height; 1.1518 + InvalidateRect(&rect); 1.1519 +} 1.1520 + 1.1521 +void nsPluginInstanceOwner::RequestFullScreen() { 1.1522 + if (mFullScreen) 1.1523 + return; 1.1524 + 1.1525 + // Remove whatever view we currently have (if any, fullscreen or otherwise) 1.1526 + RemovePluginView(); 1.1527 + 1.1528 + mFullScreen = true; 1.1529 + AddPluginView(); 1.1530 + 1.1531 + mInstance->NotifyFullScreen(mFullScreen); 1.1532 +} 1.1533 + 1.1534 +void nsPluginInstanceOwner::ExitFullScreen() { 1.1535 + if (!mFullScreen) 1.1536 + return; 1.1537 + 1.1538 + RemovePluginView(); 1.1539 + 1.1540 + mFullScreen = false; 1.1541 + 1.1542 + int32_t model = mInstance->GetANPDrawingModel(); 1.1543 + 1.1544 + if (model == kSurface_ANPDrawingModel) { 1.1545 + // We need to do this immediately, otherwise Flash 1.1546 + // sometimes causes a deadlock (bug 762407) 1.1547 + AddPluginView(GetPluginRect()); 1.1548 + } 1.1549 + 1.1550 + mInstance->NotifyFullScreen(mFullScreen); 1.1551 + 1.1552 + // This will cause Paint() to be called, which is where 1.1553 + // we normally add/update views and layers 1.1554 + Invalidate(); 1.1555 +} 1.1556 + 1.1557 +void nsPluginInstanceOwner::ExitFullScreen(jobject view) { 1.1558 + JNIEnv* env = AndroidBridge::GetJNIEnv(); 1.1559 + 1.1560 + if (sFullScreenInstance && sFullScreenInstance->mInstance && 1.1561 + env->IsSameObject(view, (jobject)sFullScreenInstance->mInstance->GetJavaSurface())) { 1.1562 + sFullScreenInstance->ExitFullScreen(); 1.1563 + } 1.1564 +} 1.1565 + 1.1566 +#endif 1.1567 + 1.1568 +nsresult nsPluginInstanceOwner::DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent) 1.1569 +{ 1.1570 +#ifdef MOZ_WIDGET_ANDROID 1.1571 + if (mInstance) { 1.1572 + ANPEvent event; 1.1573 + event.inSize = sizeof(ANPEvent); 1.1574 + event.eventType = kLifecycle_ANPEventType; 1.1575 + 1.1576 + nsAutoString eventType; 1.1577 + aFocusEvent->GetType(eventType); 1.1578 + if (eventType.EqualsLiteral("focus")) { 1.1579 + event.data.lifecycle.action = kGainFocus_ANPLifecycleAction; 1.1580 + } 1.1581 + else if (eventType.EqualsLiteral("blur")) { 1.1582 + event.data.lifecycle.action = kLoseFocus_ANPLifecycleAction; 1.1583 + } 1.1584 + else { 1.1585 + NS_ASSERTION(false, "nsPluginInstanceOwner::DispatchFocusToPlugin, wierd eventType"); 1.1586 + } 1.1587 + mInstance->HandleEvent(&event, nullptr); 1.1588 + } 1.1589 +#endif 1.1590 + 1.1591 +#ifndef XP_MACOSX 1.1592 + if (!mPluginWindow || (mPluginWindow->type == NPWindowTypeWindow)) { 1.1593 + // continue only for cases without child window 1.1594 + return aFocusEvent->PreventDefault(); // consume event 1.1595 + } 1.1596 +#endif 1.1597 + 1.1598 + WidgetEvent* theEvent = aFocusEvent->GetInternalNSEvent(); 1.1599 + if (theEvent) { 1.1600 + // we only care about the message in ProcessEvent 1.1601 + WidgetGUIEvent focusEvent(theEvent->mFlags.mIsTrusted, theEvent->message, 1.1602 + nullptr); 1.1603 + nsEventStatus rv = ProcessEvent(focusEvent); 1.1604 + if (nsEventStatus_eConsumeNoDefault == rv) { 1.1605 + aFocusEvent->PreventDefault(); 1.1606 + aFocusEvent->StopPropagation(); 1.1607 + } 1.1608 + } 1.1609 + 1.1610 + return NS_OK; 1.1611 +} 1.1612 + 1.1613 +nsresult nsPluginInstanceOwner::ProcessKeyPress(nsIDOMEvent* aKeyEvent) 1.1614 +{ 1.1615 +#ifdef XP_MACOSX 1.1616 + return DispatchKeyToPlugin(aKeyEvent); 1.1617 +#else 1.1618 + if (SendNativeEvents()) 1.1619 + DispatchKeyToPlugin(aKeyEvent); 1.1620 + 1.1621 + if (mInstance) { 1.1622 + // If this event is going to the plugin, we want to kill it. 1.1623 + // Not actually sending keypress to the plugin, since we didn't before. 1.1624 + aKeyEvent->PreventDefault(); 1.1625 + aKeyEvent->StopPropagation(); 1.1626 + } 1.1627 + return NS_OK; 1.1628 +#endif 1.1629 +} 1.1630 + 1.1631 +nsresult nsPluginInstanceOwner::DispatchKeyToPlugin(nsIDOMEvent* aKeyEvent) 1.1632 +{ 1.1633 +#if !defined(XP_MACOSX) 1.1634 + if (!mPluginWindow || (mPluginWindow->type == NPWindowTypeWindow)) 1.1635 + return aKeyEvent->PreventDefault(); // consume event 1.1636 + // continue only for cases without child window 1.1637 +#endif 1.1638 + 1.1639 + if (mInstance) { 1.1640 + WidgetKeyboardEvent* keyEvent = 1.1641 + aKeyEvent->GetInternalNSEvent()->AsKeyboardEvent(); 1.1642 + if (keyEvent && keyEvent->eventStructType == NS_KEY_EVENT) { 1.1643 + nsEventStatus rv = ProcessEvent(*keyEvent); 1.1644 + if (nsEventStatus_eConsumeNoDefault == rv) { 1.1645 + aKeyEvent->PreventDefault(); 1.1646 + aKeyEvent->StopPropagation(); 1.1647 + } 1.1648 + } 1.1649 + } 1.1650 + 1.1651 + return NS_OK; 1.1652 +} 1.1653 + 1.1654 +nsresult 1.1655 +nsPluginInstanceOwner::ProcessMouseDown(nsIDOMEvent* aMouseEvent) 1.1656 +{ 1.1657 +#if !defined(XP_MACOSX) 1.1658 + if (!mPluginWindow || (mPluginWindow->type == NPWindowTypeWindow)) 1.1659 + return aMouseEvent->PreventDefault(); // consume event 1.1660 + // continue only for cases without child window 1.1661 +#endif 1.1662 + 1.1663 + // if the plugin is windowless, we need to set focus ourselves 1.1664 + // otherwise, we might not get key events 1.1665 + if (mObjectFrame && mPluginWindow && 1.1666 + mPluginWindow->type == NPWindowTypeDrawable) { 1.1667 + 1.1668 + nsIFocusManager* fm = nsFocusManager::GetFocusManager(); 1.1669 + if (fm) { 1.1670 + nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(mContent); 1.1671 + fm->SetFocus(elem, 0); 1.1672 + } 1.1673 + } 1.1674 + 1.1675 + WidgetMouseEvent* mouseEvent = 1.1676 + aMouseEvent->GetInternalNSEvent()->AsMouseEvent(); 1.1677 + if (mouseEvent && mouseEvent->eventStructType == NS_MOUSE_EVENT) { 1.1678 + mLastMouseDownButtonType = mouseEvent->button; 1.1679 + nsEventStatus rv = ProcessEvent(*mouseEvent); 1.1680 + if (nsEventStatus_eConsumeNoDefault == rv) { 1.1681 + return aMouseEvent->PreventDefault(); // consume event 1.1682 + } 1.1683 + } 1.1684 + 1.1685 + return NS_OK; 1.1686 +} 1.1687 + 1.1688 +nsresult nsPluginInstanceOwner::DispatchMouseToPlugin(nsIDOMEvent* aMouseEvent, 1.1689 + bool aAllowPropagate) 1.1690 +{ 1.1691 +#if !defined(XP_MACOSX) 1.1692 + if (!mPluginWindow || (mPluginWindow->type == NPWindowTypeWindow)) 1.1693 + return aMouseEvent->PreventDefault(); // consume event 1.1694 + // continue only for cases without child window 1.1695 +#endif 1.1696 + // don't send mouse events if we are hidden 1.1697 + if (!mWidgetVisible) 1.1698 + return NS_OK; 1.1699 + 1.1700 + WidgetMouseEvent* mouseEvent = 1.1701 + aMouseEvent->GetInternalNSEvent()->AsMouseEvent(); 1.1702 + if (mouseEvent && mouseEvent->eventStructType == NS_MOUSE_EVENT) { 1.1703 + nsEventStatus rv = ProcessEvent(*mouseEvent); 1.1704 + if (nsEventStatus_eConsumeNoDefault == rv) { 1.1705 + aMouseEvent->PreventDefault(); 1.1706 + if (!aAllowPropagate) { 1.1707 + aMouseEvent->StopPropagation(); 1.1708 + } 1.1709 + } 1.1710 + if (mouseEvent->message == NS_MOUSE_BUTTON_UP) { 1.1711 + mLastMouseDownButtonType = -1; 1.1712 + } 1.1713 + } 1.1714 + return NS_OK; 1.1715 +} 1.1716 + 1.1717 +nsresult 1.1718 +nsPluginInstanceOwner::HandleEvent(nsIDOMEvent* aEvent) 1.1719 +{ 1.1720 + NS_ASSERTION(mInstance, "Should have a valid plugin instance or not receive events."); 1.1721 + 1.1722 + nsAutoString eventType; 1.1723 + aEvent->GetType(eventType); 1.1724 + if (eventType.EqualsLiteral("focus")) { 1.1725 + mContentFocused = true; 1.1726 + return DispatchFocusToPlugin(aEvent); 1.1727 + } 1.1728 + if (eventType.EqualsLiteral("blur")) { 1.1729 + mContentFocused = false; 1.1730 + return DispatchFocusToPlugin(aEvent); 1.1731 + } 1.1732 + if (eventType.EqualsLiteral("mousedown")) { 1.1733 + return ProcessMouseDown(aEvent); 1.1734 + } 1.1735 + if (eventType.EqualsLiteral("mouseup")) { 1.1736 + // Don't send a mouse-up event to the plugin if its button type doesn't 1.1737 + // match that of the preceding mouse-down event (if any). This kind of 1.1738 + // mismatch can happen if the previous mouse-down event was sent to a DOM 1.1739 + // element above the plugin, the mouse is still above the plugin, and the 1.1740 + // mouse-down event caused the element to disappear. See bug 627649 and 1.1741 + // bug 909678. 1.1742 + WidgetMouseEvent* mouseEvent = aEvent->GetInternalNSEvent()->AsMouseEvent(); 1.1743 + if (mouseEvent && 1.1744 + static_cast<int>(mouseEvent->button) != mLastMouseDownButtonType) { 1.1745 + aEvent->PreventDefault(); 1.1746 + return NS_OK; 1.1747 + } 1.1748 + return DispatchMouseToPlugin(aEvent); 1.1749 + } 1.1750 + if (eventType.EqualsLiteral("mousemove")) { 1.1751 + return DispatchMouseToPlugin(aEvent, true); 1.1752 + } 1.1753 + if (eventType.EqualsLiteral("click") || 1.1754 + eventType.EqualsLiteral("dblclick") || 1.1755 + eventType.EqualsLiteral("mouseover") || 1.1756 + eventType.EqualsLiteral("mouseout")) { 1.1757 + return DispatchMouseToPlugin(aEvent); 1.1758 + } 1.1759 + if (eventType.EqualsLiteral("keydown") || 1.1760 + eventType.EqualsLiteral("keyup")) { 1.1761 + return DispatchKeyToPlugin(aEvent); 1.1762 + } 1.1763 + if (eventType.EqualsLiteral("keypress")) { 1.1764 + return ProcessKeyPress(aEvent); 1.1765 + } 1.1766 + 1.1767 + nsCOMPtr<nsIDOMDragEvent> dragEvent(do_QueryInterface(aEvent)); 1.1768 + if (dragEvent && mInstance) { 1.1769 + WidgetEvent* ievent = aEvent->GetInternalNSEvent(); 1.1770 + if ((ievent && ievent->mFlags.mIsTrusted) && 1.1771 + ievent->message != NS_DRAGDROP_ENTER && ievent->message != NS_DRAGDROP_OVER) { 1.1772 + aEvent->PreventDefault(); 1.1773 + } 1.1774 + 1.1775 + // Let the plugin handle drag events. 1.1776 + aEvent->StopPropagation(); 1.1777 + } 1.1778 + return NS_OK; 1.1779 +} 1.1780 + 1.1781 +#ifdef MOZ_X11 1.1782 +static unsigned int XInputEventState(const WidgetInputEvent& anEvent) 1.1783 +{ 1.1784 + unsigned int state = 0; 1.1785 + if (anEvent.IsShift()) state |= ShiftMask; 1.1786 + if (anEvent.IsControl()) state |= ControlMask; 1.1787 + if (anEvent.IsAlt()) state |= Mod1Mask; 1.1788 + if (anEvent.IsMeta()) state |= Mod4Mask; 1.1789 + return state; 1.1790 +} 1.1791 +#endif 1.1792 + 1.1793 +nsEventStatus nsPluginInstanceOwner::ProcessEvent(const WidgetGUIEvent& anEvent) 1.1794 +{ 1.1795 + nsEventStatus rv = nsEventStatus_eIgnore; 1.1796 + 1.1797 + if (!mInstance || !mObjectFrame) // if mInstance is null, we shouldn't be here 1.1798 + return nsEventStatus_eIgnore; 1.1799 + 1.1800 +#ifdef XP_MACOSX 1.1801 + if (!mWidget) 1.1802 + return nsEventStatus_eIgnore; 1.1803 + 1.1804 + // we never care about synthesized mouse enter 1.1805 + if (anEvent.message == NS_MOUSE_ENTER_SYNTH) 1.1806 + return nsEventStatus_eIgnore; 1.1807 + 1.1808 + nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget); 1.1809 + if (!pluginWidget || NS_FAILED(pluginWidget->StartDrawPlugin())) 1.1810 + return nsEventStatus_eIgnore; 1.1811 + 1.1812 + NPEventModel eventModel = GetEventModel(); 1.1813 + 1.1814 + // If we have to synthesize an event we'll use one of these. 1.1815 + NPCocoaEvent synthCocoaEvent; 1.1816 + void* event = anEvent.pluginEvent; 1.1817 + nsPoint pt = 1.1818 + nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mObjectFrame) - 1.1819 + mObjectFrame->GetContentRectRelativeToSelf().TopLeft(); 1.1820 + nsPresContext* presContext = mObjectFrame->PresContext(); 1.1821 + // Plugin event coordinates need to be translated from device pixels 1.1822 + // into "display pixels" in HiDPI modes. 1.1823 + double scaleFactor = 1.0; 1.1824 + GetContentsScaleFactor(&scaleFactor); 1.1825 + size_t intScaleFactor = ceil(scaleFactor); 1.1826 + nsIntPoint ptPx(presContext->AppUnitsToDevPixels(pt.x) / intScaleFactor, 1.1827 + presContext->AppUnitsToDevPixels(pt.y) / intScaleFactor); 1.1828 + 1.1829 + if (!event) { 1.1830 + InitializeNPCocoaEvent(&synthCocoaEvent); 1.1831 + switch (anEvent.message) { 1.1832 + case NS_MOUSE_MOVE: 1.1833 + { 1.1834 + // Ignore mouse-moved events that happen as part of a dragging 1.1835 + // operation that started over another frame. See bug 525078. 1.1836 + nsRefPtr<nsFrameSelection> frameselection = mObjectFrame->GetFrameSelection(); 1.1837 + if (!frameselection->GetMouseDownState() || 1.1838 + (nsIPresShell::GetCapturingContent() == mObjectFrame->GetContent())) { 1.1839 + synthCocoaEvent.type = NPCocoaEventMouseMoved; 1.1840 + synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x); 1.1841 + synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y); 1.1842 + event = &synthCocoaEvent; 1.1843 + } 1.1844 + } 1.1845 + break; 1.1846 + case NS_MOUSE_BUTTON_DOWN: 1.1847 + synthCocoaEvent.type = NPCocoaEventMouseDown; 1.1848 + synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x); 1.1849 + synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y); 1.1850 + event = &synthCocoaEvent; 1.1851 + break; 1.1852 + case NS_MOUSE_BUTTON_UP: 1.1853 + // If we're in a dragging operation that started over another frame, 1.1854 + // convert it into a mouse-entered event (in the Cocoa Event Model). 1.1855 + // See bug 525078. 1.1856 + if (anEvent.AsMouseEvent()->button == WidgetMouseEvent::eLeftButton && 1.1857 + (nsIPresShell::GetCapturingContent() != mObjectFrame->GetContent())) { 1.1858 + synthCocoaEvent.type = NPCocoaEventMouseEntered; 1.1859 + synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x); 1.1860 + synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y); 1.1861 + event = &synthCocoaEvent; 1.1862 + } else { 1.1863 + synthCocoaEvent.type = NPCocoaEventMouseUp; 1.1864 + synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x); 1.1865 + synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y); 1.1866 + event = &synthCocoaEvent; 1.1867 + } 1.1868 + break; 1.1869 + default: 1.1870 + break; 1.1871 + } 1.1872 + 1.1873 + // If we still don't have an event, bail. 1.1874 + if (!event) { 1.1875 + pluginWidget->EndDrawPlugin(); 1.1876 + return nsEventStatus_eIgnore; 1.1877 + } 1.1878 + } 1.1879 + 1.1880 + int16_t response = kNPEventNotHandled; 1.1881 + void* window = FixUpPluginWindow(ePluginPaintEnable); 1.1882 + if (window || (eventModel == NPEventModelCocoa)) { 1.1883 + mInstance->HandleEvent(event, &response, NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO); 1.1884 + } 1.1885 + 1.1886 + if (eventModel == NPEventModelCocoa && response == kNPEventStartIME) { 1.1887 + pluginWidget->StartComplexTextInputForCurrentEvent(); 1.1888 + } 1.1889 + 1.1890 + if ((response == kNPEventHandled || response == kNPEventStartIME) && 1.1891 + !(anEvent.message == NS_MOUSE_BUTTON_DOWN && 1.1892 + anEvent.AsMouseEvent()->button == WidgetMouseEvent::eLeftButton && 1.1893 + !mContentFocused)) { 1.1894 + rv = nsEventStatus_eConsumeNoDefault; 1.1895 + } 1.1896 + 1.1897 + pluginWidget->EndDrawPlugin(); 1.1898 +#endif 1.1899 + 1.1900 +#ifdef XP_WIN 1.1901 + // this code supports windowless plugins 1.1902 + NPEvent *pPluginEvent = (NPEvent*)anEvent.pluginEvent; 1.1903 + // we can get synthetic events from the EventStateManager... these 1.1904 + // have no pluginEvent 1.1905 + NPEvent pluginEvent; 1.1906 + if (anEvent.eventStructType == NS_MOUSE_EVENT) { 1.1907 + if (!pPluginEvent) { 1.1908 + // XXX Should extend this list to synthesize events for more event 1.1909 + // types 1.1910 + pluginEvent.event = 0; 1.1911 + const WidgetMouseEvent* mouseEvent = anEvent.AsMouseEvent(); 1.1912 + switch (anEvent.message) { 1.1913 + case NS_MOUSE_MOVE: 1.1914 + pluginEvent.event = WM_MOUSEMOVE; 1.1915 + break; 1.1916 + case NS_MOUSE_BUTTON_DOWN: { 1.1917 + static const int downMsgs[] = 1.1918 + { WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN }; 1.1919 + static const int dblClickMsgs[] = 1.1920 + { WM_LBUTTONDBLCLK, WM_MBUTTONDBLCLK, WM_RBUTTONDBLCLK }; 1.1921 + if (mouseEvent->clickCount == 2) { 1.1922 + pluginEvent.event = dblClickMsgs[mouseEvent->button]; 1.1923 + } else { 1.1924 + pluginEvent.event = downMsgs[mouseEvent->button]; 1.1925 + } 1.1926 + break; 1.1927 + } 1.1928 + case NS_MOUSE_BUTTON_UP: { 1.1929 + static const int upMsgs[] = 1.1930 + { WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP }; 1.1931 + pluginEvent.event = upMsgs[mouseEvent->button]; 1.1932 + break; 1.1933 + } 1.1934 + // don't synthesize anything for NS_MOUSE_DOUBLECLICK, since that 1.1935 + // is a synthetic event generated on mouse-up, and Windows WM_*DBLCLK 1.1936 + // messages are sent on mouse-down 1.1937 + default: 1.1938 + break; 1.1939 + } 1.1940 + if (pluginEvent.event) { 1.1941 + pPluginEvent = &pluginEvent; 1.1942 + pluginEvent.wParam = 1.1943 + (::GetKeyState(VK_CONTROL) ? MK_CONTROL : 0) | 1.1944 + (::GetKeyState(VK_SHIFT) ? MK_SHIFT : 0) | 1.1945 + (::GetKeyState(VK_LBUTTON) ? MK_LBUTTON : 0) | 1.1946 + (::GetKeyState(VK_MBUTTON) ? MK_MBUTTON : 0) | 1.1947 + (::GetKeyState(VK_RBUTTON) ? MK_RBUTTON : 0) | 1.1948 + (::GetKeyState(VK_XBUTTON1) ? MK_XBUTTON1 : 0) | 1.1949 + (::GetKeyState(VK_XBUTTON2) ? MK_XBUTTON2 : 0); 1.1950 + } 1.1951 + } 1.1952 + if (pPluginEvent) { 1.1953 + // Make event coordinates relative to our enclosing widget, 1.1954 + // not the widget they were received on. 1.1955 + // See use of NPEvent in widget/windows/nsWindow.cpp 1.1956 + // for why this assert should be safe 1.1957 + NS_ASSERTION(anEvent.message == NS_MOUSE_BUTTON_DOWN || 1.1958 + anEvent.message == NS_MOUSE_BUTTON_UP || 1.1959 + anEvent.message == NS_MOUSE_DOUBLECLICK || 1.1960 + anEvent.message == NS_MOUSE_ENTER_SYNTH || 1.1961 + anEvent.message == NS_MOUSE_EXIT_SYNTH || 1.1962 + anEvent.message == NS_MOUSE_MOVE, 1.1963 + "Incorrect event type for coordinate translation"); 1.1964 + nsPoint pt = 1.1965 + nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mObjectFrame) - 1.1966 + mObjectFrame->GetContentRectRelativeToSelf().TopLeft(); 1.1967 + nsPresContext* presContext = mObjectFrame->PresContext(); 1.1968 + nsIntPoint ptPx(presContext->AppUnitsToDevPixels(pt.x), 1.1969 + presContext->AppUnitsToDevPixels(pt.y)); 1.1970 + nsIntPoint widgetPtPx = ptPx + mObjectFrame->GetWindowOriginInPixels(true); 1.1971 + pPluginEvent->lParam = MAKELPARAM(widgetPtPx.x, widgetPtPx.y); 1.1972 + } 1.1973 + } 1.1974 + else if (!pPluginEvent) { 1.1975 + switch (anEvent.message) { 1.1976 + case NS_FOCUS_CONTENT: 1.1977 + pluginEvent.event = WM_SETFOCUS; 1.1978 + pluginEvent.wParam = 0; 1.1979 + pluginEvent.lParam = 0; 1.1980 + pPluginEvent = &pluginEvent; 1.1981 + break; 1.1982 + case NS_BLUR_CONTENT: 1.1983 + pluginEvent.event = WM_KILLFOCUS; 1.1984 + pluginEvent.wParam = 0; 1.1985 + pluginEvent.lParam = 0; 1.1986 + pPluginEvent = &pluginEvent; 1.1987 + break; 1.1988 + } 1.1989 + } 1.1990 + 1.1991 + if (pPluginEvent && !pPluginEvent->event) { 1.1992 + // Don't send null events to plugins. 1.1993 + NS_WARNING("nsObjectFrame ProcessEvent: trying to send null event to plugin."); 1.1994 + return rv; 1.1995 + } 1.1996 + 1.1997 + if (pPluginEvent) { 1.1998 + int16_t response = kNPEventNotHandled; 1.1999 + mInstance->HandleEvent(pPluginEvent, &response, NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO); 1.2000 + if (response == kNPEventHandled) 1.2001 + rv = nsEventStatus_eConsumeNoDefault; 1.2002 + } 1.2003 +#endif 1.2004 + 1.2005 +#ifdef MOZ_X11 1.2006 + // this code supports windowless plugins 1.2007 + nsIWidget* widget = anEvent.widget; 1.2008 + XEvent pluginEvent = XEvent(); 1.2009 + pluginEvent.type = 0; 1.2010 + 1.2011 + switch(anEvent.eventStructType) 1.2012 + { 1.2013 + case NS_MOUSE_EVENT: 1.2014 + { 1.2015 + switch (anEvent.message) 1.2016 + { 1.2017 + case NS_MOUSE_CLICK: 1.2018 + case NS_MOUSE_DOUBLECLICK: 1.2019 + // Button up/down events sent instead. 1.2020 + return rv; 1.2021 + } 1.2022 + 1.2023 + // Get reference point relative to plugin origin. 1.2024 + const nsPresContext* presContext = mObjectFrame->PresContext(); 1.2025 + nsPoint appPoint = 1.2026 + nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mObjectFrame) - 1.2027 + mObjectFrame->GetContentRectRelativeToSelf().TopLeft(); 1.2028 + nsIntPoint pluginPoint(presContext->AppUnitsToDevPixels(appPoint.x), 1.2029 + presContext->AppUnitsToDevPixels(appPoint.y)); 1.2030 + const WidgetMouseEvent& mouseEvent = *anEvent.AsMouseEvent(); 1.2031 + // Get reference point relative to screen: 1.2032 + LayoutDeviceIntPoint rootPoint(-1, -1); 1.2033 + if (widget) 1.2034 + rootPoint = anEvent.refPoint + 1.2035 + LayoutDeviceIntPoint::FromUntyped(widget->WidgetToScreenOffset()); 1.2036 +#ifdef MOZ_WIDGET_GTK 1.2037 + Window root = GDK_ROOT_WINDOW(); 1.2038 +#elif defined(MOZ_WIDGET_QT) 1.2039 + Window root = RootWindowOfScreen(DefaultScreenOfDisplay(mozilla::DefaultXDisplay())); 1.2040 +#else 1.2041 + Window root = None; // Could XQueryTree, but this is not important. 1.2042 +#endif 1.2043 + 1.2044 + switch (anEvent.message) 1.2045 + { 1.2046 + case NS_MOUSE_ENTER_SYNTH: 1.2047 + case NS_MOUSE_EXIT_SYNTH: 1.2048 + { 1.2049 + XCrossingEvent& event = pluginEvent.xcrossing; 1.2050 + event.type = anEvent.message == NS_MOUSE_ENTER_SYNTH ? 1.2051 + EnterNotify : LeaveNotify; 1.2052 + event.root = root; 1.2053 + event.time = anEvent.time; 1.2054 + event.x = pluginPoint.x; 1.2055 + event.y = pluginPoint.y; 1.2056 + event.x_root = rootPoint.x; 1.2057 + event.y_root = rootPoint.y; 1.2058 + event.state = XInputEventState(mouseEvent); 1.2059 + // information lost 1.2060 + event.subwindow = None; 1.2061 + event.mode = -1; 1.2062 + event.detail = NotifyDetailNone; 1.2063 + event.same_screen = True; 1.2064 + event.focus = mContentFocused; 1.2065 + } 1.2066 + break; 1.2067 + case NS_MOUSE_MOVE: 1.2068 + { 1.2069 + XMotionEvent& event = pluginEvent.xmotion; 1.2070 + event.type = MotionNotify; 1.2071 + event.root = root; 1.2072 + event.time = anEvent.time; 1.2073 + event.x = pluginPoint.x; 1.2074 + event.y = pluginPoint.y; 1.2075 + event.x_root = rootPoint.x; 1.2076 + event.y_root = rootPoint.y; 1.2077 + event.state = XInputEventState(mouseEvent); 1.2078 + // information lost 1.2079 + event.subwindow = None; 1.2080 + event.is_hint = NotifyNormal; 1.2081 + event.same_screen = True; 1.2082 + } 1.2083 + break; 1.2084 + case NS_MOUSE_BUTTON_DOWN: 1.2085 + case NS_MOUSE_BUTTON_UP: 1.2086 + { 1.2087 + XButtonEvent& event = pluginEvent.xbutton; 1.2088 + event.type = anEvent.message == NS_MOUSE_BUTTON_DOWN ? 1.2089 + ButtonPress : ButtonRelease; 1.2090 + event.root = root; 1.2091 + event.time = anEvent.time; 1.2092 + event.x = pluginPoint.x; 1.2093 + event.y = pluginPoint.y; 1.2094 + event.x_root = rootPoint.x; 1.2095 + event.y_root = rootPoint.y; 1.2096 + event.state = XInputEventState(mouseEvent); 1.2097 + switch (mouseEvent.button) 1.2098 + { 1.2099 + case WidgetMouseEvent::eMiddleButton: 1.2100 + event.button = 2; 1.2101 + break; 1.2102 + case WidgetMouseEvent::eRightButton: 1.2103 + event.button = 3; 1.2104 + break; 1.2105 + default: // WidgetMouseEvent::eLeftButton; 1.2106 + event.button = 1; 1.2107 + break; 1.2108 + } 1.2109 + // information lost: 1.2110 + event.subwindow = None; 1.2111 + event.same_screen = True; 1.2112 + } 1.2113 + break; 1.2114 + } 1.2115 + } 1.2116 + break; 1.2117 + 1.2118 + //XXX case NS_MOUSE_SCROLL_EVENT: not received. 1.2119 + 1.2120 + case NS_KEY_EVENT: 1.2121 + if (anEvent.pluginEvent) 1.2122 + { 1.2123 + XKeyEvent &event = pluginEvent.xkey; 1.2124 +#ifdef MOZ_WIDGET_GTK 1.2125 + event.root = GDK_ROOT_WINDOW(); 1.2126 + event.time = anEvent.time; 1.2127 + const GdkEventKey* gdkEvent = 1.2128 + static_cast<const GdkEventKey*>(anEvent.pluginEvent); 1.2129 + event.keycode = gdkEvent->hardware_keycode; 1.2130 + event.state = gdkEvent->state; 1.2131 + switch (anEvent.message) 1.2132 + { 1.2133 + case NS_KEY_DOWN: 1.2134 + // Handle NS_KEY_DOWN for modifier key presses 1.2135 + // For non-modifiers we get NS_KEY_PRESS 1.2136 + if (gdkEvent->is_modifier) 1.2137 + event.type = XKeyPress; 1.2138 + break; 1.2139 + case NS_KEY_PRESS: 1.2140 + event.type = XKeyPress; 1.2141 + break; 1.2142 + case NS_KEY_UP: 1.2143 + event.type = KeyRelease; 1.2144 + break; 1.2145 + } 1.2146 +#endif 1.2147 + 1.2148 + // Information that could be obtained from pluginEvent but we may not 1.2149 + // want to promise to provide: 1.2150 + event.subwindow = None; 1.2151 + event.x = 0; 1.2152 + event.y = 0; 1.2153 + event.x_root = -1; 1.2154 + event.y_root = -1; 1.2155 + event.same_screen = False; 1.2156 + } 1.2157 + else 1.2158 + { 1.2159 + // If we need to send synthesized key events, then 1.2160 + // DOMKeyCodeToGdkKeyCode(keyEvent.keyCode) and 1.2161 + // gdk_keymap_get_entries_for_keyval will be useful, but the 1.2162 + // mappings will not be unique. 1.2163 + NS_WARNING("Synthesized key event not sent to plugin"); 1.2164 + } 1.2165 + break; 1.2166 + 1.2167 + default: 1.2168 + switch (anEvent.message) 1.2169 + { 1.2170 + case NS_FOCUS_CONTENT: 1.2171 + case NS_BLUR_CONTENT: 1.2172 + { 1.2173 + XFocusChangeEvent &event = pluginEvent.xfocus; 1.2174 + event.type = 1.2175 + anEvent.message == NS_FOCUS_CONTENT ? FocusIn : FocusOut; 1.2176 + // information lost: 1.2177 + event.mode = -1; 1.2178 + event.detail = NotifyDetailNone; 1.2179 + } 1.2180 + break; 1.2181 + } 1.2182 + } 1.2183 + 1.2184 + if (!pluginEvent.type) { 1.2185 + return rv; 1.2186 + } 1.2187 + 1.2188 + // Fill in (useless) generic event information. 1.2189 + XAnyEvent& event = pluginEvent.xany; 1.2190 + event.display = widget ? 1.2191 + static_cast<Display*>(widget->GetNativeData(NS_NATIVE_DISPLAY)) : nullptr; 1.2192 + event.window = None; // not a real window 1.2193 + // information lost: 1.2194 + event.serial = 0; 1.2195 + event.send_event = False; 1.2196 + 1.2197 + int16_t response = kNPEventNotHandled; 1.2198 + mInstance->HandleEvent(&pluginEvent, &response, NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO); 1.2199 + if (response == kNPEventHandled) 1.2200 + rv = nsEventStatus_eConsumeNoDefault; 1.2201 +#endif 1.2202 + 1.2203 +#ifdef MOZ_WIDGET_ANDROID 1.2204 + // this code supports windowless plugins 1.2205 + { 1.2206 + // The plugin needs focus to receive keyboard and touch events 1.2207 + nsIFocusManager* fm = nsFocusManager::GetFocusManager(); 1.2208 + if (fm) { 1.2209 + nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(mContent); 1.2210 + fm->SetFocus(elem, 0); 1.2211 + } 1.2212 + } 1.2213 + switch(anEvent.eventStructType) 1.2214 + { 1.2215 + case NS_MOUSE_EVENT: 1.2216 + { 1.2217 + switch (anEvent.message) 1.2218 + { 1.2219 + case NS_MOUSE_CLICK: 1.2220 + case NS_MOUSE_DOUBLECLICK: 1.2221 + // Button up/down events sent instead. 1.2222 + return rv; 1.2223 + } 1.2224 + 1.2225 + // Get reference point relative to plugin origin. 1.2226 + const nsPresContext* presContext = mObjectFrame->PresContext(); 1.2227 + nsPoint appPoint = 1.2228 + nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mObjectFrame) - 1.2229 + mObjectFrame->GetContentRectRelativeToSelf().TopLeft(); 1.2230 + nsIntPoint pluginPoint(presContext->AppUnitsToDevPixels(appPoint.x), 1.2231 + presContext->AppUnitsToDevPixels(appPoint.y)); 1.2232 + 1.2233 + switch (anEvent.message) 1.2234 + { 1.2235 + case NS_MOUSE_MOVE: 1.2236 + { 1.2237 + // are these going to be touch events? 1.2238 + // pluginPoint.x; 1.2239 + // pluginPoint.y; 1.2240 + } 1.2241 + break; 1.2242 + case NS_MOUSE_BUTTON_DOWN: 1.2243 + { 1.2244 + ANPEvent event; 1.2245 + event.inSize = sizeof(ANPEvent); 1.2246 + event.eventType = kMouse_ANPEventType; 1.2247 + event.data.mouse.action = kDown_ANPMouseAction; 1.2248 + event.data.mouse.x = pluginPoint.x; 1.2249 + event.data.mouse.y = pluginPoint.y; 1.2250 + mInstance->HandleEvent(&event, nullptr, NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO); 1.2251 + } 1.2252 + break; 1.2253 + case NS_MOUSE_BUTTON_UP: 1.2254 + { 1.2255 + ANPEvent event; 1.2256 + event.inSize = sizeof(ANPEvent); 1.2257 + event.eventType = kMouse_ANPEventType; 1.2258 + event.data.mouse.action = kUp_ANPMouseAction; 1.2259 + event.data.mouse.x = pluginPoint.x; 1.2260 + event.data.mouse.y = pluginPoint.y; 1.2261 + mInstance->HandleEvent(&event, nullptr, NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO); 1.2262 + } 1.2263 + break; 1.2264 + } 1.2265 + } 1.2266 + break; 1.2267 + 1.2268 + case NS_KEY_EVENT: 1.2269 + { 1.2270 + const WidgetKeyboardEvent& keyEvent = *anEvent.AsKeyboardEvent(); 1.2271 + LOG("Firing NS_KEY_EVENT %d %d\n", keyEvent.keyCode, keyEvent.charCode); 1.2272 + // pluginEvent is initialized by nsWindow::InitKeyEvent(). 1.2273 + ANPEvent* pluginEvent = reinterpret_cast<ANPEvent*>(keyEvent.pluginEvent); 1.2274 + if (pluginEvent) { 1.2275 + MOZ_ASSERT(pluginEvent->inSize == sizeof(ANPEvent)); 1.2276 + MOZ_ASSERT(pluginEvent->eventType == kKey_ANPEventType); 1.2277 + mInstance->HandleEvent(pluginEvent, nullptr, NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO); 1.2278 + } 1.2279 + } 1.2280 + break; 1.2281 + 1.2282 + default: 1.2283 + break; 1.2284 + } 1.2285 + rv = nsEventStatus_eConsumeNoDefault; 1.2286 +#endif 1.2287 + 1.2288 + return rv; 1.2289 +} 1.2290 + 1.2291 +nsresult 1.2292 +nsPluginInstanceOwner::Destroy() 1.2293 +{ 1.2294 + SetFrame(nullptr); 1.2295 + 1.2296 +#ifdef XP_MACOSX 1.2297 + RemoveFromCARefreshTimer(); 1.2298 + if (mColorProfile) 1.2299 + ::CGColorSpaceRelease(mColorProfile); 1.2300 +#endif 1.2301 + 1.2302 + // unregister context menu listener 1.2303 + if (mCXMenuListener) { 1.2304 + mCXMenuListener->Destroy(mContent); 1.2305 + mCXMenuListener = nullptr; 1.2306 + } 1.2307 + 1.2308 + mContent->RemoveEventListener(NS_LITERAL_STRING("focus"), this, false); 1.2309 + mContent->RemoveEventListener(NS_LITERAL_STRING("blur"), this, false); 1.2310 + mContent->RemoveEventListener(NS_LITERAL_STRING("mouseup"), this, false); 1.2311 + mContent->RemoveEventListener(NS_LITERAL_STRING("mousedown"), this, false); 1.2312 + mContent->RemoveEventListener(NS_LITERAL_STRING("mousemove"), this, false); 1.2313 + mContent->RemoveEventListener(NS_LITERAL_STRING("click"), this, false); 1.2314 + mContent->RemoveEventListener(NS_LITERAL_STRING("dblclick"), this, false); 1.2315 + mContent->RemoveEventListener(NS_LITERAL_STRING("mouseover"), this, false); 1.2316 + mContent->RemoveEventListener(NS_LITERAL_STRING("mouseout"), this, false); 1.2317 + mContent->RemoveEventListener(NS_LITERAL_STRING("keypress"), this, true); 1.2318 + mContent->RemoveEventListener(NS_LITERAL_STRING("keydown"), this, true); 1.2319 + mContent->RemoveEventListener(NS_LITERAL_STRING("keyup"), this, true); 1.2320 + mContent->RemoveEventListener(NS_LITERAL_STRING("drop"), this, true); 1.2321 + mContent->RemoveEventListener(NS_LITERAL_STRING("dragdrop"), this, true); 1.2322 + mContent->RemoveEventListener(NS_LITERAL_STRING("drag"), this, true); 1.2323 + mContent->RemoveEventListener(NS_LITERAL_STRING("dragenter"), this, true); 1.2324 + mContent->RemoveEventListener(NS_LITERAL_STRING("dragover"), this, true); 1.2325 + mContent->RemoveEventListener(NS_LITERAL_STRING("dragleave"), this, true); 1.2326 + mContent->RemoveEventListener(NS_LITERAL_STRING("dragexit"), this, true); 1.2327 + mContent->RemoveEventListener(NS_LITERAL_STRING("dragstart"), this, true); 1.2328 + mContent->RemoveEventListener(NS_LITERAL_STRING("draggesture"), this, true); 1.2329 + mContent->RemoveEventListener(NS_LITERAL_STRING("dragend"), this, true); 1.2330 + 1.2331 +#if MOZ_WIDGET_ANDROID 1.2332 + RemovePluginView(); 1.2333 +#endif 1.2334 + 1.2335 + if (mWidget) { 1.2336 + if (mPluginWindow) { 1.2337 + mPluginWindow->SetPluginWidget(nullptr); 1.2338 + } 1.2339 + 1.2340 + nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget); 1.2341 + if (pluginWidget) { 1.2342 + pluginWidget->SetPluginInstanceOwner(nullptr); 1.2343 + } 1.2344 + mWidget->Destroy(); 1.2345 + } 1.2346 + 1.2347 + return NS_OK; 1.2348 +} 1.2349 + 1.2350 +// Paints are handled differently, so we just simulate an update event. 1.2351 + 1.2352 +#ifdef XP_MACOSX 1.2353 +void nsPluginInstanceOwner::Paint(const gfxRect& aDirtyRect, CGContextRef cgContext) 1.2354 +{ 1.2355 + if (!mInstance || !mObjectFrame) 1.2356 + return; 1.2357 + 1.2358 + gfxRect dirtyRectCopy = aDirtyRect; 1.2359 + double scaleFactor = 1.0; 1.2360 + GetContentsScaleFactor(&scaleFactor); 1.2361 + if (scaleFactor != 1.0) { 1.2362 + ::CGContextScaleCTM(cgContext, scaleFactor, scaleFactor); 1.2363 + // Convert aDirtyRect from device pixels to "display pixels" 1.2364 + // for HiDPI modes 1.2365 + dirtyRectCopy.ScaleRoundOut(1.0 / scaleFactor); 1.2366 + } 1.2367 + 1.2368 + nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget); 1.2369 + if (pluginWidget && NS_SUCCEEDED(pluginWidget->StartDrawPlugin())) { 1.2370 + DoCocoaEventDrawRect(dirtyRectCopy, cgContext); 1.2371 + pluginWidget->EndDrawPlugin(); 1.2372 + } 1.2373 +} 1.2374 + 1.2375 +void nsPluginInstanceOwner::DoCocoaEventDrawRect(const gfxRect& aDrawRect, CGContextRef cgContext) 1.2376 +{ 1.2377 + if (!mInstance || !mObjectFrame) 1.2378 + return; 1.2379 + 1.2380 + // The context given here is only valid during the HandleEvent call. 1.2381 + NPCocoaEvent updateEvent; 1.2382 + InitializeNPCocoaEvent(&updateEvent); 1.2383 + updateEvent.type = NPCocoaEventDrawRect; 1.2384 + updateEvent.data.draw.context = cgContext; 1.2385 + updateEvent.data.draw.x = aDrawRect.X(); 1.2386 + updateEvent.data.draw.y = aDrawRect.Y(); 1.2387 + updateEvent.data.draw.width = aDrawRect.Width(); 1.2388 + updateEvent.data.draw.height = aDrawRect.Height(); 1.2389 + 1.2390 + mInstance->HandleEvent(&updateEvent, nullptr); 1.2391 +} 1.2392 +#endif 1.2393 + 1.2394 +#ifdef XP_WIN 1.2395 +void nsPluginInstanceOwner::Paint(const RECT& aDirty, HDC aDC) 1.2396 +{ 1.2397 + if (!mInstance || !mObjectFrame) 1.2398 + return; 1.2399 + 1.2400 + NPEvent pluginEvent; 1.2401 + pluginEvent.event = WM_PAINT; 1.2402 + pluginEvent.wParam = WPARAM(aDC); 1.2403 + pluginEvent.lParam = LPARAM(&aDirty); 1.2404 + mInstance->HandleEvent(&pluginEvent, nullptr); 1.2405 +} 1.2406 +#endif 1.2407 + 1.2408 +#ifdef MOZ_WIDGET_ANDROID 1.2409 + 1.2410 +void nsPluginInstanceOwner::Paint(gfxContext* aContext, 1.2411 + const gfxRect& aFrameRect, 1.2412 + const gfxRect& aDirtyRect) 1.2413 +{ 1.2414 + if (!mInstance || !mObjectFrame || !mPluginDocumentActiveState || mFullScreen) 1.2415 + return; 1.2416 + 1.2417 + int32_t model = mInstance->GetANPDrawingModel(); 1.2418 + 1.2419 + if (model == kSurface_ANPDrawingModel) { 1.2420 + if (!AddPluginView(GetPluginRect())) { 1.2421 + Invalidate(); 1.2422 + } 1.2423 + return; 1.2424 + } 1.2425 + 1.2426 + if (model != kBitmap_ANPDrawingModel) 1.2427 + return; 1.2428 + 1.2429 +#ifdef ANP_BITMAP_DRAWING_MODEL 1.2430 + static nsRefPtr<gfxImageSurface> pluginSurface; 1.2431 + 1.2432 + if (pluginSurface == nullptr || 1.2433 + aFrameRect.width != pluginSurface->Width() || 1.2434 + aFrameRect.height != pluginSurface->Height()) { 1.2435 + 1.2436 + pluginSurface = new gfxImageSurface(gfxIntSize(aFrameRect.width, aFrameRect.height), 1.2437 + gfxImageFormat::ARGB32); 1.2438 + if (!pluginSurface) 1.2439 + return; 1.2440 + } 1.2441 + 1.2442 + // Clears buffer. I think this is needed. 1.2443 + nsRefPtr<gfxContext> ctx = new gfxContext(pluginSurface); 1.2444 + ctx->SetOperator(gfxContext::OPERATOR_CLEAR); 1.2445 + ctx->Paint(); 1.2446 + 1.2447 + ANPEvent event; 1.2448 + event.inSize = sizeof(ANPEvent); 1.2449 + event.eventType = 4; 1.2450 + event.data.draw.model = 1; 1.2451 + 1.2452 + event.data.draw.clip.top = 0; 1.2453 + event.data.draw.clip.left = 0; 1.2454 + event.data.draw.clip.bottom = aFrameRect.width; 1.2455 + event.data.draw.clip.right = aFrameRect.height; 1.2456 + 1.2457 + event.data.draw.data.bitmap.format = kRGBA_8888_ANPBitmapFormat; 1.2458 + event.data.draw.data.bitmap.width = aFrameRect.width; 1.2459 + event.data.draw.data.bitmap.height = aFrameRect.height; 1.2460 + event.data.draw.data.bitmap.baseAddr = pluginSurface->Data(); 1.2461 + event.data.draw.data.bitmap.rowBytes = aFrameRect.width * 4; 1.2462 + 1.2463 + if (!mInstance) 1.2464 + return; 1.2465 + 1.2466 + mInstance->HandleEvent(&event, nullptr); 1.2467 + 1.2468 + aContext->SetOperator(gfxContext::OPERATOR_SOURCE); 1.2469 + aContext->SetSource(pluginSurface, gfxPoint(aFrameRect.x, aFrameRect.y)); 1.2470 + aContext->Clip(aFrameRect); 1.2471 + aContext->Paint(); 1.2472 +#endif 1.2473 +} 1.2474 +#endif 1.2475 + 1.2476 +#if defined(MOZ_X11) 1.2477 +void nsPluginInstanceOwner::Paint(gfxContext* aContext, 1.2478 + const gfxRect& aFrameRect, 1.2479 + const gfxRect& aDirtyRect) 1.2480 +{ 1.2481 + if (!mInstance || !mObjectFrame) 1.2482 + return; 1.2483 + 1.2484 + // to provide crisper and faster drawing. 1.2485 + gfxRect pluginRect = aFrameRect; 1.2486 + if (aContext->UserToDevicePixelSnapped(pluginRect)) { 1.2487 + pluginRect = aContext->DeviceToUser(pluginRect); 1.2488 + } 1.2489 + 1.2490 + // Round out the dirty rect to plugin pixels to ensure the plugin draws 1.2491 + // enough pixels for interpolation to device pixels. 1.2492 + gfxRect dirtyRect = aDirtyRect - pluginRect.TopLeft(); 1.2493 + dirtyRect.RoundOut(); 1.2494 + 1.2495 + // Plugins can only draw an integer number of pixels. 1.2496 + // 1.2497 + // With translation-only transformation matrices, pluginRect is already 1.2498 + // pixel-aligned. 1.2499 + // 1.2500 + // With more complex transformations, modifying the scales in the 1.2501 + // transformation matrix could retain subpixel accuracy and let the plugin 1.2502 + // draw a suitable number of pixels for interpolation to device pixels in 1.2503 + // Renderer::Draw, but such cases are not common enough to warrant the 1.2504 + // effort now. 1.2505 + nsIntSize pluginSize(NS_lround(pluginRect.width), 1.2506 + NS_lround(pluginRect.height)); 1.2507 + 1.2508 + // Determine what the plugin needs to draw. 1.2509 + nsIntRect pluginDirtyRect(int32_t(dirtyRect.x), 1.2510 + int32_t(dirtyRect.y), 1.2511 + int32_t(dirtyRect.width), 1.2512 + int32_t(dirtyRect.height)); 1.2513 + if (!pluginDirtyRect. 1.2514 + IntersectRect(nsIntRect(0, 0, pluginSize.width, pluginSize.height), 1.2515 + pluginDirtyRect)) 1.2516 + return; 1.2517 + 1.2518 + NPWindow* window; 1.2519 + GetWindow(window); 1.2520 + 1.2521 + uint32_t rendererFlags = 0; 1.2522 + if (!mFlash10Quirks) { 1.2523 + rendererFlags |= 1.2524 + Renderer::DRAW_SUPPORTS_CLIP_RECT | 1.2525 + Renderer::DRAW_SUPPORTS_ALTERNATE_VISUAL; 1.2526 + } 1.2527 + 1.2528 + bool transparent; 1.2529 + mInstance->IsTransparent(&transparent); 1.2530 + if (!transparent) 1.2531 + rendererFlags |= Renderer::DRAW_IS_OPAQUE; 1.2532 + 1.2533 + // Renderer::Draw() draws a rectangle with top-left at the aContext origin. 1.2534 + gfxContextAutoSaveRestore autoSR(aContext); 1.2535 + aContext->Translate(pluginRect.TopLeft()); 1.2536 + 1.2537 + Renderer renderer(window, this, pluginSize, pluginDirtyRect); 1.2538 + 1.2539 + Display* dpy = mozilla::DefaultXDisplay(); 1.2540 + Screen* screen = DefaultScreenOfDisplay(dpy); 1.2541 + Visual* visual = DefaultVisualOfScreen(screen); 1.2542 + 1.2543 + renderer.Draw(aContext, nsIntSize(window->width, window->height), 1.2544 + rendererFlags, screen, visual); 1.2545 +} 1.2546 +nsresult 1.2547 +nsPluginInstanceOwner::Renderer::DrawWithXlib(cairo_surface_t* xsurface, 1.2548 + nsIntPoint offset, 1.2549 + nsIntRect *clipRects, 1.2550 + uint32_t numClipRects) 1.2551 +{ 1.2552 + Screen *screen = cairo_xlib_surface_get_screen(xsurface); 1.2553 + Colormap colormap; 1.2554 + Visual* visual; 1.2555 + if (!gfxXlibSurface::GetColormapAndVisual(xsurface, &colormap, &visual)) { 1.2556 + NS_ERROR("Failed to get visual and colormap"); 1.2557 + return NS_ERROR_UNEXPECTED; 1.2558 + } 1.2559 + 1.2560 + nsNPAPIPluginInstance *instance = mInstanceOwner->mInstance; 1.2561 + if (!instance) 1.2562 + return NS_ERROR_FAILURE; 1.2563 + 1.2564 + // See if the plugin must be notified of new window parameters. 1.2565 + bool doupdatewindow = false; 1.2566 + 1.2567 + if (mWindow->x != offset.x || mWindow->y != offset.y) { 1.2568 + mWindow->x = offset.x; 1.2569 + mWindow->y = offset.y; 1.2570 + doupdatewindow = true; 1.2571 + } 1.2572 + 1.2573 + if (nsIntSize(mWindow->width, mWindow->height) != mPluginSize) { 1.2574 + mWindow->width = mPluginSize.width; 1.2575 + mWindow->height = mPluginSize.height; 1.2576 + doupdatewindow = true; 1.2577 + } 1.2578 + 1.2579 + // The clip rect is relative to drawable top-left. 1.2580 + NS_ASSERTION(numClipRects <= 1, "We don't support multiple clip rectangles!"); 1.2581 + nsIntRect clipRect; 1.2582 + if (numClipRects) { 1.2583 + clipRect.x = clipRects[0].x; 1.2584 + clipRect.y = clipRects[0].y; 1.2585 + clipRect.width = clipRects[0].width; 1.2586 + clipRect.height = clipRects[0].height; 1.2587 + // NPRect members are unsigned, but clip rectangles should be contained by 1.2588 + // the surface. 1.2589 + NS_ASSERTION(clipRect.x >= 0 && clipRect.y >= 0, 1.2590 + "Clip rectangle offsets are negative!"); 1.2591 + } 1.2592 + else { 1.2593 + clipRect.x = offset.x; 1.2594 + clipRect.y = offset.y; 1.2595 + clipRect.width = mWindow->width; 1.2596 + clipRect.height = mWindow->height; 1.2597 + // Don't ask the plugin to draw outside the drawable. 1.2598 + // This also ensures that the unsigned clip rectangle offsets won't be -ve. 1.2599 + clipRect.IntersectRect(clipRect, 1.2600 + nsIntRect(0, 0, 1.2601 + cairo_xlib_surface_get_width(xsurface), 1.2602 + cairo_xlib_surface_get_height(xsurface))); 1.2603 + } 1.2604 + 1.2605 + NPRect newClipRect; 1.2606 + newClipRect.left = clipRect.x; 1.2607 + newClipRect.top = clipRect.y; 1.2608 + newClipRect.right = clipRect.XMost(); 1.2609 + newClipRect.bottom = clipRect.YMost(); 1.2610 + if (mWindow->clipRect.left != newClipRect.left || 1.2611 + mWindow->clipRect.top != newClipRect.top || 1.2612 + mWindow->clipRect.right != newClipRect.right || 1.2613 + mWindow->clipRect.bottom != newClipRect.bottom) { 1.2614 + mWindow->clipRect = newClipRect; 1.2615 + doupdatewindow = true; 1.2616 + } 1.2617 + 1.2618 + NPSetWindowCallbackStruct* ws_info = 1.2619 + static_cast<NPSetWindowCallbackStruct*>(mWindow->ws_info); 1.2620 +#ifdef MOZ_X11 1.2621 + if (ws_info->visual != visual || ws_info->colormap != colormap) { 1.2622 + ws_info->visual = visual; 1.2623 + ws_info->colormap = colormap; 1.2624 + ws_info->depth = gfxXlibSurface::DepthOfVisual(screen, visual); 1.2625 + doupdatewindow = true; 1.2626 + } 1.2627 +#endif 1.2628 + 1.2629 + { 1.2630 + if (doupdatewindow) 1.2631 + instance->SetWindow(mWindow); 1.2632 + } 1.2633 + 1.2634 + // Translate the dirty rect to drawable coordinates. 1.2635 + nsIntRect dirtyRect = mDirtyRect + offset; 1.2636 + if (mInstanceOwner->mFlash10Quirks) { 1.2637 + // Work around a bug in Flash up to 10.1 d51 at least, where expose event 1.2638 + // top left coordinates within the plugin-rect and not at the drawable 1.2639 + // origin are misinterpreted. (We can move the top left coordinate 1.2640 + // provided it is within the clipRect.) 1.2641 + dirtyRect.SetRect(offset.x, offset.y, 1.2642 + mDirtyRect.XMost(), mDirtyRect.YMost()); 1.2643 + } 1.2644 + // Intersect the dirty rect with the clip rect to ensure that it lies within 1.2645 + // the drawable. 1.2646 + if (!dirtyRect.IntersectRect(dirtyRect, clipRect)) 1.2647 + return NS_OK; 1.2648 + 1.2649 + { 1.2650 + XEvent pluginEvent = XEvent(); 1.2651 + XGraphicsExposeEvent& exposeEvent = pluginEvent.xgraphicsexpose; 1.2652 + // set the drawing info 1.2653 + exposeEvent.type = GraphicsExpose; 1.2654 + exposeEvent.display = DisplayOfScreen(screen); 1.2655 + exposeEvent.drawable = cairo_xlib_surface_get_drawable(xsurface); 1.2656 + exposeEvent.x = dirtyRect.x; 1.2657 + exposeEvent.y = dirtyRect.y; 1.2658 + exposeEvent.width = dirtyRect.width; 1.2659 + exposeEvent.height = dirtyRect.height; 1.2660 + exposeEvent.count = 0; 1.2661 + // information not set: 1.2662 + exposeEvent.serial = 0; 1.2663 + exposeEvent.send_event = False; 1.2664 + exposeEvent.major_code = 0; 1.2665 + exposeEvent.minor_code = 0; 1.2666 + 1.2667 + instance->HandleEvent(&pluginEvent, nullptr); 1.2668 + } 1.2669 + return NS_OK; 1.2670 +} 1.2671 +#endif 1.2672 + 1.2673 +nsresult nsPluginInstanceOwner::Init(nsIContent* aContent) 1.2674 +{ 1.2675 + mLastEventloopNestingLevel = GetEventloopNestingLevel(); 1.2676 + 1.2677 + mContent = aContent; 1.2678 + 1.2679 + // Get a frame, don't reflow. If a reflow was necessary it should have been 1.2680 + // done at a higher level than this (content). 1.2681 + nsIFrame* frame = aContent->GetPrimaryFrame(); 1.2682 + nsIObjectFrame* iObjFrame = do_QueryFrame(frame); 1.2683 + nsObjectFrame* objFrame = static_cast<nsObjectFrame*>(iObjFrame); 1.2684 + if (objFrame) { 1.2685 + SetFrame(objFrame); 1.2686 + // Some plugins require a specific sequence of shutdown and startup when 1.2687 + // a page is reloaded. Shutdown happens usually when the last instance 1.2688 + // is destroyed. Here we make sure the plugin instance in the old 1.2689 + // document is destroyed before we try to create the new one. 1.2690 + objFrame->PresContext()->EnsureVisible(); 1.2691 + } else { 1.2692 + NS_NOTREACHED("Should not be initializing plugin without a frame"); 1.2693 + return NS_ERROR_FAILURE; 1.2694 + } 1.2695 + 1.2696 + // register context menu listener 1.2697 + mCXMenuListener = new nsPluginDOMContextMenuListener(aContent); 1.2698 + 1.2699 + mContent->AddEventListener(NS_LITERAL_STRING("focus"), this, false, 1.2700 + false); 1.2701 + mContent->AddEventListener(NS_LITERAL_STRING("blur"), this, false, 1.2702 + false); 1.2703 + mContent->AddEventListener(NS_LITERAL_STRING("mouseup"), this, false, 1.2704 + false); 1.2705 + mContent->AddEventListener(NS_LITERAL_STRING("mousedown"), this, false, 1.2706 + false); 1.2707 + mContent->AddEventListener(NS_LITERAL_STRING("mousemove"), this, false, 1.2708 + false); 1.2709 + mContent->AddEventListener(NS_LITERAL_STRING("click"), this, false, 1.2710 + false); 1.2711 + mContent->AddEventListener(NS_LITERAL_STRING("dblclick"), this, false, 1.2712 + false); 1.2713 + mContent->AddEventListener(NS_LITERAL_STRING("mouseover"), this, false, 1.2714 + false); 1.2715 + mContent->AddEventListener(NS_LITERAL_STRING("mouseout"), this, false, 1.2716 + false); 1.2717 + mContent->AddEventListener(NS_LITERAL_STRING("keypress"), this, true); 1.2718 + mContent->AddEventListener(NS_LITERAL_STRING("keydown"), this, true); 1.2719 + mContent->AddEventListener(NS_LITERAL_STRING("keyup"), this, true); 1.2720 + mContent->AddEventListener(NS_LITERAL_STRING("drop"), this, true); 1.2721 + mContent->AddEventListener(NS_LITERAL_STRING("dragdrop"), this, true); 1.2722 + mContent->AddEventListener(NS_LITERAL_STRING("drag"), this, true); 1.2723 + mContent->AddEventListener(NS_LITERAL_STRING("dragenter"), this, true); 1.2724 + mContent->AddEventListener(NS_LITERAL_STRING("dragover"), this, true); 1.2725 + mContent->AddEventListener(NS_LITERAL_STRING("dragleave"), this, true); 1.2726 + mContent->AddEventListener(NS_LITERAL_STRING("dragexit"), this, true); 1.2727 + mContent->AddEventListener(NS_LITERAL_STRING("dragstart"), this, true); 1.2728 + mContent->AddEventListener(NS_LITERAL_STRING("draggesture"), this, true); 1.2729 + mContent->AddEventListener(NS_LITERAL_STRING("dragend"), this, true); 1.2730 + 1.2731 + return NS_OK; 1.2732 +} 1.2733 + 1.2734 +void* nsPluginInstanceOwner::GetPluginPortFromWidget() 1.2735 +{ 1.2736 +//!!! Port must be released for windowless plugins on Windows, because it is HDC !!! 1.2737 + 1.2738 + void* result = nullptr; 1.2739 + if (mWidget) { 1.2740 +#ifdef XP_WIN 1.2741 + if (mPluginWindow && (mPluginWindow->type == NPWindowTypeDrawable)) 1.2742 + result = mWidget->GetNativeData(NS_NATIVE_GRAPHIC); 1.2743 + else 1.2744 +#endif 1.2745 +#ifdef XP_MACOSX 1.2746 + if (GetDrawingModel() == NPDrawingModelCoreGraphics || 1.2747 + GetDrawingModel() == NPDrawingModelCoreAnimation || 1.2748 + GetDrawingModel() == NPDrawingModelInvalidatingCoreAnimation) 1.2749 + result = mWidget->GetNativeData(NS_NATIVE_PLUGIN_PORT_CG); 1.2750 + else 1.2751 +#endif 1.2752 + result = mWidget->GetNativeData(NS_NATIVE_PLUGIN_PORT); 1.2753 + } 1.2754 + return result; 1.2755 +} 1.2756 + 1.2757 +void nsPluginInstanceOwner::ReleasePluginPort(void * pluginPort) 1.2758 +{ 1.2759 +#ifdef XP_WIN 1.2760 + if (mWidget && mPluginWindow && 1.2761 + mPluginWindow->type == NPWindowTypeDrawable) { 1.2762 + mWidget->FreeNativeData((HDC)pluginPort, NS_NATIVE_GRAPHIC); 1.2763 + } 1.2764 +#endif 1.2765 +} 1.2766 + 1.2767 +NS_IMETHODIMP nsPluginInstanceOwner::CreateWidget(void) 1.2768 +{ 1.2769 + NS_ENSURE_TRUE(mPluginWindow, NS_ERROR_NULL_POINTER); 1.2770 + 1.2771 + nsresult rv = NS_ERROR_FAILURE; 1.2772 + 1.2773 + // Can't call this twice! 1.2774 + if (mWidget) { 1.2775 + NS_WARNING("Trying to create a plugin widget twice!"); 1.2776 + return NS_ERROR_FAILURE; 1.2777 + } 1.2778 + 1.2779 + bool windowless = false; 1.2780 + mInstance->IsWindowless(&windowless); 1.2781 + if (!windowless && !nsIWidget::UsePuppetWidgets()) { 1.2782 + // Try to get a parent widget, on some platforms widget creation will fail without 1.2783 + // a parent. 1.2784 + nsCOMPtr<nsIWidget> parentWidget; 1.2785 + nsIDocument *doc = nullptr; 1.2786 + if (mContent) { 1.2787 + doc = mContent->OwnerDoc(); 1.2788 + parentWidget = nsContentUtils::WidgetForDocument(doc); 1.2789 + } 1.2790 + 1.2791 + mWidget = do_CreateInstance(kWidgetCID, &rv); 1.2792 + if (NS_FAILED(rv)) { 1.2793 + return rv; 1.2794 + } 1.2795 + 1.2796 + nsWidgetInitData initData; 1.2797 + initData.mWindowType = eWindowType_plugin; 1.2798 + initData.mUnicode = false; 1.2799 + initData.clipChildren = true; 1.2800 + initData.clipSiblings = true; 1.2801 + rv = mWidget->Create(parentWidget.get(), nullptr, nsIntRect(0,0,0,0), 1.2802 + nullptr, &initData); 1.2803 + if (NS_FAILED(rv)) { 1.2804 + mWidget->Destroy(); 1.2805 + mWidget = nullptr; 1.2806 + return rv; 1.2807 + } 1.2808 + 1.2809 + mWidget->EnableDragDrop(true); 1.2810 + mWidget->Show(false); 1.2811 + mWidget->Enable(false); 1.2812 + 1.2813 +#ifdef XP_MACOSX 1.2814 + // Now that we have a widget we want to set the event model before 1.2815 + // any events are processed. 1.2816 + nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget); 1.2817 + if (!pluginWidget) { 1.2818 + return NS_ERROR_FAILURE; 1.2819 + } 1.2820 + pluginWidget->SetPluginEventModel(GetEventModel()); 1.2821 + pluginWidget->SetPluginDrawingModel(GetDrawingModel()); 1.2822 + 1.2823 + if (GetDrawingModel() == NPDrawingModelCoreAnimation) { 1.2824 + AddToCARefreshTimer(); 1.2825 + } 1.2826 +#endif 1.2827 + } 1.2828 + 1.2829 + if (mObjectFrame) { 1.2830 + // nullptr widget is fine, will result in windowless setup. 1.2831 + mObjectFrame->PrepForDrawing(mWidget); 1.2832 + } 1.2833 + 1.2834 + if (windowless) { 1.2835 + mPluginWindow->type = NPWindowTypeDrawable; 1.2836 + 1.2837 + // this needs to be a HDC according to the spec, but I do 1.2838 + // not see the right way to release it so let's postpone 1.2839 + // passing HDC till paint event when it is really 1.2840 + // needed. Change spec? 1.2841 + mPluginWindow->window = nullptr; 1.2842 +#ifdef MOZ_X11 1.2843 + // Fill in the display field. 1.2844 + NPSetWindowCallbackStruct* ws_info = 1.2845 + static_cast<NPSetWindowCallbackStruct*>(mPluginWindow->ws_info); 1.2846 + ws_info->display = DefaultXDisplay(); 1.2847 + 1.2848 + nsAutoCString description; 1.2849 + GetPluginDescription(description); 1.2850 + NS_NAMED_LITERAL_CSTRING(flash10Head, "Shockwave Flash 10."); 1.2851 + mFlash10Quirks = StringBeginsWith(description, flash10Head); 1.2852 +#endif 1.2853 + } else if (mWidget) { 1.2854 + // mPluginWindow->type is used in |GetPluginPort| so it must 1.2855 + // be initialized first 1.2856 + mPluginWindow->type = NPWindowTypeWindow; 1.2857 + mPluginWindow->window = GetPluginPortFromWidget(); 1.2858 + // tell the plugin window about the widget 1.2859 + mPluginWindow->SetPluginWidget(mWidget); 1.2860 + 1.2861 + // tell the widget about the current plugin instance owner. 1.2862 + nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget); 1.2863 + if (pluginWidget) { 1.2864 + pluginWidget->SetPluginInstanceOwner(this); 1.2865 + } 1.2866 + } 1.2867 + 1.2868 + mWidgetCreationComplete = true; 1.2869 + 1.2870 + return NS_OK; 1.2871 +} 1.2872 + 1.2873 +// Mac specific code to fix up the port location and clipping region 1.2874 +#ifdef XP_MACOSX 1.2875 + 1.2876 +void* nsPluginInstanceOwner::FixUpPluginWindow(int32_t inPaintState) 1.2877 +{ 1.2878 + if (!mWidget || !mPluginWindow || !mInstance || !mObjectFrame) 1.2879 + return nullptr; 1.2880 + 1.2881 + nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget); 1.2882 + if (!pluginWidget) 1.2883 + return nullptr; 1.2884 + 1.2885 + // If we've already set up a CGContext in nsObjectFrame::PaintPlugin(), we 1.2886 + // don't want calls to SetPluginPortAndDetectChange() to step on our work. 1.2887 + if (mInCGPaintLevel < 1) { 1.2888 + SetPluginPortAndDetectChange(); 1.2889 + } 1.2890 + 1.2891 + // We'll need the top-level Cocoa window for the Cocoa event model. 1.2892 + nsIWidget* widget = mObjectFrame->GetNearestWidget(); 1.2893 + if (!widget) 1.2894 + return nullptr; 1.2895 + void *cocoaTopLevelWindow = widget->GetNativeData(NS_NATIVE_WINDOW); 1.2896 + if (!cocoaTopLevelWindow) 1.2897 + return nullptr; 1.2898 + 1.2899 + nsIntPoint pluginOrigin; 1.2900 + nsIntRect widgetClip; 1.2901 + bool widgetVisible; 1.2902 + pluginWidget->GetPluginClipRect(widgetClip, pluginOrigin, widgetVisible); 1.2903 + mWidgetVisible = widgetVisible; 1.2904 + 1.2905 + // printf("GetPluginClipRect returning visible %d\n", widgetVisible); 1.2906 + 1.2907 + // This would be a lot easier if we could use obj-c here, 1.2908 + // but we can't. Since we have only nsIWidget and we can't 1.2909 + // use its native widget (an obj-c object) we have to go 1.2910 + // from the widget's screen coordinates to its window coords 1.2911 + // instead of straight to window coords. 1.2912 + nsIntPoint geckoScreenCoords = mWidget->WidgetToScreenOffset(); 1.2913 + 1.2914 + nsRect windowRect; 1.2915 + NS_NPAPI_CocoaWindowFrame(cocoaTopLevelWindow, windowRect); 1.2916 + 1.2917 + double scaleFactor = 1.0; 1.2918 + GetContentsScaleFactor(&scaleFactor); 1.2919 + int intScaleFactor = ceil(scaleFactor); 1.2920 + 1.2921 + // Convert geckoScreenCoords from device pixels to "display pixels" 1.2922 + // for HiDPI modes. 1.2923 + mPluginWindow->x = geckoScreenCoords.x/intScaleFactor - windowRect.x; 1.2924 + mPluginWindow->y = geckoScreenCoords.y/intScaleFactor - windowRect.y; 1.2925 + 1.2926 + NPRect oldClipRect = mPluginWindow->clipRect; 1.2927 + 1.2928 + // fix up the clipping region 1.2929 + mPluginWindow->clipRect.top = widgetClip.y; 1.2930 + mPluginWindow->clipRect.left = widgetClip.x; 1.2931 + 1.2932 + if (!mWidgetVisible || inPaintState == ePluginPaintDisable) { 1.2933 + mPluginWindow->clipRect.bottom = mPluginWindow->clipRect.top; 1.2934 + mPluginWindow->clipRect.right = mPluginWindow->clipRect.left; 1.2935 + } 1.2936 + else if (inPaintState == ePluginPaintEnable) 1.2937 + { 1.2938 + mPluginWindow->clipRect.bottom = mPluginWindow->clipRect.top + widgetClip.height; 1.2939 + mPluginWindow->clipRect.right = mPluginWindow->clipRect.left + widgetClip.width; 1.2940 + } 1.2941 + 1.2942 + // if the clip rect changed, call SetWindow() 1.2943 + // (RealPlayer needs this to draw correctly) 1.2944 + if (mPluginWindow->clipRect.left != oldClipRect.left || 1.2945 + mPluginWindow->clipRect.top != oldClipRect.top || 1.2946 + mPluginWindow->clipRect.right != oldClipRect.right || 1.2947 + mPluginWindow->clipRect.bottom != oldClipRect.bottom || 1.2948 + mPluginPortChanged) 1.2949 + { 1.2950 + if (UseAsyncRendering()) { 1.2951 + mInstance->AsyncSetWindow(mPluginWindow); 1.2952 + } 1.2953 + else { 1.2954 + mPluginWindow->CallSetWindow(mInstance); 1.2955 + } 1.2956 + mPluginPortChanged = false; 1.2957 + } 1.2958 + 1.2959 + // After the first NPP_SetWindow call we need to send an initial 1.2960 + // top-level window focus event. 1.2961 + if (!mSentInitialTopLevelWindowEvent) { 1.2962 + // Set this before calling ProcessEvent to avoid endless recursion. 1.2963 + mSentInitialTopLevelWindowEvent = true; 1.2964 + 1.2965 + WidgetPluginEvent pluginEvent(true, NS_PLUGIN_FOCUS_EVENT, nullptr); 1.2966 + NPCocoaEvent cocoaEvent; 1.2967 + InitializeNPCocoaEvent(&cocoaEvent); 1.2968 + cocoaEvent.type = NPCocoaEventWindowFocusChanged; 1.2969 + cocoaEvent.data.focus.hasFocus = NS_NPAPI_CocoaWindowIsMain(cocoaTopLevelWindow); 1.2970 + pluginEvent.pluginEvent = &cocoaEvent; 1.2971 + ProcessEvent(pluginEvent); 1.2972 + } 1.2973 + 1.2974 + return nullptr; 1.2975 +} 1.2976 + 1.2977 +void 1.2978 +nsPluginInstanceOwner::HidePluginWindow() 1.2979 +{ 1.2980 + if (!mPluginWindow || !mInstance) { 1.2981 + return; 1.2982 + } 1.2983 + 1.2984 + mPluginWindow->clipRect.bottom = mPluginWindow->clipRect.top; 1.2985 + mPluginWindow->clipRect.right = mPluginWindow->clipRect.left; 1.2986 + mWidgetVisible = false; 1.2987 + if (UseAsyncRendering()) { 1.2988 + mInstance->AsyncSetWindow(mPluginWindow); 1.2989 + } else { 1.2990 + mInstance->SetWindow(mPluginWindow); 1.2991 + } 1.2992 +} 1.2993 + 1.2994 +#else // XP_MACOSX 1.2995 + 1.2996 +void nsPluginInstanceOwner::UpdateWindowPositionAndClipRect(bool aSetWindow) 1.2997 +{ 1.2998 + if (!mPluginWindow) 1.2999 + return; 1.3000 + 1.3001 + // For windowless plugins a non-empty clip rectangle will be 1.3002 + // passed to the plugin during paint, an additional update 1.3003 + // of the the clip rectangle here is not required 1.3004 + if (aSetWindow && !mWidget && mPluginWindowVisible && !UseAsyncRendering()) 1.3005 + return; 1.3006 + 1.3007 + const NPWindow oldWindow = *mPluginWindow; 1.3008 + 1.3009 + bool windowless = (mPluginWindow->type == NPWindowTypeDrawable); 1.3010 + nsIntPoint origin = mObjectFrame->GetWindowOriginInPixels(windowless); 1.3011 + 1.3012 + mPluginWindow->x = origin.x; 1.3013 + mPluginWindow->y = origin.y; 1.3014 + 1.3015 + mPluginWindow->clipRect.left = 0; 1.3016 + mPluginWindow->clipRect.top = 0; 1.3017 + 1.3018 + if (mPluginWindowVisible && mPluginDocumentActiveState) { 1.3019 + mPluginWindow->clipRect.right = mPluginWindow->width; 1.3020 + mPluginWindow->clipRect.bottom = mPluginWindow->height; 1.3021 + } else { 1.3022 + mPluginWindow->clipRect.right = 0; 1.3023 + mPluginWindow->clipRect.bottom = 0; 1.3024 + } 1.3025 + 1.3026 + if (!aSetWindow) 1.3027 + return; 1.3028 + 1.3029 + if (mPluginWindow->x != oldWindow.x || 1.3030 + mPluginWindow->y != oldWindow.y || 1.3031 + mPluginWindow->clipRect.left != oldWindow.clipRect.left || 1.3032 + mPluginWindow->clipRect.top != oldWindow.clipRect.top || 1.3033 + mPluginWindow->clipRect.right != oldWindow.clipRect.right || 1.3034 + mPluginWindow->clipRect.bottom != oldWindow.clipRect.bottom) { 1.3035 + CallSetWindow(); 1.3036 + } 1.3037 +} 1.3038 + 1.3039 +void 1.3040 +nsPluginInstanceOwner::UpdateWindowVisibility(bool aVisible) 1.3041 +{ 1.3042 + mPluginWindowVisible = aVisible; 1.3043 + UpdateWindowPositionAndClipRect(true); 1.3044 +} 1.3045 + 1.3046 +void 1.3047 +nsPluginInstanceOwner::UpdateDocumentActiveState(bool aIsActive) 1.3048 +{ 1.3049 + mPluginDocumentActiveState = aIsActive; 1.3050 + UpdateWindowPositionAndClipRect(true); 1.3051 + 1.3052 +#ifdef MOZ_WIDGET_ANDROID 1.3053 + if (mInstance) { 1.3054 + if (!mPluginDocumentActiveState) 1.3055 + RemovePluginView(); 1.3056 + 1.3057 + mInstance->NotifyOnScreen(mPluginDocumentActiveState); 1.3058 + 1.3059 + // This is, perhaps, incorrect. It is supposed to be sent 1.3060 + // when "the webview has paused or resumed". The side effect 1.3061 + // is that Flash video players pause or resume (if they were 1.3062 + // playing before) based on the value here. I personally think 1.3063 + // we want that on Android when switching to another tab, so 1.3064 + // that's why we call it here. 1.3065 + mInstance->NotifyForeground(mPluginDocumentActiveState); 1.3066 + } 1.3067 +#endif 1.3068 +} 1.3069 +#endif // XP_MACOSX 1.3070 + 1.3071 +NS_IMETHODIMP 1.3072 +nsPluginInstanceOwner::CallSetWindow() 1.3073 +{ 1.3074 + if (mObjectFrame) { 1.3075 + mObjectFrame->CallSetWindow(false); 1.3076 + } else if (mInstance) { 1.3077 + if (UseAsyncRendering()) { 1.3078 + mInstance->AsyncSetWindow(mPluginWindow); 1.3079 + } else { 1.3080 + mInstance->SetWindow(mPluginWindow); 1.3081 + } 1.3082 + } 1.3083 + 1.3084 + return NS_OK; 1.3085 +} 1.3086 + 1.3087 +NS_IMETHODIMP 1.3088 +nsPluginInstanceOwner::GetContentsScaleFactor(double *result) 1.3089 +{ 1.3090 + NS_ENSURE_ARG_POINTER(result); 1.3091 + double scaleFactor = 1.0; 1.3092 + // On Mac, device pixels need to be translated to (and from) "display pixels" 1.3093 + // for plugins. On other platforms, plugin coordinates are always in device 1.3094 + // pixels. 1.3095 +#if defined(XP_MACOSX) 1.3096 + nsIPresShell* presShell = nsContentUtils::FindPresShellForDocument(mContent->OwnerDoc()); 1.3097 + if (presShell) { 1.3098 + scaleFactor = double(nsPresContext::AppUnitsPerCSSPixel())/ 1.3099 + presShell->GetPresContext()->DeviceContext()->UnscaledAppUnitsPerDevPixel(); 1.3100 + } 1.3101 +#endif 1.3102 + *result = scaleFactor; 1.3103 + return NS_OK; 1.3104 +} 1.3105 + 1.3106 +void nsPluginInstanceOwner::SetFrame(nsObjectFrame *aFrame) 1.3107 +{ 1.3108 + // Don't do anything if the frame situation hasn't changed. 1.3109 + if (mObjectFrame == aFrame) { 1.3110 + return; 1.3111 + } 1.3112 + 1.3113 + // If we already have a frame that is changing or going away... 1.3114 + if (mObjectFrame) { 1.3115 + // Make sure the old frame isn't holding a reference to us. 1.3116 + mObjectFrame->SetInstanceOwner(nullptr); 1.3117 + } 1.3118 + 1.3119 + // Swap in the new frame (or no frame) 1.3120 + mObjectFrame = aFrame; 1.3121 + 1.3122 + // Set up a new frame 1.3123 + if (mObjectFrame) { 1.3124 + mObjectFrame->SetInstanceOwner(this); 1.3125 + // Can only call PrepForDrawing on an object frame once. Don't do it here unless 1.3126 + // widget creation is complete. Doesn't matter if we actually have a widget. 1.3127 + if (mWidgetCreationComplete) { 1.3128 + mObjectFrame->PrepForDrawing(mWidget); 1.3129 + } 1.3130 + mObjectFrame->FixupWindow(mObjectFrame->GetContentRectRelativeToSelf().Size()); 1.3131 + mObjectFrame->InvalidateFrame(); 1.3132 + 1.3133 + nsFocusManager* fm = nsFocusManager::GetFocusManager(); 1.3134 + const nsIContent* content = aFrame->GetContent(); 1.3135 + if (fm && content) { 1.3136 + mContentFocused = (content == fm->GetFocusedContent()); 1.3137 + } 1.3138 + } 1.3139 +} 1.3140 + 1.3141 +nsObjectFrame* nsPluginInstanceOwner::GetFrame() 1.3142 +{ 1.3143 + return mObjectFrame; 1.3144 +} 1.3145 + 1.3146 +// Little helper function to resolve relative URL in 1.3147 +// |value| for certain inputs of |name| 1.3148 +void nsPluginInstanceOwner::FixUpURLS(const nsString &name, nsAString &value) 1.3149 +{ 1.3150 + if (name.LowerCaseEqualsLiteral("pluginspage")) { 1.3151 + nsCOMPtr<nsIURI> baseURI = GetBaseURI(); 1.3152 + nsAutoString newURL; 1.3153 + NS_MakeAbsoluteURI(newURL, value, baseURI); 1.3154 + if (!newURL.IsEmpty()) 1.3155 + value = newURL; 1.3156 + } 1.3157 +} 1.3158 + 1.3159 +NS_IMETHODIMP nsPluginInstanceOwner::PrivateModeChanged(bool aEnabled) 1.3160 +{ 1.3161 + return mInstance ? mInstance->PrivateModeStateChanged(aEnabled) : NS_OK; 1.3162 +} 1.3163 + 1.3164 +already_AddRefed<nsIURI> nsPluginInstanceOwner::GetBaseURI() const 1.3165 +{ 1.3166 + if (!mContent) { 1.3167 + return nullptr; 1.3168 + } 1.3169 + return mContent->GetBaseURI(); 1.3170 +} 1.3171 + 1.3172 +// nsPluginDOMContextMenuListener class implementation 1.3173 + 1.3174 +nsPluginDOMContextMenuListener::nsPluginDOMContextMenuListener(nsIContent* aContent) 1.3175 +{ 1.3176 + aContent->AddEventListener(NS_LITERAL_STRING("contextmenu"), this, true); 1.3177 +} 1.3178 + 1.3179 +nsPluginDOMContextMenuListener::~nsPluginDOMContextMenuListener() 1.3180 +{ 1.3181 +} 1.3182 + 1.3183 +NS_IMPL_ISUPPORTS(nsPluginDOMContextMenuListener, 1.3184 + nsIDOMEventListener) 1.3185 + 1.3186 +NS_IMETHODIMP 1.3187 +nsPluginDOMContextMenuListener::HandleEvent(nsIDOMEvent* aEvent) 1.3188 +{ 1.3189 + aEvent->PreventDefault(); // consume event 1.3190 + 1.3191 + return NS_OK; 1.3192 +} 1.3193 + 1.3194 +void nsPluginDOMContextMenuListener::Destroy(nsIContent* aContent) 1.3195 +{ 1.3196 + // Unregister context menu listener 1.3197 + aContent->RemoveEventListener(NS_LITERAL_STRING("contextmenu"), this, true); 1.3198 +}