public bool EvaluateTrustedScript(string jsScript, out string result) { throw new NotImplementedException(); var ptr = new JsVal(); IntPtr globalObject = SpiderMonkey.JS_GetGlobalForScopeChain(_cx); bool ret; IntPtr systemGlobalObject = SpiderMonkey.JS_GetGlobalForScopeChain(GlobalJSContextHolder.BackstageJSContext); // Compartments have to be entered and left in LIFO order. bool inSystemCompartment = false; IntPtr oldCompartment = IntPtr.Zero; try { // Allow access to any object on page. oldCompartment = SpiderMonkey.JS_EnterCompartment(_cx, systemGlobalObject); // At any time, a JSContext has a current (possibly-NULL) compartment. inSystemCompartment = true; ret = SpiderMonkey.JS_EvaluateScript(_cx, globalObject, jsScript, (uint)jsScript.Length, "script", 1, ref ptr); result = ConvertValueToString(ptr); } finally { if (inSystemCompartment) { SpiderMonkey.JS_LeaveCompartment(_cx, oldCompartment); } } return(ret); }
private static IntPtr GetContextByName(string contextName) { Xpcom.AssertCorrectThread(); IntPtr rt = Runtime; IntPtr iterp = IntPtr.Zero; IntPtr cx; while ((cx = SpiderMonkey.JS_ContextIterator(rt, ref iterp)) != IntPtr.Zero) { IntPtr global = SpiderMonkey.JS_GetGlobalObject(cx); if (global != IntPtr.Zero) { IntPtr classp = SpiderMonkey.JS_GetClass(global); // get class name if (classp != IntPtr.Zero) { string className = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(classp)); if (className == contextName) { return(cx); } } } } return(IntPtr.Zero); }
internal string ConvertValueToString(JsVal value) { if (value.IsString) { var v = Xpcom.XPConnect.Instance.JSValToVariant(ContextPointer, ref value); return(nsString.Get(v.GetAsAString)); } // Fallback for non string JsVal's // If the JsVal is not a string convert it to a JSString // then convert the JSString to a utf8 string. // NOTE: This fallback isn't ideal and may cause unicode replacement chars to appear. IntPtr jsp = SpiderMonkey.ToStringSlow(ContextPointer, value); var utf8StrPtr = SpiderMonkey.JS_EncodeStringToUTF8(ContextPointer, jsp); if (utf8StrPtr != IntPtr.Zero) { try { var length = SpiderMonkey.JS_GetStringEncodingLength(ContextPointer, jsp); byte[] result = new byte[length]; Marshal.Copy(utf8StrPtr, result, 0, length); return(Encoding.UTF8.GetString(result, 0, length)); } finally { SpiderMonkey.JS_Free(ContextPointer, utf8StrPtr); } } return(null); }
public ComPtr <nsISupports> GetGlobalNsObject() { IntPtr globalObject = SpiderMonkey.CurrentGlobalOrNull(_cx); if (globalObject != IntPtr.Zero) { Guid guid = typeof(nsISupports).GUID; IntPtr pUnk = IntPtr.Zero; try { pUnk = Xpcom.XPConnect.Instance.WrapJS(_cx, globalObject, ref guid); object comObj = Xpcom.GetObjectForIUnknown(pUnk); try { return(Xpcom.QueryInterface <nsISupports>(comObj).AsComPtr()); } finally { Xpcom.FreeComObject(ref comObj); } } finally { if (pUnk != IntPtr.Zero) { Marshal.Release(pUnk); } } } return(null); }
/// <summary> /// Working similar to SelectSingle but not throwing exceptions on error (simply return first result) /// </summary> /// <param name="xpath"></param> /// <returns></returns> public GeckoNode SelectFirst(string xpath) { var r = EvaluateXPathInternal(xpath); nsIDOMNode singleNode = null; using (var context = new AutoJSContext()) { var jsObject = context.ConvertCOMObjectToJSObject((nsISupports)r); // TODO: (Idenally I would generate these calls via a webidl-> C# compiler but for now just do it via manually written spidermonkey calls..) var resultType = SpiderMonkey.JS_GetProperty(context.ContextPointer, jsObject, "resultType").ToInteger(); switch (resultType) { case nsIDOMXPathResultConsts.UNORDERED_NODE_ITERATOR_TYPE: singleNode = (nsIDOMNode)SpiderMonkey.JS_CallFunctionName(context.ContextPointer, jsObject, "iterateNext", new JsVal[0]).ToComObject(context.ContextPointer); break; case nsIDOMXPathResultConsts.FIRST_ORDERED_NODE_TYPE: case nsIDOMXPathResultConsts.ANY_UNORDERED_NODE_TYPE: singleNode = (nsIDOMNode)SpiderMonkey.JS_GetProperty(context.ContextPointer, jsObject, "singleNodeValue").ToComObject(context.ContextPointer); break; } var ret = singleNode.Wrap(GeckoNode.Create); Xpcom.FreeComObject(ref r); return(ret); } }
/// <summary> /// Evaluate JavaScript in specified window, and with specified scope. /// Throws GeckoJavaScriptException on error. /// </summary> /// <param name="javascript">The javascript to run.</param> /// <param name="window">The window to execuate javascript in. (ie. the global object)</param> /// <param name="scope">object to use as scope.</param> /// <returns>The return value of the script as a JsVal</returns> public JsVal EvaluateScript(string javascript, nsISupports window, nsISupports scope) { string msg = String.Empty; JsVal exceptionJsVal = default(JsVal); IntPtr globalObject = ConvertCOMObjectToJSObject(window); using (new JSAutoCompartment(ContextPointer, globalObject)) { var old = SpiderMonkey.JS_SetErrorReporter(SpiderMonkey.JS_GetRuntime(ContextPointer), (cx, message, report) => { var exception = SpiderMonkey.JS_GetPendingException(ContextPointer); if (exception != IntPtr.Zero) { exceptionJsVal = JsVal.FromPtr(exception); } msg = message; }); try { var retJsVal = new JsVal(); bool ret; // If not running in window scope. if (window != scope) { var scopeJSVal = JsVal.FromPtr(ConvertCOMObjectToJSObject(scope)); if (!SpiderMonkey.JS_SetProperty(ContextPointer, globalObject, "__RequestedScope", scopeJSVal)) { throw new GeckoException("Failed to set __RequestedScope Property."); } javascript = InsertReturnStatement(javascript); string s = "(function() { " + javascript + " }).call(this.__RequestedScope)"; ret = SpiderMonkey.JS_EvaluateScript(ContextPointer, s, (uint)s.Length, "script", 1, ref retJsVal); } else { ret = SpiderMonkey.JS_EvaluateScript(ContextPointer, javascript, (uint)javascript.Length, "script", 1, ref retJsVal); } if (ret) { return(retJsVal); } msg += GetStackTrace(globalObject, exceptionJsVal); throw new GeckoJavaScriptException(String.Format("JSError : {0}", msg)); } finally { SpiderMonkey.JS_SetErrorReporter(SpiderMonkey.JS_GetRuntime(ContextPointer), old); } } }
/// <summary> /// Evaluate javascript in the current context. /// </summary> /// <param name="jsScript"></param> /// <param name="thisObject">a nsISupports com object that this is set too.</param> /// <param name="result"></param> /// <returns></returns> public bool EvaluateScript(string jsScript, nsISupports thisObject, out string result) { try { var ptr = new JsVal(); IntPtr globalObject = ConvertCOMObjectToJSObject(thisObject); using (new JSAutoCompartment(_cx, globalObject)) { bool ret = SpiderMonkey.JS_EvaluateScript(_cx, globalObject, jsScript, (uint)jsScript.Length, "script", 1, ref ptr); if (GetComponentsObject().GetUtilsAttribute().IsXrayWrapper(ref ptr)) { ptr = GetComponentsObject().GetUtilsAttribute().WaiveXrays(ref ptr, _cx); } result = ret ? ConvertValueToString(ptr) : null; return(ret); } } catch (Exception e) { Console.WriteLine("Exception {0}", e); result = String.Empty; return(false); } }
private static void HandleInvokeFailure(IntPtr cx, IntPtr jsObject, string name) { var exception = SpiderMonkey.JS_GetPendingException(cx); if (exception != IntPtr.Zero) { var exceptionJsVal = JsVal.FromPtr(exception); string st = string.Empty; try { st = GetStackTrace(cx, jsObject, exceptionJsVal); } catch { // ignored // we failed to get stack trace info, but still want to continue reporting exception. } var msg = exceptionJsVal.ToString(); msg += st; throw new GeckoException($"Calling function '{name}' failed: '{msg}'"); } throw new GeckoException($"Failed to call function '{name}'"); }
/// <summary> /// Converts to COM object without null check /// </summary> /// <returns></returns> private object ToComObjectInternal() { var context = AutoJSContext.Current; if (context == null) { throw new Exception("AutoJSContext not set."); } { var jsObject = SpiderMonkey.JS_ValueToObject(context.ContextPointer, this); var guid = typeof(nsISupports).GUID; var pUnk = IntPtr.Zero; try { pUnk = Xpcom.XPConnect.Instance.WrapJS(context.ContextPointer, jsObject, ref guid); var comObj = Xpcom.GetObjectForIUnknown(pUnk); return(comObj); } finally { if (pUnk != IntPtr.Zero) { Marshal.Release(pUnk); } } } }
public void Dispose() { _securityManager.PopContextPrincipal(_cx); _contextStack.Pop(); SpiderMonkey.JS_EndRequest(_cx); }
/// <summary> /// Evaluate javascript in the current context. /// </summary> /// <param name="jsScript"></param> /// <param name="jsval"></param> /// <returns></returns> public bool EvaluateScript(string jsScript, out string result) { var ptr = new JsVal(); bool ret = SpiderMonkey.JS_EvaluateScript(_cx, GetGlobalObject(), jsScript, (uint)jsScript.Length, "script", 1, ref ptr); result = ret ? ConvertValueToString(ptr) : null; return(ret); }
public override string ToString() { using (AutoJSContext context = new AutoJSContext()) { IntPtr jsString = SpiderMonkey.JS_ValueToString(context.ContextPointer, this); return(Marshal.PtrToStringAnsi(SpiderMonkey.JS_EncodeString(context.ContextPointer, jsString))); } }
private IntPtr GetGlobalObject() { IntPtr globalObject = SpiderMonkey.CurrentGlobalOrNull(_cx); if (globalObject == IntPtr.Zero) { throw new ObjectDisposedException(this.GetType().Name); } return(globalObject); }
public static IntPtr GetJSContextForDomWindow(nsIDOMWindow window) { IntPtr context = window.GetWindowRootAttribute().GetJSContextForEventHandlers(); if (context == IntPtr.Zero) { IntPtr pUnk = Marshal.GetIUnknownForObject(window); Marshal.Release(pUnk); if (!_windowContexts.TryGetValue(pUnk, out context)) { context = IntPtr.Zero; IntPtr cx; IntPtr iterp = IntPtr.Zero; IntPtr rt = Runtime; while ((cx = SpiderMonkey.JS_ContextIterator(rt, ref iterp)) != IntPtr.Zero) { IntPtr pGlobal = SpiderMonkey.JS_GetGlobalObject(cx); if (pGlobal != IntPtr.Zero) { using (var auto = new AutoJSContext(cx)) { nsISupports global = auto.GetGlobalNsObject(); if (global != null) { var domWindow = Xpcom.QueryInterface <nsIDOMWindow>(global); if (domWindow != null) { try { IntPtr pUnkTest = Marshal.GetIUnknownForObject(domWindow.GetWindowAttribute()); Marshal.Release(pUnkTest); if (pUnk == pUnkTest) { _windowContexts.Add(pUnk, cx); context = cx; break; } } finally { Marshal.ReleaseComObject(domWindow); } } } } } } } } return(context); }
internal string ConvertValueToString(JsVal value) { // OLD SLOW CODE // if (value.IsString) // { // var v = Xpcom.XPConnect.Instance.JSValToVariant(ContextPointer, ref value); // return nsString.Get(v.GetAsAString); //} return(SpiderMonkey.JsValToString(this._cx, value)); }
/// <summary> /// Evaluate javascript in the current context. /// </summary> /// <param name="jsScript"></param> /// <param name="jsval"></param> /// <returns></returns> public bool EvaluateScript(string jsScript, out string result) { var ptr = new JsVal(); IntPtr globalObject = SpiderMonkey.JS_GetGlobalForScopeChain(_cx); bool ret = SpiderMonkey.JS_EvaluateScript(_cx, globalObject, jsScript, (uint)jsScript.Length, "script", 1, ref ptr); IntPtr jsStringPtr = SpiderMonkey.JS_ValueToString(_cx, ptr); result = Marshal.PtrToStringAnsi(SpiderMonkey.JS_EncodeString(_cx, jsStringPtr)); return(ret); }
/// <summary> /// Evaluate javascript in the current context. /// </summary> /// <param name="jsScript"></param> /// <param name="jsval"></param> /// <returns></returns> public bool EvaluateScript(string jsScript, out string result) { var ptr = new JsVal(); bool ret = SpiderMonkey.JS_EvaluateScript(_cx, GetGlobalObject(), jsScript, (uint)jsScript.Length, "script", 1, ref ptr); // TODO: maybe getting JS_EvaluateScriptForPrincipals working would increase priviliges of the running script. //bool ret = SpiderMonkey.JS_EvaluateScriptForPrincipals(_cx, globalObject, ..., jsScript, (uint)jsScript.Length,"script", 1, ref ptr); result = ret ? ConvertValueToString(ptr) : null; return(ret); }
public void Dispose() { if (!_isDisposed) { _isDisposed = true; if (_cx != IntPtr.Zero) { SpiderMonkey.JS_LeaveCompartment(_cx, _oldCompartment); } GC.SuppressFinalize(this); } }
/// <summary> /// Evaluate JavaScript in specified window, and with specified scope. /// Throws GeckoJavaScriptException on error. /// </summary> /// <param name="javascript">The javascript to run.</param> /// <param name="window">The window to execuate javascript in. (ie. the global object)</param> /// <param name="scope">object to use as scope.</param> /// <returns>The return value of the script as a JsVal</returns> public JsVal EvaluateScript(string javascript, nsISupports window, nsISupports scope) { string msg = String.Empty; JsVal exceptionJsVal = default(JsVal); using (var globalObject = ConvertCOMObjectToJSObject(window)) using (new JSAutoCompartment(ContextPointer, globalObject.JSObject)) { var retJsVal = new JsVal(); bool ret; // If not running in window scope. if (window != scope) { using (var scopeObject = ConvertCOMObjectToJSObject(scope)) { var scopeJSVal = JsVal.FromPtr(scopeObject.JSObject); var go = globalObject.JSObject; if (!SpiderMonkey.JS_SetProperty(ContextPointer, ref go, "__RequestedScope", ref scopeJSVal)) { throw new GeckoException("Failed to set __RequestedScope Property."); } javascript = InsertReturnStatement(javascript); string s = "(function() { " + javascript + " }).call(this.__RequestedScope)"; ret = SpiderMonkey.JS_EvaluateScript(ContextPointer, s, (uint)s.Length, "script", 1, ref retJsVal); } } else { ret = SpiderMonkey.JS_EvaluateScript(ContextPointer, javascript, (uint)javascript.Length, "script", 1, ref retJsVal); } if (ret) { return(retJsVal); } var exception = SpiderMonkey.JS_GetPendingException(ContextPointer); if (exception != IntPtr.Zero) { exceptionJsVal = JsVal.FromPtr(exception); } msg += exceptionJsVal.ToString(); msg += SpiderMonkey.GetStackTrace(ContextPointer, globalObject.JSObject, exceptionJsVal); throw new GeckoJavaScriptException($"JSError : {msg}"); } }
public void Dispose() { if (_isDisposed) { return; } _isDisposed = true; if (_cx != IntPtr.Zero) { SpiderMonkey.JS_RequestLeaveCompartment(_cx, _oldCompartment); } _obj.Dispose(); GC.SuppressFinalize(this); }
/// <summary> /// Evaluate javascript in the current context. /// </summary> /// <param name="jsScript"></param> /// <param name="jsval"></param> /// <returns></returns> public bool EvaluateScript(string jsScript, out string result) { var ptr = new JsVal(); IntPtr globalObject = SpiderMonkey.JS_GetGlobalForScopeChain(_cx); bool ret = SpiderMonkey.JS_EvaluateScript(_cx, globalObject, jsScript, (uint)jsScript.Length, "script", 1, ref ptr); // TODO: maybe getting JS_EvaluateScriptForPrincipals working would increase priviliges of the running script. //bool ret = SpiderMonkey.JS_EvaluateScriptForPrincipals(_cx, globalObject, ..., jsScript, (uint)jsScript.Length,"script", 1, ref ptr); IntPtr jsStringPtr = SpiderMonkey.JS_ValueToString(_cx, ptr); result = Marshal.PtrToStringAnsi(SpiderMonkey.JS_EncodeString(_cx, jsStringPtr)); return(ret); }
/// <summary> /// Add hooks to listen for new JSContext creation and store the context for later use. /// </summary> internal static void Initialize() { Xpcom.AssertCorrectThread(); if (!_isInitialized) { _isInitialized = true; using (var runtimeService = new Gecko.Interop.ServiceWrapper <nsIJSRuntimeService>("@mozilla.org/js/xpc/RuntimeService;1")) { _originalContextCallback = SpiderMonkey.JS_SetContextCallback(Runtime, _globalContextCallback); } } }
public GeckoNode SelectSingle(string xpath) { var r = EvaluateXPathInternal(xpath); nsIDOMNode singleNode = null; using (var context = new AutoJSContext(Window)) using (var jsObject = context.ConvertCOMObjectToJSObject((nsISupports)r)) { // TODO: (Idenally I would generate these calls via a webidl-> C# compiler but for now just do it via manually written spidermonkey calls..) var resultType = SpiderMonkey.JS_GetProperty(context.ContextPointer, jsObject.JSObject, "resultType").ToInteger(); #if PORTFF60 switch (resultType) { case nsIDOMXPathResultConsts.UNORDERED_NODE_ITERATOR_TYPE: singleNode = (nsIDOMNode) SpiderMonkey.JS_CallFunctionName(context.ContextPointer, jsObject, "iterateNext", new JsVal[0]).ToComObject(context.ContextPointer); var test = (SpiderMonkey.JS_CallFunctionName(context.ContextPointer, jsObject, "iterateNext", new JsVal[0])); if (!test.IsNull) { Xpcom.FreeComObject(ref singleNode); Xpcom.FreeComObject(ref r); throw new GeckoDomException("There are more than 1 nodes in Single selection"); } break; case nsIDOMXPathResultConsts.FIRST_ORDERED_NODE_TYPE: case nsIDOMXPathResultConsts.ANY_UNORDERED_NODE_TYPE: singleNode = (nsIDOMNode) SpiderMonkey.JS_GetProperty(context.ContextPointer, jsObject, "singleNodeValue") .ToComObject(context.ContextPointer); break; } #endif throw new NotImplementedException(); } #if PORTFF60 var ret = singleNode.Wrap(GeckoNode.Create); Xpcom.FreeComObject(ref r); return(ret); #endif }
/// <summary> /// Helper method which attempts to find the global object in a Context. /// </summary> /// <returns>the Global object ptr or Null/Zero ptr if not found.</returns> private IntPtr GetGlobalFromContext(IntPtr context) { IntPtr globalObject = SpiderMonkey.CurrentGlobalOrNull(context); if (globalObject == IntPtr.Zero) { globalObject = SpiderMonkey.DefaultObjectForContextOrNull(context); if (globalObject == IntPtr.Zero) { return(IntPtr.Zero); } } return(globalObject); }
public JSAutoCompartment(IntPtr context, IntPtr obj) { if (context == IntPtr.Zero) { throw new ArgumentNullException("context"); } if (context == IntPtr.Zero) { throw new ArgumentNullException("obj"); } _obj = obj; _oldCompartment = SpiderMonkey.JS_EnterCompartment(context, _obj); _cx = context; }
internal string ConvertValueToString(JsVal value) { IntPtr jsp = SpiderMonkey.JS_ValueToString(_cx, value); if (jsp != IntPtr.Zero) { uint length; var chars = SpiderMonkey.JS_GetStringCharsAndLength(_cx, jsp, out length); if (chars != IntPtr.Zero) { return(Marshal.PtrToStringUni(chars, (int)length)); } } return(null); }
public IEnumerator <GeckoNode> GetEnumerator() { using (var context = new AutoJSContext()) { var jsObject = context.ConvertCOMObjectToJSObject((nsISupports)xpathResult); JsVal jsVal; do { while ( !(jsVal = SpiderMonkey.JS_CallFunctionName(context.ContextPointer, jsObject, "iterateNext")).IsNull) { yield return((jsVal.ToComObject(context.ContextPointer) as nsIDOMNode).Wrap(GeckoNode.Create)); } } while (!jsVal.IsNull); } }
/// <summary> /// Create a AutoJSContext using the SafeJSContext. /// If context is IntPtr.Zero use the SafeJSContext /// </summary> /// <param name="context"></param> public AutoJSContext(IntPtr context) { if (context == IntPtr.Zero) { context = GlobalJSContextHolder.SafeJSContext; } _cx = context; // TODO: calling BeginRequest may not be neccessary anymore. // begin a new request SpiderMonkey.JS_BeginRequest(_cx); // TODO: pushing the context onto the context stack may not be neccessary anymore. // push the context onto the context stack _contextStack = Xpcom.GetService <nsIJSContextStack>("@mozilla.org/js/xpc/ContextStack;1"); _contextStack.Push(_cx); }
public JSAutoCompartment(AutoJSContext context, nsISupports comObject) { if (context == null) { throw new ArgumentNullException("context"); } if (context.ContextPointer == IntPtr.Zero) { throw new ArgumentException("context has Null ContextPointer"); } if (context == null) { throw new ArgumentNullException("comObject"); } _obj = context.ConvertCOMObjectToJSObject(comObject); _cx = context.ContextPointer; _oldCompartment = SpiderMonkey.JS_EnterCompartment(_cx, _obj); }
private string GetStackTrace(IntPtr globalObject, JsVal exceptionJsVal) { if (!exceptionJsVal.IsObject) { return(String.Empty); } if (!SpiderMonkey.JS_SetProperty(ContextPointer, globalObject, "__RequestedScope", exceptionJsVal)) { throw new GeckoException("Failed to set __RequestedScope Property."); } const string s = "(function() { " + "return this.stack" + " }).call(this.__RequestedScope)"; var retJsVal = new JsVal(); var success = SpiderMonkey.JS_EvaluateScript(ContextPointer, s, (uint)s.Length, "script", 1, ref retJsVal); return(!success ? String.Empty : String.Format(" StackTrace: {0}", retJsVal)); }