Add support for mocking failed loads to WebURLLoaderMock.
[chromium-blink-merge.git] / webkit / support / webkit_support.cc
blob95e554b3c573833fec9be25c359bb6ddd01b6136
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.
5 #include "webkit/support/webkit_support.h"
7 #include "base/at_exit.h"
8 #include "base/base64.h"
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/command_line.h"
12 #include "base/debug/debugger.h"
13 #include "base/file_path.h"
14 #include "base/file_util.h"
15 #include "base/i18n/icu_util.h"
16 #include "base/logging.h"
17 #include "base/memory/ref_counted.h"
18 #include "base/memory/weak_ptr.h"
19 #include "base/message_loop.h"
20 #include "base/path_service.h"
21 #include "base/process_util.h"
22 #include "base/scoped_temp_dir.h"
23 #include "base/string_piece.h"
24 #include "base/string_util.h"
25 #include "base/stringprintf.h"
26 #include "base/sys_string_conversions.h"
27 #include "base/time.h"
28 #include "base/utf_string_conversions.h"
29 #include "googleurl/src/url_util.h"
30 #include "grit/webkit_chromium_resources.h"
31 #include "media/base/filter_collection.h"
32 #include "media/base/media_log.h"
33 #include "media/base/message_loop_factory.h"
34 #include "net/base/escape.h"
35 #include "net/base/net_errors.h"
36 #include "net/base/net_util.h"
37 #include "testing/gtest/include/gtest/gtest.h"
38 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCache.h"
39 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFileSystemCallbacks.h"
40 #include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h"
41 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginParams.h"
42 #include "third_party/WebKit/Source/WebKit/chromium/public/WebStorageNamespace.h"
43 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
44 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLError.h"
45 #if defined(TOOLKIT_GTK)
46 #include "ui/base/keycodes/keyboard_code_conversion_gtk.h"
47 #endif
48 #include "ui/gl/gl_context.h"
49 #include "ui/gl/gl_implementation.h"
50 #include "ui/gl/gl_surface.h"
51 #include "webkit/appcache/web_application_cache_host_impl.h"
52 #include "webkit/fileapi/isolated_context.h"
53 #include "webkit/glue/user_agent.h"
54 #include "webkit/glue/webkit_constants.h"
55 #include "webkit/glue/webkit_glue.h"
56 #include "webkit/glue/webkitplatformsupport_impl.h"
57 #include "webkit/glue/weburlrequest_extradata_impl.h"
58 #include "webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
59 #include "webkit/gpu/webgraphicscontext3d_in_process_impl.h"
60 #if defined(OS_ANDROID)
61 #include "webkit/media/android/webmediaplayer_android.h"
62 #include "webkit/media/android/webmediaplayer_manager_android.h"
63 #endif
64 #include "webkit/media/webmediaplayer_impl.h"
65 #include "webkit/plugins/npapi/plugin_list.h"
66 #include "webkit/plugins/npapi/webplugin_impl.h"
67 #include "webkit/plugins/npapi/webplugin_page_delegate.h"
68 #include "webkit/plugins/webplugininfo.h"
69 #include "webkit/support/platform_support.h"
70 #include "webkit/support/simple_database_system.h"
71 #include "webkit/support/test_webkit_platform_support.h"
72 #include "webkit/support/test_webplugin_page_delegate.h"
73 #include "webkit/tools/test_shell/simple_appcache_system.h"
74 #include "webkit/tools/test_shell/simple_dom_storage_system.h"
75 #include "webkit/tools/test_shell/simple_file_system.h"
76 #include "webkit/tools/test_shell/simple_resource_loader_bridge.h"
78 #if defined(OS_ANDROID)
79 #include "base/test/test_support_android.h"
80 #include "webkit/support/test_stream_texture_factory_android.h"
81 #endif
83 using WebKit::WebCString;
84 using WebKit::WebDevToolsAgentClient;
85 using WebKit::WebFileSystem;
86 using WebKit::WebFileSystemCallbacks;
87 using WebKit::WebFrame;
88 using WebKit::WebMediaPlayerClient;
89 using WebKit::WebPlugin;
90 using WebKit::WebPluginParams;
91 using WebKit::WebString;
92 using WebKit::WebURL;
93 using webkit::gpu::WebGraphicsContext3DInProcessImpl;
94 using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl;
96 namespace {
98 // All fatal log messages (e.g. DCHECK failures) imply unit test failures
99 void UnitTestAssertHandler(const std::string& str) {
100 FAIL() << str;
103 void InitLogging() {
104 #if defined(OS_WIN)
105 if (!::IsDebuggerPresent()) {
106 UINT new_flags = SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX
107 | SEM_NOGPFAULTERRORBOX;
109 // Preserve existing error mode, as discussed at
110 // http://blogs.msdn.com/oldnewthing/archive/2004/07/27/198410.aspx
111 UINT existing_flags = SetErrorMode(new_flags);
112 SetErrorMode(existing_flags | new_flags);
114 #endif
116 #if defined(OS_ANDROID)
117 // On Android we expect the log to appear in logcat.
118 base::InitAndroidTestLogging();
119 #else
120 FilePath log_filename;
121 PathService::Get(base::DIR_EXE, &log_filename);
122 log_filename = log_filename.AppendASCII("DumpRenderTree.log");
123 logging::InitLogging(
124 log_filename.value().c_str(),
125 // Only log to a file. This prevents debugging output from disrupting
126 // whether or not we pass.
127 logging::LOG_ONLY_TO_FILE,
128 // We might have multiple DumpRenderTree processes going at once.
129 logging::LOCK_LOG_FILE,
130 logging::DELETE_OLD_LOG_FILE,
131 logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS);
133 // We want process and thread IDs because we may have multiple processes.
134 const bool kProcessId = true;
135 const bool kThreadId = true;
136 const bool kTimestamp = true;
137 const bool kTickcount = true;
138 logging::SetLogItems(kProcessId, kThreadId, !kTimestamp, kTickcount);
139 #endif // else defined(OS_ANDROID)
142 class TestEnvironment {
143 public:
144 #if defined(OS_ANDROID)
145 // Android UI message loop goes through Java, so don't use it in tests.
146 typedef MessageLoop MessageLoopType;
147 #else
148 typedef MessageLoopForUI MessageLoopType;
149 #endif
151 TestEnvironment(bool unit_test_mode,
152 base::AtExitManager* existing_at_exit_manager,
153 WebKit::Platform* shadow_platform_delegate) {
154 if (unit_test_mode) {
155 logging::SetLogAssertHandler(UnitTestAssertHandler);
156 } else {
157 // The existing_at_exit_manager must be not NULL.
158 at_exit_manager_.reset(existing_at_exit_manager);
159 InitLogging();
161 main_message_loop_.reset(new MessageLoopType);
163 // TestWebKitPlatformSupport must be instantiated after MessageLoopType.
164 webkit_platform_support_.reset(
165 new TestWebKitPlatformSupport(unit_test_mode,
166 shadow_platform_delegate));
168 #if defined(OS_ANDROID)
169 media_player_manager_.reset(
170 new webkit_media::WebMediaPlayerManagerAndroid());
171 #endif
174 ~TestEnvironment() {
175 SimpleResourceLoaderBridge::Shutdown();
178 TestWebKitPlatformSupport* webkit_platform_support() const {
179 return webkit_platform_support_.get();
182 #if defined(OS_WIN) || defined(OS_MACOSX)
183 void set_theme_engine(WebKit::WebThemeEngine* engine) {
184 DCHECK(webkit_platform_support_ != 0);
185 webkit_platform_support_->SetThemeEngine(engine);
188 WebKit::WebThemeEngine* theme_engine() const {
189 return webkit_platform_support_->themeEngine();
191 #endif
193 #if defined(OS_ANDROID)
194 // On Android under layout test mode, we mock the current directory
195 // in SetCurrentDirectoryForFileURL() and GetAbsoluteWebStringFromUTF8Path(),
196 // as the directory might not exist on the device because we are using
197 // file-over-http bridge.
198 void set_mock_current_directory(const FilePath& directory) {
199 mock_current_directory_ = directory;
202 FilePath mock_current_directory() const {
203 return mock_current_directory_;
206 webkit_media::WebMediaPlayerManagerAndroid* media_player_manager() {
207 return media_player_manager_.get();
209 #endif
211 private:
212 // Data member at_exit_manager_ will take the ownership of the input
213 // AtExitManager and manage its lifecycle.
214 scoped_ptr<base::AtExitManager> at_exit_manager_;
215 scoped_ptr<MessageLoopType> main_message_loop_;
216 scoped_ptr<TestWebKitPlatformSupport> webkit_platform_support_;
218 #if defined(OS_ANDROID)
219 FilePath mock_current_directory_;
220 scoped_ptr<webkit_media::WebMediaPlayerManagerAndroid> media_player_manager_;
221 #endif
224 class WebPluginImplWithPageDelegate
225 : public webkit_support::TestWebPluginPageDelegate,
226 public base::SupportsWeakPtr<WebPluginImplWithPageDelegate>,
227 public webkit::npapi::WebPluginImpl {
228 public:
229 WebPluginImplWithPageDelegate(WebFrame* frame,
230 const WebPluginParams& params,
231 const FilePath& path)
232 : webkit_support::TestWebPluginPageDelegate(),
233 webkit::npapi::WebPluginImpl(frame, params, path, AsWeakPtr()) {}
234 virtual ~WebPluginImplWithPageDelegate() {}
235 private:
236 DISALLOW_COPY_AND_ASSIGN(WebPluginImplWithPageDelegate);
239 FilePath GetWebKitRootDirFilePath() {
240 FilePath basePath;
241 PathService::Get(base::DIR_SOURCE_ROOT, &basePath);
242 if (file_util::PathExists(
243 basePath.Append(FILE_PATH_LITERAL("third_party/WebKit")))) {
244 // We're in a WebKit-in-chrome checkout.
245 return basePath.Append(FILE_PATH_LITERAL("third_party/WebKit"));
246 } else if (file_util::PathExists(
247 basePath.Append(FILE_PATH_LITERAL("chromium")))) {
248 // We're in a WebKit-only checkout on Windows.
249 return basePath.Append(FILE_PATH_LITERAL("../.."));
250 } else if (file_util::PathExists(
251 basePath.Append(FILE_PATH_LITERAL("webkit/support")))) {
252 // We're in a WebKit-only/xcodebuild checkout on Mac
253 return basePath.Append(FILE_PATH_LITERAL("../../.."));
255 // We're in a WebKit-only, make-build, so the DIR_SOURCE_ROOT is already the
256 // WebKit root. That, or we have no idea where we are.
257 return basePath;
260 class WebKitClientMessageLoopImpl
261 : public WebDevToolsAgentClient::WebKitClientMessageLoop {
262 public:
263 WebKitClientMessageLoopImpl() : message_loop_(MessageLoop::current()) {}
264 virtual ~WebKitClientMessageLoopImpl() {
265 message_loop_ = NULL;
267 virtual void run() {
268 MessageLoop::ScopedNestableTaskAllower allow(message_loop_);
269 message_loop_->Run();
271 virtual void quitNow() {
272 message_loop_->QuitNow();
274 private:
275 MessageLoop* message_loop_;
278 webkit_support::GraphicsContext3DImplementation
279 g_graphics_context_3d_implementation =
280 webkit_support::IN_PROCESS_COMMAND_BUFFER;
282 TestEnvironment* test_environment;
284 void SetUpTestEnvironmentImpl(bool unit_test_mode,
285 WebKit::Platform* shadow_platform_delegate) {
286 base::EnableInProcessStackDumping();
287 base::EnableTerminationOnHeapCorruption();
289 // Initialize the singleton CommandLine with fixed values. Some code refer to
290 // CommandLine::ForCurrentProcess(). We don't use the actual command-line
291 // arguments of DRT to avoid unexpected behavior change.
293 // webkit/glue/plugin/plugin_list_posix.cc checks --debug-plugin-loading.
294 // webkit/glue/plugin/plugin_list_win.cc checks --old-wmp.
295 // If DRT needs these flags, specify them in the following kFixedArguments.
296 const char* kFixedArguments[] = {"DumpRenderTree"};
297 CommandLine::Init(arraysize(kFixedArguments), kFixedArguments);
299 // Explicitly initialize the GURL library before spawning any threads.
300 // Otherwise crash may happend when different threads try to create a GURL
301 // at same time.
302 url_util::Initialize();
303 base::AtExitManager* at_exit_manager = NULL;
304 // In Android DumpRenderTree, AtExitManager is created in
305 // testing/android/native_test_wrapper.cc before main() is called.
306 #if !defined(OS_ANDROID)
307 // Some initialization code may use a AtExitManager before initializing
308 // TestEnvironment, so we create a AtExitManager early and pass its ownership
309 // to TestEnvironment.
310 if (!unit_test_mode)
311 at_exit_manager = new base::AtExitManager;
312 #endif
313 webkit_support::BeforeInitialize(unit_test_mode);
314 test_environment = new TestEnvironment(unit_test_mode, at_exit_manager,
315 shadow_platform_delegate);
316 webkit_support::AfterInitialize(unit_test_mode);
317 if (!unit_test_mode) {
318 // Load ICU data tables. This has to run after TestEnvironment is created
319 // because on Linux, we need base::AtExitManager.
320 icu_util::Initialize();
322 webkit_glue::SetUserAgent(webkit_glue::BuildUserAgentFromProduct(
323 "DumpRenderTree/0.0.0.0"), false);
326 } // namespace
328 namespace webkit_support {
330 void SetUpTestEnvironment() {
331 SetUpTestEnvironment(NULL);
334 void SetUpTestEnvironmentForUnitTests() {
335 SetUpTestEnvironmentForUnitTests(NULL);
338 void SetUpTestEnvironment(WebKit::Platform* shadow_platform_delegate) {
339 SetUpTestEnvironmentImpl(false, shadow_platform_delegate);
342 void SetUpTestEnvironmentForUnitTests(
343 WebKit::Platform* shadow_platform_delegate) {
344 SetUpTestEnvironmentImpl(true, shadow_platform_delegate);
347 void TearDownTestEnvironment() {
348 // Flush any remaining messages before we kill ourselves.
349 // http://code.google.com/p/chromium/issues/detail?id=9500
350 MessageLoop::current()->RunAllPending();
352 BeforeShutdown();
353 if (RunningOnValgrind())
354 WebKit::WebCache::clear();
355 WebKit::shutdown();
356 delete test_environment;
357 test_environment = NULL;
358 AfterShutdown();
359 logging::CloseLogFile();
362 WebKit::WebKitPlatformSupport* GetWebKitPlatformSupport() {
363 DCHECK(test_environment);
364 return test_environment->webkit_platform_support();
367 WebPlugin* CreateWebPlugin(WebFrame* frame,
368 const WebPluginParams& params) {
369 const bool kAllowWildcard = true;
370 std::vector<webkit::WebPluginInfo> plugins;
371 std::vector<std::string> mime_types;
372 webkit::npapi::PluginList::Singleton()->GetPluginInfoArray(
373 params.url, params.mimeType.utf8(), kAllowWildcard,
374 NULL, &plugins, &mime_types);
375 if (plugins.empty())
376 return NULL;
378 WebPluginParams new_params = params;
379 new_params.mimeType = WebString::fromUTF8(mime_types.front());
380 return new WebPluginImplWithPageDelegate(
381 frame, new_params, plugins.front().path);
384 WebKit::WebMediaPlayer* CreateMediaPlayer(
385 WebFrame* frame,
386 WebMediaPlayerClient* client,
387 webkit_media::MediaStreamClient* media_stream_client) {
388 #if defined(OS_ANDROID)
389 return new webkit_media::WebMediaPlayerAndroid(
390 frame,
391 client,
392 GetWebKitPlatformSupport()->cookieJar(),
393 test_environment->media_player_manager(),
394 new webkit_support::TestStreamTextureFactory());
395 #else
396 scoped_ptr<media::MessageLoopFactory> message_loop_factory(
397 new media::MessageLoopFactory());
399 scoped_ptr<media::FilterCollection> collection(
400 new media::FilterCollection());
402 return new webkit_media::WebMediaPlayerImpl(
403 frame,
404 client,
405 base::WeakPtr<webkit_media::WebMediaPlayerDelegate>(),
406 collection.release(),
407 NULL,
408 NULL,
409 message_loop_factory.release(),
410 media_stream_client,
411 new media::MediaLog());
412 #endif
415 WebKit::WebMediaPlayer* CreateMediaPlayer(
416 WebFrame* frame,
417 WebMediaPlayerClient* client) {
418 return CreateMediaPlayer(frame, client, NULL);
421 #if defined(OS_ANDROID)
422 void ReleaseMediaResources() {
423 test_environment->media_player_manager()->ReleaseMediaResources();
425 #endif
427 WebKit::WebApplicationCacheHost* CreateApplicationCacheHost(
428 WebFrame*, WebKit::WebApplicationCacheHostClient* client) {
429 return SimpleAppCacheSystem::CreateApplicationCacheHost(client);
432 WebKit::WebStorageNamespace* CreateSessionStorageNamespace(unsigned quota) {
433 return SimpleDomStorageSystem::instance().CreateSessionStorageNamespace();
436 WebKit::WebString GetWebKitRootDir() {
437 FilePath path = GetWebKitRootDirFilePath();
438 std::string path_ascii = path.MaybeAsASCII();
439 CHECK(!path_ascii.empty());
440 return WebKit::WebString::fromUTF8(path_ascii.c_str());
443 void SetUpGLBindings(GLBindingPreferences bindingPref) {
444 switch (bindingPref) {
445 case GL_BINDING_DEFAULT:
446 gfx::GLSurface::InitializeOneOff();
447 break;
448 case GL_BINDING_SOFTWARE_RENDERER:
449 gfx::InitializeGLBindings(gfx::kGLImplementationOSMesaGL);
450 break;
451 default:
452 NOTREACHED();
456 void SetGraphicsContext3DImplementation(GraphicsContext3DImplementation impl) {
457 g_graphics_context_3d_implementation = impl;
460 GraphicsContext3DImplementation GetGraphicsContext3DImplementation() {
461 return g_graphics_context_3d_implementation;
464 WebKit::WebGraphicsContext3D* CreateGraphicsContext3D(
465 const WebKit::WebGraphicsContext3D::Attributes& attributes,
466 WebKit::WebView* web_view) {
467 switch (webkit_support::GetGraphicsContext3DImplementation()) {
468 case webkit_support::IN_PROCESS:
469 return WebGraphicsContext3DInProcessImpl::CreateForWebView(
470 attributes, true /* direct */);
471 case webkit_support::IN_PROCESS_COMMAND_BUFFER: {
472 scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> context(
473 new WebGraphicsContext3DInProcessCommandBufferImpl());
474 if (!context->Initialize(attributes, NULL))
475 return NULL;
476 return context.release();
479 NOTREACHED();
480 return NULL;
483 void RegisterMockedURL(const WebKit::WebURL& url,
484 const WebKit::WebURLResponse& response,
485 const WebKit::WebString& file_path) {
486 test_environment->webkit_platform_support()->url_loader_factory()->
487 RegisterURL(url, response, file_path);
490 void RegisterMockedErrorURL(const WebKit::WebURL& url,
491 const WebKit::WebURLResponse& response,
492 const WebKit::WebURLError& error) {
493 test_environment->webkit_platform_support()->url_loader_factory()->
494 RegisterErrorURL(url, response, error);
497 void UnregisterMockedURL(const WebKit::WebURL& url) {
498 test_environment->webkit_platform_support()->url_loader_factory()->
499 UnregisterURL(url);
502 void UnregisterAllMockedURLs() {
503 test_environment->webkit_platform_support()->url_loader_factory()->
504 UnregisterAllURLs();
507 void ServeAsynchronousMockedRequests() {
508 test_environment->webkit_platform_support()->url_loader_factory()->
509 ServeAsynchronousRequests();
512 WebKit::WebURLRequest GetLastHandledAsynchronousMockedRequest() {
513 return test_environment->webkit_platform_support()->url_loader_factory()->
514 GetLastHandledAsynchronousRequest();
517 // Wrapper for debug_util
518 bool BeingDebugged() {
519 return base::debug::BeingDebugged();
522 // Wrappers for MessageLoop
524 void RunMessageLoop() {
525 MessageLoop::current()->Run();
528 void QuitMessageLoop() {
529 MessageLoop::current()->Quit();
532 void QuitMessageLoopNow() {
533 MessageLoop::current()->QuitNow();
536 void RunAllPendingMessages() {
537 MessageLoop::current()->RunAllPending();
540 bool MessageLoopNestableTasksAllowed() {
541 return MessageLoop::current()->NestableTasksAllowed();
544 void MessageLoopSetNestableTasksAllowed(bool allowed) {
545 MessageLoop::current()->SetNestableTasksAllowed(allowed);
548 void DispatchMessageLoop() {
549 MessageLoop* current = MessageLoop::current();
550 MessageLoop::ScopedNestableTaskAllower allow(current);
551 current->RunAllPending();
554 WebDevToolsAgentClient::WebKitClientMessageLoop* CreateDevToolsMessageLoop() {
555 return new WebKitClientMessageLoopImpl();
558 void PostDelayedTask(void (*func)(void*), void* context, int64 delay_ms) {
559 MessageLoop::current()->PostDelayedTask(
560 FROM_HERE,
561 base::Bind(func, context),
562 base::TimeDelta::FromMilliseconds(delay_ms));
565 void PostDelayedTask(TaskAdaptor* task, int64 delay_ms) {
566 MessageLoop::current()->PostDelayedTask(
567 FROM_HERE,
568 base::Bind(&TaskAdaptor::Run, base::Owned(task)),
569 base::TimeDelta::FromMilliseconds(delay_ms));
572 // Wrappers for FilePath and file_util
574 WebString GetAbsoluteWebStringFromUTF8Path(const std::string& utf8_path) {
575 #if defined(OS_WIN)
576 FilePath path(UTF8ToWide(utf8_path));
577 file_util::AbsolutePath(&path);
578 return WebString(path.value());
579 #else
580 FilePath path(base::SysWideToNativeMB(base::SysUTF8ToWide(utf8_path)));
581 #if defined(OS_ANDROID)
582 if (WebKit::layoutTestMode()) {
583 // See comment of TestEnvironment::set_mock_current_directory().
584 if (!path.IsAbsolute()) {
585 // Not using FilePath::Append() because it can't handle '..' in path.
586 DCHECK(test_environment);
587 GURL base_url = net::FilePathToFileURL(
588 test_environment->mock_current_directory()
589 .Append(FILE_PATH_LITERAL("foo")));
590 net::FileURLToFilePath(base_url.Resolve(path.value()), &path);
592 } else {
593 file_util::AbsolutePath(&path);
595 #else
596 file_util::AbsolutePath(&path);
597 #endif // else defined(OS_ANDROID)
598 return WideToUTF16(base::SysNativeMBToWide(path.value()));
599 #endif // else defined(OS_WIN)
602 WebURL CreateURLForPathOrURL(const std::string& path_or_url_in_nativemb) {
603 // NativeMB to UTF-8
604 std::wstring wide_path_or_url
605 = base::SysNativeMBToWide(path_or_url_in_nativemb);
606 std::string path_or_url_in_utf8 = WideToUTF8(wide_path_or_url);
608 GURL url(path_or_url_in_utf8);
609 if (url.is_valid() && url.has_scheme())
610 return WebURL(url);
611 #if defined(OS_WIN)
612 return net::FilePathToFileURL(FilePath(wide_path_or_url));
613 #else
614 return net::FilePathToFileURL(FilePath(path_or_url_in_nativemb));
615 #endif
618 WebURL RewriteLayoutTestsURL(const std::string& utf8_url) {
619 const char kPrefix[] = "file:///tmp/LayoutTests/";
620 const int kPrefixLen = arraysize(kPrefix) - 1;
622 if (utf8_url.compare(0, kPrefixLen, kPrefix, kPrefixLen))
623 return WebURL(GURL(utf8_url));
625 FilePath replacePath =
626 GetWebKitRootDirFilePath().Append(FILE_PATH_LITERAL("LayoutTests/"));
628 // On Android, the file is actually accessed through file-over-http. Disable
629 // the following CHECK because the file is unlikely to exist on the device.
630 #if !defined(OS_ANDROID)
631 CHECK(file_util::PathExists(replacePath)) << replacePath.value() <<
632 " (re-written from " << utf8_url << ") does not exit";
633 #endif
635 #if defined(OS_WIN)
636 std::string utf8_path = WideToUTF8(replacePath.value());
637 #else
638 std::string utf8_path
639 = WideToUTF8(base::SysNativeMBToWide(replacePath.value()));
640 #endif
641 std::string newUrl = std::string("file://") + utf8_path
642 + utf8_url.substr(kPrefixLen);
643 return WebURL(GURL(newUrl));
646 bool SetCurrentDirectoryForFileURL(const WebKit::WebURL& fileUrl) {
647 FilePath local_path;
648 if (!net::FileURLToFilePath(fileUrl, &local_path))
649 return false;
650 #if defined(OS_ANDROID)
651 if (WebKit::layoutTestMode()) {
652 // See comment of TestEnvironment::set_mock_current_directory().
653 DCHECK(test_environment);
654 FilePath directory = local_path.DirName();
655 test_environment->set_mock_current_directory(directory);
656 // Still try to actually change the directory, but ignore any error.
657 // For a few tests that need to access resources directly as files
658 // (e.g. blob tests) we still push the resources and need to chdir there.
659 file_util::SetCurrentDirectory(directory);
660 return true;
662 #endif
663 return file_util::SetCurrentDirectory(local_path.DirName());
666 WebURL LocalFileToDataURL(const WebURL& fileUrl) {
667 FilePath local_path;
668 if (!net::FileURLToFilePath(fileUrl, &local_path))
669 return WebURL();
671 std::string contents;
672 if (!file_util::ReadFileToString(local_path, &contents))
673 return WebURL();
675 std::string contents_base64;
676 if (!base::Base64Encode(contents, &contents_base64))
677 return WebURL();
679 const char kDataUrlPrefix[] = "data:text/css;charset=utf-8;base64,";
680 return WebURL(GURL(kDataUrlPrefix + contents_base64));
683 // A wrapper object for exporting ScopedTempDir to be used
684 // by webkit layout tests.
685 class ScopedTempDirectoryInternal : public ScopedTempDirectory {
686 public:
687 virtual bool CreateUniqueTempDir() {
688 return tempDirectory_.CreateUniqueTempDir();
691 virtual std::string path() const {
692 return tempDirectory_.path().MaybeAsASCII();
695 private:
696 ScopedTempDir tempDirectory_;
699 ScopedTempDirectory* CreateScopedTempDirectory() {
700 return new ScopedTempDirectoryInternal();
703 int64 GetCurrentTimeInMillisecond() {
704 return base::TimeTicks::Now().ToInternalValue()
705 / base::Time::kMicrosecondsPerMillisecond;
708 std::string EscapePath(const std::string& path) {
709 return net::EscapePath(path);
712 std::string MakeURLErrorDescription(const WebKit::WebURLError& error) {
713 std::string domain = error.domain.utf8();
714 int code = error.reason;
716 if (domain == net::kErrorDomain) {
717 domain = "NSURLErrorDomain";
718 switch (error.reason) {
719 case net::ERR_ABORTED:
720 code = -999; // NSURLErrorCancelled
721 break;
722 case net::ERR_UNSAFE_PORT:
723 // Our unsafe port checking happens at the network stack level, but we
724 // make this translation here to match the behavior of stock WebKit.
725 domain = "WebKitErrorDomain";
726 code = 103;
727 break;
728 case net::ERR_ADDRESS_INVALID:
729 case net::ERR_ADDRESS_UNREACHABLE:
730 case net::ERR_NETWORK_ACCESS_DENIED:
731 code = -1004; // NSURLErrorCannotConnectToHost
732 break;
734 } else {
735 DLOG(WARNING) << "Unknown error domain";
738 return base::StringPrintf("<NSError domain %s, code %d, failing URL \"%s\">",
739 domain.c_str(), code, error.unreachableURL.spec().data());
742 WebKit::WebURLError CreateCancelledError(const WebKit::WebURLRequest& request) {
743 WebKit::WebURLError error;
744 error.domain = WebKit::WebString::fromUTF8(net::kErrorDomain);
745 error.reason = net::ERR_ABORTED;
746 error.unreachableURL = request.url();
747 return error;
750 WebKit::WebURLRequest::ExtraData* CreateWebURLRequestExtraData(
751 WebKit::WebReferrerPolicy referrer_policy) {
752 return new webkit_glue::WebURLRequestExtraDataImpl(referrer_policy,
753 WebKit::WebString());
756 // Bridge for SimpleDatabaseSystem
758 void SetDatabaseQuota(int quota) {
759 SimpleDatabaseSystem::GetInstance()->SetDatabaseQuota(quota);
762 void ClearAllDatabases() {
763 SimpleDatabaseSystem::GetInstance()->ClearAllDatabases();
766 // Bridge for SimpleResourceLoaderBridge
768 void SetAcceptAllCookies(bool accept) {
769 SimpleResourceLoaderBridge::SetAcceptAllCookies(accept);
772 // Theme engine
773 #if defined(OS_WIN) || defined(OS_MACOSX)
775 void SetThemeEngine(WebKit::WebThemeEngine* engine) {
776 DCHECK(test_environment);
777 test_environment->set_theme_engine(engine);
780 WebKit::WebThemeEngine* GetThemeEngine() {
781 DCHECK(test_environment);
782 return test_environment->theme_engine();
785 #endif
787 // DevTools
788 WebURL GetDevToolsPathAsURL() {
789 FilePath dirExe;
790 if (!PathService::Get(base::DIR_EXE, &dirExe)) {
791 DCHECK(false);
792 return WebURL();
794 FilePath devToolsPath = dirExe.AppendASCII(
795 "resources/inspector/devtools.html");
796 return net::FilePathToFileURL(devToolsPath);
799 // FileSystem
800 void OpenFileSystem(WebFrame* frame, WebFileSystem::Type type,
801 long long size, bool create, WebFileSystemCallbacks* callbacks) {
802 SimpleFileSystem* fileSystem = static_cast<SimpleFileSystem*>(
803 test_environment->webkit_platform_support()->fileSystem());
804 fileSystem->OpenFileSystem(frame, type, size, create, callbacks);
807 WebKit::WebString RegisterIsolatedFileSystem(
808 const WebKit::WebVector<WebKit::WebString>& filenames) {
809 fileapi::IsolatedContext::FileInfoSet files;
810 for (size_t i = 0; i < filenames.size(); ++i) {
811 FilePath path = webkit_glue::WebStringToFilePath(filenames[i]);
812 files.AddPath(path, NULL);
814 std::string filesystemId =
815 fileapi::IsolatedContext::GetInstance()->RegisterDraggedFileSystem(files);
816 return UTF8ToUTF16(filesystemId);
819 // Keyboard code
820 #if defined(TOOLKIT_GTK)
821 int NativeKeyCodeForWindowsKeyCode(int keycode, bool shift) {
822 ui::KeyboardCode code = static_cast<ui::KeyboardCode>(keycode);
823 return ui::GdkNativeKeyCodeForWindowsKeyCode(code, shift);
825 #endif
827 // Timers
828 double GetForegroundTabTimerInterval() {
829 return webkit_glue::kForegroundTabTimerInterval;
832 // Logging
833 void EnableWebCoreLogChannels(const std::string& channels) {
834 webkit_glue::EnableWebCoreLogChannels(channels);
837 void SetGamepadData(const WebKit::WebGamepads& pads) {
838 test_environment->webkit_platform_support()->setGamepadData(pads);
841 } // namespace webkit_support