private LocalRenderCallInfo AddLocalCallback(PluginMessage pluginMessage, IV8Callback callback, IJavaScriptParameterCallback parameterCallback) { var info = new LocalRenderCallInfo(this, pluginMessage, callback, parameterCallback); _pendingCallbacks.Add(info); return(info); }
public void RemoveEventListener(JavaScriptPlugin targetPlugin, string eventName, IV8Callback callback) { Logger.Info("RemoveEventListener Local Plugin {0} Event {1}", targetPlugin.Descriptor.PluginId, eventName); if (!EnsureOnRendererThread()) { return; } try { var info = (LocalRenderCallInfo)_pendingCallbacks.Remove(callback.Identifier); info.Dispose(); targetPlugin.RemoveEventListener(eventName, info); } catch (Exception exception) { Logger.Error("RemoveEventListener Failed Local Plugin {0} Event {1}: {2}", targetPlugin.Descriptor.PluginId, eventName, exception); } }
private RenderCallInfo AddRemoteCallback(PluginMessage pluginMessage, IV8Callback callback) { var info = new RenderCallInfo(pluginMessage, callback); _pendingCallbacks.Add(info); return(info); }
/// <summary> /// Invoke a local function. /// </summary> /// <param name="context"> /// The current V8 context that is making the function call. /// </param> /// <param name="targetPlugin"> /// The local plugin that owns the target method. /// </param> /// <param name="methodDescriptor"> /// The method to invoke. /// </param> /// <param name="parameters"> /// An interface for the local plugin to obtain the parameters from before invoking the function. /// </param> /// <param name="callback"> /// Optional callback into V8. /// </param> public void InvokeFunction( CefV8Context context, JavaScriptPlugin targetPlugin, MethodDescriptor methodDescriptor, IJavaScriptParameters parameters, IV8Callback callback) { Logger.Info("InvokeFunction Local Plugin {0} Method {1}", targetPlugin.Descriptor.PluginId, methodDescriptor.MethodName); if (!EnsureOnRendererThread()) { return; } if (!targetPlugin.IsValid) { Logger.Warn("InvokeFunction Local Plugin {0} is invalid", targetPlugin.Descriptor.PluginId); if (callback != null) { callback.Invoke(this, context, null, CallInfo.ErrorCodeCallCanceled, CallInfo.ErrorCallCanceled); } return; } var parameterCallbackInfo = GetOrCreateParameterCallback(context, methodDescriptor, callback); var functionInvokeMessage = CreateMessage(context, targetPlugin.Descriptor, methodDescriptor.MethodName, callback); functionInvokeMessage.MessageId = Guid.NewGuid(); functionInvokeMessage.MessageType = PluginMessageType.FunctionInvoke; // Add the call info into the pending calls for the browser var info = methodDescriptor.HasCallbackParameter ? AddLocalCallback(functionInvokeMessage, null, parameterCallbackInfo) : AddLocalCallback(functionInvokeMessage, callback, null); try { targetPlugin.InvokeFunctionDirect( null, functionInvokeMessage.BrowserId, functionInvokeMessage.FrameId, functionInvokeMessage.ContextId, methodDescriptor.MethodName, parameters, info); } catch (Exception ex) { LocalCallbackInvoked(info, null, -1, ex.Message); Logger.Error("InvokeFunction Failed Local Plugin {0} Method {1}: {2}", targetPlugin.Descriptor.PluginId, methodDescriptor.MethodName, ex); } }
/// <summary> /// Invoke a remote function. /// </summary> /// <param name="context"> /// The current V8 context that is making the function call. /// </param> /// <param name="targetPlugin"> /// The remote plugin that owns the target method. /// </param> /// <param name="methodDescriptor"> /// The method to invoke. /// </param> /// <param name="parameters"> /// The parameters to pass to the remote function. /// </param> /// <param name="callback"> /// Optional callback into V8. /// </param> public void InvokeFunction( CefV8Context context, PluginDescriptor targetPlugin, MethodDescriptor methodDescriptor, JArray parameters, IV8Callback callback) { Logger.Debug("InvokeFunction Remote Plugin {0} Method {1}", targetPlugin.PluginId, methodDescriptor.MethodName); if (!EnsureOnRendererThread()) { return; } GetOrCreateParameterCallback(context, methodDescriptor, callback); var functionInvokeMessage = CreateMessage(context, targetPlugin, methodDescriptor.MethodName, callback); functionInvokeMessage.MessageId = Guid.NewGuid(); functionInvokeMessage.MessageType = PluginMessageType.FunctionInvoke; functionInvokeMessage.Data = parameters != null?parameters.ToString() : string.Empty; // Add the call info into the pending calls for the browser if the return type // is not void or the method has a callback arg. // TODO: We should verify that the signature of the JavaScript call matches the plugin method and throw an exception for invalid invocations. if (!methodDescriptor.IsVoid || methodDescriptor.HasCallbackParameter || callback != null) { AddRemoteCallback(functionInvokeMessage, methodDescriptor.HasCallbackParameter ? null : callback); } try { using (var browser = context.GetBrowser()) { // Send the request message to the browser SendMessage(browser, functionInvokeMessage); } } catch (Exception ex) { // If the request could not be sent, remove the call from the list var error = new ResultData { ErrorCode = -1, Error = ex.Message }; OnBrowserCallbackInvokeReceived(functionInvokeMessage, error); Logger.Error("InvokeFunction Failed Remote Plugin {0} Method {1}: {2}", targetPlugin.PluginId, methodDescriptor.MethodName, ex); } }
private PluginMessage CreateMessage( CefV8Context context, PluginDescriptor targetPlugin, string memberName, IV8Callback callback) { var message = new PluginMessage { PluginId = targetPlugin.PluginId, MemberName = memberName, BrowserId = context.GetBrowserId(), ContextId = GetIdForContext(context, false), FrameId = context.GetFrame().Identifier, V8CallbackId = callback != null ? callback.Identifier : Guid.Empty }; return(message); }
private LocalRenderCallInfo GetOrCreateParameterCallback(CefV8Context context, MethodDescriptor methodDescriptor, IV8Callback callback) { LocalRenderCallInfo parameterCallbackInfo = null; if (methodDescriptor.HasCallbackParameter && callback != null) { // Create a second stored callback info which represents the V8 callback function itself // rather than the method that is being invoked now. This allows the callback function // to be passed to and invoked by multiple native methods that accept a callback parameter. parameterCallbackInfo = (LocalRenderCallInfo)_pendingCallbacks.Get(callback.Identifier); if (parameterCallbackInfo == null) { var parameterCallbackMessage = new PluginMessage { MessageId = callback.Identifier, MessageType = PluginMessageType.ParameterCallback, PluginId = string.Empty, MemberName = string.Empty, BrowserId = context.GetBrowserId(), ContextId = GetIdForContext(context, false), FrameId = context.GetFrame().Identifier, V8CallbackId = Guid.Empty }; parameterCallbackInfo = AddLocalCallback(parameterCallbackMessage, callback, null); } } return(parameterCallbackInfo); }
/// <summary> /// Add a local V8 callback to a local event as a listener. /// </summary> /// <param name="context"> /// The current V8 context that is adding the listener. /// </param> /// <param name="targetPlugin"> /// The local plugin that owns the event. /// </param> /// <param name="eventName"> /// The name of the event to attach to. /// </param> /// <param name="callback"> /// The callback to V8 to invoke when the event is raised. /// </param> public void AddEventListener(CefV8Context context, JavaScriptPlugin targetPlugin, string eventName, IV8Callback callback) { Logger.Info("AddEventListener Local Plugin {0} Event {1}", targetPlugin.Descriptor.PluginId, eventName); if (!EnsureOnRendererThread()) { return; } if (!targetPlugin.IsValid) { Logger.Warn("AddEventListener Local Plugin {0} is invalid", targetPlugin.Descriptor.PluginId); if (callback != null) { callback.Invoke(this, context, null, CallInfo.ErrorCodeCallCanceled, CallInfo.ErrorCallCanceled); } return; } var addListenerMessage = CreateMessage(context, targetPlugin.Descriptor, eventName, callback); addListenerMessage.MessageId = callback.Identifier; addListenerMessage.MessageType = PluginMessageType.AddListener; // Add the call info into the pending calls for the browser var info = AddLocalCallback(addListenerMessage, callback, null); try { targetPlugin.AddEventListener(eventName, info); } catch (Exception ex) { // Remove listener from calls cache _pendingCallbacks.Remove(info); info.Dispose(); Logger.Error("AddEventListener Failed Local Plugin {0} Event {1}: {2}", targetPlugin.Descriptor.PluginId, eventName, ex); } }
/// <summary> /// Remove a local V8 callback from a remote event. /// </summary> /// <param name="context"> /// The current V8 context that is removing the listener. /// </param> /// <param name="targetPlugin"> /// The remote plugin that owns the event. /// </param> /// <param name="eventName"> /// The name of the event to detach from. /// </param> /// <param name="callback"> /// The callback to remove.</param> public void RemoveEventListener(CefV8Context context, PluginDescriptor targetPlugin, string eventName, IV8Callback callback) { Logger.Info("RemoveEventListener Remote Plugin {0} Event {1}", targetPlugin.PluginId, eventName); if (!EnsureOnRendererThread()) { return; } var callId = callback.Identifier; var info = _pendingCallbacks.Remove(callId); info.Dispose(); var removeListenerMessage = CreateMessage(context, targetPlugin, eventName, callback); // Use identifier from callback as ID for listener message. // Remote process will find and remove listener based on the MessageId. removeListenerMessage.MessageId = callId; removeListenerMessage.MessageType = PluginMessageType.RemoveRetained; removeListenerMessage.Data = string.Empty; // Send the request message to the browser try { using (var browser = context.GetBrowser()) { SendMessage(browser, removeListenerMessage); } } catch (Exception ex) { Logger.Error("RemoveEventListener Failed Remote Plugin {0} Event {1}: {2}", targetPlugin.PluginId, eventName, ex); } }
/// <summary> /// Add a local V8 callback to a remote event as a listener. /// </summary> /// <param name="context"> /// The current V8 context that is adding the listener. /// </param> /// <param name="targetPlugin"> /// The remote plugin that owns the event. /// </param> /// <param name="eventName"> /// The name of the event to attach to. /// </param> /// <param name="callback"> /// The callback to V8 to invoke when the remote event is raised. /// </param> public void AddEventListener(CefV8Context context, PluginDescriptor targetPlugin, string eventName, IV8Callback callback) { Logger.Info("AddEventListener Remote Plugin {0} Event {1}", targetPlugin.PluginId, eventName); if (!EnsureOnRendererThread()) { return; } var addListenerMessage = CreateMessage(context, targetPlugin, eventName, callback); // Use identifier from callback as ID for listener message. // When remote event fired, renderer will receive an EventFired message with this same ID as its MessageId. addListenerMessage.MessageId = callback.Identifier; addListenerMessage.MessageType = PluginMessageType.AddListener; addListenerMessage.Data = string.Empty; // Add the call info into the pending calls for the browser var info = AddRemoteCallback(addListenerMessage, callback); // Send the request message to the browser try { using (var browser = context.GetBrowser()) { SendMessage(browser, addListenerMessage); } } catch (Exception ex) { // If the request could not be sent, remove the call from the list _pendingCallbacks.Remove(info); info.Dispose(); Logger.Error("AddEventListener Failed Remote Plugin {0} Event {1}: {2}", targetPlugin.PluginId, eventName, ex); } }
public LocalRenderCallInfo(IRenderSideMessageRouter router, PluginMessage requestMesage, IV8Callback callback, IJavaScriptParameterCallback parameterCallback) : base(requestMesage, callback) { _router = router; _parameterCallback = parameterCallback; }
public RenderCallInfo(PluginMessage requestMessage, IV8Callback callback) : base(requestMessage) { Callback = callback; }