public void CSharpInvokingJavascriptComObjects()
        {
            // Note: Firefox 17 removed enablePrivilege #546848 - refactored test so that javascript to create "@mozillazine.org/example/priority;1" is now executated by AutoJsContext

            // Register a C# COM Object

            // TODO would be nice to get nsIComponentRegistrar the xpcom way with CreateInstance
            // ie Xpcom.CreateInstance<nsIComponentRegistrar>(...
            Guid aClass  = new Guid("a7139c0e-962c-44b6-bec3-aaaaaaaaaaac");
            var  factory = new MyCSharpClassThatContainsXpComJavascriptObjectsFactory();

            Xpcom.ComponentRegistrar.RegisterFactory(ref aClass, "Example C sharp com component", "@geckofx/myclass;1", factory);

            // In order to use Components.classes etc we need to enable certan privileges.
            GeckoPreferences.User["capability.principal.codebase.p0.granted"]     = "UniversalXPConnect";
            GeckoPreferences.User["capability.principal.codebase.p0.id"]          = "file://";
            GeckoPreferences.User["capability.principal.codebase.p0.subjectName"] = "";
            GeckoPreferences.User["security.fileuri.strict_origin_policy"]        = false;

#if PORT
            browser.JavascriptError += (x, w) => Console.WriteLine("Message = {0}", w.Message);
#endif

            string intialPage = "<html><body></body></html>";

            string initialjavascript =
                "var myClassInstance = Components.classes['@geckofx/myclass;1'].createInstance(Components.interfaces.nsIWebPageDescriptor);" +
                "var reg = myClassInstance.currentDescriptor.QueryInterface(Components.interfaces.nsIComponentRegistrar);" +
                "Components.utils.import(\"resource://gre/modules/XPCOMUtils.jsm\"); " +
                "const nsISupportsPriority = Components.interfaces.nsISupportsPriority;" +
                "const nsISupports = Components.interfaces.nsISupports;" +
                "const CLASS_ID = Components.ID(\"{1C0E8D86-B661-40d0-AE3D-CA012FADF170}\");" +
                "const CLASS_NAME = \"My Supports Priority Component\";" +
                "const CONTRACT_ID = \"@mozillazine.org/example/priority;1\";" +
                "function MyPriority() {" +
                "	this._priority = nsISupportsPriority.PRIORITY_LOWEST;"+
                "};" +
                "MyPriority.prototype = {" +
                "  _priority: null," +

                "  get priority() { return this._priority; }," +
                "  set priority(aValue) { this._priority = aValue; }," +

                "  adjustPriority: function(aDelta) {" +
                "	this._priority += aDelta;"+
                "  }," +

                "  QueryInterface: function(aIID)" +
                "  { " +
                "	/*if (!aIID.equals(nsISupportsPriority) &&    "+
                "		!aIID.equals(nsISupports))"+
                "	  throw Components.results.NS_ERROR_NO_INTERFACE;*/"+
                "	return this;"+
                "  }" +
                "};" +
                "" +
                "var MyPriorityFactory = {" +
                "  createInstance: function (aOuter, aIID)" +
                "  { " +
                "	if (aOuter != null)"+
                "	  throw Components.results.NS_ERROR_NO_AGGREGATION; "+
                "	return (new MyPriority()).QueryInterface(aIID);"+
                "  }" +
                "};" +
                "" +
                "var MyPriorityModule = {" +
                "  _firstTime: true," +
                "  registerSelf: function(aCompMgr, aFileSpec, aLocation, aType)" +
                "  {" +
                "	aCompMgr = aCompMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);"+
                "	aCompMgr.registerFactory(CLASS_ID, CLASS_NAME, CONTRACT_ID, MyPriorityFactory);"+
                "  }," +
                "" +
                "  unregisterSelf: function(aCompMgr, aLocation, aType)" +
                "  {" +
                "	aCompMgr = aCompMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);"+
                "	aCompMgr.unregisterFactoryLocation(CLASS_ID, aLocation);        "+
                "  }," +
                "" +
                "  getClassObject: function(aCompMgr, aCID, aIID)" +
                "  {alert('hi');" +
                "	if (!aIID.equals(Components.interfaces.nsIFactory))"+
                "	  throw Components.results.NS_ERROR_NOT_IMPLEMENTED;"+
                "" +
                "	if (aCID.equals(CLASS_ID))"+
                "	  return MyPriorityFactory;"+
                "" +
                "	throw Components.results.NS_ERROR_NO_INTERFACE;"+
                "  }," +
                "" +
                "  canUnload: function(aCompMgr) { return true; }" +
                "};" +
                "MyPriorityModule.registerSelf(reg);" +
                "";

            // Create temp file to load
            var tempfilename = Path.GetTempFileName();
            tempfilename += ".html";
            using (TextWriter tw = new StreamWriter(tempfilename))
            {
                tw.WriteLine(intialPage);
                tw.Close();
            }

            browser.Navigate(tempfilename);
            browser.NavigateFinishedNotifier.BlockUntilNavigationFinished();

            using (var context = new AutoJSContext(GlobalJSContextHolder.BackstageJSContext))
            {
                string result  = String.Empty;
                var    success = context.EvaluateScript(initialjavascript, out result);
                Console.WriteLine("success = {0} result = {1}", success, result);
            }

            File.Delete(tempfilename);

            // Create instance of javascript xpcom objects
            var p = Xpcom.CreateInstance <nsISupportsPriority>("@mozillazine.org/example/priority;1");
            Assert.NotNull(p);

            // test invoking method of javascript xpcom object.
            Assert.AreEqual(20, p.GetPriorityAttribute());

            Xpcom.ComponentRegistrar.UnregisterFactory(ref aClass, factory);
        }
        public void CSharpInvokingJavascriptComObjects()
        {
            // Note: Firefox 17 removed enablePrivilege #546848 - refactored test so that javascript to create "@mozillazine.org/example/priority;1" is now executated by AutoJsContext

            // Register a C# COM Object

            // TODO would be nice to get nsIComponentRegistrar the xpcom way with CreateInstance
            // ie Xpcom.CreateInstance<nsIComponentRegistrar>(...
            Guid aClass = new Guid("a7139c0e-962c-44b6-bec3-aaaaaaaaaaac");
            var factory = new MyCSharpClassThatContainsXpComJavascriptObjectsFactory();
            Xpcom.ComponentRegistrar.RegisterFactory(ref aClass, "Example C sharp com component", "@geckofx/myclass;1", factory);

            // In order to use Components.classes etc we need to enable certan privileges.
            GeckoPreferences.User["capability.principal.codebase.p0.granted"] = "UniversalXPConnect";
            GeckoPreferences.User["capability.principal.codebase.p0.id"] = "file://";
            GeckoPreferences.User["capability.principal.codebase.p0.subjectName"] = "";
            GeckoPreferences.User["security.fileuri.strict_origin_policy"] = false;

            browser.JavascriptError += (x, w) => Console.WriteLine("Message = {0}", w.Message);

            string intialPage = "<html><body></body></html>";

            string initialjavascript =
                "var myClassInstance = Components.classes['@geckofx/myclass;1'].createInstance(Components.interfaces.nsIWebPageDescriptor);" +
                "var reg = myClassInstance.currentDescriptor.QueryInterface(Components.interfaces.nsIComponentRegistrar);" +
                "Components.utils.import(\"resource://gre/modules/XPCOMUtils.jsm\"); " +
                "const nsISupportsPriority = Components.interfaces.nsISupportsPriority;" +
                "const nsISupports = Components.interfaces.nsISupports;" +
                "const CLASS_ID = Components.ID(\"{1C0E8D86-B661-40d0-AE3D-CA012FADF170}\");" +
                "const CLASS_NAME = \"My Supports Priority Component\";" +
                "const CONTRACT_ID = \"@mozillazine.org/example/priority;1\";" +
                "function MyPriority() {" +
                "	this._priority = nsISupportsPriority.PRIORITY_LOWEST;" +
                "};" +
                "MyPriority.prototype = {" +
                "  _priority: null," +

                "  get priority() { return this._priority; }," +
                "  set priority(aValue) { this._priority = aValue; }," +

                "  adjustPriority: function(aDelta) {" +
                "	this._priority += aDelta;" +
                "  }," +

                "  QueryInterface: function(aIID)" +
                "  { " +
                "	/*if (!aIID.equals(nsISupportsPriority) &&    " +
                "		!aIID.equals(nsISupports))" +
                "	  throw Components.results.NS_ERROR_NO_INTERFACE;*/" +
                "	return this;" +
                "  }" +
                "};" +
                "" +
                "var MyPriorityFactory = {" +
                "  createInstance: function (aOuter, aIID)" +
                "  { " +
                "	if (aOuter != null)" +
                "	  throw Components.results.NS_ERROR_NO_AGGREGATION; " +
                "	return (new MyPriority()).QueryInterface(aIID);" +
                "  }" +
                "};" +
                "" +
                "var MyPriorityModule = {" +
                "  _firstTime: true," +
                "  registerSelf: function(aCompMgr, aFileSpec, aLocation, aType)" +
                "  {" +
                "	aCompMgr = aCompMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);" +
                "	aCompMgr.registerFactory(CLASS_ID, CLASS_NAME, CONTRACT_ID, MyPriorityFactory);" +
                "  }," +
                "" +
                "  unregisterSelf: function(aCompMgr, aLocation, aType)" +
                "  {" +
                "	aCompMgr = aCompMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);" +
                "	aCompMgr.unregisterFactoryLocation(CLASS_ID, aLocation);        " +
                "  }," +
                "" +
                "  getClassObject: function(aCompMgr, aCID, aIID)" +
                "  {alert('hi');" +
                "	if (!aIID.equals(Components.interfaces.nsIFactory))" +
                "	  throw Components.results.NS_ERROR_NOT_IMPLEMENTED;" +
                "" +
                "	if (aCID.equals(CLASS_ID))" +
                "	  return MyPriorityFactory;" +
                "" +
                "	throw Components.results.NS_ERROR_NO_INTERFACE;" +
                "  }," +
                "" +
                "  canUnload: function(aCompMgr) { return true; }" +
                "};" +
                "MyPriorityModule.registerSelf(reg);" +
                "";

            // Create temp file to load
            var tempfilename = Path.GetTempFileName();
            tempfilename += ".html";
            using (TextWriter tw = new StreamWriter(tempfilename))
            {
                tw.WriteLine(intialPage);
                tw.Close();
            }

            browser.Navigate(tempfilename);
            browser.NavigateFinishedNotifier.BlockUntilNavigationFinished();

            using (var context = new AutoJSContext(GlobalJSContextHolder.BackstageJSContext))
            {
                string result = String.Empty;
                var success = context.EvaluateScript(initialjavascript, out result);
                Console.WriteLine("sucess = {0} result = {1}", success, result);
            }

            File.Delete(tempfilename);

            // Create instance of javascript xpcom objects
            var p = Xpcom.CreateInstance<nsISupportsPriority>("@mozillazine.org/example/priority;1");
            Assert.NotNull(p);

            // test invoking method of javascript xpcom object.
            Assert.AreEqual(20, p.GetPriorityAttribute());

            Xpcom.ComponentRegistrar.UnregisterFactory(aClass, factory);
        }