Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: src/plugin/PluginClass.cpp

Issue 29330403: Issue #1467, #3397 - Rewrite the map from threads to tabs (Closed)
Patch Set: rebase only Created Dec. 8, 2015, 7:43 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
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 12 matching lines...) Expand all
23 #include "PluginFilter.h" 23 #include "PluginFilter.h"
24 #include "PluginMimeFilterClient.h" 24 #include "PluginMimeFilterClient.h"
25 #include "AdblockPlusClient.h" 25 #include "AdblockPlusClient.h"
26 #include "PluginClientBase.h" 26 #include "PluginClientBase.h"
27 #include "PluginClientFactory.h" 27 #include "PluginClientFactory.h"
28 #include "PluginUtil.h" 28 #include "PluginUtil.h"
29 #include "../shared/Utils.h" 29 #include "../shared/Utils.h"
30 #include "../shared/Dictionary.h" 30 #include "../shared/Dictionary.h"
31 #include "IeVersion.h" 31 #include "IeVersion.h"
32 #include "../shared/Version.h" 32 #include "../shared/Version.h"
33 #include "Instances.h"
33 #include <thread> 34 #include <thread>
34 #include <array> 35 #include <array>
35 36
36 #ifdef DEBUG_HIDE_EL 37 #ifdef DEBUG_HIDE_EL
37 DWORD profileTime = 0; 38 DWORD profileTime = 0;
38 #endif 39 #endif
39 40
40 extern CComModule _Module; 41 extern CComModule _Module;
41 42
42 typedef HANDLE (WINAPI *OPENTHEMEDATA)(HWND, LPCWSTR); 43 typedef HANDLE (WINAPI *OPENTHEMEDATA)(HWND, LPCWSTR);
43 typedef HRESULT (WINAPI *DRAWTHEMEBACKGROUND)(HANDLE, HDC, INT, INT, LPRECT, LPR ECT); 44 typedef HRESULT (WINAPI *DRAWTHEMEBACKGROUND)(HANDLE, HDC, INT, INT, LPRECT, LPR ECT);
44 typedef HRESULT (WINAPI *CLOSETHEMEDATA)(HANDLE); 45 typedef HRESULT (WINAPI *CLOSETHEMEDATA)(HANDLE);
45 46
46 HICON CPluginClass::s_hIcons[ICON_MAX] = { NULL, NULL, NULL }; 47 HICON CPluginClass::s_hIcons[ICON_MAX] = { NULL, NULL, NULL };
47 DWORD CPluginClass::s_hIconTypes[ICON_MAX] = { IDI_ICON_DISABLED, IDI_ICON_ENABL ED, IDI_ICON_DEACTIVATED }; 48 DWORD CPluginClass::s_hIconTypes[ICON_MAX] = { IDI_ICON_DISABLED, IDI_ICON_ENABL ED, IDI_ICON_DEACTIVATED };
48 uint32_t iconHeight = 32; 49 uint32_t iconHeight = 32;
49 uint32_t iconWidth = 32; 50 uint32_t iconWidth = 32;
50 51
51 CPluginMimeFilterClient* CPluginClass::s_mimeFilter = NULL; 52 CPluginMimeFilterClient* CPluginClass::s_mimeFilter = NULL;
52 53
53 CLOSETHEMEDATA pfnClose = NULL; 54 CLOSETHEMEDATA pfnClose = NULL;
54 DRAWTHEMEBACKGROUND pfnDrawThemeBackground = NULL; 55 DRAWTHEMEBACKGROUND pfnDrawThemeBackground = NULL;
55 OPENTHEMEDATA pfnOpenThemeData = NULL; 56 OPENTHEMEDATA pfnOpenThemeData = NULL;
56 57
57 ATOM CPluginClass::s_atomPaneClass = NULL; 58 ATOM CPluginClass::s_atomPaneClass = NULL;
58 HINSTANCE CPluginClass::s_hUxtheme = NULL; 59 HINSTANCE CPluginClass::s_hUxtheme = NULL;
59 std::set<CPluginClass*> CPluginClass::s_instances; 60 std::set<CPluginClass*> CPluginClass::s_instances;
60 std::map<DWORD, CPluginClass*> CPluginClass::s_threadInstances;
61 61
62 CComAutoCriticalSection CPluginClass::s_criticalSectionLocal; 62 CComAutoCriticalSection CPluginClass::s_criticalSectionLocal;
63 CComAutoCriticalSection CPluginClass::s_criticalSectionWindow; 63 CComAutoCriticalSection CPluginClass::s_criticalSectionWindow;
64 64
65 CComQIPtr<IWebBrowser2> CPluginClass::s_asyncWebBrowser2; 65 CComQIPtr<IWebBrowser2> CPluginClass::s_asyncWebBrowser2;
66 66
67
sergei 2016/02/01 15:50:43 Why not to put it into anonymous namespace?
Eric 2016/02/03 17:17:05 OK.
68 /**
69 * A synchronized map whose key is always the current thread ID.
70 */
71 class CurrentThreadMap
72 : public SyncMap<DWORD, CPluginClass*, nullptr>
73 {
74 typedef SyncMap<DWORD, CPluginClass*, nullptr> Base;
75
76 public:
77 bool AddIfAbsent(CPluginClass* p)
78 {
79 return Base::AddIfAbsent(::GetCurrentThreadId(), p);
80 }
81
82 bool RemoveAndCheck()
83 {
84 return Base::RemoveAndCheck(::GetCurrentThreadId());
85 }
86
87 CPluginClass* Locate()
88 {
89 return Base::Locate(::GetCurrentThreadId());
90 }
91 };
92
93 /**
94 * Map from thread ID's to CPluginClass instances
95 */
96 CurrentThreadMap threadMap;
sergei 2016/02/01 15:50:43 Off topic: Still a global variable. When will we s
Eric 2016/02/03 17:17:05 The map from threads to BHO instances is inherentl
97
67 /* 98 /*
68 * Without namespace declaration, the identifier "Rectangle" is ambiguous 99 * Without namespace declaration, the identifier "Rectangle" is ambiguous
69 * See http://msdn.microsoft.com/en-us/library/windows/desktop/dd162898(v=vs.85) .aspx 100 * See http://msdn.microsoft.com/en-us/library/windows/desktop/dd162898(v=vs.85) .aspx
70 */ 101 */
71 namespace AdblockPlus 102 namespace AdblockPlus
72 { 103 {
73 /** 104 /**
74 * Replacement for ATL type CRect. 105 * Replacement for ATL type CRect.
75 */ 106 */
76 class Rectangle 107 class Rectangle
(...skipping 19 matching lines...) Expand all
96 // _CrtDumpMemoryLeaks(); 127 // _CrtDumpMemoryLeaks();
97 128
98 m_isAdvised = false; 129 m_isAdvised = false;
99 m_hTabWnd = NULL; 130 m_hTabWnd = NULL;
100 m_hStatusBarWnd = NULL; 131 m_hStatusBarWnd = NULL;
101 m_hPaneWnd = NULL; 132 m_hPaneWnd = NULL;
102 m_nPaneWidth = 0; 133 m_nPaneWidth = 0;
103 m_pWndProcStatus = NULL; 134 m_pWndProcStatus = NULL;
104 m_hTheme = NULL; 135 m_hTheme = NULL;
105 m_isInitializedOk = false; 136 m_isInitializedOk = false;
106
107
108 m_tab = new CPluginTab(this); 137 m_tab = new CPluginTab(this);
109
110 Dictionary::Create(GetBrowserLanguage()); 138 Dictionary::Create(GetBrowserLanguage());
111 } 139 }
112 140
113 CPluginClass::~CPluginClass() 141 CPluginClass::~CPluginClass()
114 { 142 {
115 delete m_tab; 143 delete m_tab;
116 } 144 }
117 145
118 HWND CPluginClass::GetBrowserHWND() const 146 HWND CPluginClass::GetBrowserHWND() const
119 { 147 {
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 236
209 /* 237 /*
210 * We were instantiated as a BHO, so our site is always of type IWebBrowse r2. 238 * We were instantiated as a BHO, so our site is always of type IWebBrowse r2.
211 */ 239 */
212 m_webBrowser2 = ATL::CComQIPtr<IWebBrowser2>(unknownSite); 240 m_webBrowser2 = ATL::CComQIPtr<IWebBrowser2>(unknownSite);
213 if (!m_webBrowser2) 241 if (!m_webBrowser2)
214 { 242 {
215 throw std::logic_error("CPluginClass::SetSite - Unable to convert site p ointer to IWebBrowser2*"); 243 throw std::logic_error("CPluginClass::SetSite - Unable to convert site p ointer to IWebBrowser2*");
216 } 244 }
217 245
246 /*
247 * Add ourselves to the thread map.
248 */
249 if (!threadMap.AddIfAbsent(this))
250 {
251 throw std::logic_error("CPluginClass::SetSite - May not overwrite existi ng entry in thread map");
sergei 2016/02/01 15:50:43 That looks suspicious. It can happen that two inst
Eric 2016/02/03 17:17:05 Actually, that cannot happen.
252 }
253
218 //register the mimefilter 254 //register the mimefilter
219 //and only mimefilter 255 //and only mimefilter
220 //on some few computers the mimefilter does not get properly registered wh en it is done on another thread 256 //on some few computers the mimefilter does not get properly registered wh en it is done on another thread
221 s_criticalSectionLocal.Lock(); 257 s_criticalSectionLocal.Lock();
222 { 258 {
223 // Always register on startup, then check if we need to unregister in a separate thread 259 // Always register on startup, then check if we need to unregister in a separate thread
224 s_mimeFilter = CPluginClientFactory::GetMimeFilterClientInstance(); 260 s_mimeFilter = CPluginClientFactory::GetMimeFilterClientInstance();
225 s_asyncWebBrowser2 = unknownSite; 261 s_asyncWebBrowser2 = unknownSite;
226 s_instances.insert(this); 262 s_instances.insert(this);
227 } 263 }
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 m_hPaneWnd = NULL; 310 m_hPaneWnd = NULL;
275 } 311 }
276 312
277 m_hTabWnd = NULL; 313 m_hTabWnd = NULL;
278 m_hStatusBarWnd = NULL; 314 m_hStatusBarWnd = NULL;
279 315
280 // Remove instance from the list, shutdown threads 316 // Remove instance from the list, shutdown threads
281 HANDLE hMainThread = NULL; 317 HANDLE hMainThread = NULL;
282 HANDLE hTabThread = NULL; 318 HANDLE hTabThread = NULL;
283 319
320 if (!threadMap.RemoveAndCheck())
321 {
322 throw std::logic_error("CPluginClass::SetSite - Missing entry in thread map");
323 }
324
284 s_criticalSectionLocal.Lock(); 325 s_criticalSectionLocal.Lock();
285 { 326 {
286 s_instances.erase(this); 327 s_instances.erase(this);
287
288 std::map<DWORD,CPluginClass*>::iterator it = s_threadInstances.find(::Ge tCurrentThreadId());
289 if (it != s_threadInstances.end())
290 {
291 s_threadInstances.erase(it);
292 }
293 if (s_instances.empty()) 328 if (s_instances.empty())
294 { 329 {
295 // TODO: Explicitly releasing a resource when a container becomes empt y looks like a job better suited for shared_ptr 330 // TODO: Explicitly releasing a resource when a container becomes empt y looks like a job better suited for shared_ptr
296 CPluginClientFactory::ReleaseMimeFilterClientInstance(); 331 CPluginClientFactory::ReleaseMimeFilterClientInstance();
297 } 332 }
298 } 333 }
299 s_criticalSectionLocal.Unlock(); 334 s_criticalSectionLocal.Unlock();
300 335
301 m_webBrowser2 = nullptr; 336 m_webBrowser2 = nullptr;
302 337
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
519 // Entry point 554 // Entry point
520 void STDMETHODCALLTYPE CPluginClass::OnWindowStateChanged(unsigned long flags, u nsigned long validFlagsMask) 555 void STDMETHODCALLTYPE CPluginClass::OnWindowStateChanged(unsigned long flags, u nsigned long validFlagsMask)
521 { 556 {
522 try 557 try
523 { 558 {
524 DEBUG_GENERAL(L"WindowStateChanged (check tab changed)"); 559 DEBUG_GENERAL(L"WindowStateChanged (check tab changed)");
525 bool newtabshown = validFlagsMask == (OLECMDIDF_WINDOWSTATE_USERVISIBLE | OL ECMDIDF_WINDOWSTATE_ENABLED) 560 bool newtabshown = validFlagsMask == (OLECMDIDF_WINDOWSTATE_USERVISIBLE | OL ECMDIDF_WINDOWSTATE_ENABLED)
526 && flags == (OLECMDIDF_WINDOWSTATE_USERVISIBLE | OLECMDIDF_WINDOWSTATE_ENA BLED); 561 && flags == (OLECMDIDF_WINDOWSTATE_USERVISIBLE | OLECMDIDF_WINDOWSTATE_ENA BLED);
527 if (newtabshown) 562 if (newtabshown)
528 { 563 {
529 std::map<DWORD,CPluginClass*>::const_iterator it = s_threadInstances.find( GetCurrentThreadId()); 564 if (!m_isInitializedOk)
530 if (it == s_threadInstances.end())
531 { 565 {
532 s_threadInstances[::GetCurrentThreadId()] = this; 566 m_isInitializedOk = true;
sergei 2016/02/01 15:50:43 Pay attention that we are overriding the value of
Eric 2016/02/03 17:17:05 I don't know what you mean here.
533 if (!m_isInitializedOk) 567 InitObject();
534 { 568 UpdateStatusBar();
535 m_isInitializedOk = true;
536 InitObject();
537 UpdateStatusBar();
538 }
539 } 569 }
540 } 570 }
541 notificationMessage.Hide(); 571 notificationMessage.Hide();
542 DEBUG_GENERAL(L"WindowStateChanged (check tab changed) end"); 572 DEBUG_GENERAL(L"WindowStateChanged (check tab changed) end");
543 } 573 }
544 catch (...) 574 catch (...)
545 { 575 {
546 } 576 }
547 } 577 }
548 578
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after
947 s_criticalSectionLocal.Unlock(); 977 s_criticalSectionLocal.Unlock();
948 978
949 return result; 979 return result;
950 } 980 }
951 981
952 CPluginTab* CPluginClass::GetTab() 982 CPluginTab* CPluginClass::GetTab()
953 { 983 {
954 return m_tab; 984 return m_tab;
955 } 985 }
956 986
957 CPluginTab* CPluginClass::GetTab(DWORD dwThreadId) 987 CPluginTab* CPluginClass::GetTabCurrentThread()
958 { 988 {
959 CPluginTab* tab = NULL; 989 auto p = threadMap.Locate();
960 990 return p ? p->m_tab : nullptr;
961 s_criticalSectionLocal.Lock();
962 {
963 std::map<DWORD,CPluginClass*>::const_iterator it = s_threadInstances.find(dw ThreadId);
964 if (it != s_threadInstances.end())
965 {
966 tab = it->second->m_tab;
967 }
968 }
969 s_criticalSectionLocal.Unlock();
970
971 return tab;
972 } 991 }
973 992
974 993
975 STDMETHODIMP CPluginClass::QueryStatus(const GUID* pguidCmdGroup, ULONG cCmds, O LECMD prgCmds[], OLECMDTEXT* pCmdText) 994 STDMETHODIMP CPluginClass::QueryStatus(const GUID* pguidCmdGroup, ULONG cCmds, O LECMD prgCmds[], OLECMDTEXT* pCmdText)
976 { 995 {
977 if (cCmds == 0) return E_INVALIDARG; 996 if (cCmds == 0) return E_INVALIDARG;
978 if (prgCmds == 0) return E_POINTER; 997 if (prgCmds == 0) return E_POINTER;
979 998
980 prgCmds[0].cmdf = OLECMDF_ENABLED; 999 prgCmds[0].cmdf = OLECMDF_ENABLED;
981 1000
(...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after
1342 return result; 1361 return result;
1343 1362
1344 } 1363 }
1345 1364
1346 1365
1347 HICON CPluginClass::GetStatusBarIcon(const std::wstring& url) 1366 HICON CPluginClass::GetStatusBarIcon(const std::wstring& url)
1348 { 1367 {
1349 // use the disable icon as defualt, if the client doesn't exists 1368 // use the disable icon as defualt, if the client doesn't exists
1350 HICON hIcon = GetIcon(ICON_PLUGIN_DEACTIVATED); 1369 HICON hIcon = GetIcon(ICON_PLUGIN_DEACTIVATED);
1351 1370
1352 CPluginTab* tab = GetTab(::GetCurrentThreadId()); 1371 CPluginTab* tab = GetTabCurrentThread();
1353 if (tab) 1372 if (tab)
1354 { 1373 {
1355 CPluginClient* client = CPluginClient::GetInstance(); 1374 CPluginClient* client = CPluginClient::GetInstance();
1356 if (CPluginSettings::GetInstance()->IsPluginEnabled()) 1375 if (CPluginSettings::GetInstance()->IsPluginEnabled())
1357 { 1376 {
1358 if (client->IsWhitelistedUrl(url)) 1377 if (client->IsWhitelistedUrl(url))
1359 { 1378 {
1360 hIcon = GetIcon(ICON_PLUGIN_DISABLED); 1379 hIcon = GetIcon(ICON_PLUGIN_DISABLED);
1361 } 1380 }
1362 else 1381 else
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
1505 pClass->DisplayPluginMenu(hMenu, -1, pt, TPM_LEFTALIGN|TPM_BOTTOMALIGN); 1524 pClass->DisplayPluginMenu(hMenu, -1, pt, TPM_LEFTALIGN|TPM_BOTTOMALIGN);
1506 } 1525 }
1507 break; 1526 break;
1508 case WM_DESTROY: 1527 case WM_DESTROY:
1509 break; 1528 break;
1510 case SC_CLOSE: 1529 case SC_CLOSE:
1511 break; 1530 break;
1512 1531
1513 case WM_UPDATEUISTATE: 1532 case WM_UPDATEUISTATE:
1514 { 1533 {
1515 CPluginTab* tab = GetTab(::GetCurrentThreadId()); 1534 CPluginTab* tab = GetTabCurrentThread();
1516 if (tab) 1535 if (tab)
1517 { 1536 {
1518 tab->OnActivate(); 1537 tab->OnActivate();
1519 RECT rect; 1538 RECT rect;
1520 GetWindowRect(pClass->m_hPaneWnd, &rect); 1539 GetWindowRect(pClass->m_hPaneWnd, &rect);
1521 pClass->notificationMessage.Move(rect.left + (rect.right - rect.left) / 2, rect.top + (rect.bottom - rect.top) / 2); 1540 pClass->notificationMessage.Move(rect.left + (rect.right - rect.left) / 2, rect.top + (rect.bottom - rect.top) / 2);
1522 } 1541 }
1523 if (LOWORD(wParam) == UIS_CLEAR) 1542 if (LOWORD(wParam) == UIS_CLEAR)
1524 { 1543 {
1525 pClass->notificationMessage.Hide(); 1544 pClass->notificationMessage.Hide();
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1633 s_criticalSectionLocal.Unlock(); 1652 s_criticalSectionLocal.Unlock();
1634 1653
1635 return icon; 1654 return icon;
1636 } 1655 }
1637 1656
1638 ATOM CPluginClass::GetAtomPaneClass() 1657 ATOM CPluginClass::GetAtomPaneClass()
1639 { 1658 {
1640 return s_atomPaneClass; 1659 return s_atomPaneClass;
1641 } 1660 }
1642 1661
OLDNEW

Powered by Google App Engine
This is Rietveld