| Index: src/plugin/PluginClass.cpp |
| =================================================================== |
| --- a/src/plugin/PluginClass.cpp |
| +++ b/src/plugin/PluginClass.cpp |
| @@ -201,7 +201,7 @@ |
| { |
| if (thisPtr == NULL) |
| return 0; |
| - if (!((CPluginClass*)thisPtr)->InitObject(true)) |
| + if (!((CPluginClass*)thisPtr)->InitObject()) |
| { |
| ((CPluginClass*)thisPtr)->Unadvise(); |
| } |
| @@ -209,169 +209,143 @@ |
| return 0; |
| } |
| -// 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/30 11:26:23
This comment
|
| 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; |
| + } |
| + s_criticalSectionBrowser.Unlock(); |
| - HRESULT hr = ::CoInitialize(NULL); |
| - if (FAILED(hr)) |
| + //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_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 |
| + { |
| + auto webBrowser = GetBrowser(); |
| + if (webBrowser) |
| + { |
| + DEBUG_GENERAL("Loaded as BHO"); |
| + HRESULT hr = DispEventAdvise(webBrowser); |
| + if (SUCCEEDED(hr)) |
| + { |
| + m_isAdvised = true; |
| + 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 |
| + { |
| + DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_ADVICE, "Class::SetSite - Advise"); |
| + } |
| + } |
| + } |
| + catch (const std::runtime_error& ex) |
| + { |
| + DEBUG_EXCEPTION(ex); |
| + Unadvise(); |
| + } |
| + } |
| + else |
| { |
| - DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_COINIT, "Class::SetSite - CoInitialize"); |
| + Unadvise(); |
| + |
| + // 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()) |
| + { |
| + 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(); |
| } |
| - s_criticalSectionBrowser.Lock(); |
| - { |
| - m_webBrowser2 = unknownSite; |
| - } |
| - s_criticalSectionBrowser.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 |
| - |
| - 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 |
| - auto webBrowser = GetBrowser(); |
| - if (webBrowser) |
| - { |
| - DEBUG_GENERAL("Loaded as BHO"); |
| - HRESULT hr = DispEventAdvise(webBrowser); |
| - if (SUCCEEDED(hr)) |
| - { |
| - m_isAdvised = true; |
| - 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 |
| - { |
| - DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_ADVICE, "Class::SetSite - Advise"); |
| - } |
| - } |
| - else // Check if loaded as toolbar handler |
| - { |
| - DEBUG_GENERAL("Loaded as toolbar handler"); |
| - CComPtr<IServiceProvider> pServiceProvider; |
| - |
| - HRESULT hr = unknownSite->QueryInterface(&pServiceProvider); |
| - if (SUCCEEDED(hr)) |
| - { |
| - 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(); |
| - } |
| - } |
| - else |
| - { |
| - DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_QUERY_SERVICE_PROVIDER, "Class::SetSite - QueryInterface (service provider)"); |
| - } |
| - } |
| - } |
| - catch (const std::runtime_error& ex) |
| - { |
| - DEBUG_EXCEPTION(ex); |
| - Unadvise(); |
| - } |
| + IObjectWithSiteImpl<CPluginClass>::SetSite(unknownSite); |
| } |
| - else |
| + catch (...) |
| { |
| - Unadvise(); |
| - |
| - // 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()) |
| - { |
| - 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(); |
| } |
| - |
| - return IObjectWithSiteImpl<CPluginClass>::SetSite(unknownSite); |
| + return S_OK; |
| } |
| bool CPluginClass::IsStatusBarEnabled() |
| @@ -601,7 +575,7 @@ |
| if (!m_isInitializedOk) |
| { |
| m_isInitializedOk = true; |
| - InitObject(true); |
| + InitObject(); |
| UpdateStatusBar(); |
| } |
| } |
| @@ -654,7 +628,7 @@ |
| } |
| } |
| -bool CPluginClass::InitObject(bool bBHO) |
| +bool CPluginClass::InitObject() |
| { |
| DEBUG_GENERAL("InitObject"); |
| CPluginSettings* settings = CPluginSettings::GetInstance(); |
| @@ -731,7 +705,7 @@ |
| int ieVersion = AdblockPlus::IE::InstalledMajorVersion(); |
| // Create status pane |
| - if (bBHO && ieVersion > 6 && !CreateStatusBarPane()) |
| + if (ieVersion > 6 && !CreateStatusBarPane()) |
| { |
| return false; |
| } |