summaryrefslogtreecommitdiffstats
path: root/chrome_frame
diff options
context:
space:
mode:
Diffstat (limited to 'chrome_frame')
-rw-r--r--chrome_frame/chrome_active_document.cc74
-rw-r--r--chrome_frame/chrome_active_document.h35
-rw-r--r--chrome_frame/test/util_unittests.cc10
-rw-r--r--chrome_frame/utils.cc23
-rw-r--r--chrome_frame/utils.h7
5 files changed, 128 insertions, 21 deletions
diff --git a/chrome_frame/chrome_active_document.cc b/chrome_frame/chrome_active_document.cc
index fc896a0..bd8d7a4 100644
--- a/chrome_frame/chrome_active_document.cc
+++ b/chrome_frame/chrome_active_document.cc
@@ -18,6 +18,7 @@
#include "base/command_line.h"
#include "base/file_util.h"
+#include "base/file_version_info.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/process_util.h"
@@ -432,7 +433,7 @@ STDMETHODIMP ChromeActiveDocument::Reset() {
return S_OK;
}
-STDMETHODIMP ChromeActiveDocument::GetSize(unsigned long* size) {
+STDMETHODIMP ChromeActiveDocument::GetSize(DWORD* size) {
if (!size)
return E_POINTER;
@@ -449,7 +450,7 @@ STDMETHODIMP ChromeActiveDocument::GetPrivacyImpacted(BOOL* privacy_impacted) {
}
STDMETHODIMP ChromeActiveDocument::Next(BSTR* url, BSTR* policy,
- long* reserved, unsigned long* flags) {
+ LONG* reserved, DWORD* flags) {
if (!url || !policy || !flags)
return E_POINTER;
@@ -754,10 +755,12 @@ void ChromeActiveDocument::UpdateNavigationState(
// Now call the FireNavigateCompleteEvent which makes IE update the text
// in the address-bar.
doc_object_svc->FireNavigateComplete2(this, 0);
- doc_object_svc->FireDocumentComplete(this, 0);
+ if (ShouldFireDocumentComplete())
+ doc_object_svc->FireDocumentComplete(this, 0);
} else if (web_browser_events_svc) {
web_browser_events_svc->FireNavigateComplete2Event();
- web_browser_events_svc->FireDocumentCompleteEvent();
+ if (ShouldFireDocumentComplete())
+ web_browser_events_svc->FireDocumentCompleteEvent();
}
}
@@ -916,8 +919,8 @@ HRESULT ChromeActiveDocument::IEExec(const GUID* cmd_group_guid,
return hr;
}
-unsigned long ChromeActiveDocument::MapUrlToZone(const wchar_t* url) {
- unsigned long zone = URLZONE_INVALID;
+DWORD ChromeActiveDocument::MapUrlToZone(const wchar_t* url) {
+ DWORD zone = URLZONE_INVALID;
if (security_manager_.get() == NULL) {
HRESULT hr = CoCreateInstance(
CLSID_InternetSecurityManager,
@@ -1251,3 +1254,62 @@ LRESULT ChromeActiveDocument::OnFirePrivacyChange(UINT message, WPARAM wparam,
NOTREACHED() << "Failed to retrieve IWebBrowser2 interface.";
return 0;
}
+
+namespace {
+struct ModuleAndVersion {
+ const char* module_name_;
+ const uint32 major_version_;
+ const uint32 minor_version_;
+};
+} // end namespace
+
+// static
+bool ChromeActiveDocument::ShouldFireDocumentComplete() {
+ typedef enum ModuleCheckResult {
+ CHECK_NOT_DONE,
+ DOCUMENT_COMPLETE_OK,
+ DOCUMENT_COMPLETE_NOT_OK
+ };
+
+ static ModuleCheckResult results = CHECK_NOT_DONE;
+
+ if (results == CHECK_NOT_DONE) {
+ // These modules are missing some checks in their DocumentComplete
+ // implementation that causes a crash.
+ static const ModuleAndVersion buggy_modules[] = {
+ { "askbar.dll", 4, 1 }, // biggest troublemaker: 4.1.0.5.
+ { "gbieh.dll", 3, 8 }, // biggest troublemaker: 3.8.14.12
+ { "gbiehcef.dll", 3, 8 }, // biggest troublemaker: 3.8.11.23
+ };
+
+ for (size_t i = 0; results == CHECK_NOT_DONE &&
+ i < arraysize(buggy_modules); ++i) {
+ const ModuleAndVersion& module = buggy_modules[i];
+ HMODULE mod = ::GetModuleHandleA(module.module_name_);
+ if (mod) {
+ wchar_t path[MAX_PATH * 2] = {0};
+ ::GetModuleFileNameW(mod, path, arraysize(path));
+ scoped_ptr<FileVersionInfo> version_info(
+ FileVersionInfo::CreateFileVersionInfo(FilePath(path)));
+ DCHECK(version_info.get());
+ if (version_info.get()) {
+ uint32 major = 0, minor = 0;
+ if (!ParseVersion(version_info->file_version(), &major, &minor))
+ ParseVersion(version_info->product_version(), &major, &minor);
+ if (major < module.major_version_ ||
+ (major == module.major_version_ &&
+ minor <= module.minor_version_)) {
+ DLOG(WARNING) << "Buggy module found: " << module.module_name_;
+ results = DOCUMENT_COMPLETE_NOT_OK;
+ }
+ }
+ }
+ }
+
+ if (results == CHECK_NOT_DONE)
+ results = DOCUMENT_COMPLETE_OK;
+ }
+
+ return results == DOCUMENT_COMPLETE_OK;
+}
+
diff --git a/chrome_frame/chrome_active_document.h b/chrome_frame/chrome_active_document.h
index 1360ff1..6bd8e4d 100644
--- a/chrome_frame/chrome_active_document.h
+++ b/chrome_frame/chrome_active_document.h
@@ -9,10 +9,11 @@
#include <atlcom.h>
#include <atlctl.h>
#include <htiframe.h>
-#include <map>
#include <mshtmcid.h>
#include <perhist.h>
+#include <map>
+
#include "base/scoped_ptr.h"
#include "base/scoped_comptr_win.h"
#include "base/thread.h"
@@ -130,16 +131,16 @@ extern const DWORD kIEEncodingIdArray[];
// This macro should be defined in the public section of the class.
#define BEGIN_EXEC_COMMAND_MAP(theClass) \
- public: \
- HRESULT ProcessExecCommand(const GUID* cmd_group_guid, DWORD command_id, \
- DWORD cmd_exec_opt, VARIANT* in_args, \
- VARIANT* out_args) { \
- HRESULT hr = OLECMDERR_E_NOTSUPPORTED; \
- do {
+ public: \
+ HRESULT ProcessExecCommand(const GUID* cmd_group_guid, DWORD command_id, \
+ DWORD cmd_exec_opt, VARIANT* in_args, \
+ VARIANT* out_args) { \
+ HRESULT hr = OLECMDERR_E_NOTSUPPORTED; \
+ do {
#define EXEC_COMMAND_HANDLER(group, id, handler) \
if ((id == command_id) && ((group != NULL && cmd_group_guid != NULL && \
- IsEqualGUID(*(GUID*)group,*cmd_group_guid)) || \
+ IsEqualGUID(*reinterpret_cast<const GUID*>(group), *cmd_group_guid)) || \
(group == NULL && cmd_group_guid == NULL))) { \
hr = S_OK; \
handler(cmd_group_guid, command_id, cmd_exec_opt, in_args, out_args); \
@@ -148,7 +149,7 @@ extern const DWORD kIEEncodingIdArray[];
#define EXEC_COMMAND_HANDLER_NO_ARGS(group, id, handler) \
if ((id == command_id) && ((group != NULL && cmd_group_guid != NULL && \
- IsEqualGUID(*(GUID*)group,*cmd_group_guid)) || \
+ IsEqualGUID(*reinterpret_cast<const GUID*>(group), *cmd_group_guid)) || \
(group == NULL && cmd_group_guid == NULL))) { \
hr = S_OK; \
handler(); \
@@ -157,7 +158,7 @@ extern const DWORD kIEEncodingIdArray[];
#define EXEC_COMMAND_HANDLER_GENERIC(group, id, code) \
if ((id == command_id) && ((group != NULL && cmd_group_guid != NULL && \
- IsEqualGUID(*(GUID*)group,*cmd_group_guid)) || \
+ IsEqualGUID(*reinterpret_cast<const GUID*>(group), *cmd_group_guid)) || \
(group == NULL && cmd_group_guid == NULL))) { \
hr = S_OK; \
code; \
@@ -176,7 +177,8 @@ extern const DWORD kIEEncodingIdArray[];
commands++; \
} \
if (id_in_group_commands && ((group != NULL && cmd_group_guid != NULL && \
- IsEqualGUID(*(GUID*)group,*cmd_group_guid)) || \
+ IsEqualGUID(*reinterpret_cast<const GUID*>(group), \
+ *cmd_group_guid)) || \
(group == NULL && cmd_group_guid == NULL))) { \
hr = S_OK; \
handler(cmd_group_guid, command_id, cmd_exec_opt, in_args, out_args); \
@@ -343,10 +345,9 @@ END_EXEC_COMMAND_MAP()
// IEnumPrivacyRecords
STDMETHOD(Reset)();
- STDMETHOD(GetSize)(unsigned long* size);
+ STDMETHOD(GetSize)(ULONG* size);
STDMETHOD(GetPrivacyImpacted)(BOOL* privacy_impacted);
- STDMETHOD(Next)(BSTR* url, BSTR* policy, long* reserved,
- unsigned long* flags);
+ STDMETHOD(Next)(BSTR* url, BSTR* policy, LONG* reserved, DWORD* flags);
protected:
// ChromeFrameActivexBase overrides
@@ -379,7 +380,7 @@ END_EXEC_COMMAND_MAP()
HRESULT IEExec(const GUID* cmd_group_guid, DWORD command_id,
DWORD cmd_exec_opt, VARIANT* in_args, VARIANT* out_args);
- unsigned long MapUrlToZone(const wchar_t* url);
+ DWORD MapUrlToZone(const wchar_t* url);
// Parses the URL and returns information whether it is a new navigation and
// the actual url after stripping out the cf: prefix if any.
@@ -421,6 +422,10 @@ END_EXEC_COMMAND_MAP()
LRESULT OnFirePrivacyChange(UINT message, WPARAM wparam, LPARAM lparam,
BOOL& handled);
+ // Checks for the presence of known-to-be-buggy BHOs. If we find any
+ // we do not fire the DocumentComplete event to avoid a crash.
+ static bool ShouldFireDocumentComplete();
+
protected:
typedef std::map<int, bool> EnabledCommandsMap;
diff --git a/chrome_frame/test/util_unittests.cc b/chrome_frame/test/util_unittests.cc
index 0187f5d..cedff5d 100644
--- a/chrome_frame/test/util_unittests.cc
+++ b/chrome_frame/test/util_unittests.cc
@@ -137,3 +137,13 @@ TEST(UtilTests, ParseAttachTabUrlTest) {
&disposition));
}
+TEST(UtilTests, ParseVersionTest) {
+ uint32 high = 0, low = 0;
+ EXPECT_FALSE(ParseVersion(L"", &high, &low));
+ EXPECT_TRUE(ParseVersion(L"1", &high, &low) && high == 1 && low == 0);
+ EXPECT_TRUE(ParseVersion(L"1.", &high, &low) && high == 1 && low == 0);
+ EXPECT_TRUE(ParseVersion(L"1.2", &high, &low) && high == 1 && low == 2);
+ EXPECT_TRUE(ParseVersion(L"1.2.3.4", &high, &low) && high == 1 && low == 2);
+ EXPECT_TRUE(ParseVersion(L"10.20", &high, &low) && high == 10 && low == 20);
+}
+
diff --git a/chrome_frame/utils.cc b/chrome_frame/utils.cc
index a864200..6a9d0a2 100644
--- a/chrome_frame/utils.cc
+++ b/chrome_frame/utils.cc
@@ -534,6 +534,29 @@ bool GetModuleVersion(HMODULE module, uint32* high, uint32* low) {
return ok;
}
+bool ParseVersion(const std::wstring& version, uint32* high, uint32* low) {
+ DCHECK(high);
+ if (!isdigit(version[0]))
+ return false;
+
+ *high = _wtoi(version.c_str());
+ if (low) {
+ *low = 0;
+ size_t i = version.find(L'.');
+ if (i != std::wstring::npos) {
+ *low = _wtoi(version.c_str() + i + 1);
+ }
+ }
+
+ return true;
+}
+
+HMODULE GetModuleFromAddress(void* address) {
+ MEMORY_BASIC_INFORMATION info = {0};
+ ::VirtualQuery(address, &info, sizeof(info));
+ return reinterpret_cast<HMODULE>(info.AllocationBase);
+}
+
namespace {
const int kMaxSubmenuDepth = 10;
diff --git a/chrome_frame/utils.h b/chrome_frame/utils.h
index 11b050d..5561331 100644
--- a/chrome_frame/utils.h
+++ b/chrome_frame/utils.h
@@ -189,6 +189,13 @@ FilePath GetIETemporaryFilesFolder();
// @returns true if the version info was successfully retrieved.
bool GetModuleVersion(HMODULE module, uint32* high, uint32* low);
+// Parses a version string and returns the major, minor versions or 0 if not
+// present in the string. The rest of the version string is ignored.
+bool ParseVersion(const std::wstring& version, uint32* high, uint32* low);
+
+// @returns the module handle to which an address belongs.
+HMODULE GetModuleFromAddress(void* address);
+
// Return if the IEXPLORE is in private mode. The IEIsInPrivateBrowsing() checks
// whether current process is IEXPLORE.
bool IsIEInPrivate();