Skip to content

Commit 2e70c01

Browse files
committed
BrowserSubprocess - Refactor to support .Net Core
- Added BrowserSubprocessExecutable for use with .Net Core (no WCF) - Added WcfBrowserSubprocessExecutable for use with the existing CefSharp.BrowserSubprocess.exe which supports WCF (conditionally)
1 parent 21d272f commit 2e70c01

File tree

7 files changed

+180
-54
lines changed

7 files changed

+180
-54
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright © 2019 The CefSharp Authors. All rights reserved.
2+
//
3+
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
4+
5+
#pragma once
6+
7+
#include "Stdafx.h"
8+
9+
#include "SubProcess.h"
10+
#include "WcfEnabledSubProcess.h"
11+
12+
using namespace System;
13+
using namespace CefSharp::Internals;
14+
15+
namespace CefSharp
16+
{
17+
namespace BrowserSubprocess
18+
{
19+
/// <summary>
20+
/// BrowserSubprocessExecutable provides the fundimental browser process handling for
21+
/// CefSharp.BrowserSubprocess.exe and can be used to self host the BrowserSubProcess in your
22+
/// existing application (preferred approach for .Net Core).
23+
/// </summary>
24+
public ref class BrowserSubprocessExecutable
25+
{
26+
public:
27+
BrowserSubprocessExecutable()
28+
{
29+
30+
}
31+
32+
int Main(IEnumerable<String^>^ args, IRenderProcessHandler^ handler)
33+
{
34+
int result;
35+
auto type = CommandLineArgsParser::GetArgumentValue(args, CefSharpArguments::SubProcessTypeArgument);
36+
37+
auto parentProcessId = -1;
38+
39+
// The Crashpad Handler doesn't have any HostProcessIdArgument, so we must not try to
40+
// parse it lest we want an ArgumentNullException.
41+
if (type != "crashpad-handler")
42+
{
43+
parentProcessId = int::Parse(CommandLineArgsParser::GetArgumentValue(args, CefSharpArguments::HostProcessIdArgument));
44+
if (CommandLineArgsParser::HasArgument(args, CefSharpArguments::ExitIfParentProcessClosed))
45+
{
46+
ParentProcessMonitor::StartMonitorTask(parentProcessId);
47+
}
48+
}
49+
50+
// Use our custom subProcess provides features like EvaluateJavascript
51+
if (type == "renderer")
52+
{
53+
auto subProcess = GetSubprocess(args, parentProcessId, handler);
54+
55+
try
56+
{
57+
result = subProcess->Run();
58+
}
59+
finally
60+
{
61+
delete subProcess;
62+
}
63+
}
64+
else
65+
{
66+
result = SubProcess::ExecuteProcess(args);
67+
}
68+
69+
return result;
70+
}
71+
72+
protected:
73+
virtual SubProcess^ GetSubprocess(IEnumerable<String^>^ args, int parentProcessId, IRenderProcessHandler^ handler)
74+
{
75+
return gcnew SubProcess(handler, args);
76+
}
77+
};
78+
}
79+
}

CefSharp.BrowserSubprocess.Core/CefSharp.BrowserSubprocess.Core.vcxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,13 +173,15 @@
173173
<ClInclude Include="..\CefSharp.Core\Internals\Serialization\Primitives.h" />
174174
<ClInclude Include="..\CefSharp.Core\Internals\StringUtils.h" />
175175
<ClInclude Include="BindObjectAsyncHandler.h" />
176+
<ClCompile Include="BrowserSubprocessExecutable.h" />
176177
<ClInclude Include="SubProcessApp.h" />
177178
<ClInclude Include="Async\JavascriptAsyncMethodCallback.h" />
178179
<ClInclude Include="Async\JavascriptAsyncMethodHandler.h" />
179180
<ClInclude Include="Async\JavascriptAsyncMethodWrapper.h" />
180181
<ClInclude Include="Async\JavascriptAsyncObjectWrapper.h" />
181182
<ClInclude Include="CefAppUnmanagedWrapper.h" />
182183
<ClInclude Include="JavascriptPostMessageHandler.h" />
184+
<ClCompile Include="WcfBrowserSubprocessExecutable.h" />
183185
<ClInclude Include="Wrapper\Frame.h" />
184186
<ClInclude Include="Wrapper\Browser.h" />
185187
<ClInclude Include="Wrapper\V8Context.h" />

