2020-06-06 13:02:44 +02:00
/*
2022-08-04 21:30:33 +02:00
* Copyright ( c ) 2020 - 2022 , Andreas Kling < kling @ serenityos . org >
2020-06-06 13:02:44 +02:00
*
2021-04-22 01:24:48 -07:00
* SPDX - License - Identifier : BSD - 2 - Clause
2020-06-06 13:02:44 +02:00
*/
2021-01-17 18:17:00 +01:00
# include <AK/Debug.h>
2021-08-11 06:09:35 +08:00
# include <AK/JsonArray.h>
2020-06-06 13:02:44 +02:00
# include <AK/LexicalPath.h>
2021-04-22 00:00:06 +02:00
# include <AK/SourceGenerator.h>
2020-06-06 13:02:44 +02:00
# include <LibGemini/Document.h>
# include <LibGfx/ImageDecoder.h>
# include <LibMarkdown/Document.h>
2022-02-12 16:02:56 +02:00
# include <LibWeb/Cookie/ParsedCookie.h>
2020-06-25 23:50:35 +02:00
# include <LibWeb/DOM/Document.h>
2020-06-06 13:02:44 +02:00
# include <LibWeb/DOM/ElementFactory.h>
# include <LibWeb/DOM/Text.h>
2021-11-18 15:01:28 +01:00
# include <LibWeb/HTML/BrowsingContext.h>
2020-09-22 17:53:40 +02:00
# include <LibWeb/HTML/HTMLIFrameElement.h>
2022-08-04 21:30:33 +02:00
# include <LibWeb/HTML/NavigationParams.h>
2021-09-25 23:15:48 +02:00
# include <LibWeb/HTML/Parser/HTMLParser.h>
2020-06-06 13:02:44 +02:00
# include <LibWeb/Loader/FrameLoader.h>
# include <LibWeb/Loader/ResourceLoader.h>
2020-07-28 19:27:41 +02:00
# include <LibWeb/Page/Page.h>
2022-09-16 15:01:47 +02:00
# include <LibWeb/Platform/ImageCodecPlugin.h>
2022-03-28 16:25:17 +04:30
# include <LibWeb/XML/XMLDocumentBuilder.h>
2020-06-06 13:02:44 +02:00
namespace Web {
2022-04-03 16:36:28 +02:00
static String s_default_favicon_path = " /res/icons/16x16/app-browser.png " ;
2021-08-07 04:28:22 +08:00
static RefPtr < Gfx : : Bitmap > s_default_favicon_bitmap ;
2022-04-03 16:36:28 +02:00
void FrameLoader : : set_default_favicon_path ( String path )
{
s_default_favicon_path = move ( path ) ;
}
2021-11-18 15:01:28 +01:00
FrameLoader : : FrameLoader ( HTML : : BrowsingContext & browsing_context )
2021-05-30 12:36:53 +02:00
: m_browsing_context ( browsing_context )
2020-06-06 13:02:44 +02:00
{
2021-08-07 04:28:22 +08:00
if ( ! s_default_favicon_bitmap ) {
2022-04-03 16:36:28 +02:00
s_default_favicon_bitmap = Gfx : : Bitmap : : try_load_from_file ( s_default_favicon_path ) . release_value_but_fixme_should_propagate_errors ( ) ;
2021-08-07 04:28:22 +08:00
VERIFY ( s_default_favicon_bitmap ) ;
}
2020-06-06 13:02:44 +02:00
}
2022-03-14 13:21:51 -06:00
FrameLoader : : ~ FrameLoader ( ) = default ;
2020-06-06 13:02:44 +02:00
2022-04-01 20:58:27 +03:00
static bool build_markdown_document ( DOM : : Document & document , ByteBuffer const & data )
2020-06-06 13:02:44 +02:00
{
auto markdown_document = Markdown : : Document : : parse ( data ) ;
if ( ! markdown_document )
2020-12-13 17:38:03 +01:00
return false ;
2020-06-06 13:02:44 +02:00
2022-02-21 21:54:21 +01:00
auto parser = HTML : : HTMLParser : : create ( document , markdown_document - > render_to_html ( ) , " utf-8 " ) ;
parser - > run ( document . url ( ) ) ;
2020-12-13 17:38:03 +01:00
return true ;
2020-06-06 13:02:44 +02:00
}
2022-04-01 20:58:27 +03:00
static bool build_text_document ( DOM : : Document & document , ByteBuffer const & data )
2020-06-06 13:02:44 +02:00
{
2022-02-26 10:00:49 +01:00
auto html_element = document . create_element ( " html " ) . release_value ( ) ;
2020-12-13 17:38:03 +01:00
document . append_child ( html_element ) ;
2020-06-06 13:02:44 +02:00
2022-02-26 10:00:49 +01:00
auto head_element = document . create_element ( " head " ) . release_value ( ) ;
2020-06-06 13:02:44 +02:00
html_element - > append_child ( head_element ) ;
2022-02-26 10:00:49 +01:00
auto title_element = document . create_element ( " title " ) . release_value ( ) ;
2020-06-06 13:02:44 +02:00
head_element - > append_child ( title_element ) ;
2020-12-13 17:38:03 +01:00
auto title_text = document . create_text_node ( document . url ( ) . basename ( ) ) ;
2020-06-06 13:02:44 +02:00
title_element - > append_child ( title_text ) ;
2022-02-26 10:00:49 +01:00
auto body_element = document . create_element ( " body " ) . release_value ( ) ;
2020-06-06 13:02:44 +02:00
html_element - > append_child ( body_element ) ;
2022-02-26 10:00:49 +01:00
auto pre_element = document . create_element ( " pre " ) . release_value ( ) ;
2020-06-06 13:02:44 +02:00
body_element - > append_child ( pre_element ) ;
2020-12-13 17:38:03 +01:00
pre_element - > append_child ( document . create_text_node ( String : : copy ( data ) ) ) ;
return true ;
2020-06-06 13:02:44 +02:00
}
2021-11-20 10:56:36 +01:00
static bool build_image_document ( DOM : : Document & document , ByteBuffer const & data )
2020-06-06 13:02:44 +02:00
{
2022-09-16 15:01:47 +02:00
auto image = Platform : : ImageCodecPlugin : : the ( ) . decode_image ( data ) ;
2021-11-20 10:56:36 +01:00
if ( ! image . has_value ( ) | | image - > frames . is_empty ( ) )
2021-07-27 01:12:53 +02:00
return false ;
2021-11-20 10:56:36 +01:00
auto const & frame = image - > frames [ 0 ] ;
auto const & bitmap = frame . bitmap ;
2020-12-13 17:38:03 +01:00
if ( ! bitmap )
return false ;
2020-06-06 13:02:44 +02:00
2022-02-26 10:00:49 +01:00
auto html_element = document . create_element ( " html " ) . release_value ( ) ;
2020-12-13 17:38:03 +01:00
document . append_child ( html_element ) ;
2020-06-06 13:02:44 +02:00
2022-02-26 10:00:49 +01:00
auto head_element = document . create_element ( " head " ) . release_value ( ) ;
2020-06-06 13:02:44 +02:00
html_element - > append_child ( head_element ) ;
2022-02-26 10:00:49 +01:00
auto title_element = document . create_element ( " title " ) . release_value ( ) ;
2020-06-06 13:02:44 +02:00
head_element - > append_child ( title_element ) ;
2021-06-29 16:46:16 +02:00
auto basename = LexicalPath : : basename ( document . url ( ) . path ( ) ) ;
2022-08-28 13:42:07 +02:00
auto title_text = document . heap ( ) . allocate < DOM : : Text > ( document . realm ( ) , document , String : : formatted ( " {} [{}x{}] " , basename , bitmap - > width ( ) , bitmap - > height ( ) ) ) ;
title_element - > append_child ( * title_text ) ;
2020-06-06 13:02:44 +02:00
2022-02-26 10:00:49 +01:00
auto body_element = document . create_element ( " body " ) . release_value ( ) ;
2020-06-06 13:02:44 +02:00
html_element - > append_child ( body_element ) ;
2022-02-26 10:00:49 +01:00
auto image_element = document . create_element ( " img " ) . release_value ( ) ;
2020-12-13 17:38:03 +01:00
image_element - > set_attribute ( HTML : : AttributeNames : : src , document . url ( ) . to_string ( ) ) ;
2020-06-06 13:02:44 +02:00
body_element - > append_child ( image_element ) ;
2020-12-13 17:38:03 +01:00
return true ;
2020-06-06 13:02:44 +02:00
}
2022-04-01 20:58:27 +03:00
static bool build_gemini_document ( DOM : : Document & document , ByteBuffer const & data )
2020-06-06 13:02:44 +02:00
{
2020-10-06 11:08:37 -04:00
StringView gemini_data { data } ;
2020-12-13 17:38:03 +01:00
auto gemini_document = Gemini : : Document : : parse ( gemini_data , document . url ( ) ) ;
2020-10-06 11:08:37 -04:00
String html_data = gemini_document - > render_to_html ( ) ;
2021-05-01 21:10:08 +02:00
dbgln_if ( GEMINI_DEBUG , " Gemini data: \n \" \" \" {} \" \" \" " , gemini_data ) ;
dbgln_if ( GEMINI_DEBUG , " Converted to HTML: \n \" \" \" {} \" \" \" " , html_data ) ;
2020-06-06 13:02:44 +02:00
2022-02-21 21:54:21 +01:00
auto parser = HTML : : HTMLParser : : create ( document , html_data , " utf-8 " ) ;
parser - > run ( document . url ( ) ) ;
2020-12-13 17:38:03 +01:00
return true ;
2020-06-06 13:02:44 +02:00
}
2022-04-01 20:58:27 +03:00
static bool build_xml_document ( DOM : : Document & document , ByteBuffer const & data )
2022-03-28 16:25:17 +04:30
{
XML : : Parser parser ( data , { . resolve_external_resource = resolve_xml_resource } ) ;
XMLDocumentBuilder builder { document } ;
auto result = parser . parse_with_listener ( builder ) ;
return ! result . is_error ( ) & & ! builder . has_error ( ) ;
}
2022-04-01 20:58:27 +03:00
bool FrameLoader : : parse_document ( DOM : : Document & document , ByteBuffer const & data )
2020-06-06 13:02:44 +02:00
{
2020-12-13 17:38:03 +01:00
auto & mime_type = document . content_type ( ) ;
2020-09-07 19:45:14 +02:00
if ( mime_type = = " text/html " | | mime_type = = " image/svg+xml " ) {
2021-09-25 23:15:48 +02:00
auto parser = HTML : : HTMLParser : : create_with_uncertain_encoding ( document , data ) ;
2021-05-12 10:47:12 +02:00
parser - > run ( document . url ( ) ) ;
2020-12-13 17:38:03 +01:00
return true ;
2020-09-07 19:45:14 +02:00
}
2022-07-11 17:32:29 +00:00
if ( mime_type . ends_with ( " +xml " sv ) | | mime_type . is_one_of ( " text/xml " , " application/xml " ) )
2022-03-28 16:25:17 +04:30
return build_xml_document ( document , data ) ;
2022-07-11 17:32:29 +00:00
if ( mime_type . starts_with ( " image/ " sv ) )
2020-12-13 17:38:03 +01:00
return build_image_document ( document , data ) ;
2021-03-20 18:46:22 +04:00
if ( mime_type = = " text/plain " | | mime_type = = " application/json " )
2020-12-13 17:38:03 +01:00
return build_text_document ( document , data ) ;
if ( mime_type = = " text/markdown " )
return build_markdown_document ( document , data ) ;
if ( mime_type = = " text/gemini " )
return build_gemini_document ( document , data ) ;
return false ;
2020-06-06 13:02:44 +02:00
}
2021-09-11 21:15:15 -07:00
bool FrameLoader : : load ( LoadRequest & request , Type type )
2020-06-06 13:02:44 +02:00
{
2020-09-28 11:55:26 +02:00
if ( ! request . is_valid ( ) ) {
load_error_page ( request . url ( ) , " Invalid request " ) ;
2020-06-06 13:02:44 +02:00
return false ;
}
2021-05-30 12:36:53 +02:00
if ( ! m_browsing_context . is_frame_nesting_allowed ( request . url ( ) ) ) {
2021-04-19 14:30:08 +02:00
dbgln ( " No further recursion is allowed for the frame, abort load! " ) ;
return false ;
}
2020-09-28 11:55:26 +02:00
auto & url = request . url ( ) ;
2021-05-29 01:27:06 +01:00
if ( type = = Type : : Navigation | | type = = Type : : Reload ) {
2022-09-25 12:28:40 +02:00
if ( auto * page = browsing_context ( ) . page ( ) ) {
if ( & page - > top_level_browsing_context ( ) = = & m_browsing_context )
page - > client ( ) . page_did_start_loading ( url ) ;
}
2020-11-12 18:23:05 +01:00
}
2020-06-06 13:02:44 +02:00
2022-02-17 23:23:01 +00:00
// https://fetch.spec.whatwg.org/#concept-fetch
// Step 12: If request’ s header list does not contain `Accept`, then:
// 1. Let value be `*/*`. (NOTE: Not necessary as we're about to override it)
// 2. A user agent should set value to the first matching statement, if any, switching on request’ s destination:
// -> "document"
// -> "frame"
// -> "iframe"
// `text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8`
// FIXME: This should be case-insensitive.
if ( ! request . headers ( ) . contains ( " Accept " ) )
request . set_header ( " Accept " , " text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 " ) ;
2021-05-29 01:17:36 +01:00
set_resource ( ResourceLoader : : the ( ) . load_resource ( Resource : : Type : : Generic , request ) ) ;
2020-11-07 09:03:52 +00:00
if ( type = = Type : : IFrame )
return true ;
2022-04-03 19:56:15 +02:00
auto * document = browsing_context ( ) . active_document ( ) ;
if ( document & & document - > has_active_favicon ( ) )
return true ;
2020-11-07 09:03:52 +00:00
if ( url . protocol ( ) = = " http " | | url . protocol ( ) = = " https " ) {
2021-09-13 00:33:23 +03:00
AK : : URL favicon_url ;
2020-06-06 13:02:44 +02:00
favicon_url . set_protocol ( url . protocol ( ) ) ;
favicon_url . set_host ( url . host ( ) ) ;
2021-09-13 23:12:16 +03:00
favicon_url . set_port ( url . port_or_default ( ) ) ;
2021-05-27 21:27:51 +02:00
favicon_url . set_paths ( { " favicon.ico " } ) ;
2020-06-06 13:02:44 +02:00
ResourceLoader : : the ( ) . load (
favicon_url ,
2021-04-03 15:11:36 +02:00
[ this , favicon_url ] ( auto data , auto & , auto ) {
2022-04-03 19:56:15 +02:00
// Always fetch the current document
auto * document = this - > browsing_context ( ) . active_document ( ) ;
if ( document & & document - > has_active_favicon ( ) )
return ;
2021-08-07 16:37:26 +08:00
dbgln_if ( SPAM_DEBUG , " Favicon downloaded, {} bytes from {} " , data . size ( ) , favicon_url ) ;
2021-09-24 20:28:03 +05:30
if ( data . is_empty ( ) )
return ;
2021-08-07 04:28:22 +08:00
RefPtr < Gfx : : Bitmap > favicon_bitmap ;
2022-09-16 15:01:47 +02:00
auto decoded_image = Platform : : ImageCodecPlugin : : the ( ) . decode_image ( data ) ;
2021-11-20 11:25:46 +01:00
if ( ! decoded_image . has_value ( ) | | decoded_image - > frames . is_empty ( ) ) {
dbgln ( " Could not decode favicon {} " , favicon_url ) ;
2021-08-07 04:28:22 +08:00
} else {
2021-11-20 11:25:46 +01:00
favicon_bitmap = decoded_image - > frames [ 0 ] . bitmap ;
dbgln_if ( IMAGE_DECODER_DEBUG , " Decoded favicon, {} " , favicon_bitmap - > size ( ) ) ;
2021-07-27 01:12:53 +02:00
}
2021-08-07 04:28:22 +08:00
load_favicon ( favicon_bitmap ) ;
} ,
[ this ] ( auto & , auto ) {
2022-04-03 19:56:15 +02:00
// Always fetch the current document
auto * document = this - > browsing_context ( ) . active_document ( ) ;
if ( document & & document - > has_active_favicon ( ) )
return ;
2021-08-07 04:28:22 +08:00
load_favicon ( ) ;
2020-06-06 13:02:44 +02:00
} ) ;
2021-08-07 04:28:22 +08:00
} else {
load_favicon ( ) ;
2020-06-06 13:02:44 +02:00
}
return true ;
}
2021-09-13 00:33:23 +03:00
bool FrameLoader : : load ( const AK : : URL & url , Type type )
2020-09-28 11:55:26 +02:00
{
2021-08-07 16:37:26 +08:00
dbgln_if ( SPAM_DEBUG , " FrameLoader::load: {} " , url ) ;
2020-09-28 11:55:26 +02:00
if ( ! url . is_valid ( ) ) {
load_error_page ( url , " Invalid URL " ) ;
return false ;
}
2021-05-30 12:36:53 +02:00
auto request = LoadRequest : : create_for_url_on_page ( url , browsing_context ( ) . page ( ) ) ;
2020-09-28 11:55:26 +02:00
return load ( request , type ) ;
}
2021-11-11 00:55:02 +01:00
void FrameLoader : : load_html ( StringView html , const AK : : URL & url )
2020-10-08 21:03:16 +01:00
{
2022-08-04 21:30:33 +02:00
auto response = make < Fetch : : Infrastructure : : Response > ( ) ;
response - > url_list ( ) . append ( url ) ;
HTML : : NavigationParams navigation_params {
. id = { } ,
. request = nullptr ,
. response = move ( response ) ,
. origin = HTML : : Origin { } ,
. policy_container = HTML : : PolicyContainer { } ,
. final_sandboxing_flag_set = HTML : : SandboxingFlagSet { } ,
. cross_origin_opener_policy = HTML : : CrossOriginOpenerPolicy { } ,
. coop_enforcement_result = HTML : : CrossOriginOpenerPolicyEnforcementResult { } ,
. reserved_environment = { } ,
. browsing_context = browsing_context ( ) ,
} ;
auto document = DOM : : Document : : create_and_initialize (
DOM : : Document : : Type : : HTML ,
" text/html " ,
move ( navigation_params ) ) ;
2022-02-21 21:54:21 +01:00
auto parser = HTML : : HTMLParser : : create ( document , html , " utf-8 " ) ;
parser - > run ( url ) ;
2022-09-20 21:44:42 +02:00
browsing_context ( ) . set_active_document ( parser - > document ( ) ) ;
2020-10-08 21:03:16 +01:00
}
2022-04-03 18:01:10 +02:00
static String s_error_page_url = " file:///res/html/error.html " ;
void FrameLoader : : set_error_page_url ( String error_page_url )
{
s_error_page_url = error_page_url ;
}
2021-01-12 01:01:33 +11:00
// FIXME: Use an actual templating engine (our own one when it's built, preferably
// with a way to check these usages at compile time)
2022-04-01 20:58:27 +03:00
void FrameLoader : : load_error_page ( const AK : : URL & failed_url , String const & error )
2020-06-06 13:02:44 +02:00
{
ResourceLoader : : the ( ) . load (
2022-04-03 18:01:10 +02:00
s_error_page_url ,
2021-04-03 15:11:36 +02:00
[ this , failed_url , error ] ( auto data , auto & , auto ) {
2021-02-23 20:42:32 +01:00
VERIFY ( ! data . is_null ( ) ) ;
2021-04-22 00:00:06 +02:00
StringBuilder builder ;
SourceGenerator generator { builder } ;
2021-04-22 10:17:00 +02:00
generator . set ( " failed_url " , escape_html_entities ( failed_url . to_string ( ) ) ) ;
generator . set ( " error " , escape_html_entities ( error ) ) ;
2021-04-22 00:00:06 +02:00
generator . append ( data ) ;
2022-04-06 14:47:06 +02:00
load_html ( generator . as_string_view ( ) , failed_url ) ;
2020-06-06 13:02:44 +02:00
} ,
2021-04-03 15:11:36 +02:00
[ ] ( auto & error , auto ) {
2021-01-17 18:17:00 +01:00
dbgln ( " Failed to load error page: {} " , error ) ;
2021-02-23 20:42:32 +01:00
VERIFY_NOT_REACHED ( ) ;
2020-06-06 13:02:44 +02:00
} ) ;
}
2021-08-07 04:28:22 +08:00
void FrameLoader : : load_favicon ( RefPtr < Gfx : : Bitmap > bitmap )
{
if ( auto * page = browsing_context ( ) . page ( ) ) {
if ( bitmap )
page - > client ( ) . page_did_change_favicon ( * bitmap ) ;
2022-04-03 16:36:28 +02:00
else if ( s_default_favicon_bitmap )
2021-08-07 04:28:22 +08:00
page - > client ( ) . page_did_change_favicon ( * s_default_favicon_bitmap ) ;
}
}
2022-02-12 16:02:56 +02:00
void FrameLoader : : store_response_cookies ( AK : : URL const & url , String const & cookies )
{
auto * page = browsing_context ( ) . page ( ) ;
if ( ! page )
return ;
auto set_cookie_json_value = MUST ( JsonValue : : from_string ( cookies ) ) ;
VERIFY ( set_cookie_json_value . type ( ) = = JsonValue : : Type : : Array ) ;
2022-04-01 20:58:27 +03:00
for ( auto const & set_cookie_entry : set_cookie_json_value . as_array ( ) . values ( ) ) {
2022-02-12 16:02:56 +02:00
VERIFY ( set_cookie_entry . type ( ) = = JsonValue : : Type : : String ) ;
auto cookie = Cookie : : parse_cookie ( set_cookie_entry . as_string ( ) ) ;
if ( ! cookie . has_value ( ) )
continue ;
page - > client ( ) . page_did_set_cookie ( url , cookie . value ( ) , Cookie : : Source : : Http ) ; // FIXME: Determine cookie source correctly
}
}
2020-06-06 13:38:08 +02:00
void FrameLoader : : resource_did_load ( )
{
auto url = resource ( ) - > url ( ) ;
2022-02-12 16:02:56 +02:00
if ( auto set_cookie = resource ( ) - > response_headers ( ) . get ( " Set-Cookie " ) ; set_cookie . has_value ( ) )
store_response_cookies ( url , * set_cookie ) ;
2022-02-12 15:42:48 +02:00
// For 3xx (Redirection) responses, the Location value refers to the preferred target resource for automatically redirecting the request.
auto status_code = resource ( ) - > status_code ( ) ;
if ( status_code . has_value ( ) & & * status_code > = 300 & & * status_code < = 399 ) {
auto location = resource ( ) - > response_headers ( ) . get ( " Location " ) ;
if ( location . has_value ( ) ) {
if ( m_redirects_count > maximum_redirects_allowed ) {
m_redirects_count = 0 ;
load_error_page ( url , " Too many redirects " ) ;
return ;
}
m_redirects_count + + ;
load ( url . complete_url ( location . value ( ) ) , FrameLoader : : Type : : Navigation ) ;
2021-05-11 22:22:56 +03:00
return ;
}
2020-06-06 13:38:08 +02:00
}
2021-05-11 22:22:56 +03:00
m_redirects_count = 0 ;
2020-06-06 13:38:08 +02:00
2021-05-12 10:21:00 +02:00
if ( resource ( ) - > has_encoding ( ) ) {
2021-08-07 16:37:26 +08:00
dbgln_if ( RESOURCE_DEBUG , " This content has MIME type '{}', encoding '{}' " , resource ( ) - > mime_type ( ) , resource ( ) - > encoding ( ) . value ( ) ) ;
2021-05-12 10:21:00 +02:00
} else {
2021-08-07 16:37:26 +08:00
dbgln_if ( RESOURCE_DEBUG , " This content has MIME type '{}', encoding unknown " , resource ( ) - > mime_type ( ) ) ;
2021-05-12 10:21:00 +02:00
}
2020-12-13 17:38:03 +01:00
2022-08-25 19:04:27 +01:00
auto final_sandboxing_flag_set = HTML : : SandboxingFlagSet { } ;
// (Part of https://html.spec.whatwg.org/#navigating-across-documents)
// 3. Let responseOrigin be the result of determining the origin given browsingContext, resource's url, finalSandboxFlags, and incumbentNavigationOrigin.
// FIXME: Pass incumbentNavigationOrigin
auto response_origin = HTML : : determine_the_origin ( browsing_context ( ) , url , final_sandboxing_flag_set , { } ) ;
2022-08-04 21:30:33 +02:00
auto response = make < Fetch : : Infrastructure : : Response > ( ) ;
response - > url_list ( ) . append ( url ) ;
HTML : : NavigationParams navigation_params {
. id = { } ,
. request = nullptr ,
. response = move ( response ) ,
2022-08-25 19:04:27 +01:00
. origin = move ( response_origin ) ,
2022-08-04 21:30:33 +02:00
. policy_container = HTML : : PolicyContainer { } ,
2022-08-25 19:04:27 +01:00
. final_sandboxing_flag_set = move ( final_sandboxing_flag_set ) ,
2022-08-04 21:30:33 +02:00
. cross_origin_opener_policy = HTML : : CrossOriginOpenerPolicy { } ,
. coop_enforcement_result = HTML : : CrossOriginOpenerPolicyEnforcementResult { } ,
. reserved_environment = { } ,
. browsing_context = browsing_context ( ) ,
} ;
auto document = DOM : : Document : : create_and_initialize (
DOM : : Document : : Type : : HTML ,
" text/html " ,
move ( navigation_params ) ) ;
2020-12-13 17:38:03 +01:00
document - > set_url ( url ) ;
2021-05-12 10:32:41 +02:00
document - > set_encoding ( resource ( ) - > encoding ( ) ) ;
2020-12-13 17:38:03 +01:00
document - > set_content_type ( resource ( ) - > mime_type ( ) ) ;
2020-06-06 14:06:37 +02:00
2021-09-09 13:14:32 +02:00
browsing_context ( ) . set_active_document ( document ) ;
2022-09-21 17:12:00 +02:00
if ( auto * page = browsing_context ( ) . page ( ) )
page - > client ( ) . page_did_create_main_document ( ) ;
2020-12-13 17:38:03 +01:00
if ( ! parse_document ( * document , resource ( ) - > encoded_data ( ) ) ) {
2020-06-06 14:06:37 +02:00
load_error_page ( url , " Failed to parse content. " ) ;
return ;
}
2020-06-06 13:38:08 +02:00
if ( ! url . fragment ( ) . is_empty ( ) )
2021-05-30 12:36:53 +02:00
browsing_context ( ) . scroll_to_anchor ( url . fragment ( ) ) ;
2021-09-08 11:56:50 +02:00
else
2022-04-06 15:32:38 +02:00
browsing_context ( ) . scroll_to ( { 0 , 0 } ) ;
2020-09-22 17:53:40 +02:00
2021-05-30 12:36:53 +02:00
if ( auto * page = browsing_context ( ) . page ( ) )
2020-12-08 21:44:42 +01:00
page - > client ( ) . page_did_finish_loading ( url ) ;
2020-06-06 13:38:08 +02:00
}
void FrameLoader : : resource_did_fail ( )
{
load_error_page ( resource ( ) - > url ( ) , resource ( ) - > error ( ) ) ;
}
2020-06-06 13:02:44 +02:00
}