| Left: | ||
| Right: |
| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * This file is part of Adblock Plus <https://adblockplus.org/>, | 2 * This file is part of Adblock Plus <https://adblockplus.org/>, |
| 3 * Copyright (C) 2006-2015 Eyeo GmbH | 3 * Copyright (C) 2006-2015 Eyeo GmbH |
| 4 * | 4 * |
| 5 * Adblock Plus is free software: you can redistribute it and/or modify | 5 * Adblock Plus is free software: you can redistribute it and/or modify |
| 6 * it under the terms of the GNU General Public License version 3 as | 6 * it under the terms of the GNU General Public License version 3 as |
| 7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
| 8 * | 8 * |
| 9 * Adblock Plus is distributed in the hope that it will be useful, | 9 * Adblock Plus is distributed in the hope that it will be useful, |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 121 | 121 |
| 122 HRESULT CPluginClass::FinalConstruct() | 122 HRESULT CPluginClass::FinalConstruct() |
| 123 { | 123 { |
| 124 return S_OK; | 124 return S_OK; |
| 125 } | 125 } |
| 126 | 126 |
| 127 void CPluginClass::FinalRelease() | 127 void CPluginClass::FinalRelease() |
| 128 { | 128 { |
| 129 s_criticalSectionBrowser.Lock(); | 129 s_criticalSectionBrowser.Lock(); |
| 130 { | 130 { |
| 131 m_webBrowser2.Release(); | 131 m_webBrowser2.Release(); |
|
Eric
2015/03/06 15:58:04
Explicit release.
| |
| 132 } | 132 } |
| 133 s_criticalSectionBrowser.Unlock(); | 133 s_criticalSectionBrowser.Unlock(); |
| 134 } | 134 } |
| 135 | 135 |
| 136 | 136 |
| 137 // This method tries to get a 'connection point' from the stored browser, which can be | 137 // This method tries to get a 'connection point' from the stored browser, which can be |
| 138 // used to attach or detach from the stream of browser events | 138 // used to attach or detach from the stream of browser events |
| 139 CComPtr<IConnectionPoint> CPluginClass::GetConnectionPoint() | 139 CComPtr<IConnectionPoint> CPluginClass::GetConnectionPoint() |
| 140 { | 140 { |
| 141 CComQIPtr<IConnectionPointContainer, &IID_IConnectionPointContainer> pContaine r(GetBrowser()); | 141 CComQIPtr<IConnectionPointContainer, &IID_IConnectionPointContainer> pContaine r(GetBrowser()); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 226 return 0; | 226 return 0; |
| 227 if (!((CPluginClass*)thisPtr)->InitObject(true)) | 227 if (!((CPluginClass*)thisPtr)->InitObject(true)) |
| 228 { | 228 { |
| 229 ((CPluginClass*)thisPtr)->Unadvice(); | 229 ((CPluginClass*)thisPtr)->Unadvice(); |
| 230 } | 230 } |
| 231 | 231 |
| 232 return 0; | 232 return 0; |
| 233 } | 233 } |
| 234 | 234 |
| 235 | 235 |
| 236 | 236 /* |
| 237 // This gets called when a new browser window is created (which also triggers th e | 237 * IE calls this when it creates a new browser window or tab, immediately after it also |
| 238 // creation of this object). The pointer passed in should be to a IWebBrowser2 | 238 * creates the object. The argument 'unknownSite' in is the OLE "site" of the ob ject, |
| 239 // interface that represents the browser for the window. | 239 * which is an IWebBrowser2 interface associated with the window/tab. |
| 240 // it is also called when a tab is closed, this unknownSite will be null | 240 * |
| 241 // so we should handle that it is called this way several times during a session | 241 * IE also ordinarily calls this again when its window/tab is closed, in which c ase |
| 242 * 'unknownSite' will be null. Extraordinarily, this is sometimes _not_ called w hen IE | |
| 243 * is shutting down. Thus 'SetSite(nullptr)' has some similarities with a destru ctor, | |
| 244 * 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(
| |
| 245 */ | |
| 242 STDMETHODIMP CPluginClass::SetSite(IUnknown* unknownSite) | 246 STDMETHODIMP CPluginClass::SetSite(IUnknown* unknownSite) |
| 243 { | 247 { |
| 244 CPluginSettings* settings = CPluginSettings::GetInstance(); | 248 try |
| 249 { | |
| 250 if (unknownSite) | |
| 251 { | |
| 245 | 252 |
| 246 MULTIPLE_VERSIONS_CHECK(); | 253 DEBUG_GENERAL(L"========================================================== ======================\nNEW TAB UI\n============================================ ====================================") |
| 247 | 254 |
| 248 if (unknownSite) | 255 HRESULT hr = ::CoInitialize(NULL); |
| 249 { | 256 if (FAILED(hr)) |
| 257 { | |
| 258 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_COINIT, "Class::SetSite - CoInitialize"); | |
| 259 } | |
| 250 | 260 |
| 251 DEBUG_GENERAL(L"============================================================ ====================\nNEW TAB UI\n============================================== ==================================") | 261 s_criticalSectionBrowser.Lock(); |
| 262 { | |
| 263 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.
| |
| 264 } | |
| 265 s_criticalSectionBrowser.Unlock(); | |
| 252 | 266 |
| 253 HRESULT hr = ::CoInitialize(NULL); | 267 //register the mimefilter |
| 254 if (FAILED(hr)) | 268 //and only mimefilter |
| 255 { | 269 //on some few computers the mimefilter does not get properly registered wh en it is done on another thread |
| 256 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_COINIT, " Class::SetSite - CoInitialize"); | |
| 257 } | |
| 258 | 270 |
| 259 s_criticalSectionBrowser.Lock(); | 271 s_criticalSectionLocal.Lock(); |
| 260 { | 272 { |
| 261 m_webBrowser2 = unknownSite; | 273 // Always register on startup, then check if we need to unregister in a separate thread |
| 262 } | 274 s_mimeFilter = CPluginClientFactory::GetMimeFilterClientInstance(); |
| 263 s_criticalSectionBrowser.Unlock(); | 275 s_asyncWebBrowser2 = unknownSite; |
| 276 s_instances.insert(this); | |
| 277 } | |
| 278 s_criticalSectionLocal.Unlock(); | |
| 264 | 279 |
| 265 //register the mimefilter | 280 try |
| 266 //and only mimefilter | 281 { |
| 267 //on some few computers the mimefilter does not get properly registered when it is done on another thread | 282 // Check if loaded as BHO |
| 283 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.
| |
| 284 { | |
| 285 DEBUG_GENERAL("Loaded as BHO"); | |
| 286 CComPtr<IConnectionPoint> pPoint = GetConnectionPoint(); | |
| 287 if (pPoint) | |
| 288 { | |
| 289 HRESULT hr = pPoint->Advise((IDispatch*)this, &m_nConnectionID); | |
| 290 if (SUCCEEDED(hr)) | |
| 291 { | |
| 292 m_isAdviced = true; | |
| 268 | 293 |
| 269 s_criticalSectionLocal.Lock(); | 294 try |
| 270 { | 295 { |
| 271 // Always register on startup, then check if we need to unregister in a se parate thread | 296 std::thread startInitObjectThread(StartInitObject, this); |
| 272 s_mimeFilter = CPluginClientFactory::GetMimeFilterClientInstance(); | 297 startInitObjectThread.detach(); // TODO: but actually we should wait for the thread in the dtr. |
| 273 s_asyncWebBrowser2 = unknownSite; | 298 } |
| 274 s_instances.insert(this); | 299 catch (const std::system_error& ex) |
| 275 } | 300 { |
| 276 s_criticalSectionLocal.Unlock(); | 301 DEBUG_SYSTEM_EXCEPTION(ex, PLUGIN_ERROR_THREAD, PLUGIN_ERROR_MAI N_THREAD_CREATE_PROCESS, |
| 277 | 302 "Class::Thread - Failed to create StartInitObject thread"); |
| 278 try | 303 } |
| 279 { | 304 } |
| 280 // Check if loaded as BHO | 305 else |
| 281 if (GetBrowser()) | |
| 282 { | |
| 283 DEBUG_GENERAL("Loaded as BHO"); | |
| 284 CComPtr<IConnectionPoint> pPoint = GetConnectionPoint(); | |
| 285 if (pPoint) | |
| 286 { | |
| 287 HRESULT hr = pPoint->Advise((IDispatch*)this, &m_nConnectionID); | |
| 288 if (SUCCEEDED(hr)) | |
| 289 { | |
| 290 m_isAdviced = true; | |
| 291 | |
| 292 try | |
| 293 { | 306 { |
| 294 std::thread startInitObjectThread(StartInitObject, this); | 307 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_A DVICE, "Class::SetSite - Advice"); |
| 295 startInitObjectThread.detach(); // TODO: but actually we should wa it for the thread in the dtr. | |
| 296 } | 308 } |
| 297 catch (const std::system_error& ex) | |
| 298 { | |
| 299 DEBUG_SYSTEM_EXCEPTION(ex, PLUGIN_ERROR_THREAD, PLUGIN_ERROR_MAIN_ THREAD_CREATE_PROCESS, | |
| 300 "Class::Thread - Failed to create StartInitObject thread"); | |
| 301 } | |
| 302 } | |
| 303 else | |
| 304 { | |
| 305 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_ADV ICE, "Class::SetSite - Advice"); | |
| 306 } | 309 } |
| 307 } | 310 } |
| 308 } | 311 } |
| 309 else // Check if loaded as toolbar handler | 312 catch (const std::runtime_error& ex) |
| 310 { | 313 { |
| 311 DEBUG_GENERAL("Loaded as toolbar handler"); | 314 DEBUG_EXCEPTION(ex); |
| 312 CComPtr<IServiceProvider> pServiceProvider; | 315 Unadvice(); |
| 316 } | |
| 317 } | |
| 318 else | |
| 319 { | |
| 320 // Unadvice | |
| 321 Unadvice(); | |
| 313 | 322 |
| 314 HRESULT hr = unknownSite->QueryInterface(&pServiceProvider); | 323 // Destroy window |
| 315 if (SUCCEEDED(hr)) | 324 if (m_pWndProcStatus) |
| 325 { | |
| 326 ::SetWindowLongPtr(m_hStatusBarWnd, GWLP_WNDPROC, (LPARAM)(WNDPROC)m_pWn dProcStatus); | |
| 327 | |
| 328 m_pWndProcStatus = NULL; | |
| 329 } | |
| 330 | |
| 331 if (m_hPaneWnd) | |
| 332 { | |
| 333 DestroyWindow(m_hPaneWnd); | |
| 334 m_hPaneWnd = NULL; | |
| 335 } | |
| 336 | |
| 337 m_hTabWnd = NULL; | |
| 338 m_hStatusBarWnd = NULL; | |
| 339 | |
| 340 // Remove instance from the list, shutdown threads | |
| 341 HANDLE hMainThread = NULL; | |
| 342 HANDLE hTabThread = NULL; | |
| 343 | |
| 344 s_criticalSectionLocal.Lock(); | |
| 345 { | |
| 346 s_instances.erase(this); | |
| 347 | |
| 348 std::map<DWORD,CPluginClass*>::iterator it = s_threadInstances.find(::Ge tCurrentThreadId()); | |
| 349 if (it != s_threadInstances.end()) | |
| 316 { | 350 { |
| 317 if (pServiceProvider) | 351 s_threadInstances.erase(it); |
| 318 { | |
| 319 s_criticalSectionBrowser.Lock(); | |
| 320 { | |
| 321 HRESULT hr = pServiceProvider->QueryService(IID_IWebBrowserApp, &m _webBrowser2); | |
| 322 if (SUCCEEDED(hr)) | |
| 323 { | |
| 324 if (m_webBrowser2) | |
| 325 { | |
| 326 InitObject(false); | |
| 327 } | |
| 328 } | |
| 329 else | |
| 330 { | |
| 331 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE _QUERY_BROWSER, "Class::SetSite - QueryService (IID_IWebBrowserApp)"); | |
| 332 } | |
| 333 } | |
| 334 s_criticalSectionBrowser.Unlock(); | |
| 335 } | |
| 336 } | 352 } |
| 337 else | 353 if (s_instances.empty()) |
| 338 { | 354 { |
| 339 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_QUERY _SERVICE_PROVIDER, "Class::SetSite - QueryInterface (service provider)"); | 355 // TODO: Explicitly releasing a resource when a container becomes empt y looks like a job better suited for shared_ptr |
| 356 CPluginClientFactory::ReleaseMimeFilterClientInstance(); | |
| 340 } | 357 } |
| 341 } | 358 } |
| 342 } | 359 s_criticalSectionLocal.Unlock(); |
| 343 catch (const std::runtime_error& ex) | |
| 344 { | |
| 345 DEBUG_EXCEPTION(ex); | |
| 346 Unadvice(); | |
| 347 } | |
| 348 } | |
| 349 else | |
| 350 { | |
| 351 // Unadvice | |
| 352 Unadvice(); | |
| 353 | 360 |
| 354 // Destroy window | 361 // Release browser interface |
| 355 if (m_pWndProcStatus) | 362 s_criticalSectionBrowser.Lock(); |
| 356 { | 363 { |
| 357 ::SetWindowLongPtr(m_hStatusBarWnd, GWLP_WNDPROC, (LPARAM)(WNDPROC)m_pWndP rocStatus); | 364 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
| |
| 365 } | |
| 366 s_criticalSectionBrowser.Unlock(); | |
| 358 | 367 |
| 359 m_pWndProcStatus = NULL; | 368 DEBUG_GENERAL("=========================================================== =====================\nNEW TAB UI - END\n======================================= =========================================") |
| 369 | |
| 370 ::CoUninitialize(); | |
| 360 } | 371 } |
| 361 | 372 |
| 362 if (m_hPaneWnd) | 373 IObjectWithSiteImpl<CPluginClass>::SetSite(unknownSite); |
| 363 { | |
| 364 DestroyWindow(m_hPaneWnd); | |
| 365 m_hPaneWnd = NULL; | |
| 366 } | |
| 367 | |
| 368 m_hTabWnd = NULL; | |
| 369 m_hStatusBarWnd = NULL; | |
| 370 | |
| 371 // Remove instance from the list, shutdown threads | |
| 372 HANDLE hMainThread = NULL; | |
| 373 HANDLE hTabThread = NULL; | |
| 374 | |
| 375 s_criticalSectionLocal.Lock(); | |
| 376 { | |
| 377 s_instances.erase(this); | |
| 378 | |
| 379 std::map<DWORD,CPluginClass*>::iterator it = s_threadInstances.find(::GetC urrentThreadId()); | |
| 380 if (it != s_threadInstances.end()) | |
| 381 { | |
| 382 s_threadInstances.erase(it); | |
| 383 } | |
| 384 if (s_instances.empty()) | |
| 385 { | |
| 386 // TODO: Explicitly releasing a resource when a container becomes empty looks like a job better suited for shared_ptr | |
| 387 CPluginClientFactory::ReleaseMimeFilterClientInstance(); | |
| 388 } | |
| 389 } | |
| 390 s_criticalSectionLocal.Unlock(); | |
| 391 | |
| 392 // Release browser interface | |
| 393 s_criticalSectionBrowser.Lock(); | |
| 394 { | |
| 395 m_webBrowser2.Release(); | |
| 396 } | |
| 397 s_criticalSectionBrowser.Unlock(); | |
| 398 | |
| 399 DEBUG_GENERAL("============================================================= ===================\nNEW TAB UI - END\n========================================= =======================================") | |
| 400 | |
| 401 ::CoUninitialize(); | |
| 402 } | 374 } |
| 403 | 375 catch (...) |
| 404 return IObjectWithSiteImpl<CPluginClass>::SetSite(unknownSite); | 376 { |
| 377 } | |
| 378 return S_OK; | |
| 405 } | 379 } |
| 406 | 380 |
| 407 bool CPluginClass::IsStatusBarEnabled() | 381 bool CPluginClass::IsStatusBarEnabled() |
| 408 { | 382 { |
| 409 DEBUG_GENERAL("IsStatusBarEnabled start"); | 383 DEBUG_GENERAL("IsStatusBarEnabled start"); |
| 410 HKEY pHkey; | 384 HKEY pHkey; |
| 411 HKEY pHkeySub; | 385 HKEY pHkeySub; |
| 412 RegOpenCurrentUser(KEY_QUERY_VALUE, &pHkey); | 386 RegOpenCurrentUser(KEY_QUERY_VALUE, &pHkey); |
| 413 DWORD truth = 1; | 387 DWORD truth = 1; |
| 414 DWORD truthSize = sizeof(truth); | 388 DWORD truthSize = sizeof(truth); |
| (...skipping 1471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1886 } | 1860 } |
| 1887 } | 1861 } |
| 1888 } | 1862 } |
| 1889 | 1863 |
| 1890 hTabWnd = ::GetWindow(hTabWnd, GW_HWNDNEXT); | 1864 hTabWnd = ::GetWindow(hTabWnd, GW_HWNDNEXT); |
| 1891 } | 1865 } |
| 1892 | 1866 |
| 1893 return hTabWnd; | 1867 return hTabWnd; |
| 1894 | 1868 |
| 1895 } | 1869 } |
| OLD | NEW |