protected override CefResourceHandler GetResourceHandler(CefBrowser browser, CefFrame frame, CefRequest request)
            {
                if (request.Url == OwnerWebView.DefaultLocalUrl)
                {
                    return(AsyncResourceHandler.FromText(OwnerWebView.htmlToLoad ?? ""));
                }

                if (UrlHelper.IsChromeInternalUrl(request.Url))
                {
                    return(null);
                }

                var resourceHandler = new ResourceHandler(request, OwnerWebView.GetRequestUrl(request.Url, (ResourceType)request.ResourceType));

                void TriggerBeforeResourceLoadEvent()
                {
                    var beforeResourceLoad = OwnerWebView.BeforeResourceLoad;

                    if (beforeResourceLoad != null)
                    {
                        OwnerWebView.ExecuteWithAsyncErrorHandling(() => beforeResourceLoad(resourceHandler));
                    }
                }

                if (Uri.TryCreate(resourceHandler.Url, UriKind.Absolute, out var url) && url.Scheme == ResourceUrl.EmbeddedScheme)
                {
                    resourceHandler.BeginAsyncResponse(() => {
                        var urlWithoutQuery = new UriBuilder(url);
                        if (!string.IsNullOrEmpty(url.Query))
                        {
                            urlWithoutQuery.Query = string.Empty;
                        }

                        OwnerWebView.ExecuteWithAsyncErrorHandling(() => ResourcesProvider.LoadEmbeddedResource(resourceHandler, urlWithoutQuery.Uri));

                        TriggerBeforeResourceLoadEvent();

                        if (resourceHandler.Handled || OwnerWebView.IgnoreMissingResources)
                        {
                            return;
                        }

                        var resourceLoadFailed = OwnerWebView.ResourceLoadFailed;
                        if (resourceLoadFailed != null)
                        {
                            resourceLoadFailed(url.ToString());
                        }
                        else
                        {
                            OwnerWebView.ForwardUnhandledAsyncException(new InvalidOperationException("Resource not found: " + url));
                        }
                    });
                }
                else
                {
                    TriggerBeforeResourceLoadEvent();
                }

                return(resourceHandler.Handler);
            }
            private void FlushScripts()
            {
#if DEBUG
                System.Diagnostics.Debug.WriteLine($"{nameof(FlushScripts)} running ('{Id}')");
#endif
                OwnerWebView.ExecuteWithAsyncErrorHandling(InnerFlushScripts);
            }
            protected override void OnRenderProcessTerminated(IWebBrowser chromiumWebBrowser, IBrowser browser, CefTerminationStatus status)
            {
                OwnerWebView.RenderProcessCrashed?.Invoke();

                const string ExceptionPrefix = "WebView render process ";

                Exception exception;

                switch (status)
                {
                case CefTerminationStatus.ProcessCrashed:
                    exception = new RenderProcessCrashedException(ExceptionPrefix + "crashed");
                    break;

                case CefTerminationStatus.ProcessWasKilled:
                    exception = new RenderProcessKilledException(ExceptionPrefix + "was killed", OwnerWebView.IsDisposing);
                    break;

                case CefTerminationStatus.OutOfMemory:
                    exception = new RenderProcessOutOfMemoryException(ExceptionPrefix + "ran out-of-memory");
                    break;

                default:
                    exception = new RenderProcessCrashedException(ExceptionPrefix + "terminated with an unknown reason");
                    break;
                }

                OwnerWebView.ForwardUnhandledAsyncException(exception);
            }
            private void InnerFlushScripts() {
                ScriptTask scriptToEvaluate = null;
                var scriptsToExecute = new List<ScriptTask>();

                do {
                    var scriptTask = PendingScripts.Take(FlushTaskCancelationToken.Token);
                    if (scriptTask.Evaluate == null) {
                        scriptsToExecute.Add(scriptTask);
                    } else { 
                        scriptToEvaluate = scriptTask;
                        break; // this script result needs to be handled separately
                    }
                } while (PendingScripts.Count > 0);

                if (scriptsToExecute.Count > 0) {
                    var script = string.Join(";" + Environment.NewLine, scriptsToExecute.Select(s => s.Script));
                    if (frame.IsValid) {
                        var frameName = frame.Name;
                        try {
                            var task = OwnerWebView.chromium.EvaluateJavaScript<object>(WrapScriptWithErrorHandling(script));
                            var timeout = OwnerWebView.DefaultScriptsExecutionTimeout ?? DefaultTimeout;
                            task.Wait((int)timeout.TotalMilliseconds, FlushTaskCancelationToken.Token);
                        } catch (Exception e) {
                            var evaluatedScriptFunctions = scriptsToExecute.Select(s => s.FunctionName);
                            OwnerWebView.ForwardUnhandledAsyncException(ParseException(e, evaluatedScriptFunctions), frameName);
                        }
                    }
                }

                if (scriptToEvaluate != null) {
                    scriptToEvaluate.Evaluate();
                }
            }
 private void FlushScripts() {
     OwnerWebView.ExecuteWithAsyncErrorHandling(() => {
         try {
             isFlushRunning = true;
             while (!FlushTaskCancelationToken.IsCancellationRequested) {
                 InnerFlushScripts();
             }
         } catch (OperationCanceledException) {
             // stop
         } finally {
             isFlushRunning = false;
             StoppedFlushHandle.Set();
         }
     });
 }
            private void BulkExecuteScripts(IEnumerable <ScriptTask> scriptsToExecute)
            {
                var script = string.Join(";" + Environment.NewLine, scriptsToExecute.Select(s => s.Script));

                if (frame.IsValid)
                {
                    var frameName = frame.Name;
                    try {
                        var timeout = OwnerWebView.DefaultScriptsExecutionTimeout ?? DefaultTimeout;
                        var task    = OwnerWebView.chromium.EvaluateJavaScript <object>(WrapScriptWithErrorHandling(script), timeout: timeout);
                        task.Wait(FlushTaskCancelationToken.Token);
                    } catch (OperationCanceledException) {
                        // ignore
                    } catch (Exception e) {
                        var evaluatedScriptFunctions = scriptsToExecute.Select(s => s.FunctionName);
                        OwnerWebView.ForwardUnhandledAsyncException(ParseException(e, evaluatedScriptFunctions), frameName);
                    }
                }
            }
            protected override bool OnBeforeBrowse(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool userGesture, bool isRedirect)
            {
                if (OwnerWebView.FilterUrl(request.Url))
                {
                    return(false);
                }

                if (OwnerWebView.IsHistoryDisabled && (request.TransitionType & TransitionType.ForwardBack) == TransitionType.ForwardBack)
                {
                    return(true);
                }

                bool cancel = false;

                if (OwnerWebView.BeforeNavigate != null)
                {
                    var wrappedRequest = new Request(request, OwnerWebView.GetRequestUrl(request.Url, (ResourceType)request.ResourceType));
                    OwnerWebView.ExecuteWithAsyncErrorHandling(() => OwnerWebView.BeforeNavigate(wrappedRequest));
                    cancel = wrappedRequest.Canceled;
                }

                return(cancel);
            }
            protected override bool OnBeforeBrowse(CefBrowser browser, CefFrame frame, CefRequest request, bool userGesture, bool isRedirect)
            {
                if (UrlHelper.IsInternalUrl(request.Url))
                {
                    return(false);
                }

                if (OwnerWebView.IsHistoryDisabled && request.TransitionType.HasFlag(CefTransitionType.ForwardBackFlag))
                {
                    return(true);
                }

                var cancel         = false;
                var beforeNavigate = OwnerWebView.BeforeNavigate;

                if (beforeNavigate != null)
                {
                    var wrappedRequest = new Request(request, OwnerWebView.GetRequestUrl(request.Url, (ResourceType)request.ResourceType));
                    OwnerWebView.ExecuteWithAsyncErrorHandling(() => beforeNavigate(wrappedRequest));
                    cancel = wrappedRequest.Canceled;
                }

                return(cancel);
            }