summaryrefslogtreecommitdiffstats
path: root/webkit
diff options
context:
space:
mode:
authortc@google.com <tc@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-29 22:56:12 +0000
committertc@google.com <tc@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-29 22:56:12 +0000
commit27d8c1ba2b7990e45e8498264224a11a082d5b82 (patch)
tree7a884086f01f7687cef6aa2fab1e85815233b1a5 /webkit
parentea3f5cf79a8e5d9cd9825bcbc71d448534350135 (diff)
downloadchromium_src-27d8c1ba2b7990e45e8498264224a11a082d5b82.zip
chromium_src-27d8c1ba2b7990e45e8498264224a11a082d5b82.tar.gz
chromium_src-27d8c1ba2b7990e45e8498264224a11a082d5b82.tar.bz2
Split test_shell.cc into test_shell.cc and test_shell_win.cc.
This currently moves too much code out of test_shell.cc, but I wanted to be able to just move code now and I'll refactor stuff back into test_shell.cc I also tried to make test_shell_win.cc conform to google style. Review URL: http://codereview.chromium.org/8209 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@4182 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r--webkit/tools/test_shell/SConscript1
-rw-r--r--webkit/tools/test_shell/test_shell.cc736
-rw-r--r--webkit/tools/test_shell/test_shell.h4
-rw-r--r--webkit/tools/test_shell/test_shell.vcproj4
-rw-r--r--webkit/tools/test_shell/test_shell_tests.vcproj4
-rw-r--r--webkit/tools/test_shell/test_shell_win.cc740
6 files changed, 760 insertions, 729 deletions
diff --git a/webkit/tools/test_shell/SConscript b/webkit/tools/test_shell/SConscript
index 23ba6020..70c9260 100644
--- a/webkit/tools/test_shell/SConscript
+++ b/webkit/tools/test_shell/SConscript
@@ -106,6 +106,7 @@ if env['PLATFORM'] == 'win32':
'event_sending_controller.cc',
'layout_test_controller.cc',
'test_shell.cc',
+ 'test_shell_win.cc',
'test_webview_delegate.cc',
'text_input_controller.cc',
'webview_host.cc',
diff --git a/webkit/tools/test_shell/test_shell.cc b/webkit/tools/test_shell/test_shell.cc
index 202552b..fcbc730 100644
--- a/webkit/tools/test_shell/test_shell.cc
+++ b/webkit/tools/test_shell/test_shell.cc
@@ -2,30 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <windows.h>
-#include <atlbase.h>
-#include <commdlg.h>
-#include <objbase.h>
-#include <shlwapi.h>
-#include <wininet.h>
-
#include "webkit/tools/test_shell/test_shell.h"
#include "base/command_line.h"
#include "base/debug_on_start.h"
#include "base/file_util.h"
-#include "base/gfx/bitmap_platform_device_win.h"
-#include "base/gfx/png_encoder.h"
+#include "base/gfx/bitmap_platform_device.h"
#include "base/gfx/size.h"
#include "base/icu_util.h"
-#include "base/md5.h"
-#include "base/memory_debug.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/stats_table.h"
#include "base/string_util.h"
-#include "base/trace_event.h"
-#include "base/win_util.h"
#include "googleurl/src/url_util.h"
#include "net/base/mime_util.h"
#include "net/url_request/url_request_file_job.h"
@@ -40,28 +28,12 @@
#include "webkit/glue/webview.h"
#include "webkit/glue/webwidget.h"
#include "webkit/glue/plugins/plugin_list.h"
-#include "webkit/tools/test_shell/simple_resource_loader_bridge.h"
#include "webkit/tools/test_shell/test_navigation_controller.h"
#include "webkit_strings.h"
#include "SkBitmap.h"
-using std::min;
-using std::max;
-
-#define MAX_LOADSTRING 100
-
-#define BUTTON_WIDTH 72
-#define URLBAR_HEIGHT 24
-
-// Global Variables:
-static TCHAR g_windowTitle[MAX_LOADSTRING]; // The title bar text
-static TCHAR g_windowClass[MAX_LOADSTRING]; // The main window class name
-
-// Forward declarations of functions included in this code module:
-static INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
-
// Default timeout for page load when running non-interactive file
// tests, in ms.
const int kDefaultFileTestTimeoutMillisecs = 10 * 1000;
@@ -70,22 +42,8 @@ const int kDefaultFileTestTimeoutMillisecs = 10 * 1000;
const int kTestWindowWidth = 800;
const int kTestWindowHeight = 600;
-// The W3C SVG layout tests use a different size than the other layout tests
-const int kSVGTestWindowWidth = 480;
-const int kSVGTestWindowHeight = 360;
-
-// Hide the window offscreen when it is non-interactive.
-// This would correspond with a minimized window position if x = y = -32000.
-// However we shift the x to 0 to pass test cross-frame-access-put.html
-// which expects screenX/screenLeft to be 0 (http://b/issue?id=1227945).
-// TODO(ericroman): x should be defined as 0 rather than -4. There is
-// probably a frameborder not being accounted for in the setting/getting.
-const int kTestWindowXLocation = -4;
-const int kTestWindowYLocation = -32000;
-
// Initialize static member variable
WindowList* TestShell::window_list_;
-HINSTANCE TestShell::instance_handle_;
WebPreferences* TestShell::web_prefs_ = NULL;
bool TestShell::interactive_ = true;
int TestShell::file_test_timeout_ms_ = kDefaultFileTestTimeoutMillisecs;
@@ -111,7 +69,7 @@ class URLRequestTestShellFileJob : public URLRequestFileJob {
this->file_path_ = path; // set URLRequestFileJob::file_path_
}
- DISALLOW_EVIL_CONSTRUCTORS(URLRequestTestShellFileJob);
+ DISALLOW_COPY_AND_ASSIGN(URLRequestTestShellFileJob);
};
TestShell::TestShell()
@@ -121,11 +79,11 @@ TestShell::TestShell()
m_popupHost(NULL),
m_focusedWidgetHost(NULL),
default_edit_wnd_proc_(0),
- delegate_(new TestWebViewDelegate(this)),
test_is_preparing_(false),
test_is_pending_(false),
is_modal_(false),
dump_stats_table_on_exit_(false) {
+ delegate_ = new TestWebViewDelegate(this);
layout_test_controller_.reset(new LayoutTestController(this));
event_sending_controller_.reset(new EventSendingController(this));
text_input_controller_.reset(new TextInputController(this));
@@ -137,16 +95,14 @@ TestShell::TestShell()
url_util::AddStandardScheme("test-shell-resource");
}
+
TestShell::~TestShell() {
// Call GC twice to clean up garbage.
CallJSGC();
CallJSGC();
- // When the window is destroyed, tell the Edit field to forget about us,
- // otherwise we will crash.
- win_util::SetWindowProc(m_editWnd, default_edit_wnd_proc_);
- win_util::SetWindowUserData(m_editWnd, NULL);
+ PlatformCleanUp();
StatsTable *table = StatsTable::current();
if (dump_stats_table_on_exit_) {
@@ -217,21 +173,6 @@ void TestShell::SetAllowScriptsToCloseWindows() {
}
// static
-void TestShell::InitializeTestShell(bool interactive) {
- // Start COM stuff.
- HRESULT res = OleInitialize(NULL);
- DCHECK(SUCCEEDED(res));
-
- window_list_ = new WindowList;
- instance_handle_ = ::GetModuleHandle(NULL);
- interactive_ = interactive;
-
- web_prefs_ = new WebPreferences;
-
- ResetWebPreferences();
-}
-
-// static
void TestShell::ResetWebPreferences() {
DCHECK(web_prefs_);
@@ -270,180 +211,10 @@ void TestShell::ResetWebPreferences() {
}
}
-// static
-void TestShell::ShutdownTestShell() {
- delete window_list_;
- SimpleResourceLoaderBridge::Shutdown();
- delete TestShell::web_prefs_;
- OleUninitialize();
-}
-
-bool TestShell::Initialize(const std::wstring& startingURL) {
- // Perform application initialization:
- m_mainWnd = CreateWindow(g_windowClass, g_windowTitle,
- WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
- CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
- NULL, NULL, instance_handle_, NULL);
- win_util::SetWindowUserData(m_mainWnd, this);
-
- HWND hwnd;
- int x = 0;
-
- hwnd = CreateWindow(L"BUTTON", L"Back",
- WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON ,
- x, 0, BUTTON_WIDTH, URLBAR_HEIGHT,
- m_mainWnd, (HMENU) IDC_NAV_BACK, instance_handle_, 0);
- x += BUTTON_WIDTH;
-
- hwnd = CreateWindow(L"BUTTON", L"Forward",
- WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON ,
- x, 0, BUTTON_WIDTH, URLBAR_HEIGHT,
- m_mainWnd, (HMENU) IDC_NAV_FORWARD, instance_handle_, 0);
- x += BUTTON_WIDTH;
-
- hwnd = CreateWindow(L"BUTTON", L"Reload",
- WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON ,
- x, 0, BUTTON_WIDTH, URLBAR_HEIGHT,
- m_mainWnd, (HMENU) IDC_NAV_RELOAD, instance_handle_, 0);
- x += BUTTON_WIDTH;
-
- hwnd = CreateWindow(L"BUTTON", L"Stop",
- WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON ,
- x, 0, BUTTON_WIDTH, URLBAR_HEIGHT,
- m_mainWnd, (HMENU) IDC_NAV_STOP, instance_handle_, 0);
- x += BUTTON_WIDTH;
-
- // this control is positioned by ResizeSubViews
- m_editWnd = CreateWindow(L"EDIT", 0,
- WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT |
- ES_AUTOVSCROLL | ES_AUTOHSCROLL,
- x, 0, 0, 0, m_mainWnd, 0, instance_handle_, 0);
-
- default_edit_wnd_proc_ =
- win_util::SetWindowProc(m_editWnd, TestShell::EditWndProc);
- win_util::SetWindowUserData(m_editWnd, this);
-
- // create webview
- m_webViewHost.reset(
- WebViewHost::Create(m_mainWnd, delegate_.get(), *TestShell::web_prefs_));
- webView()->SetUseEditorDelegate(true);
- delegate_->RegisterDragDrop();
-
- // Load our initial content.
- if (!startingURL.empty())
- LoadURL(startingURL.c_str());
-
- ShowWindow(webViewWnd(), SW_SHOW);
-
- bool bIsSVGTest = startingURL.find(L"W3C-SVG-1.1") != std::wstring::npos;
-
- if (bIsSVGTest) {
- SizeTo(kSVGTestWindowWidth, kSVGTestWindowHeight);
- } else {
- SizeToDefault();
- }
-
- return true;
-}
-
-void TestShell::TestFinished() {
- if (!test_is_pending_)
- return; // reached when running under test_shell_tests
-
- UINT_PTR timer_id = reinterpret_cast<UINT_PTR>(this);
- KillTimer(mainWnd(), timer_id);
-
- test_is_pending_ = false;
- MessageLoop::current()->Quit();
-}
-
-// Thread main to run for the thread which just tests for timeout.
-unsigned int __stdcall WatchDogThread(void *arg)
-{
- // If we're debugging a layout test, don't timeout.
- if (::IsDebuggerPresent())
- return 0;
-
- TestShell* shell = static_cast<TestShell*>(arg);
- DWORD timeout = static_cast<DWORD>(shell->GetFileTestTimeout() * 2.5);
- DWORD rv = WaitForSingleObject(shell->finished_event(), timeout);
- if (rv == WAIT_TIMEOUT) {
- // Print a warning to be caught by the layout-test script.
- // Note: the layout test driver may or may not recognize
- // this as a timeout.
- puts("#TEST_TIMED_OUT\n");
- puts("#EOF\n");
- fflush(stdout);
- TerminateProcess(GetCurrentProcess(), 0);
- }
- // Finished normally.
- return 0;
-}
-
-void TestShell::WaitTestFinished() {
- DCHECK(!test_is_pending_) << "cannot be used recursively";
-
- test_is_pending_ = true;
-
- // Create a watchdog thread which just sets a timer and
- // kills the process if it times out. This catches really
- // bad hangs where the shell isn't coming back to the
- // message loop. If the watchdog is what catches a
- // timeout, it can't do anything except terminate the test
- // shell, which is unfortunate.
- finished_event_ = CreateEvent(NULL, TRUE, FALSE, NULL);
- DCHECK(finished_event_ != NULL);
-
- HANDLE thread_handle = reinterpret_cast<HANDLE>(_beginthreadex(
- NULL,
- 0,
- &WatchDogThread,
- this,
- 0,
- 0));
- DCHECK(thread_handle != NULL);
-
- // TestFinished() will post a quit message to break this loop when the page
- // finishes loading.
- while (test_is_pending_)
- MessageLoop::current()->Run();
-
- // Tell the watchdog that we are finished.
- SetEvent(finished_event_);
-
- // Wait to join the watchdog thread. (up to 1s, then quit)
- WaitForSingleObject(thread_handle, 1000);
-}
-
void TestShell::Show(WebView* webview, WindowOpenDisposition disposition) {
delegate_->Show(webview, disposition);
}
-void TestShell::SetFocus(WebWidgetHost* host, bool enable) {
- if (interactive_) {
- if (enable) {
- ::SetFocus(host->window_handle());
- } else {
- if (GetFocus() == host->window_handle())
- ::SetFocus(NULL);
- }
- } else {
- if (enable) {
- if (m_focusedWidgetHost != host) {
- if (m_focusedWidgetHost)
- m_focusedWidgetHost->webwidget()->SetFocus(false);
- host->webwidget()->SetFocus(enable);
- m_focusedWidgetHost = host;
- }
- } else {
- if (m_focusedWidgetHost == host) {
- host->webwidget()->SetFocus(enable);
- m_focusedWidgetHost = NULL;
- }
- }
- }
-}
-
void TestShell::BindJSObjectsToWindow(WebFrame* frame) {
// Only bind the test classes if we're running tests.
if (!interactive_) {
@@ -463,25 +234,6 @@ void TestShell::CallJSGC() {
}
-/*static*/
-bool TestShell::CreateNewWindow(const std::wstring& startingURL,
- TestShell** result) {
- TestShell* shell = new TestShell();
- bool rv = shell->Initialize(startingURL);
- if (rv) {
- if (result)
- *result = shell;
- TestShell::windowList()->push_back(shell->m_mainWnd);
- }
- return rv;
-}
-
-/*static*/
-void TestShell::DestroyWindow(gfx::WindowHandle windowHandle) {
- // Do we want to tear down some of the machinery behind the scenes too?
- ::DestroyWindow(windowHandle);
-}
-
WebView* TestShell::CreateWebView(WebView* webview) {
// If we're running layout tests, only open a new window if the test has
// called layoutTestController.setCanOpenWindows()
@@ -495,381 +247,15 @@ WebView* TestShell::CreateWebView(WebView* webview) {
return new_win->webView();
}
-WebWidget* TestShell::CreatePopupWidget(WebView* webview) {
- DCHECK(!m_popupHost);
- m_popupHost = WebWidgetHost::Create(NULL, delegate_.get());
- ShowWindow(popupWnd(), SW_SHOW);
-
- return m_popupHost->webwidget();
-}
-
-void TestShell::ClosePopup() {
- PostMessage(popupWnd(), WM_CLOSE, 0, 0);
- m_popupHost = NULL;
-}
-
void TestShell::SizeToDefault() {
SizeTo(kTestWindowWidth, kTestWindowHeight);
}
-void TestShell::SizeTo(int width, int height) {
- RECT rc, rw;
- GetClientRect(m_mainWnd, &rc);
- GetWindowRect(m_mainWnd, &rw);
-
- int client_width = rc.right - rc.left;
- int window_width = rw.right - rw.left;
- window_width = (window_width - client_width) + width;
-
- int client_height = rc.bottom - rc.top;
- int window_height = rw.bottom - rw.top;
- window_height = (window_height - client_height) + height;
-
- // add space for the url bar:
- window_height += URLBAR_HEIGHT;
-
- SetWindowPos(m_mainWnd, NULL, 0, 0, window_width, window_height,
- SWP_NOMOVE | SWP_NOZORDER);
-}
-
-void TestShell::ResizeSubViews() {
- RECT rc;
- GetClientRect(m_mainWnd, &rc);
-
- int x = BUTTON_WIDTH * 4;
- MoveWindow(m_editWnd, x, 0, rc.right - x, URLBAR_HEIGHT, TRUE);
-
- MoveWindow(webViewWnd(), 0, URLBAR_HEIGHT, rc.right,
- rc.bottom - URLBAR_HEIGHT, TRUE);
-}
-
-/* static */ std::string TestShell::DumpImage(
- WebFrame* web_frame,
- const std::wstring& file_name) {
- gfx::BitmapPlatformDeviceWin device(web_frame->CaptureImage(true));
- const SkBitmap& src_bmp = device.accessBitmap(false);
-
- // Encode image.
- std::vector<unsigned char> png;
- SkAutoLockPixels src_bmp_lock(src_bmp);
- PNGEncoder::Encode(
- reinterpret_cast<const unsigned char*>(src_bmp.getPixels()),
- PNGEncoder::FORMAT_BGRA, src_bmp.width(), src_bmp.height(),
- static_cast<int>(src_bmp.rowBytes()), true, &png);
-
- // Write to disk.
- FILE* file = NULL;
- if (_wfopen_s(&file, file_name.c_str(), L"wb") == 0) {
- fwrite(&png[0], 1, png.size(), file);
- fclose(file);
- }
-
- // Compute MD5 sum.
- MD5Context ctx;
- MD5Init(&ctx);
- MD5Update(&ctx, src_bmp.getPixels(), src_bmp.getSize());
-
- MD5Digest digest;
- MD5Final(&digest, &ctx);
- return MD5DigestToBase16(digest);
-}
-
-/* static */ void TestShell::DumpBackForwardList(std::wstring* result) {
- result->clear();
- for (WindowList::iterator iter = TestShell::windowList()->begin();
- iter != TestShell::windowList()->end(); iter++) {
- HWND hwnd = *iter;
- TestShell* shell =
- static_cast<TestShell*>(win_util::GetWindowUserData(hwnd));
- webkit_glue::DumpBackForwardList(shell->webView(), NULL, result);
- }
-}
-
-/* static */ bool TestShell::RunFileTest(const char *filename,
- const TestParams& params) {
- // Load the test file into the first available window.
- if (TestShell::windowList()->empty()) {
- LOG(ERROR) << "No windows open.";
- return false;
- }
- HWND hwnd = *(TestShell::windowList()->begin());
- TestShell* shell =
- static_cast<TestShell*>(win_util::GetWindowUserData(hwnd));
- shell->ResetTestController();
-
- // ResetTestController may have closed the window we were holding on to.
- // Grab the first window again.
- hwnd = *(TestShell::windowList()->begin());
- shell = static_cast<TestShell*>(win_util::GetWindowUserData(hwnd));
- DCHECK(shell);
-
- // Clear focus between tests.
- shell->m_focusedWidgetHost = NULL;
-
- // Make sure the previous load is stopped.
- shell->webView()->StopLoading();
- shell->navigation_controller()->Reset();
-
- // Clean up state between test runs.
- webkit_glue::ResetBeforeTestRun(shell->webView());
- ResetWebPreferences();
- shell->webView()->SetPreferences(*web_prefs_);
-
- SetWindowPos(shell->m_mainWnd, NULL,
- kTestWindowXLocation, kTestWindowYLocation, 0, 0,
- SWP_NOSIZE | SWP_NOZORDER);
- shell->ResizeSubViews();
-
- if (strstr(filename, "loading/") || strstr(filename, "loading\\"))
- shell->layout_test_controller()->SetShouldDumpFrameLoadCallbacks(true);
-
- shell->test_is_preparing_ = true;
-
- std::wstring wstr = UTF8ToWide(filename);
- shell->LoadURL(wstr.c_str());
-
- shell->test_is_preparing_ = false;
- shell->WaitTestFinished();
-
- // Echo the url in the output so we know we're not getting out of sync.
- printf("#URL:%s\n", filename);
-
- // Dump the requested representation.
- WebFrame* webFrame = shell->webView()->GetMainFrame();
- if (webFrame) {
- bool should_dump_as_text =
- shell->layout_test_controller_->ShouldDumpAsText();
- bool dumped_anything = false;
- if (params.dump_tree) {
- dumped_anything = true;
- // Text output: the test page can request different types of output
- // which we handle here.
- if (!should_dump_as_text) {
- // Plain text pages should be dumped as text
- std::wstring mime_type = webFrame->GetDataSource()->GetResponseMimeType();
- should_dump_as_text = (mime_type == L"text/plain");
- }
- if (should_dump_as_text) {
- bool recursive = shell->layout_test_controller_->
- ShouldDumpChildFramesAsText();
- std::string data_utf8 = WideToUTF8(
- webkit_glue::DumpFramesAsText(webFrame, recursive));
- fwrite(data_utf8.c_str(), 1, data_utf8.size(), stdout);
- } else {
- printf("%s", WideToUTF8(
- webkit_glue::DumpRenderer(webFrame)).c_str());
-
- bool recursive = shell->layout_test_controller_->
- ShouldDumpChildFrameScrollPositions();
- printf("%s", WideToUTF8(
- webkit_glue::DumpFrameScrollPosition(webFrame, recursive)).
- c_str());
- }
-
- if (shell->layout_test_controller_->ShouldDumpBackForwardList()) {
- std::wstring bfDump;
- DumpBackForwardList(&bfDump);
- printf("%s", WideToUTF8(bfDump).c_str());
- }
- }
-
- if (params.dump_pixels && !should_dump_as_text) {
- // Image output: we write the image data to the file given on the
- // command line (for the dump pixels argument), and the MD5 sum to
- // stdout.
- dumped_anything = true;
- std::string md5sum = DumpImage(webFrame, params.pixel_file_name);
- printf("#MD5:%s\n", md5sum.c_str());
- }
- if (dumped_anything)
- printf("#EOF\n");
- fflush(stdout);
- }
-
- return true;
-}
-
-
-/* static */
-ATOM TestShell::RegisterWindowClass()
-{
- LoadString(instance_handle_, IDS_APP_TITLE, g_windowTitle, MAX_LOADSTRING);
- LoadString(instance_handle_, IDC_TESTSHELL, g_windowClass, MAX_LOADSTRING);
-
- WNDCLASSEX wcex = {
- /* cbSize = */ sizeof(WNDCLASSEX),
- /* style = */ CS_HREDRAW | CS_VREDRAW,
- /* lpfnWndProc = */ TestShell::WndProc,
- /* cbClsExtra = */ 0,
- /* cbWndExtra = */ 0,
- /* hInstance = */ instance_handle_,
- /* hIcon = */ LoadIcon(instance_handle_, MAKEINTRESOURCE(IDI_TESTSHELL)),
- /* hCursor = */ LoadCursor(NULL, IDC_ARROW),
- /* hbrBackground = */ 0,
- /* lpszMenuName = */ MAKEINTRESOURCE(IDC_TESTSHELL),
- /* lpszClassName = */ g_windowClass,
- /* hIconSm = */ LoadIcon(instance_handle_, MAKEINTRESOURCE(IDI_SMALL)),
- };
- return RegisterClassEx(&wcex);
-}
-
-LRESULT CALLBACK TestShell::WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
- TestShell* shell = static_cast<TestShell*>(win_util::GetWindowUserData(hwnd));
-
- switch (message) {
- case WM_COMMAND:
- {
- int wmId = LOWORD(wParam);
- int wmEvent = HIWORD(wParam);
-
- switch (wmId) {
- case IDM_ABOUT:
- DialogBox(shell->instance_handle_, MAKEINTRESOURCE(IDD_ABOUTBOX), hwnd,
- About);
- break;
- case IDM_EXIT:
- DestroyWindow(hwnd);
- break;
- case IDC_NAV_BACK:
- shell->GoBackOrForward(-1);
- break;
- case IDC_NAV_FORWARD:
- shell->GoBackOrForward(1);
- break;
- case IDC_NAV_RELOAD:
- case IDC_NAV_STOP:
- {
- if (wmId == IDC_NAV_RELOAD) {
- shell->Reload();
- } else {
- shell->webView()->StopLoading();
- }
- }
- break;
- case IDM_DUMP_BODY_TEXT:
- shell->DumpDocumentText();
- break;
- case IDM_DUMP_RENDER_TREE:
- shell->DumpRenderTree();
- break;
- case IDM_SHOW_WEB_INSPECTOR:
- shell->webView()->InspectElement(0, 0);
- break;
- }
- }
- break;
-
- case WM_DESTROY:
- {
- // Dump all in use memory just before shutdown if in use memory
- // debugging has been enabled.
- base::MemoryDebug::DumpAllMemoryInUse();
-
- WindowList::iterator entry =
- std::find(TestShell::windowList()->begin(),
- TestShell::windowList()->end(), hwnd);
- if (entry != TestShell::windowList()->end())
- TestShell::windowList()->erase(entry);
-
- if (TestShell::windowList()->empty() || shell->is_modal()) {
- MessageLoop::current()->PostTask(
- FROM_HERE, new MessageLoop::QuitTask());
- }
- delete shell;
- }
- return 0;
-
- case WM_SIZE:
- if (shell->webView())
- shell->ResizeSubViews();
- return 0;
- }
-
- return DefWindowProc(hwnd, message, wParam, lParam);
-}
-
-
-#define MAX_URL_LENGTH 1024
-
-LRESULT CALLBACK TestShell::EditWndProc(HWND hwnd, UINT message,
- WPARAM wParam, LPARAM lParam)
-{
- TestShell* shell =
- static_cast<TestShell*>(win_util::GetWindowUserData(hwnd));
-
- switch (message) {
- case WM_CHAR:
- if (wParam == 13) { // Enter Key
- wchar_t strPtr[MAX_URL_LENGTH];
- *((LPWORD)strPtr) = MAX_URL_LENGTH;
- LRESULT strLen = SendMessage(hwnd, EM_GETLINE, 0, (LPARAM)strPtr);
- if (strLen > 0)
- shell->LoadURL(strPtr);
-
- return 0;
- }
- }
-
- return (LRESULT) CallWindowProc(shell->default_edit_wnd_proc_, hwnd,
- message, wParam, lParam);
-}
-
-
-// Message handler for about box.
-INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
-{
- UNREFERENCED_PARAMETER(lParam);
- switch (message) {
- case WM_INITDIALOG:
- return (INT_PTR)TRUE;
-
- case WM_COMMAND:
- if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
- EndDialog(hDlg, LOWORD(wParam));
- return (INT_PTR)TRUE;
- }
- break;
- }
- return (INT_PTR)FALSE;
-}
-
-void TestShell::LoadURL(const wchar_t* url)
-{
+void TestShell::LoadURL(const wchar_t* url) {
LoadURLForFrame(url, NULL);
}
-void TestShell::LoadURLForFrame(const wchar_t* url,
- const wchar_t* frame_name) {
- if (!url)
- return;
-
- TRACE_EVENT_BEGIN("url.load", this, WideToUTF8(url));
- bool bIsSVGTest = wcsstr(url, L"W3C-SVG-1.1") > 0;
-
- if (bIsSVGTest) {
- SizeTo(kSVGTestWindowWidth, kSVGTestWindowHeight);
- } else {
- SizeToDefault();
- }
-
- std::wstring urlString(url);
- if (!urlString.empty() && (PathFileExists(url) || PathIsUNC(url))) {
- TCHAR fileURL[INTERNET_MAX_URL_LENGTH];
- DWORD fileURLLength = sizeof(fileURL)/sizeof(fileURL[0]);
- if (SUCCEEDED(UrlCreateFromPath(url, fileURL, &fileURLLength, 0)))
- urlString.assign(fileURL);
- }
-
- std::wstring frame_string;
- if (frame_name)
- frame_string = frame_name;
-
- navigation_controller_->LoadEntry(new TestNavigationEntry(
- -1, GURL(urlString), std::wstring(), frame_string));
-}
-
bool TestShell::Navigate(const TestNavigationEntry& entry, bool reload) {
WebRequestCachePolicy cache_policy;
if (reload) {
@@ -913,90 +299,14 @@ void TestShell::GoBackOrForward(int offset) {
navigation_controller_->GoToOffset(offset);
}
-bool TestShell::PromptForSaveFile(const wchar_t* prompt_title,
- std::wstring* result)
-{
- wchar_t path_buf[MAX_PATH] = L"data.txt";
-
- OPENFILENAME info = {0};
- info.lStructSize = sizeof(info);
- info.hwndOwner = m_mainWnd;
- info.hInstance = instance_handle_;
- info.lpstrFilter = L"*.txt";
- info.lpstrFile = path_buf;
- info.nMaxFile = arraysize(path_buf);
- info.lpstrTitle = prompt_title;
- if (!GetSaveFileName(&info))
- return false;
-
- result->assign(info.lpstrFile);
- return true;
-}
-
-static void WriteTextToFile(const std::wstring& data,
- const std::wstring& file_path)
-{
- FILE* fp;
- errno_t err = _wfopen_s(&fp, file_path.c_str(), L"wt");
- if (err)
- return;
- std::string data_utf8 = WideToUTF8(data);
- fwrite(data_utf8.c_str(), 1, data_utf8.size(), fp);
- fclose(fp);
-}
-
-std::wstring TestShell::GetDocumentText()
-{
+std::wstring TestShell::GetDocumentText() {
return webkit_glue::DumpDocumentText(webView()->GetMainFrame());
}
-void TestShell::DumpDocumentText()
-{
- std::wstring file_path;
- if (!PromptForSaveFile(L"Dump document text", &file_path))
- return;
-
- WriteTextToFile(webkit_glue::DumpDocumentText(webView()->GetMainFrame()),
- file_path);
-}
-
-void TestShell::DumpRenderTree()
-{
- std::wstring file_path;
- if (!PromptForSaveFile(L"Dump render tree", &file_path))
- return;
-
- WriteTextToFile(webkit_glue::DumpRenderer(webView()->GetMainFrame()),
- file_path);
-}
-
void TestShell::Reload() {
navigation_controller_->Reload();
}
-/* static */
-std::string TestShell::RewriteLocalUrl(const std::string& url) {
- // Convert file:///tmp/LayoutTests urls to the actual location on disk.
- const char kPrefix[] = "file:///tmp/LayoutTests/";
- const int kPrefixLen = arraysize(kPrefix) - 1;
-
- std::string new_url(url);
- if (url.compare(0, kPrefixLen, kPrefix, kPrefixLen) == 0) {
- std::wstring replace_url;
- PathService::Get(base::DIR_EXE, &replace_url);
- file_util::UpOneDirectory(&replace_url);
- file_util::UpOneDirectory(&replace_url);
- file_util::AppendToPath(&replace_url, L"webkit");
- file_util::AppendToPath(&replace_url, L"data");
- file_util::AppendToPath(&replace_url, L"layout_tests");
- file_util::AppendToPath(&replace_url, L"LayoutTests");
- replace_url.push_back(file_util::kPathSeparator);
- new_url = std::string("file:///") +
- WideToUTF8(replace_url).append(url.substr(kPrefixLen));
- }
- return new_url;
-}
-
//-----------------------------------------------------------------------------
namespace webkit_glue {
@@ -1023,21 +333,6 @@ bool GetPreferredExtensionForMimeType(const std::string& mime_type,
return net::GetPreferredExtensionForMimeType(mime_type, ext);
}
-IMLangFontLink2* GetLangFontLink() {
- return webkit_glue::GetLangFontLinkHelper();
-}
-
-std::wstring GetLocalizedString(int message_id) {
- const ATLSTRINGRESOURCEIMAGE* image =
- AtlGetStringResourceImage(_AtlBaseModule.GetModuleInstance(),
- message_id);
- if (!image) {
- NOTREACHED();
- return L"No string for this identifier!";
- }
- return std::wstring(image->achString, image->nLength);
-}
-
std::string GetDataResource(int resource_id) {
if (resource_id == IDR_BROKENIMAGE) {
// Use webkit's broken image icon (16x16)
@@ -1067,10 +362,6 @@ std::string GetDataResource(int resource_id) {
}
}
-HCURSOR LoadCursor(int cursor_id) {
- return NULL;
-}
-
SkBitmap* GetBitmapResource(int resource_id) {
return NULL;
}
@@ -1107,18 +398,6 @@ bool webkit_glue::IsPluginRunningInRendererProcess() {
return true;
}
-bool EnsureFontLoaded(HFONT font) {
- return true;
-}
-
-MONITORINFOEX GetMonitorInfoForWindow(HWND window) {
- return webkit_glue::GetMonitorInfoForWindowHelper(window);
-}
-
-bool DownloadUrl(const std::string& url, HWND caller_window) {
- return false;
-}
-
bool GetPluginFinderURL(std::string* plugin_finder_url) {
return false;
}
@@ -1132,4 +411,3 @@ std::wstring GetWebKitLocale() {
}
} // namespace webkit_glue
-
diff --git a/webkit/tools/test_shell/test_shell.h b/webkit/tools/test_shell/test_shell.h
index abab9db..a0e7f34 100644
--- a/webkit/tools/test_shell/test_shell.h
+++ b/webkit/tools/test_shell/test_shell.h
@@ -80,6 +80,10 @@ public:
static bool interactive() { return interactive_; }
+ // Called from the destructor to let each platform do any necessary
+ // cleanup.
+ void PlatformCleanUp();
+
WebView* webView() {
return m_webViewHost.get() ? m_webViewHost->webview() : NULL;
}
diff --git a/webkit/tools/test_shell/test_shell.vcproj b/webkit/tools/test_shell/test_shell.vcproj
index 8a373b48..4e97611 100644
--- a/webkit/tools/test_shell/test_shell.vcproj
+++ b/webkit/tools/test_shell/test_shell.vcproj
@@ -224,6 +224,10 @@
>
</File>
<File
+ RelativePath=".\test_shell_win.cc"
+ >
+ </File>
+ <File
RelativePath=".\test_shell_request_context.cc"
>
</File>
diff --git a/webkit/tools/test_shell/test_shell_tests.vcproj b/webkit/tools/test_shell/test_shell_tests.vcproj
index 34d3970..20b4eba 100644
--- a/webkit/tools/test_shell/test_shell_tests.vcproj
+++ b/webkit/tools/test_shell/test_shell_tests.vcproj
@@ -219,6 +219,10 @@
>
</File>
<File
+ RelativePath=".\test_shell_win.cc"
+ >
+ </File>
+ <File
RelativePath=".\resources\test_shell.ico"
>
</File>
diff --git a/webkit/tools/test_shell/test_shell_win.cc b/webkit/tools/test_shell/test_shell_win.cc
new file mode 100644
index 0000000..cfbf3318
--- /dev/null
+++ b/webkit/tools/test_shell/test_shell_win.cc
@@ -0,0 +1,740 @@
+// Copyright (c) 2006-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.
+
+#include <windows.h>
+#include <atlbase.h>
+#include <commdlg.h>
+#include <objbase.h>
+#include <shlwapi.h>
+#include <wininet.h>
+
+#include "webkit/tools/test_shell/test_shell.h"
+
+#include "base/gfx/bitmap_platform_device.h"
+#include "base/gfx/png_encoder.h"
+#include "base/md5.h"
+#include "base/memory_debug.h"
+#include "base/message_loop.h"
+#include "base/path_service.h"
+#include "base/string_util.h"
+#include "base/trace_event.h"
+#include "base/win_util.h"
+#include "net/url_request/url_request_file_job.h"
+#include "webkit/glue/webdatasource.h"
+#include "webkit/glue/webframe.h"
+#include "webkit/glue/webkit_glue.h"
+#include "webkit/glue/webpreferences.h"
+#include "webkit/glue/webview.h"
+#include "webkit/tools/test_shell/simple_resource_loader_bridge.h"
+#include "webkit/tools/test_shell/test_navigation_controller.h"
+
+#define MAX_LOADSTRING 100
+
+#define BUTTON_WIDTH 72
+#define URLBAR_HEIGHT 24
+
+// Global Variables:
+static TCHAR g_windowTitle[MAX_LOADSTRING]; // The title bar text
+static TCHAR g_windowClass[MAX_LOADSTRING]; // The main window class name
+
+// Forward declarations of functions included in this code module:
+static INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
+
+// The W3C SVG layout tests use a different size than the other layout tests
+const int kSVGTestWindowWidth = 480;
+const int kSVGTestWindowHeight = 360;
+
+// Hide the window offscreen when it is non-interactive.
+// This would correspond with a minimized window position if x = y = -32000.
+// However we shift the x to 0 to pass test cross-frame-access-put.html
+// which expects screenX/screenLeft to be 0 (http://b/issue?id=1227945).
+// TODO(ericroman): x should be defined as 0 rather than -4. There is
+// probably a frameborder not being accounted for in the setting/getting.
+const int kTestWindowXLocation = -4;
+const int kTestWindowYLocation = -32000;
+
+// Initialize static member variable
+HINSTANCE TestShell::instance_handle_;
+
+/////////////////////////////////////////////////////////////////////////////
+// static methods on TestShell
+
+void TestShell::InitializeTestShell(bool interactive) {
+ // Start COM stuff.
+ HRESULT res = OleInitialize(NULL);
+ DCHECK(SUCCEEDED(res));
+
+ window_list_ = new WindowList;
+ instance_handle_ = ::GetModuleHandle(NULL);
+ interactive_ = interactive;
+
+ web_prefs_ = new WebPreferences;
+
+ ResetWebPreferences();
+}
+
+void TestShell::ShutdownTestShell() {
+ delete window_list_;
+ SimpleResourceLoaderBridge::Shutdown();
+ delete TestShell::web_prefs_;
+ OleUninitialize();
+}
+
+bool TestShell::CreateNewWindow(const std::wstring& startingURL,
+ TestShell** result) {
+ TestShell* shell = new TestShell();
+ bool rv = shell->Initialize(startingURL);
+ if (rv) {
+ if (result)
+ *result = shell;
+ TestShell::windowList()->push_back(shell->m_mainWnd);
+ }
+ return rv;
+}
+
+void TestShell::DestroyWindow(gfx::WindowHandle windowHandle) {
+ // Do we want to tear down some of the machinery behind the scenes too?
+ ::DestroyWindow(windowHandle);
+}
+
+ATOM TestShell::RegisterWindowClass() {
+ LoadString(instance_handle_, IDS_APP_TITLE, g_windowTitle, MAX_LOADSTRING);
+ LoadString(instance_handle_, IDC_TESTSHELL, g_windowClass, MAX_LOADSTRING);
+
+ WNDCLASSEX wcex = {
+ sizeof(WNDCLASSEX),
+ CS_HREDRAW | CS_VREDRAW,
+ TestShell::WndProc,
+ 0,
+ 0,
+ instance_handle_,
+ LoadIcon(instance_handle_, MAKEINTRESOURCE(IDI_TESTSHELL)),
+ LoadCursor(NULL, IDC_ARROW),
+ 0,
+ MAKEINTRESOURCE(IDC_TESTSHELL),
+ g_windowClass,
+ LoadIcon(instance_handle_, MAKEINTRESOURCE(IDI_SMALL)),
+ };
+ return RegisterClassEx(&wcex);
+}
+
+// static
+std::string TestShell::DumpImage(WebFrame* web_frame,
+ const std::wstring& file_name) {
+ gfx::BitmapPlatformDevice device(web_frame->CaptureImage(true));
+ const SkBitmap& src_bmp = device.accessBitmap(false);
+
+ // Encode image.
+ std::vector<unsigned char> png;
+ SkAutoLockPixels src_bmp_lock(src_bmp);
+ PNGEncoder::Encode(
+ reinterpret_cast<const unsigned char*>(src_bmp.getPixels()),
+ PNGEncoder::FORMAT_BGRA, src_bmp.width(), src_bmp.height(),
+ static_cast<int>(src_bmp.rowBytes()), true, &png);
+
+ // Write to disk.
+ FILE* file = NULL;
+ if (_wfopen_s(&file, file_name.c_str(), L"wb") == 0) {
+ fwrite(&png[0], 1, png.size(), file);
+ fclose(file);
+ }
+
+ // Compute MD5 sum.
+ MD5Context ctx;
+ MD5Init(&ctx);
+ MD5Update(&ctx, src_bmp.getPixels(), src_bmp.getSize());
+
+ MD5Digest digest;
+ MD5Final(&digest, &ctx);
+ return MD5DigestToBase16(digest);
+}
+
+void TestShell::DumpBackForwardList(std::wstring* result) {
+ result->clear();
+ for (WindowList::iterator iter = TestShell::windowList()->begin();
+ iter != TestShell::windowList()->end(); iter++) {
+ HWND hwnd = *iter;
+ TestShell* shell =
+ static_cast<TestShell*>(win_util::GetWindowUserData(hwnd));
+ webkit_glue::DumpBackForwardList(shell->webView(), NULL, result);
+ }
+}
+
+bool TestShell::RunFileTest(const char *filename, const TestParams& params) {
+ // Load the test file into the first available window.
+ if (TestShell::windowList()->empty()) {
+ LOG(ERROR) << "No windows open.";
+ return false;
+ }
+
+ HWND hwnd = *(TestShell::windowList()->begin());
+ TestShell* shell =
+ static_cast<TestShell*>(win_util::GetWindowUserData(hwnd));
+ shell->ResetTestController();
+
+ // ResetTestController may have closed the window we were holding on to.
+ // Grab the first window again.
+ hwnd = *(TestShell::windowList()->begin());
+ shell = static_cast<TestShell*>(win_util::GetWindowUserData(hwnd));
+ DCHECK(shell);
+
+ // Clear focus between tests.
+ shell->m_focusedWidgetHost = NULL;
+
+ // Make sure the previous load is stopped.
+ shell->webView()->StopLoading();
+ shell->navigation_controller()->Reset();
+
+ // Clean up state between test runs.
+ webkit_glue::ResetBeforeTestRun(shell->webView());
+ ResetWebPreferences();
+ shell->webView()->SetPreferences(*web_prefs_);
+
+ SetWindowPos(shell->m_mainWnd, NULL,
+ kTestWindowXLocation, kTestWindowYLocation, 0, 0,
+ SWP_NOSIZE | SWP_NOZORDER);
+ shell->ResizeSubViews();
+
+ if (strstr(filename, "loading/") || strstr(filename, "loading\\"))
+ shell->layout_test_controller()->SetShouldDumpFrameLoadCallbacks(true);
+
+ shell->test_is_preparing_ = true;
+
+ std::wstring wstr = UTF8ToWide(filename);
+ shell->LoadURL(wstr.c_str());
+
+ shell->test_is_preparing_ = false;
+ shell->WaitTestFinished();
+
+ // Echo the url in the output so we know we're not getting out of sync.
+ printf("#URL:%s\n", filename);
+
+ // Dump the requested representation.
+ WebFrame* webFrame = shell->webView()->GetMainFrame();
+ if (webFrame) {
+ bool should_dump_as_text =
+ shell->layout_test_controller_->ShouldDumpAsText();
+ bool dumped_anything = false;
+ if (params.dump_tree) {
+ dumped_anything = true;
+ // Text output: the test page can request different types of output
+ // which we handle here.
+ if (!should_dump_as_text) {
+ // Plain text pages should be dumped as text
+ std::wstring mime_type = webFrame->GetDataSource()->GetResponseMimeType();
+ should_dump_as_text = (mime_type == L"text/plain");
+ }
+ if (should_dump_as_text) {
+ bool recursive = shell->layout_test_controller_->
+ ShouldDumpChildFramesAsText();
+ std::string data_utf8 = WideToUTF8(
+ webkit_glue::DumpFramesAsText(webFrame, recursive));
+ fwrite(data_utf8.c_str(), 1, data_utf8.size(), stdout);
+ } else {
+ printf("%s", WideToUTF8(
+ webkit_glue::DumpRenderer(webFrame)).c_str());
+
+ bool recursive = shell->layout_test_controller_->
+ ShouldDumpChildFrameScrollPositions();
+ printf("%s", WideToUTF8(
+ webkit_glue::DumpFrameScrollPosition(webFrame, recursive)).c_str());
+ }
+
+ if (shell->layout_test_controller_->ShouldDumpBackForwardList()) {
+ std::wstring bfDump;
+ DumpBackForwardList(&bfDump);
+ printf("%s", WideToUTF8(bfDump).c_str());
+ }
+ }
+
+ if (params.dump_pixels && !should_dump_as_text) {
+ // Image output: we write the image data to the file given on the
+ // command line (for the dump pixels argument), and the MD5 sum to
+ // stdout.
+ dumped_anything = true;
+ std::string md5sum = DumpImage(webFrame, params.pixel_file_name);
+ printf("#MD5:%s\n", md5sum.c_str());
+ }
+ if (dumped_anything)
+ printf("#EOF\n");
+ fflush(stdout);
+ }
+
+ return true;
+}
+
+std::string TestShell::RewriteLocalUrl(const std::string& url) {
+ // Convert file:///tmp/LayoutTests urls to the actual location on disk.
+ const char kPrefix[] = "file:///tmp/LayoutTests/";
+ const int kPrefixLen = arraysize(kPrefix) - 1;
+
+ std::string new_url(url);
+ if (url.compare(0, kPrefixLen, kPrefix, kPrefixLen) == 0) {
+ std::wstring replace_url;
+ PathService::Get(base::DIR_EXE, &replace_url);
+ file_util::UpOneDirectory(&replace_url);
+ file_util::UpOneDirectory(&replace_url);
+ file_util::AppendToPath(&replace_url, L"webkit");
+ file_util::AppendToPath(&replace_url, L"data");
+ file_util::AppendToPath(&replace_url, L"layout_tests");
+ file_util::AppendToPath(&replace_url, L"LayoutTests");
+ replace_url.push_back(file_util::kPathSeparator);
+ new_url = std::string("file:///") +
+ WideToUTF8(replace_url).append(url.substr(kPrefixLen));
+ }
+ return new_url;
+}
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+// TestShell implementation
+
+void TestShell::PlatformCleanUp() {
+ // When the window is destroyed, tell the Edit field to forget about us,
+ // otherwise we will crash.
+ win_util::SetWindowProc(m_editWnd, default_edit_wnd_proc_);
+ win_util::SetWindowUserData(m_editWnd, NULL);
+}
+
+bool TestShell::Initialize(const std::wstring& startingURL) {
+ // Perform application initialization:
+ m_mainWnd = CreateWindow(g_windowClass, g_windowTitle,
+ WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
+ CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
+ NULL, NULL, instance_handle_, NULL);
+ win_util::SetWindowUserData(m_mainWnd, this);
+
+ HWND hwnd;
+ int x = 0;
+
+ hwnd = CreateWindow(L"BUTTON", L"Back",
+ WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON ,
+ x, 0, BUTTON_WIDTH, URLBAR_HEIGHT,
+ m_mainWnd, (HMENU) IDC_NAV_BACK, instance_handle_, 0);
+ x += BUTTON_WIDTH;
+
+ hwnd = CreateWindow(L"BUTTON", L"Forward",
+ WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON ,
+ x, 0, BUTTON_WIDTH, URLBAR_HEIGHT,
+ m_mainWnd, (HMENU) IDC_NAV_FORWARD, instance_handle_, 0);
+ x += BUTTON_WIDTH;
+
+ hwnd = CreateWindow(L"BUTTON", L"Reload",
+ WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON ,
+ x, 0, BUTTON_WIDTH, URLBAR_HEIGHT,
+ m_mainWnd, (HMENU) IDC_NAV_RELOAD, instance_handle_, 0);
+ x += BUTTON_WIDTH;
+
+ hwnd = CreateWindow(L"BUTTON", L"Stop",
+ WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON ,
+ x, 0, BUTTON_WIDTH, URLBAR_HEIGHT,
+ m_mainWnd, (HMENU) IDC_NAV_STOP, instance_handle_, 0);
+ x += BUTTON_WIDTH;
+
+ // this control is positioned by ResizeSubViews
+ m_editWnd = CreateWindow(L"EDIT", 0,
+ WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT |
+ ES_AUTOVSCROLL | ES_AUTOHSCROLL,
+ x, 0, 0, 0, m_mainWnd, 0, instance_handle_, 0);
+
+ default_edit_wnd_proc_ =
+ win_util::SetWindowProc(m_editWnd, TestShell::EditWndProc);
+ win_util::SetWindowUserData(m_editWnd, this);
+
+ // create webview
+ m_webViewHost.reset(
+ WebViewHost::Create(m_mainWnd, delegate_.get(), *TestShell::web_prefs_));
+ webView()->SetUseEditorDelegate(true);
+ delegate_->RegisterDragDrop();
+
+ // Load our initial content.
+ if (!startingURL.empty())
+ LoadURL(startingURL.c_str());
+
+ ShowWindow(webViewWnd(), SW_SHOW);
+
+ bool bIsSVGTest = startingURL.find(L"W3C-SVG-1.1") != std::wstring::npos;
+
+ if (bIsSVGTest) {
+ SizeTo(kSVGTestWindowWidth, kSVGTestWindowHeight);
+ } else {
+ SizeToDefault();
+ }
+
+ return true;
+}
+
+void TestShell::TestFinished() {
+ if (!test_is_pending_)
+ return; // reached when running under test_shell_tests
+
+ UINT_PTR timer_id = reinterpret_cast<UINT_PTR>(this);
+ KillTimer(mainWnd(), timer_id);
+
+ test_is_pending_ = false;
+ MessageLoop::current()->Quit();
+}
+
+// Thread main to run for the thread which just tests for timeout.
+unsigned int __stdcall WatchDogThread(void *arg) {
+ // If we're debugging a layout test, don't timeout.
+ if (::IsDebuggerPresent())
+ return 0;
+
+ TestShell* shell = static_cast<TestShell*>(arg);
+ DWORD timeout = static_cast<DWORD>(shell->GetFileTestTimeout() * 2.5);
+ DWORD rv = WaitForSingleObject(shell->finished_event(), timeout);
+ if (rv == WAIT_TIMEOUT) {
+ // Print a warning to be caught by the layout-test script.
+ // Note: the layout test driver may or may not recognize
+ // this as a timeout.
+ puts("#TEST_TIMED_OUT\n");
+ puts("#EOF\n");
+ fflush(stdout);
+ TerminateProcess(GetCurrentProcess(), 0);
+ }
+ // Finished normally.
+ return 0;
+}
+
+void TestShell::WaitTestFinished() {
+ DCHECK(!test_is_pending_) << "cannot be used recursively";
+
+ test_is_pending_ = true;
+
+ // Create a watchdog thread which just sets a timer and
+ // kills the process if it times out. This catches really
+ // bad hangs where the shell isn't coming back to the
+ // message loop. If the watchdog is what catches a
+ // timeout, it can't do anything except terminate the test
+ // shell, which is unfortunate.
+ finished_event_ = CreateEvent(NULL, TRUE, FALSE, NULL);
+ DCHECK(finished_event_ != NULL);
+
+ HANDLE thread_handle = reinterpret_cast<HANDLE>(_beginthreadex(
+ NULL,
+ 0,
+ &WatchDogThread,
+ this,
+ 0,
+ 0));
+ DCHECK(thread_handle != NULL);
+
+ // TestFinished() will post a quit message to break this loop when the page
+ // finishes loading.
+ while (test_is_pending_)
+ MessageLoop::current()->Run();
+
+ // Tell the watchdog that we are finished.
+ SetEvent(finished_event_);
+
+ // Wait to join the watchdog thread. (up to 1s, then quit)
+ WaitForSingleObject(thread_handle, 1000);
+}
+
+void TestShell::SetFocus(WebWidgetHost* host, bool enable) {
+ if (interactive_) {
+ if (enable) {
+ ::SetFocus(host->window_handle());
+ } else {
+ if (GetFocus() == host->window_handle())
+ ::SetFocus(NULL);
+ }
+ } else {
+ if (enable) {
+ if (m_focusedWidgetHost != host) {
+ if (m_focusedWidgetHost)
+ m_focusedWidgetHost->webwidget()->SetFocus(false);
+ host->webwidget()->SetFocus(enable);
+ m_focusedWidgetHost = host;
+ }
+ } else {
+ if (m_focusedWidgetHost == host) {
+ host->webwidget()->SetFocus(enable);
+ m_focusedWidgetHost = NULL;
+ }
+ }
+ }
+}
+
+WebWidget* TestShell::CreatePopupWidget(WebView* webview) {
+ DCHECK(!m_popupHost);
+ m_popupHost = WebWidgetHost::Create(NULL, delegate_.get());
+ ShowWindow(popupWnd(), SW_SHOW);
+
+ return m_popupHost->webwidget();
+}
+
+void TestShell::ClosePopup() {
+ PostMessage(popupWnd(), WM_CLOSE, 0, 0);
+ m_popupHost = NULL;
+}
+
+void TestShell::SizeTo(int width, int height) {
+ RECT rc, rw;
+ GetClientRect(m_mainWnd, &rc);
+ GetWindowRect(m_mainWnd, &rw);
+
+ int client_width = rc.right - rc.left;
+ int window_width = rw.right - rw.left;
+ window_width = (window_width - client_width) + width;
+
+ int client_height = rc.bottom - rc.top;
+ int window_height = rw.bottom - rw.top;
+ window_height = (window_height - client_height) + height;
+
+ // add space for the url bar:
+ window_height += URLBAR_HEIGHT;
+
+ SetWindowPos(m_mainWnd, NULL, 0, 0, window_width, window_height,
+ SWP_NOMOVE | SWP_NOZORDER);
+}
+
+void TestShell::ResizeSubViews() {
+ RECT rc;
+ GetClientRect(m_mainWnd, &rc);
+
+ int x = BUTTON_WIDTH * 4;
+ MoveWindow(m_editWnd, x, 0, rc.right - x, URLBAR_HEIGHT, TRUE);
+
+ MoveWindow(webViewWnd(), 0, URLBAR_HEIGHT, rc.right,
+ rc.bottom - URLBAR_HEIGHT, TRUE);
+}
+
+void TestShell::LoadURLForFrame(const wchar_t* url,
+ const wchar_t* frame_name) {
+ if (!url)
+ return;
+
+ TRACE_EVENT_BEGIN("url.load", this, WideToUTF8(url));
+ bool bIsSVGTest = wcsstr(url, L"W3C-SVG-1.1") > 0;
+
+ if (bIsSVGTest) {
+ SizeTo(kSVGTestWindowWidth, kSVGTestWindowHeight);
+ } else {
+ SizeToDefault();
+ }
+
+ std::wstring urlString(url);
+ if (!urlString.empty() && (PathFileExists(url) || PathIsUNC(url))) {
+ TCHAR fileURL[INTERNET_MAX_URL_LENGTH];
+ DWORD fileURLLength = sizeof(fileURL)/sizeof(fileURL[0]);
+ if (SUCCEEDED(UrlCreateFromPath(url, fileURL, &fileURLLength, 0)))
+ urlString.assign(fileURL);
+ }
+
+ std::wstring frame_string;
+ if (frame_name)
+ frame_string = frame_name;
+
+ navigation_controller_->LoadEntry(new TestNavigationEntry(
+ -1, GURL(urlString), std::wstring(), frame_string));
+}
+
+LRESULT CALLBACK TestShell::WndProc(HWND hwnd, UINT message, WPARAM wParam,
+ LPARAM lParam) {
+ TestShell* shell = static_cast<TestShell*>(win_util::GetWindowUserData(hwnd));
+
+ switch (message) {
+ case WM_COMMAND:
+ {
+ int wmId = LOWORD(wParam);
+ int wmEvent = HIWORD(wParam);
+
+ switch (wmId) {
+ case IDM_ABOUT:
+ DialogBox(shell->instance_handle_, MAKEINTRESOURCE(IDD_ABOUTBOX), hwnd,
+ About);
+ break;
+ case IDM_EXIT:
+ DestroyWindow(hwnd);
+ break;
+ case IDC_NAV_BACK:
+ shell->GoBackOrForward(-1);
+ break;
+ case IDC_NAV_FORWARD:
+ shell->GoBackOrForward(1);
+ break;
+ case IDC_NAV_RELOAD:
+ case IDC_NAV_STOP:
+ {
+ if (wmId == IDC_NAV_RELOAD) {
+ shell->Reload();
+ } else {
+ shell->webView()->StopLoading();
+ }
+ }
+ break;
+ case IDM_DUMP_BODY_TEXT:
+ shell->DumpDocumentText();
+ break;
+ case IDM_DUMP_RENDER_TREE:
+ shell->DumpRenderTree();
+ break;
+ case IDM_SHOW_WEB_INSPECTOR:
+ shell->webView()->InspectElement(0, 0);
+ break;
+ }
+ }
+ break;
+
+ case WM_DESTROY:
+ {
+ // Dump all in use memory just before shutdown if in use memory
+ // debugging has been enabled.
+ base::MemoryDebug::DumpAllMemoryInUse();
+
+ WindowList::iterator entry =
+ std::find(TestShell::windowList()->begin(),
+ TestShell::windowList()->end(), hwnd);
+ if (entry != TestShell::windowList()->end())
+ TestShell::windowList()->erase(entry);
+
+ if (TestShell::windowList()->empty() || shell->is_modal()) {
+ MessageLoop::current()->PostTask(FROM_HERE,
+ new MessageLoop::QuitTask());
+ }
+ delete shell;
+ }
+ return 0;
+
+ case WM_SIZE:
+ if (shell->webView())
+ shell->ResizeSubViews();
+ return 0;
+ }
+
+ return DefWindowProc(hwnd, message, wParam, lParam);
+}
+
+
+#define MAX_URL_LENGTH 1024
+
+LRESULT CALLBACK TestShell::EditWndProc(HWND hwnd, UINT message,
+ WPARAM wParam, LPARAM lParam) {
+ TestShell* shell =
+ static_cast<TestShell*>(win_util::GetWindowUserData(hwnd));
+
+ switch (message) {
+ case WM_CHAR:
+ if (wParam == VK_RETURN) {
+ wchar_t strPtr[MAX_URL_LENGTH];
+ *((LPWORD)strPtr) = MAX_URL_LENGTH;
+ LRESULT strLen = SendMessage(hwnd, EM_GETLINE, 0, (LPARAM)strPtr);
+ if (strLen > 0)
+ shell->LoadURL(strPtr);
+
+ return 0;
+ }
+ }
+
+ return (LRESULT) CallWindowProc(shell->default_edit_wnd_proc_, hwnd,
+ message, wParam, lParam);
+}
+
+
+// Message handler for about box.
+INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
+ UNREFERENCED_PARAMETER(lParam);
+ switch (message) {
+ case WM_INITDIALOG:
+ return (INT_PTR)TRUE;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
+ EndDialog(hDlg, LOWORD(wParam));
+ return (INT_PTR)TRUE;
+ }
+ break;
+ }
+ return (INT_PTR)FALSE;
+}
+
+bool TestShell::PromptForSaveFile(const wchar_t* prompt_title,
+ std::wstring* result) {
+ wchar_t path_buf[MAX_PATH] = L"data.txt";
+
+ OPENFILENAME info = {0};
+ info.lStructSize = sizeof(info);
+ info.hwndOwner = m_mainWnd;
+ info.hInstance = instance_handle_;
+ info.lpstrFilter = L"*.txt";
+ info.lpstrFile = path_buf;
+ info.nMaxFile = arraysize(path_buf);
+ info.lpstrTitle = prompt_title;
+ if (!GetSaveFileName(&info))
+ return false;
+
+ result->assign(info.lpstrFile);
+ return true;
+}
+
+// TODO(tc): Use methods in base or net/base for this.
+static void WriteTextToFile(const std::wstring& data,
+ const std::wstring& file_path) {
+ FILE* fp;
+ errno_t err = _wfopen_s(&fp, file_path.c_str(), L"wt");
+ if (err)
+ return;
+ std::string data_utf8 = WideToUTF8(data);
+ fwrite(data_utf8.c_str(), 1, data_utf8.size(), fp);
+ fclose(fp);
+}
+
+void TestShell::DumpDocumentText() {
+ std::wstring file_path;
+ if (!PromptForSaveFile(L"Dump document text", &file_path))
+ return;
+
+ WriteTextToFile(webkit_glue::DumpDocumentText(webView()->GetMainFrame()),
+ file_path);
+}
+
+void TestShell::DumpRenderTree() {
+ std::wstring file_path;
+ if (!PromptForSaveFile(L"Dump render tree", &file_path))
+ return;
+
+ WriteTextToFile(webkit_glue::DumpRenderer(webView()->GetMainFrame()),
+ file_path);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// WebKit glue functions
+
+namespace webkit_glue {
+
+IMLangFontLink2* GetLangFontLink() {
+ return webkit_glue::GetLangFontLinkHelper();
+}
+
+std::wstring GetLocalizedString(int message_id) {
+ const ATLSTRINGRESOURCEIMAGE* image =
+ AtlGetStringResourceImage(_AtlBaseModule.GetModuleInstance(),
+ message_id);
+ if (!image) {
+ NOTREACHED();
+ return L"No string for this identifier!";
+ }
+ return std::wstring(image->achString, image->nLength);
+}
+
+HCURSOR LoadCursor(int cursor_id) {
+ return NULL;
+}
+
+bool EnsureFontLoaded(HFONT font) {
+ return true;
+}
+
+MONITORINFOEX GetMonitorInfoForWindow(HWND window) {
+ return webkit_glue::GetMonitorInfoForWindowHelper(window);
+}
+
+bool DownloadUrl(const std::string& url, HWND caller_window) {
+ return false;
+}
+
+} // namespace webkit_glue