/// <summary> /// Retrieves command call parameters and creates wrapper for them /// </summary> /// <param name="commandStr">Command string in the form 'service/action/callback/args'</param> /// <returns>New class instance or null of string does not represent Cordova command</returns> public static CordovaCommandCall Parse(string commandStr) { if (string.IsNullOrEmpty(commandStr)) { return null; //throw new ArgumentNullException("commandStr"); } string[] split = commandStr.Split('/'); if (split.Length < 3) { return null; } var commandCallParameters = new CordovaCommandCall(); commandCallParameters.Service = split[0]; commandCallParameters.Action = split[1]; commandCallParameters.CallbackId = split[2]; commandCallParameters.Args = split.Length <= 3 ? String.Empty : String.Join("/", split.Skip(3)); // sanity check for illegal names // was failing with :: // CordovaCommandResult :: 1, Device1, {"status":1,"message":"{\"name\":\"XD..... if (commandCallParameters.Service.IndexOfAny(new[] {'@', ':', ',', '!', ' '}) > -1) { return null; } return commandCallParameters; }
/// <summary> /// Executes command and returns result back. /// </summary> /// <param name="commandCallParams">Command to execute</param> public void ProcessCommand(CordovaCommandCall commandCallParams) { if (commandCallParams == null) { throw new ArgumentNullException("commandCallParams"); } webBrowser.AddCommandId(commandCallParams.CallbackId); try { BaseCommand bc = CommandFactory.CreateByServiceName(commandCallParams.Service); if (bc == null) { OnCommandResult(commandCallParams.CallbackId, new PluginResult(PluginResult.Status.CLASS_NOT_FOUND_EXCEPTION)); return; } EventHandler<PluginResult> onCommandResultHandler = (o, res) => OnCommandResult(commandCallParams.CallbackId, res); bc.OnCommandResult += onCommandResultHandler; EventHandler<ScriptCallback> onCustomScriptHandler = (o, script) => InvokeScriptCallback(script); bc.OnCustomScript += onCustomScriptHandler; // TODO: alternative way is using thread pool (ThreadPool.QueueUserWorkItem) instead of // new thread for every command call; but num threads are not sufficient - 2 threads per CPU core var thread = new Thread(func => { try { bc.InvokeMethodNamed(commandCallParams.Action, commandCallParams.Args); } catch (Exception) { bc.OnCommandResult -= onCommandResultHandler; bc.OnCustomScript -= onCustomScriptHandler; Debug.WriteLine("failed to InvokeMethodNamed :: " + commandCallParams.Action + " on Object :: " + commandCallParams.Service); OnCommandResult(commandCallParams.CallbackId, new PluginResult(PluginResult.Status.INVALID_ACTION)); return; } }); thread.Start(); } catch (Exception ex) { // ERROR Debug.WriteLine(String.Format("Unable to execute command :: {0}:{1}:{3} ", commandCallParams.Service, commandCallParams.Action, ex.Message)); OnCommandResult(commandCallParams.CallbackId, new PluginResult(PluginResult.Status.ERROR)); return; } }