8de53059160fd0e7cf8cb2198f29297b80c8bb0f
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / fetch / Resource.cpp
1 /*
2     Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
3     Copyright (C) 2001 Dirk Mueller (mueller@kde.org)
4     Copyright (C) 2002 Waldo Bastian (bastian@kde.org)
5     Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
6     Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
7
8     This library is free software; you can redistribute it and/or
9     modify it under the terms of the GNU Library General Public
10     License as published by the Free Software Foundation; either
11     version 2 of the License, or (at your option) any later version.
12
13     This library is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16     Library General Public License for more details.
17
18     You should have received a copy of the GNU Library General Public License
19     along with this library; see the file COPYING.LIB.  If not, write to
20     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21     Boston, MA 02110-1301, USA.
22 */
23
24 #include "config.h"
25 #include "core/fetch/Resource.h"
26
27 #include "FetchInitiatorTypeNames.h"
28 #include "core/fetch/CachedMetadata.h"
29 #include "core/fetch/CrossOriginAccessControl.h"
30 #include "core/fetch/MemoryCache.h"
31 #include "core/fetch/ResourceClient.h"
32 #include "core/fetch/ResourceClientWalker.h"
33 #include "core/fetch/ResourceFetcher.h"
34 #include "core/fetch/ResourceLoader.h"
35 #include "core/fetch/ResourcePtr.h"
36 #include "core/inspector/InspectorInstrumentation.h"
37 #include "platform/Logging.h"
38 #include "platform/SharedBuffer.h"
39 #include "platform/weborigin/KURL.h"
40 #include "public/platform/Platform.h"
41 #include "wtf/CurrentTime.h"
42 #include "wtf/MathExtras.h"
43 #include "wtf/RefCountedLeakCounter.h"
44 #include "wtf/StdLibExtras.h"
45 #include "wtf/Vector.h"
46 #include "wtf/text/CString.h"
47
48 using namespace WTF;
49
50 namespace WebCore {
51
52 // These response headers are not copied from a revalidated response to the
53 // cached response headers. For compatibility, this list is based on Chromium's
54 // net/http/http_response_headers.cc.
55 const char* const headersToIgnoreAfterRevalidation[] = {
56     "allow",
57     "connection",
58     "etag",
59     "expires",
60     "keep-alive",
61     "last-modified"
62     "proxy-authenticate",
63     "proxy-connection",
64     "trailer",
65     "transfer-encoding",
66     "upgrade",
67     "www-authenticate",
68     "x-frame-options",
69     "x-xss-protection",
70 };
71
72 // Some header prefixes mean "Don't copy this header from a 304 response.".
73 // Rather than listing all the relevant headers, we can consolidate them into
74 // this list, also grabbed from Chromium's net/http/http_response_headers.cc.
75 const char* const headerPrefixesToIgnoreAfterRevalidation[] = {
76     "content-",
77     "x-content-",
78     "x-webkit-"
79 };
80
81 static inline bool shouldUpdateHeaderAfterRevalidation(const AtomicString& header)
82 {
83     for (size_t i = 0; i < WTF_ARRAY_LENGTH(headersToIgnoreAfterRevalidation); i++) {
84         if (equalIgnoringCase(header, headersToIgnoreAfterRevalidation[i]))
85             return false;
86     }
87     for (size_t i = 0; i < WTF_ARRAY_LENGTH(headerPrefixesToIgnoreAfterRevalidation); i++) {
88         if (header.startsWith(headerPrefixesToIgnoreAfterRevalidation[i], false))
89             return false;
90     }
91     return true;
92 }
93
94 DEFINE_DEBUG_ONLY_GLOBAL(RefCountedLeakCounter, cachedResourceLeakCounter, ("Resource"));
95
96 Resource::Resource(const ResourceRequest& request, Type type)
97     : m_resourceRequest(request)
98     , m_responseTimestamp(currentTime())
99     , m_cancelTimer(this, &Resource::cancelTimerFired)
100     , m_lastDecodedAccessTime(0)
101     , m_loadFinishTime(0)
102     , m_identifier(0)
103     , m_encodedSize(0)
104     , m_decodedSize(0)
105     , m_handleCount(0)
106     , m_preloadCount(0)
107     , m_protectorCount(0)
108     , m_preloadResult(PreloadNotReferenced)
109     , m_cacheLiveResourcePriority(CacheLiveResourcePriorityLow)
110     , m_requestedFromNetworkingLayer(false)
111     , m_loading(false)
112     , m_switchingClientsToRevalidatedResource(false)
113     , m_type(type)
114     , m_status(Pending)
115     , m_wasPurged(false)
116     , m_needsSynchronousCacheHit(false)
117 #ifdef ENABLE_RESOURCE_IS_DELETED_CHECK
118     , m_deleted(false)
119 #endif
120     , m_resourceToRevalidate(0)
121     , m_proxyResource(0)
122 {
123     ASSERT(m_type == unsigned(type)); // m_type is a bitfield, so this tests careless updates of the enum.
124 #ifndef NDEBUG
125     cachedResourceLeakCounter.increment();
126 #endif
127
128     if (!m_resourceRequest.url().hasFragmentIdentifier())
129         return;
130     KURL urlForCache = MemoryCache::removeFragmentIdentifierIfNeeded(m_resourceRequest.url());
131     if (urlForCache.hasFragmentIdentifier())
132         return;
133     m_fragmentIdentifierForRequest = m_resourceRequest.url().fragmentIdentifier();
134     m_resourceRequest.setURL(urlForCache);
135 }
136
137 Resource::~Resource()
138 {
139     ASSERT(!m_resourceToRevalidate); // Should be true because canDelete() checks this.
140     ASSERT(canDelete());
141     RELEASE_ASSERT(!memoryCache()->contains(this));
142     RELEASE_ASSERT(!ResourceCallback::callbackHandler()->isScheduled(this));
143     ASSERT(url().isNull() || memoryCache()->resourceForURL(KURL(ParsedURLString, url())) != this);
144     assertAlive();
145
146 #ifdef ENABLE_RESOURCE_IS_DELETED_CHECK
147     m_deleted = true;
148 #endif
149 #ifndef NDEBUG
150     cachedResourceLeakCounter.decrement();
151 #endif
152 }
153
154 void Resource::failBeforeStarting()
155 {
156     WTF_LOG(ResourceLoading, "Cannot start loading '%s'", url().string().latin1().data());
157     error(Resource::LoadError);
158 }
159
160 void Resource::load(ResourceFetcher* fetcher, const ResourceLoaderOptions& options)
161 {
162     if (!fetcher->frame()) {
163         failBeforeStarting();
164         return;
165     }
166
167     m_options = options;
168     m_loading = true;
169
170     if (!accept().isEmpty())
171         m_resourceRequest.setHTTPAccept(accept());
172
173     // FIXME: It's unfortunate that the cache layer and below get to know anything about fragment identifiers.
174     // We should look into removing the expectation of that knowledge from the platform network stacks.
175     ResourceRequest request(m_resourceRequest);
176     if (!m_fragmentIdentifierForRequest.isNull()) {
177         KURL url = request.url();
178         url.setFragmentIdentifier(m_fragmentIdentifierForRequest);
179         request.setURL(url);
180         m_fragmentIdentifierForRequest = String();
181     }
182     m_status = Pending;
183     if (m_loader) {
184         RELEASE_ASSERT(m_options.synchronousPolicy == RequestSynchronously);
185         m_loader->changeToSynchronous();
186         return;
187     }
188     m_loader = ResourceLoader::create(fetcher, this, request, options);
189     m_loader->start();
190 }
191
192 void Resource::checkNotify()
193 {
194     if (isLoading())
195         return;
196
197     ResourceClientWalker<ResourceClient> w(m_clients);
198     while (ResourceClient* c = w.next())
199         c->notifyFinished(this);
200 }
201
202 void Resource::appendData(const char* data, int length)
203 {
204     TRACE_EVENT0("webkit", "Resource::appendData");
205     ASSERT(!m_resourceToRevalidate);
206     ASSERT(!errorOccurred());
207     if (m_options.dataBufferingPolicy == DoNotBufferData)
208         return;
209     if (m_data)
210         m_data->append(data, length);
211     else
212         m_data = SharedBuffer::createPurgeable(data, length);
213     setEncodedSize(m_data->size());
214 }
215
216 void Resource::setResourceBuffer(PassRefPtr<SharedBuffer> resourceBuffer)
217 {
218     ASSERT(!m_resourceToRevalidate);
219     ASSERT(!errorOccurred());
220     ASSERT(m_options.dataBufferingPolicy == BufferData);
221     m_data = resourceBuffer;
222     setEncodedSize(m_data->size());
223 }
224
225 void Resource::setDataBufferingPolicy(DataBufferingPolicy dataBufferingPolicy)
226 {
227     m_options.dataBufferingPolicy = dataBufferingPolicy;
228     m_data.clear();
229     setEncodedSize(0);
230 }
231
232 void Resource::error(Resource::Status status)
233 {
234     if (m_resourceToRevalidate)
235         revalidationFailed();
236
237     if (!m_error.isNull() && (m_error.isCancellation() || !isPreloaded()))
238         memoryCache()->remove(this);
239
240     setStatus(status);
241     ASSERT(errorOccurred());
242     m_data.clear();
243
244     setLoading(false);
245     checkNotify();
246 }
247
248 void Resource::finishOnePart()
249 {
250     setLoading(false);
251     checkNotify();
252 }
253
254 void Resource::finish(double finishTime)
255 {
256     ASSERT(!m_resourceToRevalidate);
257     ASSERT(!errorOccurred());
258     m_loadFinishTime = finishTime;
259     finishOnePart();
260     if (!errorOccurred())
261         m_status = Cached;
262 }
263
264 bool Resource::passesAccessControlCheck(SecurityOrigin* securityOrigin)
265 {
266     String ignoredErrorDescription;
267     return passesAccessControlCheck(securityOrigin, ignoredErrorDescription);
268 }
269
270 bool Resource::passesAccessControlCheck(SecurityOrigin* securityOrigin, String& errorDescription)
271 {
272     return WebCore::passesAccessControlCheck(m_response, resourceRequest().allowStoredCredentials() ? AllowStoredCredentials : DoNotAllowStoredCredentials, securityOrigin, errorDescription);
273 }
274
275 static double currentAge(const ResourceResponse& response, double responseTimestamp)
276 {
277     // RFC2616 13.2.3
278     // No compensation for latency as that is not terribly important in practice
279     double dateValue = response.date();
280     double apparentAge = std::isfinite(dateValue) ? std::max(0., responseTimestamp - dateValue) : 0;
281     double ageValue = response.age();
282     double correctedReceivedAge = std::isfinite(ageValue) ? std::max(apparentAge, ageValue) : apparentAge;
283     double residentTime = currentTime() - responseTimestamp;
284     return correctedReceivedAge + residentTime;
285 }
286
287 static double freshnessLifetime(const ResourceResponse& response, double responseTimestamp)
288 {
289 #if !OS(ANDROID)
290     // On desktop, local files should be reloaded in case they change.
291     if (response.url().isLocalFile())
292         return 0;
293 #endif
294
295     // Cache other non-http / non-filesystem resources liberally.
296     if (!response.url().protocolIsInHTTPFamily()
297         && !response.url().protocolIs("filesystem"))
298         return std::numeric_limits<double>::max();
299
300     // RFC2616 13.2.4
301     double maxAgeValue = response.cacheControlMaxAge();
302     if (std::isfinite(maxAgeValue))
303         return maxAgeValue;
304     double expiresValue = response.expires();
305     double dateValue = response.date();
306     double creationTime = std::isfinite(dateValue) ? dateValue : responseTimestamp;
307     if (std::isfinite(expiresValue))
308         return expiresValue - creationTime;
309     double lastModifiedValue = response.lastModified();
310     if (std::isfinite(lastModifiedValue))
311         return (creationTime - lastModifiedValue) * 0.1;
312     // If no cache headers are present, the specification leaves the decision to the UA. Other browsers seem to opt for 0.
313     return 0;
314 }
315
316 static bool canUseResponse(const ResourceResponse& response, double responseTimestamp)
317 {
318     if (response.isNull())
319         return false;
320
321     // FIXME: Why isn't must-revalidate considered a reason we can't use the response?
322     if (response.cacheControlContainsNoCache() || response.cacheControlContainsNoStore())
323         return false;
324
325     if (response.httpStatusCode() == 303)  {
326         // Must not be cached.
327         return false;
328     }
329
330     if (response.httpStatusCode() == 302 || response.httpStatusCode() == 307) {
331         // Default to not cacheable.
332         // FIXME: Consider allowing these to be cached if they have headers permitting caching.
333         return false;
334     }
335
336     return currentAge(response, responseTimestamp) <= freshnessLifetime(response, responseTimestamp);
337 }
338
339 const ResourceRequest& Resource::lastResourceRequest()
340 {
341     if (!m_redirectChain.size())
342         return m_resourceRequest;
343     return m_redirectChain.last().m_request;
344 }
345
346 void Resource::willSendRequest(ResourceRequest& request, const ResourceResponse& response)
347 {
348     m_redirectChain.append(RedirectPair(request, response));
349     m_requestedFromNetworkingLayer = true;
350 }
351
352 bool Resource::unlock()
353 {
354     if (!m_data)
355         return false;
356
357     if (!m_data->isLocked())
358         return true;
359
360     if (!memoryCache()->contains(this) || hasClients() || m_handleCount > 1 || m_proxyResource || m_resourceToRevalidate || !m_loadFinishTime || !isSafeToUnlock())
361         return false;
362
363     m_data->unlock();
364     return true;
365 }
366
367 void Resource::responseReceived(const ResourceResponse& response)
368 {
369     setResponse(response);
370     m_responseTimestamp = currentTime();
371     String encoding = response.textEncodingName();
372     if (!encoding.isNull())
373         setEncoding(encoding);
374
375     if (!m_resourceToRevalidate)
376         return;
377     if (response.httpStatusCode() == 304)
378         revalidationSucceeded(response);
379     else
380         revalidationFailed();
381 }
382
383 void Resource::setSerializedCachedMetadata(const char* data, size_t size)
384 {
385     // We only expect to receive cached metadata from the platform once.
386     // If this triggers, it indicates an efficiency problem which is most
387     // likely unexpected in code designed to improve performance.
388     ASSERT(!m_cachedMetadata);
389     ASSERT(!m_resourceToRevalidate);
390
391     m_cachedMetadata = CachedMetadata::deserialize(data, size);
392 }
393
394 void Resource::setCachedMetadata(unsigned dataTypeID, const char* data, size_t size)
395 {
396     // Currently, only one type of cached metadata per resource is supported.
397     // If the need arises for multiple types of metadata per resource this could
398     // be enhanced to store types of metadata in a map.
399     ASSERT(!m_cachedMetadata);
400
401     m_cachedMetadata = CachedMetadata::create(dataTypeID, data, size);
402     const Vector<char>& serializedData = m_cachedMetadata->serialize();
403     blink::Platform::current()->cacheMetadata(m_response.url(), m_response.responseTime(), serializedData.data(), serializedData.size());
404 }
405
406 CachedMetadata* Resource::cachedMetadata(unsigned dataTypeID) const
407 {
408     if (!m_cachedMetadata || m_cachedMetadata->dataTypeID() != dataTypeID)
409         return 0;
410     return m_cachedMetadata.get();
411 }
412
413 void Resource::setCacheLiveResourcePriority(CacheLiveResourcePriority priority)
414 {
415     if (memoryCache()->contains(this) && memoryCache()->isInLiveDecodedResourcesList(this) && cacheLiveResourcePriority() != static_cast<unsigned>(priority)) {
416         memoryCache()->removeFromLiveDecodedResourcesList(this);
417         m_cacheLiveResourcePriority = priority;
418         memoryCache()->insertInLiveDecodedResourcesList(this);
419         memoryCache()->prune();
420     }
421 }
422
423 void Resource::clearLoader()
424 {
425     m_loader = nullptr;
426 }
427
428 void Resource::addClient(ResourceClient* client)
429 {
430     if (addClientToSet(client))
431         didAddClient(client);
432 }
433
434 void Resource::didAddClient(ResourceClient* c)
435 {
436     if (!isLoading() && !stillNeedsLoad())
437         c->notifyFinished(this);
438 }
439
440 static bool shouldSendCachedDataSynchronouslyForType(Resource::Type type)
441 {
442     // Some resources types default to return data synchronously.
443     // For most of these, it's because there are layout tests that
444     // expect data to return synchronously in case of cache hit. In
445     // the case of fonts, there was a performance regression.
446     // FIXME: Get to the point where we don't need to special-case sync/async
447     // behavior for different resource types.
448     if (type == Resource::Image)
449         return true;
450     if (type == Resource::CSSStyleSheet)
451         return true;
452     if (type == Resource::Script)
453         return true;
454     if (type == Resource::Font)
455         return true;
456     return false;
457 }
458
459 bool Resource::addClientToSet(ResourceClient* client)
460 {
461     ASSERT(!isPurgeable());
462
463     if (m_preloadResult == PreloadNotReferenced) {
464         if (isLoaded())
465             m_preloadResult = PreloadReferencedWhileComplete;
466         else if (m_requestedFromNetworkingLayer)
467             m_preloadResult = PreloadReferencedWhileLoading;
468         else
469             m_preloadResult = PreloadReferenced;
470     }
471     if (!hasClients() && memoryCache()->contains(this))
472         memoryCache()->addToLiveResourcesSize(this);
473
474     // If we have existing data to send to the new client and the resource type supprts it, send it asynchronously.
475     if (!m_response.isNull() && !m_proxyResource && !shouldSendCachedDataSynchronouslyForType(type()) && !m_needsSynchronousCacheHit) {
476         m_clientsAwaitingCallback.add(client);
477         ResourceCallback::callbackHandler()->schedule(this);
478         return false;
479     }
480
481     m_clients.add(client);
482     return true;
483 }
484
485 void Resource::removeClient(ResourceClient* client)
486 {
487     if (m_clientsAwaitingCallback.contains(client)) {
488         ASSERT(!m_clients.contains(client));
489         m_clientsAwaitingCallback.remove(client);
490         if (m_clientsAwaitingCallback.isEmpty())
491             ResourceCallback::callbackHandler()->cancel(this);
492     } else {
493         ASSERT(m_clients.contains(client));
494         m_clients.remove(client);
495         didRemoveClient(client);
496     }
497
498     bool deleted = deleteIfPossible();
499     if (!deleted && !hasClients()) {
500         if (memoryCache()->contains(this)) {
501             memoryCache()->removeFromLiveResourcesSize(this);
502             memoryCache()->removeFromLiveDecodedResourcesList(this);
503         }
504         if (!m_switchingClientsToRevalidatedResource)
505             allClientsRemoved();
506
507         // RFC2616 14.9.2:
508         // "no-store: ... MUST make a best-effort attempt to remove the information from volatile storage as promptly as possible"
509         // "... History buffers MAY store such responses as part of their normal operation."
510         // We allow non-secure content to be reused in history, but we do not allow secure content to be reused.
511         if (response().cacheControlContainsNoStore() && url().protocolIs("https")) {
512             memoryCache()->remove(this);
513             memoryCache()->prune();
514         } else {
515             memoryCache()->prune(this);
516         }
517     }
518     // This object may be dead here.
519 }
520
521 void Resource::allClientsRemoved()
522 {
523     if (!m_loader)
524         return;
525     if (m_type == MainResource || m_type == Raw)
526         cancelTimerFired(&m_cancelTimer);
527     else if (!m_cancelTimer.isActive())
528         m_cancelTimer.startOneShot(0, FROM_HERE);
529
530     unlock();
531 }
532
533 void Resource::cancelTimerFired(Timer<Resource>* timer)
534 {
535     ASSERT_UNUSED(timer, timer == &m_cancelTimer);
536     if (hasClients() || !m_loader)
537         return;
538     ResourcePtr<Resource> protect(this);
539     m_loader->cancelIfNotFinishing();
540     if (m_status != Cached)
541         memoryCache()->remove(this);
542 }
543
544 bool Resource::deleteIfPossible()
545 {
546     if (canDelete() && !memoryCache()->contains(this)) {
547         InspectorInstrumentation::willDestroyResource(this);
548         delete this;
549         return true;
550     }
551     return false;
552 }
553
554 void Resource::setDecodedSize(size_t decodedSize)
555 {
556     if (decodedSize == m_decodedSize)
557         return;
558     size_t oldSize = size();
559     m_decodedSize = decodedSize;
560
561     if (memoryCache()->contains(this)) {
562         // Insert into or remove from the live decoded list if necessary.
563         // When inserting into the LiveDecodedResourcesList it is possible
564         // that the m_lastDecodedAccessTime is still zero or smaller than
565         // the m_lastDecodedAccessTime of the current list head. This is a
566         // violation of the invariant that the list is to be kept sorted
567         // by access time. The weakening of the invariant does not pose
568         // a problem. For more details please see: https://bugs.webkit.org/show_bug.cgi?id=30209
569         if (m_decodedSize && !memoryCache()->isInLiveDecodedResourcesList(this) && hasClients())
570             memoryCache()->insertInLiveDecodedResourcesList(this);
571         else if (!m_decodedSize && memoryCache()->isInLiveDecodedResourcesList(this))
572             memoryCache()->removeFromLiveDecodedResourcesList(this);
573
574         // Update the cache's size totals.
575         memoryCache()->update(this, oldSize, size());
576     }
577 }
578
579 void Resource::setEncodedSize(size_t encodedSize)
580 {
581     if (encodedSize == m_encodedSize)
582         return;
583     size_t oldSize = size();
584     m_encodedSize = encodedSize;
585     if (memoryCache()->contains(this))
586         memoryCache()->update(this, oldSize, size());
587 }
588
589 void Resource::didAccessDecodedData(double timeStamp)
590 {
591     m_lastDecodedAccessTime = timeStamp;
592     if (memoryCache()->contains(this)) {
593         if (memoryCache()->isInLiveDecodedResourcesList(this)) {
594             memoryCache()->removeFromLiveDecodedResourcesList(this);
595             memoryCache()->insertInLiveDecodedResourcesList(this);
596         }
597         memoryCache()->prune();
598     }
599 }
600
601 void Resource::finishPendingClients()
602 {
603     while (!m_clientsAwaitingCallback.isEmpty()) {
604         ResourceClient* client = m_clientsAwaitingCallback.begin()->key;
605         m_clientsAwaitingCallback.remove(client);
606         m_clients.add(client);
607         didAddClient(client);
608     }
609 }
610
611 void Resource::prune()
612 {
613     destroyDecodedDataIfPossible();
614     unlock();
615 }
616
617 void Resource::setResourceToRevalidate(Resource* resource)
618 {
619     ASSERT(resource);
620     ASSERT(!m_resourceToRevalidate);
621     ASSERT(resource != this);
622     ASSERT(m_handlesToRevalidate.isEmpty());
623     ASSERT(resource->type() == type());
624
625     WTF_LOG(ResourceLoading, "Resource %p setResourceToRevalidate %p", this, resource);
626
627     // The following assert should be investigated whenever it occurs. Although it should never fire, it currently does in rare circumstances.
628     // https://bugs.webkit.org/show_bug.cgi?id=28604.
629     // So the code needs to be robust to this assert failing thus the "if (m_resourceToRevalidate->m_proxyResource == this)" in Resource::clearResourceToRevalidate.
630     ASSERT(!resource->m_proxyResource);
631
632     resource->m_proxyResource = this;
633     m_resourceToRevalidate = resource;
634 }
635
636 void Resource::clearResourceToRevalidate()
637 {
638     ASSERT(m_resourceToRevalidate);
639     if (m_switchingClientsToRevalidatedResource)
640         return;
641
642     // A resource may start revalidation before this method has been called, so check that this resource is still the proxy resource before clearing it out.
643     if (m_resourceToRevalidate->m_proxyResource == this) {
644         m_resourceToRevalidate->m_proxyResource = 0;
645         m_resourceToRevalidate->deleteIfPossible();
646     }
647     m_handlesToRevalidate.clear();
648     m_resourceToRevalidate = 0;
649     deleteIfPossible();
650 }
651
652 void Resource::switchClientsToRevalidatedResource()
653 {
654     ASSERT(m_resourceToRevalidate);
655     ASSERT(memoryCache()->contains(m_resourceToRevalidate));
656     ASSERT(!memoryCache()->contains(this));
657
658     WTF_LOG(ResourceLoading, "Resource %p switchClientsToRevalidatedResource %p", this, m_resourceToRevalidate);
659
660     m_resourceToRevalidate->m_identifier = m_identifier;
661
662     m_switchingClientsToRevalidatedResource = true;
663     HashSet<ResourcePtrBase*>::iterator end = m_handlesToRevalidate.end();
664     for (HashSet<ResourcePtrBase*>::iterator it = m_handlesToRevalidate.begin(); it != end; ++it) {
665         ResourcePtrBase* handle = *it;
666         handle->m_resource = m_resourceToRevalidate;
667         m_resourceToRevalidate->registerHandle(handle);
668         --m_handleCount;
669     }
670     ASSERT(!m_handleCount);
671     m_handlesToRevalidate.clear();
672
673     Vector<ResourceClient*> clientsToMove;
674     HashCountedSet<ResourceClient*>::iterator end2 = m_clients.end();
675     for (HashCountedSet<ResourceClient*>::iterator it = m_clients.begin(); it != end2; ++it) {
676         ResourceClient* client = it->key;
677         unsigned count = it->value;
678         while (count) {
679             clientsToMove.append(client);
680             --count;
681         }
682     }
683
684     unsigned moveCount = clientsToMove.size();
685     for (unsigned n = 0; n < moveCount; ++n)
686         removeClient(clientsToMove[n]);
687     ASSERT(m_clients.isEmpty());
688
689     for (unsigned n = 0; n < moveCount; ++n)
690         m_resourceToRevalidate->addClientToSet(clientsToMove[n]);
691     for (unsigned n = 0; n < moveCount; ++n) {
692         // Calling didAddClient may do anything, including trying to cancel revalidation.
693         // Assert that it didn't succeed.
694         ASSERT(m_resourceToRevalidate);
695         // Calling didAddClient for a client may end up removing another client. In that case it won't be in the set anymore.
696         if (m_resourceToRevalidate->m_clients.contains(clientsToMove[n]))
697             m_resourceToRevalidate->didAddClient(clientsToMove[n]);
698     }
699     m_switchingClientsToRevalidatedResource = false;
700 }
701
702 void Resource::updateResponseAfterRevalidation(const ResourceResponse& validatingResponse)
703 {
704     m_responseTimestamp = currentTime();
705
706     // RFC2616 10.3.5
707     // Update cached headers from the 304 response
708     const HTTPHeaderMap& newHeaders = validatingResponse.httpHeaderFields();
709     HTTPHeaderMap::const_iterator end = newHeaders.end();
710     for (HTTPHeaderMap::const_iterator it = newHeaders.begin(); it != end; ++it) {
711         // Entity headers should not be sent by servers when generating a 304
712         // response; misconfigured servers send them anyway. We shouldn't allow
713         // such headers to update the original request. We'll base this on the
714         // list defined by RFC2616 7.1, with a few additions for extension headers
715         // we care about.
716         if (!shouldUpdateHeaderAfterRevalidation(it->key))
717             continue;
718         m_response.setHTTPHeaderField(it->key, it->value);
719     }
720 }
721
722 void Resource::revalidationSucceeded(const ResourceResponse& response)
723 {
724     ASSERT(m_resourceToRevalidate);
725     ASSERT(!memoryCache()->contains(m_resourceToRevalidate));
726     ASSERT(m_resourceToRevalidate->isLoaded());
727     ASSERT(memoryCache()->contains(this));
728
729     // Calling evict() can potentially delete revalidatingResource, which we use
730     // below. This mustn't be the case since revalidation means it is loaded
731     // and so canDelete() is false.
732     ASSERT(!canDelete());
733
734     m_resourceToRevalidate->updateResponseAfterRevalidation(response);
735     memoryCache()->replace(m_resourceToRevalidate, this);
736
737     switchClientsToRevalidatedResource();
738     assertAlive();
739     // clearResourceToRevalidate deletes this.
740     clearResourceToRevalidate();
741 }
742
743 void Resource::revalidationFailed()
744 {
745     ASSERT(WTF::isMainThread());
746     WTF_LOG(ResourceLoading, "Revalidation failed for %p", this);
747     ASSERT(resourceToRevalidate());
748     clearResourceToRevalidate();
749 }
750
751 void Resource::registerHandle(ResourcePtrBase* h)
752 {
753     assertAlive();
754     ++m_handleCount;
755     if (m_resourceToRevalidate)
756         m_handlesToRevalidate.add(h);
757 }
758
759 void Resource::unregisterHandle(ResourcePtrBase* h)
760 {
761     assertAlive();
762     ASSERT(m_handleCount > 0);
763     --m_handleCount;
764
765     if (m_resourceToRevalidate)
766         m_handlesToRevalidate.remove(h);
767
768     if (!m_handleCount) {
769         if (deleteIfPossible())
770             return;
771         unlock();
772     } else if (m_handleCount == 1 && memoryCache()->contains(this)) {
773         unlock();
774     }
775 }
776
777 bool Resource::canReuseRedirectChain() const
778 {
779     for (size_t i = 0; i < m_redirectChain.size(); ++i) {
780         if (!canUseResponse(m_redirectChain[i].m_redirectResponse, m_responseTimestamp))
781             return false;
782     }
783     return true;
784 }
785
786 bool Resource::mustRevalidateDueToCacheHeaders() const
787 {
788     return !canUseResponse(m_response, m_responseTimestamp);
789 }
790
791 bool Resource::canUseCacheValidator() const
792 {
793     if (m_loading || errorOccurred())
794         return false;
795
796     if (m_response.cacheControlContainsNoStore())
797         return false;
798     return m_response.hasCacheValidatorFields();
799 }
800
801 bool Resource::isPurgeable() const
802 {
803     return m_data && !m_data->isLocked();
804 }
805
806 bool Resource::wasPurged() const
807 {
808     return m_wasPurged;
809 }
810
811 bool Resource::lock()
812 {
813     if (!m_data)
814         return true;
815     if (m_data->isLocked())
816         return true;
817
818     ASSERT(!hasClients());
819
820     if (!m_data->lock()) {
821         m_wasPurged = true;
822         return false;
823     }
824     return true;
825 }
826
827 size_t Resource::overheadSize() const
828 {
829     static const int kAverageClientsHashMapSize = 384;
830     return sizeof(Resource) + m_response.memoryUsage() + kAverageClientsHashMapSize + m_resourceRequest.url().string().length() * 2;
831 }
832
833 void Resource::didChangePriority(ResourceLoadPriority loadPriority, int intraPriorityValue)
834 {
835     if (m_loader)
836         m_loader->didChangePriority(loadPriority, intraPriorityValue);
837 }
838
839 Resource::ResourceCallback* Resource::ResourceCallback::callbackHandler()
840 {
841     DEFINE_STATIC_LOCAL(ResourceCallback, callbackHandler, ());
842     return &callbackHandler;
843 }
844
845 Resource::ResourceCallback::ResourceCallback()
846     : m_callbackTimer(this, &ResourceCallback::timerFired)
847 {
848 }
849
850 void Resource::ResourceCallback::schedule(Resource* resource)
851 {
852     if (!m_callbackTimer.isActive())
853         m_callbackTimer.startOneShot(0, FROM_HERE);
854     resource->assertAlive();
855     m_resourcesWithPendingClients.add(resource);
856 }
857
858 void Resource::ResourceCallback::cancel(Resource* resource)
859 {
860     resource->assertAlive();
861     m_resourcesWithPendingClients.remove(resource);
862     if (m_callbackTimer.isActive() && m_resourcesWithPendingClients.isEmpty())
863         m_callbackTimer.stop();
864 }
865
866 bool Resource::ResourceCallback::isScheduled(Resource* resource) const
867 {
868     return m_resourcesWithPendingClients.contains(resource);
869 }
870
871 void Resource::ResourceCallback::timerFired(Timer<ResourceCallback>*)
872 {
873     HashSet<Resource*>::iterator end = m_resourcesWithPendingClients.end();
874     Vector<ResourcePtr<Resource> > resources;
875     for (HashSet<Resource*>::iterator it = m_resourcesWithPendingClients.begin(); it != end; ++it)
876         resources.append(*it);
877     m_resourcesWithPendingClients.clear();
878
879     for (size_t i = 0; i < resources.size(); i++) {
880         resources[i]->assertAlive();
881         resources[i]->finishPendingClients();
882         resources[i]->assertAlive();
883     }
884
885     for (size_t i = 0; i < resources.size(); i++)
886         resources[i]->assertAlive();
887 }
888
889 static const char* initatorTypeNameToString(const AtomicString& initiatorTypeName)
890 {
891     if (initiatorTypeName == FetchInitiatorTypeNames::css)
892         return "CSS resource";
893     if (initiatorTypeName == FetchInitiatorTypeNames::document)
894         return "Document";
895     if (initiatorTypeName == FetchInitiatorTypeNames::icon)
896         return "Icon";
897     if (initiatorTypeName == FetchInitiatorTypeNames::internal)
898         return "Internal resource";
899     if (initiatorTypeName == FetchInitiatorTypeNames::link)
900         return "Link element resource";
901     if (initiatorTypeName == FetchInitiatorTypeNames::processinginstruction)
902         return "Processing instruction";
903     if (initiatorTypeName == FetchInitiatorTypeNames::texttrack)
904         return "Text track";
905     if (initiatorTypeName == FetchInitiatorTypeNames::xml)
906         return "XML resource";
907     if (initiatorTypeName == FetchInitiatorTypeNames::xmlhttprequest)
908         return "XMLHttpRequest";
909
910     return "Resource";
911 }
912
913 const char* Resource::resourceTypeToString(Type type, const FetchInitiatorInfo& initiatorInfo)
914 {
915     switch (type) {
916     case Resource::MainResource:
917         return "Main resource";
918     case Resource::Image:
919         return "Image";
920     case Resource::CSSStyleSheet:
921         return "CSS stylesheet";
922     case Resource::Script:
923         return "Script";
924     case Resource::Font:
925         return "Font";
926     case Resource::Raw:
927         return initatorTypeNameToString(initiatorInfo.name);
928     case Resource::SVGDocument:
929         return "SVG document";
930     case Resource::XSLStyleSheet:
931         return "XSL stylesheet";
932     case Resource::LinkPrefetch:
933         return "Link prefetch resource";
934     case Resource::LinkSubresource:
935         return "Link subresource";
936     case Resource::TextTrack:
937         return "Text track";
938     case Resource::Shader:
939         return "Shader";
940     case Resource::ImportResource:
941         return "Imported resource";
942     }
943     ASSERT_NOT_REACHED();
944     return initatorTypeNameToString(initiatorInfo.name);
945 }
946
947 #if !LOG_DISABLED
948 const char* ResourceTypeName(Resource::Type type)
949 {
950     switch (type) {
951     case Resource::MainResource:
952         return "MainResource";
953     case Resource::Image:
954         return "Image";
955     case Resource::CSSStyleSheet:
956         return "CSSStyleSheet";
957     case Resource::Script:
958         return "Script";
959     case Resource::Font:
960         return "Font";
961     case Resource::Raw:
962         return "Raw";
963     case Resource::SVGDocument:
964         return "SVGDocument";
965     case Resource::XSLStyleSheet:
966         return "XSLStyleSheet";
967     case Resource::LinkPrefetch:
968         return "LinkPrefetch";
969     case Resource::LinkSubresource:
970         return "LinkSubresource";
971     case Resource::TextTrack:
972         return "TextTrack";
973     case Resource::Shader:
974         return "Shader";
975     case Resource::ImportResource:
976         return "ImportResource";
977     }
978     ASSERT_NOT_REACHED();
979     return "Unknown";
980 }
981 #endif // !LOG_DISABLED
982
983 }