Skip to content

Commit dda2249

Browse files
authored
Merge b260b35 into f8ac2d9
2 parents f8ac2d9 + b260b35 commit dda2249

3 files changed

Lines changed: 44 additions & 6 deletions

File tree

CefSharp.BrowserSubprocess.Core/CefAppUnmanagedWrapper.cpp

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,24 @@ namespace CefSharp
5555
return this;
5656
};
5757

58+
ref struct CefBrowserWrapperUpdater
59+
{
60+
CefBrowserWrapper^ _capture;
61+
CefAppUnmanagedWrapper& _wrapper;
62+
CefBrowserWrapperUpdater(CefBrowserWrapper^ capture, CefAppUnmanagedWrapper& wrapper) :
63+
_capture(capture),
64+
_wrapper(wrapper) {
65+
}
66+
67+
public:
68+
CefBrowserWrapper^ update(int key, CefBrowserWrapper^ oldValue)
69+
{
70+
_wrapper._onBrowserDestroyed->Invoke(oldValue);
71+
delete oldValue;
72+
return _capture;
73+
}
74+
};
75+
5876
// CefRenderProcessHandler
5977
void CefAppUnmanagedWrapper::OnBrowserCreated(CefRefPtr<CefBrowser> browser, CefRefPtr<CefDictionaryValue> extraInfo)
6078
{
@@ -63,7 +81,14 @@ namespace CefSharp
6381

6482
//Multiple CefBrowserWrappers created when opening popups
6583
auto browserId = browser->GetIdentifier();
66-
_browserWrappers->TryAdd(browserId, wrapper);
84+
85+
// In some cases CEF recreates the browser with identical id instead of making a new one
86+
// If this happens it will call OnBrowserCreated a second time before calling OnBrowserDestroyed for the first browser
87+
// We need to check if the browser wrapper with given id already exists and if it does destroy it before adding the new one
88+
// https://github.com/chromiumembedded/cef/blob/ffa86e361d9c210136b539953663526add56191e/include/cef_render_process_handler.h#L67
89+
auto updater = gcnew CefBrowserWrapperUpdater(wrapper, *this);
90+
auto updateFunc = gcnew Func<int, CefBrowserWrapper^, CefBrowserWrapper^>(updater, &CefBrowserWrapperUpdater::update);
91+
_browserWrappers->AddOrUpdate(browserId, wrapper, updateFunc);
6792

6893
static gcroot<Func<int, JavascriptBindingSettings^>^> factory =
6994
gcnew Func<int, JavascriptBindingSettings^>(CefAppUnmanagedWrapper::JavascriptBindingSettingsFactory);
@@ -136,11 +161,20 @@ namespace CefSharp
136161

137162
void CefAppUnmanagedWrapper::OnBrowserDestroyed(CefRefPtr<CefBrowser> browser)
138163
{
139-
CefBrowserWrapper^ wrapper;
140-
if (_browserWrappers->TryRemove(browser->GetIdentifier(), wrapper))
141-
{
142-
_onBrowserDestroyed->Invoke(wrapper);
143-
delete wrapper;
164+
int browserId = browser->GetIdentifier();
165+
CefBrowserWrapper^ currentValue;
166+
if (_browserWrappers->TryGetValue(browserId, currentValue)) {
167+
// Check if another wrapper hasn't already taken our place
168+
if (currentValue->IsSameBrowser(browser)) {
169+
CefBrowserWrapper^ wrapper;
170+
// This is technically a race condition since the entry for browser id might have changed between TryGetValue
171+
// and TryRemove. No clear way to fix this with ConcurrentDictionary
172+
if (_browserWrappers->TryRemove(browserId, wrapper))
173+
{
174+
_onBrowserDestroyed->Invoke(wrapper);
175+
delete wrapper;
176+
}
177+
}
144178
}
145179

146180
// Don't remove javascript settings because cef is unreliable in calling OnBrowserCreated/OnBrowserDestroyed consistently:

CefSharp.BrowserSubprocess.Core/CefAppUnmanagedWrapper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ namespace CefSharp
2222
// This class is the native subprocess level CEF object wrapper.
2323
private class CefAppUnmanagedWrapper : SubProcessApp, CefRenderProcessHandler
2424
{
25+
friend ref struct CefBrowserWrapperUpdater;
2526
private:
2627
gcroot<IRenderProcessHandler^> _handler;
2728
gcroot<Action<CefBrowserWrapper^>^> _onBrowserCreated;

CefSharp.BrowserSubprocess.Core/CefBrowserWrapper.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ namespace CefSharp
4646
{
4747
this->!CefBrowserWrapper();
4848
}
49+
bool IsSameBrowser(CefRefPtr<CefBrowser> other) {
50+
return this->_cefBrowser->IsSame(other);
51+
}
4952

5053
property int BrowserId;
5154
property bool IsPopup;

0 commit comments

Comments
 (0)