diff --git a/Base/res/html/error.html b/Base/res/html/error.html new file mode 100644 index 0000000000..058ae0514a --- /dev/null +++ b/Base/res/html/error.html @@ -0,0 +1,21 @@ + + + + Error! + + + +
+ Warning +

Failed to load %s

+
+

Error: %s

+ + diff --git a/Libraries/LibWeb/HtmlView.cpp b/Libraries/LibWeb/HtmlView.cpp index c4224a9f7e..8d28fd4af3 100644 --- a/Libraries/LibWeb/HtmlView.cpp +++ b/Libraries/LibWeb/HtmlView.cpp @@ -346,23 +346,51 @@ void HtmlView::load(const URL& url) if (on_load_start) on_load_start(url); - ResourceLoader::the().load(url, [this, url](auto data) { - if (data.is_null()) { - dbg() << "Load failed!"; - ASSERT_NOT_REACHED(); - } + ResourceLoader::the().load( + url, + [this, url](auto data) { + if (data.is_null()) { + load_error_page(url, "No data"); + return; + } - RefPtr document; - if (url.path().ends_with(".png")) { - document = create_image_document(data, url); - } else { - document = parse_html_document(data, url); - } - ASSERT(document); - set_document(document); - if (on_title_change) - on_title_change(document->title()); - }); + RefPtr document; + if (url.path().ends_with(".png")) { + document = create_image_document(data, url); + } else { + document = parse_html_document(data, url); + } + ASSERT(document); + set_document(document); + if (on_title_change) + 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 diff --git a/Libraries/LibWeb/HtmlView.h b/Libraries/LibWeb/HtmlView.h index c287b4a3dd..0780224e63 100644 --- a/Libraries/LibWeb/HtmlView.h +++ b/Libraries/LibWeb/HtmlView.h @@ -50,6 +50,7 @@ public: void reload(); void load(const URL&); + void load_error_page(const URL&, const String& error); void scroll_to_anchor(const StringView&); URL url() const; diff --git a/Libraries/LibWeb/ResourceLoader.cpp b/Libraries/LibWeb/ResourceLoader.cpp index ac11e40da0..daf2b813eb 100644 --- a/Libraries/LibWeb/ResourceLoader.cpp +++ b/Libraries/LibWeb/ResourceLoader.cpp @@ -26,9 +26,9 @@ #include #include -#include #include #include +#include namespace Web { @@ -45,36 +45,37 @@ ResourceLoader::ResourceLoader() { } -void ResourceLoader::load(const URL& url, Function callback) +void ResourceLoader::load(const URL& url, Function success_callback, Function error_callback) { if (url.protocol() == "file") { auto f = Core::File::construct(); f->set_filename(url.path()); if (!f->open(Core::IODevice::OpenMode::ReadOnly)) { dbg() << "ResourceLoader::load: Error: " << f->error_string(); - callback({}); + if (error_callback) + error_callback(f->error_string()); return; } auto data = f->read_all(); - deferred_invoke([data = move(data), callback = move(callback)](auto&) { - callback(data); + deferred_invoke([data = move(data), success_callback = move(success_callback)](auto&) { + success_callback(data); }); return; } if (url.protocol() == "http") { 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; if (on_load_counter_change) on_load_counter_change(); if (!success) { - dbg() << "HTTP load failed!"; - callback({}); + if (error_callback) + error_callback("HTTP load failed"); return; } - callback(ByteBuffer::copy(payload.data(), payload.size())); + success_callback(ByteBuffer::copy(payload.data(), payload.size())); }; ++m_pending_loads; if (on_load_counter_change) @@ -82,8 +83,8 @@ void ResourceLoader::load(const URL& url, Function call return; } - dbg() << "Unimplemented protocol: " << url.protocol(); - ASSERT_NOT_REACHED(); + if (error_callback) + error_callback(String::format("Protocol not implemented: %s", url.protocol().characters())); } } diff --git a/Libraries/LibWeb/ResourceLoader.h b/Libraries/LibWeb/ResourceLoader.h index fafd5156fd..26f122bbf6 100644 --- a/Libraries/LibWeb/ResourceLoader.h +++ b/Libraries/LibWeb/ResourceLoader.h @@ -41,7 +41,7 @@ class ResourceLoader : public Core::Object { public: static ResourceLoader& the(); - void load(const URL&, Function); + void load(const URL&, Function success_callback, Function error_callback = nullptr); Function on_load_counter_change;