Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / shell / browser / blink_test_controller.cc
blob97c533737119c48cf36c4851488f14c05fc2a0e0
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_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"
44 namespace content {
46 const int kTestSVGWindowWidthDip = 480;
47 const int kTestSVGWindowHeightDip = 360;
49 // BlinkTestResultPrinter ----------------------------------------------------
51 BlinkTestResultPrinter::BlinkTestResultPrinter(std::ostream* output,
52 std::ostream* error)
53 : state_(DURING_TEST),
54 capture_text_only_(false),
55 encode_binary_data_(false),
56 output_(output),
57 error_(error) {
60 BlinkTestResultPrinter::~BlinkTestResultPrinter() {
63 void BlinkTestResultPrinter::PrintTextHeader() {
64 if (state_ != DURING_TEST)
65 return;
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)
73 return;
74 *output_ << block;
77 void BlinkTestResultPrinter::PrintTextFooter() {
78 if (state_ != IN_TEXT_BLOCK)
79 return;
80 if (!capture_text_only_) {
81 *output_ << "#EOF\n";
82 output_->flush();
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_)
91 return;
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_)
100 return;
101 *output_ << "Content-Type: image/png\n";
102 if (encode_binary_data_) {
103 PrintEncodedBinaryData(png_image);
104 return;
107 *output_ << "Content-Length: " << png_image.size() << "\n";
108 output_->write(
109 reinterpret_cast<const char*>(&png_image[0]), png_image.size());
112 void BlinkTestResultPrinter::PrintImageFooter() {
113 if (state_ != IN_IMAGE_BLOCK)
114 return;
115 if (!capture_text_only_) {
116 *output_ << "#EOF\n";
117 output_->flush();
119 state_ = AFTER_TEST;
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_)
132 return;
133 if (encode_binary_data_) {
134 PrintEncodedBinaryData(audio_data);
135 return;
138 *output_ << "Content-Length: " << audio_data.size() << "\n";
139 output_->write(
140 reinterpret_cast<const char*>(&audio_data[0]), audio_data.size());
143 void BlinkTestResultPrinter::PrintAudioFooter() {
144 if (state_ != IN_AUDIO_BLOCK)
145 return;
146 if (!capture_text_only_) {
147 *output_ << "#EOF\n";
148 output_->flush();
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)
159 return;
160 *output_ << message;
163 void BlinkTestResultPrinter::AddErrorMessage(const std::string& message) {
164 if (!capture_text_only_)
165 *error_ << message << "\n";
166 if (state_ != DURING_TEST)
167 return;
168 PrintTextHeader();
169 *output_ << message << "\n";
170 PrintTextFooter();
171 PrintImageFooter();
174 void BlinkTestResultPrinter::PrintEncodedBinaryData(
175 const std::vector<unsigned char>& data) {
176 *output_ << "Content-Transfer-Encoding: base64\n";
178 std::string data_base64;
179 base::Base64Encode(
180 base::StringPiece(reinterpret_cast<const char*>(&data[0]), data.size()),
181 &data_base64);
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)
189 return;
190 if (!capture_text_only_) {
191 *error_ << "#EOF\n";
192 error_->flush();
196 // BlinkTestController -------------------------------------------------------
198 BlinkTestController* BlinkTestController::instance_ = NULL;
200 // static
201 BlinkTestController* BlinkTestController::Get() {
202 DCHECK(instance_);
203 return instance_;
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) {
214 CHECK(!instance_);
215 instance_ = this;
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);
228 registrar_.Add(this,
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);
240 DiscardMainWindow();
241 instance_ = NULL;
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;
255 printer_->reset();
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);
264 if (!main_window_) {
265 main_window_ = content::Shell::CreateNewWindow(
266 browser_context,
267 GURL(),
268 NULL,
269 initial_size_);
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);
274 } else {
275 #if defined(OS_MACOSX)
276 // Shell::SizeTo is not implemented on all platforms.
277 main_window_->SizeTo(initial_size_);
278 #endif
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();
298 return true;
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();
311 test_url_ = GURL();
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.
318 DiscardMainWindow();
319 #endif
320 return true;
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_) {
334 *prefs = prefs_;
335 } else {
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)
348 return;
350 Shell::CreateNewWindow(main_window_->web_contents()->GetBrowserContext(),
351 url,
352 main_window_->web_contents()->GetSiteInstance(),
353 gfx::Size());
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);
375 return nullptr;
378 bool BlinkTestController::OnMessageReceived(const IPC::Message& message) {
379 DCHECK(CalledOnValidThread());
380 bool handled = true;
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()
411 return handled;
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(
420 FROM_HERE,
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_)
432 return;
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_) + ")");
442 } else {
443 printer_->AddErrorMessage("#CRASHED - renderer");
445 DiscardMainWindow();
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");
459 DiscardMainWindow();
462 void BlinkTestController::Observe(int type,
463 const NotificationSource& source,
464 const NotificationDetails& details) {
465 DCHECK(CalledOnValidThread());
466 switch (type) {
467 case NOTIFICATION_RENDERER_PROCESS_CREATED: {
468 if (!main_window_)
469 return;
470 RenderViewHost* render_view_host =
471 main_window_->web_contents()->GetRenderViewHost();
472 if (!render_view_host)
473 return;
474 RenderProcessHost* render_process_host =
475 Source<RenderProcessHost>(source).ptr();
476 if (render_process_host != render_view_host->GetProcess())
477 return;
478 current_pid_ = base::GetProcId(render_process_host->GetHandle());
479 break;
481 default:
482 NOTREACHED();
486 void BlinkTestController::OnGpuProcessCrashed(
487 base::TerminationStatus exit_code) {
488 DCHECK(CalledOnValidThread());
489 printer_->AddErrorMessage("#CRASHED - gpu");
490 DiscardMainWindow();
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();
506 main_window_ = NULL;
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,
569 comments,
570 &png);
571 if (success)
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;
595 prefs_ = prefs;
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("", "")
605 .GetOrigin());
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);
613 } else {
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();
648 ++window) {
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()) {
655 continue;
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();
662 ++entry) {
663 PageState state = web_contents->GetController().GetEntryAtIndex(entry)->
664 GetPageState();
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(),
675 routing_ids,
676 session_histories,
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()));
700 return;
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());
712 return;
715 printer_->AddErrorMessage(
716 base::StringPrintf("#LEAK - renderer pid %d (%s)", current_pid_,
717 result.detail.c_str()));
718 CHECK(!crash_when_leak_found_);
720 DiscardMainWindow();
723 void BlinkTestController::OnSetBluetoothManualChooser(bool enable) {
724 bluetooth_chooser_factory_.reset();
725 if (enable) {
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.");
736 return;
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.");
748 return;
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;
755 } else {
756 printer_->AddErrorMessage(base::StringPrintf(
757 "FAIL: Unexpected sendBluetoothManualChooserEvent() event name '%s'.",
758 event_name.c_str()));
759 return;
761 bluetooth_chooser_factory_->SendEvent(event, argument);
764 } // namespace content