2 This file is part of the KDE libraries
4 Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
5 Copyright (C) 2001 Dirk Mueller (mueller@kde.org)
6 Copyright (C) 2002 Waldo Bastian (bastian@kde.org)
7 Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
8 Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Library General Public
12 License as published by the Free Software Foundation; either
13 version 2 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Library General Public License for more details.
20 You should have received a copy of the GNU Library General Public License
21 along with this library; see the file COPYING.LIB. If not, write to
22 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA.
25 This class provides all functionality needed for loading images, style sheets and html
26 pages from the web. It has a memory cache for these objects.
33 #include "CachedImage.h"
34 #include "CachedResource.h"
35 #include "DocLoader.h"
37 #include "HTMLDocument.h"
38 #include "LoaderFunctions.h"
40 #include "ResourceLoader.h"
41 #include <wtf/Assertions.h>
42 #include <wtf/Vector.h>
48 m_requestsPending.setAutoDelete(true);
53 deleteAllValues(m_requestsLoading);
56 void Loader::load(DocLoader* dl, CachedResource* object, bool incremental)
58 Request* req = new Request(dl, object, incremental);
59 m_requestsPending.append(req);
60 servePendingRequests();
63 void Loader::servePendingRequests()
65 if (m_requestsPending.count() == 0)
68 // get the first pending request
69 Request* req = m_requestsPending.take(0);
71 KURL u(req->cachedObject()->url().deprecatedString());
72 RefPtr<ResourceLoader> loader = ResourceLoader::create(this, "GET", u);
74 if (!req->cachedObject()->accept().isEmpty())
75 loader->addMetaData("accept", req->cachedObject()->accept());
76 if (req->docLoader()) {
77 KURL r = req->docLoader()->doc()->URL();
78 if (r.protocol().startsWith("http") && r.path().isEmpty())
80 loader->addMetaData("referrer", r.url());
81 DeprecatedString domain = r.host();
82 if (req->docLoader()->doc()->isHTMLDocument())
83 domain = static_cast<HTMLDocument*>(req->docLoader()->doc())->domain().deprecatedString();
86 if (loader->start(req->docLoader()))
87 m_requestsLoading.add(loader.get(), req);
90 void Loader::receivedAllData(ResourceLoader* job, PlatformData allData)
92 RequestMap::iterator i = m_requestsLoading.find(job);
93 if (i == m_requestsLoading.end())
96 Request* req = i->second;
97 m_requestsLoading.remove(i);
99 CachedResource* object = req->cachedObject();
100 DocLoader* docLoader = req->docLoader();
102 if (job->error() || job->isErrorPage()) {
103 docLoader->setLoadInProgress(true);
105 docLoader->setLoadInProgress(false);
106 Cache::remove(object);
108 docLoader->setLoadInProgress(true);
109 object->data(req->buffer(), true);
110 object->setAllData(allData);
111 docLoader->setLoadInProgress(false);
117 servePendingRequests();
120 void Loader::receivedResponse(ResourceLoader* job, PlatformResponse response)
122 Request* req = m_requestsLoading.get(job);
127 ASSERT(!response.isEmpty());
130 req->cachedObject()->setResponse(response);
131 req->cachedObject()->setExpireDate(CacheObjectExpiresTime(req->docLoader(), response), false);
133 DeprecatedString chs = job->queryMetaData("charset").deprecatedString();
135 req->cachedObject()->setCharset(chs);
137 if (req->isMultipart()) {
138 ASSERT(req->cachedObject()->isImage());
139 static_cast<CachedImage*>(req->cachedObject())->clear();
140 if (req->docLoader()->frame())
141 req->docLoader()->frame()->checkCompleted();
142 } else if (ResponseIsMultipart(response)) {
143 req->setIsMultipart(true);
144 if (!req->cachedObject()->isImage())
149 void Loader::receivedData(ResourceLoader* job, const char* data, int size)
151 Request* request = m_requestsLoading.get(job);
155 CachedResource* object = request->cachedObject();
156 Vector<char>& buffer = object->bufferData(data, size, request);
159 if (request->isMultipart())
160 // The loader delivers the data in a multipart section all at once, send eof.
161 object->data(buffer, true);
162 else if (request->isIncremental())
163 object->data(buffer, false);
166 int Loader::numRequests(DocLoader* dl) const
168 // FIXME: Maybe we should keep a collection of requests by DocLoader, so we can do this instantly.
172 DeprecatedPtrListIterator<Request> pIt(m_requestsPending);
173 for (; pIt.current(); ++pIt) {
174 if (pIt.current()->docLoader() == dl)
178 RequestMap::const_iterator end = m_requestsLoading.end();
179 for (RequestMap::const_iterator i = m_requestsLoading.begin(); !(i == end); ++i) {
180 Request* r = i->second;
181 res += (r->docLoader() == dl && !r->isMultipart());
184 DeprecatedPtrListIterator<Request> bdIt(m_requestsBackgroundDecoding);
185 for (; bdIt.current(); ++bdIt)
186 if (bdIt.current()->docLoader() == dl)
189 if (dl->loadInProgress())
195 void Loader::cancelRequests(DocLoader* dl)
197 DeprecatedPtrListIterator<Request> pIt(m_requestsPending);
198 while (pIt.current()) {
199 if (pIt.current()->docLoader() == dl) {
200 Cache::remove(pIt.current()->cachedObject());
201 m_requestsPending.remove(pIt);
206 Vector<ResourceLoader*, 256> jobsToCancel;
208 RequestMap::iterator end = m_requestsLoading.end();
209 for (RequestMap::iterator i = m_requestsLoading.begin(); i != end; ++i) {
210 Request* r = i->second;
211 if (r->docLoader() == dl)
212 jobsToCancel.append(i->first);
215 for (unsigned i = 0; i < jobsToCancel.size(); ++i) {
216 ResourceLoader* job = jobsToCancel[i];
217 Request* r = m_requestsLoading.get(job);
218 m_requestsLoading.remove(job);
219 Cache::remove(r->cachedObject());
223 DeprecatedPtrListIterator<Request> bdIt(m_requestsBackgroundDecoding);
224 while (bdIt.current()) {
225 if (bdIt.current()->docLoader() == dl) {
226 Cache::remove(bdIt.current()->cachedObject());
227 m_requestsBackgroundDecoding.remove(bdIt);
233 void Loader::removeBackgroundDecodingRequest(Request* r)
235 if (m_requestsBackgroundDecoding.containsRef(r))
236 m_requestsBackgroundDecoding.remove(r);
239 ResourceLoader* Loader::jobForRequest(const String& URL) const
241 RequestMap::const_iterator end = m_requestsLoading.end();
242 for (RequestMap::const_iterator i = m_requestsLoading.begin(); i != end; ++i) {
243 CachedResource* obj = i->second->cachedObject();
244 if (obj && obj->url() == URL)
250 } //namespace WebCore