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

Delta Between Two Patch Sets: src/plugin/PluginClass.cpp

Issue 29332848: Issue #3432 - Manage COM events with a resource class
Left Patch Set: rebase Created Jan. 5, 2016, 4:21 p.m.
Right Patch Set: rebase only Created July 27, 2016, 8:55 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « src/plugin/PluginClass.h ('k') | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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-2016 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
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18 #include "PluginStdAfx.h" 18 #include "PluginStdAfx.h"
19 19
20 #include "PluginClass.h" 20 #include "PluginClass.h"
21 #include "PluginSettings.h" 21 #include "PluginSettings.h"
22 #include "PluginSystem.h" 22 #include "PluginSystem.h"
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
67 namespace
68 {
69 /**
70 * A synchronized map whose key is always the current thread ID.
71 */
72 class CurrentThreadMap
73 : public SyncMap<DWORD, CPluginClass*, nullptr>
74 {
75 typedef SyncMap<DWORD, CPluginClass*, nullptr> Base;
76
77 public:
78 bool AddIfAbsent(CPluginClass* p)
79 {
80 return Base::AddIfAbsent(::GetCurrentThreadId(), p);
81 }
82
83 bool RemoveAndCheck()
84 {
85 return Base::RemoveIfPresent(::GetCurrentThreadId());
86 }
87
88 CPluginClass* Locate()
89 {
90 return Base::Locate(::GetCurrentThreadId());
91 }
92 };
93
94 /**
95 * Map from thread ID's to CPluginClass instances
96 */
97 CurrentThreadMap threadMap;
98 }
66 99
67 /* 100 /*
68 * Without namespace declaration, the identifier "Rectangle" is ambiguous 101 * Without namespace declaration, the identifier "Rectangle" is ambiguous
69 * See http://msdn.microsoft.com/en-us/library/windows/desktop/dd162898(v=vs.85) .aspx 102 * See http://msdn.microsoft.com/en-us/library/windows/desktop/dd162898(v=vs.85) .aspx
70 */ 103 */
71 namespace AdblockPlus 104 namespace AdblockPlus
72 { 105 {
73 /** 106 /**
74 * Replacement for ATL type CRect. 107 * Replacement for ATL type CRect.
75 */ 108 */
76 class Rectangle 109 class Rectangle
77 : public RECT 110 : public RECT
78 { 111 {
79 public: 112 public:
80 int Height() const 113 unsigned long Height() const
81 { 114 {
82 return bottom - top; 115 if (bottom < top)
83 } 116 {
84 117 throw std::runtime_error("invariant violation: rectangle bottom < top");
85 int Width() const 118 }
86 { 119 return static_cast<unsigned long>(bottom - top);
87 return right - left; 120 }
121
122 unsigned long Width() const
123 {
124 if (right < left)
125 {
126 throw std::runtime_error("invariant violation: rectangle right < left");
127 }
128 return static_cast<unsigned long>(right - left);
88 } 129 }
89 }; 130 };
90 } 131 }
91 132
92 CPluginClass::CPluginClass() 133 CPluginClass::CPluginClass()
93 : m_webBrowser2(nullptr), 134 : m_webBrowser2(nullptr),
94 detachedInitializationFailed(false) 135 detachedInitializationFailed(false)
95 { 136 {
96 DEBUG_GENERAL([this]() -> std::wstring 137 DEBUG_GENERAL([this]() -> std::wstring
97 { 138 {
98 std::wstring s = L"CPluginClass::<constructor>, this = "; 139 std::wstring s = L"CPluginClass::<constructor>, this = ";
99 s += ToHexLiteral(this); 140 s += ToHexLiteral(this);
100 return s; 141 return s;
101 }()); 142 }());
102 143
103 //Use this line to debug memory leaks 144 //Use this line to debug memory leaks
104 // _CrtDumpMemoryLeaks(); 145 // _CrtDumpMemoryLeaks();
105 146
106 m_hTabWnd = NULL; 147 m_hTabWnd = NULL;
107 m_hStatusBarWnd = NULL; 148 m_hStatusBarWnd = NULL;
108 m_hPaneWnd = NULL; 149 m_hPaneWnd = NULL;
109 m_nPaneWidth = 0; 150 m_nPaneWidth = 0;
110 m_pWndProcStatus = NULL; 151 m_pWndProcStatus = NULL;
111 m_hTheme = NULL; 152 m_hTheme = NULL;
112 m_isInitializedOk = false; 153 m_isInitializedOk = false;
113
114
115 m_tab = new CPluginTab(); 154 m_tab = new CPluginTab();
116
117 Dictionary::Create(GetBrowserLanguage()); 155 Dictionary::Create(GetBrowserLanguage());
118 } 156 }
119 157
120 CPluginClass::~CPluginClass() 158 CPluginClass::~CPluginClass()
121 { 159 {
122 DEBUG_GENERAL([this]() -> std::wstring 160 DEBUG_GENERAL([this]() -> std::wstring
123 { 161 {
124 std::wstring s = L"CPluginClass::<destructor>, this = "; 162 std::wstring s = L"CPluginClass::<destructor>, this = ";
125 s += ToHexLiteral(this); 163 s += ToHexLiteral(this);
126 return s; 164 return s;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 201
164 return browser; 202 return browser;
165 } 203 }
166 204
167 std::wstring CPluginClass::GetBrowserUrl() const 205 std::wstring CPluginClass::GetBrowserUrl() const
168 { 206 {
169 std::wstring url; 207 std::wstring url;
170 if (m_webBrowser2) 208 if (m_webBrowser2)
171 { 209 {
172 CComBSTR bstrURL; 210 CComBSTR bstrURL;
173 if (SUCCEEDED(m_webBrowser2->get_LocationURL(&bstrURL)) && bstrURL) 211 if (SUCCEEDED(m_webBrowser2->get_LocationURL(&bstrURL)))
174 { 212 {
175 url = std::wstring(bstrURL, SysStringLen(bstrURL)); 213 url = ToWstring(bstrURL);
176 } 214 }
177 } 215 }
178 else 216 else
179 { 217 {
180 DEBUG_ERROR_LOG(0, 0, 0, "CPluginClass::GetBrowserUrl - Reached with m_webBr owser2 == nullptr"); 218 DEBUG_GENERAL(L"CPluginClass::GetBrowserUrl - Reached with m_webBrowser2 == nullptr (probable invariant violation)");
219 }
220 if (url.empty())
221 {
181 url = m_tab->GetDocumentUrl(); 222 url = m_tab->GetDocumentUrl();
182 } 223 }
183 return url; 224 return url;
184 } 225 }
185 226
186 DWORD WINAPI CPluginClass::StartInitObject(LPVOID thisPtr) 227 DWORD WINAPI CPluginClass::StartInitObject(LPVOID thisPtr)
187 { 228 {
188 if (thisPtr == NULL) 229 if (thisPtr == NULL)
189 return 0; 230 return 0;
190 auto self = static_cast<CPluginClass*>(thisPtr); 231 auto self = static_cast<CPluginClass*>(thisPtr);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 throw std::logic_error("CPluginClass::SetSite - Unable to convert site p ointer to IWebBrowser2*"); 268 throw std::logic_error("CPluginClass::SetSite - Unable to convert site p ointer to IWebBrowser2*");
228 } 269 }
229 DEBUG_GENERAL([this]() -> std::wstring 270 DEBUG_GENERAL([this]() -> std::wstring
230 { 271 {
231 std::wstringstream ss; 272 std::wstringstream ss;
232 ss << L"CPluginClass::SetSite, this = " << ToHexLiteral(this); 273 ss << L"CPluginClass::SetSite, this = " << ToHexLiteral(this);
233 ss << L", browser = " << ToHexLiteral(m_webBrowser2); 274 ss << L", browser = " << ToHexLiteral(m_webBrowser2);
234 return ss.str(); 275 return ss.str();
235 }()); 276 }());
236 277
278 /*
279 * Add ourselves to the thread map.
280 */
281 if (!threadMap.AddIfAbsent(this))
282 {
283 throw std::logic_error("CPluginClass::SetSite - May not overwrite existi ng entry in thread map");
284 }
285
237 //register the mimefilter 286 //register the mimefilter
238 //and only mimefilter 287 //and only mimefilter
239 //on some few computers the mimefilter does not get properly registered wh en it is done on another thread 288 //on some few computers the mimefilter does not get properly registered wh en it is done on another thread
240 s_criticalSectionLocal.Lock(); 289 s_criticalSectionLocal.Lock();
241 { 290 {
242 // Always register on startup, then check if we need to unregister in a separate thread 291 // Always register on startup, then check if we need to unregister in a separate thread
243 s_mimeFilter = CPluginClientFactory::GetMimeFilterClientInstance(); 292 s_mimeFilter = CPluginClientFactory::GetMimeFilterClientInstance();
244 s_asyncWebBrowser2 = unknownSite; 293 s_asyncWebBrowser2 = unknownSite;
245 s_instances.insert(this); 294 s_instances.insert(this);
246 } 295 }
247 s_criticalSectionLocal.Unlock(); 296 s_criticalSectionLocal.Unlock();
248 297
249 try 298 try
250 { 299 {
251 std::thread startInitObjectThread(StartInitObject, this); 300 std::thread startInitObjectThread(StartInitObject, this);
252 startInitObjectThread.detach(); // TODO: but actually we should wait for the thread in the dtr. 301 startInitObjectThread.detach(); // TODO: but actually we should wait for the thread in the dtr.
253 } 302 }
254 catch (const std::system_error& ex) 303 catch (const std::system_error& ex)
255 { 304 {
256 detachedInitializationFailed = true; 305 detachedInitializationFailed = true;
257 DEBUG_SYSTEM_EXCEPTION(ex, PLUGIN_ERROR_THREAD, PLUGIN_ERROR_MAIN_THREAD _CREATE_PROCESS, 306 DEBUG_SYSTEM_EXCEPTION(ex, PLUGIN_ERROR_THREAD, PLUGIN_ERROR_MAIN_THREAD _CREATE_PROCESS,
258 "Class::Thread - Failed to create StartInitObject thread"); 307 "Class::Thread - Failed to create StartInitObject thread");
259 } 308 }
260 309
261 // Start event last, after everything is ready to go 310 // Start events last to alleviate issues with deferred evaluation
sergei 2016/01/06 08:41:57 This comment is confusing because not everything i
Eric 2016/01/07 16:24:47 Reworded.
262 browserEvents.Start(this, m_webBrowser2); 311 browserEvents.Start(this, m_webBrowser2);
263 } 312 }
264 else 313 else
265 { 314 {
266 browserEvents.Stop(); 315 browserEvents.Stop();
267 DEBUG_GENERAL([this]() -> std::wstring 316 DEBUG_GENERAL([this]() -> std::wstring
268 { 317 {
269 std::wstringstream ss; 318 std::wstringstream ss;
270 ss << L"CPluginClass::SetSite, this = " << ToHexLiteral(this); 319 ss << L"CPluginClass::SetSite, this = " << ToHexLiteral(this);
271 ss << L", browser = nullptr"; 320 ss << L", browser = nullptr";
(...skipping 15 matching lines...) Expand all
287 m_hPaneWnd = NULL; 336 m_hPaneWnd = NULL;
288 } 337 }
289 338
290 m_hTabWnd = NULL; 339 m_hTabWnd = NULL;
291 m_hStatusBarWnd = NULL; 340 m_hStatusBarWnd = NULL;
292 341
293 // Remove instance from the list, shutdown threads 342 // Remove instance from the list, shutdown threads
294 HANDLE hMainThread = NULL; 343 HANDLE hMainThread = NULL;
295 HANDLE hTabThread = NULL; 344 HANDLE hTabThread = NULL;
296 345
346 if (!threadMap.RemoveAndCheck())
347 {
348 throw std::logic_error("CPluginClass::SetSite - Missing entry in thread map");
349 }
350
297 s_criticalSectionLocal.Lock(); 351 s_criticalSectionLocal.Lock();
298 { 352 {
299 s_instances.erase(this); 353 s_instances.erase(this);
300
301 std::map<DWORD,CPluginClass*>::iterator it = s_threadInstances.find(::Ge tCurrentThreadId());
302 if (it != s_threadInstances.end())
303 {
304 s_threadInstances.erase(it);
305 }
306 if (s_instances.empty()) 354 if (s_instances.empty())
307 { 355 {
308 // TODO: Explicitly releasing a resource when a container becomes empt y looks like a job better suited for shared_ptr 356 // TODO: Explicitly releasing a resource when a container becomes empt y looks like a job better suited for shared_ptr
309 CPluginClientFactory::ReleaseMimeFilterClientInstance(); 357 CPluginClientFactory::ReleaseMimeFilterClientInstance();
310 } 358 }
311 } 359 }
312 s_criticalSectionLocal.Unlock(); 360 s_criticalSectionLocal.Unlock();
313 361
314 m_webBrowser2 = nullptr; 362 m_webBrowser2 = nullptr;
315 363
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
444 IDispatch* frameBrowserDisp /**< [in] */, 492 IDispatch* frameBrowserDisp /**< [in] */,
445 VARIANT* urlVariant /**< [in] */, 493 VARIANT* urlVariant /**< [in] */,
446 VARIANT* /**< [in] Flags*/, 494 VARIANT* /**< [in] Flags*/,
447 VARIANT* /**< [in] TargetFrameName*/, 495 VARIANT* /**< [in] TargetFrameName*/,
448 VARIANT* /**< [in] PostData*/, 496 VARIANT* /**< [in] PostData*/,
449 VARIANT* /**< [in] Headers*/, 497 VARIANT* /**< [in] Headers*/,
450 VARIANT_BOOL* /**< [in, out] Cancel*/) 498 VARIANT_BOOL* /**< [in, out] Cancel*/)
451 { 499 {
452 try 500 try
453 { 501 {
454 if (detachedInitializationFailed) return; 502 if (detachedInitializationFailed) return;
sergei 2016/01/06 08:41:57 Basically all these checks in each method are indi
sergei 2016/01/06 08:41:57 it would be better to use some method `bool IsInit
Eric 2016/01/07 16:24:47 Something is definitely wrong with the design. It'
Eric 2016/01/07 16:24:48 I don't disagree in principle, but that change is
sergei 2016/02/04 13:45:49 Acknowledged.
455 503
456 ATL::CComQIPtr<IWebBrowser2> webBrowser = frameBrowserDisp; 504 ATL::CComQIPtr<IWebBrowser2> webBrowser = frameBrowserDisp;
457 if (!webBrowser) 505 if (!webBrowser)
458 { 506 {
459 return; 507 return;
460 } 508 }
461 if (!urlVariant || urlVariant->vt != VT_BSTR) 509 if (!urlVariant || urlVariant->vt != VT_BSTR)
462 { 510 {
463 return; 511 return;
464 } 512 }
465 std::wstring url(urlVariant->bstrVal, SysStringLen(urlVariant->bstrVal)); 513 std::wstring url = ToWstring(urlVariant->bstrVal);
466 514
467 // If webbrowser2 is equal to top level browser (as set in SetSite), we are 515 // If webbrowser2 is equal to top level browser (as set in SetSite), we are
468 // navigating new page 516 // navigating new page
469 CPluginClient* client = CPluginClient::GetInstance(); 517 CPluginClient* client = CPluginClient::GetInstance();
470 if (url.find(L"javascript") == 0) 518 if (url.find(L"javascript") == 0)
471 { 519 {
472 } 520 }
473 else if (IsRootBrowser(webBrowser)) 521 else if (IsRootBrowser(webBrowser))
474 { 522 {
475 m_tab->OnNavigate(url); 523 m_tab->OnNavigate(url);
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
537 void STDMETHODCALLTYPE CPluginClass::OnWindowStateChanged(unsigned long flags, u nsigned long validFlagsMask) 585 void STDMETHODCALLTYPE CPluginClass::OnWindowStateChanged(unsigned long flags, u nsigned long validFlagsMask)
538 { 586 {
539 if (detachedInitializationFailed) return; 587 if (detachedInitializationFailed) return;
540 try 588 try
541 { 589 {
542 DEBUG_GENERAL(L"WindowStateChanged (check tab changed)"); 590 DEBUG_GENERAL(L"WindowStateChanged (check tab changed)");
543 bool newtabshown = validFlagsMask == (OLECMDIDF_WINDOWSTATE_USERVISIBLE | OL ECMDIDF_WINDOWSTATE_ENABLED) 591 bool newtabshown = validFlagsMask == (OLECMDIDF_WINDOWSTATE_USERVISIBLE | OL ECMDIDF_WINDOWSTATE_ENABLED)
544 && flags == (OLECMDIDF_WINDOWSTATE_USERVISIBLE | OLECMDIDF_WINDOWSTATE_ENA BLED); 592 && flags == (OLECMDIDF_WINDOWSTATE_USERVISIBLE | OLECMDIDF_WINDOWSTATE_ENA BLED);
545 if (newtabshown) 593 if (newtabshown)
546 { 594 {
547 std::map<DWORD,CPluginClass*>::const_iterator it = s_threadInstances.find( GetCurrentThreadId()); 595 if (!m_isInitializedOk)
548 if (it == s_threadInstances.end()) 596 {
549 { 597 m_isInitializedOk = true;
550 s_threadInstances[::GetCurrentThreadId()] = this; 598 InitObject();
551 if (!m_isInitializedOk) 599 UpdateStatusBar();
552 {
553 m_isInitializedOk = true;
554 InitObject();
555 UpdateStatusBar();
556 }
557 } 600 }
558 } 601 }
559 notificationMessage.Hide(); 602 notificationMessage.Hide();
560 DEBUG_GENERAL(L"WindowStateChanged (check tab changed) end"); 603 DEBUG_GENERAL(L"WindowStateChanged (check tab changed) end");
561 } 604 }
562 catch (...) 605 catch (...)
563 { 606 {
564 } 607 }
565 } 608 }
566 609
(...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after
954 s_criticalSectionLocal.Unlock(); 997 s_criticalSectionLocal.Unlock();
955 998
956 return result; 999 return result;
957 } 1000 }
958 1001
959 CPluginTab* CPluginClass::GetTab() 1002 CPluginTab* CPluginClass::GetTab()
960 { 1003 {
961 return m_tab; 1004 return m_tab;
962 } 1005 }
963 1006
964 CPluginTab* CPluginClass::GetTab(DWORD dwThreadId) 1007 CPluginTab* CPluginClass::GetTabForCurrentThread()
965 { 1008 {
966 CPluginTab* tab = NULL; 1009 auto p = threadMap.Locate();
967 1010 return p ? p->m_tab : nullptr;
968 s_criticalSectionLocal.Lock(); 1011 }
969 { 1012
970 std::map<DWORD,CPluginClass*>::const_iterator it = s_threadInstances.find(dw ThreadId); 1013 // Entry point
971 if (it != s_threadInstances.end())
972 {
973 tab = it->second->m_tab;
974 }
975 }
976 s_criticalSectionLocal.Unlock();
977
978 return tab;
979 }
980
981
982 STDMETHODIMP CPluginClass::QueryStatus(const GUID* pguidCmdGroup, ULONG cCmds, O LECMD prgCmds[], OLECMDTEXT* pCmdText) 1014 STDMETHODIMP CPluginClass::QueryStatus(const GUID* pguidCmdGroup, ULONG cCmds, O LECMD prgCmds[], OLECMDTEXT* pCmdText)
983 { 1015 {
984 if (detachedInitializationFailed) return; 1016 if (detachedInitializationFailed) return S_OK;
985 if (cCmds == 0) return E_INVALIDARG; 1017 try
986 if (prgCmds == 0) return E_POINTER; 1018 {
987 1019 if (cCmds == 0) return E_INVALIDARG;
988 prgCmds[0].cmdf = OLECMDF_ENABLED; 1020 if (prgCmds == 0) return E_POINTER;
989 1021
1022 prgCmds[0].cmdf = OLECMDF_ENABLED;
1023 }
1024 catch (...)
1025 {
1026 DEBUG_GENERAL(L"CPluginClass::QueryStatus - exception");
1027 return E_FAIL;
1028 }
990 return S_OK; 1029 return S_OK;
991 } 1030 }
992 1031
993 HMENU CPluginClass::CreatePluginMenu(const std::wstring& url) 1032 HMENU CPluginClass::CreatePluginMenu(const std::wstring& url)
994 { 1033 {
995 DEBUG_GENERAL("CreatePluginMenu"); 1034 DEBUG_GENERAL("CreatePluginMenu");
996 HINSTANCE hInstance = _AtlBaseModule.GetModuleInstance(); 1035 HINSTANCE hInstance = _AtlBaseModule.GetModuleInstance();
997 1036
998 HMENU hMenu = ::LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU1)); 1037 HMENU hMenu = ::LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU1));
999 1038
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
1129 1168
1130 MENUITEMINFOW miiSep = {}; 1169 MENUITEMINFOW miiSep = {};
1131 miiSep.cbSize = sizeof(miiSep); 1170 miiSep.cbSize = sizeof(miiSep);
1132 miiSep.fMask = MIIM_TYPE | MIIM_FTYPE; 1171 miiSep.fMask = MIIM_TYPE | MIIM_FTYPE;
1133 miiSep.fType = MFT_SEPARATOR; 1172 miiSep.fType = MFT_SEPARATOR;
1134 1173
1135 CPluginClient* client = CPluginClient::GetInstance(); 1174 CPluginClient* client = CPluginClient::GetInstance();
1136 CPluginSettings* settings = CPluginSettings::GetInstance(); 1175 CPluginSettings* settings = CPluginSettings::GetInstance();
1137 { 1176 {
1138 ctext = dictionary->Lookup("menu", "menu-disable-on-site"); 1177 ctext = dictionary->Lookup("menu", "menu-disable-on-site");
1139 // Is domain in white list?
1140 ReplaceString(ctext, L"?1?", client->GetHostFromUrl(url)); 1178 ReplaceString(ctext, L"?1?", client->GetHostFromUrl(url));
1141 if (client->IsWhitelistedUrl(GetTab()->GetDocumentUrl())) 1179 /*
1142 { 1180 * The display state of the "disable on this site" menu item depends upon ta b content
1181 */
1182 if (!GetTab()->IsPossibleToDisableOnSite())
1183 {
1184 // Since we can't disable the present content,
1185 // it makes no sense to offer the user an option to block it.
1186 fmii.fState = MFS_UNCHECKED | MFS_DISABLED;
1187 }
1188 else if (client->IsWhitelistedUrl(GetTab()->GetDocumentUrl()))
1189 {
1190 // Domain is in white list, indicated by a check mark
1143 fmii.fState = MFS_CHECKED | MFS_ENABLED; 1191 fmii.fState = MFS_CHECKED | MFS_ENABLED;
1144 } 1192 }
1145 else 1193 else
1146 { 1194 {
1147 fmii.fState = MFS_UNCHECKED | MFS_ENABLED; 1195 fmii.fState = MFS_UNCHECKED | MFS_ENABLED;
1148 } 1196 }
1149 fmii.fMask = MIIM_STRING | MIIM_STATE; 1197 fmii.fMask = MIIM_STRING | MIIM_STATE;
1150 fmii.dwTypeData = const_cast<LPWSTR>(ctext.c_str()); 1198 fmii.dwTypeData = const_cast<LPWSTR>(ctext.c_str());
1151 fmii.cch = static_cast<UINT>(ctext.size()); 1199 fmii.cch = static_cast<UINT>(ctext.size());
1152 1200
(...skipping 28 matching lines...) Expand all
1181 ctext = dictionary->Lookup("menu", "menu-settings"); 1229 ctext = dictionary->Lookup("menu", "menu-settings");
1182 fmii.fMask = MIIM_STATE | MIIM_STRING; 1230 fmii.fMask = MIIM_STATE | MIIM_STRING;
1183 fmii.fState = MFS_ENABLED; 1231 fmii.fState = MFS_ENABLED;
1184 fmii.dwTypeData = const_cast<LPWSTR>(ctext.c_str()); 1232 fmii.dwTypeData = const_cast<LPWSTR>(ctext.c_str());
1185 fmii.cch = static_cast<UINT>(ctext.size()); 1233 fmii.cch = static_cast<UINT>(ctext.size());
1186 ::SetMenuItemInfoW(hMenu, ID_MENU_SETTINGS, FALSE, &fmii); 1234 ::SetMenuItemInfoW(hMenu, ID_MENU_SETTINGS, FALSE, &fmii);
1187 1235
1188 return true; 1236 return true;
1189 } 1237 }
1190 1238
1191 1239 // Entry point
1192 STDMETHODIMP CPluginClass::Exec(const GUID*, DWORD nCmdID, DWORD, VARIANTARG*, V ARIANTARG*) 1240 STDMETHODIMP CPluginClass::Exec(const GUID*, DWORD nCmdID, DWORD, VARIANTARG*, V ARIANTARG*)
1193 { 1241 {
1194 if (detachedInitializationFailed) return; 1242 if (detachedInitializationFailed) return S_OK;
1195 HWND hBrowserWnd = GetBrowserHWND(); 1243 try
1196 if (!hBrowserWnd) 1244 {
1197 { 1245 HWND hBrowserWnd = GetBrowserHWND();
1198 return E_FAIL; 1246 if (!hBrowserWnd)
1199 } 1247 {
1200 1248 return E_FAIL;
1201 // Create menu 1249 }
1202 HMENU hMenu = CreatePluginMenu(m_tab->GetDocumentUrl()); 1250
1203 if (!hMenu) 1251 // Create menu
1204 { 1252 HMENU hMenu = CreatePluginMenu(m_tab->GetDocumentUrl());
1205 return E_FAIL; 1253 if (!hMenu)
1206 } 1254 {
1207 1255 return E_FAIL;
1208 // Check if button in toolbar was pressed 1256 }
1209 int nIDCommand = -1; 1257
1210 BOOL bRightAlign = FALSE; 1258 // Check if button in toolbar was pressed
1211 1259 int nIDCommand = -1;
1212 POINT pt; 1260 BOOL bRightAlign = FALSE;
1213 GetCursorPos(&pt); 1261
1214 1262 POINT pt;
1215 HWND hWndToolBar = ::WindowFromPoint(pt); 1263 GetCursorPos(&pt);
1216 1264
1217 DWORD nProcessId; 1265 HWND hWndToolBar = ::WindowFromPoint(pt);
1218 ::GetWindowThreadProcessId(hWndToolBar, &nProcessId); 1266
1219 1267 DWORD nProcessId;
1220 if (hWndToolBar && ::GetCurrentProcessId() == nProcessId) 1268 ::GetWindowThreadProcessId(hWndToolBar, &nProcessId);
1221 { 1269
1222 ::ScreenToClient(hWndToolBar, &pt); 1270 if (hWndToolBar && ::GetCurrentProcessId() == nProcessId)
1223 int nButton = (int)::SendMessage(hWndToolBar, TB_HITTEST, 0, (LPARAM)&pt); 1271 {
1224 1272 ::ScreenToClient(hWndToolBar, &pt);
1225 if (nButton > 0) 1273 int nButton = (int)::SendMessage(hWndToolBar, TB_HITTEST, 0, (LPARAM)&pt);
1226 { 1274
1227 TBBUTTON pTBBtn = {}; 1275 if (nButton > 0)
1228 1276 {
1229 if (SendMessage(hWndToolBar, TB_GETBUTTON, nButton, (LPARAM)&pTBBtn)) 1277 TBBUTTON pTBBtn = {};
1230 { 1278
1231 RECT rcButton; 1279 if (SendMessage(hWndToolBar, TB_GETBUTTON, nButton, (LPARAM)&pTBBtn))
1232 nIDCommand = pTBBtn.idCommand; 1280 {
1233 1281 RECT rcButton;
1234 if (SendMessage(hWndToolBar, TB_GETRECT, nIDCommand, (LPARAM)&rcButton)) 1282 nIDCommand = pTBBtn.idCommand;
1235 { 1283
1236 pt.x = rcButton.left; 1284 if (SendMessage(hWndToolBar, TB_GETRECT, nIDCommand, (LPARAM)&rcButton ))
1237 pt.y = rcButton.bottom;
1238 ClientToScreen(hWndToolBar, &pt);
1239
1240 RECT rcWorkArea;
1241 SystemParametersInfo(SPI_GETWORKAREA, 0, (LPVOID)&rcWorkArea, 0);
1242 if (rcWorkArea.right - pt.x < 150)
1243 { 1285 {
1244 bRightAlign = TRUE; 1286 pt.x = rcButton.left;
1245 pt.x = rcButton.right;
1246 pt.y = rcButton.bottom; 1287 pt.y = rcButton.bottom;
1247 ClientToScreen(hWndToolBar, &pt); 1288 ClientToScreen(hWndToolBar, &pt);
1289
1290 RECT rcWorkArea;
1291 SystemParametersInfo(SPI_GETWORKAREA, 0, (LPVOID)&rcWorkArea, 0);
1292 if (rcWorkArea.right - pt.x < 150)
1293 {
1294 bRightAlign = TRUE;
1295 pt.x = rcButton.right;
1296 pt.y = rcButton.bottom;
1297 ClientToScreen(hWndToolBar, &pt);
1298 }
1248 } 1299 }
1249 } 1300 }
1250 } 1301 }
1302 else
1303 {
1304 GetCursorPos(&pt);
1305 }
1306 }
1307
1308 // Display menu
1309 UINT nFlags = 0;
1310 if (bRightAlign)
1311 {
1312 nFlags |= TPM_RIGHTALIGN;
1251 } 1313 }
1252 else 1314 else
1253 { 1315 {
1254 GetCursorPos(&pt); 1316 nFlags |= TPM_LEFTALIGN;
1255 } 1317 }
1256 } 1318
1257 1319 DisplayPluginMenu(hMenu, nIDCommand, pt, nFlags);
1258 // Display menu 1320 }
1259 UINT nFlags = 0; 1321 catch (...)
1260 if (bRightAlign) 1322 {
1261 { 1323 // Suppress exception, log only
1262 nFlags |= TPM_RIGHTALIGN; 1324 DEBUG_GENERAL(L"CPluginClass::Exec - exception");
1263 } 1325 return E_FAIL;
1264 else 1326 }
1265 {
1266 nFlags |= TPM_LEFTALIGN;
1267 }
1268
1269 DisplayPluginMenu(hMenu, nIDCommand, pt, nFlags);
1270 1327
1271 return S_OK; 1328 return S_OK;
1272 } 1329 }
1273 1330
1274 ///////////////////////////////////////////////////////////////////////////// 1331 // Entry point
1275 // Window procedures
1276
1277 LRESULT CALLBACK CPluginClass::NewStatusProc(HWND hWnd, UINT message, WPARAM wPa ram, LPARAM lParam) 1332 LRESULT CALLBACK CPluginClass::NewStatusProc(HWND hWnd, UINT message, WPARAM wPa ram, LPARAM lParam)
1278 { 1333 {
1279 // Find tab 1334 CPluginClass *pClass;
1280 CPluginClass *pClass = FindInstance(hWnd); 1335 try
1281 if (!pClass) 1336 {
1282 { 1337 // Find tab
1283 return DefWindowProc(hWnd, message, wParam, lParam); 1338 pClass = FindInstance(hWnd);
1284 } 1339 if (!pClass)
1285 1340 {
1286 // Process message 1341 /*
1287 switch (message) 1342 * Race condition if reached.
1288 { 1343 * We did not unhook the window procedure for the status bar when the last BHO instance using it terminated.
1289 case SB_SIMPLE: 1344 * The next best thing is to call the system default window function.
1290 { 1345 */
1291 ShowWindow(pClass->m_hPaneWnd, !wParam); 1346 return DefWindowProc(hWnd, message, wParam, lParam);
1347 }
1348
1349 // Process message
1350 switch (message)
1351 {
1352 case SB_SIMPLE:
1353 {
1354 ShowWindow(pClass->m_hPaneWnd, !wParam);
1355 break;
1356 }
1357
1358 case WM_SYSCOLORCHANGE:
1359 {
1360 pClass->UpdateTheme();
1361 break;
1362 }
1363
1364 case SB_SETPARTS:
1365 {
1366 if (!lParam || !wParam || wParam > 30 || !IsWindow(pClass->m_hPaneWnd))
1367 {
1368 return CallWindowProc(pClass->m_pWndProcStatus, hWnd, message, wParam, lParam);
1369 }
1370
1371 WPARAM nParts = wParam;
1372 if (STATUSBAR_PANE_NUMBER >= nParts)
1373 {
1374 return CallWindowProc(pClass->m_pWndProcStatus, hWnd, message, wParam, lParam);
1375 }
1376
1377 HLOCAL hLocal = LocalAlloc(LHND, sizeof(int) * (nParts + 1));
1378 LPINT lpParts = (LPINT)LocalLock(hLocal);
1379 memcpy(lpParts, (void*)lParam, wParam*sizeof(int));
1380
1381 for (unsigned i = 0; i < STATUSBAR_PANE_NUMBER; i++)
1382 {
1383 lpParts[i] -= pClass->m_nPaneWidth;
1384 }
1385 LRESULT hRet = CallWindowProc(pClass->m_pWndProcStatus, hWnd, message, w Param, (LPARAM)lpParts);
1386
1387 AdblockPlus::Rectangle rcPane;
1388 ::SendMessage(hWnd, SB_GETRECT, STATUSBAR_PANE_NUMBER, (LPARAM)&rcPane);
1389
1390 AdblockPlus::Rectangle rcClient;
1391 ::GetClientRect(hWnd, &rcClient);
1392
1393 ::MoveWindow(
1394 pClass->m_hPaneWnd,
1395 lpParts[STATUSBAR_PANE_NUMBER] - pClass->m_nPaneWidth,
1396 0,
1397 pClass->m_nPaneWidth,
1398 rcClient.Height(),
1399 TRUE);
1400
1401 ::LocalFree(hLocal);
1402 return hRet;
1403 }
1404
1405 default:
1292 break; 1406 break;
1293 } 1407 }
1294 1408 }
1295 case WM_SYSCOLORCHANGE: 1409 catch (...)
1296 { 1410 {
1297 pClass->UpdateTheme(); 1411 // Suppress exception. Fall through to default handler.
1298 break; 1412 DEBUG_GENERAL(L"CPluginClass::NewStatusProc - exception");
1299 } 1413 }
1300 1414 return ::CallWindowProc(pClass->m_pWndProcStatus, hWnd, message, wParam, lPara m);
1301 case SB_SETPARTS:
1302 {
1303 if (!lParam || !wParam || wParam > 30 || !IsWindow(pClass->m_hPaneWnd))
1304 {
1305 return CallWindowProc(pClass->m_pWndProcStatus, hWnd, message, wParam, l Param);
1306 }
1307
1308 WPARAM nParts = wParam;
1309 if (STATUSBAR_PANE_NUMBER >= nParts)
1310 {
1311 return CallWindowProc(pClass->m_pWndProcStatus, hWnd, message, wParam, l Param);
1312 }
1313
1314 HLOCAL hLocal = LocalAlloc(LHND, sizeof(int) * (nParts+1));
1315 LPINT lpParts = (LPINT)LocalLock(hLocal);
1316 memcpy(lpParts, (void*)lParam, wParam*sizeof(int));
1317
1318 for (unsigned i = 0; i < STATUSBAR_PANE_NUMBER; i++)
1319 {
1320 lpParts[i] -= pClass->m_nPaneWidth;
1321 }
1322 LRESULT hRet = CallWindowProc(pClass->m_pWndProcStatus, hWnd, message, wPa ram, (LPARAM)lpParts);
1323
1324 AdblockPlus::Rectangle rcPane;
1325 ::SendMessage(hWnd, SB_GETRECT, STATUSBAR_PANE_NUMBER, (LPARAM)&rcPane);
1326
1327 AdblockPlus::Rectangle rcClient;
1328 ::GetClientRect(hWnd, &rcClient);
1329
1330 ::MoveWindow(
1331 pClass->m_hPaneWnd,
1332 lpParts[STATUSBAR_PANE_NUMBER] - pClass->m_nPaneWidth,
1333 0,
1334 pClass->m_nPaneWidth,
1335 rcClient.Height(),
1336 TRUE);
1337
1338 ::LocalFree(hLocal);
1339
1340
1341 return hRet;
1342 }
1343
1344 default:
1345 break;
1346 }
1347
1348 LRESULT result = CallWindowProc(pClass->m_pWndProcStatus, hWnd, message, wPara m, lParam);
1349
1350
1351 return result;
1352
1353 } 1415 }
1354 1416
1355 1417
1356 HICON CPluginClass::GetStatusBarIcon(const std::wstring& url) 1418 HICON CPluginClass::GetStatusBarIcon(const std::wstring& url)
1357 { 1419 {
1358 // use the disable icon as defualt, if the client doesn't exists 1420 // use the disable icon as defualt, if the client doesn't exists
1359 HICON hIcon = GetIcon(ICON_PLUGIN_DEACTIVATED); 1421 HICON hIcon = GetIcon(ICON_PLUGIN_DEACTIVATED);
1360 1422
1361 CPluginTab* tab = GetTab(::GetCurrentThreadId()); 1423 CPluginTab* tab = GetTabForCurrentThread();
1362 if (tab) 1424 if (tab)
1363 { 1425 {
1364 CPluginClient* client = CPluginClient::GetInstance(); 1426 CPluginClient* client = CPluginClient::GetInstance();
1365 if (CPluginSettings::GetInstance()->IsPluginEnabled()) 1427 if (CPluginSettings::GetInstance()->IsPluginEnabled())
1366 { 1428 {
1367 if (client->IsWhitelistedUrl(url)) 1429 if (client->IsWhitelistedUrl(url))
1368 { 1430 {
1369 hIcon = GetIcon(ICON_PLUGIN_DISABLED); 1431 hIcon = GetIcon(ICON_PLUGIN_DISABLED);
1370 } 1432 }
1371 else 1433 else
1372 { 1434 {
1373 CPluginSettings* settings = CPluginSettings::GetInstance(); 1435 CPluginSettings* settings = CPluginSettings::GetInstance();
1374 hIcon = GetIcon(ICON_PLUGIN_ENABLED); 1436 hIcon = GetIcon(ICON_PLUGIN_ENABLED);
1375 } 1437 }
1376 } 1438 }
1377 } 1439 }
1378 return hIcon; 1440 return hIcon;
1379 } 1441 }
1380 1442
1381 1443 // Entry point
1382 LRESULT CALLBACK CPluginClass::PaneWindowProc(HWND hWnd, UINT message, WPARAM wP aram, LPARAM lParam) 1444 LRESULT CALLBACK CPluginClass::PaneWindowProc(HWND hWnd, UINT message, WPARAM wP aram, LPARAM lParam)
1383 { 1445 {
1384 // Find tab 1446 try
1385 CPluginClass *pClass = FindInstance(GetParent(hWnd)); 1447 {
1386 if (!pClass) 1448 // Find tab
1387 { 1449 CPluginClass *pClass = FindInstance(GetParent(hWnd));
1388 return ::DefWindowProc(hWnd, message, wParam, lParam); 1450 if (!pClass)
1389 } 1451 {
1390 1452 return ::DefWindowProc(hWnd, message, wParam, lParam);
1391 // Process message 1453 }
1392 switch (message) 1454
1393 { 1455 // Process message
1394 1456 switch (message)
1395 case WM_SETCURSOR: 1457 {
1396 { 1458 case WM_SETCURSOR:
1397 ::SetCursor(::LoadCursor(NULL, IDC_ARROW)); 1459 {
1398 return TRUE; 1460 ::SetCursor(::LoadCursor(NULL, IDC_ARROW));
1399 } 1461 return TRUE;
1400 case WM_PAINT: 1462 }
1401 { 1463 case WM_PAINT:
1402 PAINTSTRUCT ps; 1464 {
1403 HDC hDC = ::BeginPaint(hWnd, &ps); 1465 PAINTSTRUCT ps;
1404 1466 HDC hDC = ::BeginPaint(hWnd, &ps);
1405 AdblockPlus::Rectangle rcClient; 1467
1406 ::GetClientRect(hWnd, &rcClient); 1468 AdblockPlus::Rectangle rcClient;
1407 1469 ::GetClientRect(hWnd, &rcClient);
1408 int nDrawEdge = 0; 1470
1409 1471 int nDrawEdge = 0;
1410 // Old Windows background drawing 1472
1411 if (pClass->m_hTheme == NULL) 1473 // Old Windows background drawing
1412 { 1474 if (pClass->m_hTheme == NULL)
1413 ::FillRect(hDC, &rcClient, (HBRUSH)(COLOR_BTNFACE + 1)); 1475 {
1414 ::DrawEdge(hDC, &rcClient, BDR_RAISEDINNER, BF_LEFT); 1476 ::FillRect(hDC, &rcClient, (HBRUSH)(COLOR_BTNFACE + 1));
1415 1477 ::DrawEdge(hDC, &rcClient, BDR_RAISEDINNER, BF_LEFT);
1416 nDrawEdge = 3; 1478
1417 rcClient.left += 3; 1479 nDrawEdge = 3;
1418 1480 rcClient.left += 3;
1419 ::DrawEdge(hDC, &rcClient, BDR_SUNKENOUTER, BF_RECT); 1481
1420 } 1482 ::DrawEdge(hDC, &rcClient, BDR_SUNKENOUTER, BF_RECT);
1421 // Themed background drawing 1483 }
1422 else 1484 // Themed background drawing
1423 { 1485 else
1424 // Draw background 1486 {
1425 if (pfnDrawThemeBackground) 1487 // Draw background
1426 { 1488 if (pfnDrawThemeBackground)
1427 AdblockPlus::Rectangle rc = rcClient;
1428 rc.right -= 2;
1429 pfnDrawThemeBackground(pClass->m_hTheme, hDC, 0, 0, &rc, NULL);
1430 }
1431
1432 // Copy separator picture to left side
1433 int nHeight = rcClient.Height();
1434 int nWidth = rcClient.Width() - 2;
1435
1436 for (int i = 0; i < 2; i++)
1437 {
1438 for (int j = 0; j < nHeight; j++)
1439 { 1489 {
1440 COLORREF clr = ::GetPixel(hDC, i + nWidth, j); 1490 AdblockPlus::Rectangle rc = rcClient;
1441 1491 rc.right -= 2;
1442 // Ignore black boxes (if source is obscured by other windows) 1492 pfnDrawThemeBackground(pClass->m_hTheme, hDC, 0, 0, &rc, NULL);
1443 if (clr != -1 && (GetRValue(clr) > 8 || GetGValue(clr) > 8 || GetBVa lue(clr) > 8)) 1493 }
1494
1495 // Copy separator picture to left side
1496 int nHeight = rcClient.Height();
1497 int nWidth = rcClient.Width() - 2;
1498
1499 for (int i = 0; i < 2; i++)
1500 {
1501 for (int j = 0; j < nHeight; j++)
1444 { 1502 {
1445 ::SetPixel(hDC, i, j, clr); 1503 COLORREF clr = ::GetPixel(hDC, i + nWidth, j);
1504
1505 // Ignore black boxes (if source is obscured by other windows)
1506 if (clr != -1 && (GetRValue(clr) > 8 || GetGValue(clr) > 8 || GetB Value(clr) > 8))
1507 {
1508 ::SetPixel(hDC, i, j, clr);
1509 }
1446 } 1510 }
1447 } 1511 }
1448 } 1512 }
1449 } 1513
1450 1514 // Draw icon
1451 // Draw icon 1515 if (CPluginClient::GetInstance())
1452 if (CPluginClient::GetInstance()) 1516 {
1453 { 1517 HICON hIcon = GetStatusBarIcon(pClass->GetTab()->GetDocumentUrl());
1454 HICON hIcon = GetStatusBarIcon(pClass->GetTab()->GetDocumentUrl()); 1518
1455 1519 int offx = nDrawEdge;
1456 int offx = nDrawEdge; 1520 if (hIcon)
1457 if (hIcon) 1521 {
1458 { 1522 //Get the RECT for the leftmost pane (the status text pane)
1459 //Get the RECT for the leftmost pane (the status text pane) 1523 RECT rect;
1524 BOOL rectRes = ::SendMessage(pClass->m_hStatusBarWnd, SB_GETRECT, 0, (LPARAM)&rect);
1525 ::DrawIconEx(hDC, 0, rect.bottom - rect.top - iconHeight, hIcon, ico nWidth, iconHeight, NULL, NULL, DI_NORMAL);
1526 offx += iconWidth;
1527 }
1528 #ifdef _DEBUG
1529 // Display version
1530 HFONT hFont = (HFONT)::SendMessage(pClass->m_hStatusBarWnd, WM_GETFONT , 0, 0);
1531 HGDIOBJ hOldFont = ::SelectObject(hDC, hFont);
1532
1533 AdblockPlus::Rectangle rcText = rcClient;
1534 rcText.left += offx;
1535 ::SetBkMode(hDC, TRANSPARENT);
1536 ::DrawTextW(hDC, IEPLUGIN_VERSION, -1, &rcText, DT_WORD_ELLIPSIS | DT_ LEFT | DT_SINGLELINE | DT_VCENTER);
1537
1538 ::SelectObject(hDC, hOldFont);
1539 #endif // _DEBUG
1540 }
1541
1542 // Done!
1543 EndPaint(hWnd, &ps);
1544
1545 return 0;
1546 }
1547
1548 case WM_LBUTTONUP:
1549 case WM_RBUTTONUP:
1550 {
1551 std::wstring url = pClass->GetBrowserUrl();
1552 if (url != pClass->GetTab()->GetDocumentUrl())
1553 {
1554 pClass->GetTab()->SetDocumentUrl(url);
1555 }
1556
1557 // Create menu
1558 HMENU hMenu = pClass->CreatePluginMenu(url);
1559 if (!hMenu)
1560 {
1561 return 0;
1562 }
1563
1564 // Display menu
1565 POINT pt;
1566 ::GetCursorPos(&pt);
1567
1568 RECT rc;
1569 ::GetWindowRect(hWnd, &rc);
1570
1571 if (rc.left >= 0 && rc.top >= 0)
1572 {
1573 pt.x = rc.left;
1574 pt.y = rc.top;
1575 }
1576
1577 pClass->DisplayPluginMenu(hMenu, -1, pt, TPM_LEFTALIGN | TPM_BOTTOMALIGN );
1578 break;
1579 }
1580 case WM_DESTROY:
1581 break;
1582 case SC_CLOSE:
1583 break;
1584
1585 case WM_UPDATEUISTATE:
1586 {
1587 CPluginTab* tab = GetTabForCurrentThread();
1588 if (tab)
1589 {
1590 tab->OnActivate();
1460 RECT rect; 1591 RECT rect;
1461 BOOL rectRes = ::SendMessage(pClass->m_hStatusBarWnd, SB_GETRECT, 0, ( LPARAM)&rect); 1592 GetWindowRect(pClass->m_hPaneWnd, &rect);
1462 ::DrawIconEx(hDC, 0, rect.bottom - rect.top - iconHeight, hIcon, iconW idth, iconHeight, NULL, NULL, DI_NORMAL); 1593 pClass->notificationMessage.MoveToCenter(rect);
1463 offx += iconWidth; 1594 }
1464 } 1595 if (LOWORD(wParam) == UIS_CLEAR)
1465 #ifdef _DEBUG 1596 {
1466 // Display version 1597 pClass->notificationMessage.Hide();
1467 HFONT hFont = (HFONT)::SendMessage(pClass->m_hStatusBarWnd, WM_GETFONT, 0, 0); 1598 }
1468 HGDIOBJ hOldFont = ::SelectObject(hDC,hFont); 1599 break;
1469 1600 }
1470 AdblockPlus::Rectangle rcText = rcClient; 1601 case WM_WINDOWPOSCHANGING:
1471 rcText.left += offx; 1602 {
1472 ::SetBkMode(hDC, TRANSPARENT);
1473 ::DrawTextW(hDC, IEPLUGIN_VERSION, -1, &rcText, DT_WORD_ELLIPSIS|DT_LEFT |DT_SINGLELINE|DT_VCENTER);
1474
1475 ::SelectObject(hDC, hOldFont);
1476 #endif // _DEBUG
1477 }
1478
1479 // Done!
1480 EndPaint(hWnd, &ps);
1481
1482 return 0;
1483 }
1484
1485 case WM_LBUTTONUP:
1486 case WM_RBUTTONUP:
1487 {
1488 std::wstring url = pClass->GetBrowserUrl();
1489 if (url != pClass->GetTab()->GetDocumentUrl())
1490 {
1491 pClass->GetTab()->SetDocumentUrl(url);
1492 }
1493
1494 // Create menu
1495 HMENU hMenu = pClass->CreatePluginMenu(url);
1496 if (!hMenu)
1497 {
1498 return 0;
1499 }
1500
1501 // Display menu
1502 POINT pt;
1503 ::GetCursorPos(&pt);
1504
1505 RECT rc;
1506 ::GetWindowRect(hWnd, &rc);
1507
1508 if (rc.left >= 0 && rc.top >= 0)
1509 {
1510 pt.x = rc.left;
1511 pt.y = rc.top;
1512 }
1513
1514 pClass->DisplayPluginMenu(hMenu, -1, pt, TPM_LEFTALIGN|TPM_BOTTOMALIGN);
1515 }
1516 break;
1517 case WM_DESTROY:
1518 break;
1519 case SC_CLOSE:
1520 break;
1521
1522 case WM_UPDATEUISTATE:
1523 {
1524 CPluginTab* tab = GetTab(::GetCurrentThreadId());
1525 if (tab)
1526 {
1527 tab->OnActivate();
1528 RECT rect; 1603 RECT rect;
1529 GetWindowRect(pClass->m_hPaneWnd, &rect); 1604 GetWindowRect(pClass->m_hPaneWnd, &rect);
1530 pClass->notificationMessage.Move(rect.left + (rect.right - rect.left) / 2, rect.top + (rect.bottom - rect.top) / 2); 1605 if (pClass->notificationMessage.IsVisible())
1531 } 1606 {
1532 if (LOWORD(wParam) == UIS_CLEAR) 1607 pClass->notificationMessage.MoveToCenter(rect);
1533 { 1608 }
1534 pClass->notificationMessage.Hide(); 1609 break;
1535 } 1610 }
1536 } 1611 case WM_WINDOWPOSCHANGED:
1537 break; 1612 {
1538 case WM_WINDOWPOSCHANGING: 1613 WINDOWPOS* wndPos = reinterpret_cast<WINDOWPOS*>(lParam);
1539 { 1614 if (wndPos->flags & SWP_HIDEWINDOW)
1540 RECT rect; 1615 {
1541 GetWindowRect(pClass->m_hPaneWnd, &rect); 1616 pClass->notificationMessage.Hide();
1542 if (pClass->notificationMessage.IsVisible()) 1617 }
1543 { 1618 break;
1544 pClass->notificationMessage.Move(rect.left + (rect.right - rect.left) / 2, rect.top + (rect.bottom - rect.top) / 2); 1619 }
1545 } 1620 case WM_ALREADY_UP_TO_DATE:
1546 } 1621 {
1547 break; 1622 Dictionary* dictionary = Dictionary::GetInstance();
1548 case WM_WINDOWPOSCHANGED: 1623 std::wstring upToDateText = dictionary->Lookup("updater", "update-alread y-up-to-date-text");
1549 { 1624 std::wstring upToDateTitle = dictionary->Lookup("updater", "update-alrea dy-up-to-date-title");
1550 WINDOWPOS* wndPos = reinterpret_cast<WINDOWPOS*>(lParam); 1625 pClass->notificationMessage.SetTextAndIcon(upToDateText, upToDateTitle, TTI_INFO);
1551 if (wndPos->flags & SWP_HIDEWINDOW) 1626 break;
1552 { 1627 }
1553 pClass->notificationMessage.Hide(); 1628 case WM_UPDATE_CHECK_ERROR:
1554 } 1629 {
1555 } 1630 Dictionary* dictionary = Dictionary::GetInstance();
1556 break; 1631 std::wstring errorText = dictionary->Lookup("updater", "update-error-tex t");
1557 case WM_ALREADY_UP_TO_DATE: 1632 std::wstring errorTitle = dictionary->Lookup("updater", "update-error-ti tle");
1558 { 1633 pClass->notificationMessage.SetTextAndIcon(errorText, errorTitle, TTI_ER ROR);
1559 Dictionary* dictionary = Dictionary::GetInstance(); 1634 break;
1560 std::wstring upToDateText = dictionary->Lookup("updater", "update-already- up-to-date-text"); 1635 }
1561 std::wstring upToDateTitle = dictionary->Lookup("updater", "update-already -up-to-date-title"); 1636 case WM_DOWNLOADING_UPDATE:
1562 pClass->notificationMessage.SetTextAndIcon(upToDateText, upToDateTitle, TT I_INFO); 1637 {
1563 } 1638 Dictionary* dictionary = Dictionary::GetInstance();
1564 break; 1639 std::wstring downloadingText = dictionary->Lookup("updater", "downloadin g-update-text");
1565 case WM_UPDATE_CHECK_ERROR: 1640 std::wstring downloadingTitle = dictionary->Lookup("updater", "downloadi ng-update-title");
1566 { 1641 pClass->notificationMessage.SetTextAndIcon(downloadingText, downloadingT itle, TTI_INFO);
1567 Dictionary* dictionary = Dictionary::GetInstance(); 1642 break;
1568 std::wstring errorText = dictionary->Lookup("updater", "update-error-text" ); 1643 }
1569 std::wstring errorTitle = dictionary->Lookup("updater", "update-error-titl e"); 1644 }
1570 pClass->notificationMessage.SetTextAndIcon(errorText, errorText, TTI_ERROR ); 1645 }
1571 } 1646 catch (...)
1572 break; 1647 {
1573 case WM_DOWNLOADING_UPDATE: 1648 // Suppress exception. Fall through to default handler.
1574 { 1649 DEBUG_GENERAL(L"CPluginClass::PaneWindowProc - exception");
1575 Dictionary* dictionary = Dictionary::GetInstance(); 1650 }
1576 std::wstring downloadingText = dictionary->Lookup("updater", "downloading- update-text"); 1651 return ::DefWindowProc(hWnd, message, wParam, lParam);
1577 std::wstring downloadingTitle = dictionary->Lookup("updater", "downloading -update-title");
1578 pClass->notificationMessage.SetTextAndIcon(downloadingText, downloadingTit le, TTI_INFO);
1579 }
1580 break;
1581 }
1582
1583 return DefWindowProc(hWnd, message, wParam, lParam);
1584 } 1652 }
1585 1653
1586 1654
1587 void CPluginClass::UpdateStatusBar() 1655 void CPluginClass::UpdateStatusBar()
1588 { 1656 {
1589 DEBUG_GENERAL("*** Updating statusbar") 1657 DEBUG_GENERAL("*** Updating statusbar")
1590 if (m_hPaneWnd == NULL) 1658 if (m_hPaneWnd == NULL)
1591 { 1659 {
1592 CreateStatusBarPane(); 1660 CreateStatusBarPane();
1593 } 1661 }
(...skipping 25 matching lines...) Expand all
1619 s_criticalSectionLocal.Unlock(); 1687 s_criticalSectionLocal.Unlock();
1620 1688
1621 return icon; 1689 return icon;
1622 } 1690 }
1623 1691
1624 ATOM CPluginClass::GetAtomPaneClass() 1692 ATOM CPluginClass::GetAtomPaneClass()
1625 { 1693 {
1626 return s_atomPaneClass; 1694 return s_atomPaneClass;
1627 } 1695 }
1628 1696
LEFTRIGHT

Powered by Google App Engine
This is Rietveld