feat_allow_code_cache_in_custom_schemes.patch 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
  2. From: Cheng Zhao <[email protected]>
  3. Date: Thu, 14 Dec 2023 21:16:53 +0900
  4. Subject: Enable V8 code cache for custom schemes
  5. Add a new category in ContentClient::AddAdditionalSchemes which allows
  6. embedders to make custom schemes allow V8 code cache.
  7. Chromium CL: https://chromium-review.googlesource.com/c/chromium/src/+/5019665
  8. diff --git a/content/browser/code_cache/generated_code_cache.cc b/content/browser/code_cache/generated_code_cache.cc
  9. index fa46d81e3a46a6d3f289fc8d184b434da1888d7a..169dd7dc24b09d319a7510184aab3b1bb96a1a85 100644
  10. --- a/content/browser/code_cache/generated_code_cache.cc
  11. +++ b/content/browser/code_cache/generated_code_cache.cc
  12. @@ -12,6 +12,7 @@
  13. #include <iostream>
  14. #include <string_view>
  15. +#include "base/containers/contains.h"
  16. #include "base/feature_list.h"
  17. #include "base/functional/bind.h"
  18. #include "base/functional/callback_helpers.h"
  19. @@ -36,6 +37,7 @@
  20. #include "net/http/http_cache.h"
  21. #include "third_party/blink/public/common/scheme_registry.h"
  22. #include "url/gurl.h"
  23. +#include "url/url_util.h"
  24. using storage::BigIOBuffer;
  25. @@ -48,7 +50,7 @@ constexpr char kSeparator[] = " \n";
  26. // We always expect to receive valid URLs that can be used as keys to the code
  27. // cache. The relevant checks (for ex: resource_url is valid, origin_lock is
  28. -// not opque etc.,) must be done prior to requesting the code cache.
  29. +// not opaque etc.,) must be done prior to requesting the code cache.
  30. //
  31. // This function doesn't enforce anything in the production code. It is here
  32. // to make the assumptions explicit and to catch any errors when DCHECKs are
  33. @@ -58,33 +60,55 @@ void CheckValidKeys(const GURL& resource_url,
  34. GeneratedCodeCache::CodeCacheType cache_type) {
  35. // If the resource url is invalid don't cache the code.
  36. DCHECK(resource_url.is_valid());
  37. - bool resource_url_is_chrome_or_chrome_untrusted =
  38. +
  39. + // There are 3 kind of URL scheme compatible for the `resource_url`.
  40. + // 1. http: and https: URLs.
  41. + // 2. chrome: and chrome-untrusted: URLs.
  42. + // 3. URLs whose scheme are allowed by the content/ embedder.
  43. + const bool resource_url_http = resource_url.SchemeIsHTTPOrHTTPS();
  44. + const bool resource_url_webui =
  45. resource_url.SchemeIs(content::kChromeUIScheme) ||
  46. resource_url.SchemeIs(content::kChromeUIUntrustedScheme);
  47. - DCHECK(resource_url.SchemeIsHTTPOrHTTPS() ||
  48. - resource_url_is_chrome_or_chrome_untrusted ||
  49. - blink::CommonSchemeRegistry::IsExtensionScheme(resource_url.scheme()));
  50. -
  51. - // |origin_lock| should be either empty or should have
  52. - // Http/Https/chrome/chrome-untrusted schemes and it should not be a URL with
  53. - // opaque origin. Empty origin_locks are allowed when the renderer is not
  54. - // locked to an origin.
  55. - bool origin_lock_is_chrome_or_chrome_untrusted =
  56. +
  57. + const bool resource_url_embedder =
  58. + base::Contains(url::GetCodeCacheSchemes(), resource_url.scheme());
  59. + DCHECK(resource_url_http || resource_url_webui || resource_url_embedder);
  60. +
  61. + // |origin_lock| should be either empty or should have code cache allowed
  62. + // schemes (http/https/chrome/chrome-untrusted or other custom schemes added
  63. + // by url::AddCodeCacheScheme), and it should not be a URL with opaque
  64. + // origin. Empty origin_locks are allowed when the renderer is not locked to
  65. + // an origin.
  66. + const bool origin_lock_empty = origin_lock.is_empty();
  67. + const bool origin_lock_for_http = origin_lock.SchemeIsHTTPOrHTTPS();
  68. + const bool origin_lock_for_webui =
  69. origin_lock.SchemeIs(content::kChromeUIScheme) ||
  70. origin_lock.SchemeIs(content::kChromeUIUntrustedScheme);
  71. - DCHECK(
  72. - origin_lock.is_empty() ||
  73. - ((origin_lock.SchemeIsHTTPOrHTTPS() ||
  74. - origin_lock_is_chrome_or_chrome_untrusted ||
  75. - blink::CommonSchemeRegistry::IsExtensionScheme(origin_lock.scheme())) &&
  76. - !url::Origin::Create(origin_lock).opaque()));
  77. -
  78. - // The chrome and chrome-untrusted schemes are only used with the WebUI
  79. - // code cache type.
  80. - DCHECK_EQ(origin_lock_is_chrome_or_chrome_untrusted,
  81. - cache_type == GeneratedCodeCache::kWebUIJavaScript);
  82. - DCHECK_EQ(resource_url_is_chrome_or_chrome_untrusted,
  83. - cache_type == GeneratedCodeCache::kWebUIJavaScript);
  84. + const bool origin_lock_for_embedder =
  85. + base::Contains(url::GetCodeCacheSchemes(), origin_lock.scheme());
  86. +
  87. + DCHECK(origin_lock_empty || ((origin_lock_for_http || origin_lock_for_webui ||
  88. + origin_lock_for_embedder) &&
  89. + !url::Origin::Create(origin_lock).opaque()));
  90. +
  91. + // The webui schemes are only used with their dedicated code cache type.
  92. + switch (cache_type) {
  93. + case GeneratedCodeCache::kJavaScript:
  94. + case GeneratedCodeCache::kWebAssembly:
  95. + DCHECK(!origin_lock_for_webui);
  96. + DCHECK(!resource_url_webui);
  97. + break;
  98. + case GeneratedCodeCache::kWebUIJavaScript:
  99. + DCHECK(origin_lock_for_webui);
  100. + DCHECK(resource_url_webui);
  101. + break;
  102. + }
  103. +
  104. + // The custom schemes share the cache type with http(s).
  105. + if (origin_lock_for_embedder || resource_url_embedder) {
  106. + DCHECK(cache_type == GeneratedCodeCache::kJavaScript ||
  107. + cache_type == GeneratedCodeCache::kWebAssembly);
  108. + }
  109. }
  110. // Generates the cache key for the given |resource_url|, |origin_lock| and
  111. diff --git a/content/browser/code_cache/generated_code_cache.h b/content/browser/code_cache/generated_code_cache.h
  112. index e0cdc785d2557bc79bde98728c23c239ed8d0961..74e0acbea1e0c18a6ac8971170efc945ca58f4ed 100644
  113. --- a/content/browser/code_cache/generated_code_cache.h
  114. +++ b/content/browser/code_cache/generated_code_cache.h
  115. @@ -52,12 +52,14 @@ class CONTENT_EXPORT GeneratedCodeCache {
  116. // Cache type. Used for collecting statistics for JS and Wasm in separate
  117. // buckets.
  118. enum CodeCacheType {
  119. - // JavaScript from http(s) pages.
  120. + // JavaScript from pages of http(s) schemes or custom schemes registered by
  121. + // url::AddCodeCacheScheme.
  122. kJavaScript,
  123. - // WebAssembly from http(s) pages. This cache allows more total size and
  124. - // more size per item than the JavaScript cache, since some
  125. - // WebAssembly programs are very large.
  126. + // WebAssembly from pages of http(s) schemes or custom schemes registered by
  127. + // url::AddCodeCacheScheme. This cache allows more total size and more size
  128. + // per item than the JavaScript cache, since some WebAssembly programs are
  129. + // very large.
  130. kWebAssembly,
  131. // JavaScript from chrome and chrome-untrusted pages. The resource URLs are
  132. diff --git a/content/browser/code_cache/generated_code_cache_browsertest.cc b/content/browser/code_cache/generated_code_cache_browsertest.cc
  133. index 61c8b54bc5a9ea59c90e8627ab01745e0c328382..f9521b7aac19bf3994517906b85fc92800b18003 100644
  134. --- a/content/browser/code_cache/generated_code_cache_browsertest.cc
  135. +++ b/content/browser/code_cache/generated_code_cache_browsertest.cc
  136. @@ -11,17 +11,22 @@
  137. #include "base/time/time.h"
  138. #include "content/browser/code_cache/generated_code_cache_context.h"
  139. #include "content/browser/renderer_host/code_cache_host_impl.h"
  140. +#include "content/browser/storage_partition_impl.h"
  141. #include "content/browser/web_contents/web_contents_impl.h"
  142. #include "content/common/renderer.mojom.h"
  143. +#include "content/common/url_schemes.h"
  144. #include "content/public/browser/browser_context.h"
  145. +#include "content/public/browser/browser_thread.h"
  146. #include "content/public/browser/render_process_host.h"
  147. #include "content/public/browser/storage_partition.h"
  148. #include "content/public/test/browser_test.h"
  149. #include "content/public/test/browser_test_utils.h"
  150. #include "content/public/test/content_browser_test.h"
  151. #include "content/public/test/content_browser_test_utils.h"
  152. +#include "content/public/test/test_browser_context.h"
  153. #include "content/shell/browser/shell.h"
  154. #include "content/test/content_browser_test_utils_internal.h"
  155. +#include "content/test/test_content_client.h"
  156. #include "net/dns/mock_host_resolver.h"
  157. #include "third_party/blink/public/common/features.h"
  158. #include "third_party/blink/public/common/page/v8_compile_hints_histograms.h"
  159. @@ -30,6 +35,8 @@ namespace content {
  160. namespace {
  161. +const std::string kCodeCacheScheme = "test-code-cache";
  162. +
  163. bool SupportsSharedWorker() {
  164. #if BUILDFLAG(IS_ANDROID)
  165. // SharedWorkers are not enabled on Android. https://crbug.com/154571
  166. @@ -875,4 +882,82 @@ IN_PROC_BROWSER_TEST_F(LocalCompileHintsBrowserTest, LocalCompileHints) {
  167. }
  168. }
  169. +class CodeCacheInCustomSchemeBrowserTest : public ContentBrowserTest,
  170. + public TestContentClient {
  171. + public:
  172. + CodeCacheInCustomSchemeBrowserTest() {
  173. + SetContentClient(this);
  174. + ReRegisterContentSchemesForTests();
  175. + }
  176. +
  177. + ~CodeCacheInCustomSchemeBrowserTest() override { SetContentClient(nullptr); }
  178. +
  179. + private:
  180. + void AddAdditionalSchemes(Schemes* schemes) override {
  181. + schemes->standard_schemes.push_back(kCodeCacheScheme);
  182. + schemes->code_cache_schemes.push_back(kCodeCacheScheme);
  183. + }
  184. +
  185. + url::ScopedSchemeRegistryForTests scheme_registry_;
  186. +};
  187. +
  188. +IN_PROC_BROWSER_TEST_F(CodeCacheInCustomSchemeBrowserTest,
  189. + AllowedCustomSchemeCanGenerateCodeCache) {
  190. + StoragePartitionImpl* partition =
  191. + static_cast<StoragePartitionImpl*>(shell()
  192. + ->web_contents()
  193. + ->GetBrowserContext()
  194. + ->GetDefaultStoragePartition());
  195. + scoped_refptr<GeneratedCodeCacheContext> context =
  196. + partition->GetGeneratedCodeCacheContext();
  197. + EXPECT_NE(context, nullptr);
  198. +
  199. + GURL url(kCodeCacheScheme + "://host4/script.js");
  200. + GURL origin(kCodeCacheScheme + "://host1:1/");
  201. + ASSERT_TRUE(url.is_valid());
  202. + ASSERT_TRUE(origin.is_valid());
  203. + std::string data("SomeData");
  204. +
  205. + // Add a code cache entry for the custom scheme.
  206. + base::test::TestFuture<void> add_entry_future;
  207. + GeneratedCodeCacheContext::RunOrPostTask(
  208. + context.get(), FROM_HERE,
  209. + base::BindOnce(
  210. + [](scoped_refptr<GeneratedCodeCacheContext> context, const GURL& url,
  211. + const GURL& origin, const std::string& data,
  212. + base::OnceClosure callback) {
  213. + context->generated_js_code_cache()->WriteEntry(
  214. + url, origin, net::NetworkIsolationKey(), base::Time::Now(),
  215. + std::vector<uint8_t>(data.begin(), data.end()));
  216. + GetUIThreadTaskRunner({})->PostTask(FROM_HERE, std::move(callback));
  217. + },
  218. + context, url, origin, data, add_entry_future.GetCallback()));
  219. + ASSERT_TRUE(add_entry_future.Wait());
  220. +
  221. + // Get the code cache entry.
  222. + base::test::TestFuture<std::string> get_entry_future;
  223. + GeneratedCodeCacheContext::RunOrPostTask(
  224. + context.get(), FROM_HERE,
  225. + base::BindOnce(
  226. + [](scoped_refptr<GeneratedCodeCacheContext> context, const GURL& url,
  227. + const GURL& origin,
  228. + base::OnceCallback<void(std::string)> callback) {
  229. + context->generated_js_code_cache()->FetchEntry(
  230. + url, origin, net::NetworkIsolationKey(),
  231. + base::BindOnce(
  232. + [](base::OnceCallback<void(std::string)> callback,
  233. + const base::Time& response_time,
  234. + mojo_base::BigBuffer buffer) {
  235. + std::string data(buffer.data(),
  236. + buffer.data() + buffer.size());
  237. + GetUIThreadTaskRunner({})->PostTask(
  238. + FROM_HERE, base::BindOnce(std::move(callback), data));
  239. + },
  240. + std::move(callback)));
  241. + },
  242. + context, url, origin, get_entry_future.GetCallback()));
  243. + ASSERT_TRUE(get_entry_future.Wait());
  244. + ASSERT_EQ(data, get_entry_future.Get<0>());
  245. +}
  246. +
  247. } // namespace content
  248. diff --git a/content/browser/renderer_host/code_cache_host_impl.cc b/content/browser/renderer_host/code_cache_host_impl.cc
  249. index e5f48a4e0a6059f9555516a3e824e2157e3b0b60..37cd9b6e15cbbc31a19ee8317786c9c5f09199e2 100644
  250. --- a/content/browser/renderer_host/code_cache_host_impl.cc
  251. +++ b/content/browser/renderer_host/code_cache_host_impl.cc
  252. @@ -6,6 +6,7 @@
  253. #include <utility>
  254. +#include "base/containers/contains.h"
  255. #include "base/functional/bind.h"
  256. #include "base/functional/callback_helpers.h"
  257. #include "base/metrics/histogram_functions.h"
  258. @@ -29,6 +30,7 @@
  259. #include "third_party/blink/public/common/scheme_registry.h"
  260. #include "url/gurl.h"
  261. #include "url/origin.h"
  262. +#include "url/url_util.h"
  263. using blink::mojom::CacheStorageError;
  264. @@ -36,6 +38,11 @@ namespace content {
  265. namespace {
  266. +bool ProcessLockURLIsCodeCacheScheme(const ProcessLock& process_lock) {
  267. + return base::Contains(url::GetCodeCacheSchemes(),
  268. + process_lock.lock_url().scheme());
  269. +}
  270. +
  271. bool CheckSecurityForAccessingCodeCacheData(
  272. const GURL& resource_url,
  273. int render_process_id,
  274. @@ -46,39 +53,57 @@ bool CheckSecurityForAccessingCodeCacheData(
  275. // Code caching is only allowed for http(s) and chrome/chrome-untrusted
  276. // scripts. Furthermore, there is no way for http(s) pages to load chrome or
  277. + // Code caching is only allowed for scripts from:
  278. + // 1. http: and https: schemes.
  279. + // 2. chrome: and chrome-untrusted: schemes.
  280. + // 3. Schemes registered by content/ embedder via url::AddCodeCacheScheme.
  281. + //
  282. + // Furthermore, we know there are no way for http(s) pages to load chrome or
  283. // chrome-untrusted scripts, so any http(s) page attempting to store data
  284. // about a chrome or chrome-untrusted script would be an indication of
  285. // suspicious activity.
  286. - if (resource_url.SchemeIs(content::kChromeUIScheme) ||
  287. - resource_url.SchemeIs(content::kChromeUIUntrustedScheme)) {
  288. - if (!process_lock.is_locked_to_site()) {
  289. - // We can't tell for certain whether this renderer is doing something
  290. - // malicious, but we don't trust it enough to store data.
  291. - return false;
  292. - }
  293. + if (resource_url.SchemeIsHTTPOrHTTPS()) {
  294. if (process_lock.matches_scheme(url::kHttpScheme) ||
  295. process_lock.matches_scheme(url::kHttpsScheme)) {
  296. - if (operation == CodeCacheHostImpl::Operation::kWrite) {
  297. + return true;
  298. + }
  299. + // Pages in custom schemes like isolated-app: are allowed to load http(s)
  300. + // resources.
  301. + if (ProcessLockURLIsCodeCacheScheme(process_lock)) {
  302. + return true;
  303. + }
  304. + // It is possible for WebUI pages to include open-web content, but such
  305. + // usage is rare and we've decided that reasoning about security is easier
  306. + // if the WebUI code cache includes only WebUI scripts.
  307. + return false;
  308. + }
  309. +
  310. + if (resource_url.SchemeIs(kChromeUIScheme) ||
  311. + resource_url.SchemeIs(kChromeUIUntrustedScheme)) {
  312. + if (process_lock.matches_scheme(kChromeUIScheme) ||
  313. + process_lock.matches_scheme(kChromeUIUntrustedScheme)) {
  314. + return true;
  315. + }
  316. + if (operation == CodeCacheHostImpl::Operation::kWrite) {
  317. + if (process_lock.matches_scheme(url::kHttpScheme) ||
  318. + process_lock.matches_scheme(url::kHttpsScheme)) {
  319. mojo::ReportBadMessage("HTTP(S) pages cannot cache WebUI code");
  320. }
  321. + if (ProcessLockURLIsCodeCacheScheme(process_lock)) {
  322. + mojo::ReportBadMessage(
  323. + "Page whose scheme are allowed by content/ embedders cannot cache "
  324. + "WebUI code. Did the embedder misconfigured content/?");
  325. + }
  326. return false;
  327. }
  328. // Other schemes which might successfully load chrome or chrome-untrusted
  329. // scripts, such as the PDF viewer, are unsupported but not considered
  330. - // dangerous.
  331. - return process_lock.matches_scheme(content::kChromeUIScheme) ||
  332. - process_lock.matches_scheme(content::kChromeUIUntrustedScheme);
  333. + // dangerous. Similarly, the process might not be locked to a site.
  334. + return false;
  335. }
  336. - if (resource_url.SchemeIsHTTPOrHTTPS() ||
  337. - blink::CommonSchemeRegistry::IsExtensionScheme(resource_url.scheme())) {
  338. - if (process_lock.matches_scheme(content::kChromeUIScheme) ||
  339. - process_lock.matches_scheme(content::kChromeUIUntrustedScheme)) {
  340. - // It is possible for WebUI pages to include open-web content, but such
  341. - // usage is rare and we've decided that reasoning about security is easier
  342. - // if the WebUI code cache includes only WebUI scripts.
  343. - return false;
  344. - }
  345. - return true;
  346. +
  347. + if (base::Contains(url::GetCodeCacheSchemes(), resource_url.scheme())) {
  348. + return ProcessLockURLIsCodeCacheScheme(process_lock);
  349. }
  350. if (operation == CodeCacheHostImpl::Operation::kWrite) {
  351. @@ -433,6 +458,7 @@ std::optional<GURL> CodeCacheHostImpl::GetSecondaryKeyForCodeCache(
  352. process_lock.matches_scheme(url::kHttpsScheme) ||
  353. process_lock.matches_scheme(content::kChromeUIScheme) ||
  354. process_lock.matches_scheme(content::kChromeUIUntrustedScheme) ||
  355. + ProcessLockURLIsCodeCacheScheme(process_lock) ||
  356. blink::CommonSchemeRegistry::IsExtensionScheme(
  357. process_lock.lock_url().scheme())) {
  358. return process_lock.lock_url();
  359. diff --git a/content/common/url_schemes.cc b/content/common/url_schemes.cc
  360. index ce9644d33fe83379127b01bf9a2b1c4badc3bc7c..fd486d4637ae4766ed78571dee7f9cebbd809f38 100644
  361. --- a/content/common/url_schemes.cc
  362. +++ b/content/common/url_schemes.cc
  363. @@ -98,6 +98,14 @@ void RegisterContentSchemes(bool should_lock_registry) {
  364. for (auto& scheme : schemes.empty_document_schemes)
  365. url::AddEmptyDocumentScheme(scheme.c_str());
  366. + for (auto& scheme : schemes.code_cache_schemes) {
  367. + CHECK_NE(scheme, kChromeUIScheme);
  368. + CHECK_NE(scheme, kChromeUIUntrustedScheme);
  369. + CHECK_NE(scheme, url::kHttpScheme);
  370. + CHECK_NE(scheme, url::kHttpsScheme);
  371. + url::AddCodeCacheScheme(scheme.c_str());
  372. + }
  373. +
  374. #if BUILDFLAG(IS_ANDROID)
  375. if (schemes.allow_non_standard_schemes_in_origins)
  376. url::EnableNonStandardSchemesForAndroidWebView();
  377. diff --git a/content/public/common/content_client.h b/content/public/common/content_client.h
  378. index 89b70ce1e26612ae85dfcfa088718cb0c79881a2..f78342eca69ace7c3bb5f63cc986074657435ac2 100644
  379. --- a/content/public/common/content_client.h
  380. +++ b/content/public/common/content_client.h
  381. @@ -142,6 +142,9 @@ class CONTENT_EXPORT ContentClient {
  382. // Registers a URL scheme as strictly empty documents, allowing them to
  383. // commit synchronously.
  384. std::vector<std::string> empty_document_schemes;
  385. + // Registers a URL scheme whose js and wasm scripts have V8 code cache
  386. + // enabled.
  387. + std::vector<std::string> code_cache_schemes;
  388. // Registers a URL scheme as extension scheme.
  389. std::vector<std::string> extension_schemes;
  390. // Registers a URL scheme with a predefined default custom handler.
  391. diff --git a/url/url_util.cc b/url/url_util.cc
  392. index 67c4c5f3ce124e111fb7a70e16386120cf24d9b8..d9876cd58ff28ea1af87596691cd836b815825dd 100644
  393. --- a/url/url_util.cc
  394. +++ b/url/url_util.cc
  395. @@ -135,6 +135,9 @@ struct SchemeRegistry {
  396. kMaterializedViewScheme,
  397. };
  398. + // Embedder schemes that have V8 code cache enabled in js and wasm scripts.
  399. + std::vector<std::string> code_cache_schemes = {};
  400. +
  401. // Schemes with a predefined default custom handler.
  402. std::vector<SchemeWithHandler> predefined_handler_schemes;
  403. @@ -717,6 +720,15 @@ const std::vector<std::string>& GetEmptyDocumentSchemes() {
  404. return GetSchemeRegistry().empty_document_schemes;
  405. }
  406. +void AddCodeCacheScheme(const char* new_scheme) {
  407. + DoAddScheme(new_scheme,
  408. + &GetSchemeRegistryWithoutLocking()->code_cache_schemes);
  409. +}
  410. +
  411. +const std::vector<std::string>& GetCodeCacheSchemes() {
  412. + return GetSchemeRegistry().code_cache_schemes;
  413. +}
  414. +
  415. void AddPredefinedHandlerScheme(const char* new_scheme, const char* handler) {
  416. DoAddSchemeWithHandler(
  417. new_scheme, handler,
  418. diff --git a/url/url_util.h b/url/url_util.h
  419. index e39a44057cebce7cdf90bcb02a7463e88bd271b4..e80b81d2ddeb2ec201b143d86bec6ee54ca49afc 100644
  420. --- a/url/url_util.h
  421. +++ b/url/url_util.h
  422. @@ -115,6 +115,15 @@ COMPONENT_EXPORT(URL) const std::vector<std::string>& GetCSPBypassingSchemes();
  423. COMPONENT_EXPORT(URL) void AddEmptyDocumentScheme(const char* new_scheme);
  424. COMPONENT_EXPORT(URL) const std::vector<std::string>& GetEmptyDocumentSchemes();
  425. +// Adds an application-defined scheme to the list of schemes that have V8 code
  426. +// cache enabled for the js and wasm scripts.
  427. +// The WebUI schemes (chrome/chrome-untrusted) do not belong to this list, as
  428. +// they are treated as a separate cache type for security purpose.
  429. +// The http(s) schemes do not belong to this list neither, they always have V8
  430. +// code cache enabled.
  431. +COMPONENT_EXPORT(URL) void AddCodeCacheScheme(const char* new_scheme);
  432. +COMPONENT_EXPORT(URL) const std::vector<std::string>& GetCodeCacheSchemes();
  433. +
  434. // Adds a scheme with a predefined default handler.
  435. //
  436. // This pair of strings must be normalized protocol handler parameters as