Add reconnect logic to URLLoaderFactoryBundle
This CL:
1. Allows |RenderFrameHostImpl| to push new |URLLoaderFactoryBundle|
to |RenderFrameImpl| after navigation so they can send updated
Network Service factories in case of crash.
2. Adds a 'content_browsertests' to verify XHR still works after
Network Service crash.
Bug: 780956
Change-Id: I4323648c7475ff311b1e3825aeb804265ad6899c
Reviewed-on: https://chromium-review.googlesource.com/858428
Reviewed-by: Kinuko Yasuda <[email protected]>
Reviewed-by: Ken Rockot <[email protected]>
Commit-Queue: Chong Zhang <[email protected]>
Cr-Commit-Position: refs/heads/master@{#531449}
diff --git a/content/browser/network_service_restart_browsertest.cc b/content/browser/network_service_restart_browsertest.cc
index a3b91fb..60cd70d6 100644
--- a/content/browser/network_service_restart_browsertest.cc
+++ b/content/browser/network_service_restart_browsertest.cc
@@ -4,18 +4,22 @@
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/url_loader_factory_getter.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_features.h"
+#include "content/public/common/content_switches.h"
#include "content/public/common/simple_url_loader.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/simple_url_loader_test_helper.h"
#include "content/shell/browser/shell.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/http_request.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "services/network/public/interfaces/network_service.mojom.h"
@@ -75,7 +79,11 @@
public:
NetworkServiceRestartBrowserTest() {
scoped_feature_list_.InitAndEnableFeature(features::kNetworkService);
+ }
+
+ void SetUpOnMainThread() override {
EXPECT_TRUE(embedded_test_server()->Start());
+ ContentBrowserTest::SetUpOnMainThread();
}
GURL GetTestURL() const {
@@ -188,4 +196,91 @@
NavigateToURL(shell(), embedded_test_server()->GetURL("/title2.html")));
}
+class NetworkServiceRestartDisableWebSecurityTest
+ : public NetworkServiceRestartBrowserTest {
+ public:
+ NetworkServiceRestartDisableWebSecurityTest() {}
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ // Simulate a compromised renderer, otherwise the cross-origin request is
+ // blocked.
+ command_line->AppendSwitch(switches::kDisableWebSecurity);
+ NetworkServiceRestartBrowserTest::SetUpCommandLine(command_line);
+ }
+
+ void SetUpOnMainThread() override {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ embedded_test_server()->RegisterRequestMonitor(base::BindRepeating(
+ &NetworkServiceRestartDisableWebSecurityTest::MonitorRequest,
+ base::Unretained(this)));
+ NetworkServiceRestartBrowserTest::SetUpOnMainThread();
+ }
+
+ RenderFrameHostImpl* main_frame() {
+ return static_cast<RenderFrameHostImpl*>(
+ shell()->web_contents()->GetMainFrame());
+ }
+
+ bool CheckCanLoadHttp(const std::string& relative_url) {
+ GURL test_url = embedded_test_server()->GetURL(relative_url);
+ std::string script(
+ "var xhr = new XMLHttpRequest();"
+ "xhr.open('GET', '");
+ script += test_url.spec() +
+ "', true);"
+ "xhr.onload = function (e) {"
+ " if (xhr.readyState === 4) {"
+ " window.domAutomationController.send(xhr.status === 200);"
+ " }"
+ "};"
+ "xhr.onerror = function () {"
+ " window.domAutomationController.send(false);"
+ "};"
+ "xhr.send(null)";
+ bool xhr_result = false;
+ // The JS call will fail if disallowed because the process will be killed.
+ bool execute_result =
+ ExecuteScriptAndExtractBool(shell(), script, &xhr_result);
+ return xhr_result && execute_result;
+ }
+
+ // Called by |embedded_test_server()|.
+ void MonitorRequest(const net::test_server::HttpRequest& request) {
+ last_request_relative_url_ = request.relative_url;
+ }
+
+ std::string last_request_relative_url() const {
+ return last_request_relative_url_;
+ }
+
+ private:
+ std::string last_request_relative_url_;
+
+ DISALLOW_COPY_AND_ASSIGN(NetworkServiceRestartDisableWebSecurityTest);
+};
+
+// Make sure basic XHR works after crash.
+IN_PROC_BROWSER_TEST_F(NetworkServiceRestartDisableWebSecurityTest, BasicXHR) {
+ StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
+ BrowserContext::GetDefaultStoragePartition(browser_context()));
+
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL("foo.com", "/echo")));
+ EXPECT_TRUE(CheckCanLoadHttp("/title1.html"));
+ EXPECT_EQ(last_request_relative_url(), "/title1.html");
+
+ // Crash the NetworkService process. Existing interfaces should receive error
+ // notifications at some point.
+ SimulateNetworkServiceCrash();
+ // Flush the interface to make sure the error notification was received.
+ partition->FlushNetworkInterfaceForTesting();
+ // Flush the interface to make sure the frame host has received error
+ // notification and the new URLLoaderFactoryBundle has been received by the
+ // frame.
+ main_frame()->FlushNetworkAndNavigationInterfacesForTesting();
+
+ EXPECT_TRUE(CheckCanLoadHttp("/title2.html"));
+ EXPECT_EQ(last_request_relative_url(), "/title2.html");
+}
+
} // namespace content