Skip to content

Commit 02d0458

Browse files
committed
Core - CefSettings no longer implements IDisposable
**This is a breaking change** - CefSharp.Core.CefSettingsBase is now disposed when calling Cef.Initialize - CefSharpApp was refactored to no longer need a reference to CefSettingsBase so it can be disposed Resolves #3220
1 parent 8afe0df commit 02d0458

File tree

3 files changed

+100
-61
lines changed

3 files changed

+100
-61
lines changed

CefSharp.Core.Runtime/Cef.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,11 @@ namespace CefSharp
246246
//To allow FolderSchemeHandlerFactory to access GetMimeType we pass in a Func
247247
CefSharp::SchemeHandler::FolderSchemeHandlerFactory::GetMimeTypeDelegate = gcnew Func<String^, String^>(&GetMimeType);
248248

249-
CefRefPtr<CefSharpApp> app(new CefSharpApp(cefSettings, cefApp));
249+
CefRefPtr<CefSharpApp> app(new CefSharpApp(cefSettings->ExternalMessagePump,
250+
cefSettings->CommandLineArgsDisabled,
251+
cefSettings->CefCommandLineArgs,
252+
cefSettings->CefCustomSchemes,
253+
cefApp));
250254
CefMainArgs main_args;
251255

252256
auto success = CefInitialize(main_args, *(cefSettings->_cefSettings), app.get(), NULL);

CefSharp.Core.Runtime/Internals/CefSharpApp.h

Lines changed: 58 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,66 @@ namespace CefSharp
2222
private class CefSharpApp : public CefApp,
2323
public CefBrowserProcessHandler
2424
{
25-
gcroot<CefSettingsBase^> _cefSettings;
25+
gcroot<IEnumerable<CefCustomScheme^>^> _customSchemes;
26+
gcroot<CommandLineArgDictionary^> _commandLineArgs;
2627
gcroot<IApp^> _app;
28+
bool _commandLineDisabled;
29+
bool _hasCustomScheme;
30+
gcroot<String^> _customSchemeArg;
2731

2832
public:
29-
CefSharpApp(CefSettingsBase^ cefSettings, IApp^ app) :
30-
_cefSettings(cefSettings),
31-
_app(app)
33+
CefSharpApp(bool externalMessagePump, bool commandLineDisabled, CommandLineArgDictionary^ commandLineArgs, IEnumerable<CefCustomScheme^>^ customSchemes, IApp^ app) :
34+
_commandLineDisabled(commandLineDisabled),
35+
_commandLineArgs(commandLineArgs),
36+
_customSchemes(customSchemes),
37+
_app(app),
38+
_hasCustomScheme(false)
3239
{
3340
auto isMissingHandler = Object::ReferenceEquals(app, nullptr) || Object::ReferenceEquals(app->BrowserProcessHandler, nullptr);
34-
if (cefSettings->ExternalMessagePump && isMissingHandler)
41+
if (externalMessagePump && isMissingHandler)
3542
{
3643
throw gcnew Exception("browserProcessHandler cannot be null when using cefSettings.ExternalMessagePump");
3744
}
45+
46+
if (System::Linq::Enumerable::Count(customSchemes) > 0)
47+
{
48+
String^ argument = "=";
49+
auto registeredSchemes = gcnew List<String^>();
50+
51+
for each (CefCustomScheme ^ scheme in customSchemes)
52+
{
53+
//We don't need to register http or https in the render process
54+
if (scheme->SchemeName == "http" ||
55+
scheme->SchemeName == "https")
56+
{
57+
continue;
58+
}
59+
60+
//We've already registered this scheme name
61+
if (registeredSchemes->Contains(scheme->SchemeName))
62+
{
63+
continue;
64+
}
65+
66+
_hasCustomScheme = true;
67+
68+
registeredSchemes->Add(scheme->SchemeName);
69+
70+
argument += scheme->SchemeName + "|";
71+
argument += ((int)scheme->Options).ToString() + ";";
72+
}
73+
74+
if (_hasCustomScheme)
75+
{
76+
_customSchemeArg = argument->TrimEnd(';');
77+
}
78+
}
3879
}
3980

4081
~CefSharpApp()
4182
{
42-
_cefSettings = nullptr;
83+
_customSchemes = nullptr;
84+
_commandLineArgs = nullptr;
4385
delete _app;
4486
_app = nullptr;
4587
}
@@ -56,8 +98,10 @@ namespace CefSharp
5698
_app->BrowserProcessHandler->OnContextInitialized();
5799
}
58100

