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: 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:
View unified diff | Download patch
« no previous file with comments | « src/plugin/PluginClass.h ('k') | test/plugin/InstancesTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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-2016 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
(...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 "Instances.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 std::set<CPluginClass*> CPluginClass::s_instances; 61 SyncSet<CPluginClass*, nullptr> instanceSet;
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 namespace 66 namespace
68 { 67 {
69 /** 68 /**
70 * A synchronized map whose key is always the current thread ID. 69 * A synchronized map whose key is always the current thread ID.
71 */ 70 */
72 class CurrentThreadMap 71 class CurrentThreadMap
73 : public SyncMap<DWORD, CPluginClass*, nullptr> 72 : public SyncMap<DWORD, CPluginClass*, nullptr>
74 { 73 {
75 typedef SyncMap<DWORD, CPluginClass*, nullptr> Base; 74 typedef SyncMap<DWORD, CPluginClass*, nullptr> Base;
76 75
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 { 122 {
124 if (right < left) 123 if (right < left)
125 { 124 {
126 throw std::runtime_error("invariant violation: rectangle right < left"); 125 throw std::runtime_error("invariant violation: rectangle right < left");
127 } 126 }
128 return static_cast<unsigned long>(right - left); 127 return static_cast<unsigned long>(right - left);
129 } 128 }
130 }; 129 };
131 } 130 }
132 131
132 /**
133 * Wrapper class for a browser site object that ensures proper site life cycle.
134 *
135 * The browser is guaranteed to be valid for the lifetime of the object.
136 * What that means is that SetSite(0) on the containing BHO instance will not re turn before this object is destroyed.
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.
138 *
139 * This class may wrap a null browser site at the very beginning or very end of IE life time.
140 * Always check the contained value before using.
141 * 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.
142 * If a null value is found at the end, it's probably harmless, since IE is shut ting down.
143 *
144 * \par Invariant
145 * - if 'browser' is nullptr then 'setSiteLock' does not own any mutex
146 * - if 'browser' is not nullptr then
147 * - 'setSiteLock' owns the 'siteGuard' mutex of the CPluginClass instanc e from which 'browser' was copied
148 * - 'setSiteLock' is still locked
149 */
150 class AnyCurrentSiteBrowser {
151 /**
152 * The underlying browser is a raw pointer copy of 'm_webBrowser2' for some ob ject.
153 * Synchronization ensures that it is not nullified for the life span of this object.
154 */
155 IWebBrowser2* browser;
156
157 /**
158 * Lock lasts for the duration of this object, if acquired in the constructor
159 */
160 std::unique_lock<std::mutex> setSiteLock;
161
162 /*
163 * This class is for scope variables only.
164 */
165 AnyCurrentSiteBrowser(const AnyCurrentSiteBrowser&); // = delete
166 AnyCurrentSiteBrowser& operator=(const AnyCurrentSiteBrowser&); // = delete
167 AnyCurrentSiteBrowser(AnyCurrentSiteBrowser&&); // = delete
168 AnyCurrentSiteBrowser& operator=(AnyCurrentSiteBrowser&&); // = delete
169
170 public:
171 /**
172 * Default constructor copies one of the currently valid sites.
173 */
174 AnyCurrentSiteBrowser()
175 {
176 // Find a current site instance whose SetSite() lock we can acquire.
177 auto instance = instanceSet.LinearSearch(
178 [this](CPluginClass* p) -> bool
179 {
180 // Avoid deadlock with try-lock constructor
181 setSiteLock = std::unique_lock<std::mutex>(p->siteGuard, std::try_to_loc k); // synchronize with return from p->SetSite()
182 if (!setSiteLock.owns_lock())
183 {
184 // SetSite(0) is currently executing in another thread, so we'll ignor e this instance
185 return false;
186 }
187 // Assert 'setSiteLock' owns the mutex p->siteGuard and it is locked.
188 return true;
189 });
190 if (!instance)
191 {
192 browser = nullptr;
193 }
194 else
195 {
196 browser = instance->m_webBrowser2;
197 if (!browser)
198 {
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");
200 }
201 }
202 };
203
204 /**
205 * Destructor releases any lock held and allows SetSite() to complete.
206 */
207 ~AnyCurrentSiteBrowser() {}; // = default
208
209 IWebBrowser2* operator->() const
210 {
211 return browser;
212 }
213
214 operator IWebBrowser2*() const
215 {
216 return browser;
217 }
218
219 operator bool() const
220 {
221 return browser != nullptr;
222 }
223 };
224
133 CPluginClass::CPluginClass() 225 CPluginClass::CPluginClass()
134 : m_webBrowser2(nullptr) 226 : m_webBrowser2(nullptr)
135 { 227 {
136 DEBUG_GENERAL([this]() -> std::wstring 228 DEBUG_GENERAL([this]() -> std::wstring
137 { 229 {
138 std::wstring s = L"CPluginClass::<constructor>, this = "; 230 std::wstring s = L"CPluginClass::<constructor>, this = ";
139 s += ToHexLiteral(this); 231 s += ToHexLiteral(this);
140 return s; 232 return s;
141 }()); 233 }());
142 234
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 return nullptr; 274 return nullptr;
183 } 275 }
184 return (HWND)hBrowserWndHandle; 276 return (HWND)hBrowserWndHandle;
185 } 277 }
186 278
187 bool CPluginClass::IsRootBrowser(IWebBrowser2* otherBrowser) 279 bool CPluginClass::IsRootBrowser(IWebBrowser2* otherBrowser)
188 { 280 {
189 return m_webBrowser2.IsEqualObject(otherBrowser); 281 return m_webBrowser2.IsEqualObject(otherBrowser);
190 } 282 }
191 283
192 CComQIPtr<IWebBrowser2> CPluginClass::GetAsyncBrowser()
193 {
194 CComQIPtr<IWebBrowser2> browser;
195
196 s_criticalSectionLocal.Lock();
197 {
198 browser = s_asyncWebBrowser2;
199 }
200 s_criticalSectionLocal.Unlock();
201
202 return browser;
203 }
204
205 std::wstring CPluginClass::GetBrowserUrl() const 284 std::wstring CPluginClass::GetBrowserUrl() const
206 { 285 {
207 std::wstring url; 286 std::wstring url;
208 if (m_webBrowser2) 287 if (m_webBrowser2)
209 { 288 {
210 CComBSTR bstrURL; 289 CComBSTR bstrURL;
211 if (SUCCEEDED(m_webBrowser2->get_LocationURL(&bstrURL))) 290 if (SUCCEEDED(m_webBrowser2->get_LocationURL(&bstrURL)))
212 { 291 {
213 url = ToWstring(bstrURL); 292 url = ToWstring(bstrURL);
214 } 293 }
(...skipping 28 matching lines...) Expand all
243 * 322 *
244 * IE also ordinarily calls this again when its window/tab is closed, in which c ase 323 * IE also ordinarily calls this again when its window/tab is closed, in which c ase
245 * 'unknownSite' will be null. Extraordinarily, this is sometimes _not_ called w hen IE 324 * 'unknownSite' will be null. Extraordinarily, this is sometimes _not_ called w hen IE
246 * is shutting down. Thus 'SetSite(nullptr)' has some similarities with a destru ctor, 325 * is shutting down. Thus 'SetSite(nullptr)' has some similarities with a destru ctor,
247 * but it is not a proper substitute for one. 326 * but it is not a proper substitute for one.
248 */ 327 */
249 STDMETHODIMP CPluginClass::SetSite(IUnknown* unknownSite) 328 STDMETHODIMP CPluginClass::SetSite(IUnknown* unknownSite)
250 { 329 {
251 try 330 try
252 { 331 {
332 std::lock_guard<std::mutex> lock(siteGuard);
333
253 if (unknownSite) 334 if (unknownSite)
254 { 335 {
255 DEBUG_GENERAL(L"========================================================== ======================\nNEW TAB UI\n============================================ ===================================="); 336 DEBUG_GENERAL(L"========================================================== ======================\nNEW TAB UI\n============================================ ====================================");
256 337
257 HRESULT hr = ::CoInitialize(NULL); 338 HRESULT hr = ::CoInitialize(NULL);
258 if (FAILED(hr)) 339 if (FAILED(hr))
259 { 340 {
260 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");
261 } 342 }
262 343
(...skipping 13 matching lines...) Expand all
276 return ss.str(); 357 return ss.str();
277 }()); 358 }());
278 359
279 /* 360 /*
280 * Add ourselves to the thread map. 361 * Add ourselves to the thread map.
281 */ 362 */
282 if (!threadMap.AddIfAbsent(this)) 363 if (!threadMap.AddIfAbsent(this))
283 { 364 {
284 throw std::logic_error("CPluginClass::SetSite - May not overwrite existi ng entry in thread map"); 365 throw std::logic_error("CPluginClass::SetSite - May not overwrite existi ng entry in thread map");
285 } 366 }
367 if (!instanceSet.InsertIfAbsent(this))
368 {
369 throw std::logic_error("CPluginClass::SetSite - May not overwrite existi ng entry in instance set");
370 }
371
286 372
287 //register the mimefilter 373 //register the mimefilter
288 //and only mimefilter 374 //and only mimefilter
289 //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
290 s_criticalSectionLocal.Lock(); 376 s_criticalSectionLocal.Lock();
291 { 377 {
292 // Always register on startup, then check if we need to unregister in a separate thread
293 s_mimeFilter = CPluginClientFactory::GetMimeFilterClientInstance(); 378 s_mimeFilter = CPluginClientFactory::GetMimeFilterClientInstance();
294 s_asyncWebBrowser2 = unknownSite;
295 s_instances.insert(this);
296 } 379 }
297 s_criticalSectionLocal.Unlock(); 380 s_criticalSectionLocal.Unlock();
298 381
299 try 382 try
300 { 383 {
301 HRESULT hr = DispEventAdvise(m_webBrowser2); 384 HRESULT hr = DispEventAdvise(m_webBrowser2);
302 if (SUCCEEDED(hr)) 385 if (SUCCEEDED(hr))
303 { 386 {
304 m_isAdvised = true; 387 m_isAdvised = true;
305 try 388 try
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
350 m_hPaneWnd = NULL; 433 m_hPaneWnd = NULL;
351 } 434 }
352 435
353 m_hTabWnd = NULL; 436 m_hTabWnd = NULL;
354 m_hStatusBarWnd = NULL; 437 m_hStatusBarWnd = NULL;
355 438
356 // Remove instance from the list, shutdown threads 439 // Remove instance from the list, shutdown threads
357 HANDLE hMainThread = NULL; 440 HANDLE hMainThread = NULL;
358 HANDLE hTabThread = NULL; 441 HANDLE hTabThread = NULL;
359 442
443 if (!instanceSet.EraseWithCheck(this))
444 {
445 throw std::logic_error("CPluginClass::SetSite - Missing entry in instanc e set");
446 }
360 if (!threadMap.RemoveAndCheck()) 447 if (!threadMap.RemoveAndCheck())
361 { 448 {
362 throw std::logic_error("CPluginClass::SetSite - Missing entry in thread map"); 449 throw std::logic_error("CPluginClass::SetSite - Missing entry in thread map");
363 } 450 }
364
365 s_criticalSectionLocal.Lock(); 451 s_criticalSectionLocal.Lock();
366 { 452 {
367 s_instances.erase(this); 453 if (instanceSet.Empty())
368 if (s_instances.empty())
369 { 454 {
370 // 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
371 CPluginClientFactory::ReleaseMimeFilterClientInstance(); 456 CPluginClientFactory::ReleaseMimeFilterClientInstance();
372 } 457 }
373 } 458 }
374 s_criticalSectionLocal.Unlock(); 459 s_criticalSectionLocal.Unlock();
375
376 m_webBrowser2 = nullptr; 460 m_webBrowser2 = nullptr;
377 461
378 DEBUG_GENERAL("=========================================================== =====================\nNEW TAB UI - END\n======================================= =========================================") 462 DEBUG_GENERAL("=========================================================== =====================\nNEW TAB UI - END\n======================================= =========================================")
379 463
380 ::CoUninitialize(); 464 ::CoUninitialize();
381 } 465 }
382 466
383 } 467 }
384 catch (...) 468 catch (...)
385 { 469 {
386 } 470 }
387 IObjectWithSiteImpl<CPluginClass>::SetSite(unknownSite); 471 IObjectWithSiteImpl<CPluginClass>::SetSite(unknownSite);
388 return S_OK; 472 return S_OK;
389 } 473 }
390 474
391 bool CPluginClass::IsStatusBarEnabled() 475 namespace
392 { 476 {
393 DEBUG_GENERAL("IsStatusBarEnabled start"); 477 bool IsStatusBarDisabledInRegistry()
394 HKEY pHkey;
395 HKEY pHkeySub;
396 RegOpenCurrentUser(KEY_QUERY_VALUE, &pHkey);
397 DWORD truth = 1;
398 DWORD truthSize = sizeof(truth);
399 RegOpenKey(pHkey, L"Software\\Microsoft\\Internet Explorer\\Main", &pHkeySub);
400 LONG res = RegQueryValueEx(pHkeySub, L"StatusBarWeb", NULL, NULL, (BYTE*)&trut h, &truthSize);
401 RegCloseKey(pHkey);
402 if (res != ERROR_SUCCESS)
403 { 478 {
404 res = RegOpenKey(pHkey, L"Software\\Microsoft\\Internet Explorer\\MINIE", &p HkeySub); 479 DEBUG_GENERAL("IsStatusBarDisabledInRegistry start");
405 if (res == ERROR_SUCCESS) 480 HKEY pHkey;
481 HKEY pHkeySub;
482 RegOpenCurrentUser(KEY_QUERY_VALUE, &pHkey);
483 DWORD truth = 1;
484 DWORD truthSize = sizeof(truth);
485 RegOpenKey(pHkey, L"Software\\Microsoft\\Internet Explorer\\Main", &pHkeySub );
486 LONG res = RegQueryValueEx(pHkeySub, L"StatusBarWeb", NULL, NULL, (BYTE*)&tr uth, &truthSize);
487 RegCloseKey(pHkey);
488 if (res != ERROR_SUCCESS)
406 { 489 {
407 LONG res = RegQueryValueEx(pHkeySub, L"ShowStatusBar", NULL, NULL, (BYTE*) &truth, &truthSize); 490 res = RegOpenKey(pHkey, L"Software\\Microsoft\\Internet Explorer\\MINIE", &pHkeySub);
408 if (res == ERROR_SUCCESS) 491 if (res == ERROR_SUCCESS)
409 { 492 {
410 RegCloseKey(pHkey); 493 LONG res = RegQueryValueEx(pHkeySub, L"ShowStatusBar", NULL, NULL, (BYTE *)&truth, &truthSize);
494 if (res == ERROR_SUCCESS)
495 {
496 RegCloseKey(pHkey);
497 }
411 } 498 }
412 } 499 }
500 DEBUG_GENERAL("IsStatusBarDisabledInRegistry end");
501 return truth != 1;
413 } 502 }
414 DEBUG_GENERAL("IsStatusBarEnabled end"); 503
415 return truth == 1; 504 /**
505 * Navigate to a new tab, falling back to a new window if needed.
506 */
507 bool NavigateNewTab(IWebBrowser2* browser, const std::wstring& targetUrl)
508 {
509 ATL::CComBSTR targetUrlBstr(static_cast<int>(targetUrl.length()), targetUrl. c_str());
510 VARIANT vFlags;
511 vFlags.vt = VT_I4;
512 vFlags.intVal = navOpenInNewTab;
513 HRESULT hr = browser->Navigate(targetUrlBstr, &vFlags, NULL, NULL, NULL);
514 if (FAILED(hr))
515 {
516 vFlags.intVal = navOpenInNewWindow;
517
518 hr = browser->Navigate(targetUrlBstr, &vFlags, NULL, NULL, NULL);
519 if (FAILED(hr))
520 {
521 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_NAVIGATION, 0, "Navigation::Failed");
522 return false;
523 }
524 }
525 return true;
526 }
416 } 527 }
417 528
418 void CPluginClass::ShowStatusBar() 529 void CPluginClass::ShowStatusBar()
419 { 530 {
420 DEBUG_GENERAL("ShowStatusBar start"); 531 DEBUG_GENERAL("ShowStatusBar start");
421 532 AnyCurrentSiteBrowser browser;
533 if (!browser)
534 {
535 DEBUG_GENERAL("ShowStatusBar abort; no browser");
536 return;
537 }
422 VARIANT_BOOL isVisible; 538 VARIANT_BOOL isVisible;
423 539 HRESULT hr = browser->get_StatusBar(&isVisible);
424 540 if (FAILED(hr))
425 CComQIPtr<IWebBrowser2> browser = GetAsyncBrowser();
426 if (browser)
427 { 541 {
428 HRESULT hr = S_OK; 542 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_UI, PLUGIN_ERROR_UI_GET_STATUSBAR, "CPlugin Class::ShowStatusBar get_StatusBar");
429 hr = browser->get_StatusBar(&isVisible); 543 return;
430 if (SUCCEEDED(hr))
431 {
432 if (!isVisible)
433 {
434 SHANDLE_PTR pBrowserHWnd;
435 browser->get_HWND((SHANDLE_PTR*)&pBrowserHWnd);
436 Dictionary* dictionary = Dictionary::GetInstance();
437
438 HKEY pHkey;
439 HKEY pHkeySub;
440 LSTATUS regRes = 0;
441 regRes = RegOpenCurrentUser(KEY_WRITE, &pHkey);
442
443 // Do we have enough rights to enable a status bar?
444 if (regRes != 0)
445 {
446 // We use the tab window here and in the next few calls, since the bro wser window may still not be available
447 LRESULT res = MessageBox((HWND)m_hTabWnd,
448 dictionary->Lookup("status-bar", "error-text").c_str(),
449 dictionary->Lookup("status-bar", "error-title").c_str(),
450 MB_OK);
451 return;
452 }
453 // Ask if a user wants to enable a status bar automatically
454 LRESULT res = MessageBox((HWND)m_hTabWnd,
455 dictionary->Lookup("status-bar", "question").c_str(),
456 dictionary->Lookup("status-bar", "title").c_str(),
457 MB_YESNO);
458 if (res == IDYES)
459 {
460 DWORD truth = 1;
461 regRes = RegOpenKey(pHkey, L"Software\\Microsoft\\Internet Explorer\\M INIE", &pHkeySub);
462 regRes = RegSetValueEx(pHkeySub, L"ShowStatusBar", 0, REG_DWORD, (BYTE *)&truth, sizeof(truth));
463 regRes = RegCloseKey(pHkeySub);
464 regRes = RegOpenKey(pHkey, L"Software\\Microsoft\\Internet Explorer\\M ain", &pHkeySub);
465 regRes = RegSetValueEx(pHkeySub, L"StatusBarWeb", 0, REG_DWORD, (BYTE* )&truth, sizeof(truth));
466 regRes = RegCloseKey(pHkeySub);
467 hr = browser->put_StatusBar(TRUE);
468 if (FAILED(hr))
469 {
470 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_UI, PLUGIN_ERROR_UI_PUT_STATUSBAR, "Class::Enable statusbar");
471 }
472 CreateStatusBarPane();
473
474 // We need to restart the tab now, to enable the status bar properly
475 VARIANT vFlags;
476 vFlags.vt = VT_I4;
477 vFlags.intVal = navOpenInNewTab;
478
479 CComBSTR curLoc;
480 browser->get_LocationURL(&curLoc);
481 HRESULT hr = browser->Navigate(curLoc, &vFlags, NULL, NULL, NULL);
482 if (FAILED(hr))
483 {
484 vFlags.intVal = navOpenInNewWindow;
485
486 hr = browser->Navigate(CComBSTR(curLoc), &vFlags, NULL, NULL, NULL);
487 if (FAILED(hr))
488 {
489 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_NAVIGATION, PLUGIN_ERROR_NAVIGATI ON, "Navigation::Failed")
490 }
491 }
492 browser->Quit();
493 }
494 }
495 }
496 else
497 {
498 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_UI, PLUGIN_ERROR_UI_GET_STATUSBAR, "Class ::Get statusbar state");
499 }
500 } 544 }
545 if (!isVisible)
546 {
547 DEBUG_GENERAL("ShowStatusBar end early; browser told us status bar is visibl e");
548 return;
549 }
550 Dictionary* dictionary = Dictionary::GetInstance();
551 /*
552 * Do we have enough rights to enable a status bar?
553 */
554 HKEY pHkey;
555 LSTATUS regRes = RegOpenCurrentUser(KEY_WRITE, &pHkey);
556 if (regRes != 0)
557 {
558 // We use the tab window here and in the next few calls, since the browser w indow may still not be available
559 LRESULT res = MessageBox((HWND)m_hTabWnd,
560 dictionary->Lookup("status-bar", "error-text").c_str(),
561 dictionary->Lookup("status-bar", "error-title").c_str(),
562 MB_OK);
563 DEBUG_GENERAL("ShowStatusBar end early; user must enable status bar");
564 return;
565 }
566 /*
567 * Ask if a user wants to enable a status bar automatically
568 */
569 LRESULT res = MessageBox((HWND)m_hTabWnd,
570 dictionary->Lookup("status-bar", "question").c_str(),
571 dictionary->Lookup("status-bar", "title").c_str(),
572 MB_YESNO);
573 if (res != IDYES)
574 {
575 DEBUG_GENERAL("ShowStatusBar end early; user did not enable status bar");
576 return;
577 }
578 HKEY pHkeySub;
579 DWORD truth = 1;
580 regRes = RegOpenKey(pHkey, L"Software\\Microsoft\\Internet Explorer\\MINIE", & pHkeySub);
581 regRes = RegSetValueEx(pHkeySub, L"ShowStatusBar", 0, REG_DWORD, (BYTE*)&truth , sizeof(truth));
582 regRes = RegCloseKey(pHkeySub);
583 regRes = RegOpenKey(pHkey, L"Software\\Microsoft\\Internet Explorer\\Main", &p HkeySub);
584 regRes = RegSetValueEx(pHkeySub, L"StatusBarWeb", 0, REG_DWORD, (BYTE*)&truth, sizeof(truth));
585 regRes = RegCloseKey(pHkeySub);
586 hr = browser->put_StatusBar(TRUE);
587 if (FAILED(hr))
588 {
589 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_UI, PLUGIN_ERROR_UI_PUT_STATUSBAR, "Class:: Enable statusbar");
590 // Ignore error
591 }
592 CreateStatusBarPane();
593 CComBSTR curLoc;
594 browser->get_LocationURL(&curLoc);
595 std::wstring currentLocation(ToWstring(curLoc));
596 NavigateNewTab(browser, currentLocation);
597 browser->Quit();
501 DEBUG_GENERAL("ShowStatusBar end"); 598 DEBUG_GENERAL("ShowStatusBar end");
502 } 599 }
503 600
504 // Entry point 601 // Entry point
505 void STDMETHODCALLTYPE CPluginClass::OnBeforeNavigate2( 602 void STDMETHODCALLTYPE CPluginClass::OnBeforeNavigate2(
506 IDispatch* frameBrowserDisp /**< [in] */, 603 IDispatch* frameBrowserDisp /**< [in] */,
507 VARIANT* urlVariant /**< [in] */, 604 VARIANT* urlVariant /**< [in] */,
508 VARIANT* /**< [in] Flags*/, 605 VARIANT* /**< [in] Flags*/,
509 VARIANT* /**< [in] TargetFrameName*/, 606 VARIANT* /**< [in] TargetFrameName*/,
510 VARIANT* /**< [in] PostData*/, 607 VARIANT* /**< [in] PostData*/,
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
754 851
755 // IE6 can't be accessed from another thread, execute in current thread 852 // IE6 can't be accessed from another thread, execute in current thread
756 if (ieVersion < 7) 853 if (ieVersion < 7)
757 { 854 {
758 FirstRunThread(); 855 FirstRunThread();
759 } 856 }
760 else 857 else
761 { 858 {
762 CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)CPluginClass::FirstRunThr ead, NULL, NULL, NULL); 859 CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)CPluginClass::FirstRunThr ead, NULL, NULL, NULL);
763 } 860 }
764 if (((m_hPaneWnd == NULL) || !IsStatusBarEnabled()) && isFirstRun) 861 if (((m_hPaneWnd == NULL) || IsStatusBarDisabledInRegistry()) && isFirstRun)
765 { 862 {
766 ShowStatusBar(); 863 ShowStatusBar();
767 } 864 }
768 865
769 // Enable acceptable ads by default 866 // Enable acceptable ads by default
770 std::wstring aaUrl = CPluginClient::GetInstance()->GetPref(L"subscriptions_e xceptionsurl", L""); 867 std::wstring aaUrl = CPluginClient::GetInstance()->GetPref(L"subscriptions_e xceptionsurl", L"");
771 CPluginClient::GetInstance()->AddSubscription(aaUrl); 868 CPluginClient::GetInstance()->AddSubscription(aaUrl);
772 } 869 }
773 s_criticalSectionLocal.Unlock(); 870 s_criticalSectionLocal.Unlock();
774 871
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
812 { 909 {
813 hTabWnd2 = ::FindWindowEx(hTabWnd2, NULL, L"TabWindowClass", NULL); 910 hTabWnd2 = ::FindWindowEx(hTabWnd2, NULL, L"TabWindowClass", NULL);
814 } 911 }
815 912
816 if (hTabWnd2) 913 if (hTabWnd2)
817 { 914 {
818 DWORD nProcessId; 915 DWORD nProcessId;
819 ::GetWindowThreadProcessId(hTabWnd2, &nProcessId); 916 ::GetWindowThreadProcessId(hTabWnd2, &nProcessId);
820 if (::GetCurrentProcessId() == nProcessId) 917 if (::GetCurrentProcessId() == nProcessId)
821 { 918 {
822 bool bExistingTab = false; 919 auto instance = instanceSet.LinearSearch(
823 920 [hTabWnd2](CPluginClass* p)
824 s_criticalSectionLocal.Lock();
825 {
826 for (auto instance : s_instances)
827 { 921 {
828 if (instance->m_hTabWnd == hTabWnd2) 922 return p->m_hTabWnd == hTabWnd2;
829 { 923 });
830 bExistingTab = true; 924 if (!instance)
831 break;
832 }
833 }
834 }
835 s_criticalSectionLocal.Unlock();
836
837 if (!bExistingTab)
838 { 925 {
839 amoundOfNewTabs ++; 926 amoundOfNewTabs ++;
840 uniqueNewTab = hTabWnd2; 927 uniqueNewTab = hTabWnd2;
841 if (GetCurrentThreadId() == GetWindowThreadProcessId(hTabWnd2, NULL) ) 928 if (GetCurrentThreadId() == GetWindowThreadProcessId(hTabWnd2, NULL) )
842 { 929 {
843 hBrowserWnd = hTabWnd = hTabWnd2; 930 hBrowserWnd = hTabWnd = hTabWnd2;
844 break; 931 break;
845 } 932 }
846 933
847 } 934 }
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
940 delete []pData; 1027 delete []pData;
941 } 1028 }
942 1029
943 HDC hdc = GetWindowDC(m_hStatusBarWnd); 1030 HDC hdc = GetWindowDC(m_hStatusBarWnd);
944 SendMessage(m_hStatusBarWnd, WM_PAINT, (WPARAM)hdc, 0); 1031 SendMessage(m_hStatusBarWnd, WM_PAINT, (WPARAM)hdc, 0);
945 ReleaseDC(m_hStatusBarWnd, hdc); 1032 ReleaseDC(m_hStatusBarWnd, hdc);
946 1033
947 return true; 1034 return true;
948 } 1035 }
949 1036
1037 // Entry point
950 void CPluginClass::FirstRunThread() 1038 void CPluginClass::FirstRunThread()
951 { 1039 {
952 // Just return if the First Run Page should be suppressed 1040 try
953 if (CPluginClient::GetInstance()->GetPref(L"suppress_first_run_page", false)) 1041 {
954 return; 1042 // Just return if the First Run Page should be suppressed
1043 if (CPluginClient::GetInstance()->GetPref(L"suppress_first_run_page", false) )
1044 return;
955 1045
956 CoInitialize(NULL); 1046 if (SUCCEEDED(CoInitialize(NULL)))
957 VARIANT vFlags; 1047 {
958 vFlags.vt = VT_I4; 1048 AnyCurrentSiteBrowser browser;
959 vFlags.intVal = navOpenInNewTab; 1049 if (browser)
960 1050 {
961 CComBSTR navigatePath = CComBSTR(FirstRunPageFileUrl().c_str()); 1051 NavigateNewTab(browser, FirstRunPageFileUrl());
962 1052 }
963 HRESULT hr = GetAsyncBrowser()->Navigate(navigatePath, &vFlags, NULL, NULL, NU LL); 1053 }
964 if (FAILED(hr)) 1054 CoUninitialize();
1055 }
1056 catch (...)
965 { 1057 {
966 vFlags.intVal = navOpenInNewWindow; 1058 // Suppress errors
967 hr = GetAsyncBrowser()->Navigate(navigatePath, &vFlags, NULL, NULL, NULL);
968 }
969
970 if (FAILED(hr))
971 {
972 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_NAVIGATION, PLUGIN_ERROR_NAVIGATION_WELCOME , "Navigation::Welcome page failed")
973 } 1059 }
974 } 1060 }
1061
975 void CPluginClass::CloseTheme() 1062 void CPluginClass::CloseTheme()
976 { 1063 {
977 if (m_hTheme) 1064 if (m_hTheme)
978 { 1065 {
979 if (pfnClose) 1066 if (pfnClose)
980 { 1067 {
981 pfnClose(m_hTheme); 1068 pfnClose(m_hTheme);
982 } 1069 }
983 1070
984 m_hTheme = NULL; 1071 m_hTheme = NULL;
985 } 1072 }
986 } 1073 }
987 1074
988 void CPluginClass::UpdateTheme() 1075 void CPluginClass::UpdateTheme()
989 { 1076 {
990 CloseTheme(); 1077 CloseTheme();
991 1078
992 if (pfnOpenThemeData) 1079 if (pfnOpenThemeData)
993 { 1080 {
994 m_hTheme = pfnOpenThemeData(m_hPaneWnd, L"STATUS"); 1081 m_hTheme = pfnOpenThemeData(m_hPaneWnd, L"STATUS");
995 if (!m_hTheme) 1082 if (!m_hTheme)
996 { 1083 {
997 } 1084 }
998 } 1085 }
999 } 1086 }
1000 1087
1001
1002 CPluginClass* CPluginClass::FindInstance(HWND hStatusBarWnd) 1088 CPluginClass* CPluginClass::FindInstance(HWND hStatusBarWnd)
1003 { 1089 {
1004 CPluginClass* result = nullptr; 1090 return instanceSet.LinearSearch(
1005 1091 [hStatusBarWnd](CPluginClass* p) -> bool
1006 s_criticalSectionLocal.Lock();
1007 {
1008 for (auto instance : s_instances)
1009 { 1092 {
1010 if (instance->m_hStatusBarWnd == hStatusBarWnd) 1093 return p->m_hStatusBarWnd == hStatusBarWnd;
1011 { 1094 });
1012 result = instance;
1013 break;
1014 }
1015 }
1016 }
1017 s_criticalSectionLocal.Unlock();
1018
1019 return result;
1020 } 1095 }
1021 1096
1022 CPluginTab* CPluginClass::GetTab() 1097 CPluginTab* CPluginClass::GetTab()
1023 { 1098 {
1024 return m_tab; 1099 return m_tab;
1025 } 1100 }
1026 1101
1027 CPluginTab* CPluginClass::GetTabForCurrentThread() 1102 CPluginTab* CPluginClass::GetTabForCurrentThread()
1028 { 1103 {
1029 auto p = threadMap.Locate(); 1104 auto p = threadMap.Locate();
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
1123 s_mimeFilter = NULL; 1198 s_mimeFilter = NULL;
1124 1199
1125 CPluginClientFactory::ReleaseMimeFilterClientInstance(); 1200 CPluginClientFactory::ReleaseMimeFilterClientInstance();
1126 } 1201 }
1127 } 1202 }
1128 s_criticalSectionLocal.Unlock(); 1203 s_criticalSectionLocal.Unlock();
1129 } 1204 }
1130 break; 1205 break;
1131 case ID_MENU_SETTINGS: 1206 case ID_MENU_SETTINGS:
1132 { 1207 {
1133 CComQIPtr<IWebBrowser2> browser = GetAsyncBrowser(); 1208 AnyCurrentSiteBrowser browser;
1134 if (browser) 1209 if (browser)
1135 { 1210 {
1136 VARIANT vFlags; 1211 NavigateNewTab(browser, UserSettingsFileUrl());
1137 vFlags.vt = VT_I4;
1138 vFlags.intVal = navOpenInNewTab;
1139
1140 auto userSettingsFileUrl = UserSettingsFileUrl();
1141 ATL::CComBSTR urlToNavigate(static_cast<int>(userSettingsFileUrl.length( )), userSettingsFileUrl.c_str());
1142 HRESULT hr = browser->Navigate(urlToNavigate, &vFlags, NULL, NULL, NULL) ;
1143 if (FAILED(hr))
1144 {
1145 vFlags.intVal = navOpenInNewWindow;
1146
1147 hr = browser->Navigate(urlToNavigate, &vFlags, NULL, NULL, NULL);
1148 if (FAILED(hr))
1149 {
1150 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_NAVIGATION, PLUGIN_ERROR_NAVIGATION _SETTINGS, "Navigation::Failed")
1151 }
1152 }
1153 } 1212 }
1154 break;
1155 } 1213 }
1214 break;
1156 case ID_MENU_DISABLE_ON_SITE: 1215 case ID_MENU_DISABLE_ON_SITE:
1157 { 1216 {
1158 std::wstring urlString = GetTab()->GetDocumentUrl(); 1217 std::wstring urlString = GetTab()->GetDocumentUrl();
1159 std::string filterText = client->GetWhitelistingFilter(urlString); 1218 std::string filterText = client->GetWhitelistingFilter(urlString);
1160 if (!filterText.empty()) 1219 if (!filterText.empty())
1161 { 1220 {
1162 client->RemoveFilter(filterText); 1221 client->RemoveFilter(filterText);
1163 } 1222 }
1164 else 1223 else
1165 { 1224 {
(...skipping 562 matching lines...) Expand 10 before | Expand all | Expand 10 after
1728 s_criticalSectionLocal.Unlock(); 1787 s_criticalSectionLocal.Unlock();
1729 1788
1730 return icon; 1789 return icon;
1731 } 1790 }
1732 1791
1733 ATOM CPluginClass::GetAtomPaneClass() 1792 ATOM CPluginClass::GetAtomPaneClass()
1734 { 1793 {
1735 return s_atomPaneClass; 1794 return s_atomPaneClass;
1736 } 1795 }
1737 1796
OLDNEW
« no previous file with comments | « src/plugin/PluginClass.h ('k') | test/plugin/InstancesTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld