Coverage Report

Created: 2025-11-02 07:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/serenity/Userland/Libraries/LibWeb/HTML/ImageRequest.cpp
Line
Count
Source
1
/*
2
 * Copyright (c) 2023, Andreas Kling <kling@serenityos.org>
3
 *
4
 * SPDX-License-Identifier: BSD-2-Clause
5
 */
6
7
#include <AK/HashTable.h>
8
#include <LibGfx/Bitmap.h>
9
#include <LibWeb/Fetch/Fetching/Fetching.h>
10
#include <LibWeb/Fetch/Infrastructure/FetchAlgorithms.h>
11
#include <LibWeb/Fetch/Infrastructure/FetchController.h>
12
#include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h>
13
#include <LibWeb/HTML/AnimatedBitmapDecodedImageData.h>
14
#include <LibWeb/HTML/DecodedImageData.h>
15
#include <LibWeb/HTML/ImageRequest.h>
16
#include <LibWeb/HTML/ListOfAvailableImages.h>
17
#include <LibWeb/HTML/SharedResourceRequest.h>
18
#include <LibWeb/Page/Page.h>
19
#include <LibWeb/Platform/ImageCodecPlugin.h>
20
#include <LibWeb/SVG/SVGDecodedImageData.h>
21
22
namespace Web::HTML {
23
24
JS_DEFINE_ALLOCATOR(ImageRequest);
25
26
JS::NonnullGCPtr<ImageRequest> ImageRequest::create(JS::Realm& realm, JS::NonnullGCPtr<Page> page)
27
0
{
28
0
    return realm.heap().allocate<ImageRequest>(realm, page);
29
0
}
30
31
ImageRequest::ImageRequest(JS::NonnullGCPtr<Page> page)
32
0
    : m_page(page)
33
0
{
34
0
}
35
36
ImageRequest::~ImageRequest()
37
0
{
38
0
}
39
40
void ImageRequest::visit_edges(JS::Cell::Visitor& visitor)
41
0
{
42
0
    Base::visit_edges(visitor);
43
0
    visitor.visit(m_shared_resource_request);
44
0
    visitor.visit(m_page);
45
0
    visitor.visit(m_image_data);
46
0
}
47
48
// https://html.spec.whatwg.org/multipage/images.html#img-available
49
bool ImageRequest::is_available() const
50
0
{
51
    // When an image request's state is either partially available or completely available, the image request is said to be available.
52
0
    return m_state == State::PartiallyAvailable || m_state == State::CompletelyAvailable;
53
0
}
54
55
bool ImageRequest::is_fetching() const
56
0
{
57
0
    return m_shared_resource_request && m_shared_resource_request->is_fetching();
58
0
}
59
60
ImageRequest::State ImageRequest::state() const
61
0
{
62
0
    return m_state;
63
0
}
64
65
void ImageRequest::set_state(State state)
66
0
{
67
0
    m_state = state;
68
0
}
69
70
URL::URL const& ImageRequest::current_url() const
71
0
{
72
0
    return m_current_url;
73
0
}
74
75
void ImageRequest::set_current_url(JS::Realm& realm, URL::URL url)
76
0
{
77
0
    m_current_url = move(url);
78
0
    if (m_current_url.is_valid())
79
0
        m_shared_resource_request = SharedResourceRequest::get_or_create(realm, m_page, m_current_url);
80
0
}
81
82
// https://html.spec.whatwg.org/multipage/images.html#abort-the-image-request
83
void abort_the_image_request(JS::Realm&, ImageRequest* image_request)
84
0
{
85
    // 1. If image request is null, then return.
86
0
    if (!image_request)
87
0
        return;
88
89
    // 2. Forget image request's image data, if any.
90
0
    image_request->set_image_data(nullptr);
91
92
    // 3. Abort any instance of the fetching algorithm for image request,
93
    //    discarding any pending tasks generated by that algorithm.
94
    // AD-HOC: We simply don't do this, since our SharedResourceRequest may be used by someone else.
95
0
}
96
97
JS::GCPtr<DecodedImageData> ImageRequest::image_data() const
98
0
{
99
0
    return m_image_data;
100
0
}
101
102
void ImageRequest::set_image_data(JS::GCPtr<DecodedImageData> data)
103
0
{
104
0
    m_image_data = data;
105
0
}
106
107
// https://html.spec.whatwg.org/multipage/images.html#prepare-an-image-for-presentation
108
void ImageRequest::prepare_for_presentation(HTMLImageElement&)
109
0
{
110
    // FIXME: 1. Let exifTagMap be the EXIF tags obtained from req's image data, as defined by the relevant codec. [EXIF]
111
    // FIXME: 2. Let physicalWidth and physicalHeight be the width and height obtained from req's image data, as defined by the relevant codec.
112
    // FIXME: 3. Let dimX be the value of exifTagMap's tag 0xA002 (PixelXDimension).
113
    // FIXME: 4. Let dimY be the value of exifTagMap's tag 0xA003 (PixelYDimension).
114
    // FIXME: 5. Let resX be the value of exifTagMap's tag 0x011A (XResolution).
115
    // FIXME: 6. Let resY be the value of exifTagMap's tag 0x011B (YResolution).
116
    // FIXME: 7. Let resUnit be the value of exifTagMap's tag 0x0128 (ResolutionUnit).
117
    // FIXME: 8. If either dimX or dimY is not a positive integer, then return.
118
    // FIXME: 9. If either resX or resY is not a positive floating-point number, then return.
119
    // FIXME: 10. If resUnit is not equal to 2 (Inch), then return.
120
    // FIXME: 11. Let widthFromDensity be the value of physicalWidth, multiplied by 72 and divided by resX.
121
    // FIXME: 12. Let heightFromDensity be the value of physicalHeight, multiplied by 72 and divided by resY.
122
    // FIXME: 13. If widthFromDensity is not equal to dimX or heightFromDensity is not equal to dimY, then return.
123
    // FIXME: 14. If req's image data is CORS-cross-origin, then set img's intrinsic dimensions to dimX and dimY, scale img's pixel data accordingly, and return.
124
    // FIXME: 15. Set req's preferred density-corrected dimensions to a struct with its width set to dimX and its height set to dimY.
125
    // FIXME: 16. Update req's img element's presentation appropriately.
126
0
}
127
128
void ImageRequest::fetch_image(JS::Realm& realm, JS::NonnullGCPtr<Fetch::Infrastructure::Request> request)
129
0
{
130
0
    VERIFY(m_shared_resource_request);
131
0
    m_shared_resource_request->fetch_resource(realm, request);
132
0
}
133
134
void ImageRequest::add_callbacks(Function<void()> on_finish, Function<void()> on_fail)
135
0
{
136
0
    VERIFY(m_shared_resource_request);
137
0
    m_shared_resource_request->add_callbacks(move(on_finish), move(on_fail));
138
0
}
139
140
}