Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / content / shell / browser / blink_test_controller.cc
blob459057919fc2b8bc1c0821f82044b076a591fc87
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/blink_test_controller.h"
7 #include <iostream>
9 #include "base/base64.h"
10 #include "base/callback.h"
11 #include "base/command_line.h"
12 #include "base/location.h"
13 #include "base/run_loop.h"
14 #include "base/single_thread_task_runner.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/stringprintf.h"
17 #include "base/thread_task_runner_handle.h"
18 #include "content/public/browser/devtools_agent_host.h"
19 #include "content/public/browser/dom_storage_context.h"
20 #include "content/public/browser/gpu_data_manager.h"
21 #include "content/public/browser/navigation_controller.h"
22 #include "content/public/browser/navigation_entry.h"
23 #include "content/public/browser/notification_service.h"
24 #include "content/public/browser/notification_types.h"
25 #include "content/public/browser/render_process_host.h"
26 #include "content/public/browser/render_view_host.h"
27 #include "content/public/browser/render_widget_host_view.h"
28 #include "content/public/browser/service_worker_context.h"
29 #include "content/public/browser/storage_partition.h"
30 #include "content/public/browser/web_contents.h"
31 #include "content/public/common/content_switches.h"
32 #include "content/public/common/url_constants.h"
33 #include "content/shell/browser/layout_test/layout_test_devtools_frontend.h"
34 #include "content/shell/browser/shell.h"
35 #include "content/shell/browser/shell_browser_context.h"
36 #include "content/shell/browser/shell_content_browser_client.h"
37 #include "content/shell/browser/shell_devtools_frontend.h"
38 #include "content/shell/common/shell_messages.h"
39 #include "content/shell/common/shell_switches.h"
40 #include "content/shell/renderer/layout_test/blink_test_helpers.h"
41 #include "ui/gfx/codec/png_codec.h"
43 namespace content {
45 const int kTestSVGWindowWidthDip = 480;
46 const int kTestSVGWindowHeightDip = 360;
48 // BlinkTestResultPrinter ----------------------------------------------------
50 BlinkTestResultPrinter::BlinkTestResultPrinter(std::ostream* output,
51 std::ostream* error)
52 : state_(DURING_TEST),
53 capture_text_only_(false),
54 encode_binary_data_(false),
55 output_(output),
56 error_(error) {
59 BlinkTestResultPrinter::~BlinkTestResultPrinter() {
62 void BlinkTestResultPrinter::PrintTextHeader() {
63 if (state_ != DURING_TEST)
64 return;
65 if (!capture_text_only_)
66 *output_ << "Content-Type: text/plain\n";
67 state_ = IN_TEXT_BLOCK;
70 void BlinkTestResultPrinter::PrintTextBlock(const std::string& block) {
71 if (state_ != IN_TEXT_BLOCK)
72 return;
73 *output_ << block;
76 void BlinkTestResultPrinter::PrintTextFooter() {
77 if (state_ != IN_TEXT_BLOCK)
78 return;
79 if (!capture_text_only_) {
80 *output_ << "#EOF\n";
81 output_->flush();
83 state_ = IN_IMAGE_BLOCK;
86 void BlinkTestResultPrinter::PrintImageHeader(
87 const std::string& actual_hash,
88 const std::string& expected_hash) {
89 if (state_ != IN_IMAGE_BLOCK || capture_text_only_)
90 return;
91 *output_ << "\nActualHash: " << actual_hash << "\n";
92 if (!expected_hash.empty())
93 *output_ << "\nExpectedHash: " << expected_hash << "\n";
96 void BlinkTestResultPrinter::PrintImageBlock(
97 const std::vector<unsigned char>& png_image) {
98 if (state_ != IN_IMAGE_BLOCK || capture_text_only_)
99 return;
100 *output_ << "Content-Type: image/png\n";
101 if (encode_binary_data_) {
102 PrintEncodedBinaryData(png_image);
103 return;
106 *output_ << "Content-Length: " << png_image.size() << "\n";
107 output_->write(
108 reinterpret_cast<const char*>(&png_image[0]), png_image.size());
111 void BlinkTestResultPrinter::PrintImageFooter() {
112 if (state_ != IN_IMAGE_BLOCK)
113 return;
114 if (!capture_text_only_) {
115 *output_ << "#EOF\n";
116 output_->flush();
118 state_ = AFTER_TEST;
121 void BlinkTestResultPrinter::PrintAudioHeader() {
122 DCHECK_EQ(state_, DURING_TEST);
123 if (!capture_text_only_)
124 *output_ << "Content-Type: audio/wav\n";
125 state_ = IN_AUDIO_BLOCK;
128 void BlinkTestResultPrinter::PrintAudioBlock(
129 const std::vector<unsigned char>& audio_data) {
130 if (state_ != IN_AUDIO_BLOCK || capture_text_only_)
131 return;
132 if (encode_binary_data_) {
133 PrintEncodedBinaryData(audio_data);
134 return;
137 *output_ << "Content-Length: " << audio_data.size() << "\n";
138 output_->write(
139 reinterpret_cast<const char*>(&audio_data[0]), audio_data.size());
142 void BlinkTestResultPrinter::PrintAudioFooter() {
143 if (state_ != IN_AUDIO_BLOCK)
144 return;
145 if (!capture_text_only_) {
146 *output_ << "#EOF\n";
147 output_->flush();
149 state_ = IN_IMAGE_BLOCK;
152 void BlinkTestResultPrinter::AddMessage(const std::string& message) {
153 AddMessageRaw(message + "\n");
156 void BlinkTestResultPrinter::AddMessageRaw(const std::string& message) {
157 if (state_ != DURING_TEST)
158 return;
159 *output_ << message;
162 void BlinkTestResultPrinter::AddErrorMessage(const std::string& message) {
163 if (!capture_text_only_)
164 *error_ << message << "\n";
165 if (state_ != DURING_TEST)
166 return;
167 PrintTextHeader();
168 *output_ << message << "\n";
169 PrintTextFooter();
170 PrintImageFooter();
173 void BlinkTestResultPrinter::PrintEncodedBinaryData(
174 const std::vector<unsigned char>& data) {
175 *output_ << "Content-Transfer-Encoding: base64\n";
177 std::string data_base64;
178 base::Base64Encode(
179 base::StringPiece(reinterpret_cast<const char*>(&data[0]), data.size()),
180 &data_base64);
182 *output_ << "Content-Length: " << data_base64.length() << "\n";
183 output_->write(data_base64.c_str(), data_base64.length());
186 void BlinkTestResultPrinter::CloseStderr() {
187 if (state_ != AFTER_TEST)
188 return;
189 if (!capture_text_only_) {
190 *error_ << "#EOF\n";
191 error_->flush();
195 // BlinkTestController -------------------------------------------------------
197 BlinkTestController* BlinkTestController::instance_ = NULL;
199 // static
200 BlinkTestController* BlinkTestController::Get() {
201 DCHECK(instance_);
202 return instance_;
205 BlinkTestController::BlinkTestController()
206 : main_window_(NULL),
207 test_phase_(BETWEEN_TESTS),
208 is_leak_detection_enabled_(
209 base::CommandLine::ForCurrentProcess()->HasSwitch(
210 switches::kEnableLeakDetection)),
211 crash_when_leak_found_(false),
212 devtools_frontend_(NULL) {
213 CHECK(!instance_);
214 instance_ = this;
216 if (is_leak_detection_enabled_) {
217 std::string switchValue =
218 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
219 switches::kEnableLeakDetection);
220 crash_when_leak_found_ = switchValue == switches::kCrashOnFailure;
223 printer_.reset(new BlinkTestResultPrinter(&std::cout, &std::cerr));
224 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
225 switches::kEncodeBinary))
226 printer_->set_encode_binary_data(true);
227 registrar_.Add(this,
228 NOTIFICATION_RENDERER_PROCESS_CREATED,
229 NotificationService::AllSources());
230 GpuDataManager::GetInstance()->AddObserver(this);
231 ResetAfterLayoutTest();
234 BlinkTestController::~BlinkTestController() {
235 DCHECK(CalledOnValidThread());
236 CHECK(instance_ == this);
237 CHECK(test_phase_ == BETWEEN_TESTS);
238 GpuDataManager::GetInstance()->RemoveObserver(this);
239 DiscardMainWindow();
240 instance_ = NULL;
243 bool BlinkTestController::PrepareForLayoutTest(
244 const GURL& test_url,
245 const base::FilePath& current_working_directory,
246 bool enable_pixel_dumping,
247 const std::string& expected_pixel_hash) {
248 DCHECK(CalledOnValidThread());
249 test_phase_ = DURING_TEST;
250 current_working_directory_ = current_working_directory;
251 enable_pixel_dumping_ = enable_pixel_dumping;
252 expected_pixel_hash_ = expected_pixel_hash;
253 test_url_ = test_url;
254 printer_->reset();
255 ShellBrowserContext* browser_context =
256 ShellContentBrowserClient::Get()->browser_context();
257 if (test_url.spec().find("compositing/") != std::string::npos)
258 is_compositing_test_ = true;
259 initial_size_ = Shell::GetShellDefaultSize();
260 // The W3C SVG layout tests use a different size than the other layout tests.
261 if (test_url.spec().find("W3C-SVG-1.1") != std::string::npos)
262 initial_size_ = gfx::Size(kTestSVGWindowWidthDip, kTestSVGWindowHeightDip);
263 if (!main_window_) {
264 main_window_ = content::Shell::CreateNewWindow(
265 browser_context,
266 GURL(),
267 NULL,
268 initial_size_);
269 WebContentsObserver::Observe(main_window_->web_contents());
270 send_configuration_to_next_host_ = true;
271 current_pid_ = base::kNullProcessId;
272 main_window_->LoadURL(test_url);
273 } else {
274 #if defined(OS_MACOSX)
275 // Shell::SizeTo is not implemented on all platforms.
276 main_window_->SizeTo(initial_size_);
277 #endif
278 main_window_->web_contents()->GetRenderViewHost()->GetView()
279 ->SetSize(initial_size_);
280 main_window_->web_contents()->GetRenderViewHost()->WasResized();
281 RenderViewHost* render_view_host =
282 main_window_->web_contents()->GetRenderViewHost();
283 WebPreferences prefs = render_view_host->GetWebkitPreferences();
284 OverrideWebkitPrefs(&prefs);
285 render_view_host->UpdateWebkitPreferences(prefs);
286 SendTestConfiguration();
288 NavigationController::LoadURLParams params(test_url);
289 params.transition_type = ui::PageTransitionFromInt(
290 ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
291 params.should_clear_history_list = true;
292 main_window_->web_contents()->GetController().LoadURLWithParams(params);
293 main_window_->web_contents()->Focus();
295 main_window_->web_contents()->GetRenderViewHost()->SetActive(true);
296 main_window_->web_contents()->GetRenderViewHost()->Focus();
297 return true;
300 bool BlinkTestController::ResetAfterLayoutTest() {
301 DCHECK(CalledOnValidThread());
302 printer_->PrintTextFooter();
303 printer_->PrintImageFooter();
304 printer_->CloseStderr();
305 send_configuration_to_next_host_ = false;
306 test_phase_ = BETWEEN_TESTS;
307 is_compositing_test_ = false;
308 enable_pixel_dumping_ = false;
309 expected_pixel_hash_.clear();
310 test_url_ = GURL();
311 prefs_ = WebPreferences();
312 should_override_prefs_ = false;
314 #if defined(OS_ANDROID)
315 // Re-using the shell's main window on Android causes issues with networking
316 // requests never succeeding. See http://crbug.com/277652.
317 DiscardMainWindow();
318 #endif
319 return true;
322 void BlinkTestController::SetTempPath(const base::FilePath& temp_path) {
323 temp_path_ = temp_path;
326 void BlinkTestController::RendererUnresponsive() {
327 DCHECK(CalledOnValidThread());
328 LOG(WARNING) << "renderer unresponsive";
331 void BlinkTestController::OverrideWebkitPrefs(WebPreferences* prefs) {
332 if (should_override_prefs_) {
333 *prefs = prefs_;
334 } else {
335 ApplyLayoutTestDefaultPreferences(prefs);
336 if (is_compositing_test_) {
337 base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess();
338 if (!command_line.HasSwitch(switches::kDisableGpu))
339 prefs->accelerated_2d_canvas_enabled = true;
340 prefs->mock_scrollbars_enabled = true;
345 void BlinkTestController::OpenURL(const GURL& url) {
346 if (test_phase_ != DURING_TEST)
347 return;
349 Shell::CreateNewWindow(main_window_->web_contents()->GetBrowserContext(),
350 url,
351 main_window_->web_contents()->GetSiteInstance(),
352 gfx::Size());
355 void BlinkTestController::TestFinishedInSecondaryWindow() {
356 RenderViewHost* render_view_host =
357 main_window_->web_contents()->GetRenderViewHost();
358 render_view_host->Send(
359 new ShellViewMsg_NotifyDone(render_view_host->GetRoutingID()));
362 bool BlinkTestController::IsMainWindow(WebContents* web_contents) const {
363 return main_window_ && web_contents == main_window_->web_contents();
366 bool BlinkTestController::OnMessageReceived(const IPC::Message& message) {
367 DCHECK(CalledOnValidThread());
368 bool handled = true;
369 IPC_BEGIN_MESSAGE_MAP(BlinkTestController, message)
370 IPC_MESSAGE_HANDLER(ShellViewHostMsg_PrintMessage, OnPrintMessage)
371 IPC_MESSAGE_HANDLER(ShellViewHostMsg_TextDump, OnTextDump)
372 IPC_MESSAGE_HANDLER(ShellViewHostMsg_ImageDump, OnImageDump)
373 IPC_MESSAGE_HANDLER(ShellViewHostMsg_AudioDump, OnAudioDump)
374 IPC_MESSAGE_HANDLER(ShellViewHostMsg_OverridePreferences,
375 OnOverridePreferences)
376 IPC_MESSAGE_HANDLER(ShellViewHostMsg_TestFinished, OnTestFinished)
377 IPC_MESSAGE_HANDLER(ShellViewHostMsg_ClearDevToolsLocalStorage,
378 OnClearDevToolsLocalStorage)
379 IPC_MESSAGE_HANDLER(ShellViewHostMsg_ShowDevTools, OnShowDevTools)
380 IPC_MESSAGE_HANDLER(ShellViewHostMsg_CloseDevTools, OnCloseDevTools)
381 IPC_MESSAGE_HANDLER(ShellViewHostMsg_GoToOffset, OnGoToOffset)
382 IPC_MESSAGE_HANDLER(ShellViewHostMsg_Reload, OnReload)
383 IPC_MESSAGE_HANDLER(ShellViewHostMsg_LoadURLForFrame, OnLoadURLForFrame)
384 IPC_MESSAGE_HANDLER(ShellViewHostMsg_CaptureSessionHistory,
385 OnCaptureSessionHistory)
386 IPC_MESSAGE_HANDLER(ShellViewHostMsg_CloseRemainingWindows,
387 OnCloseRemainingWindows)
388 IPC_MESSAGE_HANDLER(ShellViewHostMsg_ResetDone, OnResetDone)
389 IPC_MESSAGE_HANDLER(ShellViewHostMsg_LeakDetectionDone, OnLeakDetectionDone)
390 IPC_MESSAGE_UNHANDLED(handled = false)
391 IPC_END_MESSAGE_MAP()
393 return handled;
396 void BlinkTestController::PluginCrashed(const base::FilePath& plugin_path,
397 base::ProcessId plugin_pid) {
398 DCHECK(CalledOnValidThread());
399 printer_->AddErrorMessage(
400 base::StringPrintf("#CRASHED - plugin (pid %d)", plugin_pid));
401 base::ThreadTaskRunnerHandle::Get()->PostTask(
402 FROM_HERE,
403 base::Bind(base::IgnoreResult(&BlinkTestController::DiscardMainWindow),
404 base::Unretained(this)));
407 void BlinkTestController::RenderViewCreated(RenderViewHost* render_view_host) {
408 DCHECK(CalledOnValidThread());
409 // Might be kNullProcessHandle, in which case we will receive a notification
410 // later when the RenderProcessHost was created.
411 if (render_view_host->GetProcess()->GetHandle() != base::kNullProcessHandle)
412 current_pid_ = base::GetProcId(render_view_host->GetProcess()->GetHandle());
413 if (!send_configuration_to_next_host_)
414 return;
415 send_configuration_to_next_host_ = false;
416 SendTestConfiguration();
419 void BlinkTestController::RenderProcessGone(base::TerminationStatus status) {
420 DCHECK(CalledOnValidThread());
421 if (current_pid_ != base::kNullProcessId) {
422 printer_->AddErrorMessage(std::string("#CRASHED - renderer (pid ") +
423 base::IntToString(current_pid_) + ")");
424 } else {
425 printer_->AddErrorMessage("#CRASHED - renderer");
427 DiscardMainWindow();
430 void BlinkTestController::DevToolsProcessCrashed() {
431 DCHECK(CalledOnValidThread());
432 printer_->AddErrorMessage("#CRASHED - devtools");
433 if (devtools_frontend_)
434 devtools_frontend_->Close();
435 devtools_frontend_ = NULL;
438 void BlinkTestController::WebContentsDestroyed() {
439 DCHECK(CalledOnValidThread());
440 printer_->AddErrorMessage("FAIL: main window was destroyed");
441 DiscardMainWindow();
444 void BlinkTestController::Observe(int type,
445 const NotificationSource& source,
446 const NotificationDetails& details) {
447 DCHECK(CalledOnValidThread());
448 switch (type) {
449 case NOTIFICATION_RENDERER_PROCESS_CREATED: {
450 if (!main_window_)
451 return;
452 RenderViewHost* render_view_host =
453 main_window_->web_contents()->GetRenderViewHost();
454 if (!render_view_host)
455 return;
456 RenderProcessHost* render_process_host =
457 Source<RenderProcessHost>(source).ptr();
458 if (render_process_host != render_view_host->GetProcess())
459 return;
460 current_pid_ = base::GetProcId(render_process_host->GetHandle());
461 break;
463 default:
464 NOTREACHED();
468 void BlinkTestController::OnGpuProcessCrashed(
469 base::TerminationStatus exit_code) {
470 DCHECK(CalledOnValidThread());
471 printer_->AddErrorMessage("#CRASHED - gpu");
472 DiscardMainWindow();
475 void BlinkTestController::DiscardMainWindow() {
476 // If we're running a test, we need to close all windows and exit the message
477 // loop. Otherwise, we're already outside of the message loop, and we just
478 // discard the main window.
479 WebContentsObserver::Observe(NULL);
480 if (test_phase_ != BETWEEN_TESTS) {
481 Shell::CloseAllWindows();
482 base::ThreadTaskRunnerHandle::Get()->PostTask(
483 FROM_HERE, base::MessageLoop::QuitClosure());
484 test_phase_ = CLEAN_UP;
485 } else if (main_window_) {
486 main_window_->Close();
488 main_window_ = NULL;
489 current_pid_ = base::kNullProcessId;
492 void BlinkTestController::SendTestConfiguration() {
493 RenderViewHost* render_view_host =
494 main_window_->web_contents()->GetRenderViewHost();
495 ShellTestConfiguration params;
496 params.current_working_directory = current_working_directory_;
497 params.temp_path = temp_path_;
498 params.test_url = test_url_;
499 params.enable_pixel_dumping = enable_pixel_dumping_;
500 params.allow_external_pages =
501 base::CommandLine::ForCurrentProcess()->HasSwitch(
502 switches::kAllowExternalPages);
503 params.expected_pixel_hash = expected_pixel_hash_;
504 params.initial_size = initial_size_;
505 render_view_host->Send(new ShellViewMsg_SetTestConfiguration(
506 render_view_host->GetRoutingID(), params));
509 void BlinkTestController::OnTestFinished() {
510 test_phase_ = CLEAN_UP;
511 if (!printer_->output_finished())
512 printer_->PrintImageFooter();
513 RenderViewHost* render_view_host =
514 main_window_->web_contents()->GetRenderViewHost();
515 main_window_->web_contents()->ExitFullscreen();
517 ShellBrowserContext* browser_context =
518 ShellContentBrowserClient::Get()->browser_context();
519 StoragePartition* storage_partition =
520 BrowserContext::GetStoragePartition(browser_context, nullptr);
521 storage_partition->GetServiceWorkerContext()->ClearAllServiceWorkersForTest(
522 base::Bind(base::IgnoreResult(&BlinkTestController::Send),
523 base::Unretained(this),
524 new ShellViewMsg_Reset(render_view_host->GetRoutingID())));
527 void BlinkTestController::OnImageDump(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::kForceOverlayFullscreenVideo))
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 BlinkTestController::OnAudioDump(const std::vector<unsigned char>& dump) {
560 printer_->PrintAudioHeader();
561 printer_->PrintAudioBlock(dump);
562 printer_->PrintAudioFooter();
565 void BlinkTestController::OnTextDump(const std::string& dump) {
566 printer_->PrintTextHeader();
567 printer_->PrintTextBlock(dump);
568 printer_->PrintTextFooter();
571 void BlinkTestController::OnPrintMessage(const std::string& message) {
572 printer_->AddMessageRaw(message);
575 void BlinkTestController::OnOverridePreferences(const WebPreferences& prefs) {
576 should_override_prefs_ = true;
577 prefs_ = prefs;
580 void BlinkTestController::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 BlinkTestController::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 BlinkTestController::OnCloseDevTools() {
603 if (devtools_frontend_)
604 devtools_frontend_->DisconnectFromTarget();
607 void BlinkTestController::OnGoToOffset(int offset) {
608 main_window_->GoBackOrForward(offset);
611 void BlinkTestController::OnReload() {
612 main_window_->Reload();
615 void BlinkTestController::OnLoadURLForFrame(const GURL& url,
616 const std::string& frame_name) {
617 main_window_->LoadURLForFrame(url, frame_name);
620 void BlinkTestController::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.
635 if (render_view_host->GetProcess() !=
636 web_contents->GetRenderViewHost()->GetProcess()) {
637 continue;
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());
651 history.push_back(state);
653 session_histories.push_back(history);
656 Send(new ShellViewMsg_SessionHistory(render_view_host->GetRoutingID(),
657 routing_ids,
658 session_histories,
659 current_entry_indexes));
662 void BlinkTestController::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();
671 base::MessageLoop::current()->RunUntilIdle();
674 void BlinkTestController::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()));
682 return;
685 base::ThreadTaskRunnerHandle::Get()->PostTask(
686 FROM_HERE, base::MessageLoop::QuitClosure());
689 void BlinkTestController::OnLeakDetectionDone(
690 const LeakDetectionResult& result) {
691 if (!result.leaked) {
692 base::ThreadTaskRunnerHandle::Get()->PostTask(
693 FROM_HERE, base::MessageLoop::QuitClosure());
694 return;
697 printer_->AddErrorMessage(
698 base::StringPrintf("#LEAK - renderer pid %d (%s)", current_pid_,
699 result.detail.c_str()));
700 CHECK(!crash_when_leak_found_);
702 DiscardMainWindow();
705 } // namespace content