1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 // vim:set ts=2 sts=2 sw=2 et cin:
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef nsPluginInstanceOwner_h_
8 #define nsPluginInstanceOwner_h_
9 
10 #include "mozilla/Attributes.h"
11 #include "mozilla/StaticPtr.h"
12 #include "npapi.h"
13 #include "nsCOMPtr.h"
14 #include "nsIKeyEventInPluginCallback.h"
15 #include "nsIPluginInstanceOwner.h"
16 #include "nsIPrivacyTransitionObserver.h"
17 #include "nsIDOMEventListener.h"
18 #include "nsPluginHost.h"
19 #include "nsPluginNativeWindow.h"
20 #include "nsWeakReference.h"
21 #include "gfxRect.h"
22 
23 #ifdef XP_MACOSX
24 #include "mozilla/gfx/QuartzSupport.h"
25 #include <ApplicationServices/ApplicationServices.h>
26 #endif
27 
28 class nsIInputStream;
29 class nsPluginDOMContextMenuListener;
30 class nsPluginFrame;
31 class nsDisplayListBuilder;
32 
33 #if defined(MOZ_X11)
34 class gfxContext;
35 #endif
36 
37 namespace mozilla {
38 class TextComposition;
39 namespace dom {
40 struct MozPluginParameter;
41 }  // namespace dom
42 namespace widget {
43 class PuppetWidget;
44 }  // namespace widget
45 }  // namespace mozilla
46 
47 using mozilla::widget::PuppetWidget;
48 
49 #ifdef MOZ_X11
50 #include "gfxXlibNativeRenderer.h"
51 #endif
52 
53 class nsPluginInstanceOwner final : public nsIPluginInstanceOwner,
54                                     public nsIDOMEventListener,
55                                     public nsIPrivacyTransitionObserver,
56                                     public nsIKeyEventInPluginCallback,
57                                     public nsSupportsWeakReference {
58  public:
59   typedef mozilla::gfx::DrawTarget DrawTarget;
60 
61   nsPluginInstanceOwner();
62 
63   NS_DECL_ISUPPORTS
64   NS_DECL_NSIPLUGININSTANCEOWNER
65   NS_DECL_NSIPRIVACYTRANSITIONOBSERVER
66 
67   NS_IMETHOD GetURL(const char* aURL, const char* aTarget,
68                     nsIInputStream* aPostStream, void* aHeadersData,
69                     uint32_t aHeadersDataLen,
70                     bool aDoCheckLoadURIChecks) override;
71 
72   NPBool ConvertPoint(double sourceX, double sourceY,
73                       NPCoordinateSpace sourceSpace, double* destX,
74                       double* destY, NPCoordinateSpace destSpace) override;
75 
76   NPError InitAsyncSurface(NPSize* size, NPImageFormat format, void* initData,
77                            NPAsyncSurface* surface) override;
78   NPError FinalizeAsyncSurface(NPAsyncSurface* surface) override;
79   void SetCurrentAsyncSurface(NPAsyncSurface* surface,
80                               NPRect* changed) override;
81 
82   /**
83    * Get the type of the HTML tag that was used ot instantiate this
84    * plugin.  Currently supported tags are EMBED or OBJECT.
85    */
86   NS_IMETHOD GetTagType(nsPluginTagType* aResult);
87 
88   void GetParameters(nsTArray<mozilla::dom::MozPluginParameter>& parameters);
89   void GetAttributes(nsTArray<mozilla::dom::MozPluginParameter>& attributes);
90 
91   /**
92    * Returns the DOM element corresponding to the tag which references
93    * this plugin in the document.
94    *
95    * @param aDOMElement - resulting DOM element
96    * @result - NS_OK if this operation was successful
97    */
98   NS_IMETHOD GetDOMElement(nsIDOMElement** aResult);
99 
100   // nsIDOMEventListener interfaces
101   NS_DECL_NSIDOMEVENTLISTENER
102 
103   nsresult ProcessMouseDown(nsIDOMEvent* aKeyEvent);
104   nsresult ProcessKeyPress(nsIDOMEvent* aKeyEvent);
105   nsresult Destroy();
106 
107 #ifdef XP_WIN
108   void Paint(const RECT& aDirty, HDC aDC);
109 #elif defined(XP_MACOSX)
110   void Paint(const gfxRect& aDirtyRect, CGContextRef cgContext);
111   void RenderCoreAnimation(CGContextRef aCGContext, int aWidth, int aHeight);
112   void DoCocoaEventDrawRect(const gfxRect& aDrawRect, CGContextRef cgContext);
113 #elif defined(MOZ_X11)
114   void Paint(gfxContext* aContext, const gfxRect& aFrameRect,
115              const gfxRect& aDirtyRect);
116 #endif
117 
118   // locals
119 
120   nsresult Init(nsIContent* aContent);
121 
122   void* GetPluginPort();
123   void ReleasePluginPort(void* pluginPort);
124 
125   nsEventStatus ProcessEvent(const mozilla::WidgetGUIEvent& anEvent);
126 
127   static void GeneratePluginEvent(
128       const mozilla::WidgetCompositionEvent* aSrcCompositionEvent,
129       mozilla::WidgetCompositionEvent* aDistCompositionEvent);
130 
131 #if defined(XP_WIN)
132   void SetWidgetWindowAsParent(HWND aWindowToAdopt);
133   nsresult SetNetscapeWindowAsParent(HWND aWindowToAdopt);
134 #endif
135 
136 #ifdef XP_MACOSX
137   enum {ePluginPaintEnable, ePluginPaintDisable};
138 
139   void WindowFocusMayHaveChanged();
140 
141   bool WindowIsActive();
142   void SendWindowFocusChanged(bool aIsActive);
143   NPDrawingModel GetDrawingModel();
144   bool IsRemoteDrawingCoreAnimation();
145 
146   NPEventModel GetEventModel();
147   static void CARefresh(nsITimer* aTimer, void* aClosure);
148   void AddToCARefreshTimer();
149   void RemoveFromCARefreshTimer();
150   // This calls into the plugin (NPP_SetWindow) and can run script.
151   void FixUpPluginWindow(int32_t inPaintState);
152   void HidePluginWindow();
153   // Set plugin port info in the plugin (in the 'window' member of the
154   // NPWindow structure passed to the plugin by SetWindow()).
155   void SetPluginPort();
156 #else   // XP_MACOSX
157   void UpdateWindowPositionAndClipRect(bool aSetWindow);
158   void UpdateWindowVisibility(bool aVisible);
159 #endif  // XP_MACOSX
160 
161   void ResolutionMayHaveChanged();
162 #if defined(XP_MACOSX) || defined(XP_WIN)
163   nsresult ContentsScaleFactorChanged(double aContentsScaleFactor);
164 #endif
165 
166   void UpdateDocumentActiveState(bool aIsActive);
167 
168   void SetFrame(nsPluginFrame* aFrame);
169   nsPluginFrame* GetFrame();
170 
GetLastEventloopNestingLevel()171   uint32_t GetLastEventloopNestingLevel() const {
172     return mLastEventloopNestingLevel;
173   }
174 
175   static uint32_t GetEventloopNestingLevel();
176 
ConsiderNewEventloopNestingLevel()177   void ConsiderNewEventloopNestingLevel() {
178     uint32_t currentLevel = GetEventloopNestingLevel();
179 
180     if (currentLevel < mLastEventloopNestingLevel) {
181       mLastEventloopNestingLevel = currentLevel;
182     }
183   }
184 
GetPluginName()185   const char* GetPluginName() {
186     if (mInstance && mPluginHost) {
187       const char* name = nullptr;
188       if (NS_SUCCEEDED(mPluginHost->GetPluginName(mInstance, &name)) && name)
189         return name;
190     }
191     return "";
192   }
193 
194 #ifdef MOZ_X11
GetPluginDescription(nsACString & aDescription)195   void GetPluginDescription(nsACString& aDescription) {
196     aDescription.Truncate();
197     if (mInstance && mPluginHost) {
198       nsCOMPtr<nsIPluginTag> pluginTag;
199 
200       mPluginHost->GetPluginTagForInstance(mInstance,
201                                            getter_AddRefs(pluginTag));
202       if (pluginTag) {
203         pluginTag->GetDescription(aDescription);
204       }
205     }
206   }
207 #endif
208 
SendNativeEvents()209   bool SendNativeEvents() {
210 #ifdef XP_WIN
211     // XXX we should remove the plugin name check
212     return mPluginWindow->type == NPWindowTypeDrawable &&
213            (MatchPluginName("Shockwave Flash") ||
214             MatchPluginName("Test Plug-in"));
215 #elif defined(MOZ_X11) || defined(XP_MACOSX)
216     return true;
217 #else
218     return false;
219 #endif
220   }
221 
MatchPluginName(const char * aPluginName)222   bool MatchPluginName(const char* aPluginName) {
223     return strncmp(GetPluginName(), aPluginName, strlen(aPluginName)) == 0;
224   }
225 
226   void NotifyPaintWaiter(nsDisplayListBuilder* aBuilder);
227 
228   // Returns the image container that has our currently displayed image.
229   already_AddRefed<mozilla::layers::ImageContainer> GetImageContainer();
230   // Returns true if this is windowed plugin that can return static captures
231   // for scroll operations.
232   bool NeedsScrollImageLayer();
233 
234   void DidComposite();
235 
236   /**
237    * Returns the bounds of the current async-rendered surface. This can only
238    * change in response to messages received by the event loop (i.e. not during
239    * painting).
240    */
241   nsIntSize GetCurrentImageSize();
242 
243   // Methods to update the background image we send to async plugins.
244   // The eventual target of these operations is PluginInstanceParent,
245   // but it takes several hops to get there.
246   void SetBackgroundUnknown();
247   already_AddRefed<DrawTarget> BeginUpdateBackground(const nsIntRect& aRect);
248   void EndUpdateBackground(const nsIntRect& aRect);
249 
250   bool UseAsyncRendering();
251 
252   already_AddRefed<nsIURI> GetBaseURI() const;
253 
254   bool GetCompositionString(uint32_t aIndex, nsTArray<uint8_t>* aString,
255                             int32_t* aLength);
256   bool SetCandidateWindow(
257       const mozilla::widget::CandidateWindowPosition& aPosition);
258   bool RequestCommitOrCancel(bool aCommitted);
259   bool EnableIME(bool aEnable);
260 
261   // See nsIKeyEventInPluginCallback
262   virtual void HandledWindowedPluginKeyEvent(
263       const mozilla::NativeEventData& aKeyEventData, bool aIsConsumed) override;
264 
265   /**
266    * OnWindowedPluginKeyEvent() is called when the plugin process receives
267    * native key event directly.
268    *
269    * @param aNativeKeyData      The key event which was received by the
270    *                            plugin process directly.
271    */
272   void OnWindowedPluginKeyEvent(const mozilla::NativeEventData& aNativeKeyData);
273 
274   void GetCSSZoomFactor(float* result);
275 
276  private:
277   virtual ~nsPluginInstanceOwner();
278 
279   // return FALSE if LayerSurface dirty (newly created and don't have valid
280   // plugin content yet)
IsUpToDate()281   bool IsUpToDate() {
282     nsIntSize size;
283     return NS_SUCCEEDED(mInstance->GetImageSize(&size)) &&
284            size == nsIntSize(mPluginWindow->width, mPluginWindow->height);
285   }
286 
287 #if defined(XP_WIN)
288   nsIWidget* GetContainingWidgetIfOffset();
289   already_AddRefed<mozilla::TextComposition> GetTextComposition();
290   void HandleNoConsumedCompositionMessage(
291       mozilla::WidgetCompositionEvent* aCompositionEvent,
292       const NPEvent* aPluginEvent);
293   bool mGotCompositionData;
294   bool mSentStartComposition;
295   bool mPluginDidNotHandleIMEComposition;
296 #endif
297 
298   nsPluginNativeWindow* mPluginWindow;
299   RefPtr<nsNPAPIPluginInstance> mInstance;
300   nsPluginFrame* mPluginFrame;
301   nsWeakPtr mContent;  // WEAK, content owns us
302   nsCString mDocumentBase;
303   bool mWidgetCreationComplete;
304   nsCOMPtr<nsIWidget> mWidget;
305   RefPtr<nsPluginHost> mPluginHost;
306 
307 #ifdef XP_MACOSX
308   static mozilla::StaticRefPtr<nsITimer> sCATimer;
309   static nsTArray<nsPluginInstanceOwner*>* sCARefreshListeners;
310   bool mSentInitialTopLevelWindowEvent;
311   bool mLastWindowIsActive;
312   bool mLastContentFocused;
313   // True if, the next time the window is activated, we should blur ourselves.
314   bool mShouldBlurOnActivate;
315 #endif
316   double mLastScaleFactor;
317   double mLastCSSZoomFactor;
318   // Initially, the event loop nesting level we were created on, it's updated
319   // if we detect the appshell is on a lower level as long as we're not stopped.
320   // We delay DoStopPlugin() until the appshell reaches this level or lower.
321   uint32_t mLastEventloopNestingLevel;
322   bool mContentFocused;
323   bool mWidgetVisible;  // used on Mac to store our widget's visible state
324 #ifdef MOZ_X11
325   // Used with windowless plugins only, initialized in CreateWidget().
326   bool mFlash10Quirks;
327 #endif
328   bool mPluginWindowVisible;
329   bool mPluginDocumentActiveState;
330 
331 #ifdef XP_MACOSX
332   NPEventModel mEventModel;
333   // This is a hack! UseAsyncRendering() can incorrectly return false
334   // when we don't have an object frame (possible as of bug 90268).
335   // We hack around this by always returning true if we've ever
336   // returned true.
337   bool mUseAsyncRendering;
338 #endif
339 
340   // pointer to wrapper for nsIDOMContextMenuListener
341   RefPtr<nsPluginDOMContextMenuListener> mCXMenuListener;
342 
343   nsresult DispatchKeyToPlugin(nsIDOMEvent* aKeyEvent);
344   nsresult DispatchMouseToPlugin(nsIDOMEvent* aMouseEvent,
345                                  bool aAllowPropagate = false);
346   nsresult DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent);
347   nsresult DispatchCompositionToPlugin(nsIDOMEvent* aEvent);
348 
349 #ifdef XP_WIN
350   void CallDefaultProc(const mozilla::WidgetGUIEvent* aEvent);
351 #endif
352 
353 #ifdef XP_MACOSX
354   static NPBool ConvertPointPuppet(PuppetWidget* widget,
355                                    nsPluginFrame* pluginFrame, double sourceX,
356                                    double sourceY,
357                                    NPCoordinateSpace sourceSpace, double* destX,
358                                    double* destY, NPCoordinateSpace destSpace);
359   static NPBool ConvertPointNoPuppet(nsIWidget* widget,
360                                      nsPluginFrame* pluginFrame, double sourceX,
361                                      double sourceY,
362                                      NPCoordinateSpace sourceSpace,
363                                      double* destX, double* destY,
364                                      NPCoordinateSpace destSpace);
365   void PerformDelayedBlurs();
366 #endif  // XP_MACOSX
367 
368   int mLastMouseDownButtonType;
369 
370 #ifdef MOZ_X11
371   class Renderer : public gfxXlibNativeRenderer {
372    public:
Renderer(NPWindow * aWindow,nsPluginInstanceOwner * aInstanceOwner,const nsIntSize & aPluginSize,const nsIntRect & aDirtyRect)373     Renderer(NPWindow* aWindow, nsPluginInstanceOwner* aInstanceOwner,
374              const nsIntSize& aPluginSize, const nsIntRect& aDirtyRect)
375         : mWindow(aWindow),
376           mInstanceOwner(aInstanceOwner),
377           mPluginSize(aPluginSize),
378           mDirtyRect(aDirtyRect) {}
379     virtual nsresult DrawWithXlib(cairo_surface_t* surface, nsIntPoint offset,
380                                   nsIntRect* clipRects,
381                                   uint32_t numClipRects) override;
382 
383    private:
384     NPWindow* mWindow;
385     nsPluginInstanceOwner* mInstanceOwner;
386     const nsIntSize& mPluginSize;
387     const nsIntRect& mDirtyRect;
388   };
389 #endif
390 
391   bool mWaitingForPaint;
392 };
393 
394 #endif  // nsPluginInstanceOwner_h_
395