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

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

Issue 29333107: Issue #1652, #3456 - Replace 's_asyncWebBrowser2' with thread-safe facilities
Patch Set: Created Dec. 29, 2015, 5:54 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>, 2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-2015 Eyeo GmbH 3 * Copyright (C) 2006-2015 Eyeo GmbH
4 * 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify 5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as 6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 * 8 *
9 * Adblock Plus is distributed in the hope that it will be useful, 9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
(...skipping 11 matching lines...) Expand all
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 "Instances.h"
32 #include "../shared/Version.h" 33 #include "../shared/Version.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 SyncSet<CPluginClass*, nullptr> instanceSet;
60 std::map<DWORD, CPluginClass*> CPluginClass::s_threadInstances; 61 std::map<DWORD, CPluginClass*> CPluginClass::s_threadInstances;
61 62
62 CComAutoCriticalSection CPluginClass::s_criticalSectionLocal; 63 CComAutoCriticalSection CPluginClass::s_criticalSectionLocal;
63 CComAutoCriticalSection CPluginClass::s_criticalSectionWindow; 64 CComAutoCriticalSection CPluginClass::s_criticalSectionWindow;
64 65
65 CComQIPtr<IWebBrowser2> CPluginClass::s_asyncWebBrowser2;
66
67 /* 66 /*
68 * Without namespace declaration, the identifier "Rectangle" is ambiguous 67 * Without namespace declaration, the identifier "Rectangle" is ambiguous
69 * See http://msdn.microsoft.com/en-us/library/windows/desktop/dd162898(v=vs.85) .aspx 68 * See http://msdn.microsoft.com/en-us/library/windows/desktop/dd162898(v=vs.85) .aspx
70 */ 69 */
71 namespace AdblockPlus 70 namespace AdblockPlus
72 { 71 {
73 /** 72 /**
74 * Replacement for ATL type CRect. 73 * Replacement for ATL type CRect.
75 */ 74 */
76 class Rectangle 75 class Rectangle
77 : public RECT 76 : public RECT
78 { 77 {
79 public: 78 public:
80 int Height() const 79 int Height() const
81 { 80 {
82 return bottom - top; 81 return bottom - top;
83 } 82 }
84 83
85 int Width() const 84 int Width() const
86 { 85 {
87 return right - left; 86 return right - left;
88 } 87 }
89 }; 88 };
90 } 89 }
91 90
91 /**
92 * Wrapper class for a browser site object that ensures proper site life cycle.
93 *
94 * 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.
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.
97 *
98 * This class may wrap a null browser site at the very beginning or very end of IE life time.
99 * Always check the contained value before using.
100 * If a null value is found at the beginning of IE life, it's probably a logic e rror, indicating that some code was launched too soon.
101 * If a null value is found at the end, it's probably harmless, since IE is shut ting down.
102 *
103 * \par Invariant
104 * - if 'browser' is nullptr then 'setSiteLock' does not own any mutex
105 * - if 'browser' is not nullptr then
106 * - 'setSiteLock' owns the 'siteGuard' mutex of the CPluginClass instanc e from which 'browser' was copied
107 * - 'setSiteLock' is still locked
108 */
109 class AnyCurrentSiteBrowser {
110 /**
111 * The underlying browser is a raw pointer copy of 'm_webBrowser2' for some ob ject.
112 * Synchronization ensures that it is not nullified for the life span of this object.
113 */
114 IWebBrowser2* browser;
115
116 /**
117 * Lock lasts for the duration of this object, if acquired in the constructor
118 */
119 std::unique_lock<std::mutex> setSiteLock;
120
121 /*
122 * This class is for scope variables only.
123 */
124 AnyCurrentSiteBrowser(const AnyCurrentSiteBrowser&); // = delete
125 AnyCurrentSiteBrowser& operator=(const AnyCurrentSiteBrowser&); // = delete
126 AnyCurrentSiteBrowser(AnyCurrentSiteBrowser&&); // = delete
127 AnyCurrentSiteBrowser& operator=(AnyCurrentSiteBrowser&&); // = delete
128
129 public:
130 /**
131 * Default constructor copies one of the currently valid sites.
132 */
133 AnyCurrentSiteBrowser()
134 {
135 // Find a current site instance whose SetSite() lock we can acquire.
136 auto instance = instanceSet.LinearSearch(
137 [this](CPluginClass* p) -> bool
138 {
139 // Avoid deadlock with try-lock constructor
140 setSiteLock = std::unique_lock<std::mutex>(p->siteGuard, std::try_to_loc k); // synchronize with return from p->SetSite()
141 if (!setSiteLock.owns_lock())
142 {
143 // SetSite(0) is currently executing in another thread, so we'll ignor e this instance
144 return false;
145 }
146 // Assert 'setSiteLock' owns the mutex p->siteGuard and it is locked.
147 return true;
148 });
149 if (!instance)
150 {
151 browser = nullptr;
152 }
153 else
154 {
155 browser = instance->m_webBrowser2;
156 if (!browser)
157 {
158 throw std::logic_error("Instance without site found in set of instances with 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 }
160 }
161 };
162
163 /**
164 * Destructor releases any lock held and allows SetSite() to complete.
165 */
166 ~AnyCurrentSiteBrowser() {}; // = default
167
168 IWebBrowser2* operator->() const
169 {
170 return browser;
171 }
172
173 operator IWebBrowser2*() const
174 {
175 return browser;
176 }
177
178 operator bool() const
179 {
180 return browser != nullptr;
181 }
182 };
183
92 CPluginClass::CPluginClass() 184 CPluginClass::CPluginClass()
93 : m_webBrowser2(nullptr) 185 : m_webBrowser2(nullptr)
94 { 186 {
95 //Use this line to debug memory leaks 187 //Use this line to debug memory leaks
96 // _CrtDumpMemoryLeaks(); 188 // _CrtDumpMemoryLeaks();
97 189
98 m_isAdvised = false; 190 m_isAdvised = false;
99 m_hTabWnd = NULL; 191 m_hTabWnd = NULL;
100 m_hStatusBarWnd = NULL; 192 m_hStatusBarWnd = NULL;
101 m_hPaneWnd = NULL; 193 m_hPaneWnd = NULL;
(...skipping 28 matching lines...) Expand all
130 return nullptr; 222 return nullptr;
131 } 223 }
132 return (HWND)hBrowserWndHandle; 224 return (HWND)hBrowserWndHandle;
133 } 225 }
134 226
135 bool CPluginClass::IsRootBrowser(IWebBrowser2* otherBrowser) 227 bool CPluginClass::IsRootBrowser(IWebBrowser2* otherBrowser)
136 { 228 {
137 return m_webBrowser2.IsEqualObject(otherBrowser); 229 return m_webBrowser2.IsEqualObject(otherBrowser);
138 } 230 }
139 231
140 CComQIPtr<IWebBrowser2> CPluginClass::GetAsyncBrowser()
141 {
142 CComQIPtr<IWebBrowser2> browser;
143
144 s_criticalSectionLocal.Lock();
145 {
146 browser = s_asyncWebBrowser2;
147 }
148 s_criticalSectionLocal.Unlock();
149
150 return browser;
151 }
152
153 std::wstring CPluginClass::GetBrowserUrl() const 232 std::wstring CPluginClass::GetBrowserUrl() const
154 { 233 {
155 std::wstring url; 234 std::wstring url;
156 if (m_webBrowser2) 235 if (m_webBrowser2)
157 { 236 {
158 CComBSTR bstrURL; 237 CComBSTR bstrURL;
159 if (SUCCEEDED(m_webBrowser2->get_LocationURL(&bstrURL)) && bstrURL) 238 if (SUCCEEDED(m_webBrowser2->get_LocationURL(&bstrURL)) && bstrURL)
160 { 239 {
161 url = std::wstring(bstrURL, SysStringLen(bstrURL)); 240 url = std::wstring(bstrURL, SysStringLen(bstrURL));
162 } 241 }
(...skipping 25 matching lines...) Expand all
188 * 267 *
189 * IE also ordinarily calls this again when its window/tab is closed, in which c ase 268 * IE also ordinarily calls this again when its window/tab is closed, in which c ase
190 * 'unknownSite' will be null. Extraordinarily, this is sometimes _not_ called w hen IE 269 * 'unknownSite' will be null. Extraordinarily, this is sometimes _not_ called w hen IE
191 * is shutting down. Thus 'SetSite(nullptr)' has some similarities with a destru ctor, 270 * is shutting down. Thus 'SetSite(nullptr)' has some similarities with a destru ctor,
192 * but it is not a proper substitute for one. 271 * but it is not a proper substitute for one.
193 */ 272 */
194 STDMETHODIMP CPluginClass::SetSite(IUnknown* unknownSite) 273 STDMETHODIMP CPluginClass::SetSite(IUnknown* unknownSite)
195 { 274 {
196 try 275 try
197 { 276 {
277 std::lock_guard<std::mutex> lock(siteGuard);
278
198 if (unknownSite) 279 if (unknownSite)
199 { 280 {
200 281
201 DEBUG_GENERAL(L"========================================================== ======================\nNEW TAB UI\n============================================ ====================================") 282 DEBUG_GENERAL(L"========================================================== ======================\nNEW TAB UI\n============================================ ====================================")
202 283
203 HRESULT hr = ::CoInitialize(NULL); 284 HRESULT hr = ::CoInitialize(NULL);
204 if (FAILED(hr)) 285 if (FAILED(hr))
205 { 286 {
206 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_COINIT, "Class::SetSite - CoInitialize"); 287 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_COINIT, "Class::SetSite - CoInitialize");
207 } 288 }
208 289
209 /* 290 /*
210 * We were instantiated as a BHO, so our site is always of type IWebBrowse r2. 291 * We were instantiated as a BHO, so our site is always of type IWebBrowse r2.
211 */ 292 */
212 m_webBrowser2 = ATL::CComQIPtr<IWebBrowser2>(unknownSite); 293 m_webBrowser2 = ATL::CComQIPtr<IWebBrowser2>(unknownSite);
213 if (!m_webBrowser2) 294 if (!m_webBrowser2)
214 { 295 {
215 throw std::logic_error("CPluginClass::SetSite - Unable to convert site p ointer to IWebBrowser2*"); 296 throw std::logic_error("CPluginClass::SetSite - Unable to convert site p ointer to IWebBrowser2*");
216 } 297 }
298 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 {
300 throw std::logic_error("CPluginClass::SetSite - May not overwrite existi ng entry in instance set");
301 }
217 302
218 //register the mimefilter 303 //register the mimefilter
219 //and only mimefilter 304 //and only mimefilter
220 //on some few computers the mimefilter does not get properly registered wh en it is done on another thread 305 //on some few computers the mimefilter does not get properly registered wh en it is done on another thread
221 s_criticalSectionLocal.Lock(); 306 s_criticalSectionLocal.Lock();
222 { 307 {
223 // Always register on startup, then check if we need to unregister in a separate thread
224 s_mimeFilter = CPluginClientFactory::GetMimeFilterClientInstance(); 308 s_mimeFilter = CPluginClientFactory::GetMimeFilterClientInstance();
225 s_asyncWebBrowser2 = unknownSite;
226 s_instances.insert(this);
227 } 309 }
228 s_criticalSectionLocal.Unlock(); 310 s_criticalSectionLocal.Unlock();
229 311
230 try 312 try
231 { 313 {
232 DEBUG_GENERAL("Loaded as BHO"); 314 DEBUG_GENERAL("Loaded as BHO");
233 HRESULT hr = DispEventAdvise(m_webBrowser2); 315 HRESULT hr = DispEventAdvise(m_webBrowser2);
234 if (SUCCEEDED(hr)) 316 if (SUCCEEDED(hr))
235 { 317 {
236 m_isAdvised = true; 318 m_isAdvised = true;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 m_hPaneWnd = NULL; 356 m_hPaneWnd = NULL;
275 } 357 }
276 358
277 m_hTabWnd = NULL; 359 m_hTabWnd = NULL;
278 m_hStatusBarWnd = NULL; 360 m_hStatusBarWnd = NULL;
279 361
280 // Remove instance from the list, shutdown threads 362 // Remove instance from the list, shutdown threads
281 HANDLE hMainThread = NULL; 363 HANDLE hMainThread = NULL;
282 HANDLE hTabThread = NULL; 364 HANDLE hTabThread = NULL;
283 365
366 if (!instanceSet.EraseWithCheck(this))
367 {
368 throw std::logic_error("CPluginClass::SetSite - Missing entry in instanc e set");
369 }
284 s_criticalSectionLocal.Lock(); 370 s_criticalSectionLocal.Lock();
285 { 371 {
286 s_instances.erase(this); 372 if (instanceSet.Empty())
287
288 std::map<DWORD,CPluginClass*>::iterator it = s_threadInstances.find(::Ge tCurrentThreadId());
289 if (it != s_threadInstances.end())
290 {
291 s_threadInstances.erase(it);
292 }
293 if (s_instances.empty())
294 { 373 {
295 // TODO: Explicitly releasing a resource when a container becomes empt y looks like a job better suited for shared_ptr 374 // TODO: Explicitly releasing a resource when a container becomes empt y looks like a job better suited for shared_ptr
296 CPluginClientFactory::ReleaseMimeFilterClientInstance(); 375 CPluginClientFactory::ReleaseMimeFilterClientInstance();
297 } 376 }
298 } 377 }
299 s_criticalSectionLocal.Unlock(); 378 s_criticalSectionLocal.Unlock();
300
301 m_webBrowser2 = nullptr; 379 m_webBrowser2 = nullptr;
302 380
303 DEBUG_GENERAL("=========================================================== =====================\nNEW TAB UI - END\n======================================= =========================================") 381 DEBUG_GENERAL("=========================================================== =====================\nNEW TAB UI - END\n======================================= =========================================")
304 382
305 ::CoUninitialize(); 383 ::CoUninitialize();
306 } 384 }
307 385
308 } 386 }
309 catch (...) 387 catch (...)
310 { 388 {
311 } 389 }
312 IObjectWithSiteImpl<CPluginClass>::SetSite(unknownSite); 390 IObjectWithSiteImpl<CPluginClass>::SetSite(unknownSite);
313 return S_OK; 391 return S_OK;
314 } 392 }
315 393
316 bool CPluginClass::IsStatusBarEnabled() 394 namespace
317 { 395 {
318 DEBUG_GENERAL("IsStatusBarEnabled start"); 396 bool IsStatusBarDisabledInRegistry()
319 HKEY pHkey;
320 HKEY pHkeySub;
321 RegOpenCurrentUser(KEY_QUERY_VALUE, &pHkey);
322 DWORD truth = 1;
323 DWORD truthSize = sizeof(truth);
324 RegOpenKey(pHkey, L"Software\\Microsoft\\Internet Explorer\\Main", &pHkeySub);
325 LONG res = RegQueryValueEx(pHkeySub, L"StatusBarWeb", NULL, NULL, (BYTE*)&trut h, &truthSize);
326 RegCloseKey(pHkey);
327 if (res != ERROR_SUCCESS)
328 { 397 {
329 res = RegOpenKey(pHkey, L"Software\\Microsoft\\Internet Explorer\\MINIE", &p HkeySub); 398 DEBUG_GENERAL("IsStatusBarDisabledInRegistry start");
330 if (res == ERROR_SUCCESS) 399 HKEY pHkey;
400 HKEY pHkeySub;
401 RegOpenCurrentUser(KEY_QUERY_VALUE, &pHkey);
402 DWORD truth = 1;
403 DWORD truthSize = sizeof(truth);
404 RegOpenKey(pHkey, L"Software\\Microsoft\\Internet Explorer\\Main", &pHkeySub );
405 LONG res = RegQueryValueEx(pHkeySub, L"StatusBarWeb", NULL, NULL, (BYTE*)&tr uth, &truthSize);
406 RegCloseKey(pHkey);
407 if (res != ERROR_SUCCESS)
331 { 408 {
332 LONG res = RegQueryValueEx(pHkeySub, L"ShowStatusBar", NULL, NULL, (BYTE*) &truth, &truthSize); 409 res = RegOpenKey(pHkey, L"Software\\Microsoft\\Internet Explorer\\MINIE", &pHkeySub);
333 if (res == ERROR_SUCCESS) 410 if (res == ERROR_SUCCESS)
334 { 411 {
335 RegCloseKey(pHkey); 412 LONG res = RegQueryValueEx(pHkeySub, L"ShowStatusBar", NULL, NULL, (BYTE *)&truth, &truthSize);
413 if (res == ERROR_SUCCESS)
414 {
415 RegCloseKey(pHkey);
416 }
336 } 417 }
337 } 418 }
419 DEBUG_GENERAL("IsStatusBarDisabledInRegistry end");
420 return truth != 1;
338 } 421 }
339 DEBUG_GENERAL("IsStatusBarEnabled end"); 422
340 return truth == 1; 423 /**
424 * Navigate to a new tab, falling back to a new window if needed.
425 */
426 bool NavigateNewTab(IWebBrowser2* browser, const std::wstring& targetUrl)
427 {
428 ATL::CComBSTR targetUrlBstr(static_cast<int>(targetUrl.length()), targetUrl. c_str());
429 VARIANT vFlags;
430 vFlags.vt = VT_I4;
431 vFlags.intVal = navOpenInNewTab;
432 HRESULT hr = browser->Navigate(targetUrlBstr, &vFlags, NULL, NULL, NULL);
433 if (FAILED(hr))
434 {
435 vFlags.intVal = navOpenInNewWindow;
436
437 hr = browser->Navigate(targetUrlBstr, &vFlags, NULL, NULL, NULL);
438 if (FAILED(hr))
439 {
440 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_NAVIGATION, 0, "Navigation::Failed");
441 return false;
442 }
443 }
444 return true;
445 }
341 } 446 }
342 447
343 void CPluginClass::ShowStatusBar() 448 void CPluginClass::ShowStatusBar()
344 { 449 {
345 DEBUG_GENERAL("ShowStatusBar start"); 450 DEBUG_GENERAL("ShowStatusBar start");
346 451 AnyCurrentSiteBrowser browser;
452 if (!browser)
453 {
454 DEBUG_GENERAL("ShowStatusBar abort; no browser");
455 return;
456 }
347 VARIANT_BOOL isVisible; 457 VARIANT_BOOL isVisible;
348 458 HRESULT hr = browser->get_StatusBar(&isVisible);
349 459 if (FAILED(hr))
350 CComQIPtr<IWebBrowser2> browser = GetAsyncBrowser();
351 if (browser)
352 { 460 {
353 HRESULT hr = S_OK; 461 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_UI, PLUGIN_ERROR_UI_GET_STATUSBAR, "CPlugin Class::ShowStatusBar get_StatusBar");
354 hr = browser->get_StatusBar(&isVisible); 462 return;
355 if (SUCCEEDED(hr))
356 {
357 if (!isVisible)
358 {
359 SHANDLE_PTR pBrowserHWnd;
360 browser->get_HWND((SHANDLE_PTR*)&pBrowserHWnd);
361 Dictionary* dictionary = Dictionary::GetInstance();
362
363 HKEY pHkey;
364 HKEY pHkeySub;
365 LSTATUS regRes = 0;
366 regRes = RegOpenCurrentUser(KEY_WRITE, &pHkey);
367
368 // Do we have enough rights to enable a status bar?
369 if (regRes != 0)
370 {
371 // We use the tab window here and in the next few calls, since the bro wser window may still not be available
372 LRESULT res = MessageBox((HWND)m_hTabWnd,
373 dictionary->Lookup("status-bar", "error-text").c_str(),
374 dictionary->Lookup("status-bar", "error-title").c_str(),
375 MB_OK);
376 return;
377 }
378 // Ask if a user wants to enable a status bar automatically
379 LRESULT res = MessageBox((HWND)m_hTabWnd,
380 dictionary->Lookup("status-bar", "question").c_str(),
381 dictionary->Lookup("status-bar", "title").c_str(),
382 MB_YESNO);
383 if (res == IDYES)
384 {
385 DWORD truth = 1;
386 regRes = RegOpenKey(pHkey, L"Software\\Microsoft\\Internet Explorer\\M INIE", &pHkeySub);
387 regRes = RegSetValueEx(pHkeySub, L"ShowStatusBar", 0, REG_DWORD, (BYTE *)&truth, sizeof(truth));
388 regRes = RegCloseKey(pHkeySub);
389 regRes = RegOpenKey(pHkey, L"Software\\Microsoft\\Internet Explorer\\M ain", &pHkeySub);
390 regRes = RegSetValueEx(pHkeySub, L"StatusBarWeb", 0, REG_DWORD, (BYTE* )&truth, sizeof(truth));
391 regRes = RegCloseKey(pHkeySub);
392 hr = browser->put_StatusBar(TRUE);
393 if (FAILED(hr))
394 {
395 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_UI, PLUGIN_ERROR_UI_PUT_STATUSBAR, "Class::Enable statusbar");
396 }
397 CreateStatusBarPane();
398
399 // We need to restart the tab now, to enable the status bar properly
400 VARIANT vFlags;
401 vFlags.vt = VT_I4;
402 vFlags.intVal = navOpenInNewTab;
403
404 CComBSTR curLoc;
405 browser->get_LocationURL(&curLoc);
406 HRESULT hr = browser->Navigate(curLoc, &vFlags, NULL, NULL, NULL);
407 if (FAILED(hr))
408 {
409 vFlags.intVal = navOpenInNewWindow;
410
411 hr = browser->Navigate(CComBSTR(curLoc), &vFlags, NULL, NULL, NULL);
412 if (FAILED(hr))
413 {
414 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_NAVIGATION, PLUGIN_ERROR_NAVIGATI ON, "Navigation::Failed")
415 }
416 }
417 browser->Quit();
418 }
419 }
420 }
421 else
422 {
423 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_UI, PLUGIN_ERROR_UI_GET_STATUSBAR, "Class ::Get statusbar state");
424 }
425 } 463 }
464 if (!isVisible)
465 {
466 DEBUG_GENERAL("ShowStatusBar end early; browser told us status bar is visibl e");
467 return;
468 }
469 Dictionary* dictionary = Dictionary::GetInstance();
470 /*
471 * Do we have enough rights to enable a status bar?
472 */
473 HKEY pHkey;
474 LSTATUS regRes = RegOpenCurrentUser(KEY_WRITE, &pHkey);
475 if (regRes != 0)
476 {
477 // We use the tab window here and in the next few calls, since the browser w indow may still not be available
478 LRESULT res = MessageBox((HWND)m_hTabWnd,
479 dictionary->Lookup("status-bar", "error-text").c_str(),
480 dictionary->Lookup("status-bar", "error-title").c_str(),
481 MB_OK);
482 DEBUG_GENERAL("ShowStatusBar end early; user must enable status bar");
483 return;
484 }
485 /*
486 * Ask if a user wants to enable a status bar automatically
487 */
488 LRESULT res = MessageBox((HWND)m_hTabWnd,
489 dictionary->Lookup("status-bar", "question").c_str(),
490 dictionary->Lookup("status-bar", "title").c_str(),
491 MB_YESNO);
492 if (res != IDYES)
493 {
494 DEBUG_GENERAL("ShowStatusBar end early; user did not enable status bar");
495 return;
496 }
497 HKEY pHkeySub;
498 DWORD truth = 1;
499 regRes = RegOpenKey(pHkey, L"Software\\Microsoft\\Internet Explorer\\MINIE", & pHkeySub);
500 regRes = RegSetValueEx(pHkeySub, L"ShowStatusBar", 0, REG_DWORD, (BYTE*)&truth , sizeof(truth));
501 regRes = RegCloseKey(pHkeySub);
502 regRes = RegOpenKey(pHkey, L"Software\\Microsoft\\Internet Explorer\\Main", &p HkeySub);
503 regRes = RegSetValueEx(pHkeySub, L"StatusBarWeb", 0, REG_DWORD, (BYTE*)&truth, sizeof(truth));
504 regRes = RegCloseKey(pHkeySub);
505 hr = browser->put_StatusBar(TRUE);
506 if (FAILED(hr))
507 {
508 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_UI, PLUGIN_ERROR_UI_PUT_STATUSBAR, "Class:: Enable statusbar");
509 // Ignore error
510 }
511 CreateStatusBarPane();
512 CComBSTR curLoc;
513 browser->get_LocationURL(&curLoc);
514 std::wstring currentLocation(ToWstring(curLoc));
515 NavigateNewTab(browser, currentLocation);
516 browser->Quit();
426 DEBUG_GENERAL("ShowStatusBar end"); 517 DEBUG_GENERAL("ShowStatusBar end");
427 } 518 }
428 519
429 // Entry point 520 // Entry point
430 void STDMETHODCALLTYPE CPluginClass::OnBeforeNavigate2( 521 void STDMETHODCALLTYPE CPluginClass::OnBeforeNavigate2(
431 IDispatch* frameBrowserDisp /**< [in] */, 522 IDispatch* frameBrowserDisp /**< [in] */,
432 VARIANT* urlVariant /**< [in] */, 523 VARIANT* urlVariant /**< [in] */,
433 VARIANT* /**< [in] Flags*/, 524 VARIANT* /**< [in] Flags*/,
434 VARIANT* /**< [in] TargetFrameName*/, 525 VARIANT* /**< [in] TargetFrameName*/,
435 VARIANT* /**< [in] PostData*/, 526 VARIANT* /**< [in] PostData*/,
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
684 775
685 // IE6 can't be accessed from another thread, execute in current thread 776 // IE6 can't be accessed from another thread, execute in current thread
686 if (ieVersion < 7) 777 if (ieVersion < 7)
687 { 778 {
688 FirstRunThread(); 779 FirstRunThread();
689 } 780 }
690 else 781 else
691 { 782 {
692 CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)CPluginClass::FirstRunThr ead, NULL, NULL, NULL); 783 CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)CPluginClass::FirstRunThr ead, NULL, NULL, NULL);
693 } 784 }
694 if (((m_hPaneWnd == NULL) || !IsStatusBarEnabled()) && isFirstRun) 785 if (((m_hPaneWnd == NULL) || IsStatusBarDisabledInRegistry()) && isFirstRun)
695 { 786 {
696 ShowStatusBar(); 787 ShowStatusBar();
697 } 788 }
698 789
699 // Enable acceptable ads by default 790 // Enable acceptable ads by default
700 std::wstring aaUrl = CPluginClient::GetInstance()->GetPref(L"subscriptions_e xceptionsurl", L""); 791 std::wstring aaUrl = CPluginClient::GetInstance()->GetPref(L"subscriptions_e xceptionsurl", L"");
701 CPluginClient::GetInstance()->AddSubscription(aaUrl); 792 CPluginClient::GetInstance()->AddSubscription(aaUrl);
702 } 793 }
703 s_criticalSectionLocal.Unlock(); 794 s_criticalSectionLocal.Unlock();
704 795
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
742 { 833 {
743 hTabWnd2 = ::FindWindowEx(hTabWnd2, NULL, L"TabWindowClass", NULL); 834 hTabWnd2 = ::FindWindowEx(hTabWnd2, NULL, L"TabWindowClass", NULL);
744 } 835 }
745 836
746 if (hTabWnd2) 837 if (hTabWnd2)
747 { 838 {
748 DWORD nProcessId; 839 DWORD nProcessId;
749 ::GetWindowThreadProcessId(hTabWnd2, &nProcessId); 840 ::GetWindowThreadProcessId(hTabWnd2, &nProcessId);
750 if (::GetCurrentProcessId() == nProcessId) 841 if (::GetCurrentProcessId() == nProcessId)
751 { 842 {
752 bool bExistingTab = false; 843 auto instance = instanceSet.LinearSearch(
753 844 [hTabWnd2](CPluginClass* p)
754 s_criticalSectionLocal.Lock();
755 {
756 for (auto instance : s_instances)
757 { 845 {
758 if (instance->m_hTabWnd == hTabWnd2) 846 return p->m_hTabWnd == hTabWnd2;
759 { 847 });
760 bExistingTab = true; 848 if (!instance)
761 break;
762 }
763 }
764 }
765 s_criticalSectionLocal.Unlock();
766
767 if (!bExistingTab)
768 { 849 {
769 amoundOfNewTabs ++; 850 amoundOfNewTabs ++;
770 uniqueNewTab = hTabWnd2; 851 uniqueNewTab = hTabWnd2;
771 if (GetCurrentThreadId() == GetWindowThreadProcessId(hTabWnd2, NULL) ) 852 if (GetCurrentThreadId() == GetWindowThreadProcessId(hTabWnd2, NULL) )
772 { 853 {
773 hBrowserWnd = hTabWnd = hTabWnd2; 854 hBrowserWnd = hTabWnd = hTabWnd2;
774 break; 855 break;
775 } 856 }
776 857
777 } 858 }
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
870 delete []pData; 951 delete []pData;
871 } 952 }
872 953
873 HDC hdc = GetWindowDC(m_hStatusBarWnd); 954 HDC hdc = GetWindowDC(m_hStatusBarWnd);
874 SendMessage(m_hStatusBarWnd, WM_PAINT, (WPARAM)hdc, 0); 955 SendMessage(m_hStatusBarWnd, WM_PAINT, (WPARAM)hdc, 0);
875 ReleaseDC(m_hStatusBarWnd, hdc); 956 ReleaseDC(m_hStatusBarWnd, hdc);
876 957
877 return true; 958 return true;
878 } 959 }
879 960
961 // Entry point
880 void CPluginClass::FirstRunThread() 962 void CPluginClass::FirstRunThread()
881 { 963 {
882 // Just return if the First Run Page should be suppressed 964 try
883 if (CPluginClient::GetInstance()->GetPref(L"suppress_first_run_page", false)) 965 {
884 return; 966 // Just return if the First Run Page should be suppressed
967 if (CPluginClient::GetInstance()->GetPref(L"suppress_first_run_page", false) )
968 return;
885 969
886 CoInitialize(NULL); 970 if (SUCCEEDED(CoInitialize(NULL)))
887 VARIANT vFlags; 971 {
888 vFlags.vt = VT_I4; 972 AnyCurrentSiteBrowser browser;
889 vFlags.intVal = navOpenInNewTab; 973 if (browser)
890 974 {
891 CComBSTR navigatePath = CComBSTR(FirstRunPageFileUrl().c_str()); 975 NavigateNewTab(browser, FirstRunPageFileUrl());
892 976 }
893 HRESULT hr = GetAsyncBrowser()->Navigate(navigatePath, &vFlags, NULL, NULL, NU LL); 977 }
894 if (FAILED(hr)) 978 CoUninitialize();
979 }
980 catch (...)
895 { 981 {
896 vFlags.intVal = navOpenInNewWindow; 982 // Suppress errors
897 hr = GetAsyncBrowser()->Navigate(navigatePath, &vFlags, NULL, NULL, NULL);
898 }
899
900 if (FAILED(hr))
901 {
902 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_NAVIGATION, PLUGIN_ERROR_NAVIGATION_WELCOME , "Navigation::Welcome page failed")
903 } 983 }
904 } 984 }
985
905 void CPluginClass::CloseTheme() 986 void CPluginClass::CloseTheme()
906 { 987 {
907 if (m_hTheme) 988 if (m_hTheme)
908 { 989 {
909 if (pfnClose) 990 if (pfnClose)
910 { 991 {
911 pfnClose(m_hTheme); 992 pfnClose(m_hTheme);
912 } 993 }
913 994
914 m_hTheme = NULL; 995 m_hTheme = NULL;
915 } 996 }
916 } 997 }
917 998
918 void CPluginClass::UpdateTheme() 999 void CPluginClass::UpdateTheme()
919 { 1000 {
920 CloseTheme(); 1001 CloseTheme();
921 1002
922 if (pfnOpenThemeData) 1003 if (pfnOpenThemeData)
923 { 1004 {
924 m_hTheme = pfnOpenThemeData(m_hPaneWnd, L"STATUS"); 1005 m_hTheme = pfnOpenThemeData(m_hPaneWnd, L"STATUS");
925 if (!m_hTheme) 1006 if (!m_hTheme)
926 { 1007 {
927 } 1008 }
928 } 1009 }
929 } 1010 }
930 1011
931
932 CPluginClass* CPluginClass::FindInstance(HWND hStatusBarWnd) 1012 CPluginClass* CPluginClass::FindInstance(HWND hStatusBarWnd)
933 { 1013 {
934 CPluginClass* result = nullptr; 1014 return instanceSet.LinearSearch(
935 1015 [hStatusBarWnd](CPluginClass* p) -> bool
936 s_criticalSectionLocal.Lock();
937 {
938 for (auto instance : s_instances)
939 { 1016 {
940 if (instance->m_hStatusBarWnd == hStatusBarWnd) 1017 return p->m_hStatusBarWnd == hStatusBarWnd;
941 { 1018 });
942 result = instance;
943 break;
944 }
945 }
946 }
947 s_criticalSectionLocal.Unlock();
948
949 return result;
950 } 1019 }
951 1020
952 CPluginTab* CPluginClass::GetTab() 1021 CPluginTab* CPluginClass::GetTab()
953 { 1022 {
954 return m_tab; 1023 return m_tab;
955 } 1024 }
956 1025
957 CPluginTab* CPluginClass::GetTab(DWORD dwThreadId) 1026 CPluginTab* CPluginClass::GetTab(DWORD dwThreadId)
958 { 1027 {
959 CPluginTab* tab = NULL; 1028 CPluginTab* tab = NULL;
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
1057 s_mimeFilter = NULL; 1126 s_mimeFilter = NULL;
1058 1127
1059 CPluginClientFactory::ReleaseMimeFilterClientInstance(); 1128 CPluginClientFactory::ReleaseMimeFilterClientInstance();
1060 } 1129 }
1061 } 1130 }
1062 s_criticalSectionLocal.Unlock(); 1131 s_criticalSectionLocal.Unlock();
1063 } 1132 }
1064 break; 1133 break;
1065 case ID_MENU_SETTINGS: 1134 case ID_MENU_SETTINGS:
1066 { 1135 {
1067 CComQIPtr<IWebBrowser2> browser = GetAsyncBrowser(); 1136 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.
1068 if (browser) 1137 if (browser)
1069 { 1138 {
1070 VARIANT vFlags; 1139 NavigateNewTab(browser, UserSettingsFileUrl());
1071 vFlags.vt = VT_I4;
1072 vFlags.intVal = navOpenInNewTab;
1073
1074 auto userSettingsFileUrl = UserSettingsFileUrl();
1075 ATL::CComBSTR urlToNavigate(static_cast<int>(userSettingsFileUrl.length( )), userSettingsFileUrl.c_str());
1076 HRESULT hr = browser->Navigate(urlToNavigate, &vFlags, NULL, NULL, NULL) ;
1077 if (FAILED(hr))
1078 {
1079 vFlags.intVal = navOpenInNewWindow;
1080
1081 hr = browser->Navigate(urlToNavigate, &vFlags, NULL, NULL, NULL);
1082 if (FAILED(hr))
1083 {
1084 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_NAVIGATION, PLUGIN_ERROR_NAVIGATION _SETTINGS, "Navigation::Failed")
1085 }
1086 }
1087 } 1140 }
1088 break;
1089 } 1141 }
1142 break;
1090 case ID_MENU_DISABLE_ON_SITE: 1143 case ID_MENU_DISABLE_ON_SITE:
1091 { 1144 {
1092 std::wstring urlString = GetTab()->GetDocumentUrl(); 1145 std::wstring urlString = GetTab()->GetDocumentUrl();
1093 std::string filterText = client->GetWhitelistingFilter(urlString); 1146 std::string filterText = client->GetWhitelistingFilter(urlString);
1094 if (!filterText.empty()) 1147 if (!filterText.empty())
1095 { 1148 {
1096 client->RemoveFilter(filterText); 1149 client->RemoveFilter(filterText);
1097 } 1150 }
1098 else 1151 else
1099 { 1152 {
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after
1633 s_criticalSectionLocal.Unlock(); 1686 s_criticalSectionLocal.Unlock();
1634 1687
1635 return icon; 1688 return icon;
1636 } 1689 }
1637 1690
1638 ATOM CPluginClass::GetAtomPaneClass() 1691 ATOM CPluginClass::GetAtomPaneClass()
1639 { 1692 {
1640 return s_atomPaneClass; 1693 return s_atomPaneClass;
1641 } 1694 }
1642 1695
OLDNEW

Powered by Google App Engine
This is Rietveld