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