| Index: content/public/test/browser_test_utils.cc
|
| diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc
|
| index b88b61ffe449bd5af1a018dee4025a59c1ab66fe..725456c384ee70162e673e3cfe0556da395ca275 100644
|
| --- a/content/public/test/browser_test_utils.cc
|
| +++ b/content/public/test/browser_test_utils.cc
|
| @@ -12,6 +12,7 @@
|
| #include "base/bind.h"
|
| #include "base/bind_helpers.h"
|
| #include "base/command_line.h"
|
| +#include "base/guid.h"
|
| #include "base/json/json_reader.h"
|
| #include "base/macros.h"
|
| #include "base/process/kill.h"
|
| @@ -20,6 +21,7 @@
|
| #include "base/strings/pattern.h"
|
| #include "base/strings/string_number_conversions.h"
|
| #include "base/strings/string_piece.h"
|
| +#include "base/strings/stringprintf.h"
|
| #include "base/strings/utf_string_conversions.h"
|
| #include "base/synchronization/waitable_event.h"
|
| #include "base/test/test_timeouts.h"
|
| @@ -175,6 +177,36 @@ bool ExecuteScriptHelper(RenderFrameHost* render_frame_host,
|
| return true;
|
| }
|
|
|
| +bool ExecuteScriptWithUserGestureControl(RenderFrameHost* frame,
|
| + const std::string& script,
|
| + bool user_gesture) {
|
| + // TODO(lukasza): ExecuteScript should just call
|
| + // ExecuteJavaScriptWithUserGestureForTests and avoid modifying the original
|
| + // script (and at that point we should merge it with and remove
|
| + // ExecuteScriptAsync). This is difficult to change, because many tests
|
| + // depend on the message loop pumping done by ExecuteScriptHelper below (this
|
| + // is fragile - these tests should wait on a more specific thing instead).
|
| +
|
| + std::string expected_response = "ExecuteScript-" + base::GenerateGUID();
|
| + std::string new_script = base::StringPrintf(
|
| + R"( %s; // Original script.
|
| + window.domAutomationController.send('%s'); )",
|
| + script.c_str(), expected_response.c_str());
|
| +
|
| + std::unique_ptr<base::Value> value;
|
| + if (!ExecuteScriptHelper(frame, new_script, user_gesture, &value) ||
|
| + !value.get()) {
|
| + return false;
|
| + }
|
| +
|
| + DCHECK_EQ(base::Value::Type::STRING, value->GetType());
|
| + std::string actual_response;
|
| + if (value->GetAsString(&actual_response))
|
| + DCHECK_EQ(expected_response, actual_response);
|
| +
|
| + return true;
|
| +}
|
| +
|
| // Specifying a prototype so that we can add the WARN_UNUSED_RESULT attribute.
|
| bool ExecuteScriptInIsolatedWorldHelper(RenderFrameHost* render_frame_host,
|
| const int world_id,
|
| @@ -414,19 +446,18 @@ void AppendGzippedResource(const base::RefCountedMemory& encoded,
|
| //
|
| // Returns has-video-input-device to the test if there is a webcam available,
|
| // no-video-input-devices otherwise.
|
| -const char kHasVideoInputDeviceOnSystem[] =
|
| - "(function() {"
|
| - "navigator.mediaDevices.enumerateDevices()"
|
| - ".then(function(devices) {"
|
| - "devices.forEach(function(device) {"
|
| - "if (device.kind == 'videoinput') {"
|
| - "window.domAutomationController.send('has-video-input-device');"
|
| - "return;"
|
| - "}"
|
| - "});"
|
| - "window.domAutomationController.send('no-video-input-devices');"
|
| - "});"
|
| - "})()";
|
| +const char kHasVideoInputDeviceOnSystem[] = R"(
|
| + (function() {
|
| + navigator.mediaDevices.enumerateDevices()
|
| + .then(function(devices) {
|
| + if (devices.some((device) => device.kind == 'videoinput')) {
|
| + window.domAutomationController.send('has-video-input-device');
|
| + } else {
|
| + window.domAutomationController.send('no-video-input-devices');
|
| + }
|
| + });
|
| + })()
|
| +)";
|
|
|
| const char kHasVideoInputDevice[] = "has-video-input-device";
|
|
|
| @@ -817,17 +848,20 @@ RenderFrameHost* ConvertToRenderFrameHost(RenderFrameHost* render_frame_host) {
|
|
|
| bool ExecuteScript(const ToRenderFrameHost& adapter,
|
| const std::string& script) {
|
| - std::string new_script =
|
| - script + ";window.domAutomationController.send(0);";
|
| - return ExecuteScriptHelper(adapter.render_frame_host(), new_script, true,
|
| - nullptr);
|
| + return ExecuteScriptWithUserGestureControl(adapter.render_frame_host(),
|
| + script, true);
|
| }
|
|
|
| bool ExecuteScriptWithoutUserGesture(const ToRenderFrameHost& adapter,
|
| const std::string& script) {
|
| - std::string new_script = script + ";window.domAutomationController.send(0);";
|
| - return ExecuteScriptHelper(adapter.render_frame_host(), new_script, false,
|
| - nullptr);
|
| + return ExecuteScriptWithUserGestureControl(adapter.render_frame_host(),
|
| + script, false);
|
| +}
|
| +
|
| +void ExecuteScriptAsync(const ToRenderFrameHost& adapter,
|
| + const std::string& script) {
|
| + adapter.render_frame_host()->ExecuteJavaScriptWithUserGestureForTests(
|
| + base::UTF8ToUTF16(script));
|
| }
|
|
|
| bool ExecuteScriptAndExtractDouble(const ToRenderFrameHost& adapter,
|
| @@ -1000,12 +1034,10 @@ bool ExecuteWebUIResourceTest(WebContents* web_contents,
|
|
|
| script.append("\n");
|
| }
|
| - if (!ExecuteScript(web_contents, script))
|
| - return false;
|
| + ExecuteScriptAsync(web_contents, script);
|
|
|
| DOMMessageQueue message_queue;
|
| - if (!ExecuteScript(web_contents, "runTests()"))
|
| - return false;
|
| + ExecuteScriptAsync(web_contents, "runTests()");
|
|
|
| std::string message;
|
| do {
|
| @@ -1493,7 +1525,7 @@ void DOMMessageQueue::Observe(int type,
|
| const NotificationDetails& details) {
|
| Details<std::string> dom_op_result(details);
|
| message_queue_.push(*dom_op_result.ptr());
|
| - if (message_loop_runner_.get())
|
| + if (message_loop_runner_)
|
| message_loop_runner_->Quit();
|
| }
|
|
|
| @@ -1504,6 +1536,7 @@ void DOMMessageQueue::RenderProcessGone(base::TerminationStatus status) {
|
| case base::TERMINATION_STATUS_STILL_RUNNING:
|
| break;
|
| default:
|
| + renderer_crashed_ = true;
|
| if (message_loop_runner_.get())
|
| message_loop_runner_->Quit();
|
| break;
|
| @@ -1516,7 +1549,7 @@ void DOMMessageQueue::ClearQueue() {
|
|
|
| bool DOMMessageQueue::WaitForMessage(std::string* message) {
|
| DCHECK(message);
|
| - if (message_queue_.empty()) {
|
| + if (!renderer_crashed_ && message_queue_.empty()) {
|
| // This will be quit when a new message comes in.
|
| message_loop_runner_ =
|
| new MessageLoopRunner(MessageLoopRunner::QuitMode::IMMEDIATE);
|
| @@ -1527,7 +1560,7 @@ bool DOMMessageQueue::WaitForMessage(std::string* message) {
|
|
|
| bool DOMMessageQueue::PopMessage(std::string* message) {
|
| DCHECK(message);
|
| - if (message_queue_.empty())
|
| + if (renderer_crashed_ || message_queue_.empty())
|
| return false;
|
| *message = message_queue_.front();
|
| message_queue_.pop();
|
|
|