| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -237,15 +237,15 @@ Task<JavascriptResponse^>^ CefFrameWrapper::EvaluateScriptAsync(String^ script, | |||
| 237 | 237 | //If we're unable to get the underlying browser/browserhost then return null | |
| 238 | 238 | if (!browser.get() || !host.get()) | |
| 239 | 239 | { | |
| 240 | - return nullptr; | ||
| 240 | + return Task::FromException<JavascriptResponse^>(gcnew InvalidOperationException("Browser host not available")); | ||
| 241 | 241 | } | |
| 242 | 242 | ||
| 243 | 243 | auto client = static_cast<ClientAdapter*>(host->GetClient().get()); | |
| 244 | 244 | ||
| 245 | 245 | auto pendingTaskRepository = client->GetPendingTaskRepository(); | |
| 246 | 246 | ||
| 247 | 247 | //create a new taskcompletionsource | |
| 248 | - auto idAndComplectionSource = pendingTaskRepository->CreatePendingTask(timeout); | ||
| 248 | + auto idAndComplectionSource = pendingTaskRepository->CreatePendingTask(Identifier, timeout); | ||
| 249 | 249 | ||
| 250 | 250 | if (useImmediatelyInvokedFuncExpression) | |
| 251 | 251 | { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -701,6 +701,8 @@ namespace CefSharp | |||
| 701 | 701 | ||
| 702 | 702 | void ClientAdapter::OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser, TerminationStatus status, int errorCode, const CefString& errorString) | |
| 703 | 703 | { | |
| 704 | + _pendingTaskRepository->CancelPendingTasks(); | ||
| 705 | + | ||
| 704 | 706 | auto handler = _browserControl->RequestHandler; | |
| 705 | 707 | ||
| 706 | 708 | if (handler != nullptr) | |
@@ -1382,9 +1384,13 @@ namespace CefSharp | |||
| 1382 | 1384 | //we get here, only continue if we have a valid frame reference | |
| 1383 | 1385 | if (frame.get() && frame->IsValid()) | |
| 1384 | 1386 | { | |
| 1387 | + auto frameId = StringUtils::ToClr(frame->GetIdentifier()); | ||
| 1388 | + | ||
| 1389 | + _pendingTaskRepository->CancelPendingTasks(frameId); | ||
| 1390 | + | ||
| 1385 | 1391 | if (frame->IsMain()) | |
| 1386 | 1392 | { | |
| 1387 | - _browserControl->SetCanExecuteJavascriptOnMainFrame(StringUtils::ToClr(frame->GetIdentifier()), false); | ||
| 1393 | + _browserControl->SetCanExecuteJavascriptOnMainFrame(frameId, false); | ||
| 1388 | 1394 | } | |
| 1389 | 1395 | ||
| 1390 | 1396 | auto handler = _browserControl->RenderProcessMessageHandler; | |
@@ -1475,14 +1481,16 @@ namespace CefSharp | |||
| 1475 | 1481 | return true; | |
| 1476 | 1482 | } | |
| 1477 | 1483 | ||
| 1484 | + auto frameId = StringUtils::ToClr(frame->GetIdentifier()); | ||
| 1485 | + | ||
| 1478 | 1486 | auto callbackFactory = browserAdapter->JavascriptCallbackFactory; | |
| 1479 | 1487 | ||
| 1480 | 1488 | auto success = argList->GetBool(0); | |
| 1481 | 1489 | auto callbackId = GetInt64(argList, 1); | |
| 1482 | 1490 | ||
| 1483 | 1491 | auto pendingTask = name == kEvaluateJavascriptResponse ? | |
| 1484 | - _pendingTaskRepository->RemovePendingTask(callbackId) : | ||
| 1485 | - _pendingTaskRepository->RemoveJavascriptCallbackPendingTask(callbackId); | ||
| 1492 | + _pendingTaskRepository->RemovePendingTask(frameId, callbackId) : | ||
| 1493 | + _pendingTaskRepository->RemoveJavascriptCallbackPendingTask(frameId, callbackId); | ||
| 1486 | 1494 | ||
| 1487 | 1495 | if (pendingTask != nullptr) | |
| 1488 | 1496 | { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -70,8 +70,7 @@ namespace CefSharp | |||
| 70 | 70 | ||
| 71 | 71 | CloseAllPopups(true); | |
| 72 | 72 | ||
| 73 | - //this will dispose the repository and cancel all pending tasks | ||
| 74 | - delete _pendingTaskRepository; | ||
| 73 | + _pendingTaskRepository->CancelPendingTasks(); | ||
| 75 | 74 | ||
| 76 | 75 | _browser = nullptr; | |
| 77 | 76 | _browserControl = nullptr; | |
@@ -80,6 +79,7 @@ namespace CefSharp | |||
| 80 | 79 | _tooltip = nullptr; | |
| 81 | 80 | _browserAdapter = nullptr; | |
| 82 | 81 | _popupBrowsers = nullptr; | |
| 82 | + _pendingTaskRepository = nullptr; | ||
| 83 | 83 | } | |
| 84 | 84 | ||
| 85 | 85 | HWND GetBrowserHwnd() { return _browserHwnd; } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -27,30 +27,31 @@ namespace CefSharp | |||
| 27 | 27 | auto browser = GetBrowser(); | |
| 28 | 28 | if (browser == nullptr) | |
| 29 | 29 | { | |
| 30 | - throw gcnew InvalidOperationException("Browser instance is null. Check CanExecute before calling this method."); | ||
| 30 | + return Task::FromException<JavascriptResponse^>(gcnew InvalidOperationException("Browser instance is null. Check CanExecute before calling this method.")); | ||
| 31 | 31 | } | |
| 32 | 32 | ||
| 33 | 33 | auto browserWrapper = static_cast<CefBrowserWrapper^>(browser); | |
| 34 | - auto javascriptNameConverter = GetJavascriptNameConverter(); | ||
| 35 | - | ||
| 36 | - auto doneCallback = _pendingTasks->CreateJavascriptCallbackPendingTask(_callback->Id, timeout); | ||
| 37 | - | ||
| 38 | - auto callbackMessage = CefProcessMessage::Create(kJavascriptCallbackRequest); | ||
| 39 | - auto argList = callbackMessage->GetArgumentList(); | ||
| 40 | - SetInt64(argList, 0, doneCallback.Key); | ||
| 41 | - SetInt64(argList, 1, _callback->Id); | ||
| 42 | - auto paramList = CefListValue::Create(); | ||
| 43 | - for (int i = 0; i < parameters->Length; i++) | ||
| 44 | - { | ||
| 45 | - auto param = parameters[i]; | ||
| 46 | - SerializeV8Object(paramList, i, param, javascriptNameConverter); | ||
| 47 | - } | ||
| 48 | - argList->SetList(2, paramList); | ||
| 49 | 34 | ||
| 50 | 35 | auto frame = browserWrapper->Browser->GetFrameByIdentifier(StringUtils::ToNative(_callback->FrameId)); | |
| 51 | 36 | ||
| 52 | 37 | if (frame.get() && frame->IsValid()) | |
| 53 | 38 | { | |
| 39 | + auto javascriptNameConverter = GetJavascriptNameConverter(); | ||
| 40 | + | ||
| 41 | + auto doneCallback = _pendingTasks->CreateJavascriptCallbackPendingTask(_callback->FrameId, _callback->Id, timeout); | ||
| 42 | + | ||
| 43 | + auto callbackMessage = CefProcessMessage::Create(kJavascriptCallbackRequest); | ||
| 44 | + auto argList = callbackMessage->GetArgumentList(); | ||
| 45 | + SetInt64(argList, 0, doneCallback.Key); | ||
| 46 | + SetInt64(argList, 1, _callback->Id); | ||
| 47 | + auto paramList = CefListValue::Create(); | ||
| 48 | + for (int i = 0; i < parameters->Length; i++) | ||
| 49 | + { | ||
| 50 | + auto param = parameters[i]; | ||
| 51 | + SerializeV8Object(paramList, i, param, javascriptNameConverter); | ||
| 52 | + } | ||
| 53 | + argList->SetList(2, paramList); | ||
| 54 | + | ||
| 54 | 55 | frame->SendProcessMessage(CefProcessId::PID_RENDERER, callbackMessage); | |
| 55 | 56 | ||
| 56 | 57 | return doneCallback.Value->Task; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -8,6 +8,7 @@ | |||
| 8 | 8 | using System.Text; | |
| 9 | 9 | using System.Threading.Tasks; | |
| 10 | 10 | using Bogus; | |
| 11 | + using CefSharp.Example; | ||
| 11 | 12 | using Xunit; | |
| 12 | 13 | using Xunit.Abstractions; | |
| 13 | 14 | using Xunit.Repeat; | |
@@ -26,6 +27,52 @@ public EvaluateScriptAsyncTests(ITestOutputHelper output, CefSharpFixture collec | |||
| 26 | 27 | this.collectionFixture = collectionFixture; | |
| 27 | 28 | } | |
| 28 | 29 | ||
| 30 | + [Fact] | ||
| 31 | + public async Task V8Context() | ||
| 32 | + { | ||
| 33 | + Task evaluateCancelAfterDisposeTask; | ||
| 34 | + using (var browser = new CefSharp.OffScreen.ChromiumWebBrowser(automaticallyCreateBrowser: false)) | ||
| 35 | + { | ||
| 36 | + await browser.CreateBrowserAsync(); | ||
| 37 | + | ||
| 38 | + // no V8 context | ||
| 39 | + var withoutV8ContextException = await Assert.ThrowsAsync<Exception>(() => browser.EvaluateScriptAsync("1+1")); | ||
| 40 | + Assert.StartsWith("Unable to execute javascript at this time", withoutV8ContextException.Message); | ||
| 41 | + | ||
| 42 | + Task<JavascriptResponse> evaluateWithoutV8ContextTask; | ||
| 43 | + using (var frame = browser.GetMainFrame()) | ||
| 44 | + { | ||
| 45 | + evaluateWithoutV8ContextTask = frame.EvaluateScriptAsync("1+2"); | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + // V8 context | ||
| 49 | + await browser.LoadUrlAsync(CefExample.HelloWorldUrl); | ||
| 50 | + var evaluateWithoutV8ContextResponse = await evaluateWithoutV8ContextTask; | ||
| 51 | + Assert.True(evaluateWithoutV8ContextResponse.Success); | ||
| 52 | + Assert.Equal(3, evaluateWithoutV8ContextResponse.Result); | ||
| 53 | + | ||
| 54 | + var evaluateCancelAfterV8ContextChangeTask = browser.EvaluateScriptAsync("new Promise(resolve => setTimeout(resolve, 1000))"); | ||
| 55 | + | ||
| 56 | + // change V8 context | ||
| 57 | + await browser.LoadUrlAsync(CefExample.HelloWorldUrl); | ||
| 58 | + | ||
| 59 | + await Assert.ThrowsAsync<TaskCanceledException>(() => evaluateCancelAfterV8ContextChangeTask); | ||
| 60 | + | ||
| 61 | + evaluateCancelAfterDisposeTask = browser.EvaluateScriptAsync("new Promise(resolve => setTimeout(resolve, 1000))"); | ||
| 62 | + } | ||
| 63 | + await Assert.ThrowsAsync<TaskCanceledException>(() => evaluateCancelAfterDisposeTask); | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + [Fact] | ||
| 67 | + public async Task CancelEvaluateOnCrash() | ||
| 68 | + { | ||
| 69 | + AssertInitialLoadComplete(); | ||
| 70 | + | ||
| 71 | + var task = Browser.EvaluateScriptAsync("new Promise(resolve => setTimeout(resolve, 1000))"); | ||
| 72 | + await Browser.LoadUrlAsync("chrome://crash"); | ||
| 73 | + await Assert.ThrowsAsync<TaskCanceledException>(() => task); | ||
| 74 | + } | ||
| 75 | + | ||
| 29 | 76 | [Theory] | |
| 30 | 77 | [InlineData(double.MaxValue, "Number.MAX_VALUE")] | |
| 31 | 78 | [InlineData(double.MaxValue / 2, "Number.MAX_VALUE / 2")] | |
@@ -264,7 +311,7 @@ public async Task CanEvaluateScriptAsyncReturnArrayBuffer(int iteration) | |||
| 264 | 311 | ||
| 265 | 312 | var randomizer = new Randomizer(); | |
| 266 | 313 | ||
| 267 | - var expected = randomizer.Utf16String(minLength: iteration, maxLength:iteration); | ||
| 314 | + var expected = randomizer.Utf16String(minLength: iteration, maxLength: iteration); | ||
| 268 | 315 | var expectedBytes = Encoding.UTF8.GetBytes(expected); | |
| 269 | 316 | ||
| 270 | 317 | var javascriptResponse = await Browser.EvaluateScriptAsync($"new TextEncoder().encode('{expected}').buffer"); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -6,6 +6,7 @@ | |||
| 6 | 6 | using System.Dynamic; | |
| 7 | 7 | using System.Globalization; | |
| 8 | 8 | using System.Threading.Tasks; | |
| 9 | + using CefSharp.Example; | ||
| 9 | 10 | using Xunit; | |
| 10 | 11 | using Xunit.Abstractions; | |
| 11 | 12 | ||
@@ -23,6 +24,68 @@ public JavascriptCallbackTests(ITestOutputHelper output, CefSharpFixture collect | |||
| 23 | 24 | this.collectionFixture = collectionFixture; | |
| 24 | 25 | } | |
| 25 | 26 | ||
| 27 | + [Fact] | ||
| 28 | + public async Task V8Context() | ||
| 29 | + { | ||
| 30 | + Task callbackExecuteCancelAfterDisposeTask; | ||
| 31 | + using (var browser = new CefSharp.OffScreen.ChromiumWebBrowser(automaticallyCreateBrowser: false)) | ||
| 32 | + { | ||
| 33 | + await browser.CreateBrowserAsync(); | ||
| 34 | + | ||
| 35 | + // no V8 context | ||
| 36 | + var withoutV8ContextException = await Assert.ThrowsAsync<Exception>(() => browser.EvaluateScriptAsync("(function() { return 1+1; })")); | ||
| 37 | + Assert.StartsWith("Unable to execute javascript at this time", withoutV8ContextException.Message); | ||
| 38 | + | ||
| 39 | + Task<JavascriptResponse> callbackExecuteWithoutV8ContextTask; | ||
| 40 | + using (var frame = browser.GetMainFrame()) | ||
| 41 | + { | ||
| 42 | + callbackExecuteWithoutV8ContextTask = frame.EvaluateScriptAsync("(function() { return 1+2; })"); | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + // V8 context | ||
| 46 | + await browser.LoadUrlAsync(CefExample.HelloWorldUrl); | ||
| 47 | + | ||
| 48 | + var callbackExecuteWithoutV8ContextResponse = await callbackExecuteWithoutV8ContextTask; | ||
| 49 | + Assert.True(callbackExecuteWithoutV8ContextResponse.Success); | ||
| 50 | + var callbackExecuteWithoutV8ContextCallback = (IJavascriptCallback)callbackExecuteWithoutV8ContextResponse.Result; | ||
| 51 | + var callbackExecuteWithoutV8ContextExecuteResponse = await callbackExecuteWithoutV8ContextCallback.ExecuteAsync(); | ||
| 52 | + Assert.True(callbackExecuteWithoutV8ContextExecuteResponse.Success); | ||
| 53 | + Assert.Equal(3, callbackExecuteWithoutV8ContextExecuteResponse.Result); | ||
| 54 | + | ||
| 55 | + var callbackExecuteCancelAfterV8ContextResponse = await browser.EvaluateScriptAsync("(function() { return new Promise(resolve => setTimeout(resolve, 1000)); })"); | ||
| 56 | + Assert.True(callbackExecuteCancelAfterV8ContextResponse.Success); | ||
| 57 | + var evaluateCancelAfterV8ContextCallback = (IJavascriptCallback)callbackExecuteCancelAfterV8ContextResponse.Result; | ||
| 58 | + var evaluateCancelAfterV8ContextTask = evaluateCancelAfterV8ContextCallback.ExecuteAsync(); | ||
| 59 | + | ||
| 60 | + // change V8 context | ||
| 61 | + await browser.LoadUrlAsync(CefExample.HelloWorldUrl); | ||
| 62 | + | ||
| 63 | + await Assert.ThrowsAsync<TaskCanceledException>(() => evaluateCancelAfterV8ContextTask); | ||
| 64 | + | ||
| 65 | + var callbackExecuteCancelAfterDisposeResponse = await browser.EvaluateScriptAsync("(function() { return new Promise(resolve => setTimeout(resolve, 1000)); })"); | ||
| 66 | + Assert.True(callbackExecuteCancelAfterDisposeResponse.Success); | ||
| 67 | + var callbackExecuteCancelAfterDisposeCallback = (IJavascriptCallback)callbackExecuteCancelAfterDisposeResponse.Result; | ||
| 68 | + callbackExecuteCancelAfterDisposeTask = callbackExecuteCancelAfterDisposeCallback.ExecuteAsync(); | ||
| 69 | + } | ||
| 70 | + await Assert.ThrowsAsync<TaskCanceledException>(() => callbackExecuteCancelAfterDisposeTask); | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + [Fact] | ||
| 74 | + public async Task CancelCallbackOnCrash() | ||
| 75 | + { | ||
| 76 | + AssertInitialLoadComplete(); | ||
| 77 | + | ||
| 78 | + var javascriptResponse = await Browser.EvaluateScriptAsync("(function() { return new Promise(resolve => setTimeout(resolve, 1000)); })"); | ||
| 79 | + Assert.True(javascriptResponse.Success); | ||
| 80 | + | ||
| 81 | + var callback = (IJavascriptCallback)javascriptResponse.Result; | ||
| 82 | + | ||
| 83 | + var task = callback.ExecuteAsync(); | ||
| 84 | + | ||
| 85 | + await Browser.LoadUrlAsync("chrome://crash"); | ||
| 86 | + await Assert.ThrowsAsync<TaskCanceledException>(() => task); | ||
| 87 | + } | ||
| 88 | + | ||
| 26 | 89 | [Theory] | |
| 27 | 90 | [InlineData("(function() { return Promise.resolve(53)})", 53)] | |
| 28 | 91 | [InlineData("(function() { return Promise.resolve('53')})", "53")] | |
| Back | FazBrowse Home | New Git URL |
0 commit comments