1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * plugin.h: MoonLight browser plugin.
6 * Moonlight List (moonlight-list@lists.ximian.com)
8 * Copyright 2007 Novell, Inc. (http://www.novell.com)
10 * See the LICENSE file included with the distribution for details.
17 #include "moonlight.h"
20 #include <mono/jit/jit.h>
21 #include <mono/metadata/appdomain.h>
22 #include <mono/metadata/assembly.h>
23 #include <mono/metadata/debug-helpers.h>
25 /* because this header sucks */
26 #include <mono/metadata/mono-debug.h>
28 #include <mono/metadata/mono-config.h>
31 class MoonlightScriptControlObject
;
32 class PluginXamlLoader
;
39 char *NPN_strdup (const char *val
);
47 PluginInstance (NPMIMEType pluginType
, NPP instance
, guint16 mode
);
52 void Initialize (int argc
, char *const argn
[], char *const argv
[]);
55 // Mozilla plugin related methods
56 NPError
GetValue (NPPVariable variable
, void *result
);
57 NPError
SetValue (NPNVariable variable
, void *value
);
58 NPError
SetWindow (NPWindow
*window
);
59 NPError
NewStream (NPMIMEType type
, NPStream
*stream
, NPBool seekable
, guint16
*stype
);
60 NPError
DestroyStream (NPStream
*stream
, NPError reason
);
61 void StreamAsFile (NPStream
*stream
, const char *fname
);
62 gint32
WriteReady (NPStream
*stream
);
63 gint32
Write (NPStream
*stream
, gint32 offset
, gint32 len
, void *buffer
);
64 void UrlNotify (const char *url
, NPReason reason
, void *notifyData
);
67 void Print (NPPrint
*platformPrint
);
68 int16_t EventHandle (void *event
);
69 /* @GenerateCBinding,GeneratePInvoke */
70 void ReportException (char *msg
, char *details
, /* @MarshalAs=string[] */ char **stack_trace
, int num_frames
);
71 /* @GenerateCBinding,GeneratePInvoke */
72 void *Evaluate (const char *code
);
76 /* @GenerateCBinding,GeneratePInvoke */
77 void *GetBrowserHost () { return GetHost (); } // same as GetHost, just without bleeding NPObjects into the cbindings
79 void AddWrappedObject (EventObject
*obj
, NPObject
*wrapper
);
80 void RemoveWrappedObject (EventObject
*obj
);
81 NPObject
*LookupWrappedObject (EventObject
*obj
);
83 void AddCleanupPointer (gpointer p
);
84 void RemoveCleanupPointer (gpointer p
);
86 // [Obselete (this is obsolete in SL b2)]
87 guint32
TimeoutAdd (gint32 interval
, GSourceFunc callback
, gpointer data
);
88 // [Obselete (this is obsolete in SL b2)]
89 void TimeoutStop (guint32 source_id
);
93 // Property getters and setters
94 /* @GenerateCBinding,GeneratePInvoke */
95 const char *GetInitParams () { return this->initParams
; }
96 void SetInitParams (const char *value
);
97 /* @GenerateCBinding,GeneratePInvoke */
98 const char *GetSource () { return this->source
; }
99 /* @GenerateCBinding,GeneratePInvoke */
100 const char *GetSourceOriginal () { return this->source_original
; }
101 /* @GenerateCBinding,GeneratePInvoke */
102 const char *GetSourceLocation () { return this->source_location
; }
103 /* @GenerateCBinding,GeneratePInvoke */
104 const char *GetSourceLocationOriginal () { return this->source_location_original
; }
105 char *GetId () { return this->id
; }
107 void SetSource (const char *value
);
109 char *GetBackground ();
110 bool SetBackground (const char *value
);
111 bool GetEnableFramerateCounter ();
112 void SetEnableFramerateCounter (bool value
);
113 bool GetEnableRedrawRegions ();
114 void SetEnableRedrawRegions (bool value
);
115 /* @GenerateCBinding,GeneratePInvoke */
116 bool GetEnableHtmlAccess ();
117 /* @GenerateCBinding,GeneratePInvoke */
118 bool GetAllowHtmlPopupWindow ();
119 /* @GenerateCBinding,GeneratePInvoke */
120 bool GetWindowless ();
123 void SetMaxFrameRate (int value
);
124 int GetMaxFrameRate ();
125 Deployment
*GetDeployment ();
127 BrowserBridge
*GetBridge () { return bridge
; }
129 MoonlightScriptControlObject
*GetRootObject ();
131 NPWindow
*GetWindow ();
132 /* @GenerateCBinding,GeneratePInvoke */
133 Surface
*GetSurface () { return surface
; }
135 /* @GenerateCBinding,GeneratePInvoke */
136 gint32
GetActualHeight ();
137 /* @GenerateCBinding,GeneratePInvoke */
138 gint32
GetActualWidth ();
140 bool IsCrossDomainApplication () { return cross_domain_app
; }
141 static gint32
GetPluginCount ();
143 static gboolean
plugin_button_press_callback (GtkWidget
*widget
, GdkEventButton
*event
, gpointer user_data
);
145 static Downloader
*CreateDownloader (PluginInstance
*instance
);
148 struct moon_source
: List::Node
{
151 virtual ~moon_source ()
157 void AddSource (const char *uri
, const char *filename
);
162 static bool MonoIsLoaded ();
163 static bool DeploymentInit ();
165 bool InitializePluginAppDomain ();
166 bool CreatePluginDeployment ();
168 gpointer
ManagedCreateXamlLoaderForFile (XamlLoader
* loader
, const char *resourceBase
, const char *file
);
169 gpointer
ManagedCreateXamlLoaderForString (XamlLoader
* loader
, const char *resourceBase
, const char *str
);
170 void ManagedLoaderDestroy (gpointer loader_object
);
179 GtkWidget
*container
; // plugin container object
180 Surface
*surface
; // plugin surface object
181 MoonWindow
*moon_window
;
186 guint16 mode
; // NP_EMBED, NP_FULL, or NP_BACKGROUND
187 NPWindow
*window
; // Mozilla window object
188 NPP instance
; // Mozilla instance object
189 NPObject
*rootobject
; // Mozilla jscript object wrapper
190 guint32 xembed_supported
; // XEmbed Extension supported
192 GHashTable
*wrapped_objects
; // wrapped object cache
195 * Mozilla has a slightly different view on refcounting when dealing with
196 * NPObjects: normal refcounting until NPP_Destroy is called, after
197 * NPP_Destroy returns, all NPObjects are deleted no matter their refcount.
199 * See this link for some fun reading:
200 * - https://bugzilla.mozilla.org/show_bug.cgi?id=421217
202 * Apparently this behaviour is documented here: http://developer.mozilla.org/en/NPClass
203 * - The NPObjects' invalidate method is:
204 * "Called on live objects that belong to a plugin instance that is being destroyed."
205 * "This call is always followed by a call to the deallocate function called when"
206 * "the plugin is destroyed"
208 * However the documentation also says this about the deallocate method:
209 * "Called by NPN_ReleaseObject() when an object's reference count reaches zero."
211 * This contradicting documentation results in different behaviour between browsers,
212 * Safari and Opera comply 100% with refcounting laws, while firefox doesn't.
214 * This has a profound implication on for our shutdown code: it means that
215 * we can't access any NPObjects after returning from NPP_Destroy. Parts of
216 * our current shutdown is async (it wouldn't be completely impossible to
217 * make it sync, just dangerously difficult, we'd have to block the main thread
218 * until all other threads have shut down, while executing code we have little
219 * control over, exposing us to possible deadlocks).
221 * To protect against accessing NPObjects after returning from NPP_Destroy
222 * we keep a flag telling whether it's safe or not to access npobjects (which
223 * is set upon shutdown)
228 bool IsShuttingDown (); /* Not thread-safe */
229 bool HasShutdown (); /* It is not safe to access any NPObjects when this returns true. Not thread-safe. */
232 bool is_shutting_down
;
236 GSList
*cleanup_pointers
;
241 char *source_original
;
242 char *source_location
;
243 char *source_location_original
;
250 char *splashscreensource
;
251 char *onSourceDownloadProgressChanged
;
252 char *onSourceDownloadComplete
;
260 bool cross_domain_app
;
261 bool default_enable_html_access
;
262 bool enable_html_access
;
263 bool allow_html_popup_window
;
264 bool enable_framerate_counter
;
269 BrowserBridge
*bridge
;
271 GtkWidget
*properties_fps_label
;
272 GtkWidget
*properties_cache_label
;
275 // The XAML loader, contains a handle to a MonoObject *
277 PluginXamlLoader
*xaml_loader
;
278 Deployment
*deployment
;
280 MonoAssembly
*system_windows_assembly
;
282 static bool mono_is_loaded
;
285 MonoMethod
*moon_load_xaml
;
286 MonoMethod
*moon_initialize_deployment_xap
;
287 MonoMethod
*moon_initialize_deployment_xaml
;
288 MonoMethod
*moon_destroy_application
;
290 MonoClass
*moon_exception
;
291 MonoProperty
*moon_exception_message
;
292 MonoProperty
*moon_exception_error_code
;
294 void LoadXAP (const char*url
, const char *fname
);
295 void DestroyApplication ();
297 MonoMethod
*MonoGetMethodFromName (MonoClass
*klass
, const char *name
, int narg
);
298 MonoProperty
*MonoGetPropertyFromName (MonoClass
*klass
, const char *name
);
300 ErrorEventArgs
* ManagedExceptionToErrorEventArgs (MonoObject
*exc
);
302 bool ManagedInitializeDeployment (const char *file
);
303 void ManagedDestroyApplication ();
305 gpointer
ManagedCreateXamlLoader (XamlLoader
* native_loader
, const char *resourceBase
, const char *file
, const char *str
);
308 // The name of the file that we are missing, and we requested to be loaded
309 char *vm_missing_file
;
312 void CreateWindow ();
313 void UpdateSource ();
314 void UpdateSourceByReference (const char *value
);
317 char* GetPageLocation ();
318 void CrossDomainApplicationCheck (const char *source
);
320 void TryLoadBridge (const char *prefix
);
322 static gboolean
IdleUpdateSourceByReference (gpointer data
);
324 static void ReportFPS (Surface
*surface
, int nframes
, float nsecs
, void *user_data
);
325 static void ReportCache (Surface
*surface
, long bytes
, void *user_data
);
326 static void properties_dialog_response (GtkWidget
*dialog
, int response
, PluginInstance
*plugin
);
328 static void network_error_tickcall (EventObject
*data
);
329 static void splashscreen_error_tickcall (EventObject
*data
);
331 EVENTHANDLER (PluginInstance
, AppDomainUnloadedEvent
, Deployment
, EventArgs
);
334 extern GSList
*plugin_instances
;
336 #define NPID(x) NPN_GetStringIdentifier (x)
338 #define STRDUP_FROM_VARIANT(v) (g_strndup ((char *) NPVARIANT_TO_STRING (v).utf8characters, NPVARIANT_TO_STRING (v).utf8length))
339 #define STRLEN_FROM_VARIANT(v) ((size_t) NPVARIANT_TO_STRING (v).utf8length)
341 #define STREAM_NOTIFY(x) ((StreamNotify*) x)
343 #define STREAM_NOTIFY_DATA(x) ((StreamNotify*) x)->pdata
345 #define IS_NOTIFY_SOURCE(x) \
346 (!x ? true : (((StreamNotify*) x)->type == StreamNotify::SOURCE))
348 #define IS_NOTIFY_SPLASHSOURCE(x) \
349 (!x ? true : (((StreamNotify*) x)->type == StreamNotify::SPLASHSOURCE))
351 #define IS_NOTIFY_DOWNLOADER(x) \
352 (!x ? StreamNotify::NONE : (((StreamNotify*) x)->type == StreamNotify::DOWNLOADER))
354 #define IS_NOTIFY_REQUEST(x) \
355 (!x ? StreamNotify::NONE : (((StreamNotify*) x)->type == StreamNotify::REQUEST))
360 enum StreamNotifyFlags
{
368 StreamNotifyFlags type
;
371 StreamNotify () : type (NONE
), pdata (NULL
) {};
372 StreamNotify (void *data
) : type (NONE
), pdata (data
) {};
373 StreamNotify (StreamNotifyFlags type
) : type (type
), pdata (NULL
) {};
374 StreamNotify (StreamNotifyFlags type
, void *data
) : type (type
), pdata (data
) {};
375 StreamNotify (StreamNotifyFlags type
, DependencyObject
*dob
) : type (type
), pdata (dob
)
383 if (type
== DOWNLOADER
&& pdata
)
384 ((DependencyObject
*) pdata
)->unref ();
388 class PluginXamlLoader
: public XamlLoader
390 PluginXamlLoader (const char *resourceBase
, const char *filename
, const char *str
, PluginInstance
*plugin
, Surface
*surface
);
391 bool InitializeLoader ();
392 PluginInstance
*plugin
;
394 bool xaml_is_managed
;
397 gpointer managed_loader
;
401 virtual ~PluginXamlLoader ();
402 const char *TryLoad (int *error
);
404 bool SetProperty (void *parser
, Value
*top_level
, const char *xmlns
, Value
*target
, void *target_data
, Value
*target_parent
, const char *prop_xmlns
, const char *name
, Value
* value
, void* value_data
, int flags
= 0);
406 static PluginXamlLoader
*FromFilename (const char *resourceBase
, const char *filename
, PluginInstance
*plugin
, Surface
*surface
)
408 return new PluginXamlLoader (resourceBase
, filename
, NULL
, plugin
, surface
);
411 static PluginXamlLoader
*FromStr (const char *resourceBase
, const char *str
, PluginInstance
*plugin
, Surface
*surface
)
413 return new PluginXamlLoader (resourceBase
, NULL
, str
, plugin
, surface
);
416 bool IsManaged () { return xaml_is_managed
; }
418 virtual bool LoadVM ();
423 const char *get_plugin_dir (void);
425 char *plugin_instance_get_id (PluginInstance
*instance
);
427 void plugin_instance_get_browser_runtime_settings (bool *debug
, bool *html_access
,
428 bool *httpnet_access
, bool *script_access
);
430 void *plugin_instance_load_url (PluginInstance
*instance
, char *url
, gint32
*length
);
432 PluginXamlLoader
*plugin_xaml_loader_from_str (const char *str
, const char *resourceBase
, PluginInstance
*plugin
, Surface
*surface
);
436 #endif /* MOON_PLUGIN */