1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #ifndef nsNPAPIPluginInstance_h_
7 #define nsNPAPIPluginInstance_h_
8 
9 #include "nsSize.h"
10 #include "nsCOMPtr.h"
11 #include "nsTArray.h"
12 #include "nsPIDOMWindow.h"
13 #include "nsITimer.h"
14 #include "nsIPluginInstanceOwner.h"
15 #include "nsIURI.h"
16 #include "nsIChannel.h"
17 #include "nsHashKeys.h"
18 #include <prinrval.h>
19 #include "js/TypeDecls.h"
20 #include "nsIAudioChannelAgent.h"
21 
22 #include "mozilla/EventForwards.h"
23 #include "mozilla/TimeStamp.h"
24 #include "mozilla/PluginLibrary.h"
25 #include "mozilla/RefPtr.h"
26 #include "mozilla/WeakPtr.h"
27 
28 class nsPluginStreamListenerPeer;   // browser-initiated stream class
29 class nsNPAPIPluginStreamListener;  // plugin-initiated stream class
30 class nsIPluginInstanceOwner;
31 class nsIOutputStream;
32 class nsPluginInstanceOwner;
33 
34 #if defined(OS_WIN)
35 const NPDrawingModel kDefaultDrawingModel = NPDrawingModelSyncWin;
36 #elif defined(MOZ_X11)
37 const NPDrawingModel kDefaultDrawingModel = NPDrawingModelSyncX;
38 #elif defined(XP_MACOSX)
39 #ifndef NP_NO_QUICKDRAW
40 const NPDrawingModel kDefaultDrawingModel =
41     NPDrawingModelQuickDraw;  // Not supported
42 #else
43 const NPDrawingModel kDefaultDrawingModel = NPDrawingModelCoreGraphics;
44 #endif
45 #else
46 const NPDrawingModel kDefaultDrawingModel = static_cast<NPDrawingModel>(0);
47 #endif
48 
49 /**
50  * Used to indicate whether it's OK to reenter Gecko and repaint, flush frames,
51  * run scripts, etc, during this plugin call.
52  * When NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO is set, we try to avoid dangerous
53  * Gecko activities when the plugin spins a nested event loop, on a best-effort
54  * basis.
55  */
56 enum NSPluginCallReentry {
57   NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO,
58   NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO
59 };
60 
61 class nsNPAPITimer {
62  public:
63   NPP npp;
64   uint32_t id;
65   nsCOMPtr<nsITimer> timer;
66   void (*callback)(NPP npp, uint32_t timerID);
67   bool inCallback;
68   bool needUnschedule;
69 };
70 
71 class nsNPAPIPluginInstance final
72     : public nsIAudioChannelAgentCallback,
73       public mozilla::SupportsWeakPtr<nsNPAPIPluginInstance> {
74  private:
75   typedef mozilla::PluginLibrary PluginLibrary;
76 
77  public:
78   typedef mozilla::gfx::DrawTarget DrawTarget;
79 
80   MOZ_DECLARE_WEAKREFERENCE_TYPENAME(nsNPAPIPluginInstance)
81   NS_DECL_THREADSAFE_ISUPPORTS
82   NS_DECL_NSIAUDIOCHANNELAGENTCALLBACK
83 
84   nsresult Initialize(nsNPAPIPlugin* aPlugin, nsPluginInstanceOwner* aOwner,
85                       const nsACString& aMIMEType);
86   nsresult Start();
87   nsresult Stop();
88   nsresult SetWindow(NPWindow* window);
89   nsresult NewStreamFromPlugin(const char* type, const char* target,
90                                nsIOutputStream** result);
91   nsresult Print(NPPrint* platformPrint);
92   nsresult HandleEvent(void* event, int16_t* result,
93                        NSPluginCallReentry aSafeToReenterGecko =
94                            NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
95   nsresult GetValueFromPlugin(NPPVariable variable, void* value);
96   nsresult GetDrawingModel(int32_t* aModel);
97   nsresult IsRemoteDrawingCoreAnimation(bool* aDrawing);
98   nsresult ContentsScaleFactorChanged(double aContentsScaleFactor);
99   nsresult CSSZoomFactorChanged(float aCSSZoomFactor);
100   nsresult GetJSObject(JSContext* cx, JSObject** outObject);
101   bool ShouldCache();
102   nsresult IsWindowless(bool* isWindowless);
103   nsresult AsyncSetWindow(NPWindow* window);
104   nsresult GetImageContainer(mozilla::layers::ImageContainer** aContainer);
105   nsresult GetImageSize(nsIntSize* aSize);
106   nsresult NotifyPainted(void);
107   nsresult GetIsOOP(bool* aIsOOP);
108   nsresult SetBackgroundUnknown();
109   nsresult BeginUpdateBackground(nsIntRect* aRect, DrawTarget** aContext);
110   nsresult EndUpdateBackground(nsIntRect* aRect);
111   nsresult IsTransparent(bool* isTransparent);
112   nsresult GetFormValue(nsAString& aValue);
113   nsresult PushPopupsEnabledState(bool aEnabled);
114   nsresult PopPopupsEnabledState();
115   nsresult GetPluginAPIVersion(uint16_t* version);
116   nsresult InvalidateRect(NPRect* invalidRect);
117   nsresult InvalidateRegion(NPRegion invalidRegion);
118   nsresult GetMIMEType(const char** result);
119 #if defined(XP_WIN)
120   nsresult GetScrollCaptureContainer(
121       mozilla::layers::ImageContainer** aContainer);
122 #endif
123   nsresult HandledWindowedPluginKeyEvent(
124       const mozilla::NativeEventData& aKeyEventData, bool aIsConsumed);
125   nsPluginInstanceOwner* GetOwner();
126   void SetOwner(nsPluginInstanceOwner* aOwner);
127   void DidComposite();
128 
HasAudioChannelAgent()129   bool HasAudioChannelAgent() const { return !!mAudioChannelAgent; }
130 
131   void NotifyStartedPlaying();
132   void NotifyStoppedPlaying();
133 
134   nsresult SetMuted(bool aIsMuted);
135 
136   nsNPAPIPlugin* GetPlugin();
137 
138   nsresult GetNPP(NPP* aNPP);
139 
140   NPError SetWindowless(bool aWindowless);
141 
142   NPError SetTransparent(bool aTransparent);
143 
144   NPError SetWantsAllNetworkStreams(bool aWantsAllNetworkStreams);
145 
146   NPError SetUsesDOMForCursor(bool aUsesDOMForCursor);
147   bool UsesDOMForCursor();
148 
149   void SetDrawingModel(NPDrawingModel aModel);
150   void RedrawPlugin();
151 #ifdef XP_MACOSX
152   void SetEventModel(NPEventModel aModel);
153 
GetCurrentEvent()154   void* GetCurrentEvent() { return mCurrentPluginEvent; }
155 #endif
156 
157   nsresult NewStreamListener(const char* aURL, void* notifyData,
158                              nsNPAPIPluginStreamListener** listener);
159 
160   nsNPAPIPluginInstance();
161 
162   // To be called when an instance becomes orphaned, when
163   // it's plugin is no longer guaranteed to be around.
164   void Destroy();
165 
166   // Indicates whether the plugin is running normally.
IsRunning()167   bool IsRunning() { return RUNNING == mRunning; }
HasStartedDestroying()168   bool HasStartedDestroying() { return mRunning >= DESTROYING; }
169 
170   // Indicates whether the plugin is running normally or being shut down
CanFireNotifications()171   bool CanFireNotifications() {
172     return mRunning == RUNNING || mRunning == DESTROYING;
173   }
174 
175   // return is only valid when the plugin is not running
176   mozilla::TimeStamp StopTime();
177 
178   // cache this NPAPI plugin
179   void SetCached(bool aCache);
180 
181   already_AddRefed<nsPIDOMWindowOuter> GetDOMWindow();
182 
183   nsresult PrivateModeStateChanged(bool aEnabled);
184 
185   nsresult IsPrivateBrowsing(bool* aEnabled);
186 
187   nsresult GetDOMElement(nsIDOMElement** result);
188 
189   nsNPAPITimer* TimerWithID(uint32_t id, uint32_t* index);
190   uint32_t ScheduleTimer(uint32_t interval, NPBool repeat,
191                          void (*timerFunc)(NPP npp, uint32_t timerID));
192   void UnscheduleTimer(uint32_t timerID);
193   NPBool ConvertPoint(double sourceX, double sourceY,
194                       NPCoordinateSpace sourceSpace, double* destX,
195                       double* destY, NPCoordinateSpace destSpace);
196 
197   nsTArray<nsNPAPIPluginStreamListener*>* StreamListeners();
198 
199   nsTArray<nsPluginStreamListenerPeer*>* FileCachedStreamListeners();
200 
201   nsresult AsyncSetWindow(NPWindow& window);
202 
203   void URLRedirectResponse(void* notifyData, NPBool allow);
204 
205   NPError InitAsyncSurface(NPSize* size, NPImageFormat format, void* initData,
206                            NPAsyncSurface* surface);
207   NPError FinalizeAsyncSurface(NPAsyncSurface* surface);
208   void SetCurrentAsyncSurface(NPAsyncSurface* surface, NPRect* changed);
209 
210   // Returns the contents scale factor of the screen the plugin is drawn on.
211   double GetContentsScaleFactor();
212 
213   // Returns the css zoom factor of the document the plugin is drawn on.
214   float GetCSSZoomFactor();
215 
216   nsresult GetRunID(uint32_t* aRunID);
217 
InPluginCallUnsafeForReentry()218   static bool InPluginCallUnsafeForReentry() {
219     return gInUnsafePluginCalls > 0;
220   }
BeginPluginCall(NSPluginCallReentry aReentryState)221   static void BeginPluginCall(NSPluginCallReentry aReentryState) {
222     if (aReentryState == NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO) {
223       ++gInUnsafePluginCalls;
224     }
225   }
EndPluginCall(NSPluginCallReentry aReentryState)226   static void EndPluginCall(NSPluginCallReentry aReentryState) {
227     if (aReentryState == NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO) {
228       NS_ASSERTION(gInUnsafePluginCalls > 0, "Must be in plugin call");
229       --gInUnsafePluginCalls;
230     }
231   }
232 
233  protected:
234   virtual ~nsNPAPIPluginInstance();
235 
236   nsresult GetTagType(nsPluginTagType* result);
237 
238   nsresult CreateAudioChannelAgentIfNeeded();
239 
240   // The structure used to communicate between the plugin instance and
241   // the browser.
242   NPP_t mNPP;
243 
244   NPDrawingModel mDrawingModel;
245 
246   enum { NOT_STARTED, RUNNING, DESTROYING, DESTROYED } mRunning;
247 
248   // these are used to store the windowless properties
249   // which the browser will later query
250   bool mWindowless;
251   bool mTransparent;
252   bool mCached;
253   bool mUsesDOMForCursor;
254 
255  public:
256   // True while creating the plugin, or calling NPP_SetWindow() on it.
257   bool mInPluginInitCall;
258 
259  private:
260   RefPtr<nsNPAPIPlugin> mPlugin;
261 
262   nsTArray<nsNPAPIPluginStreamListener*> mStreamListeners;
263 
264   nsTArray<nsPluginStreamListenerPeer*> mFileCachedStreamListeners;
265 
266   nsTArray<PopupControlState> mPopupStates;
267 
268   char* mMIMEType;
269 
270   // Weak pointer to the owner. The owner nulls this out (by calling
271   // InvalidateOwner()) when it's no longer our owner.
272   nsPluginInstanceOwner* mOwner;
273 
274   nsTArray<nsNPAPITimer*> mTimers;
275 
276 #ifdef XP_MACOSX
277   // non-null during a HandleEvent call
278   void* mCurrentPluginEvent;
279 #endif
280 
281   // Timestamp for the last time this plugin was stopped.
282   // This is only valid when the plugin is actually stopped!
283   mozilla::TimeStamp mStopTime;
284 
285   // is this instance Java and affected by bug 750480?
286   bool mHaveJavaC2PJSObjectQuirk;
287 
288   static uint32_t gInUnsafePluginCalls;
289 
290   // The arrays can only be released when the plugin instance is destroyed,
291   // because the plugin, in in-process mode, might keep a reference to them.
292   uint32_t mCachedParamLength;
293   char** mCachedParamNames;
294   char** mCachedParamValues;
295 
296   nsCOMPtr<nsIAudioChannelAgent> mAudioChannelAgent;
297   bool mMuted;
298 };
299 
300 void NS_NotifyBeginPluginCall(NSPluginCallReentry aReentryState);
301 void NS_NotifyPluginCall(NSPluginCallReentry aReentryState);
302 
303 #define NS_TRY_SAFE_CALL_RETURN(ret, fun, pluginInst, pluginCallReentry) \
304   PR_BEGIN_MACRO                                                         \
305   NS_NotifyBeginPluginCall(pluginCallReentry);                           \
306   ret = fun;                                                             \
307   NS_NotifyPluginCall(pluginCallReentry);                                \
308   PR_END_MACRO
309 
310 #define NS_TRY_SAFE_CALL_VOID(fun, pluginInst, pluginCallReentry) \
311   PR_BEGIN_MACRO                                                  \
312   NS_NotifyBeginPluginCall(pluginCallReentry);                    \
313   fun;                                                            \
314   NS_NotifyPluginCall(pluginCallReentry);                         \
315   PR_END_MACRO
316 
317 #endif  // nsNPAPIPluginInstance_h_
318