OLD | NEW |
| (Empty) |
1 // Copyright 2013 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 "content/shell/browser/webkit_test_controller.h" | |
6 | |
7 #include <iostream> | |
8 | |
9 #include "base/base64.h" | |
10 #include "base/command_line.h" | |
11 #include "base/message_loop/message_loop.h" | |
12 #include "base/run_loop.h" | |
13 #include "base/strings/string_number_conversions.h" | |
14 #include "base/strings/stringprintf.h" | |
15 #include "content/public/browser/devtools_agent_host.h" | |
16 #include "content/public/browser/dom_storage_context.h" | |
17 #include "content/public/browser/gpu_data_manager.h" | |
18 #include "content/public/browser/navigation_controller.h" | |
19 #include "content/public/browser/navigation_entry.h" | |
20 #include "content/public/browser/notification_service.h" | |
21 #include "content/public/browser/notification_types.h" | |
22 #include "content/public/browser/render_process_host.h" | |
23 #include "content/public/browser/render_view_host.h" | |
24 #include "content/public/browser/render_widget_host_view.h" | |
25 #include "content/public/browser/storage_partition.h" | |
26 #include "content/public/browser/web_contents.h" | |
27 #include "content/public/common/content_switches.h" | |
28 #include "content/public/common/url_constants.h" | |
29 #include "content/shell/browser/layout_test/layout_test_devtools_frontend.h" | |
30 #include "content/shell/browser/shell.h" | |
31 #include "content/shell/browser/shell_browser_context.h" | |
32 #include "content/shell/browser/shell_content_browser_client.h" | |
33 #include "content/shell/browser/shell_devtools_frontend.h" | |
34 #include "content/shell/common/shell_messages.h" | |
35 #include "content/shell/common/shell_switches.h" | |
36 #include "content/shell/common/webkit_test_helpers.h" | |
37 #include "ui/gfx/codec/png_codec.h" | |
38 | |
39 namespace content { | |
40 | |
41 const int kTestSVGWindowWidthDip = 480; | |
42 const int kTestSVGWindowHeightDip = 360; | |
43 | |
44 // WebKitTestResultPrinter ---------------------------------------------------- | |
45 | |
46 WebKitTestResultPrinter::WebKitTestResultPrinter( | |
47 std::ostream* output, std::ostream* error) | |
48 : state_(DURING_TEST), | |
49 capture_text_only_(false), | |
50 encode_binary_data_(false), | |
51 output_(output), | |
52 error_(error) { | |
53 } | |
54 | |
55 WebKitTestResultPrinter::~WebKitTestResultPrinter() { | |
56 } | |
57 | |
58 void WebKitTestResultPrinter::PrintTextHeader() { | |
59 if (state_ != DURING_TEST) | |
60 return; | |
61 if (!capture_text_only_) | |
62 *output_ << "Content-Type: text/plain\n"; | |
63 state_ = IN_TEXT_BLOCK; | |
64 } | |
65 | |
66 void WebKitTestResultPrinter::PrintTextBlock(const std::string& block) { | |
67 if (state_ != IN_TEXT_BLOCK) | |
68 return; | |
69 *output_ << block; | |
70 } | |
71 | |
72 void WebKitTestResultPrinter::PrintTextFooter() { | |
73 if (state_ != IN_TEXT_BLOCK) | |
74 return; | |
75 if (!capture_text_only_) { | |
76 *output_ << "#EOF\n"; | |
77 output_->flush(); | |
78 } | |
79 state_ = IN_IMAGE_BLOCK; | |
80 } | |
81 | |
82 void WebKitTestResultPrinter::PrintImageHeader( | |
83 const std::string& actual_hash, | |
84 const std::string& expected_hash) { | |
85 if (state_ != IN_IMAGE_BLOCK || capture_text_only_) | |
86 return; | |
87 *output_ << "\nActualHash: " << actual_hash << "\n"; | |
88 if (!expected_hash.empty()) | |
89 *output_ << "\nExpectedHash: " << expected_hash << "\n"; | |
90 } | |
91 | |
92 void WebKitTestResultPrinter::PrintImageBlock( | |
93 const std::vector<unsigned char>& png_image) { | |
94 if (state_ != IN_IMAGE_BLOCK || capture_text_only_) | |
95 return; | |
96 *output_ << "Content-Type: image/png\n"; | |
97 if (encode_binary_data_) { | |
98 PrintEncodedBinaryData(png_image); | |
99 return; | |
100 } | |
101 | |
102 *output_ << "Content-Length: " << png_image.size() << "\n"; | |
103 output_->write( | |
104 reinterpret_cast<const char*>(&png_image[0]), png_image.size()); | |
105 } | |
106 | |
107 void WebKitTestResultPrinter::PrintImageFooter() { | |
108 if (state_ != IN_IMAGE_BLOCK) | |
109 return; | |
110 if (!capture_text_only_) { | |
111 *output_ << "#EOF\n"; | |
112 output_->flush(); | |
113 } | |
114 state_ = AFTER_TEST; | |
115 } | |
116 | |
117 void WebKitTestResultPrinter::PrintAudioHeader() { | |
118 DCHECK_EQ(state_, DURING_TEST); | |
119 if (!capture_text_only_) | |
120 *output_ << "Content-Type: audio/wav\n"; | |
121 state_ = IN_AUDIO_BLOCK; | |
122 } | |
123 | |
124 void WebKitTestResultPrinter::PrintAudioBlock( | |
125 const std::vector<unsigned char>& audio_data) { | |
126 if (state_ != IN_AUDIO_BLOCK || capture_text_only_) | |
127 return; | |
128 if (encode_binary_data_) { | |
129 PrintEncodedBinaryData(audio_data); | |
130 return; | |
131 } | |
132 | |
133 *output_ << "Content-Length: " << audio_data.size() << "\n"; | |
134 output_->write( | |
135 reinterpret_cast<const char*>(&audio_data[0]), audio_data.size()); | |
136 } | |
137 | |
138 void WebKitTestResultPrinter::PrintAudioFooter() { | |
139 if (state_ != IN_AUDIO_BLOCK) | |
140 return; | |
141 if (!capture_text_only_) { | |
142 *output_ << "#EOF\n"; | |
143 output_->flush(); | |
144 } | |
145 state_ = IN_IMAGE_BLOCK; | |
146 } | |
147 | |
148 void WebKitTestResultPrinter::AddMessage(const std::string& message) { | |
149 AddMessageRaw(message + "\n"); | |
150 } | |
151 | |
152 void WebKitTestResultPrinter::AddMessageRaw(const std::string& message) { | |
153 if (state_ != DURING_TEST) | |
154 return; | |
155 *output_ << message; | |
156 } | |
157 | |
158 void WebKitTestResultPrinter::AddErrorMessage(const std::string& message) { | |
159 if (!capture_text_only_) | |
160 *error_ << message << "\n"; | |
161 if (state_ != DURING_TEST) | |
162 return; | |
163 PrintTextHeader(); | |
164 *output_ << message << "\n"; | |
165 PrintTextFooter(); | |
166 PrintImageFooter(); | |
167 } | |
168 | |
169 void WebKitTestResultPrinter::PrintEncodedBinaryData( | |
170 const std::vector<unsigned char>& data) { | |
171 *output_ << "Content-Transfer-Encoding: base64\n"; | |
172 | |
173 std::string data_base64; | |
174 base::Base64Encode( | |
175 base::StringPiece(reinterpret_cast<const char*>(&data[0]), data.size()), | |
176 &data_base64); | |
177 | |
178 *output_ << "Content-Length: " << data_base64.length() << "\n"; | |
179 output_->write(data_base64.c_str(), data_base64.length()); | |
180 } | |
181 | |
182 void WebKitTestResultPrinter::CloseStderr() { | |
183 if (state_ != AFTER_TEST) | |
184 return; | |
185 if (!capture_text_only_) { | |
186 *error_ << "#EOF\n"; | |
187 error_->flush(); | |
188 } | |
189 } | |
190 | |
191 | |
192 // WebKitTestController ------------------------------------------------------- | |
193 | |
194 WebKitTestController* WebKitTestController::instance_ = NULL; | |
195 | |
196 // static | |
197 WebKitTestController* WebKitTestController::Get() { | |
198 DCHECK(instance_); | |
199 return instance_; | |
200 } | |
201 | |
202 WebKitTestController::WebKitTestController() | |
203 : main_window_(NULL), | |
204 test_phase_(BETWEEN_TESTS), | |
205 is_leak_detection_enabled_( | |
206 base::CommandLine::ForCurrentProcess()->HasSwitch( | |
207 switches::kEnableLeakDetection)), | |
208 crash_when_leak_found_(false), | |
209 devtools_frontend_(NULL) { | |
210 CHECK(!instance_); | |
211 instance_ = this; | |
212 | |
213 if (is_leak_detection_enabled_) { | |
214 std::string switchValue = | |
215 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | |
216 switches::kEnableLeakDetection); | |
217 crash_when_leak_found_ = switchValue == switches::kCrashOnFailure; | |
218 } | |
219 | |
220 printer_.reset(new WebKitTestResultPrinter(&std::cout, &std::cerr)); | |
221 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | |
222 switches::kEncodeBinary)) | |
223 printer_->set_encode_binary_data(true); | |
224 registrar_.Add(this, | |
225 NOTIFICATION_RENDERER_PROCESS_CREATED, | |
226 NotificationService::AllSources()); | |
227 GpuDataManager::GetInstance()->AddObserver(this); | |
228 ResetAfterLayoutTest(); | |
229 } | |
230 | |
231 WebKitTestController::~WebKitTestController() { | |
232 DCHECK(CalledOnValidThread()); | |
233 CHECK(instance_ == this); | |
234 CHECK(test_phase_ == BETWEEN_TESTS); | |
235 GpuDataManager::GetInstance()->RemoveObserver(this); | |
236 DiscardMainWindow(); | |
237 instance_ = NULL; | |
238 } | |
239 | |
240 bool WebKitTestController::PrepareForLayoutTest( | |
241 const GURL& test_url, | |
242 const base::FilePath& current_working_directory, | |
243 bool enable_pixel_dumping, | |
244 const std::string& expected_pixel_hash) { | |
245 DCHECK(CalledOnValidThread()); | |
246 test_phase_ = DURING_TEST; | |
247 current_working_directory_ = current_working_directory; | |
248 enable_pixel_dumping_ = enable_pixel_dumping; | |
249 expected_pixel_hash_ = expected_pixel_hash; | |
250 test_url_ = test_url; | |
251 printer_->reset(); | |
252 ShellBrowserContext* browser_context = | |
253 ShellContentBrowserClient::Get()->browser_context(); | |
254 if (test_url.spec().find("compositing/") != std::string::npos) | |
255 is_compositing_test_ = true; | |
256 initial_size_ = Shell::GetShellDefaultSize(); | |
257 // The W3C SVG layout tests use a different size than the other layout tests. | |
258 if (test_url.spec().find("W3C-SVG-1.1") != std::string::npos) | |
259 initial_size_ = gfx::Size(kTestSVGWindowWidthDip, kTestSVGWindowHeightDip); | |
260 if (!main_window_) { | |
261 main_window_ = content::Shell::CreateNewWindow( | |
262 browser_context, | |
263 GURL(), | |
264 NULL, | |
265 initial_size_); | |
266 WebContentsObserver::Observe(main_window_->web_contents()); | |
267 send_configuration_to_next_host_ = true; | |
268 current_pid_ = base::kNullProcessId; | |
269 main_window_->LoadURL(test_url); | |
270 } else { | |
271 #if defined(OS_MACOSX) | |
272 // Shell::SizeTo is not implemented on all platforms. | |
273 main_window_->SizeTo(initial_size_); | |
274 #endif | |
275 main_window_->web_contents()->GetRenderViewHost()->GetView() | |
276 ->SetSize(initial_size_); | |
277 main_window_->web_contents()->GetRenderViewHost()->WasResized(); | |
278 RenderViewHost* render_view_host = | |
279 main_window_->web_contents()->GetRenderViewHost(); | |
280 WebPreferences prefs = render_view_host->GetWebkitPreferences(); | |
281 OverrideWebkitPrefs(&prefs); | |
282 render_view_host->UpdateWebkitPreferences(prefs); | |
283 SendTestConfiguration(); | |
284 | |
285 NavigationController::LoadURLParams params(test_url); | |
286 params.transition_type = ui::PageTransitionFromInt( | |
287 ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR); | |
288 params.should_clear_history_list = true; | |
289 main_window_->web_contents()->GetController().LoadURLWithParams(params); | |
290 main_window_->web_contents()->Focus(); | |
291 } | |
292 main_window_->web_contents()->GetRenderViewHost()->SetActive(true); | |
293 main_window_->web_contents()->GetRenderViewHost()->Focus(); | |
294 return true; | |
295 } | |
296 | |
297 bool WebKitTestController::ResetAfterLayoutTest() { | |
298 DCHECK(CalledOnValidThread()); | |
299 printer_->PrintTextFooter(); | |
300 printer_->PrintImageFooter(); | |
301 printer_->CloseStderr(); | |
302 send_configuration_to_next_host_ = false; | |
303 test_phase_ = BETWEEN_TESTS; | |
304 is_compositing_test_ = false; | |
305 enable_pixel_dumping_ = false; | |
306 expected_pixel_hash_.clear(); | |
307 test_url_ = GURL(); | |
308 prefs_ = WebPreferences(); | |
309 should_override_prefs_ = false; | |
310 | |
311 #if defined(OS_ANDROID) | |
312 // Re-using the shell's main window on Android causes issues with networking | |
313 // requests never succeeding. See http://crbug.com/277652. | |
314 DiscardMainWindow(); | |
315 #endif | |
316 return true; | |
317 } | |
318 | |
319 void WebKitTestController::SetTempPath(const base::FilePath& temp_path) { | |
320 temp_path_ = temp_path; | |
321 } | |
322 | |
323 void WebKitTestController::RendererUnresponsive() { | |
324 DCHECK(CalledOnValidThread()); | |
325 LOG(WARNING) << "renderer unresponsive"; | |
326 } | |
327 | |
328 void WebKitTestController::WorkerCrashed() { | |
329 DCHECK(CalledOnValidThread()); | |
330 printer_->AddErrorMessage("#CRASHED - worker"); | |
331 DiscardMainWindow(); | |
332 } | |
333 | |
334 void WebKitTestController::OverrideWebkitPrefs(WebPreferences* prefs) { | |
335 if (should_override_prefs_) { | |
336 *prefs = prefs_; | |
337 } else { | |
338 ApplyLayoutTestDefaultPreferences(prefs); | |
339 if (is_compositing_test_) { | |
340 base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); | |
341 if (!command_line.HasSwitch(switches::kDisableGpu)) | |
342 prefs->accelerated_2d_canvas_enabled = true; | |
343 prefs->mock_scrollbars_enabled = true; | |
344 } | |
345 } | |
346 } | |
347 | |
348 void WebKitTestController::OpenURL(const GURL& url) { | |
349 if (test_phase_ != DURING_TEST) | |
350 return; | |
351 | |
352 Shell::CreateNewWindow(main_window_->web_contents()->GetBrowserContext(), | |
353 url, | |
354 main_window_->web_contents()->GetSiteInstance(), | |
355 gfx::Size()); | |
356 } | |
357 | |
358 void WebKitTestController::TestFinishedInSecondaryWindow() { | |
359 RenderViewHost* render_view_host = | |
360 main_window_->web_contents()->GetRenderViewHost(); | |
361 render_view_host->Send( | |
362 new ShellViewMsg_NotifyDone(render_view_host->GetRoutingID())); | |
363 } | |
364 | |
365 bool WebKitTestController::IsMainWindow(WebContents* web_contents) const { | |
366 return main_window_ && web_contents == main_window_->web_contents(); | |
367 } | |
368 | |
369 bool WebKitTestController::OnMessageReceived(const IPC::Message& message) { | |
370 DCHECK(CalledOnValidThread()); | |
371 bool handled = true; | |
372 IPC_BEGIN_MESSAGE_MAP(WebKitTestController, message) | |
373 IPC_MESSAGE_HANDLER(ShellViewHostMsg_PrintMessage, OnPrintMessage) | |
374 IPC_MESSAGE_HANDLER(ShellViewHostMsg_TextDump, OnTextDump) | |
375 IPC_MESSAGE_HANDLER(ShellViewHostMsg_ImageDump, OnImageDump) | |
376 IPC_MESSAGE_HANDLER(ShellViewHostMsg_AudioDump, OnAudioDump) | |
377 IPC_MESSAGE_HANDLER(ShellViewHostMsg_OverridePreferences, | |
378 OnOverridePreferences) | |
379 IPC_MESSAGE_HANDLER(ShellViewHostMsg_TestFinished, OnTestFinished) | |
380 IPC_MESSAGE_HANDLER(ShellViewHostMsg_ClearDevToolsLocalStorage, | |
381 OnClearDevToolsLocalStorage) | |
382 IPC_MESSAGE_HANDLER(ShellViewHostMsg_ShowDevTools, OnShowDevTools) | |
383 IPC_MESSAGE_HANDLER(ShellViewHostMsg_CloseDevTools, OnCloseDevTools) | |
384 IPC_MESSAGE_HANDLER(ShellViewHostMsg_GoToOffset, OnGoToOffset) | |
385 IPC_MESSAGE_HANDLER(ShellViewHostMsg_Reload, OnReload) | |
386 IPC_MESSAGE_HANDLER(ShellViewHostMsg_LoadURLForFrame, OnLoadURLForFrame) | |
387 IPC_MESSAGE_HANDLER(ShellViewHostMsg_CaptureSessionHistory, | |
388 OnCaptureSessionHistory) | |
389 IPC_MESSAGE_HANDLER(ShellViewHostMsg_CloseRemainingWindows, | |
390 OnCloseRemainingWindows) | |
391 IPC_MESSAGE_HANDLER(ShellViewHostMsg_ResetDone, OnResetDone) | |
392 IPC_MESSAGE_HANDLER(ShellViewHostMsg_LeakDetectionDone, OnLeakDetectionDone) | |
393 IPC_MESSAGE_UNHANDLED(handled = false) | |
394 IPC_END_MESSAGE_MAP() | |
395 | |
396 return handled; | |
397 } | |
398 | |
399 void WebKitTestController::PluginCrashed(const base::FilePath& plugin_path, | |
400 base::ProcessId plugin_pid) { | |
401 DCHECK(CalledOnValidThread()); | |
402 printer_->AddErrorMessage( | |
403 base::StringPrintf("#CRASHED - plugin (pid %d)", plugin_pid)); | |
404 base::MessageLoop::current()->PostTask( | |
405 FROM_HERE, | |
406 base::Bind(base::IgnoreResult(&WebKitTestController::DiscardMainWindow), | |
407 base::Unretained(this))); | |
408 } | |
409 | |
410 void WebKitTestController::RenderViewCreated(RenderViewHost* render_view_host) { | |
411 DCHECK(CalledOnValidThread()); | |
412 // Might be kNullProcessHandle, in which case we will receive a notification | |
413 // later when the RenderProcessHost was created. | |
414 if (render_view_host->GetProcess()->GetHandle() != base::kNullProcessHandle) | |
415 current_pid_ = base::GetProcId(render_view_host->GetProcess()->GetHandle()); | |
416 if (!send_configuration_to_next_host_) | |
417 return; | |
418 send_configuration_to_next_host_ = false; | |
419 SendTestConfiguration(); | |
420 } | |
421 | |
422 void WebKitTestController::RenderProcessGone(base::TerminationStatus status) { | |
423 DCHECK(CalledOnValidThread()); | |
424 if (current_pid_ != base::kNullProcessId) { | |
425 printer_->AddErrorMessage(std::string("#CRASHED - renderer (pid ") + | |
426 base::IntToString(current_pid_) + ")"); | |
427 } else { | |
428 printer_->AddErrorMessage("#CRASHED - renderer"); | |
429 } | |
430 DiscardMainWindow(); | |
431 } | |
432 | |
433 void WebKitTestController::DevToolsProcessCrashed() { | |
434 DCHECK(CalledOnValidThread()); | |
435 printer_->AddErrorMessage("#CRASHED - devtools"); | |
436 if (devtools_frontend_) | |
437 devtools_frontend_->Close(); | |
438 devtools_frontend_ = NULL; | |
439 } | |
440 | |
441 void WebKitTestController::WebContentsDestroyed() { | |
442 DCHECK(CalledOnValidThread()); | |
443 printer_->AddErrorMessage("FAIL: main window was destroyed"); | |
444 DiscardMainWindow(); | |
445 } | |
446 | |
447 void WebKitTestController::Observe(int type, | |
448 const NotificationSource& source, | |
449 const NotificationDetails& details) { | |
450 DCHECK(CalledOnValidThread()); | |
451 switch (type) { | |
452 case NOTIFICATION_RENDERER_PROCESS_CREATED: { | |
453 if (!main_window_) | |
454 return; | |
455 RenderViewHost* render_view_host = | |
456 main_window_->web_contents()->GetRenderViewHost(); | |
457 if (!render_view_host) | |
458 return; | |
459 RenderProcessHost* render_process_host = | |
460 Source<RenderProcessHost>(source).ptr(); | |
461 if (render_process_host != render_view_host->GetProcess()) | |
462 return; | |
463 current_pid_ = base::GetProcId(render_process_host->GetHandle()); | |
464 break; | |
465 } | |
466 default: | |
467 NOTREACHED(); | |
468 } | |
469 } | |
470 | |
471 void WebKitTestController::OnGpuProcessCrashed( | |
472 base::TerminationStatus exit_code) { | |
473 DCHECK(CalledOnValidThread()); | |
474 printer_->AddErrorMessage("#CRASHED - gpu"); | |
475 DiscardMainWindow(); | |
476 } | |
477 | |
478 void WebKitTestController::DiscardMainWindow() { | |
479 // If we're running a test, we need to close all windows and exit the message | |
480 // loop. Otherwise, we're already outside of the message loop, and we just | |
481 // discard the main window. | |
482 WebContentsObserver::Observe(NULL); | |
483 if (test_phase_ != BETWEEN_TESTS) { | |
484 Shell::CloseAllWindows(); | |
485 base::MessageLoop::current()->PostTask(FROM_HERE, | |
486 base::MessageLoop::QuitClosure()); | |
487 test_phase_ = CLEAN_UP; | |
488 } else if (main_window_) { | |
489 main_window_->Close(); | |
490 } | |
491 main_window_ = NULL; | |
492 current_pid_ = base::kNullProcessId; | |
493 } | |
494 | |
495 void WebKitTestController::SendTestConfiguration() { | |
496 RenderViewHost* render_view_host = | |
497 main_window_->web_contents()->GetRenderViewHost(); | |
498 ShellTestConfiguration params; | |
499 params.current_working_directory = current_working_directory_; | |
500 params.temp_path = temp_path_; | |
501 params.test_url = test_url_; | |
502 params.enable_pixel_dumping = enable_pixel_dumping_; | |
503 params.allow_external_pages = | |
504 base::CommandLine::ForCurrentProcess()->HasSwitch( | |
505 switches::kAllowExternalPages); | |
506 params.expected_pixel_hash = expected_pixel_hash_; | |
507 params.initial_size = initial_size_; | |
508 render_view_host->Send(new ShellViewMsg_SetTestConfiguration( | |
509 render_view_host->GetRoutingID(), params)); | |
510 } | |
511 | |
512 void WebKitTestController::OnTestFinished() { | |
513 test_phase_ = CLEAN_UP; | |
514 if (!printer_->output_finished()) | |
515 printer_->PrintImageFooter(); | |
516 RenderViewHost* render_view_host = | |
517 main_window_->web_contents()->GetRenderViewHost(); | |
518 main_window_->web_contents()->ExitFullscreen(); | |
519 base::MessageLoop::current()->PostTask( | |
520 FROM_HERE, | |
521 base::Bind(base::IgnoreResult(&WebKitTestController::Send), | |
522 base::Unretained(this), | |
523 new ShellViewMsg_Reset(render_view_host->GetRoutingID()))); | |
524 } | |
525 | |
526 void WebKitTestController::OnImageDump( | |
527 const std::string& actual_pixel_hash, | |
528 const SkBitmap& image) { | |
529 SkAutoLockPixels image_lock(image); | |
530 | |
531 printer_->PrintImageHeader(actual_pixel_hash, expected_pixel_hash_); | |
532 | |
533 // Only encode and dump the png if the hashes don't match. Encoding the | |
534 // image is really expensive. | |
535 if (actual_pixel_hash != expected_pixel_hash_) { | |
536 std::vector<unsigned char> png; | |
537 | |
538 bool discard_transparency = true; | |
539 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | |
540 switches::kEnableOverlayFullscreenVideo)) | |
541 discard_transparency = false; | |
542 | |
543 std::vector<gfx::PNGCodec::Comment> comments; | |
544 comments.push_back(gfx::PNGCodec::Comment("checksum", actual_pixel_hash)); | |
545 bool success = gfx::PNGCodec::Encode( | |
546 static_cast<const unsigned char*>(image.getPixels()), | |
547 gfx::PNGCodec::FORMAT_BGRA, | |
548 gfx::Size(image.width(), image.height()), | |
549 static_cast<int>(image.rowBytes()), | |
550 discard_transparency, | |
551 comments, | |
552 &png); | |
553 if (success) | |
554 printer_->PrintImageBlock(png); | |
555 } | |
556 printer_->PrintImageFooter(); | |
557 } | |
558 | |
559 void WebKitTestController::OnAudioDump(const std::vector<unsigned char>& dump) { | |
560 printer_->PrintAudioHeader(); | |
561 printer_->PrintAudioBlock(dump); | |
562 printer_->PrintAudioFooter(); | |
563 } | |
564 | |
565 void WebKitTestController::OnTextDump(const std::string& dump) { | |
566 printer_->PrintTextHeader(); | |
567 printer_->PrintTextBlock(dump); | |
568 printer_->PrintTextFooter(); | |
569 } | |
570 | |
571 void WebKitTestController::OnPrintMessage(const std::string& message) { | |
572 printer_->AddMessageRaw(message); | |
573 } | |
574 | |
575 void WebKitTestController::OnOverridePreferences(const WebPreferences& prefs) { | |
576 should_override_prefs_ = true; | |
577 prefs_ = prefs; | |
578 } | |
579 | |
580 void WebKitTestController::OnClearDevToolsLocalStorage() { | |
581 ShellBrowserContext* browser_context = | |
582 ShellContentBrowserClient::Get()->browser_context(); | |
583 StoragePartition* storage_partition = | |
584 BrowserContext::GetStoragePartition(browser_context, NULL); | |
585 storage_partition->GetDOMStorageContext()->DeleteLocalStorage( | |
586 content::LayoutTestDevToolsFrontend::GetDevToolsPathAsURL("", "") | |
587 .GetOrigin()); | |
588 } | |
589 | |
590 void WebKitTestController::OnShowDevTools(const std::string& settings, | |
591 const std::string& frontend_url) { | |
592 if (!devtools_frontend_) { | |
593 devtools_frontend_ = LayoutTestDevToolsFrontend::Show( | |
594 main_window_->web_contents(), settings, frontend_url); | |
595 } else { | |
596 devtools_frontend_->ReuseFrontend(settings, frontend_url); | |
597 } | |
598 devtools_frontend_->Activate(); | |
599 devtools_frontend_->Focus(); | |
600 } | |
601 | |
602 void WebKitTestController::OnCloseDevTools() { | |
603 if (devtools_frontend_) | |
604 devtools_frontend_->DisconnectFromTarget(); | |
605 } | |
606 | |
607 void WebKitTestController::OnGoToOffset(int offset) { | |
608 main_window_->GoBackOrForward(offset); | |
609 } | |
610 | |
611 void WebKitTestController::OnReload() { | |
612 main_window_->Reload(); | |
613 } | |
614 | |
615 void WebKitTestController::OnLoadURLForFrame(const GURL& url, | |
616 const std::string& frame_name) { | |
617 main_window_->LoadURLForFrame(url, frame_name); | |
618 } | |
619 | |
620 void WebKitTestController::OnCaptureSessionHistory() { | |
621 std::vector<int> routing_ids; | |
622 std::vector<std::vector<PageState> > session_histories; | |
623 std::vector<unsigned> current_entry_indexes; | |
624 | |
625 RenderViewHost* render_view_host = | |
626 main_window_->web_contents()->GetRenderViewHost(); | |
627 | |
628 for (std::vector<Shell*>::iterator window = Shell::windows().begin(); | |
629 window != Shell::windows().end(); | |
630 ++window) { | |
631 WebContents* web_contents = (*window)->web_contents(); | |
632 // Only capture the history from windows in the same process as the main | |
633 // window. During layout tests, we only use two processes when an | |
634 // devtools window is open. | |
635 if (render_view_host->GetProcess() != | |
636 web_contents->GetRenderViewHost()->GetProcess()) { | |
637 continue; | |
638 } | |
639 routing_ids.push_back(web_contents->GetRenderViewHost()->GetRoutingID()); | |
640 current_entry_indexes.push_back( | |
641 web_contents->GetController().GetCurrentEntryIndex()); | |
642 std::vector<PageState> history; | |
643 for (int entry = 0; entry < web_contents->GetController().GetEntryCount(); | |
644 ++entry) { | |
645 PageState state = web_contents->GetController().GetEntryAtIndex(entry)-> | |
646 GetPageState(); | |
647 if (!state.IsValid()) { | |
648 state = PageState::CreateFromURL( | |
649 web_contents->GetController().GetEntryAtIndex(entry)->GetURL()); | |
650 } | |
651 history.push_back(state); | |
652 } | |
653 session_histories.push_back(history); | |
654 } | |
655 | |
656 Send(new ShellViewMsg_SessionHistory(render_view_host->GetRoutingID(), | |
657 routing_ids, | |
658 session_histories, | |
659 current_entry_indexes)); | |
660 } | |
661 | |
662 void WebKitTestController::OnCloseRemainingWindows() { | |
663 DevToolsAgentHost::DetachAllClients(); | |
664 std::vector<Shell*> open_windows(Shell::windows()); | |
665 Shell* devtools_shell = devtools_frontend_ ? | |
666 devtools_frontend_->frontend_shell() : NULL; | |
667 for (size_t i = 0; i < open_windows.size(); ++i) { | |
668 if (open_windows[i] != main_window_ && open_windows[i] != devtools_shell) | |
669 open_windows[i]->Close(); | |
670 } | |
671 base::MessageLoop::current()->RunUntilIdle(); | |
672 } | |
673 | |
674 void WebKitTestController::OnResetDone() { | |
675 if (is_leak_detection_enabled_) { | |
676 if (main_window_ && main_window_->web_contents()) { | |
677 RenderViewHost* render_view_host = | |
678 main_window_->web_contents()->GetRenderViewHost(); | |
679 render_view_host->Send( | |
680 new ShellViewMsg_TryLeakDetection(render_view_host->GetRoutingID())); | |
681 } | |
682 return; | |
683 } | |
684 | |
685 base::MessageLoop::current()->PostTask(FROM_HERE, | |
686 base::MessageLoop::QuitClosure()); | |
687 } | |
688 | |
689 void WebKitTestController::OnLeakDetectionDone( | |
690 const LeakDetectionResult& result) { | |
691 if (!result.leaked) { | |
692 base::MessageLoop::current()->PostTask(FROM_HERE, | |
693 base::MessageLoop::QuitClosure()); | |
694 return; | |
695 } | |
696 | |
697 printer_->AddErrorMessage( | |
698 base::StringPrintf("#LEAK - renderer pid %d (%s)", current_pid_, | |
699 result.detail.c_str())); | |
700 CHECK(!crash_when_leak_found_); | |
701 | |
702 DiscardMainWindow(); | |
703 } | |
704 | |
705 } // namespace content | |
OLD | NEW |