Coverage Report

Created: 2026-09-26 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}