2021-02-21 13:36:34 -03:00
/*
* Copyright ( c ) 2021 , the SerenityOS developers .
2021-11-18 14:34:53 -03:00
* Copyright ( c ) 2021 , Sam Atkins < atkinssj @ serenityos . org >
2024-10-12 11:52:36 -03:00
* Copyright ( c ) 2022 - 2024 , Andreas Kling < andreas @ ladybird . org >
2021-02-21 13:36:34 -03:00
*
2021-04-22 05:24:48 -03:00
* SPDX - License - Identifier : BSD - 2 - Clause
2021-02-21 13:36:34 -03:00
*/
2021-11-18 14:34:53 -03:00
# include <AK/Debug.h>
2024-10-12 11:52:36 -03:00
# include <LibTextCodec/Decoder.h>
2024-03-18 00:22:27 -03:00
# include <LibURL/URL.h>
2022-09-24 19:34:04 -03:00
# include <LibWeb/Bindings/CSSImportRulePrototype.h>
# include <LibWeb/Bindings/Intrinsics.h>
2021-02-21 13:36:34 -03:00
# include <LibWeb/CSS/CSSImportRule.h>
2021-11-18 14:34:53 -03:00
# include <LibWeb/CSS/Parser/Parser.h>
2023-05-08 01:37:18 -03:00
# include <LibWeb/CSS/StyleComputer.h>
2021-11-18 14:34:53 -03:00
# include <LibWeb/DOM/Document.h>
2022-08-28 08:42:07 -03:00
# include <LibWeb/HTML/Window.h>
2021-11-18 14:34:53 -03:00
# include <LibWeb/Loader/ResourceLoader.h>
2021-02-21 13:36:34 -03:00
namespace Web : : CSS {
2024-11-14 12:01:23 -03:00
GC_DEFINE_ALLOCATOR ( CSSImportRule ) ;
2023-11-19 15:47:52 -03:00
2024-11-14 12:01:23 -03:00
GC : : Ref < CSSImportRule > CSSImportRule : : create ( URL : : URL url , DOM : : Document & document )
2022-08-07 10:46:44 -03:00
{
2022-09-24 19:34:04 -03:00
auto & realm = document . realm ( ) ;
2024-11-13 13:50:17 -03:00
return realm . create < CSSImportRule > ( move ( url ) , document ) ;
2022-08-07 10:46:44 -03:00
}
2024-03-18 00:22:27 -03:00
CSSImportRule : : CSSImportRule ( URL : : URL url , DOM : : Document & document )
2024-10-28 16:16:28 -03:00
: CSSRule ( document . realm ( ) , Type : : Import )
2022-08-07 10:46:44 -03:00
, m_url ( move ( url ) )
2021-11-18 14:34:53 -03:00
, m_document ( document )
2021-02-21 13:36:34 -03:00
{
2021-11-18 14:34:53 -03:00
dbgln_if ( CSS_LOADER_DEBUG , " CSSImportRule: Loading import URL: {} " , m_url ) ;
2023-12-15 11:41:28 -03:00
auto request = LoadRequest : : create_for_url_on_page ( m_url , & document . page ( ) ) ;
2022-02-15 10:10:16 -03:00
// NOTE: Mark this rule as delaying the document load event *before* calling set_resource()
// as it may trigger a synchronous resource_did_load() callback.
2021-12-05 11:28:38 -03:00
m_document_load_event_delayer . emplace ( document ) ;
2022-02-15 10:10:16 -03:00
set_resource ( ResourceLoader : : the ( ) . load_resource ( Resource : : Type : : Generic , request ) ) ;
2021-02-21 13:36:34 -03:00
}
2023-08-07 03:41:28 -03:00
void CSSImportRule : : initialize ( JS : : Realm & realm )
2023-01-10 08:28:20 -03:00
{
2023-08-07 03:41:28 -03:00
Base : : initialize ( realm ) ;
2024-03-16 09:13:08 -03:00
WEB_SET_PROTOTYPE_FOR_INTERFACE ( CSSImportRule ) ;
2023-01-10 08:28:20 -03:00
}
2022-08-07 10:46:44 -03:00
void CSSImportRule : : visit_edges ( Cell : : Visitor & visitor )
{
Base : : visit_edges ( visitor ) ;
2022-09-03 10:44:06 -03:00
visitor . visit ( m_document ) ;
2022-08-07 10:46:44 -03:00
visitor . visit ( m_style_sheet ) ;
}
2021-10-15 15:38:39 -03:00
// https://www.w3.org/TR/cssom/#serialize-a-css-rule
2023-11-20 07:16:39 -03:00
String CSSImportRule : : serialized ( ) const
2021-10-01 14:57:45 -03:00
{
StringBuilder builder ;
// The result of concatenating the following:
// 1. The string "@import" followed by a single SPACE (U+0020).
builder . append ( " @import " sv ) ;
// 2. The result of performing serialize a URL on the rule’ s location.
2024-12-03 06:31:33 -03:00
serialize_a_url ( builder , m_url . to_string ( ) ) ;
2021-10-01 14:57:45 -03:00
// FIXME: 3. If the rule’ s associated media list is not empty, a single SPACE (U+0020) followed by the result of performing serialize a media query list on the media list.
// 4. The string ";", i.e., SEMICOLON (U+003B).
builder . append ( ' ; ' ) ;
2023-11-20 07:16:39 -03:00
return MUST ( builder . to_string ( ) ) ;
2021-10-01 14:57:45 -03:00
}
2021-11-18 14:34:53 -03:00
void CSSImportRule : : resource_did_fail ( )
{
dbgln_if ( CSS_LOADER_DEBUG , " CSSImportRule: Resource did fail. URL: {} " , resource ( ) - > url ( ) ) ;
m_document_load_event_delayer . clear ( ) ;
}
void CSSImportRule : : resource_did_load ( )
{
VERIFY ( resource ( ) ) ;
2021-12-05 11:28:38 -03:00
if ( ! m_document )
return ;
2021-11-18 14:34:53 -03:00
m_document_load_event_delayer . clear ( ) ;
if ( ! resource ( ) - > has_encoded_data ( ) ) {
dbgln_if ( CSS_LOADER_DEBUG , " CSSImportRule: Resource did load, no encoded data. URL: {} " , resource ( ) - > url ( ) ) ;
} else {
dbgln_if ( CSS_LOADER_DEBUG , " CSSImportRule: Resource did load, has encoded data. URL: {} " , resource ( ) - > url ( ) ) ;
}
2024-10-12 11:52:36 -03:00
// FIXME: The fallback here should be the `environment encoding` of the importing style sheet.
auto encoding = resource ( ) - > encoding ( ) . value_or ( " utf-8 " ) ;
auto maybe_decoder = TextCodec : : decoder_for ( encoding ) ;
if ( ! maybe_decoder . has_value ( ) ) {
dbgln ( " CSSImportRule: Failed to decode CSS file: {} Unsupported encoding: {} " , resource ( ) - > url ( ) , encoding ) ;
return ;
}
auto & decoder = maybe_decoder . release_value ( ) ;
auto decoded_or_error = TextCodec : : convert_input_to_utf8_using_given_decoder_unless_there_is_a_byte_order_mark ( decoder , resource ( ) - > encoded_data ( ) ) ;
if ( decoded_or_error . is_error ( ) ) {
dbgln ( " CSSImportRule: Failed to decode CSS file: {} Encoding was: {} " , resource ( ) - > url ( ) , encoding ) ;
return ;
}
auto decoded = decoded_or_error . release_value ( ) ;
auto * sheet = parse_css_stylesheet ( CSS : : Parser : : ParsingContext ( * m_document , resource ( ) - > url ( ) ) , decoded , resource ( ) - > url ( ) ) ;
2021-11-18 14:34:53 -03:00
if ( ! sheet ) {
dbgln_if ( CSS_LOADER_DEBUG , " CSSImportRule: Failed to parse stylesheet: {} " , resource ( ) - > url ( ) ) ;
return ;
}
2022-08-07 10:46:44 -03:00
m_style_sheet = sheet ;
2024-08-23 13:47:05 -03:00
m_style_sheet - > set_owner_css_rule ( this ) ;
2022-03-14 16:56:05 -03:00
2022-03-14 16:31:57 -03:00
m_document - > style_computer ( ) . invalidate_rule_cache ( ) ;
2023-08-12 12:28:40 -03:00
m_document - > style_computer ( ) . load_fonts_from_sheet ( * m_style_sheet ) ;
2024-09-04 05:01:08 -03:00
m_document - > invalidate_style ( DOM : : StyleInvalidationReason : : CSSImportRule ) ;
2021-11-18 14:34:53 -03:00
}
2021-02-21 13:36:34 -03:00
}