Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/layout/generic/nsPluginFrame.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
/* rendering objects for replaced elements implemented by a plugin */
8
9
#include "nsPluginFrame.h"
10
11
#include "gfx2DGlue.h"
12
#include "gfxContext.h"
13
#include "gfxMatrix.h"
14
#include "mozilla/gfx/2D.h"
15
#include "mozilla/BasicEvents.h"
16
#include "mozilla/MouseEvents.h"
17
#ifdef XP_WIN
18
// This is needed for DoublePassRenderingEvent.
19
#include "mozilla/plugins/PluginMessageUtils.h"
20
#endif
21
22
#include "nscore.h"
23
#include "nsCOMPtr.h"
24
#include "nsPresContext.h"
25
#include "nsIPresShell.h"
26
#include "nsWidgetsCID.h"
27
#include "nsView.h"
28
#include "nsViewManager.h"
29
#include "nsString.h"
30
#include "nsGkAtoms.h"
31
#include "nsIPluginInstanceOwner.h"
32
#include "nsNPAPIPluginInstance.h"
33
#include "npapi.h"
34
#include "nsIObjectLoadingContent.h"
35
#include "nsContentUtils.h"
36
#include "nsDisplayList.h"
37
#include "nsFocusManager.h"
38
#include "nsLayoutUtils.h"
39
#include "nsFrameManager.h"
40
#include "nsIObserverService.h"
41
#include "GeckoProfiler.h"
42
#include <algorithm>
43
44
#include "nsIObjectFrame.h"
45
#include "nsPluginNativeWindow.h"
46
#include "FrameLayerBuilder.h"
47
48
#include "ImageLayers.h"
49
#include "nsPluginInstanceOwner.h"
50
51
#ifdef XP_WIN
52
#include "gfxWindowsNativeDrawing.h"
53
#include "gfxWindowsSurface.h"
54
#endif
55
56
#include "Layers.h"
57
#include "ReadbackLayer.h"
58
#include "ImageContainer.h"
59
#include "mozilla/layers/WebRenderLayerManager.h"
60
61
// accessibility support
62
#ifdef ACCESSIBILITY
63
#include "nsAccessibilityService.h"
64
#endif
65
66
#include "mozilla/Logging.h"
67
68
#ifdef XP_MACOSX
69
#include "gfxQuartzNativeDrawing.h"
70
#include "mozilla/gfx/QuartzSupport.h"
71
#endif
72
73
#ifdef MOZ_X11
74
#include "mozilla/X11Util.h"
75
using mozilla::DefaultXDisplay;
76
#endif
77
78
#ifdef XP_WIN
79
#include <wtypes.h>
80
#include <winuser.h>
81
#endif
82
83
#include "mozilla/dom/TabChild.h"
84
85
#ifdef CreateEvent // Thank you MS.
86
#undef CreateEvent
87
#endif
88
89
static mozilla::LazyLogModule sPluginFrameLog("nsPluginFrame");
90
91
using namespace mozilla;
92
using namespace mozilla::gfx;
93
using namespace mozilla::layers;
94
95
class PluginBackgroundSink : public ReadbackSink {
96
public:
97
  PluginBackgroundSink(nsPluginFrame* aFrame, uint64_t aStartSequenceNumber)
98
0
    : mLastSequenceNumber(aStartSequenceNumber), mFrame(aFrame) {}
99
  ~PluginBackgroundSink() override
100
0
  {
101
0
    if (mFrame) {
102
0
      mFrame->mBackgroundSink = nullptr;
103
0
    }
104
0
  }
105
106
  void SetUnknown(uint64_t aSequenceNumber) override
107
0
  {
108
0
    if (!AcceptUpdate(aSequenceNumber))
109
0
      return;
110
0
    mFrame->mInstanceOwner->SetBackgroundUnknown();
111
0
  }
112
113
  already_AddRefed<DrawTarget>
114
      BeginUpdate(const nsIntRect& aRect, uint64_t aSequenceNumber) override
115
0
  {
116
0
    if (!AcceptUpdate(aSequenceNumber))
117
0
      return nullptr;
118
0
    return mFrame->mInstanceOwner->BeginUpdateBackground(aRect);
119
0
  }
120
121
  void EndUpdate(const nsIntRect& aRect) override
122
0
  {
123
0
    return mFrame->mInstanceOwner->EndUpdateBackground(aRect);
124
0
  }
125
126
0
  void Destroy() { mFrame = nullptr; }
127
128
protected:
129
0
  bool AcceptUpdate(uint64_t aSequenceNumber) {
130
0
    if (aSequenceNumber > mLastSequenceNumber && mFrame &&
131
0
        mFrame->mInstanceOwner) {
132
0
      mLastSequenceNumber = aSequenceNumber;
133
0
      return true;
134
0
    }
135
0
    return false;
136
0
  }
137
138
  uint64_t mLastSequenceNumber;
139
  nsPluginFrame* mFrame;
140
};
141
142
nsPluginFrame::nsPluginFrame(ComputedStyle* aStyle)
143
  : nsFrame(aStyle, kClassID)
144
  , mInstanceOwner(nullptr)
145
  , mOuterView(nullptr)
146
  , mInnerView(nullptr)
147
  , mBackgroundSink(nullptr)
148
  , mReflowCallbackPosted(false)
149
0
{
150
0
  MOZ_LOG(sPluginFrameLog, LogLevel::Debug,
151
0
         ("Created new nsPluginFrame %p\n", this));
152
0
}
153
154
nsPluginFrame::~nsPluginFrame()
155
0
{
156
0
  MOZ_LOG(sPluginFrameLog, LogLevel::Debug,
157
0
         ("nsPluginFrame %p deleted\n", this));
158
0
}
159
160
0
NS_QUERYFRAME_HEAD(nsPluginFrame)
161
0
  NS_QUERYFRAME_ENTRY(nsPluginFrame)
162
0
  NS_QUERYFRAME_ENTRY(nsIObjectFrame)
163
0
NS_QUERYFRAME_TAIL_INHERITING(nsFrame)
164
165
#ifdef ACCESSIBILITY
166
a11y::AccType
167
nsPluginFrame::AccessibleType()
168
0
{
169
0
  return a11y::ePluginType;
170
0
}
171
172
#ifdef XP_WIN
173
NS_IMETHODIMP nsPluginFrame::GetPluginPort(HWND *aPort)
174
{
175
  *aPort = (HWND) mInstanceOwner->GetPluginPort();
176
  return NS_OK;
177
}
178
#endif
179
#endif
180
181
void
182
nsPluginFrame::Init(nsIContent*       aContent,
183
                    nsContainerFrame* aParent,
184
                    nsIFrame*         aPrevInFlow)
