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