BlobURLStore.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /*
  2. * Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org>
  3. * Copyright (c) 2024, Andreas Kling <kling@serenityos.org>
  4. * Copyright (c) 2024, Shannon Booth <shannon@serenityos.org>
  5. *
  6. * SPDX-License-Identifier: BSD-2-Clause
  7. */
  8. #include <AK/StringBuilder.h>
  9. #include <LibURL/URL.h>
  10. #include <LibWeb/Crypto/Crypto.h>
  11. #include <LibWeb/DOM/Document.h>
  12. #include <LibWeb/FileAPI/Blob.h>
  13. #include <LibWeb/FileAPI/BlobURLStore.h>
  14. #include <LibWeb/HTML/Origin.h>
  15. #include <LibWeb/HTML/Scripting/Environments.h>
  16. namespace Web::FileAPI {
  17. BlobURLStore& blob_url_store()
  18. {
  19. static HashMap<String, BlobURLEntry> store;
  20. return store;
  21. }
  22. // https://w3c.github.io/FileAPI/#unicodeBlobURL
  23. ErrorOr<String> generate_new_blob_url()
  24. {
  25. // 1. Let result be the empty string.
  26. StringBuilder result;
  27. // 2. Append the string "blob:" to result.
  28. TRY(result.try_append("blob:"sv));
  29. // 3. Let settings be the current settings object
  30. auto& settings = HTML::current_settings_object();
  31. // 4. Let origin be settings’s origin.
  32. auto origin = settings.origin();
  33. // 5. Let serialized be the ASCII serialization of origin.
  34. auto serialized = origin.serialize();
  35. // 6. If serialized is "null", set it to an implementation-defined value.
  36. if (serialized == "null"sv)
  37. serialized = "ladybird"sv;
  38. // 7. Append serialized to result.
  39. TRY(result.try_append(serialized));
  40. // 8. Append U+0024 SOLIDUS (/) to result.
  41. TRY(result.try_append('/'));
  42. // 9. Generate a UUID [RFC4122] as a string and append it to result.
  43. auto uuid = TRY(Crypto::generate_random_uuid());
  44. TRY(result.try_append(uuid));
  45. // 10. Return result.
  46. return result.to_string();
  47. }
  48. // https://w3c.github.io/FileAPI/#add-an-entry
  49. ErrorOr<String> add_entry_to_blob_url_store(JS::NonnullGCPtr<Blob> object)
  50. {
  51. // 1. Let store be the user agent’s blob URL store.
  52. auto& store = blob_url_store();
  53. // 2. Let url be the result of generating a new blob URL.
  54. auto url = TRY(generate_new_blob_url());
  55. // 3. Let entry be a new blob URL entry consisting of object and the current settings object.
  56. BlobURLEntry entry { object, HTML::current_settings_object() };
  57. // 4. Set store[url] to entry.
  58. TRY(store.try_set(url, move(entry)));
  59. // 5. Return url.
  60. return url;
  61. }
  62. // https://w3c.github.io/FileAPI/#removeTheEntry
  63. ErrorOr<void> remove_entry_from_blob_url_store(StringView url)
  64. {
  65. // 1. Let store be the user agent’s blob URL store;
  66. auto& store = blob_url_store();
  67. // 2. Let url string be the result of serializing url.
  68. auto url_string = TRY(URL::URL { url }.to_string());
  69. // 3. Remove store[url string].
  70. store.remove(url_string);
  71. return {};
  72. }
  73. // https://w3c.github.io/FileAPI/#lifeTime
  74. void run_unloading_cleanup_steps(JS::NonnullGCPtr<DOM::Document> document)
  75. {
  76. // 1. Let environment be the Document's relevant settings object.
  77. auto& environment = document->relevant_settings_object();
  78. // 2. Let store be the user agent’s blob URL store;
  79. auto& store = FileAPI::blob_url_store();
  80. // 3. Remove from store any entries for which the value's environment is equal to environment.
  81. store.remove_all_matching([&](auto&, auto& value) {
  82. return value.environment == &environment;
  83. });
  84. }
  85. // https://w3c.github.io/FileAPI/#blob-url-resolve
  86. Optional<BlobURLEntry> resolve_a_blob_url(URL::URL const& url)
  87. {
  88. // 1. Assert: url’s scheme is "blob".
  89. VERIFY(url.scheme() == "blob"sv);
  90. // 2. Let store be the user agent’s blob URL store.
  91. auto& store = blob_url_store();
  92. // 3. Let url string be the result of serializing url with the exclude fragment flag set.
  93. auto url_string = MUST(String::from_byte_string(url.serialize(URL::ExcludeFragment::Yes)));
  94. // 4. If store[url string] exists, return store[url string]; otherwise return failure.
  95. return store.get(url_string);
  96. }
  97. }