185
0
{
186
0
  MOZ_LOG(sPluginFrameLog, LogLevel::Debug,
187
0
         ("Initializing nsPluginFrame %p for content %p\n", this, aContent));
188
0
189
0
  nsFrame::Init(aContent, aParent, aPrevInFlow);
190
0
  CreateView();
191
0
}
192
193
void
194
nsPluginFrame::DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData)
195
0
{
196
0
  if (mReflowCallbackPosted) {
197
0
    PresShell()->CancelReflowCallback(this);
198
0
  }
199
0
200
0
  // Ensure our DidComposite observer is gone.
201
0
  mDidCompositeObserver = nullptr;
202
0
203
0
  // Tell content owner of the instance to disconnect its frame.
204
0
  nsCOMPtr<nsIObjectLoadingContent> objContent(do_QueryInterface(mContent));
205
0
  NS_ASSERTION(objContent, "Why not an object loading content?");
206
0
207
0
  // The content might not have a reference to the instance owner any longer in
208
0
  // the case of re-entry during instantiation or teardown, so make sure we're
209
0
  // dissociated.
210
0
  if (mInstanceOwner) {
211
0
    mInstanceOwner->SetFrame(nullptr);
212
0
  }
213
0
  objContent->HasNewFrame(nullptr);
214
0
215
0
  if (mBackgroundSink) {
216
0
    mBackgroundSink->Destroy();
217
0
  }
218
0
219
0
  nsFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
220
0
}
221
222
/* virtual */ void
223
nsPluginFrame::DidSetComputedStyle(ComputedStyle* aOldComputedStyle)
224
0
{
225
0
  if (HasView()) {
226
0
    nsView* view = GetView();
227
0
    nsViewManager* vm = view->GetViewManager();
228
0
    if (vm) {
229
0
      nsViewVisibility visibility =
230
0
        IsHidden() ? nsViewVisibility_kHide : nsViewVisibility_kShow;
231
0
      vm->SetViewVisibility(view, visibility);
232
0
    }
233
0
  }
234
0
235
0
  nsFrame::DidSetComputedStyle(aOldComputedStyle);
236
0
}
237
238
#ifdef DEBUG_FRAME_DUMP
239
nsresult
240
nsPluginFrame::GetFrameName(nsAString& aResult) const
241
{
242
  return MakeFrameName(NS_LITERAL_STRING("PluginFrame"), aResult);
243
}
244
#endif
245
246
nsresult
247
nsPluginFrame::PrepForDrawing(nsIWidget *aWidget)
248
0
{
249
0
  mWidget = aWidget;
250
0
251
0
  nsView* view = GetView();
252
0
  NS_ASSERTION(view, "Object frames must have views");
253
0
  if (!view) {
254
0
    return NS_ERROR_FAILURE;
255
0
  }
256
0
257
0
  nsViewManager* viewMan = view->GetViewManager();
258
0
  // mark the view as hidden since we don't know the (x,y) until Paint
259
0
  // XXX is the above comment correct?
260
0
  viewMan->SetViewVisibility(view, nsViewVisibility_kHide);
261
0
262
0
  //this is ugly. it was ripped off from didreflow(). MMP
263
0
  // Position and size view relative to its parent, not relative to our
264
0
  // parent frame (our parent frame may not have a view).
265
0
266
0
  nsView* parentWithView;
267
0
  nsPoint origin;
268
0
  nsRect r(0, 0, mRect.width, mRect.height);
269
0
270
0
  GetOffsetFromView(origin, &parentWithView);
271
0
  viewMan->ResizeView(view, r);
272
0
  viewMan->MoveViewTo(view, origin.x, origin.y);
273
0
274
0
  nsPresContext* presContext = PresContext();
275
0
  nsRootPresContext* rpc = presContext->GetRootPresContext();
276
0
  if (!rpc) {
277
0
    return NS_ERROR_FAILURE;
278
0
  }
279
0
280
0
  if (mWidget) {
281
0
    // Disallow windowed plugins in popups
282
0
    nsIFrame* rootFrame = rpc->PresShell()->GetRootFrame();
283
0
    nsIWidget* parentWidget = rootFrame->GetNearestWidget();
284
0
    if (!parentWidget || nsLayoutUtils::GetDisplayRootFrame(this) != rootFrame) {
285
0
      return NS_ERROR_FAILURE;
286
0
    }
287
0
288
0
    // We can already have mInnerView if our instance owner went away and then
289
0
    // came back. So clear the old one before creating a new one.
290
0
    if (mInnerView) {
291
0
      if (mInnerView->GetWidget()) {
292
0
        // The widget listener should have already been cleared by
293
0
        // SetInstanceOwner (with a null instance owner).
294
0
        MOZ_RELEASE_ASSERT(mInnerView->GetWidget()->GetWidgetListener() == nullptr);
295
0
      }
296
0
      mInnerView->Destroy();
297
0
      mInnerView = nullptr;
298
0
    }
299
0
    mInnerView = viewMan->CreateView(GetContentRectRelativeToSelf(), view);
300
0
    if (!mInnerView) {
301
0
      NS_ERROR("Could not create inner view");
302
0
      return NS_ERROR_OUT_OF_MEMORY;
303
0
    }
304
0
    viewMan->InsertChild(view, mInnerView, nullptr, true);
305
0
306
0
    mWidget->SetParent(parentWidget);
307
0
    mWidget->Enable(true);
308
0
    mWidget->Show(true);
309
0
310
0
    // Set the plugin window to have an empty clip region until we know
311
0
    // what our true position, size and clip region are. These
312
0
    // will be reset when nsRootPresContext computes our true
313
0
    // geometry. The plugin window does need to have a good size here, so
314
0
    // set the size explicitly to a reasonable guess.
315
0
    AutoTArray<nsIWidget::Configuration,1> configurations;
316
0
    nsIWidget::Configuration* configuration = configurations.AppendElement();
317
0
    nscoord appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
318
0
    configuration->mChild = mWidget;
319
0
    configuration->mBounds.width = NSAppUnitsToIntPixels(mRect.width, appUnitsPerDevPixel);
320
0
    configuration->mBounds.height = NSAppUnitsToIntPixels(mRect.height, appUnitsPerDevPixel);
321
0
    parentWidget->ConfigureChildren(configurations);
322
0
323
0
    mInnerView->AttachWidgetEventHandler(mWidget);
324
0
325
#ifdef XP_MACOSX
326
    // On Mac, we need to invalidate ourselves since even windowed
327
    // plugins are painted through Thebes and we need to ensure
328
    // the PaintedLayer containing the plugin is updated.
329
    if (parentWidget == GetNearestWidget()) {
330
      InvalidateFrame();
331
    }
332
#endif
333
334
0
    RegisterPluginForGeometryUpdates();
335
0
336
0
    // Here we set the background color for this widget because some plugins will use
337
0
    // the child window background color when painting. If it's not set, it may default to gray
338
0
    // Sometimes, a frame doesn't have a background color or is transparent. In this
339
0
    // case, walk up the frame tree until we do find a frame with a background color
340
0
    for (nsIFrame* frame = this; frame; frame = frame->GetParent()) {
341
0
      nscolor bgcolor = frame->
342
0
        GetVisitedDependentColor(&nsStyleBackground::mBackgroundColor);
343
0
      if (NS_GET_A(bgcolor) > 0) {  // make sure we got an actual color
344
0
        mWidget->SetBackgroundColor(bgcolor);
345
0
        break;
346
0
      }
347
0
    }
348
0
  } else {
349
0
    // Changing to windowless mode changes the NPWindow geometry.
350
0
    FixupWindow(GetContentRectRelativeToSelf().Size());
351
0
    RegisterPluginForGeometryUpdates();
352
0
  }
353
0
354
0
  if (!IsHidden()) {
355
0
    viewMan->SetViewVisibility(view, nsViewVisibility_kShow);
356
0
  }
357
0
358
0
#ifdef ACCESSIBILITY
359
0
  nsAccessibilityService* accService = nsIPresShell::AccService();
360
0
  if (accService) {
361
0
    accService->RecreateAccessible(PresShell(), mContent);
362
0
  }
363
0
#endif
364
0
365
0
  return NS_OK;
366
0
}
367
368
0
#define EMBED_DEF_WIDTH 240
369
0
#define EMBED_DEF_HEIGHT 200
370
371
/* virtual */ nscoord
372
nsPluginFrame::GetMinISize(gfxContext *aRenderingContext)
373
0
{
374
0
  nscoord result = 0;
375
0
376
0
  if (!IsHidden(false)) {
377
0
    if (mContent->IsHTMLElement(nsGkAtoms::embed)) {
378
0
      bool vertical = GetWritingMode().IsVertical();
379
0
      result = nsPresContext::CSSPixelsToAppUnits(
380
0
        vertical ? EMBED_DEF_HEIGHT : EMBED_DEF_WIDTH);
381
0
    }
382
0
  }
383
0
384
0
  DISPLAY_MIN_INLINE_SIZE(this, result);
385
0
  return result;
386
0
}
387
388
/* virtual */ nscoord
389
nsPluginFrame::GetPrefISize(gfxContext *aRenderingContext)
390
0
{
391
0
  return nsPluginFrame::GetMinISize(aRenderingContext);
392
0
}
393
394
void
395
nsPluginFrame::GetWidgetConfiguration(nsTArray<nsIWidget::Configuration>* aConfigurations)
396
0
{
397
0
  if (!mWidget) {
398
0
    return;
399
0
  }
400
0
401
0
  if (!mWidget->GetParent()) {
402
0
    // Plugin widgets should not be toplevel except when they're out of the
403
0
    // document, in which case the plugin should not be registered for
404
0
    // geometry updates and this should not be called. But apparently we
405
0
    // have bugs where mWidget sometimes is toplevel here. Bail out.
406
0
    NS_ERROR("Plugin widgets registered for geometry updates should not be toplevel");
407
0
    return;
408
0
  }
409
0
410
0
  nsIWidget::Configuration* configuration = aConfigurations->AppendElement();
411
0
  configuration->mChild = mWidget;
412
0
  configuration->mBounds = mNextConfigurationBounds;
413
0
  configuration->mClipRegion = mNextConfigurationClipRegion;
414
0
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
415
0
  if (XRE_IsContentProcess()) {
416
0
    configuration->mWindowID = (uintptr_t)mWidget->GetNativeData(NS_NATIVE_PLUGIN_PORT);
417
0
    configuration->mVisible = mWidget->IsVisible();
418
0
419
0
  }
420
0
#endif // defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
421
0
}
422
423
void
424
nsPluginFrame::GetDesiredSize(nsPresContext* aPresContext,
425
                              const ReflowInput& aReflowInput,
426
                              ReflowOutput& aMetrics)
427
0
{
428
0
  // By default, we have no area
429
0
  aMetrics.ClearSize();
430
0
431
0
  if (IsHidden(false)) {
432
0
    return;
433
0
  }
434
0
435
0
  aMetrics.Width() = aReflowInput.ComputedWidth();
436
0
  aMetrics.Height() = aReflowInput.ComputedHeight();
437
0
438
0
  // for EMBED, default to 240x200 for compatibility
439
0
  if (mContent->IsHTMLElement(nsGkAtoms::embed)) {
440
0
    if (aMetrics.Width() == NS_UNCONSTRAINEDSIZE) {
441
0
      aMetrics.Width() = clamped(nsPresContext::CSSPixelsToAppUnits(EMBED_DEF_WIDTH),
442
0
                               aReflowInput.ComputedMinWidth(),
443
0
                               aReflowInput.ComputedMaxWidth());
444
0
    }
445
0
    if (aMetrics.Height() == NS_UNCONSTRAINEDSIZE) {
446
0
      aMetrics.Height() = clamped(nsPresContext::CSSPixelsToAppUnits(EMBED_DEF_HEIGHT),
447
0
                                aReflowInput.ComputedMinHeight(),
448
0
                                aReflowInput.ComputedMaxHeight());
449
0
    }
450
0
451
0
#if defined(MOZ_WIDGET_GTK)
452
0
    // We need to make sure that the size of the object frame does not
453
0
    // exceed the maximum size of X coordinates.  See bug #225357 for
454
0
    // more information.  In theory Gtk2 can handle large coordinates,
455
0
    // but underlying plugins can't.
456
0
    aMetrics.Height() = std::min(aPresContext->DevPixelsToAppUnits(INT16_MAX), aMetrics.Height());
457
0
    aMetrics.Width() = std::min(aPresContext->DevPixelsToAppUnits(INT16_MAX), aMetrics.Width());
458
0
#endif
459
0
  }
460
0
461
0
  // At this point, the width has an unconstrained value only if we have
462
0
  // nothing to go on (no width set, no information from the plugin, nothing).
463
0
  // Make up a number.
464
0
  if (aMetrics.Width() == NS_UNCONSTRAINEDSIZE) {
465
0
    aMetrics.Width() =
466
0
      (aReflowInput.ComputedMinWidth() != NS_UNCONSTRAINEDSIZE) ?
467
0
        aReflowInput.ComputedMinWidth() : 0;
468
0
  }
469
0
470
0
  // At this point, the height has an unconstrained value only in two cases:
471
0
  // a) We are in standards mode with percent heights and parent is auto-height
472
0
  // b) We have no height information at all.
473
0
  // In either case, we have to make up a number.
474
0
  if (aMetrics.Height() == NS_UNCONSTRAINEDSIZE) {
475
0
    aMetrics.Height() =
476
0
      (aReflowInput.ComputedMinHeight() != NS_UNCONSTRAINEDSIZE) ?
477
0
        aReflowInput.ComputedMinHeight() : 0;
478
0
  }
479
0
480
0
  // XXXbz don't add in the border and padding, because we screw up our
481
0
  // plugin's size and positioning if we do...  Eventually we _do_ want to
482
0
  // paint borders, though!  At that point, we will need to adjust the desired
483
0
  // size either here or in Reflow....  Further, we will need to fix Paint() to
484
0
  // call the superclass in all cases.
485
0
}
486
487
void
488
nsPluginFrame::Reflow(nsPresContext*           aPresContext,
489
                      ReflowOutput&     aMetrics,
490
                      const ReflowInput& aReflowInput,
491
                      nsReflowStatus&          aStatus)
