Initial (Prototype) Implementation of HTTPS image redirects.


Uses the ResourceRequest pointer in URLLoaderThrottle to redirect image
subresources on a page to a compressed version of the same resource.
This initial implementation will return a 200 when it successfully swaps
compressed version and a 307 when it needs to fall back onto the
original uncompressed resource.  It currently only handles those 2
scenarios.

This is a prototype implementation and is behind a flag.

Bug: 960513
Change-Id: I1d47e9f958a92e1ffb970d6852cdcab2acd9e698
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1606220
Commit-Queue: Sean Harrison <harrisonsean@chromium.org>
Reviewed-by: Tarun Bansal <tbansal@chromium.org>
Reviewed-by: John Abd-El-Malek <jam@chromium.org>
Reviewed-by: Robert Ogden <robertogden@chromium.org>
Cr-Commit-Position: refs/heads/master@{#661421}
diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn
index 2bcc4d5..cc5a38a2 100644
--- a/chrome/renderer/BUILD.gn
+++ b/chrome/renderer/BUILD.gn
@@ -100,6 +100,14 @@
     "sandbox_status_extension_android.h",
     "security_interstitials/security_interstitial_page_controller.cc",
     "security_interstitials/security_interstitial_page_controller.h",
+    "subresource_redirect/subresource_redirect_params.cc",
+    "subresource_redirect/subresource_redirect_params.h",
+    "subresource_redirect/subresource_redirect_switches.cc",
+    "subresource_redirect/subresource_redirect_switches.h",
+    "subresource_redirect/subresource_redirect_url_loader_throttle.cc",
+    "subresource_redirect/subresource_redirect_url_loader_throttle.h",
+    "subresource_redirect/subresource_redirect_util.cc",
+    "subresource_redirect/subresource_redirect_util.h",
     "supervised_user/supervised_user_error_page_controller.cc",
     "supervised_user/supervised_user_error_page_controller.h",
     "tts_dispatcher.cc",
diff --git a/chrome/renderer/subresource_redirect/DEPS b/chrome/renderer/subresource_redirect/DEPS
new file mode 100644
index 0000000..a7c8042
--- /dev/null
+++ b/chrome/renderer/subresource_redirect/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+components/base32",
+]
diff --git a/chrome/renderer/subresource_redirect/OWNERS b/chrome/renderer/subresource_redirect/OWNERS
new file mode 100644
index 0000000..b3958dc
--- /dev/null
+++ b/chrome/renderer/subresource_redirect/OWNERS
@@ -0,0 +1,4 @@
+tbansal@chromium.org
+robertogden@chromium.org
+
+# COMPONENT: Internals>Network>DataProxy
\ No newline at end of file
diff --git a/chrome/renderer/subresource_redirect/subresource_redirect_params.cc b/chrome/renderer/subresource_redirect/subresource_redirect_params.cc
new file mode 100644
index 0000000..f4e9602
--- /dev/null
+++ b/chrome/renderer/subresource_redirect/subresource_redirect_params.cc
@@ -0,0 +1,17 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/renderer/subresource_redirect/subresource_redirect_params.h"
+
+#include "base/command_line.h"
+#include "chrome/renderer/subresource_redirect/subresource_redirect_switches.h"
+
+namespace subresource_redirect {
+
+bool ShouldForceEnableSubresourceRedirect() {
+  return base::CommandLine::ForCurrentProcess()->HasSwitch(
+      subresource_redirect::kEnableSubresourceRedirect);
+}
+
+}  // namespace subresource_redirect
\ No newline at end of file
diff --git a/chrome/renderer/subresource_redirect/subresource_redirect_params.h b/chrome/renderer/subresource_redirect/subresource_redirect_params.h
new file mode 100644
index 0000000..c4012d7c
--- /dev/null
+++ b/chrome/renderer/subresource_redirect/subresource_redirect_params.h
@@ -0,0 +1,16 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_RENDERER_SUBRESOURCE_REDIRECT_SUBRESOURCE_REDIRECT_PARAMS_H_
+#define CHROME_RENDERER_SUBRESOURCE_REDIRECT_SUBRESOURCE_REDIRECT_PARAMS_H_
+
+namespace subresource_redirect {
+
+// Returns true if Subresource Redirect is forced to be enabled from the
+// command line.
+bool ShouldForceEnableSubresourceRedirect();
+
+}  // namespace subresource_redirect
+
+#endif  // CHROME_RENDERER_SUBRESOURCE_REDIRECT_SUBRESOURCE_REDIRECT_PARAMS_H_
\ No newline at end of file
diff --git a/chrome/renderer/subresource_redirect/subresource_redirect_switches.cc b/chrome/renderer/subresource_redirect/subresource_redirect_switches.cc
new file mode 100644
index 0000000..be27e68
--- /dev/null
+++ b/chrome/renderer/subresource_redirect/subresource_redirect_switches.cc
@@ -0,0 +1,13 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/renderer/subresource_redirect/subresource_redirect_switches.h"
+
+namespace subresource_redirect {
+
+// Feature flag to enable HTTPS subresource internal redirects to compressed
+// versions.
+const char kEnableSubresourceRedirect[] = "enable-subresource-redirect";
+
+}  // namespace subresource_redirect
\ No newline at end of file
diff --git a/chrome/renderer/subresource_redirect/subresource_redirect_switches.h b/chrome/renderer/subresource_redirect/subresource_redirect_switches.h
new file mode 100644
index 0000000..faf45c8
--- /dev/null
+++ b/chrome/renderer/subresource_redirect/subresource_redirect_switches.h
@@ -0,0 +1,17 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_RENDERER_SUBRESOURCE_REDIRECT_SUBRESOURCE_REDIRECT_SWITCHES_H_
+#define CHROME_RENDERER_SUBRESOURCE_REDIRECT_SUBRESOURCE_REDIRECT_SWITCHES_H_
+
+namespace subresource_redirect {
+
+// All switches in alphabetical order. The switches should be documented
+// alongside the definition of their values in the .cc file.
+
+extern const char kEnableSubresourceRedirect[];
+
+}  // namespace subresource_redirect
+
+#endif  // CHROME_RENDERER_SUBRESOURCE_REDIRECT_SUBRESOURCE_REDIRECT_SWITCHES_H_
\ No newline at end of file
diff --git a/chrome/renderer/subresource_redirect/subresource_redirect_url_loader_throttle.cc b/chrome/renderer/subresource_redirect/subresource_redirect_url_loader_throttle.cc
new file mode 100644
index 0000000..facef78
--- /dev/null
+++ b/chrome/renderer/subresource_redirect/subresource_redirect_url_loader_throttle.cc
@@ -0,0 +1,33 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/renderer/subresource_redirect/subresource_redirect_url_loader_throttle.h"
+
+#include "chrome/renderer/subresource_redirect/subresource_redirect_util.h"
+#include "content/public/common/resource_type.h"
+#include "url/gurl.h"
+
+namespace subresource_redirect {
+
+SubresourceRedirectURLLoaderThrottle::SubresourceRedirectURLLoaderThrottle() =
+    default;
+SubresourceRedirectURLLoaderThrottle::~SubresourceRedirectURLLoaderThrottle() =
+    default;
+
+void SubresourceRedirectURLLoaderThrottle::WillStartRequest(
+    network::ResourceRequest* request,
+    bool* defer) {
+  if (request->resource_type != static_cast<int>(content::ResourceType::kImage))
+    return;
+
+  if (!request->url.SchemeIs(url::kHttpsScheme))
+    return;
+
+  request->url = GetSubresourceURLForURL(request->url);
+  *defer = false;
+}
+
+void SubresourceRedirectURLLoaderThrottle::DetachFromCurrentSequence() {}
+
+}  // namespace subresource_redirect
\ No newline at end of file
diff --git a/chrome/renderer/subresource_redirect/subresource_redirect_url_loader_throttle.h b/chrome/renderer/subresource_redirect/subresource_redirect_url_loader_throttle.h
new file mode 100644
index 0000000..b9b12433
--- /dev/null
+++ b/chrome/renderer/subresource_redirect/subresource_redirect_url_loader_throttle.h
@@ -0,0 +1,27 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_RENDERER_SUBRESOURCE_REDIRECT_SUBRESOURCE_REDIRECT_URL_LOADER_THROTTLE_H_
+#define CHROME_RENDERER_SUBRESOURCE_REDIRECT_SUBRESOURCE_REDIRECT_URL_LOADER_THROTTLE_H_
+
+#include "content/public/common/url_loader_throttle.h"
+
+namespace subresource_redirect {
+
+// This class handles internal redirects for subresouces on HTTPS sites to
+// compressed versions of subresources.
+class SubresourceRedirectURLLoaderThrottle : public content::URLLoaderThrottle {
+ public:
+  SubresourceRedirectURLLoaderThrottle();
+  ~SubresourceRedirectURLLoaderThrottle() override;
+
+  // content::URLLoaderThrottle:
+  void WillStartRequest(network::ResourceRequest* request,
+                        bool* defer) override;
+  void DetachFromCurrentSequence() override;
+};
+
+}  // namespace subresource_redirect
+
+#endif  // CHROME_RENDERER_SUBRESOURCE_REDIRECT_SUBRESOURCE_REDIRECT_URL_LOADER_THROTTLE_H_
\ No newline at end of file
diff --git a/chrome/renderer/subresource_redirect/subresource_redirect_url_loader_throttle_unittest.cc b/chrome/renderer/subresource_redirect/subresource_redirect_url_loader_throttle_unittest.cc
new file mode 100644
index 0000000..810ea8d
--- /dev/null
+++ b/chrome/renderer/subresource_redirect/subresource_redirect_url_loader_throttle_unittest.cc
@@ -0,0 +1,71 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/renderer/subresource_redirect/subresource_redirect_url_loader_throttle.h"
+
+#include "chrome/renderer/subresource_redirect/subresource_redirect_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace subresource_redirect {
+
+namespace {
+
+TEST(SubresourceRedirectURLLoaderThrottleTest, TestGetSubresourceURL) {
+  struct TestCase {
+    GURL original_url;
+    int resource_type;
+    GURL redirected_subresource_url;
+  };
+
+  const TestCase kTestCases[]{
+      {
+          GURL("https://www.test.com/test.jpg"),
+          static_cast<int>(content::ResourceType::kImage),
+          GetSubresourceURLForURL(GURL("https://www.test.com/test.jpg")),
+      },
+      {
+          GURL("https://www.test.com/test.jpg#test"),
+          static_cast<int>(content::ResourceType::kImage),
+          GetSubresourceURLForURL(GURL("https://www.test.com/test.jpg#test")),
+      },
+      {
+          GURL("https://www.test.com/test.css"),
+          static_cast<int>(content::ResourceType::kStylesheet),
+          GURL("https://www.test.com/test.css"),
+      },
+      {
+          GURL("http://www.insecure.com/test.jpg"),
+          static_cast<int>(content::ResourceType::kImage),
+          GURL("http://www.insecure.com/test.jpg"),
+      },
+  };
+
+  for (const TestCase& test_case : kTestCases) {
+    network::ResourceRequest request;
+    request.url = test_case.original_url;
+    request.resource_type = test_case.resource_type;
+    bool defer = false;
+
+    SubresourceRedirectURLLoaderThrottle throttle;
+    throttle.WillStartRequest(&request, &defer);
+
+    EXPECT_FALSE(defer);
+    EXPECT_EQ(request.url, test_case.redirected_subresource_url);
+  }
+}
+
+TEST(SubresourceRedirectURLLoaderThrottleTest, DeferOverridenToFalse) {
+  SubresourceRedirectURLLoaderThrottle throttle;
+
+  network::ResourceRequest request;
+  request.url = GURL("https://www.test.com/test.jpg");
+  request.resource_type = static_cast<int>(content::ResourceType::kImage);
+  bool defer = true;
+
+  throttle.WillStartRequest(&request, &defer);
+  EXPECT_FALSE(defer);
+}
+
+}  // namespace
+}  // namespace subresource_redirect
\ No newline at end of file
diff --git a/chrome/renderer/subresource_redirect/subresource_redirect_util.cc b/chrome/renderer/subresource_redirect/subresource_redirect_util.cc
new file mode 100644
index 0000000..92316250
--- /dev/null
+++ b/chrome/renderer/subresource_redirect/subresource_redirect_util.cc
@@ -0,0 +1,51 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/renderer/subresource_redirect/subresource_redirect_util.h"
+
+#include <string>
+
+#include "base/strings/safe_sprintf.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "components/base32/base32.h"
+#include "crypto/sha2.h"
+#include "net/base/escape.h"
+#include "net/base/url_util.h"
+#include "url/gurl.h"
+
+namespace subresource_redirect {
+
+GURL GetSubresourceURLForURL(const GURL& original_url) {
+  DCHECK(original_url.is_valid());
+
+  std::string fragment;
+  if (original_url.has_ref()) {
+    fragment = "#" + original_url.ref();
+  }
+
+  std::string origin_hash = base::ToLowerASCII(base32::Base32Encode(
+      crypto::SHA256HashString(
+          original_url.scheme() + "://" + original_url.host() + ":" +
+          base::NumberToString(original_url.EffectiveIntPort())),
+      base32::Base32EncodePolicy::OMIT_PADDING));
+  GURL subresource_host("https://litepages.googlezip.net/");
+  // TODO(harrisonsean): Add experiment (x=) param.
+  GURL compressed_url(
+      subresource_host.scheme() + "://" + origin_hash + "." +
+      subresource_host.host() +
+      (subresource_host.has_port() ? (":" + subresource_host.port()) : "") +
+      "/sr?u=" +
+      // Strip out the fragment so that it is not sent to the server.
+      net::EscapeQueryParamValue(original_url.GetAsReferrer().spec(),
+                                 true /* use_plus */) +
+      "&t=image" + fragment);
+
+  DCHECK(compressed_url.is_valid());
+  DCHECK_EQ(subresource_host.scheme(), compressed_url.scheme());
+  return compressed_url;
+}
+
+}  // namespace subresource_redirect
\ No newline at end of file
diff --git a/chrome/renderer/subresource_redirect/subresource_redirect_util.h b/chrome/renderer/subresource_redirect/subresource_redirect_util.h
new file mode 100644
index 0000000..20ce031d
--- /dev/null
+++ b/chrome/renderer/subresource_redirect/subresource_redirect_util.h
@@ -0,0 +1,18 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_RENDERER_SUBRESOURCE_REDIRECT_SUBRESOURCE_REDIRECT_UTIL_H_
+#define CHROME_RENDERER_SUBRESOURCE_REDIRECT_SUBRESOURCE_REDIRECT_UTIL_H_
+
+#include "url/gurl.h"
+
+namespace subresource_redirect {
+
+// Gets the new URL for the compressed version of the image resource to enable
+// internal redirects.
+GURL GetSubresourceURLForURL(const GURL& original_url);
+
+}  // namespace subresource_redirect
+
+#endif  // CHROME_RENDERER_SUBRESOURCE_REDIRECT_SUBRESOURCE_REDIRECT_UTIL_H_
\ No newline at end of file
diff --git a/chrome/renderer/subresource_redirect/subresource_redirect_util_unittest.cc b/chrome/renderer/subresource_redirect/subresource_redirect_util_unittest.cc
new file mode 100644
index 0000000..e0df1d6
--- /dev/null
+++ b/chrome/renderer/subresource_redirect/subresource_redirect_util_unittest.cc
@@ -0,0 +1,74 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/renderer/subresource_redirect/subresource_redirect_util.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace subresource_redirect {
+
+TEST(SubresourceRedirectURL, ProperlyChangesURL) {
+  EXPECT_EQ(GetSubresourceURLForURL(GURL("https://www.test.com/test.jpg")),
+            GURL("https://"
+                 "jy6r5d5zc3n6juvq35nveinxzyuk4n4wndppyli5x5ycmrza36fa."
+                 "litepages.googlezip.net/"
+                 "sr?u=https%3A%2F%2Fwww.test.com%2Ftest.jpg&t=image"));
+}
+
+TEST(SubresourceRedirectURL, ProperlyHandlesFragment) {
+  EXPECT_EQ(GetSubresourceURLForURL(GURL("https://www.test.com/test.jpg#test")),
+            GURL("https://"
+                 "jy6r5d5zc3n6juvq35nveinxzyuk4n4wndppyli5x5ycmrza36fa."
+                 "litepages.googlezip.net/"
+                 "sr?u=https%3A%2F%2Fwww.test.com%2Ftest.jpg&t=image#test"));
+}
+
+TEST(SubresourceRedirectURL, ProperlyHandlesSetPort) {
+  EXPECT_EQ(GetSubresourceURLForURL(GURL("https://www.test.com:4444/test.jpg")),
+            GURL("https://flm6clfkawcjb2bw5cnrrcdf4fkoliileuljcc23lahdet75ouqq."
+                 "litepages.googlezip.net/sr?u=https%3A%2F%2Fwww.test."
+                 "com%3A4444%2Ftest.jpg&t=image"));
+}
+
+TEST(SubresourceRedirectURL, ProperlyHandlesQueryParams) {
+  EXPECT_EQ(GetSubresourceURLForURL(
+                GURL("https://www.test.com/test.jpg?color=yellow")),
+            GURL("https://"
+                 "jy6r5d5zc3n6juvq35nveinxzyuk4n4wndppyli5x5ycmrza36fa."
+                 "litepages.googlezip.net/"
+                 "sr?u=https%3A%2F%2Fwww.test.com%2Ftest.jpg%3Fcolor%3Dyellow&"
+                 "t=image"));
+}
+
+TEST(SubresourceRedirectURL, ProperlyHandlesMultipleQueryParams) {
+  EXPECT_EQ(GetSubresourceURLForURL(
+                GURL("https://www.test.com/test.jpg?color=yellow&name=test")),
+            GURL("https://"
+                 "jy6r5d5zc3n6juvq35nveinxzyuk4n4wndppyli5x5ycmrza36fa."
+                 "litepages.googlezip.net/"
+                 "sr?u=https%3A%2F%2Fwww.test.com%2Ftest.jpg%3Fcolor%3Dyellow%"
+                 "26name%3Dtest&t=image"));
+}
+
+TEST(SubresourceRedirectURL, ProperlyHandlesQueryParamsWithFragments) {
+  EXPECT_EQ(GetSubresourceURLForURL(
+                GURL("https://www.test.com/test.jpg?color=yellow#test")),
+            GURL("https://"
+                 "jy6r5d5zc3n6juvq35nveinxzyuk4n4wndppyli5x5ycmrza36fa."
+                 "litepages.googlezip.net/"
+                 "sr?u=https%3A%2F%2Fwww.test.com%2Ftest.jpg%3Fcolor%3Dyellow&"
+                 "t=image#test"));
+}
+
+// Currently redirects are not supported for HTTP subresources, but there is
+// potential to add them in the future.
+TEST(SubresourceRedirectURL, ProperlyChangesHTTPURL) {
+  EXPECT_EQ(
+      GetSubresourceURLForURL(GURL("http://www.test.com/test.jpg")),
+      GURL("https://bc6pgqmtr6nlicooao2zh77svcptncpwfolwlgbrop6gqnr6ck3q."
+           "litepages.googlezip.net/sr?u=http%3A%2F%2Fwww.test.com%2Ftest."
+           "jpg&t=image"));
+}
+
+}  // namespace subresource_redirect
\ No newline at end of file
diff --git a/chrome/renderer/url_loader_throttle_provider_impl.cc b/chrome/renderer/url_loader_throttle_provider_impl.cc
index a549b15..692d318 100644
--- a/chrome/renderer/url_loader_throttle_provider_impl.cc
+++ b/chrome/renderer/url_loader_throttle_provider_impl.cc
@@ -17,6 +17,8 @@
 #include "chrome/renderer/chrome_render_thread_observer.h"
 #include "chrome/renderer/prerender/prerender_dispatcher.h"
 #include "chrome/renderer/prerender/prerender_helper.h"
