These are some notes on Silverlight Hosting APIs and how the plugin works / should work. They are likely incorrect
Table of contents
How it works
First step: create an <object> element of type application/ag-plugin.
This is not mandatory unless you run silverlight apps written in Microsoft ways:
- The web browser loads HTML, which contains "SilverlightControlHost" element.
- createSilverlight() invokes createObjectEx() which is defined in silverlight.js.
- createObjectEx() either creates an <object> element of type application/ag-plugin, or download/support links.
- <object> element of type application/ag-plugin is recognized by the moonlight plugin.
We could just directly include such an <object> element in the HTML instead.
Second step: bootstrapping Silverlight control
It is done by moonlight plugin.
- The plugin is triggered by the <object> element.
- It loads the "source" XAML file. If there isn't, then nothing is warned.
- It looks for the implementation class from "x:class", which looks like : "SilverlightProject1.Page;assembly=ClientBin/SilverlightProject1.dll"
- Create a GTK+ canvas for Silverlight object (indicated by "source")
System.Silverlight.dll and Microsoft.Scripting.Silverlight.dll are involved.
Microsoft.Scripting.Silverlight is smaller:
- ErrorHandler : static aggregated class of error handling which dispatch managed exceptions to browser.
- For now simple string and primitive types are supported as method parameters. (See below for details.)
How to enable ScriptableObject in managed code
- Add ScriptableAttribute on the class, and property, method and events.
- Call WebApplication.Current.RegisterScriptableObject(nameOnJS, instance).
- registered scriptable objects are accessible via document.getElementById ("SilverlightControl").Content as its properties.
- Events are created as event triggers which expects two arguments (sender, eargs).
- functions are created as functions as they are.
- Types are strictly limited: bool, string, char, numeric types except for Decimal are OK. No other types are allowed (object, Guid, DateTime, IDictionary<string,object>, any custom types). Only In parameters allowed.
- Every ScriptableObject seems to check its hosting environment. For example, HtmlPage.Document causes an error (NRE at alpha1) outside hosted environment (for example console app).
List for some objects/methods that need interaction from managed code to DOM:
- ScriptableObject.GetProperty<T>(string name)
- T must be derived from ScriptableObject. For example, HtmlPage.Document.GetProperty<object>("documentElement")
- HtmlObject.AttachEvent(string name,EventHandler handler)
- HtmlObject.DetachEvent(string name,EventHandler handler)
- generic way to invoke methods (e.g. getElementByTagName(), createElement() etc.)
In agclr, System.Windows.ErrorEventHandler and ErrorEventArgs are used to handle errors at managed side.
Microsoft.Scripting.Silverlight.ErrorHandler is (in a sense) the closest API to the browser. It is tied to ErrorEventArgs in agclr and "default_error_handler" in silverlight.js, which
- expects ParserError and RuntimeError as errorType (ParserErrorEventArgs/RuntimeErrorEventArgs in agclr)
- expects errorCode, errorType and errorMessage (ErrorEventArgs properties)
- WebApplication.Current is created and used to serve RegisterScriptableObject().
- NPN_CreateObject() is likely used.
- I'm not sure if SilverlightScriptHost and SilverlightPAL are created on silverlight apps. ScriptDomainManager.CurrentManager.PAL is not an instance of SilverlightPAL on silverlight apps.
- static property HtmlPage.Document accesses to the document. It somehow causes NRE on non-silverlight app.
Implementation status notes
Already written as DllImport (note that they are not in moon/plugin yet):
- InvokeMethodInternal(IntPtr xpp, IntPtr obj, string name,object args)
- GetPropertyInternal(IntPtr xpp,IntPtr obj, string name)
- SetPropertyInternal(IntPtr xpp,IntPtr obj, string name, object value); They are commonized accessors and used by several classes such as HtmlElement.AppendChild().
- AttachEvent(IntPtr xpp, IntPtr obj, string name, EventHandler h)
- AttachEvent(IntPtr xpp, IntPtr obj, string name, EventHandler<HtmlEventArgs> h)
- DetachEvent(IntPtr xpp, IntPtr obj, string name, EventHandler h)
- DetachEvent(IntPtr xpp, IntPtr obj, string name, EventHandler<HtmlEventArgs> h)
- Navigate (IntPtr npp, string uri)
- Navigate (IntPtr npp, string uri, string target, string features) (returns a handle)
- NavigateToBookmark (IntPtr xpp, string bookmark)
- Submit (IntPtr xpp, string formId)
Just rough ideas:
- WebApplication.Current is likely hold a pointer to NPP instance, a pointer to PluginInstance, and so on. Use AppDomain.GetData() to return pointers here.
- WebApplication.RegisterScriptableObject() has to create a NPObject. Also, access to the members must be reflected to the managed object (and vice versa).
- WebApplication.StartupArguments. Not sure what should be set here.
- HtmlPage properties:
- Cookies, string
- CurrentBookmark, string
- Document, IntPtr to NPObject?
- DocumentUri, string
- QueryString, string or dictionary
- Window, IntPtr to PluginInstance->window
- HtmlElement.SetStyleAttribute() and RemoveStyleAttribute() ; not sure how it is done.