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