492
0
{
493
0
  MarkInReflow();
494
0
  DO_GLOBAL_REFLOW_COUNT("nsPluginFrame");
495
0
  DISPLAY_REFLOW(aPresContext, this, aReflowInput, aMetrics, aStatus);
496
0
  MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!");
497
0
498
0
  // Get our desired size
499
0
  GetDesiredSize(aPresContext, aReflowInput, aMetrics);
500
0
  aMetrics.SetOverflowAreasToDesiredBounds();
501
0
  FinishAndStoreOverflow(&aMetrics);
502
0
503
0
  // delay plugin instantiation until all children have
504
0
  // arrived. Otherwise there may be PARAMs or other stuff that the
505
0
  // plugin needs to see that haven't arrived yet.
506
0
  if (!GetContent()->IsDoneAddingChildren()) {
507
0
    return;
508
0
  }
509
0
510
0
  // if we are printing or print previewing, bail for now
511
0
  if (aPresContext->Medium() == nsGkAtoms::print) {
512
0
    return;
513
0
  }
514
0
515
0
  nsRect r(0, 0, aMetrics.Width(), aMetrics.Height());
516
0
  r.Deflate(aReflowInput.ComputedPhysicalBorderPadding());
517
0
518
0
  if (mInnerView) {
519
0
    nsViewManager* vm = mInnerView->GetViewManager();
520
0
    vm->MoveViewTo(mInnerView, r.x, r.y);
521
0
    vm->ResizeView(mInnerView, nsRect(nsPoint(0, 0), r.Size()), true);
522
0
  }
523
0
524
0
  FixupWindow(r.Size());
525
0
  if (!mReflowCallbackPosted) {
526
0
    mReflowCallbackPosted = true;
527
0
    aPresContext->PresShell()->PostReflowCallback(this);
528
0
  }
529
0
530
0
  NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aMetrics);
531
0
}
532
533
///////////// nsIReflowCallback ///////////////
534
535
bool
536
nsPluginFrame::ReflowFinished()
537
0
{
538
0
  mReflowCallbackPosted = false;
539
0
  CallSetWindow();
540
0
  return true;
541
0
}
542
543
void
544
nsPluginFrame::ReflowCallbackCanceled()
545
0
{
546
0
  mReflowCallbackPosted = false;
547
0
}
548
549
void
550
nsPluginFrame::FixupWindow(const nsSize& aSize)
551
0
{
552
0
  nsPresContext* presContext = PresContext();
553
0
554
0
  if (!mInstanceOwner)
555
0
    return;
556
0
557
0
  NPWindow *window;
558
0
  mInstanceOwner->GetWindow(window);
559
0
560
0
  NS_ENSURE_TRUE_VOID(window);
561
0
562
0
  bool windowless = (window->type == NPWindowTypeDrawable);
563
0
564
0
  nsIntPoint origin = GetWindowOriginInPixels(windowless);
565
0
566
0
  // window must be in "display pixels"
567
#if defined(XP_MACOSX)
568
  // window must be in "display pixels"
569
  double scaleFactor = 1.0;
570
  if (NS_FAILED(mInstanceOwner->GetContentsScaleFactor(&scaleFactor))) {
571
    scaleFactor = 1.0;
572
  }
573
  int intScaleFactor = ceil(scaleFactor);
574
  window->x = origin.x / intScaleFactor;
575
  window->y = origin.y / intScaleFactor;
576
  window->width = presContext->AppUnitsToDevPixels(aSize.width) / intScaleFactor;
577
  window->height = presContext->AppUnitsToDevPixels(aSize.height) / intScaleFactor;
578
#else
579
  window->x = origin.x;
580
0
  window->y = origin.y;
581
0
  window->width = presContext->AppUnitsToDevPixels(aSize.width);
582
0
  window->height = presContext->AppUnitsToDevPixels(aSize.height);
583
0
#endif
584
0
585
0
#ifndef XP_MACOSX
586
0
  mInstanceOwner->UpdateWindowPositionAndClipRect(false);
587
0
#endif
588
0
589
0
  NotifyPluginReflowObservers();
590
0
}
591
592
nsresult
593
nsPluginFrame::CallSetWindow(bool aCheckIsHidden)
594
0
{
595
0
  NPWindow *win = nullptr;
596
0
597
0
  nsresult rv = NS_ERROR_FAILURE;
598
0
  RefPtr<nsNPAPIPluginInstance> pi;
599
0
  if (!mInstanceOwner ||
600
0
      NS_FAILED(rv = mInstanceOwner->GetInstance(getter_AddRefs(pi))) ||
601
0
      !pi ||
602
0
      NS_FAILED(rv = mInstanceOwner->GetWindow(win)) ||
603
0
      !win)
604
0
    return rv;
605
0
606
0
  nsPluginNativeWindow *window = (nsPluginNativeWindow *)win;
607
0
608
0
  if (aCheckIsHidden && IsHidden())
609
0
    return NS_ERROR_FAILURE;
610
0
611
0
  // Calling either nsPluginInstanceOwner::FixUpPluginWindow() (here,
612
0
  // on OS X) or SetWindow() (below, on all platforms) can destroy this
613
0
  // frame.  (FixUpPluginWindow() calls SetWindow()).  So grab a safe
614
0
  // reference to mInstanceOwner which we can use below, if needed.
615
0
  RefPtr<nsPluginInstanceOwner> instanceOwnerRef(mInstanceOwner);
616
0
617
0
  // refresh the plugin port as well
618
#ifdef XP_MACOSX
619
  mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintEnable);
620
  // Bail now if our frame has been destroyed.
621
  if (!instanceOwnerRef->GetFrame()) {
622
    return NS_ERROR_FAILURE;
623
  }
624
#endif
625
  window->window = mInstanceOwner->GetPluginPort();
626
0
627
0
  // Adjust plugin dimensions according to pixel snap results
628
0
  // and reduce amount of SetWindow calls
629
0
  nsPresContext* presContext = PresContext();
630
0
  nsRootPresContext* rootPC = presContext->GetRootPresContext();
631
0
  if (!rootPC)
632
0
    return NS_ERROR_FAILURE;
633
0
  int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
634
0
  nsIFrame* rootFrame = rootPC->PresShell()->GetRootFrame();
635
0
  nsRect bounds = GetContentRectRelativeToSelf() + GetOffsetToCrossDoc(rootFrame);
636
0
  nsIntRect intBounds = bounds.ToNearestPixels(appUnitsPerDevPixel);
637
0
638
0
  // In e10s, this returns the offset to the top level window, in non-e10s
639
0
  // it return 0,0.
640
0
  LayoutDeviceIntPoint intOffset = GetRemoteTabChromeOffset();
641
0
  intBounds.x += intOffset.x;
642
0
  intBounds.y += intOffset.y;
643
0
644
#if defined(XP_MACOSX)
645
  // window must be in "display pixels"
646
  double scaleFactor = 1.0;
647
  if (NS_FAILED(instanceOwnerRef->GetContentsScaleFactor(&scaleFactor))) {
648
    scaleFactor = 1.0;
649
  }
650
651
  size_t intScaleFactor = ceil(scaleFactor);
652
  window->x = intBounds.x / intScaleFactor;
653
  window->y = intBounds.y / intScaleFactor;
654
  window->width = intBounds.width / intScaleFactor;
655
  window->height = intBounds.height / intScaleFactor;
656
#else
657
  window->x = intBounds.x;
658
0
  window->y = intBounds.y;
659
0
  window->width = intBounds.width;
660
0
  window->height = intBounds.height;
661
0
#endif
662
0
  // BE CAREFUL: By the time we get here the PluginFrame is sometimes destroyed
663
0
  // and poisoned. If we reference local fields (implicit this deref),
664
0
  // we will crash.
665
0
  instanceOwnerRef->ResolutionMayHaveChanged();
666
0
667
0
  // This will call pi->SetWindow and take care of window subclassing
668
0
  // if needed, see bug 132759. Calling SetWindow can destroy this frame
669
0
  // so check for that before doing anything else with this frame's memory.
670
0
  if (instanceOwnerRef->UseAsyncRendering()) {
671
0
    rv = pi->AsyncSetWindow(window);
672
0
  }
673
0
  else {
674
0
    rv = window->CallSetWindow(pi);
675
0
  }
676
0
677
0
  instanceOwnerRef->ReleasePluginPort(window->window);
678
0
679
0
  return rv;
