Make Blink's unit tests closer to real world

... by replicating async navigation logic from RenderFrameImpl.

Some tests have to change to account for new asynchrony.

Bug: 855189
Change-Id: Ib92d8f4a9f6afc6527e9db7fc03765e0f6138e76
Reviewed-on: https://chromium-review.googlesource.com/c/1396399
Reviewed-by: Nate Chapin <japhet@chromium.org>
Commit-Queue: Dmitry Gozman <dgozman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#620960}
diff --git a/third_party/blink/renderer/core/exported/web_frame_test.cc b/third_party/blink/renderer/core/exported/web_frame_test.cc
index 01d74d2b..6dd3f7f 100644
--- a/third_party/blink/renderer/core/exported/web_frame_test.cc
+++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -7724,6 +7724,9 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "push_state.html", &client);
 
+  // Wait for push state navigation to complete.
+  frame_test_helpers::PumpPendingRequestsForFrameToLoad(
+      web_view_helper.LocalMainFrame());
   EXPECT_EQ(client.StartLoadingCount(), 2);
   EXPECT_EQ(client.StopLoadingCount(), 2);
 }
@@ -10005,6 +10008,8 @@
   RegisterMockedHttpURLLoad("send_beacon.html");
   RegisterMockedHttpURLLoad("reload_post.html");  // url param to sendBeacon()
   frame_test_helpers::LoadFrame(local_frame, base_url_ + "send_beacon.html");
+  // Wait for the post.
+  frame_test_helpers::PumpPendingRequestsForFrameToLoad(local_frame);
 }
 
 TEST_F(WebFrameTest, SiteForCookiesFromChildWithRemoteMainFrame) {
diff --git a/third_party/blink/renderer/core/frame/ad_tracker_test.cc b/third_party/blink/renderer/core/frame/ad_tracker_test.cc
index bb5bf78..617ca7c1 100644
--- a/third_party/blink/renderer/core/frame/ad_tracker_test.cc
+++ b/third_party/blink/renderer/core/frame/ad_tracker_test.cc
@@ -366,7 +366,7 @@
   const char kAdUrl[] = "https://example.com/ad_script.js";
   const char kVanillaUrl[] = "https://example.com/vanilla_page.html";
   SimSubresourceRequest ad_resource(kAdUrl, "text/javascript");
-  SimSubresourceRequest vanilla_page(kVanillaUrl, "text/html");
+  SimRequest vanilla_page(kVanillaUrl, "text/html");
 
   ad_tracker_->SetAdSuffix("ad_script.js");
 
diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.cc b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
index d9d6947f..edb5a03 100644
--- a/third_party/blink/renderer/core/frame/frame_test_helpers.cc
+++ b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
@@ -49,6 +49,7 @@
 #include "third_party/blink/public/web/web_view_client.h"
 #include "third_party/blink/renderer/core/exported/web_remote_frame_impl.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
+#include "third_party/blink/renderer/core/loader/document_loader.h"
 #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
 #include "third_party/blink/renderer/core/testing/fake_web_plugin.h"
 #include "third_party/blink/renderer/platform/scheduler/public/thread.h"
@@ -104,18 +105,21 @@
 
 }  // namespace
 
