Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / shell / renderer / layout_test / blink_test_runner.cc
blobbc52f3ebc3d0ec46fddee042430c975c924227d5
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"
7 #include <algorithm>
8 #include <clocale>
9 #include <cmath>
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"
17 #include "base/md5.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/WebTaskRunner.h"
60 #include "third_party/WebKit/public/platform/WebThread.h"
61 #include "third_party/WebKit/public/platform/WebTraceLocation.h"
62 #include "third_party/WebKit/public/platform/WebURL.h"
63 #include "third_party/WebKit/public/platform/WebURLError.h"
64 #include "third_party/WebKit/public/platform/WebURLRequest.h"
65 #include "third_party/WebKit/public/platform/WebURLResponse.h"
66 #include "third_party/WebKit/public/platform/modules/app_banner/WebAppBannerPromptReply.h"
67 #include "third_party/WebKit/public/web/WebArrayBufferView.h"
68 #include "third_party/WebKit/public/web/WebContextMenuData.h"
69 #include "third_party/WebKit/public/web/WebDataSource.h"
70 #include "third_party/WebKit/public/web/WebDevToolsAgent.h"
71 #include "third_party/WebKit/public/web/WebDocument.h"
72 #include "third_party/WebKit/public/web/WebElement.h"
73 #include "third_party/WebKit/public/web/WebHistoryItem.h"
74 #include "third_party/WebKit/public/web/WebKit.h"
75 #include "third_party/WebKit/public/web/WebLeakDetector.h"
76 #include "third_party/WebKit/public/web/WebLocalFrame.h"
77 #include "third_party/WebKit/public/web/WebScriptSource.h"
78 #include "third_party/WebKit/public/web/WebTestingSupport.h"
79 #include "third_party/WebKit/public/web/WebView.h"
80 #include "ui/gfx/geometry/rect.h"
82 using blink::Platform;
83 using blink::WebArrayBufferView;
84 using blink::WebContextMenuData;
85 using blink::WebDevToolsAgent;
86 using blink::WebDeviceMotionData;
87 using blink::WebDeviceOrientationData;
88 using blink::WebElement;
89 using blink::WebLocalFrame;
90 using blink::WebHistoryItem;
91 using blink::WebLocalFrame;
92 using blink::WebPoint;
93 using blink::WebRect;
94 using blink::WebScriptSource;
95 using blink::WebSize;
96 using blink::WebString;
97 using blink::WebURL;
98 using blink::WebURLError;
99 using blink::WebURLRequest;
100 using blink::WebScreenOrientationType;
101 using blink::WebTestingSupport;
102 using blink::WebTraceLocation;
103 using blink::WebThread;
104 using blink::WebVector;
105 using blink::WebView;
107 namespace content {
109 namespace {
111 class InvokeTaskHelper : public blink::WebTaskRunner::Task {
112 public:
113 InvokeTaskHelper(scoped_ptr<test_runner::WebTask> task)
114 : task_(task.Pass()) {}
116 // WebThread::Task implementation:
117 void run() override { task_->run(); }
119 private:
120 scoped_ptr<test_runner::WebTask> task_;
123 class SyncNavigationStateVisitor : public RenderViewVisitor {
124 public:
125 SyncNavigationStateVisitor() {}
126 ~SyncNavigationStateVisitor() override {}
128 bool Visit(RenderView* render_view) override {
129 SyncNavigationState(render_view);
130 return true;
132 private:
133 DISALLOW_COPY_AND_ASSIGN(SyncNavigationStateVisitor);
136 class ProxyToRenderViewVisitor : public RenderViewVisitor {
137 public:
138 explicit ProxyToRenderViewVisitor(test_runner::WebTestProxyBase* proxy)
139 : proxy_(proxy),
140 render_view_(NULL) {
142 ~ProxyToRenderViewVisitor() override {}
144 RenderView* render_view() const { return render_view_; }
146 bool Visit(RenderView* render_view) override {
147 BlinkTestRunner* test_runner = BlinkTestRunner::Get(render_view);
148 if (!test_runner) {
149 NOTREACHED();
150 return true;
152 if (test_runner->proxy() == proxy_) {
153 render_view_ = render_view;
154 return false;
156 return true;
159 private:
160 test_runner::WebTestProxyBase* proxy_;
161 RenderView* render_view_;
163 DISALLOW_COPY_AND_ASSIGN(ProxyToRenderViewVisitor);
166 class NavigateAwayVisitor : public RenderViewVisitor {
167 public:
168 explicit NavigateAwayVisitor(RenderView* main_render_view)
169 : main_render_view_(main_render_view) {}
170 ~NavigateAwayVisitor() override {}
172 bool Visit(RenderView* render_view) override {
173 if (render_view == main_render_view_)
174 return true;
175 render_view->GetWebView()->mainFrame()->loadRequest(
176 WebURLRequest(GURL(url::kAboutBlankURL)));
177 return true;
180 private:
181 RenderView* main_render_view_;
183 DISALLOW_COPY_AND_ASSIGN(NavigateAwayVisitor);
186 class UseSynchronousResizeModeVisitor : public RenderViewVisitor {
187 public:
188 explicit UseSynchronousResizeModeVisitor(bool enable) : enable_(enable) {}
189 ~UseSynchronousResizeModeVisitor() override {}
191 bool Visit(RenderView* render_view) override {
192 UseSynchronousResizeMode(render_view, enable_);
193 return true;
196 private:
197 bool enable_;
200 class MockGamepadProvider : public RendererGamepadProvider {
201 public:
202 explicit MockGamepadProvider(test_runner::GamepadController* controller)
203 : RendererGamepadProvider(nullptr), controller_(controller) {}
204 ~MockGamepadProvider() override {
205 StopIfObserving();
208 // RendererGamepadProvider implementation.
209 void SampleGamepads(blink::WebGamepads& gamepads) override {
210 controller_->SampleGamepads(gamepads);
212 void Start(blink::WebPlatformEventListener* listener) override {
213 controller_->SetListener(static_cast<blink::WebGamepadListener*>(listener));
214 RendererGamepadProvider::Start(listener);
216 void SendStartMessage() override {}
217 void SendStopMessage() override {}
219 private:
220 scoped_ptr<test_runner::GamepadController> controller_;
222 DISALLOW_COPY_AND_ASSIGN(MockGamepadProvider);
225 } // namespace
227 BlinkTestRunner::BlinkTestRunner(RenderView* render_view)
228 : RenderViewObserver(render_view),
229 RenderViewObserverTracker<BlinkTestRunner>(render_view),
230 proxy_(NULL),
231 focused_view_(NULL),
232 is_main_window_(false),
233 focus_on_next_commit_(false),
234 leak_detector_(new LeakDetector(this)) {
237 BlinkTestRunner::~BlinkTestRunner() {
240 // WebTestDelegate -----------------------------------------------------------
242 void BlinkTestRunner::ClearEditCommand() {
243 render_view()->ClearEditCommands();
246 void BlinkTestRunner::SetEditCommand(const std::string& name,
247 const std::string& value) {
248 render_view()->SetEditCommandForNextKeyEvent(name, value);
251 void BlinkTestRunner::SetGamepadProvider(
252 test_runner::GamepadController* controller) {
253 scoped_ptr<MockGamepadProvider> provider(new MockGamepadProvider(controller));
254 SetMockGamepadProvider(provider.Pass());
257 void BlinkTestRunner::SetDeviceLightData(const double data) {
258 SetMockDeviceLightData(data);
261 void BlinkTestRunner::SetDeviceMotionData(const WebDeviceMotionData& data) {
262 SetMockDeviceMotionData(data);
265 void BlinkTestRunner::SetDeviceOrientationData(
266 const WebDeviceOrientationData& data) {
267 SetMockDeviceOrientationData(data);
270 void BlinkTestRunner::SetScreenOrientation(
271 const WebScreenOrientationType& orientation) {
272 test_runner::MockScreenOrientationClient* mock_client =
273 proxy()->GetScreenOrientationClientMock();
274 mock_client->UpdateDeviceOrientation(
275 render_view()->GetWebView()->mainFrame()->toWebLocalFrame(), orientation);
278 void BlinkTestRunner::ResetScreenOrientation() {
279 test_runner::MockScreenOrientationClient* mock_client =
280 proxy()->GetScreenOrientationClientMock();
281 mock_client->ResetData();
284 void BlinkTestRunner::DidChangeBatteryStatus(
285 const blink::WebBatteryStatus& status) {
286 MockBatteryStatusChanged(status);
289 void BlinkTestRunner::PrintMessage(const std::string& message) {
290 Send(new ShellViewHostMsg_PrintMessage(routing_id(), message));
293 void BlinkTestRunner::PostTask(test_runner::WebTask* task) {
294 Platform::current()->currentThread()->taskRunner()->postTask(
295 WebTraceLocation(__FUNCTION__, __FILE__),
296 new InvokeTaskHelper(make_scoped_ptr(task)));
299 void BlinkTestRunner::PostDelayedTask(test_runner::WebTask* task,
300 long long ms) {
301 Platform::current()->currentThread()->taskRunner()->postDelayedTask(
302 WebTraceLocation(__FUNCTION__, __FILE__),
303 new InvokeTaskHelper(make_scoped_ptr(task)), ms);
306 WebString BlinkTestRunner::RegisterIsolatedFileSystem(
307 const blink::WebVector<blink::WebString>& absolute_filenames) {
308 std::vector<base::FilePath> files;
309 for (size_t i = 0; i < absolute_filenames.size(); ++i)
310 files.push_back(base::FilePath::FromUTF16Unsafe(absolute_filenames[i]));
311 std::string filesystem_id;
312 Send(new LayoutTestHostMsg_RegisterIsolatedFileSystem(
313 routing_id(), files, &filesystem_id));
314 return WebString::fromUTF8(filesystem_id);
317 long long BlinkTestRunner::GetCurrentTimeInMillisecond() {
318 return base::TimeDelta(base::Time::Now() -
319 base::Time::UnixEpoch()).ToInternalValue() /
320 base::Time::kMicrosecondsPerMillisecond;
323 WebString BlinkTestRunner::GetAbsoluteWebStringFromUTF8Path(
324 const std::string& utf8_path) {
325 base::FilePath path = base::FilePath::FromUTF8Unsafe(utf8_path);
326 if (!path.IsAbsolute()) {
327 GURL base_url =
328 net::FilePathToFileURL(test_config_.current_working_directory.Append(
329 FILE_PATH_LITERAL("foo")));
330 net::FileURLToFilePath(base_url.Resolve(utf8_path), &path);
332 return path.AsUTF16Unsafe();
335 WebURL BlinkTestRunner::LocalFileToDataURL(const WebURL& file_url) {
336 base::FilePath local_path;
337 if (!net::FileURLToFilePath(file_url, &local_path))
338 return WebURL();
340 std::string contents;
341 Send(new LayoutTestHostMsg_ReadFileToString(
342 routing_id(), local_path, &contents));
344 std::string contents_base64;
345 base::Base64Encode(contents, &contents_base64);
347 const char data_url_prefix[] = "data:text/css:charset=utf-8;base64,";
348 return WebURL(GURL(data_url_prefix + contents_base64));
351 WebURL BlinkTestRunner::RewriteLayoutTestsURL(const std::string& utf8_url) {
352 const char kPrefix[] = "file:///tmp/LayoutTests/";
353 const int kPrefixLen = arraysize(kPrefix) - 1;
355 if (utf8_url.compare(0, kPrefixLen, kPrefix, kPrefixLen))
356 return WebURL(GURL(utf8_url));
358 base::FilePath replace_path =
359 LayoutTestRenderProcessObserver::GetInstance()->webkit_source_dir()
360 .Append(FILE_PATH_LITERAL("LayoutTests/"));
361 #if defined(OS_WIN)
362 std::string utf8_path = base::WideToUTF8(replace_path.value());
363 #else
364 std::string utf8_path =
365 base::WideToUTF8(base::SysNativeMBToWide(replace_path.value()));
366 #endif
367 std::string new_url =
368 std::string("file://") + utf8_path + utf8_url.substr(kPrefixLen);
369 return WebURL(GURL(new_url));
372 test_runner::TestPreferences* BlinkTestRunner::Preferences() {
373 return &prefs_;
376 void BlinkTestRunner::ApplyPreferences() {
377 WebPreferences prefs = render_view()->GetWebkitPreferences();
378 ExportLayoutTestSpecificPreferences(prefs_, &prefs);
379 render_view()->SetWebkitPreferences(prefs);
380 Send(new ShellViewHostMsg_OverridePreferences(routing_id(), prefs));
383 std::string BlinkTestRunner::makeURLErrorDescription(const WebURLError& error) {
384 std::string domain = error.domain.utf8();
385 int code = error.reason;
387 if (domain == net::kErrorDomain) {
388 domain = "NSURLErrorDomain";
389 switch (error.reason) {
390 case net::ERR_ABORTED:
391 code = -999; // NSURLErrorCancelled
392 break;
393 case net::ERR_UNSAFE_PORT:
394 // Our unsafe port checking happens at the network stack level, but we
395 // make this translation here to match the behavior of stock WebKit.
396 domain = "WebKitErrorDomain";
397 code = 103;
398 break;
399 case net::ERR_ADDRESS_INVALID:
400 case net::ERR_ADDRESS_UNREACHABLE:
401 case net::ERR_NETWORK_ACCESS_DENIED:
402 code = -1004; // NSURLErrorCannotConnectToHost
403 break;
405 } else {
406 DLOG(WARNING) << "Unknown error domain";
409 return base::StringPrintf("<NSError domain %s, code %d, failing URL \"%s\">",
410 domain.c_str(), code, error.unreachableURL.spec().data());
413 void BlinkTestRunner::UseUnfortunateSynchronousResizeMode(bool enable) {
414 UseSynchronousResizeModeVisitor visitor(enable);
415 RenderView::ForEach(&visitor);
418 void BlinkTestRunner::EnableAutoResizeMode(const WebSize& min_size,
419 const WebSize& max_size) {
420 content::EnableAutoResizeMode(render_view(), min_size, max_size);
423 void BlinkTestRunner::DisableAutoResizeMode(const WebSize& new_size) {
424 content::DisableAutoResizeMode(render_view(), new_size);
425 if (!new_size.isEmpty())
426 ForceResizeRenderView(render_view(), new_size);
429 void BlinkTestRunner::ClearDevToolsLocalStorage() {
430 Send(new ShellViewHostMsg_ClearDevToolsLocalStorage(routing_id()));
433 void BlinkTestRunner::ShowDevTools(const std::string& settings,
434 const std::string& frontend_url) {
435 Send(new ShellViewHostMsg_ShowDevTools(
436 routing_id(), settings, frontend_url));
439 void BlinkTestRunner::CloseDevTools() {
440 Send(new ShellViewHostMsg_CloseDevTools(routing_id()));
441 WebDevToolsAgent* agent =
442 render_view()->GetMainRenderFrame()->GetWebFrame()->devToolsAgent();
443 if (agent)
444 agent->detach();
447 void BlinkTestRunner::EvaluateInWebInspector(long call_id,
448 const std::string& script) {
449 WebDevToolsAgent* agent =
450 render_view()->GetMainRenderFrame()->GetWebFrame()->devToolsAgent();
451 if (agent)
452 agent->evaluateInWebInspector(call_id, WebString::fromUTF8(script));
455 void BlinkTestRunner::ClearAllDatabases() {
456 Send(new LayoutTestHostMsg_ClearAllDatabases(routing_id()));
459 void BlinkTestRunner::SetDatabaseQuota(int quota) {
460 Send(new LayoutTestHostMsg_SetDatabaseQuota(routing_id(), quota));
463 void BlinkTestRunner::SimulateWebNotificationClick(const std::string& title,
464 int action_index) {
465 Send(new LayoutTestHostMsg_SimulateWebNotificationClick(routing_id(), title,
466 action_index));
469 void BlinkTestRunner::SetDeviceScaleFactor(float factor) {
470 content::SetDeviceScaleFactor(render_view(), factor);
473 void BlinkTestRunner::SetDeviceColorProfile(const std::string& name) {
474 content::SetDeviceColorProfile(render_view(), name);
477 void BlinkTestRunner::SetBluetoothMockDataSet(const std::string& name) {
478 Send(new LayoutTestHostMsg_SetBluetoothAdapter(name));
479 // Auto-reset the chooser type so we don't get order dependence when some
480 // tests forget to do it explicitly.
481 Send(new ShellViewHostMsg_SetBluetoothManualChooser(routing_id(), false));
484 void BlinkTestRunner::SetBluetoothManualChooser() {
485 Send(new ShellViewHostMsg_SetBluetoothManualChooser(routing_id(), true));
487 std::vector<std::string> BlinkTestRunner::GetBluetoothManualChooserEvents() {
488 std::vector<std::string> result;
489 Send(new ShellViewHostMsg_GetBluetoothManualChooserEvents(routing_id(),
490 &result));
491 return result;
493 void BlinkTestRunner::SendBluetoothManualChooserEvent(
494 const std::string& event,
495 const std::string& argument) {
496 Send(new ShellViewHostMsg_SendBluetoothManualChooserEvent(routing_id(), event,
497 argument));
500 void BlinkTestRunner::SetGeofencingMockProvider(bool service_available) {
501 content::SetGeofencingMockProvider(service_available);
504 void BlinkTestRunner::ClearGeofencingMockProvider() {
505 content::ClearGeofencingMockProvider();
508 void BlinkTestRunner::SetGeofencingMockPosition(double latitude,
509 double longitude) {
510 content::SetGeofencingMockPosition(latitude, longitude);
513 void BlinkTestRunner::SetFocus(test_runner::WebTestProxyBase* proxy,
514 bool focus) {
515 ProxyToRenderViewVisitor visitor(proxy);
516 RenderView::ForEach(&visitor);
517 if (!visitor.render_view()) {
518 NOTREACHED();
519 return;
522 // Check whether the focused view was closed meanwhile.
523 if (!BlinkTestRunner::Get(focused_view_))
524 focused_view_ = NULL;
526 if (focus) {
527 if (focused_view_ != visitor.render_view()) {
528 if (focused_view_)
529 SetFocusAndActivate(focused_view_, false);
530 SetFocusAndActivate(visitor.render_view(), true);
531 focused_view_ = visitor.render_view();
533 } else {
534 if (focused_view_ == visitor.render_view()) {
535 SetFocusAndActivate(visitor.render_view(), false);
536 focused_view_ = NULL;
541 void BlinkTestRunner::SetAcceptAllCookies(bool accept) {
542 Send(new LayoutTestHostMsg_AcceptAllCookies(routing_id(), accept));
545 std::string BlinkTestRunner::PathToLocalResource(const std::string& resource) {
546 #if defined(OS_WIN)
547 if (resource.find("/tmp/") == 0) {
548 // We want a temp file.
549 GURL base_url = net::FilePathToFileURL(test_config_.temp_path);
550 return base_url.Resolve(resource.substr(strlen("/tmp/"))).spec();
552 #endif
554 // Some layout tests use file://// which we resolve as a UNC path. Normalize
555 // them to just file:///.
556 std::string result = resource;
557 while (base::ToLowerASCII(result).find("file:////") == 0) {
558 result = result.substr(0, strlen("file:///")) +
559 result.substr(strlen("file:////"));
561 return RewriteLayoutTestsURL(result).spec();
564 void BlinkTestRunner::SetLocale(const std::string& locale) {
565 setlocale(LC_ALL, locale.c_str());
568 void BlinkTestRunner::TestFinished() {
569 if (!is_main_window_) {
570 Send(new ShellViewHostMsg_TestFinishedInSecondaryWindow(routing_id()));
571 return;
573 test_runner::WebTestInterfaces* interfaces =
574 LayoutTestRenderProcessObserver::GetInstance()->test_interfaces();
575 interfaces->SetTestIsRunning(false);
576 if (interfaces->TestRunner()->ShouldDumpBackForwardList()) {
577 SyncNavigationStateVisitor visitor;
578 RenderView::ForEach(&visitor);
579 Send(new ShellViewHostMsg_CaptureSessionHistory(routing_id()));
580 } else {
581 CaptureDump();
585 void BlinkTestRunner::CloseRemainingWindows() {
586 NavigateAwayVisitor visitor(render_view());
587 RenderView::ForEach(&visitor);
588 Send(new ShellViewHostMsg_CloseRemainingWindows(routing_id()));
591 void BlinkTestRunner::DeleteAllCookies() {
592 Send(new LayoutTestHostMsg_DeleteAllCookies(routing_id()));
595 int BlinkTestRunner::NavigationEntryCount() {
596 return GetLocalSessionHistoryLength(render_view());
599 void BlinkTestRunner::GoToOffset(int offset) {
600 Send(new ShellViewHostMsg_GoToOffset(routing_id(), offset));
603 void BlinkTestRunner::Reload() {
604 Send(new ShellViewHostMsg_Reload(routing_id()));
607 void BlinkTestRunner::LoadURLForFrame(const WebURL& url,
608 const std::string& frame_name) {
609 Send(new ShellViewHostMsg_LoadURLForFrame(
610 routing_id(), url, frame_name));
613 bool BlinkTestRunner::AllowExternalPages() {
614 return test_config_.allow_external_pages;
617 std::string BlinkTestRunner::DumpHistoryForWindow(
618 test_runner::WebTestProxyBase* proxy) {
619 size_t pos = 0;
620 std::vector<int>::iterator id;
621 for (id = routing_ids_.begin(); id != routing_ids_.end(); ++id, ++pos) {
622 RenderView* render_view = RenderView::FromRoutingID(*id);
623 if (!render_view) {
624 NOTREACHED();
625 continue;
627 if (BlinkTestRunner::Get(render_view)->proxy() == proxy)
628 break;
631 if (id == routing_ids_.end()) {
632 NOTREACHED();
633 return std::string();
635 return DumpBackForwardList(session_histories_[pos],
636 current_entry_indexes_[pos]);
639 void BlinkTestRunner::FetchManifest(
640 blink::WebView* view,
641 const GURL& url,
642 const base::Callback<void(const blink::WebURLResponse& response,
643 const std::string& data)>& callback) {
644 ::content::FetchManifest(view, url, callback);
647 void BlinkTestRunner::SetPermission(const std::string& name,
648 const std::string& value,
649 const GURL& origin,
650 const GURL& embedding_origin) {
651 content::PermissionStatus status;
652 if (value == "granted")
653 status = PERMISSION_STATUS_GRANTED;
654 else if (value == "prompt")
655 status = PERMISSION_STATUS_ASK;
656 else if (value == "denied")
657 status = PERMISSION_STATUS_DENIED;
658 else {
659 NOTREACHED();
660 status = PERMISSION_STATUS_DENIED;
663 Send(new LayoutTestHostMsg_SetPermission(
664 routing_id(), name, status, origin, embedding_origin));
667 void BlinkTestRunner::ResetPermissions() {
668 Send(new LayoutTestHostMsg_ResetPermissions(routing_id()));
671 cc::SharedBitmapManager* BlinkTestRunner::GetSharedBitmapManager() {
672 return RenderThread::Get()->GetSharedBitmapManager();
675 void BlinkTestRunner::DispatchBeforeInstallPromptEvent(
676 int request_id,
677 const std::vector<std::string>& event_platforms,
678 const base::Callback<void(bool)>& callback) {
679 // Send the event to the frame.
680 blink::WebAppBannerPromptReply reply;
681 std::vector<blink::WebString> blink_web_strings;
682 for (const auto& platform : event_platforms)
683 blink_web_strings.push_back(blink::WebString::fromUTF8(platform));
684 blink::WebVector<blink::WebString> blink_event_platforms(blink_web_strings);
686 WebLocalFrame* main_frame =
687 render_view()->GetWebView()->mainFrame()->toWebLocalFrame();
688 main_frame->willShowInstallBannerPrompt(request_id, blink_event_platforms,
689 &reply);
691 callback.Run(reply == blink::WebAppBannerPromptReply::Cancel);
694 void BlinkTestRunner::ResolveBeforeInstallPromptPromise(
695 int request_id, const std::string& platform) {
696 test_runner::WebTestInterfaces* interfaces =
697 LayoutTestRenderProcessObserver::GetInstance()->test_interfaces();
698 if (interfaces->GetAppBannerClient())
699 interfaces->GetAppBannerClient()->ResolvePromise(request_id, platform);
702 blink::WebPlugin* BlinkTestRunner::CreatePluginPlaceholder(
703 blink::WebLocalFrame* frame, const blink::WebPluginParams& params) {
704 if (params.mimeType != "application/x-plugin-placeholder-test")
705 return nullptr;
707 plugins::PluginPlaceholder* placeholder =
708 new plugins::PluginPlaceholder(render_view()->GetMainRenderFrame(), frame,
709 params, "<div>Test content</div>");
710 return placeholder->plugin();
713 void BlinkTestRunner::OnWebTestProxyBaseDestroy(
714 test_runner::WebTestProxyBase* proxy) {
717 // RenderViewObserver --------------------------------------------------------
719 void BlinkTestRunner::DidClearWindowObject(WebLocalFrame* frame) {
720 WebTestingSupport::injectInternalsObject(frame);
721 LayoutTestRenderProcessObserver::GetInstance()->test_interfaces()->BindTo(
722 frame);
723 GCController::Install(frame);
726 bool BlinkTestRunner::OnMessageReceived(const IPC::Message& message) {
727 bool handled = true;
728 IPC_BEGIN_MESSAGE_MAP(BlinkTestRunner, message)
729 IPC_MESSAGE_HANDLER(ShellViewMsg_SetTestConfiguration,
730 OnSetTestConfiguration)
731 IPC_MESSAGE_HANDLER(ShellViewMsg_SessionHistory, OnSessionHistory)
732 IPC_MESSAGE_HANDLER(ShellViewMsg_Reset, OnReset)
733 IPC_MESSAGE_HANDLER(ShellViewMsg_NotifyDone, OnNotifyDone)
734 IPC_MESSAGE_HANDLER(ShellViewMsg_TryLeakDetection, OnTryLeakDetection)
735 IPC_MESSAGE_UNHANDLED(handled = false)
736 IPC_END_MESSAGE_MAP()
738 return handled;
741 void BlinkTestRunner::Navigate(const GURL& url) {
742 focus_on_next_commit_ = true;
743 if (!is_main_window_ &&
744 LayoutTestRenderProcessObserver::GetInstance()->main_test_runner() ==
745 this) {
746 test_runner::WebTestInterfaces* interfaces =
747 LayoutTestRenderProcessObserver::GetInstance()->test_interfaces();
748 interfaces->SetTestIsRunning(true);
749 interfaces->ConfigureForTestWithURL(GURL(), false);
750 ForceResizeRenderView(render_view(), WebSize(800, 600));
754 void BlinkTestRunner::DidCommitProvisionalLoad(WebLocalFrame* frame,
755 bool is_new_navigation) {
756 if (!focus_on_next_commit_)
757 return;
758 focus_on_next_commit_ = false;
759 render_view()->GetWebView()->setFocusedFrame(frame);
762 void BlinkTestRunner::DidFailProvisionalLoad(WebLocalFrame* frame,
763 const WebURLError& error) {
764 focus_on_next_commit_ = false;
767 // Public methods - -----------------------------------------------------------
769 void BlinkTestRunner::Reset() {
770 // The proxy_ is always non-NULL, it is set right after construction.
771 proxy_->set_widget(render_view()->GetWebView());
772 proxy_->Reset();
773 prefs_.Reset();
774 routing_ids_.clear();
775 session_histories_.clear();
776 current_entry_indexes_.clear();
778 render_view()->ClearEditCommands();
779 if (render_view()->GetWebView()->mainFrame()->isWebLocalFrame())
780 render_view()->GetWebView()->mainFrame()->setName(WebString());
781 render_view()->GetWebView()->mainFrame()->clearOpener();
783 // Resetting the internals object also overrides the WebPreferences, so we
784 // have to sync them to WebKit again.
785 if (render_view()->GetWebView()->mainFrame()->isWebLocalFrame()) {
786 WebTestingSupport::resetInternalsObject(
787 render_view()->GetWebView()->mainFrame()->toWebLocalFrame());
788 render_view()->SetWebkitPreferences(render_view()->GetWebkitPreferences());
792 // Private methods -----------------------------------------------------------
794 void BlinkTestRunner::CaptureDump() {
795 test_runner::WebTestInterfaces* interfaces =
796 LayoutTestRenderProcessObserver::GetInstance()->test_interfaces();
797 TRACE_EVENT0("shell", "BlinkTestRunner::CaptureDump");
799 if (interfaces->TestRunner()->ShouldDumpAsAudio()) {
800 std::vector<unsigned char> vector_data;
801 interfaces->TestRunner()->GetAudioData(&vector_data);
802 Send(new ShellViewHostMsg_AudioDump(routing_id(), vector_data));
803 } else {
804 const base::CommandLine& command_line =
805 *base::CommandLine::ForCurrentProcess();
806 Send(new ShellViewHostMsg_TextDump(
807 routing_id(), proxy()->CaptureTree(
808 false, command_line.HasSwitch(switches::kDumpLineBoxTrees))));
810 if (test_config_.enable_pixel_dumping &&
811 interfaces->TestRunner()->ShouldGeneratePixelResults()) {
812 CHECK(render_view()->GetWebView()->isAcceleratedCompositingActive());
813 proxy()->CapturePixelsAsync(base::Bind(
814 &BlinkTestRunner::CaptureDumpPixels, base::Unretained(this)));
815 return;
818 #ifndef NDEBUG
819 // Force a layout/paint by the end of the test to ensure test coverage of
820 // incremental painting.
821 proxy()->LayoutAndPaintAsyncThen(base::Bind(
822 &BlinkTestRunner::CaptureDumpComplete, base::Unretained(this)));
823 return;
824 #else
825 CaptureDumpComplete();
826 #endif
829 void BlinkTestRunner::CaptureDumpPixels(const SkBitmap& snapshot) {
830 DCHECK_NE(0, snapshot.info().width());
831 DCHECK_NE(0, snapshot.info().height());
833 SkAutoLockPixels snapshot_lock(snapshot);
834 // The snapshot arrives from the GPU process via shared memory. Because MSan
835 // can't track initializedness across processes, we must assure it that the
836 // pixels are in fact initialized.
837 MSAN_UNPOISON(snapshot.getPixels(), snapshot.getSize());
838 base::MD5Digest digest;
839 base::MD5Sum(snapshot.getPixels(), snapshot.getSize(), &digest);
840 std::string actual_pixel_hash = base::MD5DigestToBase16(digest);
842 if (actual_pixel_hash == test_config_.expected_pixel_hash) {
843 SkBitmap empty_image;
844 Send(new ShellViewHostMsg_ImageDump(
845 routing_id(), actual_pixel_hash, empty_image));
846 } else {
847 Send(new ShellViewHostMsg_ImageDump(
848 routing_id(), actual_pixel_hash, snapshot));
851 CaptureDumpComplete();
854 void BlinkTestRunner::CaptureDumpComplete() {
855 render_view()->GetWebView()->mainFrame()->stopLoading();
857 base::ThreadTaskRunnerHandle::Get()->PostTask(
858 FROM_HERE, base::Bind(base::IgnoreResult(&BlinkTestRunner::Send),
859 base::Unretained(this),
860 new ShellViewHostMsg_TestFinished(routing_id())));
863 void BlinkTestRunner::OnSetTestConfiguration(
864 const ShellTestConfiguration& params) {
865 test_config_ = params;
866 is_main_window_ = true;
868 ForceResizeRenderView(
869 render_view(),
870 WebSize(params.initial_size.width(), params.initial_size.height()));
871 SetFocus(proxy_, true);
873 test_runner::WebTestInterfaces* interfaces =
874 LayoutTestRenderProcessObserver::GetInstance()->test_interfaces();
875 interfaces->SetTestIsRunning(true);
876 interfaces->ConfigureForTestWithURL(params.test_url,
877 params.enable_pixel_dumping);
880 void BlinkTestRunner::OnSessionHistory(
881 const std::vector<int>& routing_ids,
882 const std::vector<std::vector<PageState>>& session_histories,
883 const std::vector<unsigned>& current_entry_indexes) {
884 routing_ids_ = routing_ids;
885 session_histories_ = session_histories;
886 current_entry_indexes_ = current_entry_indexes;
887 CaptureDump();
890 void BlinkTestRunner::OnReset() {
891 LayoutTestRenderProcessObserver::GetInstance()->test_interfaces()->ResetAll();
892 Reset();
893 // Navigating to about:blank will make sure that no new loads are initiated
894 // by the renderer.
895 render_view()->GetWebView()->mainFrame()->loadRequest(
896 WebURLRequest(GURL(url::kAboutBlankURL)));
897 Send(new ShellViewHostMsg_ResetDone(routing_id()));
900 void BlinkTestRunner::OnNotifyDone() {
901 render_view()->GetWebView()->mainFrame()->executeScript(
902 WebScriptSource(WebString::fromUTF8("testRunner.notifyDone();")));
905 void BlinkTestRunner::OnTryLeakDetection() {
906 WebLocalFrame* main_frame =
907 render_view()->GetWebView()->mainFrame()->toWebLocalFrame();
908 DCHECK_EQ(GURL(url::kAboutBlankURL), GURL(main_frame->document().url()));
909 DCHECK(!main_frame->isLoading());
911 leak_detector_->TryLeakDetection(main_frame);
914 void BlinkTestRunner::ReportLeakDetectionResult(
915 const LeakDetectionResult& report) {
916 Send(new ShellViewHostMsg_LeakDetectionDone(routing_id(), report));
919 } // namespace content