CefSharp.BrowserSubprocess.Core/CefSharp.BrowserSubprocess.Core.vcxproj.filters

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,12 @@
181181
<ClCompile Include="Wrapper\Browser.cpp">
182182
<Filter>Source Files</Filter>
183183
</ClCompile>
184+
<ClCompile Include="WcfBrowserSubprocessExecutable.h">
185+
<Filter>Header Files</Filter>
186+
</ClCompile>
187+
<ClCompile Include="BrowserSubprocessExecutable.h">
188+
<Filter>Header Files</Filter>
189+
</ClCompile>
184190
</ItemGroup>
185191
<ItemGroup>
186192
<ResourceCompile Include="Resource.rc" />
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright © 2019 The CefSharp Authors. All rights reserved.
2+
//
3+
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
4+
5+
#pragma once
6+
7+
#include "Stdafx.h"
8+
9+
#include "SubProcess.h"
10+
#include "WcfEnabledSubProcess.h"
11+
#include "BrowserSubprocessExecutable.h"
12+
13+
using namespace System;
14+
using namespace CefSharp::Internals;
15+
16+
namespace CefSharp
17+
{
18+
namespace BrowserSubprocess
19+
{
20+
public ref class WcfBrowserSubprocessExecutable : BrowserSubprocessExecutable
21+
{
22+
public:
23+
WcfBrowserSubprocessExecutable()
24+
{
25+
26+
}
27+
protected:
28+
SubProcess^ GetSubprocess(IEnumerable<String^>^ args, int parentProcessId, IRenderProcessHandler^ handler) override
29+
{
30+
auto wcfEnabled = CommandLineArgsParser::HasArgument(args, CefSharpArguments::WcfEnabledArgument);
31+
if (wcfEnabled)
32+
{
33+
return gcnew WcfEnabledSubProcess(parentProcessId, handler, args);
34+
}
35+
return gcnew SubProcess(handler, args);
36+
}
37+
};
38+
}
39+
}

CefSharp.BrowserSubprocess/Program.cs

Lines changed: 4 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
using System;
66
using System.Diagnostics;
7-
using System.Threading.Tasks;
8-
using CefSharp.Internals;
97
using CefSharp.RenderProcess;
108

119
namespace CefSharp.BrowserSubprocess
@@ -23,63 +21,15 @@ public static int Main(string[] args)
2321

2422
SubProcess.EnableHighDPISupport();
2523

26-
int result;
27-
var type = args.GetArgumentValue(CefSharpArguments.SubProcessTypeArgument);
24+
//Add your own custom implementation of IRenderProcessHandler here
25+
IRenderProcessHandler handler = null;
2826

29-
var parentProcessId = -1;
30-
31-
// The Crashpad Handler doesn't have any HostProcessIdArgument, so we must not try to
32-
// parse it lest we want an ArgumentNullException.
33-
if (type != "crashpad-handler")
34-
{
35-
parentProcessId = int.Parse(args.GetArgumentValue(CefSharpArguments.HostProcessIdArgument));
36-
if (args.HasArgument(CefSharpArguments.ExitIfParentProcessClosed))
37-
{
38-
Task.Factory.StartNew(() => AwaitParentProcessExit(parentProcessId), TaskCreationOptions.LongRunning);
39-
}
40-
}
41-
42-
// Use our custom subProcess provides features like EvaluateJavascript
43-
if (type == "renderer")
44-
{
45-
//Add your own custom implementation of IRenderProcessHandler here
46-
IRenderProcessHandler handler = null;
47-
var wcfEnabled = args.HasArgument(CefSharpArguments.WcfEnabledArgument);
48-
var subProcess = wcfEnabled ? new WcfEnabledSubProcess(parentProcessId, handler, args) : new SubProcess(handler, args);
49-
50-
using (subProcess)
51-
{
52-
result = subProcess.Run();
53-
}
54-
}
55-
else
56-
{
57-
result = SubProcess.ExecuteProcess(args);
58-
}
27+
var browserProcessExe = new WcfBrowserSubprocessExecutable();
28+
var result = browserProcessExe.Main(args, handler);
5929

