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/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_bluetooth_chooser_factory.h"
34 #include "content/shell/browser/layout_test/layout_test_devtools_frontend.h"
35 #include "content/shell/browser/shell.h"
36 #include "content/shell/browser/shell_browser_context.h"
37 #include "content/shell/browser/shell_content_browser_client.h"
38 #include "content/shell/browser/shell_devtools_frontend.h"
39 #include "content/shell/common/shell_messages.h"
40 #include "content/shell/common/shell_switches.h"
41 #include "content/shell/renderer/layout_test/blink_test_helpers.h"
42 #include "ui/gfx/codec/png_codec.h"
46 const int kTestSVGWindowWidthDip
= 480;
47 const int kTestSVGWindowHeightDip
= 360;
49 // BlinkTestResultPrinter ----------------------------------------------------
51 BlinkTestResultPrinter::BlinkTestResultPrinter(std::ostream
* output
,
53 : state_(DURING_TEST
),
54 capture_text_only_(false),
55 encode_binary_data_(false),
60 BlinkTestResultPrinter::~BlinkTestResultPrinter() {
63 void BlinkTestResultPrinter::PrintTextHeader() {
64 if (state_
!= DURING_TEST
)
66 if (!capture_text_only_
)
67 *output_
<< "Content-Type: text/plain\n";
68 state_
= IN_TEXT_BLOCK
;
71 void BlinkTestResultPrinter::PrintTextBlock(const std::string
& block
) {
72 if (state_
!= IN_TEXT_BLOCK
)
77 void BlinkTestResultPrinter::PrintTextFooter() {
78 if (state_
!= IN_TEXT_BLOCK
)
80 if (!capture_text_only_
) {
84 state_
= IN_IMAGE_BLOCK
;
87 void BlinkTestResultPrinter::PrintImageHeader(
88 const std::string
& actual_hash
,
89 const std::string
& expected_hash
) {
90 if (state_
!= IN_IMAGE_BLOCK
|| capture_text_only_
)
92 *output_
<< "\nActualHash: " << actual_hash
<< "\n";
93 if (!expected_hash
.empty())
94 *output_
<< "\nExpectedHash: " << expected_hash
<< "\n";
97 void BlinkTestResultPrinter::PrintImageBlock(
98 const std::vector
<unsigned char>& png_image
) {
99 if (state_
!= IN_IMAGE_BLOCK
|| capture_text_only_
)
101 *output_
<< "Content-Type: image/png\n";
102 if (encode_binary_data_
) {
103 PrintEncodedBinaryData(png_image
);
107 *output_
<< "Content-Length: " << png_image
.size() << "\n";
109 reinterpret_cast<const char*>(&png_image
[0]), png_image
.size());
112 void BlinkTestResultPrinter::PrintImageFooter() {
113 if (state_
!= IN_IMAGE_BLOCK
)
115 if (!capture_text_only_
) {
116 *output_
<< "#EOF\n";
122 void BlinkTestResultPrinter::PrintAudioHeader() {
123 DCHECK_EQ(state_
, DURING_TEST
);
124 if (!capture_text_only_
)
125 *output_
<< "Content-Type: audio/wav\n";
126 state_
= IN_AUDIO_BLOCK
;
129 void BlinkTestResultPrinter::PrintAudioBlock(
130 const std::vector
<unsigned char>& audio_data
) {
131 if (state_
!= IN_AUDIO_BLOCK
|| capture_text_only_
)
133 if (encode_binary_data_
) {
134 PrintEncodedBinaryData(audio_data
);
138 *output_
<< "Content-Length: " << audio_data
.size() << "\n";
140 reinterpret_cast<const char*>(&audio_data
[0]), audio_data
.size());
143 void BlinkTestResultPrinter::PrintAudioFooter() {
144 if (state_
!= IN_AUDIO_BLOCK
)
146 if (!capture_text_only_
) {
147 *output_
<< "#EOF\n";
150 state_
= IN_IMAGE_BLOCK
;
153 void BlinkTestResultPrinter::AddMessage(const std::string
& message
) {
154 AddMessageRaw(message
+ "\n");
157 void BlinkTestResultPrinter::AddMessageRaw(const std::string
& message
) {
158 if (state_
!= DURING_TEST
)
163 void BlinkTestResultPrinter::AddErrorMessage(const std::string
& message
) {
164 if (!capture_text_only_
)
165 *error_
<< message
<< "\n";
166 if (state_
!= DURING_TEST
)
169 *output_
<< message
<< "\n";
174 void BlinkTestResultPrinter::PrintEncodedBinaryData(
175 const std::vector
<unsigned char>& data
) {
176 *output_
<< "Content-Transfer-Encoding: base64\n";
178 std::string data_base64
;
180 base::StringPiece(reinterpret_cast<const char*>(&data
[0]), data
.size()),
183 *output_
<< "Content-Length: " << data_base64
.length() << "\n";
184 output_
->write(data_base64
.c_str(), data_base64
.length());
187 void BlinkTestResultPrinter::CloseStderr() {
188 if (state_
!= AFTER_TEST
)
190 if (!capture_text_only_
) {
196 // BlinkTestController -------------------------------------------------------
198 BlinkTestController
* BlinkTestController::instance_
= NULL
;
201 BlinkTestController
* BlinkTestController::Get() {
206 BlinkTestController::BlinkTestController()
207 : main_window_(NULL
),
208 test_phase_(BETWEEN_TESTS
),
209 is_leak_detection_enabled_(
210 base::CommandLine::ForCurrentProcess()->HasSwitch(
211 switches::kEnableLeakDetection
)),
212 crash_when_leak_found_(false),
213 devtools_frontend_(NULL
) {
217 if (is_leak_detection_enabled_
) {
218 std::string switchValue
=
219 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
220 switches::kEnableLeakDetection
);
221 crash_when_leak_found_
= switchValue
== switches::kCrashOnFailure
;
224 printer_
.reset(new BlinkTestResultPrinter(&std::cout
, &std::cerr
));
225 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
226 switches::kEncodeBinary
))
227 printer_
->set_encode_binary_data(true);
229 NOTIFICATION_RENDERER_PROCESS_CREATED
,
230 NotificationService::AllSources());
231 GpuDataManager::GetInstance()->AddObserver(this);
232 ResetAfterLayoutTest();
235 BlinkTestController::~BlinkTestController() {
236 DCHECK(CalledOnValidThread());
237 CHECK(instance_
== this);
238 CHECK(test_phase_
== BETWEEN_TESTS
);
239 GpuDataManager::GetInstance()->RemoveObserver(this);
244 bool BlinkTestController::PrepareForLayoutTest(
245 const GURL
& test_url
,
246 const base::FilePath
& current_working_directory
,
247 bool enable_pixel_dumping
,
248 const std::string
& expected_pixel_hash
) {
249 DCHECK(CalledOnValidThread());
250 test_phase_
= DURING_TEST
;
251 current_working_directory_
= current_working_directory
;
252 enable_pixel_dumping_
= enable_pixel_dumping
;
253 expected_pixel_hash_
= expected_pixel_hash
;
254 test_url_
= test_url
;
256 ShellBrowserContext
* browser_context
=
257 ShellContentBrowserClient::Get()->browser_context();
258 if (test_url
.spec().find("compositing/") != std::string::npos
)
259 is_compositing_test_
= true;
260 initial_size_
= Shell::GetShellDefaultSize();
261 // The W3C SVG layout tests use a different size than the other layout tests.
262 if (test_url
.spec().find("W3C-SVG-1.1") != std::string::npos
)
263 initial_size_
= gfx::Size(kTestSVGWindowWidthDip
, kTestSVGWindowHeightDip
);
265 main_window_
= content::Shell::CreateNewWindow(
270 WebContentsObserver::Observe(main_window_
->web_contents());
271 send_configuration_to_next_host_
= true;
272 current_pid_
= base::kNullProcessId
;
273 main_window_
->LoadURL(test_url
);
275 #if defined(OS_MACOSX)
276 // Shell::SizeTo is not implemented on all platforms.
277 main_window_
->SizeTo(initial_size_
);
279 main_window_
->web_contents()->GetRenderViewHost()->GetView()
280 ->SetSize(initial_size_
);
281 main_window_
->web_contents()->GetRenderViewHost()->WasResized();
282 RenderViewHost
* render_view_host
=
283 main_window_
->web_contents()->GetRenderViewHost();
284 WebPreferences prefs
= render_view_host
->GetWebkitPreferences();
285 OverrideWebkitPrefs(&prefs
);
286 render_view_host
->UpdateWebkitPreferences(prefs
);
287 SendTestConfiguration();
289 NavigationController::LoadURLParams
params(test_url
);
290 params
.transition_type
= ui::PageTransitionFromInt(
291 ui::PAGE_TRANSITION_TYPED
| ui::PAGE_TRANSITION_FROM_ADDRESS_BAR
);
292 params
.should_clear_history_list
= true;
293 main_window_
->web_contents()->GetController().LoadURLWithParams(params
);
294 main_window_
->web_contents()->Focus();
296 main_window_
->web_contents()->GetRenderViewHost()->SetActive(true);
297 main_window_
->web_contents()->GetRenderViewHost()->Focus();
301 bool BlinkTestController::ResetAfterLayoutTest() {
302 DCHECK(CalledOnValidThread());
303 printer_
->PrintTextFooter();
304 printer_
->PrintImageFooter();
305 printer_
->CloseStderr();
306 send_configuration_to_next_host_
= false;
307 test_phase_
= BETWEEN_TESTS
;
308 is_compositing_test_
= false;
309 enable_pixel_dumping_
= false;
310 expected_pixel_hash_
.clear();
312 prefs_
= WebPreferences();
313 should_override_prefs_
= false;
315 #if defined(OS_ANDROID)
316 // Re-using the shell's main window on Android causes issues with networking
317 // requests never succeeding. See http://crbug.com/277652.
323 void BlinkTestController::SetTempPath(const base::FilePath
& temp_path
) {
324 temp_path_
= temp_path
;
327 void BlinkTestController::RendererUnresponsive() {
328 DCHECK(CalledOnValidThread());
329 LOG(WARNING
) << "renderer unresponsive";
332 void BlinkTestController::OverrideWebkitPrefs(WebPreferences
* prefs
) {
333 if (should_override_prefs_
) {
336 ApplyLayoutTestDefaultPreferences(prefs
);
337 if (is_compositing_test_
) {
338 base::CommandLine
& command_line
= *base::CommandLine::ForCurrentProcess();
339 if (!command_line
.HasSwitch(switches::kDisableGpu
))
340 prefs
->accelerated_2d_canvas_enabled
= true;
341 prefs
->mock_scrollbars_enabled
= true;
346 void BlinkTestController::OpenURL(const GURL
& url
) {
347 if (test_phase_
!= DURING_TEST
)
350 Shell::CreateNewWindow(main_window_
->web_contents()->GetBrowserContext(),
352 main_window_
->web_contents()->GetSiteInstance(),
356 void BlinkTestController::TestFinishedInSecondaryWindow() {
357 RenderViewHost
* render_view_host
=
358 main_window_
->web_contents()->GetRenderViewHost();
359 render_view_host
->Send(
360 new ShellViewMsg_NotifyDone(render_view_host
->GetRoutingID()));
363 bool BlinkTestController::IsMainWindow(WebContents
* web_contents
) const {
364 return main_window_
&& web_contents
== main_window_
->web_contents();
367 scoped_ptr
<BluetoothChooser
> BlinkTestController::RunBluetoothChooser(
368 WebContents
* web_contents
,
369 const BluetoothChooser::EventHandler
& event_handler
,
370 const GURL
& origin
) {
371 if (bluetooth_chooser_factory_
) {
372 return bluetooth_chooser_factory_
->RunBluetoothChooser(
373 web_contents
, event_handler
, origin
);
378 bool BlinkTestController::OnMessageReceived(const IPC::Message
& message
) {
379 DCHECK(CalledOnValidThread());
381 IPC_BEGIN_MESSAGE_MAP(BlinkTestController
, message
)
382 IPC_MESSAGE_HANDLER(ShellViewHostMsg_PrintMessage
, OnPrintMessage
)
383 IPC_MESSAGE_HANDLER(ShellViewHostMsg_TextDump
, OnTextDump
)
384 IPC_MESSAGE_HANDLER(ShellViewHostMsg_ImageDump
, OnImageDump
)
385 IPC_MESSAGE_HANDLER(ShellViewHostMsg_AudioDump
, OnAudioDump
)
386 IPC_MESSAGE_HANDLER(ShellViewHostMsg_OverridePreferences
,
387 OnOverridePreferences
)
388 IPC_MESSAGE_HANDLER(ShellViewHostMsg_TestFinished
, OnTestFinished
)
389 IPC_MESSAGE_HANDLER(ShellViewHostMsg_ClearDevToolsLocalStorage
,
390 OnClearDevToolsLocalStorage
)
391 IPC_MESSAGE_HANDLER(ShellViewHostMsg_ShowDevTools
, OnShowDevTools
)
392 IPC_MESSAGE_HANDLER(ShellViewHostMsg_CloseDevTools
, OnCloseDevTools
)
393 IPC_MESSAGE_HANDLER(ShellViewHostMsg_GoToOffset
, OnGoToOffset
)
394 IPC_MESSAGE_HANDLER(ShellViewHostMsg_Reload
, OnReload
)
395 IPC_MESSAGE_HANDLER(ShellViewHostMsg_LoadURLForFrame
, OnLoadURLForFrame
)
396 IPC_MESSAGE_HANDLER(ShellViewHostMsg_CaptureSessionHistory
,
397 OnCaptureSessionHistory
)
398 IPC_MESSAGE_HANDLER(ShellViewHostMsg_CloseRemainingWindows
,
399 OnCloseRemainingWindows
)
400 IPC_MESSAGE_HANDLER(ShellViewHostMsg_ResetDone
, OnResetDone
)
401 IPC_MESSAGE_HANDLER(ShellViewHostMsg_LeakDetectionDone
, OnLeakDetectionDone
)
402 IPC_MESSAGE_HANDLER(ShellViewHostMsg_SetBluetoothManualChooser
,
403 OnSetBluetoothManualChooser
)
404 IPC_MESSAGE_HANDLER(ShellViewHostMsg_GetBluetoothManualChooserEvents
,
405 OnGetBluetoothManualChooserEvents
)
406 IPC_MESSAGE_HANDLER(ShellViewHostMsg_SendBluetoothManualChooserEvent
,
407 OnSendBluetoothManualChooserEvent
)
408 IPC_MESSAGE_UNHANDLED(handled
= false)
409 IPC_END_MESSAGE_MAP()
414 void BlinkTestController::PluginCrashed(const base::FilePath
& plugin_path
,
415 base::ProcessId plugin_pid
) {
416 DCHECK(CalledOnValidThread());
417 printer_
->AddErrorMessage(
418 base::StringPrintf("#CRASHED - plugin (pid %d)", plugin_pid
));
419 base::ThreadTaskRunnerHandle::Get()->PostTask(
421 base::Bind(base::IgnoreResult(&BlinkTestController::DiscardMainWindow
),
422 base::Unretained(this)));
425 void BlinkTestController::RenderViewCreated(RenderViewHost
* render_view_host
) {
426 DCHECK(CalledOnValidThread());
427 // Might be kNullProcessHandle, in which case we will receive a notification
428 // later when the RenderProcessHost was created.
429 if (render_view_host
->GetProcess()->GetHandle() != base::kNullProcessHandle
)
430 current_pid_
= base::GetProcId(render_view_host
->GetProcess()->GetHandle());
431 if (!send_configuration_to_next_host_
)
433 send_configuration_to_next_host_
= false;
434 SendTestConfiguration();
437 void BlinkTestController::RenderProcessGone(base::TerminationStatus status
) {
438 DCHECK(CalledOnValidThread());
439 if (current_pid_
!= base::kNullProcessId
) {
440 printer_
->AddErrorMessage(std::string("#CRASHED - renderer (pid ") +
441 base::IntToString(current_pid_
) + ")");
443 printer_
->AddErrorMessage("#CRASHED - renderer");
448 void BlinkTestController::DevToolsProcessCrashed() {
449 DCHECK(CalledOnValidThread());
450 printer_
->AddErrorMessage("#CRASHED - devtools");
451 if (devtools_frontend_
)
452 devtools_frontend_
->Close();
453 devtools_frontend_
= NULL
;
456 void BlinkTestController::WebContentsDestroyed() {
457 DCHECK(CalledOnValidThread());
458 printer_
->AddErrorMessage("FAIL: main window was destroyed");
462 void BlinkTestController::Observe(int type
,
463 const NotificationSource
& source
,
464 const NotificationDetails
& details
) {
465 DCHECK(CalledOnValidThread());
467 case NOTIFICATION_RENDERER_PROCESS_CREATED
: {
470 RenderViewHost
* render_view_host
=
471 main_window_
->web_contents()->GetRenderViewHost();
472 if (!render_view_host
)
474 RenderProcessHost
* render_process_host
=
475 Source
<RenderProcessHost
>(source
).ptr();
476 if (render_process_host
!= render_view_host
->GetProcess())
478 current_pid_
= base::GetProcId(render_process_host
->GetHandle());
486 void BlinkTestController::OnGpuProcessCrashed(
487 base::TerminationStatus exit_code
) {
488 DCHECK(CalledOnValidThread());
489 printer_
->AddErrorMessage("#CRASHED - gpu");
493 void BlinkTestController::DiscardMainWindow() {
494 // If we're running a test, we need to close all windows and exit the message
495 // loop. Otherwise, we're already outside of the message loop, and we just
496 // discard the main window.
497 WebContentsObserver::Observe(NULL
);
498 if (test_phase_
!= BETWEEN_TESTS
) {
499 Shell::CloseAllWindows();
500 base::ThreadTaskRunnerHandle::Get()->PostTask(
501 FROM_HERE
, base::MessageLoop::QuitClosure());
502 test_phase_
= CLEAN_UP
;
503 } else if (main_window_
) {
504 main_window_
->Close();
507 current_pid_
= base::kNullProcessId
;
510 void BlinkTestController::SendTestConfiguration() {
511 RenderViewHost
* render_view_host
=
512 main_window_
->web_contents()->GetRenderViewHost();
513 ShellTestConfiguration params
;
514 params
.current_working_directory
= current_working_directory_
;
515 params
.temp_path
= temp_path_
;
516 params
.test_url
= test_url_
;
517 params
.enable_pixel_dumping
= enable_pixel_dumping_
;
518 params
.allow_external_pages
=
519 base::CommandLine::ForCurrentProcess()->HasSwitch(
520 switches::kAllowExternalPages
);
521 params
.expected_pixel_hash
= expected_pixel_hash_
;
522 params
.initial_size
= initial_size_
;
523 render_view_host
->Send(new ShellViewMsg_SetTestConfiguration(
524 render_view_host
->GetRoutingID(), params
));
527 void BlinkTestController::OnTestFinished() {
528 test_phase_
= CLEAN_UP
;
529 if (!printer_
->output_finished())
530 printer_
->PrintImageFooter();
531 RenderViewHost
* render_view_host
=
532 main_window_
->web_contents()->GetRenderViewHost();
533 main_window_
->web_contents()->ExitFullscreen();
535 ShellBrowserContext
* browser_context
=
536 ShellContentBrowserClient::Get()->browser_context();
537 StoragePartition
* storage_partition
=
538 BrowserContext::GetStoragePartition(browser_context
, nullptr);
539 storage_partition
->GetServiceWorkerContext()->ClearAllServiceWorkersForTest(
540 base::Bind(base::IgnoreResult(&BlinkTestController::Send
),
541 base::Unretained(this),
542 new ShellViewMsg_Reset(render_view_host
->GetRoutingID())));
545 void BlinkTestController::OnImageDump(const std::string
& actual_pixel_hash
,
546 const SkBitmap
& image
) {
547 SkAutoLockPixels
image_lock(image
);
549 printer_
->PrintImageHeader(actual_pixel_hash
, expected_pixel_hash_
);
551 // Only encode and dump the png if the hashes don't match. Encoding the
552 // image is really expensive.
553 if (actual_pixel_hash
!= expected_pixel_hash_
) {
554 std::vector
<unsigned char> png
;
556 bool discard_transparency
= true;
557 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
558 switches::kForceOverlayFullscreenVideo
))
559 discard_transparency
= false;
561 std::vector
<gfx::PNGCodec::Comment
> comments
;
562 comments
.push_back(gfx::PNGCodec::Comment("checksum", actual_pixel_hash
));
563 bool success
= gfx::PNGCodec::Encode(
564 static_cast<const unsigned char*>(image
.getPixels()),
565 gfx::PNGCodec::FORMAT_BGRA
,
566 gfx::Size(image
.width(), image
.height()),
567 static_cast<int>(image
.rowBytes()),
568 discard_transparency
,
572 printer_
->PrintImageBlock(png
);
574 printer_
->PrintImageFooter();
577 void BlinkTestController::OnAudioDump(const std::vector
<unsigned char>& dump
) {
578 printer_
->PrintAudioHeader();
579 printer_
->PrintAudioBlock(dump
);
580 printer_
->PrintAudioFooter();
583 void BlinkTestController::OnTextDump(const std::string
& dump
) {
584 printer_
->PrintTextHeader();
585 printer_
->PrintTextBlock(dump
);
586 printer_
->PrintTextFooter();
589 void BlinkTestController::OnPrintMessage(const std::string
& message
) {
590 printer_
->AddMessageRaw(message
);
593 void BlinkTestController::OnOverridePreferences(const WebPreferences
& prefs
) {
594 should_override_prefs_
= true;
598 void BlinkTestController::OnClearDevToolsLocalStorage() {
599 ShellBrowserContext
* browser_context
=
600 ShellContentBrowserClient::Get()->browser_context();
601 StoragePartition
* storage_partition
=
602 BrowserContext::GetStoragePartition(browser_context
, NULL
);
603 storage_partition
->GetDOMStorageContext()->DeleteLocalStorage(
604 content::LayoutTestDevToolsFrontend::GetDevToolsPathAsURL("", "")
608 void BlinkTestController::OnShowDevTools(const std::string
& settings
,
609 const std::string
& frontend_url
) {
610 if (!devtools_frontend_
) {
611 devtools_frontend_
= LayoutTestDevToolsFrontend::Show(
612 main_window_
->web_contents(), settings
, frontend_url
);
614 devtools_frontend_
->ReuseFrontend(settings
, frontend_url
);
616 devtools_frontend_
->Activate();
617 devtools_frontend_
->Focus();
620 void BlinkTestController::OnCloseDevTools() {
621 if (devtools_frontend_
)
622 devtools_frontend_
->DisconnectFromTarget();
625 void BlinkTestController::OnGoToOffset(int offset
) {
626 main_window_
->GoBackOrForward(offset
);
629 void BlinkTestController::OnReload() {
630 main_window_
->Reload();
633 void BlinkTestController::OnLoadURLForFrame(const GURL
& url
,
634 const std::string
& frame_name
) {
635 main_window_
->LoadURLForFrame(url
, frame_name
);
638 void BlinkTestController::OnCaptureSessionHistory() {
639 std::vector
<int> routing_ids
;
640 std::vector
<std::vector
<PageState
> > session_histories
;
641 std::vector
<unsigned> current_entry_indexes
;
643 RenderViewHost
* render_view_host
=
644 main_window_
->web_contents()->GetRenderViewHost();
646 for (std::vector
<Shell
*>::iterator window
= Shell::windows().begin();
647 window
!= Shell::windows().end();
649 WebContents
* web_contents
= (*window
)->web_contents();
650 // Only capture the history from windows in the same process as the main
651 // window. During layout tests, we only use two processes when an
652 // devtools window is open.
653 if (render_view_host
->GetProcess() !=
654 web_contents
->GetRenderViewHost()->GetProcess()) {
657 routing_ids
.push_back(web_contents
->GetRenderViewHost()->GetRoutingID());
658 current_entry_indexes
.push_back(
659 web_contents
->GetController().GetCurrentEntryIndex());
660 std::vector
<PageState
> history
;
661 for (int entry
= 0; entry
< web_contents
->GetController().GetEntryCount();
663 PageState state
= web_contents
->GetController().GetEntryAtIndex(entry
)->
665 if (!state
.IsValid()) {
666 state
= PageState::CreateFromURL(
667 web_contents
->GetController().GetEntryAtIndex(entry
)->GetURL());
669 history
.push_back(state
);
671 session_histories
.push_back(history
);
674 Send(new ShellViewMsg_SessionHistory(render_view_host
->GetRoutingID(),
677 current_entry_indexes
));
680 void BlinkTestController::OnCloseRemainingWindows() {
681 DevToolsAgentHost::DetachAllClients();
682 std::vector
<Shell
*> open_windows(Shell::windows());
683 Shell
* devtools_shell
= devtools_frontend_
?
684 devtools_frontend_
->frontend_shell() : NULL
;
685 for (size_t i
= 0; i
< open_windows
.size(); ++i
) {
686 if (open_windows
[i
] != main_window_
&& open_windows
[i
] != devtools_shell
)
687 open_windows
[i
]->Close();
689 base::MessageLoop::current()->RunUntilIdle();
692 void BlinkTestController::OnResetDone() {
693 if (is_leak_detection_enabled_
) {
694 if (main_window_
&& main_window_
->web_contents()) {
695 RenderViewHost
* render_view_host
=
696 main_window_
->web_contents()->GetRenderViewHost();
697 render_view_host
->Send(
698 new ShellViewMsg_TryLeakDetection(render_view_host
->GetRoutingID()));
703 base::ThreadTaskRunnerHandle::Get()->PostTask(
704 FROM_HERE
, base::MessageLoop::QuitClosure());
707 void BlinkTestController::OnLeakDetectionDone(
708 const LeakDetectionResult
& result
) {
709 if (!result
.leaked
) {
710 base::ThreadTaskRunnerHandle::Get()->PostTask(
711 FROM_HERE
, base::MessageLoop::QuitClosure());
715 printer_
->AddErrorMessage(
716 base::StringPrintf("#LEAK - renderer pid %d (%s)", current_pid_
,
717 result
.detail
.c_str()));
718 CHECK(!crash_when_leak_found_
);
723 void BlinkTestController::OnSetBluetoothManualChooser(bool enable
) {
724 bluetooth_chooser_factory_
.reset();
726 bluetooth_chooser_factory_
.reset(new LayoutTestBluetoothChooserFactory());
730 void BlinkTestController::OnGetBluetoothManualChooserEvents(
731 std::vector
<std::string
>* events
) {
732 if (!bluetooth_chooser_factory_
) {
733 printer_
->AddErrorMessage(
734 "FAIL: Must call setBluetoothManualChooser before "
735 "getBluetoothManualChooserEvents.");
738 *events
= bluetooth_chooser_factory_
->GetAndResetEvents();
741 void BlinkTestController::OnSendBluetoothManualChooserEvent(
742 const std::string
& event_name
,
743 const std::string
& argument
) {
744 if (!bluetooth_chooser_factory_
) {
745 printer_
->AddErrorMessage(
746 "FAIL: Must call setBluetoothManualChooser before "
747 "sendBluetoothManualChooserEvent.");
750 BluetoothChooser::Event event
;
751 if (event_name
== "cancelled") {
752 event
= BluetoothChooser::Event::CANCELLED
;
753 } else if (event_name
== "selected") {
754 event
= BluetoothChooser::Event::SELECTED
;
756 printer_
->AddErrorMessage(base::StringPrintf(
757 "FAIL: Unexpected sendBluetoothManualChooserEvent() event name '%s'.",
758 event_name
.c_str()));
761 bluetooth_chooser_factory_
->SendEvent(event
, argument
);
764 } // namespace content