diff options
-rw-r--r-- | base/base.xcodeproj/project.pbxproj | 4 | ||||
-rw-r--r-- | base/base_lib.scons | 2 | ||||
-rw-r--r-- | base/event_recorder.cc | 4 | ||||
-rw-r--r-- | base/event_recorder.h | 8 | ||||
-rw-r--r-- | base/event_recorder_stubs.cc | 28 | ||||
-rw-r--r-- | webkit/tools/test_shell/SConscript | 2 | ||||
-rw-r--r-- | webkit/tools/test_shell/mac/TestShell.xcodeproj/project.pbxproj | 22 | ||||
-rw-r--r-- | webkit/tools/test_shell/mac/main.mm | 348 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell.vcproj | 8 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell_mac.mm | 234 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell_main.cc | 151 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell_platform_delegate.h | 58 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell_platform_delegate_gtk.cc | 44 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell_platform_delegate_mac.mm | 286 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell_platform_delegate_win.cc | 110 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell_tests.vcproj | 8 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell_win.cc | 10 |
17 files changed, 611 insertions, 716 deletions
diff --git a/base/base.xcodeproj/project.pbxproj b/base/base.xcodeproj/project.pbxproj index e404033..e5ef83a 100644 --- a/base/base.xcodeproj/project.pbxproj +++ b/base/base.xcodeproj/project.pbxproj @@ -155,6 +155,7 @@ A5A0270B0E4A630D00498DA9 /* file_util_mac.mm in Sources */ = {isa = PBXBuildFile; fileRef = A5A0270A0E4A630D00498DA9 /* file_util_mac.mm */; }; A5CE1D2B0E55F4D800AD0606 /* file_util_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = A5A0282D0E4CFA8500498DA9 /* file_util_unittest.cc */; }; AB4C147D0EC0E3F600655FED /* time_mac.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BEB81490D9B0F33009BA8DD /* time_mac.cc */; }; + AB4FA13A0F2A101100D6572F /* event_recorder_stubs.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB4FA1390F2A101100D6572F /* event_recorder_stubs.cc */; }; ABE1BA2A0E7574D1009041DA /* ApplicationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ABE1BA290E7574D1009041DA /* ApplicationServices.framework */; }; ABF4B98F0DC2BA6900A6E319 /* base_paths_mac.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABF4B98E0DC2BA6900A6E319 /* base_paths_mac.mm */; }; ABF4B99E0DC2BB6000A6E319 /* clipboard_mac.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABF4B99D0DC2BB6000A6E319 /* clipboard_mac.mm */; }; @@ -612,6 +613,7 @@ A5A0276B0E4BA33700498DA9 /* build_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = build_config.h; path = ../build/build_config.h; sourceTree = SOURCE_ROOT; }; A5A0282D0E4CFA8500498DA9 /* file_util_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = file_util_unittest.cc; sourceTree = "<group>"; }; AB14B6060EBFA74C00FB3807 /* time_posix.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = time_posix.cc; sourceTree = "<group>"; }; + AB4FA1390F2A101100D6572F /* event_recorder_stubs.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = event_recorder_stubs.cc; sourceTree = "<group>"; }; ABE1BA290E7574D1009041DA /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = System/Library/Frameworks/ApplicationServices.framework; sourceTree = "<group>"; }; ABF4B98E0DC2BA6900A6E319 /* base_paths_mac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = base_paths_mac.mm; sourceTree = "<group>"; }; ABF4B99D0DC2BB6000A6E319 /* clipboard_mac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = clipboard_mac.mm; sourceTree = "<group>"; }; @@ -852,6 +854,7 @@ 536092F80ECE474500D1B91E /* dtoa.cc */, 825402FF0D92D1BC0006B936 /* event_recorder.cc */, 825403000D92D1BC0006B936 /* event_recorder.h */, + AB4FA1390F2A101100D6572F /* event_recorder_stubs.cc */, ABF68B270EB0F93100E72835 /* field_trial.h */, ABF68B280EB0F93100E72835 /* field_trial.cc */, ABF68B260EB0F93100E72835 /* field_trial_unittest.cc */, @@ -1359,6 +1362,7 @@ 7B78CE250E5314A000609465 /* debug_util.cc in Sources */, 7B78CE120E53131800609465 /* debug_util_posix.cc in Sources */, 536092FA0ECE474500D1B91E /* dtoa.cc in Sources */, + AB4FA13A0F2A101100D6572F /* event_recorder_stubs.cc in Sources */, ABF68B2A0EB0F93100E72835 /* field_trial.cc in Sources */, 4D11B89E0E929F0400EF7617 /* file_path.cc in Sources */, A5A026550E4A214600498DA9 /* file_util.cc in Sources */, diff --git a/base/base_lib.scons b/base/base_lib.scons index 7965c5e..93bf869 100644 --- a/base/base_lib.scons +++ b/base/base_lib.scons @@ -353,6 +353,7 @@ if env.Bit('posix'): if env.Bit('mac'): input_files.Extend([ 'base_paths_mac.mm', + 'event_recorder_stubs.cc', 'clipboard_mac.mm', 'file_util_mac.mm', 'file_version_info_mac.mm', @@ -372,6 +373,7 @@ if env.Bit('linux'): 'base_paths_linux.cc', 'clipboard_linux.cc', 'data_pack.cc', + 'event_recorder_stubs.cc', 'file_util_linux.cc', 'file_version_info_linux.cc', 'hmac_nss.cc', diff --git a/base/event_recorder.cc b/base/event_recorder.cc index ab7fcf9..0f1fb21 100644 --- a/base/event_recorder.cc +++ b/base/event_recorder.cc @@ -2,10 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/event_recorder.h" +#include "build/build_config.h" +#include <windows.h> #include <mmsystem.h> +#include "base/event_recorder.h" #include "base/file_util.h" #include "base/logging.h" #include "base/time.h" diff --git a/base/event_recorder.h b/base/event_recorder.h index a258d3a..43278c6 100644 --- a/base/event_recorder.h +++ b/base/event_recorder.h @@ -6,7 +6,9 @@ #define BASE_EVENT_RECORDER_H_ #include <string> +#if defined(OS_WIN) #include <windows.h> +#endif #include "base/basictypes.h" namespace base { @@ -55,10 +57,12 @@ class EventRecorder { // Is the EventRecorder currently playing. bool is_playing() const { return is_playing_; } +#if defined(OS_WIN) // C-style callbacks for the EventRecorder. // Used for internal purposes only. LRESULT RecordWndProc(int nCode, WPARAM wParam, LPARAM lParam); LRESULT PlaybackWndProc(int nCode, WPARAM wParam, LPARAM lParam); +#endif private: // Create a new EventRecorder. Events are saved to the file filename. @@ -67,8 +71,10 @@ class EventRecorder { explicit EventRecorder() : is_recording_(false), is_playing_(false), +#if defined(OS_WIN) journal_hook_(NULL), file_(NULL), +#endif playback_first_msg_time_(0), playback_start_time_(0) { } @@ -78,9 +84,11 @@ class EventRecorder { bool is_recording_; bool is_playing_; +#if defined(OS_WIN) HHOOK journal_hook_; FILE* file_; EVENTMSG playback_msg_; +#endif int playback_first_msg_time_; int playback_start_time_; diff --git a/base/event_recorder_stubs.cc b/base/event_recorder_stubs.cc new file mode 100644 index 0000000..9499c75 --- /dev/null +++ b/base/event_recorder_stubs.cc @@ -0,0 +1,28 @@ +// Copyright (c) 2009 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. + +#include "base/event_recorder.h" + +// This file implements a link stub for EventRecorder that can be used on +// platforms that don't have a working EventRecorder implementation. + +namespace base { + +EventRecorder* EventRecorder::current_; // Our singleton. + +bool EventRecorder::StartRecording(const std::wstring& filename) { + return true; +} + +void EventRecorder::StopRecording() { +} + +bool EventRecorder::StartPlayback(const std::wstring& filename) { + return false; +} + +void EventRecorder::StopPlayback() { +} + +} // namespace diff --git a/webkit/tools/test_shell/SConscript b/webkit/tools/test_shell/SConscript index 8bf73b2..4bdfea9 100644 --- a/webkit/tools/test_shell/SConscript +++ b/webkit/tools/test_shell/SConscript @@ -119,6 +119,7 @@ if env.Bit('windows'): input_files.extend([ 'drag_delegate.cc', 'drop_delegate.cc', + 'test_shell_platform_delegate_win.cc', 'test_shell_win.cc', 'test_webview_delegate_win.cc', 'webview_host_win.cc', @@ -129,6 +130,7 @@ elif env.Bit('linux'): 'webview_host_gtk.cc', 'webwidget_host_gtk.cc', 'test_shell_gtk.cc', + 'test_shell_platform_delegate_gtk.cc', 'test_webview_delegate_gtk.cc', ]) diff --git a/webkit/tools/test_shell/mac/TestShell.xcodeproj/project.pbxproj b/webkit/tools/test_shell/mac/TestShell.xcodeproj/project.pbxproj index 902bbf3a..655d179 100644 --- a/webkit/tools/test_shell/mac/TestShell.xcodeproj/project.pbxproj +++ b/webkit/tools/test_shell/mac/TestShell.xcodeproj/project.pbxproj @@ -85,6 +85,9 @@ 93AF4F350EFAFE2C0073C62D /* GKURL_unittest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93AF4F310EFAFE2C0073C62D /* GKURL_unittest.cpp */; }; 93AF4F360EFAFE2C0073C62D /* ICOImageDecoder_unittest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93AF4F320EFAFE2C0073C62D /* ICOImageDecoder_unittest.cpp */; }; 93AF4F370EFAFE2C0073C62D /* XBMImageDecoder_unittest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93AF4F330EFAFE2C0073C62D /* XBMImageDecoder_unittest.cpp */; }; + AB19AC150F1BBBD000673E20 /* test_shell_main.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB19AC140F1BBBD000673E20 /* test_shell_main.cc */; }; + AB19AC290F1BD6C900673E20 /* test_shell_platform_delegate_mac.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB19AC280F1BD6C900673E20 /* test_shell_platform_delegate_mac.mm */; }; + AB19AD380F1D0AF200673E20 /* test_shell_mac.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABA9CAE90DBC521D00CB1EFB /* test_shell_mac.mm */; }; E43A79AA0F1CE23800ABD5D1 /* textAreaResizeCorner.png in Resources */ = {isa = PBXBuildFile; fileRef = E43A79A90F1CE23800ABD5D1 /* textAreaResizeCorner.png */; }; E44662070ECCD652000B9316 /* test_webview_delegate.cc in Sources */ = {isa = PBXBuildFile; fileRef = E44662060ECCD652000B9316 /* test_webview_delegate.cc */; }; E450637E0E4100740025A81A /* test_shell_request_context.cc in Sources */ = {isa = PBXBuildFile; fileRef = E450637D0E4100740025A81A /* test_shell_request_context.cc */; }; @@ -193,11 +196,9 @@ E456290C0E26B4FE005E4685 /* test_shell_switches.cc in Sources */ = {isa = PBXBuildFile; fileRef = ABCF253C0DB8436B00099567 /* test_shell_switches.cc */; }; E456290F0E26B4FE005E4685 /* webview_host.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB8A785E0DC553EE005C27B8 /* webview_host.mm */; }; E45629100E26B4FE005E4685 /* webwidget_host.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABD16F380DC6A73B0013D3AA /* webwidget_host.mm */; }; - E45629150E26B4FE005E4685 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.mm */; }; E45629160E26B4FE005E4685 /* event_sending_controller.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB8A78520DC553A8005C27B8 /* event_sending_controller.cc */; }; E45629170E26B4FE005E4685 /* layout_test_controller.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB8A77FD0DC54DD6005C27B8 /* layout_test_controller.cc */; }; E45629190E26B4FE005E4685 /* test_navigation_controller.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB351E2E0DC7B290002F427A /* test_navigation_controller.cc */; }; - E456291A0E26B4FE005E4685 /* test_shell_mac.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABA9CAE90DBC521D00CB1EFB /* test_shell_mac.mm */; }; E456291C0E26B4FE005E4685 /* test_webview_delegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB8A78580DC553D7005C27B8 /* test_webview_delegate.mm */; }; E456291D0E26B4FE005E4685 /* text_input_controller.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB8A785B0DC553E4005C27B8 /* text_input_controller.cc */; }; E456291E0E26B4FE005E4685 /* test_shell_webview.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABA65EFE0DD50BFF003A4FC8 /* test_shell_webview.mm */; }; @@ -721,7 +722,6 @@ /* Begin PBXFileReference section */ 089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; }; 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = "<group>"; }; - 29B97316FDCFA39411CA2CEA /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = "<group>"; }; 29B97319FDCFA39411CA2CEA /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/MainMenu.nib; sourceTree = "<group>"; }; 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = "<group>"; }; 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = "<group>"; }; @@ -787,6 +787,11 @@ 93AF4F310EFAFE2C0073C62D /* GKURL_unittest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GKURL_unittest.cpp; path = ../../webcore_unit_tests/GKURL_unittest.cpp; sourceTree = SOURCE_ROOT; }; 93AF4F320EFAFE2C0073C62D /* ICOImageDecoder_unittest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ICOImageDecoder_unittest.cpp; path = ../../webcore_unit_tests/ICOImageDecoder_unittest.cpp; sourceTree = SOURCE_ROOT; }; 93AF4F330EFAFE2C0073C62D /* XBMImageDecoder_unittest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = XBMImageDecoder_unittest.cpp; path = ../../webcore_unit_tests/XBMImageDecoder_unittest.cpp; sourceTree = SOURCE_ROOT; }; + AB19AC140F1BBBD000673E20 /* test_shell_main.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = test_shell_main.cc; sourceTree = "<group>"; }; + AB19AC1B0F1BC29D00673E20 /* test_shell_platform_delegate_win.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = test_shell_platform_delegate_win.cc; sourceTree = "<group>"; }; + AB19AC1F0F1BD2D800673E20 /* test_shell_platform_delegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = test_shell_platform_delegate.h; sourceTree = "<group>"; }; + AB19AC280F1BD6C900673E20 /* test_shell_platform_delegate_mac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = test_shell_platform_delegate_mac.mm; sourceTree = "<group>"; }; + AB19AC2D0F1BD6E200673E20 /* test_shell_platform_delegate_gtk.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = test_shell_platform_delegate_gtk.cc; sourceTree = "<group>"; }; AB351E2E0DC7B290002F427A /* test_navigation_controller.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = test_navigation_controller.cc; sourceTree = "<group>"; }; AB351E2F0DC7B290002F427A /* test_navigation_controller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = test_navigation_controller.h; sourceTree = "<group>"; }; AB8665450DC78A5A002CE06A /* googleurl.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = googleurl.xcodeproj; path = build/googleurl.xcodeproj; sourceTree = "<group>"; }; @@ -1186,7 +1191,6 @@ F431EA490F1D141300E8D37F /* DumpRenderTreePasteboard.h */, 4D4164FA0F212E6500F2F4A0 /* KeystoneGlue.h */, 4D4164FB0F212E6500F2F4A0 /* KeystoneGlue.m */, - 29B97316FDCFA39411CA2CEA /* main.mm */, ABA65EFD0DD50BFF003A4FC8 /* test_shell_webview.h */, ABA65EFE0DD50BFF003A4FC8 /* test_shell_webview.mm */, 32CA4F630368D1EE00C91783 /* TestShell_Prefix.pch */, @@ -1277,6 +1281,11 @@ E45449360EC9FD15000DFA6E /* test_shell.cc */, ABA9CAE80DBC521D00CB1EFB /* test_shell.h */, ABA9CAE90DBC521D00CB1EFB /* test_shell_mac.mm */, + AB19AC140F1BBBD000673E20 /* test_shell_main.cc */, + AB19AC1F0F1BD2D800673E20 /* test_shell_platform_delegate.h */, + AB19AC2D0F1BD6E200673E20 /* test_shell_platform_delegate_gtk.cc */, + AB19AC280F1BD6C900673E20 /* test_shell_platform_delegate_mac.mm */, + AB19AC1B0F1BC29D00673E20 /* test_shell_platform_delegate_win.cc */, E450637D0E4100740025A81A /* test_shell_request_context.cc */, E450637C0E4100740025A81A /* test_shell_request_context.h */, ABCF253C0DB8436B00099567 /* test_shell_switches.cc */, @@ -1941,12 +1950,10 @@ E45629160E26B4FE005E4685 /* event_sending_controller.cc in Sources */, 4D4164FC0F212E6500F2F4A0 /* KeystoneGlue.m in Sources */, E45629170E26B4FE005E4685 /* layout_test_controller.cc in Sources */, - E45629150E26B4FE005E4685 /* main.mm in Sources */, 53E50D280ECA1B21001784B4 /* simple_clipboard_impl.cc in Sources */, E456296A0E26B64D005E4685 /* simple_resource_loader_bridge.cc in Sources */, E45629190E26B4FE005E4685 /* test_navigation_controller.cc in Sources */, E45449370EC9FD15000DFA6E /* test_shell.cc in Sources */, - E456291A0E26B4FE005E4685 /* test_shell_mac.mm in Sources */, E450637E0E4100740025A81A /* test_shell_request_context.cc in Sources */, E456290C0E26B4FE005E4685 /* test_shell_switches.cc in Sources */, E456291E0E26B4FE005E4685 /* test_shell_webview.mm in Sources */, @@ -1955,6 +1962,9 @@ E456291D0E26B4FE005E4685 /* text_input_controller.cc in Sources */, E456290F0E26B4FE005E4685 /* webview_host.mm in Sources */, E45629100E26B4FE005E4685 /* webwidget_host.mm in Sources */, + AB19AC150F1BBBD000673E20 /* test_shell_main.cc in Sources */, + AB19AC290F1BD6C900673E20 /* test_shell_platform_delegate_mac.mm in Sources */, + AB19AD380F1D0AF200673E20 /* test_shell_mac.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/webkit/tools/test_shell/mac/main.mm b/webkit/tools/test_shell/mac/main.mm deleted file mode 100644 index 1f73d53..0000000 --- a/webkit/tools/test_shell/mac/main.mm +++ /dev/null @@ -1,348 +0,0 @@ -// Copyright (c) 2008 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. - -#import <Cocoa/Cocoa.h> -#include <sys/syslimits.h> -#include <unistd.h> -#import <mach/task.h> - -#include <string> - -#include "base/at_exit.h" -#include "base/basictypes.h" -#include "base/command_line.h" -#include "base/file_util.h" -#include "base/icu_util.h" -#include "base/memory_debug.h" -#include "base/message_loop.h" -#include "base/path_service.h" -#include "base/string_util.h" -#include "net/base/cookie_monster.h" -#include "net/http/http_cache.h" -#include "webkit/glue/webkit_glue.h" -#include "webkit/tools/test_shell/simple_resource_loader_bridge.h" -#include "webkit/tools/test_shell/test_shell.h" -#include "webkit/tools/test_shell/test_shell_request_context.h" -#include "webkit/tools/test_shell/test_shell_switches.h" -#import "webkit/tools/test_shell/mac/KeystoneGlue.h" - -#include "WebSystemInterface.h" - -static char g_currentTestName[PATH_MAX]; - -static const char* kStatsFile = "testshell"; -static int kStatsFileThreads = 20; -static int kStatsFileCounters = 100; - -// Extracts the name of the test from the given path and sets the test name -// global. -static void SetCurrentTestName(char* path) { - char* lastSlash = strrchr(path, '/'); - if (lastSlash) { - ++lastSlash; - } else { - lastSlash = path; - } - - strncpy(g_currentTestName, lastSlash, PATH_MAX); - g_currentTestName[PATH_MAX-1] = '\0'; -} - -// The application delegate, used to hook application termination so that we -// can kill the TestShell object and do some other app-wide cleanup. Once we -// go into the run-loop, we never come back to main. -@interface TestShellAppDelegate : NSObject { - @private - TestShell* shell_; // strong -} -- (id)initWithShell:(TestShell*)shell; -@end - -@implementation TestShellAppDelegate -- (id)initWithShell:(TestShell*)shell { - if ((self = [super init])) { - shell_ = shell; - } - return self; -} - -- (void)dealloc { - // Flush any remaining messages. This ensures that any accumulated - // Task objects get destroyed before we exit, which avoids noise in - // purify leak-test results. - MessageLoop::current()->RunAllPending(); - - TestShell::ShutdownTestShell(); - - // get rid of the stats table last, V8 relies on it - StatsTable* table = StatsTable::current(); - StatsTable::set_current(NULL); - delete table; - - TestShell::CleanupLogging(); - - [super dealloc]; -} - -// Called because we're the NSApp's delegate. Destroy ourselves which forces -// shutdown cleanup to be called. -- (void)applicationWillTerminate:(id)sender { - // commit suicide. - [self release]; -} - -@end - -int main(const int argc, const char *argv[]) { - InitWebCoreSystemInterface(); - - // Some tests may use base::Singleton<>, thus we need to instantiate - // the AtExitManager or else we will leak objects. - base::AtExitManager at_exit_manager; - - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - // Allocate a message loop for this thread. Although it is not used - // directly, its constructor sets up some necessary state. - MessageLoop main_message_loop(MessageLoop::TYPE_UI); - - // Force AppKit to init itself, but don't start the runloop yet - [NSApplication sharedApplication]; - [NSBundle loadNibNamed:@"MainMenu" owner:NSApp]; - - // Interpret the same flags as - // the windows version, so that we can run the same test scripts. stop - // if we hit something that's not a switch (like, oh, a URL). - - CommandLine::Init(argc, argv); - const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess(); - - if (parsed_command_line.HasSwitch(test_shell::kCheckLayoutTestSystemDeps)) { - // Always succeed the deps check, currently just used by windows port. - exit(0); - } - - if (parsed_command_line.HasSwitch(test_shell::kStartupDialog)) { - //TODO: add alert to allow attaching via gdb before things really get going - } - - if (parsed_command_line.HasSwitch(test_shell::kCrashDumps)) { - std::wstring dir = - parsed_command_line.GetSwitchValue(test_shell::kCrashDumps); - // TODO: enable breakpad - // new google_breakpad::ExceptionHandler(dir, 0, &MinidumpCallback, 0, true); - } - - bool suppress_error_dialogs = (getenv("CHROME_HEADLESS") != NULL) || - parsed_command_line.HasSwitch(test_shell::kNoErrorDialogs) || - parsed_command_line.HasSwitch(test_shell::kLayoutTests); - bool layout_test_mode = - parsed_command_line.HasSwitch(test_shell::kLayoutTests); - - TestShell::InitLogging(suppress_error_dialogs, layout_test_mode, false); - TestShell::InitializeTestShell(layout_test_mode); - - bool no_tree = parsed_command_line.HasSwitch(test_shell::kNoTree); - - bool dump_pixels = parsed_command_line.HasSwitch(test_shell::kDumpPixels); - std::wstring pixel_file_name; - if (dump_pixels) { - pixel_file_name = - parsed_command_line.GetSwitchValue(test_shell::kDumpPixels); - if (pixel_file_name.size() == 0) { - fprintf(stderr, "No file specified for pixel tests"); - exit(1); - } - } - - if (parsed_command_line.HasSwitch(test_shell::kTestShellTimeOut)) { - const std::wstring timeout_str = parsed_command_line.GetSwitchValue( - test_shell::kTestShellTimeOut); - int timeout_ms = static_cast<int>(StringToInt64(timeout_str.c_str())); - if (timeout_ms > 0) - TestShell::SetFileTestTimeout(timeout_ms); - } - - std::wstring javascript_flags = - parsed_command_line.GetSwitchValue(test_shell::kJavaScriptFlags); - // Test shell always exposes the GC. - javascript_flags += L" --expose-gc"; - webkit_glue::SetJavaScriptFlags(javascript_flags); - - // Load and initialize the stats table (one per process, so that multiple - // instances don't interfere with each other) - char statsfile[64]; - snprintf(statsfile, 64, "%s-%d", kStatsFile, getpid()); - StatsTable *table = - new StatsTable(statsfile, kStatsFileThreads, kStatsFileCounters); - StatsTable::set_current(table); - - net::HttpCache::Mode cache_mode = net::HttpCache::NORMAL; - bool playback_mode = - parsed_command_line.HasSwitch(test_shell::kPlaybackMode); - bool record_mode = - parsed_command_line.HasSwitch(test_shell::kRecordMode); - - if (playback_mode) - cache_mode = net::HttpCache::PLAYBACK; - else if (record_mode) - cache_mode = net::HttpCache::RECORD; - - bool dump_stats_table = - parsed_command_line.HasSwitch(test_shell::kDumpStatsTable); - - bool debug_memory_in_use = - parsed_command_line.HasSwitch(test_shell::kDebugMemoryInUse); - - if (layout_test_mode || - parsed_command_line.HasSwitch(test_shell::kEnableFileCookies)) - net::CookieMonster::EnableFileScheme(); - - std::wstring cache_path = - parsed_command_line.GetSwitchValue(test_shell::kCacheDir); - if (cache_path.empty()) { - PathService::Get(base::DIR_EXE, &cache_path); - file_util::AppendToPath(&cache_path, L"cache"); - } - - // Initializing with a default context, which means no on-disk cookie DB, - // and no support for directory listings. - SimpleResourceLoaderBridge::Init( - new TestShellRequestContext(cache_path, cache_mode, layout_test_mode)); - - // Load ICU data tables - icu_util::Initialize(); - - // Config the network module so it has access to a limited set of resources. - // NetModule::SetResourceProvider(NetResourceProvider); - - // Treat the first loose value as the initial URL to open. - std::wstring uri; - - // Default to a homepage if we're interactive - if (!layout_test_mode) { - // If Keystone is available, set it up if needed and register with it. - [KeystoneGlue registerWithKeystone]; - - NSString *resourcePath = [[NSBundle mainBundle] resourcePath]; - NSString *testShellPath = - [resourcePath stringByAppendingPathComponent:@"test_shell/index.html"]; - // don't use NSURL; it puts a "localhost" bit in that freaks out our URL - // handling - NSString *testShellURL = [NSString stringWithFormat:@"file://%@", - testShellPath]; - uri = UTF8ToWide([testShellURL UTF8String]); - } - - std::vector<std::wstring> values = parsed_command_line.GetLooseValues(); - if (values.size() > 0) - uri = values[0]; - - TestShell* shell; - if (TestShell::CreateNewWindow(uri, &shell)) { -#ifdef NOTYET - if (record_mode || playback_mode) { - // Move the window to the upper left corner for consistent - // record/playback mode. For automation, we want this to work - // on build systems where the script invoking us is a background - // process. So for this case, make our window the topmost window - // as well. - // ForegroundHelper::SetForeground(shell->mainWnd()); - // ::SetWindowPos(shell->mainWnd(), HWND_TOP, 0, 0, 600, 800, 0); - // Tell webkit as well. - webkit_glue::SetRecordPlaybackMode(true); - } -#endif - shell->Show(shell->webView(), NEW_WINDOW); - - if (dump_stats_table) - shell->DumpStatsTableOnExit(); - -#ifdef NOTYET - if ((record_mode || playback_mode) && !no_events) { - std::string script_path = cache_path; - // Create the cache directory in case it doesn't exist. - file_util::CreateDirectory(cache_path); - file_util::AppendToPath(&script_path, "script.log"); - if (record_mode) - base::EventRecorder::current()->StartRecording(script_path); - if (playback_mode) - base::EventRecorder::current()->StartPlayback(script_path); - } -#endif - - if (debug_memory_in_use) { - base::MemoryDebug::SetMemoryInUseEnabled(true); - base::MemoryDebug::DumpAllMemoryInUse(); - } - - // Set up our app delegate so we can tear down the TestShell object when - // necessary. |delegate| takes ownership of |shell|, and will clean itself - // up when it receives the notification that the app is terminating. - TestShellAppDelegate* delegate = [[TestShellAppDelegate alloc] - initWithShell:shell]; - [[NSApplication sharedApplication] setDelegate:delegate]; - - if (layout_test_mode) { - // If we die during tests, we don't want to be spamming the user's crash - // reporter. Set our exception port to null. - if (task_set_exception_ports(mach_task_self(), - EXC_MASK_ALL, - MACH_PORT_NULL, - EXCEPTION_DEFAULT, - THREAD_STATE_NONE) != KERN_SUCCESS) { - return -1; - } - - // Cocoa housekeeping - [NSApp finishLaunching]; - webkit_glue::SetLayoutTestMode(true); - - // Set up for the kind of test requested. - TestShell::TestParams params; - if (dump_pixels) { - // The pixel test flag also gives the image file name to use. - params.dump_pixels = true; - params.pixel_file_name = pixel_file_name; - if (params.pixel_file_name.size() == 0) { - fprintf(stderr, "No file specified for pixel tests"); - exit(1); - } - } - if (no_tree) - params.dump_tree = false; - if (uri.length() == 0) { - // Watch stdin for URLs. - char filenameBuffer[2048]; - while (fgets(filenameBuffer, sizeof(filenameBuffer), stdin)) { - char *newLine = strchr(filenameBuffer, '\n'); - if (newLine) - *newLine = '\0'; - if (!*filenameBuffer) - continue; - - SetCurrentTestName(filenameBuffer); - params.test_url = filenameBuffer; - if (!TestShell::RunFileTest(params)) - break; - } - } else { - params.test_url = WideToUTF8(uri).c_str(); - TestShell::RunFileTest(params); - } - } else { - main_message_loop.Run(); - } - -#ifdef NOTYET - if (record_mode) - base::EventRecorder::current()->StopRecording(); - if (playback_mode) - base::EventRecorder::current()->StopPlayback(); -#endif - } - - [pool release]; - return 0; -} diff --git a/webkit/tools/test_shell/test_shell.vcproj b/webkit/tools/test_shell/test_shell.vcproj index b652571..c7e2d96 100644 --- a/webkit/tools/test_shell/test_shell.vcproj +++ b/webkit/tools/test_shell/test_shell.vcproj @@ -266,6 +266,14 @@ > </File> <File + RelativePath=".\test_shell_platform_delegate.h" + > + </File> + <File + RelativePath=".\test_shell_platform_delegate_win.cc" + > + </File> + <File RelativePath=".\test_shell_request_context.cc" > </File> diff --git a/webkit/tools/test_shell/test_shell_mac.mm b/webkit/tools/test_shell/test_shell_mac.mm index 789fc4e..0d004a5 100644 --- a/webkit/tools/test_shell/test_shell_mac.mm +++ b/webkit/tools/test_shell/test_shell_mac.mm @@ -48,7 +48,10 @@ #define MAX_LOADSTRING 100 +// Sizes for URL bar layout +#define BUTTON_HEIGHT 22 #define BUTTON_WIDTH 72 +#define BUTTON_MARGIN 8 #define URLBAR_HEIGHT 32 // Global Variables: @@ -157,230 +160,14 @@ void TestShell::PlatformShutdown() { [DumpRenderTreePasteboard releaseLocalPasteboards]; } -#if OBJC_API_VERSION == 2 -static void SwizzleAllMethods(Class imposter, Class original) { - unsigned int imposterMethodCount = 0; - Method* imposterMethods = class_copyMethodList(imposter, &imposterMethodCount); - - unsigned int originalMethodCount = 0; - Method* originalMethods = class_copyMethodList(original, &originalMethodCount); - - for (unsigned int i = 0; i < imposterMethodCount; i++) { - SEL imposterMethodName = method_getName(imposterMethods[i]); - - // Attempt to add the method to the original class. If it fails, the method - // already exists and we should instead exchange the implementations. - if (class_addMethod(original, - imposterMethodName, - method_getImplementation(originalMethods[i]), - method_getTypeEncoding(originalMethods[i]))) { - continue; - } - - unsigned int j = 0; - for (; j < originalMethodCount; j++) { - SEL originalMethodName = method_getName(originalMethods[j]); - if (sel_isEqual(imposterMethodName, originalMethodName)) { - break; - } - } - - // If class_addMethod failed above then the method must exist on the - // original class. - DCHECK(j < originalMethodCount) << "method wasn't found?"; - method_exchangeImplementations(imposterMethods[i], originalMethods[j]); - } - - if (imposterMethods) { - free(imposterMethods); - } - if (originalMethods) { - free(originalMethods); - } -} -#endif - -static void SwizzleNSPasteboard(void) { - // We replace NSPaseboard w/ the shim (from WebKit) that avoids having - // sideeffects w/ whatever the user does at the same time. - - Class imposterClass = objc_getClass("DumpRenderTreePasteboard"); - Class originalClass = objc_getClass("NSPasteboard"); -#if OBJC_API_VERSION == 0 - class_poseAs(imposterClass, originalClass); -#else - // Swizzle instance methods... - SwizzleAllMethods(imposterClass, originalClass); - // and then class methods. - SwizzleAllMethods(object_getClass(imposterClass), - object_getClass(originalClass)); -#endif -} - -static void SetDefaultsToLayoutTestValues(void) { - // So we can match the WebKit layout tests, we want to force a bunch of - // preferences that control appearance to match. - // (We want to do this as early as possible in application startup so - // the settings are in before any higher layers could cache values.) - - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - - const NSInteger kMinFontSizeCGSmoothes = 4; - const NSInteger kNoFontSmoothing = 0; - const NSInteger kBlueTintedAppearance = 1; - [defaults setInteger:kMinFontSizeCGSmoothes - forKey:@"AppleAntiAliasingThreshold"]; - [defaults setInteger:kNoFontSmoothing - forKey:@"AppleFontSmoothing"]; - [defaults setInteger:kBlueTintedAppearance - forKey:@"AppleAquaColorVariant"]; - [defaults setObject:@"0.709800 0.835300 1.000000" - forKey:@"AppleHighlightColor"]; - [defaults setObject:@"0.500000 0.500000 0.500000" - forKey:@"AppleOtherHighlightColor"]; - [defaults setObject:[NSArray arrayWithObject:@"en"] - forKey:@"AppleLanguages"]; - - // AppKit pulls scrollbar style from NSUserDefaults. HIToolbox uses - // CFPreferences, but AnyApplication, so we set it, force it to load, and - // then reset the pref to what it was (HIToolbox will cache what it loaded). - [defaults setObject:@"DoubleMax" forKey:@"AppleScrollBarVariant"]; - CFTypeRef initialValue - = CFPreferencesCopyValue(CFSTR("AppleScrollBarVariant"), - kCFPreferencesAnyApplication, - kCFPreferencesCurrentUser, - kCFPreferencesAnyHost); - CFPreferencesSetValue(CFSTR("AppleScrollBarVariant"), - CFSTR("DoubleMax"), - kCFPreferencesAnyApplication, - kCFPreferencesCurrentUser, - kCFPreferencesAnyHost); - // Make HIToolbox read from CFPreferences - ThemeScrollBarArrowStyle style; - GetThemeScrollBarArrowStyle(&style); - if (initialValue) { - // Reset the preference to what it was - CFPreferencesSetValue(CFSTR("AppleScrollBarVariant"), - initialValue, - kCFPreferencesAnyApplication, - kCFPreferencesCurrentUser, - kCFPreferencesAnyHost); - CFRelease(initialValue); - } -} - -static void ClearAnyDefaultsForLayoutTests(void) { - // Not running a test, clear the keys so the TestShell looks right to the - // running user. - - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - - [defaults removeObjectForKey:@"AppleAntiAliasingThreshold"]; - [defaults removeObjectForKey:@"AppleFontSmoothing"]; - [defaults removeObjectForKey:@"AppleAquaColorVariant"]; - [defaults removeObjectForKey:@"AppleHighlightColor"]; - [defaults removeObjectForKey:@"AppleOtherHighlightColor"]; - [defaults removeObjectForKey:@"AppleLanguages"]; - [defaults removeObjectForKey:@"AppleScrollBarVariant"]; -} - -static CMProfileRef gUsersColorProfile = NULL; - -static void RestoreUsersColorProfile(void) { - // This is called from the unsafe signal handers, so doing just about anything - // isn't really safe. But since we're already gonna crash, we give it a try - // anyways... (and WebKit uses this strategy...) - - if (gUsersColorProfile) { - CGDirectDisplayID displayID = CGMainDisplayID(); - CMError error = CMSetProfileByAVID((UInt32)displayID, gUsersColorProfile); - CMCloseProfile(gUsersColorProfile); - if (error) { - fprintf(stderr, "Failed to restore color profile, use System " - "Preferences -> Displays -> Color to reset. Error: %d", - (int)error); - } - gUsersColorProfile = NULL; - } -} - -static void SimpleSignalHandler(int sig) { - // Try to restore and try to go down cleanly - RestoreUsersColorProfile(); - exit(128 + sig); -} - -static void CrashSignalHandler(int sig) { - // Try to restore and get out fast... - RestoreUsersColorProfile(); - _exit(128 + sig); -} - -static void InstallLayoutTestColorProfile(void) { - // To make sure we get consisten colors (not dependent on the Main display), - // we force the generic rgb color profile. This cases a change the user can - // see. We use the same basic method as WebKit for trying to make sure we - // get the profile back if we go down in flames. - - // Save off the current - CGDirectDisplayID displayID = CGMainDisplayID(); - CMProfileRef previousProfile; - CMError error = CMGetProfileByAVID((UInt32)displayID, &previousProfile); - if (error) { - DLOG(WARNING) << "failed to get the current color profile, " - "pixmaps won't match. Error: " << (int)error; - return; - } - - // Install the generic one - NSColorSpace *genericSpace = [NSColorSpace genericRGBColorSpace]; - CMProfileRef genericProfile = (CMProfileRef)[genericSpace colorSyncProfile]; - if ((error = CMSetProfileByAVID((UInt32)displayID, genericProfile))) { - DLOG(WARNING) << "failed install the generic color profile, " - "pixmaps won't match. Error: " << (int)error; - return; - } - - // Save the starting profile, and hook in as best we can to make sure when - // we exit, it's restored (use atexit() so direct calls to exit() call us). - gUsersColorProfile = previousProfile; - atexit(RestoreUsersColorProfile); - // The less scary signals... - signal(SIGINT, SimpleSignalHandler); - signal(SIGHUP, SimpleSignalHandler); - signal(SIGTERM, SimpleSignalHandler); - // And now the scary ones... - signal(SIGILL, CrashSignalHandler); // 4: illegal instruction - signal(SIGTRAP, CrashSignalHandler); // 5: trace trap - signal(SIGEMT, CrashSignalHandler); // 7: EMT instruction - signal(SIGFPE, CrashSignalHandler); // 8: floating point exception - signal(SIGBUS, CrashSignalHandler); // 10: bus error - signal(SIGSEGV, CrashSignalHandler); // 11: segmentation violation - signal(SIGSYS, CrashSignalHandler); // 12: bad argument to system call - signal(SIGPIPE, CrashSignalHandler); // 13: write on a pipe with no reader - signal(SIGXCPU, CrashSignalHandler); // 24: exceeded CPU time limit - signal(SIGXFSZ, CrashSignalHandler); // 25: exceeded file size limit -} - // static void TestShell::InitializeTestShell(bool layout_test_mode) { // This should move to a per-process platform-specific initialization function // when one exists. - [NSApplication sharedApplication]; window_list_ = new WindowList; layout_test_mode_ = layout_test_mode; - if (layout_test_mode_) { - SwizzleNSPasteboard(); - SetDefaultsToLayoutTestValues(); - // If we could check the command line to see if we're doing pixel tests, - // then we only install the color profile in that case. - InstallLayoutTestColorProfile(); - } else { - ClearAnyDefaultsForLayoutTests(); - } - web_prefs_ = new WebPreferences; ResetWebPreferences(); @@ -450,8 +237,7 @@ bool TestShell::Initialize(const std::wstring& startingURL) { styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | - NSResizableWindowMask | - NSTexturedBackgroundWindowMask) + NSResizableWindowMask ) backing:NSBackingStoreBuffered defer:NO]; [m_mainWnd setTitle:@"TestShell"]; @@ -481,9 +267,10 @@ bool TestShell::Initialize(const std::wstring& startingURL) { // create buttons NSRect button_rect = [[m_mainWnd contentView] bounds]; - button_rect.origin.y = window_rect.size.height - 22; - button_rect.size.height = 22; - button_rect.origin.x += 16; + button_rect.origin.y = window_rect.size.height - URLBAR_HEIGHT + + (URLBAR_HEIGHT - BUTTON_HEIGHT) / 2; + button_rect.size.height = BUTTON_HEIGHT; + button_rect.origin.x += BUTTON_MARGIN; button_rect.size.width = BUTTON_WIDTH; NSView* content = [m_mainWnd contentView]; @@ -507,9 +294,9 @@ bool TestShell::Initialize(const std::wstring& startingURL) { [button setAction:@selector(stopLoading:)]; // text field for URL - button_rect.origin.x += 16; + button_rect.origin.x += BUTTON_MARGIN; button_rect.size.width = [[m_mainWnd contentView] bounds].size.width - - button_rect.origin.x - 32; + button_rect.origin.x - BUTTON_MARGIN; m_editWnd = [[NSTextField alloc] initWithFrame:button_rect]; [[m_mainWnd contentView] addSubview:m_editWnd]; [m_editWnd setAutoresizingMask:(NSViewWidthSizable | NSViewMinYMargin)]; @@ -595,7 +382,6 @@ void TestShell::TestFinished() { puts("#TEST_TIMED_OUT\n"); puts("#EOF\n"); fflush(stdout); - RestoreUsersColorProfile(); abort(); } diff --git a/webkit/tools/test_shell/test_shell_main.cc b/webkit/tools/test_shell/test_shell_main.cc index 3a52828..e895626 100644 --- a/webkit/tools/test_shell/test_shell_main.cc +++ b/webkit/tools/test_shell/test_shell_main.cc @@ -5,25 +5,10 @@ // Creates an instance of the test_shell. #include "build/build_config.h" -#include <stdlib.h> // required by _set_abort_behavior - -#if defined(OS_WIN) -#include <windows.h> -#include <commctrl.h> -#include "base/event_recorder.h" -#include "base/gfx/native_theme.h" -#include "base/resource_util.h" -#include "base/win_util.h" -#include "webkit/tools/test_shell/foreground_helper.h" -#endif - -#if defined(OS_LINUX) -#include <gtk/gtk.h> -#endif - #include "base/at_exit.h" #include "base/basictypes.h" #include "base/command_line.h" +#include "base/event_recorder.h" #include "base/file_util.h" #include "base/icu_util.h" #include "base/memory_debug.h" @@ -43,6 +28,7 @@ #include "webkit/glue/window_open_disposition.h" #include "webkit/tools/test_shell/simple_resource_loader_bridge.h" #include "webkit/tools/test_shell/test_shell.h" +#include "webkit/tools/test_shell/test_shell_platform_delegate.h" #include "webkit/tools/test_shell/test_shell_request_context.h" #include "webkit/tools/test_shell/test_shell_switches.h" @@ -58,93 +44,26 @@ static const char* kStatsFilePrefix = "testshell_"; static int kStatsFileThreads = 20; static int kStatsFileCounters = 200; -#if defined(OS_WIN) -// This test approximates whether you have the Windows XP theme selected by -// inspecting a couple of metrics. It does not catch all cases, but it does -// pick up on classic vs xp, and normal vs large fonts. Something it misses -// is changes to the color scheme (which will infact cause pixel test -// failures). -// -// ** Expected dependencies ** -// + Theme: Windows XP -// + Color scheme: Default (blue) -// + Font size: Normal -// + Font smoothing: off (minor impact). -// -bool HasLayoutTestThemeDependenciesWin() { - // This metric will be 17 when font size is "Normal". The size of drop-down - // menus depends on it. - if (::GetSystemMetrics(SM_CXVSCROLL) != 17) - return false; - - // Check that the system fonts RenderThemeWin relies on are Tahoma 11 pt. - NONCLIENTMETRICS metrics; - win_util::GetNonClientMetrics(&metrics); - LOGFONTW* system_fonts[] = - { &metrics.lfStatusFont, &metrics.lfMenuFont, &metrics.lfSmCaptionFont }; - - for (size_t i = 0; i < arraysize(system_fonts); ++i) { - if (system_fonts[i]->lfHeight != -11 || - 0 != wcscmp(L"Tahoma", system_fonts[i]->lfFaceName)) - return false; - } - return true; -} - -bool CheckLayoutTestSystemDependenciesWin() { - bool has_deps = HasLayoutTestThemeDependenciesWin(); - if (!has_deps) { - fprintf(stderr, - "\n" - "###############################################################\n" - "## Layout test system dependencies check failed.\n" - "## Some layout tests may fail due to unexpected theme.\n" - "##\n" - "## To fix, go to Display Properties -> Appearance, and select:\n" - "## + Windows and buttons: Windows XP style\n" - "## + Color scheme: Default (blue)\n" - "## + Font size: Normal\n" - "###############################################################\n"); - } - return has_deps; -} - -#endif - -bool CheckLayoutTestSystemDependencies() { -#if defined(OS_WIN) - return CheckLayoutTestSystemDependenciesWin(); -#else - return true; -#endif -} - } // namespace - int main(int argc, char* argv[]) { base::EnableTerminationOnHeapCorruption(); -#ifdef _CRTDBG_MAP_ALLOC - _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); - _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); -#endif + // Some tests may use base::Singleton<>, thus we need to instanciate // the AtExitManager or else we will leak objects. base::AtExitManager at_exit_manager; -#if defined(OS_LINUX) - gtk_init(&argc, &argv); -#endif - - // Only parse the command line after GTK's had a crack at it. + TestShellPlatformDelegate::PreflightArgs(&argc, &argv); CommandLine::Init(argc, argv); - const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess(); + + TestShellPlatformDelegate platform(parsed_command_line); + if (parsed_command_line.HasSwitch(test_shell::kStartupDialog)) TestShell::ShowStartupDebuggingDialog(); if (parsed_command_line.HasSwitch(test_shell::kCheckLayoutTestSystemDeps)) { - exit(CheckLayoutTestSystemDependencies() ? 0 : 1); + exit(platform.CheckLayoutTestSystemDependencies() ? 0 : 1); } // Allocate a message loop for this thread. Although it is not used @@ -159,10 +78,8 @@ int main(int argc, char* argv[]) { parsed_command_line.HasSwitch(test_shell::kLayoutTests); bool enable_gp_fault_error_box = false; -#if defined(OS_WIN) enable_gp_fault_error_box = parsed_command_line.HasSwitch(test_shell::kGPFaultErrorBox); -#endif TestShell::InitLogging(suppress_error_dialogs, layout_test_mode, enable_gp_fault_error_box); @@ -172,11 +89,9 @@ int main(int argc, char* argv[]) { // Suppress abort message in v8 library in debugging mode. // V8 calls abort() when it hits assertion errors. -#if defined(OS_WIN) if (suppress_error_dialogs) { - _set_abort_behavior(0, _WRITE_ABORT_MSG); + platform.SuppressErrorReporting(); } -#endif if (parsed_command_line.HasSwitch(test_shell::kEnableTracing)) base::TraceLog::StartTracing(); @@ -211,16 +126,7 @@ int main(int argc, char* argv[]) { // Load ICU data tables icu_util::Initialize(); - // Config the network module so it has access to a limited set of resources. - net::NetModule::SetResourceProvider(TestShell::NetResourceProvider); - -#if defined(OS_WIN) - INITCOMMONCONTROLSEX InitCtrlEx; - - InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX); - InitCtrlEx.dwICC = ICC_STANDARD_CLASSES; - InitCommonControlsEx(&InitCtrlEx); -#endif + platform.InitializeGUI(); TestShell::InitializeTestShell(layout_test_mode); @@ -229,16 +135,7 @@ int main(int argc, char* argv[]) { // Disable user themes for layout tests so pixel tests are consistent. if (layout_test_mode) { -#if defined(OS_WIN) - gfx::NativeTheme::instance()->DisableTheming(); -#elif defined(OS_LINUX) - // Pick a theme that uses Cairo for drawing, since we: - // 1) currently don't support GTK themes that use the GDK drawing APIs, and - // 2) need to use a unified theme for layout tests anyway. - g_object_set(gtk_settings_get_default(), - "gtk-theme-name", "Mist", - NULL); -#endif + platform.SelectUnifiedTheme(); } if (parsed_command_line.HasSwitch(test_shell::kTestShellTimeOut)) { @@ -249,11 +146,6 @@ int main(int argc, char* argv[]) { TestShell::SetFileTestTimeout(timeout_ms); } -#if defined(OS_WIN) - // Initialize global strings - TestShell::RegisterWindowClass(); -#endif - // Treat the first loose value as the initial URL to open. std::wstring uri; @@ -281,33 +173,26 @@ int main(int argc, char* argv[]) { // Load and initialize the stats table. Attempt to construct a somewhat // unique name to isolate separate instances from each other. StatsTable *table = new StatsTable( - kStatsFilePrefix + Uint64ToString(base::RandUint64()), + // truncate the random # to 32 bits for the benefit of Mac OS X, to + // avoid tripping over its maximum shared memory segment name length + kStatsFilePrefix + Uint64ToString(base::RandUint64() & 0xFFFFFFFFL), kStatsFileThreads, kStatsFileCounters); StatsTable::set_current(table); TestShell* shell; if (TestShell::CreateNewWindow(uri, &shell)) { -#if defined(OS_WIN) if (record_mode || playback_mode) { - // Move the window to the upper left corner for consistent - // record/playback mode. For automation, we want this to work - // on build systems where the script invoking us is a background - // process. So for this case, make our window the topmost window - // as well. - ForegroundHelper::SetForeground(shell->mainWnd()); - ::SetWindowPos(shell->mainWnd(), HWND_TOP, 0, 0, 600, 800, 0); + platform.SetWindowPositionForRecording(shell); // Tell webkit as well. webkit_glue::SetRecordPlaybackMode(true); } -#endif shell->Show(shell->webView(), NEW_WINDOW); if (parsed_command_line.HasSwitch(test_shell::kDumpStatsTable)) shell->DumpStatsTableOnExit(); -#if defined(OS_WIN) bool no_events = parsed_command_line.HasSwitch(test_shell::kNoEvents); if ((record_mode || playback_mode) && !no_events) { std::wstring script_path = cache_path; @@ -319,7 +204,6 @@ int main(int argc, char* argv[]) { if (playback_mode) base::EventRecorder::current()->StartPlayback(script_path); } -#endif if (parsed_command_line.HasSwitch(test_shell::kDebugMemoryInUse)) { base::MemoryDebug::SetMemoryInUseEnabled(true); @@ -382,12 +266,10 @@ int main(int argc, char* argv[]) { // purify leak-test results. MessageLoop::current()->RunAllPending(); -#if defined(OS_WIN) if (record_mode) base::EventRecorder::current()->StopRecording(); if (playback_mode) base::EventRecorder::current()->StopPlayback(); -#endif } TestShell::ShutdownTestShell(); @@ -397,8 +279,5 @@ int main(int argc, char* argv[]) { StatsTable::set_current(NULL); delete table; -#ifdef _CRTDBG_MAP_ALLOC - _CrtDumpMemoryLeaks(); -#endif return 0; } diff --git a/webkit/tools/test_shell/test_shell_platform_delegate.h b/webkit/tools/test_shell/test_shell_platform_delegate.h new file mode 100644 index 0000000..5be147a --- /dev/null +++ b/webkit/tools/test_shell/test_shell_platform_delegate.h @@ -0,0 +1,58 @@ +// Copyright (c) 2009 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. + +// TestShellPlatformDelegate isolates a variety of platform-specific +// functions so that code can invoke them by purpose without resorting to +// ifdefs or runtime platform checks. Each platform should define an +// implementation of this class. In many cases, implementation of methods +// in this class will be stubs on platforms where those functions are +// unnecessary. + +class TestShellPlatformDelegate { + public: + // The TestShellPlatformDelegate object is scoped to main(), and so + // its constructor is a good place to put per-application initialization + // (as opposed to per-test code, which should go into the TestShell class). + TestShellPlatformDelegate(const CommandLine& command_line); + ~TestShellPlatformDelegate(); + + // EnableMemoryDebugging: turn on platform memory debugging assistance + // (console messages, heap checking, leak detection, etc.). + void EnableMemoryDebugging(); + + // CheckLayoutTestSystemDependencies: check for any system dependencies that + // can't be easily overridden from within an application (for example, UI or + // display settings). Returns false if any dependencies are not met. + bool CheckLayoutTestSystemDependencies(); + + // PreflightArgs: give the platform first crack at the arguments to main() + // before we parse the command line. For example, some UI toolkits have + // runtime flags that they can pre-filter. + static void PreflightArgs(int* argc, char*** argv); + + // SuppressErrorReporting: if possible, turn off platform error reporting + // dialogs, crash dumps, etc. + void SuppressErrorReporting(); + + // InitializeGUI: do any special initialization that the UI needs before + // we start the main message loop + void InitializeGUI(); + + // SelectUnifiedTheme: override user preferences so that the UI theme matches + // what's in the baseline files. Whenever possible, override user settings + // here rather than testing them in CheckLayoutTestSystemDependencies. + void SelectUnifiedTheme(); + + // AboutToExit: give the platform delegate a last chance to restore platform + // settings. Normally called by the destructor, but also called before + // abort() (example: test timeouts). + void AboutToExit(); + + // SetWindowPositionForRecording: if the platform's implementation of + // EventRecorder requires the window to be in a particular absolute position, + // make it so. This is called by TestShell after it creates the window. + void SetWindowPositionForRecording(TestShell *shell); + private: + const CommandLine& command_line_; +}; diff --git a/webkit/tools/test_shell/test_shell_platform_delegate_gtk.cc b/webkit/tools/test_shell/test_shell_platform_delegate_gtk.cc new file mode 100644 index 0000000..8846f19 --- /dev/null +++ b/webkit/tools/test_shell/test_shell_platform_delegate_gtk.cc @@ -0,0 +1,44 @@ +// Copyright (c) 2009 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. + +#include <stdlib.h> // required by _set_abort_behavior +#include <gtk/gtk.h> + +#include "base/command_line.h" +#include "webkit/tools/test_shell/test_shell.h" +#include "webkit/tools/test_shell/test_shell_platform_delegate.h" + +void TestShellPlatformDelegate::PreflightArgs(int *argc, char ***argv) { + gtk_init(argc, argv); +} + +void TestShellPlatformDelegate::SelectUnifiedTheme() { + // Pick a theme that uses Cairo for drawing, since we: + // 1) currently don't support GTK themes that use the GDK drawing APIs, and + // 2) need to use a unified theme for layout tests anyway. + g_object_set(gtk_settings_get_default(), + "gtk-theme-name", "Mist", + NULL); +} + +TestShellPlatformDelegate::TestShellPlatformDelegate( + const CommandLine& command_line) + : command_line_(command_line) { +} + +bool TestShellPlatformDelegate::CheckLayoutTestSystemDependencies() { + return true; +} + +void TestShellPlatformDelegate::SuppressErrorReporting() { +} + +void TestShellPlatformDelegate::InitializeGUI() { +} + +void TestShellPlatformDelegate::SetWindowPositionForRecording(TestShell *) { +} + +TestShellPlatformDelegate::~TestShellPlatformDelegate() { +} diff --git a/webkit/tools/test_shell/test_shell_platform_delegate_mac.mm b/webkit/tools/test_shell/test_shell_platform_delegate_mac.mm new file mode 100644 index 0000000..3642e35 --- /dev/null +++ b/webkit/tools/test_shell/test_shell_platform_delegate_mac.mm @@ -0,0 +1,286 @@ +// Copyright (c) 2006-2009 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. + +#include "build/build_config.h" + +// #include <Carbon/Carbon.h> +// #include <ApplicationServices/ApplicationServices.h> +#import <Cocoa/Cocoa.h> +#import <objc/objc-runtime.h> +#include <sys/syslimits.h> +#include <unistd.h> +#include <string> +#include <stdlib.h> +#include <mach/task.h> + +#include "base/command_line.h" +#include "base/logging.h" +#include "webkit/tools/test_shell/test_shell.h" +#include "webkit/tools/test_shell/test_shell_platform_delegate.h" +#include "webkit/tools/test_shell/test_shell_switches.h" +#include "WebSystemInterface.h" + +static NSAutoreleasePool *gTestShellAutoreleasePool = nil; + +static void SetDefaultsToLayoutTestValues(void) { + // So we can match the WebKit layout tests, we want to force a bunch of + // preferences that control appearance to match. + // (We want to do this as early as possible in application startup so + // the settings are in before any higher layers could cache values.) + + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + + const NSInteger kMinFontSizeCGSmoothes = 4; + const NSInteger kNoFontSmoothing = 0; + const NSInteger kBlueTintedAppearance = 1; + [defaults setInteger:kMinFontSizeCGSmoothes + forKey:@"AppleAntiAliasingThreshold"]; + [defaults setInteger:kNoFontSmoothing + forKey:@"AppleFontSmoothing"]; + [defaults setInteger:kBlueTintedAppearance + forKey:@"AppleAquaColorVariant"]; + [defaults setObject:@"0.709800 0.835300 1.000000" + forKey:@"AppleHighlightColor"]; + [defaults setObject:@"0.500000 0.500000 0.500000" + forKey:@"AppleOtherHighlightColor"]; + [defaults setObject:[NSArray arrayWithObject:@"en"] + forKey:@"AppleLanguages"]; + + // AppKit pulls scrollbar style from NSUserDefaults. HIToolbox uses + // CFPreferences, but AnyApplication, so we set it, force it to load, and + // then reset the pref to what it was (HIToolbox will cache what it loaded). + [defaults setObject:@"DoubleMax" forKey:@"AppleScrollBarVariant"]; + CFTypeRef initialValue = + CFPreferencesCopyValue(CFSTR("AppleScrollBarVariant"), + kCFPreferencesAnyApplication, + kCFPreferencesCurrentUser, + kCFPreferencesAnyHost); + CFPreferencesSetValue(CFSTR("AppleScrollBarVariant"), + CFSTR("DoubleMax"), + kCFPreferencesAnyApplication, + kCFPreferencesCurrentUser, + kCFPreferencesAnyHost); + // Make HIToolbox read from CFPreferences + ThemeScrollBarArrowStyle style; + GetThemeScrollBarArrowStyle(&style); + if (initialValue) { + // Reset the preference to what it was + CFPreferencesSetValue(CFSTR("AppleScrollBarVariant"), + initialValue, + kCFPreferencesAnyApplication, + kCFPreferencesCurrentUser, + kCFPreferencesAnyHost); + CFRelease(initialValue); + } +} + +static void ClearAnyDefaultsForLayoutTests(void) { + // Not running a test, clear the keys so the TestShell looks right to the + // running user. + + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + + [defaults removeObjectForKey:@"AppleAntiAliasingThreshold"]; + [defaults removeObjectForKey:@"AppleFontSmoothing"]; + [defaults removeObjectForKey:@"AppleAquaColorVariant"]; + [defaults removeObjectForKey:@"AppleHighlightColor"]; + [defaults removeObjectForKey:@"AppleOtherHighlightColor"]; + [defaults removeObjectForKey:@"AppleLanguages"]; + [defaults removeObjectForKey:@"AppleScrollBarVariant"]; +} + +static CMProfileRef gUsersColorProfile = NULL; + +static void RestoreUsersColorProfile(void) { + // This is called from the unsafe signal handers, so doing just about anything + // isn't really safe. But since we're already gonna crash, we give it a try + // anyways... (and WebKit uses this strategy...) + + if (gUsersColorProfile) { + CGDirectDisplayID displayID = CGMainDisplayID(); + CMError error = CMSetProfileByAVID((UInt32)displayID, gUsersColorProfile); + CMCloseProfile(gUsersColorProfile); + if (error) { + fprintf(stderr, "Failed to restore color profile, use System " + "Preferences -> Displays -> Color to reset. Error: %d", + (int)error); + } + gUsersColorProfile = NULL; + } +} + +static void SimpleSignalHandler(int sig) { + // Try to restore and try to go down cleanly + RestoreUsersColorProfile(); + exit(128 + sig); +} + +static void CrashSignalHandler(int sig) { + // Try to restore and get out fast... + RestoreUsersColorProfile(); + _exit(128 + sig); +} + +static void InstallLayoutTestColorProfile(void) { + // To make sure we get consisten colors (not dependent on the Main display), + // we force the generic rgb color profile. This cases a change the user can + // see. We use the same basic method as WebKit for trying to make sure we + // get the profile back if we go down in flames. + + // Save off the current + CGDirectDisplayID displayID = CGMainDisplayID(); + CMProfileRef previousProfile; + CMError error = CMGetProfileByAVID((UInt32)displayID, &previousProfile); + if (error) { + DLOG(WARNING) << "failed to get the current color profile, " + "pixmaps won't match. Error: " << (int)error; + return; + } + + // Install the generic one + NSColorSpace *genericSpace = [NSColorSpace genericRGBColorSpace]; + CMProfileRef genericProfile = (CMProfileRef)[genericSpace colorSyncProfile]; + if ((error = CMSetProfileByAVID((UInt32)displayID, genericProfile))) { + DLOG(WARNING) << "failed install the generic color profile, " + "pixmaps won't match. Error: " << (int)error; + return; + } + + // Save the starting profile, and hook in as best we can to make sure when + // we exit, it's restored (use atexit() so direct calls to exit() call us). + gUsersColorProfile = previousProfile; + atexit(RestoreUsersColorProfile); + // The less scary signals... + signal(SIGINT, SimpleSignalHandler); + signal(SIGHUP, SimpleSignalHandler); + signal(SIGTERM, SimpleSignalHandler); + // And now the scary ones... + signal(SIGABRT, CrashSignalHandler); // abort() called + signal(SIGILL, CrashSignalHandler); // 4: illegal instruction + signal(SIGTRAP, CrashSignalHandler); // 5: trace trap + signal(SIGEMT, CrashSignalHandler); // 7: EMT instruction + signal(SIGFPE, CrashSignalHandler); // 8: floating point exception + signal(SIGBUS, CrashSignalHandler); // 10: bus error + signal(SIGSEGV, CrashSignalHandler); // 11: segmentation violation + signal(SIGSYS, CrashSignalHandler); // 12: bad argument to system call + signal(SIGPIPE, CrashSignalHandler); // 13: write on a pipe with no reader + signal(SIGXCPU, CrashSignalHandler); // 24: exceeded CPU time limit + signal(SIGXFSZ, CrashSignalHandler); // 25: exceeded file size limit +} + +#if OBJC_API_VERSION == 2 +static void SwizzleAllMethods(Class imposter, Class original) { + unsigned int imposterMethodCount = 0; + Method* imposterMethods = class_copyMethodList(imposter, &imposterMethodCount); + + unsigned int originalMethodCount = 0; + Method* originalMethods = class_copyMethodList(original, &originalMethodCount); + + for (unsigned int i = 0; i < imposterMethodCount; i++) { + SEL imposterMethodName = method_getName(imposterMethods[i]); + + // Attempt to add the method to the original class. If it fails, the method + // already exists and we should instead exchange the implementations. + if (class_addMethod(original, + imposterMethodName, + method_getImplementation(originalMethods[i]), + method_getTypeEncoding(originalMethods[i]))) { + continue; + } + + unsigned int j = 0; + for (; j < originalMethodCount; j++) { + SEL originalMethodName = method_getName(originalMethods[j]); + if (sel_isEqual(imposterMethodName, originalMethodName)) { + break; + } + } + + // If class_addMethod failed above then the method must exist on the + // original class. + DCHECK(j < originalMethodCount) << "method wasn't found?"; + method_exchangeImplementations(imposterMethods[i], originalMethods[j]); + } + + if (imposterMethods) { + free(imposterMethods); + } + if (originalMethods) { + free(originalMethods); + } +} +#endif + +static void SwizzleNSPasteboard(void) { + // We replace NSPaseboard w/ the shim (from WebKit) that avoids having + // sideeffects w/ whatever the user does at the same time. + + Class imposterClass = objc_getClass("DumpRenderTreePasteboard"); + Class originalClass = objc_getClass("NSPasteboard"); +#if OBJC_API_VERSION == 0 + class_poseAs(imposterClass, originalClass); +#else + // Swizzle instance methods... + SwizzleAllMethods(imposterClass, originalClass); + // and then class methods. + SwizzleAllMethods(object_getClass(imposterClass), + object_getClass(originalClass)); +#endif +} + +TestShellPlatformDelegate::TestShellPlatformDelegate( + const CommandLine &command_line) + : command_line_(command_line) { + gTestShellAutoreleasePool = [[NSAutoreleasePool alloc] init]; + InitWebCoreSystemInterface(); + // Force AppKit to init itself, but don't start the runloop yet + [NSApplication sharedApplication]; + [NSBundle loadNibNamed:@"MainMenu" owner:NSApp]; +} + +TestShellPlatformDelegate::~TestShellPlatformDelegate() { + // if we have changed the user's display color profile for pixel tests, + // restore it. + RestoreUsersColorProfile(); + [gTestShellAutoreleasePool release]; +} + +bool TestShellPlatformDelegate::CheckLayoutTestSystemDependencies() { + return true; +} + +void TestShellPlatformDelegate::InitializeGUI() { + if (command_line_.HasSwitch(test_shell::kLayoutTests)) { + // If we're doing automated testing, we won't be using a conventional + // run loop, so tell Cocoa to finish initializing. + [NSApp finishLaunching]; + } +} + +void TestShellPlatformDelegate::PreflightArgs(int *argc, char ***argv) { +} + +void TestShellPlatformDelegate::SetWindowPositionForRecording(TestShell *) { +} + +void TestShellPlatformDelegate::SelectUnifiedTheme() { + if (command_line_.HasSwitch(test_shell::kLayoutTests)) { + SetDefaultsToLayoutTestValues(); + SwizzleNSPasteboard(); + + if (command_line_.HasSwitch(test_shell::kDumpPixels)) { + InstallLayoutTestColorProfile(); + } + } else { + ClearAnyDefaultsForLayoutTests(); + } +} + +void TestShellPlatformDelegate::SuppressErrorReporting() { + // If we die during tests, we don't want to be spamming the user's crash + // reporter. Set our exception port to null. + task_set_exception_ports(mach_task_self(), EXC_MASK_ALL, MACH_PORT_NULL, + EXCEPTION_DEFAULT, THREAD_STATE_NONE); +} + diff --git a/webkit/tools/test_shell/test_shell_platform_delegate_win.cc b/webkit/tools/test_shell/test_shell_platform_delegate_win.cc new file mode 100644 index 0000000..d03dc5f --- /dev/null +++ b/webkit/tools/test_shell/test_shell_platform_delegate_win.cc @@ -0,0 +1,110 @@ +// Copyright (c) 2006-2009 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. + +#include <windows.h> +#include <commctrl.h> +#include "base/command_line.h" +#include "base/event_recorder.h" +#include "base/gfx/native_theme.h" +#include "base/resource_util.h" +#include "base/win_util.h" +#include "webkit/tools/test_shell/foreground_helper.h" +#include "webkit/tools/test_shell/test_shell.h" +#include "webkit/tools/test_shell/test_shell_platform_delegate.h" + +TestShellPlatformDelegate::TestShellPlatformDelegate( + const CommandLine& command_line) + : command_line_(command_line) { +#ifdef _CRTDBG_MAP_ALLOC + _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); + _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); +#endif +} + +TestShellPlatformDelegate::~TestShellPlatformDelegate() { +#ifdef _CRTDBG_MAP_ALLOC + _CrtDumpMemoryLeaks(); +#endif +} + +void TestShellPlatformDelegate::PreflightArgs(int *argc, char ***argv) { +} + +// This test approximates whether you have the Windows XP theme selected by +// inspecting a couple of metrics. It does not catch all cases, but it does +// pick up on classic vs xp, and normal vs large fonts. Something it misses +// is changes to the color scheme (which will infact cause pixel test +// failures). +// +// ** Expected dependencies ** +// + Theme: Windows XP +// + Color scheme: Default (blue) +// + Font size: Normal +// + Font smoothing: off (minor impact). +// +static bool HasLayoutTestThemeDependenciesWin() { + // This metric will be 17 when font size is "Normal". The size of drop-down + // menus depends on it. + if (::GetSystemMetrics(SM_CXVSCROLL) != 17) + return false; + + // Check that the system fonts RenderThemeWin relies on are Tahoma 11 pt. + NONCLIENTMETRICS metrics; + win_util::GetNonClientMetrics(&metrics); + LOGFONTW* system_fonts[] = + { &metrics.lfStatusFont, &metrics.lfMenuFont, &metrics.lfSmCaptionFont }; + + for (size_t i = 0; i < arraysize(system_fonts); ++i) { + if (system_fonts[i]->lfHeight != -11 || + 0 != wcscmp(L"Tahoma", system_fonts[i]->lfFaceName)) + return false; + } + return true; +} + +bool TestShellPlatformDelegate::CheckLayoutTestSystemDependencies() { + bool has_deps = HasLayoutTestThemeDependenciesWin(); + if (!has_deps) { + fprintf(stderr, + "\n" + "###############################################################\n" + "## Layout test system dependencies check failed.\n" + "## Some layout tests may fail due to unexpected theme.\n" + "##\n" + "## To fix, go to Display Properties -> Appearance, and select:\n" + "## + Windows and buttons: Windows XP style\n" + "## + Color scheme: Default (blue)\n" + "## + Font size: Normal\n" + "###############################################################\n"); + } + return has_deps; +} + +void TestShellPlatformDelegate::SuppressErrorReporting() { + _set_abort_behavior(0, _WRITE_ABORT_MSG); +} + +void TestShellPlatformDelegate::InitializeGUI() { + INITCOMMONCONTROLSEX InitCtrlEx; + + InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX); + InitCtrlEx.dwICC = ICC_STANDARD_CLASSES; + InitCommonControlsEx(&InitCtrlEx); + TestShell::RegisterWindowClass(); +} + +void TestShellPlatformDelegate::SelectUnifiedTheme() { + gfx::NativeTheme::instance()->DisableTheming(); +} + +void TestShellPlatformDelegate::SetWindowPositionForRecording( + TestShell *shell) { + // Move the window to the upper left corner for consistent + // record/playback mode. For automation, we want this to work + // on build systems where the script invoking us is a background + // process. So for this case, make our window the topmost window + // as well. + ForegroundHelper::SetForeground(shell->mainWnd()); + ::SetWindowPos(shell->mainWnd(), HWND_TOP, 0, 0, 600, 800, 0); +} diff --git a/webkit/tools/test_shell/test_shell_tests.vcproj b/webkit/tools/test_shell/test_shell_tests.vcproj index 2b0bb22..3251e8c 100644 --- a/webkit/tools/test_shell/test_shell_tests.vcproj +++ b/webkit/tools/test_shell/test_shell_tests.vcproj @@ -226,6 +226,14 @@ RelativePath=".\resources\test_shell.rc" > </File> + <File + RelativePath=".\test_shell_platform_delegate.h" + > + </File> + <File + RelativePath=".\test_shell_platform_delegate_win.cc" + > + </File> <File RelativePath=".\test_shell_request_context.cc" > diff --git a/webkit/tools/test_shell/test_shell_win.cc b/webkit/tools/test_shell/test_shell_win.cc index 28fabc5..3f82fe8 100644 --- a/webkit/tools/test_shell/test_shell_win.cc +++ b/webkit/tools/test_shell/test_shell_win.cc @@ -22,6 +22,7 @@ #include "base/trace_event.h" #include "base/win_util.h" #include "breakpad/src/client/windows/handler/exception_handler.h" +#include "net/base/net_module.h" #include "net/http/http_network_layer.h" #include "net/url_request/url_request_file_job.h" #include "skia/ext/bitmap_platform_device.h" @@ -126,7 +127,7 @@ FilePath GetResourcesFilePath() { return path.AppendASCII("resources"); } -StringPiece GetRawDataResource(HMODULE module, int resource_id) { +static StringPiece GetRawDataResource(HMODULE module, int resource_id) { void* data_ptr; size_t data_size; return base::GetDataResourceFromModule(module, resource_id, &data_ptr, @@ -134,6 +135,11 @@ StringPiece GetRawDataResource(HMODULE module, int resource_id) { StringPiece(static_cast<char*>(data_ptr), data_size) : StringPiece(); } +// This is called indirectly by the network layer to access resources. +StringPiece NetResourceProvider(int key) { + return GetRawDataResource(::GetModuleHandle(NULL), key); +} + } // namespace // Initialize static member variable @@ -143,6 +149,8 @@ HINSTANCE TestShell::instance_handle_; // static methods on TestShell void TestShell::InitializeTestShell(bool layout_test_mode) { + net::NetModule::SetResourceProvider(NetResourceProvider); + // Start COM stuff. HRESULT res = OleInitialize(NULL); DCHECK(SUCCEEDED(res)); |