6030
Debug.WriteLine("BrowserSubprocess shutting down.");
6131

6232
return result;
6333
}
64-
65-
private static async void AwaitParentProcessExit(int parentProcessId)
66-
{
67-
try
68-
{
69-
var parentProcess = Process.GetProcessById(parentProcessId);
70-
parentProcess.WaitForExit();
71-
}
72-
catch (Exception e)
73-
{
74-
//main process probably died already
75-
Debug.WriteLine(e);
76-
}
77-
78-
await Task.Delay(1000); //wait a bit before exiting
79-
80-
Debug.WriteLine("BrowserSubprocess shutting down forcibly.");
81-
82-
Process.GetCurrentProcess().Kill();
83-
}
8434
}
8535
}

CefSharp/CefSharp.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@
103103
<Compile Include="DefaultApp.cs" />
104104
<Compile Include="Enums\SchemeOptions.cs" />
105105
<Compile Include="Internals\CommandLineArgDictionary.cs" />
106+
<Compile Include="Internals\ParentProcessMonitor.cs" />
106107
<Compile Include="Internals\ReadOnlyNameValueCollection.cs" />
107108
<Compile Include="Internals\TaskScheduler\LimitedConcurrencyLevelTaskScheduler.cs" />
108109
<Compile Include="IUrlRequest.cs" />
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright © 2019 The CefSharp Authors. All rights reserved.
2+
//
3+
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
4+
5+
using System;
6+
using System.Diagnostics;
7+
using System.Threading.Tasks;
8+
9+
namespace CefSharp.Internals
10+
{
11+
/// <summary>
12+
/// Monitor the parent process and exit if the parent process closes
13+
/// before the subprocess. This class is used by the CefSharp.BrowserSubprocess to
14+
/// self terminate if the parent dies without notifying it to exit.
15+
/// See https://github.com/cefsharp/CefSharp/issues/2359 for more information.
16+
/// </summary>
17+
public static class ParentProcessMonitor
18+
{
19+
/// <summary>
20+
/// Starts a long running task (spawns new thread) used to monitor the parent process
21+
/// and calls <see cref="Process.Kill"/> if the parent exits unexpectedly (usually result of a crash).
22+
/// </summary>
23+
/// <param name="parentProcessId">process Id of the parent application</param>
24+
public static void StartMonitorTask(int parentProcessId)
25+
{
26+
Task.Factory.StartNew(() => AwaitParentProcessExit(parentProcessId), TaskCreationOptions.LongRunning);
27+
}
28+
29+
private static async void AwaitParentProcessExit(int parentProcessId)
30+
{
31+
try
32+
{
33+
var parentProcess = Process.GetProcessById(parentProcessId);
34+
parentProcess.WaitForExit();
35+
}
36+
catch (Exception e)
37+
{
38+
//main process probably died already
39+
Debug.WriteLine(e);
40+
}
41+
42+
await Task.Delay(1000); //wait a bit before exiting
43+
44+
Debug.WriteLine("BrowserSubprocess shutting down forcibly.");
45+
46+
Process.GetCurrentProcess().Kill();
47+
}
48+
}
49+
}

0 commit comments

Comments
 (0)