mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 13:18:13 +00:00
LibWeb: Pass optional status code to ResourceLoader callbacks
This is needed for XMLHttpRequest, and will certainly be useful for other things, too.
This commit is contained in:
parent
975b209b9b
commit
000ef96613
8 changed files with 42 additions and 39 deletions
|
@ -231,7 +231,7 @@ void HTMLScriptElement::prepare_script()
|
||||||
m_script_filename = url.basename();
|
m_script_filename = url.basename();
|
||||||
ResourceLoader::the().load_sync(
|
ResourceLoader::the().load_sync(
|
||||||
url,
|
url,
|
||||||
[this, url](auto data, auto&) {
|
[this, url](auto data, auto&, auto) {
|
||||||
if (data.is_null()) {
|
if (data.is_null()) {
|
||||||
dbgln("HTMLScriptElement: Failed to load {}", url);
|
dbgln("HTMLScriptElement: Failed to load {}", url);
|
||||||
return;
|
return;
|
||||||
|
@ -239,7 +239,7 @@ void HTMLScriptElement::prepare_script()
|
||||||
m_script_source = String::copy(data);
|
m_script_source = String::copy(data);
|
||||||
script_became_ready();
|
script_became_ready();
|
||||||
},
|
},
|
||||||
[this](auto&) {
|
[this](auto&, auto) {
|
||||||
m_failed_to_load = true;
|
m_failed_to_load = true;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -178,7 +178,7 @@ bool FrameLoader::load(const LoadRequest& request, Type type)
|
||||||
|
|
||||||
ResourceLoader::the().load(
|
ResourceLoader::the().load(
|
||||||
favicon_url,
|
favicon_url,
|
||||||
[this, favicon_url](auto data, auto&) {
|
[this, favicon_url](auto data, auto&, auto) {
|
||||||
dbgln("Favicon downloaded, {} bytes from {}", data.size(), favicon_url);
|
dbgln("Favicon downloaded, {} bytes from {}", data.size(), favicon_url);
|
||||||
auto decoder = Gfx::ImageDecoder::create(data.data(), data.size());
|
auto decoder = Gfx::ImageDecoder::create(data.data(), data.size());
|
||||||
auto bitmap = decoder->bitmap();
|
auto bitmap = decoder->bitmap();
|
||||||
|
@ -226,7 +226,7 @@ void FrameLoader::load_error_page(const URL& failed_url, const String& error)
|
||||||
auto error_page_url = "file:///res/html/error.html";
|
auto error_page_url = "file:///res/html/error.html";
|
||||||
ResourceLoader::the().load(
|
ResourceLoader::the().load(
|
||||||
error_page_url,
|
error_page_url,
|
||||||
[this, failed_url, error](auto data, auto&) {
|
[this, failed_url, error](auto data, auto&, auto) {
|
||||||
VERIFY(!data.is_null());
|
VERIFY(!data.is_null());
|
||||||
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
|
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
|
||||||
auto html = String::format(
|
auto html = String::format(
|
||||||
|
@ -238,7 +238,7 @@ void FrameLoader::load_error_page(const URL& failed_url, const String& error)
|
||||||
VERIFY(document);
|
VERIFY(document);
|
||||||
frame().set_document(document);
|
frame().set_document(document);
|
||||||
},
|
},
|
||||||
[](auto error) {
|
[](auto& error, auto) {
|
||||||
dbgln("Failed to load error page: {}", error);
|
dbgln("Failed to load error page: {}", error);
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
});
|
});
|
||||||
|
|
|
@ -85,11 +85,12 @@ static String mime_type_from_content_type(const String& content_type)
|
||||||
return content_type;
|
return content_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Resource::did_load(Badge<ResourceLoader>, ReadonlyBytes data, const HashMap<String, String, CaseInsensitiveStringTraits>& headers)
|
void Resource::did_load(Badge<ResourceLoader>, ReadonlyBytes data, const HashMap<String, String, CaseInsensitiveStringTraits>& headers, Optional<u32> status_code)
|
||||||
{
|
{
|
||||||
VERIFY(!m_loaded);
|
VERIFY(!m_loaded);
|
||||||
m_encoded_data = ByteBuffer::copy(data);
|
m_encoded_data = ByteBuffer::copy(data);
|
||||||
m_response_headers = headers;
|
m_response_headers = headers;
|
||||||
|
m_status_code = move(status_code);
|
||||||
m_loaded = true;
|
m_loaded = true;
|
||||||
|
|
||||||
auto content_type = headers.get("Content-Type");
|
auto content_type = headers.get("Content-Type");
|
||||||
|
@ -116,9 +117,10 @@ void Resource::did_load(Badge<ResourceLoader>, ReadonlyBytes data, const HashMap
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Resource::did_fail(Badge<ResourceLoader>, const String& error)
|
void Resource::did_fail(Badge<ResourceLoader>, const String& error, Optional<u32> status_code)
|
||||||
{
|
{
|
||||||
m_error = error;
|
m_error = error;
|
||||||
|
m_status_code = move(status_code);
|
||||||
m_failed = true;
|
m_failed = true;
|
||||||
|
|
||||||
for_each_client([](auto& client) {
|
for_each_client([](auto& client) {
|
||||||
|
|
|
@ -77,8 +77,8 @@ public:
|
||||||
|
|
||||||
void for_each_client(Function<void(ResourceClient&)>);
|
void for_each_client(Function<void(ResourceClient&)>);
|
||||||
|
|
||||||
void did_load(Badge<ResourceLoader>, ReadonlyBytes data, const HashMap<String, String, CaseInsensitiveStringTraits>& headers);
|
void did_load(Badge<ResourceLoader>, ReadonlyBytes data, const HashMap<String, String, CaseInsensitiveStringTraits>& headers, Optional<u32> status_code);
|
||||||
void did_fail(Badge<ResourceLoader>, const String& error);
|
void did_fail(Badge<ResourceLoader>, const String& error, Optional<u32> status_code);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
explicit Resource(Type, const LoadRequest&);
|
explicit Resource(Type, const LoadRequest&);
|
||||||
|
@ -93,6 +93,7 @@ private:
|
||||||
String m_encoding;
|
String m_encoding;
|
||||||
String m_mime_type;
|
String m_mime_type;
|
||||||
HashMap<String, String, CaseInsensitiveStringTraits> m_response_headers;
|
HashMap<String, String, CaseInsensitiveStringTraits> m_response_headers;
|
||||||
|
Optional<u32> m_status_code;
|
||||||
HashTable<ResourceClient*> m_clients;
|
HashTable<ResourceClient*> m_clients;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -52,19 +52,19 @@ ResourceLoader::ResourceLoader()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceLoader::load_sync(const URL& url, Function<void(ReadonlyBytes, const HashMap<String, String, CaseInsensitiveStringTraits>& response_headers)> success_callback, Function<void(const String&)> error_callback)
|
void ResourceLoader::load_sync(const URL& url, Function<void(ReadonlyBytes, const HashMap<String, String, CaseInsensitiveStringTraits>& response_headers, Optional<u32> status_code)> success_callback, Function<void(const String&, Optional<u32> status_code)> error_callback)
|
||||||
{
|
{
|
||||||
Core::EventLoop loop;
|
Core::EventLoop loop;
|
||||||
|
|
||||||
load(
|
load(
|
||||||
url,
|
url,
|
||||||
[&](auto data, auto& response_headers) {
|
[&](auto data, auto& response_headers, auto status_code) {
|
||||||
success_callback(data, response_headers);
|
success_callback(data, response_headers, status_code);
|
||||||
loop.quit(0);
|
loop.quit(0);
|
||||||
},
|
},
|
||||||
[&](auto& string) {
|
[&](auto& string, auto status_code) {
|
||||||
if (error_callback)
|
if (error_callback)
|
||||||
error_callback(string);
|
error_callback(string, status_code);
|
||||||
loop.quit(0);
|
loop.quit(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -99,17 +99,17 @@ RefPtr<Resource> ResourceLoader::load_resource(Resource::Type type, const LoadRe
|
||||||
|
|
||||||
load(
|
load(
|
||||||
request,
|
request,
|
||||||
[=](auto data, auto& headers) {
|
[=](auto data, auto& headers, auto status_code) {
|
||||||
const_cast<Resource&>(*resource).did_load({}, data, headers);
|
const_cast<Resource&>(*resource).did_load({}, data, headers, status_code);
|
||||||
},
|
},
|
||||||
[=](auto& error) {
|
[=](auto& error, auto status_code) {
|
||||||
const_cast<Resource&>(*resource).did_fail({}, error);
|
const_cast<Resource&>(*resource).did_fail({}, error, status_code);
|
||||||
});
|
});
|
||||||
|
|
||||||
return resource;
|
return resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceLoader::load(const LoadRequest& request, Function<void(ReadonlyBytes, const HashMap<String, String, CaseInsensitiveStringTraits>& response_headers)> success_callback, Function<void(const String&)> error_callback)
|
void ResourceLoader::load(const LoadRequest& request, Function<void(ReadonlyBytes, const HashMap<String, String, CaseInsensitiveStringTraits>& response_headers, Optional<u32> status_code)> success_callback, Function<void(const String&, Optional<u32> status_code)> error_callback)
|
||||||
{
|
{
|
||||||
auto& url = request.url();
|
auto& url = request.url();
|
||||||
|
|
||||||
|
@ -120,14 +120,14 @@ void ResourceLoader::load(const LoadRequest& request, Function<void(ReadonlyByte
|
||||||
|
|
||||||
if (ContentFilter::the().is_filtered(url)) {
|
if (ContentFilter::the().is_filtered(url)) {
|
||||||
dbgln("\033[32;1mResourceLoader::load: URL was filtered! {}\033[0m", url);
|
dbgln("\033[32;1mResourceLoader::load: URL was filtered! {}\033[0m", url);
|
||||||
error_callback("URL was filtered");
|
error_callback("URL was filtered", {});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (url.protocol() == "about") {
|
if (url.protocol() == "about") {
|
||||||
dbgln("Loading about: URL {}", url);
|
dbgln("Loading about: URL {}", url);
|
||||||
deferred_invoke([success_callback = move(success_callback)](auto&) {
|
deferred_invoke([success_callback = move(success_callback)](auto&) {
|
||||||
success_callback(String::empty().to_byte_buffer(), {});
|
success_callback(String::empty().to_byte_buffer(), {}, {});
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -145,7 +145,7 @@ void ResourceLoader::load(const LoadRequest& request, Function<void(ReadonlyByte
|
||||||
data = url.data_payload().to_byte_buffer();
|
data = url.data_payload().to_byte_buffer();
|
||||||
|
|
||||||
deferred_invoke([data = move(data), success_callback = move(success_callback)](auto&) {
|
deferred_invoke([data = move(data), success_callback = move(success_callback)](auto&) {
|
||||||
success_callback(data, {});
|
success_callback(data, {}, {});
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -156,13 +156,13 @@ void ResourceLoader::load(const LoadRequest& request, Function<void(ReadonlyByte
|
||||||
if (!f->open(Core::IODevice::OpenMode::ReadOnly)) {
|
if (!f->open(Core::IODevice::OpenMode::ReadOnly)) {
|
||||||
dbgln("ResourceLoader::load: Error: {}", f->error_string());
|
dbgln("ResourceLoader::load: Error: {}", f->error_string());
|
||||||
if (error_callback)
|
if (error_callback)
|
||||||
error_callback(f->error_string());
|
error_callback(f->error_string(), {});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data = f->read_all();
|
auto data = f->read_all();
|
||||||
deferred_invoke([data = move(data), success_callback = move(success_callback)](auto&) {
|
deferred_invoke([data = move(data), success_callback = move(success_callback)](auto&) {
|
||||||
success_callback(data, {});
|
success_callback(data, {}, {});
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -179,13 +179,13 @@ void ResourceLoader::load(const LoadRequest& request, Function<void(ReadonlyByte
|
||||||
auto download = protocol_client().start_download(request.method(), url.to_string(), headers, request.body());
|
auto download = protocol_client().start_download(request.method(), url.to_string(), headers, request.body());
|
||||||
if (!download) {
|
if (!download) {
|
||||||
if (error_callback)
|
if (error_callback)
|
||||||
error_callback("Failed to initiate load");
|
error_callback("Failed to initiate load", {});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
download->on_buffered_download_finish = [this, success_callback = move(success_callback), error_callback = move(error_callback), download](bool success, auto, auto& response_headers, auto status_code, ReadonlyBytes payload) {
|
download->on_buffered_download_finish = [this, success_callback = move(success_callback), error_callback = move(error_callback), download](bool success, auto, auto& response_headers, auto status_code, ReadonlyBytes payload) {
|
||||||
if (status_code.has_value() && status_code.value() >= 400 && status_code.value() <= 499) {
|
if (status_code.has_value() && status_code.value() >= 400 && status_code.value() <= 499) {
|
||||||
if (error_callback)
|
if (error_callback)
|
||||||
error_callback(String::formatted("HTTP error ({})", status_code.value()));
|
error_callback(String::formatted("HTTP error ({})", status_code.value()), status_code);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
--m_pending_loads;
|
--m_pending_loads;
|
||||||
|
@ -193,14 +193,14 @@ void ResourceLoader::load(const LoadRequest& request, Function<void(ReadonlyByte
|
||||||
on_load_counter_change();
|
on_load_counter_change();
|
||||||
if (!success) {
|
if (!success) {
|
||||||
if (error_callback)
|
if (error_callback)
|
||||||
error_callback("HTTP load failed");
|
error_callback("HTTP load failed", {});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
deferred_invoke([download](auto&) {
|
deferred_invoke([download](auto&) {
|
||||||
// Clear circular reference of `download` captured by copy
|
// Clear circular reference of `download` captured by copy
|
||||||
const_cast<Protocol::Download&>(*download).on_buffered_download_finish = nullptr;
|
const_cast<Protocol::Download&>(*download).on_buffered_download_finish = nullptr;
|
||||||
});
|
});
|
||||||
success_callback(payload, response_headers);
|
success_callback(payload, response_headers, status_code);
|
||||||
};
|
};
|
||||||
download->set_should_buffer_all_input(true);
|
download->set_should_buffer_all_input(true);
|
||||||
download->on_certificate_requested = []() -> Protocol::Download::CertificateAndKey {
|
download->on_certificate_requested = []() -> Protocol::Download::CertificateAndKey {
|
||||||
|
@ -213,10 +213,10 @@ void ResourceLoader::load(const LoadRequest& request, Function<void(ReadonlyByte
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error_callback)
|
if (error_callback)
|
||||||
error_callback(String::formatted("Protocol not implemented: {}", url.protocol()));
|
error_callback(String::formatted("Protocol not implemented: {}", url.protocol()), {});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceLoader::load(const URL& url, Function<void(ReadonlyBytes, const HashMap<String, String, CaseInsensitiveStringTraits>& response_headers)> success_callback, Function<void(const String&)> error_callback)
|
void ResourceLoader::load(const URL& url, Function<void(ReadonlyBytes, const HashMap<String, String, CaseInsensitiveStringTraits>& response_headers, Optional<u32> status_code)> success_callback, Function<void(const String&, Optional<u32> status_code)> error_callback)
|
||||||
{
|
{
|
||||||
LoadRequest request;
|
LoadRequest request;
|
||||||
request.set_url(url);
|
request.set_url(url);
|
||||||
|
|
|
@ -44,9 +44,9 @@ public:
|
||||||
|
|
||||||
RefPtr<Resource> load_resource(Resource::Type, const LoadRequest&);
|
RefPtr<Resource> load_resource(Resource::Type, const LoadRequest&);
|
||||||
|
|
||||||
void load(const LoadRequest&, Function<void(ReadonlyBytes, const HashMap<String, String, CaseInsensitiveStringTraits>& response_headers)> success_callback, Function<void(const String&)> error_callback = nullptr);
|
void load(const LoadRequest&, Function<void(ReadonlyBytes, const HashMap<String, String, CaseInsensitiveStringTraits>& response_headers, Optional<u32> status_code)> success_callback, Function<void(const String&, Optional<u32> status_code)> error_callback = nullptr);
|
||||||
void load(const URL&, Function<void(ReadonlyBytes, const HashMap<String, String, CaseInsensitiveStringTraits>& response_headers)> success_callback, Function<void(const String&)> error_callback = nullptr);
|
void load(const URL&, Function<void(ReadonlyBytes, const HashMap<String, String, CaseInsensitiveStringTraits>& response_headers, Optional<u32> status_code)> success_callback, Function<void(const String&, Optional<u32> status_code)> error_callback = nullptr);
|
||||||
void load_sync(const URL&, Function<void(ReadonlyBytes, const HashMap<String, String, CaseInsensitiveStringTraits>& response_headers)> success_callback, Function<void(const String&)> error_callback = nullptr);
|
void load_sync(const URL&, Function<void(ReadonlyBytes, const HashMap<String, String, CaseInsensitiveStringTraits>& response_headers, Optional<u32> status_code)> success_callback, Function<void(const String&, Optional<u32> status_code)> error_callback = nullptr);
|
||||||
|
|
||||||
Function<void()> on_load_counter_change;
|
Function<void()> on_load_counter_change;
|
||||||
|
|
||||||
|
|
|
@ -228,7 +228,7 @@ DOM::ExceptionOr<void> XMLHttpRequest::send()
|
||||||
// we need to make ResourceLoader give us more detailed updates than just "done" and "error".
|
// we need to make ResourceLoader give us more detailed updates than just "done" and "error".
|
||||||
ResourceLoader::the().load(
|
ResourceLoader::the().load(
|
||||||
request,
|
request,
|
||||||
[weak_this = make_weak_ptr()](auto data, auto&) {
|
[weak_this = make_weak_ptr()](auto data, auto&, auto) {
|
||||||
if (!weak_this)
|
if (!weak_this)
|
||||||
return;
|
return;
|
||||||
auto& xhr = const_cast<XMLHttpRequest&>(*weak_this);
|
auto& xhr = const_cast<XMLHttpRequest&>(*weak_this);
|
||||||
|
@ -248,7 +248,7 @@ DOM::ExceptionOr<void> XMLHttpRequest::send()
|
||||||
xhr.fire_progress_event(EventNames::load, transmitted, length);
|
xhr.fire_progress_event(EventNames::load, transmitted, length);
|
||||||
xhr.fire_progress_event(EventNames::loadend, transmitted, length);
|
xhr.fire_progress_event(EventNames::loadend, transmitted, length);
|
||||||
},
|
},
|
||||||
[weak_this = make_weak_ptr()](auto& error) {
|
[weak_this = make_weak_ptr()](auto& error, auto) {
|
||||||
if (!weak_this)
|
if (!weak_this)
|
||||||
return;
|
return;
|
||||||
dbgln("XHR failed to load: {}", error);
|
dbgln("XHR failed to load: {}", error);
|
||||||
|
|
|
@ -211,11 +211,11 @@ void TestRunner::run()
|
||||||
|
|
||||||
Web::ResourceLoader::the().load_sync(
|
Web::ResourceLoader::the().load_sync(
|
||||||
page_to_load,
|
page_to_load,
|
||||||
[&](auto data, auto&) {
|
[&](auto data, auto&, auto) {
|
||||||
Web::HTML::HTMLDocumentParser parser(*m_page_view->document(), data, "utf-8");
|
Web::HTML::HTMLDocumentParser parser(*m_page_view->document(), data, "utf-8");
|
||||||
parser.run(page_to_load);
|
parser.run(page_to_load);
|
||||||
},
|
},
|
||||||
[page_to_load](auto error) {
|
[page_to_load](auto& error, auto) {
|
||||||
printf("Failed to load test page: %s (%s)", page_to_load.to_string().characters(), error.characters());
|
printf("Failed to load test page: %s (%s)", page_to_load.to_string().characters(), error.characters());
|
||||||
cleanup_and_exit();
|
cleanup_and_exit();
|
||||||
});
|
});
|
||||||
|
@ -317,7 +317,7 @@ JSFileResult TestRunner::run_file_test(const String& test_path)
|
||||||
|
|
||||||
Web::ResourceLoader::the().load_sync(
|
Web::ResourceLoader::the().load_sync(
|
||||||
page_to_load,
|
page_to_load,
|
||||||
[&](auto data, auto&) {
|
[&](auto data, auto&, auto) {
|
||||||
// Create a new parser and immediately get its document to replace the old interpreter.
|
// Create a new parser and immediately get its document to replace the old interpreter.
|
||||||
auto document = Web::DOM::Document::create();
|
auto document = Web::DOM::Document::create();
|
||||||
Web::HTML::HTMLDocumentParser parser(document, data, "utf-8");
|
Web::HTML::HTMLDocumentParser parser(document, data, "utf-8");
|
||||||
|
@ -417,7 +417,7 @@ JSFileResult TestRunner::run_file_test(const String& test_path)
|
||||||
file_result.time_taken = get_time_in_ms() - start_time;
|
file_result.time_taken = get_time_in_ms() - start_time;
|
||||||
m_total_elapsed_time_in_ms += file_result.time_taken;
|
m_total_elapsed_time_in_ms += file_result.time_taken;
|
||||||
},
|
},
|
||||||
[page_to_load](auto error) {
|
[page_to_load](auto& error, auto) {
|
||||||
printf("Failed to load test page: %s (%s)", page_to_load.to_string().characters(), error.characters());
|
printf("Failed to load test page: %s (%s)", page_to_load.to_string().characters(), error.characters());
|
||||||
cleanup_and_exit();
|
cleanup_and_exit();
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue