diff options
author | robertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-01 02:25:11 +0000 |
---|---|---|
committer | robertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-01 02:25:11 +0000 |
commit | 87ba2e6056bfe771ddc6ce540cf3d4e413d4e6f4 (patch) | |
tree | fabaa7bfcd986c6ea6481d571e7ccad4afc74ced /chrome_frame | |
parent | 35c96084eb0abf809bb86c9c95c74ac4e6284fe5 (diff) | |
download | chromium_src-87ba2e6056bfe771ddc6ce540cf3d4e413d4e6f4.zip chromium_src-87ba2e6056bfe771ddc6ce540cf3d4e413d4e6f4.tar.gz chromium_src-87ba2e6056bfe771ddc6ce540cf3d4e413d4e6f4.tar.bz2 |
Add an integration test for Chrome Frame's DllRedirector class.
Fix a bug in the DllRedirector module loading code.
Expand the alternate version generator code to provide a function for generating new versions of single modules.
Remove the LI SACL from the shared memory lock for Win XP.
BUG=NONE
TEST=NONE
Review URL: http://codereview.chromium.org/6600001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@76338 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame')
-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 |
6 files changed, 233 insertions, 8 deletions
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. |