OLD | NEW |
1 /* | 1 /* |
2 Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) | 2 Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) |
3 Copyright (C) 2001 Dirk Mueller (mueller@kde.org) | 3 Copyright (C) 2001 Dirk Mueller (mueller@kde.org) |
4 Copyright (C) 2002 Waldo Bastian (bastian@kde.org) | 4 Copyright (C) 2002 Waldo Bastian (bastian@kde.org) |
5 Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All
rights reserved. | 5 Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All
rights reserved. |
6 Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/ | 6 Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/ |
7 | 7 |
8 This library is free software; you can redistribute it and/or | 8 This library is free software; you can redistribute it and/or |
9 modify it under the terms of the GNU Library General Public | 9 modify it under the terms of the GNU Library General Public |
10 License as published by the Free Software Foundation; either | 10 License as published by the Free Software Foundation; either |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 return true; | 247 return true; |
248 if (resource->stillNeedsLoad()) | 248 if (resource->stillNeedsLoad()) |
249 return true; | 249 return true; |
250 return request.options().synchronousPolicy == RequestSynchronously && resour
ce->isLoading(); | 250 return request.options().synchronousPolicy == RequestSynchronously && resour
ce->isLoading(); |
251 } | 251 } |
252 | 252 |
253 // Limit the number of URLs in m_validatedURLs to avoid memory bloat. | 253 // Limit the number of URLs in m_validatedURLs to avoid memory bloat. |
254 // http://crbug.com/52411 | 254 // http://crbug.com/52411 |
255 static const int kMaxValidatedURLsSize = 10000; | 255 static const int kMaxValidatedURLsSize = 10000; |
256 | 256 |
257 void ResourceFetcher::requestLoadStarted(Resource* resource, const FetchRequest&
request, ResourceLoadStartType type) | 257 void ResourceFetcher::requestLoadStarted(Resource* resource, const FetchRequest&
request, ResourceLoadStartType type, bool isStaticData) |
258 { | 258 { |
259 if (type == ResourceLoadingFromCache) | 259 if (type == ResourceLoadingFromCache) |
260 notifyLoadedFromMemoryCache(resource); | 260 notifyLoadedFromMemoryCache(resource); |
261 | 261 |
262 if (request.resourceRequest().url().protocolIsData() || context().hasSubstit
uteData()) | 262 if (isStaticData) |
263 return; | 263 return; |
264 | 264 |
265 if (type == ResourceLoadingFromCache && !resource->stillNeedsLoad() && !m_va
lidatedURLs.contains(request.resourceRequest().url())) { | 265 if (type == ResourceLoadingFromCache && !resource->stillNeedsLoad() && !m_va
lidatedURLs.contains(request.resourceRequest().url())) { |
266 // Resources loaded from memory cache should be reported the first time
they're used. | 266 // Resources loaded from memory cache should be reported the first time
they're used. |
267 OwnPtr<ResourceTimingInfo> info = ResourceTimingInfo::create(request.opt
ions().initiatorInfo.name, monotonicallyIncreasingTime(), resource->type() == Re
source::MainResource); | 267 OwnPtr<ResourceTimingInfo> info = ResourceTimingInfo::create(request.opt
ions().initiatorInfo.name, monotonicallyIncreasingTime(), resource->type() == Re
source::MainResource); |
268 populateResourceTiming(info.get(), resource, true); | 268 populateResourceTiming(info.get(), resource, true); |
269 m_scheduledResourceTimingReports.append(info.release()); | 269 m_scheduledResourceTimingReports.append(info.release()); |
270 if (!m_resourceTimingReportTimer.isActive()) | 270 if (!m_resourceTimingReportTimer.isActive()) |
271 m_resourceTimingReportTimer.startOneShot(0, FROM_HERE); | 271 m_resourceTimingReportTimer.startOneShot(0, FROM_HERE); |
272 } | 272 } |
273 | 273 |
274 if (m_validatedURLs.size() >= kMaxValidatedURLsSize) { | 274 if (m_validatedURLs.size() >= kMaxValidatedURLsSize) { |
275 m_validatedURLs.clear(); | 275 m_validatedURLs.clear(); |
276 } | 276 } |
277 m_validatedURLs.add(request.resourceRequest().url()); | 277 m_validatedURLs.add(request.resourceRequest().url()); |
278 } | 278 } |
279 | 279 |
280 static PassRefPtr<TraceEvent::ConvertableToTraceFormat> urlForTraceEvent(const K
URL& url) | 280 static PassRefPtr<TraceEvent::ConvertableToTraceFormat> urlForTraceEvent(const K
URL& url) |
281 { | 281 { |
282 RefPtr<TracedValue> value = TracedValue::create(); | 282 RefPtr<TracedValue> value = TracedValue::create(); |
283 value->setString("url", url.string()); | 283 value->setString("url", url.string()); |
284 return value.release(); | 284 return value.release(); |
285 } | 285 } |
286 | 286 |
287 ResourcePtr<Resource> ResourceFetcher::requestResource(FetchRequest& request, co
nst ResourceFactory& factory) | 287 void ResourceFetcher::preCacheData(const FetchRequest& request, const ResourceFa
ctory& factory, const SubstituteData& substituteData) |
| 288 { |
| 289 const KURL& url = request.resourceRequest().url(); |
| 290 ASSERT(url.protocolIsData() || substituteData.isValid()); |
| 291 if ((factory.type() == Resource::MainResource && !substituteData.isValid())
|| factory.type() == Resource::Raw || factory.type() == Resource::Media) |
| 292 return; |
| 293 |
| 294 const String cacheIdentifier = getCacheIdentifier(); |
| 295 if (Resource* oldResource = memoryCache()->resourceForURL(url, cacheIdentifi
er)) { |
| 296 if (!substituteData.isValid()) |
| 297 return; |
| 298 memoryCache()->remove(oldResource); |
| 299 } |
| 300 |
| 301 WebString mimetype; |
| 302 WebString charset; |
| 303 RefPtr<SharedBuffer> data; |
| 304 if (substituteData.isValid()) { |
| 305 mimetype = substituteData.mimeType(); |
| 306 charset = substituteData.textEncoding(); |
| 307 data = substituteData.content(); |
| 308 } else { |
| 309 data = PassRefPtr<SharedBuffer>(Platform::current()->parseDataURL(url, m
imetype, charset)); |
| 310 if (!data) |
| 311 return; |
| 312 } |
| 313 ResourceResponse response(url, mimetype, data->size(), charset, String()); |
| 314 response.setHTTPStatusCode(200); |
| 315 response.setHTTPStatusText("OK"); |
| 316 |
| 317 ResourcePtr<Resource> resource = factory.create(request.resourceRequest(), r
equest.charset()); |
| 318 resource->setNeedsSynchronousCacheHit(substituteData.forceSynchronousLoad())
; |
| 319 resource->setOptions(request.options()); |
| 320 // FIXME: We should provide a body stream here. |
| 321 resource->responseReceived(response, nullptr); |
| 322 resource->setDataBufferingPolicy(BufferData); |
| 323 if (data->size()) |
| 324 resource->setResourceBuffer(data); |
| 325 resource->setIdentifier(createUniqueIdentifier()); |
| 326 resource->setCacheIdentifier(cacheIdentifier); |
| 327 resource->finish(); |
| 328 memoryCache()->add(resource.get()); |
| 329 scheduleDocumentResourcesGC(); |
| 330 } |
| 331 |
| 332 ResourcePtr<Resource> ResourceFetcher::requestResource(FetchRequest& request, co
nst ResourceFactory& factory, const SubstituteData& substituteData) |
288 { | 333 { |
289 ASSERT(request.options().synchronousPolicy == RequestAsynchronously || facto
ry.type() == Resource::Raw); | 334 ASSERT(request.options().synchronousPolicy == RequestAsynchronously || facto
ry.type() == Resource::Raw); |
290 | 335 |
291 context().upgradeInsecureRequest(request); | 336 context().upgradeInsecureRequest(request); |
292 context().addClientHintsIfNecessary(request); | 337 context().addClientHintsIfNecessary(request); |
293 context().addCSPHeaderIfNecessary(factory.type(), request); | 338 context().addCSPHeaderIfNecessary(factory.type(), request); |
294 | 339 |
| 340 bool isStaticData = request.resourceRequest().url().protocolIsData() || subs
tituteData.isValid(); |
| 341 if (isStaticData) |
| 342 preCacheData(request, factory, substituteData); |
| 343 |
295 KURL url = request.resourceRequest().url(); | 344 KURL url = request.resourceRequest().url(); |
296 TRACE_EVENT1("blink", "ResourceFetcher::requestResource", "url", urlForTrace
Event(url)); | 345 TRACE_EVENT1("blink", "ResourceFetcher::requestResource", "url", urlForTrace
Event(url)); |
297 | 346 |
298 WTF_LOG(ResourceLoading, "ResourceFetcher::requestResource '%s', charset '%s
', priority=%d, forPreload=%u, type=%s", url.elidedString().latin1().data(), req
uest.charset().latin1().data(), request.priority(), request.forPreload(), Resour
ceTypeName(factory.type())); | 347 WTF_LOG(ResourceLoading, "ResourceFetcher::requestResource '%s', charset '%s
', priority=%d, forPreload=%u, type=%s", url.elidedString().latin1().data(), req
uest.charset().latin1().data(), request.priority(), request.forPreload(), Resour
ceTypeName(factory.type())); |
299 | 348 |
300 // If only the fragment identifiers differ, it is the same resource. | 349 // If only the fragment identifiers differ, it is the same resource. |
301 url = MemoryCache::removeFragmentIdentifierIfNeeded(url); | 350 url = MemoryCache::removeFragmentIdentifierIfNeeded(url); |
302 | 351 |
303 if (!url.isValid()) | 352 if (!url.isValid()) |
304 return nullptr; | 353 return nullptr; |
(...skipping 14 matching lines...) Expand all Loading... |
319 Vector<String> argv; | 368 Vector<String> argv; |
320 argv.append(Resource::resourceTypeToString(factory.type(), request.o
ptions().initiatorInfo)); | 369 argv.append(Resource::resourceTypeToString(factory.type(), request.o
ptions().initiatorInfo)); |
321 argv.append(url); | 370 argv.append(url); |
322 activityLogger->logEvent("blinkRequestResource", argv.size(), argv.d
ata()); | 371 activityLogger->logEvent("blinkRequestResource", argv.size(), argv.d
ata()); |
323 } | 372 } |
324 } | 373 } |
325 | 374 |
326 // See if we can use an existing resource from the cache. | 375 // See if we can use an existing resource from the cache. |
327 ResourcePtr<Resource> resource = memoryCache()->resourceForURL(url, getCache
Identifier()); | 376 ResourcePtr<Resource> resource = memoryCache()->resourceForURL(url, getCache
Identifier()); |
328 | 377 |
329 const RevalidationPolicy policy = determineRevalidationPolicy(factory.type()
, request, resource.get()); | 378 const RevalidationPolicy policy = determineRevalidationPolicy(factory.type()
, request, resource.get(), isStaticData); |
330 switch (policy) { | 379 switch (policy) { |
331 case Reload: | 380 case Reload: |
332 memoryCache()->remove(resource.get()); | 381 memoryCache()->remove(resource.get()); |
333 // Fall through | 382 // Fall through |
334 case Load: | 383 case Load: |
335 resource = createResourceForLoading(request, request.charset(), factory)
; | 384 resource = createResourceForLoading(request, request.charset(), factory)
; |
336 break; | 385 break; |
337 case Revalidate: | 386 case Revalidate: |
338 resource = createResourceForRevalidation(request, resource.get(), factor
y); | 387 resource = createResourceForRevalidation(request, resource.get(), factor
y); |
339 break; | 388 break; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
390 return request.options().synchronousPolicy == RequestSynchronously ?
resource : nullptr; | 439 return request.options().synchronousPolicy == RequestSynchronously ?
resource : nullptr; |
391 } | 440 } |
392 } | 441 } |
393 | 442 |
394 // FIXME: Temporarily leave main resource caching disabled for chromium, | 443 // FIXME: Temporarily leave main resource caching disabled for chromium, |
395 // see https://bugs.webkit.org/show_bug.cgi?id=107962. Before caching main | 444 // see https://bugs.webkit.org/show_bug.cgi?id=107962. Before caching main |
396 // resources, we should be sure to understand the implications for memory | 445 // resources, we should be sure to understand the implications for memory |
397 // use. | 446 // use. |
398 // Remove main resource from cache to prevent reuse. | 447 // Remove main resource from cache to prevent reuse. |
399 if (factory.type() == Resource::MainResource) { | 448 if (factory.type() == Resource::MainResource) { |
400 ASSERT(policy != Use || context().hasSubstituteData()); | 449 ASSERT(policy != Use || substituteData.isValid()); |
401 ASSERT(policy != Revalidate); | 450 ASSERT(policy != Revalidate); |
402 memoryCache()->remove(resource.get()); | 451 memoryCache()->remove(resource.get()); |
403 } | 452 } |
404 | 453 |
405 requestLoadStarted(resource.get(), request, policy == Use ? ResourceLoadingF
romCache : ResourceLoadingFromNetwork); | 454 requestLoadStarted(resource.get(), request, policy == Use ? ResourceLoadingF
romCache : ResourceLoadingFromNetwork, isStaticData); |
406 | 455 |
407 ASSERT(resource->url() == url.string()); | 456 ASSERT(resource->url() == url.string()); |
408 m_documentResources.set(resource->url(), resource); | 457 m_documentResources.set(resource->url(), resource); |
409 return resource; | 458 return resource; |
410 } | 459 } |
411 | 460 |
412 void ResourceFetcher::resourceTimingReportTimerFired(Timer<ResourceFetcher>* tim
er) | 461 void ResourceFetcher::resourceTimingReportTimerFired(Timer<ResourceFetcher>* tim
er) |
413 { | 462 { |
414 ASSERT_UNUSED(timer, timer == &m_resourceTimingReportTimer); | 463 ASSERT_UNUSED(timer, timer == &m_resourceTimingReportTimer); |
415 Vector<OwnPtr<ResourceTimingInfo>> timingReports; | 464 Vector<OwnPtr<ResourceTimingInfo>> timingReports; |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
502 if (resource->isCacheValidator()) { | 551 if (resource->isCacheValidator()) { |
503 const AtomicString& timingAllowOrigin = resource->resourceToRevalidate()
->response().httpHeaderField("Timing-Allow-Origin"); | 552 const AtomicString& timingAllowOrigin = resource->resourceToRevalidate()
->response().httpHeaderField("Timing-Allow-Origin"); |
504 if (!timingAllowOrigin.isEmpty()) | 553 if (!timingAllowOrigin.isEmpty()) |
505 info->setOriginalTimingAllowOrigin(timingAllowOrigin); | 554 info->setOriginalTimingAllowOrigin(timingAllowOrigin); |
506 } | 555 } |
507 | 556 |
508 if (resource->type() != Resource::MainResource || context().updateTimingInfo
ForIFrameNavigation(info.get())) | 557 if (resource->type() != Resource::MainResource || context().updateTimingInfo
ForIFrameNavigation(info.get())) |
509 m_resourceTimingInfoMap.add(resource, info.release()); | 558 m_resourceTimingInfoMap.add(resource, info.release()); |
510 } | 559 } |
511 | 560 |
512 ResourceFetcher::RevalidationPolicy ResourceFetcher::determineRevalidationPolicy
(Resource::Type type, const FetchRequest& fetchRequest, Resource* existingResour
ce) const | 561 ResourceFetcher::RevalidationPolicy ResourceFetcher::determineRevalidationPolicy
(Resource::Type type, const FetchRequest& fetchRequest, Resource* existingResour
ce, bool isStaticData) const |
513 { | 562 { |
514 const ResourceRequest& request = fetchRequest.resourceRequest(); | 563 const ResourceRequest& request = fetchRequest.resourceRequest(); |
515 | 564 |
516 if (!existingResource) | 565 if (!existingResource) |
517 return Load; | 566 return Load; |
518 | 567 |
519 // We already have a preload going for this URL. | 568 // We already have a preload going for this URL. |
520 if (fetchRequest.forPreload() && existingResource->isPreloaded()) | 569 if (fetchRequest.forPreload() && existingResource->isPreloaded()) |
521 return Use; | 570 return Use; |
522 | 571 |
523 // If the same URL has been loaded as a different type, we need to reload. | 572 // If the same URL has been loaded as a different type, we need to reload. |
524 if (existingResource->type() != type) { | 573 if (existingResource->type() != type) { |
525 // FIXME: If existingResource is a Preload and the new type is LinkPrefe
tch | 574 // FIXME: If existingResource is a Preload and the new type is LinkPrefe
tch |
526 // We really should discard the new prefetch since the preload has more | 575 // We really should discard the new prefetch since the preload has more |
527 // specific type information! crbug.com/379893 | 576 // specific type information! crbug.com/379893 |
528 // fast/dom/HTMLLinkElement/link-and-subresource-test hits this case. | 577 // fast/dom/HTMLLinkElement/link-and-subresource-test hits this case. |
529 WTF_LOG(ResourceLoading, "ResourceFetcher::determineRevalidationPolicy r
eloading due to type mismatch."); | 578 WTF_LOG(ResourceLoading, "ResourceFetcher::determineRevalidationPolicy r
eloading due to type mismatch."); |
530 return Reload; | 579 return Reload; |
531 } | 580 } |
532 | 581 |
533 // Do not load from cache if images are not enabled. The load for this image
will be blocked | 582 // Do not load from cache if images are not enabled. The load for this image
will be blocked |
534 // in ImageResource::load. | 583 // in ImageResource::load. |
535 if (FetchRequest::DeferredByClient == fetchRequest.defer()) | 584 if (FetchRequest::DeferredByClient == fetchRequest.defer()) |
536 return Reload; | 585 return Reload; |
537 | 586 |
538 // Always use data uris. | |
539 // FIXME: Extend this to non-images. | |
540 if (type == Resource::Image && request.url().protocolIsData()) | |
541 return Use; | |
542 | |
543 // If a main resource was populated from a SubstituteData load, use it. | |
544 if (type == Resource::MainResource && context().hasSubstituteData()) | |
545 return Use; | |
546 | |
547 if (!existingResource->canReuse(request)) | |
548 return Reload; | |
549 | |
550 // Never use cache entries for downloadToFile / useStreamOnResponse | 587 // Never use cache entries for downloadToFile / useStreamOnResponse |
551 // requests. The data will be delivered through other paths. | 588 // requests. The data will be delivered through other paths. |
552 if (request.downloadToFile() || request.useStreamOnResponse()) | 589 if (request.downloadToFile() || request.useStreamOnResponse()) |
553 return Reload; | 590 return Reload; |
554 | 591 |
| 592 // If resource was populated from a SubstituteData load or data: url, use it
. |
| 593 if (isStaticData) |
| 594 return Use; |
| 595 |
| 596 if (!existingResource->canReuse(request)) |
| 597 return Reload; |
| 598 |
555 // Certain requests (e.g., XHRs) might have manually set headers that requir
e revalidation. | 599 // Certain requests (e.g., XHRs) might have manually set headers that requir
e revalidation. |
556 // FIXME: In theory, this should be a Revalidate case. In practice, the Memo
ryCache revalidation path assumes a whole bunch | 600 // FIXME: In theory, this should be a Revalidate case. In practice, the Memo
ryCache revalidation path assumes a whole bunch |
557 // of things about how revalidation works that manual headers violate, so pu
nt to Reload instead. | 601 // of things about how revalidation works that manual headers violate, so pu
nt to Reload instead. |
558 if (request.isConditional()) | 602 if (request.isConditional()) |
559 return Reload; | 603 return Reload; |
560 | 604 |
561 // Don't reload resources while pasting. | 605 // Don't reload resources while pasting. |
562 if (m_allowStaleResources) | 606 if (m_allowStaleResources) |
563 return Use; | 607 return Use; |
564 | 608 |
(...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1103 visitor->trace(m_archiveResourceCollection); | 1147 visitor->trace(m_archiveResourceCollection); |
1104 visitor->trace(m_loaders); | 1148 visitor->trace(m_loaders); |
1105 visitor->trace(m_nonBlockingLoaders); | 1149 visitor->trace(m_nonBlockingLoaders); |
1106 #if ENABLE(OILPAN) | 1150 #if ENABLE(OILPAN) |
1107 visitor->trace(m_preloads); | 1151 visitor->trace(m_preloads); |
1108 visitor->trace(m_resourceTimingInfoMap); | 1152 visitor->trace(m_resourceTimingInfoMap); |
1109 #endif | 1153 #endif |
1110 } | 1154 } |
1111 | 1155 |
1112 } | 1156 } |
OLD | NEW |