ladybird/Userland/Libraries/LibWeb/HTML/SharedImageRequest.h
Aliaksandr Kalenik 8ebb4e8047 LibWeb: Forbid sharing image requests across documents
This change addresses the bug where images unable to load when the
reload button in the UI is clicked repeatedly. Before this fix, it was
possible to use SharedImageRequests across multiple documents. However,
when the document that initiated the request is gone, tasks scheduled
on the event loop remain in the fetching state because the originating
document is no longer active. Furthermore, another reason to prohibit
the sharing of image requests across documents is that the "Origin"
header in an image request is dependent on the document.
2023-10-18 10:58:01 +02:00

74 lines
1.9 KiB
C++

/*
* Copyright (c) 2023, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Error.h>
#include <AK/OwnPtr.h>
#include <AK/URL.h>
#include <LibGfx/Size.h>
#include <LibJS/Heap/Handle.h>
#include <LibJS/Heap/HeapFunction.h>
#include <LibJS/SafeFunction.h>
#include <LibWeb/Forward.h>
namespace Web::HTML {
class SharedImageRequest : public JS::Cell {
JS_CELL(ImageRequest, JS::Cell);
public:
[[nodiscard]] static JS::NonnullGCPtr<SharedImageRequest> get_or_create(JS::Realm&, Page&, AK::URL const&);
~SharedImageRequest();
AK::URL const& url() const { return m_url; }
[[nodiscard]] RefPtr<DecodedImageData const> image_data() const;
[[nodiscard]] JS::GCPtr<Fetch::Infrastructure::FetchController> fetch_controller();
void set_fetch_controller(JS::GCPtr<Fetch::Infrastructure::FetchController>);
void fetch_image(JS::Realm&, JS::NonnullGCPtr<Fetch::Infrastructure::Request>);
void add_callbacks(Function<void()> on_finish, Function<void()> on_fail);
bool is_fetching() const;
bool needs_fetching() const;
virtual void visit_edges(JS::Cell::Visitor&) override;
private:
explicit SharedImageRequest(Page&, AK::URL, JS::NonnullGCPtr<DOM::Document>);
void handle_successful_fetch(AK::URL const&, StringView mime_type, ByteBuffer data);
void handle_failed_fetch();
enum class State {
New,
Fetching,
Finished,
Failed,
};
State m_state { State::New };
Page& m_page;
struct Callbacks {
JS::GCPtr<JS::HeapFunction<void()>> on_finish;
JS::GCPtr<JS::HeapFunction<void()>> on_fail;
};
Vector<Callbacks> m_callbacks;
AK::URL m_url;
RefPtr<DecodedImageData const> m_image_data;
JS::GCPtr<Fetch::Infrastructure::FetchController> m_fetch_controller;
JS::GCPtr<DOM::Document> m_document;
};
}