1 // Copyright (c) 2012 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/renderer/layout_test/blink_test_runner.h"
11 #include "base/base64.h"
12 #include "base/command_line.h"
13 #include "base/compiler_specific.h"
14 #include "base/debug/debugger.h"
15 #include "base/files/file_path.h"
16 #include "base/location.h"
18 #include "base/memory/scoped_ptr.h"
19 #include "base/single_thread_task_runner.h"
20 #include "base/strings/string_util.h"
21 #include "base/strings/stringprintf.h"
22 #include "base/strings/sys_string_conversions.h"
23 #include "base/strings/utf_string_conversions.h"
24 #include "base/thread_task_runner_handle.h"
25 #include "base/time/time.h"
26 #include "components/plugins/renderer/plugin_placeholder.h"
27 #include "components/test_runner/app_banner_client.h"
28 #include "components/test_runner/gamepad_controller.h"
29 #include "components/test_runner/mock_screen_orientation_client.h"
30 #include "components/test_runner/test_interfaces.h"
31 #include "components/test_runner/web_task.h"
32 #include "components/test_runner/web_test_interfaces.h"
33 #include "components/test_runner/web_test_proxy.h"
34 #include "components/test_runner/web_test_runner.h"
35 #include "content/public/common/content_switches.h"
36 #include "content/public/common/url_constants.h"
37 #include "content/public/common/web_preferences.h"
38 #include "content/public/renderer/render_frame.h"
39 #include "content/public/renderer/render_view.h"
40 #include "content/public/renderer/render_view_visitor.h"
41 #include "content/public/renderer/renderer_gamepad_provider.h"
42 #include "content/public/test/layouttest_support.h"
43 #include "content/shell/common/layout_test/layout_test_messages.h"
44 #include "content/shell/common/shell_messages.h"
45 #include "content/shell/common/shell_switches.h"
46 #include "content/shell/renderer/layout_test/blink_test_helpers.h"
47 #include "content/shell/renderer/layout_test/gc_controller.h"
48 #include "content/shell/renderer/layout_test/layout_test_render_process_observer.h"
49 #include "content/shell/renderer/layout_test/leak_detector.h"
50 #include "net/base/filename_util.h"
51 #include "net/base/net_errors.h"
52 #include "skia/ext/platform_canvas.h"
53 #include "third_party/WebKit/public/platform/Platform.h"
54 #include "third_party/WebKit/public/platform/WebCString.h"
55 #include "third_party/WebKit/public/platform/WebPoint.h"
56 #include "third_party/WebKit/public/platform/WebRect.h"
57 #include "third_party/WebKit/public/platform/WebSize.h"
58 #include "third_party/WebKit/public/platform/WebString.h"
59 #include "third_party/WebKit/public/platform/WebThread.h"
60 #include "third_party/WebKit/public/platform/WebTraceLocation.h"
61 #include "third_party/WebKit/public/platform/WebURL.h"
62 #include "third_party/WebKit/public/platform/WebURLError.h"
63 #include "third_party/WebKit/public/platform/WebURLRequest.h"
64 #include "third_party/WebKit/public/platform/WebURLResponse.h"
65 #include "third_party/WebKit/public/platform/modules/app_banner/WebAppBannerPromptReply.h"
66 #include "third_party/WebKit/public/web/WebArrayBufferView.h"
67 #include "third_party/WebKit/public/web/WebContextMenuData.h"
68 #include "third_party/WebKit/public/web/WebDataSource.h"
69 #include "third_party/WebKit/public/web/WebDevToolsAgent.h"
70 #include "third_party/WebKit/public/web/WebDocument.h"
71 #include "third_party/WebKit/public/web/WebElement.h"
72 #include "third_party/WebKit/public/web/WebHistoryItem.h"
73 #include "third_party/WebKit/public/web/WebKit.h"
74 #include "third_party/WebKit/public/web/WebLeakDetector.h"
75 #include "third_party/WebKit/public/web/WebLocalFrame.h"
76 #include "third_party/WebKit/public/web/WebScriptSource.h"
77 #include "third_party/WebKit/public/web/WebTestingSupport.h"
78 #include "third_party/WebKit/public/web/WebView.h"
79 #include "ui/gfx/geometry/rect.h"
81 using blink::Platform
;
82 using blink::WebArrayBufferView
;
83 using blink::WebContextMenuData
;
84 using blink::WebDevToolsAgent
;
85 using blink::WebDeviceMotionData
;
86 using blink::WebDeviceOrientationData
;
87 using blink::WebElement
;
88 using blink::WebLocalFrame
;
89 using blink::WebHistoryItem
;
90 using blink::WebLocalFrame
;
91 using blink::WebPoint
;
93 using blink::WebScriptSource
;
95 using blink::WebString
;
97 using blink::WebURLError
;
98 using blink::WebURLRequest
;
99 using blink::WebScreenOrientationType
;
100 using blink::WebTestingSupport
;
101 using blink::WebTraceLocation
;
102 using blink::WebThread
;
103 using blink::WebVector
;
104 using blink::WebView
;
110 class InvokeTaskHelper
: public WebThread::Task
{
112 InvokeTaskHelper(scoped_ptr
<test_runner::WebTask
> task
)
113 : task_(task
.Pass()) {}
115 // WebThread::Task implementation:
116 void run() override
{ task_
->run(); }
119 scoped_ptr
<test_runner::WebTask
> task_
;
122 class SyncNavigationStateVisitor
: public RenderViewVisitor
{
124 SyncNavigationStateVisitor() {}
125 ~SyncNavigationStateVisitor() override
{}
127 bool Visit(RenderView
* render_view
) override
{
128 SyncNavigationState(render_view
);
132 DISALLOW_COPY_AND_ASSIGN(SyncNavigationStateVisitor
);
135 class ProxyToRenderViewVisitor
: public RenderViewVisitor
{
137 explicit ProxyToRenderViewVisitor(test_runner::WebTestProxyBase
* proxy
)
141 ~ProxyToRenderViewVisitor() override
{}
143 RenderView
* render_view() const { return render_view_
; }
145 bool Visit(RenderView
* render_view
) override
{
146 BlinkTestRunner
* test_runner
= BlinkTestRunner::Get(render_view
);
151 if (test_runner
->proxy() == proxy_
) {
152 render_view_
= render_view
;
159 test_runner::WebTestProxyBase
* proxy_
;
160 RenderView
* render_view_
;
162 DISALLOW_COPY_AND_ASSIGN(ProxyToRenderViewVisitor
);
165 class NavigateAwayVisitor
: public RenderViewVisitor
{
167 explicit NavigateAwayVisitor(RenderView
* main_render_view
)
168 : main_render_view_(main_render_view
) {}
169 ~NavigateAwayVisitor() override
{}
171 bool Visit(RenderView
* render_view
) override
{
172 if (render_view
== main_render_view_
)
174 render_view
->GetWebView()->mainFrame()->loadRequest(
175 WebURLRequest(GURL(url::kAboutBlankURL
)));
180 RenderView
* main_render_view_
;
182 DISALLOW_COPY_AND_ASSIGN(NavigateAwayVisitor
);
185 class UseSynchronousResizeModeVisitor
: public RenderViewVisitor
{
187 explicit UseSynchronousResizeModeVisitor(bool enable
) : enable_(enable
) {}
188 ~UseSynchronousResizeModeVisitor() override
{}
190 bool Visit(RenderView
* render_view
) override
{
191 UseSynchronousResizeMode(render_view
, enable_
);
199 class MockGamepadProvider
: public RendererGamepadProvider
{
201 explicit MockGamepadProvider(test_runner::GamepadController
* controller
)
202 : RendererGamepadProvider(nullptr), controller_(controller
) {}
203 ~MockGamepadProvider() override
{
207 // RendererGamepadProvider implementation.
208 void SampleGamepads(blink::WebGamepads
& gamepads
) override
{
209 controller_
->SampleGamepads(gamepads
);
211 void Start(blink::WebPlatformEventListener
* listener
) override
{
212 controller_
->SetListener(static_cast<blink::WebGamepadListener
*>(listener
));
213 RendererGamepadProvider::Start(listener
);
215 void SendStartMessage() override
{}
216 void SendStopMessage() override
{}
219 scoped_ptr
<test_runner::GamepadController
> controller_
;
221 DISALLOW_COPY_AND_ASSIGN(MockGamepadProvider
);
226 BlinkTestRunner::BlinkTestRunner(RenderView
* render_view
)
227 : RenderViewObserver(render_view
),
228 RenderViewObserverTracker
<BlinkTestRunner
>(render_view
),
231 is_main_window_(false),
232 focus_on_next_commit_(false),
233 leak_detector_(new LeakDetector(this)) {
236 BlinkTestRunner::~BlinkTestRunner() {
239 // WebTestDelegate -----------------------------------------------------------
241 void BlinkTestRunner::ClearEditCommand() {
242 render_view()->ClearEditCommands();
245 void BlinkTestRunner::SetEditCommand(const std::string
& name
,
246 const std::string
& value
) {
247 render_view()->SetEditCommandForNextKeyEvent(name
, value
);
250 void BlinkTestRunner::SetGamepadProvider(
251 test_runner::GamepadController
* controller
) {
252 scoped_ptr
<MockGamepadProvider
> provider(new MockGamepadProvider(controller
));
253 SetMockGamepadProvider(provider
.Pass());
256 void BlinkTestRunner::SetDeviceLightData(const double data
) {
257 SetMockDeviceLightData(data
);
260 void BlinkTestRunner::SetDeviceMotionData(const WebDeviceMotionData
& data
) {
261 SetMockDeviceMotionData(data
);
264 void BlinkTestRunner::SetDeviceOrientationData(
265 const WebDeviceOrientationData
& data
) {
266 SetMockDeviceOrientationData(data
);
269 void BlinkTestRunner::SetScreenOrientation(
270 const WebScreenOrientationType
& orientation
) {
271 test_runner::MockScreenOrientationClient
* mock_client
=
272 proxy()->GetScreenOrientationClientMock();
273 mock_client
->UpdateDeviceOrientation(
274 render_view()->GetWebView()->mainFrame()->toWebLocalFrame(), orientation
);
277 void BlinkTestRunner::ResetScreenOrientation() {
278 test_runner::MockScreenOrientationClient
* mock_client
=
279 proxy()->GetScreenOrientationClientMock();
280 mock_client
->ResetData();
283 void BlinkTestRunner::DidChangeBatteryStatus(
284 const blink::WebBatteryStatus
& status
) {
285 MockBatteryStatusChanged(status
);
288 void BlinkTestRunner::PrintMessage(const std::string
& message
) {
289 Send(new ShellViewHostMsg_PrintMessage(routing_id(), message
));
292 void BlinkTestRunner::PostTask(test_runner::WebTask
* task
) {
293 Platform::current()->currentThread()->postTask(
294 WebTraceLocation(__FUNCTION__
, __FILE__
),
295 new InvokeTaskHelper(make_scoped_ptr(task
)));
298 void BlinkTestRunner::PostDelayedTask(test_runner::WebTask
* task
,
300 Platform::current()->currentThread()->postDelayedTask(
301 WebTraceLocation(__FUNCTION__
, __FILE__
),
302 new InvokeTaskHelper(make_scoped_ptr(task
)), ms
);
305 WebString
BlinkTestRunner::RegisterIsolatedFileSystem(
306 const blink::WebVector
<blink::WebString
>& absolute_filenames
) {
307 std::vector
<base::FilePath
> files
;
308 for (size_t i
= 0; i
< absolute_filenames
.size(); ++i
)
309 files
.push_back(base::FilePath::FromUTF16Unsafe(absolute_filenames
[i
]));
310 std::string filesystem_id
;
311 Send(new LayoutTestHostMsg_RegisterIsolatedFileSystem(
312 routing_id(), files
, &filesystem_id
));
313 return WebString::fromUTF8(filesystem_id
);
316 long long BlinkTestRunner::GetCurrentTimeInMillisecond() {
317 return base::TimeDelta(base::Time::Now() -
318 base::Time::UnixEpoch()).ToInternalValue() /
319 base::Time::kMicrosecondsPerMillisecond
;
322 WebString
BlinkTestRunner::GetAbsoluteWebStringFromUTF8Path(
323 const std::string
& utf8_path
) {
324 base::FilePath path
= base::FilePath::FromUTF8Unsafe(utf8_path
);
325 if (!path
.IsAbsolute()) {
327 net::FilePathToFileURL(test_config_
.current_working_directory
.Append(
328 FILE_PATH_LITERAL("foo")));
329 net::FileURLToFilePath(base_url
.Resolve(utf8_path
), &path
);
331 return path
.AsUTF16Unsafe();
334 WebURL
BlinkTestRunner::LocalFileToDataURL(const WebURL
& file_url
) {
335 base::FilePath local_path
;
336 if (!net::FileURLToFilePath(file_url
, &local_path
))
339 std::string contents
;
340 Send(new LayoutTestHostMsg_ReadFileToString(
341 routing_id(), local_path
, &contents
));
343 std::string contents_base64
;
344 base::Base64Encode(contents
, &contents_base64
);
346 const char data_url_prefix
[] = "data:text/css:charset=utf-8;base64,";
347 return WebURL(GURL(data_url_prefix
+ contents_base64
));
350 WebURL
BlinkTestRunner::RewriteLayoutTestsURL(const std::string
& utf8_url
) {
351 const char kPrefix
[] = "file:///tmp/LayoutTests/";
352 const int kPrefixLen
= arraysize(kPrefix
) - 1;
354 if (utf8_url
.compare(0, kPrefixLen
, kPrefix
, kPrefixLen
))
355 return WebURL(GURL(utf8_url
));
357 base::FilePath replace_path
=
358 LayoutTestRenderProcessObserver::GetInstance()->webkit_source_dir()
359 .Append(FILE_PATH_LITERAL("LayoutTests/"));
361 std::string utf8_path
= base::WideToUTF8(replace_path
.value());
363 std::string utf8_path
=
364 base::WideToUTF8(base::SysNativeMBToWide(replace_path
.value()));
366 std::string new_url
=
367 std::string("file://") + utf8_path
+ utf8_url
.substr(kPrefixLen
);
368 return WebURL(GURL(new_url
));
371 test_runner::TestPreferences
* BlinkTestRunner::Preferences() {
375 void BlinkTestRunner::ApplyPreferences() {
376 WebPreferences prefs
= render_view()->GetWebkitPreferences();
377 ExportLayoutTestSpecificPreferences(prefs_
, &prefs
);
378 render_view()->SetWebkitPreferences(prefs
);
379 Send(new ShellViewHostMsg_OverridePreferences(routing_id(), prefs
));
382 std::string
BlinkTestRunner::makeURLErrorDescription(const WebURLError
& error
) {
383 std::string domain
= error
.domain
.utf8();
384 int code
= error
.reason
;
386 if (domain
== net::kErrorDomain
) {
387 domain
= "NSURLErrorDomain";
388 switch (error
.reason
) {
389 case net::ERR_ABORTED
:
390 code
= -999; // NSURLErrorCancelled
392 case net::ERR_UNSAFE_PORT
:
393 // Our unsafe port checking happens at the network stack level, but we
394 // make this translation here to match the behavior of stock WebKit.
395 domain
= "WebKitErrorDomain";
398 case net::ERR_ADDRESS_INVALID
:
399 case net::ERR_ADDRESS_UNREACHABLE
:
400 case net::ERR_NETWORK_ACCESS_DENIED
:
401 code
= -1004; // NSURLErrorCannotConnectToHost
405 DLOG(WARNING
) << "Unknown error domain";
408 return base::StringPrintf("<NSError domain %s, code %d, failing URL \"%s\">",
409 domain
.c_str(), code
, error
.unreachableURL
.spec().data());
412 void BlinkTestRunner::UseUnfortunateSynchronousResizeMode(bool enable
) {
413 UseSynchronousResizeModeVisitor
visitor(enable
);
414 RenderView::ForEach(&visitor
);
417 void BlinkTestRunner::EnableAutoResizeMode(const WebSize
& min_size
,
418 const WebSize
& max_size
) {
419 content::EnableAutoResizeMode(render_view(), min_size
, max_size
);
422 void BlinkTestRunner::DisableAutoResizeMode(const WebSize
& new_size
) {
423 content::DisableAutoResizeMode(render_view(), new_size
);
424 if (!new_size
.isEmpty())
425 ForceResizeRenderView(render_view(), new_size
);
428 void BlinkTestRunner::ClearDevToolsLocalStorage() {
429 Send(new ShellViewHostMsg_ClearDevToolsLocalStorage(routing_id()));
432 void BlinkTestRunner::ShowDevTools(const std::string
& settings
,
433 const std::string
& frontend_url
) {
434 Send(new ShellViewHostMsg_ShowDevTools(
435 routing_id(), settings
, frontend_url
));
438 void BlinkTestRunner::CloseDevTools() {
439 Send(new ShellViewHostMsg_CloseDevTools(routing_id()));
440 WebDevToolsAgent
* agent
=
441 render_view()->GetMainRenderFrame()->GetWebFrame()->devToolsAgent();
446 void BlinkTestRunner::EvaluateInWebInspector(long call_id
,
447 const std::string
& script
) {
448 WebDevToolsAgent
* agent
=
449 render_view()->GetMainRenderFrame()->GetWebFrame()->devToolsAgent();
451 agent
->evaluateInWebInspector(call_id
, WebString::fromUTF8(script
));
454 void BlinkTestRunner::ClearAllDatabases() {
455 Send(new LayoutTestHostMsg_ClearAllDatabases(routing_id()));
458 void BlinkTestRunner::SetDatabaseQuota(int quota
) {
459 Send(new LayoutTestHostMsg_SetDatabaseQuota(routing_id(), quota
));
462 void BlinkTestRunner::SimulateWebNotificationClick(const std::string
& title
) {
463 Send(new LayoutTestHostMsg_SimulateWebNotificationClick(routing_id(), title
));
466 void BlinkTestRunner::SetDeviceScaleFactor(float factor
) {
467 content::SetDeviceScaleFactor(render_view(), factor
);
470 void BlinkTestRunner::SetDeviceColorProfile(const std::string
& name
) {
471 content::SetDeviceColorProfile(render_view(), name
);
474 void BlinkTestRunner::SetBluetoothMockDataSet(const std::string
& name
) {
475 Send(new LayoutTestHostMsg_SetBluetoothAdapter(name
));
478 void BlinkTestRunner::SetGeofencingMockProvider(bool service_available
) {
479 content::SetGeofencingMockProvider(service_available
);
482 void BlinkTestRunner::ClearGeofencingMockProvider() {
483 content::ClearGeofencingMockProvider();
486 void BlinkTestRunner::SetGeofencingMockPosition(double latitude
,
488 content::SetGeofencingMockPosition(latitude
, longitude
);
491 void BlinkTestRunner::SetFocus(test_runner::WebTestProxyBase
* proxy
,
493 ProxyToRenderViewVisitor
visitor(proxy
);
494 RenderView::ForEach(&visitor
);
495 if (!visitor
.render_view()) {
500 // Check whether the focused view was closed meanwhile.
501 if (!BlinkTestRunner::Get(focused_view_
))
502 focused_view_
= NULL
;
505 if (focused_view_
!= visitor
.render_view()) {
507 SetFocusAndActivate(focused_view_
, false);
508 SetFocusAndActivate(visitor
.render_view(), true);
509 focused_view_
= visitor
.render_view();
512 if (focused_view_
== visitor
.render_view()) {
513 SetFocusAndActivate(visitor
.render_view(), false);
514 focused_view_
= NULL
;
519 void BlinkTestRunner::SetAcceptAllCookies(bool accept
) {
520 Send(new LayoutTestHostMsg_AcceptAllCookies(routing_id(), accept
));
523 std::string
BlinkTestRunner::PathToLocalResource(const std::string
& resource
) {
525 if (resource
.find("/tmp/") == 0) {
526 // We want a temp file.
527 GURL base_url
= net::FilePathToFileURL(test_config_
.temp_path
);
528 return base_url
.Resolve(resource
.substr(strlen("/tmp/"))).spec();
532 // Some layout tests use file://// which we resolve as a UNC path. Normalize
533 // them to just file:///.
534 std::string result
= resource
;
535 while (base::StringToLowerASCII(result
).find("file:////") == 0) {
536 result
= result
.substr(0, strlen("file:///")) +
537 result
.substr(strlen("file:////"));
539 return RewriteLayoutTestsURL(result
).spec();
542 void BlinkTestRunner::SetLocale(const std::string
& locale
) {
543 setlocale(LC_ALL
, locale
.c_str());
546 void BlinkTestRunner::TestFinished() {
547 if (!is_main_window_
) {
548 Send(new ShellViewHostMsg_TestFinishedInSecondaryWindow(routing_id()));
551 test_runner::WebTestInterfaces
* interfaces
=
552 LayoutTestRenderProcessObserver::GetInstance()->test_interfaces();
553 interfaces
->SetTestIsRunning(false);
554 if (interfaces
->TestRunner()->ShouldDumpBackForwardList()) {
555 SyncNavigationStateVisitor visitor
;
556 RenderView::ForEach(&visitor
);
557 Send(new ShellViewHostMsg_CaptureSessionHistory(routing_id()));
563 void BlinkTestRunner::CloseRemainingWindows() {
564 NavigateAwayVisitor
visitor(render_view());
565 RenderView::ForEach(&visitor
);
566 Send(new ShellViewHostMsg_CloseRemainingWindows(routing_id()));
569 void BlinkTestRunner::DeleteAllCookies() {
570 Send(new LayoutTestHostMsg_DeleteAllCookies(routing_id()));
573 int BlinkTestRunner::NavigationEntryCount() {
574 return GetLocalSessionHistoryLength(render_view());
577 void BlinkTestRunner::GoToOffset(int offset
) {
578 Send(new ShellViewHostMsg_GoToOffset(routing_id(), offset
));
581 void BlinkTestRunner::Reload() {
582 Send(new ShellViewHostMsg_Reload(routing_id()));
585 void BlinkTestRunner::LoadURLForFrame(const WebURL
& url
,
586 const std::string
& frame_name
) {
587 Send(new ShellViewHostMsg_LoadURLForFrame(
588 routing_id(), url
, frame_name
));
591 bool BlinkTestRunner::AllowExternalPages() {
592 return test_config_
.allow_external_pages
;
595 std::string
BlinkTestRunner::DumpHistoryForWindow(
596 test_runner::WebTestProxyBase
* proxy
) {
598 std::vector
<int>::iterator id
;
599 for (id
= routing_ids_
.begin(); id
!= routing_ids_
.end(); ++id
, ++pos
) {
600 RenderView
* render_view
= RenderView::FromRoutingID(*id
);
605 if (BlinkTestRunner::Get(render_view
)->proxy() == proxy
)
609 if (id
== routing_ids_
.end()) {
611 return std::string();
613 return DumpBackForwardList(session_histories_
[pos
],
614 current_entry_indexes_
[pos
]);
617 void BlinkTestRunner::FetchManifest(
618 blink::WebView
* view
,
620 const base::Callback
<void(const blink::WebURLResponse
& response
,
621 const std::string
& data
)>& callback
) {
622 ::content::FetchManifest(view
, url
, callback
);
625 void BlinkTestRunner::SetPermission(const std::string
& name
,
626 const std::string
& value
,
628 const GURL
& embedding_origin
) {
629 content::PermissionStatus status
;
630 if (value
== "granted")
631 status
= PERMISSION_STATUS_GRANTED
;
632 else if (value
== "prompt")
633 status
= PERMISSION_STATUS_ASK
;
634 else if (value
== "denied")
635 status
= PERMISSION_STATUS_DENIED
;
638 status
= PERMISSION_STATUS_DENIED
;
641 Send(new LayoutTestHostMsg_SetPermission(
642 routing_id(), name
, status
, origin
, embedding_origin
));
645 void BlinkTestRunner::ResetPermissions() {
646 Send(new LayoutTestHostMsg_ResetPermissions(routing_id()));
649 scoped_refptr
<cc::TextureLayer
> BlinkTestRunner::CreateTextureLayerForMailbox(
650 cc::TextureLayerClient
* client
) {
651 return ::content::CreateTextureLayerForMailbox(client
);
654 blink::WebLayer
* BlinkTestRunner::InstantiateWebLayer(
655 scoped_refptr
<cc::TextureLayer
> layer
) {
656 return ::content::InstantiateWebLayer(layer
);
659 cc::SharedBitmapManager
* BlinkTestRunner::GetSharedBitmapManager() {
660 return RenderThread::Get()->GetSharedBitmapManager();
663 void BlinkTestRunner::DispatchBeforeInstallPromptEvent(
665 const std::vector
<std::string
>& event_platforms
,
666 const base::Callback
<void(bool)>& callback
) {
667 // Send the event to the frame.
668 blink::WebAppBannerPromptReply reply
;
669 std::vector
<blink::WebString
> blink_web_strings
;
670 for (const auto& platform
: event_platforms
)
671 blink_web_strings
.push_back(blink::WebString::fromUTF8(platform
));
672 blink::WebVector
<blink::WebString
> blink_event_platforms(blink_web_strings
);
674 WebLocalFrame
* main_frame
=
675 render_view()->GetWebView()->mainFrame()->toWebLocalFrame();
676 main_frame
->willShowInstallBannerPrompt(request_id
, blink_event_platforms
,
679 callback
.Run(reply
== blink::WebAppBannerPromptReply::Cancel
);
682 void BlinkTestRunner::ResolveBeforeInstallPromptPromise(
683 int request_id
, const std::string
& platform
) {
684 test_runner::WebTestInterfaces
* interfaces
=
685 LayoutTestRenderProcessObserver::GetInstance()->test_interfaces();
686 if (interfaces
->GetAppBannerClient())
687 interfaces
->GetAppBannerClient()->ResolvePromise(request_id
, platform
);
690 blink::WebPlugin
* BlinkTestRunner::CreatePluginPlaceholder(
691 blink::WebLocalFrame
* frame
, const blink::WebPluginParams
& params
) {
692 if (params
.mimeType
!= "application/x-plugin-placeholder-test")
695 plugins::PluginPlaceholder
* placeholder
=
696 new plugins::PluginPlaceholder(render_view()->GetMainRenderFrame(), frame
,
697 params
, "<div>Test content</div>");
698 return placeholder
->plugin();
701 // RenderViewObserver --------------------------------------------------------
703 void BlinkTestRunner::DidClearWindowObject(WebLocalFrame
* frame
) {
704 WebTestingSupport::injectInternalsObject(frame
);
705 LayoutTestRenderProcessObserver::GetInstance()->test_interfaces()->BindTo(
707 GCController::Install(frame
);
710 bool BlinkTestRunner::OnMessageReceived(const IPC::Message
& message
) {
712 IPC_BEGIN_MESSAGE_MAP(BlinkTestRunner
, message
)
713 IPC_MESSAGE_HANDLER(ShellViewMsg_SetTestConfiguration
,
714 OnSetTestConfiguration
)
715 IPC_MESSAGE_HANDLER(ShellViewMsg_SessionHistory
, OnSessionHistory
)
716 IPC_MESSAGE_HANDLER(ShellViewMsg_Reset
, OnReset
)
717 IPC_MESSAGE_HANDLER(ShellViewMsg_NotifyDone
, OnNotifyDone
)
718 IPC_MESSAGE_HANDLER(ShellViewMsg_TryLeakDetection
, OnTryLeakDetection
)
719 IPC_MESSAGE_UNHANDLED(handled
= false)
720 IPC_END_MESSAGE_MAP()
725 void BlinkTestRunner::Navigate(const GURL
& url
) {
726 focus_on_next_commit_
= true;
727 if (!is_main_window_
&&
728 LayoutTestRenderProcessObserver::GetInstance()->main_test_runner() ==
730 test_runner::WebTestInterfaces
* interfaces
=
731 LayoutTestRenderProcessObserver::GetInstance()->test_interfaces();
732 interfaces
->SetTestIsRunning(true);
733 interfaces
->ConfigureForTestWithURL(GURL(), false);
734 ForceResizeRenderView(render_view(), WebSize(800, 600));
738 void BlinkTestRunner::DidCommitProvisionalLoad(WebLocalFrame
* frame
,
739 bool is_new_navigation
) {
740 if (!focus_on_next_commit_
)
742 focus_on_next_commit_
= false;
743 render_view()->GetWebView()->setFocusedFrame(frame
);
746 void BlinkTestRunner::DidFailProvisionalLoad(WebLocalFrame
* frame
,
747 const WebURLError
& error
) {
748 focus_on_next_commit_
= false;
751 // Public methods - -----------------------------------------------------------
753 void BlinkTestRunner::Reset() {
754 // The proxy_ is always non-NULL, it is set right after construction.
755 proxy_
->set_widget(render_view()->GetWebView());
758 routing_ids_
.clear();
759 session_histories_
.clear();
760 current_entry_indexes_
.clear();
762 render_view()->ClearEditCommands();
763 if (render_view()->GetWebView()->mainFrame()->isWebLocalFrame())
764 render_view()->GetWebView()->mainFrame()->setName(WebString());
765 render_view()->GetWebView()->mainFrame()->clearOpener();
767 // Resetting the internals object also overrides the WebPreferences, so we
768 // have to sync them to WebKit again.
769 if (render_view()->GetWebView()->mainFrame()->isWebLocalFrame()) {
770 WebTestingSupport::resetInternalsObject(
771 render_view()->GetWebView()->mainFrame()->toWebLocalFrame());
772 render_view()->SetWebkitPreferences(render_view()->GetWebkitPreferences());
776 // Private methods -----------------------------------------------------------
778 void BlinkTestRunner::CaptureDump() {
779 test_runner::WebTestInterfaces
* interfaces
=
780 LayoutTestRenderProcessObserver::GetInstance()->test_interfaces();
781 TRACE_EVENT0("shell", "BlinkTestRunner::CaptureDump");
783 if (interfaces
->TestRunner()->ShouldDumpAsAudio()) {
784 std::vector
<unsigned char> vector_data
;
785 interfaces
->TestRunner()->GetAudioData(&vector_data
);
786 Send(new ShellViewHostMsg_AudioDump(routing_id(), vector_data
));
788 const base::CommandLine
& command_line
=
789 *base::CommandLine::ForCurrentProcess();
790 Send(new ShellViewHostMsg_TextDump(
791 routing_id(), proxy()->CaptureTree(
792 false, command_line
.HasSwitch(switches::kDumpLineBoxTrees
))));
794 if (test_config_
.enable_pixel_dumping
&&
795 interfaces
->TestRunner()->ShouldGeneratePixelResults()) {
796 CHECK(render_view()->GetWebView()->isAcceleratedCompositingActive());
797 proxy()->CapturePixelsAsync(base::Bind(
798 &BlinkTestRunner::CaptureDumpPixels
, base::Unretained(this)));
803 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
804 switches::kEnableSlimmingPaint
) ||
805 !base::CommandLine::ForCurrentProcess()->HasSwitch(
806 switches::kDisableSlimmingPaint
)) {
807 // Force a layout/paint by the end of the test to ensure test coverage of
808 // incremental painting in slimming paint mode.
809 proxy()->LayoutAndPaintAsyncThen(base::Bind(
810 &BlinkTestRunner::CaptureDumpComplete
, base::Unretained(this)));
814 CaptureDumpComplete();
817 void BlinkTestRunner::CaptureDumpPixels(const SkBitmap
& snapshot
) {
818 DCHECK_NE(0, snapshot
.info().width());
819 DCHECK_NE(0, snapshot
.info().height());
821 SkAutoLockPixels
snapshot_lock(snapshot
);
822 // The snapshot arrives from the GPU process via shared memory. Because MSan
823 // can't track initializedness across processes, we must assure it that the
824 // pixels are in fact initialized.
825 MSAN_UNPOISON(snapshot
.getPixels(), snapshot
.getSize());
826 base::MD5Digest digest
;
827 base::MD5Sum(snapshot
.getPixels(), snapshot
.getSize(), &digest
);
828 std::string actual_pixel_hash
= base::MD5DigestToBase16(digest
);
830 if (actual_pixel_hash
== test_config_
.expected_pixel_hash
) {
831 SkBitmap empty_image
;
832 Send(new ShellViewHostMsg_ImageDump(
833 routing_id(), actual_pixel_hash
, empty_image
));
835 Send(new ShellViewHostMsg_ImageDump(
836 routing_id(), actual_pixel_hash
, snapshot
));
839 CaptureDumpComplete();
842 void BlinkTestRunner::CaptureDumpComplete() {
843 render_view()->GetWebView()->mainFrame()->stopLoading();
845 base::ThreadTaskRunnerHandle::Get()->PostTask(
846 FROM_HERE
, base::Bind(base::IgnoreResult(&BlinkTestRunner::Send
),
847 base::Unretained(this),
848 new ShellViewHostMsg_TestFinished(routing_id())));
851 void BlinkTestRunner::OnSetTestConfiguration(
852 const ShellTestConfiguration
& params
) {
853 test_config_
= params
;
854 is_main_window_
= true;
856 ForceResizeRenderView(
858 WebSize(params
.initial_size
.width(), params
.initial_size
.height()));
859 SetFocus(proxy_
, true);
861 test_runner::WebTestInterfaces
* interfaces
=
862 LayoutTestRenderProcessObserver::GetInstance()->test_interfaces();
863 interfaces
->SetTestIsRunning(true);
864 interfaces
->ConfigureForTestWithURL(params
.test_url
,
865 params
.enable_pixel_dumping
);
868 void BlinkTestRunner::OnSessionHistory(
869 const std::vector
<int>& routing_ids
,
870 const std::vector
<std::vector
<PageState
>>& session_histories
,
871 const std::vector
<unsigned>& current_entry_indexes
) {
872 routing_ids_
= routing_ids
;
873 session_histories_
= session_histories
;
874 current_entry_indexes_
= current_entry_indexes
;
878 void BlinkTestRunner::OnReset() {
879 LayoutTestRenderProcessObserver::GetInstance()->test_interfaces()->ResetAll();
881 // Navigating to about:blank will make sure that no new loads are initiated
883 render_view()->GetWebView()->mainFrame()->loadRequest(
884 WebURLRequest(GURL(url::kAboutBlankURL
)));
885 Send(new ShellViewHostMsg_ResetDone(routing_id()));
888 void BlinkTestRunner::OnNotifyDone() {
889 render_view()->GetWebView()->mainFrame()->executeScript(
890 WebScriptSource(WebString::fromUTF8("testRunner.notifyDone();")));
893 void BlinkTestRunner::OnTryLeakDetection() {
894 WebLocalFrame
* main_frame
=
895 render_view()->GetWebView()->mainFrame()->toWebLocalFrame();
896 DCHECK_EQ(GURL(url::kAboutBlankURL
), GURL(main_frame
->document().url()));
897 DCHECK(!main_frame
->isLoading());
899 leak_detector_
->TryLeakDetection(main_frame
);
902 void BlinkTestRunner::ReportLeakDetectionResult(
903 const LeakDetectionResult
& report
) {
904 Send(new ShellViewHostMsg_LeakDetectionDone(routing_id(), report
));
907 } // namespace content