diff options
author | avi@google.com <avi@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-09-12 15:49:16 +0000 |
---|---|---|
committer | avi@google.com <avi@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-09-12 15:49:16 +0000 |
commit | 9e9a32e553a0593d200b1f990162e63c5c0a9c9a (patch) | |
tree | 9cf164bef0a27f45ceb45a8a2bf809eb2d2fc2a1 /webkit/tools/test_shell/test_shell_mac.mm | |
parent | 6043312ed0815d5cdeb625638c56a284e8b62755 (diff) | |
download | chromium_src-9e9a32e553a0593d200b1f990162e63c5c0a9c9a.zip chromium_src-9e9a32e553a0593d200b1f990162e63c5c0a9c9a.tar.gz chromium_src-9e9a32e553a0593d200b1f990162e63c5c0a9c9a.tar.bz2 |
Bring the Mac test shell into the fold.
Review URL: http://codereview.chromium.org/2444
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@2112 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/tools/test_shell/test_shell_mac.mm')
-rw-r--r-- | webkit/tools/test_shell/test_shell_mac.mm | 947 |
1 files changed, 947 insertions, 0 deletions
diff --git a/webkit/tools/test_shell/test_shell_mac.mm b/webkit/tools/test_shell/test_shell_mac.mm new file mode 100644 index 0000000..9ee3f62 --- /dev/null +++ b/webkit/tools/test_shell/test_shell_mac.mm @@ -0,0 +1,947 @@ +// Copyright 2006 Google Inc. All Rights Reserved. + +#include <Cocoa/Cocoa.h> +#include <sys/stat.h> + +//#include "config.h" + +#include "webkit/tools/test_shell/test_shell.h" + +#include "base/basictypes.h" +#include "base/debug_on_start.h" +#include "base/file_util.h" +#include "base/gfx/bitmap_platform_device.h" +#include "base/gfx/png_encoder.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 "net/base/mime_util.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "webkit/glue/webdatasource.h" +#include "webkit/glue/webframe.h" +#include "webkit/glue/webkit_glue.h" +#include "webkit/glue/webkit_resources.h" +#include "webkit/glue/webpreferences.h" +#include "webkit/glue/weburlrequest.h" +#include "webkit/glue/webview.h" +#include "webkit/glue/webwidget.h" +#include "webkit/glue/plugins/plugin_list.h" +#include "webkit/tools/test_shell/mac/test_shell_webview.h" +#include "webkit/tools/test_shell/simple_resource_loader_bridge.h" +#include "webkit/tools/test_shell/test_navigation_controller.h" + +// #include "webkit_strings.h" + +#import "skia/include/SkBitmap.h" + +using std::min; +using std::max; + +#define MAX_LOADSTRING 100 + +#define BUTTON_WIDTH 72 +#define URLBAR_HEIGHT 24 + +// Global Variables: + +// Default timeout for page load when running non-interactive file +// tests, in ms. +const int kDefaultFileTestTimeoutMillisecs = 10 * 1000; + +// Content area size for newly created windows. +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. Mac OS X limits +// window positions to +/- 16000 +const int kTestWindowXLocation = -14000; +const int kTestWindowYLocation = -14000; + +static const wchar_t* kStatsFile = L"testshell"; +static int kStatsFileThreads = 20; +static int kStatsFileCounters = 100; + +// Initialize static member variables +WindowList* TestShell::window_list_; +WebPreferences* TestShell::web_prefs_ = NULL; +bool TestShell::interactive_ = true; +int TestShell::file_test_timeout_ms_ = kDefaultFileTestTimeoutMillisecs; +std::map<gfx::WindowHandle, TestShell *> TestShell::window_map_; + + +TestShell::TestShell() + : m_mainWnd(NULL), + m_editWnd(NULL), + m_webViewHost(NULL), + m_popupHost(NULL), + m_focusedWidgetHost(NULL), + delegate_(new TestWebViewDelegate(this)), + test_is_preparing_(false), + test_is_pending_(false), + dump_stats_table_on_exit_(false) { + layout_test_controller_.reset(new LayoutTestController(this)); + event_sending_controller_.reset(new EventSendingController(this)); + text_input_controller_.reset(new TextInputController(this)); + navigation_controller_.reset(new TestNavigationController(this)); + + // load and initialize the stats table (one per process, so that multiple + // instances don't interfere with each other) + wchar_t statsfile[64]; + swprintf(statsfile, 64, L"%ls-%d", kStatsFile, getpid()); + + StatsTable *table = new StatsTable(statsfile, kStatsFileThreads, kStatsFileCounters); + StatsTable::set_current(table); +} + +TestShell::~TestShell() { + window_map_.erase(m_mainWnd); + + if (dump_stats_table_on_exit_) { + // Dump the stats table. + printf("<stats>\n"); + StatsTable *table = StatsTable::current(); + if (table != NULL) { + int counter_max = table->GetMaxCounters(); + for (int index=0; index < counter_max; index++) { + std::string name(WideToUTF8(table->GetRowName(index))); + if (name.length() > 0) { + int value = table->GetRowValue(index); + printf("%s:\t%d\n", name.c_str(), value); + } + } + } + printf("</stats>\n"); + } +} + +// All fatal log messages (e.g. DCHECK failures) imply unit test failures +static void UnitTestAssertHandler(const std::string& str) { + FAIL() << str; +} + +// static +void TestShell::InitLogging(bool suppress_error_dialogs) { + if (suppress_error_dialogs) { + logging::SetLogAssertHandler(UnitTestAssertHandler); + } + + // We might have multiple test_shell processes going at once + char log_filename_template[] = "/tmp/test_shell_XXXXXX"; + char* log_filename = mktemp(log_filename_template); + logging::InitLogging(log_filename, + logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG, + logging::LOCK_LOG_FILE, + logging::DELETE_OLD_LOG_FILE); + + // we want process and thread IDs because we may have multiple processes + logging::SetLogItems(true, true, false, true); +} + +// static +void TestShell::CleanupLogging() { + logging::CloseLogFile(); +} + +// static +void TestShell::InitializeTestShell(bool interactive) { + window_list_ = new WindowList; + interactive_ = interactive; + + web_prefs_ = new WebPreferences; + + ResetWebPreferences(); +} + +// static +void TestShell::ResetWebPreferences() { + DCHECK(web_prefs_); + + // Match the settings used by Mac DumpRenderTree. + if (web_prefs_) { + web_prefs_->standard_font_family = L"Times"; + web_prefs_->fixed_font_family = L"Courier"; + web_prefs_->serif_font_family = L"Times"; + web_prefs_->sans_serif_font_family = L"Helvetica"; + web_prefs_->cursive_font_family = L"Apple Chancery"; + web_prefs_->fantasy_font_family = L"Papyrus"; + web_prefs_->default_encoding = L"ISO-8859-1"; + web_prefs_->default_font_size = 16; + web_prefs_->default_fixed_font_size = 13; + web_prefs_->minimum_font_size = 1; + web_prefs_->minimum_logical_font_size = 9; + web_prefs_->javascript_can_open_windows_automatically = true; + web_prefs_->dom_paste_enabled = true; + web_prefs_->developer_extras_enabled = interactive_; + web_prefs_->shrinks_standalone_images_to_fit = false; + web_prefs_->uses_universal_detector = false; + web_prefs_->text_areas_are_resizable = false; + web_prefs_->user_agent = webkit_glue::GetDefaultUserAgent(); + web_prefs_->dashboard_compatibility_mode = false; + web_prefs_->java_enabled = true; + } +} + +// static +void TestShell::ShutdownTestShell() { + delete window_list_; + delete TestShell::web_prefs_; +} + +NSButton *MakeTestButton(NSRect *rect, NSString *title, NSView *parent) { + NSButton *button = [[NSButton alloc] initWithFrame:*rect]; + [button setTitle:title]; + [button setBezelStyle:NSSmallSquareBezelStyle]; + [button setAutoresizingMask:(NSViewMaxXMargin | NSViewMinYMargin)]; + [parent addSubview:button]; + rect->origin.x += BUTTON_WIDTH; + return button; +} + +bool TestShell::Initialize(const std::wstring& startingURL) { + // Perform application initialization: + // send message to app controller? need to work this out + + //TODO(awalker): this is a straight recreation of windows test_shell.cc's + // window creation code--we should really pull this from the nib and grab + // references to the already-created subviews that way. + NSRect screen_rect = [[NSScreen mainScreen] visibleFrame]; + NSRect window_rect = { {0, screen_rect.size.height - kTestWindowHeight}, + {kTestWindowWidth, kTestWindowHeight} }; + m_mainWnd = [[NSWindow alloc] + initWithContentRect:window_rect + styleMask:(NSTitledWindowMask | + NSClosableWindowMask | + NSMiniaturizableWindowMask | + NSResizableWindowMask | + NSTexturedBackgroundWindowMask) + backing:NSBackingStoreBuffered + defer:NO]; + [m_mainWnd setTitle:@"TestShell"]; + + // create webview + m_webViewHost.reset( + WebViewHost::Create(m_mainWnd, delegate_.get(), *TestShell::web_prefs_)); + webView()->SetUseEditorDelegate(true); + delegate_->RegisterDragDrop(); + TestShellWebView *web_view = + static_cast<TestShellWebView*>(m_webViewHost->window_handle()); + [web_view setShell:this]; + + // 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.size.width = BUTTON_WIDTH; + + NSView *content = [m_mainWnd contentView]; + + NSButton *button = MakeTestButton(&button_rect, @"Back", content); + [button setTarget:web_view]; + [button setAction:@selector(goBack:)]; + + button = MakeTestButton(&button_rect, @"Forward", content); + [button setTarget:web_view]; + [button setAction:@selector(goForward:)]; + + // reload button + button = MakeTestButton(&button_rect, @"Reload", content); + [button setTarget:web_view]; + [button setAction:@selector(reload:)]; + + // stop button + button = MakeTestButton(&button_rect, @"Stop", content); + [button setTarget:web_view]; + [button setAction:@selector(stopLoading:)]; + + // text field for URL + button_rect.origin.x += 16; + button_rect.size.width = [[m_mainWnd contentView] bounds].size.width - + button_rect.origin.x - 32; + m_editWnd = [[NSTextField alloc] initWithFrame:button_rect]; + [[m_mainWnd contentView] addSubview:m_editWnd]; + [m_editWnd setAutoresizingMask:(NSViewWidthSizable | NSViewMinYMargin)]; + [m_editWnd setTarget:web_view]; + [m_editWnd setAction:@selector(takeURLStringValueFrom:)]; + + // show the window + [m_mainWnd makeKeyAndOrderFront: nil]; + + // Load our initial content. + if (!startingURL.empty()) + LoadURL(startingURL.c_str()); + + 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 + + test_is_pending_ = false; + MessageLoop::current()->Quit(); +} + +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. + + // TODO(port): implement this + + // TestFinished() will post a quit message to break this loop when the page + // finishes loading. + while (test_is_pending_) + MessageLoop::current()->Run(); +} + +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_) { + layout_test_controller_->BindToJavascript(frame, + L"layoutTestController"); + event_sending_controller_->BindToJavascript(frame, + L"eventSender"); + text_input_controller_->BindToJavascript(frame, + L"textInputController"); + } +} + +/*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); + window_map_[shell->m_mainWnd] = shell; + } + return rv; +} + +/*static*/ +void TestShell::DestroyWindow(gfx::WindowHandle windowHandle) { + // Do we want to tear down some of the machinery behind the scenes too? + [windowHandle performClose:nil]; +} + +WebView* TestShell::CreateWebView(WebView* webview) { + // If we're running layout tests, only open a new window if the test has + // called layoutTestController.setCanOpenWindows() + if (!interactive_ && !layout_test_controller_->CanOpenWindows()) + return NULL; + + TestShell* new_win; + if (!CreateNewWindow(std::wstring(), &new_win)) + return NULL; + + 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) { + NSRect r = [m_mainWnd contentRectForFrameRect:[m_mainWnd frame]]; + r.size.width = width; + r.size.height = height; + [m_mainWnd setFrame:[m_mainWnd frameRectForContentRect:r] display:YES]; +} + +void TestShell::ResizeSubViews() { + // handled by Cocoa for us +} + +/* 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 = fopen(WideToUTF8(file_name).c_str(), "w"); + if (file) { + 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++) { +#if 0 + HWND hwnd = *iter; + TestShell* shell = + static_cast<TestShell*>(win_util::GetWindowUserData(hwnd)); + webkit_glue::DumpBackForwardList(shell->webView(), NULL, result); +#endif + } +} + +/* 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; + } + + NSWindow *window = *(TestShell::windowList()->begin()); + TestShell* shell = window_map_[window]; + shell->ResetTestController(); + + // ResetTestController may have closed the window we were holding on to. + // Grab the first window again. + window = *(TestShell::windowList()->begin()); + shell = window_map_[window]; + 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_); + + [shell->m_mainWnd setFrameTopLeftPoint:NSMakePoint(kTestWindowXLocation, + kTestWindowYLocation)]; + shell->ResizeSubViews(); + + if (strstr(filename, "loading/") || strstr(filename, "loading\\")) + shell->layout_test_controller()->SetShouldDumpFrameLoadCallbacks(true); + + shell->test_is_preparing_ = true; + + shell->LoadURL(UTF8ToWide(filename).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::string mime_type = + WideToUTF8(webFrame->GetDataSource()->GetResponseMimeType()); + should_dump_as_text = (mime_type == "text/plain"); + } + if (should_dump_as_text) { + bool recursive = shell->layout_test_controller_-> + ShouldDumpChildFramesAsText(); + printf("%s", WideToUTF8( + webkit_glue::DumpFramesAsText(webFrame, recursive)). + c_str()); + } 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; +} + +#define MAX_URL_LENGTH 1024 + +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; + + std::string url8 = WideToUTF8(url); + + bool bIsSVGTest = strstr(url8.c_str(), "W3C-SVG-1.1") != NULL; + + if (bIsSVGTest) { + SizeTo(kSVGTestWindowWidth, kSVGTestWindowHeight); + } else { + // SizeToDefault(); + } + + std::string urlString(url8); + struct stat stat_buf; + if (!urlString.empty() && stat(url8.c_str(), &stat_buf) == 0) { + urlString.insert(0, "file://"); + } + + 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) { + const TestNavigationEntry& test_entry = + *static_cast<const TestNavigationEntry*>(&entry); + + WebRequestCachePolicy cache_policy; + if (reload) { + cache_policy = WebRequestReloadIgnoringCacheData; + } else if (entry.GetPageID() != -1) { + cache_policy = WebRequestReturnCacheDataElseLoad; + } else { + cache_policy = WebRequestUseProtocolCachePolicy; + } + + scoped_ptr<WebRequest> request(WebRequest::Create(entry.GetURL())); + request->SetCachePolicy(cache_policy); + // If we are reloading, then WebKit will use the state of the current page. + // Otherwise, we give it the state to navigate to. + if (!reload) + request->SetHistoryState(entry.GetContentState()); + + request->SetExtraData(new TestShellExtraRequestData(entry.GetPageID())); + + // Get the right target frame for the entry. + WebFrame* frame = webView()->GetMainFrame(); + if (!test_entry.GetTargetFrame().empty()) + frame = webView()->GetFrameWithName(test_entry.GetTargetFrame()); + // TODO(mpcomplete): should we clear the target frame, or should + // back/forward navigations maintain the target frame? + + frame->LoadRequest(request.get()); + // Restore focus to the main frame prior to loading new request. + // This makes sure that we don't have a focused iframe. Otherwise, that + // iframe would keep focus when the SetFocus called immediately after + // LoadRequest, thus making some tests fail (see http://b/issue?id=845337 + // for more details). + webView()->SetFocusedFrame(frame); + SetFocus(webViewHost(), true); + + return true; +} + +void TestShell::GoBackOrForward(int offset) { + navigation_controller_->GoToOffset(offset); +} + +bool TestShell::PromptForSaveFile(const wchar_t* prompt_title, + std::wstring* result) +{ + NSSavePanel *save_panel = [NSSavePanel savePanel]; + + /* set up new attributes */ + [save_panel setRequiredFileType:@"txt"]; + [save_panel setMessage:[[NSString alloc] initWithUTF8String:WideToUTF8(prompt_title).c_str()]]; + + /* display the NSSavePanel */ + if ([save_panel runModalForDirectory:NSHomeDirectory() file:@""] == NSOKButton) { + result->assign(UTF8ToWide([[save_panel filename] UTF8String])); + return true; + } + return false; +} + +static void WriteTextToFile(const std::string& data, + const std::string& file_path) +{ + FILE* fp = fopen(file_path.c_str(), "w"); + if (!fp) + return; + fwrite(data.c_str(), 1, data.size(), fp); + fclose(fp); +} + +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(WideToUTF8(webkit_glue::DumpDocumentText(webView()->GetMainFrame())), + WideToUTF8(file_path)); +} + +void TestShell::DumpRenderTree() +{ + std::wstring file_path; + if (!PromptForSaveFile(L"Dump render tree", &file_path)) + return; + + WriteTextToFile(WideToUTF8(webkit_glue::DumpRenderer(webView()->GetMainFrame())), + WideToUTF8(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); + std::string replace_url8 = WideToUTF8(replace_url); + new_url = std::string("file:///") + replace_url8.append(url.substr(kPrefixLen)); + } + return new_url; +} + +//----------------------------------------------------------------------------- + +namespace webkit_glue { + +bool HistoryContains(const char16* url, int url_length, + const char* document_host, int document_host_length, + bool is_dns_prefetch_enabled) { + return false; +} + +void DnsPrefetchUrl(const char16* url, int url_length) {} + +void PrecacheUrl(const char16* url, int url_length) {} + +void AppendToLog(const char* file, int line, const char* msg) { + logging::LogMessage(file, line).stream() << msg; +} + +bool GetMimeTypeFromExtension(std::string &ext, std::string *mime_type) { + return net::GetMimeTypeFromExtension(UTF8ToWide(ext), mime_type); +} + +bool GetMimeTypeFromFile(const std::string &file_path, + std::string *mime_type) { + return net::GetMimeTypeFromFile(UTF8ToWide(file_path), mime_type); +} + +bool GetPreferredExtensionForMimeType(const std::string& mime_type, + std::string* ext) { + std::wstring wide_ext; + bool result = net::GetPreferredExtensionForMimeType(mime_type, &wide_ext); + if (result) + *ext = WideToUTF8(wide_ext); + return result; +} + +// IMLangFontLink2* GetLangFontLink() { +// return webkit_glue::GetLangFontLinkHelper(); +//} + +std::wstring GetLocalizedString(int message_id) { + NSString *idString = [NSString stringWithFormat:@"%d", message_id]; + NSString *localString = NSLocalizedString(idString, @""); + + return UTF8ToWide([localString UTF8String]); +} + +std::string GetDataResource(int resource_id) { + if (resource_id == IDR_BROKENIMAGE) { + // Use webkit's broken image icon (16x16) + static std::string broken_image_data; + if (broken_image_data.empty()) { + std::wstring path; + PathService::Get(base::DIR_SOURCE_ROOT, &path); + file_util::AppendToPath(&path, L"webkit"); + file_util::AppendToPath(&path, L"tools"); + file_util::AppendToPath(&path, L"test_shel"); + file_util::AppendToPath(&path, L"resources"); + file_util::AppendToPath(&path, L"missingImage.gif"); + bool success = file_util::ReadFileToString(path, &broken_image_data); + if (!success) { + LOG(FATAL) << "Failed reading: " << path; + } + } + return broken_image_data; + } else if (resource_id == IDR_FEED_PREVIEW) { + // It is necessary to return a feed preview template that contains + // a {{URL}} substring where the feed URL should go; see the code + // that computes feed previews in feed_preview.cc:MakeFeedPreview. + // This fixes issue #932714. + return std::string("Feed preview for {{URL}}"); + } else { + return std::string(); + } +} + +NSCursor *LoadCursor(int cursor_id) { + switch (cursor_id) { + default: + return [NSCursor arrowCursor]; + } + return NULL; +} + +bool GetApplicationDirectory(std::string *path) { + NSString *bundle_path = [[NSBundle mainBundle] bundlePath]; + if (!bundle_path) + return false; + *path = [bundle_path UTF8String]; + return true; +} + +GURL GetInspectorURL() { + NSLog(@"GetInspectorURL"); + return GURL("test-shell-resource://inspector/inspector.html"); // is this right? +} + +std::string GetUIResourceProtocol() { + return "test-shell-resource"; +} + +bool GetInspectorHTMLPath(std::string *path) { + NSString *resource_path = [[NSBundle mainBundle] resourcePath]; + if (!resource_path) + return false; + *path = [resource_path UTF8String]; + *path += "/Inspector/inspector.htm"; + return true; +} + +bool GetExeDirectory(std::string *path) { + NSString *executable_path = [[NSBundle mainBundle] executablePath]; + if (!executable_path) + return false; + *path = [executable_path UTF8String]; + return true; +} + +bool SpellCheckWord(const char* word, int word_len, + int* misspelling_start, int* misspelling_len) { + // Report all words being correctly spelled. + *misspelling_start = 0; + *misspelling_len = 0; + return true; +} + +bool GetPlugins(bool refresh, std::vector<WebPluginInfo>* plugins) { + return false; // NPAPI::PluginList::Singleton()->GetPlugins(refresh, plugins); +} + +bool IsPluginRunningInRendererProcess() { + return true; +} + +bool DownloadUrl(const std::string& url, NSWindow *caller_window) { + return false; +} + +bool GetPluginFinderURL(std::string* plugin_finder_url) { + return false; +} + +bool IsDefaultPluginEnabled() { + return false; +} + +std::wstring GetWebKitLocale() { + return L"en-US"; +} + +void DidLoadPlugin(const std::string& filename) { +} + +void DidUnloadPlugin(const std::string& filename) { +} + +} // namespace webkit_glue + + +namespace activex_shim { + +bool IsActiveXAllowed(const std::string& clsid, const GURL& url) { + return false; // Um, no...On second thought, no. +} + +bool IsMimeTypeActiveX(const std::string& mimetype) { + return false; +} + +bool IsActiveXInstalled(const std::string& combined_clsid) { + return false; +} + + +bool GetClsidFromClassidAttribute(const std::string& classid, + std::string* clsid) { + return false; +} + +std::string GetVersionFromCodebaseAttribute(const std::string& codebase) { + return ""; +} + +} + +// These are here ONLY to satisfy link errors until we reinstate the objC +// bindings into WebCore. + +@interface DOMRange : NSObject { +}; +@end +@implementation DOMRange +@end + +@interface DOMDocumentFragment : NSObject { +}; +@end +@implementation DOMDocumentFragment +@end + +@interface DOMNode : NSObject { +}; +@end +@implementation DOMNode +@end + +@interface DOMElement : NSObject { +}; +@end +@implementation DOMElement +@end + +@interface DOMCSSStyleDeclaration : NSObject { +}; +@end +@implementation DOMCSSStyleDeclaration +@end |