Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5495)

Unified Diff: chrome_frame/buggy_bho_handling.cc

Issue 6493002: A number of poorly written IE BHO's crash IE if ChromeFrame is the currently ... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome_frame/buggy_bho_handling.cc
===================================================================
--- chrome_frame/buggy_bho_handling.cc (revision 74374)
+++ chrome_frame/buggy_bho_handling.cc (working copy)
@@ -75,30 +75,101 @@
return false;
}
-BuggyBhoTls::BuggyBhoTls() : previous_instance_(s_bad_object_tls_.Get()) {
+BuggyBhoTls::BuggyBhoTls() {
+ DCHECK(BuggyBhoTls::GetInstance() == NULL);
tommi (sloooow) - chröme 2011/02/11 19:34:15 lint will probably ask you to use DCHECK_EQ here a
ananta 2011/02/11 21:19:35 DCHECK_EQ would need a reintepret_cast. I left thi
s_bad_object_tls_.Set(this);
}
BuggyBhoTls::~BuggyBhoTls() {
- DCHECK(FromCurrentThread() == this);
- s_bad_object_tls_.Set(previous_instance_);
+ DCHECK(BuggyBhoTls::GetInstance() == this);
+ s_bad_object_tls_.Set(NULL);
}
void BuggyBhoTls::AddBuggyObject(IDispatch* obj) {
bad_objects_.push_back(obj);
}
-bool BuggyBhoTls::IsBuggyObject(IDispatch* obj) const {
- return std::find(bad_objects_.begin(), bad_objects_.end(), obj) !=
- bad_objects_.end();
+bool BuggyBhoTls::ShouldSkipInvoke(IDispatch* obj) const {
+ DCHECK(web_browser2_ != NULL);
+ if (IsChromeFrameDocument(web_browser2_)) {
+ return std::find(bad_objects_.begin(), bad_objects_.end(), obj) !=
+ bad_objects_.end();
+ }
+ return false;
}
// static
-BuggyBhoTls* BuggyBhoTls::FromCurrentThread() {
- return s_bad_object_tls_.Get();
+BuggyBhoTls* BuggyBhoTls::GetInstance() {
+ BuggyBhoTls* tls_instance = s_bad_object_tls_.Get();
+ if (!tls_instance) {
+ tls_instance = new BuggyBhoTls();
+ DCHECK(s_bad_object_tls_.Get() != NULL);
+ }
+ return tls_instance;
}
// static
+void BuggyBhoTls::DestroyInstance() {
+ BuggyBhoTls* tls_instance = s_bad_object_tls_.Get();
+ if (tls_instance) {
+ delete tls_instance;
tommi (sloooow) - chröme 2011/02/11 19:34:15 also set s_bad_object_tls to NULL
ananta 2011/02/11 21:19:35 That happens in the destructor. Added a DCHECK aft
+ }
+}
+
+HRESULT BuggyBhoTls::PatchBuggyBHOs(IWebBrowser2* browser) {
+ DCHECK(browser);
tommi (sloooow) - chröme 2011/02/11 19:34:15 should we also dcheck that web_browser2_ is NULL?
ananta 2011/02/11 21:19:35 Done.
+
+ ScopedComPtr<IConnectionPointContainer> cpc;
+ HRESULT hr = cpc.QueryFrom(browser);
+ if (SUCCEEDED(hr)) {
+ const GUID sinks[] = { DIID_DWebBrowserEvents2, DIID_DWebBrowserEvents };
+ for (size_t i = 0; i < arraysize(sinks); ++i) {
+ ScopedComPtr<IConnectionPoint> cp;
+ cpc->FindConnectionPoint(sinks[i], cp.Receive());
+ if (cp) {
+ ScopedComPtr<IEnumConnections> connections;
+ cp->EnumConnections(connections.Receive());
+ if (connections) {
+ CONNECTDATA cd = {0};
+ DWORD fetched = 0;
+ while (connections->Next(1, &cd, &fetched) == S_OK && fetched) {
+ PatchIfBuggy(&cd, sinks[i]);
+ cd.pUnk->Release();
+ fetched = 0;
+ }
+ }
+ }
+ }
+ }
+ web_browser2_ = browser;
+ return hr;
+}
+
+bool BuggyBhoTls::PatchIfBuggy(CONNECTDATA* cd, const IID& diid) {
amit 2011/02/11 19:49:40 nit: why not pass cd->punk directly?
ananta 2011/02/11 21:19:35 Done.
+ DCHECK(cd);
+ PROC* methods = *reinterpret_cast<PROC**>(cd->pUnk);
+ HMODULE mod = GetModuleFromAddress(methods[0]);
+ if (!IsBuggyBho(mod))
+ return false;
+
+ ScopedComPtr<IDispatch> disp;
+ HRESULT hr = cd->pUnk->QueryInterface(diid,
+ reinterpret_cast<void**>(disp.Receive()));
+ if (FAILED(hr)) // Sometimes only IDispatch QI is supported
+ hr = disp.QueryFrom(cd->pUnk);
+ DCHECK(SUCCEEDED(hr));
+
+ if (SUCCEEDED(hr)) {
+ const int kInvokeIndex = 6;
+ DCHECK(static_cast<IUnknown*>(disp) == cd->pUnk);
+ if (SUCCEEDED(PatchInvokeMethod(&methods[kInvokeIndex]))) {
+ AddBuggyObject(disp);
+ }
+ }
+ return false;
+}
+
+// static
STDMETHODIMP BuggyBhoTls::BuggyBhoInvoke(InvokeFunc original, IDispatch* me,
DISPID dispid, REFIID riid, LCID lcid,
WORD flags, DISPPARAMS* params,
@@ -106,8 +177,10 @@
UINT* err) {
DVLOG(1) << __FUNCTION__;
- const BuggyBhoTls* tls = BuggyBhoTls::FromCurrentThread();
- if (tls && tls->IsBuggyObject(me)) {
+ DCHECK(BuggyBhoTls::GetInstance())
+ << "You must first have an instance of BuggyBhoTls on this thread";
+ if (BuggyBhoTls::GetInstance() &&
amit 2011/02/11 19:49:40 Maybe we can avoid the TLS altogether with followi
+ BuggyBhoTls::GetInstance()->ShouldSkipInvoke(me)) {
// Ignore this call and avoid the bug.
// TODO(tommi): Maybe we should check a specific list of DISPIDs too?
return S_OK;
@@ -147,72 +220,8 @@
::FlushInstructionCache(::GetCurrentProcess(), invoke, sizeof(PROC));
}
}
-
::VirtualProtect(invoke, sizeof(PROC), flags, &flags);
-
return hr;
}
-// static
-bool BuggyBhoTls::PatchIfBuggy(CONNECTDATA* cd, const IID& diid) {
- DCHECK(cd);
- PROC* methods = *reinterpret_cast<PROC**>(cd->pUnk);
- HMODULE mod = GetModuleFromAddress(methods[0]);
- if (!IsBuggyBho(mod))
- return false;
-
- ScopedComPtr<IDispatch> disp;
- HRESULT hr = cd->pUnk->QueryInterface(diid,
- reinterpret_cast<void**>(disp.Receive()));
- if (FAILED(hr)) // Sometimes only IDispatch QI is supported
- hr = disp.QueryFrom(cd->pUnk);
- DCHECK(SUCCEEDED(hr));
-
- if (SUCCEEDED(hr)) {
- const int kInvokeIndex = 6;
- DCHECK(static_cast<IUnknown*>(disp) == cd->pUnk);
- if (SUCCEEDED(PatchInvokeMethod(&methods[kInvokeIndex]))) {
- BuggyBhoTls* tls = BuggyBhoTls::FromCurrentThread();
- DCHECK(tls);
- if (tls) {
- tls->AddBuggyObject(disp);
- }
- }
- }
-
- return false;
-}
-
-// static
-HRESULT BuggyBhoTls::PatchBuggyBHOs(IWebBrowser2* browser) {
- DCHECK(browser);
- DCHECK(BuggyBhoTls::FromCurrentThread())
- << "You must first have an instance of BuggyBhoTls on this thread";
-
- ScopedComPtr<IConnectionPointContainer> cpc;
- HRESULT hr = cpc.QueryFrom(browser);
- if (SUCCEEDED(hr)) {
- const GUID sinks[] = { DIID_DWebBrowserEvents2, DIID_DWebBrowserEvents };
- for (size_t i = 0; i < arraysize(sinks); ++i) {
- ScopedComPtr<IConnectionPoint> cp;
- cpc->FindConnectionPoint(sinks[i], cp.Receive());
- if (cp) {
- ScopedComPtr<IEnumConnections> connections;
- cp->EnumConnections(connections.Receive());
- if (connections) {
- CONNECTDATA cd = {0};
- DWORD fetched = 0;
- while (connections->Next(1, &cd, &fetched) == S_OK && fetched) {
- PatchIfBuggy(&cd, sinks[i]);
- cd.pUnk->Release();
- fetched = 0;
- }
- }
- }
- }
- }
-
- return hr;
-}
-
} // end namespace buggy_bho

Powered by Google App Engine
This is Rietveld 408576698