680
0
}
681
682
void
683
nsPluginFrame::RegisterPluginForGeometryUpdates()
684
0
{
685
0
  nsRootPresContext* rpc = PresContext()->GetRootPresContext();
686
0
  NS_ASSERTION(rpc, "We should have a root pres context!");
687
0
  if (mRootPresContextRegisteredWith == rpc || !rpc) {
688
0
    // Already registered with current root pres context,
689
0
    // or null root pres context...
690
0
    return;
691
0
  }
692
0
  if (mRootPresContextRegisteredWith && mRootPresContextRegisteredWith != rpc) {
693
0
    // Registered to some other root pres context. Unregister, and
694
0
    // re-register with our current one...
695
0
    UnregisterPluginForGeometryUpdates();
696
0
  }
697
0
  mRootPresContextRegisteredWith = rpc;
698
0
  mRootPresContextRegisteredWith->RegisterPluginForGeometryUpdates(mContent);
699
0
}
700
701
void
702
nsPluginFrame::UnregisterPluginForGeometryUpdates()
703
0
{
704
0
  if (!mRootPresContextRegisteredWith) {
705
0
    // Not registered...
706
0
    return;
707
0
  }
708
0
  mRootPresContextRegisteredWith->UnregisterPluginForGeometryUpdates(mContent);
709
0
  mRootPresContextRegisteredWith = nullptr;
710
0
}
711
712
void
713
nsPluginFrame::SetInstanceOwner(nsPluginInstanceOwner* aOwner)
714
0
{
715
0
  // The ownership model here is historically fuzzy. This should only be called
716
0
  // by nsPluginInstanceOwner when it is given a new frame, and
717
0
  // nsObjectLoadingContent should be arbitrating frame-ownership via its
718
0
  // HasNewFrame callback.
719
0
  mInstanceOwner = aOwner;
720
0
721
0
  // Reset the DidCompositeObserver since the owner changed.
722
0
  mDidCompositeObserver = nullptr;
723
0
724
0
  if (mInstanceOwner) {
725
0
    return;
726
0
  }
727
0
728
0
  UnregisterPluginForGeometryUpdates();
729
0
  if (mWidget && mInnerView) {
730
0
    mInnerView->DetachWidgetEventHandler(mWidget);
731
0
    // Make sure the plugin is hidden in case an update of plugin geometry
732
0
    // hasn't happened since this plugin became hidden.
733
0
    nsIWidget* parent = mWidget->GetParent();
734
0
    if (parent) {
735
0
      nsTArray<nsIWidget::Configuration> configurations;
736
0
      nsIWidget::Configuration* configuration = configurations.AppendElement();
737
0
      configuration->mChild = mWidget;
738
0
      parent->ConfigureChildren(configurations);
739
0
740
0
      mWidget->Show(false);
741
0
      mWidget->Enable(false);
742
0
      mWidget->SetParent(nullptr);
743
0
    }
744
0
  }
745
0
}
746
747
bool
748
nsPluginFrame::IsFocusable(int32_t *aTabIndex, bool aWithMouse)
749
0
{
750
0
  if (aTabIndex)
751
0
    *aTabIndex = -1;
752
0
  return nsFrame::IsFocusable(aTabIndex, aWithMouse);
753
0
}
754
755
bool
756
nsPluginFrame::IsHidden(bool aCheckVisibilityStyle) const
757
0
{
758
0
  if (aCheckVisibilityStyle) {
759
0
    if (!StyleVisibility()->IsVisibleOrCollapsed())
760
0
      return true;
761
0
  }
762
0
763
0
  // only <embed> tags support the HIDDEN attribute
764
0
  if (mContent->IsHTMLElement(nsGkAtoms::embed)) {
765
0
    // Yes, these are really the kooky ways that you could tell 4.x
766
0
    // not to hide the <embed> once you'd put the 'hidden' attribute
767
0
    // on the tag...
768
0
769
0
    // HIDDEN w/ no attributes gets translated as we are hidden for
770
0
    // compatibility w/ 4.x and IE so we don't create a non-painting
771
0
    // widget in layout. See bug 188959.
772
0
    nsAutoString hidden;
773
0
    if (mContent->AsElement()->GetAttr(kNameSpaceID_None,
774
0
                                       nsGkAtoms::hidden,
775
0
                                       hidden) &&
776
0
       (hidden.IsEmpty() ||
777
0
        (!hidden.LowerCaseEqualsLiteral("false") &&
778
0
         !hidden.LowerCaseEqualsLiteral("no") &&
779
0
         !hidden.LowerCaseEqualsLiteral("off")))) {
780
0
      return true;
781
0
    }
782
0
  }
783
0
784
0
  return false;
785
0
}
786
787
mozilla::LayoutDeviceIntPoint
788
nsPluginFrame::GetRemoteTabChromeOffset()
789
0
{
790
0
  LayoutDeviceIntPoint offset;
791
0
  if (XRE_IsContentProcess()) {
792
0
    if (nsPIDOMWindowOuter* window = GetContent()->OwnerDoc()->GetWindow()) {
793
0
      if (nsCOMPtr<nsPIDOMWindowOuter> topWindow = window->GetTop()) {
794
0
        dom::TabChild* tc = dom::TabChild::GetFrom(topWindow);
795
0
        if (tc) {
796
0
          offset += tc->GetChromeOffset();
797
0
        }
798
0
      }
799
0
    }
800
0
  }
801
0
  return offset;
802
0
}
803
804
nsIntPoint
805
nsPluginFrame::GetWindowOriginInPixels(bool aWindowless)
806
0
{
807
0
  nsView * parentWithView;
808
0
  nsPoint origin(0,0);
809
0
810
0
  GetOffsetFromView(origin, &parentWithView);
811
0
812
0
  // if it's windowless, let's make sure we have our origin set right
813
0
  // it may need to be corrected, like after scrolling
814
0
  if (aWindowless && parentWithView) {
815
0
    nsPoint offsetToWidget;
816
0
    parentWithView->GetNearestWidget(&offsetToWidget);
817
0
    origin += offsetToWidget;
818
0
  }
819
0
  origin += GetContentRectRelativeToSelf().TopLeft();
820
0
821
0
  nsIntPoint pt(PresContext()->AppUnitsToDevPixels(origin.x),
822
0
                PresContext()->AppUnitsToDevPixels(origin.y));
823
0
824
0
  // If we're in the content process offsetToWidget is tied to the top level
825
0
  // widget we can access in the child process, which is the tab. We need the
826
0
  // offset all the way up to the top level native window here. (If this is
827
0
  // non-e10s this routine will return 0,0.)
828
0
  if (aWindowless) {
829
0
    mozilla::LayoutDeviceIntPoint lpt = GetRemoteTabChromeOffset();
830
0
    pt += nsIntPoint(lpt.x, lpt.y);
831
0
  }
832
0
833
0
  return pt;
834
0
}
835
836
void
837
nsPluginFrame::DidReflow(nsPresContext*     aPresContext,
838
                         const ReflowInput* aReflowInput)
839
0
{
840
0
  // Do this check before calling the superclass, as that clears
841
0
  // NS_FRAME_FIRST_REFLOW
842
0
  if (GetStateBits() & NS_FRAME_FIRST_REFLOW) {
843
0
    nsCOMPtr<nsIObjectLoadingContent> objContent(do_QueryInterface(mContent));
844
0
    NS_ASSERTION(objContent, "Why not an object loading content?");
845
0
    objContent->HasNewFrame(this);
846
0
  }
847
0
848
0
  nsFrame::DidReflow(aPresContext, aReflowInput);
849
0
850
0
  if (HasView()) {
851
0
    nsView* view = GetView();
852
0
    nsViewManager* vm = view->GetViewManager();
853
0
    if (vm)
854
0
      vm->SetViewVisibility(view, IsHidden() ? nsViewVisibility_kHide : nsViewVisibility_kShow);
855
0
  }
856
0
}
857
858
/* static */ void
859
nsPluginFrame::PaintPrintPlugin(nsIFrame* aFrame, gfxContext* aCtx,
860
                                const nsRect& aDirtyRect, nsPoint aPt)
861
0
{
862
0
  // Translate the context:
863
0
  nsPoint pt = aPt + aFrame->GetContentRectRelativeToSelf().TopLeft();
864
0
  gfxPoint devPixelPt =
865
0
    nsLayoutUtils::PointToGfxPoint(pt, aFrame->PresContext()->AppUnitsPerDevPixel());
866
0
867
0
  gfxContextMatrixAutoSaveRestore autoSR(aCtx);
868
0
  aCtx->SetMatrixDouble(aCtx->CurrentMatrixDouble().PreTranslate(devPixelPt));
869
0
870
0
  // FIXME - Bug 385435: Doesn't aDirtyRect need translating too?
871
0
872
0
  static_cast<nsPluginFrame*>(aFrame)->PrintPlugin(*aCtx, aDirtyRect);
873
0
}
874
875
/**
876
 * nsDisplayPluginReadback creates an active ReadbackLayer. The ReadbackLayer
877
 * obtains from the compositor the contents of the window underneath
878
 * the ReadbackLayer, which we then use as an opaque buffer for plugins to
879
 * asynchronously draw onto.
880
 */
881
class nsDisplayPluginReadback : public nsDisplayItem {
882
public:
883
  nsDisplayPluginReadback(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
884
    : nsDisplayItem(aBuilder, aFrame)
885
0
  {
886
0
    MOZ_COUNT_CTOR(nsDisplayPluginReadback);
887
0
  }
888
#ifdef NS_BUILD_REFCNT_LOGGING
889
  ~nsDisplayPluginReadback() override {
890
    MOZ_COUNT_DTOR(nsDisplayPluginReadback);
891
  }
892
#endif
893
894
  nsRect GetBounds(nsDisplayListBuilder* aBuilder,
895
                   bool* aSnap) const override;
896
897
  NS_DISPLAY_DECL_NAME("PluginReadback", TYPE_PLUGIN_READBACK)
898
899
  already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
900
                                             LayerManager* aManager,
901
                                             const ContainerLayerParameters& aContainerParameters) override
902
0
  {
903
0
    return static_cast<nsPluginFrame*>(mFrame)->BuildLayer(aBuilder, aManager, this, aContainerParameters);
904
0
  }
905
906
  LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
907
                                   LayerManager* aManager,
908
                                   const ContainerLayerParameters& aParameters) override
909
0
  {
910
0
    return LAYER_ACTIVE;
911
0
  }
912
913
  virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
914
0
  {
915
0
    return new nsDisplayPluginGeometry(this, aBuilder);
916
0
  }
917
};
918
919
static nsRect
920
GetDisplayItemBounds(nsDisplayListBuilder* aBuilder,
921
                     const nsDisplayItem* aItem,
922
                     nsIFrame* aFrame)
923
0
{
924
0
  // XXX For slightly more accurate region computations we should pixel-snap this
925
0
  return aFrame->GetContentRectRelativeToSelf() + aItem->ToReferenceFrame();
926
0
}
927
928
nsRect
929
nsDisplayPluginReadback::GetBounds(nsDisplayListBuilder* aBuilder,
930
                                   bool* aSnap) const
931
0
{
932
0
  *aSnap = false;
933
0
  return GetDisplayItemBounds(aBuilder, this, mFrame);
934
0
}
935
936
nsRect
937
nsDisplayPlugin::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const
938
0
{
939
0
  *aSnap = true;
940
0
  return GetDisplayItemBounds(aBuilder, this, mFrame);
941
0
}
942
943
void
944
nsDisplayPlugin::Paint(nsDisplayListBuilder* aBuilder,
945
                       gfxContext* aCtx)
