/// <summary> /// Registers an object with the specified name in the window context of the browser /// </summary> /// <param name="name"></param> /// <param name="objectToBind"></param> /// <param name="interceptCall"></param> /// <param name="executeCallsInUI"></param> /// <returns>True if the object was registered or false if the object was already registered before</returns> public bool RegisterJavascriptObject(string name, object objectToBind, Func <Func <object>, object> interceptCall = null, bool executeCallsInUI = false) { if (chromium.IsJavascriptObjectRegistered(name)) { return(false); } if (executeCallsInUI) { return(RegisterJavascriptObject(name, objectToBind, target => ExecuteInUI <object>(target), false)); } if (interceptCall == null) { interceptCall = target => target(); } object CallTargetMethod(Func <object> target) { if (isDisposing) { return(null); } try { JavascriptPendingCalls.AddCount(); if (isDisposing) { // check again, to avoid concurrency problems with dispose return(null); } return(interceptCall(target)); } finally { JavascriptPendingCalls.Signal(); } } chromium.RegisterJavascriptObject(objectToBind, name, CallTargetMethod); return(true); }
private void Dispose(bool isDisposing = true) { if (isDisposing) { lock (SyncRoot) { if (this.isDisposing) { return; } this.isDisposing = true; } GC.SuppressFinalize(this); } var disposed = false; void InternalDispose() { if (disposed) { return; // bail-out } disposed = true; AsyncCancellationTokenSource?.Cancel(); WebViewInitialized = null; BeforeNavigate = null; BeforeResourceLoad = null; Navigated = null; LoadFailed = null; DownloadProgressChanged = null; DownloadCompleted = null; DownloadCancelled = null; JavascriptContextCreated = null; TitleChanged = null; UnhandledAsyncException = null; JavascriptContextReleased = null; foreach (var disposable in disposables.Concat(JsExecutors?.Values)) { disposable?.Dispose(); } Disposed?.Invoke(); } if (JavascriptPendingCalls?.CurrentCount > 1) { // avoid dead-lock, wait for all pending calls to finish Task.Run(() => { JavascriptPendingCalls?.Signal(); // remove dummy entry JavascriptPendingCalls?.Wait(); InternalDispose(); }); return; } InternalDispose(); }
private void InnerDispose() { lock (SyncRoot) { if (isDisposing) { return; } isDisposing = true; } var disposed = false; void InternalDispose() { if (disposed) { return; // bail-out } disposed = true; AsyncCancellationTokenSource?.Cancel(); chromium.JavascriptContextCreated -= OnJavascriptContextCreated; chromium.JavascriptContextReleased -= OnJavascriptContextReleased; WebViewInitialized = null; BeforeNavigate = null; BeforeResourceLoad = null; Navigated = null; LoadFailed = null; DownloadProgressChanged = null; DownloadCompleted = null; DownloadCancelled = null; JavascriptContextCreated = null; TitleChanged = null; UnhandledAsyncException = null; JavascriptContextReleased = null; // dispose the js executors before the browser to prevent (the browser) from throwing cancellation exceptions DisposeJavascriptExecutors(); foreach (var disposable in disposables) { disposable?.Dispose(); } Disposed?.Invoke(); } if (JavascriptPendingCalls?.CurrentCount > 1) { // avoid dead-lock, wait for all pending calls to finish Task.Run(() => { JavascriptPendingCalls?.Signal(); // remove dummy entry JavascriptPendingCalls?.Wait(); InternalDispose(); }); return; } InternalDispose(); }