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

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

Issue 29333107: Issue #1652, #3456 - Replace 's_asyncWebBrowser2' with thread-safe facilities
Left Patch Set: Created Dec. 29, 2015, 5:54 p.m.
Right Patch Set: rebase only Created July 27, 2016, 10:26 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') | test/plugin/InstancesTest.cpp » ('j') | 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 *
(...skipping 10 matching lines...) Expand all
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 "Instances.h" 32 #include "Instances.h"
33 #include "../shared/Version.h" 33 #include "../shared/Version.h"
34 #include "Instances.h"
34 #include <thread> 35 #include <thread>
35 #include <array> 36 #include <array>
36 37
37 #ifdef DEBUG_HIDE_EL 38 #ifdef DEBUG_HIDE_EL
38 DWORD profileTime = 0; 39 DWORD profileTime = 0;
39 #endif 40 #endif
40 41
41 extern CComModule _Module; 42 extern CComModule _Module;
42 43
43 typedef HANDLE (WINAPI *OPENTHEMEDATA)(HWND, LPCWSTR); 44 typedef HANDLE (WINAPI *OPENTHEMEDATA)(HWND, LPCWSTR);
44 typedef HRESULT (WINAPI *DRAWTHEMEBACKGROUND)(HANDLE, HDC, INT, INT, LPRECT, LPR ECT); 45 typedef HRESULT (WINAPI *DRAWTHEMEBACKGROUND)(HANDLE, HDC, INT, INT, LPRECT, LPR ECT);
45 typedef HRESULT (WINAPI *CLOSETHEMEDATA)(HANDLE); 46 typedef HRESULT (WINAPI *CLOSETHEMEDATA)(HANDLE);
46 47
47 HICON CPluginClass::s_hIcons[ICON_MAX] = { NULL, NULL, NULL }; 48 HICON CPluginClass::s_hIcons[ICON_MAX] = { NULL, NULL, NULL };
48 DWORD CPluginClass::s_hIconTypes[ICON_MAX] = { IDI_ICON_DISABLED, IDI_ICON_ENABL ED, IDI_ICON_DEACTIVATED }; 49 DWORD CPluginClass::s_hIconTypes[ICON_MAX] = { IDI_ICON_DISABLED, IDI_ICON_ENABL ED, IDI_ICON_DEACTIVATED };
49 uint32_t iconHeight = 32; 50 uint32_t iconHeight = 32;
50 uint32_t iconWidth = 32; 51 uint32_t iconWidth = 32;
51 52
52 CPluginMimeFilterClient* CPluginClass::s_mimeFilter = NULL; 53 CPluginMimeFilterClient* CPluginClass::s_mimeFilter = NULL;
53 54
54 CLOSETHEMEDATA pfnClose = NULL; 55 CLOSETHEMEDATA pfnClose = NULL;
55 DRAWTHEMEBACKGROUND pfnDrawThemeBackground = NULL; 56 DRAWTHEMEBACKGROUND pfnDrawThemeBackground = NULL;
56 OPENTHEMEDATA pfnOpenThemeData = NULL; 57 OPENTHEMEDATA pfnOpenThemeData = NULL;
57 58
58 ATOM CPluginClass::s_atomPaneClass = NULL; 59 ATOM CPluginClass::s_atomPaneClass = NULL;
59 HINSTANCE CPluginClass::s_hUxtheme = NULL; 60 HINSTANCE CPluginClass::s_hUxtheme = NULL;
60 SyncSet<CPluginClass*, nullptr> instanceSet; 61 SyncSet<CPluginClass*, nullptr> instanceSet;
61 std::map<DWORD, CPluginClass*> CPluginClass::s_threadInstances;
62 62
63 CComAutoCriticalSection CPluginClass::s_criticalSectionLocal; 63 CComAutoCriticalSection CPluginClass::s_criticalSectionLocal;
64 CComAutoCriticalSection CPluginClass::s_criticalSectionWindow; 64 CComAutoCriticalSection CPluginClass::s_criticalSectionWindow;
65
66 namespace
67 {
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::RemoveIfPresent(::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;
97 }
65 98
66 /* 99 /*
67 * Without namespace declaration, the identifier "Rectangle" is ambiguous 100 * Without namespace declaration, the identifier "Rectangle" is ambiguous
68 * See http://msdn.microsoft.com/en-us/library/windows/desktop/dd162898(v=vs.85) .aspx 101 * See http://msdn.microsoft.com/en-us/library/windows/desktop/dd162898(v=vs.85) .aspx
69 */ 102 */
70 namespace AdblockPlus 103 namespace AdblockPlus
71 { 104 {
72 /** 105 /**
73 * Replacement for ATL type CRect. 106 * Replacement for ATL type CRect.
74 */ 107 */
75 class Rectangle 108 class Rectangle
76 : public RECT 109 : public RECT
77 { 110 {
78 public: 111 public:
79 int Height() const 112 unsigned long Height() const
80 { 113 {
81 return bottom - top; 114 if (bottom < top)
82 } 115 {
83 116 throw std::runtime_error("invariant violation: rectangle bottom < top");
84 int Width() const 117 }
85 { 118 return static_cast<unsigned long>(bottom - top);
86 return right - left; 119 }
120
121 unsigned long Width() const
122 {
123 if (right < left)
124 {
125 throw std::runtime_error("invariant violation: rectangle right < left");
126 }
127 return static_cast<unsigned long>(right - left);
87 } 128 }
88 }; 129 };
89 } 130 }
90 131
91 /** 132 /**
92 * Wrapper class for a browser site object that ensures proper site life cycle. 133 * Wrapper class for a browser site object that ensures proper site life cycle.
93 * 134 *
94 * The browser is guaranteed to be valid for the lifetime of the object. 135 * The browser is guaranteed to be valid for the lifetime of the object.
95 * What that means is that SetSite(0) on the containing BHO instance will not re turn before this object is destroyed. 136 * What that means is that SetSite(0) on the containing BHO instance will not re turn before this object is destroyed.
96 * This property avoids a race condition where one thread is using a browser sit e for services while IE is simultaneously shutting it down. 137 * This property avoids a race condition where one thread is using a browser sit e for services while IE is simultaneously shutting it down.
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
148 }); 189 });
149 if (!instance) 190 if (!instance)
150 { 191 {
151 browser = nullptr; 192 browser = nullptr;
152 } 193 }
153 else 194 else
154 { 195 {
155 browser = instance->m_webBrowser2; 196 browser = instance->m_webBrowser2;
156 if (!browser) 197 if (!browser)
157 { 198 {
158 throw std::logic_error("Instance without site found in set of instances with site"); 199 throw std::logic_error("invariant violation: BHO instance without site f ound in a set of instances each of which must have a current site");
sergei 2016/01/04 15:34:31 "... where site is a browser (IWebBrowser2) and in
Eric 2016/01/04 17:49:20 When I encounter such messages in a log, I immedia
159 } 200 }
160 } 201 }
161 }; 202 };
162 203
163 /** 204 /**
164 * Destructor releases any lock held and allows SetSite() to complete. 205 * Destructor releases any lock held and allows SetSite() to complete.
165 */ 206 */
166 ~AnyCurrentSiteBrowser() {}; // = default 207 ~AnyCurrentSiteBrowser() {}; // = default
167 208
168 IWebBrowser2* operator->() const 209 IWebBrowser2* operator->() const
169 { 210 {
170 return browser; 211 return browser;
171 } 212 }
172 213
173 operator IWebBrowser2*() const 214 operator IWebBrowser2*() const
174 { 215 {
175 return browser; 216 return browser;
176 } 217 }
177 218
178 operator bool() const 219 operator bool() const
179 { 220 {
180 return browser != nullptr; 221 return browser != nullptr;
181 } 222 }
182 }; 223 };
183 224
184 CPluginClass::CPluginClass() 225 CPluginClass::CPluginClass()
185 : m_webBrowser2(nullptr) 226 : m_webBrowser2(nullptr)
186 { 227 {
228 DEBUG_GENERAL([this]() -> std::wstring
229 {
230 std::wstring s = L"CPluginClass::<constructor>, this = ";
231 s += ToHexLiteral(this);
232 return s;
233 }());
234
187 //Use this line to debug memory leaks 235 //Use this line to debug memory leaks
188 // _CrtDumpMemoryLeaks(); 236 // _CrtDumpMemoryLeaks();
189 237
190 m_isAdvised = false; 238 m_isAdvised = false;
191 m_hTabWnd = NULL; 239 m_hTabWnd = NULL;
192 m_hStatusBarWnd = NULL; 240 m_hStatusBarWnd = NULL;
193 m_hPaneWnd = NULL; 241 m_hPaneWnd = NULL;
194 m_nPaneWidth = 0; 242 m_nPaneWidth = 0;
195 m_pWndProcStatus = NULL; 243 m_pWndProcStatus = NULL;
196 m_hTheme = NULL; 244 m_hTheme = NULL;
197 m_isInitializedOk = false; 245 m_isInitializedOk = false;
198 246 m_tab = new CPluginTab();
199
200 m_tab = new CPluginTab(this);
201
202 Dictionary::Create(GetBrowserLanguage()); 247 Dictionary::Create(GetBrowserLanguage());
203 } 248 }
204 249
205 CPluginClass::~CPluginClass() 250 CPluginClass::~CPluginClass()
206 { 251 {
252 DEBUG_GENERAL([this]() -> std::wstring
253 {
254 std::wstring s = L"CPluginClass::<destructor>, this = ";
255 s += ToHexLiteral(this);
256 return s;
257 }());
258
207 delete m_tab; 259 delete m_tab;
208 } 260 }
209 261
210 HWND CPluginClass::GetBrowserHWND() const 262 HWND CPluginClass::GetBrowserHWND() const
211 { 263 {
212 if (!m_webBrowser2) 264 if (!m_webBrowser2)
213 { 265 {
214 DEBUG_ERROR_LOG(0, 0, 0, "CPluginClass::GetBrowserHWND - Reached with m_webB rowser2 == nullptr"); 266 DEBUG_ERROR_LOG(0, 0, 0, "CPluginClass::GetBrowserHWND - Reached with m_webB rowser2 == nullptr");
215 return nullptr; 267 return nullptr;
216 } 268 }
(...skipping 11 matching lines...) Expand all
228 { 280 {
229 return m_webBrowser2.IsEqualObject(otherBrowser); 281 return m_webBrowser2.IsEqualObject(otherBrowser);
230 } 282 }
231 283
232 std::wstring CPluginClass::GetBrowserUrl() const 284 std::wstring CPluginClass::GetBrowserUrl() const
233 { 285 {
234 std::wstring url; 286 std::wstring url;
235 if (m_webBrowser2) 287 if (m_webBrowser2)
236 { 288 {
237 CComBSTR bstrURL; 289 CComBSTR bstrURL;
238 if (SUCCEEDED(m_webBrowser2->get_LocationURL(&bstrURL)) && bstrURL) 290 if (SUCCEEDED(m_webBrowser2->get_LocationURL(&bstrURL)))
239 { 291 {
240 url = std::wstring(bstrURL, SysStringLen(bstrURL)); 292 url = ToWstring(bstrURL);
241 } 293 }
242 } 294 }
243 else 295 else
244 { 296 {
245 DEBUG_ERROR_LOG(0, 0, 0, "CPluginClass::GetBrowserUrl - Reached with m_webBr owser2 == nullptr"); 297 DEBUG_GENERAL(L"CPluginClass::GetBrowserUrl - Reached with m_webBrowser2 == nullptr (probable invariant violation)");
298 }
299 if (url.empty())
300 {
246 url = m_tab->GetDocumentUrl(); 301 url = m_tab->GetDocumentUrl();
247 } 302 }
248 return url; 303 return url;
249 } 304 }
250 305
251 DWORD WINAPI CPluginClass::StartInitObject(LPVOID thisPtr) 306 DWORD WINAPI CPluginClass::StartInitObject(LPVOID thisPtr)
252 { 307 {
253 if (thisPtr == NULL) 308 if (thisPtr == NULL)
254 return 0; 309 return 0;
255 if (!((CPluginClass*)thisPtr)->InitObject()) 310 if (!((CPluginClass*)thisPtr)->InitObject())
(...skipping 15 matching lines...) Expand all
271 * but it is not a proper substitute for one. 326 * but it is not a proper substitute for one.
272 */ 327 */
273 STDMETHODIMP CPluginClass::SetSite(IUnknown* unknownSite) 328 STDMETHODIMP CPluginClass::SetSite(IUnknown* unknownSite)
274 { 329 {
275 try 330 try
276 { 331 {
277 std::lock_guard<std::mutex> lock(siteGuard); 332 std::lock_guard<std::mutex> lock(siteGuard);
278 333
279 if (unknownSite) 334 if (unknownSite)
280 { 335 {
281 336 DEBUG_GENERAL(L"========================================================== ======================\nNEW TAB UI\n============================================ ====================================");
282 DEBUG_GENERAL(L"========================================================== ======================\nNEW TAB UI\n============================================ ====================================")
283 337
284 HRESULT hr = ::CoInitialize(NULL); 338 HRESULT hr = ::CoInitialize(NULL);
285 if (FAILED(hr)) 339 if (FAILED(hr))
286 { 340 {
287 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_COINIT, "Class::SetSite - CoInitialize"); 341 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_COINIT, "Class::SetSite - CoInitialize");
288 } 342 }
289 343
290 /* 344 /*
291 * We were instantiated as a BHO, so our site is always of type IWebBrowse r2. 345 * We were instantiated as a BHO, so our site is always of type IWebBrowse r2.
292 */ 346 */
293 m_webBrowser2 = ATL::CComQIPtr<IWebBrowser2>(unknownSite); 347 m_webBrowser2 = ATL::CComQIPtr<IWebBrowser2>(unknownSite);
294 if (!m_webBrowser2) 348 if (!m_webBrowser2)
295 { 349 {
296 throw std::logic_error("CPluginClass::SetSite - Unable to convert site p ointer to IWebBrowser2*"); 350 throw std::logic_error("CPluginClass::SetSite - Unable to convert site p ointer to IWebBrowser2*");
297 } 351 }
352 DEBUG_GENERAL([this]() -> std::wstring
353 {
354 std::wstringstream ss;
355 ss << L"CPluginClass::SetSite, this = " << ToHexLiteral(this);
356 ss << L", browser = " << ToHexLiteral(m_webBrowser2);
357 return ss.str();
358 }());
359
360 /*
361 * Add ourselves to the thread map.
362 */
363 if (!threadMap.AddIfAbsent(this))
364 {
365 throw std::logic_error("CPluginClass::SetSite - May not overwrite existi ng entry in thread map");
366 }
298 if (!instanceSet.InsertIfAbsent(this)) 367 if (!instanceSet.InsertIfAbsent(this))
sergei 2016/01/04 15:34:31 I would like to have `assert`s in addition to thro
Eric 2016/01/04 17:49:20 'assert' is a C mechanism, and it's only active du
sergei 2016/01/29 15:28:56 `assert` is also C++ mechanism. Yes, it's active o
Eric 2016/01/29 16:16:12 You're advocating code bloat for zero-to-minimal b
299 { 368 {
300 throw std::logic_error("CPluginClass::SetSite - May not overwrite existi ng entry in instance set"); 369 throw std::logic_error("CPluginClass::SetSite - May not overwrite existi ng entry in instance set");
301 } 370 }
371
302 372
303 //register the mimefilter 373 //register the mimefilter
304 //and only mimefilter 374 //and only mimefilter
305 //on some few computers the mimefilter does not get properly registered wh en it is done on another thread 375 //on some few computers the mimefilter does not get properly registered wh en it is done on another thread
306 s_criticalSectionLocal.Lock(); 376 s_criticalSectionLocal.Lock();
307 { 377 {
308 s_mimeFilter = CPluginClientFactory::GetMimeFilterClientInstance(); 378 s_mimeFilter = CPluginClientFactory::GetMimeFilterClientInstance();
309 } 379 }
310 s_criticalSectionLocal.Unlock(); 380 s_criticalSectionLocal.Unlock();
311 381
312 try 382 try
313 { 383 {
314 DEBUG_GENERAL("Loaded as BHO");
315 HRESULT hr = DispEventAdvise(m_webBrowser2); 384 HRESULT hr = DispEventAdvise(m_webBrowser2);
316 if (SUCCEEDED(hr)) 385 if (SUCCEEDED(hr))
317 { 386 {
318 m_isAdvised = true; 387 m_isAdvised = true;
319 try 388 try
320 { 389 {
321 std::thread startInitObjectThread(StartInitObject, this); 390 std::thread startInitObjectThread(StartInitObject, this);
322 startInitObjectThread.detach(); // TODO: but actually we should wait for the thread in the dtr. 391 startInitObjectThread.detach(); // TODO: but actually we should wait for the thread in the dtr.
323 } 392 }
324 catch (const std::system_error& ex) 393 catch (const std::system_error& ex)
325 { 394 {
326 DEBUG_SYSTEM_EXCEPTION(ex, PLUGIN_ERROR_THREAD, PLUGIN_ERROR_MAIN_TH READ_CREATE_PROCESS, 395 DEBUG_SYSTEM_EXCEPTION(ex, PLUGIN_ERROR_THREAD, PLUGIN_ERROR_MAIN_TH READ_CREATE_PROCESS,
327 "Class::Thread - Failed to create StartInitObject thread"); 396 "Class::Thread - Failed to create StartInitObject thread");
328 } 397 }
329 } 398 }
330 else 399 else
331 { 400 {
332 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_ADVIC E, "Class::SetSite - Advise"); 401 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_ADVIC E, "Class::SetSite - Advise");
333 } 402 }
334 } 403 }
335 catch (const std::runtime_error& ex) 404 catch (const std::runtime_error& ex)
336 { 405 {
337 DEBUG_EXCEPTION(ex); 406 DEBUG_EXCEPTION(ex);
338 Unadvise(); 407 Unadvise();
339 } 408 }
340 } 409 }
341 else 410 else
342 { 411 {
412 DEBUG_GENERAL([this]() -> std::wstring
413 {
414 std::wstringstream ss;
415 ss << L"CPluginClass::SetSite, this = " << ToHexLiteral(this);
416 ss << L", browser = nullptr";
417 return ss.str();
418 }());
419
343 Unadvise(); 420 Unadvise();
344 421
345 // Destroy window 422 // Destroy window
346 if (m_pWndProcStatus) 423 if (m_pWndProcStatus)
347 { 424 {
348 ::SetWindowLongPtr(m_hStatusBarWnd, GWLP_WNDPROC, (LPARAM)(WNDPROC)m_pWn dProcStatus); 425 ::SetWindowLongPtr(m_hStatusBarWnd, GWLP_WNDPROC, (LPARAM)(WNDPROC)m_pWn dProcStatus);
349 426
350 m_pWndProcStatus = NULL; 427 m_pWndProcStatus = NULL;
351 } 428 }
352 429
353 if (m_hPaneWnd) 430 if (m_hPaneWnd)
354 { 431 {
355 DestroyWindow(m_hPaneWnd); 432 DestroyWindow(m_hPaneWnd);
356 m_hPaneWnd = NULL; 433 m_hPaneWnd = NULL;
357 } 434 }
358 435
359 m_hTabWnd = NULL; 436 m_hTabWnd = NULL;
360 m_hStatusBarWnd = NULL; 437 m_hStatusBarWnd = NULL;
361 438
362 // Remove instance from the list, shutdown threads 439 // Remove instance from the list, shutdown threads
363 HANDLE hMainThread = NULL; 440 HANDLE hMainThread = NULL;
364 HANDLE hTabThread = NULL; 441 HANDLE hTabThread = NULL;
365 442
366 if (!instanceSet.EraseWithCheck(this)) 443 if (!instanceSet.EraseWithCheck(this))
367 { 444 {
368 throw std::logic_error("CPluginClass::SetSite - Missing entry in instanc e set"); 445 throw std::logic_error("CPluginClass::SetSite - Missing entry in instanc e set");
446 }
447 if (!threadMap.RemoveAndCheck())
448 {
449 throw std::logic_error("CPluginClass::SetSite - Missing entry in thread map");
369 } 450 }
370 s_criticalSectionLocal.Lock(); 451 s_criticalSectionLocal.Lock();
371 { 452 {
372 if (instanceSet.Empty()) 453 if (instanceSet.Empty())
373 { 454 {
374 // TODO: Explicitly releasing a resource when a container becomes empt y looks like a job better suited for shared_ptr 455 // TODO: Explicitly releasing a resource when a container becomes empt y looks like a job better suited for shared_ptr
375 CPluginClientFactory::ReleaseMimeFilterClientInstance(); 456 CPluginClientFactory::ReleaseMimeFilterClientInstance();
376 } 457 }
377 } 458 }
378 s_criticalSectionLocal.Unlock(); 459 s_criticalSectionLocal.Unlock();
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
531 { 612 {
532 ATL::CComQIPtr<IWebBrowser2> webBrowser = frameBrowserDisp; 613 ATL::CComQIPtr<IWebBrowser2> webBrowser = frameBrowserDisp;
533 if (!webBrowser) 614 if (!webBrowser)
534 { 615 {
535 return; 616 return;
536 } 617 }
537 if (!urlVariant || urlVariant->vt != VT_BSTR) 618 if (!urlVariant || urlVariant->vt != VT_BSTR)
538 { 619 {
539 return; 620 return;
540 } 621 }
541 std::wstring url(urlVariant->bstrVal, SysStringLen(urlVariant->bstrVal)); 622 std::wstring url = ToWstring(urlVariant->bstrVal);
542 623
543 // If webbrowser2 is equal to top level browser (as set in SetSite), we are 624 // If webbrowser2 is equal to top level browser (as set in SetSite), we are
544 // navigating new page 625 // navigating new page
545 CPluginClient* client = CPluginClient::GetInstance(); 626 CPluginClient* client = CPluginClient::GetInstance();
546 if (url.find(L"javascript") == 0) 627 if (url.find(L"javascript") == 0)
547 { 628 {
548 } 629 }
549 else if (IsRootBrowser(webBrowser)) 630 else if (IsRootBrowser(webBrowser))
550 { 631 {
551 m_tab->OnNavigate(url); 632 m_tab->OnNavigate(url);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
610 // Entry point 691 // Entry point
611 void STDMETHODCALLTYPE CPluginClass::OnWindowStateChanged(unsigned long flags, u nsigned long validFlagsMask) 692 void STDMETHODCALLTYPE CPluginClass::OnWindowStateChanged(unsigned long flags, u nsigned long validFlagsMask)
612 { 693 {
613 try 694 try
614 { 695 {
615 DEBUG_GENERAL(L"WindowStateChanged (check tab changed)"); 696 DEBUG_GENERAL(L"WindowStateChanged (check tab changed)");
616 bool newtabshown = validFlagsMask == (OLECMDIDF_WINDOWSTATE_USERVISIBLE | OL ECMDIDF_WINDOWSTATE_ENABLED) 697 bool newtabshown = validFlagsMask == (OLECMDIDF_WINDOWSTATE_USERVISIBLE | OL ECMDIDF_WINDOWSTATE_ENABLED)
617 && flags == (OLECMDIDF_WINDOWSTATE_USERVISIBLE | OLECMDIDF_WINDOWSTATE_ENA BLED); 698 && flags == (OLECMDIDF_WINDOWSTATE_USERVISIBLE | OLECMDIDF_WINDOWSTATE_ENA BLED);
618 if (newtabshown) 699 if (newtabshown)
619 { 700 {
620 std::map<DWORD,CPluginClass*>::const_iterator it = s_threadInstances.find( GetCurrentThreadId()); 701 if (!m_isInitializedOk)
621 if (it == s_threadInstances.end()) 702 {
622 { 703 m_isInitializedOk = true;
623 s_threadInstances[::GetCurrentThreadId()] = this; 704 InitObject();
624 if (!m_isInitializedOk) 705 UpdateStatusBar();
625 {
626 m_isInitializedOk = true;
627 InitObject();
628 UpdateStatusBar();
629 }
630 } 706 }
631 } 707 }
632 notificationMessage.Hide(); 708 notificationMessage.Hide();
633 DEBUG_GENERAL(L"WindowStateChanged (check tab changed) end"); 709 DEBUG_GENERAL(L"WindowStateChanged (check tab changed) end");
634 } 710 }
635 catch (...) 711 catch (...)
636 { 712 {
637 } 713 }
638 } 714 }
639 715
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after
1016 { 1092 {
1017 return p->m_hStatusBarWnd == hStatusBarWnd; 1093 return p->m_hStatusBarWnd == hStatusBarWnd;
1018 }); 1094 });
1019 } 1095 }
1020 1096
1021 CPluginTab* CPluginClass::GetTab() 1097 CPluginTab* CPluginClass::GetTab()
1022 { 1098 {
1023 return m_tab; 1099 return m_tab;
1024 } 1100 }
1025 1101
1026 CPluginTab* CPluginClass::GetTab(DWORD dwThreadId) 1102 CPluginTab* CPluginClass::GetTabForCurrentThread()
1027 { 1103 {
1028 CPluginTab* tab = NULL; 1104 auto p = threadMap.Locate();
1029 1105 return p ? p->m_tab : nullptr;
1030 s_criticalSectionLocal.Lock(); 1106 }
1031 { 1107
1032 std::map<DWORD,CPluginClass*>::const_iterator it = s_threadInstances.find(dw ThreadId); 1108 // Entry point
1033 if (it != s_threadInstances.end())
1034 {
1035 tab = it->second->m_tab;
1036 }
1037 }
1038 s_criticalSectionLocal.Unlock();
1039
1040 return tab;
1041 }
1042
1043
1044 STDMETHODIMP CPluginClass::QueryStatus(const GUID* pguidCmdGroup, ULONG cCmds, O LECMD prgCmds[], OLECMDTEXT* pCmdText) 1109 STDMETHODIMP CPluginClass::QueryStatus(const GUID* pguidCmdGroup, ULONG cCmds, O LECMD prgCmds[], OLECMDTEXT* pCmdText)
1045 { 1110 {
1046 if (cCmds == 0) return E_INVALIDARG; 1111 try
1047 if (prgCmds == 0) return E_POINTER; 1112 {
1048 1113 if (cCmds == 0) return E_INVALIDARG;
1049 prgCmds[0].cmdf = OLECMDF_ENABLED; 1114 if (prgCmds == 0) return E_POINTER;
1050 1115
1116 prgCmds[0].cmdf = OLECMDF_ENABLED;
1117 }
1118 catch (...)
1119 {
1120 DEBUG_GENERAL(L"CPluginClass::QueryStatus - exception");
1121 return E_FAIL;
1122 }
1051 return S_OK; 1123 return S_OK;
1052 } 1124 }
1053 1125
1054 HMENU CPluginClass::CreatePluginMenu(const std::wstring& url) 1126 HMENU CPluginClass::CreatePluginMenu(const std::wstring& url)
1055 { 1127 {
1056 DEBUG_GENERAL("CreatePluginMenu"); 1128 DEBUG_GENERAL("CreatePluginMenu");
1057 HINSTANCE hInstance = _AtlBaseModule.GetModuleInstance(); 1129 HINSTANCE hInstance = _AtlBaseModule.GetModuleInstance();
1058 1130
1059 HMENU hMenu = ::LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU1)); 1131 HMENU hMenu = ::LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU1));
1060 1132
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1126 s_mimeFilter = NULL; 1198 s_mimeFilter = NULL;
1127 1199
1128 CPluginClientFactory::ReleaseMimeFilterClientInstance(); 1200 CPluginClientFactory::ReleaseMimeFilterClientInstance();
1129 } 1201 }
1130 } 1202 }
1131 s_criticalSectionLocal.Unlock(); 1203 s_criticalSectionLocal.Unlock();
1132 } 1204 }
1133 break; 1205 break;
1134 case ID_MENU_SETTINGS: 1206 case ID_MENU_SETTINGS:
1135 { 1207 {
1136 AnyCurrentSiteBrowser browser; 1208 AnyCurrentSiteBrowser browser;
sergei 2016/01/04 15:34:31 Why can we not use `m_webBrowser2` here? When can
sergei 2016/01/29 15:28:56 Not answered.
Eric 2016/01/29 16:16:12 This function can be called from a worker thread w
Eric 2016/01/29 16:16:12 Sorry. Must have missed it earlier.
1137 if (browser) 1209 if (browser)
1138 { 1210 {
1139 NavigateNewTab(browser, UserSettingsFileUrl()); 1211 NavigateNewTab(browser, UserSettingsFileUrl());
1140 } 1212 }
1141 } 1213 }
1142 break; 1214 break;
1143 case ID_MENU_DISABLE_ON_SITE: 1215 case ID_MENU_DISABLE_ON_SITE:
1144 { 1216 {
1145 std::wstring urlString = GetTab()->GetDocumentUrl(); 1217 std::wstring urlString = GetTab()->GetDocumentUrl();
1146 std::string filterText = client->GetWhitelistingFilter(urlString); 1218 std::string filterText = client->GetWhitelistingFilter(urlString);
(...skipping 27 matching lines...) Expand all
1174 1246
1175 MENUITEMINFOW miiSep = {}; 1247 MENUITEMINFOW miiSep = {};
1176 miiSep.cbSize = sizeof(miiSep); 1248 miiSep.cbSize = sizeof(miiSep);
1177 miiSep.fMask = MIIM_TYPE | MIIM_FTYPE; 1249 miiSep.fMask = MIIM_TYPE | MIIM_FTYPE;
1178 miiSep.fType = MFT_SEPARATOR; 1250 miiSep.fType = MFT_SEPARATOR;
1179 1251
1180 CPluginClient* client = CPluginClient::GetInstance(); 1252 CPluginClient* client = CPluginClient::GetInstance();
1181 CPluginSettings* settings = CPluginSettings::GetInstance(); 1253 CPluginSettings* settings = CPluginSettings::GetInstance();
1182 { 1254 {
1183 ctext = dictionary->Lookup("menu", "menu-disable-on-site"); 1255 ctext = dictionary->Lookup("menu", "menu-disable-on-site");
1184 // Is domain in white list?
1185 ReplaceString(ctext, L"?1?", client->GetHostFromUrl(url)); 1256 ReplaceString(ctext, L"?1?", client->GetHostFromUrl(url));
1186 if (client->IsWhitelistedUrl(GetTab()->GetDocumentUrl())) 1257 /*
1187 { 1258 * The display state of the "disable on this site" menu item depends upon ta b content
1259 */
1260 if (!GetTab()->IsPossibleToDisableOnSite())
1261 {
1262 // Since we can't disable the present content,
1263 // it makes no sense to offer the user an option to block it.
1264 fmii.fState = MFS_UNCHECKED | MFS_DISABLED;
1265 }
1266 else if (client->IsWhitelistedUrl(GetTab()->GetDocumentUrl()))
1267 {
1268 // Domain is in white list, indicated by a check mark
1188 fmii.fState = MFS_CHECKED | MFS_ENABLED; 1269 fmii.fState = MFS_CHECKED | MFS_ENABLED;
1189 } 1270 }
1190 else 1271 else
1191 { 1272 {
1192 fmii.fState = MFS_UNCHECKED | MFS_ENABLED; 1273 fmii.fState = MFS_UNCHECKED | MFS_ENABLED;
1193 } 1274 }
1194 fmii.fMask = MIIM_STRING | MIIM_STATE; 1275 fmii.fMask = MIIM_STRING | MIIM_STATE;
1195 fmii.dwTypeData = const_cast<LPWSTR>(ctext.c_str()); 1276 fmii.dwTypeData = const_cast<LPWSTR>(ctext.c_str());
1196 fmii.cch = static_cast<UINT>(ctext.size()); 1277 fmii.cch = static_cast<UINT>(ctext.size());
1197 1278
(...skipping 28 matching lines...) Expand all
1226 ctext = dictionary->Lookup("menu", "menu-settings"); 1307 ctext = dictionary->Lookup("menu", "menu-settings");
1227 fmii.fMask = MIIM_STATE | MIIM_STRING; 1308 fmii.fMask = MIIM_STATE | MIIM_STRING;
1228 fmii.fState = MFS_ENABLED; 1309 fmii.fState = MFS_ENABLED;
1229 fmii.dwTypeData = const_cast<LPWSTR>(ctext.c_str()); 1310 fmii.dwTypeData = const_cast<LPWSTR>(ctext.c_str());
1230 fmii.cch = static_cast<UINT>(ctext.size()); 1311 fmii.cch = static_cast<UINT>(ctext.size());
1231 ::SetMenuItemInfoW(hMenu, ID_MENU_SETTINGS, FALSE, &fmii); 1312 ::SetMenuItemInfoW(hMenu, ID_MENU_SETTINGS, FALSE, &fmii);
1232 1313
1233 return true; 1314 return true;
1234 } 1315 }
1235 1316
1236 1317 // Entry point
1237 STDMETHODIMP CPluginClass::Exec(const GUID*, DWORD nCmdID, DWORD, VARIANTARG*, V ARIANTARG*) 1318 STDMETHODIMP CPluginClass::Exec(const GUID*, DWORD nCmdID, DWORD, VARIANTARG*, V ARIANTARG*)
1238 { 1319 {
1239 HWND hBrowserWnd = GetBrowserHWND(); 1320 try
1240 if (!hBrowserWnd) 1321 {
1241 { 1322 HWND hBrowserWnd = GetBrowserHWND();
1242 return E_FAIL; 1323 if (!hBrowserWnd)
1243 } 1324 {
1244 1325 return E_FAIL;
1245 // Create menu 1326 }
1246 HMENU hMenu = CreatePluginMenu(m_tab->GetDocumentUrl()); 1327
1247 if (!hMenu) 1328 // Create menu
1248 { 1329 HMENU hMenu = CreatePluginMenu(m_tab->GetDocumentUrl());
1249 return E_FAIL; 1330 if (!hMenu)
1250 } 1331 {
1251 1332 return E_FAIL;
1252 // Check if button in toolbar was pressed 1333 }
1253 int nIDCommand = -1; 1334
1254 BOOL bRightAlign = FALSE; 1335 // Check if button in toolbar was pressed
1255 1336 int nIDCommand = -1;
1256 POINT pt; 1337 BOOL bRightAlign = FALSE;
1257 GetCursorPos(&pt); 1338
1258 1339 POINT pt;
1259 HWND hWndToolBar = ::WindowFromPoint(pt); 1340 GetCursorPos(&pt);
1260 1341
1261 DWORD nProcessId; 1342 HWND hWndToolBar = ::WindowFromPoint(pt);
1262 ::GetWindowThreadProcessId(hWndToolBar, &nProcessId); 1343
1263 1344 DWORD nProcessId;
1264 if (hWndToolBar && ::GetCurrentProcessId() == nProcessId) 1345 ::GetWindowThreadProcessId(hWndToolBar, &nProcessId);
1265 { 1346
1266 ::ScreenToClient(hWndToolBar, &pt); 1347 if (hWndToolBar && ::GetCurrentProcessId() == nProcessId)
1267 int nButton = (int)::SendMessage(hWndToolBar, TB_HITTEST, 0, (LPARAM)&pt); 1348 {
1268 1349 ::ScreenToClient(hWndToolBar, &pt);
1269 if (nButton > 0) 1350 int nButton = (int)::SendMessage(hWndToolBar, TB_HITTEST, 0, (LPARAM)&pt);
1270 { 1351
1271 TBBUTTON pTBBtn = {}; 1352 if (nButton > 0)
1272 1353 {
1273 if (SendMessage(hWndToolBar, TB_GETBUTTON, nButton, (LPARAM)&pTBBtn)) 1354 TBBUTTON pTBBtn = {};
1274 { 1355
1275 RECT rcButton; 1356 if (SendMessage(hWndToolBar, TB_GETBUTTON, nButton, (LPARAM)&pTBBtn))
1276 nIDCommand = pTBBtn.idCommand; 1357 {
1277 1358 RECT rcButton;
1278 if (SendMessage(hWndToolBar, TB_GETRECT, nIDCommand, (LPARAM)&rcButton)) 1359 nIDCommand = pTBBtn.idCommand;
1279 { 1360
1280 pt.x = rcButton.left; 1361 if (SendMessage(hWndToolBar, TB_GETRECT, nIDCommand, (LPARAM)&rcButton ))
1281 pt.y = rcButton.bottom;
1282 ClientToScreen(hWndToolBar, &pt);
1283
1284 RECT rcWorkArea;
1285 SystemParametersInfo(SPI_GETWORKAREA, 0, (LPVOID)&rcWorkArea, 0);
1286 if (rcWorkArea.right - pt.x < 150)
1287 { 1362 {
1288 bRightAlign = TRUE; 1363 pt.x = rcButton.left;
1289 pt.x = rcButton.right;
1290 pt.y = rcButton.bottom; 1364 pt.y = rcButton.bottom;
1291 ClientToScreen(hWndToolBar, &pt); 1365 ClientToScreen(hWndToolBar, &pt);
1366
1367 RECT rcWorkArea;
1368 SystemParametersInfo(SPI_GETWORKAREA, 0, (LPVOID)&rcWorkArea, 0);
1369 if (rcWorkArea.right - pt.x < 150)
1370 {
1371 bRightAlign = TRUE;
1372 pt.x = rcButton.right;
1373 pt.y = rcButton.bottom;
1374 ClientToScreen(hWndToolBar, &pt);
1375 }
1292 } 1376 }
1293 } 1377 }
1294 } 1378 }
1379 else
1380 {
1381 GetCursorPos(&pt);
1382 }
1383 }
1384
1385 // Display menu
1386 UINT nFlags = 0;
1387 if (bRightAlign)
1388 {
1389 nFlags |= TPM_RIGHTALIGN;
1295 } 1390 }
1296 else 1391 else
1297 { 1392 {
1298 GetCursorPos(&pt); 1393 nFlags |= TPM_LEFTALIGN;
1299 } 1394 }
1300 } 1395
1301 1396 DisplayPluginMenu(hMenu, nIDCommand, pt, nFlags);
1302 // Display menu 1397 }
1303 UINT nFlags = 0; 1398 catch (...)
1304 if (bRightAlign) 1399 {
1305 { 1400 // Suppress exception, log only
1306 nFlags |= TPM_RIGHTALIGN; 1401 DEBUG_GENERAL(L"CPluginClass::Exec - exception");
1307 } 1402 return E_FAIL;
1308 else 1403 }
1309 {
1310 nFlags |= TPM_LEFTALIGN;
1311 }
1312
1313 DisplayPluginMenu(hMenu, nIDCommand, pt, nFlags);
1314 1404
1315 return S_OK; 1405 return S_OK;
1316 } 1406 }
1317 1407
1318 ///////////////////////////////////////////////////////////////////////////// 1408 // Entry point
1319 // Window procedures
1320
1321 LRESULT CALLBACK CPluginClass::NewStatusProc(HWND hWnd, UINT message, WPARAM wPa ram, LPARAM lParam) 1409 LRESULT CALLBACK CPluginClass::NewStatusProc(HWND hWnd, UINT message, WPARAM wPa ram, LPARAM lParam)
1322 { 1410 {
1323 // Find tab 1411 CPluginClass *pClass;
1324 CPluginClass *pClass = FindInstance(hWnd); 1412 try
1325 if (!pClass) 1413 {
1326 { 1414 // Find tab
1327 return DefWindowProc(hWnd, message, wParam, lParam); 1415 pClass = FindInstance(hWnd);
1328 } 1416 if (!pClass)
1329 1417 {
1330 // Process message 1418 /*
1331 switch (message) 1419 * Race condition if reached.
1332 { 1420 * We did not unhook the window procedure for the status bar when the last BHO instance using it terminated.
1333 case SB_SIMPLE: 1421 * The next best thing is to call the system default window function.
1334 { 1422 */
1335 ShowWindow(pClass->m_hPaneWnd, !wParam); 1423 return DefWindowProc(hWnd, message, wParam, lParam);
1424 }
1425
1426 // Process message
1427 switch (message)
1428 {
1429 case SB_SIMPLE:
1430 {
1431 ShowWindow(pClass->m_hPaneWnd, !wParam);
1432 break;
1433 }
1434
1435 case WM_SYSCOLORCHANGE:
1436 {
1437 pClass->UpdateTheme();
1438 break;
1439 }
1440
1441 case SB_SETPARTS:
1442 {
1443 if (!lParam || !wParam || wParam > 30 || !IsWindow(pClass->m_hPaneWnd))
1444 {
1445 return CallWindowProc(pClass->m_pWndProcStatus, hWnd, message, wParam, lParam);
1446 }
1447
1448 WPARAM nParts = wParam;
1449 if (STATUSBAR_PANE_NUMBER >= nParts)
1450 {
1451 return CallWindowProc(pClass->m_pWndProcStatus, hWnd, message, wParam, lParam);
1452 }
1453
1454 HLOCAL hLocal = LocalAlloc(LHND, sizeof(int) * (nParts + 1));
1455 LPINT lpParts = (LPINT)LocalLock(hLocal);
1456 memcpy(lpParts, (void*)lParam, wParam*sizeof(int));
1457
1458 for (unsigned i = 0; i < STATUSBAR_PANE_NUMBER; i++)
1459 {
1460 lpParts[i] -= pClass->m_nPaneWidth;
1461 }
1462 LRESULT hRet = CallWindowProc(pClass->m_pWndProcStatus, hWnd, message, w Param, (LPARAM)lpParts);
1463
1464 AdblockPlus::Rectangle rcPane;
1465 ::SendMessage(hWnd, SB_GETRECT, STATUSBAR_PANE_NUMBER, (LPARAM)&rcPane);
1466
1467 AdblockPlus::Rectangle rcClient;
1468 ::GetClientRect(hWnd, &rcClient);
1469
1470 ::MoveWindow(
1471 pClass->m_hPaneWnd,
1472 lpParts[STATUSBAR_PANE_NUMBER] - pClass->m_nPaneWidth,
1473 0,
1474 pClass->m_nPaneWidth,
1475 rcClient.Height(),
1476 TRUE);
1477
1478 ::LocalFree(hLocal);
1479 return hRet;
1480 }
1481
1482 default:
1336 break; 1483 break;
1337 } 1484 }
1338 1485 }
1339 case WM_SYSCOLORCHANGE: 1486 catch (...)
1340 { 1487 {
1341 pClass->UpdateTheme(); 1488 // Suppress exception. Fall through to default handler.
1342 break; 1489 DEBUG_GENERAL(L"CPluginClass::NewStatusProc - exception");
1343 } 1490 }
1344 1491 return ::CallWindowProc(pClass->m_pWndProcStatus, hWnd, message, wParam, lPara m);
1345 case SB_SETPARTS:
1346 {
1347 if (!lParam || !wParam || wParam > 30 || !IsWindow(pClass->m_hPaneWnd))
1348 {
1349 return CallWindowProc(pClass->m_pWndProcStatus, hWnd, message, wParam, l Param);
1350 }
1351
1352 WPARAM nParts = wParam;
1353 if (STATUSBAR_PANE_NUMBER >= nParts)
1354 {
1355 return CallWindowProc(pClass->m_pWndProcStatus, hWnd, message, wParam, l Param);
1356 }
1357
1358 HLOCAL hLocal = LocalAlloc(LHND, sizeof(int) * (nParts+1));
1359 LPINT lpParts = (LPINT)LocalLock(hLocal);
1360 memcpy(lpParts, (void*)lParam, wParam*sizeof(int));
1361
1362 for (unsigned i = 0; i < STATUSBAR_PANE_NUMBER; i++)
1363 {
1364 lpParts[i] -= pClass->m_nPaneWidth;
1365 }
1366 LRESULT hRet = CallWindowProc(pClass->m_pWndProcStatus, hWnd, message, wPa ram, (LPARAM)lpParts);
1367
1368 AdblockPlus::Rectangle rcPane;
1369 ::SendMessage(hWnd, SB_GETRECT, STATUSBAR_PANE_NUMBER, (LPARAM)&rcPane);
1370
1371 AdblockPlus::Rectangle rcClient;
1372 ::GetClientRect(hWnd, &rcClient);
1373
1374 ::MoveWindow(
1375 pClass->m_hPaneWnd,
1376 lpParts[STATUSBAR_PANE_NUMBER] - pClass->m_nPaneWidth,
1377 0,
1378 pClass->m_nPaneWidth,
1379 rcClient.Height(),
1380 TRUE);
1381
1382 ::LocalFree(hLocal);
1383
1384
1385 return hRet;
1386 }
1387
1388 default:
1389 break;
1390 }
1391
1392 LRESULT result = CallWindowProc(pClass->m_pWndProcStatus, hWnd, message, wPara m, lParam);
1393
1394
1395 return result;
1396
1397 } 1492 }
1398 1493
1399 1494
1400 HICON CPluginClass::GetStatusBarIcon(const std::wstring& url) 1495 HICON CPluginClass::GetStatusBarIcon(const std::wstring& url)
1401 { 1496 {
1402 // use the disable icon as defualt, if the client doesn't exists 1497 // use the disable icon as defualt, if the client doesn't exists
1403 HICON hIcon = GetIcon(ICON_PLUGIN_DEACTIVATED); 1498 HICON hIcon = GetIcon(ICON_PLUGIN_DEACTIVATED);
1404 1499
1405 CPluginTab* tab = GetTab(::GetCurrentThreadId()); 1500 CPluginTab* tab = GetTabForCurrentThread();
1406 if (tab) 1501 if (tab)
1407 { 1502 {
1408 CPluginClient* client = CPluginClient::GetInstance(); 1503 CPluginClient* client = CPluginClient::GetInstance();
1409 if (CPluginSettings::GetInstance()->IsPluginEnabled()) 1504 if (CPluginSettings::GetInstance()->IsPluginEnabled())
1410 { 1505 {
1411 if (client->IsWhitelistedUrl(url)) 1506 if (client->IsWhitelistedUrl(url))
1412 { 1507 {
1413 hIcon = GetIcon(ICON_PLUGIN_DISABLED); 1508 hIcon = GetIcon(ICON_PLUGIN_DISABLED);
1414 } 1509 }
1415 else 1510 else
1416 { 1511 {
1417 CPluginSettings* settings = CPluginSettings::GetInstance(); 1512 CPluginSettings* settings = CPluginSettings::GetInstance();
1418 hIcon = GetIcon(ICON_PLUGIN_ENABLED); 1513 hIcon = GetIcon(ICON_PLUGIN_ENABLED);
1419 } 1514 }
1420 } 1515 }
1421 } 1516 }
1422 return hIcon; 1517 return hIcon;
1423 } 1518 }
1424 1519
1425 1520 // Entry point
1426 LRESULT CALLBACK CPluginClass::PaneWindowProc(HWND hWnd, UINT message, WPARAM wP aram, LPARAM lParam) 1521 LRESULT CALLBACK CPluginClass::PaneWindowProc(HWND hWnd, UINT message, WPARAM wP aram, LPARAM lParam)
1427 { 1522 {
1428 // Find tab 1523 try
1429 CPluginClass *pClass = FindInstance(GetParent(hWnd)); 1524 {
1430 if (!pClass) 1525 // Find tab
1431 { 1526 CPluginClass *pClass = FindInstance(GetParent(hWnd));
1432 return ::DefWindowProc(hWnd, message, wParam, lParam); 1527 if (!pClass)
1433 } 1528 {
1434 1529 return ::DefWindowProc(hWnd, message, wParam, lParam);
1435 // Process message 1530 }
1436 switch (message) 1531
1437 { 1532 // Process message
1438 1533 switch (message)
1439 case WM_SETCURSOR: 1534 {
1440 { 1535 case WM_SETCURSOR:
1441 ::SetCursor(::LoadCursor(NULL, IDC_ARROW)); 1536 {
1442 return TRUE; 1537 ::SetCursor(::LoadCursor(NULL, IDC_ARROW));
1443 } 1538 return TRUE;
1444 case WM_PAINT: 1539 }
1445 { 1540 case WM_PAINT:
1446 PAINTSTRUCT ps; 1541 {
1447 HDC hDC = ::BeginPaint(hWnd, &ps); 1542 PAINTSTRUCT ps;
1448 1543 HDC hDC = ::BeginPaint(hWnd, &ps);
1449 AdblockPlus::Rectangle rcClient; 1544
1450 ::GetClientRect(hWnd, &rcClient); 1545 AdblockPlus::Rectangle rcClient;
1451 1546 ::GetClientRect(hWnd, &rcClient);
1452 int nDrawEdge = 0; 1547
1453 1548 int nDrawEdge = 0;
1454 // Old Windows background drawing 1549
1455 if (pClass->m_hTheme == NULL) 1550 // Old Windows background drawing
1456 { 1551 if (pClass->m_hTheme == NULL)
1457 ::FillRect(hDC, &rcClient, (HBRUSH)(COLOR_BTNFACE + 1)); 1552 {
1458 ::DrawEdge(hDC, &rcClient, BDR_RAISEDINNER, BF_LEFT); 1553 ::FillRect(hDC, &rcClient, (HBRUSH)(COLOR_BTNFACE + 1));
1459 1554 ::DrawEdge(hDC, &rcClient, BDR_RAISEDINNER, BF_LEFT);
1460 nDrawEdge = 3; 1555
1461 rcClient.left += 3; 1556 nDrawEdge = 3;
1462 1557 rcClient.left += 3;
1463 ::DrawEdge(hDC, &rcClient, BDR_SUNKENOUTER, BF_RECT); 1558
1464 } 1559 ::DrawEdge(hDC, &rcClient, BDR_SUNKENOUTER, BF_RECT);
1465 // Themed background drawing 1560 }
1466 else 1561 // Themed background drawing
1467 { 1562 else
1468 // Draw background 1563 {
1469 if (pfnDrawThemeBackground) 1564 // Draw background
1470 { 1565 if (pfnDrawThemeBackground)
1471 AdblockPlus::Rectangle rc = rcClient;
1472 rc.right -= 2;
1473 pfnDrawThemeBackground(pClass->m_hTheme, hDC, 0, 0, &rc, NULL);
1474 }
1475
1476 // Copy separator picture to left side
1477 int nHeight = rcClient.Height();
1478 int nWidth = rcClient.Width() - 2;
1479
1480 for (int i = 0; i < 2; i++)
1481 {
1482 for (int j = 0; j < nHeight; j++)
1483 { 1566 {
1484 COLORREF clr = ::GetPixel(hDC, i + nWidth, j); 1567 AdblockPlus::Rectangle rc = rcClient;
1485 1568 rc.right -= 2;
1486 // Ignore black boxes (if source is obscured by other windows) 1569 pfnDrawThemeBackground(pClass->m_hTheme, hDC, 0, 0, &rc, NULL);
1487 if (clr != -1 && (GetRValue(clr) > 8 || GetGValue(clr) > 8 || GetBVa lue(clr) > 8)) 1570 }
1571
1572 // Copy separator picture to left side
1573 int nHeight = rcClient.Height();
1574 int nWidth = rcClient.Width() - 2;
1575
1576 for (int i = 0; i < 2; i++)
1577 {
1578 for (int j = 0; j < nHeight; j++)
1488 { 1579 {
1489 ::SetPixel(hDC, i, j, clr); 1580 COLORREF clr = ::GetPixel(hDC, i + nWidth, j);
1581
1582 // Ignore black boxes (if source is obscured by other windows)
1583 if (clr != -1 && (GetRValue(clr) > 8 || GetGValue(clr) > 8 || GetB Value(clr) > 8))
1584 {
1585 ::SetPixel(hDC, i, j, clr);
1586 }
1490 } 1587 }
1491 } 1588 }
1492 } 1589 }
1493 } 1590
1494 1591 // Draw icon
1495 // Draw icon 1592 if (CPluginClient::GetInstance())
1496 if (CPluginClient::GetInstance()) 1593 {
1497 { 1594 HICON hIcon = GetStatusBarIcon(pClass->GetTab()->GetDocumentUrl());
1498 HICON hIcon = GetStatusBarIcon(pClass->GetTab()->GetDocumentUrl()); 1595
1499 1596 int offx = nDrawEdge;
1500 int offx = nDrawEdge; 1597 if (hIcon)
1501 if (hIcon) 1598 {
1502 { 1599 //Get the RECT for the leftmost pane (the status text pane)
1503 //Get the RECT for the leftmost pane (the status text pane) 1600 RECT rect;
1601 BOOL rectRes = ::SendMessage(pClass->m_hStatusBarWnd, SB_GETRECT, 0, (LPARAM)&rect);
1602 ::DrawIconEx(hDC, 0, rect.bottom - rect.top - iconHeight, hIcon, ico nWidth, iconHeight, NULL, NULL, DI_NORMAL);
1603 offx += iconWidth;
1604 }
1605 #ifdef _DEBUG
1606 // Display version
1607 HFONT hFont = (HFONT)::SendMessage(pClass->m_hStatusBarWnd, WM_GETFONT , 0, 0);
1608 HGDIOBJ hOldFont = ::SelectObject(hDC, hFont);
1609
1610 AdblockPlus::Rectangle rcText = rcClient;
1611 rcText.left += offx;
1612 ::SetBkMode(hDC, TRANSPARENT);
1613 ::DrawTextW(hDC, IEPLUGIN_VERSION, -1, &rcText, DT_WORD_ELLIPSIS | DT_ LEFT | DT_SINGLELINE | DT_VCENTER);
1614
1615 ::SelectObject(hDC, hOldFont);
1616 #endif // _DEBUG
1617 }
1618
1619 // Done!
1620 EndPaint(hWnd, &ps);
1621
1622 return 0;
1623 }
1624
1625 case WM_LBUTTONUP:
1626 case WM_RBUTTONUP:
1627 {
1628 std::wstring url = pClass->GetBrowserUrl();
1629 if (url != pClass->GetTab()->GetDocumentUrl())
1630 {
1631 pClass->GetTab()->SetDocumentUrl(url);
1632 }
1633
1634 // Create menu
1635 HMENU hMenu = pClass->CreatePluginMenu(url);
1636 if (!hMenu)
1637 {
1638 return 0;
1639 }
1640
1641 // Display menu
1642 POINT pt;
1643 ::GetCursorPos(&pt);
1644
1645 RECT rc;
1646 ::GetWindowRect(hWnd, &rc);
1647
1648 if (rc.left >= 0 && rc.top >= 0)
1649 {
1650 pt.x = rc.left;
1651 pt.y = rc.top;
1652 }
1653
1654 pClass->DisplayPluginMenu(hMenu, -1, pt, TPM_LEFTALIGN | TPM_BOTTOMALIGN );
1655 break;
1656 }
1657 case WM_DESTROY:
1658 break;
1659 case SC_CLOSE:
1660 break;
1661
1662 case WM_UPDATEUISTATE:
1663 {
1664 CPluginTab* tab = GetTabForCurrentThread();
1665 if (tab)
1666 {
1667 tab->OnActivate();
1504 RECT rect; 1668 RECT rect;
1505 BOOL rectRes = ::SendMessage(pClass->m_hStatusBarWnd, SB_GETRECT, 0, ( LPARAM)&rect); 1669 GetWindowRect(pClass->m_hPaneWnd, &rect);
1506 ::DrawIconEx(hDC, 0, rect.bottom - rect.top - iconHeight, hIcon, iconW idth, iconHeight, NULL, NULL, DI_NORMAL); 1670 pClass->notificationMessage.MoveToCenter(rect);
1507 offx += iconWidth; 1671 }
1508 } 1672 if (LOWORD(wParam) == UIS_CLEAR)
1509 #ifdef _DEBUG 1673 {
1510 // Display version 1674 pClass->notificationMessage.Hide();
1511 HFONT hFont = (HFONT)::SendMessage(pClass->m_hStatusBarWnd, WM_GETFONT, 0, 0); 1675 }
1512 HGDIOBJ hOldFont = ::SelectObject(hDC,hFont); 1676 break;
1513 1677 }
1514 AdblockPlus::Rectangle rcText = rcClient; 1678 case WM_WINDOWPOSCHANGING:
1515 rcText.left += offx; 1679 {
1516 ::SetBkMode(hDC, TRANSPARENT);
1517 ::DrawTextW(hDC, IEPLUGIN_VERSION, -1, &rcText, DT_WORD_ELLIPSIS|DT_LEFT |DT_SINGLELINE|DT_VCENTER);
1518
1519 ::SelectObject(hDC, hOldFont);
1520 #endif // _DEBUG
1521 }
1522
1523 // Done!
1524 EndPaint(hWnd, &ps);
1525
1526 return 0;
1527 }
1528
1529 case WM_LBUTTONUP:
1530 case WM_RBUTTONUP:
1531 {
1532 std::wstring url = pClass->GetBrowserUrl();
1533 if (url != pClass->GetTab()->GetDocumentUrl())
1534 {
1535 pClass->GetTab()->SetDocumentUrl(url);
1536 }
1537
1538 // Create menu
1539 HMENU hMenu = pClass->CreatePluginMenu(url);
1540 if (!hMenu)
1541 {
1542 return 0;
1543 }
1544
1545 // Display menu
1546 POINT pt;
1547 ::GetCursorPos(&pt);
1548
1549 RECT rc;
1550 ::GetWindowRect(hWnd, &rc);
1551
1552 if (rc.left >= 0 && rc.top >= 0)
1553 {
1554 pt.x = rc.left;
1555 pt.y = rc.top;
1556 }
1557
1558 pClass->DisplayPluginMenu(hMenu, -1, pt, TPM_LEFTALIGN|TPM_BOTTOMALIGN);
1559 }
1560 break;
1561 case WM_DESTROY:
1562 break;
1563 case SC_CLOSE:
1564 break;
1565
1566 case WM_UPDATEUISTATE:
1567 {
1568 CPluginTab* tab = GetTab(::GetCurrentThreadId());
1569 if (tab)
1570 {
1571 tab->OnActivate();
1572 RECT rect; 1680 RECT rect;
1573 GetWindowRect(pClass->m_hPaneWnd, &rect); 1681 GetWindowRect(pClass->m_hPaneWnd, &rect);
1574 pClass->notificationMessage.Move(rect.left + (rect.right - rect.left) / 2, rect.top + (rect.bottom - rect.top) / 2); 1682 if (pClass->notificationMessage.IsVisible())
1575 } 1683 {
1576 if (LOWORD(wParam) == UIS_CLEAR) 1684 pClass->notificationMessage.MoveToCenter(rect);
1577 { 1685 }
1578 pClass->notificationMessage.Hide(); 1686 break;
1579 } 1687 }
1580 } 1688 case WM_WINDOWPOSCHANGED:
1581 break; 1689 {
1582 case WM_WINDOWPOSCHANGING: 1690 WINDOWPOS* wndPos = reinterpret_cast<WINDOWPOS*>(lParam);
1583 { 1691 if (wndPos->flags & SWP_HIDEWINDOW)
1584 RECT rect; 1692 {
1585 GetWindowRect(pClass->m_hPaneWnd, &rect); 1693 pClass->notificationMessage.Hide();
1586 if (pClass->notificationMessage.IsVisible()) 1694 }
1587 { 1695 break;
1588 pClass->notificationMessage.Move(rect.left + (rect.right - rect.left) / 2, rect.top + (rect.bottom - rect.top) / 2); 1696 }
1589 } 1697 case WM_ALREADY_UP_TO_DATE:
1590 } 1698 {
1591 break; 1699 Dictionary* dictionary = Dictionary::GetInstance();
1592 case WM_WINDOWPOSCHANGED: 1700 std::wstring upToDateText = dictionary->Lookup("updater", "update-alread y-up-to-date-text");
1593 { 1701 std::wstring upToDateTitle = dictionary->Lookup("updater", "update-alrea dy-up-to-date-title");
1594 WINDOWPOS* wndPos = reinterpret_cast<WINDOWPOS*>(lParam); 1702 pClass->notificationMessage.SetTextAndIcon(upToDateText, upToDateTitle, TTI_INFO);
1595 if (wndPos->flags & SWP_HIDEWINDOW) 1703 break;
1596 { 1704 }
1597 pClass->notificationMessage.Hide(); 1705 case WM_UPDATE_CHECK_ERROR:
1598 } 1706 {
1599 } 1707 Dictionary* dictionary = Dictionary::GetInstance();
1600 break; 1708 std::wstring errorText = dictionary->Lookup("updater", "update-error-tex t");
1601 case WM_ALREADY_UP_TO_DATE: 1709 std::wstring errorTitle = dictionary->Lookup("updater", "update-error-ti tle");
1602 { 1710 pClass->notificationMessage.SetTextAndIcon(errorText, errorTitle, TTI_ER ROR);
1603 Dictionary* dictionary = Dictionary::GetInstance(); 1711 break;
1604 std::wstring upToDateText = dictionary->Lookup("updater", "update-already- up-to-date-text"); 1712 }
1605 std::wstring upToDateTitle = dictionary->Lookup("updater", "update-already -up-to-date-title"); 1713 case WM_DOWNLOADING_UPDATE:
1606 pClass->notificationMessage.SetTextAndIcon(upToDateText, upToDateTitle, TT I_INFO); 1714 {
1607 } 1715 Dictionary* dictionary = Dictionary::GetInstance();
1608 break; 1716 std::wstring downloadingText = dictionary->Lookup("updater", "downloadin g-update-text");
1609 case WM_UPDATE_CHECK_ERROR: 1717 std::wstring downloadingTitle = dictionary->Lookup("updater", "downloadi ng-update-title");
1610 { 1718 pClass->notificationMessage.SetTextAndIcon(downloadingText, downloadingT itle, TTI_INFO);
1611 Dictionary* dictionary = Dictionary::GetInstance(); 1719 break;
1612 std::wstring errorText = dictionary->Lookup("updater", "update-error-text" ); 1720 }
1613 std::wstring errorTitle = dictionary->Lookup("updater", "update-error-titl e"); 1721 }
1614 pClass->notificationMessage.SetTextAndIcon(errorText, errorText, TTI_ERROR ); 1722 }
1615 } 1723 catch (...)
1616 break; 1724 {
1617 case WM_DOWNLOADING_UPDATE: 1725 // Suppress exception. Fall through to default handler.
1618 { 1726 DEBUG_GENERAL(L"CPluginClass::PaneWindowProc - exception");
1619 Dictionary* dictionary = Dictionary::GetInstance(); 1727 }
1620 std::wstring downloadingText = dictionary->Lookup("updater", "downloading- update-text"); 1728 return ::DefWindowProc(hWnd, message, wParam, lParam);
1621 std::wstring downloadingTitle = dictionary->Lookup("updater", "downloading -update-title");
1622 pClass->notificationMessage.SetTextAndIcon(downloadingText, downloadingTit le, TTI_INFO);
1623 }
1624 break;
1625 }
1626
1627 return DefWindowProc(hWnd, message, wParam, lParam);
1628 } 1729 }
1629 1730
1630 1731
1631 void CPluginClass::UpdateStatusBar() 1732 void CPluginClass::UpdateStatusBar()
1632 { 1733 {
1633 DEBUG_GENERAL("*** Updating statusbar") 1734 DEBUG_GENERAL("*** Updating statusbar")
1634 if (m_hPaneWnd == NULL) 1735 if (m_hPaneWnd == NULL)
1635 { 1736 {
1636 CreateStatusBarPane(); 1737 CreateStatusBarPane();
1637 } 1738 }
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1686 s_criticalSectionLocal.Unlock(); 1787 s_criticalSectionLocal.Unlock();
1687 1788
1688 return icon; 1789 return icon;
1689 } 1790 }
1690 1791
1691 ATOM CPluginClass::GetAtomPaneClass() 1792 ATOM CPluginClass::GetAtomPaneClass()
1692 { 1793 {
1693 return s_atomPaneClass; 1794 return s_atomPaneClass;
1694 } 1795 }
1695 1796
LEFTRIGHT

Powered by Google App Engine
This is Rietveld