Replace IdleNotification calls with IdleNotificationDeadline
[chromium-blink-merge.git] / content / shell / browser / webkit_test_controller.cc
blob2eeead8bfcf5df9eadd6041c3127a2d67be2c09d
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.
5 #include "content/shell/browser/webkit_test_controller.h"
7 #include <iostream>
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"
39 namespace content {
41 const int kTestSVGWindowWidthDip = 480;
42 const int kTestSVGWindowHeightDip = 360;
44 // WebKitTestResultPrinter ----------------------------------------------------
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) {
55 WebKitTestResultPrinter::~WebKitTestResultPrinter() {
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;
66 void WebKitTestResultPrinter::PrintTextBlock(const std::string& block) {
67 if (state_ != IN_TEXT_BLOCK)
68 return;
69 *output_ << block;
72 void WebKitTestResultPrinter::PrintTextFooter() {
73 if (state_ != IN_TEXT_BLOCK)
74 return;
75 if (!capture_text_only_) {
76 *output_ << "#EOF\n";
77 output_->flush();
79 state_ = IN_IMAGE_BLOCK;
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";
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;
102 *output_ << "Content-Length: " << png_image.size() << "\n";
103 output_->write(
104 reinterpret_cast<const char*>(&png_image[0]), png_image.size());
107 void WebKitTestResultPrinter::PrintImageFooter() {
108 if (state_ != IN_IMAGE_BLOCK)
109 return;
110 if (!capture_text_only_) {
111 *output_ << "#EOF\n";
112 output_->flush();
114 state_ = AFTER_TEST;
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;
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;
133 *output_ << "Content-Length: " << audio_data.size() << "\n";
134 output_->write(
135 reinterpret_cast<const char*>(&audio_data[0]), audio_data.size());
138 void WebKitTestResultPrinter::PrintAudioFooter() {
139 if (state_ != IN_AUDIO_BLOCK)
140 return;
141 if (!capture_text_only_) {
142 *output_ << "#EOF\n";
143 output_->flush();
145 state_ = IN_IMAGE_BLOCK;
148 void WebKitTestResultPrinter::AddMessage(const std::string& message) {
149 AddMessageRaw(message + "\n");
152 void WebKitTestResultPrinter::AddMessageRaw(const std::string& message) {
153 if (state_ != DURING_TEST)
154 return;
155 *output_ << message;
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();
169 void WebKitTestResultPrinter::PrintEncodedBinaryData(
170 const std::vector<unsigned char>& data) {
171 *output_ << "Content-Transfer-Encoding: base64\n";
173 std::string data_base64;
174 base::Base64Encode(
175 base::StringPiece(reinterpret_cast<const char*>(&data[0]), data.size()),
176 &data_base64);
178 *output_ << "Content-Length: " << data_base64.length() << "\n";
179 output_->write(data_base64.c_str(), data_base64.length());
182 void WebKitTestResultPrinter::CloseStderr() {
183 if (state_ != AFTER_TEST)
184 return;
185 if (!capture_text_only_) {
186 *error_ << "#EOF\n";
187 error_->flush();
192 // WebKitTestController -------------------------------------------------------
194 WebKitTestController* WebKitTestController::instance_ = NULL;
196 // static
197 WebKitTestController* WebKitTestController::Get() {
198 DCHECK(instance_);
199 return instance_;
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;
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;
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();
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;
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();
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();
292 main_window_->web_contents()->GetRenderViewHost()->SetActive(true);
293 main_window_->web_contents()->GetRenderViewHost()->Focus();
294 return true;
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;
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;
319 void WebKitTestController::SetTempPath(const base::FilePath& temp_path) {
320 temp_path_ = temp_path;
323 void WebKitTestController::RendererUnresponsive() {
324 DCHECK(CalledOnValidThread());
325 LOG(WARNING) << "renderer unresponsive";
328 void WebKitTestController::WorkerCrashed() {
329 DCHECK(CalledOnValidThread());
330 printer_->AddErrorMessage("#CRASHED - worker");
331 DiscardMainWindow();
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;
348 void WebKitTestController::OpenURL(const GURL& url) {
349 if (test_phase_ != DURING_TEST)
350 return;
352 Shell::CreateNewWindow(main_window_->web_contents()->GetBrowserContext(),
353 url,
354 main_window_->web_contents()->GetSiteInstance(),
355 gfx::Size());
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()));
365 bool WebKitTestController::IsMainWindow(WebContents* web_contents) const {
366 return main_window_ && web_contents == main_window_->web_contents();
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()
396 return handled;
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)));
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();
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");
430 DiscardMainWindow();
433 void WebKitTestController::DevToolsProcessCrashed() {
434 DCHECK(CalledOnValidThread());
435 printer_->AddErrorMessage("#CRASHED - devtools");
436 if (devtools_frontend_)
437 devtools_frontend_->Close();
438 devtools_frontend_ = NULL;
441 void WebKitTestController::WebContentsDestroyed() {
442 DCHECK(CalledOnValidThread());
443 printer_->AddErrorMessage("FAIL: main window was destroyed");
444 DiscardMainWindow();
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;
466 default:
467 NOTREACHED();
471 void WebKitTestController::OnGpuProcessCrashed(
472 base::TerminationStatus exit_code) {
473 DCHECK(CalledOnValidThread());
474 printer_->AddErrorMessage("#CRASHED - gpu");
475 DiscardMainWindow();
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();
491 main_window_ = NULL;
492 current_pid_ = base::kNullProcessId;
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));
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())));
526 void WebKitTestController::OnImageDump(
527 const std::string& actual_pixel_hash,
528 const SkBitmap& image) {
529 SkAutoLockPixels image_lock(image);
531 printer_->PrintImageHeader(actual_pixel_hash, expected_pixel_hash_);
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;
538 bool discard_transparency = true;
539 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
540 switches::kEnableOverlayFullscreenVideo))
541 discard_transparency = false;
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);
556 printer_->PrintImageFooter();
559 void WebKitTestController::OnAudioDump(const std::vector<unsigned char>& dump) {
560 printer_->PrintAudioHeader();
561 printer_->PrintAudioBlock(dump);
562 printer_->PrintAudioFooter();
565 void WebKitTestController::OnTextDump(const std::string& dump) {
566 printer_->PrintTextHeader();
567 printer_->PrintTextBlock(dump);
568 printer_->PrintTextFooter();
571 void WebKitTestController::OnPrintMessage(const std::string& message) {
572 printer_->AddMessageRaw(message);
575 void WebKitTestController::OnOverridePreferences(const WebPreferences& prefs) {
576 should_override_prefs_ = true;
577 prefs_ = prefs;
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());
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);
598 devtools_frontend_->Activate();
599 devtools_frontend_->Focus();
602 void WebKitTestController::OnCloseDevTools() {
603 if (devtools_frontend_)
604 devtools_frontend_->DisconnectFromTarget();
607 void WebKitTestController::OnGoToOffset(int offset) {
608 main_window_->GoBackOrForward(offset);
611 void WebKitTestController::OnReload() {
612 main_window_->Reload();
615 void WebKitTestController::OnLoadURLForFrame(const GURL& url,
616 const std::string& frame_name) {
617 main_window_->LoadURLForFrame(url, frame_name);
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;
625 RenderViewHost* render_view_host =
626 main_window_->web_contents()->GetRenderViewHost();
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. This should not happen during history navigation
635 // tests.
636 if (render_view_host->GetProcess() !=
637 web_contents->GetRenderViewHost()->GetProcess()) {
638 NOTREACHED();
639 continue;
641 routing_ids.push_back(web_contents->GetRenderViewHost()->GetRoutingID());
642 current_entry_indexes.push_back(
643 web_contents->GetController().GetCurrentEntryIndex());
644 std::vector<PageState> history;
645 for (int entry = 0; entry < web_contents->GetController().GetEntryCount();
646 ++entry) {
647 PageState state = web_contents->GetController().GetEntryAtIndex(entry)->
648 GetPageState();
649 if (!state.IsValid()) {
650 state = PageState::CreateFromURL(
651 web_contents->GetController().GetEntryAtIndex(entry)->GetURL());
653 history.push_back(state);
655 session_histories.push_back(history);
658 Send(new ShellViewMsg_SessionHistory(render_view_host->GetRoutingID(),
659 routing_ids,
660 session_histories,
661 current_entry_indexes));
664 void WebKitTestController::OnCloseRemainingWindows() {
665 DevToolsAgentHost::DetachAllClients();
666 std::vector<Shell*> open_windows(Shell::windows());
667 Shell* devtools_shell = devtools_frontend_ ?
668 devtools_frontend_->frontend_shell() : NULL;
669 for (size_t i = 0; i < open_windows.size(); ++i) {
670 if (open_windows[i] != main_window_ && open_windows[i] != devtools_shell)
671 open_windows[i]->Close();
673 base::MessageLoop::current()->RunUntilIdle();
676 void WebKitTestController::OnResetDone() {
677 if (is_leak_detection_enabled_) {
678 if (main_window_ && main_window_->web_contents()) {
679 RenderViewHost* render_view_host =
680 main_window_->web_contents()->GetRenderViewHost();
681 render_view_host->Send(
682 new ShellViewMsg_TryLeakDetection(render_view_host->GetRoutingID()));
684 return;
687 base::MessageLoop::current()->PostTask(FROM_HERE,
688 base::MessageLoop::QuitClosure());
691 void WebKitTestController::OnLeakDetectionDone(
692 const LeakDetectionResult& result) {
693 if (!result.leaked) {
694 base::MessageLoop::current()->PostTask(FROM_HERE,
695 base::MessageLoop::QuitClosure());
696 return;
699 printer_->AddErrorMessage(
700 base::StringPrintf("#LEAK - renderer pid %d (%s)", current_pid_,
701 result.detail.c_str()));
702 CHECK(!crash_when_leak_found_);
704 DiscardMainWindow();
707 } // namespace content