946
0
{
947
0
  nsPluginFrame* f = static_cast<nsPluginFrame*>(mFrame);
948
0
  bool snap;
949
0
  f->PaintPlugin(aBuilder, *aCtx, GetPaintRect(), GetBounds(aBuilder, &snap));
950
0
}
951
952
static nsRect
953
GetClippedBoundsIncludingAllScrollClips(nsDisplayItem* aItem,
954
                                        nsDisplayListBuilder* aBuilder)
955
0
{
956
0
  nsRect r = aItem->GetClippedBounds(aBuilder);
957
0
  for (auto* sc = aItem->GetClipChain(); sc; sc = sc->mParent) {
958
0
    r = sc->mClip.ApplyNonRoundedIntersection(r);
959
0
  }
960
0
  return r;
961
0
}
962
963
bool
964
nsDisplayPlugin::ComputeVisibility(nsDisplayListBuilder* aBuilder,
965
                                   nsRegion* aVisibleRegion)
966
0
{
967
0
  if (aBuilder->IsForPluginGeometry()) {
968
0
    nsPluginFrame* f = static_cast<nsPluginFrame*>(mFrame);
969
0
    if (!aBuilder->IsInTransform() || f->IsPaintedByGecko()) {
970
0
      // Since transforms induce reference frames, we don't need to worry
971
0
      // about this method fluffing out due to non-rectilinear transforms.
972
0
      nsRect rAncestor = nsLayoutUtils::TransformFrameRectToAncestor(f,
973
0
          f->GetContentRectRelativeToSelf(), ReferenceFrame());
974
0
      nscoord appUnitsPerDevPixel =
975
0
        ReferenceFrame()->PresContext()->AppUnitsPerDevPixel();
976
0
      f->mNextConfigurationBounds = LayoutDeviceIntRect::FromUnknownRect(
977
0
        rAncestor.ToNearestPixels(appUnitsPerDevPixel));
978
0
979
0
      nsRegion visibleRegion;
980
0
      // Apply all scroll clips when computing the clipped bounds of this item.
981
0
      // We hide windowed plugins during APZ scrolling, so there never is an
982
0
      // async transform that we need to take into account when clipping.
983
0
      visibleRegion.And(*aVisibleRegion, GetClippedBoundsIncludingAllScrollClips(this, aBuilder));
984
0
      // Make visibleRegion relative to f
985
0
      visibleRegion.MoveBy(-ToReferenceFrame());
986
0
987
0
      f->mNextConfigurationClipRegion.Clear();
988
0
      for (auto iter = visibleRegion.RectIter(); !iter.Done(); iter.Next()) {
989
0
        nsRect rAncestor =
990
0
          nsLayoutUtils::TransformFrameRectToAncestor(f, iter.Get(), ReferenceFrame());
991
0
        LayoutDeviceIntRect rPixels =
992
0
          LayoutDeviceIntRect::FromUnknownRect(rAncestor.ToNearestPixels(appUnitsPerDevPixel)) -
993
0
          f->mNextConfigurationBounds.TopLeft();
994
0
        if (!rPixels.IsEmpty()) {
995
0
          f->mNextConfigurationClipRegion.AppendElement(rPixels);
996
0
        }
997
0
      }
998
0
    }
999
0
1000
0
    if (f->mInnerView) {
1001
0
      // This should produce basically the same rectangle (but not relative
1002
0
      // to the root frame). We only call this here for the side-effect of
1003
0
      // setting mViewToWidgetOffset on the view.
1004
0
      f->mInnerView->CalcWidgetBounds(eWindowType_plugin);
1005
0
    }
1006
0
  }
1007
0
1008
0
  return nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion);
1009
0
}
1010
1011
nsRegion
1012
nsDisplayPlugin::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
1013
                                 bool* aSnap) const
1014
0
{
1015
0
  *aSnap = false;
1016
0
  nsRegion result;
1017
0
  nsPluginFrame* f = static_cast<nsPluginFrame*>(mFrame);
1018
0
  if (!aBuilder->IsForPluginGeometry()) {
1019
0
    nsIWidget* widget = f->GetWidget();
1020
0
    if (widget) {
1021
0
      // Be conservative and treat plugins with widgets as not opaque,
1022
0
      // because that's simple and we might need the content under the widget
1023
0
      // if the widget is unexpectedly clipped away. (As can happen when
1024
0
      // chrome content over a plugin forces us to clip out the plugin for
1025
0
      // security reasons.)
1026
0
      // We shouldn't be repainting the content under plugins much anyway
1027
0
      // since there generally shouldn't be anything to invalidate or paint
1028
0
      // in PaintedLayers there.
1029
0
      return result;
1030
0
    }
1031
0
  }
1032
0
1033
0
  if (f->IsOpaque()) {
1034
0
    nsRect bounds = GetBounds(aBuilder, aSnap);
1035
0
    if (aBuilder->IsForPluginGeometry() ||
1036
0
        (f->GetPaintedRect(this) + ToReferenceFrame()).Contains(bounds)) {
1037
0
      // We can treat this as opaque
1038
0
      result = bounds;
1039
0
    }
1040
0
  }
1041
0
1042
0
  return result;
1043
0
}
1044
1045
bool
1046
nsDisplayPlugin::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
1047
                                         mozilla::wr::IpcResourceUpdateQueue& aResources,
1048
                                         const StackingContextHelper& aSc,
1049
                                         mozilla::layers::WebRenderLayerManager* aManager,
1050
                                         nsDisplayListBuilder* aDisplayListBuilder)
1051
0
{
1052
0
  return static_cast<nsPluginFrame*>(mFrame)->CreateWebRenderCommands(this,
1053
0
                                                                      aBuilder,
1054
0
                                                                      aResources,
1055
0
                                                                      aSc,
1056
0
                                                                      aManager,
1057
0
                                                                      aDisplayListBuilder);
1058
0
}
1059
1060
nsresult
1061
0
nsPluginFrame::PluginEventNotifier::Run() {
1062
0
  nsCOMPtr<nsIObserverService> obsSvc =
1063
0
    mozilla::services::GetObserverService();
1064
0
  obsSvc->NotifyObservers(nullptr, "plugin-changed-event", mEventType.get());
1065
0
  return NS_OK;
1066
0
}
1067
1068
void
1069
nsPluginFrame::NotifyPluginReflowObservers()
1070
0
{
1071
0
  nsContentUtils::AddScriptRunner(new PluginEventNotifier(NS_LITERAL_STRING("reflow")));
1072
0
}
1073
1074
void
1075
nsPluginFrame::DidSetWidgetGeometry()
1076
0
{
1077
#if defined(XP_MACOSX)
1078
  if (mInstanceOwner && !IsHidden()) {
1079
    mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintEnable);
1080
  }
1081
#else
1082
0
  if (!mWidget && mInstanceOwner) {
1083
0
    // UpdateWindowVisibility will notify the plugin of position changes
1084
0
    // by updating the NPWindow and calling NPP_SetWindow/AsyncSetWindow.
1085
0
    // We treat windowless plugins inside popups as always visible, since
1086
0
    // plugins inside popups don't get valid mNextConfigurationBounds
1087
0
    // set up.
1088
0
    mInstanceOwner->UpdateWindowVisibility(
1089
0
      nsLayoutUtils::IsPopup(nsLayoutUtils::GetDisplayRootFrame(this)) ||
1090
0
      !mNextConfigurationBounds.IsEmpty());
1091
0
  }
1092
0
#endif
1093
0
}
1094
1095
bool
1096
nsPluginFrame::IsOpaque() const
1097
0
{
1098
#if defined(XP_MACOSX)
1099
  return false;
1100
#else
1101
1102
0
  if (mInstanceOwner && mInstanceOwner->UseAsyncRendering()) {
1103
0
    return false;
1104
0
  }
1105
0
  return !IsTransparentMode();
1106
0
#endif
1107
0
}
1108
1109
bool
1110
nsPluginFrame::IsTransparentMode() const
1111
0
{
1112
#if defined(XP_MACOSX)
1113
  return false;
1114
#else
1115
0
  if (!mInstanceOwner)
1116
0
    return false;
1117
0
1118
0
  NPWindow *window = nullptr;
1119
0
  mInstanceOwner->GetWindow(window);
1120
0
  if (!window) {
1121
0
    return false;
1122
0
  }
1123
0
1124
0
  if (window->type != NPWindowTypeDrawable)
1125
0
    return false;
1126
0
1127
0
  nsresult rv;
1128
0
  RefPtr<nsNPAPIPluginInstance> pi;
1129
0
  rv = mInstanceOwner->GetInstance(getter_AddRefs(pi));
1130
0
  if (NS_FAILED(rv) || !pi)
1131
0
    return false;
1132
0
1133
0
  bool transparent = false;
1134
0
  pi->IsTransparent(&transparent);
1135
0
  return transparent;
1136
0
#endif
1137
0
}
1138
1139
void
1140
nsPluginFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
1141
                                const nsDisplayListSet& aLists)
