on_load_script_injector_host.cc 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/on_load_script_injector/browser/on_load_script_injector_host.h"
  5. #include <utility>
  6. #include "base/numerics/safe_math.h"
  7. #include "base/strings/utf_string_conversions.h"
  8. #include "components/on_load_script_injector/on_load_script_injector.mojom.h"
  9. #include "content/public/browser/render_frame_host.h"
  10. #include "mojo/public/cpp/bindings/associated_remote.h"
  11. #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
  12. #include "url/gurl.h"
  13. namespace on_load_script_injector {
  14. OriginScopedScript::OriginScopedScript() = default;
  15. OriginScopedScript::OriginScopedScript(std::vector<url::Origin> origins,
  16. base::ReadOnlySharedMemoryRegion script)
  17. : origins_(std::move(origins)), script_(std::move(script)) {}
  18. OriginScopedScript& OriginScopedScript::operator=(OriginScopedScript&& other) {
  19. origins_ = std::move(other.origins_);
  20. script_ = std::move(other.script_);
  21. return *this;
  22. }
  23. OriginScopedScript::~OriginScopedScript() = default;
  24. template <typename ScriptId>
  25. OnLoadScriptInjectorHost<ScriptId>::OnLoadScriptInjectorHost() = default;
  26. template <typename ScriptId>
  27. OnLoadScriptInjectorHost<ScriptId>::~OnLoadScriptInjectorHost() = default;
  28. template <typename ScriptId>
  29. void OnLoadScriptInjectorHost<ScriptId>::AddScript(
  30. ScriptId id,
  31. std::vector<url::Origin> origins_to_inject,
  32. base::StringPiece script) {
  33. // If there is no script with the identifier |id|, then create a place for
  34. // it at the end of the injection sequence.
  35. if (before_load_scripts_.find(id) == before_load_scripts_.end())
  36. before_load_scripts_order_.push_back(id);
  37. // Convert script to UTF-16.
  38. std::u16string script_utf16 = base::UTF8ToUTF16(script);
  39. size_t script_utf16_size =
  40. (base::CheckedNumeric<size_t>(script_utf16.size()) * sizeof(char16_t))
  41. .ValueOrDie();
  42. base::WritableSharedMemoryRegion script_shared_memory =
  43. base::WritableSharedMemoryRegion::Create(script_utf16_size);
  44. memcpy(script_shared_memory.Map().memory(), script_utf16.data(),
  45. script_utf16_size);
  46. base::ReadOnlySharedMemoryRegion script_shared_memory_readonly =
  47. base::WritableSharedMemoryRegion::ConvertToReadOnly(
  48. std::move(script_shared_memory));
  49. CHECK(script_shared_memory_readonly.IsValid());
  50. before_load_scripts_[id] = OriginScopedScript(
  51. origins_to_inject, std::move(script_shared_memory_readonly));
  52. }
  53. template <typename ScriptId>
  54. void OnLoadScriptInjectorHost<ScriptId>::AddScriptForAllOrigins(
  55. ScriptId id,
  56. base::StringPiece script) {
  57. AddScript(id, {kMatchAllOrigins}, script);
  58. }
  59. template <typename ScriptId>
  60. void OnLoadScriptInjectorHost<ScriptId>::RemoveScript(ScriptId id) {
  61. before_load_scripts_.erase(id);
  62. for (auto script_id_iter = before_load_scripts_order_.begin();
  63. script_id_iter != before_load_scripts_order_.end(); ++script_id_iter) {
  64. if (*script_id_iter == id) {
  65. before_load_scripts_order_.erase(script_id_iter);
  66. return;
  67. }
  68. }
  69. LOG(WARNING) << "Ignoring attempt to remove unknown OnLoad script: " << id;
  70. }
  71. template <typename ScriptId>
  72. void OnLoadScriptInjectorHost<ScriptId>::InjectScriptsForURL(
  73. const GURL& url,
  74. content::RenderFrameHost* render_frame_host) {
  75. DCHECK(url.is_valid());
  76. mojo::AssociatedRemote<mojom::OnLoadScriptInjector> injector;
  77. render_frame_host->GetRemoteAssociatedInterfaces()->GetInterface(&injector);
  78. injector->ClearOnLoadScripts();
  79. if (before_load_scripts_.empty())
  80. return;
  81. // Provision the renderer's ScriptInjector with the scripts associated with
  82. // |url|.
  83. for (ScriptId script_id : before_load_scripts_order_) {
  84. const OriginScopedScript& script = before_load_scripts_[script_id];
  85. if (IsUrlMatchedByOriginList(url, script.origins()))
  86. injector->AddOnLoadScript(script.script().Duplicate());
  87. }
  88. }
  89. template <typename ScriptId>
  90. bool OnLoadScriptInjectorHost<ScriptId>::IsUrlMatchedByOriginList(
  91. const GURL& url,
  92. const std::vector<url::Origin>& allowed_origins) {
  93. for (const url::Origin& allowed_origin : allowed_origins) {
  94. if (allowed_origin == kMatchAllOrigins)
  95. return true;
  96. DCHECK(!allowed_origin.opaque());
  97. if (allowed_origin.IsSameOriginWith(url))
  98. return true;
  99. }
  100. return false;
  101. }
  102. template class OnLoadScriptInjectorHost<std::string>;
  103. template class OnLoadScriptInjectorHost<uint64_t>;
  104. } // namespace on_load_script_injector