diff options
-rw-r--r-- | chrome/installer/test/alternate_version_generator.cc | 93 | ||||
-rw-r--r-- | chrome/installer/test/alternate_version_generator.h | 7 | ||||
-rw-r--r-- | chrome/installer/upgrade_test.gyp | 50 | ||||
-rw-r--r-- | chrome_frame/chrome_frame.gyp | 2 | ||||
-rw-r--r-- | chrome_frame/dll_redirector.cc | 14 | ||||
-rw-r--r-- | chrome_frame/test/dll_redirector_loading_test.cc | 209 | ||||
-rw-r--r-- | chrome_frame/test/test_with_web_server.cc | 4 | ||||
-rw-r--r-- | chrome_frame/test_utils.cc | 6 | ||||
-rw-r--r-- | chrome_frame/test_utils.h | 6 |
9 files changed, 335 insertions, 56 deletions
diff --git a/chrome/installer/test/alternate_version_generator.cc b/chrome/installer/test/alternate_version_generator.cc index c6416ef..7af5cc6 100644 --- a/chrome/installer/test/alternate_version_generator.cc +++ b/chrome/installer/test/alternate_version_generator.cc @@ -45,7 +45,6 @@ #include "chrome/installer/test/resource_loader.h" #include "chrome/installer/test/resource_updater.h" #include "chrome/installer/util/lzma_util.h" -#include "testing/gtest/include/gtest/gtest.h" namespace { @@ -148,10 +147,14 @@ class MappedFile { MappedFile::~MappedFile() { if (view_ != NULL) { - EXPECT_NE(0, UnmapViewOfFile(view_)); + if (UnmapViewOfFile(view_) == 0) { + PLOG(DFATAL) << "MappedFile failed to unmap view."; + } } if (mapping_ != NULL) { - EXPECT_NE(0, CloseHandle(mapping_)); + if (CloseHandle(mapping_) == 0) { + PLOG(DFATAL) << "Could not close file mapping handle."; + } } } @@ -211,17 +214,17 @@ bool RunProcessAndWait(const wchar_t* exe_path, const std::wstring& cmdline, return result; } -// Retrieves the version number of setup.exe in |work_dir| from its version +// Retrieves the version number of |pe_file| from its version // resource, placing the value in |version|. Returns true on success. -bool GetSetupExeVersion(const FilePath& work_dir, ChromeVersion* version) { +bool GetFileVersion(const FilePath& pe_file, ChromeVersion* version) { DCHECK(version); bool result = false; - upgrade_test::ResourceLoader setup; + upgrade_test::ResourceLoader pe_file_loader; std::pair<const uint8*, DWORD> version_info_data; - if (setup.Initialize(work_dir.Append(&kSetupExe[0])) && - setup.Load(VS_VERSION_INFO, reinterpret_cast<WORD>(RT_VERSION), - &version_info_data)) { + if (pe_file_loader.Initialize(pe_file) && + pe_file_loader.Load(VS_VERSION_INFO, reinterpret_cast<WORD>(RT_VERSION), + &version_info_data)) { const VS_FIXEDFILEINFO* fixed_file_info; UINT ver_info_len; if (VerQueryValue(version_info_data.first, L"\\", @@ -240,6 +243,13 @@ bool GetSetupExeVersion(const FilePath& work_dir, ChromeVersion* version) { return result; } +// Retrieves the version number of setup.exe in |work_dir| from its version +// resource, placing the value in |version|. Returns true on success. +bool GetSetupExeVersion(const FilePath& work_dir, ChromeVersion* version) { + return GetFileVersion(work_dir.Append(&kSetupExe[0]), version); +} + + // Replace all occurrences in the sequence [|dest_first|, |dest_last) that // equals [|src_first|, |src_last) with the sequence at |replacement_first| of // the same length. Returns true on success. If non-NULL, |replacements_made| @@ -343,6 +353,27 @@ bool UpdateVersionIfMatch(const FilePath& image_file, return result; } +bool IncrementNewVersion(upgrade_test::Direction direction, + VisitResourceContext* ctx) { + DCHECK(ctx); + + // Figure out a past or future version with the same string length as this one + // by decrementing or incrementing each component. + LONGLONG incrementer = (direction == upgrade_test::PREVIOUS_VERSION ? -1 : 1); + + do { + if (incrementer == 0) { + LOG(DFATAL) << "Improbable version at the cusp of complete rollover"; + return false; + } + ctx->new_version.set_value(ctx->current_version.value() + incrementer); + ctx->new_version_str = ctx->new_version.ToString(); + incrementer <<= 16; + } while (ctx->new_version_str.size() != ctx->current_version_str.size()); + + return true; +} + // Raises or lowers the version of all .exe and .dll files in |work_dir| as well // as the |work-dir|\Chrome-bin\w.x.y.z directory. |original_version| and // |new_version|, when non-NULL, are given the original and new version numbers @@ -357,19 +388,9 @@ bool ApplyAlternateVersion(const FilePath& work_dir, } ctx.current_version_str = ctx.current_version.ToString(); - // Figure out a past or future version with the same string length as this one - // by decrementing or incrementing each component. - LONGLONG incrementer = (direction == upgrade_test::PREVIOUS_VERSION ? -1 : 1); - - do { - if (incrementer == 0) { - LOG(DFATAL) << "Improbable version at the cusp of complete rollover"; - return false; - } - ctx.new_version.set_value(ctx.current_version.value() + incrementer); - ctx.new_version_str = ctx.new_version.ToString(); - incrementer <<= 16; - } while (ctx.new_version_str.size() != ctx.current_version_str.size()); + if (!IncrementNewVersion(direction, &ctx)) { + return false; + } // Modify all .dll and .exe files with the current version. bool doing_great = true; @@ -590,4 +611,32 @@ bool GenerateAlternateVersion(const FilePath& original_installer_path, return file_util::Move(mini_installer, target_path); } +bool GenerateAlternatePEFileVersion(const FilePath& original_file, + const FilePath& target_file, + Direction direction) { + // First copy original_file to target_file. + if (!file_util::CopyFile(original_file, target_file)) { + LOG(DFATAL) << "Failed copying \"" << original_file.value() + << "\" to \"" << target_file.value() << "\""; + return false; + } + + VisitResourceContext ctx; + if (!GetFileVersion(target_file, &ctx.current_version)) { + LOG(DFATAL) << "Failed reading version from \"" << target_file.value() + << "\""; + return false; + } + ctx.current_version_str = ctx.current_version.ToString(); + + if (!IncrementNewVersion(direction, &ctx) || + !UpdateVersionIfMatch(target_file, &ctx)) { + LOG(DFATAL) << "Failed to update version in \"" << target_file.value() + << "\""; + return false; + } + + return true; +} + } // namespace upgrade_test diff --git a/chrome/installer/test/alternate_version_generator.h b/chrome/installer/test/alternate_version_generator.h index cce83b0..43ef9f4 100644 --- a/chrome/installer/test/alternate_version_generator.h +++ b/chrome/installer/test/alternate_version_generator.h @@ -31,6 +31,13 @@ bool GenerateAlternateVersion(const FilePath& original_installer_path, std::wstring* original_version, std::wstring* new_version); +// Given a path to a PEImage in |original_file|, copy that file to +// |target_file|, modifying the version of the copy according to |direction|. +// Any previous file at |target_file| is clobbered. Returns true on success. +bool GenerateAlternatePEFileVersion(const FilePath& original_file, + const FilePath& target_file, + Direction direction); + } // namespace upgrade_test #endif // CHROME_INSTALLER_TEST_ALTERNATE_VERSION_GENERATOR_H_ diff --git a/chrome/installer/upgrade_test.gyp b/chrome/installer/upgrade_test.gyp index 52b69ea..5f155e0 100644 --- a/chrome/installer/upgrade_test.gyp +++ b/chrome/installer/upgrade_test.gyp @@ -9,35 +9,35 @@ }, 'conditions': [ ['OS=="win"', { - 'target_defaults': { - 'variables': { - 'alternate_version_generator_target': 0, - }, - 'target_conditions': [ - # This part is shared between the two targets. - ['alternate_version_generator_target==1', { - 'sources': [ - 'test/alternate_version_generator.cc', - 'test/alternate_version_generator.h', - 'test/pe_image_resources.cc', - 'test/pe_image_resources.h', - 'test/resource_loader.cc', - 'test/resource_loader.h', - 'test/resource_updater.cc', - 'test/resource_updater.h', - ], - }], - ], - }, 'targets': [ { + 'target_name': 'alternate_version_generator_lib', + 'msvs_guid': '66723D46-A641-4182-A321-923FD6335D9B', + 'type': 'static_library', + 'dependencies': [ + '../chrome.gyp:common_constants', + '../chrome.gyp:installer_util', + ], + 'include_dirs': [ + '../..', + ], + 'sources': [ + 'test/alternate_version_generator.cc', + 'test/alternate_version_generator.h', + 'test/pe_image_resources.cc', + 'test/pe_image_resources.h', + 'test/resource_loader.cc', + 'test/resource_loader.h', + 'test/resource_updater.cc', + 'test/resource_updater.h', + ], + }, + { 'target_name': 'upgrade_test', 'msvs_guid': 'BC4D6130-FDAD-47FB-B4FD-FCAF78DCBC3C', 'type': 'executable', - 'variables': { - 'alternate_version_generator_target': 1, - }, 'dependencies': [ + 'alternate_version_generator_lib', # This dependency, although correct, results in the mini installer # being rebuilt every time upgrade_test is built. So disable it # for now. @@ -62,10 +62,8 @@ 'target_name': 'alternate_version_generator', 'msvs_guid': 'E6E6B339-AEC0-44C9-B9D0-E30138108379', 'type': 'executable', - 'variables': { - 'alternate_version_generator_target': 1, - }, 'dependencies': [ + 'alternate_version_generator_lib', '../../base/base.gyp:test_support_base', '../../testing/gtest.gyp:gtest', '../chrome.gyp:common_constants', diff --git a/chrome_frame/chrome_frame.gyp b/chrome_frame/chrome_frame.gyp index 00662af4..273ae7c 100644 --- a/chrome_frame/chrome_frame.gyp +++ b/chrome_frame/chrome_frame.gyp @@ -238,6 +238,7 @@ '../chrome/chrome.gyp:browser', '../chrome/chrome.gyp:debugger', '../chrome/chrome.gyp:renderer', + '../chrome/installer/upgrade_test.gyp:alternate_version_generator_lib', '../net/net.gyp:net_test_support', '../testing/gmock.gyp:gmock', '../testing/gtest.gyp:gtest', @@ -264,6 +265,7 @@ 'test/chrome_frame_automation_mock.cc', 'test/chrome_frame_automation_mock.h', 'test/delete_chrome_history_test.cc', + 'test/dll_redirector_loading_test.cc', 'test/header_test.cc', 'test/ie_event_sink.cc', 'test/ie_event_sink.h', diff --git a/chrome_frame/dll_redirector.cc b/chrome_frame/dll_redirector.cc index d7de158..f03c124 100644 --- a/chrome_frame/dll_redirector.cc +++ b/chrome_frame/dll_redirector.cc @@ -18,6 +18,7 @@ #include "base/sys_info.h" #include "base/utf_string_conversions.h" #include "base/version.h" +#include "base/win/windows_version.h" #include "chrome_frame/utils.h" const wchar_t kSharedMemoryName[] = L"ChromeFrameVersionBeacon_"; @@ -29,7 +30,7 @@ DllRedirector::DllRedirector() : first_module_handle_(NULL) { // TODO(robertshield): Allow for overrides to be taken from the environment. std::wstring beacon_name(kSharedMemoryName); beacon_name += GetHostProcessName(false); - shared_memory_.reset(new base::SharedMemory()); + shared_memory_.reset(new base::SharedMemory(beacon_name)); shared_memory_name_ = WideToUTF8(beacon_name); } @@ -132,7 +133,10 @@ bool DllRedirector::RegisterAsFirstCFModule() { bool lock_acquired = false; CSecurityAttributes sec_attr; - if (BuildSecurityAttributesForLock(&sec_attr)) { + if (base::win::GetVersion() >= base::win::VERSION_VISTA && + BuildSecurityAttributesForLock(&sec_attr)) { + // On vista and above, we need to explicitly allow low integrity access + // to our objects. On XP, we don't bother. lock_acquired = shared_memory_->Lock(kSharedMemoryLockTimeoutMs, &sec_attr); } else { lock_acquired = shared_memory_->Lock(kSharedMemoryLockTimeoutMs, NULL); @@ -274,11 +278,15 @@ HMODULE DllRedirector::LoadVersionedModule(Version* version) { DCHECK(version); FilePath module_path; - PathService::Get(base::DIR_MODULE, &module_path); + PathService::Get(base::FILE_MODULE, &module_path); DCHECK(!module_path.empty()); + // For a module located in + // Foo\XXXXXXXXX\<module>.dll, load + // Foo\<version>\<module>.dll: FilePath module_name = module_path.BaseName(); module_path = module_path.DirName() + .DirName() .Append(ASCIIToWide(version->GetString())) .Append(module_name); diff --git a/chrome_frame/test/dll_redirector_loading_test.cc b/chrome_frame/test/dll_redirector_loading_test.cc new file mode 100644 index 0000000..0dbf104 --- /dev/null +++ b/chrome_frame/test/dll_redirector_loading_test.cc @@ -0,0 +1,209 @@ +// Copyright (c) 2011 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. + +// A test that exercises Chrome Frame's DLL Redirctor update code. This test +// generates a new version of CF from the one already in the build folder and +// then loads them both into the current process to verify the handoff. + +#include "base/file_path.h" +#include "base/file_util.h" +#include "base/file_version_info.h" +#include "base/path_service.h" +#include "base/scoped_native_library.h" +#include "base/scoped_temp_dir.h" +#include "base/shared_memory.h" +#include "base/string_util.h" +#include "base/version.h" +#include "base/win/scoped_comptr.h" +#include "chrome/installer/test/alternate_version_generator.h" +#include "chrome/installer/util/delete_after_reboot_helper.h" +#include "chrome_frame/test_utils.h" +#include "chrome_frame/utils.h" +#include "testing/gtest/include/gtest/gtest.h" + +#include "chrome_tab.h" // NOLINT + +namespace { +const wchar_t kSharedMemoryPrefix[] = L"ChromeFrameVersionBeacon_"; +const uint32 kSharedMemoryBytes = 128; +} + +class DllRedirectorLoadingTest : public testing::Test { + public: + // This sets up the following directory structure: + // TEMP\<version X>\npchrome_frame.dll + // \<version X+1>\npchrome_frame.dll + // + // This structure emulates enough of the directory structure of a Chrome + // install to test upgrades. + static void SetUpTestCase() { + // First ensure that we can find the built Chrome Frame DLL. + FilePath build_chrome_frame_dll = GetChromeFrameBuildPath(); + ASSERT_TRUE(file_util::PathExists(build_chrome_frame_dll)); + + // Then grab its version. + scoped_ptr<FileVersionInfo> original_version_info( + FileVersionInfo::CreateFileVersionInfo(build_chrome_frame_dll)); + ASSERT_TRUE(original_version_info != NULL); + original_version_.reset(Version::GetVersionFromString( + WideToASCII(original_version_info->file_version()))); + ASSERT_TRUE(original_version_ != NULL); + + // Make a place for us to run the test from. + ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); + + // Make a versioned dir for the original chrome frame dll to run under. + FilePath original_version_dir( + temp_dir_.path().AppendASCII(original_version_->GetString())); + ASSERT_TRUE(file_util::CreateDirectory(original_version_dir)); + + // Now move the original DLL that we will operate on into a named-version + // folder. + original_chrome_frame_dll_ = + original_version_dir.Append(build_chrome_frame_dll.BaseName()); + ASSERT_TRUE(file_util::CopyFile(build_chrome_frame_dll, + original_chrome_frame_dll_)); + ASSERT_TRUE(file_util::PathExists(original_chrome_frame_dll_)); + + // Temporary location for the new Chrome Frame DLL. + FilePath temporary_new_chrome_frame_dll( + temp_dir_.path().Append(build_chrome_frame_dll.BaseName())); + + // Generate the version-bumped Chrome Frame DLL to a temporary path. + ASSERT_TRUE( + upgrade_test::GenerateAlternatePEFileVersion( + original_chrome_frame_dll_, + temporary_new_chrome_frame_dll, + upgrade_test::NEXT_VERSION)); + + // Ensure it got created and grab its version. + scoped_ptr<FileVersionInfo> new_version_info( + FileVersionInfo::CreateFileVersionInfo(temporary_new_chrome_frame_dll)); + ASSERT_TRUE(new_version_info != NULL); + new_version_.reset(Version::GetVersionFromString( + WideToASCII(new_version_info->file_version()))); + ASSERT_TRUE(new_version_ != NULL); + + // Make sure the new version is larger than the old. + ASSERT_EQ(new_version_->CompareTo(*original_version_.get()), 1); + + // Now move the new Chrome Frame dll to its final resting place: + FilePath new_version_dir( + temp_dir_.path().AppendASCII(new_version_->GetString())); + ASSERT_TRUE(file_util::CreateDirectory(new_version_dir)); + new_chrome_frame_dll_ = + new_version_dir.Append(build_chrome_frame_dll.BaseName()); + ASSERT_TRUE(file_util::Move(temporary_new_chrome_frame_dll, + new_chrome_frame_dll_)); + ASSERT_TRUE(file_util::PathExists(new_chrome_frame_dll_)); + } + + static void TearDownTestCase() { + if (!temp_dir_.Delete()) { + // The temp_dir cleanup has been observed to fail in some cases. It looks + // like something is holding on to the Chrome Frame DLLs after they have + // been explicitly unloaded. At least schedule them for cleanup on reboot. + ScheduleDirectoryForDeletion(temp_dir_.path().value().c_str()); + } + } + + protected: + static FilePath original_chrome_frame_dll_; + static FilePath new_chrome_frame_dll_; + static scoped_ptr<Version> original_version_; + static scoped_ptr<Version> new_version_; + + static ScopedTempDir temp_dir_; +}; // class DllRedirectorLoadingTest + +FilePath DllRedirectorLoadingTest::original_chrome_frame_dll_; +FilePath DllRedirectorLoadingTest::new_chrome_frame_dll_; +scoped_ptr<Version> DllRedirectorLoadingTest::original_version_; +scoped_ptr<Version> DllRedirectorLoadingTest::new_version_; +ScopedTempDir DllRedirectorLoadingTest::temp_dir_; + +TEST_F(DllRedirectorLoadingTest, TestDllRedirection) { + struct TestData { + FilePath first_dll; + FilePath second_dll; + Version* expected_beacon_version; + } test_data[] = { + { + original_chrome_frame_dll_, + new_chrome_frame_dll_, + original_version_.get() + }, + { + new_chrome_frame_dll_, + original_chrome_frame_dll_, + new_version_.get() + } + }; + + for (int i = 0; i < arraysize(test_data); ++i) { + // First load the original dll into our test process. + base::ScopedNativeLibrary original_library(test_data[i].first_dll); + + ASSERT_TRUE(original_library.is_valid()); + + // Now query the original dll for its DllGetClassObject method and use that + // to get the class factory for a known CLSID. + LPFNGETCLASSOBJECT original_dgco_ptr = + reinterpret_cast<LPFNGETCLASSOBJECT>( + original_library.GetFunctionPointer("DllGetClassObject")); + + ASSERT_TRUE(original_dgco_ptr != NULL); + + base::win::ScopedComPtr<IClassFactory> original_class_factory; + HRESULT hr = original_dgco_ptr( + CLSID_ChromeFrame, + IID_IClassFactory, + reinterpret_cast<void**>(original_class_factory.Receive())); + + ASSERT_HRESULT_SUCCEEDED(hr); + + // Now load the new dll into our test process. + base::ScopedNativeLibrary new_library(test_data[i].second_dll); + + ASSERT_TRUE(new_library.is_valid()); + + // Now query the new dll for its DllGetClassObject method and use that + // to get the class factory for a known CLSID. + LPFNGETCLASSOBJECT new_dgco_ptr = + reinterpret_cast<LPFNGETCLASSOBJECT>( + new_library.GetFunctionPointer("DllGetClassObject")); + + ASSERT_TRUE(new_dgco_ptr != NULL); + + base::win::ScopedComPtr<IClassFactory> new_class_factory; + hr = new_dgco_ptr(CLSID_ChromeFrame, + IID_IClassFactory, + reinterpret_cast<void**>(new_class_factory.Receive())); + + ASSERT_HRESULT_SUCCEEDED(hr); + + base::win::ScopedComPtr<IUnknown> qi_test; + EXPECT_HRESULT_SUCCEEDED(original_class_factory.QueryInterface(IID_IUnknown, + reinterpret_cast<void**>(qi_test.Receive()))); + + EXPECT_TRUE(new_class_factory.IsSameObject(qi_test)); + + // Check the version beacon. + std::wstring beacon_name(kSharedMemoryPrefix); + beacon_name += GetHostProcessName(false /* without extension */); + base::SharedMemory beacon(beacon_name); + + EXPECT_TRUE(beacon.Open(WideToASCII(beacon_name), true /* read_only */)); + EXPECT_TRUE(beacon.Map(0)); + EXPECT_TRUE(beacon.memory()); + + char buffer[kSharedMemoryBytes] = {0}; + memcpy(buffer, beacon.memory(), kSharedMemoryBytes - 1); + scoped_ptr<Version> beacon_version(Version::GetVersionFromString(buffer)); + ASSERT_TRUE(beacon_version != NULL); + + EXPECT_EQ(0, + beacon_version->CompareTo(*test_data[i].expected_beacon_version)); + } +} diff --git a/chrome_frame/test/test_with_web_server.cc b/chrome_frame/test/test_with_web_server.cc index adb0b96..8c62f03 100644 --- a/chrome_frame/test/test_with_web_server.cc +++ b/chrome_frame/test/test_with_web_server.cc @@ -929,7 +929,7 @@ const wchar_t kInstallFlowTestUrl[] = TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_InstallFlowTest) { if (base::win::GetVersion() < base::win::VERSION_VISTA) { ScopedChromeFrameRegistrar::UnregisterAtPath( - ScopedChromeFrameRegistrar::GetChromeFrameBuildPath().value(), + GetChromeFrameBuildPath().value(), chrome_frame_test::GetTestBedType()); ASSERT_TRUE(LaunchBrowser(IE, kInstallFlowTestUrl)); @@ -937,7 +937,7 @@ TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_InstallFlowTest) { loop_.RunFor(kChromeFrameLongNavigationTimeoutInSeconds); ScopedChromeFrameRegistrar::RegisterAtPath( - ScopedChromeFrameRegistrar::GetChromeFrameBuildPath().value(), + GetChromeFrameBuildPath().value(), chrome_frame_test::GetTestBedType()); server_mock_.ExpectAndHandlePostedResult(CFInvocation(CFInvocation::NONE), diff --git a/chrome_frame/test_utils.cc b/chrome_frame/test_utils.cc index 924ea53..258b0fa 100644 --- a/chrome_frame/test_utils.cc +++ b/chrome_frame/test_utils.cc @@ -25,8 +25,7 @@ const wchar_t kChromeFrameDllName[] = L"npchrome_frame.dll"; const wchar_t kChromeLauncherExeName[] = L"chrome_launcher.exe"; -// Statics -FilePath ScopedChromeFrameRegistrar::GetChromeFrameBuildPath() { +FilePath GetChromeFrameBuildPath() { FilePath build_path; PathService::Get(chrome::DIR_APP, &build_path); @@ -46,11 +45,13 @@ FilePath ScopedChromeFrameRegistrar::GetChromeFrameBuildPath() { return dll_path; } +// static void ScopedChromeFrameRegistrar::RegisterDefaults() { FilePath dll_path = GetChromeFrameBuildPath(); RegisterAtPath(dll_path.value(), chrome_frame_test::GetTestBedType()); } +// static void ScopedChromeFrameRegistrar::RegisterAtPath( const std::wstring& path, RegistrationType registration_type) { @@ -88,6 +89,7 @@ void ScopedChromeFrameRegistrar::RegisterAtPath( ASSERT_TRUE(FreeLibrary(dll_handle)); } +// static void ScopedChromeFrameRegistrar::UnregisterAtPath( const std::wstring& path, RegistrationType registration_type) { diff --git a/chrome_frame/test_utils.h b/chrome_frame/test_utils.h index f3947c0..7b66083 100644 --- a/chrome_frame/test_utils.h +++ b/chrome_frame/test_utils.h @@ -41,7 +41,6 @@ class ScopedChromeFrameRegistrar { std::wstring GetChromeFrameDllPath() const; - static FilePath GetChromeFrameBuildPath(); static void RegisterAtPath(const std::wstring& path, RegistrationType registration_type); static void UnregisterAtPath(const std::wstring& path, @@ -60,6 +59,11 @@ class ScopedChromeFrameRegistrar { RegistrationType registration_type_; }; +// Returns the path to the Chrome Frame DLL in the build directory. Assumes +// that the test executable is running from the build folder or a similar +// folder structure. +FilePath GetChromeFrameBuildPath(); + // Callback description for onload, onloaderror, onmessage static _ATL_FUNC_INFO g_single_param = {CC_STDCALL, VT_EMPTY, 1, {VT_VARIANT}}; // Simple class that forwards the callbacks. |