layout/generic/nsObjectFrame.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 // vim:set ts=2 sts=2 sw=2 et cin:
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 /* rendering objects for replaced elements implemented by a plugin */
     9 #include "nsObjectFrame.h"
    11 #include "gfx2DGlue.h"
    12 #include "mozilla/BasicEvents.h"
    13 #ifdef XP_WIN
    14 // This is needed for DoublePassRenderingEvent.
    15 #include "mozilla/plugins/PluginMessageUtils.h"
    16 #endif
    18 #include "nscore.h"
    19 #include "nsCOMPtr.h"
    20 #include "nsPresContext.h"
    21 #include "nsIPresShell.h"
    22 #include "nsWidgetsCID.h"
    23 #include "nsView.h"
    24 #include "nsViewManager.h"
    25 #include "nsString.h"
    26 #include "nsGkAtoms.h"
    27 #include "nsIPluginInstanceOwner.h"
    28 #include "nsNPAPIPluginInstance.h"
    29 #include "nsIDOMElement.h"
    30 #include "nsRenderingContext.h"
    31 #include "npapi.h"
    32 #include "nsIObjectLoadingContent.h"
    33 #include "nsContentUtils.h"
    34 #include "nsDisplayList.h"
    35 #include "nsFocusManager.h"
    36 #include "nsLayoutUtils.h"
    37 #include "nsFrameManager.h"
    38 #include "nsIObserverService.h"
    39 #include "GeckoProfiler.h"
    40 #include <algorithm>
    42 #include "nsIObjectFrame.h"
    43 #include "nsPluginNativeWindow.h"
    44 #include "FrameLayerBuilder.h"
    46 #include "ImageLayers.h"
    47 #include "nsPluginInstanceOwner.h"
    49 #ifdef XP_WIN
    50 #include "gfxWindowsNativeDrawing.h"
    51 #include "gfxWindowsSurface.h"
    52 #endif
    54 #include "Layers.h"
    55 #include "ReadbackLayer.h"
    56 #include "ImageContainer.h"
    58 // accessibility support
    59 #ifdef ACCESSIBILITY
    60 #include "nsAccessibilityService.h"
    61 #endif
    63 #ifdef MOZ_LOGGING
    64 #define FORCE_PR_LOG 1 /* Allow logging in the release build */
    65 #endif /* MOZ_LOGGING */
    66 #include "prlog.h"
    68 #ifdef XP_MACOSX
    69 #include "gfxQuartzNativeDrawing.h"
    70 #include "nsPluginUtilsOSX.h"
    71 #include "mozilla/gfx/QuartzSupport.h"
    72 #endif
    74 #ifdef MOZ_X11
    75 #include "mozilla/X11Util.h"
    76 using mozilla::DefaultXDisplay;
    77 #endif
    79 #ifdef XP_WIN
    80 #include <wtypes.h>
    81 #include <winuser.h>
    82 #endif
    84 #ifdef MOZ_WIDGET_ANDROID
    85 #include "AndroidBridge.h"
    86 #include "GLContext.h"
    87 #endif
    89 #ifdef CreateEvent // Thank you MS.
    90 #undef CreateEvent
    91 #endif
    93 #ifdef PR_LOGGING 
    94 static PRLogModuleInfo *
    95 GetObjectFrameLog()
    96 {
    97   static PRLogModuleInfo *sLog;
    98   if (!sLog)
    99     sLog = PR_NewLogModule("nsObjectFrame");
   100   return sLog;
   101 }
   102 #endif /* PR_LOGGING */
   104 #if defined(XP_MACOSX) && !defined(__LP64__)
   106 // The header files QuickdrawAPI.h and QDOffscreen.h are missing on OS X 10.7
   107 // and up (though the QuickDraw APIs defined in them are still present) -- so
   108 // we need to supply the relevant parts of their contents here.  It's likely
   109 // that Apple will eventually remove the APIs themselves (probably in OS X
   110 // 10.8), so we need to make them weak imports, and test for their presence
   111 // before using them.
   112 extern "C" {
   113   #if !defined(__QUICKDRAWAPI__)
   114   extern void SetRect(
   115     Rect * r,
   116     short  left,
   117     short  top,
   118     short  right,
   119     short  bottom)
   120     __attribute__((weak_import));
   121   #endif /* __QUICKDRAWAPI__ */
   123   #if !defined(__QDOFFSCREEN__)
   124   extern QDErr NewGWorldFromPtr(
   125     GWorldPtr *   offscreenGWorld,
   126     UInt32        PixelFormat,
   127     const Rect *  boundsRect,
   128     CTabHandle    cTable,                /* can be nullptr */
   129     GDHandle      aGDevice,              /* can be nullptr */
   130     GWorldFlags   flags,
   131     Ptr           newBuffer,
   132     SInt32        rowBytes)
   133     __attribute__((weak_import));
   134   extern void DisposeGWorld(GWorldPtr offscreenGWorld)
   135     __attribute__((weak_import));
   136   #endif /* __QDOFFSCREEN__ */
   137 }
   139 #endif /* #if defined(XP_MACOSX) && !defined(__LP64__) */
   141 using namespace mozilla;
   142 using namespace mozilla::gfx;
   143 using namespace mozilla::layers;
   145 class PluginBackgroundSink : public ReadbackSink {
   146 public:
   147   PluginBackgroundSink(nsObjectFrame* aFrame, uint64_t aStartSequenceNumber)
   148     : mLastSequenceNumber(aStartSequenceNumber), mFrame(aFrame) {}
   149   ~PluginBackgroundSink()
   150   {
   151     if (mFrame) {
   152       mFrame->mBackgroundSink = nullptr;
   153     }
   154   }
   156   virtual void SetUnknown(uint64_t aSequenceNumber)
   157   {
   158     if (!AcceptUpdate(aSequenceNumber))
   159       return;
   160     mFrame->mInstanceOwner->SetBackgroundUnknown();
   161   }
   163   virtual already_AddRefed<gfxContext>
   164       BeginUpdate(const nsIntRect& aRect, uint64_t aSequenceNumber)
   165   {
   166     if (!AcceptUpdate(aSequenceNumber))
   167       return nullptr;
   168     return mFrame->mInstanceOwner->BeginUpdateBackground(aRect);
   169   }
   171   virtual void EndUpdate(gfxContext* aContext, const nsIntRect& aRect)
   172   {
   173     return mFrame->mInstanceOwner->EndUpdateBackground(aContext, aRect);
   174   }
   176   void Destroy() { mFrame = nullptr; }
   178 protected:
   179   bool AcceptUpdate(uint64_t aSequenceNumber) {
   180     if (aSequenceNumber > mLastSequenceNumber && mFrame &&
   181         mFrame->mInstanceOwner) {
   182       mLastSequenceNumber = aSequenceNumber;
   183       return true;
   184     }
   185     return false;
   186   }
   188   uint64_t mLastSequenceNumber;
   189   nsObjectFrame* mFrame;
   190 };
   192 nsObjectFrame::nsObjectFrame(nsStyleContext* aContext)
   193   : nsObjectFrameSuper(aContext)
   194   , mReflowCallbackPosted(false)
   195 {
   196   PR_LOG(GetObjectFrameLog(), PR_LOG_DEBUG,
   197          ("Created new nsObjectFrame %p\n", this));
   198 }
   200 nsObjectFrame::~nsObjectFrame()
   201 {
   202   PR_LOG(GetObjectFrameLog(), PR_LOG_DEBUG,
   203          ("nsObjectFrame %p deleted\n", this));
   204 }
   206 NS_QUERYFRAME_HEAD(nsObjectFrame)
   207   NS_QUERYFRAME_ENTRY(nsObjectFrame)
   208   NS_QUERYFRAME_ENTRY(nsIObjectFrame)
   209 NS_QUERYFRAME_TAIL_INHERITING(nsObjectFrameSuper)
   211 #ifdef ACCESSIBILITY
   212 a11y::AccType
   213 nsObjectFrame::AccessibleType()
   214 {
   215   return a11y::ePluginType;
   216 }
   218 #ifdef XP_WIN
   219 NS_IMETHODIMP nsObjectFrame::GetPluginPort(HWND *aPort)
   220 {
   221   *aPort = (HWND) mInstanceOwner->GetPluginPortFromWidget();
   222   return NS_OK;
   223 }
   224 #endif
   225 #endif
   227 void
   228 nsObjectFrame::Init(nsIContent*      aContent,
   229                     nsIFrame*        aParent,
   230                     nsIFrame*        aPrevInFlow)
   231 {
   232   PR_LOG(GetObjectFrameLog(), PR_LOG_DEBUG,
   233          ("Initializing nsObjectFrame %p for content %p\n", this, aContent));
   235   nsObjectFrameSuper::Init(aContent, aParent, aPrevInFlow);
   236 }
   238 void
   239 nsObjectFrame::DestroyFrom(nsIFrame* aDestructRoot)
   240 {
   241   if (mReflowCallbackPosted) {
   242     PresContext()->PresShell()->CancelReflowCallback(this);
   243   }
   245   // Tell content owner of the instance to disconnect its frame.
   246   nsCOMPtr<nsIObjectLoadingContent> objContent(do_QueryInterface(mContent));
   247   NS_ASSERTION(objContent, "Why not an object loading content?");
   249   // The content might not have a reference to the instance owner any longer in
   250   // the case of re-entry during instantiation or teardown, so make sure we're
   251   // dissociated.
   252   if (mInstanceOwner) {
   253     mInstanceOwner->SetFrame(nullptr);
   254   }
   255   objContent->HasNewFrame(nullptr);
   257   if (mBackgroundSink) {
   258     mBackgroundSink->Destroy();
   259   }
   261   nsObjectFrameSuper::DestroyFrom(aDestructRoot);
   262 }
   264 /* virtual */ void
   265 nsObjectFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
   266 {
   267   if (HasView()) {
   268     nsView* view = GetView();
   269     nsViewManager* vm = view->GetViewManager();
   270     if (vm) {
   271       nsViewVisibility visibility = 
   272         IsHidden() ? nsViewVisibility_kHide : nsViewVisibility_kShow;
   273       vm->SetViewVisibility(view, visibility);
   274     }
   275   }
   277   nsObjectFrameSuper::DidSetStyleContext(aOldStyleContext);
   278 }
   280 nsIAtom*
   281 nsObjectFrame::GetType() const
   282 {
   283   return nsGkAtoms::objectFrame; 
   284 }
   286 #ifdef DEBUG_FRAME_DUMP
   287 nsresult
   288 nsObjectFrame::GetFrameName(nsAString& aResult) const
   289 {
   290   return MakeFrameName(NS_LITERAL_STRING("ObjectFrame"), aResult);
   291 }
   292 #endif
   294 nsresult
   295 nsObjectFrame::PrepForDrawing(nsIWidget *aWidget)
   296 {
   297   mWidget = aWidget;
   299   nsView* view = GetView();
   300   NS_ASSERTION(view, "Object frames must have views");  
   301   if (!view) {
   302     return NS_ERROR_FAILURE;
   303   }
   305   nsViewManager* viewMan = view->GetViewManager();
   306   // mark the view as hidden since we don't know the (x,y) until Paint
   307   // XXX is the above comment correct?
   308   viewMan->SetViewVisibility(view, nsViewVisibility_kHide);
   310   //this is ugly. it was ripped off from didreflow(). MMP
   311   // Position and size view relative to its parent, not relative to our
   312   // parent frame (our parent frame may not have a view).
   314   nsView* parentWithView;
   315   nsPoint origin;
   316   nsRect r(0, 0, mRect.width, mRect.height);
   318   GetOffsetFromView(origin, &parentWithView);
   319   viewMan->ResizeView(view, r);
   320   viewMan->MoveViewTo(view, origin.x, origin.y);
   322   nsPresContext* presContext = PresContext();
   323   nsRootPresContext* rpc = presContext->GetRootPresContext();
   324   if (!rpc) {
   325     return NS_ERROR_FAILURE;
   326   }
   328   if (mWidget) {
   329     // Disallow windowed plugins in popups
   330     nsIFrame* rootFrame = rpc->PresShell()->FrameManager()->GetRootFrame();
   331     nsIWidget* parentWidget = rootFrame->GetNearestWidget();
   332     if (!parentWidget || nsLayoutUtils::GetDisplayRootFrame(this) != rootFrame) {
   333       return NS_ERROR_FAILURE;
   334     }
   336     mInnerView = viewMan->CreateView(GetContentRectRelativeToSelf(), view);
   337     if (!mInnerView) {
   338       NS_ERROR("Could not create inner view");
   339       return NS_ERROR_OUT_OF_MEMORY;
   340     }
   341     viewMan->InsertChild(view, mInnerView, nullptr, true);
   343     mWidget->SetParent(parentWidget);
   344     mWidget->Show(true);
   345     mWidget->Enable(true);
   347     // Set the plugin window to have an empty clip region until we know
   348     // what our true position, size and clip region are. These
   349     // will be reset when nsRootPresContext computes our true
   350     // geometry. The plugin window does need to have a good size here, so
   351     // set the size explicitly to a reasonable guess.
   352     nsAutoTArray<nsIWidget::Configuration,1> configurations;
   353     nsIWidget::Configuration* configuration = configurations.AppendElement();
   354     nscoord appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
   355     configuration->mChild = mWidget;
   356     configuration->mBounds.width = NSAppUnitsToIntPixels(mRect.width, appUnitsPerDevPixel);
   357     configuration->mBounds.height = NSAppUnitsToIntPixels(mRect.height, appUnitsPerDevPixel);
   358     parentWidget->ConfigureChildren(configurations);
   360     nsRefPtr<nsDeviceContext> dx = viewMan->GetDeviceContext();
   361     mInnerView->AttachWidgetEventHandler(mWidget);
   363 #ifdef XP_MACOSX
   364     // On Mac, we need to invalidate ourselves since even windowed
   365     // plugins are painted through Thebes and we need to ensure
   366     // the Thebes layer containing the plugin is updated.
   367     if (parentWidget == GetNearestWidget()) {
   368       InvalidateFrame();
   369     }
   370 #endif
   372     RegisterPluginForGeometryUpdates();
   374     // Here we set the background color for this widget because some plugins will use 
   375     // the child window background color when painting. If it's not set, it may default to gray
   376     // Sometimes, a frame doesn't have a background color or is transparent. In this
   377     // case, walk up the frame tree until we do find a frame with a background color
   378     for (nsIFrame* frame = this; frame; frame = frame->GetParent()) {
   379       nscolor bgcolor =
   380         frame->GetVisitedDependentColor(eCSSProperty_background_color);
   381       if (NS_GET_A(bgcolor) > 0) {  // make sure we got an actual color
   382         mWidget->SetBackgroundColor(bgcolor);
   383         break;
   384       }
   385     }
   386   } else {
   387     // Changing to windowless mode changes the NPWindow geometry.
   388     FixupWindow(GetContentRectRelativeToSelf().Size());
   390 #ifndef XP_MACOSX
   391     RegisterPluginForGeometryUpdates();
   392 #endif
   393   }
   395   if (!IsHidden()) {
   396     viewMan->SetViewVisibility(view, nsViewVisibility_kShow);
   397   }
   399 #ifdef ACCESSIBILITY
   400   nsAccessibilityService* accService = nsIPresShell::AccService();
   401   if (accService) {
   402     accService->RecreateAccessible(PresContext()->PresShell(), mContent);
   403   }
   404 #endif
   406   return NS_OK;
   407 }
   409 #define EMBED_DEF_WIDTH 240
   410 #define EMBED_DEF_HEIGHT 200
   412 /* virtual */ nscoord
   413 nsObjectFrame::GetMinWidth(nsRenderingContext *aRenderingContext)
   414 {
   415   nscoord result = 0;
   417   if (!IsHidden(false)) {
   418     nsIAtom *atom = mContent->Tag();
   419     if (atom == nsGkAtoms::applet || atom == nsGkAtoms::embed) {
   420       result = nsPresContext::CSSPixelsToAppUnits(EMBED_DEF_WIDTH);
   421     }
   422   }
   424   DISPLAY_MIN_WIDTH(this, result);
   425   return result;
   426 }
   428 /* virtual */ nscoord
   429 nsObjectFrame::GetPrefWidth(nsRenderingContext *aRenderingContext)
   430 {
   431   return nsObjectFrame::GetMinWidth(aRenderingContext);
   432 }
   434 void
   435 nsObjectFrame::GetDesiredSize(nsPresContext* aPresContext,
   436                               const nsHTMLReflowState& aReflowState,
   437                               nsHTMLReflowMetrics& aMetrics)
   438 {
   439   // By default, we have no area
   440   aMetrics.Width() = 0;
   441   aMetrics.Height() = 0;
   443   if (IsHidden(false)) {
   444     return;
   445   }
   447   aMetrics.Width() = aReflowState.ComputedWidth();
   448   aMetrics.Height() = aReflowState.ComputedHeight();
   450   // for EMBED and APPLET, default to 240x200 for compatibility
   451   nsIAtom *atom = mContent->Tag();
   452   if (atom == nsGkAtoms::applet || atom == nsGkAtoms::embed) {
   453     if (aMetrics.Width() == NS_UNCONSTRAINEDSIZE) {
   454       aMetrics.Width() = clamped(nsPresContext::CSSPixelsToAppUnits(EMBED_DEF_WIDTH),
   455                                aReflowState.ComputedMinWidth(),
   456                                aReflowState.ComputedMaxWidth());
   457     }
   458     if (aMetrics.Height() == NS_UNCONSTRAINEDSIZE) {
   459       aMetrics.Height() = clamped(nsPresContext::CSSPixelsToAppUnits(EMBED_DEF_HEIGHT),
   460                                 aReflowState.ComputedMinHeight(),
   461                                 aReflowState.ComputedMaxHeight());
   462     }
   464 #if defined(MOZ_WIDGET_GTK)
   465     // We need to make sure that the size of the object frame does not
   466     // exceed the maximum size of X coordinates.  See bug #225357 for
   467     // more information.  In theory Gtk2 can handle large coordinates,
   468     // but underlying plugins can't.
   469     aMetrics.Height() = std::min(aPresContext->DevPixelsToAppUnits(INT16_MAX), aMetrics.Height());
   470     aMetrics.Width() = std::min(aPresContext->DevPixelsToAppUnits(INT16_MAX), aMetrics.Width());
   471 #endif
   472   }
   474   // At this point, the width has an unconstrained value only if we have
   475   // nothing to go on (no width set, no information from the plugin, nothing).
   476   // Make up a number.
   477   if (aMetrics.Width() == NS_UNCONSTRAINEDSIZE) {
   478     aMetrics.Width() =
   479       (aReflowState.ComputedMinWidth() != NS_UNCONSTRAINEDSIZE) ?
   480         aReflowState.ComputedMinWidth() : 0;
   481   }
   483   // At this point, the height has an unconstrained value only in two cases:
   484   // a) We are in standards mode with percent heights and parent is auto-height
   485   // b) We have no height information at all.
   486   // In either case, we have to make up a number.
   487   if (aMetrics.Height() == NS_UNCONSTRAINEDSIZE) {
   488     aMetrics.Height() =
   489       (aReflowState.ComputedMinHeight() != NS_UNCONSTRAINEDSIZE) ?
   490         aReflowState.ComputedMinHeight() : 0;
   491   }
   493   // XXXbz don't add in the border and padding, because we screw up our
   494   // plugin's size and positioning if we do...  Eventually we _do_ want to
   495   // paint borders, though!  At that point, we will need to adjust the desired
   496   // size either here or in Reflow....  Further, we will need to fix Paint() to
   497   // call the superclass in all cases.
   498 }
   500 nsresult
   501 nsObjectFrame::Reflow(nsPresContext*           aPresContext,
   502                       nsHTMLReflowMetrics&     aMetrics,
   503                       const nsHTMLReflowState& aReflowState,
   504                       nsReflowStatus&          aStatus)
   505 {
   506   DO_GLOBAL_REFLOW_COUNT("nsObjectFrame");
   507   DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus);
   509   // Get our desired size
   510   GetDesiredSize(aPresContext, aReflowState, aMetrics);
   511   aMetrics.SetOverflowAreasToDesiredBounds();
   512   FinishAndStoreOverflow(&aMetrics);
   514   // delay plugin instantiation until all children have
   515   // arrived. Otherwise there may be PARAMs or other stuff that the
   516   // plugin needs to see that haven't arrived yet.
   517   if (!GetContent()->IsDoneAddingChildren()) {
   518     aStatus = NS_FRAME_COMPLETE;
   519     return NS_OK;
   520   }
   522   // if we are printing or print previewing, bail for now
   523   if (aPresContext->Medium() == nsGkAtoms::print) {
   524     aStatus = NS_FRAME_COMPLETE;
   525     return NS_OK;
   526   }
   528   nsRect r(0, 0, aMetrics.Width(), aMetrics.Height());
   529   r.Deflate(aReflowState.ComputedPhysicalBorderPadding());
   531   if (mInnerView) {
   532     nsViewManager* vm = mInnerView->GetViewManager();
   533     vm->MoveViewTo(mInnerView, r.x, r.y);
   534     vm->ResizeView(mInnerView, nsRect(nsPoint(0, 0), r.Size()), true);
   535   }
   537   FixupWindow(r.Size());
   538   if (!mReflowCallbackPosted) {
   539     mReflowCallbackPosted = true;
   540     aPresContext->PresShell()->PostReflowCallback(this);
   541   }
   543   aStatus = NS_FRAME_COMPLETE;
   545   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
   546   return NS_OK;
   547 }
   549 ///////////// nsIReflowCallback ///////////////
   551 bool
   552 nsObjectFrame::ReflowFinished()
   553 {
   554   mReflowCallbackPosted = false;
   555   CallSetWindow();
   556   return true;
   557 }
   559 void
   560 nsObjectFrame::ReflowCallbackCanceled()
   561 {
   562   mReflowCallbackPosted = false;
   563 }
   565 void
   566 nsObjectFrame::FixupWindow(const nsSize& aSize)
   567 {
   568   nsPresContext* presContext = PresContext();
   570   if (!mInstanceOwner)
   571     return;
   573   NPWindow *window;
   574   mInstanceOwner->GetWindow(window);
   576   NS_ENSURE_TRUE_VOID(window);
   578 #ifdef XP_MACOSX
   579   nsWeakFrame weakFrame(this);
   580   mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintDisable);
   581   if (!weakFrame.IsAlive()) {
   582     return;
   583   }
   584 #endif
   586   bool windowless = (window->type == NPWindowTypeDrawable);
   588   nsIntPoint origin = GetWindowOriginInPixels(windowless);
   590   // window must be in "display pixels"
   591   double scaleFactor = 1.0;
   592   if (NS_FAILED(mInstanceOwner->GetContentsScaleFactor(&scaleFactor))) {
   593     scaleFactor = 1.0;
   594   }
   595   int intScaleFactor = ceil(scaleFactor);
   596   window->x = origin.x / intScaleFactor;
   597   window->y = origin.y / intScaleFactor;
   598   window->width = presContext->AppUnitsToDevPixels(aSize.width) / intScaleFactor;
   599   window->height = presContext->AppUnitsToDevPixels(aSize.height) / intScaleFactor;
   601   // on the Mac we need to set the clipRect to { 0, 0, 0, 0 } for now. This will keep
   602   // us from drawing on screen until the widget is properly positioned, which will not
   603   // happen until we have finished the reflow process.
   604 #ifdef XP_MACOSX
   605   window->clipRect.top = 0;
   606   window->clipRect.left = 0;
   607   window->clipRect.bottom = 0;
   608   window->clipRect.right = 0;
   609 #else
   610   mInstanceOwner->UpdateWindowPositionAndClipRect(false);
   611 #endif
   613   NotifyPluginReflowObservers();
   614 }
   616 nsresult
   617 nsObjectFrame::CallSetWindow(bool aCheckIsHidden)
   618 {
   619   NPWindow *win = nullptr;
   621   nsresult rv = NS_ERROR_FAILURE;
   622   nsRefPtr<nsNPAPIPluginInstance> pi;
   623   if (!mInstanceOwner ||
   624       NS_FAILED(rv = mInstanceOwner->GetInstance(getter_AddRefs(pi))) ||
   625       !pi ||
   626       NS_FAILED(rv = mInstanceOwner->GetWindow(win)) || 
   627       !win)
   628     return rv;
   630   nsPluginNativeWindow *window = (nsPluginNativeWindow *)win;
   631 #ifdef XP_MACOSX
   632   nsWeakFrame weakFrame(this);
   633   mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintDisable);
   634   if (!weakFrame.IsAlive()) {
   635     return NS_ERROR_NOT_AVAILABLE;
   636   }
   637 #endif
   639   if (aCheckIsHidden && IsHidden())
   640     return NS_ERROR_FAILURE;
   642   // refresh the plugin port as well
   643   window->window = mInstanceOwner->GetPluginPortFromWidget();
   645   // Adjust plugin dimensions according to pixel snap results
   646   // and reduce amount of SetWindow calls
   647   nsPresContext* presContext = PresContext();
   648   nsRootPresContext* rootPC = presContext->GetRootPresContext();
   649   if (!rootPC)
   650     return NS_ERROR_FAILURE;
   651   int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
   652   nsIFrame* rootFrame = rootPC->PresShell()->FrameManager()->GetRootFrame();
   653   nsRect bounds = GetContentRectRelativeToSelf() + GetOffsetToCrossDoc(rootFrame);
   654   nsIntRect intBounds = bounds.ToNearestPixels(appUnitsPerDevPixel);
   656   // window must be in "display pixels"
   657   double scaleFactor = 1.0;
   658   if (NS_FAILED(mInstanceOwner->GetContentsScaleFactor(&scaleFactor))) {
   659     scaleFactor = 1.0;
   660   }
   661   size_t intScaleFactor = ceil(scaleFactor);
   662   window->x = intBounds.x / intScaleFactor;
   663   window->y = intBounds.y / intScaleFactor;
   664   window->width = intBounds.width / intScaleFactor;
   665   window->height = intBounds.height / intScaleFactor;
   667   // Calling SetWindow might destroy this frame. We need to use the instance
   668   // owner to clean up so hold a ref.
   669   nsRefPtr<nsPluginInstanceOwner> instanceOwnerRef(mInstanceOwner);
   671   // This will call pi->SetWindow and take care of window subclassing
   672   // if needed, see bug 132759. Calling SetWindow can destroy this frame
   673   // so check for that before doing anything else with this frame's memory.
   674   if (mInstanceOwner->UseAsyncRendering()) {
   675     rv = pi->AsyncSetWindow(window);
   676   }
   677   else {
   678     rv = window->CallSetWindow(pi);
   679   }
   681   instanceOwnerRef->ReleasePluginPort(window->window);
   683   return rv;
   684 }
   686 void
   687 nsObjectFrame::RegisterPluginForGeometryUpdates()
   688 {
   689   nsRootPresContext* rpc = PresContext()->GetRootPresContext();
   690   NS_ASSERTION(rpc, "We should have a root pres context!");
   691   if (mRootPresContextRegisteredWith == rpc || !rpc) {
   692     // Already registered with current root pres context,
   693     // or null root pres context...
   694     return;
   695   }
   696   if (mRootPresContextRegisteredWith && mRootPresContextRegisteredWith != rpc) {
   697     // Registered to some other root pres context. Unregister, and
   698     // re-register with our current one...
   699     UnregisterPluginForGeometryUpdates();
   700   }
   701   mRootPresContextRegisteredWith = rpc;
   702   mRootPresContextRegisteredWith->RegisterPluginForGeometryUpdates(mContent);
   703 }
   705 void
   706 nsObjectFrame::UnregisterPluginForGeometryUpdates()
   707 {
   708   if (!mRootPresContextRegisteredWith) {
   709     // Not registered...
   710     return;
   711   }
   712   mRootPresContextRegisteredWith->UnregisterPluginForGeometryUpdates(mContent);
   713   mRootPresContextRegisteredWith = nullptr;
   714 }
   716 void
   717 nsObjectFrame::SetInstanceOwner(nsPluginInstanceOwner* aOwner)
   718 {
   719   // The ownership model here is historically fuzzy. This should only be called
   720   // by nsPluginInstanceOwner when it is given a new frame, and
   721   // nsObjectLoadingContent should be arbitrating frame-ownership via its
   722   // HasNewFrame callback.
   723   mInstanceOwner = aOwner;
   724   if (mInstanceOwner) {
   725     return;
   726   }
   727   UnregisterPluginForGeometryUpdates();
   728   if (mWidget && mInnerView) {
   729     mInnerView->DetachWidgetEventHandler(mWidget);
   730     // Make sure the plugin is hidden in case an update of plugin geometry
   731     // hasn't happened since this plugin became hidden.
   732     nsIWidget* parent = mWidget->GetParent();
   733     if (parent) {
   734       nsTArray<nsIWidget::Configuration> configurations;
   735       nsIWidget::Configuration* configuration = configurations.AppendElement();
   736       configuration->mChild = mWidget;
   737       parent->ConfigureChildren(configurations);
   739       mWidget->Show(false);
   740       mWidget->Enable(false);
   741       mWidget->SetParent(nullptr);
   742     }
   743   }
   744 }
   746 bool
   747 nsObjectFrame::IsFocusable(int32_t *aTabIndex, bool aWithMouse)
   748 {
   749   if (aTabIndex)
   750     *aTabIndex = -1;
   751   return nsObjectFrameSuper::IsFocusable(aTabIndex, aWithMouse);
   752 }
   754 bool
   755 nsObjectFrame::IsHidden(bool aCheckVisibilityStyle) const
   756 {
   757   if (aCheckVisibilityStyle) {
   758     if (!StyleVisibility()->IsVisibleOrCollapsed())
   759       return true;    
   760   }
   762   // only <embed> tags support the HIDDEN attribute
   763   if (mContent->Tag() == nsGkAtoms::embed) {
   764     // Yes, these are really the kooky ways that you could tell 4.x
   765     // not to hide the <embed> once you'd put the 'hidden' attribute
   766     // on the tag...
   768     // HIDDEN w/ no attributes gets translated as we are hidden for
   769     // compatibility w/ 4.x and IE so we don't create a non-painting
   770     // widget in layout. See bug 188959.
   771     nsAutoString hidden;
   772     if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::hidden, hidden) &&
   773        (hidden.IsEmpty() ||
   774         (!hidden.LowerCaseEqualsLiteral("false") &&
   775          !hidden.LowerCaseEqualsLiteral("no") &&
   776          !hidden.LowerCaseEqualsLiteral("off")))) {
   777       return true;
   778     }
   779   }
   781   return false;
   782 }
   784 nsIntPoint nsObjectFrame::GetWindowOriginInPixels(bool aWindowless)
   785 {
   786   nsView * parentWithView;
   787   nsPoint origin(0,0);
   789   GetOffsetFromView(origin, &parentWithView);
   791   // if it's windowless, let's make sure we have our origin set right
   792   // it may need to be corrected, like after scrolling
   793   if (aWindowless && parentWithView) {
   794     nsPoint offsetToWidget;
   795     parentWithView->GetNearestWidget(&offsetToWidget);
   796     origin += offsetToWidget;
   797   }
   798   origin += GetContentRectRelativeToSelf().TopLeft();
   800   return nsIntPoint(PresContext()->AppUnitsToDevPixels(origin.x),
   801                     PresContext()->AppUnitsToDevPixels(origin.y));
   802 }
   804 nsresult
   805 nsObjectFrame::DidReflow(nsPresContext*            aPresContext,
   806                          const nsHTMLReflowState*  aReflowState,
   807                          nsDidReflowStatus         aStatus)
   808 {
   809   // Do this check before calling the superclass, as that clears
   810   // NS_FRAME_FIRST_REFLOW
   811   if (aStatus == nsDidReflowStatus::FINISHED &&
   812       (GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
   813     nsCOMPtr<nsIObjectLoadingContent> objContent(do_QueryInterface(mContent));
   814     NS_ASSERTION(objContent, "Why not an object loading content?");
   815     objContent->HasNewFrame(this);
   816   }
   818   nsresult rv = nsObjectFrameSuper::DidReflow(aPresContext, aReflowState, aStatus);
   820   // The view is created hidden; once we have reflowed it and it has been
   821   // positioned then we show it.
   822   if (aStatus != nsDidReflowStatus::FINISHED)
   823     return rv;
   825   if (HasView()) {
   826     nsView* view = GetView();
   827     nsViewManager* vm = view->GetViewManager();
   828     if (vm)
   829       vm->SetViewVisibility(view, IsHidden() ? nsViewVisibility_kHide : nsViewVisibility_kShow);
   830   }
   832   return rv;
   833 }
   835 /* static */ void
   836 nsObjectFrame::PaintPrintPlugin(nsIFrame* aFrame, nsRenderingContext* aCtx,
   837                                 const nsRect& aDirtyRect, nsPoint aPt)
   838 {
   839   nsPoint pt = aPt + aFrame->GetContentRectRelativeToSelf().TopLeft();
   840   nsRenderingContext::AutoPushTranslation translate(aCtx, pt);
   841   // FIXME - Bug 385435: Doesn't aDirtyRect need translating too?
   842   static_cast<nsObjectFrame*>(aFrame)->PrintPlugin(*aCtx, aDirtyRect);
   843 }
   845 class nsDisplayPluginReadback : public nsDisplayItem {
   846 public:
   847   nsDisplayPluginReadback(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
   848     : nsDisplayItem(aBuilder, aFrame)
   849   {
   850     MOZ_COUNT_CTOR(nsDisplayPluginReadback);
   851   }
   852 #ifdef NS_BUILD_REFCNT_LOGGING
   853   virtual ~nsDisplayPluginReadback() {
   854     MOZ_COUNT_DTOR(nsDisplayPluginReadback);
   855   }
   856 #endif
   858   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
   859                            bool* aSnap) MOZ_OVERRIDE;
   860   virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
   861                                    nsRegion* aVisibleRegion,
   862                                    const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
   864   NS_DISPLAY_DECL_NAME("PluginReadback", TYPE_PLUGIN_READBACK)
   866   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
   867                                              LayerManager* aManager,
   868                                              const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE
   869   {
   870     return static_cast<nsObjectFrame*>(mFrame)->BuildLayer(aBuilder, aManager, this, aContainerParameters);
   871   }
   873   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
   874                                    LayerManager* aManager,
   875                                    const ContainerLayerParameters& aParameters) MOZ_OVERRIDE
   876   {
   877     return LAYER_ACTIVE;
   878   }
   879 };
   881 static nsRect
   882 GetDisplayItemBounds(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem, nsIFrame* aFrame)
   883 {
   884   // XXX For slightly more accurate region computations we should pixel-snap this
   885   return aFrame->GetContentRectRelativeToSelf() + aItem->ToReferenceFrame();
   886 }
   888 nsRect
   889 nsDisplayPluginReadback::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
   890 {
   891   *aSnap = false;
   892   return GetDisplayItemBounds(aBuilder, this, mFrame);
   893 }
   895 bool
   896 nsDisplayPluginReadback::ComputeVisibility(nsDisplayListBuilder* aBuilder,
   897                                            nsRegion* aVisibleRegion,
   898                                            const nsRect& aAllowVisibleRegionExpansion)
   899 {
   900   if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
   901                                         aAllowVisibleRegionExpansion))
   902     return false;
   904   nsRect expand;
   905   bool snap;
   906   expand.IntersectRect(aAllowVisibleRegionExpansion, GetBounds(aBuilder, &snap));
   907   // *Add* our bounds to the visible region so that stuff underneath us is
   908   // likely to be made visible, so we can use it for a background! This is
   909   // a bit crazy since we normally only subtract from the visible region.
   910   aVisibleRegion->Or(*aVisibleRegion, expand);
   911   return true;
   912 }
   914 #ifdef MOZ_WIDGET_ANDROID
   916 class nsDisplayPluginVideo : public nsDisplayItem {
   917 public:
   918   nsDisplayPluginVideo(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsNPAPIPluginInstance::VideoInfo* aVideoInfo)
   919     : nsDisplayItem(aBuilder, aFrame), mVideoInfo(aVideoInfo)
   920   {
   921     MOZ_COUNT_CTOR(nsDisplayPluginVideo);
   922   }
   923 #ifdef NS_BUILD_REFCNT_LOGGING
   924   virtual ~nsDisplayPluginVideo() {
   925     MOZ_COUNT_DTOR(nsDisplayPluginVideo);
   926   }
   927 #endif
   929   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
   930                            bool* aSnap) MOZ_OVERRIDE;
   931   virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
   932                                    nsRegion* aVisibleRegion,
   933                                    const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
   935   NS_DISPLAY_DECL_NAME("PluginVideo", TYPE_PLUGIN_VIDEO)
   937   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
   938                                              LayerManager* aManager,
   939                                              const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE
   940   {
   941     return static_cast<nsObjectFrame*>(mFrame)->BuildLayer(aBuilder, aManager, this, aContainerParameters);
   942   }
   944   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
   945                                    LayerManager* aManager,
   946                                    const ContainerLayerParameters& aParameters) MOZ_OVERRIDE
   947   {
   948     return LAYER_ACTIVE;
   949   }
   951   nsNPAPIPluginInstance::VideoInfo* VideoInfo() { return mVideoInfo; }
   953 private:
   954   nsNPAPIPluginInstance::VideoInfo* mVideoInfo;
   955 };
   957 nsRect
   958 nsDisplayPluginVideo::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
   959 {
   960   *aSnap = false;
   961   return GetDisplayItemBounds(aBuilder, this, mFrame);
   962 }
   964 bool
   965 nsDisplayPluginVideo::ComputeVisibility(nsDisplayListBuilder* aBuilder,
   966                                            nsRegion* aVisibleRegion,
   967                                            const nsRect& aAllowVisibleRegionExpansion)
   968 {
   969   return nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
   970                                           aAllowVisibleRegionExpansion);
   971 }
   973 #endif
   975 nsRect
   976 nsDisplayPlugin::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
   977 {
   978   *aSnap = true;
   979   return GetDisplayItemBounds(aBuilder, this, mFrame);
   980 }
   982 void
   983 nsDisplayPlugin::Paint(nsDisplayListBuilder* aBuilder,
   984                        nsRenderingContext* aCtx)
   985 {
   986   nsObjectFrame* f = static_cast<nsObjectFrame*>(mFrame);
   987   bool snap;
   988   f->PaintPlugin(aBuilder, *aCtx, mVisibleRect, GetBounds(aBuilder, &snap));
   989 }
   991 bool
   992 nsDisplayPlugin::ComputeVisibility(nsDisplayListBuilder* aBuilder,
   993                                    nsRegion* aVisibleRegion,
   994                                    const nsRect& aAllowVisibleRegionExpansion)
   995 {
   996   if (aBuilder->IsForPluginGeometry()) {
   997     nsObjectFrame* f = static_cast<nsObjectFrame*>(mFrame);
   998     if (!aBuilder->IsInTransform() || f->IsPaintedByGecko()) {
   999       // Since transforms induce reference frames, we don't need to worry
  1000       // about this method fluffing out due to non-rectilinear transforms.
  1001       nsRect rAncestor = nsLayoutUtils::TransformFrameRectToAncestor(f,
  1002           f->GetContentRectRelativeToSelf(), ReferenceFrame());
  1003       nscoord appUnitsPerDevPixel =
  1004         ReferenceFrame()->PresContext()->AppUnitsPerDevPixel();
  1005       f->mNextConfigurationBounds = rAncestor.ToNearestPixels(appUnitsPerDevPixel);
  1007       nsRegion visibleRegion;
  1008       visibleRegion.And(*aVisibleRegion, GetClippedBounds(aBuilder));
  1009       // Make visibleRegion relative to f
  1010       visibleRegion.MoveBy(-ToReferenceFrame());
  1012       f->mNextConfigurationClipRegion.Clear();
  1013       nsRegionRectIterator iter(visibleRegion);
  1014       for (const nsRect* r = iter.Next(); r; r = iter.Next()) {
  1015         nsRect rAncestor =
  1016           nsLayoutUtils::TransformFrameRectToAncestor(f, *r, ReferenceFrame());
  1017         nsIntRect rPixels = rAncestor.ToNearestPixels(appUnitsPerDevPixel)
  1018             - f->mNextConfigurationBounds.TopLeft();
  1019         if (!rPixels.IsEmpty()) {
  1020           f->mNextConfigurationClipRegion.AppendElement(rPixels);
  1025     if (f->mInnerView) {
  1026       // This should produce basically the same rectangle (but not relative
  1027       // to the root frame). We only call this here for the side-effect of
  1028       // setting mViewToWidgetOffset on the view.
  1029       f->mInnerView->CalcWidgetBounds(eWindowType_plugin);
  1033   return nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
  1034                                           aAllowVisibleRegionExpansion);
  1037 nsRegion
  1038 nsDisplayPlugin::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
  1039                                  bool* aSnap)
  1041   *aSnap = false;
  1042   nsRegion result;
  1043   nsObjectFrame* f = static_cast<nsObjectFrame*>(mFrame);
  1044   if (!aBuilder->IsForPluginGeometry()) {
  1045     nsIWidget* widget = f->GetWidget();
  1046     if (widget) {
  1047       // Be conservative and treat plugins with widgets as not opaque,
  1048       // because that's simple and we might need the content under the widget
  1049       // if the widget is unexpectedly clipped away. (As can happen when
  1050       // chrome content over a plugin forces us to clip out the plugin for
  1051       // security reasons.)
  1052       // We shouldn't be repainting the content under plugins much anyway
  1053       // since there generally shouldn't be anything to invalidate or paint
  1054       // in ThebesLayers there.
  1055   	  return result;
  1059   if (f->IsOpaque()) {
  1060     nsRect bounds = GetBounds(aBuilder, aSnap);
  1061     if (aBuilder->IsForPluginGeometry() ||
  1062         (f->GetPaintedRect(this) + ToReferenceFrame()).Contains(bounds)) {
  1063       // We can treat this as opaque
  1064       result = bounds;
  1068   return result;
  1071 nsresult
  1072 nsObjectFrame::PluginEventNotifier::Run() {
  1073   nsCOMPtr<nsIObserverService> obsSvc =
  1074     mozilla::services::GetObserverService();
  1075   obsSvc->NotifyObservers(nullptr, "plugin-changed-event", mEventType.get());
  1076   return NS_OK;
  1079 void
  1080 nsObjectFrame::NotifyPluginReflowObservers()
  1082   nsContentUtils::AddScriptRunner(new PluginEventNotifier(NS_LITERAL_STRING("reflow")));
  1085 void
  1086 nsObjectFrame::DidSetWidgetGeometry()
  1088 #if defined(XP_MACOSX)
  1089   if (mInstanceOwner) {
  1090     mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintEnable);
  1092 #else
  1093   if (!mWidget && mInstanceOwner) {
  1094     // UpdateWindowVisibility will notify the plugin of position changes
  1095     // by updating the NPWindow and calling NPP_SetWindow/AsyncSetWindow.
  1096     // We treat windowless plugins inside popups as always visible, since
  1097     // plugins inside popups don't get valid mNextConfigurationBounds
  1098     // set up.
  1099     mInstanceOwner->UpdateWindowVisibility(
  1100       nsLayoutUtils::IsPopup(nsLayoutUtils::GetDisplayRootFrame(this)) ||
  1101       !mNextConfigurationBounds.IsEmpty());
  1103 #endif
  1106 bool
  1107 nsObjectFrame::IsOpaque() const
  1109 #if defined(XP_MACOSX)
  1110   // ???
  1111   return false;
  1112 #elif defined(MOZ_WIDGET_ANDROID)
  1113   // We don't know, so just assume transparent
  1114   return false;
  1115 #else
  1116   return !IsTransparentMode();
  1117 #endif
  1120 bool
  1121 nsObjectFrame::IsTransparentMode() const
  1123 #if defined(XP_MACOSX)
  1124   // ???
  1125   return false;
  1126 #else
  1127   if (!mInstanceOwner)
  1128     return false;
  1130   NPWindow *window = nullptr;
  1131   mInstanceOwner->GetWindow(window);
  1132   if (!window) {
  1133     return false;
  1136   if (window->type != NPWindowTypeDrawable)
  1137     return false;
  1139   nsresult rv;
  1140   nsRefPtr<nsNPAPIPluginInstance> pi;
  1141   rv = mInstanceOwner->GetInstance(getter_AddRefs(pi));
  1142   if (NS_FAILED(rv) || !pi)
  1143     return false;
  1145   bool transparent = false;
  1146   pi->IsTransparent(&transparent);
  1147   return transparent;
  1148 #endif
  1151 void
  1152 nsObjectFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
  1153                                 const nsRect&           aDirtyRect,
  1154                                 const nsDisplayListSet& aLists)
  1156   // XXX why are we painting collapsed object frames?
  1157   if (!IsVisibleOrCollapsedForPainting(aBuilder))
  1158     return;
  1160   DisplayBorderBackgroundOutline(aBuilder, aLists);
  1162   nsPresContext::nsPresContextType type = PresContext()->Type();
  1164   // If we are painting in Print Preview do nothing....
  1165   if (type == nsPresContext::eContext_PrintPreview)
  1166     return;
  1168   DO_GLOBAL_REFLOW_COUNT_DSP("nsObjectFrame");
  1170 #ifndef XP_MACOSX
  1171   if (mWidget && aBuilder->IsInTransform()) {
  1172     // Windowed plugins should not be rendered inside a transform.
  1173     return;
  1175 #endif
  1177   if (aBuilder->IsForPainting() && mInstanceOwner && mInstanceOwner->UseAsyncRendering()) {
  1178     NPWindow* window = nullptr;
  1179     mInstanceOwner->GetWindow(window);
  1180     bool isVisible = window && window->width > 0 && window->height > 0;
  1181     if (isVisible && aBuilder->ShouldSyncDecodeImages()) {
  1182   #ifndef XP_MACOSX
  1183       mInstanceOwner->UpdateWindowVisibility(true);
  1184   #endif
  1187     mInstanceOwner->NotifyPaintWaiter(aBuilder);
  1190   DisplayListClipState::AutoClipContainingBlockDescendantsToContentBox
  1191     clip(aBuilder, this, DisplayListClipState::ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT);
  1193   // determine if we are printing
  1194   if (type == nsPresContext::eContext_Print) {
  1195     aLists.Content()->AppendNewToTop(new (aBuilder)
  1196       nsDisplayGeneric(aBuilder, this, PaintPrintPlugin, "PrintPlugin",
  1197                        nsDisplayItem::TYPE_PRINT_PLUGIN));
  1198   } else {
  1199     LayerState state = GetLayerState(aBuilder, nullptr);
  1200     if (state == LAYER_INACTIVE &&
  1201         nsDisplayItem::ForceActiveLayers()) {
  1202       state = LAYER_ACTIVE;
  1204     // We don't need this on Android, and it just confuses things
  1205 #if !MOZ_WIDGET_ANDROID
  1206     if (aBuilder->IsPaintingToWindow() &&
  1207         state == LAYER_ACTIVE &&
  1208         IsTransparentMode()) {
  1209       aLists.Content()->AppendNewToTop(new (aBuilder)
  1210         nsDisplayPluginReadback(aBuilder, this));
  1212 #endif
  1214 #if MOZ_WIDGET_ANDROID
  1215     if (aBuilder->IsPaintingToWindow() &&
  1216         state == LAYER_ACTIVE) {
  1218       nsTArray<nsNPAPIPluginInstance::VideoInfo*> videos;
  1219       mInstanceOwner->GetVideos(videos);
  1221       for (uint32_t i = 0; i < videos.Length(); i++) {
  1222         aLists.Content()->AppendNewToTop(new (aBuilder)
  1223           nsDisplayPluginVideo(aBuilder, this, videos[i]));
  1226 #endif
  1228     aLists.Content()->AppendNewToTop(new (aBuilder)
  1229       nsDisplayPlugin(aBuilder, this));
  1233 void
  1234 nsObjectFrame::PrintPlugin(nsRenderingContext& aRenderingContext,
  1235                            const nsRect& aDirtyRect)
  1237   nsCOMPtr<nsIObjectLoadingContent> obj(do_QueryInterface(mContent));
  1238   if (!obj)
  1239     return;
  1241   nsIFrame* frame = nullptr;
  1242   obj->GetPrintFrame(&frame);
  1243   if (!frame)
  1244     return;
  1246   nsPresContext* presContext = PresContext();
  1247   // make sure this is REALLY an nsIObjectFrame
  1248   // we may need to go through the children to get it
  1249   nsIObjectFrame* objectFrame = do_QueryFrame(frame);
  1250   if (!objectFrame)
  1251     objectFrame = GetNextObjectFrame(presContext,frame);
  1252   if (!objectFrame)
  1253     return;
  1255   // finally we can get our plugin instance
  1256   nsRefPtr<nsNPAPIPluginInstance> pi;
  1257   if (NS_FAILED(objectFrame->GetPluginInstance(getter_AddRefs(pi))) || !pi)
  1258     return;
  1260   // now we need to setup the correct location for printing
  1261   NPWindow window;
  1262   window.window = nullptr;
  1264   // prepare embedded mode printing struct
  1265   NPPrint npprint;
  1266   npprint.mode = NP_EMBED;
  1268   // we need to find out if we are windowless or not
  1269   bool windowless = false;
  1270   pi->IsWindowless(&windowless);
  1271   window.type = windowless ? NPWindowTypeDrawable : NPWindowTypeWindow;
  1273   window.clipRect.bottom = 0; window.clipRect.top = 0;
  1274   window.clipRect.left = 0; window.clipRect.right = 0;
  1276 // platform specific printing code
  1277 #if defined(XP_MACOSX) && !defined(__LP64__)
  1278 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
  1279   // Don't use this code if any of the QuickDraw APIs it currently requires
  1280   // are missing (as they probably will be on OS X 10.8 and up).
  1281   if (!&::SetRect || !&::NewGWorldFromPtr || !&::DisposeGWorld) {
  1282     NS_WARNING("Cannot print plugin -- required QuickDraw APIs are missing!");
  1283     return;
  1286   nsSize contentSize = GetContentRectRelativeToSelf().Size();
  1287   window.x = 0;
  1288   window.y = 0;
  1289   window.width = presContext->AppUnitsToDevPixels(contentSize.width);
  1290   window.height = presContext->AppUnitsToDevPixels(contentSize.height);
  1292   gfxContext *ctx = aRenderingContext.ThebesContext();
  1293   if (!ctx)
  1294     return;
  1295   gfxContextAutoSaveRestore save(ctx);
  1297   ctx->NewPath();
  1299   gfxRect rect(window.x, window.y, window.width, window.height);
  1301   ctx->Rectangle(rect);
  1302   ctx->Clip();
  1304   gfxQuartzNativeDrawing nativeDraw(ctx, rect);
  1305   CGContextRef cgContext = nativeDraw.BeginNativeDrawing();
  1306   if (!cgContext) {
  1307     nativeDraw.EndNativeDrawing();
  1308     return;
  1311   window.clipRect.right = window.width;
  1312   window.clipRect.bottom = window.height;
  1313   window.type = NPWindowTypeDrawable;
  1315   ::Rect gwBounds;
  1316   ::SetRect(&gwBounds, 0, 0, window.width, window.height);
  1318   nsTArray<char> buffer(window.width * window.height * 4);
  1319   CGColorSpaceRef cspace = ::CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
  1320   if (!cspace) {
  1321     nativeDraw.EndNativeDrawing();
  1322     return;
  1324   CGContextRef cgBuffer =
  1325     ::CGBitmapContextCreate(buffer.Elements(), 
  1326                             window.width, window.height, 8, window.width * 4,
  1327                             cspace, kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedFirst);
  1328   ::CGColorSpaceRelease(cspace);
  1329   if (!cgBuffer) {
  1330     nativeDraw.EndNativeDrawing();
  1331     return;
  1333   GWorldPtr gWorld;
  1334   if (::NewGWorldFromPtr(&gWorld, k32ARGBPixelFormat, &gwBounds,
  1335                          nullptr, nullptr, 0,
  1336                          buffer.Elements(), window.width * 4) != noErr) {
  1337     ::CGContextRelease(cgBuffer);
  1338     nativeDraw.EndNativeDrawing();
  1339     return;
  1342   window.clipRect.right = window.width;
  1343   window.clipRect.bottom = window.height;
  1344   window.type = NPWindowTypeDrawable;
  1345   // Setting nsPluginPrint/NPPrint.print.embedPrint.window.window to
  1346   // &GWorldPtr and nsPluginPrint/NPPrint.print.embedPrint.platformPrint to
  1347   // GWorldPtr isn't any kind of standard (it's not documented anywhere).
  1348   // But that's what WebKit does.  And it's what the Flash plugin (apparently
  1349   // the only NPAPI plugin on OS X to support printing) seems to expect.  So
  1350   // we do the same.  The Flash plugin uses the CoreGraphics drawing mode.
  1351   // But a GWorldPtr should be usable in either CoreGraphics or QuickDraw
  1352   // drawing mode.  See bug 191046.
  1353   window.window = &gWorld;
  1354   npprint.print.embedPrint.platformPrint = gWorld;
  1355   npprint.print.embedPrint.window = window;
  1356   pi->Print(&npprint);
  1358   ::CGContextTranslateCTM(cgContext, 0.0f, float(window.height));
  1359   ::CGContextScaleCTM(cgContext, 1.0f, -1.0f);
  1360   CGImageRef image = ::CGBitmapContextCreateImage(cgBuffer);
  1361   if (!image) {
  1362     ::CGContextRestoreGState(cgContext);
  1363     ::CGContextRelease(cgBuffer);
  1364     ::DisposeGWorld(gWorld);
  1365     nativeDraw.EndNativeDrawing();
  1366     return;
  1368   ::CGContextDrawImage(cgContext,
  1369                        ::CGRectMake(0, 0, window.width, window.height),
  1370                        image);
  1371   ::CGImageRelease(image);
  1372   ::CGContextRelease(cgBuffer);
  1374   ::DisposeGWorld(gWorld);
  1376   nativeDraw.EndNativeDrawing();
  1377 #pragma clang diagnostic warning "-Wdeprecated-declarations"
  1378 #elif defined(XP_UNIX)
  1380   /* XXX this just flat-out doesn't work in a thebes world --
  1381    * RenderEPS is a no-op.  So don't bother to do any work here.
  1382    */
  1383   (void)window;
  1384   (void)npprint;
  1386 #elif defined(XP_WIN)
  1388   /* On Windows, we use the win32 printing surface to print.  This, in
  1389    * turn, uses the Cairo paginated surface, which in turn uses the
  1390    * meta surface to record all operations and then play them back.
  1391    * This doesn't work too well for plugins, because if plugins render
  1392    * directly into the DC, the meta surface won't have any knowledge
  1393    * of them, and so at the end when it actually does the replay step,
  1394    * it'll fill the background with white and draw over whatever was
  1395    * rendered before.
  1397    * So, to avoid this, we use PushGroup, which creates a new windows
  1398    * surface, the plugin renders to that, and then we use normal
  1399    * cairo methods to composite that in such that it's recorded using the
  1400    * meta surface.
  1401    */
  1403   /* we'll already be translated into the right spot by gfxWindowsNativeDrawing */
  1404   nsSize contentSize = GetContentRectRelativeToSelf().Size();
  1405   window.x = 0;
  1406   window.y = 0;
  1407   window.width = presContext->AppUnitsToDevPixels(contentSize.width);
  1408   window.height = presContext->AppUnitsToDevPixels(contentSize.height);
  1410   gfxContext *ctx = aRenderingContext.ThebesContext();
  1412   ctx->Save();
  1414   /* Make sure plugins don't do any damage outside of where they're supposed to */
  1415   ctx->NewPath();
  1416   gfxRect r(window.x, window.y, window.width, window.height);
  1417   ctx->Rectangle(r);
  1418   ctx->Clip();
  1420   gfxWindowsNativeDrawing nativeDraw(ctx, r);
  1421   do {
  1422     HDC dc = nativeDraw.BeginNativeDrawing();
  1423     if (!dc)
  1424       return;
  1426     // XXX don't we need to call nativeDraw.TransformToNativeRect here?
  1427     npprint.print.embedPrint.platformPrint = dc;
  1428     npprint.print.embedPrint.window = window;
  1429     // send off print info to plugin
  1430     pi->Print(&npprint);
  1432     nativeDraw.EndNativeDrawing();
  1433   } while (nativeDraw.ShouldRenderAgain());
  1434   nativeDraw.PaintToContext();
  1436   ctx->Restore();
  1437 #endif
  1439   // XXX Nav 4.x always sent a SetWindow call after print. Should we do the same?
  1440   // XXX Calling DidReflow here makes no sense!!!
  1441   nsDidReflowStatus status = nsDidReflowStatus::FINISHED; // should we use a special status?
  1442   frame->DidReflow(presContext,
  1443                    nullptr, status);  // DidReflow will take care of it
  1446 nsRect
  1447 nsObjectFrame::GetPaintedRect(nsDisplayPlugin* aItem)
  1449   if (!mInstanceOwner)
  1450     return nsRect();
  1451   nsRect r = GetContentRectRelativeToSelf();
  1452   if (!mInstanceOwner->UseAsyncRendering())
  1453     return r;
  1455   nsIntSize size = mInstanceOwner->GetCurrentImageSize();
  1456   nsPresContext* pc = PresContext();
  1457   r.IntersectRect(r, nsRect(0, 0, pc->DevPixelsToAppUnits(size.width),
  1458                                   pc->DevPixelsToAppUnits(size.height)));
  1459   return r;
  1462 LayerState
  1463 nsObjectFrame::GetLayerState(nsDisplayListBuilder* aBuilder,
  1464                              LayerManager* aManager)
  1466   if (!mInstanceOwner)
  1467     return LAYER_NONE;
  1469 #ifdef MOZ_WIDGET_ANDROID
  1470   // We always want a layer on Honeycomb and later
  1471   if (AndroidBridge::Bridge()->GetAPIVersion() >= 11)
  1472     return LAYER_ACTIVE;
  1473 #endif
  1475   if (!mInstanceOwner->UseAsyncRendering()) {
  1476     return LAYER_NONE;
  1479   return LAYER_ACTIVE;
  1482 already_AddRefed<Layer>
  1483 nsObjectFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
  1484                           LayerManager* aManager,
  1485                           nsDisplayItem* aItem,
  1486                           const ContainerLayerParameters& aContainerParameters)
  1488   if (!mInstanceOwner)
  1489     return nullptr;
  1491   NPWindow* window = nullptr;
  1492   mInstanceOwner->GetWindow(window);
  1493   if (!window)
  1494     return nullptr;
  1496   if (window->width <= 0 || window->height <= 0)
  1497     return nullptr;
  1499   // window is in "display pixels", but size needs to be in device pixels
  1500   double scaleFactor = 1.0;
  1501   if (NS_FAILED(mInstanceOwner->GetContentsScaleFactor(&scaleFactor))) {
  1502     scaleFactor = 1.0;
  1504   int intScaleFactor = ceil(scaleFactor);
  1505   IntSize size(window->width * intScaleFactor, window->height * intScaleFactor);
  1507   nsRect area = GetContentRectRelativeToSelf() + aItem->ToReferenceFrame();
  1508   gfxRect r = nsLayoutUtils::RectToGfxRect(area, PresContext()->AppUnitsPerDevPixel());
  1509   // to provide crisper and faster drawing.
  1510   r.Round();
  1511   nsRefPtr<Layer> layer =
  1512     (aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, aItem));
  1514   if (aItem->GetType() == nsDisplayItem::TYPE_PLUGIN) {
  1515     // Create image
  1516     nsRefPtr<ImageContainer> container = mInstanceOwner->GetImageContainer();
  1517     if (!container) {
  1518       // This can occur if our instance is gone.
  1519       return nullptr;
  1522     if (!layer) {
  1523       mInstanceOwner->NotifyPaintWaiter(aBuilder);
  1524       // Initialize ImageLayer
  1525       layer = aManager->CreateImageLayer();
  1526       if (!layer)
  1527         return nullptr;
  1530     NS_ASSERTION(layer->GetType() == Layer::TYPE_IMAGE, "Bad layer type");
  1531     ImageLayer* imglayer = static_cast<ImageLayer*>(layer.get());
  1532 #ifdef XP_MACOSX
  1533     if (!mInstanceOwner->UseAsyncRendering()) {
  1534       mInstanceOwner->DoCocoaEventDrawRect(r, nullptr);
  1536 #endif
  1538     imglayer->SetScaleToSize(size, ScaleMode::STRETCH);
  1539     imglayer->SetContainer(container);
  1540     GraphicsFilter filter =
  1541       nsLayoutUtils::GetGraphicsFilterForFrame(this);
  1542 #ifdef MOZ_GFX_OPTIMIZE_MOBILE
  1543     if (!aManager->IsCompositingCheap()) {
  1544       // Pixman just horrible with bilinear filter scaling
  1545       filter = GraphicsFilter::FILTER_NEAREST;
  1547 #endif
  1548     imglayer->SetFilter(filter);
  1550     layer->SetContentFlags(IsOpaque() ? Layer::CONTENT_OPAQUE : 0);
  1551 #ifdef MOZ_WIDGET_ANDROID
  1552   } else if (aItem->GetType() == nsDisplayItem::TYPE_PLUGIN_VIDEO) {
  1553     nsDisplayPluginVideo* videoItem = reinterpret_cast<nsDisplayPluginVideo*>(aItem);
  1554     nsNPAPIPluginInstance::VideoInfo* videoInfo = videoItem->VideoInfo();
  1556     nsRefPtr<ImageContainer> container = mInstanceOwner->GetImageContainerForVideo(videoInfo);
  1557     if (!container)
  1558       return nullptr;
  1560     if (!layer) {
  1561       // Initialize ImageLayer
  1562       layer = aManager->CreateImageLayer();
  1563       if (!layer)
  1564         return nullptr;
  1567     ImageLayer* imglayer = static_cast<ImageLayer*>(layer.get());
  1568     imglayer->SetContainer(container);
  1570     layer->SetContentFlags(IsOpaque() ? Layer::CONTENT_OPAQUE : 0);
  1572     // Set the offset and size according to the video dimensions
  1573     r.MoveBy(videoInfo->mDimensions.TopLeft());
  1574     size.width = videoInfo->mDimensions.width;
  1575     size.height = videoInfo->mDimensions.height;
  1576 #endif
  1577   } else {
  1578     NS_ASSERTION(aItem->GetType() == nsDisplayItem::TYPE_PLUGIN_READBACK,
  1579                  "Unknown item type");
  1580     NS_ABORT_IF_FALSE(!IsOpaque(), "Opaque plugins don't use backgrounds");
  1582     if (!layer) {
  1583       layer = aManager->CreateReadbackLayer();
  1584       if (!layer)
  1585         return nullptr;
  1587     NS_ASSERTION(layer->GetType() == Layer::TYPE_READBACK, "Bad layer type");
  1589     ReadbackLayer* readback = static_cast<ReadbackLayer*>(layer.get());
  1590     if (readback->GetSize() != ThebesIntSize(size)) {
  1591       // This will destroy any old background sink and notify us that the
  1592       // background is now unknown
  1593       readback->SetSink(nullptr);
  1594       readback->SetSize(ThebesIntSize(size));
  1596       if (mBackgroundSink) {
  1597         // Maybe we still have a background sink associated with another
  1598         // readback layer that wasn't recycled for some reason? Unhook it
  1599         // now so that if this frame goes away, it doesn't have a dangling
  1600         // reference to us.
  1601         mBackgroundSink->Destroy();
  1603       mBackgroundSink =
  1604         new PluginBackgroundSink(this,
  1605                                  readback->AllocateSequenceNumber());
  1606       readback->SetSink(mBackgroundSink);
  1607       // The layer has taken ownership of our sink. When either the sink dies
  1608       // or the frame dies, the connection from the surviving object is nulled out.
  1612   // Set a transform on the layer to draw the plugin in the right place
  1613   Matrix transform;
  1614   gfxPoint p = r.TopLeft() + aContainerParameters.mOffset;
  1615   transform.Translate(p.x, p.y);
  1617   layer->SetBaseTransform(Matrix4x4::From2D(transform));
  1618   layer->SetVisibleRegion(ThebesIntRect(IntRect(IntPoint(0, 0), size)));
  1619   return layer.forget();
  1622 void
  1623 nsObjectFrame::PaintPlugin(nsDisplayListBuilder* aBuilder,
  1624                            nsRenderingContext& aRenderingContext,
  1625                            const nsRect& aDirtyRect, const nsRect& aPluginRect)
  1627 #if defined(MOZ_WIDGET_ANDROID)
  1628   if (mInstanceOwner) {
  1629     gfxRect frameGfxRect =
  1630       PresContext()->AppUnitsToGfxUnits(aPluginRect);
  1631     gfxRect dirtyGfxRect =
  1632       PresContext()->AppUnitsToGfxUnits(aDirtyRect);
  1634     gfxContext* ctx = aRenderingContext.ThebesContext();
  1636     mInstanceOwner->Paint(ctx, frameGfxRect, dirtyGfxRect);
  1637     return;
  1639 #endif
  1641   // Screen painting code
  1642 #if defined(XP_MACOSX)
  1643   // delegate all painting to the plugin instance.
  1644   if (mInstanceOwner) {
  1645     if (mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreGraphics ||
  1646         mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreAnimation ||
  1647         mInstanceOwner->GetDrawingModel() == 
  1648                                   NPDrawingModelInvalidatingCoreAnimation) {
  1649       int32_t appUnitsPerDevPixel = PresContext()->AppUnitsPerDevPixel();
  1650       // Clip to the content area where the plugin should be drawn. If
  1651       // we don't do this, the plugin can draw outside its bounds.
  1652       nsIntRect contentPixels = aPluginRect.ToNearestPixels(appUnitsPerDevPixel);
  1653       nsIntRect dirtyPixels = aDirtyRect.ToOutsidePixels(appUnitsPerDevPixel);
  1654       nsIntRect clipPixels;
  1655       clipPixels.IntersectRect(contentPixels, dirtyPixels);
  1657       // Don't invoke the drawing code if the clip is empty.
  1658       if (clipPixels.IsEmpty())
  1659         return;
  1661       gfxRect nativeClipRect(clipPixels.x, clipPixels.y,
  1662                              clipPixels.width, clipPixels.height);
  1663       gfxContext* ctx = aRenderingContext.ThebesContext();
  1665       gfxContextAutoSaveRestore save(ctx);
  1666       ctx->NewPath();
  1667       ctx->Rectangle(nativeClipRect);
  1668       ctx->Clip();
  1669       gfxPoint offset(contentPixels.x, contentPixels.y);
  1670       ctx->Translate(offset);
  1672       gfxQuartzNativeDrawing nativeDrawing(ctx, nativeClipRect - offset);
  1674       CGContextRef cgContext = nativeDrawing.BeginNativeDrawing();
  1675       if (!cgContext) {
  1676         NS_WARNING("null CGContextRef during PaintPlugin");
  1677         return;
  1680       nsRefPtr<nsNPAPIPluginInstance> inst;
  1681       GetPluginInstance(getter_AddRefs(inst));
  1682       if (!inst) {
  1683         NS_WARNING("null plugin instance during PaintPlugin");
  1684         nativeDrawing.EndNativeDrawing();
  1685         return;
  1687       NPWindow* window;
  1688       mInstanceOwner->GetWindow(window);
  1689       if (!window) {
  1690         NS_WARNING("null plugin window during PaintPlugin");
  1691         nativeDrawing.EndNativeDrawing();
  1692         return;
  1694       NP_CGContext* cgPluginPortCopy =
  1695                 static_cast<NP_CGContext*>(mInstanceOwner->GetPluginPortCopy());
  1696       if (!cgPluginPortCopy) {
  1697         NS_WARNING("null plugin port copy during PaintPlugin");
  1698         nativeDrawing.EndNativeDrawing();
  1699         return;
  1702       mInstanceOwner->BeginCGPaint();
  1703       if (mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreAnimation ||
  1704           mInstanceOwner->GetDrawingModel() == 
  1705                                    NPDrawingModelInvalidatingCoreAnimation) {
  1706         // CoreAnimation is updated, render the layer and perform a readback.
  1707         mInstanceOwner->RenderCoreAnimation(cgContext, window->width, window->height);
  1708       } else {
  1709         mInstanceOwner->Paint(nativeClipRect - offset, cgContext);
  1711       mInstanceOwner->EndCGPaint();
  1713       nativeDrawing.EndNativeDrawing();
  1714     } else {
  1715       // FIXME - Bug 385435: Doesn't aDirtyRect need translating too?
  1716       nsRenderingContext::AutoPushTranslation
  1717         translate(&aRenderingContext, aPluginRect.TopLeft());
  1719       // this rect is used only in the CoreGraphics drawing model
  1720       gfxRect tmpRect(0, 0, 0, 0);
  1721       mInstanceOwner->Paint(tmpRect, nullptr);
  1724 #elif defined(MOZ_X11)
  1725   if (mInstanceOwner) {
  1726     NPWindow *window;
  1727     mInstanceOwner->GetWindow(window);
  1728     if (window->type == NPWindowTypeDrawable) {
  1729       gfxRect frameGfxRect =
  1730         PresContext()->AppUnitsToGfxUnits(aPluginRect);
  1731       gfxRect dirtyGfxRect =
  1732         PresContext()->AppUnitsToGfxUnits(aDirtyRect);
  1733       gfxContext* ctx = aRenderingContext.ThebesContext();
  1735       mInstanceOwner->Paint(ctx, frameGfxRect, dirtyGfxRect);
  1738 #elif defined(XP_WIN)
  1739   nsRefPtr<nsNPAPIPluginInstance> inst;
  1740   GetPluginInstance(getter_AddRefs(inst));
  1741   if (inst) {
  1742     gfxRect frameGfxRect =
  1743       PresContext()->AppUnitsToGfxUnits(aPluginRect);
  1744     gfxRect dirtyGfxRect =
  1745       PresContext()->AppUnitsToGfxUnits(aDirtyRect);
  1746     gfxContext *ctx = aRenderingContext.ThebesContext();
  1747     gfxMatrix currentMatrix = ctx->CurrentMatrix();
  1749     if (ctx->UserToDevicePixelSnapped(frameGfxRect, false)) {
  1750       dirtyGfxRect = ctx->UserToDevice(dirtyGfxRect);
  1751       ctx->IdentityMatrix();
  1753     dirtyGfxRect.RoundOut();
  1755     // Look if it's windowless
  1756     NPWindow *window;
  1757     mInstanceOwner->GetWindow(window);
  1759     if (window->type == NPWindowTypeDrawable) {
  1760       // the offset of the DC
  1761       nsPoint origin;
  1763       gfxWindowsNativeDrawing nativeDraw(ctx, frameGfxRect);
  1764       if (nativeDraw.IsDoublePass()) {
  1765         // OOP plugin specific: let the shim know before we paint if we are doing a
  1766         // double pass render. If this plugin isn't oop, the register window message
  1767         // will be ignored.
  1768         NPEvent pluginEvent;
  1769         pluginEvent.event = plugins::DoublePassRenderingEvent();
  1770         pluginEvent.wParam = 0;
  1771         pluginEvent.lParam = 0;
  1772         if (pluginEvent.event)
  1773           inst->HandleEvent(&pluginEvent, nullptr);
  1775       do {
  1776         HDC hdc = nativeDraw.BeginNativeDrawing();
  1777         if (!hdc)
  1778           return;
  1780         RECT dest;
  1781         nativeDraw.TransformToNativeRect(frameGfxRect, dest);
  1782         RECT dirty;
  1783         nativeDraw.TransformToNativeRect(dirtyGfxRect, dirty);
  1785         window->window = hdc;
  1786         window->x = dest.left;
  1787         window->y = dest.top;
  1788         window->clipRect.left = 0;
  1789         window->clipRect.top = 0;
  1790         // if we're painting, we're visible.
  1791         window->clipRect.right = window->width;
  1792         window->clipRect.bottom = window->height;
  1794         // Windowless plugins on windows need a special event to update their location,
  1795         // see bug 135737.
  1796         //
  1797         // bug 271442: note, the rectangle we send is now purely the bounds of the plugin
  1798         // relative to the window it is contained in, which is useful for the plugin to
  1799         // correctly translate mouse coordinates.
  1800         //
  1801         // this does not mesh with the comments for bug 135737 which imply that the rectangle
  1802         // must be clipped in some way to prevent the plugin attempting to paint over areas
  1803         // it shouldn't.
  1804         //
  1805         // since the two uses of the rectangle are mutually exclusive in some cases, and
  1806         // since I don't see any incorrect painting (at least with Flash and ViewPoint -
  1807         // the originator of bug 135737), it seems that windowless plugins are not relying
  1808         // on information here for clipping their drawing, and we can safely use this message
  1809         // to tell the plugin exactly where it is in all cases.
  1811         nsIntPoint origin = GetWindowOriginInPixels(true);
  1812         nsIntRect winlessRect = nsIntRect(origin, nsIntSize(window->width, window->height));
  1814         if (!mWindowlessRect.IsEqualEdges(winlessRect)) {
  1815           mWindowlessRect = winlessRect;
  1817           WINDOWPOS winpos;
  1818           memset(&winpos, 0, sizeof(winpos));
  1819           winpos.x = mWindowlessRect.x;
  1820           winpos.y = mWindowlessRect.y;
  1821           winpos.cx = mWindowlessRect.width;
  1822           winpos.cy = mWindowlessRect.height;
  1824           // finally, update the plugin by sending it a WM_WINDOWPOSCHANGED event
  1825           NPEvent pluginEvent;
  1826           pluginEvent.event = WM_WINDOWPOSCHANGED;
  1827           pluginEvent.wParam = 0;
  1828           pluginEvent.lParam = (LPARAM)&winpos;
  1829           inst->HandleEvent(&pluginEvent, nullptr);
  1832         inst->SetWindow(window);
  1834         mInstanceOwner->Paint(dirty, hdc);
  1835         nativeDraw.EndNativeDrawing();
  1836       } while (nativeDraw.ShouldRenderAgain());
  1837       nativeDraw.PaintToContext();
  1840     ctx->SetMatrix(currentMatrix);
  1842 #endif
  1845 nsresult
  1846 nsObjectFrame::HandleEvent(nsPresContext* aPresContext,
  1847                            WidgetGUIEvent* anEvent,
  1848                            nsEventStatus* anEventStatus)
  1850   NS_ENSURE_ARG_POINTER(anEvent);
  1851   NS_ENSURE_ARG_POINTER(anEventStatus);
  1852   nsresult rv = NS_OK;
  1854   if (!mInstanceOwner)
  1855     return NS_ERROR_NULL_POINTER;
  1857   mInstanceOwner->ConsiderNewEventloopNestingLevel();
  1859   if (anEvent->message == NS_PLUGIN_ACTIVATE) {
  1860     nsIFocusManager* fm = nsFocusManager::GetFocusManager();
  1861     nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(GetContent());
  1862     if (fm && elem)
  1863       return fm->SetFocus(elem, 0);
  1865   else if (anEvent->message == NS_PLUGIN_FOCUS) {
  1866     nsIFocusManager* fm = nsFocusManager::GetFocusManager();
  1867     if (fm)
  1868       return fm->FocusPlugin(GetContent());
  1871 #ifdef XP_MACOSX
  1872   if (anEvent->message == NS_PLUGIN_RESOLUTION_CHANGED) {
  1873     double scaleFactor = 1.0;
  1874     mInstanceOwner->GetContentsScaleFactor(&scaleFactor);
  1875     mInstanceOwner->ContentsScaleFactorChanged(scaleFactor);
  1876     return NS_OK;
  1878 #endif
  1880   if (mInstanceOwner->SendNativeEvents() &&
  1881       anEvent->IsNativeEventDelivererForPlugin()) {
  1882     *anEventStatus = mInstanceOwner->ProcessEvent(*anEvent);
  1883     // Due to plugin code reentering Gecko, this frame may be dead at this
  1884     // point.
  1885     return rv;
  1888 #ifdef XP_WIN
  1889   rv = nsObjectFrameSuper::HandleEvent(aPresContext, anEvent, anEventStatus);
  1890   return rv;
  1891 #endif
  1893 #ifdef XP_MACOSX
  1894   // we want to process some native mouse events in the cocoa event model
  1895   if ((anEvent->message == NS_MOUSE_ENTER ||
  1896        anEvent->message == NS_WHEEL_WHEEL) &&
  1897       mInstanceOwner->GetEventModel() == NPEventModelCocoa) {
  1898     *anEventStatus = mInstanceOwner->ProcessEvent(*anEvent);
  1899     // Due to plugin code reentering Gecko, this frame may be dead at this
  1900     // point.
  1901     return rv;
  1904   // These two calls to nsIPresShell::SetCapturingContext() (on mouse-down
  1905   // and mouse-up) are needed to make the routing of mouse events while
  1906   // dragging conform to standard OS X practice, and to the Cocoa NPAPI spec.
  1907   // See bug 525078 and bug 909678.
  1908   if (anEvent->message == NS_MOUSE_BUTTON_DOWN) {
  1909     nsIPresShell::SetCapturingContent(GetContent(), CAPTURE_IGNOREALLOWED);
  1911 #endif
  1913   rv = nsObjectFrameSuper::HandleEvent(aPresContext, anEvent, anEventStatus);
  1915   // We need to be careful from this point because the call to
  1916   // nsObjectFrameSuper::HandleEvent() might have killed us.
  1918 #ifdef XP_MACOSX
  1919   if (anEvent->message == NS_MOUSE_BUTTON_UP) {
  1920     nsIPresShell::SetCapturingContent(nullptr, 0);
  1922 #endif
  1924   return rv;
  1927 nsresult
  1928 nsObjectFrame::GetPluginInstance(nsNPAPIPluginInstance** aPluginInstance)
  1930   *aPluginInstance = nullptr;
  1932   if (!mInstanceOwner) {
  1933     return NS_OK;
  1936   return mInstanceOwner->GetInstance(aPluginInstance);
  1939 nsresult
  1940 nsObjectFrame::GetCursor(const nsPoint& aPoint, nsIFrame::Cursor& aCursor)
  1942   if (!mInstanceOwner) {
  1943     return NS_ERROR_FAILURE;
  1946   nsRefPtr<nsNPAPIPluginInstance> inst;
  1947   mInstanceOwner->GetInstance(getter_AddRefs(inst));
  1948   if (!inst) {
  1949     return NS_ERROR_FAILURE;
  1952   bool useDOMCursor = static_cast<nsNPAPIPluginInstance*>(inst.get())->UsesDOMForCursor();
  1953   if (!useDOMCursor) {
  1954     return NS_ERROR_FAILURE;
  1957   return nsObjectFrameSuper::GetCursor(aPoint, aCursor);
  1960 void
  1961 nsObjectFrame::SetIsDocumentActive(bool aIsActive)
  1963 #ifndef XP_MACOSX
  1964   if (mInstanceOwner) {
  1965     mInstanceOwner->UpdateDocumentActiveState(aIsActive);
  1967 #endif
  1970 // static
  1971 nsIObjectFrame *
  1972 nsObjectFrame::GetNextObjectFrame(nsPresContext* aPresContext, nsIFrame* aRoot)
  1974   nsIFrame* child = aRoot->GetFirstPrincipalChild();
  1976   while (child) {
  1977     nsIObjectFrame* outFrame = do_QueryFrame(child);
  1978     if (outFrame) {
  1979       nsRefPtr<nsNPAPIPluginInstance> pi;
  1980       outFrame->GetPluginInstance(getter_AddRefs(pi));  // make sure we have a REAL plugin
  1981       if (pi)
  1982         return outFrame;
  1985     outFrame = GetNextObjectFrame(aPresContext, child);
  1986     if (outFrame)
  1987       return outFrame;
  1988     child = child->GetNextSibling();
  1991   return nullptr;
  1994 /*static*/ void
  1995 nsObjectFrame::BeginSwapDocShells(nsIContent* aContent, void*)
  1997   NS_PRECONDITION(aContent, "");
  1999   // This function is called from a document content enumerator so we need
  2000   // to filter out the nsObjectFrames and ignore the rest.
  2001   nsIObjectFrame* obj = do_QueryFrame(aContent->GetPrimaryFrame());
  2002   if (!obj)
  2003     return;
  2005   nsObjectFrame* objectFrame = static_cast<nsObjectFrame*>(obj);
  2006   NS_ASSERTION(!objectFrame->mWidget || objectFrame->mWidget->GetParent(),
  2007                "Plugin windows must not be toplevel");
  2008   objectFrame->UnregisterPluginForGeometryUpdates();
  2011 /*static*/ void
  2012 nsObjectFrame::EndSwapDocShells(nsIContent* aContent, void*)
  2014   NS_PRECONDITION(aContent, "");
  2016   // This function is called from a document content enumerator so we need
  2017   // to filter out the nsObjectFrames and ignore the rest.
  2018   nsIObjectFrame* obj = do_QueryFrame(aContent->GetPrimaryFrame());
  2019   if (!obj)
  2020     return;
  2022   nsObjectFrame* objectFrame = static_cast<nsObjectFrame*>(obj);
  2023   nsRootPresContext* rootPC = objectFrame->PresContext()->GetRootPresContext();
  2024   NS_ASSERTION(rootPC, "unable to register the plugin frame");
  2025   nsIWidget* widget = objectFrame->mWidget;
  2026   if (widget) {
  2027     // Reparent the widget.
  2028     nsIWidget* parent =
  2029       rootPC->PresShell()->GetRootFrame()->GetNearestWidget();
  2030     widget->SetParent(parent);
  2031     nsWeakFrame weakFrame(objectFrame);
  2032     objectFrame->CallSetWindow();
  2033     if (!weakFrame.IsAlive()) {
  2034       return;
  2038 #ifdef XP_MACOSX
  2039   if (objectFrame->mWidget) {
  2040     objectFrame->RegisterPluginForGeometryUpdates();
  2042 #else
  2043   objectFrame->RegisterPluginForGeometryUpdates();
  2044 #endif
  2047 nsIFrame*
  2048 NS_NewObjectFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
  2050   return new (aPresShell) nsObjectFrame(aContext);
  2053 bool
  2054 nsObjectFrame::IsPaintedByGecko() const
  2056 #ifdef XP_MACOSX
  2057   return true;
  2058 #else
  2059   return !mWidget;
  2060 #endif
  2063 NS_IMPL_FRAMEARENA_HELPERS(nsObjectFrame)

mercurial