delay_lock_the_protocol_scheme_registry.patch 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
  2. From: Andy Locascio <[email protected]>
  3. Date: Tue, 18 Feb 2020 14:35:04 -0800
  4. Subject: content: allow embedder to prevent locking scheme registry
  5. The //content layer requires all schemes to be registered during startup,
  6. because Add*Scheme aren't threadsafe. However, Electron exposes the option to
  7. register additional schemes via JavaScript in the main process before the app
  8. is ready, but after the //content layer has already locked the registry.
  9. This allows embedders to optionally keep the scheme registry unlocked, and it
  10. is their responsibility to ensure that it is not accessed in a way that would
  11. cause potential thread-safety issues.
  12. Previously upstreamed patch: https://chromium-review.googlesource.com/c/chromium/src/+/1637040
  13. This change was lost during upstream refactor in
  14. https://chromium-review.googlesource.com/c/chromium/src/+/1901591, we should try
  15. re-submitting the patch.
  16. diff --git a/content/app/content_main_runner_impl.cc b/content/app/content_main_runner_impl.cc
  17. index 81e48e33cad43875634d4ab6a5625c16d4c37891..230f9348128d2630e80f1c0f346be23b15446dd7 100644
  18. --- a/content/app/content_main_runner_impl.cc
  19. +++ b/content/app/content_main_runner_impl.cc
  20. @@ -738,7 +738,7 @@ int ContentMainRunnerImpl::Initialize(const ContentMainParams& params) {
  21. }
  22. #endif
  23. - RegisterContentSchemes();
  24. + RegisterContentSchemes(delegate_->ShouldLockSchemeRegistry());
  25. ContentClientInitializer::Set(process_type, delegate_);
  26. #if !defined(OS_ANDROID)
  27. diff --git a/content/common/url_schemes.cc b/content/common/url_schemes.cc
  28. index dc37f121130d83e200d73dd1ad566847548ac0fd..63080c1bc486a488841fc5d2081f4d5d4a00bde3 100644
  29. --- a/content/common/url_schemes.cc
  30. +++ b/content/common/url_schemes.cc
  31. @@ -49,7 +49,7 @@ std::vector<std::string>& GetMutableServiceWorkerSchemes() {
  32. } // namespace
  33. -void RegisterContentSchemes() {
  34. +void RegisterContentSchemes(bool should_lock_registry) {
  35. // On Android and in tests, schemes may have been registered already.
  36. if (g_registered_url_schemes)
  37. return;
  38. @@ -106,7 +106,8 @@ void RegisterContentSchemes() {
  39. // threadsafe so must be called when GURL isn't used on any other thread. This
  40. // is really easy to mess up, so we say that all calls to Add*Scheme in Chrome
  41. // must be inside this function.
  42. - url::LockSchemeRegistries();
  43. + if (should_lock_registry)
  44. + url::LockSchemeRegistries();
  45. // Combine the default savable schemes with the additional ones given.
  46. GetMutableSavableSchemes().assign(std::begin(kDefaultSavableSchemes),
  47. diff --git a/content/common/url_schemes.h b/content/common/url_schemes.h
  48. index 3038f9d25798f36811b6398f8cc0e7d83ecc41b0..68189c36c47ef85b345b0ccc40c456f889977bee 100644
  49. --- a/content/common/url_schemes.h
  50. +++ b/content/common/url_schemes.h
  51. @@ -16,7 +16,7 @@ namespace content {
  52. // parsed as "standard" or "referrer" with the src/url/ library, then locks the
  53. // sets of schemes down. The embedder can add additional schemes by
  54. // overriding the ContentClient::AddAdditionalSchemes method.
  55. -CONTENT_EXPORT void RegisterContentSchemes();
  56. +CONTENT_EXPORT void RegisterContentSchemes(bool should_lock_registry = true);
  57. // Re-initializes schemes for tests.
  58. CONTENT_EXPORT void ReRegisterContentSchemesForTests();
  59. diff --git a/content/public/app/content_main_delegate.cc b/content/public/app/content_main_delegate.cc
  60. index 17d256b852b6e7615cf4e52e4a2d7fa326a4df44..bd0512902df4484e8714cda9ab1352b1c672a1cd 100644
  61. --- a/content/public/app/content_main_delegate.cc
  62. +++ b/content/public/app/content_main_delegate.cc
  63. @@ -42,6 +42,10 @@ bool ContentMainDelegate::ShouldHandleConsoleControlEvents() {
  64. }
  65. #endif
  66. +bool ContentMainDelegate::ShouldLockSchemeRegistry() {
  67. + return true;
  68. +}
  69. +
  70. bool ContentMainDelegate::ShouldCreateFeatureList() {
  71. return true;
  72. }
  73. diff --git a/content/public/app/content_main_delegate.h b/content/public/app/content_main_delegate.h
  74. index 4162083f789b6cf5e29e52e4bd498c377cab1a20..d6010bc0e4dba560d10c3ed4729d77b5a60eddcd 100644
  75. --- a/content/public/app/content_main_delegate.h
  76. +++ b/content/public/app/content_main_delegate.h
  77. @@ -65,6 +65,20 @@ class CONTENT_EXPORT ContentMainDelegate {
  78. // returning initialization error code. Default behavior is CHECK(false).
  79. virtual int TerminateForFatalInitializationError();
  80. + // Allows the embedder to prevent locking the scheme registry. The scheme
  81. + // registry is the list of URL schemes we recognize, with some additional
  82. + // information about each scheme such as whether it expects a host. The
  83. + // scheme registry is not thread-safe, so by default it is locked before any
  84. + // threads are created to ensure single-threaded access. An embedder can
  85. + // override this to prevent the scheme registry from being locked during
  86. + // startup, but if they do so then they are responsible for making sure that
  87. + // the registry is only accessed in a thread-safe way, and for calling
  88. + // url::LockSchemeRegistries() when initialization is complete. If possible,
  89. + // prefer registering additional schemes through
  90. + // ContentClient::AddAdditionalSchemes over preventing the scheme registry
  91. + // from being locked.
  92. + virtual bool ShouldLockSchemeRegistry();
  93. +
  94. // Allows the embedder to perform platform-specific initialization before
  95. // creating the main message loop.
  96. virtual void PreCreateMainMessageLoop() {}