1142
0
{
1143
0
  // XXX why are we painting collapsed object frames?
1144
0
  if (!IsVisibleOrCollapsedForPainting(aBuilder))
1145
0
    return;
1146
0
1147
0
  DisplayBorderBackgroundOutline(aBuilder, aLists);
1148
0
1149
0
  nsPresContext::nsPresContextType type = PresContext()->Type();
1150
0
1151
0
  // If we are painting in Print Preview do nothing....
1152
0
  if (type == nsPresContext::eContext_PrintPreview)
1153
0
    return;
1154
0
1155
0
  DO_GLOBAL_REFLOW_COUNT_DSP("nsPluginFrame");
1156
0
1157
0
#ifndef XP_MACOSX
1158
0
  if (mWidget && aBuilder->IsInTransform()) {
1159
0
    // Windowed plugins should not be rendered inside a transform.
1160
0
    return;
1161
0
  }
1162
0
#endif
1163
0
1164
0
  if (aBuilder->IsForPainting() && mInstanceOwner) {
1165
0
    // Update plugin frame for both content scaling and full zoom changes.
1166
0
    mInstanceOwner->ResolutionMayHaveChanged();
1167
#ifdef XP_MACOSX
1168
    mInstanceOwner->WindowFocusMayHaveChanged();
1169
#endif
1170
0
    if (mInstanceOwner->UseAsyncRendering()) {
1171
0
      NPWindow* window = nullptr;
1172
0
      mInstanceOwner->GetWindow(window);
1173
0
      bool isVisible = window && window->width > 0 && window->height > 0;
1174
0
      if (isVisible && aBuilder->ShouldSyncDecodeImages()) {
1175
0
#ifndef XP_MACOSX
1176
0
        mInstanceOwner->UpdateWindowVisibility(true);
1177
0
#endif
1178
0
      }
1179
0
1180
0
      mInstanceOwner->NotifyPaintWaiter(aBuilder);
1181
0
    }
1182
0
  }
1183
0
1184
0
  DisplayListClipState::AutoClipContainingBlockDescendantsToContentBox
1185
0
    clip(aBuilder, this);
1186
0
1187
0
  // determine if we are printing
1188
0
  if (type == nsPresContext::eContext_Print) {
1189
0
    aLists.Content()->AppendToTop(
1190
0
      MakeDisplayItem<nsDisplayGeneric>(aBuilder, this, PaintPrintPlugin, "PrintPlugin",
1191
0
                                        DisplayItemType::TYPE_PRINT_PLUGIN));
1192
0
  } else {
1193
0
    LayerState state = GetLayerState(aBuilder, nullptr);
1194
0
    if (state == LAYER_INACTIVE &&
1195
0
        nsDisplayItem::ForceActiveLayers()) {
1196
0
      state = LAYER_ACTIVE;
1197
0
    }
1198
0
    if (aBuilder->IsPaintingToWindow() &&
1199
0
        state == LAYER_ACTIVE &&
1200
0
        IsTransparentMode()) {
1201
0
      aLists.Content()->AppendToTop(
1202
0
        MakeDisplayItem<nsDisplayPluginReadback>(aBuilder, this));
1203
0
    }
1204
0
1205
0
    aLists.Content()->AppendToTop(
1206
0
      MakeDisplayItem<nsDisplayPlugin>(aBuilder, this));
1207
0
  }
1208
0
}
1209
1210
void
1211
nsPluginFrame::PrintPlugin(gfxContext& aRenderingContext,
1212
                           const nsRect& aDirtyRect)
1213
0
{
1214
0
  nsCOMPtr<nsIObjectLoadingContent> obj(do_QueryInterface(mContent));
1215
0
  if (!obj)
1216
0
    return;
1217
0
1218
0
  nsIFrame* frame = nullptr;
1219
0
  obj->GetPrintFrame(&frame);
1220
0
  if (!frame)
1221
0
    return;
1222
0
1223
0
  nsPresContext* presContext = PresContext();
1224
0
  // make sure this is REALLY an nsIObjectFrame
1225
0
  // we may need to go through the children to get it
1226
0
  nsIObjectFrame* objectFrame = do_QueryFrame(frame);
1227
0
  if (!objectFrame)
1228
0
    objectFrame = GetNextObjectFrame(presContext,frame);
1229
0
  if (!objectFrame)
1230
0
    return;
1231
0
1232
0
  // finally we can get our plugin instance
1233
0
  RefPtr<nsNPAPIPluginInstance> pi;
1234
0
  if (NS_FAILED(objectFrame->GetPluginInstance(getter_AddRefs(pi))) || !pi)
1235
0
    return;
1236
0
1237
0
  // now we need to setup the correct location for printing
1238
0
  NPWindow window;
1239
0
  window.window = nullptr;
1240
0
1241
0
  // prepare embedded mode printing struct
1242
0
  NPPrint npprint;
1243
0
  npprint.mode = NP_EMBED;
1244
0
1245
0
  // we need to find out if we are windowless or not
1246
0
  bool windowless = false;
1247
0
  pi->IsWindowless(&windowless);
1248
0
  window.type = windowless ? NPWindowTypeDrawable : NPWindowTypeWindow;
1249
0
1250
0
  window.clipRect.bottom = 0; window.clipRect.top = 0;
1251
0
  window.clipRect.left = 0; window.clipRect.right = 0;
1252
0
1253
0
// platform specific printing code
1254
0
#if defined(XP_UNIX) || defined(XP_MACOSX)
1255
0
  // Doesn't work in a thebes world, or on OS X.
1256
0
  (void)window;
1257
0
  (void)npprint;
1258
#elif defined(XP_WIN)
1259
1260
  /* On Windows, we use the win32 printing surface to print.  This, in
1261
   * turn, uses the Cairo paginated surface, which in turn uses the
1262
   * meta surface to record all operations and then play them back.
1263
   * This doesn't work too well for plugins, because if plugins render
1264
   * directly into the DC, the meta surface won't have any knowledge
1265
   * of them, and so at the end when it actually does the replay step,
1266
   * it'll fill the background with white and draw over whatever was
1267
   * rendered before.
1268
   *
1269
   * So, to avoid this, we use PushGroup, which creates a new windows
1270
   * surface, the plugin renders to that, and then we use normal
1271
   * cairo methods to composite that in such that it's recorded using the
1272
   * meta surface.
1273
   */
1274
1275
  /* we'll already be translated into the right spot by gfxWindowsNativeDrawing */
1276
  nsSize contentSize = GetContentRectRelativeToSelf().Size();
1277
  window.x = 0;
1278
  window.y = 0;
1279
  window.width = presContext->AppUnitsToDevPixels(contentSize.width);
1280
  window.height = presContext->AppUnitsToDevPixels(contentSize.height);
1281
1282
  aRenderingContext.Save();
1283
1284
  /* Make sure plugins don't do any damage outside of where they're supposed to */
1285
  aRenderingContext.NewPath();
1286
  gfxRect r(window.x, window.y, window.width, window.height);
1287
  aRenderingContext.Rectangle(r);
1288
  aRenderingContext.Clip();
1289
1290
  gfxWindowsNativeDrawing nativeDraw(&aRenderingContext, r);
1291
  do {
1292
    HDC dc = nativeDraw.BeginNativeDrawing();
1293
    if (!dc)
1294
      return;
1295
1296
    // XXX don't we need to call nativeDraw.TransformToNativeRect here?
1297
    npprint.print.embedPrint.platformPrint = dc;
1298
    npprint.print.embedPrint.window = window;
1299
    // send off print info to plugin
1300
    pi->Print(&npprint);
1301
1302
    nativeDraw.EndNativeDrawing();
1303
  } while (nativeDraw.ShouldRenderAgain());
1304
  nativeDraw.PaintToContext();
1305
1306
  aRenderingContext.Restore();
1307
#endif
1308
1309
0
  // XXX Nav 4.x always sent a SetWindow call after print. Should we do the same?
1310
0
  // XXX Calling DidReflow here makes no sense!!!
1311
0
  frame->DidReflow(presContext, nullptr);  // DidReflow will take care of it
1312
0
}
1313
1314
nsRect
1315
nsPluginFrame::GetPaintedRect(const nsDisplayPlugin* aItem) const
1316
0
{
1317
0
  if (!mInstanceOwner)
1318
0
    return nsRect();
1319
0
  nsRect r = GetContentRectRelativeToSelf();
1320
0
  if (!mInstanceOwner->UseAsyncRendering())
1321
0
    return r;
1322
0
1323
0
  nsIntSize size = mInstanceOwner->GetCurrentImageSize();
1324
0
  nsPresContext* pc = PresContext();
1325
0
  r.IntersectRect(r, nsRect(0, 0, pc->DevPixelsToAppUnits(size.width),
1326
0
                                  pc->DevPixelsToAppUnits(size.height)));
1327
0
  return r;
1328
0
}
1329
1330
LayerState
1331
nsPluginFrame::GetLayerState(nsDisplayListBuilder* aBuilder,
1332
                             LayerManager* aManager)
1333
0
{
1334
0
  if (!mInstanceOwner)
1335
0
    return LAYER_NONE;
1336
0
1337
0
  if (mInstanceOwner->NeedsScrollImageLayer()) {
1338
0
    return LAYER_ACTIVE;
1339
0
  }
1340
0
1341
0
  if (!mInstanceOwner->UseAsyncRendering()) {
1342
0
    return LAYER_NONE;
1343
0
  }
1344
0
1345
0
  return LAYER_ACTIVE_FORCE;
1346
0
}
1347
1348
class PluginFrameDidCompositeObserver final : public DidCompositeObserver
1349
{
1350
public:
1351
  PluginFrameDidCompositeObserver(nsPluginInstanceOwner* aOwner, LayerManager* aLayerManager)
1352
    : mInstanceOwner(aOwner),
1353
      mLayerManager(aLayerManager)
1354
0
  {
1355
0
  }
1356
0
  ~PluginFrameDidCompositeObserver() {
1357
0
    mLayerManager->RemoveDidCompositeObserver(this);
1358
0
  }
1359
0
  void DidComposite() override {
1360
0
    mInstanceOwner->DidComposite();
1361
0
  }
1362
0
  bool IsValid(LayerManager* aLayerManager) {
1363
0
    return aLayerManager == mLayerManager;
1364
0
  }
1365
1366
private:
1367
  nsPluginInstanceOwner* mInstanceOwner;
1368
  RefPtr<LayerManager> mLayerManager;
1369
};
1370
1371
bool
1372
nsPluginFrame::GetBounds(nsDisplayItem* aItem, IntSize& aSize, gfxRect& aRect)
1373
0
{
1374
0
  if (!mInstanceOwner)
1375
0
    return false;
1376
0
1377
0
  NPWindow* window = nullptr;
1378
0
  mInstanceOwner->GetWindow(window);
1379
0
  if (!window)
1380
0
    return false;
1381
0
1382
0
  if (window->width <= 0 || window->height <= 0)
1383
0
    return false;
1384
0
1385
#if defined(XP_MACOSX)
1386
  // window is in "display pixels", but size needs to be in device pixels
1387
  // window must be in "display pixels"
1388
  double scaleFactor = 1.0;
1389
  if (NS_FAILED(mInstanceOwner->GetContentsScaleFactor(&scaleFactor))) {
1390
    scaleFactor = 1.0;
1391
  }
1392
1393
  size_t intScaleFactor = ceil(scaleFactor);
1394
#else
1395
0
  size_t intScaleFactor = 1;
1396
0
#endif
1397
0
1398
0
  aSize = IntSize(window->width * intScaleFactor, window->height * intScaleFactor);
1399
0
1400
0
  nsRect area = GetContentRectRelativeToSelf() + aItem->ToReferenceFrame();
1401
0
  aRect = nsLayoutUtils::RectToGfxRect(area, PresContext()->AppUnitsPerDevPixel());
1402
0
  // to provide crisper and faster drawing.
1403
0
  aRect.Round();
1404
0
1405
0
  return true;
1406
0
}
1407
1408
bool
1409
nsPluginFrame::CreateWebRenderCommands(nsDisplayItem* aItem,
1410
                                       mozilla::wr::DisplayListBuilder& aBuilder,
1411
                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
1412
                                       const StackingContextHelper& aSc,
1413
                                       mozilla::layers::WebRenderLayerManager* aManager,
1414
                                       nsDisplayListBuilder* aDisplayListBuilder)
