mirror of
https://github.com/RGBCube/serenity
synced 2025-05-30 23:18:10 +00:00
Browser: Add error page
Add a simple HTML error page that gets loaded into the HtmlView when loading the page fails. Closes #1210 and #1516
This commit is contained in:
parent
b1365d94f4
commit
021d78f8f7
5 changed files with 79 additions and 28 deletions
21
Base/res/html/error.html
Normal file
21
Base/res/html/error.html
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Error!</title>
|
||||||
|
<style>
|
||||||
|
h1 {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
header {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<img src="file:///res/icons/32x32/msgbox-warning.png" alt="Warning" width="24" height="24">
|
||||||
|
<h1>Failed to load %s</h1>
|
||||||
|
</header>
|
||||||
|
<p>Error: %s</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -346,23 +346,51 @@ void HtmlView::load(const URL& url)
|
||||||
if (on_load_start)
|
if (on_load_start)
|
||||||
on_load_start(url);
|
on_load_start(url);
|
||||||
|
|
||||||
ResourceLoader::the().load(url, [this, url](auto data) {
|
ResourceLoader::the().load(
|
||||||
if (data.is_null()) {
|
url,
|
||||||
dbg() << "Load failed!";
|
[this, url](auto data) {
|
||||||
ASSERT_NOT_REACHED();
|
if (data.is_null()) {
|
||||||
}
|
load_error_page(url, "No data");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
RefPtr<Document> document;
|
RefPtr<Document> document;
|
||||||
if (url.path().ends_with(".png")) {
|
if (url.path().ends_with(".png")) {
|
||||||
document = create_image_document(data, url);
|
document = create_image_document(data, url);
|
||||||
} else {
|
} else {
|
||||||
document = parse_html_document(data, url);
|
document = parse_html_document(data, url);
|
||||||
}
|
}
|
||||||
ASSERT(document);
|
ASSERT(document);
|
||||||
set_document(document);
|
set_document(document);
|
||||||
if (on_title_change)
|
if (on_title_change)
|
||||||
on_title_change(document->title());
|
on_title_change(document->title());
|
||||||
});
|
},
|
||||||
|
[this, url](auto error) {
|
||||||
|
load_error_page(url, error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void HtmlView::load_error_page(const URL& failed_url, const String& error)
|
||||||
|
{
|
||||||
|
auto error_page_url = "file:///res/html/error.html";
|
||||||
|
ResourceLoader::the().load(
|
||||||
|
error_page_url,
|
||||||
|
[this, failed_url, error](auto data) {
|
||||||
|
ASSERT(!data.is_null());
|
||||||
|
auto html = String::format(
|
||||||
|
String::copy(data).characters(),
|
||||||
|
escape_html_entities(failed_url.to_string()).characters(),
|
||||||
|
escape_html_entities(error).characters());
|
||||||
|
auto document = parse_html_document(html, failed_url);
|
||||||
|
ASSERT(document);
|
||||||
|
set_document(document);
|
||||||
|
if (on_title_change)
|
||||||
|
on_title_change(document->title());
|
||||||
|
},
|
||||||
|
[](auto error) {
|
||||||
|
dbg() << "Failed to load error page: " << error;
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const LayoutDocument* HtmlView::layout_root() const
|
const LayoutDocument* HtmlView::layout_root() const
|
||||||
|
|
|
@ -50,6 +50,7 @@ public:
|
||||||
|
|
||||||
void reload();
|
void reload();
|
||||||
void load(const URL&);
|
void load(const URL&);
|
||||||
|
void load_error_page(const URL&, const String& error);
|
||||||
void scroll_to_anchor(const StringView&);
|
void scroll_to_anchor(const StringView&);
|
||||||
|
|
||||||
URL url() const;
|
URL url() const;
|
||||||
|
|
|
@ -26,9 +26,9 @@
|
||||||
|
|
||||||
#include <AK/SharedBuffer.h>
|
#include <AK/SharedBuffer.h>
|
||||||
#include <LibCore/File.h>
|
#include <LibCore/File.h>
|
||||||
#include <LibWeb/ResourceLoader.h>
|
|
||||||
#include <LibProtocol/Client.h>
|
#include <LibProtocol/Client.h>
|
||||||
#include <LibProtocol/Download.h>
|
#include <LibProtocol/Download.h>
|
||||||
|
#include <LibWeb/ResourceLoader.h>
|
||||||
|
|
||||||
namespace Web {
|
namespace Web {
|
||||||
|
|
||||||
|
@ -45,36 +45,37 @@ ResourceLoader::ResourceLoader()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceLoader::load(const URL& url, Function<void(const ByteBuffer&)> callback)
|
void ResourceLoader::load(const URL& url, Function<void(const ByteBuffer&)> success_callback, Function<void(const String&)> error_callback)
|
||||||
{
|
{
|
||||||
if (url.protocol() == "file") {
|
if (url.protocol() == "file") {
|
||||||
auto f = Core::File::construct();
|
auto f = Core::File::construct();
|
||||||
f->set_filename(url.path());
|
f->set_filename(url.path());
|
||||||
if (!f->open(Core::IODevice::OpenMode::ReadOnly)) {
|
if (!f->open(Core::IODevice::OpenMode::ReadOnly)) {
|
||||||
dbg() << "ResourceLoader::load: Error: " << f->error_string();
|
dbg() << "ResourceLoader::load: Error: " << f->error_string();
|
||||||
callback({});
|
if (error_callback)
|
||||||
|
error_callback(f->error_string());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data = f->read_all();
|
auto data = f->read_all();
|
||||||
deferred_invoke([data = move(data), callback = move(callback)](auto&) {
|
deferred_invoke([data = move(data), success_callback = move(success_callback)](auto&) {
|
||||||
callback(data);
|
success_callback(data);
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (url.protocol() == "http") {
|
if (url.protocol() == "http") {
|
||||||
auto download = protocol_client().start_download(url.to_string());
|
auto download = protocol_client().start_download(url.to_string());
|
||||||
download->on_finish = [this, callback = move(callback)](bool success, const ByteBuffer& payload, auto) {
|
download->on_finish = [this, success_callback = move(success_callback), error_callback = move(error_callback)](bool success, const ByteBuffer& payload, auto) {
|
||||||
--m_pending_loads;
|
--m_pending_loads;
|
||||||
if (on_load_counter_change)
|
if (on_load_counter_change)
|
||||||
on_load_counter_change();
|
on_load_counter_change();
|
||||||
if (!success) {
|
if (!success) {
|
||||||
dbg() << "HTTP load failed!";
|
if (error_callback)
|
||||||
callback({});
|
error_callback("HTTP load failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
callback(ByteBuffer::copy(payload.data(), payload.size()));
|
success_callback(ByteBuffer::copy(payload.data(), payload.size()));
|
||||||
};
|
};
|
||||||
++m_pending_loads;
|
++m_pending_loads;
|
||||||
if (on_load_counter_change)
|
if (on_load_counter_change)
|
||||||
|
@ -82,8 +83,8 @@ void ResourceLoader::load(const URL& url, Function<void(const ByteBuffer&)> call
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg() << "Unimplemented protocol: " << url.protocol();
|
if (error_callback)
|
||||||
ASSERT_NOT_REACHED();
|
error_callback(String::format("Protocol not implemented: %s", url.protocol().characters()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ class ResourceLoader : public Core::Object {
|
||||||
public:
|
public:
|
||||||
static ResourceLoader& the();
|
static ResourceLoader& the();
|
||||||
|
|
||||||
void load(const URL&, Function<void(const ByteBuffer&)>);
|
void load(const URL&, Function<void(const ByteBuffer&)> success_callback, Function<void(const String&)> error_callback = nullptr);
|
||||||
|
|
||||||
Function<void()> on_load_counter_change;
|
Function<void()> on_load_counter_change;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue