2023-08-01 18:29:54 -04:00
/*
* Copyright ( c ) 2023 , Tim Flynn < trflynn89 @ serenityos . org >
2024-10-04 13:19:50 +02:00
* Copyright ( c ) 2024 , Andreas Kling < andreas @ ladybird . org >
2025-01-19 19:02:18 +13:00
* Copyright ( c ) 2024 - 2025 , Shannon Booth < shannon @ serenityos . org >
2023-08-01 18:29:54 -04:00
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
# include <AK/StringBuilder.h>
2024-10-05 15:33:34 +13:00
# include <LibURL/Origin.h>
2024-03-18 16:22:27 +13:00
# include <LibURL/URL.h>
2023-08-01 18:29:54 -04:00
# include <LibWeb/Crypto/Crypto.h>
2024-04-03 20:17:09 +02:00
# include <LibWeb/DOM/Document.h>
2023-08-01 18:29:54 -04:00
# include <LibWeb/FileAPI/Blob.h>
# include <LibWeb/FileAPI/BlobURLStore.h>
# include <LibWeb/HTML/Scripting/Environments.h>
2025-01-19 19:02:18 +13:00
# include <LibWeb/StorageAPI/StorageKey.h>
2023-08-01 18:29:54 -04:00
namespace Web : : FileAPI {
BlobURLStore & blob_url_store ( )
{
static HashMap < String , BlobURLEntry > store ;
return store ;
}
// https://w3c.github.io/FileAPI/#unicodeBlobURL
ErrorOr < String > generate_new_blob_url ( )
{
// 1. Let result be the empty string.
StringBuilder result ;
// 2. Append the string "blob:" to result.
TRY ( result . try_append ( " blob: " sv ) ) ;
// 3. Let settings be the current settings object
2024-10-21 13:35:24 +13:00
auto & settings = HTML : : current_principal_settings_object ( ) ;
2023-08-01 18:29:54 -04:00
// 4. Let origin be settings’ s origin.
auto origin = settings . origin ( ) ;
// 5. Let serialized be the ASCII serialization of origin.
auto serialized = origin . serialize ( ) ;
// 6. If serialized is "null", set it to an implementation-defined value.
if ( serialized = = " null " sv )
2024-11-23 20:10:34 +13:00
serialized = " ladybird " _string ;
2023-08-01 18:29:54 -04:00
// 7. Append serialized to result.
TRY ( result . try_append ( serialized ) ) ;
// 8. Append U+0024 SOLIDUS (/) to result.
TRY ( result . try_append ( ' / ' ) ) ;
// 9. Generate a UUID [RFC4122] as a string and append it to result.
auto uuid = TRY ( Crypto : : generate_random_uuid ( ) ) ;
TRY ( result . try_append ( uuid ) ) ;
// 10. Return result.
return result . to_string ( ) ;
}
// https://w3c.github.io/FileAPI/#add-an-entry
2024-11-15 04:01:23 +13:00
ErrorOr < String > add_entry_to_blob_url_store ( GC : : Ref < Blob > object )
2023-08-01 18:29:54 -04:00
{
// 1. Let store be the user agent’ s blob URL store.
auto & store = blob_url_store ( ) ;
// 2. Let url be the result of generating a new blob URL.
auto url = TRY ( generate_new_blob_url ( ) ) ;
// 3. Let entry be a new blob URL entry consisting of object and the current settings object.
2024-10-21 13:35:24 +13:00
BlobURLEntry entry { object , HTML : : current_principal_settings_object ( ) } ;
2023-08-01 18:29:54 -04:00
// 4. Set store[url] to entry.
TRY ( store . try_set ( url , move ( entry ) ) ) ;
// 5. Return url.
return url ;
}
2025-01-19 19:02:18 +13:00
// https://www.w3.org/TR/FileAPI/#check-for-same-partition-blob-url-usage
bool check_for_same_partition_blob_url_usage ( URL : : BlobURLEntry const & blob_url_entry , GC : : Ref < HTML : : Environment > environment )
{
// 1. Let blobStorageKey be the result of obtaining a storage key for non-storage purposes with blobUrlEntry’ s environment.
auto blob_storage_key = StorageAPI : : obtain_a_storage_key_for_non_storage_purposes ( blob_url_entry . environment . origin ) ;
// 2. Let environmentStorageKey be the result of obtaining a storage key for non-storage purposes with environment.
auto environment_storage_key = StorageAPI : : obtain_a_storage_key_for_non_storage_purposes ( environment ) ;
// 3. If blobStorageKey is not equal to environmentStorageKey, then return false.
if ( blob_storage_key ! = environment_storage_key )
return false ;
// 4. Return true.
return true ;
}
// https://www.w3.org/TR/FileAPI/#blob-url-obtain-object
Optional < URL : : BlobURLEntry : : Object > obtain_a_blob_object ( URL : : BlobURLEntry const & blob_url_entry , Variant < GC : : Ref < HTML : : Environment > , NavigationEnvironment > environment )
{
// 1. Let isAuthorized be true.
bool is_authorized = true ;
// 2. If environment is not the string "navigation", then set isAuthorized to the result of checking for same-partition blob URL usage with blobUrlEntry and environment.
if ( ! environment . has < NavigationEnvironment > ( ) )
is_authorized = check_for_same_partition_blob_url_usage ( blob_url_entry , environment . get < GC : : Ref < HTML : : Environment > > ( ) ) ;
// 3. If isAuthorized is false, then return failure.
if ( ! is_authorized )
return { } ;
// 4. Return blobUrlEntry’ s object.
return blob_url_entry . object ;
}
2023-08-01 18:29:54 -04:00
// https://w3c.github.io/FileAPI/#removeTheEntry
2025-01-22 17:21:14 +13:00
void remove_entry_from_blob_url_store ( URL : : URL const & url )
2023-08-01 18:29:54 -04:00
{
// 1. Let store be the user agent’ s blob URL store;
auto & store = blob_url_store ( ) ;
// 2. Let url string be the result of serializing url.
2025-01-22 17:21:14 +13:00
auto url_string = url . serialize ( ) ;
2023-08-01 18:29:54 -04:00
// 3. Remove store[url string].
store . remove ( url_string ) ;
}
2024-04-03 20:17:09 +02:00
// https://w3c.github.io/FileAPI/#lifeTime
2024-11-15 04:01:23 +13:00
void run_unloading_cleanup_steps ( GC : : Ref < DOM : : Document > document )
2024-04-03 20:17:09 +02:00
{
// 1. Let environment be the Document's relevant settings object.
auto & environment = document - > relevant_settings_object ( ) ;
// 2. Let store be the user agent’ s blob URL store;
auto & store = FileAPI : : blob_url_store ( ) ;
// 3. Remove from store any entries for which the value's environment is equal to environment.
store . remove_all_matching ( [ & ] ( auto & , auto & value ) {
return value . environment = = & environment ;
} ) ;
}
2024-05-05 19:59:18 +12:00
// https://w3c.github.io/FileAPI/#blob-url-resolve
2024-11-25 13:23:31 +01:00
Optional < BlobURLEntry const & > resolve_a_blob_url ( URL : : URL const & url )
2024-05-05 19:59:18 +12:00
{
// 1. Assert: url’ s scheme is "blob".
VERIFY ( url . scheme ( ) = = " blob " sv ) ;
// 2. Let store be the user agent’ s blob URL store.
auto & store = blob_url_store ( ) ;
// 3. Let url string be the result of serializing url with the exclude fragment flag set.
2024-12-03 22:31:33 +13:00
auto url_string = url . serialize ( URL : : ExcludeFragment : : Yes ) ;
2024-05-05 19:59:18 +12:00
// 4. If store[url string] exists, return store[url string]; otherwise return failure.
return store . get ( url_string ) ;
}
2023-08-01 18:29:54 -04:00
}