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"
9 #include "base/base64.h"
10 #include "base/command_line.h"
11 #include "base/location.h"
12 #include "base/run_loop.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/thread_task_runner_handle.h"
17 #include "content/public/browser/devtools_agent_host.h"
18 #include "content/public/browser/dom_storage_context.h"
19 #include "content/public/browser/gpu_data_manager.h"
20 #include "content/public/browser/navigation_controller.h"
21 #include "content/public/browser/navigation_entry.h"
22 #include "content/public/browser/notification_service.h"
23 #include "content/public/browser/notification_types.h"
24 #include "content/public/browser/render_process_host.h"
25 #include "content/public/browser/render_view_host.h"
26 #include "content/public/browser/render_widget_host_view.h"
27 #include "content/public/browser/storage_partition.h"
28 #include "content/public/browser/web_contents.h"
29 #include "content/public/common/content_switches.h"
30 #include "content/public/common/url_constants.h"
31 #include "content/shell/browser/layout_test/layout_test_devtools_frontend.h"
32 #include "content/shell/browser/shell.h"
33 #include "content/shell/browser/shell_browser_context.h"
34 #include "content/shell/browser/shell_content_browser_client.h"
35 #include "content/shell/browser/shell_devtools_frontend.h"
36 #include "content/shell/common/shell_messages.h"
37 #include "content/shell/common/shell_switches.h"
38 #include "content/shell/renderer/layout_test/blink_test_helpers.h"
39 #include "ui/gfx/codec/png_codec.h"
43 const int kTestSVGWindowWidthDip
= 480;
44 const int kTestSVGWindowHeightDip
= 360;
46 // BlinkTestResultPrinter ----------------------------------------------------
48 BlinkTestResultPrinter::BlinkTestResultPrinter(std::ostream
* output
,
50 : state_(DURING_TEST
),
51 capture_text_only_(false),
52 encode_binary_data_(false),
57 BlinkTestResultPrinter::~BlinkTestResultPrinter() {
60 void BlinkTestResultPrinter::PrintTextHeader() {
61 if (state_
!= DURING_TEST
)
63 if (!capture_text_only_
)
64 *output_
<< "Content-Type: text/plain\n";
65 state_
= IN_TEXT_BLOCK
;
68 void BlinkTestResultPrinter::PrintTextBlock(const std::string
& block
) {
69 if (state_
!= IN_TEXT_BLOCK
)
74 void BlinkTestResultPrinter::PrintTextFooter() {
75 if (state_
!= IN_TEXT_BLOCK
)
77 if (!capture_text_only_
) {
81 state_
= IN_IMAGE_BLOCK
;
84 void BlinkTestResultPrinter::PrintImageHeader(
85 const std::string
& actual_hash
,
86 const std::string
& expected_hash
) {
87 if (state_
!= IN_IMAGE_BLOCK
|| capture_text_only_
)
89 *output_
<< "\nActualHash: " << actual_hash
<< "\n";
90 if (!expected_hash
.empty())
91 *output_
<< "\nExpectedHash: " << expected_hash
<< "\n";
94 void BlinkTestResultPrinter::PrintImageBlock(
95 const std::vector
<unsigned char>& png_image
) {
96 if (state_
!= IN_IMAGE_BLOCK
|| capture_text_only_
)
98 *output_
<< "Content-Type: image/png\n";
99 if (encode_binary_data_
) {
100 PrintEncodedBinaryData(png_image
);
104 *output_
<< "Content-Length: " << png_image
.size() << "\n";
106 reinterpret_cast<const char*>(&png_image
[0]), png_image
.size());
109 void BlinkTestResultPrinter::PrintImageFooter() {
110 if (state_
!= IN_IMAGE_BLOCK
)
112 if (!capture_text_only_
) {
113 *output_
<< "#EOF\n";
119 void BlinkTestResultPrinter::PrintAudioHeader() {
120 DCHECK_EQ(state_
, DURING_TEST
);
121 if (!capture_text_only_
)
122 *output_
<< "Content-Type: audio/wav\n";
123 state_
= IN_AUDIO_BLOCK
;
126 void BlinkTestResultPrinter::PrintAudioBlock(
127 const std::vector
<unsigned char>& audio_data
) {
128 if (state_
!= IN_AUDIO_BLOCK
|| capture_text_only_
)
130 if (encode_binary_data_
) {
131 PrintEncodedBinaryData(audio_data
);
135 *output_
<< "Content-Length: " << audio_data
.size() << "\n";
137 reinterpret_cast<const char*>(&audio_data
[0]), audio_data
.size());
140 void BlinkTestResultPrinter::PrintAudioFooter() {
141 if (state_
!= IN_AUDIO_BLOCK
)
143 if (!capture_text_only_
) {
144 *output_
<< "#EOF\n";
147 state_
= IN_IMAGE_BLOCK
;
150 void BlinkTestResultPrinter::AddMessage(const std::string
& message
) {
151 AddMessageRaw(message
+ "\n");
154 void BlinkTestResultPrinter::AddMessageRaw(const std::string
& message
) {
155 if (state_
!= DURING_TEST
)
160 void BlinkTestResultPrinter::AddErrorMessage(const std::string
& message
) {
161 if (!capture_text_only_
)
162 *error_
<< message
<< "\n";
163 if (state_
!= DURING_TEST
)
166 *output_
<< message
<< "\n";
171 void BlinkTestResultPrinter::PrintEncodedBinaryData(
172 const std::vector
<unsigned char>& data
) {
173 *output_
<< "Content-Transfer-Encoding: base64\n";
175 std::string data_base64
;
177 base::StringPiece(reinterpret_cast<const char*>(&data
[0]), data
.size()),
180 *output_
<< "Content-Length: " << data_base64
.length() << "\n";
181 output_
->write(data_base64
.c_str(), data_base64
.length());
184 void BlinkTestResultPrinter::CloseStderr() {
185 if (state_
!= AFTER_TEST
)
187 if (!capture_text_only_
) {
193 // BlinkTestController -------------------------------------------------------
195 BlinkTestController
* BlinkTestController::instance_
= NULL
;
198 BlinkTestController
* BlinkTestController::Get() {
203 BlinkTestController::BlinkTestController()
204 : main_window_(NULL
),
205 test_phase_(BETWEEN_TESTS
),
206 is_leak_detection_enabled_(
207 base::CommandLine::ForCurrentProcess()->HasSwitch(
208 switches::kEnableLeakDetection
)),
209 crash_when_leak_found_(false),
210 devtools_frontend_(NULL
) {
214 if (is_leak_detection_enabled_
) {
215 std::string switchValue
=
216 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
217 switches::kEnableLeakDetection
);
218 crash_when_leak_found_
= switchValue
== switches::kCrashOnFailure
;
221 printer_
.reset(new BlinkTestResultPrinter(&std::cout
, &std::cerr
));
222 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
223 switches::kEncodeBinary
))
224 printer_
->set_encode_binary_data(true);
226 NOTIFICATION_RENDERER_PROCESS_CREATED
,
227 NotificationService::AllSources());
228 GpuDataManager::GetInstance()->AddObserver(this);
229 ResetAfterLayoutTest();
232 BlinkTestController::~BlinkTestController() {
233 DCHECK(CalledOnValidThread());
234 CHECK(instance_
== this);
235 CHECK(test_phase_
== BETWEEN_TESTS
);
236 GpuDataManager::GetInstance()->RemoveObserver(this);
241 bool BlinkTestController::PrepareForLayoutTest(
242 const GURL
& test_url
,
243 const base::FilePath
& current_working_directory
,
244 bool enable_pixel_dumping
,
245 const std::string
& expected_pixel_hash
) {
246 DCHECK(CalledOnValidThread());
247 test_phase_
= DURING_TEST
;
248 current_working_directory_
= current_working_directory
;
249 enable_pixel_dumping_
= enable_pixel_dumping
;
250 expected_pixel_hash_
= expected_pixel_hash
;
251 test_url_
= test_url
;
253 ShellBrowserContext
* browser_context
=
254 ShellContentBrowserClient::Get()->browser_context();
255 if (test_url
.spec().find("compositing/") != std::string::npos
)
256 is_compositing_test_
= true;
257 initial_size_
= Shell::GetShellDefaultSize();
258 // The W3C SVG layout tests use a different size than the other layout tests.
259 if (test_url
.spec().find("W3C-SVG-1.1") != std::string::npos
)
260 initial_size_
= gfx::Size(kTestSVGWindowWidthDip
, kTestSVGWindowHeightDip
);
262 main_window_
= content::Shell::CreateNewWindow(
267 WebContentsObserver::Observe(main_window_
->web_contents());
268 send_configuration_to_next_host_
= true;
269 current_pid_
= base::kNullProcessId
;
270 main_window_
->LoadURL(test_url
);
272 #if defined(OS_MACOSX)
273 // Shell::SizeTo is not implemented on all platforms.
274 main_window_
->SizeTo(initial_size_
);
276 main_window_
->web_contents()->GetRenderViewHost()->GetView()
277 ->SetSize(initial_size_
);
278 main_window_
->web_contents()->GetRenderViewHost()->WasResized();
279 RenderViewHost
* render_view_host
=
280 main_window_
->web_contents()->GetRenderViewHost();
281 WebPreferences prefs
= render_view_host
->GetWebkitPreferences();
282 OverrideWebkitPrefs(&prefs
);
283 render_view_host
->UpdateWebkitPreferences(prefs
);
284 SendTestConfiguration();
286 NavigationController::LoadURLParams
params(test_url
);
287 params
.transition_type
= ui::PageTransitionFromInt(
288 ui::PAGE_TRANSITION_TYPED
| ui::PAGE_TRANSITION_FROM_ADDRESS_BAR
);
289 params
.should_clear_history_list
= true;
290 main_window_
->web_contents()->GetController().LoadURLWithParams(params
);
291 main_window_
->web_contents()->Focus();
293 main_window_
->web_contents()->GetRenderViewHost()->SetActive(true);
294 main_window_
->web_contents()->GetRenderViewHost()->Focus();
298 bool BlinkTestController::ResetAfterLayoutTest() {
299 DCHECK(CalledOnValidThread());
300 printer_
->PrintTextFooter();
301 printer_
->PrintImageFooter();
302 printer_
->CloseStderr();
303 send_configuration_to_next_host_
= false;
304 test_phase_
= BETWEEN_TESTS
;
305 is_compositing_test_
= false;
306 enable_pixel_dumping_
= false;
307 expected_pixel_hash_
.clear();
309 prefs_
= WebPreferences();
310 should_override_prefs_
= false;
312 #if defined(OS_ANDROID)
313 // Re-using the shell's main window on Android causes issues with networking
314 // requests never succeeding. See http://crbug.com/277652.
320 void BlinkTestController::SetTempPath(const base::FilePath
& temp_path
) {
321 temp_path_
= temp_path
;
324 void BlinkTestController::RendererUnresponsive() {
325 DCHECK(CalledOnValidThread());
326 LOG(WARNING
) << "renderer unresponsive";
329 void BlinkTestController::OverrideWebkitPrefs(WebPreferences
* prefs
) {
330 if (should_override_prefs_
) {
333 ApplyLayoutTestDefaultPreferences(prefs
);
334 if (is_compositing_test_
) {
335 base::CommandLine
& command_line
= *base::CommandLine::ForCurrentProcess();
336 if (!command_line
.HasSwitch(switches::kDisableGpu
))
337 prefs
->accelerated_2d_canvas_enabled
= true;
338 prefs
->mock_scrollbars_enabled
= true;
343 void BlinkTestController::OpenURL(const GURL
& url
) {
344 if (test_phase_
!= DURING_TEST
)
347 Shell::CreateNewWindow(main_window_
->web_contents()->GetBrowserContext(),
349 main_window_
->web_contents()->GetSiteInstance(),
353 void BlinkTestController::TestFinishedInSecondaryWindow() {
354 RenderViewHost
* render_view_host
=
355 main_window_
->web_contents()->GetRenderViewHost();
356 render_view_host
->Send(
357 new ShellViewMsg_NotifyDone(render_view_host
->GetRoutingID()));
360 bool BlinkTestController::IsMainWindow(WebContents
* web_contents
) const {
361 return main_window_
&& web_contents
== main_window_
->web_contents();
364 bool BlinkTestController::OnMessageReceived(const IPC::Message
& message
) {
365 DCHECK(CalledOnValidThread());
367 IPC_BEGIN_MESSAGE_MAP(BlinkTestController
, message
)
368 IPC_MESSAGE_HANDLER(ShellViewHostMsg_PrintMessage
, OnPrintMessage
)
369 IPC_MESSAGE_HANDLER(ShellViewHostMsg_TextDump
, OnTextDump
)
370 IPC_MESSAGE_HANDLER(ShellViewHostMsg_ImageDump
, OnImageDump
)
371 IPC_MESSAGE_HANDLER(ShellViewHostMsg_AudioDump
, OnAudioDump
)
372 IPC_MESSAGE_HANDLER(ShellViewHostMsg_OverridePreferences
,
373 OnOverridePreferences
)
374 IPC_MESSAGE_HANDLER(ShellViewHostMsg_TestFinished
, OnTestFinished
)
375 IPC_MESSAGE_HANDLER(ShellViewHostMsg_ClearDevToolsLocalStorage
,
376 OnClearDevToolsLocalStorage
)
377 IPC_MESSAGE_HANDLER(ShellViewHostMsg_ShowDevTools
, OnShowDevTools
)
378 IPC_MESSAGE_HANDLER(ShellViewHostMsg_CloseDevTools
, OnCloseDevTools
)
379 IPC_MESSAGE_HANDLER(ShellViewHostMsg_GoToOffset
, OnGoToOffset
)
380 IPC_MESSAGE_HANDLER(ShellViewHostMsg_Reload
, OnReload
)
381 IPC_MESSAGE_HANDLER(ShellViewHostMsg_LoadURLForFrame
, OnLoadURLForFrame
)
382 IPC_MESSAGE_HANDLER(ShellViewHostMsg_CaptureSessionHistory
,
383 OnCaptureSessionHistory
)
384 IPC_MESSAGE_HANDLER(ShellViewHostMsg_CloseRemainingWindows
,
385 OnCloseRemainingWindows
)
386 IPC_MESSAGE_HANDLER(ShellViewHostMsg_ResetDone
, OnResetDone
)
387 IPC_MESSAGE_HANDLER(ShellViewHostMsg_LeakDetectionDone
, OnLeakDetectionDone
)
388 IPC_MESSAGE_UNHANDLED(handled
= false)
389 IPC_END_MESSAGE_MAP()
394 void BlinkTestController::PluginCrashed(const base::FilePath
& plugin_path
,
395 base::ProcessId plugin_pid
) {
396 DCHECK(CalledOnValidThread());
397 printer_
->AddErrorMessage(
398 base::StringPrintf("#CRASHED - plugin (pid %d)", plugin_pid
));
399 base::ThreadTaskRunnerHandle::Get()->PostTask(
401 base::Bind(base::IgnoreResult(&BlinkTestController::DiscardMainWindow
),
402 base::Unretained(this)));
405 void BlinkTestController::RenderViewCreated(RenderViewHost
* render_view_host
) {
406 DCHECK(CalledOnValidThread());
407 // Might be kNullProcessHandle, in which case we will receive a notification
408 // later when the RenderProcessHost was created.
409 if (render_view_host
->GetProcess()->GetHandle() != base::kNullProcessHandle
)
410 current_pid_
= base::GetProcId(render_view_host
->GetProcess()->GetHandle());
411 if (!send_configuration_to_next_host_
)
413 send_configuration_to_next_host_
= false;
414 SendTestConfiguration();
417 void BlinkTestController::RenderProcessGone(base::TerminationStatus status
) {
418 DCHECK(CalledOnValidThread());
419 if (current_pid_
!= base::kNullProcessId
) {
420 printer_
->AddErrorMessage(std::string("#CRASHED - renderer (pid ") +
421 base::IntToString(current_pid_
) + ")");
423 printer_
->AddErrorMessage("#CRASHED - renderer");
428 void BlinkTestController::DevToolsProcessCrashed() {
429 DCHECK(CalledOnValidThread());
430 printer_
->AddErrorMessage("#CRASHED - devtools");
431 if (devtools_frontend_
)
432 devtools_frontend_
->Close();
433 devtools_frontend_
= NULL
;
436 void BlinkTestController::WebContentsDestroyed() {
437 DCHECK(CalledOnValidThread());
438 printer_
->AddErrorMessage("FAIL: main window was destroyed");
442 void BlinkTestController::Observe(int type
,
443 const NotificationSource
& source
,
444 const NotificationDetails
& details
) {
445 DCHECK(CalledOnValidThread());
447 case NOTIFICATION_RENDERER_PROCESS_CREATED
: {
450 RenderViewHost
* render_view_host
=
451 main_window_
->web_contents()->GetRenderViewHost();
452 if (!render_view_host
)
454 RenderProcessHost
* render_process_host
=
455 Source
<RenderProcessHost
>(source
).ptr();
456 if (render_process_host
!= render_view_host
->GetProcess())
458 current_pid_
= base::GetProcId(render_process_host
->GetHandle());
466 void BlinkTestController::OnGpuProcessCrashed(
467 base::TerminationStatus exit_code
) {
468 DCHECK(CalledOnValidThread());
469 printer_
->AddErrorMessage("#CRASHED - gpu");
473 void BlinkTestController::DiscardMainWindow() {
474 // If we're running a test, we need to close all windows and exit the message
475 // loop. Otherwise, we're already outside of the message loop, and we just
476 // discard the main window.
477 WebContentsObserver::Observe(NULL
);
478 if (test_phase_
!= BETWEEN_TESTS
) {
479 Shell::CloseAllWindows();
480 base::ThreadTaskRunnerHandle::Get()->PostTask(
481 FROM_HERE
, base::MessageLoop::QuitClosure());
482 test_phase_
= CLEAN_UP
;
483 } else if (main_window_
) {
484 main_window_
->Close();
487 current_pid_
= base::kNullProcessId
;
490 void BlinkTestController::SendTestConfiguration() {
491 RenderViewHost
* render_view_host
=
492 main_window_
->web_contents()->GetRenderViewHost();
493 ShellTestConfiguration params
;
494 params
.current_working_directory
= current_working_directory_
;
495 params
.temp_path
= temp_path_
;
496 params
.test_url
= test_url_
;
497 params
.enable_pixel_dumping
= enable_pixel_dumping_
;
498 params
.allow_external_pages
=
499 base::CommandLine::ForCurrentProcess()->HasSwitch(
500 switches::kAllowExternalPages
);
501 params
.expected_pixel_hash
= expected_pixel_hash_
;
502 params
.initial_size
= initial_size_
;
503 render_view_host
->Send(new ShellViewMsg_SetTestConfiguration(
504 render_view_host
->GetRoutingID(), params
));
507 void BlinkTestController::OnTestFinished() {
508 test_phase_
= CLEAN_UP
;
509 if (!printer_
->output_finished())
510 printer_
->PrintImageFooter();
511 RenderViewHost
* render_view_host
=
512 main_window_
->web_contents()->GetRenderViewHost();
513 main_window_
->web_contents()->ExitFullscreen();
514 base::ThreadTaskRunnerHandle::Get()->PostTask(
516 base::Bind(base::IgnoreResult(&BlinkTestController::Send
),
517 base::Unretained(this),
518 new ShellViewMsg_Reset(render_view_host
->GetRoutingID())));
521 void BlinkTestController::OnImageDump(const std::string
& actual_pixel_hash
,
522 const SkBitmap
& image
) {
523 SkAutoLockPixels
image_lock(image
);
525 printer_
->PrintImageHeader(actual_pixel_hash
, expected_pixel_hash_
);
527 // Only encode and dump the png if the hashes don't match. Encoding the
528 // image is really expensive.
529 if (actual_pixel_hash
!= expected_pixel_hash_
) {
530 std::vector
<unsigned char> png
;
532 bool discard_transparency
= true;
533 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
534 switches::kEnableOverlayFullscreenVideo
))
535 discard_transparency
= false;
537 std::vector
<gfx::PNGCodec::Comment
> comments
;
538 comments
.push_back(gfx::PNGCodec::Comment("checksum", actual_pixel_hash
));
539 bool success
= gfx::PNGCodec::Encode(
540 static_cast<const unsigned char*>(image
.getPixels()),
541 gfx::PNGCodec::FORMAT_BGRA
,
542 gfx::Size(image
.width(), image
.height()),
543 static_cast<int>(image
.rowBytes()),
544 discard_transparency
,
548 printer_
->PrintImageBlock(png
);
550 printer_
->PrintImageFooter();
553 void BlinkTestController::OnAudioDump(const std::vector
<unsigned char>& dump
) {
554 printer_
->PrintAudioHeader();
555 printer_
->PrintAudioBlock(dump
);
556 printer_
->PrintAudioFooter();
559 void BlinkTestController::OnTextDump(const std::string
& dump
) {
560 printer_
->PrintTextHeader();
561 printer_
->PrintTextBlock(dump
);
562 printer_
->PrintTextFooter();
565 void BlinkTestController::OnPrintMessage(const std::string
& message
) {
566 printer_
->AddMessageRaw(message
);
569 void BlinkTestController::OnOverridePreferences(const WebPreferences
& prefs
) {
570 should_override_prefs_
= true;
574 void BlinkTestController::OnClearDevToolsLocalStorage() {
575 ShellBrowserContext
* browser_context
=
576 ShellContentBrowserClient::Get()->browser_context();
577 StoragePartition
* storage_partition
=
578 BrowserContext::GetStoragePartition(browser_context
, NULL
);
579 storage_partition
->GetDOMStorageContext()->DeleteLocalStorage(
580 content::LayoutTestDevToolsFrontend::GetDevToolsPathAsURL("", "")
584 void BlinkTestController::OnShowDevTools(const std::string
& settings
,
585 const std::string
& frontend_url
) {
586 if (!devtools_frontend_
) {
587 devtools_frontend_
= LayoutTestDevToolsFrontend::Show(
588 main_window_
->web_contents(), settings
, frontend_url
);
590 devtools_frontend_
->ReuseFrontend(settings
, frontend_url
);
592 devtools_frontend_
->Activate();
593 devtools_frontend_
->Focus();
596 void BlinkTestController::OnCloseDevTools() {
597 if (devtools_frontend_
)
598 devtools_frontend_
->DisconnectFromTarget();
601 void BlinkTestController::OnGoToOffset(int offset
) {
602 main_window_
->GoBackOrForward(offset
);
605 void BlinkTestController::OnReload() {
606 main_window_
->Reload();
609 void BlinkTestController::OnLoadURLForFrame(const GURL
& url
,
610 const std::string
& frame_name
) {
611 main_window_
->LoadURLForFrame(url
, frame_name
);
614 void BlinkTestController::OnCaptureSessionHistory() {
615 std::vector
<int> routing_ids
;
616 std::vector
<std::vector
<PageState
> > session_histories
;
617 std::vector
<unsigned> current_entry_indexes
;
619 RenderViewHost
* render_view_host
=
620 main_window_
->web_contents()->GetRenderViewHost();
622 for (std::vector
<Shell
*>::iterator window
= Shell::windows().begin();
623 window
!= Shell::windows().end();
625 WebContents
* web_contents
= (*window
)->web_contents();
626 // Only capture the history from windows in the same process as the main
627 // window. During layout tests, we only use two processes when an
628 // devtools window is open.
629 if (render_view_host
->GetProcess() !=
630 web_contents
->GetRenderViewHost()->GetProcess()) {
633 routing_ids
.push_back(web_contents
->GetRenderViewHost()->GetRoutingID());
634 current_entry_indexes
.push_back(
635 web_contents
->GetController().GetCurrentEntryIndex());
636 std::vector
<PageState
> history
;
637 for (int entry
= 0; entry
< web_contents
->GetController().GetEntryCount();
639 PageState state
= web_contents
->GetController().GetEntryAtIndex(entry
)->
641 if (!state
.IsValid()) {
642 state
= PageState::CreateFromURL(
643 web_contents
->GetController().GetEntryAtIndex(entry
)->GetURL());
645 history
.push_back(state
);
647 session_histories
.push_back(history
);
650 Send(new ShellViewMsg_SessionHistory(render_view_host
->GetRoutingID(),
653 current_entry_indexes
));
656 void BlinkTestController::OnCloseRemainingWindows() {
657 DevToolsAgentHost::DetachAllClients();
658 std::vector
<Shell
*> open_windows(Shell::windows());
659 Shell
* devtools_shell
= devtools_frontend_
?
660 devtools_frontend_
->frontend_shell() : NULL
;
661 for (size_t i
= 0; i
< open_windows
.size(); ++i
) {
662 if (open_windows
[i
] != main_window_
&& open_windows
[i
] != devtools_shell
)
663 open_windows
[i
]->Close();
665 base::MessageLoop::current()->RunUntilIdle();
668 void BlinkTestController::OnResetDone() {
669 if (is_leak_detection_enabled_
) {
670 if (main_window_
&& main_window_
->web_contents()) {
671 RenderViewHost
* render_view_host
=
672 main_window_
->web_contents()->GetRenderViewHost();
673 render_view_host
->Send(
674 new ShellViewMsg_TryLeakDetection(render_view_host
->GetRoutingID()));
679 base::ThreadTaskRunnerHandle::Get()->PostTask(
680 FROM_HERE
, base::MessageLoop::QuitClosure());
683 void BlinkTestController::OnLeakDetectionDone(
684 const LeakDetectionResult
& result
) {
685 if (!result
.leaked
) {
686 base::ThreadTaskRunnerHandle::Get()->PostTask(
687 FROM_HERE
, base::MessageLoop::QuitClosure());
691 printer_
->AddErrorMessage(
692 base::StringPrintf("#LEAK - renderer pid %d (%s)", current_pid_
,
693 result
.detail
.c_str()));
694 CHECK(!crash_when_leak_found_
);
699 } // namespace content