/* * Copyright (c) 2020, Andreas Kling * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include namespace Web { NonnullRefPtr Resource::create(Badge, Type type, const LoadRequest& request) { if (type == Type::Image) return adopt(*new ImageResource(request)); return adopt(*new Resource(type, request)); } Resource::Resource(Type type, const LoadRequest& request) : m_request(request) , m_type(type) { } Resource::~Resource() { } void Resource::for_each_client(Function callback) { Vector, 16> clients_copy; clients_copy.ensure_capacity(m_clients.size()); for (auto* client : m_clients) clients_copy.append(client->make_weak_ptr()); for (auto client : clients_copy) { if (client) callback(*client); } } void Resource::did_load(Badge, const ByteBuffer& data, const HashMap& headers) { ASSERT(!m_loaded); m_encoded_data = data; m_response_headers = headers; m_loaded = true; for_each_client([](auto& client) { client.resource_did_load(); }); } void Resource::did_fail(Badge, const String& error) { m_error = error; m_failed = true; for_each_client([](auto& client) { client.resource_did_fail(); }); } void Resource::register_client(Badge, ResourceClient& client) { ASSERT(!m_clients.contains(&client)); m_clients.set(&client); } void Resource::unregister_client(Badge, ResourceClient& client) { ASSERT(m_clients.contains(&client)); m_clients.remove(&client); } void ResourceClient::set_resource(Resource* resource) { if (m_resource) m_resource->unregister_client({}, *this); m_resource = resource; if (m_resource) { m_resource->register_client({}, *this); // Make sure that reused resources also have their load callback fired. if (resource->is_loaded()) resource_did_load(); // Make sure that reused resources also have their fail callback fired. if (resource->is_failed()) resource_did_fail(); } } ResourceClient::~ResourceClient() { if (m_resource) m_resource->unregister_client({}, *this); } }