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 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is Mozilla Communicator client code.
18 * The Initial Developer of the Original Code is
19 * Netscape Communications Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 1998
21 * the Initial Developer. All Rights Reserved.
24 * Pierre Phaneuf <pp@ludusdesign.com>
25 * Jacek Piskozub <piskozub@iopan.gda.pl>
26 * Leon Sha <leon.sha@sun.com>
27 * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
28 * Robert O'Callahan <roc+moz@cs.cmu.edu>
29 * Christian Biesinger <cbiesinger@web.de>
30 * Josh Aas <josh@mozilla.com>
32 * Alternatively, the contents of this file may be used under the terms of
33 * either of the GNU General Public License Version 2 or later (the "GPL"),
34 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
35 * in which case the provisions of the GPL or the LGPL are applicable instead
36 * of those above. If you wish to allow use of your version of this file only
37 * under the terms of either the GPL or the LGPL, and not to allow others to
38 * use your version of this file under the terms of the MPL, indicate your
39 * decision by deleting the provisions above and replace them with the notice
40 * and other provisions required by the GPL or the LGPL. If you do not delete
41 * the provisions above, a recipient may use your version of this file under
42 * the terms of any one of the MPL, the GPL or the LGPL.
44 * ***** END LICENSE BLOCK ***** */
46 /* rendering objects for replaced elements implemented by a plugin */
50 #include "nsPresContext.h"
51 #include "nsIPresShell.h"
52 #include "nsWidgetsCID.h"
54 #include "nsIViewManager.h"
55 #include "nsIDOMKeyListener.h"
56 #include "nsIPluginHost.h"
59 #include "nsReadableUtils.h"
61 #include "nsGkAtoms.h"
62 #include "nsIAppShell.h"
63 #include "nsIDocument.h"
64 #include "nsINodeInfo.h"
66 #include "nsNetUtil.h"
67 #include "nsIPluginInstanceOwner.h"
69 #include "nsILinkHandler.h"
71 #include "nsIJVMPluginTagInfo.h"
73 #include "nsIEventListener.h"
74 #include "nsIScrollableView.h"
75 #include "nsIScrollPositionListener.h"
77 #include "nsIDocShellTreeItem.h"
78 #include "nsIDocShellTreeOwner.h"
79 #include "nsDocShellCID.h"
80 #include "nsIWebBrowserChrome.h"
81 #include "nsIDOMElement.h"
82 #include "nsIDOMNodeList.h"
83 #include "nsIDOMHTMLObjectElement.h"
84 #include "nsIDOMHTMLEmbedElement.h"
85 #include "nsIDOMHTMLAppletElement.h"
86 #include "nsIDOMWindow.h"
87 #include "nsIDOMDocumentEvent.h"
88 #include "nsIDOMMouseListener.h"
89 #include "nsIDOMMouseMotionListener.h"
90 #include "nsIDOMFocusListener.h"
91 #include "nsIDOMContextMenuListener.h"
92 #include "nsIDOMDragListener.h"
93 #include "nsIDOMEventTarget.h"
94 #include "nsIDOMNSEvent.h"
95 #include "nsIPrivateDOMEvent.h"
96 #include "nsIDocumentEncoder.h"
97 #include "nsXPIDLString.h"
98 #include "nsIDOMRange.h"
99 #include "nsIPluginWidget.h"
100 #include "nsGUIEvent.h"
101 #include "nsIRenderingContext.h"
103 #include "nsTransform2D.h"
104 #include "nsIImageLoadingContent.h"
105 #include "nsIObjectLoadingContent.h"
106 #include "nsPIDOMWindow.h"
107 #include "nsContentUtils.h"
108 #include "nsDisplayList.h"
109 #include "nsAttrName.h"
110 #include "nsDataHashtable.h"
112 // headers for plugin scriptability
113 #include "nsIScriptGlobalObject.h"
114 #include "nsIScriptContext.h"
115 #include "nsIXPConnect.h"
116 #include "nsIXPCScriptable.h"
117 #include "nsIClassInfo.h"
119 #include "nsObjectFrame.h"
120 #include "nsIObjectFrame.h"
121 #include "nsPluginNativeWindow.h"
122 #include "nsPIPluginHost.h"
123 #include "nsIPluginDocument.h"
126 #include "gfxContext.h"
129 // accessibility support
131 #include "nsIAccessibilityService.h"
135 #define FORCE_PR_LOG 1 /* Allow logging in the release build */
136 #endif /* MOZ_LOGGING */
141 #include "nsContentCID.h"
142 static NS_DEFINE_CID(kRangeCID
, NS_RANGE_CID
);
154 #ifdef CreateEvent // Thank you MS.
159 static PRLogModuleInfo
*nsObjectFrameLM
= PR_NewLogModule("nsObjectFrame");
160 #endif /* PR_LOGGING */
163 #define NORMAL_PLUGIN_DELAY 17
165 // low enough to avoid audio skipping/delays
166 #define HIDDEN_PLUGIN_DELAY 100
168 // special class for handeling DOM context menu events because for
169 // some reason it starves other mouse events if implemented on the
171 class nsPluginDOMContextMenuListener
: public nsIDOMContextMenuListener
,
172 public nsIEventListener
175 nsPluginDOMContextMenuListener();
176 virtual ~nsPluginDOMContextMenuListener();
180 NS_IMETHOD
ContextMenu(nsIDOMEvent
* aContextMenuEvent
);
182 nsresult
Init(nsIContent
* aContent
);
183 nsresult
Destroy(nsIContent
* aContent
);
185 NS_IMETHOD
HandleEvent(nsIDOMEvent
* aEvent
)
189 nsEventStatus
ProcessEvent(const nsGUIEvent
& anEvent
)
191 return nsEventStatus_eConsumeNoDefault
;
196 class nsPluginInstanceOwner
: public nsIPluginInstanceOwner
,
197 public nsIPluginTagInfo2
,
199 public nsIJVMPluginTagInfo
,
201 public nsIEventListener
,
202 public nsITimerCallback
,
203 public nsIDOMMouseListener
,
204 public nsIDOMMouseMotionListener
,
205 public nsIDOMKeyListener
,
206 public nsIDOMFocusListener
,
207 public nsIScrollPositionListener
,
208 public nsIDOMDragListener
212 nsPluginInstanceOwner();
213 virtual ~nsPluginInstanceOwner();
217 //nsIPluginInstanceOwner interface
219 NS_IMETHOD
SetInstance(nsIPluginInstance
*aInstance
);
221 NS_IMETHOD
GetInstance(nsIPluginInstance
*&aInstance
);
223 NS_IMETHOD
GetWindow(nsPluginWindow
*&aWindow
);
225 NS_IMETHOD
GetMode(nsPluginMode
*aMode
);
227 NS_IMETHOD
CreateWidget(void);
229 NS_IMETHOD
GetURL(const char *aURL
, const char *aTarget
, void *aPostData
,
230 PRUint32 aPostDataLen
, void *aHeadersData
,
231 PRUint32 aHeadersDataLen
, PRBool isFile
= PR_FALSE
);
233 NS_IMETHOD
ShowStatus(const char *aStatusMsg
);
235 NS_IMETHOD
ShowStatus(const PRUnichar
*aStatusMsg
);
237 NS_IMETHOD
GetDocument(nsIDocument
* *aDocument
);
239 NS_IMETHOD
InvalidateRect(nsPluginRect
*invalidRect
);
241 NS_IMETHOD
InvalidateRegion(nsPluginRegion invalidRegion
);
243 NS_IMETHOD
ForceRedraw();
245 NS_IMETHOD
GetValue(nsPluginInstancePeerVariable variable
, void *value
);
247 //nsIPluginTagInfo interface
249 NS_IMETHOD
GetAttributes(PRUint16
& n
, const char*const*& names
,
250 const char*const*& values
);
252 NS_IMETHOD
GetAttribute(const char* name
, const char* *result
);
254 //nsIPluginTagInfo2 interface
256 NS_IMETHOD
GetTagType(nsPluginTagType
*result
);
258 NS_IMETHOD
GetTagText(const char* *result
);
260 NS_IMETHOD
GetParameters(PRUint16
& n
, const char*const*& names
, const char*const*& values
);
262 NS_IMETHOD
GetParameter(const char* name
, const char* *result
);
264 NS_IMETHOD
GetDocumentBase(const char* *result
);
266 NS_IMETHOD
GetDocumentEncoding(const char* *result
);
268 NS_IMETHOD
GetAlignment(const char* *result
);
270 NS_IMETHOD
GetWidth(PRUint32
*result
);
272 NS_IMETHOD
GetHeight(PRUint32
*result
);
274 NS_IMETHOD
GetBorderVertSpace(PRUint32
*result
);
276 NS_IMETHOD
GetBorderHorizSpace(PRUint32
*result
);
278 NS_IMETHOD
GetUniqueID(PRUint32
*result
);
280 NS_IMETHOD
GetDOMElement(nsIDOMElement
* *result
);
283 //nsIJVMPluginTagInfo interface
285 NS_IMETHOD
GetCode(const char* *result
);
287 NS_IMETHOD
GetCodeBase(const char* *result
);
289 NS_IMETHOD
GetArchive(const char* *result
);
291 NS_IMETHOD
GetName(const char* *result
);
293 NS_IMETHOD
GetMayScript(PRBool
*result
);
297 /** nsIDOMMouseListener interfaces
298 * @see nsIDOMMouseListener
300 NS_IMETHOD
MouseDown(nsIDOMEvent
* aMouseEvent
);
301 NS_IMETHOD
MouseUp(nsIDOMEvent
* aMouseEvent
);
302 NS_IMETHOD
MouseClick(nsIDOMEvent
* aMouseEvent
);
303 NS_IMETHOD
MouseDblClick(nsIDOMEvent
* aMouseEvent
);
304 NS_IMETHOD
MouseOver(nsIDOMEvent
* aMouseEvent
);
305 NS_IMETHOD
MouseOut(nsIDOMEvent
* aMouseEvent
);
306 NS_IMETHOD
HandleEvent(nsIDOMEvent
* aEvent
);
307 /* END interfaces from nsIDOMMouseListener*/
309 // nsIDOMMouseListener intefaces
310 NS_IMETHOD
MouseMove(nsIDOMEvent
* aMouseEvent
);
311 NS_IMETHOD
DragMove(nsIDOMEvent
* aMouseEvent
) { return NS_OK
; }
313 // nsIDOMKeyListener interfaces
314 NS_IMETHOD
KeyDown(nsIDOMEvent
* aKeyEvent
);
315 NS_IMETHOD
KeyUp(nsIDOMEvent
* aKeyEvent
);
316 NS_IMETHOD
KeyPress(nsIDOMEvent
* aKeyEvent
);
317 // end nsIDOMKeyListener interfaces
319 // nsIDOMFocuListener interfaces
320 NS_IMETHOD
Focus(nsIDOMEvent
* aFocusEvent
);
321 NS_IMETHOD
Blur(nsIDOMEvent
* aFocusEvent
);
323 // nsIDOMDragListener interfaces
324 NS_IMETHOD
DragEnter(nsIDOMEvent
* aMouseEvent
);
325 NS_IMETHOD
DragOver(nsIDOMEvent
* aMouseEvent
);
326 NS_IMETHOD
DragExit(nsIDOMEvent
* aMouseEvent
);
327 NS_IMETHOD
DragDrop(nsIDOMEvent
* aMouseEvent
);
328 NS_IMETHOD
DragGesture(nsIDOMEvent
* aMouseEvent
);
329 NS_IMETHOD
Drag(nsIDOMEvent
* aMouseEvent
);
330 NS_IMETHOD
DragEnd(nsIDOMEvent
* aMouseEvent
);
335 //nsIEventListener interface
336 nsEventStatus
ProcessEvent(const nsGUIEvent
& anEvent
);
338 void Paint(const nsRect
& aDirtyRect
, PRUint32 ndc
= 0);
340 // nsITimerCallback interface
341 NS_DECL_NSITIMERCALLBACK
344 void StartTimer(unsigned int aDelay
);
346 // nsIScrollPositionListener interface
347 NS_IMETHOD
ScrollPositionWillChange(nsIScrollableView
* aScrollable
, nscoord aX
, nscoord aY
);
348 NS_IMETHOD
ScrollPositionDidChange(nsIScrollableView
* aScrollable
, nscoord aX
, nscoord aY
);
352 nsresult
Init(nsPresContext
* aPresContext
, nsObjectFrame
* aFrame
,
353 nsIContent
* aContent
);
355 nsPluginPort
* GetPluginPort();
356 void ReleasePluginPort(nsPluginPort
* pluginPort
);
358 void SetPluginHost(nsIPluginHost
* aHost
);
361 NPDrawingModel
GetDrawingModel();
362 WindowRef
FixUpPluginWindow(PRInt32 inPaintState
);
363 void GUItoMacEvent(const nsGUIEvent
& anEvent
, EventRecord
* origEvent
, EventRecord
& aMacEvent
);
367 void FixUpURLS(const nsString
&name
, nsAString
&value
);
369 nsPluginNativeWindow
*mPluginWindow
;
370 nsCOMPtr
<nsIPluginInstance
> mInstance
;
371 nsObjectFrame
*mOwner
;
372 nsCOMPtr
<nsIContent
> mContent
;
373 nsCString mDocumentBase
;
375 nsCOMPtr
<nsIWidget
> mWidget
;
376 nsCOMPtr
<nsITimer
> mPluginTimer
;
377 nsCOMPtr
<nsIPluginHost
> mPluginHost
;
378 PRPackedBool mContentFocused
;
379 PRPackedBool mWidgetVisible
; // used on Mac to store our widget's visible state
380 PRUint16 mNumCachedAttrs
;
381 PRUint16 mNumCachedParams
;
382 char **mCachedAttrParamNames
;
383 char **mCachedAttrParamValues
;
385 nsPluginDOMContextMenuListener
* mCXMenuListener
; // pointer to wrapper for nsIDOMContextMenuListener
387 nsresult
DispatchKeyToPlugin(nsIDOMEvent
* aKeyEvent
);
388 nsresult
DispatchMouseToPlugin(nsIDOMEvent
* aMouseEvent
);
389 nsresult
DispatchFocusToPlugin(nsIDOMEvent
* aFocusEvent
);
391 nsresult
EnsureCachedAttrParamArrays();
394 #if defined(XP_WIN) || (defined(DO_DIRTY_INTERSECT) && defined(XP_MACOSX))
395 static void ConvertAppUnitsToPixels(nsPresContext
& aPresContext
, nsRect
& aTwipsRect
, nsRect
& aPixelRect
);
398 // Mac specific code to fix up port position and clip during paint
401 #ifdef DO_DIRTY_INTERSECT
402 // convert relative coordinates to absolute
403 static void ConvertRelativeToWindowAbsolute(nsIFrame
* aFrame
, nsPoint
& aRel
, nsPoint
& aAbs
, nsIWidget
*&aContainerWidget
);
406 enum { ePluginPaintIgnore
, ePluginPaintEnable
, ePluginPaintDisable
};
410 nsObjectFrame::~nsObjectFrame()
415 nsObjectFrame::QueryInterface(const nsIID
& aIID
, void** aInstancePtr
)
417 NS_ENSURE_ARG_POINTER(aInstancePtr
);
418 *aInstancePtr
= nsnull
;
421 if (aIID
.Equals(NS_GET_IID(nsIFrameDebug
))) {
422 *aInstancePtr
= NS_STATIC_CAST(nsIFrameDebug
*,this);
427 if (aIID
.Equals(NS_GET_IID(nsIObjectFrame
))) {
428 *aInstancePtr
= NS_STATIC_CAST(nsIObjectFrame
*,this);
430 } else if (aIID
.Equals(NS_GET_IID(nsIFrame
))) {
431 *aInstancePtr
= NS_STATIC_CAST(nsIFrame
*,this);
433 } else if (aIID
.Equals(NS_GET_IID(nsISupports
))) {
434 *aInstancePtr
= NS_STATIC_CAST(nsIObjectFrame
*,this);
437 return NS_NOINTERFACE
;
440 NS_IMETHODIMP_(nsrefcnt
) nsObjectFrame::AddRef(void)
442 NS_WARNING("not supported for frames");
446 NS_IMETHODIMP_(nsrefcnt
) nsObjectFrame::Release(void)
448 NS_WARNING("not supported for frames");
453 NS_IMETHODIMP
nsObjectFrame::GetAccessible(nsIAccessible
** aAccessible
)
455 nsCOMPtr
<nsIAccessibilityService
> accService
= do_GetService("@mozilla.org/accessibilityService;1");
458 return accService
->CreateHTMLObjectFrameAccessible(this, aAccessible
);
461 return NS_ERROR_FAILURE
;
465 NS_IMETHODIMP
nsObjectFrame::GetPluginPort(HWND
*aPort
)
467 *aPort
= (HWND
) mInstanceOwner
->GetPluginPort();
474 static NS_DEFINE_CID(kWidgetCID
, NS_CHILD_CID
);
475 static NS_DEFINE_CID(kCPluginManagerCID
, NS_PLUGINMANAGER_CID
);
477 // #define DO_DIRTY_INTERSECT 1 // enable dirty rect intersection during paint
480 nsObjectFrame::Init(nsIContent
* aContent
,
482 nsIFrame
* aPrevInFlow
)
485 mInstantiating
= PR_FALSE
;
488 nsresult rv
= nsObjectFrameSuper::Init(aContent
, aParent
, aPrevInFlow
);
489 nsCOMPtr
<nsIObjectLoadingContent
> objContent(do_QueryInterface(mContent
));
490 NS_ASSERTION(objContent
, "Why not an object loading content?");
491 objContent
->HasNewFrame(this);
496 nsObjectFrame::Destroy()
498 NS_ASSERTION(!mInstantiating
, "about to crash due to bug 136927");
500 // we need to finish with the plugin before native window is destroyed
501 // doing this in the destructor is too late.
504 nsObjectFrameSuper::Destroy();
508 nsObjectFrame::GetType() const
510 return nsGkAtoms::objectFrame
;
515 nsObjectFrame::GetFrameName(nsAString
& aResult
) const
517 return MakeFrameName(NS_LITERAL_STRING("ObjectFrame"), aResult
);
522 nsObjectFrame::CreateWidgetForView(nsIView
* aView
)
524 // Bug 179822: Create widget and allow non-unicode SubClass
525 nsWidgetInitData initData
;
526 initData
.mUnicode
= PR_FALSE
;
527 return aView
->CreateWidget(kWidgetCID
, &initData
);
531 nsObjectFrame::CreateWidget(nscoord aWidth
,
535 nsIView
* view
= GetView();
536 NS_ASSERTION(view
, "Object frames must have views");
538 return NS_OK
; //XXX why OK? MMP
541 nsIViewManager
* viewMan
= view
->GetViewManager();
542 // mark the view as hidden since we don't know the (x,y) until Paint
543 // XXX is the above comment correct?
544 viewMan
->SetViewVisibility(view
, nsViewVisibility_kHide
);
546 //this is ugly. it was ripped off from didreflow(). MMP
547 // Position and size view relative to its parent, not relative to our
548 // parent frame (our parent frame may not have a view).
550 nsIView
* parentWithView
;
552 nsRect
r(0, 0, mRect
.width
, mRect
.height
);
554 GetOffsetFromView(origin
, &parentWithView
);
555 viewMan
->ResizeView(view
, r
);
556 viewMan
->MoveViewTo(view
, origin
.x
, origin
.y
);
558 if (!aViewOnly
&& !view
->HasWidget()) {
559 nsresult rv
= CreateWidgetForView(view
);
561 return NS_OK
; //XXX why OK? MMP
566 // Here we set the background color for this widget because some plugins will use
567 // the child window background color when painting. If it's not set, it may default to gray
568 // Sometimes, a frame doesn't have a background color or is transparent. In this
569 // case, walk up the frame tree until we do find a frame with a background color
570 for (nsIFrame
* frame
= this; frame
; frame
= frame
->GetParent()) {
571 const nsStyleBackground
* background
= frame
->GetStyleBackground();
572 if (!background
->IsTransparent()) { // make sure we got an actual color
573 nsIWidget
* win
= view
->GetWidget();
575 win
->SetBackgroundColor(background
->mBackgroundColor
);
582 viewMan
->SetViewVisibility(view
, nsViewVisibility_kShow
);
587 #define EMBED_DEF_WIDTH 240
588 #define EMBED_DEF_HEIGHT 200
590 /* virtual */ nscoord
591 nsObjectFrame::GetMinWidth(nsIRenderingContext
*aRenderingContext
)
595 if (!IsHidden(PR_FALSE
)) {
596 nsIAtom
*atom
= mContent
->Tag();
597 if (atom
== nsGkAtoms::applet
|| atom
== nsGkAtoms::embed
) {
598 result
= nsPresContext::CSSPixelsToAppUnits(EMBED_DEF_WIDTH
);
602 DISPLAY_MIN_WIDTH(this, result
);
606 /* virtual */ nscoord
607 nsObjectFrame::GetPrefWidth(nsIRenderingContext
*aRenderingContext
)
609 return nsObjectFrame::GetMinWidth(aRenderingContext
);
613 nsObjectFrame::GetDesiredSize(nsPresContext
* aPresContext
,
614 const nsHTMLReflowState
& aReflowState
,
615 nsHTMLReflowMetrics
& aMetrics
)
617 // By default, we have no area
621 if (IsHidden(PR_FALSE
)) {
625 aMetrics
.width
= aReflowState
.ComputedWidth();
626 aMetrics
.height
= aReflowState
.mComputedHeight
;
628 // for EMBED and APPLET, default to 240x200 for compatibility
629 nsIAtom
*atom
= mContent
->Tag();
630 if (atom
== nsGkAtoms::applet
|| atom
== nsGkAtoms::embed
) {
631 if (aMetrics
.width
== NS_UNCONSTRAINEDSIZE
) {
632 aMetrics
.width
= PR_MIN(PR_MAX(nsPresContext::CSSPixelsToAppUnits(EMBED_DEF_WIDTH
),
633 aReflowState
.mComputedMinWidth
),
634 aReflowState
.mComputedMaxWidth
);
636 if (aMetrics
.height
== NS_UNCONSTRAINEDSIZE
) {
637 aMetrics
.height
= PR_MIN(PR_MAX(nsPresContext::CSSPixelsToAppUnits(EMBED_DEF_HEIGHT
),
638 aReflowState
.mComputedMinHeight
),
639 aReflowState
.mComputedMaxHeight
);
642 #if defined (MOZ_WIDGET_GTK2)
643 // We need to make sure that the size of the object frame does not
644 // exceed the maximum size of X coordinates. See bug #225357 for
645 // more information. In theory Gtk2 can handle large coordinates,
646 // but underlying plugins can't.
647 aMetrics
.height
= PR_MIN(aPresContext
->DevPixelsToAppUnits(PR_INT16_MAX
), aMetrics
.height
);
648 aMetrics
.width
= PR_MIN(aPresContext
->DevPixelsToAppUnits(PR_INT16_MAX
), aMetrics
.width
);
652 // At this point, the width has an unconstrained value only if we have
653 // nothing to go on (no width set, no information from the plugin, nothing).
655 if (aMetrics
.width
== NS_UNCONSTRAINEDSIZE
) {
657 (aReflowState
.mComputedMinWidth
!= NS_UNCONSTRAINEDSIZE
) ?
658 aReflowState
.mComputedMinWidth
: 0;
661 // At this point, the height has an unconstrained value only in two cases:
662 // a) We are in standards mode with percent heights and parent is auto-height
663 // b) We have no height information at all.
664 // In either case, we have to make up a number.
665 if (aMetrics
.height
== NS_UNCONSTRAINEDSIZE
) {
667 (aReflowState
.mComputedMinHeight
!= NS_UNCONSTRAINEDSIZE
) ?
668 aReflowState
.mComputedMinHeight
: 0;
671 // XXXbz don't add in the border and padding, because we screw up our
672 // plugin's size and positioning if we do... Eventually we _do_ want to
673 // paint borders, though! At that point, we will need to adjust the desired
674 // size either here or in Reflow.... Further, we will need to fix Paint() to
675 // call the superclass in all cases.
679 nsObjectFrame::Reflow(nsPresContext
* aPresContext
,
680 nsHTMLReflowMetrics
& aMetrics
,
681 const nsHTMLReflowState
& aReflowState
,
682 nsReflowStatus
& aStatus
)
684 DO_GLOBAL_REFLOW_COUNT("nsObjectFrame");
685 DISPLAY_REFLOW(aPresContext
, this, aReflowState
, aMetrics
, aStatus
);
687 // Get our desired size
688 GetDesiredSize(aPresContext
, aReflowState
, aMetrics
);
690 // delay plugin instantiation until all children have
691 // arrived. Otherwise there may be PARAMs or other stuff that the
692 // plugin needs to see that haven't arrived yet.
693 if (!GetContent()->IsDoneAddingChildren()) {
694 aStatus
= NS_FRAME_COMPLETE
;
698 // if we are printing or print previewing, bail for now
699 if (aPresContext
->Medium() == nsGkAtoms::print
) {
700 aStatus
= NS_FRAME_COMPLETE
;
705 FixupWindow(nsSize(aMetrics
.width
, aMetrics
.height
));
707 aStatus
= NS_FRAME_COMPLETE
;
709 NS_FRAME_SET_TRUNCATION(aStatus
, aReflowState
, aMetrics
);
714 nsObjectFrame::InstantiatePlugin(nsIPluginHost
* aPluginHost
,
715 const char* aMimeType
,
718 // If you add early return(s), be sure to balance this call to
719 // appShell->SuspendNative() with additional call(s) to
720 // appShell->ReturnNative().
721 static NS_DEFINE_CID(kAppShellCID
, NS_APPSHELL_CID
);
722 nsCOMPtr
<nsIAppShell
> appShell
= do_GetService(kAppShellCID
);
724 appShell
->SuspendNative();
728 mInstantiating
= PR_TRUE
;
731 NS_ASSERTION(mContent
, "We should have a content node.");
733 nsIDocument
* doc
= mContent
->GetOwnerDoc();
734 nsCOMPtr
<nsIPluginDocument
> pDoc (do_QueryInterface(doc
));
737 if (pDoc
) { /* full-page mode */
738 nsCOMPtr
<nsIStreamListener
> stream
;
739 rv
= aPluginHost
->InstantiateFullPagePlugin(aMimeType
, aURI
,
740 /* resulting stream listener */ *getter_AddRefs(stream
),
742 if (NS_SUCCEEDED(rv
))
743 pDoc
->SetStreamListener(stream
);
744 } else { /* embedded mode */
745 rv
= aPluginHost
->InstantiateEmbeddedPlugin(aMimeType
, aURI
,
749 mInstantiating
= PR_FALSE
;
753 appShell
->ResumeNative();
756 // XXX having to do this sucks. it'd be better to move the code from DidReflow
757 // to FixupWindow or something.
758 PresContext()->GetPresShell()->
759 FrameNeedsReflow(this, nsIPresShell::eStyleChange
, NS_FRAME_IS_DIRTY
);
764 nsObjectFrame::FixupWindow(const nsSize
& aSize
)
766 nsPresContext
* presContext
= PresContext();
771 nsPluginWindow
*window
;
772 mInstanceOwner
->GetWindow(window
);
774 NS_ENSURE_TRUE(window
, /**/);
777 nsIView
*parentWithView
;
778 GetOffsetFromView(origin
, &parentWithView
);
779 window
->x
= presContext
->AppUnitsToDevPixels(origin
.x
);
780 window
->y
= presContext
->AppUnitsToDevPixels(origin
.y
);
781 window
->width
= presContext
->AppUnitsToDevPixels(aSize
.width
);
782 window
->height
= presContext
->AppUnitsToDevPixels(aSize
.height
);
784 // on the Mac we need to set the clipRect to { 0, 0, 0, 0 } for now. This will keep
785 // us from drawing on screen until the widget is properly positioned, which will not
786 // happen until we have finished the reflow process.
787 window
->clipRect
.top
= 0;
788 window
->clipRect
.left
= 0;
790 window
->clipRect
.bottom
= 0;
791 window
->clipRect
.right
= 0;
793 window
->clipRect
.bottom
= presContext
->AppUnitsToDevPixels(aSize
.height
);
794 window
->clipRect
.right
= presContext
->AppUnitsToDevPixels(aSize
.width
);
799 nsObjectFrame::IsFocusable(PRInt32
*aTabIndex
, PRBool aWithMouse
)
803 return nsObjectFrameSuper::IsFocusable(aTabIndex
, aWithMouse
);
807 nsObjectFrame::IsHidden(PRBool aCheckVisibilityStyle
) const
809 if (aCheckVisibilityStyle
) {
810 if (!GetStyleVisibility()->IsVisibleOrCollapsed())
814 // only <embed> tags support the HIDDEN attribute
815 if (mContent
->Tag() == nsGkAtoms::embed
) {
816 // Yes, these are really the kooky ways that you could tell 4.x
817 // not to hide the <embed> once you'd put the 'hidden' attribute
820 // HIDDEN w/ no attributes gets translated as we are hidden for
821 // compatibility w/ 4.x and IE so we don't create a non-painting
822 // widget in layout. See bug 188959.
824 if (mContent
->GetAttr(kNameSpaceID_None
, nsGkAtoms::hidden
, hidden
) &&
826 !hidden
.LowerCaseEqualsLiteral("false") &&
827 !hidden
.LowerCaseEqualsLiteral("no") &&
828 !hidden
.LowerCaseEqualsLiteral("off"))) {
836 nsPoint
nsObjectFrame::GetWindowOriginInPixels(PRBool aWindowless
)
838 nsIView
* parentWithView
;
841 GetOffsetFromView(origin
, &parentWithView
);
843 // if it's windowless, let's make sure we have our origin set right
844 // it may need to be corrected, like after scrolling
845 if (aWindowless
&& parentWithView
) {
846 nsIViewManager
* parentVM
= parentWithView
->GetViewManager();
848 // Walk up all the views and add up their positions until we
849 // reach the first view with a window (non-null widget). This will give us our
850 // position relative to the containing window which is what we want to give the plugin
851 nsIView
* theView
= parentWithView
;
852 while (theView
&& !theView
->GetWidget()) {
853 if (theView
->GetViewManager() != parentVM
)
856 origin
+= theView
->GetPosition();
857 theView
= theView
->GetParent();
861 origin
.x
= PresContext()->AppUnitsToDevPixels(origin
.x
);
862 origin
.y
= PresContext()->AppUnitsToDevPixels(origin
.y
);
868 nsObjectFrame::DidReflow(nsPresContext
* aPresContext
,
869 const nsHTMLReflowState
* aReflowState
,
870 nsDidReflowStatus aStatus
)
872 nsresult rv
= nsObjectFrameSuper::DidReflow(aPresContext
, aReflowState
, aStatus
);
874 // The view is created hidden; once we have reflowed it and it has been
875 // positioned then we show it.
876 if (aStatus
!= NS_FRAME_REFLOW_FINISHED
)
879 PRBool bHidden
= IsHidden();
882 nsIView
* view
= GetView();
883 nsIViewManager
* vm
= view
->GetViewManager();
885 vm
->SetViewVisibility(view
, bHidden
? nsViewVisibility_kHide
: nsViewVisibility_kShow
);
888 nsPluginWindow
*win
= nsnull
;
890 nsCOMPtr
<nsIPluginInstance
> pi
;
891 if (!mInstanceOwner
||
892 NS_FAILED(rv
= mInstanceOwner
->GetInstance(*getter_AddRefs(pi
))) ||
894 NS_FAILED(rv
= mInstanceOwner
->GetWindow(win
)) ||
898 nsPluginNativeWindow
*window
= (nsPluginNativeWindow
*)win
;
901 mInstanceOwner
->FixUpPluginWindow(ePluginPaintDisable
);
907 PRBool windowless
= (window
->type
== nsPluginWindowType_Drawable
);
909 nsPoint origin
= GetWindowOriginInPixels(windowless
);
911 window
->x
= origin
.x
;
912 window
->y
= origin
.y
;
914 // refresh the plugin port as well
915 window
->window
= mInstanceOwner
->GetPluginPort();
917 // this will call pi->SetWindow and take care of window subclassing
918 // if needed, see bug 132759
919 window
->CallSetWindow(pi
);
921 mInstanceOwner
->ReleasePluginPort((nsPluginPort
*)window
->window
);
926 static void PaintPrintPlugin(nsIFrame
* aFrame
, nsIRenderingContext
* aCtx
,
927 const nsRect
& aDirtyRect
, nsPoint aPt
)
929 nsIRenderingContext::AutoPushTranslation
translate(aCtx
, aPt
.x
, aPt
.y
);
930 NS_STATIC_CAST(nsObjectFrame
*, aFrame
)->PrintPlugin(*aCtx
, aDirtyRect
);
933 static void PaintPlugin(nsIFrame
* aFrame
, nsIRenderingContext
* aCtx
,
934 const nsRect
& aDirtyRect
, nsPoint aPt
)
936 nsIRenderingContext::AutoPushTranslation
translate(aCtx
, aPt
.x
, aPt
.y
);
937 NS_STATIC_CAST(nsObjectFrame
*, aFrame
)->PaintPlugin(*aCtx
, aDirtyRect
);
941 nsObjectFrame::BuildDisplayList(nsDisplayListBuilder
* aBuilder
,
942 const nsRect
& aDirtyRect
,
943 const nsDisplayListSet
& aLists
)
945 // XXX why are we painting collapsed object frames?
946 if (!IsVisibleOrCollapsedForPainting(aBuilder
))
949 nsresult rv
= DisplayBorderBackgroundOutline(aBuilder
, aLists
);
950 NS_ENSURE_SUCCESS(rv
, rv
);
952 nsPresContext::nsPresContextType type
= PresContext()->Type();
954 // If we are painting in Print Preview do nothing....
955 if (type
== nsPresContext::eContext_PrintPreview
)
958 DO_GLOBAL_REFLOW_COUNT_DSP("nsObjectFrame");
960 // determine if we are printing
961 if (type
== nsPresContext::eContext_Print
)
962 return aLists
.Content()->AppendNewToTop(new (aBuilder
)
963 nsDisplayGeneric(this, PaintPrintPlugin
, "PrintPlugin"));
965 return aLists
.Content()->AppendNewToTop(new (aBuilder
)
966 nsDisplayGeneric(this, ::PaintPlugin
, "Plugin"));
970 nsObjectFrame::PrintPlugin(nsIRenderingContext
& aRenderingContext
,
971 const nsRect
& aDirtyRect
)
973 // if we are printing, we need to get the correct nsIPluginInstance
974 // for THIS content node in order to call ->Print() on the right plugin
976 // first, we need to get the document
977 nsIDocument
* doc
= mContent
->GetCurrentDoc();
981 // now we need to get the shell for the screen
982 // XXX assuming that the shell at zero will always be the screen one
983 nsIPresShell
*shell
= doc
->GetPrimaryShell();
987 // then the shell can give us the screen frame for this content node
988 nsIFrame
* frame
= shell
->GetPrimaryFrameFor(mContent
);
992 nsPresContext
* presContext
= PresContext();
993 // make sure this is REALLY an nsIObjectFrame
994 // we may need to go through the children to get it
995 nsIObjectFrame
* objectFrame
= nsnull
;
996 CallQueryInterface(frame
,&objectFrame
);
998 objectFrame
= GetNextObjectFrame(presContext
,frame
);
1002 // finally we can get our plugin instance
1003 nsCOMPtr
<nsIPluginInstance
> pi
;
1004 if (NS_FAILED(objectFrame
->GetPluginInstance(*getter_AddRefs(pi
))) || !pi
)
1007 // now we need to setup the correct location for printing
1009 nsPluginWindow window
;
1010 window
.window
= nsnull
;
1012 // prepare embedded mode printing struct
1013 nsPluginPrint npprint
;
1014 npprint
.mode
= nsPluginMode_Embedded
;
1016 // we need to find out if we are windowless or not
1017 PRBool windowless
= PR_FALSE
;
1018 pi
->GetValue(nsPluginInstanceVariable_WindowlessBool
, (void *)&windowless
);
1019 window
.type
= windowless
? nsPluginWindowType_Drawable
: nsPluginWindowType_Window
;
1021 // Get the offset of the DC
1022 nsTransform2D
* rcTransform
;
1023 aRenderingContext
.GetCurrentTransform(rcTransform
);
1025 rcTransform
->GetTranslationCoord(&origin
.x
, &origin
.y
);
1028 // XXX is windowless different?
1029 window
.x
= origin
.x
;
1030 window
.y
= origin
.y
;
1031 window
.width
= presContext
->AppUnitsToDevPixels(mRect
.width
);
1032 window
.height
= presContext
->AppUnitsToDevPixels(mRect
.height
);
1033 window
.clipRect
.bottom
= 0; window
.clipRect
.top
= 0;
1034 window
.clipRect
.left
= 0; window
.clipRect
.right
= 0;
1036 // XXX platform specific printing code
1037 #if defined(XP_UNIX) && !defined(XP_MACOSX)
1038 /* UNIX does things completely differently:
1039 * We call the plugin and it sends generated PostScript data into a
1040 * file handle we provide. If the plugin returns with success we embed
1041 * this PostScript code fragment into the PostScript job we send to the
1045 PR_LOG(nsObjectFrameLM
, PR_LOG_DEBUG
, ("nsObjectFrame::Paint() start for X11 platforms\n"));
1047 FILE *plugintmpfile
= tmpfile();
1048 if (!plugintmpfile
) {
1049 PR_LOG(nsObjectFrameLM
, PR_LOG_DEBUG
, ("error: could not open tmp. file, errno=%d\n", errno
));
1053 /* Send off print info to plugin */
1054 NPPrintCallbackStruct npPrintInfo
;
1055 npPrintInfo
.type
= NP_PRINT
;
1056 npPrintInfo
.fp
= plugintmpfile
;
1057 npprint
.print
.embedPrint
.platformPrint
= (void *)&npPrintInfo
;
1058 /* aDirtyRect contains the right information for ps print */
1059 window
.x
= aDirtyRect
.x
;
1060 window
.y
= aDirtyRect
.y
;
1061 window
.width
= aDirtyRect
.width
;
1062 window
.height
= aDirtyRect
.height
;
1063 npprint
.print
.embedPrint
.window
= window
;
1064 rv
= pi
->Print(&npprint
);
1065 if (NS_FAILED(rv
)) {
1066 PR_LOG(nsObjectFrameLM
, PR_LOG_DEBUG
, ("error: plugin returned failure %lx\n", (long)rv
));
1067 fclose(plugintmpfile
);
1071 /* Send data to printer */
1072 rv
= aRenderingContext
.RenderEPS(aDirtyRect
, plugintmpfile
);
1074 fclose(plugintmpfile
);
1076 PR_LOG(nsObjectFrameLM
, PR_LOG_DEBUG
, ("plugin printing done, return code is %lx\n", (long)rv
));
1080 // we need the native printer device context to pass to plugin
1081 // On Windows, this will be the HDC
1083 dc
= aRenderingContext
.GetNativeGraphicData(nsIRenderingContext::NATIVE_WINDOWS_DC
);
1085 npprint
.print
.embedPrint
.platformPrint
= dc
;
1086 npprint
.print
.embedPrint
.window
= window
;
1087 // send off print info to plugin
1088 rv
= pi
->Print(&npprint
);
1091 // XXX Nav 4.x always sent a SetWindow call after print. Should we do the same?
1092 nsDidReflowStatus status
= NS_FRAME_REFLOW_FINISHED
; // should we use a special status?
1093 frame
->DidReflow(presContext
,
1094 nsnull
, status
); // DidReflow will take care of it
1098 nsObjectFrame::PaintPlugin(nsIRenderingContext
& aRenderingContext
,
1099 const nsRect
& aDirtyRect
)
1101 // Screen painting code
1102 #if defined(XP_MACOSX)
1103 // delegate all painting to the plugin instance.
1105 mInstanceOwner
->Paint(aDirtyRect
);
1106 #elif defined (XP_WIN) // || defined(XP_OS2)
1107 // XXX for OS/2 we need to overhaul this for Cairo builds
1108 // for now just ignore plugin stuff
1109 nsCOMPtr
<nsIPluginInstance
> inst
;
1110 GetPluginInstance(*getter_AddRefs(inst
));
1112 // Look if it's windowless
1113 nsPluginWindow
* window
;
1114 mInstanceOwner
->GetWindow(window
);
1116 if (window
->type
== nsPluginWindowType_Drawable
) {
1117 // check if we need to call SetWindow with updated parameters
1118 PRBool doupdatewindow
= PR_FALSE
;
1119 // the offset of the DC
1122 // check if we need to update hdc
1123 HDC hdc
= (HDC
)aRenderingContext
.GetNativeGraphicData(nsIRenderingContext::NATIVE_WINDOWS_DC
);
1125 if (NS_REINTERPRET_CAST(HDC
, window
->window
) != hdc
) {
1126 window
->window
= NS_REINTERPRET_CAST(nsPluginPort
*, hdc
);
1127 doupdatewindow
= PR_TRUE
;
1131 * Layout now has an optimized way of painting. Now we always get
1132 * a new drawing surface, sized to be just what's needed. Windowless
1133 * plugins need a transform applied to their origin so they paint
1134 * in the right place. Since |SetWindow| is no longer being used
1135 * to tell the plugin where it is, we dispatch a NPWindow through
1136 * |HandleEvent| to tell the plugin when its window moved
1139 #ifdef MOZ_CAIRO_GFX
1140 nsRefPtr
<gfxContext
> ctx
= (gfxContext
*)aRenderingContext
.GetNativeGraphicData(nsIRenderingContext::NATIVE_THEBES_CONTEXT
);
1141 gfxMatrix ctxMatrix
= ctx
->CurrentMatrix();
1142 if (ctxMatrix
.HasNonTranslation()) {
1143 // soo; in the future, we should be able to render
1144 // the object content to an offscreen DC, and then
1145 // composite it in with the right transforms.
1147 // But, we don't bother doing that, because we don't
1148 // have the event handling story figured out yet.
1149 // Instead, let's just bail.
1154 origin
.x
= NSToIntRound(float(ctxMatrix
.GetTranslation().x
));
1155 origin
.y
= NSToIntRound(float(ctxMatrix
.GetTranslation().y
));
1159 /* Need to force the clip to be set */
1160 ctx
->UpdateSurfaceClip();
1162 /* Set the device offsets as appropriate, for whatever our current group offsets might be */
1163 gfxFloat xoff
, yoff
;
1164 nsRefPtr
<gfxASurface
> surf
= ctx
->CurrentSurface(&xoff
, &yoff
);
1166 POINT origViewportOrigin
;
1167 GetViewportOrgEx(hdc
, &origViewportOrigin
);
1168 SetViewportOrgEx(hdc
, origViewportOrigin
.x
+ (int) xoff
, origViewportOrigin
.y
+ (int) yoff
, NULL
);
1170 nsTransform2D
* rcTransform
;
1171 aRenderingContext
.GetCurrentTransform(rcTransform
);
1172 rcTransform
->GetTranslationCoord(&origin
.x
, &origin
.y
);
1175 if ((window
->x
!= origin
.x
) || (window
->y
!= origin
.y
)) {
1176 window
->x
= origin
.x
;
1177 window
->y
= origin
.y
;
1178 doupdatewindow
= PR_TRUE
;
1181 // if our location or visible area has changed, we need to tell the plugin
1182 if (doupdatewindow
) {
1183 #ifdef XP_WIN // Windowless plugins on windows need a special event to update their location, see bug 135737
1184 // bug 271442: note, the rectangle we send is now purely the bounds of the plugin
1185 // relative to the window it is contained in, which is useful for the plugin to correctly translate mouse coordinates
1187 // this does not mesh with the comments for bug 135737 which imply that the rectangle
1188 // must be clipped in some way to prevent the plugin attempting to paint over areas it shouldn't;
1190 // since the two uses of the rectangle are mutually exclusive in some cases,
1191 // and since I don't see any incorrect painting (at least with Flash and ViewPoint - the originator of 135737),
1192 // it seems that windowless plugins are not relying on information here for clipping their drawing,
1193 // and we can safely use this message to tell the plugin exactly where it is in all cases.
1195 origin
= GetWindowOriginInPixels(PR_TRUE
);
1196 nsRect winlessRect
= nsRect(origin
, nsSize(window
->width
, window
->height
));
1197 if (mWindowlessRect
!= winlessRect
) {
1198 mWindowlessRect
= winlessRect
;
1201 memset(&winpos
, 0, sizeof(winpos
));
1202 winpos
.x
= mWindowlessRect
.x
;
1203 winpos
.y
= mWindowlessRect
.y
;
1204 winpos
.cx
= mWindowlessRect
.width
;
1205 winpos
.cy
= mWindowlessRect
.height
;
1207 // finally, update the plugin by sending it a WM_WINDOWPOSCHANGED event
1208 nsPluginEvent pluginEvent
;
1209 pluginEvent
.event
= WM_WINDOWPOSCHANGED
;
1210 pluginEvent
.wParam
= 0;
1211 pluginEvent
.lParam
= (uint32
)&winpos
;
1212 PRBool eventHandled
= PR_FALSE
;
1214 inst
->HandleEvent(&pluginEvent
, &eventHandled
);
1218 inst
->SetWindow(window
);
1221 // This expects a dirty rect relative to the plugin's rect
1222 // XXX I wonder if this breaks if we give the frame a border so the
1223 // frame origin and plugin origin are not the same
1224 mInstanceOwner
->Paint(aDirtyRect
, (PRUint32
)(HDC
)hdc
);
1226 #ifdef MOZ_CAIRO_GFX
1237 nsObjectFrame::HandleEvent(nsPresContext
* aPresContext
,
1238 nsGUIEvent
* anEvent
,
1239 nsEventStatus
* anEventStatus
)
1241 NS_ENSURE_ARG_POINTER(anEventStatus
);
1242 nsresult rv
= NS_OK
;
1244 if (!mInstanceOwner
)
1245 return NS_ERROR_NULL_POINTER
;
1247 if (anEvent
->message
== NS_PLUGIN_ACTIVATE
) {
1248 nsIContent
* content
= GetContent();
1250 content
->SetFocus(aPresContext
);
1256 rv
= nsObjectFrameSuper::HandleEvent(aPresContext
, anEvent
, anEventStatus
);
1260 switch (anEvent
->message
) {
1262 mInstanceOwner
->CancelTimer();
1266 *anEventStatus
= mInstanceOwner
->ProcessEvent(*anEvent
);
1270 // instead of using an event listener, we can dispatch events to plugins directly.
1271 rv
= nsObjectFrameSuper::HandleEvent(aPresContext
, anEvent
, anEventStatus
);
1277 nsresult
nsObjectFrame::GetPluginInstance(nsIPluginInstance
*& aPluginInstance
)
1279 aPluginInstance
= nsnull
;
1281 if (!mInstanceOwner
)
1284 return mInstanceOwner
->GetInstance(aPluginInstance
);
1288 nsObjectFrame::PrepareInstanceOwner()
1290 // First, have to stop any possibly running plugins.
1293 NS_ASSERTION(!mInstanceOwner
, "Must not have an instance owner here");
1295 mInstanceOwner
= new nsPluginInstanceOwner();
1296 if (!mInstanceOwner
)
1297 return NS_ERROR_OUT_OF_MEMORY
;
1299 NS_ADDREF(mInstanceOwner
);
1300 mInstanceOwner
->Init(PresContext(), this, GetContent());
1305 nsObjectFrame::Instantiate(nsIChannel
* aChannel
, nsIStreamListener
** aStreamListener
)
1307 nsresult rv
= PrepareInstanceOwner();
1308 NS_ENSURE_SUCCESS(rv
, rv
);
1310 nsCOMPtr
<nsIPluginHost
> pluginHost(do_GetService(kCPluginManagerCID
, &rv
));
1313 mInstanceOwner
->SetPluginHost(pluginHost
);
1315 // This must be done before instantiating the plugin
1316 FixupWindow(mRect
.Size());
1318 rv
= pluginHost
->InstantiatePluginForChannel(aChannel
, mInstanceOwner
, aStreamListener
);
1320 // XXX having to do this sucks. it'd be better to move the code from DidReflow
1322 PresContext()->GetPresShell()->
1323 FrameNeedsReflow(this, nsIPresShell::eStyleChange
, NS_FRAME_IS_DIRTY
);
1328 nsObjectFrame::Instantiate(const char* aMimeType
, nsIURI
* aURI
)
1330 NS_ASSERTION(aMimeType
|| aURI
, "Need a type or a URI!");
1331 nsresult rv
= PrepareInstanceOwner();
1332 NS_ENSURE_SUCCESS(rv
, rv
);
1334 // This must be done before instantiating the plugin
1335 FixupWindow(mRect
.Size());
1337 // get the nsIPluginHost service
1338 nsCOMPtr
<nsIPluginHost
> pluginHost(do_GetService(kCPluginManagerCID
, &rv
));
1341 mInstanceOwner
->SetPluginHost(pluginHost
);
1343 rv
= InstantiatePlugin(pluginHost
, aMimeType
, aURI
);
1346 if (NS_SUCCEEDED(rv
)) {
1347 nsCOMPtr
<nsIPluginInstance
> inst
;
1348 mInstanceOwner
->GetInstance(*getter_AddRefs(inst
));
1350 // The plugin may have set up new interfaces; we need to mess with our JS
1351 // wrapper. Note that we DO NOT want to call this if there is no plugin
1352 // instance! That would just reenter Instantiate(), trying to create
1353 // said plugin instance.
1354 NotifyContentObjectWrapper();
1362 nsObjectFrame::StopPlugin()
1364 if (mInstanceOwner
!= nsnull
) {
1365 nsCOMPtr
<nsIPluginInstance
> inst
;
1366 mInstanceOwner
->GetInstance(*getter_AddRefs(inst
));
1368 nsPluginWindow
*win
;
1369 mInstanceOwner
->GetWindow(win
);
1370 nsPluginNativeWindow
*window
= (nsPluginNativeWindow
*)win
;
1371 nsCOMPtr
<nsIPluginInstance
> nullinst
;
1373 PRBool doCache
= PR_TRUE
;
1374 PRBool doCallSetWindowAfterDestroy
= PR_FALSE
;
1376 // first, determine if the plugin wants to be cached
1377 inst
->GetValue(nsPluginInstanceVariable_DoCacheBool
,
1380 // then determine if the plugin wants Destroy to be called after
1381 // Set Window. This is for bug 50547.
1382 inst
->GetValue(nsPluginInstanceVariable_CallSetWindowAfterDestroyBool
,
1383 (void *) &doCallSetWindowAfterDestroy
);
1384 if (doCallSetWindowAfterDestroy
) {
1389 window
->CallSetWindow(nullinst
);
1391 inst
->SetWindow(nsnull
);
1395 window
->CallSetWindow(nullinst
);
1397 inst
->SetWindow(nsnull
);
1405 window
->CallSetWindow(nullinst
);
1407 inst
->SetWindow(nsnull
);
1412 nsCOMPtr
<nsIPluginHost
> pluginHost
= do_GetService(kCPluginManagerCID
);
1414 pluginHost
->StopPluginInstance(inst
);
1416 // the frame is going away along with its widget
1417 // so tell the window to forget its widget too
1419 window
->SetPluginWidget(nsnull
);
1422 mInstanceOwner
->Destroy();
1423 NS_RELEASE(mInstanceOwner
);
1428 nsObjectFrame::NotifyContentObjectWrapper()
1430 nsCOMPtr
<nsIDocument
> doc
= mContent
->GetDocument();
1434 nsIScriptGlobalObject
*sgo
= doc
->GetScriptGlobalObject();
1438 nsIScriptContext
*scx
= sgo
->GetContext();
1442 JSContext
*cx
= (JSContext
*)scx
->GetNativeContext();
1444 nsCOMPtr
<nsIXPConnectWrappedNative
> wrapper
;
1445 nsContentUtils::XPConnect()->
1446 GetWrappedNativeOfNativeObject(cx
, sgo
->GetGlobalJSObject(), mContent
,
1447 NS_GET_IID(nsISupports
),
1448 getter_AddRefs(wrapper
));
1451 // Nothing to do here if there's no wrapper for mContent
1455 nsCOMPtr
<nsIClassInfo
> ci(do_QueryInterface(mContent
));
1459 nsCOMPtr
<nsISupports
> s
;
1460 ci
->GetHelperForLanguage(nsIProgrammingLanguage::JAVASCRIPT
,
1463 nsCOMPtr
<nsIXPCScriptable
> helper(do_QueryInterface(s
));
1466 // There's nothing we can do if there's no helper
1470 JSObject
*obj
= nsnull
;
1471 nsresult rv
= wrapper
->GetJSObject(&obj
);
1475 // Abuse the scriptable helper to trigger prototype setup for the
1476 // wrapper for mContent so that this plugin becomes part of the DOM
1478 helper
->PostCreate(wrapper
, cx
, obj
);
1483 nsObjectFrame::GetNextObjectFrame(nsPresContext
* aPresContext
, nsIFrame
* aRoot
)
1485 nsIFrame
* child
= aRoot
->GetFirstChild(nsnull
);
1488 nsIObjectFrame
* outFrame
= nsnull
;
1489 CallQueryInterface(child
, &outFrame
);
1491 nsCOMPtr
<nsIPluginInstance
> pi
;
1492 outFrame
->GetPluginInstance(*getter_AddRefs(pi
)); // make sure we have a REAL plugin
1497 outFrame
= GetNextObjectFrame(aPresContext
, child
);
1500 child
= child
->GetNextSibling();
1507 NS_NewObjectFrame(nsIPresShell
* aPresShell
, nsStyleContext
* aContext
)
1509 return new (aPresShell
) nsObjectFrame(aContext
);
1513 // nsPluginDOMContextMenuListener class implementation
1515 nsPluginDOMContextMenuListener::nsPluginDOMContextMenuListener()
1519 nsPluginDOMContextMenuListener::~nsPluginDOMContextMenuListener()
1523 NS_IMPL_ISUPPORTS2(nsPluginDOMContextMenuListener
, nsIDOMContextMenuListener
, nsIEventListener
)
1526 nsPluginDOMContextMenuListener::ContextMenu(nsIDOMEvent
* aContextMenuEvent
)
1528 aContextMenuEvent
->PreventDefault(); // consume event
1533 nsresult
nsPluginDOMContextMenuListener::Init(nsIContent
* aContent
)
1535 nsCOMPtr
<nsIDOMEventTarget
> receiver(do_QueryInterface(aContent
));
1537 receiver
->AddEventListener(NS_LITERAL_STRING("contextmenu"), this, PR_TRUE
);
1541 return NS_ERROR_NO_INTERFACE
;
1544 nsresult
nsPluginDOMContextMenuListener::Destroy(nsIContent
* aContent
)
1546 // Unregister context menu listener
1547 nsCOMPtr
<nsIDOMEventTarget
> receiver(do_QueryInterface(aContent
));
1549 receiver
->RemoveEventListener(NS_LITERAL_STRING("contextmenu"), this, PR_TRUE
);
1555 //plugin instance owner
1557 nsPluginInstanceOwner::nsPluginInstanceOwner()
1559 // create nsPluginNativeWindow object, it is derived from nsPluginWindow
1560 // struct and allows to manipulate native window procedure
1561 nsCOMPtr
<nsIPluginHost
> ph
= do_GetService(kCPluginManagerCID
);
1562 nsCOMPtr
<nsPIPluginHost
> pph(do_QueryInterface(ph
));
1564 pph
->NewPluginNativeWindow(&mPluginWindow
);
1566 mPluginWindow
= nsnull
;
1570 mContentFocused
= PR_FALSE
;
1571 mWidgetVisible
= PR_TRUE
;
1572 mNumCachedAttrs
= 0;
1573 mNumCachedParams
= 0;
1574 mCachedAttrParamNames
= nsnull
;
1575 mCachedAttrParamValues
= nsnull
;
1578 nsPluginInstanceOwner::~nsPluginInstanceOwner()
1582 // shut off the timer.
1583 if (mPluginTimer
!= nsnull
) {
1589 for (cnt
= 0; cnt
< (mNumCachedAttrs
+ 1 + mNumCachedParams
); cnt
++) {
1590 if (mCachedAttrParamNames
&& mCachedAttrParamNames
[cnt
]) {
1591 PR_Free(mCachedAttrParamNames
[cnt
]);
1592 mCachedAttrParamNames
[cnt
] = nsnull
;
1595 if (mCachedAttrParamValues
&& mCachedAttrParamValues
[cnt
]) {
1596 PR_Free(mCachedAttrParamValues
[cnt
]);
1597 mCachedAttrParamValues
[cnt
] = nsnull
;
1601 if (mCachedAttrParamNames
) {
1602 PR_Free(mCachedAttrParamNames
);
1603 mCachedAttrParamNames
= nsnull
;
1606 if (mCachedAttrParamValues
) {
1607 PR_Free(mCachedAttrParamValues
);
1608 mCachedAttrParamValues
= nsnull
;
1616 #if defined(XP_UNIX) && !defined(XP_MACOSX)
1617 // the mem for this struct is allocated
1618 // by PR_MALLOC in ns4xPluginInstance.cpp:ns4xPluginInstance::SetWindow()
1619 if (mPluginWindow
&& mPluginWindow
->ws_info
) {
1620 PR_Free(mPluginWindow
->ws_info
);
1621 mPluginWindow
->ws_info
= nsnull
;
1625 // clean up plugin native window object
1626 nsCOMPtr
<nsIPluginHost
> ph
= do_GetService(kCPluginManagerCID
);
1627 nsCOMPtr
<nsPIPluginHost
> pph(do_QueryInterface(ph
));
1629 pph
->DeletePluginNativeWindow(mPluginWindow
);
1630 mPluginWindow
= nsnull
;
1635 * nsISupports Implementation
1638 NS_IMPL_ADDREF(nsPluginInstanceOwner
)
1639 NS_IMPL_RELEASE(nsPluginInstanceOwner
)
1641 NS_INTERFACE_MAP_BEGIN(nsPluginInstanceOwner
)
1642 NS_INTERFACE_MAP_ENTRY(nsIPluginInstanceOwner
)
1643 NS_INTERFACE_MAP_ENTRY(nsIPluginTagInfo
)
1644 NS_INTERFACE_MAP_ENTRY(nsIPluginTagInfo2
)
1646 NS_INTERFACE_MAP_ENTRY(nsIJVMPluginTagInfo
)
1648 NS_INTERFACE_MAP_ENTRY(nsIEventListener
)
1649 NS_INTERFACE_MAP_ENTRY(nsITimerCallback
)
1650 NS_INTERFACE_MAP_ENTRY(nsIDOMMouseListener
)
1651 NS_INTERFACE_MAP_ENTRY(nsIDOMMouseMotionListener
)
1652 NS_INTERFACE_MAP_ENTRY(nsIDOMKeyListener
)
1653 NS_INTERFACE_MAP_ENTRY(nsIDOMFocusListener
)
1654 NS_INTERFACE_MAP_ENTRY(nsIScrollPositionListener
)
1655 NS_INTERFACE_MAP_ENTRY(nsIDOMDragListener
)
1656 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener
, nsIDOMMouseListener
)
1657 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIPluginInstanceOwner
)
1658 NS_INTERFACE_MAP_END
1660 NS_IMETHODIMP
nsPluginInstanceOwner::SetInstance(nsIPluginInstance
*aInstance
)
1662 mInstance
= aInstance
;
1667 NS_IMETHODIMP
nsPluginInstanceOwner::GetWindow(nsPluginWindow
*&aWindow
)
1669 NS_ASSERTION(mPluginWindow
, "the plugin window object being returned is null");
1670 aWindow
= mPluginWindow
;
1674 NS_IMETHODIMP
nsPluginInstanceOwner::GetMode(nsPluginMode
*aMode
)
1676 nsCOMPtr
<nsIDocument
> doc
;
1677 nsresult rv
= GetDocument(getter_AddRefs(doc
));
1678 nsCOMPtr
<nsIPluginDocument
> pDoc (do_QueryInterface(doc
));
1681 *aMode
= nsPluginMode_Full
;
1683 *aMode
= nsPluginMode_Embedded
;
1689 NS_IMETHODIMP
nsPluginInstanceOwner::GetAttributes(PRUint16
& n
,
1690 const char*const*& names
,
1691 const char*const*& values
)
1693 nsresult rv
= EnsureCachedAttrParamArrays();
1694 NS_ENSURE_SUCCESS(rv
, rv
);
1696 n
= mNumCachedAttrs
;
1697 names
= (const char **)mCachedAttrParamNames
;
1698 values
= (const char **)mCachedAttrParamValues
;
1703 NS_IMETHODIMP
nsPluginInstanceOwner::GetAttribute(const char* name
, const char* *result
)
1705 NS_ENSURE_ARG_POINTER(name
);
1706 NS_ENSURE_ARG_POINTER(result
);
1708 nsresult rv
= EnsureCachedAttrParamArrays();
1709 NS_ENSURE_SUCCESS(rv
, rv
);
1713 for (int i
= 0; i
< mNumCachedAttrs
; i
++) {
1714 if (0 == PL_strcasecmp(mCachedAttrParamNames
[i
], name
)) {
1715 *result
= mCachedAttrParamValues
[i
];
1720 return NS_ERROR_FAILURE
;
1723 NS_IMETHODIMP
nsPluginInstanceOwner::GetDOMElement(nsIDOMElement
* *result
)
1725 return CallQueryInterface(mContent
, result
);
1728 NS_IMETHODIMP
nsPluginInstanceOwner::GetInstance(nsIPluginInstance
*&aInstance
)
1730 NS_IF_ADDREF(aInstance
= mInstance
);
1735 NS_IMETHODIMP
nsPluginInstanceOwner::GetURL(const char *aURL
, const char *aTarget
, void *aPostData
, PRUint32 aPostDataLen
, void *aHeadersData
,
1736 PRUint32 aHeadersDataLen
, PRBool isFile
)
1738 NS_ENSURE_TRUE(mOwner
,NS_ERROR_NULL_POINTER
);
1740 // the container of the pres context will give us the link handler
1741 nsCOMPtr
<nsISupports
> container
= mOwner
->PresContext()->GetContainer();
1742 NS_ENSURE_TRUE(container
,NS_ERROR_FAILURE
);
1743 nsCOMPtr
<nsILinkHandler
> lh
= do_QueryInterface(container
);
1744 NS_ENSURE_TRUE(lh
, NS_ERROR_FAILURE
);
1746 nsAutoString unitarget
;
1747 unitarget
.AssignASCII(aTarget
); // XXX could this be nonascii?
1749 nsCOMPtr
<nsIURI
> baseURI
= mContent
->GetBaseURI();
1751 // Create an absolute URL
1752 nsCOMPtr
<nsIURI
> uri
;
1753 nsresult rv
= NS_NewURI(getter_AddRefs(uri
), aURL
, baseURI
);
1755 NS_ENSURE_SUCCESS(rv
, NS_ERROR_FAILURE
);
1757 nsCOMPtr
<nsIInputStream
> postDataStream
;
1758 nsCOMPtr
<nsIInputStream
> headersDataStream
;
1760 // deal with post data, either in a file or raw data, and any headers
1763 rv
= NS_NewPluginPostDataStream(getter_AddRefs(postDataStream
), (const char *)aPostData
, aPostDataLen
, isFile
);
1765 NS_ASSERTION(NS_SUCCEEDED(rv
),"failed in creating plugin post data stream");
1770 rv
= NS_NewPluginPostDataStream(getter_AddRefs(headersDataStream
),
1771 (const char *) aHeadersData
,
1774 PR_TRUE
); // last arg says we are headers, no /r/n/r/n fixup!
1776 NS_ASSERTION(NS_SUCCEEDED(rv
),"failed in creating plugin header data stream");
1782 PRInt32 blockPopups
=
1783 nsContentUtils::GetIntPref("privacy.popups.disable_from_plugins");
1784 nsAutoPopupStatePusher
popupStatePusher((PopupControlState
)blockPopups
);
1786 rv
= lh
->OnLinkClick(mContent
, uri
, unitarget
.get(),
1787 postDataStream
, headersDataStream
);
1792 NS_IMETHODIMP
nsPluginInstanceOwner::ShowStatus(const char *aStatusMsg
)
1794 nsresult rv
= NS_ERROR_FAILURE
;
1796 rv
= this->ShowStatus(NS_ConvertUTF8toUTF16(aStatusMsg
).get());
1801 NS_IMETHODIMP
nsPluginInstanceOwner::ShowStatus(const PRUnichar
*aStatusMsg
)
1803 nsresult rv
= NS_ERROR_FAILURE
;
1808 nsCOMPtr
<nsISupports
> cont
= mOwner
->PresContext()->GetContainer();
1813 nsCOMPtr
<nsIDocShellTreeItem
> docShellItem(do_QueryInterface(cont
, &rv
));
1814 if (NS_FAILED(rv
) || !docShellItem
) {
1818 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
1819 rv
= docShellItem
->GetTreeOwner(getter_AddRefs(treeOwner
));
1820 if (NS_FAILED(rv
) || !treeOwner
) {
1824 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome(do_GetInterface(treeOwner
, &rv
));
1825 if (NS_FAILED(rv
) || !browserChrome
) {
1828 rv
= browserChrome
->SetStatus(nsIWebBrowserChrome::STATUS_SCRIPT
,
1834 NS_IMETHODIMP
nsPluginInstanceOwner::GetDocument(nsIDocument
* *aDocument
)
1837 return NS_ERROR_NULL_POINTER
;
1839 // XXX sXBL/XBL2 issue: current doc or owner doc?
1840 // But keep in mind bug 322414 comment 33
1841 NS_IF_ADDREF(*aDocument
= mContent
->GetOwnerDoc());
1845 NS_IMETHODIMP
nsPluginInstanceOwner::InvalidateRect(nsPluginRect
*invalidRect
)
1847 nsresult rv
= NS_ERROR_FAILURE
;
1849 if (mOwner
&& invalidRect
) {
1850 //no reference count on view
1851 nsIView
* view
= mOwner
->GetView();
1854 nsPresContext
* presContext
= mOwner
->PresContext();
1856 nsRect
rect(presContext
->DevPixelsToAppUnits(invalidRect
->left
),
1857 presContext
->DevPixelsToAppUnits(invalidRect
->top
),
1858 presContext
->DevPixelsToAppUnits(invalidRect
->right
- invalidRect
->left
),
1859 presContext
->DevPixelsToAppUnits(invalidRect
->bottom
- invalidRect
->top
));
1861 //set flags to not do a synchronous update, force update does the redraw
1862 view
->GetViewManager()->UpdateView(view
, rect
, NS_VMREFRESH_NO_SYNC
);
1869 NS_IMETHODIMP
nsPluginInstanceOwner::InvalidateRegion(nsPluginRegion invalidRegion
)
1871 return NS_ERROR_NOT_IMPLEMENTED
;
1874 NS_IMETHODIMP
nsPluginInstanceOwner::ForceRedraw()
1876 nsIView
* view
= mOwner
->GetView();
1878 return view
->GetViewManager()->Composite();
1884 NS_IMETHODIMP
nsPluginInstanceOwner::GetValue(nsPluginInstancePeerVariable variable
, void *value
)
1886 nsresult rv
= NS_ERROR_FAILURE
;
1889 case nsPluginInstancePeerVariable_NetscapeWindow
:
1892 void** pvalue
= (void**)value
;
1893 nsIViewManager
* vm
= mOwner
->PresContext()->GetViewManager();
1896 // This property is provided to allow a "windowless" plugin to determine the window it is drawing
1897 // in, so it can translate mouse coordinates it receives directly from the operating system
1898 // to coordinates relative to itself.
1900 // The original code (outside this #if) returns the document's window, which is OK if the window the "windowless" plugin
1901 // is drawing into has the same origin as the document's window, but this is not the case for "windowless" plugins inside of scrolling DIVs etc
1903 // To make sure "windowless" plugins always get the right origin for translating mouse coordinates, this code
1904 // determines the window handle of the mozilla window containing the "windowless" plugin.
1906 // Given that this HWND may not be that of the document's window, there is a slight risk
1907 // of confusing a plugin that is using this HWND for illicit purposes, but since the documentation
1908 // does not suggest this HWND IS that of the document window, rather that of the window
1909 // the plugin is drawn in, this seems like a safe fix.
1911 // we only attempt to get the nearest window if this really is a "windowless" plugin so as not
1912 // to change any behaviour for the much more common windowed plugins,
1913 // though why this method would even be being called for a windowed plugin escapes me.
1914 if (mPluginWindow
&& mPluginWindow
->type
== nsPluginWindowType_Drawable
) {
1916 // it turns out that flash also uses this window for determining focus, and is currently
1917 // unable to show a caret correctly if we return the enclosing window. Therefore for
1918 // now we only return the enclosing window when there is an actual offset which
1919 // would otherwise cause coordinates to be offset incorrectly. (i.e.
1920 // if the enclosing window if offset from the document window)
1922 // fixing both the caret and ability to interact issues for a windowless control in a non document aligned windw
1923 // does not seem to be possible without a change to the flash plugin
1925 nsIWidget
* win
= mOwner
->GetWindow();
1927 nsIView
*view
= nsIView::GetViewFor(win
);
1928 NS_ASSERTION(view
, "No view for widget");
1929 nsIView
*rootView
= nsnull
;
1930 vm
->GetRootView(rootView
);
1931 NS_ASSERTION(rootView
, "No root view");
1932 nsPoint offset
= view
->GetOffsetTo(rootView
);
1934 if (offset
.x
|| offset
.y
) {
1935 // in the case the two windows are offset from eachother, we do go ahead and return the correct enclosing window
1936 // so that mouse co-ordinates are not messed up.
1937 *pvalue
= (void*)win
->GetNativeData(NS_NATIVE_WINDOW
);
1945 // simply return the document window
1946 nsCOMPtr
<nsIWidget
> widget
;
1947 rv
= vm
->GetWidget(getter_AddRefs(widget
));
1949 *pvalue
= (void*)widget
->GetNativeData(NS_NATIVE_WINDOW
);
1950 } else NS_ASSERTION(widget
, "couldn't get doc's widget in getting doc's window handle");
1951 } else NS_ASSERTION(vm
, "couldn't get view manager in getting doc's window handle");
1952 } else NS_ASSERTION(mOwner
, "plugin owner has no owner in getting doc's window handle");
1960 NS_IMETHODIMP
nsPluginInstanceOwner::GetTagType(nsPluginTagType
*result
)
1962 NS_ENSURE_ARG_POINTER(result
);
1964 *result
= nsPluginTagType_Unknown
;
1966 nsIAtom
*atom
= mContent
->Tag();
1968 if (atom
== nsGkAtoms::applet
)
1969 *result
= nsPluginTagType_Applet
;
1970 else if (atom
== nsGkAtoms::embed
)
1971 *result
= nsPluginTagType_Embed
;
1972 else if (atom
== nsGkAtoms::object
)
1973 *result
= nsPluginTagType_Object
;
1978 NS_IMETHODIMP
nsPluginInstanceOwner::GetTagText(const char* *result
)
1980 NS_ENSURE_ARG_POINTER(result
);
1981 if (nsnull
== mTagText
) {
1983 nsCOMPtr
<nsIDOMNode
> node(do_QueryInterface(mContent
, &rv
));
1987 nsCOMPtr
<nsIDocument
> document
;
1988 rv
= GetDocument(getter_AddRefs(document
));
1992 nsCOMPtr
<nsIDOMDocument
> domDoc
= do_QueryInterface(document
);
1993 NS_ASSERTION(domDoc
, "Need a document");
1995 nsCOMPtr
<nsIDocumentEncoder
> docEncoder(do_CreateInstance(NS_DOC_ENCODER_CONTRACTID_BASE
"text/html", &rv
));
1998 rv
= docEncoder
->Init(domDoc
, NS_LITERAL_STRING("text/html"), nsIDocumentEncoder::OutputEncodeBasicEntities
);
2002 nsCOMPtr
<nsIDOMRange
> range(do_CreateInstance(kRangeCID
,&rv
));
2006 rv
= range
->SelectNode(node
);
2010 docEncoder
->SetRange(range
);
2011 nsString elementHTML
;
2012 rv
= docEncoder
->EncodeToString(elementHTML
);
2016 mTagText
= ToNewUTF8String(elementHTML
);
2018 return NS_ERROR_OUT_OF_MEMORY
;
2024 NS_IMETHODIMP
nsPluginInstanceOwner::GetParameters(PRUint16
& n
, const char*const*& names
, const char*const*& values
)
2026 nsresult rv
= EnsureCachedAttrParamArrays();
2027 NS_ENSURE_SUCCESS(rv
, rv
);
2029 n
= mNumCachedParams
;
2031 names
= (const char **)(mCachedAttrParamNames
+ mNumCachedAttrs
+ 1);
2032 values
= (const char **)(mCachedAttrParamValues
+ mNumCachedAttrs
+ 1);
2034 names
= values
= nsnull
;
2039 NS_IMETHODIMP
nsPluginInstanceOwner::GetParameter(const char* name
, const char* *result
)
2041 NS_ENSURE_ARG_POINTER(name
);
2042 NS_ENSURE_ARG_POINTER(result
);
2044 nsresult rv
= EnsureCachedAttrParamArrays();
2045 NS_ENSURE_SUCCESS(rv
, rv
);
2049 for (int i
= mNumCachedAttrs
+ 1; i
< (mNumCachedParams
+ 1 + mNumCachedAttrs
); i
++) {
2050 if (0 == PL_strcasecmp(mCachedAttrParamNames
[i
], name
)) {
2051 *result
= mCachedAttrParamValues
[i
];
2056 return NS_ERROR_FAILURE
;
2059 NS_IMETHODIMP
nsPluginInstanceOwner::GetDocumentBase(const char* *result
)
2061 NS_ENSURE_ARG_POINTER(result
);
2062 nsresult rv
= NS_OK
;
2063 if (mDocumentBase
.IsEmpty()) {
2066 return NS_ERROR_FAILURE
;
2069 nsIDocument
* doc
= mContent
->GetOwnerDoc();
2070 NS_ASSERTION(doc
, "Must have an owner doc");
2071 rv
= doc
->GetBaseURI()->GetSpec(mDocumentBase
);
2073 if (NS_SUCCEEDED(rv
))
2074 *result
= ToNewCString(mDocumentBase
);
2078 static nsDataHashtable
<nsDepCharHashKey
, const char *> * gCharsetMap
;
2084 /* XXX If you add any strings longer than
2085 * {"x-mac-cyrillic", "MacCyrillic"},
2086 * {"x-mac-ukrainian", "MacUkraine"},
2087 * to the following array then you MUST update the
2088 * sizes of the arrays in the moz2javaCharset struct
2091 static const moz2javaCharset charsets
[] =
2093 {"windows-1252", "Cp1252"},
2094 {"IBM850", "Cp850"},
2095 {"IBM852", "Cp852"},
2096 {"IBM855", "Cp855"},
2097 {"IBM857", "Cp857"},
2098 {"IBM828", "Cp862"},
2099 {"IBM864", "Cp864"},
2100 {"IBM866", "Cp866"},
2101 {"windows-1250", "Cp1250"},
2102 {"windows-1251", "Cp1251"},
2103 {"windows-1253", "Cp1253"},
2104 {"windows-1254", "Cp1254"},
2105 {"windows-1255", "Cp1255"},
2106 {"windows-1256", "Cp1256"},
2107 {"windows-1257", "Cp1257"},
2108 {"windows-1258", "Cp1258"},
2109 {"EUC-JP", "EUC_JP"},
2110 {"EUC-KR", "EUC_KR"},
2111 {"x-euc-tw", "EUC_TW"},
2112 {"gb18030", "GB18030"},
2114 {"ISO-2022-JP", "ISO2022JP"},
2115 {"ISO-2022-KR", "ISO2022KR"},
2116 {"ISO-8859-2", "ISO8859_2"},
2117 {"ISO-8859-3", "ISO8859_3"},
2118 {"ISO-8859-4", "ISO8859_4"},
2119 {"ISO-8859-5", "ISO8859_5"},
2120 {"ISO-8859-6", "ISO8859_6"},
2121 {"ISO-8859-7", "ISO8859_7"},
2122 {"ISO-8859-8", "ISO8859_8"},
2123 {"ISO-8859-9", "ISO8859_9"},
2124 {"ISO-8859-13", "ISO8859_13"},
2125 {"x-johab", "Johab"},
2126 {"KOI8-R", "KOI8_R"},
2127 {"TIS-620", "MS874"},
2128 {"windows-936", "MS936"},
2129 {"x-windows-949", "MS949"},
2130 {"x-mac-arabic", "MacArabic"},
2131 {"x-mac-croatian", "MacCroatia"},
2132 {"x-mac-cyrillic", "MacCyrillic"},
2133 {"x-mac-greek", "MacGreek"},
2134 {"x-mac-hebrew", "MacHebrew"},
2135 {"x-mac-icelandic", "MacIceland"},
2136 {"x-mac-roman", "MacRoman"},
2137 {"x-mac-romanian", "MacRomania"},
2138 {"x-mac-ukrainian", "MacUkraine"},
2139 {"Shift_JIS", "SJIS"},
2140 {"TIS-620", "TIS620"}
2143 NS_IMETHODIMP
nsPluginInstanceOwner::GetDocumentEncoding(const char* *result
)
2145 NS_ENSURE_ARG_POINTER(result
);
2149 // XXX sXBL/XBL2 issue: current doc or owner doc?
2150 nsCOMPtr
<nsIDocument
> doc
;
2151 rv
= GetDocument(getter_AddRefs(doc
));
2152 NS_ASSERTION(NS_SUCCEEDED(rv
), "failed to get document");
2156 const nsCString
&charset
= doc
->GetDocumentCharacterSet();
2158 if (charset
.IsEmpty())
2161 // common charsets and those not requiring conversion first
2162 if (charset
.EqualsLiteral("us-ascii")) {
2163 *result
= PL_strdup("US_ASCII");
2164 } else if (charset
.EqualsLiteral("ISO-8859-1") ||
2165 !nsCRT::strncmp(PromiseFlatCString(charset
).get(), "UTF", 3)) {
2166 *result
= ToNewCString(charset
);
2169 const int NUM_CHARSETS
= sizeof(charsets
) / sizeof(moz2javaCharset
);
2170 gCharsetMap
= new nsDataHashtable
<nsDepCharHashKey
, const char*>();
2171 if (!gCharsetMap
|| !gCharsetMap
->Init(NUM_CHARSETS
))
2172 return NS_ERROR_OUT_OF_MEMORY
;
2174 for (PRUint16 i
= 0; i
< NUM_CHARSETS
; i
++) {
2175 gCharsetMap
->Put(charsets
[i
].mozName
, charsets
[i
].javaName
);
2178 // if found mapping, return it; otherwise return original charset
2179 const char *mapping
;
2180 *result
= gCharsetMap
->Get(charset
.get(), &mapping
) ? PL_strdup(mapping
) :
2181 ToNewCString(charset
);
2184 return (*result
) ? NS_OK
: NS_ERROR_OUT_OF_MEMORY
;
2187 NS_IMETHODIMP
nsPluginInstanceOwner::GetAlignment(const char* *result
)
2189 return GetAttribute("ALIGN", result
);
2192 NS_IMETHODIMP
nsPluginInstanceOwner::GetWidth(PRUint32
*result
)
2194 NS_ENSURE_ARG_POINTER(result
);
2196 NS_ENSURE_TRUE(mPluginWindow
, NS_ERROR_NULL_POINTER
);
2198 *result
= mPluginWindow
->width
;
2203 NS_IMETHODIMP
nsPluginInstanceOwner::GetHeight(PRUint32
*result
)
2205 NS_ENSURE_ARG_POINTER(result
);
2207 NS_ENSURE_TRUE(mPluginWindow
, NS_ERROR_NULL_POINTER
);
2209 *result
= mPluginWindow
->height
;
2215 NS_IMETHODIMP
nsPluginInstanceOwner::GetBorderVertSpace(PRUint32
*result
)
2220 rv
= GetAttribute("VSPACE", &vspace
);
2224 *result
= (PRUint32
)atol(vspace
);
2234 NS_IMETHODIMP
nsPluginInstanceOwner::GetBorderHorizSpace(PRUint32
*result
)
2239 rv
= GetAttribute("HSPACE", &hspace
);
2243 *result
= (PRUint32
)atol(hspace
);
2253 NS_IMETHODIMP
nsPluginInstanceOwner::GetUniqueID(PRUint32
*result
)
2255 NS_ENSURE_ARG_POINTER(result
);
2256 *result
= NS_PTR_TO_INT32(mOwner
);
2261 NS_IMETHODIMP
nsPluginInstanceOwner::GetCode(const char* *result
)
2264 nsPluginTagType tagType
;
2265 NS_ENSURE_SUCCESS(rv
= GetTagType(&tagType
), rv
);
2267 rv
= NS_ERROR_FAILURE
;
2268 if (nsPluginTagType_Object
!= tagType
)
2269 rv
= GetAttribute("CODE", result
);
2271 rv
= GetParameter("CODE", result
);
2276 NS_IMETHODIMP
nsPluginInstanceOwner::GetCodeBase(const char* *result
)
2279 if (NS_FAILED(rv
= GetAttribute("CODEBASE", result
)))
2280 rv
= GetParameter("CODEBASE", result
);
2284 NS_IMETHODIMP
nsPluginInstanceOwner::GetArchive(const char* *result
)
2287 if (NS_FAILED(rv
= GetAttribute("ARCHIVE", result
)))
2288 rv
= GetParameter("ARCHIVE", result
);
2292 NS_IMETHODIMP
nsPluginInstanceOwner::GetName(const char* *result
)
2295 nsPluginTagType tagType
;
2296 NS_ENSURE_SUCCESS(rv
= GetTagType(&tagType
), rv
);
2298 rv
= NS_ERROR_FAILURE
;
2299 if (nsPluginTagType_Object
!= tagType
)
2300 rv
= GetAttribute("NAME", result
);
2302 rv
= GetParameter("NAME", result
);
2307 NS_IMETHODIMP
nsPluginInstanceOwner::GetMayScript(PRBool
*result
)
2309 NS_ENSURE_ARG_POINTER(result
);
2310 nsPluginTagType tagType
;
2311 NS_ENSURE_SUCCESS(GetTagType(&tagType
), NS_ERROR_FAILURE
);
2314 if (nsPluginTagType_Object
== tagType
)
2315 *result
= NS_SUCCEEDED(GetParameter("MAYSCRIPT", &unused
));
2317 *result
= NS_SUCCEEDED(GetAttribute("MAYSCRIPT", &unused
));
2323 // Cache the attributes and/or parameters of our tag into a single set
2324 // of arrays to be compatible with 4.x. The attributes go first,
2325 // followed by a PARAM/null and then any PARAM tags. Also, hold the
2326 // cached array around for the duration of the life of the instance
2327 // because 4.x did. See bug 111008.
2329 nsresult
nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
2331 if (mCachedAttrParamValues
)
2334 NS_PRECONDITION(((mNumCachedAttrs
+ mNumCachedParams
) == 0) &&
2335 !mCachedAttrParamNames
,
2336 "re-cache of attrs/params not implemented! use the DOM "
2337 "node directy instead");
2338 NS_ENSURE_TRUE(mOwner
, NS_ERROR_NULL_POINTER
);
2340 // first, we need to find out how much we need to allocate for our
2341 // arrays count up attributes
2342 mNumCachedAttrs
= 0;
2344 PRUint32 cattrs
= mContent
->GetAttrCount();
2346 if (cattrs
< 0x0000FFFF) {
2347 // unsigned 32 bits to unsigned 16 bits conversion
2348 mNumCachedAttrs
= NS_STATIC_CAST(PRUint16
, cattrs
);
2350 mNumCachedAttrs
= 0xFFFE; // minus one in case we add an extra "src" entry below
2353 // now, we need to find all the PARAM tags that are children of us
2354 // however, be carefull NOT to include any PARAMs that don't have us
2355 // as a direct parent. For nested object (or applet) tags, be sure
2356 // to only round up the param tags that coorespond with THIS
2357 // instance. And also, weed out any bogus tags that may get in the
2358 // way, see bug 39609. Then, with any param tag that meet our
2359 // qualification, temporarly cache them in an nsCOMArray until
2360 // we can figure out what size to make our fixed char* array.
2362 mNumCachedParams
= 0;
2363 nsCOMArray
<nsIDOMElement
> ourParams
;
2365 // use the DOM to get us ALL our dependent PARAM tags, even if not
2367 nsCOMPtr
<nsIDOMElement
> mydomElement
= do_QueryInterface(mContent
);
2368 NS_ENSURE_TRUE(mydomElement
, NS_ERROR_NO_INTERFACE
);
2370 nsCOMPtr
<nsIDOMNodeList
> allParams
;
2372 nsINodeInfo
*ni
= mContent
->NodeInfo();
2374 // Making DOM method calls can cause our frame to go away, which
2376 nsCOMPtr
<nsIPluginInstanceOwner
> kungFuDeathGrip(this);
2378 if (ni
->NamespaceEquals(kNameSpaceID_XHTML
)) {
2379 // For XHTML elements we need to take the namespace URI into
2380 // account when looking for param elements.
2382 NS_NAMED_LITERAL_STRING(xhtml_ns
, "http://www.w3.org/1999/xhtml");
2384 mydomElement
->GetElementsByTagNameNS(xhtml_ns
, NS_LITERAL_STRING("param"),
2385 getter_AddRefs(allParams
));
2387 // If content is not XHTML, it must be HTML, no need to worry
2388 // about namespaces then...
2390 mydomElement
->GetElementsByTagName(NS_LITERAL_STRING("param"),
2391 getter_AddRefs(allParams
));
2395 PRUint32 numAllParams
;
2396 allParams
->GetLength(&numAllParams
);
2397 // loop through every so called dependent PARAM tag to check if it
2400 for (PRUint32 i
= 0; i
< numAllParams
; i
++) {
2401 nsCOMPtr
<nsIDOMNode
> pnode
;
2402 allParams
->Item(i
, getter_AddRefs(pnode
));
2404 nsCOMPtr
<nsIDOMElement
> domelement
= do_QueryInterface(pnode
);
2406 // let's NOT count up param tags that don't have a name attribute
2408 domelement
->GetAttribute(NS_LITERAL_STRING("name"), name
);
2409 if (!name
.IsEmpty()) {
2410 nsCOMPtr
<nsIDOMNode
> parent
;
2411 nsCOMPtr
<nsIDOMHTMLObjectElement
> domobject
;
2412 nsCOMPtr
<nsIDOMHTMLAppletElement
> domapplet
;
2413 pnode
->GetParentNode(getter_AddRefs(parent
));
2414 // walk up the parents of this PARAM until we find an object
2417 while (!(domobject
|| domapplet
) && parent
) {
2418 domobject
= do_QueryInterface(parent
);
2419 domapplet
= do_QueryInterface(parent
);
2420 nsCOMPtr
<nsIDOMNode
> temp
;
2421 parent
->GetParentNode(getter_AddRefs(temp
));
2425 if (domapplet
|| domobject
) {
2431 // now check to see if this PARAM's parent is us. if so,
2432 // cache it for later
2434 nsCOMPtr
<nsIDOMNode
> mydomNode
= do_QueryInterface(mydomElement
);
2435 if (parent
== mydomNode
) {
2436 ourParams
.AppendObject(domelement
);
2444 // We're done with DOM method calls now; make sure we still have a frame.
2445 NS_ENSURE_TRUE(mOwner
, NS_ERROR_OUT_OF_MEMORY
);
2447 PRUint32 cparams
= ourParams
.Count(); // unsigned 32 bits to unsigned 16 bits conversion
2448 if (cparams
< 0x0000FFFF)
2449 mNumCachedParams
= NS_STATIC_CAST(PRUint16
, cparams
);
2451 mNumCachedParams
= 0xFFFF;
2453 // Some plugins were never written to understand the "data" attribute of the OBJECT tag.
2454 // Real and WMP will not play unless they find a "src" attribute, see bug 152334.
2455 // Nav 4.x would simply replace the "data" with "src". Because some plugins correctly
2456 // look for "data", lets instead copy the "data" attribute and add another entry
2457 // to the bottom of the array if there isn't already a "src" specified.
2458 PRInt16 numRealAttrs
= mNumCachedAttrs
;
2460 if (mContent
->Tag() == nsGkAtoms::object
2461 && !mContent
->HasAttr(kNameSpaceID_None
, nsGkAtoms::src
)
2462 && mContent
->GetAttr(kNameSpaceID_None
, nsGkAtoms::data
, data
)) {
2466 // now lets make the arrays
2467 mCachedAttrParamNames
= (char **)PR_Calloc(sizeof(char *) * (mNumCachedAttrs
+ 1 + mNumCachedParams
), 1);
2468 NS_ENSURE_TRUE(mCachedAttrParamNames
, NS_ERROR_OUT_OF_MEMORY
);
2469 mCachedAttrParamValues
= (char **)PR_Calloc(sizeof(char *) * (mNumCachedAttrs
+ 1 + mNumCachedParams
), 1);
2470 NS_ENSURE_TRUE(mCachedAttrParamValues
, NS_ERROR_OUT_OF_MEMORY
);
2472 // let's fill in our attributes
2475 // Some plugins (eg Flash, see bug 234675.) are actually sensitive to the
2476 // attribute order. So we want to make sure we give the plugin the
2477 // attributes in the order they came in in the source, to be compatible with
2478 // other browsers. Now in HTML, the storage order is the reverse of the
2479 // source order, while in XML and XHTML it's the same as the source order
2480 // (see the AddAttributes functions in the HTML and XML content sinks).
2481 PRInt16 start
, end
, increment
;
2482 if (mContent
->IsNodeOfType(nsINode::eHTML
) &&
2483 mContent
->NodeInfo()->NamespaceEquals(kNameSpaceID_None
)) {
2484 // HTML. Walk attributes in reverse order.
2485 start
= numRealAttrs
- 1;
2489 // XHTML or XML. Walk attributes in forward order.
2494 for (PRInt16 index
= start
; index
!= end
; index
+= increment
) {
2495 const nsAttrName
* attrName
= mContent
->GetAttrNameAt(index
);
2496 nsIAtom
* atom
= attrName
->LocalName();
2498 mContent
->GetAttr(attrName
->NamespaceID(), atom
, value
);
2500 atom
->ToString(name
);
2502 FixUpURLS(name
, value
);
2504 mCachedAttrParamNames
[c
] = ToNewUTF8String(name
);
2505 mCachedAttrParamValues
[c
] = ToNewUTF8String(value
);
2509 // if the conditions above were met, copy the "data" attribute to a "src" array entry
2510 if (data
.Length()) {
2511 mCachedAttrParamNames
[mNumCachedAttrs
-1] = ToNewUTF8String(NS_LITERAL_STRING("SRC"));
2512 mCachedAttrParamValues
[mNumCachedAttrs
-1] = ToNewUTF8String(data
);
2515 // add our PARAM and null separator
2516 mCachedAttrParamNames
[mNumCachedAttrs
] = ToNewUTF8String(NS_LITERAL_STRING("PARAM"));
2517 mCachedAttrParamValues
[mNumCachedAttrs
] = nsnull
;
2519 // now fill in the PARAM name/value pairs from the cached DOM nodes
2521 for (PRInt16 idx
= 0; idx
< mNumCachedParams
; idx
++) {
2522 nsIDOMElement
* param
= ourParams
.ObjectAt(idx
);
2526 param
->GetAttribute(NS_LITERAL_STRING("name"), name
); // check for empty done above
2527 param
->GetAttribute(NS_LITERAL_STRING("value"), value
);
2529 FixUpURLS(name
, value
);
2532 * According to the HTML 4.01 spec, at
2533 * http://www.w3.org/TR/html4/types.html#type-cdata
2534 * ''User agents may ignore leading and trailing
2535 * white space in CDATA attribute values (e.g., "
2536 * myval " may be interpreted as "myval"). Authors
2537 * should not declare attribute values with
2538 * leading or trailing white space.''
2539 * However, do not trim consecutive spaces as in bug 122119
2541 name
.Trim(" \n\r\t\b", PR_TRUE
, PR_TRUE
, PR_FALSE
);
2542 value
.Trim(" \n\r\t\b", PR_TRUE
, PR_TRUE
, PR_FALSE
);
2543 mCachedAttrParamNames
[mNumCachedAttrs
+ 1 + c
] = ToNewUTF8String(name
);
2544 mCachedAttrParamValues
[mNumCachedAttrs
+ 1 + c
] = ToNewUTF8String(value
);
2553 // Here's where we forward events to plugins.
2557 static void InitializeEventRecord(EventRecord
* event
)
2559 memset(event
, 0, sizeof(EventRecord
));
2560 ::GetGlobalMouse(&event
->where
);
2561 event
->when
= ::TickCount();
2562 event
->modifiers
= ::GetCurrentKeyModifiers();
2565 NPDrawingModel
nsPluginInstanceOwner::GetDrawingModel()
2567 #ifndef NP_NO_QUICKDRAW
2568 NPDrawingModel drawingModel
= NPDrawingModelQuickDraw
;
2570 NPDrawingModel drawingModel
= NPDrawingModelCoreGraphics
;
2574 return drawingModel
;
2576 mInstance
->GetValue(nsPluginInstanceVariable_DrawingModel
,
2577 (void *)&drawingModel
);
2579 return drawingModel
;
2582 void nsPluginInstanceOwner::GUItoMacEvent(const nsGUIEvent
& anEvent
, EventRecord
* origEvent
, EventRecord
& aMacEvent
)
2584 nsPresContext
* presContext
= mOwner
? mOwner
->PresContext() : nsnull
;
2585 InitializeEventRecord(&aMacEvent
);
2586 switch (anEvent
.message
) {
2587 case NS_FOCUS_EVENT_START
: // this is the same as NS_FOCUS_CONTENT
2588 aMacEvent
.what
= nsPluginEventType_GetFocusEvent
;
2590 nsIContent
* content
= mContent
;
2592 content
->SetFocus(presContext
);
2596 case NS_BLUR_CONTENT
:
2597 aMacEvent
.what
= nsPluginEventType_LoseFocusEvent
;
2599 nsIContent
* content
= mContent
;
2601 content
->RemoveFocus(presContext
);
2606 case NS_MOUSE_ENTER
:
2608 aMacEvent
= *origEvent
;
2609 aMacEvent
.what
= nsPluginEventType_AdjustCursorEvent
;
2616 nsresult
nsPluginInstanceOwner::ScrollPositionWillChange(nsIScrollableView
* aScrollable
, nscoord aX
, nscoord aY
)
2622 nsCOMPtr
<nsIPluginWidget
> pluginWidget
= do_QueryInterface(mWidget
);
2623 if (pluginWidget
&& NS_SUCCEEDED(pluginWidget
->StartDrawPlugin())) {
2624 EventRecord scrollEvent
;
2625 InitializeEventRecord(&scrollEvent
);
2626 scrollEvent
.what
= nsPluginEventType_ScrollingBeginsEvent
;
2628 WindowRef window
= FixUpPluginWindow(ePluginPaintDisable
);
2630 nsPluginEvent pluginEvent
= { &scrollEvent
, nsPluginPlatformWindowRef(window
) };
2631 PRBool eventHandled
= PR_FALSE
;
2632 mInstance
->HandleEvent(&pluginEvent
, &eventHandled
);
2634 pluginWidget
->EndDrawPlugin();
2641 nsresult
nsPluginInstanceOwner::ScrollPositionDidChange(nsIScrollableView
* aScrollable
, nscoord aX
, nscoord aY
)
2645 nsCOMPtr
<nsIPluginWidget
> pluginWidget
= do_QueryInterface(mWidget
);
2646 if (pluginWidget
&& NS_SUCCEEDED(pluginWidget
->StartDrawPlugin())) {
2647 EventRecord scrollEvent
;
2648 InitializeEventRecord(&scrollEvent
);
2649 scrollEvent
.what
= nsPluginEventType_ScrollingEndsEvent
;
2651 WindowRef window
= FixUpPluginWindow(ePluginPaintEnable
);
2653 nsPluginEvent pluginEvent
= { &scrollEvent
, nsPluginPlatformWindowRef(window
) };
2654 PRBool eventHandled
= PR_FALSE
;
2655 mInstance
->HandleEvent(&pluginEvent
, &eventHandled
);
2657 pluginWidget
->EndDrawPlugin();
2660 // FIXME - Only invalidate the newly revealed amount.
2663 mWidget
->Invalidate(PR_TRUE
);
2667 StartTimer(NORMAL_PLUGIN_DELAY
);
2671 /*=============== nsIFocusListener ======================*/
2672 nsresult
nsPluginInstanceOwner::Focus(nsIDOMEvent
* aFocusEvent
)
2674 mContentFocused
= PR_TRUE
;
2675 return DispatchFocusToPlugin(aFocusEvent
);
2678 nsresult
nsPluginInstanceOwner::Blur(nsIDOMEvent
* aFocusEvent
)
2680 mContentFocused
= PR_FALSE
;
2681 return DispatchFocusToPlugin(aFocusEvent
);
2684 nsresult
nsPluginInstanceOwner::DispatchFocusToPlugin(nsIDOMEvent
* aFocusEvent
)
2687 if (!mPluginWindow
|| nsPluginWindowType_Window
== mPluginWindow
->type
) {
2688 // continue only for cases without child window
2689 return aFocusEvent
->PreventDefault(); // consume event
2693 nsCOMPtr
<nsIPrivateDOMEvent
> privateEvent(do_QueryInterface(aFocusEvent
));
2696 privateEvent
->GetInternalNSEvent(&theEvent
);
2698 // we only care about the message in ProcessEvent
2699 nsGUIEvent
focusEvent(NS_IS_TRUSTED_EVENT(theEvent
), theEvent
->message
,
2701 nsEventStatus rv
= ProcessEvent(focusEvent
);
2702 if (nsEventStatus_eConsumeNoDefault
== rv
) {
2703 aFocusEvent
->PreventDefault();
2704 aFocusEvent
->StopPropagation();
2707 else NS_ASSERTION(PR_FALSE
, "nsPluginInstanceOwner::DispatchFocusToPlugin failed, focusEvent null");
2709 else NS_ASSERTION(PR_FALSE
, "nsPluginInstanceOwner::DispatchFocusToPlugin failed, privateEvent null");
2714 /*=============== nsIDOMDragListener ======================*/
2715 nsresult
nsPluginInstanceOwner::DragEnter(nsIDOMEvent
* aMouseEvent
)
2718 // Let the plugin handle drag events.
2719 aMouseEvent
->PreventDefault();
2720 aMouseEvent
->StopPropagation();
2726 nsresult
nsPluginInstanceOwner::DragOver(nsIDOMEvent
* aMouseEvent
)
2729 // Let the plugin handle drag events.
2730 aMouseEvent
->PreventDefault();
2731 aMouseEvent
->StopPropagation();
2737 nsresult
nsPluginInstanceOwner::DragExit(nsIDOMEvent
* aMouseEvent
)
2740 // Let the plugin handle drag events.
2741 aMouseEvent
->PreventDefault();
2742 aMouseEvent
->StopPropagation();
2748 nsresult
nsPluginInstanceOwner::DragDrop(nsIDOMEvent
* aMouseEvent
)
2751 // Let the plugin handle drag events.
2752 aMouseEvent
->PreventDefault();
2753 aMouseEvent
->StopPropagation();
2759 nsresult
nsPluginInstanceOwner::DragGesture(nsIDOMEvent
* aMouseEvent
)
2762 // Let the plugin handle drag events.
2763 aMouseEvent
->PreventDefault();
2764 aMouseEvent
->StopPropagation();
2770 nsresult
nsPluginInstanceOwner::Drag(nsIDOMEvent
* aMouseEvent
)
2773 // Let the plugin handle drag events.
2774 aMouseEvent
->PreventDefault();
2775 aMouseEvent
->StopPropagation();
2781 nsresult
nsPluginInstanceOwner::DragEnd(nsIDOMEvent
* aMouseEvent
)
2784 // Let the plugin handle drag events.
2785 aMouseEvent
->PreventDefault();
2786 aMouseEvent
->StopPropagation();
2794 /*=============== nsIKeyListener ======================*/
2795 nsresult
nsPluginInstanceOwner::KeyDown(nsIDOMEvent
* aKeyEvent
)
2797 return DispatchKeyToPlugin(aKeyEvent
);
2800 nsresult
nsPluginInstanceOwner::KeyUp(nsIDOMEvent
* aKeyEvent
)
2802 return DispatchKeyToPlugin(aKeyEvent
);
2805 nsresult
nsPluginInstanceOwner::KeyPress(nsIDOMEvent
* aKeyEvent
)
2807 #ifdef XP_MACOSX // send KeyPress events only on Mac
2809 // KeyPress events are really synthesized keyDown events.
2810 // Here we check the native message of the event so that
2811 // we won't send the plugin two keyDown events.
2812 nsCOMPtr
<nsIPrivateDOMEvent
> privateEvent(do_QueryInterface(aKeyEvent
));
2815 privateEvent
->GetInternalNSEvent(&theEvent
);
2816 const nsGUIEvent
*guiEvent
= (nsGUIEvent
*)theEvent
;
2817 const EventRecord
*ev
= (EventRecord
*)(guiEvent
->nativeMsg
);
2819 guiEvent
->message
== NS_KEY_PRESS
&&
2821 ev
->what
== keyDown
)
2822 return aKeyEvent
->PreventDefault(); // consume event
2825 // Nasty hack to avoid recursive event dispatching with Java. Java can
2826 // dispatch key events to a TSM handler, which comes back and calls
2827 // [ChildView insertText:] on the cocoa widget, which sends a key
2829 static PRBool sInKeyDispatch
= PR_FALSE
;
2832 return aKeyEvent
->PreventDefault(); // consume event
2834 sInKeyDispatch
= PR_TRUE
;
2835 nsresult rv
= DispatchKeyToPlugin(aKeyEvent
);
2836 sInKeyDispatch
= PR_FALSE
;
2840 // If this event is going to the plugin, we want to kill it.
2841 // Not actually sending keypress to the plugin, since we didn't before.
2842 aKeyEvent
->PreventDefault();
2843 aKeyEvent
->StopPropagation();
2849 nsresult
nsPluginInstanceOwner::DispatchKeyToPlugin(nsIDOMEvent
* aKeyEvent
)
2852 if (!mPluginWindow
|| nsPluginWindowType_Window
== mPluginWindow
->type
)
2853 return aKeyEvent
->PreventDefault(); // consume event
2854 // continue only for cases without child window
2858 nsCOMPtr
<nsIPrivateDOMEvent
> privateEvent(do_QueryInterface(aKeyEvent
));
2860 nsKeyEvent
* keyEvent
= nsnull
;
2861 privateEvent
->GetInternalNSEvent((nsEvent
**)&keyEvent
);
2863 nsEventStatus rv
= ProcessEvent(*keyEvent
);
2864 if (nsEventStatus_eConsumeNoDefault
== rv
) {
2865 aKeyEvent
->PreventDefault();
2866 aKeyEvent
->StopPropagation();
2869 else NS_ASSERTION(PR_FALSE
, "nsPluginInstanceOwner::DispatchKeyToPlugin failed, keyEvent null");
2871 else NS_ASSERTION(PR_FALSE
, "nsPluginInstanceOwner::DispatchKeyToPlugin failed, privateEvent null");
2877 /*=============== nsIMouseMotionListener ======================*/
2880 nsPluginInstanceOwner::MouseMove(nsIDOMEvent
* aMouseEvent
)
2882 #if !defined(XP_MACOSX)
2883 if (!mPluginWindow
|| nsPluginWindowType_Window
== mPluginWindow
->type
)
2884 return aMouseEvent
->PreventDefault(); // consume event
2885 // continue only for cases without child window
2888 // don't send mouse events if we are hiddden
2889 if (!mWidgetVisible
)
2892 nsCOMPtr
<nsIPrivateDOMEvent
> privateEvent(do_QueryInterface(aMouseEvent
));
2894 nsMouseEvent
* mouseEvent
= nsnull
;
2895 privateEvent
->GetInternalNSEvent((nsEvent
**)&mouseEvent
);
2897 nsEventStatus rv
= ProcessEvent(*mouseEvent
);
2898 if (nsEventStatus_eConsumeNoDefault
== rv
) {
2899 return aMouseEvent
->PreventDefault(); // consume event
2902 else NS_ASSERTION(PR_FALSE
, "nsPluginInstanceOwner::MouseMove failed, mouseEvent null");
2904 else NS_ASSERTION(PR_FALSE
, "nsPluginInstanceOwner::MouseMove failed, privateEvent null");
2909 /*=============== nsIMouseListener ======================*/
2912 nsPluginInstanceOwner::MouseDown(nsIDOMEvent
* aMouseEvent
)
2914 #if !defined(XP_MACOSX)
2915 if (!mPluginWindow
|| nsPluginWindowType_Window
== mPluginWindow
->type
)
2916 return aMouseEvent
->PreventDefault(); // consume event
2917 // continue only for cases without child window
2920 // if the plugin is windowless, we need to set focus ourselves
2921 // otherwise, we might not get key events
2922 if (mOwner
&& mPluginWindow
&&
2923 mPluginWindow
->type
== nsPluginWindowType_Drawable
) {
2924 mContent
->SetFocus(mOwner
->PresContext());
2927 nsCOMPtr
<nsIPrivateDOMEvent
> privateEvent(do_QueryInterface(aMouseEvent
));
2929 nsMouseEvent
* mouseEvent
= nsnull
;
2930 privateEvent
->GetInternalNSEvent((nsEvent
**)&mouseEvent
);
2932 nsEventStatus rv
= ProcessEvent(*mouseEvent
);
2933 if (nsEventStatus_eConsumeNoDefault
== rv
) {
2934 return aMouseEvent
->PreventDefault(); // consume event
2937 else NS_ASSERTION(PR_FALSE
, "nsPluginInstanceOwner::MouseDown failed, mouseEvent null");
2939 else NS_ASSERTION(PR_FALSE
, "nsPluginInstanceOwner::MouseDown failed, privateEvent null");
2945 nsPluginInstanceOwner::MouseUp(nsIDOMEvent
* aMouseEvent
)
2947 return DispatchMouseToPlugin(aMouseEvent
);
2951 nsPluginInstanceOwner::MouseClick(nsIDOMEvent
* aMouseEvent
)
2953 return DispatchMouseToPlugin(aMouseEvent
);
2957 nsPluginInstanceOwner::MouseDblClick(nsIDOMEvent
* aMouseEvent
)
2959 return DispatchMouseToPlugin(aMouseEvent
);
2963 nsPluginInstanceOwner::MouseOver(nsIDOMEvent
* aMouseEvent
)
2965 return DispatchMouseToPlugin(aMouseEvent
);
2969 nsPluginInstanceOwner::MouseOut(nsIDOMEvent
* aMouseEvent
)
2971 return DispatchMouseToPlugin(aMouseEvent
);
2974 nsresult
nsPluginInstanceOwner::DispatchMouseToPlugin(nsIDOMEvent
* aMouseEvent
)
2976 #if !defined(XP_MACOSX)
2977 if (!mPluginWindow
|| nsPluginWindowType_Window
== mPluginWindow
->type
)
2978 return aMouseEvent
->PreventDefault(); // consume event
2979 // continue only for cases without child window
2982 // don't send mouse events if we are hiddden
2983 if (!mWidgetVisible
)
2986 nsCOMPtr
<nsIPrivateDOMEvent
> privateEvent(do_QueryInterface(aMouseEvent
));
2988 nsMouseEvent
* mouseEvent
= nsnull
;
2989 privateEvent
->GetInternalNSEvent((nsEvent
**)&mouseEvent
);
2991 nsEventStatus rv
= ProcessEvent(*mouseEvent
);
2992 if (nsEventStatus_eConsumeNoDefault
== rv
) {
2993 aMouseEvent
->PreventDefault();
2994 aMouseEvent
->StopPropagation();
2997 else NS_ASSERTION(PR_FALSE
, "nsPluginInstanceOwner::DispatchMouseToPlugin failed, mouseEvent null");
2999 else NS_ASSERTION(PR_FALSE
, "nsPluginInstanceOwner::DispatchMouseToPlugin failed, privateEvent null");
3005 nsPluginInstanceOwner::HandleEvent(nsIDOMEvent
* aEvent
)
3011 nsEventStatus
nsPluginInstanceOwner::ProcessEvent(const nsGUIEvent
& anEvent
)
3013 // printf("nsGUIEvent.message: %d\n", anEvent.message);
3014 nsEventStatus rv
= nsEventStatus_eIgnore
;
3015 if (!mInstance
) // if mInstance is null, we shouldn't be here
3019 // check for null mWidget
3021 nsCOMPtr
<nsIPluginWidget
> pluginWidget
= do_QueryInterface(mWidget
);
3022 if (pluginWidget
&& NS_SUCCEEDED(pluginWidget
->StartDrawPlugin())) {
3023 EventRecord macEvent
;
3024 EventRecord
* event
= (EventRecord
*)anEvent
.nativeMsg
;
3025 if ((event
== NULL
) || (event
->what
== nullEvent
) ||
3026 (anEvent
.message
== NS_FOCUS_CONTENT
) ||
3027 (anEvent
.message
== NS_BLUR_CONTENT
) ||
3028 (anEvent
.message
== NS_MOUSE_MOVE
) ||
3029 (anEvent
.message
== NS_MOUSE_ENTER
)) {
3030 GUItoMacEvent(anEvent
, event
, macEvent
);
3034 if (anEvent
.message
== NS_FOCUS_CONTENT
) {
3035 // Work around an issue in the Flash plugin, which can cache a pointer
3036 // to a doomed TSM document (one that belongs to a NSTSMInputContext)
3037 // and try to activate it after it has been deleted. See bug 183313.
3038 ::DeactivateTSMDocument(::TSMGetActiveDocument());
3041 PRBool eventHandled
= PR_FALSE
;
3042 WindowRef window
= FixUpPluginWindow(ePluginPaintIgnore
);
3044 nsPluginEvent pluginEvent
= { event
, nsPluginPlatformWindowRef(window
) };
3045 mInstance
->HandleEvent(&pluginEvent
, &eventHandled
);
3048 if (eventHandled
&& !(anEvent
.eventStructType
== NS_MOUSE_EVENT
&&
3049 anEvent
.message
== NS_MOUSE_BUTTON_DOWN
&&
3050 NS_STATIC_CAST(const nsMouseEvent
&, anEvent
).button
==
3051 nsMouseEvent::eLeftButton
&&
3053 rv
= nsEventStatus_eConsumeNoDefault
;
3055 pluginWidget
->EndDrawPlugin();
3061 // this code supports windowless plugins
3062 nsPluginEvent
* pPluginEvent
= (nsPluginEvent
*)anEvent
.nativeMsg
;
3063 // we can get synthetic events from the nsEventStateManager... these
3064 // have no nativeMsg
3065 nsPluginEvent pluginEvent
;
3066 if (!pPluginEvent
) {
3067 switch (anEvent
.message
) {
3068 case NS_FOCUS_CONTENT
:
3069 pluginEvent
.event
= WM_SETFOCUS
;
3070 pluginEvent
.wParam
= 0;
3071 pluginEvent
.lParam
= 0;
3072 pPluginEvent
= &pluginEvent
;
3074 case NS_BLUR_CONTENT
:
3075 pluginEvent
.event
= WM_KILLFOCUS
;
3076 pluginEvent
.wParam
= 0;
3077 pluginEvent
.lParam
= 0;
3078 pPluginEvent
= &pluginEvent
;
3084 PRBool eventHandled
= PR_FALSE
;
3085 mInstance
->HandleEvent(pPluginEvent
, &eventHandled
);
3087 rv
= nsEventStatus_eConsumeNoDefault
;
3095 nsPluginInstanceOwner::Destroy()
3097 // stop the timer explicitly to reduce reference count.
3100 // unregister context menu listener
3101 if (mCXMenuListener
) {
3102 mCXMenuListener
->Destroy(mContent
);
3103 NS_RELEASE(mCXMenuListener
);
3106 nsCOMPtr
<nsIDOMEventTarget
> target(do_QueryInterface(mContent
));
3109 nsCOMPtr
<nsIDOMEventListener
> listener
;
3110 QueryInterface(NS_GET_IID(nsIDOMEventListener
), getter_AddRefs(listener
));
3112 // Unregister focus event listener
3113 mContent
->RemoveEventListenerByIID(listener
, NS_GET_IID(nsIDOMFocusListener
));
3115 // Unregister mouse event listener
3116 mContent
->RemoveEventListenerByIID(listener
, NS_GET_IID(nsIDOMMouseListener
));
3118 // now for the mouse motion listener
3119 mContent
->RemoveEventListenerByIID(listener
, NS_GET_IID(nsIDOMMouseMotionListener
));
3121 // Unregister key event listener;
3122 target
->RemoveEventListener(NS_LITERAL_STRING("keypress"), listener
, PR_TRUE
);
3123 target
->RemoveEventListener(NS_LITERAL_STRING("keydown"), listener
, PR_TRUE
);
3124 target
->RemoveEventListener(NS_LITERAL_STRING("keyup"), listener
, PR_TRUE
);
3126 // Unregister drag event listener;
3127 target
->RemoveEventListener(NS_LITERAL_STRING("dragdrop"), listener
, PR_TRUE
);
3128 target
->RemoveEventListener(NS_LITERAL_STRING("dragover"), listener
, PR_TRUE
);
3129 target
->RemoveEventListener(NS_LITERAL_STRING("dragexit"), listener
, PR_TRUE
);
3130 target
->RemoveEventListener(NS_LITERAL_STRING("dragenter"), listener
, PR_TRUE
);
3131 target
->RemoveEventListener(NS_LITERAL_STRING("draggesture"), listener
, PR_TRUE
);
3134 // Unregister scroll position listener
3135 nsIFrame
* parentWithView
= mOwner
->GetAncestorWithView();
3136 nsIView
* curView
= parentWithView
? parentWithView
->GetView() : nsnull
;
3138 nsIScrollableView
* scrollingView
= curView
->ToScrollableView();
3140 scrollingView
->RemoveScrollPositionListener((nsIScrollPositionListener
*)this);
3142 curView
= curView
->GetParent();
3145 mOwner
= nsnull
; // break relationship between frame and plugin instance owner
3150 // Paints are handled differently, so we just simulate an update event.
3152 void nsPluginInstanceOwner::Paint(const nsRect
& aDirtyRect
, PRUint32 ndc
)
3154 if (!mInstance
|| !mOwner
)
3158 #ifdef DO_DIRTY_INTERSECT // aDirtyRect isn't always correct, see bug 56128
3159 nsPoint
rel(aDirtyRect
.x
, aDirtyRect
.y
);
3161 nsCOMPtr
<nsIWidget
> containerWidget
;
3163 // Convert dirty rect relative coordinates to absolute and also get the containerWidget
3164 ConvertRelativeToWindowAbsolute(mOwner
, rel
, abs
, *getter_AddRefs(containerWidget
));
3166 nsRect absDirtyRect
= nsRect(abs
.x
, abs
.y
, aDirtyRect
.width
, aDirtyRect
.height
);
3168 // Convert to absolute pixel values for the dirty rect
3169 nsRect absDirtyRectInPixels
;
3170 ConvertAppUnitsToPixels(*mOwner
->GetPresContext(), absDirtyRect
,
3171 absDirtyRectInPixels
);
3174 nsCOMPtr
<nsIPluginWidget
> pluginWidget
= do_QueryInterface(mWidget
);
3175 if (pluginWidget
&& NS_SUCCEEDED(pluginWidget
->StartDrawPlugin())) {
3176 WindowRef window
= FixUpPluginWindow(ePluginPaintEnable
);
3178 EventRecord updateEvent
;
3179 InitializeEventRecord(&updateEvent
);
3180 updateEvent
.what
= updateEvt
;
3181 updateEvent
.message
= UInt32(window
);
3183 nsPluginEvent pluginEvent
= { &updateEvent
, nsPluginPlatformWindowRef(window
) };
3184 PRBool eventHandled
= PR_FALSE
;
3185 mInstance
->HandleEvent(&pluginEvent
, &eventHandled
);
3187 pluginWidget
->EndDrawPlugin();
3192 nsPluginWindow
* window
;
3194 nsRect relDirtyRect
= nsRect(aDirtyRect
.x
, aDirtyRect
.y
, aDirtyRect
.width
, aDirtyRect
.height
);
3195 nsRect relDirtyRectInPixels
;
3196 ConvertAppUnitsToPixels(*mOwner
->PresContext(), relDirtyRect
,
3197 relDirtyRectInPixels
);
3199 // we got dirty rectangle in relative window coordinates, but we
3200 // need it in absolute units and in the (left, top, right, bottom) form
3202 drc
.left
= relDirtyRectInPixels
.x
+ window
->x
;
3203 drc
.top
= relDirtyRectInPixels
.y
+ window
->y
;
3204 drc
.right
= drc
.left
+ relDirtyRectInPixels
.width
;
3205 drc
.bottom
= drc
.top
+ relDirtyRectInPixels
.height
;
3207 nsPluginEvent pluginEvent
;
3208 pluginEvent
.event
= WM_PAINT
;
3209 pluginEvent
.wParam
= (uint32
)ndc
;
3210 pluginEvent
.lParam
= (uint32
)&drc
;
3211 PRBool eventHandled
= PR_FALSE
;
3212 mInstance
->HandleEvent(&pluginEvent
, &eventHandled
);
3216 // Here's how we give idle time to plugins.
3218 NS_IMETHODIMP
nsPluginInstanceOwner::Notify(nsITimer
* /* timer */)
3221 // validate the plugin clipping information by syncing the plugin window info to
3222 // reflect the current widget location. This makes sure that everything is updated
3223 // correctly in the event of scrolling in the window.
3225 nsCOMPtr
<nsIPluginWidget
> pluginWidget
= do_QueryInterface(mWidget
);
3226 if (pluginWidget
&& NS_SUCCEEDED(pluginWidget
->StartDrawPlugin())) {
3227 WindowRef window
= FixUpPluginWindow(ePluginPaintIgnore
);
3229 EventRecord idleEvent
;
3230 InitializeEventRecord(&idleEvent
);
3231 idleEvent
.what
= nullEvent
;
3233 // give a bogus 'where' field of our null event when hidden, so Flash
3234 // won't respond to mouse moves in other tabs, see bug 120875
3235 if (!mWidgetVisible
)
3236 idleEvent
.where
.h
= idleEvent
.where
.v
= 20000;
3238 nsPluginEvent pluginEvent
= { &idleEvent
, nsPluginPlatformWindowRef(window
) };
3240 PRBool eventHandled
= PR_FALSE
;
3241 mInstance
->HandleEvent(&pluginEvent
, &eventHandled
);
3244 pluginWidget
->EndDrawPlugin();
3251 void nsPluginInstanceOwner::StartTimer(unsigned int aDelay
)
3256 // start a periodic timer to provide null events to the plugin instance.
3257 if (!mPluginTimer
) {
3258 mPluginTimer
= do_CreateInstance("@mozilla.org/timer;1", &rv
);
3259 if (NS_SUCCEEDED(rv
))
3260 mPluginTimer
->InitWithCallback(this, aDelay
, nsITimer::TYPE_REPEATING_SLACK
);
3265 void nsPluginInstanceOwner::CancelTimer()
3268 mPluginTimer
->Cancel();
3269 mPluginTimer
= nsnull
;
3273 nsresult
nsPluginInstanceOwner::Init(nsPresContext
* aPresContext
,
3274 nsObjectFrame
* aFrame
,
3275 nsIContent
* aContent
)
3278 mContent
= aContent
;
3280 // Some plugins require a specific sequence of shutdown and startup when
3281 // a page is reloaded. Shutdown happens usually when the last instance
3282 // is destroyed. Here we make sure the plugin instance in the old
3283 // document is destroyed before we try to create the new one.
3284 aPresContext
->EnsureVisible(PR_TRUE
);
3286 // register context menu listener
3287 mCXMenuListener
= new nsPluginDOMContextMenuListener();
3288 if (mCXMenuListener
) {
3289 NS_ADDREF(mCXMenuListener
);
3290 mCXMenuListener
->Init(aContent
);
3293 nsCOMPtr
<nsIDOMEventTarget
> target(do_QueryInterface(mContent
));
3296 nsCOMPtr
<nsIDOMEventListener
> listener
;
3297 QueryInterface(NS_GET_IID(nsIDOMEventListener
), getter_AddRefs(listener
));
3299 // Register focus listener
3300 mContent
->AddEventListenerByIID(listener
, NS_GET_IID(nsIDOMFocusListener
));
3302 // Register mouse listener
3303 mContent
->AddEventListenerByIID(listener
, NS_GET_IID(nsIDOMMouseListener
));
3305 // now do the mouse motion listener
3306 mContent
->AddEventListenerByIID(listener
, NS_GET_IID(nsIDOMMouseMotionListener
));
3308 // Register key listener
3309 target
->AddEventListener(NS_LITERAL_STRING("keypress"), listener
, PR_TRUE
);
3310 target
->AddEventListener(NS_LITERAL_STRING("keydown"), listener
, PR_TRUE
);
3311 target
->AddEventListener(NS_LITERAL_STRING("keyup"), listener
, PR_TRUE
);
3313 // Register drag listener
3314 target
->AddEventListener(NS_LITERAL_STRING("dragdrop"), listener
, PR_TRUE
);
3315 target
->AddEventListener(NS_LITERAL_STRING("dragover"), listener
, PR_TRUE
);
3316 target
->AddEventListener(NS_LITERAL_STRING("dragexit"), listener
, PR_TRUE
);
3317 target
->AddEventListener(NS_LITERAL_STRING("dragenter"), listener
, PR_TRUE
);
3318 target
->AddEventListener(NS_LITERAL_STRING("draggesture"), listener
, PR_TRUE
);
3321 // Register scroll position listener
3322 // We need to register a scroll pos listener on every scrollable
3323 // view up to the top
3324 nsIFrame
* parentWithView
= mOwner
->GetAncestorWithView();
3325 nsIView
* curView
= parentWithView
? parentWithView
->GetView() : nsnull
;
3327 nsIScrollableView
* scrollingView
= curView
->ToScrollableView();
3329 scrollingView
->AddScrollPositionListener((nsIScrollPositionListener
*)this);
3331 curView
= curView
->GetParent();
3337 nsPluginPort
* nsPluginInstanceOwner::GetPluginPort()
3339 //!!! Port must be released for windowless plugins on Windows, because it is HDC !!!
3341 nsPluginPort
* result
= NULL
;
3344 if (mPluginWindow
&& mPluginWindow
->type
== nsPluginWindowType_Drawable
)
3345 result
= (nsPluginPort
*) mWidget
->GetNativeData(NS_NATIVE_GRAPHIC
);
3349 if (GetDrawingModel() == NPDrawingModelCoreGraphics
)
3350 result
= (nsPluginPort
*) mWidget
->GetNativeData(NS_NATIVE_PLUGIN_PORT_CG
);
3353 result
= (nsPluginPort
*) mWidget
->GetNativeData(NS_NATIVE_PLUGIN_PORT
);
3358 void nsPluginInstanceOwner::ReleasePluginPort(nsPluginPort
* pluginPort
)
3361 if (mWidget
&& mPluginWindow
&&
3362 mPluginWindow
->type
== nsPluginWindowType_Drawable
) {
3363 mWidget
->FreeNativeData((HDC
)pluginPort
, NS_NATIVE_GRAPHIC
);
3368 NS_IMETHODIMP
nsPluginInstanceOwner::CreateWidget(void)
3370 NS_ENSURE_TRUE(mPluginWindow
, NS_ERROR_NULL_POINTER
);
3373 nsresult rv
= NS_ERROR_FAILURE
;
3376 // Create view if necessary
3378 view
= mOwner
->GetView();
3380 if (!view
|| !mWidget
) {
3381 PRBool windowless
= PR_FALSE
;
3383 mInstance
->GetValue(nsPluginInstanceVariable_WindowlessBool
,
3384 (void *)&windowless
);
3386 // always create widgets in Twips, not pixels
3387 nsPresContext
* context
= mOwner
->PresContext();
3388 rv
= mOwner
->CreateWidget(context
->DevPixelsToAppUnits(mPluginWindow
->width
),
3389 context
->DevPixelsToAppUnits(mPluginWindow
->height
),
3392 view
= mOwner
->GetView();
3395 mWidget
= view
->GetWidget();
3398 if (PR_TRUE
== windowless
) {
3399 mPluginWindow
->type
= nsPluginWindowType_Drawable
;
3401 // this needs to be a HDC according to the spec, but I do
3402 // not see the right way to release it so let's postpone
3403 // passing HDC till paint event when it is really
3404 // needed. Change spec?
3405 mPluginWindow
->window
= nsnull
;
3406 } else if (mWidget
) {
3407 mWidget
->Resize(mPluginWindow
->width
, mPluginWindow
->height
,
3410 // mPluginWindow->type is used in |GetPluginPort| so it must
3411 // be initilized first
3412 mPluginWindow
->type
= nsPluginWindowType_Window
;
3413 mPluginWindow
->window
= GetPluginPort();
3415 // start the idle timer.
3416 StartTimer(NORMAL_PLUGIN_DELAY
);
3418 // tell the plugin window about the widget
3419 mPluginWindow
->SetPluginWidget(mWidget
);
3428 void nsPluginInstanceOwner::SetPluginHost(nsIPluginHost
* aHost
)
3430 mPluginHost
= aHost
;
3433 #if defined(XP_WIN) || (defined(DO_DIRTY_INTERSECT) && defined(XP_MACOSX))
3434 // convert frame coordinates from twips to pixels
3435 static void ConvertAppUnitsToPixels(nsPresContext
& aPresContext
, nsRect
& aTwipsRect
, nsRect
& aPixelRect
)
3437 aPixelRect
.x
= aPresContext
.AppUnitsToDevPixels(aTwipsRect
.x
);
3438 aPixelRect
.y
= aPresContext
.AppUnitsToDevPixels(aTwipsRect
.y
);
3439 aPixelRect
.width
= aPresContext
.AppUnitsToDevPixels(aTwipsRect
.width
);
3440 aPixelRect
.height
= aPresContext
.AppUnitsToDevPixels(aTwipsRect
.height
);
3444 // Mac specific code to fix up the port location and clipping region
3447 #ifdef DO_DIRTY_INTERSECT
3448 // Convert from a frame relative coordinate to a coordinate relative to its
3449 // containing window
3450 static void ConvertRelativeToWindowAbsolute(nsIFrame
* aFrame
,
3453 nsIWidget
*& aContainerWidget
)
3455 // See if this frame has a view
3456 nsIView
*view
= aFrame
->GetView();
3460 // Calculate frames offset from its nearest view
3461 aFrame
->GetOffsetFromView(aAbs
, &view
);
3463 // Store frames offset from its view.
3464 aAbs
= aFrame
->GetPosition();
3467 NS_ASSERTION(view
, "the object frame does not have a view");
3469 // Calculate the view's offset from its nearest widget
3471 aContainerWidget
= view
->GetNearestWidget(&viewOffset
);
3472 NS_IF_ADDREF(aContainerWidget
);
3476 // Add relative coordinate to the absolute coordinate that has been calculated
3479 #endif // DO_DIRTY_INTERSECT
3481 WindowRef
nsPluginInstanceOwner::FixUpPluginWindow(PRInt32 inPaintState
)
3483 if (!mWidget
|| !mPluginWindow
|| !mInstance
)
3486 nsPluginPort
* pluginPort
= GetPluginPort();
3491 NPDrawingModel drawingModel
= GetDrawingModel();
3493 // first, check our view for CSS visibility style
3495 mOwner
->GetView()->GetVisibility() == nsViewVisibility_kShow
;
3497 nsCOMPtr
<nsIPluginWidget
> pluginWidget
= do_QueryInterface(mWidget
);
3499 nsPoint pluginOrigin
;
3501 PRBool widgetVisible
;
3502 pluginWidget
->GetPluginClipRect(widgetClip
, pluginOrigin
, /* out */ widgetVisible
);
3504 // printf("GetPluginClipRect returning visible %d\n", widgetVisible);
3506 isVisible
&= widgetVisible
;
3510 #ifndef NP_NO_QUICKDRAW
3511 // set the port coordinates
3512 if (drawingModel
== NPDrawingModelQuickDraw
) {
3513 mPluginWindow
->x
= -pluginPort
->qdPort
.portx
;
3514 mPluginWindow
->y
= -pluginPort
->qdPort
.porty
;
3516 else if (drawingModel
== NPDrawingModelCoreGraphics
)
3519 // This would be a lot easier if we could use obj-c here,
3520 // but we can't. Since we have only nsIWidget and we can't
3521 // use its native widget (an obj-c object) we have to go
3522 // from the widget's screen coordinates to its window coords
3523 // instead of straight to window coords.
3525 mWidget
->GetBounds(geckoBounds
);
3526 // we need a rect that is the entire *internal* rect, so the
3527 // x and y coords are 0, width is the same.
3530 nsRect geckoScreenCoords
;
3531 mWidget
->WidgetToScreen(geckoBounds
, geckoScreenCoords
);
3534 WindowRef window
= (WindowRef
)pluginPort
->cgPort
.window
;
3535 ::GetWindowBounds(window
, kWindowStructureRgn
, &windowRect
);
3537 mPluginWindow
->x
= geckoScreenCoords
.x
- windowRect
.left
;
3538 mPluginWindow
->y
= geckoScreenCoords
.y
- windowRect
.top
;
3541 nsPluginRect oldClipRect
= mPluginWindow
->clipRect
;
3543 // fix up the clipping region
3544 mPluginWindow
->clipRect
.top
= widgetClip
.y
;
3545 mPluginWindow
->clipRect
.left
= widgetClip
.x
;
3547 mWidgetVisible
= isVisible
;
3549 if (!mWidgetVisible
|| inPaintState
== ePluginPaintDisable
) {
3550 mPluginWindow
->clipRect
.bottom
= mPluginWindow
->clipRect
.top
;
3551 mPluginWindow
->clipRect
.right
= mPluginWindow
->clipRect
.left
;
3552 // pluginPort = nsnull; // don't uncomment this
3554 else if (inPaintState
== ePluginPaintEnable
)
3556 mPluginWindow
->clipRect
.bottom
= mPluginWindow
->clipRect
.top
+ widgetClip
.height
;
3557 mPluginWindow
->clipRect
.right
= mPluginWindow
->clipRect
.left
+ widgetClip
.width
;
3560 // if the clip rect changed, call SetWindow()
3561 // (RealPlayer needs this to draw correctly)
3562 if (mPluginWindow
->clipRect
.left
!= oldClipRect
.left
||
3563 mPluginWindow
->clipRect
.top
!= oldClipRect
.top
||
3564 mPluginWindow
->clipRect
.right
!= oldClipRect
.right
||
3565 mPluginWindow
->clipRect
.bottom
!= oldClipRect
.bottom
)
3567 mInstance
->SetWindow(mPluginWindow
);
3568 // if the clipRect is of size 0, make the null timer fire less often
3570 if (mPluginWindow
->clipRect
.left
== mPluginWindow
->clipRect
.right
||
3571 mPluginWindow
->clipRect
.top
== mPluginWindow
->clipRect
.bottom
) {
3572 StartTimer(HIDDEN_PLUGIN_DELAY
);
3575 StartTimer(NORMAL_PLUGIN_DELAY
);
3579 #ifndef NP_NO_QUICKDRAW
3580 if (drawingModel
== NPDrawingModelQuickDraw
)
3581 return ::GetWindowFromPort(pluginPort
->qdPort
.port
);
3584 if (drawingModel
== NPDrawingModelCoreGraphics
)
3585 return pluginPort
->cgPort
.window
;
3592 // Little helper function to resolve relative URL in
3593 // |value| for certain inputs of |name|
3594 void nsPluginInstanceOwner::FixUpURLS(const nsString
&name
, nsAString
&value
)
3596 if (name
.LowerCaseEqualsLiteral("pluginurl") ||
3597 name
.LowerCaseEqualsLiteral("pluginspage")) {
3599 nsCOMPtr
<nsIURI
> baseURI
= mContent
->GetBaseURI();
3600 nsAutoString newURL
;
3601 NS_MakeAbsoluteURI(newURL
, value
, baseURI
);
3602 if (!newURL
.IsEmpty())