/src/serenity/Userland/Libraries/LibWeb/FileAPI/BlobURLStore.cpp
Line | Count | Source |
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 | | |
9 | | #include <AK/StringBuilder.h> |
10 | | #include <LibURL/Origin.h> |
11 | | #include <LibURL/URL.h> |
12 | | #include <LibWeb/Crypto/Crypto.h> |
13 | | #include <LibWeb/DOM/Document.h> |
14 | | #include <LibWeb/FileAPI/Blob.h> |
15 | | #include <LibWeb/FileAPI/BlobURLStore.h> |
16 | | #include <LibWeb/HTML/Scripting/Environments.h> |
17 | | |
18 | | namespace Web::FileAPI { |
19 | | |
20 | | BlobURLStore& blob_url_store() |
21 | 0 | { |
22 | 0 | static HashMap<String, BlobURLEntry> store; |
23 | 0 | return store; |
24 | 0 | } |
25 | | |
26 | | // https://w3c.github.io/FileAPI/#unicodeBlobURL |
27 | | ErrorOr<String> generate_new_blob_url() |
28 | 0 | { |
29 | | // 1. Let result be the empty string. |
30 | 0 | StringBuilder result; |
31 | | |
32 | | // 2. Append the string "blob:" to result. |
33 | 0 | TRY(result.try_append("blob:"sv)); |
34 | | |
35 | | // 3. Let settings be the current settings object |
36 | 0 | auto& settings = HTML::current_settings_object(); |
37 | | |
38 | | // 4. Let origin be settings’s origin. |
39 | 0 | auto origin = settings.origin(); |
40 | | |
41 | | // 5. Let serialized be the ASCII serialization of origin. |
42 | 0 | auto serialized = origin.serialize(); |
43 | | |
44 | | // 6. If serialized is "null", set it to an implementation-defined value. |
45 | 0 | if (serialized == "null"sv) |
46 | 0 | serialized = "ladybird"sv; |
47 | | |
48 | | // 7. Append serialized to result. |
49 | 0 | TRY(result.try_append(serialized)); |
50 | | |
51 | | // 8. Append U+0024 SOLIDUS (/) to result. |
52 | 0 | TRY(result.try_append('/')); |
53 | | |
54 | | // 9. Generate a UUID [RFC4122] as a string and append it to result. |
55 | 0 | auto uuid = TRY(Crypto::generate_random_uuid()); |
56 | 0 | TRY(result.try_append(uuid)); |
57 | | |
58 | | // 10. Return result. |
59 | 0 | return result.to_string(); |
60 | 0 | } |
61 | | |
62 | | // https://w3c.github.io/FileAPI/#add-an-entry |
63 | | ErrorOr<String> add_entry_to_blob_url_store(JS::NonnullGCPtr<Blob> object) |
64 | 0 | { |
65 | | // 1. Let store be the user agent’s blob URL store. |
66 | 0 | auto& store = blob_url_store(); |
67 | | |
68 | | // 2. Let url be the result of generating a new blob URL. |
69 | 0 | auto url = TRY(generate_new_blob_url()); |
70 | | |
71 | | // 3. Let entry be a new blob URL entry consisting of object and the current settings object. |
72 | 0 | BlobURLEntry entry { object, HTML::current_settings_object() }; |
73 | | |
74 | | // 4. Set store[url] to entry. |
75 | 0 | TRY(store.try_set(url, move(entry))); |
76 | | |
77 | | // 5. Return url. |
78 | 0 | return url; |
79 | 0 | } |
80 | | |
81 | | // https://w3c.github.io/FileAPI/#removeTheEntry |
82 | | ErrorOr<void> remove_entry_from_blob_url_store(StringView url) |
83 | 0 | { |
84 | | // 1. Let store be the user agent’s blob URL store; |
85 | 0 | auto& store = blob_url_store(); |
86 | | |
87 | | // 2. Let url string be the result of serializing url. |
88 | 0 | auto url_string = TRY(URL::URL { url }.to_string()); |
89 | | |
90 | | // 3. Remove store[url string]. |
91 | 0 | store.remove(url_string); |
92 | 0 | return {}; |
93 | 0 | } |
94 | | |
95 | | // https://w3c.github.io/FileAPI/#lifeTime |
96 | | void run_unloading_cleanup_steps(JS::NonnullGCPtr<DOM::Document> document) |
97 | 0 | { |
98 | | // 1. Let environment be the Document's relevant settings object. |
99 | 0 | auto& environment = document->relevant_settings_object(); |
100 | | |
101 | | // 2. Let store be the user agent’s blob URL store; |
102 | 0 | auto& store = FileAPI::blob_url_store(); |
103 | | |
104 | | // 3. Remove from store any entries for which the value's environment is equal to environment. |
105 | 0 | store.remove_all_matching([&](auto&, auto& value) { |
106 | 0 | return value.environment == &environment; |
107 | 0 | }); |
108 | 0 | } |
109 | | |
110 | | // https://w3c.github.io/FileAPI/#blob-url-resolve |
111 | | Optional<BlobURLEntry> resolve_a_blob_url(URL::URL const& url) |
112 | 0 | { |
113 | | // 1. Assert: url’s scheme is "blob". |
114 | 0 | VERIFY(url.scheme() == "blob"sv); |
115 | | |
116 | | // 2. Let store be the user agent’s blob URL store. |
117 | 0 | auto& store = blob_url_store(); |
118 | | |
119 | | // 3. Let url string be the result of serializing url with the exclude fragment flag set. |
120 | 0 | auto url_string = MUST(String::from_byte_string(url.serialize(URL::ExcludeFragment::Yes))); |
121 | | |
122 | | // 4. If store[url string] exists, return store[url string]; otherwise return failure. |
123 | 0 | return store.get(url_string).copy(); |
124 | 0 | } |
125 | | |
126 | | } |