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 #undef LOG | |
6 | |
7 #include "webkit/tools/test_shell/test_shell.h" | |
8 | |
9 #include "base/base_paths.h" | |
10 #include "base/command_line.h" | |
11 #include "base/debug/debug_on_start_win.h" | |
12 #include "base/file_util.h" | |
13 #include "base/files/file_path.h" | |
14 #include "base/md5.h" | |
15 #include "base/message_loop.h" | |
16 #include "base/metrics/stats_table.h" | |
17 #include "base/path_service.h" | |
18 #include "base/string_util.h" | |
19 #include "base/utf_string_conversions.h" | |
20 #include "build/build_config.h" | |
21 #include "googleurl/src/url_util.h" | |
22 #include "grit/webkit_strings.h" | |
23 #include "net/base/mime_util.h" | |
24 #include "net/base/net_util.h" | |
25 #include "net/url_request/url_request.h" | |
26 #include "net/url_request/url_request_file_job.h" | |
27 #include "net/url_request/url_request_filter.h" | |
28 #include "skia/ext/bitmap_platform_device.h" | |
29 #include "testing/gtest/include/gtest/gtest.h" | |
30 #include "third_party/skia/include/core/SkBitmap.h" | |
31 #include "third_party/WebKit/Source/Platform/chromium/public/WebRect.h" | |
32 #include "third_party/WebKit/Source/Platform/chromium/public/WebSize.h" | |
33 #include "third_party/WebKit/Source/Platform/chromium/public/WebString.h" | |
34 #include "third_party/WebKit/Source/Platform/chromium/public/WebURL.h" | |
35 #include "third_party/WebKit/Source/Platform/chromium/public/WebURLRequest.h" | |
36 #include "third_party/WebKit/Source/Platform/chromium/public/WebURLResponse.h" | |
37 #include "third_party/WebKit/Source/WebKit/chromium/public/WebAccessibilityObjec
t.h" | |
38 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDeviceOrientationC
lientMock.h" | |
39 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | |
40 #include "third_party/WebKit/Source/WebKit/chromium/public/WebGeolocationClientM
ock.h" | |
41 #include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h" | |
42 #include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptController.h
" | |
43 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" | |
44 #include "ui/gfx/codec/png_codec.h" | |
45 #include "ui/gfx/size.h" | |
46 #include "webkit/glue/glue_serialize.h" | |
47 #include "webkit/glue/webkit_glue.h" | |
48 #include "webkit/glue/webpreferences.h" | |
49 #include "webkit/tools/test_shell/notification_presenter.h" | |
50 #include "webkit/tools/test_shell/simple_resource_loader_bridge.h" | |
51 #include "webkit/tools/test_shell/test_navigation_controller.h" | |
52 #include "webkit/tools/test_shell/test_shell_devtools_agent.h" | |
53 #include "webkit/tools/test_shell/test_shell_devtools_client.h" | |
54 #include "webkit/tools/test_shell/test_shell_request_context.h" | |
55 #include "webkit/tools/test_shell/test_shell_switches.h" | |
56 #include "webkit/tools/test_shell/test_webview_delegate.h" | |
57 #include "webkit/user_agent/user_agent.h" | |
58 #include "webkit/user_agent/user_agent_util.h" | |
59 | |
60 using WebKit::WebCanvas; | |
61 using WebKit::WebFrame; | |
62 using WebKit::WebNavigationPolicy; | |
63 using WebKit::WebRect; | |
64 using WebKit::WebScriptController; | |
65 using WebKit::WebSize; | |
66 using WebKit::WebURLRequest; | |
67 using WebKit::WebView; | |
68 | |
69 namespace { | |
70 | |
71 // Default timeout in ms for file page loads when in layout test mode. | |
72 const int kDefaultFileTestTimeoutMillisecs = 10 * 1000; | |
73 | |
74 // Content area size for newly created windows. | |
75 const int kTestWindowWidth = 800; | |
76 const int kTestWindowHeight = 600; | |
77 | |
78 // The W3C SVG layout tests use a different size than the other layout | |
79 // tests. | |
80 const int kSVGTestWindowWidth = 480; | |
81 const int kSVGTestWindowHeight = 360; | |
82 | |
83 // URLRequestTestShellFileJob is used to serve the inspector | |
84 class URLRequestTestShellFileJob : public net::URLRequestFileJob { | |
85 public: | |
86 static net::URLRequestJob* InspectorFactory( | |
87 net::URLRequest* request, | |
88 net::NetworkDelegate* network_delegate, | |
89 const std::string& scheme) { | |
90 base::FilePath path; | |
91 PathService::Get(base::DIR_EXE, &path); | |
92 path = path.AppendASCII("resources"); | |
93 path = path.AppendASCII("inspector"); | |
94 path = path.AppendASCII(request->url().path().substr(1)); | |
95 return new URLRequestTestShellFileJob(request, network_delegate, path); | |
96 } | |
97 | |
98 private: | |
99 URLRequestTestShellFileJob(net::URLRequest* request, | |
100 net::NetworkDelegate* network_delegate, | |
101 const base::FilePath& path) | |
102 : net::URLRequestFileJob(request, network_delegate, path) { | |
103 } | |
104 virtual ~URLRequestTestShellFileJob() { } | |
105 | |
106 DISALLOW_COPY_AND_ASSIGN(URLRequestTestShellFileJob); | |
107 }; | |
108 | |
109 | |
110 } // namespace | |
111 | |
112 // Initialize static member variable | |
113 WindowList* TestShell::window_list_; | |
114 WebPreferences* TestShell::web_prefs_ = NULL; | |
115 bool TestShell::layout_test_mode_ = false; | |
116 bool TestShell::allow_external_pages_ = false; | |
117 std::vector<std::string> TestShell::js_flags_; | |
118 bool TestShell::accelerated_2d_canvas_enabled_ = false; | |
119 bool TestShell::accelerated_compositing_enabled_ = false; | |
120 | |
121 TestShell::TestParams::TestParams() | |
122 : dump_tree(true), | |
123 dump_pixels(false) { | |
124 } | |
125 | |
126 TestShell::TestShell() | |
127 : m_mainWnd(NULL), | |
128 m_editWnd(NULL), | |
129 m_webViewHost(NULL), | |
130 m_popupHost(NULL), | |
131 m_focusedWidgetHost(NULL), | |
132 #if defined(OS_WIN) | |
133 default_edit_wnd_proc_(0), | |
134 #endif | |
135 test_params_(NULL), | |
136 is_modal_(false), | |
137 is_loading_(false), | |
138 allow_images_(true), | |
139 allow_plugins_(true), | |
140 allow_scripts_(true), | |
141 dump_stats_table_on_exit_(false) { | |
142 delegate_.reset(new TestWebViewDelegate(this)); | |
143 popup_delegate_.reset(new TestWebViewDelegate(this)); | |
144 navigation_controller_.reset(new TestNavigationController(this)); | |
145 notification_presenter_.reset(new TestNotificationPresenter(this)); | |
146 | |
147 net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance(); | |
148 filter->AddHostnameHandler("test-shell-resource", "inspector", | |
149 &URLRequestTestShellFileJob::InspectorFactory); | |
150 url_util::AddStandardScheme("test-shell-resource"); | |
151 webkit_glue::SetUserAgent(webkit_glue::BuildUserAgentFromProduct( | |
152 "TestShell/0.0.0.0"), false); | |
153 } | |
154 | |
155 TestShell::~TestShell() { | |
156 delegate_->RevokeDragDrop(); | |
157 | |
158 // DevTools frontend page is supposed to be navigated only once and | |
159 // loading another URL in that Page is an error. | |
160 if (!dev_tools_client_.get()) { | |
161 // Navigate to an empty page to fire all the destruction logic for the | |
162 // current page. | |
163 LoadURL(GURL("about:blank")); | |
164 } | |
165 | |
166 net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance(); | |
167 filter->RemoveHostnameHandler("test-shell-resource", "inspector"); | |
168 | |
169 // Call GC twice to clean up garbage. | |
170 CallJSGC(); | |
171 CallJSGC(); | |
172 | |
173 // Destroy the WebView before the TestWebViewDelegate. | |
174 m_webViewHost.reset(); | |
175 | |
176 CloseDevTools(); | |
177 | |
178 PlatformCleanUp(); | |
179 | |
180 base::StatsTable *table = base::StatsTable::current(); | |
181 if (dump_stats_table_on_exit_) { | |
182 // Dump the stats table. | |
183 printf("<stats>\n"); | |
184 if (table != NULL) { | |
185 int counter_max = table->GetMaxCounters(); | |
186 for (int index = 0; index < counter_max; index++) { | |
187 std::string name(table->GetRowName(index)); | |
188 if (name.length() > 0) { | |
189 int value = table->GetRowValue(index); | |
190 printf("%s:\t%d\n", name.c_str(), value); | |
191 } | |
192 } | |
193 } | |
194 printf("</stats>\n"); | |
195 } | |
196 } | |
197 | |
198 void TestShell::UpdateNavigationControls() { | |
199 int current_index = navigation_controller()->GetCurrentEntryIndex(); | |
200 int max_index = navigation_controller()->GetEntryCount() - 1; | |
201 | |
202 EnableUIControl(BACK_BUTTON, current_index > 0); | |
203 EnableUIControl(FORWARD_BUTTON, current_index < max_index); | |
204 EnableUIControl(STOP_BUTTON, is_loading_); | |
205 } | |
206 | |
207 bool TestShell::CreateNewWindow(const GURL& starting_url, | |
208 TestShell** result) { | |
209 TestShell* shell = new TestShell(); | |
210 bool rv = shell->Initialize(starting_url); | |
211 if (rv) { | |
212 if (result) | |
213 *result = shell; | |
214 TestShell::windowList()->push_back(shell->m_mainWnd); | |
215 } | |
216 return rv; | |
217 } | |
218 | |
219 void TestShell::ShutdownTestShell() { | |
220 PlatformShutdown(); | |
221 SimpleResourceLoaderBridge::Shutdown(); | |
222 delete window_list_; | |
223 delete TestShell::web_prefs_; | |
224 } | |
225 | |
226 // All fatal log messages (e.g. DCHECK failures) imply unit test failures | |
227 static void UnitTestAssertHandler(const std::string& str) { | |
228 FAIL() << str; | |
229 } | |
230 | |
231 // static | |
232 void TestShell::InitLogging(bool suppress_error_dialogs, | |
233 bool layout_test_mode, | |
234 bool enable_gp_fault_error_box) { | |
235 if (suppress_error_dialogs) | |
236 logging::SetLogAssertHandler(UnitTestAssertHandler); | |
237 | |
238 #if defined(OS_WIN) | |
239 if (!IsDebuggerPresent()) { | |
240 UINT new_flags = SEM_FAILCRITICALERRORS | | |
241 SEM_NOOPENFILEERRORBOX; | |
242 if (!enable_gp_fault_error_box) | |
243 new_flags |= SEM_NOGPFAULTERRORBOX; | |
244 | |
245 // Preserve existing error mode, as discussed at | |
246 // http://blogs.msdn.com/oldnewthing/archive/2004/07/27/198410.aspx | |
247 UINT existing_flags = SetErrorMode(new_flags); | |
248 SetErrorMode(existing_flags | new_flags); | |
249 } | |
250 #endif | |
251 | |
252 // Only log to a file if we're running layout tests. This prevents debugging | |
253 // output from disrupting whether or not we pass. | |
254 logging::LoggingDestination destination = | |
255 logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG; | |
256 if (layout_test_mode) | |
257 destination = logging::LOG_ONLY_TO_FILE; | |
258 | |
259 // We might have multiple test_shell processes going at once | |
260 base::FilePath log_filename; | |
261 PathService::Get(base::DIR_EXE, &log_filename); | |
262 log_filename = log_filename.AppendASCII("test_shell.log"); | |
263 logging::InitLogging( | |
264 log_filename.value().c_str(), | |
265 destination, | |
266 logging::LOCK_LOG_FILE, | |
267 logging::DELETE_OLD_LOG_FILE, | |
268 logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS); | |
269 | |
270 // we want process and thread IDs because we may have multiple processes | |
271 logging::SetLogItems(true, true, false, true); | |
272 | |
273 // Turn on logging of notImplemented()s inside WebKit, but only if we're | |
274 // not running layout tests (because otherwise they'd corrupt the test | |
275 // output). | |
276 if (!layout_test_mode) | |
277 webkit_glue::EnableWebCoreLogChannels("NotYetImplemented"); | |
278 } | |
279 | |
280 // static | |
281 void TestShell::CleanupLogging() { | |
282 logging::CloseLogFile(); | |
283 } | |
284 | |
285 // static | |
286 void TestShell::SetAllowScriptsToCloseWindows() { | |
287 if (web_prefs_) | |
288 web_prefs_->allow_scripts_to_close_windows = true; | |
289 } | |
290 | |
291 // static | |
292 void TestShell::SetAccelerated2dCanvasEnabled(bool enabled) { | |
293 accelerated_2d_canvas_enabled_ = enabled; | |
294 } | |
295 | |
296 // static | |
297 void TestShell::SetAcceleratedCompositingEnabled(bool enabled) { | |
298 accelerated_compositing_enabled_ = enabled; | |
299 } | |
300 | |
301 // static | |
302 void TestShell::ResetWebPreferences() { | |
303 DCHECK(web_prefs_); | |
304 | |
305 // Match the settings used by Mac DumpRenderTree, with the exception of | |
306 // fonts. | |
307 if (web_prefs_) { | |
308 *web_prefs_ = WebPreferences(); | |
309 | |
310 #if defined(OS_MACOSX) | |
311 web_prefs_->serif_font_family_map[webkit_glue::kCommonScript] = | |
312 ASCIIToUTF16("Times"); | |
313 web_prefs_->cursive_font_family_map[webkit_glue::kCommonScript] = | |
314 ASCIIToUTF16("Apple Chancery"); | |
315 web_prefs_->fantasy_font_family_map[webkit_glue::kCommonScript] = | |
316 ASCIIToUTF16("Papyrus"); | |
317 #else | |
318 // NOTE: case matters here, this must be 'times new roman', else | |
319 // some layout tests fail. | |
320 web_prefs_->serif_font_family_map[webkit_glue::kCommonScript] = | |
321 ASCIIToUTF16("times new roman"); | |
322 | |
323 // These two fonts are picked from the intersection of | |
324 // Win XP font list and Vista font list : | |
325 // http://www.microsoft.com/typography/fonts/winxp.htm | |
326 // http://blogs.msdn.com/michkap/archive/2006/04/04/567881.aspx | |
327 // Some of them are installed only with CJK and complex script | |
328 // support enabled on Windows XP and are out of consideration here. | |
329 // (although we enabled both on our buildbots.) | |
330 // They (especially Impact for fantasy) are not typical cursive | |
331 // and fantasy fonts, but it should not matter for layout tests | |
332 // as long as they're available. | |
333 web_prefs_->cursive_font_family_map[webkit_glue::kCommonScript] = | |
334 ASCIIToUTF16("Comic Sans MS"); | |
335 web_prefs_->fantasy_font_family_map[webkit_glue::kCommonScript] = | |
336 ASCIIToUTF16("Impact"); | |
337 #endif | |
338 web_prefs_->standard_font_family_map[webkit_glue::kCommonScript] = | |
339 web_prefs_->serif_font_family_map[webkit_glue::kCommonScript]; | |
340 web_prefs_->fixed_font_family_map[webkit_glue::kCommonScript] = | |
341 ASCIIToUTF16("Courier"); | |
342 web_prefs_->sans_serif_font_family_map[webkit_glue::kCommonScript] = | |
343 ASCIIToUTF16("Helvetica"); | |
344 | |
345 web_prefs_->default_encoding = "ISO-8859-1"; | |
346 web_prefs_->default_font_size = 16; | |
347 web_prefs_->default_fixed_font_size = 13; | |
348 web_prefs_->minimum_font_size = 0; | |
349 web_prefs_->minimum_logical_font_size = 9; | |
350 web_prefs_->javascript_can_open_windows_automatically = true; | |
351 web_prefs_->dom_paste_enabled = true; | |
352 web_prefs_->site_specific_quirks_enabled = true; | |
353 web_prefs_->shrinks_standalone_images_to_fit = false; | |
354 web_prefs_->uses_universal_detector = false; | |
355 web_prefs_->java_enabled = false; | |
356 web_prefs_->allow_scripts_to_close_windows = false; | |
357 web_prefs_->javascript_can_access_clipboard = true; | |
358 web_prefs_->xss_auditor_enabled = false; | |
359 // It's off by default for Chrome, but we don't want to | |
360 // lose the coverage of dynamic font tests in webkit test. | |
361 web_prefs_->remote_fonts_enabled = true; | |
362 web_prefs_->local_storage_enabled = true; | |
363 web_prefs_->application_cache_enabled = true; | |
364 web_prefs_->databases_enabled = true; | |
365 web_prefs_->allow_file_access_from_file_urls = true; | |
366 // LayoutTests were written with Safari Mac in mind which does not allow | |
367 // tabbing to links by default. | |
368 web_prefs_->tabs_to_links = false; | |
369 web_prefs_->accelerated_2d_canvas_enabled = | |
370 accelerated_2d_canvas_enabled_; | |
371 web_prefs_->accelerated_compositing_enabled = | |
372 accelerated_compositing_enabled_; | |
373 // Allow those layout tests running as local files, i.e. under | |
374 // LayoutTests/http/tests/local, to access http server. | |
375 if (layout_test_mode_) | |
376 web_prefs_->allow_universal_access_from_file_urls = true; | |
377 web_prefs_->visual_word_movement_enabled = false; | |
378 } | |
379 } | |
380 | |
381 // static | |
382 WebPreferences* TestShell::GetWebPreferences() { | |
383 DCHECK(web_prefs_); | |
384 return web_prefs_; | |
385 } | |
386 | |
387 // static | |
388 bool TestShell::RemoveWindowFromList(gfx::NativeWindow window) { | |
389 WindowList::iterator entry = | |
390 std::find(TestShell::windowList()->begin(), | |
391 TestShell::windowList()->end(), | |
392 window); | |
393 if (entry != TestShell::windowList()->end()) { | |
394 TestShell::windowList()->erase(entry); | |
395 return true; | |
396 } | |
397 | |
398 return false; | |
399 } | |
400 | |
401 void TestShell::Show(WebNavigationPolicy policy) { | |
402 delegate_->show(policy); | |
403 } | |
404 | |
405 void TestShell::DumpBackForwardEntry(int index, base::string16* result) { | |
406 int current_index = navigation_controller_->GetLastCommittedEntryIndex(); | |
407 | |
408 std::string content_state = | |
409 navigation_controller_->GetEntryAtIndex(index)->GetContentState(); | |
410 if (content_state.empty()) { | |
411 content_state = webkit_glue::CreateHistoryStateForURL( | |
412 navigation_controller_->GetEntryAtIndex(index)->GetURL()); | |
413 } | |
414 | |
415 result->append( | |
416 webkit_glue::DumpHistoryState(content_state, 8, index == current_index)); | |
417 } | |
418 | |
419 void TestShell::DumpBackForwardList(base::string16* result) { | |
420 result->append(ASCIIToUTF16( | |
421 "\n============== Back Forward List ==============\n")); | |
422 | |
423 for (int i = 0; i < navigation_controller_->GetEntryCount(); ++i) | |
424 DumpBackForwardEntry(i, result); | |
425 | |
426 result->append(ASCIIToUTF16( | |
427 "===============================================\n")); | |
428 } | |
429 | |
430 void TestShell::CallJSGC() { | |
431 webView()->mainFrame()->collectGarbage(); | |
432 } | |
433 | |
434 WebView* TestShell::CreateWebView() { | |
435 // If we're running layout tests, only open a new window if the test has | |
436 // called testRunner.setCanOpenWindows() | |
437 if (layout_test_mode_) | |
438 return NULL; | |
439 | |
440 TestShell* new_win; | |
441 if (!CreateNewWindow(GURL(), &new_win)) | |
442 return NULL; | |
443 | |
444 return new_win->webView(); | |
445 } | |
446 | |
447 void TestShell::ShowDevTools() { | |
448 if (!devtools_shell_) { | |
449 base::FilePath dir_exe; | |
450 PathService::Get(base::DIR_EXE, &dir_exe); | |
451 base::FilePath devtools_path = | |
452 dir_exe.AppendASCII("resources/inspector/devtools.html"); | |
453 TestShell* devtools_shell; | |
454 TestShell::CreateNewWindow(GURL(devtools_path.value()), | |
455 &devtools_shell); | |
456 devtools_shell_ = devtools_shell->AsWeakPtr(); | |
457 devtools_shell_->CreateDevToolsClient(dev_tools_agent_.get()); | |
458 } | |
459 DCHECK(devtools_shell_); | |
460 devtools_shell_->Show(WebKit::WebNavigationPolicyNewWindow); | |
461 } | |
462 | |
463 void TestShell::CloseDevTools() { | |
464 if (devtools_shell_) | |
465 devtools_shell_->DestroyWindow(devtools_shell_->mainWnd()); | |
466 } | |
467 | |
468 void TestShell::CreateDevToolsClient(TestShellDevToolsAgent *agent) { | |
469 dev_tools_client_.reset(new TestShellDevToolsClient(agent, | |
470 webView())); | |
471 } | |
472 | |
473 bool TestShell::IsSVGTestURL(const GURL& url) { | |
474 return url.is_valid() && url.spec().find("W3C-SVG-1.1") != std::string::npos; | |
475 } | |
476 | |
477 void TestShell::SizeToSVG() { | |
478 SizeTo(kSVGTestWindowWidth, kSVGTestWindowHeight); | |
479 } | |
480 | |
481 void TestShell::SizeToDefault() { | |
482 SizeTo(kTestWindowWidth, kTestWindowHeight); | |
483 } | |
484 | |
485 void TestShell::ResetTestController() { | |
486 notification_presenter_->Reset(); | |
487 delegate_->Reset(); | |
488 if (geolocation_client_mock_.get()) | |
489 geolocation_client_mock_->resetMock(); | |
490 } | |
491 | |
492 void TestShell::LoadFile(const base::FilePath& file) { | |
493 LoadURLForFrame(net::FilePathToFileURL(file), base::string16()); | |
494 } | |
495 | |
496 void TestShell::LoadURL(const GURL& url) { | |
497 LoadURLForFrame(url, base::string16()); | |
498 } | |
499 | |
500 bool TestShell::Navigate(const TestNavigationEntry& entry, bool reload) { | |
501 // Get the right target frame for the entry. | |
502 WebFrame* frame = webView()->mainFrame(); | |
503 if (!entry.GetTargetFrame().empty()) | |
504 frame = webView()->findFrameByName(entry.GetTargetFrame()); | |
505 | |
506 // TODO(mpcomplete): should we clear the target frame, or should | |
507 // back/forward navigations maintain the target frame? | |
508 | |
509 // A navigation resulting from loading a javascript URL should not be | |
510 // treated as a browser initiated event. Instead, we want it to look as if | |
511 // the page initiated any load resulting from JS execution. | |
512 if (!entry.GetURL().SchemeIs("javascript")) { | |
513 delegate_->set_pending_extra_data( | |
514 new TestShellExtraData(entry.GetPageID())); | |
515 } | |
516 | |
517 // If we are reloading, then WebKit will use the state of the current page. | |
518 // Otherwise, we give it the state to navigate to. | |
519 if (reload) { | |
520 frame->reload(false); | |
521 } else if (!entry.GetContentState().empty()) { | |
522 DCHECK_NE(entry.GetPageID(), -1); | |
523 frame->loadHistoryItem( | |
524 webkit_glue::HistoryItemFromString(entry.GetContentState())); | |
525 } else { | |
526 DCHECK_EQ(entry.GetPageID(), -1); | |
527 frame->loadRequest(WebURLRequest(entry.GetURL())); | |
528 } | |
529 | |
530 // In case LoadRequest failed before DidCreateDataSource was called. | |
531 delegate_->set_pending_extra_data(NULL); | |
532 | |
533 // Restore focus to the main frame prior to loading new request. | |
534 // This makes sure that we don't have a focused iframe. Otherwise, that | |
535 // iframe would keep focus when the SetFocus called immediately after | |
536 // LoadRequest, thus making some tests fail (see http://b/issue?id=845337 | |
537 // for more details). | |
538 webView()->setFocusedFrame(frame); | |
539 SetFocus(webViewHost(), true); | |
540 | |
541 return true; | |
542 } | |
543 | |
544 void TestShell::GoBackOrForward(int offset) { | |
545 navigation_controller_->GoToOffset(offset); | |
546 } | |
547 | |
548 void TestShell::DumpDocumentText() { | |
549 base::FilePath file_path; | |
550 if (!PromptForSaveFile(L"Dump document text", &file_path)) | |
551 return; | |
552 | |
553 const std::string data = | |
554 UTF16ToUTF8(webkit_glue::DumpDocumentText(webView()->mainFrame())); | |
555 file_util::WriteFile(file_path, data.c_str(), data.length()); | |
556 } | |
557 | |
558 void TestShell::DumpRenderTree() { | |
559 base::FilePath file_path; | |
560 if (!PromptForSaveFile(L"Dump render tree", &file_path)) | |
561 return; | |
562 | |
563 const std::string data = | |
564 UTF16ToUTF8(webkit_glue::DumpRenderer(webView()->mainFrame())); | |
565 file_util::WriteFile(file_path, data.c_str(), data.length()); | |
566 } | |
567 | |
568 base::string16 TestShell::GetDocumentText() { | |
569 return webkit_glue::DumpDocumentText(webView()->mainFrame()); | |
570 } | |
571 | |
572 void TestShell::Reload() { | |
573 navigation_controller_->Reload(); | |
574 } | |
575 | |
576 void TestShell::SetFocus(WebWidgetHost* host, bool enable) { | |
577 if (!layout_test_mode_) { | |
578 InteractiveSetFocus(host, enable); | |
579 } else { | |
580 // Simulate the effects of InteractiveSetFocus(), which includes calling | |
581 // both setFocus() and setIsActive(). | |
582 if (enable) { | |
583 if (m_focusedWidgetHost != host) { | |
584 if (m_focusedWidgetHost) | |
585 m_focusedWidgetHost->webwidget()->setFocus(false); | |
586 webView()->setIsActive(enable); | |
587 host->webwidget()->setFocus(enable); | |
588 m_focusedWidgetHost = host; | |
589 } | |
590 } else { | |
591 if (m_focusedWidgetHost == host) { | |
592 host->webwidget()->setFocus(enable); | |
593 webView()->setIsActive(enable); | |
594 m_focusedWidgetHost = NULL; | |
595 } | |
596 } | |
597 } | |
598 } | |
599 | |
600 WebKit::WebDeviceOrientationClientMock* | |
601 TestShell::device_orientation_client_mock() { | |
602 if (!device_orientation_client_mock_.get()) { | |
603 device_orientation_client_mock_.reset( | |
604 WebKit::WebDeviceOrientationClientMock::create()); | |
605 } | |
606 return device_orientation_client_mock_.get(); | |
607 } | |
608 | |
609 WebKit::WebGeolocationClientMock* TestShell::geolocation_client_mock() { | |
610 if (!geolocation_client_mock_.get()) { | |
611 geolocation_client_mock_.reset( | |
612 WebKit::WebGeolocationClientMock::create()); | |
613 } | |
614 return geolocation_client_mock_.get(); | |
615 } | |
OLD | NEW |