1415
0
{
1416
0
  IntSize size;
1417
0
  gfxRect r;
1418
0
  if (!GetBounds(aItem, size, r)) {
1419
0
    return true;
1420
0
  }
1421
0
1422
0
  RefPtr<ImageContainer> container;
1423
0
  // Image for Windowed plugins that support window capturing for scroll
1424
0
  // operations or async windowless rendering.
1425
0
  container = mInstanceOwner->GetImageContainer();
1426
0
  if (!container) {
1427
0
    // This can occur if our instance is gone or if the current plugin
1428
0
    // configuration does not require a backing image layer.
1429
0
    return true;
1430
0
  }
1431
0
1432
#ifdef XP_MACOSX
1433
  if (!mInstanceOwner->UseAsyncRendering()) {
1434
    mInstanceOwner->DoCocoaEventDrawRect(r, nullptr);
1435
  }
1436
#endif
1437
1438
0
  RefPtr<LayerManager> lm = aDisplayListBuilder->GetWidgetLayerManager();
1439
0
  if (!mDidCompositeObserver || !mDidCompositeObserver->IsValid(lm)) {
1440
0
    mDidCompositeObserver = MakeUnique<PluginFrameDidCompositeObserver>(mInstanceOwner, lm);
1441
0
  }
1442
0
  lm->AddDidCompositeObserver(mDidCompositeObserver.get());
1443
0
1444
0
  // If the image container is empty, we don't want to fallback. Any other
1445
0
  // failure will be due to resource constraints and fallback is unlikely to
1446
0
  // help us. Hence we can ignore the return value from PushImage.
1447
0
  LayoutDeviceRect dest(r.x, r.y, size.width, size.height);
1448
0
  aManager->CommandBuilder().PushImage(aItem, container, aBuilder, aResources, aSc, dest);
1449
0
  return true;
1450
0
}
1451
1452
1453
already_AddRefed<Layer>
1454
nsPluginFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
1455
                          LayerManager* aManager,
1456
                          nsDisplayItem* aItem,
1457
                          const ContainerLayerParameters& aContainerParameters)
1458
0
{
1459
0
  IntSize size;
1460
0
  gfxRect r;
1461
0
  if (!GetBounds(aItem, size, r)) {
1462
0
    return nullptr;
1463
0
  }
1464
0
1465
0
  RefPtr<Layer> layer =
1466
0
    (aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, aItem));
1467
0
1468
0
  if (aItem->GetType() == DisplayItemType::TYPE_PLUGIN) {
1469
0
    RefPtr<ImageContainer> container;
1470
0
    // Image for Windowed plugins that support window capturing for scroll
1471
0
    // operations or async windowless rendering.
1472
0
    container = mInstanceOwner->GetImageContainer();
1473
0
    if (!container) {
1474
0
      // This can occur if our instance is gone or if the current plugin
1475
0
      // configuration does not require a backing image layer.
1476
0
      return nullptr;
1477
0
    }
1478
0
1479
0
    if (!layer) {
1480
0
      mInstanceOwner->NotifyPaintWaiter(aBuilder);
1481
0
      // Initialize ImageLayer
1482
0
      layer = aManager->CreateImageLayer();
1483
0
      if (!layer)
1484
0
        return nullptr;
1485
0
    }
1486
0
1487
0
    NS_ASSERTION(layer->GetType() == Layer::TYPE_IMAGE, "Bad layer type");
1488
0
    ImageLayer* imglayer = static_cast<ImageLayer*>(layer.get());
1489
#ifdef XP_MACOSX
1490
    if (!mInstanceOwner->UseAsyncRendering()) {
1491
      mInstanceOwner->DoCocoaEventDrawRect(r, nullptr);
1492
    }
1493
#endif
1494
1495
0
    imglayer->SetScaleToSize(size, ScaleMode::STRETCH);
1496
0
    imglayer->SetContainer(container);
1497
0
    SamplingFilter samplingFilter = nsLayoutUtils::GetSamplingFilterForFrame(this);
1498
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
1499
    if (!aManager->IsCompositingCheap()) {
1500
      // Pixman just horrible with bilinear filter scaling
1501
      samplingFilter = SamplingFilter::POINT;
1502
    }
1503
#endif
1504
    imglayer->SetSamplingFilter(samplingFilter);
1505
0
1506
0
    layer->SetContentFlags(IsOpaque() ? Layer::CONTENT_OPAQUE : 0);
1507
0
1508
0
    if (aBuilder->IsPaintingToWindow() &&
1509
0
        aBuilder->GetWidgetLayerManager() &&
1510
0
        (aBuilder->GetWidgetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT ||
1511
0
         aBuilder->GetWidgetLayerManager()->GetBackendType() == LayersBackend::LAYERS_WR) &&
1512
0
        mInstanceOwner->UseAsyncRendering())
1513
0
    {
1514
0
      RefPtr<LayerManager> lm = aBuilder->GetWidgetLayerManager();
1515
0
      if (!mDidCompositeObserver || !mDidCompositeObserver->IsValid(lm)) {
1516
0
        mDidCompositeObserver = MakeUnique<PluginFrameDidCompositeObserver>(mInstanceOwner, lm);
1517
0
      }
1518
0
      lm->AddDidCompositeObserver(mDidCompositeObserver.get());
1519
0
    }
1520
0
  } else {
1521
0
    NS_ASSERTION(aItem->GetType() == DisplayItemType::TYPE_PLUGIN_READBACK,
1522
0
                 "Unknown item type");
1523
0
    MOZ_ASSERT(!IsOpaque(), "Opaque plugins don't use backgrounds");
1524
0
1525
0
    if (!layer) {
1526
0
      layer = aManager->CreateReadbackLayer();
1527
0
      if (!layer)
1528
0
        return nullptr;
1529
0
    }
1530
0
    NS_ASSERTION(layer->GetType() == Layer::TYPE_READBACK, "Bad layer type");
1531
0
1532
0
    ReadbackLayer* readback = static_cast<ReadbackLayer*>(layer.get());
1533
0
    if (readback->GetSize() != size) {
1534
0
      // This will destroy any old background sink and notify us that the
1535
0
      // background is now unknown
1536
0
      readback->SetSink(nullptr);
1537
0
      readback->SetSize(size);
1538
0
1539
0
      if (mBackgroundSink) {
1540
0
        // Maybe we still have a background sink associated with another
1541
0
        // readback layer that wasn't recycled for some reason? Unhook it
1542
0
        // now so that if this frame goes away, it doesn't have a dangling
1543
0
        // reference to us.
1544
0
        mBackgroundSink->Destroy();
1545
0
      }
1546
0
      mBackgroundSink =
1547
0
        new PluginBackgroundSink(this,
1548
0
                                 readback->AllocateSequenceNumber());
1549
0
      readback->SetSink(mBackgroundSink);
1550
0
      // The layer has taken ownership of our sink. When either the sink dies
1551
0
      // or the frame dies, the connection from the surviving object is nulled out.
1552
0
    }
1553
0
  }
1554
0
1555
0
  // Set a transform on the layer to draw the plugin in the right place
1556
0
  gfxPoint p = r.TopLeft() + aContainerParameters.mOffset;
1557
0
  Matrix transform = Matrix::Translation(p.x, p.y);
1558
0
1559
0
  layer->SetBaseTransform(Matrix4x4::From2D(transform));
1560
0
  return layer.forget();
1561
0
}
1562
1563
void
1564
nsPluginFrame::PaintPlugin(nsDisplayListBuilder* aBuilder,
1565
                           gfxContext& aRenderingContext,
1566
                           const nsRect& aDirtyRect, const nsRect& aPluginRect)
1567
0
{
1568
#if defined(DEBUG)
1569
  // On Desktop, we should have built a layer as we no longer support in-process
1570
  // plugins or synchronous painting. We can only get here for windowed plugins
1571
  // (which draw themselves), or via some error/unload state.
1572
  if (mInstanceOwner) {
1573
    NPWindow *window = nullptr;
1574
    mInstanceOwner->GetWindow(window);
1575
    MOZ_ASSERT(!window || window->type == NPWindowTypeWindow);
1576
  }
1577
#endif
1578
}
1579
1580
nsresult
1581
nsPluginFrame::HandleEvent(nsPresContext* aPresContext,
1582
                           WidgetGUIEvent* anEvent,
1583
                           nsEventStatus* anEventStatus)