101+
auto customSchemes = (IEnumerable<CefCustomScheme^>^)_customSchemes;
102+
59103
//CefRegisterSchemeHandlerFactory requires access to the Global CefRequestContext
60-
for each (CefCustomScheme^ cefCustomScheme in _cefSettings->CefCustomSchemes)
104+
for each (CefCustomScheme^ cefCustomScheme in customSchemes)
61105
{
62106
if (!Object::ReferenceEquals(cefCustomScheme->SchemeHandlerFactory, nullptr))
63107
{
@@ -93,41 +137,9 @@ namespace CefSharp
93137
//We need to know the process Id to establish WCF communication and for monitoring of parent process exit
94138
commandLine->AppendArgument(StringUtils::ToNative(CefSharpArguments::HostProcessIdArgument + "=" + Process::GetCurrentProcess()->Id));
95139

96-
if (_cefSettings->_cefCustomSchemes->Count > 0)
140+
if (_hasCustomScheme)
97141
{
98-
String^ argument = "=";
99-
bool hasCustomScheme = false;
100-
auto registeredSchemes = gcnew List<String^>();
101-
102-
for each(CefCustomScheme^ scheme in _cefSettings->CefCustomSchemes)
103-
{
104-
//We don't need to register http or https in the render process
105-
if (scheme->SchemeName == "http" ||
106-
scheme->SchemeName == "https")
107-
{
108-
continue;
109-
}
110-
111-
//We've already registered this scheme name
112-
if (registeredSchemes->Contains(scheme->SchemeName))
113-
{
114-
continue;
115-
}
116-
117-
hasCustomScheme = true;
118-
119-
registeredSchemes->Add(scheme->SchemeName);
120-
121-
argument += scheme->SchemeName + "|";
122-
argument += ((int)scheme->Options).ToString() + ";";
123-
}
124-
125-
if (hasCustomScheme)
126-
{
127-
argument = argument->TrimEnd(';');
128-
129-
commandLine->AppendArgument(StringUtils::ToNative(CefSharpArguments::CustomSchemeArgument + argument));
130-
}
142+
commandLine->AppendArgument(StringUtils::ToNative(CefSharpArguments::CustomSchemeArgument + _customSchemeArg));
131143
}
132144

133145
if (CefSharpSettings::FocusedNodeChangedEnabled)
@@ -138,7 +150,7 @@ namespace CefSharp
138150

139151
virtual void OnBeforeCommandLineProcessing(const CefString& process_type, CefRefPtr<CefCommandLine> command_line) OVERRIDE
140152
{
141-
if (CefSharpSettings::Proxy != nullptr && !_cefSettings->CommandLineArgsDisabled)
153+
if (CefSharpSettings::Proxy != nullptr && !_commandLineDisabled)
142154
{
143155
command_line->AppendSwitchWithValue("proxy-server", StringUtils::ToNative(CefSharpSettings::Proxy->IP + ":" + CefSharpSettings::Proxy->Port));
144156

@@ -148,15 +160,17 @@ namespace CefSharp
148160
}
149161
}
150162

151-
if (_cefSettings->CefCommandLineArgs->Count > 0)
163+
if (_commandLineArgs->Count > 0)
152164
{
153165
auto commandLine = command_line.get();
154166

155167
// Not clear what should happen if we
156168
// * already have some command line flags given (is this possible? Perhaps from globalCommandLine)
157169
// * have no flags given (-> call SetProgramm() with first argument?)
158170

159-
for each(KeyValuePair<String^, String^>^ kvp in _cefSettings->CefCommandLineArgs)
171+
auto args = (CommandLineArgDictionary^)_commandLineArgs;
172+
173+
for each(KeyValuePair<String^, String^>^ kvp in args)
160174
{
161175
CefString name = StringUtils::ToNative(kvp->Key);
162176
CefString value = StringUtils::ToNative(kvp->Value);

CefSharp.Core/PublicApi.cs

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -220,11 +220,14 @@ public static string CefCommitHash
220220
/// application thread (typically the UI thread). If you call them on different
221221
/// threads, your application will hang. See the documentation for Cef.Shutdown() for more details.
222222
/// </summary>
223-
/// <param name="cefSettings">CefSharp configuration settings.</param>
223+
/// <param name="settings">CefSharp configuration settings.</param>
224224
/// <returns>true if successful; otherwise, false.</returns>
225-
public static bool Initialize(CefSettingsBase cefSettings)
225+
public static bool Initialize(CefSettingsBase settings)
226226
{
227-
return Core.Cef.Initialize((CefSharp.Core.CefSettingsBase)cefSettings);
227+
using (settings.settings)
228+
{
229+
return Core.Cef.Initialize(settings.settings);
230+
}
228231
}
229232

230233
/// <summary>
@@ -233,12 +236,15 @@ public static bool Initialize(CefSettingsBase cefSettings)
233236
/// application thread (typically the UI thread). If you call them on different
234237
/// threads, your application will hang. See the documentation for Cef.Shutdown() for more details.
235238
/// </summary>
236-
/// <param name="cefSettings">CefSharp configuration settings.</param>
239+
/// <param name="settings">CefSharp configuration settings.</param>
237240
/// <param name="performDependencyCheck">Check that all relevant dependencies available, throws exception if any are missing</param>
238241
/// <returns>true if successful; otherwise, false.</returns>
239-
public static bool Initialize(CefSettingsBase cefSettings, bool performDependencyCheck)
242+
public static bool Initialize(CefSettingsBase settings, bool performDependencyCheck)
240243
{
241-
return Core.Cef.Initialize((CefSharp.Core.CefSettingsBase)cefSettings, performDependencyCheck);
244+
using (settings.settings)
245+
{
246+
return Core.Cef.Initialize(settings.settings, performDependencyCheck);
247+
}
242248
}
243249

244250
/// <summary>
@@ -247,13 +253,16 @@ public static bool Initialize(CefSettingsBase cefSettings, bool performDependenc
247253
/// application thread (typically the UI thread). If you call them on different
248254
/// threads, your application will hang. See the documentation for Cef.Shutdown() for more details.
249255
/// </summary>
250-
/// <param name="cefSettings">CefSharp configuration settings.</param>
256+
/// <param name="settings">CefSharp configuration settings.</param>
251257
/// <param name="performDependencyCheck">Check that all relevant dependencies available, throws exception if any are missing</param>
252258
/// <param name="browserProcessHandler">The handler for functionality specific to the browser process. Null if you don't wish to handle these events</param>
253259
/// <returns>true if successful; otherwise, false.</returns>
254-
public static bool Initialize(CefSettingsBase cefSettings, bool performDependencyCheck, IBrowserProcessHandler browserProcessHandler)
260+
public static bool Initialize(CefSettingsBase settings, bool performDependencyCheck, IBrowserProcessHandler browserProcessHandler)
255261
{
256-
return Core.Cef.Initialize((CefSharp.Core.CefSettingsBase)cefSettings, performDependencyCheck, browserProcessHandler);
262+
using (settings.settings)
263+
{
264+
return Core.Cef.Initialize(settings.settings, performDependencyCheck, browserProcessHandler);
265+
}
257266
}
258267

259268
/// <summary>
@@ -262,13 +271,16 @@ public static bool Initialize(CefSettingsBase cefSettings, bool performDependenc
262271
/// application thread (typically the UI thread). If you call them on different
263272
/// threads, your application will hang. See the documentation for Cef.Shutdown() for more details.
264273
/// </summary>
265-
/// <param name="cefSettings">CefSharp configuration settings.</param>
274+
/// <param name="settings">CefSharp configuration settings.</param>
266275
/// <param name="performDependencyCheck">Check that all relevant dependencies available, throws exception if any are missing</param>
267276
/// <param name="cefApp">Implement this interface to provide handler implementations. Null if you don't wish to handle these events</param>
268277
/// <returns>true if successful; otherwise, false.</returns>
269-
public static bool Initialize(CefSettingsBase cefSettings, bool performDependencyCheck, IApp cefApp)
278+
public static bool Initialize(CefSettingsBase settings, bool performDependencyCheck, IApp cefApp)
270279
{
271-
return Core.Cef.Initialize((CefSharp.Core.CefSettingsBase)cefSettings, performDependencyCheck, cefApp);
280+
using (settings.settings)
281+
{
282+
return Core.Cef.Initialize(settings.settings, performDependencyCheck, cefApp);
283+
}
272284
}
273285

274286
/// <summary>
@@ -746,7 +758,11 @@ public static void WaitForBrowsersToClose()
746758
}
747759
}
748760

749-
/// <inheritdoc/>
761+
/// <summary>
762+
/// Initialization settings. Many of these and other settings can also configured using command-line switches.
763+
/// WPF/WinForms/OffScreen each have their own CefSettings implementation that sets
764+
/// relevant settings e.g. OffScreen starts with audio muted.
765+
/// </summary>
750766
public abstract class CefSettingsBase
751767
{
752768
internal Core.CefSettingsBase settings = new Core.CefSettingsBase();
@@ -763,10 +779,15 @@ public CefSettingsBase() : base()
763779
}
764780
}
765781
#endif
766-
767-
public static explicit operator CefSharp.Core.CefSettingsBase(CefSettingsBase s)
782+
/// <summary>
783+
/// Free the unmanaged CefSettingsBase instance.
784+
/// Under normal circumstances you shouldn't need to call this
785+
/// The unmanaged resource will be freed after <see cref="Cef.Initialize(CefSettingsBase)"/> (or one of the overloads) is called.
786+
/// </summary>
787+
public void Dispose()
768788
{
769-
return s.settings;
789+
settings?.Dispose();
790+
settings = null;
770791
}
771792

772793
/// <summary>

0 commit comments

Comments
 (0)