| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include <ApplicationServices/ApplicationServices.h> | |
| 6 #import <Cocoa/Cocoa.h> | |
| 7 #import <objc/objc-runtime.h> | |
| 8 #include <sys/stat.h> | |
| 9 | |
| 10 #include "webkit/tools/test_shell/test_shell.h" | |
| 11 | |
| 12 #include "base/base_paths.h" | |
| 13 #include "base/basictypes.h" | |
| 14 #include "base/debug/debugger.h" | |
| 15 #include "base/file_util.h" | |
| 16 #include "base/files/file_path.h" | |
| 17 #include "base/logging.h" | |
| 18 #include "base/mac/bundle_locations.h" | |
| 19 #include "base/mac/mac_util.h" | |
| 20 #include "base/mac/scoped_nsautorelease_pool.h" | |
| 21 #include "base/message_loop.h" | |
| 22 #include "base/path_service.h" | |
| 23 #include "base/string16.h" | |
| 24 #include "base/strings/string_piece.h" | |
| 25 #include "base/utf_string_conversions.h" | |
| 26 #include "grit/webkit_resources.h" | |
| 27 #include "net/base/mime_util.h" | |
| 28 #include "skia/ext/bitmap_platform_device.h" | |
| 29 #include "testing/gtest/include/gtest/gtest.h" | |
| 30 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | |
| 31 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" | |
| 32 #include "ui/base/resource/data_pack.h" | |
| 33 #include "ui/gfx/size.h" | |
| 34 #include "webkit/glue/webkit_glue.h" | |
| 35 #include "webkit/glue/webpreferences.h" | |
| 36 #include "webkit/plugins/npapi/plugin_list.h" | |
| 37 #include "webkit/tools/test_shell/mac/test_shell_webview.h" | |
| 38 #include "webkit/tools/test_shell/resource.h" | |
| 39 #include "webkit/tools/test_shell/simple_resource_loader_bridge.h" | |
| 40 #include "webkit/tools/test_shell/test_navigation_controller.h" | |
| 41 #include "webkit/tools/test_shell/test_shell_webkit_init.h" | |
| 42 #include "webkit/tools/test_shell/test_webview_delegate.h" | |
| 43 | |
| 44 #include "third_party/skia/include/core/SkBitmap.h" | |
| 45 | |
| 46 #import "mac/DumpRenderTreePasteboard.h" | |
| 47 | |
| 48 using WebKit::WebWidget; | |
| 49 | |
| 50 #define MAX_LOADSTRING 100 | |
| 51 | |
| 52 // Sizes for URL bar layout | |
| 53 #define BUTTON_HEIGHT 22 | |
| 54 #define BUTTON_WIDTH 72 | |
| 55 #define BUTTON_MARGIN 8 | |
| 56 #define URLBAR_HEIGHT 32 | |
| 57 | |
| 58 // Global Variables: | |
| 59 | |
| 60 // Content area size for newly created windows. | |
| 61 const int kTestWindowWidth = 800; | |
| 62 const int kTestWindowHeight = 600; | |
| 63 | |
| 64 // The W3C SVG layout tests use a different size than the other layout tests | |
| 65 const int kSVGTestWindowWidth = 480; | |
| 66 const int kSVGTestWindowHeight = 360; | |
| 67 | |
| 68 // Hide the window offscreen when in layout test mode. Mac OS X limits | |
| 69 // window positions to +/- 16000. | |
| 70 const int kTestWindowXLocation = -14000; | |
| 71 const int kTestWindowYLocation = -14000; | |
| 72 | |
| 73 // Data pack resource. This is a pointer to the mmapped resources file. | |
| 74 static ui::DataPack* g_resource_data_pack = NULL; | |
| 75 | |
| 76 // Define static member variables | |
| 77 base::LazyInstance <std::map<gfx::NativeWindow, TestShell *> > | |
| 78 TestShell::window_map_ = LAZY_INSTANCE_INITIALIZER; | |
| 79 | |
| 80 // Helper method for getting the path to the test shell resources directory. | |
| 81 base::FilePath GetResourcesFilePath() { | |
| 82 base::FilePath path; | |
| 83 // We need to know if we're bundled or not to know which path to use. | |
| 84 if (base::mac::AmIBundled()) { | |
| 85 PathService::Get(base::DIR_EXE, &path); | |
| 86 path = path.Append(base::FilePath::kParentDirectory); | |
| 87 return path.AppendASCII("Resources"); | |
| 88 } else { | |
| 89 PathService::Get(base::DIR_SOURCE_ROOT, &path); | |
| 90 path = path.AppendASCII("webkit"); | |
| 91 path = path.AppendASCII("tools"); | |
| 92 path = path.AppendASCII("test_shell"); | |
| 93 return path.AppendASCII("resources"); | |
| 94 } | |
| 95 } | |
| 96 | |
| 97 // Receives notification that the window is closing so that it can start the | |
| 98 // tear-down process. Is responsible for deleting itself when done. | |
| 99 @interface WindowDelegate : NSObject<NSWindowDelegate> { | |
| 100 @private | |
| 101 TestShellWebView* m_webView; | |
| 102 } | |
| 103 - (id)initWithWebView:(TestShellWebView*)view; | |
| 104 @end | |
| 105 | |
| 106 @implementation WindowDelegate | |
| 107 | |
| 108 - (id)initWithWebView:(TestShellWebView*)view { | |
| 109 if ((self = [super init])) { | |
| 110 m_webView = view; | |
| 111 } | |
| 112 return self; | |
| 113 } | |
| 114 | |
| 115 - (void)windowDidBecomeKey:(NSNotification*)notification { | |
| 116 [m_webView setIsActive:YES]; | |
| 117 } | |
| 118 | |
| 119 - (void)windowDidResignKey:(NSNotification*)notification { | |
| 120 [m_webView setIsActive:NO]; | |
| 121 } | |
| 122 | |
| 123 // Called when the window is about to close. Perform the self-destruction | |
| 124 // sequence by getting rid of the shell and removing it and the window from | |
| 125 // the various global lists. Instead of doing it here, however, we fire off | |
| 126 // a delayed call to |-cleanup:| to allow everything to get off the stack | |
| 127 // before we go deleting objects. By returning YES, we allow the window to be | |
| 128 // removed from the screen. | |
| 129 - (BOOL)windowShouldClose:(id)window { | |
| 130 m_webView = nil; | |
| 131 | |
| 132 // Try to make the window go away, but it may not when running layout | |
| 133 // tests due to the quirkyness of autorelease pools and having no main loop. | |
| 134 [window autorelease]; | |
| 135 | |
| 136 // clean ourselves up and do the work after clearing the stack of anything | |
| 137 // that might have the shell on it. | |
| 138 [self performSelectorOnMainThread:@selector(cleanup:) | |
| 139 withObject:window | |
| 140 waitUntilDone:NO]; | |
| 141 | |
| 142 return YES; | |
| 143 } | |
| 144 | |
| 145 // does the work of removing the window from our various bookkeeping lists | |
| 146 // and gets rid of the shell. | |
| 147 - (void)cleanup:(id)window { | |
| 148 TestShell::RemoveWindowFromList(window); | |
| 149 TestShell::DestroyAssociatedShell(window); | |
| 150 | |
| 151 [self release]; | |
| 152 } | |
| 153 | |
| 154 @end | |
| 155 | |
| 156 // Mac-specific stuff to do when the dtor is called. Nothing to do in our | |
| 157 // case. | |
| 158 void TestShell::PlatformCleanUp() { | |
| 159 } | |
| 160 | |
| 161 void TestShell::EnableUIControl(UIControl control, bool is_enabled) { | |
| 162 // TODO(darin): Implement me. | |
| 163 } | |
| 164 | |
| 165 // static | |
| 166 void TestShell::DestroyAssociatedShell(gfx::NativeWindow handle) { | |
| 167 WindowMap::iterator it = window_map_.Get().find(handle); | |
| 168 if (it != window_map_.Get().end()) { | |
| 169 // Break the view's association with its shell before deleting the shell. | |
| 170 TestShellWebView* web_view = | |
| 171 static_cast<TestShellWebView*>(it->second->m_webViewHost->view_handle()); | |
| 172 if ([web_view isKindOfClass:[TestShellWebView class]]) { | |
| 173 [web_view setShell:NULL]; | |
| 174 } | |
| 175 | |
| 176 delete it->second; | |
| 177 window_map_.Get().erase(it); | |
| 178 } else { | |
| 179 LOG(ERROR) << "Failed to find shell for window during destroy"; | |
| 180 } | |
| 181 } | |
| 182 | |
| 183 // static | |
| 184 void TestShell::PlatformShutdown() { | |
| 185 // for each window in the window list, release it and destroy its shell | |
| 186 for (WindowList::iterator it = TestShell::windowList()->begin(); | |
| 187 it != TestShell::windowList()->end(); | |
| 188 ++it) { | |
| 189 DestroyAssociatedShell(*it); | |
| 190 [*it release]; | |
| 191 } | |
| 192 // assert if we have anything left over, that would be bad. | |
| 193 DCHECK(window_map_.Get().empty()); | |
| 194 | |
| 195 // Dump the pasteboards we built up. | |
| 196 [DumpRenderTreePasteboard releaseLocalPasteboards]; | |
| 197 } | |
| 198 | |
| 199 // static | |
| 200 void TestShell::InitializeTestShell(bool layout_test_mode, | |
| 201 bool allow_external_pages) { | |
| 202 // This should move to a per-process platform-specific initialization function | |
| 203 // when one exists. | |
| 204 | |
| 205 window_list_ = new WindowList; | |
| 206 layout_test_mode_ = layout_test_mode; | |
| 207 allow_external_pages_ = allow_external_pages; | |
| 208 | |
| 209 web_prefs_ = new WebPreferences; | |
| 210 | |
| 211 // mmap the data pack which holds strings used by WebCore. This is only | |
| 212 // a fatal error if we're bundled, which means we might be running layout | |
| 213 // tests. This is a harmless failure for test_shell_tests. | |
| 214 g_resource_data_pack = new ui::DataPack(ui::SCALE_FACTOR_100P); | |
| 215 NSString *resource_path = | |
| 216 [base::mac::FrameworkBundle() pathForResource:@"test_shell" | |
| 217 ofType:@"pak"]; | |
| 218 base::FilePath resources_pak_path([resource_path fileSystemRepresentation]); | |
| 219 if (!g_resource_data_pack->LoadFromPath(resources_pak_path)) { | |
| 220 LOG(FATAL) << "failed to load test_shell.pak"; | |
| 221 } | |
| 222 | |
| 223 ResetWebPreferences(); | |
| 224 | |
| 225 // Load the Ahem font, which is used by layout tests. | |
| 226 NSString* ahem_path = [[base::mac::FrameworkBundle() resourcePath] | |
| 227 stringByAppendingPathComponent:@"AHEM____.TTF"]; | |
| 228 NSURL* ahem_path_url = [NSURL fileURLWithPath:ahem_path]; | |
| 229 CFErrorRef error; | |
| 230 if (!CTFontManagerRegisterFontsForURL((CFURLRef)ahem_path_url, | |
| 231 kCTFontManagerScopeProcess, &error)) { | |
| 232 DLOG(FATAL) << "CTFontManagerRegisterFontsForURL " | |
| 233 << [ahem_path fileSystemRepresentation] | |
| 234 << [[(NSError*)error description] UTF8String]; | |
| 235 } | |
| 236 | |
| 237 // Add <app bundle's parent dir>/plugins to the plugin path so we can load | |
| 238 // test plugins. | |
| 239 base::FilePath plugins_dir; | |
| 240 PathService::Get(base::DIR_EXE, &plugins_dir); | |
| 241 if (base::mac::AmIBundled()) { | |
| 242 plugins_dir = plugins_dir.AppendASCII("../../../plugins"); | |
| 243 } else { | |
| 244 plugins_dir = plugins_dir.AppendASCII("plugins"); | |
| 245 } | |
| 246 webkit::npapi::PluginList::Singleton()->AddExtraPluginDir(plugins_dir); | |
| 247 } | |
| 248 | |
| 249 NSButton* MakeTestButton(NSRect* rect, NSString* title, NSView* parent) { | |
| 250 NSButton* button = [[[NSButton alloc] initWithFrame:*rect] autorelease]; | |
| 251 [button setTitle:title]; | |
| 252 [button setBezelStyle:NSSmallSquareBezelStyle]; | |
| 253 [button setAutoresizingMask:(NSViewMaxXMargin | NSViewMinYMargin)]; | |
| 254 [parent addSubview:button]; | |
| 255 rect->origin.x += BUTTON_WIDTH; | |
| 256 return button; | |
| 257 } | |
| 258 | |
| 259 bool TestShell::Initialize(const GURL& starting_url) { | |
| 260 // Perform application initialization: | |
| 261 // send message to app controller? need to work this out | |
| 262 | |
| 263 // TODO(awalker): this is a straight recreation of windows test_shell.cc's | |
| 264 // window creation code--we should really pull this from the nib and grab | |
| 265 // references to the already-created subviews that way. | |
| 266 NSRect screen_rect = [[NSScreen mainScreen] visibleFrame]; | |
| 267 NSRect window_rect = { {0, screen_rect.size.height - kTestWindowHeight}, | |
| 268 {kTestWindowWidth, kTestWindowHeight} }; | |
| 269 m_mainWnd = [[NSWindow alloc] | |
| 270 initWithContentRect:window_rect | |
| 271 styleMask:(NSTitledWindowMask | | |
| 272 NSClosableWindowMask | | |
| 273 NSMiniaturizableWindowMask | | |
| 274 NSResizableWindowMask ) | |
| 275 backing:NSBackingStoreBuffered | |
| 276 defer:NO]; | |
| 277 [m_mainWnd setTitle:@"TestShell"]; | |
| 278 | |
| 279 // Add to our map | |
| 280 window_map_.Get()[m_mainWnd] = this; | |
| 281 | |
| 282 // Rely on the window delegate to clean us up rather than immediately | |
| 283 // releasing when the window gets closed. We use the delegate to do | |
| 284 // everything from the autorelease pool so the shell isn't on the stack | |
| 285 // during cleanup (ie, a window close from javascript). | |
| 286 [m_mainWnd setReleasedWhenClosed:NO]; | |
| 287 | |
| 288 // Create a webview. Note that |web_view| takes ownership of this shell so we | |
| 289 // will get cleaned up when it gets destroyed. | |
| 290 m_webViewHost.reset( | |
| 291 WebViewHost::Create([m_mainWnd contentView], | |
| 292 delegate_.get(), | |
| 293 0, | |
| 294 *TestShell::web_prefs_)); | |
| 295 delegate_->RegisterDragDrop(); | |
| 296 TestShellWebView* web_view = | |
| 297 static_cast<TestShellWebView*>(m_webViewHost->view_handle()); | |
| 298 [web_view setShell:this]; | |
| 299 | |
| 300 // Create a window delegate to watch for when it's asked to go away. It will | |
| 301 // clean itself up so we don't need to hold a reference. | |
| 302 [m_mainWnd setDelegate:[[WindowDelegate alloc] initWithWebView:web_view]]; | |
| 303 | |
| 304 // create buttons | |
| 305 NSRect button_rect = [[m_mainWnd contentView] bounds]; | |
| 306 button_rect.origin.y = window_rect.size.height - URLBAR_HEIGHT + | |
| 307 (URLBAR_HEIGHT - BUTTON_HEIGHT) / 2; | |
| 308 button_rect.size.height = BUTTON_HEIGHT; | |
| 309 button_rect.origin.x += BUTTON_MARGIN; | |
| 310 button_rect.size.width = BUTTON_WIDTH; | |
| 311 | |
| 312 NSView* content = [m_mainWnd contentView]; | |
| 313 | |
| 314 NSButton* button = MakeTestButton(&button_rect, @"Back", content); | |
| 315 [button setTarget:web_view]; | |
| 316 [button setAction:@selector(goBack:)]; | |
| 317 | |
| 318 button = MakeTestButton(&button_rect, @"Forward", content); | |
| 319 [button setTarget:web_view]; | |
| 320 [button setAction:@selector(goForward:)]; | |
| 321 | |
| 322 // reload button | |
| 323 button = MakeTestButton(&button_rect, @"Reload", content); | |
| 324 [button setTarget:web_view]; | |
| 325 [button setAction:@selector(reload:)]; | |
| 326 | |
| 327 // stop button | |
| 328 button = MakeTestButton(&button_rect, @"Stop", content); | |
| 329 [button setTarget:web_view]; | |
| 330 [button setAction:@selector(stopLoading:)]; | |
| 331 | |
| 332 // text field for URL | |
| 333 button_rect.origin.x += BUTTON_MARGIN; | |
| 334 button_rect.size.width = [[m_mainWnd contentView] bounds].size.width - | |
| 335 button_rect.origin.x - BUTTON_MARGIN; | |
| 336 m_editWnd = [[NSTextField alloc] initWithFrame:button_rect]; | |
| 337 [[m_mainWnd contentView] addSubview:m_editWnd]; | |
| 338 [m_editWnd setAutoresizingMask:(NSViewWidthSizable | NSViewMinYMargin)]; | |
| 339 [m_editWnd setTarget:web_view]; | |
| 340 [m_editWnd setAction:@selector(takeURLStringValueFrom:)]; | |
| 341 [[m_editWnd cell] setWraps:NO]; | |
| 342 [[m_editWnd cell] setScrollable:YES]; | |
| 343 | |
| 344 // show the window | |
| 345 [m_mainWnd makeKeyAndOrderFront: nil]; | |
| 346 | |
| 347 // Load our initial content. | |
| 348 if (starting_url.is_valid()) | |
| 349 LoadURL(starting_url); | |
| 350 | |
| 351 if (IsSVGTestURL(starting_url)) { | |
| 352 SizeTo(kSVGTestWindowWidth, kSVGTestWindowHeight); | |
| 353 } else { | |
| 354 SizeToDefault(); | |
| 355 } | |
| 356 | |
| 357 return true; | |
| 358 } | |
| 359 | |
| 360 void TestShell::InteractiveSetFocus(WebWidgetHost* host, bool enable) { | |
| 361 if (enable) { | |
| 362 [[host->view_handle() window] makeKeyAndOrderFront:nil]; | |
| 363 } else { | |
| 364 // There is no way to resign key window status in Cocoa. Fake it by | |
| 365 // ordering the window out (transferring key status to another window) and | |
| 366 // then ordering the window back in, but without making it key. | |
| 367 [[host->view_handle() window] orderOut:nil]; | |
| 368 [[host->view_handle() window] orderFront:nil]; | |
| 369 } | |
| 370 } | |
| 371 | |
| 372 // static | |
| 373 void TestShell::DestroyWindow(gfx::NativeWindow windowHandle) { | |
| 374 // This code is like -cleanup: on our window delegate. This call needs to be | |
| 375 // able to force down a window for tests, so it closes down the window making | |
| 376 // sure it cleans up the window delegate and the test shells list of windows | |
| 377 // and map of windows to shells. | |
| 378 | |
| 379 TestShell::RemoveWindowFromList(windowHandle); | |
| 380 TestShell::DestroyAssociatedShell(windowHandle); | |
| 381 | |
| 382 id windowDelegate = [windowHandle delegate]; | |
| 383 DCHECK(windowDelegate); | |
| 384 [windowHandle setDelegate:nil]; | |
| 385 [windowDelegate release]; | |
| 386 | |
| 387 [windowHandle close]; | |
| 388 [windowHandle autorelease]; | |
| 389 } | |
| 390 | |
| 391 WebWidget* TestShell::CreatePopupWidget() { | |
| 392 DCHECK(!m_popupHost); | |
| 393 m_popupHost = WebWidgetHost::Create(webViewWnd(), popup_delegate_.get()); | |
| 394 | |
| 395 return m_popupHost->webwidget(); | |
| 396 } | |
| 397 | |
| 398 void TestShell::ClosePopup() { | |
| 399 // PostMessage(popupWnd(), WM_CLOSE, 0, 0); | |
| 400 m_popupHost = NULL; | |
| 401 } | |
| 402 | |
| 403 void TestShell::SizeTo(int width, int height) { | |
| 404 // WebViewHost::Create() sets the HTML content rect to start 32 pixels below | |
| 405 // the top of the window to account for the "toolbar". We need to match that | |
| 406 // here otherwise the HTML content area will be too short. | |
| 407 NSRect r = [m_mainWnd contentRectForFrameRect:[m_mainWnd frame]]; | |
| 408 r.size.width = width; | |
| 409 r.size.height = height + URLBAR_HEIGHT; | |
| 410 [m_mainWnd setFrame:[m_mainWnd frameRectForContentRect:r] display:YES]; | |
| 411 } | |
| 412 | |
| 413 void TestShell::ResizeSubViews() { | |
| 414 // handled by Cocoa for us | |
| 415 } | |
| 416 | |
| 417 /* static */ void TestShell::DumpAllBackForwardLists(base::string16* result) { | |
| 418 result->clear(); | |
| 419 for (WindowList::iterator iter = TestShell::windowList()->begin(); | |
| 420 iter != TestShell::windowList()->end(); iter++) { | |
| 421 NSWindow* window = *iter; | |
| 422 WindowMap::iterator it = window_map_.Get().find(window); | |
| 423 if (it != window_map_.Get().end()) | |
| 424 it->second->DumpBackForwardList(result); | |
| 425 else | |
| 426 LOG(ERROR) << "Failed to find shell for window during dump"; | |
| 427 } | |
| 428 } | |
| 429 | |
| 430 void TestShell::LoadURLForFrame(const GURL& url, | |
| 431 const base::string16& frame_name) { | |
| 432 if (!url.is_valid()) | |
| 433 return; | |
| 434 | |
| 435 if (IsSVGTestURL(url)) { | |
| 436 SizeTo(kSVGTestWindowWidth, kSVGTestWindowHeight); | |
| 437 } else { | |
| 438 // only resize back to the default when running tests | |
| 439 if (layout_test_mode()) | |
| 440 SizeToDefault(); | |
| 441 } | |
| 442 | |
| 443 navigation_controller_->LoadEntry( | |
| 444 new TestNavigationEntry(-1, url, frame_name)); | |
| 445 } | |
| 446 | |
| 447 bool TestShell::PromptForSaveFile(const wchar_t* prompt_title, | |
| 448 base::FilePath* result) | |
| 449 { | |
| 450 NSSavePanel* save_panel = [NSSavePanel savePanel]; | |
| 451 | |
| 452 /* set up new attributes */ | |
| 453 [save_panel setAllowedFileTypes:@[@"txt"]]; | |
| 454 [save_panel setMessage: | |
| 455 [NSString stringWithUTF8String:WideToUTF8(prompt_title).c_str()]]; | |
| 456 | |
| 457 /* display the NSSavePanel */ | |
| 458 [save_panel setDirectoryURL:[NSURL fileURLWithPath:NSHomeDirectory()]]; | |
| 459 [save_panel setNameFieldStringValue:@""]; | |
| 460 if ([save_panel runModal] == NSFileHandlingPanelOKButton) { | |
| 461 *result = base::FilePath([[[save_panel URL] path] fileSystemRepresentation])
; | |
| 462 return true; | |
| 463 } | |
| 464 return false; | |
| 465 } | |
| 466 | |
| 467 // static | |
| 468 std::string TestShell::RewriteLocalUrl(const std::string& url) { | |
| 469 // Convert file:///tmp/LayoutTests urls to the actual location on disk. | |
| 470 const char kPrefix[] = "file:///tmp/LayoutTests/"; | |
| 471 const int kPrefixLen = arraysize(kPrefix) - 1; | |
| 472 | |
| 473 std::string new_url(url); | |
| 474 if (url.compare(0, kPrefixLen, kPrefix, kPrefixLen) == 0) { | |
| 475 base::FilePath replace_path; | |
| 476 PathService::Get(base::DIR_SOURCE_ROOT, &replace_path); | |
| 477 replace_path = replace_path.Append( | |
| 478 "third_party/WebKit/LayoutTests/"); | |
| 479 new_url = std::string("file://") + replace_path.value() + | |
| 480 url.substr(kPrefixLen); | |
| 481 } | |
| 482 | |
| 483 return new_url; | |
| 484 } | |
| 485 | |
| 486 // static | |
| 487 void TestShell::ShowStartupDebuggingDialog() { | |
| 488 NSAlert* alert = [[[NSAlert alloc] init] autorelease]; | |
| 489 alert.messageText = @"Attach to me?"; | |
| 490 alert.informativeText = @"This would probably be a good time to attach your " | |
| 491 "debugger."; | |
| 492 [alert addButtonWithTitle:@"OK"]; | |
| 493 | |
| 494 [alert runModal]; | |
| 495 } | |
| 496 | |
| 497 base::StringPiece TestShell::ResourceProvider(int key) { | |
| 498 base::StringPiece res; | |
| 499 g_resource_data_pack->GetStringPiece(key, &res); | |
| 500 return res; | |
| 501 } | |
| 502 | |
| 503 //----------------------------------------------------------------------------- | |
| 504 | |
| 505 base::string16 TestShellWebKitInit::GetLocalizedString(int message_id) { | |
| 506 base::StringPiece res; | |
| 507 if (!g_resource_data_pack->GetStringPiece(message_id, &res)) { | |
| 508 LOG(FATAL) << "failed to load webkit string with id " << message_id; | |
| 509 } | |
| 510 | |
| 511 // Data packs hold strings as either UTF8 or UTF16. | |
| 512 base::string16 msg; | |
| 513 switch (g_resource_data_pack->GetTextEncodingType()) { | |
| 514 case ui::DataPack::UTF8: | |
| 515 msg = UTF8ToUTF16(res); | |
| 516 break; | |
| 517 case ui::DataPack::UTF16: | |
| 518 msg = base::string16(reinterpret_cast<const char16*>(res.data()), | |
| 519 res.length() / 2); | |
| 520 break; | |
| 521 case ui::DataPack::BINARY: | |
| 522 NOTREACHED(); | |
| 523 break; | |
| 524 } | |
| 525 | |
| 526 return msg; | |
| 527 } | |
| 528 | |
| 529 base::StringPiece TestShellWebKitInit::GetDataResource( | |
| 530 int resource_id, | |
| 531 ui::ScaleFactor scale_factor) { | |
| 532 switch (resource_id) { | |
| 533 case IDR_BROKENIMAGE: { | |
| 534 // Use webkit's broken image icon (16x16) | |
| 535 static std::string broken_image_data; | |
| 536 if (broken_image_data.empty()) { | |
| 537 base::FilePath path = GetResourcesFilePath(); | |
| 538 // In order to match WebKit's colors for the missing image, we have to | |
| 539 // use a PNG. The GIF doesn't have the color range needed to correctly | |
| 540 // match the TIFF they use in Safari. | |
| 541 path = path.AppendASCII("missingImage.png"); | |
| 542 bool success = file_util::ReadFileToString(path, &broken_image_data); | |
| 543 if (!success) { | |
| 544 LOG(FATAL) << "Failed reading: " << path.value(); | |
| 545 } | |
| 546 } | |
| 547 return broken_image_data; | |
| 548 } | |
| 549 case IDR_TEXTAREA_RESIZER: { | |
| 550 // Use webkit's text area resizer image. | |
| 551 static std::string resize_corner_data; | |
| 552 if (resize_corner_data.empty()) { | |
| 553 base::FilePath path = GetResourcesFilePath(); | |
| 554 path = path.AppendASCII("textAreaResizeCorner.png"); | |
| 555 bool success = file_util::ReadFileToString(path, &resize_corner_data); | |
| 556 if (!success) { | |
| 557 LOG(FATAL) << "Failed reading: " << path.value(); | |
| 558 } | |
| 559 } | |
| 560 return resize_corner_data; | |
| 561 } | |
| 562 | |
| 563 case IDR_SEARCH_CANCEL: | |
| 564 case IDR_SEARCH_CANCEL_PRESSED: | |
| 565 case IDR_SEARCH_MAGNIFIER: | |
| 566 case IDR_SEARCH_MAGNIFIER_RESULTS: | |
| 567 case IDR_INPUT_SPEECH: | |
| 568 case IDR_INPUT_SPEECH_RECORDING: | |
| 569 case IDR_INPUT_SPEECH_WAITING: | |
| 570 // TODO(flackr): Pass scale_factor to ResourceProvider. | |
| 571 return TestShell::ResourceProvider(resource_id); | |
| 572 | |
| 573 default: | |
| 574 break; | |
| 575 } | |
| 576 | |
| 577 return base::StringPiece(); | |
| 578 } | |
| 579 | |
| 580 namespace webkit_glue { | |
| 581 | |
| 582 bool DownloadUrl(const std::string& url, NSWindow* caller_window) { | |
| 583 return false; | |
| 584 } | |
| 585 | |
| 586 void DidLoadPlugin(const std::string& filename) { | |
| 587 } | |
| 588 | |
| 589 void DidUnloadPlugin(const std::string& filename) { | |
| 590 } | |
| 591 | |
| 592 } // namespace webkit_glue | |
| OLD | NEW |