1584
0
{
1585
0
  NS_ENSURE_ARG_POINTER(anEvent);
1586
0
  NS_ENSURE_ARG_POINTER(anEventStatus);
1587
0
  nsresult rv = NS_OK;
1588
0
1589
0
  if (!mInstanceOwner)
1590
0
    return NS_ERROR_NULL_POINTER;
1591
0
1592
0
  mInstanceOwner->ConsiderNewEventloopNestingLevel();
1593
0
1594
0
  if (anEvent->mMessage == ePluginActivate) {
1595
0
    nsIFocusManager* fm = nsFocusManager::GetFocusManager();
1596
0
    if (fm) {
1597
0
      RefPtr<Element> elem = GetContent()->AsElement();
1598
0
      return fm->SetFocus(elem, 0);
1599
0
    }
1600
0
  }
1601
0
  else if (anEvent->mMessage == ePluginFocus) {
1602
0
    nsIFocusManager* fm = nsFocusManager::GetFocusManager();
1603
0
    if (fm) {
1604
0
      RefPtr<Element> elem = GetContent()->AsElement();
1605
0
      return fm->FocusPlugin(elem);
1606
0
    }
1607
0
  }
1608
0
1609
0
  if (mInstanceOwner->SendNativeEvents() &&
1610
0
      anEvent->IsNativeEventDelivererForPlugin()) {
1611
0
    *anEventStatus = mInstanceOwner->ProcessEvent(*anEvent);
1612
0
    // Due to plugin code reentering Gecko, this frame may be dead at this
1613
0
    // point.
1614
0
    return rv;
1615
0
  }
1616
0
1617
#ifdef XP_WIN
1618
  rv = nsFrame::HandleEvent(aPresContext, anEvent, anEventStatus);
1619
  return rv;
1620
#endif
1621
1622
#ifdef XP_MACOSX
1623
  // we want to process some native mouse events in the cocoa event model
1624
  if ((anEvent->mMessage == eMouseEnterIntoWidget ||
1625
       anEvent->mMessage == eWheel) &&
1626
      mInstanceOwner->GetEventModel() == NPEventModelCocoa) {
1627
    *anEventStatus = mInstanceOwner->ProcessEvent(*anEvent);
1628
    // Due to plugin code reentering Gecko, this frame may be dead at this
1629
    // point.
1630
    return rv;
1631
  }
1632
1633
  // These two calls to nsIPresShell::SetCapturingContext() (on mouse-down
1634
  // and mouse-up) are needed to make the routing of mouse events while
1635
  // dragging conform to standard OS X practice, and to the Cocoa NPAPI spec.
1636
  // See bug 525078 and bug 909678.
1637
  if (anEvent->mMessage == eMouseDown) {
1638
    nsIPresShell::SetCapturingContent(GetContent(), CAPTURE_IGNOREALLOWED);
1639
  }
1640
#endif
1641
1642
0
  rv = nsFrame::HandleEvent(aPresContext, anEvent, anEventStatus);
1643
0
1644
0
  // We need to be careful from this point because the call to
1645
0
  // nsFrame::HandleEvent() might have killed us.
1646
0
1647
#ifdef XP_MACOSX
1648
  if (anEvent->mMessage == eMouseUp) {
1649
    nsIPresShell::SetCapturingContent(nullptr, 0);
1650
  }
1651
#endif
1652
1653
0
  return rv;
1654
0
}
1655
1656
void
1657
nsPluginFrame::HandleWheelEventAsDefaultAction(WidgetWheelEvent* aWheelEvent)
1658
0
{
1659
0
  MOZ_ASSERT(WantsToHandleWheelEventAsDefaultAction());
1660
0
  MOZ_ASSERT(!aWheelEvent->DefaultPrevented());
1661
0
1662
0
  if (NS_WARN_IF(!mInstanceOwner) ||
1663
0
      NS_WARN_IF(aWheelEvent->mMessage != eWheel)) {
1664
0
    return;
1665
0
  }
1666
0
1667
0
  // If the wheel event has native message, it should may be handled by
1668
0
  // HandleEvent() in the future.  In such case, we should do nothing here.
1669
0
  if (NS_WARN_IF(!!aWheelEvent->mPluginEvent)) {
1670
0
    return;
1671
0
  }
1672
0
1673
0
  mInstanceOwner->ProcessEvent(*aWheelEvent);
1674
0
  // We need to assume that the event is always consumed/handled by the
1675
0
  // plugin.  There is no way to know if it's actually consumed/handled.
1676
0
  aWheelEvent->mViewPortIsOverscrolled = false;
1677
0
  aWheelEvent->mOverflowDeltaX = 0;
1678
0
  aWheelEvent->mOverflowDeltaY = 0;
1679
0
  // Consume the event explicitly.
1680
0
  aWheelEvent->PreventDefault();
1681
0
}
1682
1683
bool
1684
nsPluginFrame::WantsToHandleWheelEventAsDefaultAction() const
1685
0
{
1686
#ifdef XP_WIN
1687
  if (!mInstanceOwner) {
1688
    return false;
1689
  }
1690
  NPWindow* window = nullptr;
1691
  mInstanceOwner->GetWindow(window);
1692
  // On Windows, only when the plugin is windowless, we need to send wheel
1693
  // events as default action.
1694
  return window->type == NPWindowTypeDrawable;
1695
#else
1696
  return false;
1697
0
#endif
1698
0
}
1699
1700
nsresult
1701
nsPluginFrame::GetPluginInstance(nsNPAPIPluginInstance** aPluginInstance)
1702
0
{
1703
0
  *aPluginInstance = nullptr;
1704
0
1705
0
  if (!mInstanceOwner) {
1706
0
    return NS_OK;
1707
0
  }
1708
0
1709
0
  return mInstanceOwner->GetInstance(aPluginInstance);
1710
0
}
1711
1712
nsresult
1713
nsPluginFrame::GetCursor(const nsPoint& aPoint, nsIFrame::Cursor& aCursor)
1714
0
{
1715
0
  if (!mInstanceOwner) {
1716
0
    return NS_ERROR_FAILURE;
1717
0
  }
1718
0
1719
0
  RefPtr<nsNPAPIPluginInstance> inst;
1720
0
  mInstanceOwner->GetInstance(getter_AddRefs(inst));
1721
0
  if (!inst) {
1722
0
    return NS_ERROR_FAILURE;
1723
0
  }
1724
0
1725
0
  bool useDOMCursor = static_cast<nsNPAPIPluginInstance*>(inst.get())->UsesDOMForCursor();
1726
0
  if (!useDOMCursor) {
1727
0
    return NS_ERROR_FAILURE;
1728
0
  }
1729
0
1730
0
  return nsFrame::GetCursor(aPoint, aCursor);
1731
0
}
1732
1733
void
1734
nsPluginFrame::SetIsDocumentActive(bool aIsActive)
1735
0
{
1736
0
  if (mInstanceOwner) {
1737
0
    mInstanceOwner->UpdateDocumentActiveState(aIsActive);
1738
0
  }
1739
0
}
1740
1741
// static
1742
nsIObjectFrame *
1743
nsPluginFrame::GetNextObjectFrame(nsPresContext* aPresContext, nsIFrame* aRoot)
1744
0
{
1745
0
  for (nsIFrame* child : aRoot->PrincipalChildList()) {
1746
0
    nsIObjectFrame* outFrame = do_QueryFrame(child);
1747
0
    if (outFrame) {
1748
0
      RefPtr<nsNPAPIPluginInstance> pi;
1749
0
      outFrame->GetPluginInstance(getter_AddRefs(pi));  // make sure we have a REAL plugin
1750
0
      if (pi)
1751
0
        return outFrame;
1752
0
    }
1753
0
1754
0
    outFrame = GetNextObjectFrame(aPresContext, child);
1755
0
    if (outFrame)
1756
0
      return outFrame;
1757
0
  }
1758
0
1759
0
  return nullptr;
1760
0
}
1761
1762
/*static*/ void
1763
nsPluginFrame::BeginSwapDocShells(nsISupports* aSupports, void*)
1764
0
{
1765
0
  MOZ_ASSERT(aSupports, "null parameter");
1766
0
  nsCOMPtr<nsIContent> content(do_QueryInterface(aSupports));
1767
0
  if (!content) {
1768
0
    return;
1769
0
  }
1770
0
1771
0
  // This function is called from a document content enumerator so we need
1772
0
  // to filter out the nsPluginFrames and ignore the rest.
1773
0
  nsIObjectFrame* obj = do_QueryFrame(content->GetPrimaryFrame());
1774
0
  if (!obj)
1775
0
    return;
1776
0
1777
0
  nsPluginFrame* objectFrame = static_cast<nsPluginFrame*>(obj);
1778
0
  NS_ASSERTION(!objectFrame->mWidget || objectFrame->mWidget->GetParent(),
1779
0
               "Plugin windows must not be toplevel");
1780
0
  objectFrame->UnregisterPluginForGeometryUpdates();
1781
0
}
1782
1783
/*static*/ void
1784
nsPluginFrame::EndSwapDocShells(nsISupports* aSupports, void*)
1785
0
{
1786
0
  MOZ_ASSERT(aSupports, "null parameter");
1787
0
  nsCOMPtr<nsIContent> content(do_QueryInterface(aSupports));
1788
0
  if (!content) {
1789
0
    return;
1790
0
  }
1791
0
1792
0
  // This function is called from a document content enumerator so we need
1793
0
  // to filter out the nsPluginFrames and ignore the rest.
1794
0
  nsIObjectFrame* obj = do_QueryFrame(content->GetPrimaryFrame());
1795
0
  if (!obj)
1796
0
    return;
1797
0
1798
0
  nsPluginFrame* objectFrame = static_cast<nsPluginFrame*>(obj);
1799
0
  nsRootPresContext* rootPC = objectFrame->PresContext()->GetRootPresContext();
1800
0
  NS_ASSERTION(rootPC, "unable to register the plugin frame");
1801
0
  nsIWidget* widget = objectFrame->mWidget;
1802
0
  if (widget) {
1803
0
    // Reparent the widget.
1804
0
    nsIWidget* parent =
1805
0
      rootPC->PresShell()->GetRootFrame()->GetNearestWidget();
1806
0
    widget->SetParent(parent);
1807
0
    AutoWeakFrame weakFrame(objectFrame);
1808
0
    objectFrame->CallSetWindow();
1809
0
    if (!weakFrame.IsAlive()) {
1810
0
      return;
1811
0
    }
1812
0
  }
1813
0
1814
0
  if (objectFrame->mInstanceOwner) {
1815
0
    objectFrame->RegisterPluginForGeometryUpdates();
1816
0
  }
1817
0
}
1818
1819
nsIFrame*
1820
NS_NewObjectFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle)
1821
0
{
1822
0
  return new (aPresShell) nsPluginFrame(aStyle);
1823
0
}
1824
1825
bool
1826
nsPluginFrame::IsPaintedByGecko() const
1827
0
{
1828
#ifdef XP_MACOSX
1829
  return true;
1830
#else
1831
  return !mWidget;
1832
0
#endif
1833
0
}
1834
1835
NS_IMPL_FRAMEARENA_HELPERS(nsPluginFrame)