summaryrefslogtreecommitdiffstats
path: root/chrome_frame/test
diff options
context:
space:
mode:
authorrobertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-14 20:03:23 +0000
committerrobertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-14 20:03:23 +0000
commit8adbf7e5d0af7fec5d3fde8d472716739d3183fc (patch)
treec4210f0d8e9c01ad49cbe48f8c4fcaa56fa9d891 /chrome_frame/test
parentd17054237974d50db49c10d18a05a42048478db7 (diff)
downloadchromium_src-8adbf7e5d0af7fec5d3fde8d472716739d3183fc.zip
chromium_src-8adbf7e5d0af7fec5d3fde8d472716739d3183fc.tar.gz
chromium_src-8adbf7e5d0af7fec5d3fde8d472716739d3183fc.tar.bz2
Recommit of the ill-fated r44474, this time with new compiling goodness.
Add multi-version delegation to Chrome Frame such that CF will scan for older versions on load and delegate to them. This is to support clean upgrade scenarios whereby a new version is registered while IE is running. BUG=40117 TEST=Register a new CF version while an old one is loaded in IE. Open a few new tabs and observe nothing bad happening. TBR=tommi Review URL: http://codereview.chromium.org/1585037 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@44522 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame/test')
-rw-r--r--chrome_frame/test/data/test_dlls/1/TestDll.dllbin0 -> 12800 bytes
-rw-r--r--chrome_frame/test/data/test_dlls/2/TestDll.dllbin0 -> 12800 bytes
-rw-r--r--chrome_frame/test/data/test_dlls/3/TestDll.dllbin0 -> 12800 bytes
-rw-r--r--chrome_frame/test/data/test_dlls/DummyCF/npchrome_frame.dllbin0 -> 12800 bytes
-rw-r--r--chrome_frame/test/data/test_dlls/README7
-rw-r--r--chrome_frame/test/data/test_dlls/TestDllNoCF/TestDll.dllbin0 -> 7680 bytes
-rw-r--r--chrome_frame/test/module_utils_unittest.cc196
7 files changed, 203 insertions, 0 deletions
diff --git a/chrome_frame/test/data/test_dlls/1/TestDll.dll b/chrome_frame/test/data/test_dlls/1/TestDll.dll
new file mode 100644
index 0000000..9658de1
--- /dev/null
+++ b/chrome_frame/test/data/test_dlls/1/TestDll.dll
Binary files differ
diff --git a/chrome_frame/test/data/test_dlls/2/TestDll.dll b/chrome_frame/test/data/test_dlls/2/TestDll.dll
new file mode 100644
index 0000000..9501cac
--- /dev/null
+++ b/chrome_frame/test/data/test_dlls/2/TestDll.dll
Binary files differ
diff --git a/chrome_frame/test/data/test_dlls/3/TestDll.dll b/chrome_frame/test/data/test_dlls/3/TestDll.dll
new file mode 100644
index 0000000..007ba36
--- /dev/null
+++ b/chrome_frame/test/data/test_dlls/3/TestDll.dll
Binary files differ
diff --git a/chrome_frame/test/data/test_dlls/DummyCF/npchrome_frame.dll b/chrome_frame/test/data/test_dlls/DummyCF/npchrome_frame.dll
new file mode 100644
index 0000000..a616fcc
--- /dev/null
+++ b/chrome_frame/test/data/test_dlls/DummyCF/npchrome_frame.dll
Binary files differ
diff --git a/chrome_frame/test/data/test_dlls/README b/chrome_frame/test/data/test_dlls/README
new file mode 100644
index 0000000..5db353c
--- /dev/null
+++ b/chrome_frame/test/data/test_dlls/README
@@ -0,0 +1,7 @@
+This directory contains dummy DLLs intended to support testing of the module
+scanning code currently in Chrome Frame (in module_utils.cc at time of writing).
+
+The DLLs contain no code of mention and export a DllGetClassObject function.
+The only main difference between them is that they have different version
+numbers in the FileVersion and ProductVersion fields of their
+VS_VERSION_INFO resources. \ No newline at end of file
diff --git a/chrome_frame/test/data/test_dlls/TestDllNoCF/TestDll.dll b/chrome_frame/test/data/test_dlls/TestDllNoCF/TestDll.dll
new file mode 100644
index 0000000..cbdffcc
--- /dev/null
+++ b/chrome_frame/test/data/test_dlls/TestDllNoCF/TestDll.dll
Binary files differ
diff --git a/chrome_frame/test/module_utils_unittest.cc b/chrome_frame/test/module_utils_unittest.cc
new file mode 100644
index 0000000..88d52f7
--- /dev/null
+++ b/chrome_frame/test/module_utils_unittest.cc
@@ -0,0 +1,196 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This test requires loading a set of DLLs from the chrome_frame\test\data
+// directory into the process and then inspecting them. As such, it is
+// part of chrome_frame_tests.exe and not chrome_frame_unittests.exe which
+// needs to run as a standalone test. No test is an island except for
+// chrome_frame_unittests.exe.
+
+#include "chrome_frame/module_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#include "base/logging.h"
+#include "base/file_path.h"
+#include "base/path_service.h"
+#include "chrome_frame/test_utils.h"
+
+#include "chrome_tab.h" // NOLINT
+
+class ModuleUtilsTest : public testing::Test {
+ protected:
+ // Constructor
+ ModuleUtilsTest() {}
+
+ // Returns the full path to the test DLL given a name.
+ virtual bool GetDllPath(const std::wstring& dll_name, std::wstring* path) {
+ if (!path) {
+ return false;
+ }
+
+ FilePath test_path;
+ if (!PathService::Get(base::DIR_SOURCE_ROOT, &test_path)) {
+ return false;
+ }
+
+ test_path = test_path.Append(L"chrome_frame")
+ .Append(L"test")
+ .Append(L"data")
+ .Append(L"test_dlls")
+ .Append(FilePath(dll_name));
+
+ *path = test_path.value();
+ return true;
+ }
+
+ // Loads the CF Dll and returns its path in |cf_dll_path|.
+ virtual bool LoadChromeFrameDll(std::wstring* cf_dll_path) {
+ DCHECK(cf_dll_path);
+ // Look for the CF dll in both the current directory and in servers.
+ FilePath dll_path = ScopedChromeFrameRegistrar::GetChromeFrameBuildPath();
+
+ bool success = false;
+ if (!dll_path.empty()) {
+ cf_dll_path_ = dll_path.value();
+ HMODULE handle = LoadLibrary(cf_dll_path_.c_str());
+ if (handle) {
+ hmodule_map_[cf_dll_path_] = handle;
+ *cf_dll_path = cf_dll_path_;
+ success = true;
+ } else {
+ LOG(ERROR) << "Failed to load test dll: " << dll_path.value();
+ }
+ }
+
+ return success;
+ }
+
+ virtual bool LoadTestDll(const std::wstring& dll_name) {
+ bool success = false;
+ std::wstring dll_path;
+ if (GetDllPath(dll_name, &dll_path)) {
+ HMODULE handle = LoadLibrary(dll_path.c_str());
+ if (handle) {
+ hmodule_map_[dll_name] = handle;
+ success = true;
+ } else {
+ LOG(ERROR) << "Failed to load test dll: " << dll_name;
+ }
+ } else {
+ LOG(ERROR) << "Failed to get dll path for " << dll_name;
+ }
+ return success;
+ }
+
+ // Unload any DLLs we have loaded and make sure they stay unloaded.
+ virtual void TearDown() {
+ DllRedirector::PathToHModuleMap::const_iterator iter(hmodule_map_.begin());
+ for (; iter != hmodule_map_.end(); ++iter) {
+ FreeLibrary(iter->second);
+ }
+
+ // Check that the modules were actually unloaded (i.e. we had no dangling
+ // references). Do this after freeing all modules since they can have
+ // references to each other.
+ for (iter = hmodule_map_.begin(); iter != hmodule_map_.end(); ++iter) {
+ // The CF module gets pinned, so don't check that that is unloaded.
+ if (iter->first != cf_dll_path_) {
+ HMODULE temp_handle;
+ ASSERT_FALSE(GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
+ reinterpret_cast<LPCTSTR>(iter->second),
+ &temp_handle));
+ }
+ }
+
+ hmodule_map_.clear();
+ }
+
+ DllRedirector::PathToHModuleMap hmodule_map_;
+ std::wstring cf_dll_path_;
+};
+
+// Tests that if we load a few versions of the same module that all export
+// DllGetClassObject, that we correctly a) find a DllGetClassObject function
+// pointer and b) find it in the right module.
+TEST_F(ModuleUtilsTest, BasicTest) {
+ ASSERT_TRUE(LoadTestDll(L"3\\TestDll.dll"));
+ ASSERT_TRUE(LoadTestDll(L"2\\TestDll.dll"));
+ ASSERT_TRUE(LoadTestDll(L"1\\TestDll.dll"));
+
+ DllRedirector redir;
+ redir.EnsureInitialized(L"TestDll.dll", CLSID_ChromeActiveDocument);
+
+ LPFNGETCLASSOBJECT found_ptr = redir.get_dll_get_class_object_ptr();
+ EXPECT_TRUE(found_ptr != NULL);
+
+ LPFNGETCLASSOBJECT direct_ptr = reinterpret_cast<LPFNGETCLASSOBJECT>(
+ GetProcAddress(hmodule_map_[L"1\\TestDll.dll"],
+ "DllGetClassObject"));
+ EXPECT_TRUE(direct_ptr != NULL);
+
+ EXPECT_EQ(found_ptr, direct_ptr);
+}
+
+// Tests that a DLL that does not return a class factory for a Chrome Frame
+// guid even though it has a lower version string.
+TEST_F(ModuleUtilsTest, NoCFDllTest) {
+ ASSERT_TRUE(LoadTestDll(L"1\\TestDll.dll"));
+ ASSERT_TRUE(LoadTestDll(L"TestDllNoCF\\TestDll.dll"));
+
+ DllRedirector redir;
+ redir.EnsureInitialized(L"TestDll.dll", CLSID_ChromeActiveDocument);
+
+ LPFNGETCLASSOBJECT found_ptr = redir.get_dll_get_class_object_ptr();
+ EXPECT_TRUE(found_ptr != NULL);
+
+ LPFNGETCLASSOBJECT direct_ptr =
+ reinterpret_cast<LPFNGETCLASSOBJECT>(
+ GetProcAddress(hmodule_map_[L"1\\TestDll.dll"],
+ "DllGetClassObject"));
+ EXPECT_TRUE(direct_ptr != NULL);
+
+ EXPECT_EQ(found_ptr, direct_ptr);
+}
+
+// Tests that this works with the actual CF dll.
+TEST_F(ModuleUtilsTest, ChromeFrameDllTest) {
+ ASSERT_TRUE(LoadTestDll(L"DummyCF\\npchrome_frame.dll"));
+ std::wstring cf_dll_path;
+ ASSERT_TRUE(LoadChromeFrameDll(&cf_dll_path));
+ ASSERT_TRUE(!cf_dll_path.empty());
+
+ DllRedirector redir;
+ redir.EnsureInitialized(L"npchrome_frame.dll", CLSID_ChromeActiveDocument);
+
+ LPFNGETCLASSOBJECT found_ptr = redir.get_dll_get_class_object_ptr();
+ EXPECT_TRUE(found_ptr != NULL);
+
+ LPFNGETCLASSOBJECT direct_ptr = reinterpret_cast<LPFNGETCLASSOBJECT>(
+ GetProcAddress(hmodule_map_[L"DummyCF\\npchrome_frame.dll"],
+ "DllGetClassObject"));
+ EXPECT_TRUE(direct_ptr != NULL);
+
+ EXPECT_EQ(found_ptr, direct_ptr);
+
+ // Now try asking for a ChromeActiveDocument using the non-dummy CF DLL
+ // handle and make sure that the delegation to the dummy module happens
+ // correctly. Use the bare guid to keep dependencies simple
+ const wchar_t kClsidChromeActiveDocument[] =
+ L"{3e1d0e7f-f5e3-44cc-aa6a-c0a637619ab8}";
+
+ LPFNGETCLASSOBJECT cf_ptr = reinterpret_cast<LPFNGETCLASSOBJECT>(
+ GetProcAddress(hmodule_map_[cf_dll_path],
+ "DllGetClassObject"));
+ EXPECT_TRUE(cf_ptr != NULL);
+
+ CLSID cf_clsid;
+ HRESULT hr = CLSIDFromString(kClsidChromeActiveDocument, &cf_clsid);
+ EXPECT_HRESULT_SUCCEEDED(hr);
+
+ CComPtr<IClassFactory> class_factory;
+ DWORD result = cf_ptr(cf_clsid, IID_IClassFactory,
+ reinterpret_cast<void**>(&class_factory));
+
+ EXPECT_EQ(S_OK, result);
+}