+#include "chrome/renderer/subresource_redirect/subresource_redirect_params.h"
+#include "chrome/renderer/subresource_redirect/subresource_redirect_url_loader_throttle.h"
 #include "components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_throttle_manager.h"
@@ -274,6 +276,12 @@
           ->chromeos_listener()));
 #endif  // defined(OS_CHROMEOS)
 
+  if (subresource_redirect::ShouldForceEnableSubresourceRedirect()) {
+    throttles.push_back(
+        std::make_unique<
+            subresource_redirect::SubresourceRedirectURLLoaderThrottle>());
+  }
+
   return throttles;
 }
 
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 2fd5b33..986fc8ef7 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -3055,6 +3055,8 @@
     "../renderer/page_load_metrics/page_timing_metrics_sender_unittest.cc",
     "../renderer/plugins/plugin_uma_unittest.cc",
     "../renderer/prerender/prerender_dispatcher_unittest.cc",
+    "../renderer/subresource_redirect/subresource_redirect_url_loader_throttle_unittest.cc",
+    "../renderer/subresource_redirect/subresource_redirect_util_unittest.cc",
     "../renderer/v8_unwinder_unittest.cc",
     "../test/base/chrome_render_view_test.cc",
     "../test/base/chrome_render_view_test.h",
diff --git a/content/common/throttling_url_loader.cc b/content/common/throttling_url_loader.cc
index de3cff5..a2c6e14 100644
--- a/content/common/throttling_url_loader.cc
+++ b/content/common/throttling_url_loader.cc
@@ -276,7 +276,13 @@
                                       int32_t intra_priority_value) {
   if (!url_loader_) {
     if (!loader_completed_) {
-      DCHECK_EQ(DEFERRED_START, deferred_stage_);
+      // Only check |deferred_stage_| if this resource has not been redirected
+      // by a throttle.
+      if (throttle_will_start_redirect_url_.is_empty() &&
+          throttle_will_redirect_redirect_url_.is_empty()) {
+        DCHECK_EQ(DEFERRED_START, deferred_stage_);
+      }
+
       priority_info_ =
           std::make_unique<PriorityInfo>(priority, intra_priority_value);
     }
diff --git a/content/public/common/url_loader_throttle.h b/content/public/common/url_loader_throttle.h
index 35fc259..f6a7094 100644
--- a/content/public/common/url_loader_throttle.h
+++ b/content/public/common/url_loader_throttle.h
@@ -113,8 +113,7 @@
   // asynchronously touching the pointer in defer case is not valid)
   // When |request->url| is modified it will make an internal redirect, which
   // might have some side-effects: drop upload streams data might be dropped,
-  // redirect count may be reached, and cross-origin redirect are not supported
-  // (at least until we have the demand).
+  // redirect count may be reached.
   //
   // Implementations should be aware that throttling can happen multiple times
   // for the same |request|, even after one instance of the same throttle