OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |