Reflector add-in (proof of concept) for highlighting platform APIs

I was talking to one of our partners at MIX about the new security model in Silverlight. In case you're not familiar with it yet I recommend reading The Silverlight Security Model (as well as part II and III if you're interested in the details) on Shawn's blog since he explains it very well (see also the documentation on SecurityCriticalAttribute, SecuritySafeCriticalAttribute and SecurityTreatAsSafeAttribute). In a nutshell: There is no CAS in Silverlight. Instead you are simply not allowed to call certain APIs in order to provide a robust sandbox which allows you to execute applications on a website without having to worry about the application possibly compromising your computer. For example a Silverlight application can't just access the file system or connect to any machine on the Internet.

After explaining this I was asked if there was a list with all APIs you can't call in Silverlight. While I'm not sure that there is really one list somewhere covering all APIs in Silverlight I noticed that it would be quite simple to generate one by writing some code that reflects on the Silverlight assemblies. However, that's when it hit me that this theoretical list would be rather long and consisting of information you don't care about most of the time. I guess a document basically describing the differences between the full .NET Framework and Silverlight (as far as the types they have in common go) would probably be more helpful (I'm still trying figure out if we indeed have something like that).

At the same time I thought it would be handy though to have something that allows me to browse APIs with the critical and safe critical APIs marked. And since many people use Reflector (yes, even me and others with access to the source code - it's just quicker to decompile an assembly than getting the right files out of the source control system) I looked into customizing it to do exactly this. The result was the following code:

using Reflector;

using Reflector.CodeModel;

using System;

using System.Windows.Forms;

using System.Drawing;

namespace Reflector.AddIns

{

    public class SilverlightPlatformHighlighter : IPackage

    {

        #region Private Consts

        private const string CriticalAttributeTypeName = "SecurityCriticalAttribute";

        private const string CriticalAttributeTypeNamespace = "System.Security";

        private const string SafeCriticalAttributeTypeName = "SecuritySafeCriticalAttribute";

        private const string SafeCriticalAttributeTypeNamespace = "System.Security";

        private const string TreatAsSafeAttributeTypeName = "SecurityTreatAsSafeAttribute";

        private const string TreatAsSafeAttributeTypeNamespace = "System.Security";

        private readonly Color CriticalAttributeColor = Color.FromArgb(0x00, 0xFF, 0xC0, 0xC0);

        private readonly Color SafeCriticalAttributeColor = Color.FromArgb(0x00, 0xFF, 0xFF, 0x80);

        #endregion Private Consts

        #region Private Fields

        private TreeView tree;

        #endregion Private Fields

        #region IPackage Members

        public void Load(IServiceProvider serviceProvider)

        {

            tree = (TreeView)((IAssemblyBrowser)serviceProvider.GetService(typeof(IAssemblyBrowser)));

            tree.AfterExpand += new TreeViewEventHandler(tree_AfterExpand);

        }

        public void Unload()

        {

            tree.AfterExpand -= new TreeViewEventHandler(tree_AfterExpand);

        }

        #endregion IPackage Members

        #region Private Methods

        private void tree_AfterExpand(object sender, TreeViewEventArgs e)

        {

            ICustomAttributeProvider attributeProvider;

            ITypeDeclaration type;

            foreach (TreeNode node in e.Node.Nodes)

                if ((attributeProvider = node.Tag as ICustomAttributeProvider) != null)

                {

                    bool isCritical = false;

                    bool isSafeCritical = false;

                    bool treatAsSafe = false;

                    foreach (ICustomAttribute attribute in attributeProvider.Attributes)

                        if (attribute.Constructor != null &&

                            ((type = attribute.Constructor.DeclaringType as ITypeDeclaration) != null))

                        {

                            if (type.Name == CriticalAttributeTypeName &&

                                type.Namespace == CriticalAttributeTypeNamespace)

                   isCritical = true;

                            else if (type.Name == SafeCriticalAttributeTypeName &&

                                     type.Namespace == SafeCriticalAttributeTypeNamespace)

                                isSafeCritical = true;

                            else if (type.Name == TreatAsSafeAttributeTypeName &&

                                     type.Namespace == TreatAsSafeAttributeTypeNamespace)

                                treatAsSafe = true;

             }

                    if (isSafeCritical || (isCritical && treatAsSafe))

                        node.BackColor = SafeCriticalAttributeColor;

                    else if (isCritical)

                        node.BackColor = CriticalAttributeColor;

                }

        }

        #endregion Private Methods

    }

}

 

While it technically is (the code for) a Reflector add-in I'd rather call it a proof of concept since it ignores the assembly nodes in the tree as well as the parent of any given node. The code is also a bit hacky since it relies on implementation details of Reflector which may change in the future. Compiling the code into an add-in and loading it into Reflector gives you an assembly browser which marks critical types and members in red and safe critical ones in yellow (which is more of an FYI anyway):


This posting is provided "AS IS" with no warranties, and confers no rights.

Comments