-void LoadFrame(WebLocalFrame* frame, const std::string& url) {
+void LoadFrameDontWait(WebLocalFrame* frame, const WebURL& url) {
   WebLocalFrameImpl* impl = ToWebLocalFrameImpl(frame);
-  WebURL web_url(url_test_helpers::ToKURL(url));
-  if (web_url.ProtocolIs("javascript")) {
-    impl->LoadJavaScriptURL(web_url);
+  if (url.ProtocolIs("javascript")) {
+    impl->LoadJavaScriptURL(url);
   } else {
     auto params = std::make_unique<WebNavigationParams>();
-    params->request = WebURLRequest(web_url);
+    params->request = WebURLRequest(url);
     params->navigation_timings.navigation_start = base::TimeTicks::Now();
     params->navigation_timings.fetch_start = base::TimeTicks::Now();
     impl->CommitNavigation(std::move(params), nullptr /* extra_data */);
   }
+}
+
+void LoadFrame(WebLocalFrame* frame, const std::string& url) {
+  LoadFrameDontWait(frame, url_test_helpers::ToKURL(url));
   PumpPendingRequestsForFrameToLoad(frame);
 }
 
@@ -444,7 +448,8 @@
 
 TestWebFrameClient::TestWebFrameClient()
     : interface_provider_(new service_manager::InterfaceProvider()),
-      effective_connection_type_(WebEffectiveConnectionType::kTypeUnknown) {}
+      effective_connection_type_(WebEffectiveConnectionType::kTypeUnknown),
+      weak_factory_(this) {}
 
 void TestWebFrameClient::Bind(WebLocalFrame* frame,
                               std::unique_ptr<TestWebFrameClient> self_owned) {
@@ -494,8 +499,29 @@
 
 void TestWebFrameClient::BeginNavigation(
     std::unique_ptr<WebNavigationInfo> info) {
-  frame_->CommitNavigation(WebNavigationParams::CreateFromInfo(*info),
-                           nullptr /* extra_data */);
+  navigation_callback_.Cancel();
+  if (DocumentLoader::WillLoadUrlAsEmpty(info->url_request.Url()) ||
+      !frame_->HasCommittedFirstRealLoad()) {
+    CommitNavigation(std::move(info));
+    return;
+  }
+
+  if (!frame_->CreatePlaceholderDocumentLoader(*info, nullptr /* extra_data */))
+    return;
+
+  navigation_callback_.Reset(
+      base::BindOnce(&TestWebFrameClient::CommitNavigation,
+                     weak_factory_.GetWeakPtr(), std::move(info)));
+  frame_->GetTaskRunner(blink::TaskType::kInternalLoading)
+      ->PostTask(FROM_HERE, navigation_callback_.callback());
+}
+
+void TestWebFrameClient::CommitNavigation(
+    std::unique_ptr<WebNavigationInfo> info) {
+  if (!frame_)
+    return;
+  auto params = WebNavigationParams::CreateFromInfo(*info);
+  frame_->CommitNavigation(std::move(params), nullptr /* extra_data */);
 }
 
 WebEffectiveConnectionType TestWebFrameClient::GetEffectiveConnectionType() {
diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.h b/third_party/blink/renderer/core/frame/frame_test_helpers.h
index 48694ea8..5391b0e 100644
--- a/third_party/blink/renderer/core/frame/frame_test_helpers.h
+++ b/third_party/blink/renderer/core/frame/frame_test_helpers.h
@@ -37,6 +37,7 @@
 #include <string>
 
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
 #include "cc/test/test_task_graph_runner.h"
 #include "content/renderer/compositor/layer_tree_view.h"
 #include "content/test/stub_layer_tree_view_delegate.h"
@@ -96,9 +97,10 @@
 class TestWebViewClient;
 class WebViewHelper;
 
-// Loads a url into the specified WebLocalFrame for testing purposes. Pumps any
-// pending resource requests, as well as waiting for the threaded parser to
-// finish, before returning.
+// Loads a url into the specified WebLocalFrame for testing purposes.
+void LoadFrameDontWait(WebLocalFrame*, const WebURL& url);
+// Same as above, but also pumps any pending resource requests,
+// as well as waiting for the threaded parser to finish, before returning.
 void LoadFrame(WebLocalFrame*, const std::string& url);
 // Same as above, but for WebLocalFrame::LoadHTMLString().
 void LoadHTMLString(WebLocalFrame*,
@@ -375,6 +377,8 @@
   WebPlugin* CreatePlugin(const WebPluginParams& params) override;
 
  private:
+  void CommitNavigation(std::unique_ptr<WebNavigationInfo>);
+
   static int loads_in_progress_;
 
   // If set to a non-null value, self-deletes on frame detach.
@@ -388,9 +392,12 @@
   // Bind().
   WebNavigationControl* frame_ = nullptr;
 
+  base::CancelableOnceCallback<void()> navigation_callback_;
   std::unique_ptr<WebWidgetClient> owned_widget_client_;
   WebEffectiveConnectionType effective_connection_type_;
   Vector<String> console_messages_;
+
+  base::WeakPtrFactory<TestWebFrameClient> weak_factory_;
 };
 
 // Minimal implementation of WebRemoteFrameClient needed for unit tests that
diff --git a/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc b/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc
index 8f03120..d457d5a 100644
--- a/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc
+++ b/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc
@@ -2256,9 +2256,9 @@
   // Ensure that we remain the root scroller even though there's no layout in
   // the parent.
   SimRequest child_request2("https://example.com/child-next.html", "text/html");
-  WebURLRequest request(KURL("https://example.com/child-next.html"));
-  WebView().MainFrameImpl()->FirstChild()->ToWebLocalFrame()->StartNavigation(
-      request);
+  frame_test_helpers::LoadFrameDontWait(
+      WebView().MainFrameImpl()->FirstChild()->ToWebLocalFrame(),
+      KURL("https://example.com/child-next.html"));
 
   child_request2.Write(R"HTML(
         <!DOCTYPE html>
diff --git a/third_party/blink/renderer/core/testing/sim/sim_network.cc b/third_party/blink/renderer/core/testing/sim/sim_network.cc
index 5980e819..22767b3 100644
--- a/third_party/blink/renderer/core/testing/sim/sim_network.cc
+++ b/third_party/blink/renderer/core/testing/sim/sim_network.cc
@@ -87,11 +87,17 @@
 }
 
 void SimNetwork::AddRequest(SimRequestBase& request) {
-  requests_.insert(request.url_, &request);
+  requests_.insert(request.url_.GetString(), &request);
+  WebURLResponse response(request.url_);
+  response.SetMIMEType(request.mime_type_);
+  response.SetHTTPStatusCode(200);
+  Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(request.url_,
+                                                              response, "");
 }
 
 void SimNetwork::RemoveRequest(SimRequestBase& request) {
   requests_.erase(request.url_);
+  Platform::Current()->GetURLLoaderMockFactory()->UnregisterURL(request.url_);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/testing/sim/sim_request.cc b/third_party/blink/renderer/core/testing/sim/sim_request.cc
index bed57b7..4d71825 100644
--- a/third_party/blink/renderer/core/testing/sim/sim_request.cc
+++ b/third_party/blink/renderer/core/testing/sim/sim_request.cc
@@ -4,9 +4,7 @@
 
 #include "third_party/blink/renderer/core/testing/sim/sim_request.h"
 
-#include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_url_loader_client.h"
-#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
 #include "third_party/blink/renderer/core/testing/sim/sim_network.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
 
@@ -16,16 +14,11 @@
                                String mime_type,
                                bool start_immediately)
     : url_(url),
+      mime_type_(mime_type),
       start_immediately_(start_immediately),
       started_(false),
       client_(nullptr),
       total_encoded_data_length_(0) {
-  KURL full_url(url);
-  WebURLResponse response(full_url);
-  response.SetMIMEType(mime_type);
-  response.SetHTTPStatusCode(200);
-  Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(full_url,
-                                                              response, "");
   SimNetwork::Current().AddRequest(*this);
 }
 
@@ -110,7 +103,6 @@
 void SimRequestBase::Reset() {
   started_ = false;
   client_ = nullptr;
-  Platform::Current()->GetURLLoaderMockFactory()->UnregisterURL(KURL(url_));
   SimNetwork::Current().RemoveRequest(*this);
 }
 
diff --git a/third_party/blink/renderer/core/testing/sim/sim_request.h b/third_party/blink/renderer/core/testing/sim/sim_request.h
index 436d4e2..e757460 100644
--- a/third_party/blink/renderer/core/testing/sim/sim_request.h
+++ b/third_party/blink/renderer/core/testing/sim/sim_request.h
@@ -8,6 +8,7 @@
 #include "base/optional.h"
 #include "third_party/blink/public/platform/web_url_error.h"
 #include "third_party/blink/public/platform/web_url_response.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
@@ -49,7 +50,8 @@
   void DidReceiveResponse(WebURLLoaderClient*, const WebURLResponse&);
   void DidFail(const WebURLError&);
 
-  String url_;
+  KURL url_;
+  String mime_type_;
   bool start_immediately_;
   bool started_;
   WebURLResponse response_;
diff --git a/third_party/blink/renderer/core/testing/sim/sim_test.cc b/third_party/blink/renderer/core/testing/sim/sim_test.cc
index c2e09c7..3414e80 100644
--- a/third_party/blink/renderer/core/testing/sim/sim_test.cc
+++ b/third_party/blink/renderer/core/testing/sim/sim_test.cc
@@ -11,6 +11,7 @@
 #include "third_party/blink/renderer/core/exported/web_view_impl.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
+#include "third_party/blink/renderer/core/loader/document_loader.h"
 #include "third_party/blink/renderer/core/scroll/scrollbar_theme.h"
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
 #include "third_party/blink/renderer/platform/web_test_support.h"
@@ -61,11 +62,15 @@
   page_.SetPage(WebView().GetPage());
 }
 
-void SimTest::LoadURL(const String& url) {
-  auto navigation_params = std::make_unique<WebNavigationParams>();
-  navigation_params->request = WebURLRequest(KURL(url));
-  WebView().MainFrameImpl()->CommitNavigation(std::move(navigation_params),
-                                              nullptr /* extra_data */);
+void SimTest::LoadURL(const String& url_string) {
+  KURL url(url_string);
+  frame_test_helpers::LoadFrameDontWait(WebView().MainFrameImpl(), url);
+  if (DocumentLoader::WillLoadUrlAsEmpty(url) || url.ProtocolIsData()) {
+    // Empty documents and data urls are not using mocked out SimRequests,
+    // but instead load data directly.
+    frame_test_helpers::PumpPendingRequestsForFrameToLoad(
+        WebView().MainFrameImpl());
+  }
 }
 
 LocalDOMWindow& SimTest::Window() {
diff --git a/third_party/blink/renderer/core/workers/worker_thread_test.cc b/third_party/blink/renderer/core/workers/worker_thread_test.cc
index 8533d9ff..35c2fe1e 100644
--- a/third_party/blink/renderer/core/workers/worker_thread_test.cc
+++ b/third_party/blink/renderer/core/workers/worker_thread_test.cc
@@ -35,12 +35,12 @@
                        WaitableEvent* waitable_event) {
   EXPECT_TRUE(worker_thread->IsCurrentThread());
 
+  worker_thread->DebuggerTaskStarted();
   // Notify the main thread that the debugger task is waiting for the signal.
   PostCrossThreadTask(
       *worker_thread->GetParentExecutionContextTaskRunners()->Get(
           TaskType::kInternalTest),
       FROM_HERE, CrossThreadBind(&test::ExitRunLoop));
-  worker_thread->DebuggerTaskStarted();
   waitable_event->Wait();
   worker_thread->DebuggerTaskFinished();
 }