public bool AddLocalPlugin(object pluginObject)
        {
            var plugin = pluginObject as JavaScriptPlugin;

            if (plugin == null)
            {
                plugin = JavaScriptPlugin.CreateFromObject(_managerProcess, pluginObject);
                if (plugin == null)
                {
                    Logger.Error("Failed to wrap unknown plugin type");
                    return(false);
                }
            }

            if (!_localPluginsById.TryAdd(plugin.Descriptor.PluginId, plugin))
            {
                Logger.Warn("Attempt to add a duplicate plugin");
                return(false);
            }

            if (plugin.IsDynamic)
            {
                plugin.DynamicPluginDisposed += DynamicPluginDisposed;
            }

            Logger.Info("Local plugin added successfully: " + plugin.Descriptor.PluginId);
            return(true);
        }
        public PluginDescriptor AddDynamicPlugin(object pluginObject)
        {
            // Remove any dead references that may exist.
            _dynamicPluginRefs.RemoveAll(r => !r.IsAlive);

            // Check if a dynamic plugin has already been created for the specified target.
            var pluginRef = _dynamicPluginRefs.FirstOrDefault(wr => wr.MatchesTarget(pluginObject));

            if (pluginRef != null)
            {
                // Found one, return it's descriptor.
                return(pluginRef.Plugin.Descriptor);
            }

            // No existing dynamic plugin found. Create one and store a reference to it.
            var dynPlugin = JavaScriptPlugin.CreateFromObject(PluginProcess.Browser, pluginObject);

            pluginRef = new DynamicPluginRef(pluginObject, dynPlugin);
            _dynamicPluginRefs.Add(pluginRef);

            // Add the dynamic plugin to the plugin manager.
            PluginManager.AddLocalPlugin(dynPlugin);
            return(dynPlugin.Descriptor);
        }
        protected CefV8Value ToCefV8Value(IV8PluginRouter router, object result)
        {
            if (result == null)
            {
                return(CefV8Value.CreateNull());
            }

            // VALUES FROM REMOTE PLUGINS
            var remoteResult = result as ResultData;

            if (remoteResult != null)
            {
                switch (remoteResult.DataType)
                {
                case ResultDataType.Scalar:
                    if (remoteResult.Items != null && remoteResult.Items.Count != 0)
                    {
                        return(ToCefV8Value(router, remoteResult.Items[0]));
                    }
                    return(CefV8Value.CreateNull());

                case ResultDataType.Array:
                {
                    var cefArray = CefV8Value.CreateArray(remoteResult.Items.Count);
                    if (remoteResult.Items != null)
                    {
                        for (var resultIndex = 0; resultIndex < remoteResult.Items.Count; ++resultIndex)
                        {
                            var cefValue = ToCefV8Value(router, remoteResult.Items[resultIndex]);
                            cefArray.SetValue(resultIndex, cefValue);
                        }
                    }
                    return(cefArray);
                }

                case ResultDataType.Dictionary:
                {
                    var cefObject = CefV8Value.CreateObject(null);
                    if (remoteResult.Items != null)
                    {
                        foreach (var dictionaryItem in remoteResult.Items)
                        {
                            if (string.IsNullOrEmpty(dictionaryItem.Name))
                            {
                                continue;
                            }
                            var cefValue = ToCefV8Value(router, dictionaryItem);
                            cefObject.SetValue(dictionaryItem.Name, cefValue, CefV8PropertyAttribute.None);
                        }
                    }
                    return(cefObject);
                }
                }
            }
            var resultItem = result as ResultItem;

            if (resultItem != null)
            {
                return(ToCefV8Value(router, (object)resultItem.DynamicPlugin ?? resultItem.PlainData));
            }
            var pluginObjectDescriptor = result as PluginDescriptor;

            if (pluginObjectDescriptor != null)
            {
                return(V8PluginAdapter.CreateRemote(router, _plugin.PluginContext, pluginObjectDescriptor).V8Object);
            }

            // VALUES FROM REMOTE OR LOCAL PLUGINS
            var plainData = result as JToken;

            if (plainData != null)
            {
                return(CefJsonValueConverter.ToCef(plainData));
            }

            // VALUES FROM LOCAL PLUGINS
            var localArray = result as object[];

            if (localArray != null)
            {
                var cefArray = CefV8Value.CreateArray(localArray.Length);
                for (var resultIndex = 0; resultIndex < localArray.Length; ++resultIndex)
                {
                    var cefValue = ToCefV8Value(router, localArray[resultIndex]);
                    cefArray.SetValue(resultIndex, cefValue);
                }
                return(cefArray);
            }
            var localPlugin = result as JavaScriptPlugin;

            if (localPlugin != null)
            {
                return(V8PluginAdapter.CreateLocal(router, _plugin.PluginContext, localPlugin).V8Object);
            }
            if (JavaScriptPlugin.IsDynamicPlugin(result))
            {
                var dynPlugin = JavaScriptPlugin.CreateFromObject(PluginProcess.Renderer, result);
                _plugin.PluginContext.PluginManager.AddLocalPlugin(dynPlugin);
                return(V8PluginAdapter.CreateLocal(router, _plugin.PluginContext, dynPlugin).V8Object);
            }

            // local C# POCO
            return(CefNativeValueConverter.ToCef(result));
        }