| Index: src/plugin/PluginClass.cpp |
| =================================================================== |
| --- a/src/plugin/PluginClass.cpp |
| +++ b/src/plugin/PluginClass.cpp |
| @@ -233,175 +233,149 @@ |
| } |
| - |
| -// This gets called when a new browser window is created (which also triggers the |
| -// creation of this object). The pointer passed in should be to a IWebBrowser2 |
| -// interface that represents the browser for the window. |
| -// it is also called when a tab is closed, this unknownSite will be null |
| -// so we should handle that it is called this way several times during a session |
| +/* |
| + * IE calls this when it creates a new browser window or tab, immediately after it also |
| + * creates the object. The argument 'unknownSite' in is the OLE "site" of the object, |
| + * which is an IWebBrowser2 interface associated with the window/tab. |
| + * |
| + * IE also ordinarily calls this again when its window/tab is closed, in which case |
| + * 'unknownSite' will be null. Extraordinarily, this is sometimes _not_ called when IE |
| + * is shutting down. Thus 'SetSite(nullptr)' has some similarities with a destructor, |
| + * but it is not a proper substitute for one. |
|
sergei
2015/03/09 10:23:50
I'm not sure that we need this comment except the
Eric
2015/03/09 13:31:29
I was just rewriting the comment, mostly, with the
Oleksandr
2015/03/10 08:38:26
I am pretty sure it _is_ called every time when IE
Oleksandr
2015/03/10 08:42:04
https://msdn.microsoft.com/en-us/library/bb250489(
|
| + */ |
| STDMETHODIMP CPluginClass::SetSite(IUnknown* unknownSite) |
| { |
| - CPluginSettings* settings = CPluginSettings::GetInstance(); |
| + try |
| + { |
| + if (unknownSite) |
| + { |
| - MULTIPLE_VERSIONS_CHECK(); |
| + DEBUG_GENERAL(L"================================================================================\nNEW TAB UI\n================================================================================") |
| - if (unknownSite) |
| - { |
| + HRESULT hr = ::CoInitialize(NULL); |
| + if (FAILED(hr)) |
| + { |
| + DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_COINIT, "Class::SetSite - CoInitialize"); |
| + } |
| - DEBUG_GENERAL(L"================================================================================\nNEW TAB UI\n================================================================================") |
| + s_criticalSectionBrowser.Lock(); |
| + { |
| + m_webBrowser2 = unknownSite; |
|
Eric
2015/03/06 15:58:04
Assigned to m_webBrowser2 here, declared as CComQI
sergei
2015/03/06 16:07:19
Here `AddRef` is called.
|
| + } |
| + s_criticalSectionBrowser.Unlock(); |
| - HRESULT hr = ::CoInitialize(NULL); |
| - if (FAILED(hr)) |
| - { |
| - DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_COINIT, "Class::SetSite - CoInitialize"); |
| - } |
| + //register the mimefilter |
| + //and only mimefilter |
| + //on some few computers the mimefilter does not get properly registered when it is done on another thread |
| - s_criticalSectionBrowser.Lock(); |
| - { |
| - m_webBrowser2 = unknownSite; |
| - } |
| - s_criticalSectionBrowser.Unlock(); |
| + s_criticalSectionLocal.Lock(); |
| + { |
| + // Always register on startup, then check if we need to unregister in a separate thread |
| + s_mimeFilter = CPluginClientFactory::GetMimeFilterClientInstance(); |
| + s_asyncWebBrowser2 = unknownSite; |
| + s_instances.insert(this); |
| + } |
| + s_criticalSectionLocal.Unlock(); |
| - //register the mimefilter |
| - //and only mimefilter |
| - //on some few computers the mimefilter does not get properly registered when it is done on another thread |
| + try |
| + { |
| + // Check if loaded as BHO |
| + if (GetBrowser()) |
|
sergei
2015/03/09 10:23:50
We don't need this comment now.
Eric
2015/03/09 13:31:29
We don't need this particular comment, but we'll n
Eric
2015/03/17 10:41:07
Done.
|
| + { |
| + DEBUG_GENERAL("Loaded as BHO"); |
| + CComPtr<IConnectionPoint> pPoint = GetConnectionPoint(); |
| + if (pPoint) |
| + { |
| + HRESULT hr = pPoint->Advise((IDispatch*)this, &m_nConnectionID); |
| + if (SUCCEEDED(hr)) |
| + { |
| + m_isAdviced = true; |
| - s_criticalSectionLocal.Lock(); |
| - { |
| - // Always register on startup, then check if we need to unregister in a separate thread |
| - s_mimeFilter = CPluginClientFactory::GetMimeFilterClientInstance(); |
| - s_asyncWebBrowser2 = unknownSite; |
| - s_instances.insert(this); |
| - } |
| - s_criticalSectionLocal.Unlock(); |
| - |
| - try |
| - { |
| - // Check if loaded as BHO |
| - if (GetBrowser()) |
| - { |
| - DEBUG_GENERAL("Loaded as BHO"); |
| - CComPtr<IConnectionPoint> pPoint = GetConnectionPoint(); |
| - if (pPoint) |
| - { |
| - HRESULT hr = pPoint->Advise((IDispatch*)this, &m_nConnectionID); |
| - if (SUCCEEDED(hr)) |
| - { |
| - m_isAdviced = true; |
| - |
| - try |
| + try |
| + { |
| + std::thread startInitObjectThread(StartInitObject, this); |
| + startInitObjectThread.detach(); // TODO: but actually we should wait for the thread in the dtr. |
| + } |
| + catch (const std::system_error& ex) |
| + { |
| + DEBUG_SYSTEM_EXCEPTION(ex, PLUGIN_ERROR_THREAD, PLUGIN_ERROR_MAIN_THREAD_CREATE_PROCESS, |
| + "Class::Thread - Failed to create StartInitObject thread"); |
| + } |
| + } |
| + else |
| { |
| - std::thread startInitObjectThread(StartInitObject, this); |
| - startInitObjectThread.detach(); // TODO: but actually we should wait for the thread in the dtr. |
| + DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_ADVICE, "Class::SetSite - Advice"); |
| } |
| - catch (const std::system_error& ex) |
| - { |
| - DEBUG_SYSTEM_EXCEPTION(ex, PLUGIN_ERROR_THREAD, PLUGIN_ERROR_MAIN_THREAD_CREATE_PROCESS, |
| - "Class::Thread - Failed to create StartInitObject thread"); |
| - } |
| - } |
| - else |
| - { |
| - DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_ADVICE, "Class::SetSite - Advice"); |
| } |
| } |
| } |
| - else // Check if loaded as toolbar handler |
| + catch (const std::runtime_error& ex) |
| { |
| - DEBUG_GENERAL("Loaded as toolbar handler"); |
| - CComPtr<IServiceProvider> pServiceProvider; |
| + DEBUG_EXCEPTION(ex); |
| + Unadvice(); |
| + } |
| + } |
| + else |
| + { |
| + // Unadvice |
| + Unadvice(); |
| - HRESULT hr = unknownSite->QueryInterface(&pServiceProvider); |
| - if (SUCCEEDED(hr)) |
| + // Destroy window |
| + if (m_pWndProcStatus) |
| + { |
| + ::SetWindowLongPtr(m_hStatusBarWnd, GWLP_WNDPROC, (LPARAM)(WNDPROC)m_pWndProcStatus); |
| + |
| + m_pWndProcStatus = NULL; |
| + } |
| + |
| + if (m_hPaneWnd) |
| + { |
| + DestroyWindow(m_hPaneWnd); |
| + m_hPaneWnd = NULL; |
| + } |
| + |
| + m_hTabWnd = NULL; |
| + m_hStatusBarWnd = NULL; |
| + |
| + // Remove instance from the list, shutdown threads |
| + HANDLE hMainThread = NULL; |
| + HANDLE hTabThread = NULL; |
| + |
| + s_criticalSectionLocal.Lock(); |
| + { |
| + s_instances.erase(this); |
| + |
| + std::map<DWORD,CPluginClass*>::iterator it = s_threadInstances.find(::GetCurrentThreadId()); |
| + if (it != s_threadInstances.end()) |
| { |
| - if (pServiceProvider) |
| - { |
| - s_criticalSectionBrowser.Lock(); |
| - { |
| - HRESULT hr = pServiceProvider->QueryService(IID_IWebBrowserApp, &m_webBrowser2); |
| - if (SUCCEEDED(hr)) |
| - { |
| - if (m_webBrowser2) |
| - { |
| - InitObject(false); |
| - } |
| - } |
| - else |
| - { |
| - DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_QUERY_BROWSER, "Class::SetSite - QueryService (IID_IWebBrowserApp)"); |
| - } |
| - } |
| - s_criticalSectionBrowser.Unlock(); |
| - } |
| + s_threadInstances.erase(it); |
| } |
| - else |
| + if (s_instances.empty()) |
| { |
| - DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_QUERY_SERVICE_PROVIDER, "Class::SetSite - QueryInterface (service provider)"); |
| + // TODO: Explicitly releasing a resource when a container becomes empty looks like a job better suited for shared_ptr |
| + CPluginClientFactory::ReleaseMimeFilterClientInstance(); |
| } |
| } |
| - } |
| - catch (const std::runtime_error& ex) |
| - { |
| - DEBUG_EXCEPTION(ex); |
| - Unadvice(); |
| - } |
| - } |
| - else |
| - { |
| - // Unadvice |
| - Unadvice(); |
| + s_criticalSectionLocal.Unlock(); |
| - // Destroy window |
| - if (m_pWndProcStatus) |
| - { |
| - ::SetWindowLongPtr(m_hStatusBarWnd, GWLP_WNDPROC, (LPARAM)(WNDPROC)m_pWndProcStatus); |
| + // Release browser interface |
| + s_criticalSectionBrowser.Lock(); |
| + { |
| + m_webBrowser2.Release(); |
|
Eric
2015/03/06 15:58:04
Explicit release here.
sergei
2015/03/06 16:07:19
So, since `AddRef` is called and `m_webBrowser2` i
Eric
2015/03/06 16:27:22
Calling 'Release' through 'CComPtr' apparently als
|
| + } |
| + s_criticalSectionBrowser.Unlock(); |
| - m_pWndProcStatus = NULL; |
| + DEBUG_GENERAL("================================================================================\nNEW TAB UI - END\n================================================================================") |
| + |
| + ::CoUninitialize(); |
| } |
| - if (m_hPaneWnd) |
| - { |
| - DestroyWindow(m_hPaneWnd); |
| - m_hPaneWnd = NULL; |
| - } |
| - |
| - m_hTabWnd = NULL; |
| - m_hStatusBarWnd = NULL; |
| - |
| - // Remove instance from the list, shutdown threads |
| - HANDLE hMainThread = NULL; |
| - HANDLE hTabThread = NULL; |
| - |
| - s_criticalSectionLocal.Lock(); |
| - { |
| - s_instances.erase(this); |
| - |
| - std::map<DWORD,CPluginClass*>::iterator it = s_threadInstances.find(::GetCurrentThreadId()); |
| - if (it != s_threadInstances.end()) |
| - { |
| - s_threadInstances.erase(it); |
| - } |
| - if (s_instances.empty()) |
| - { |
| - // TODO: Explicitly releasing a resource when a container becomes empty looks like a job better suited for shared_ptr |
| - CPluginClientFactory::ReleaseMimeFilterClientInstance(); |
| - } |
| - } |
| - s_criticalSectionLocal.Unlock(); |
| - |
| - // Release browser interface |
| - s_criticalSectionBrowser.Lock(); |
| - { |
| - m_webBrowser2.Release(); |
| - } |
| - s_criticalSectionBrowser.Unlock(); |
| - |
| - DEBUG_GENERAL("================================================================================\nNEW TAB UI - END\n================================================================================") |
| - |
| - ::CoUninitialize(); |
| + IObjectWithSiteImpl<CPluginClass>::SetSite(unknownSite); |
| } |
| - |
| - return IObjectWithSiteImpl<CPluginClass>::SetSite(unknownSite); |
| + catch (...) |
| + { |
| + } |
| + return S_OK; |
| } |
| bool CPluginClass::IsStatusBarEnabled() |