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

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
« no previous file with comments | « chrome_frame/buggy_bho_handling.h ('k') | chrome_frame/chrome_active_document.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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,108 @@
return false;
}
-BuggyBhoTls::BuggyBhoTls() : previous_instance_(s_bad_object_tls_.Get()) {
+BuggyBhoTls::BuggyBhoTls()
+ : patched_(false) {
+ DCHECK(s_bad_object_tls_.Get() == NULL);
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;
+ DCHECK(s_bad_object_tls_.Get() == NULL);
+ }
+}
+
+HRESULT BuggyBhoTls::PatchBuggyBHOs(IWebBrowser2* browser) {
+ if (patched_)
+ return S_FALSE;
+
+ DCHECK(browser);
+ DCHECK(web_browser2_ == NULL);
+
+ 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.pUnk, sinks[i]);
+ cd.pUnk->Release();
+ fetched = 0;
+ }
+ }
+ }
+ }
+ }
+ patched_ = true;
+ web_browser2_ = browser;
+ return hr;
+}
+
+bool BuggyBhoTls::PatchIfBuggy(IUnknown* unk, const IID& diid) {
+ DCHECK(unk);
+ PROC* methods = *reinterpret_cast<PROC**>(unk);
+ HMODULE mod = GetModuleFromAddress(methods[0]);
+ if (!IsBuggyBho(mod))
+ return false;
+
+ ScopedComPtr<IDispatch> disp;
+ HRESULT hr = unk->QueryInterface(diid,
+ reinterpret_cast<void**>(disp.Receive()));
+ if (FAILED(hr)) // Sometimes only IDispatch QI is supported
+ hr = disp.QueryFrom(unk);
+ DCHECK(SUCCEEDED(hr));
+
+ if (SUCCEEDED(hr)) {
+ const int kInvokeIndex = 6;
+ DCHECK(static_cast<IUnknown*>(disp) == unk);
+ 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 +184,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() &&
+ 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 +227,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
« no previous file with comments | « chrome_frame/buggy_bho_handling.h ('k') | chrome_frame/chrome_active_document.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698