blob: 23a4fa6b64e6825e80f3aea93ea0de9ec613d08a [file] [log] [blame]
eseidel94980f22006-01-09 09:29:48 +00001/*
eseidel94980f22006-01-09 09:29:48 +00002 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)
bfulgham@apple.comb30d7f82016-06-07 15:47:30 +00005 Copyright (C) 2004-2016 Apple Inc. All rights reserved.
treat@webkit.org915ef892009-02-26 20:09:50 +00006 Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/
eseidel94980f22006-01-09 09:29:48 +00007
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
ddkilzerc8eccec2007-09-26 02:29:57 +000020 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA.
eseidel94980f22006-01-09 09:29:48 +000022
23 This class provides all functionality needed for loading images, style sheets and html
24 pages from the web. It has a memory cache for these objects.
25*/
26
27#include "config.h"
abarth@webkit.org17d66c62010-09-08 10:26:02 +000028#include "CachedResourceLoader.h"
darin644b75e2006-02-21 06:59:15 +000029
darin89ec05a2006-03-07 09:03:23 +000030#include "CachedCSSStyleSheet.h"
reni@webkit.orgf76a86e2012-02-24 14:31:59 +000031#include "CachedSVGDocument.h"
oliverd6ae4962007-10-12 14:55:24 +000032#include "CachedFont.h"
eseidel94980f22006-01-09 09:29:48 +000033#include "CachedImage.h"
japhet@chromium.orgb0444b32011-10-07 18:16:03 +000034#include "CachedRawResource.h"
commit-queue@webkit.org5e7ea1b2012-10-22 23:35:28 +000035#include "CachedResourceRequest.h"
mmaxfield@apple.comaf535632014-11-18 20:04:38 +000036#include "CachedSVGFont.h"
eseidel94980f22006-01-09 09:29:48 +000037#include "CachedScript.h"
eseidel94980f22006-01-09 09:29:48 +000038#include "CachedXSLStyleSheet.h"
dbates@webkit.orgeda26cf2014-10-22 23:43:11 +000039#include "Chrome.h"
40#include "ChromeClient.h"
commit-queue@webkit.org8090ccb2015-10-06 08:18:08 +000041#include "ContentExtensionError.h"
achristensen@apple.com364f0cf2015-03-04 01:57:19 +000042#include "ContentExtensionRule.h"
abarth@webkit.org4c18a302011-03-28 05:15:38 +000043#include "ContentSecurityPolicy.h"
abarth@webkit.org234c23a2008-06-21 20:33:53 +000044#include "DOMWindow.h"
cdumez@apple.com4c621c12015-01-22 22:19:46 +000045#include "DiagnosticLoggingClient.h"
46#include "DiagnosticLoggingKeys.h"
abarth@webkit.org94d2d9f2010-11-08 06:46:03 +000047#include "Document.h"
japhet@chromium.org97fe9052012-10-09 21:58:25 +000048#include "DocumentLoader.h"
mjs810e9762006-01-09 21:39:14 +000049#include "Frame.h"
darinc370e7e2006-11-08 05:52:27 +000050#include "FrameLoader.h"
darin@chromium.org6d318002010-01-29 08:43:28 +000051#include "FrameLoaderClient.h"
abarth@webkit.org94d2d9f2010-11-08 06:46:03 +000052#include "HTMLElement.h"
simonjam@chromium.orgc5ab4b52013-04-02 05:51:43 +000053#include "HTMLFrameOwnerElement.h"
commit-queue@webkit.org66c78112012-10-26 23:55:46 +000054#include "LoaderStrategy.h"
commit-queue@webkit.org8090ccb2015-10-06 08:18:08 +000055#include "LocalizedStrings.h"
antti@apple.comf73108e2010-12-30 20:57:02 +000056#include "Logging.h"
cdumez@apple.com4c621c12015-01-22 22:19:46 +000057#include "MainFrame.h"
abarth@webkit.org94d2d9f2010-11-08 06:46:03 +000058#include "MemoryCache.h"
commit-queue@webkit.org9ab4d3e2014-03-05 20:11:03 +000059#include "Page.h"
yoav@yoav.ws4ea6dc82016-05-02 08:21:50 +000060#include "Performance.h"
japhet@chromium.orgbc213022010-08-24 17:26:13 +000061#include "PingLoader.h"
commit-queue@webkit.org66c78112012-10-26 23:55:46 +000062#include "PlatformStrategies.h"
antti@apple.comc3cbb6b2013-09-20 08:59:25 +000063#include "RenderElement.h"
commit-queue@webkit.org5c533932015-03-12 01:03:43 +000064#include "ResourceLoadInfo.h"
yoav@yoav.ws4ea6dc82016-05-02 08:21:50 +000065#include "RuntimeEnabledFeatures.h"
weinig@apple.com123e4aa2013-04-14 00:54:27 +000066#include "ScriptController.h"
abarth@webkit.orgc17c9592008-06-21 20:33:42 +000067#include "SecurityOrigin.h"
commit-queue@webkit.org9ab4d3e2014-03-05 20:11:03 +000068#include "SessionID.h"
abarth@webkit.org234c23a2008-06-21 20:33:53 +000069#include "Settings.h"
beidson@apple.comb98919a2015-03-23 22:34:53 +000070#include "StyleSheetContents.h"
weinig@apple.com91defc82015-01-18 21:54:12 +000071#include "UserContentController.h"
beidson@apple.comb98919a2015-03-23 22:34:53 +000072#include "UserStyleSheet.h"
ossy@webkit.orgb98796d2011-01-11 16:49:38 +000073#include <wtf/text/CString.h>
zimmermann@webkit.orgb5e11e62011-05-16 07:56:06 +000074#include <wtf/text/WTFString.h>
eseidel94980f22006-01-09 09:29:48 +000075
eric.carlson@apple.coma24babb2011-10-17 19:22:45 +000076#if ENABLE(VIDEO_TRACK)
eric.carlson@apple.com4dd460d2011-10-20 18:05:14 +000077#include "CachedTextTrack.h"
eric.carlson@apple.coma24babb2011-10-17 19:22:45 +000078#endif
79
antti@apple.com6c76e542008-03-13 21:20:31 +000080#define PRELOAD_DEBUG 0
81
darin644b75e2006-02-21 06:59:15 +000082namespace WebCore {
eseidel94980f22006-01-09 09:29:48 +000083
commit-queue@webkit.org9ab4d3e2014-03-05 20:11:03 +000084static CachedResource* createResource(CachedResource::Type type, ResourceRequest& request, const String& charset, SessionID sessionID)
antti@apple.comf73108e2010-12-30 20:57:02 +000085{
86 switch (type) {
87 case CachedResource::ImageResource:
commit-queue@webkit.org9ab4d3e2014-03-05 20:11:03 +000088 return new CachedImage(request, sessionID);
antti@apple.comf73108e2010-12-30 20:57:02 +000089 case CachedResource::CSSStyleSheet:
commit-queue@webkit.org9ab4d3e2014-03-05 20:11:03 +000090 return new CachedCSSStyleSheet(request, charset, sessionID);
antti@apple.comf73108e2010-12-30 20:57:02 +000091 case CachedResource::Script:
commit-queue@webkit.org9ab4d3e2014-03-05 20:11:03 +000092 return new CachedScript(request, charset, sessionID);
reni@webkit.orgf76a86e2012-02-24 14:31:59 +000093 case CachedResource::SVGDocumentResource:
commit-queue@webkit.org9ab4d3e2014-03-05 20:11:03 +000094 return new CachedSVGDocument(request, sessionID);
mmaxfield@apple.comaf535632014-11-18 20:04:38 +000095#if ENABLE(SVG_FONTS)
96 case CachedResource::SVGFontResource:
97 return new CachedSVGFont(request, sessionID);
98#endif
antti@apple.comf73108e2010-12-30 20:57:02 +000099 case CachedResource::FontResource:
commit-queue@webkit.org9ab4d3e2014-03-05 20:11:03 +0000100 return new CachedFont(request, sessionID);
dbates@webkit.org55b489b2016-03-16 19:46:49 +0000101 case CachedResource::MediaResource:
japhet@chromium.orgb0444b32011-10-07 18:16:03 +0000102 case CachedResource::RawResource:
japhet@chromium.orga269e562012-10-25 20:05:17 +0000103 case CachedResource::MainResource:
commit-queue@webkit.org9ab4d3e2014-03-05 20:11:03 +0000104 return new CachedRawResource(request, type, sessionID);
antti@apple.comf73108e2010-12-30 20:57:02 +0000105#if ENABLE(XSLT)
106 case CachedResource::XSLStyleSheet:
commit-queue@webkit.org9ab4d3e2014-03-05 20:11:03 +0000107 return new CachedXSLStyleSheet(request, sessionID);
antti@apple.comf73108e2010-12-30 20:57:02 +0000108#endif
yoav@yoav.wsc7bd8322016-04-18 06:06:42 +0000109 case CachedResource::LinkPreload:
110 return new CachedResource(request, CachedResource::LinkPreload, sessionID);
antti@apple.comf73108e2010-12-30 20:57:02 +0000111#if ENABLE(LINK_PREFETCH)
commit-queue@webkit.org768c4022011-05-21 19:24:56 +0000112 case CachedResource::LinkPrefetch:
commit-queue@webkit.org9ab4d3e2014-03-05 20:11:03 +0000113 return new CachedResource(request, CachedResource::LinkPrefetch, sessionID);
commit-queue@webkit.org768c4022011-05-21 19:24:56 +0000114 case CachedResource::LinkSubresource:
commit-queue@webkit.org9ab4d3e2014-03-05 20:11:03 +0000115 return new CachedResource(request, CachedResource::LinkSubresource, sessionID);
antti@apple.comf73108e2010-12-30 20:57:02 +0000116#endif
eric.carlson@apple.coma24babb2011-10-17 19:22:45 +0000117#if ENABLE(VIDEO_TRACK)
japhet@chromium.org5385c712011-10-31 23:49:47 +0000118 case CachedResource::TextTrackResource:
commit-queue@webkit.org9ab4d3e2014-03-05 20:11:03 +0000119 return new CachedTextTrack(request, sessionID);
eric.carlson@apple.coma24babb2011-10-17 19:22:45 +0000120#endif
antti@apple.comf73108e2010-12-30 20:57:02 +0000121 }
122 ASSERT_NOT_REACHED();
hs85.jeong@samsung.com13179142015-10-21 02:12:32 +0000123 return nullptr;
antti@apple.comf73108e2010-12-30 20:57:02 +0000124}
125
japhet@chromium.org97fe9052012-10-09 21:58:25 +0000126CachedResourceLoader::CachedResourceLoader(DocumentLoader* documentLoader)
hs85.jeong@samsung.com13179142015-10-21 02:12:32 +0000127 : m_document(nullptr)
japhet@chromium.org97fe9052012-10-09 21:58:25 +0000128 , m_documentLoader(documentLoader)
beidson22febd12007-05-04 04:35:28 +0000129 , m_requestCount(0)
cdumez@apple.com7f86ada2015-08-01 03:41:07 +0000130 , m_garbageCollectDocumentResourcesTimer(*this, &CachedResourceLoader::garbageCollectDocumentResources)
oliver1c8a4872007-03-29 04:59:45 +0000131 , m_autoLoadImages(true)
commit-queue@webkit.org67248b22012-09-25 06:51:39 +0000132 , m_imagesEnabled(true)
oliver06d89a02007-03-29 06:15:27 +0000133 , m_allowStaleResources(false)
eseidel94980f22006-01-09 09:29:48 +0000134{
eseidel94980f22006-01-09 09:29:48 +0000135}
136
abarth@webkit.org17d66c62010-09-08 10:26:02 +0000137CachedResourceLoader::~CachedResourceLoader()
eseidel94980f22006-01-09 09:29:48 +0000138{
hs85.jeong@samsung.com13179142015-10-21 02:12:32 +0000139 m_documentLoader = nullptr;
140 m_document = nullptr;
andreas.kling@nokia.comc9291032011-02-17 13:38:06 +0000141
antti@apple.com6c76e542008-03-13 21:20:31 +0000142 clearPreloads();
commit-queue@webkit.orgacddfad2015-09-30 05:53:51 +0000143 for (auto& resource : m_documentResources.values())
144 resource->setOwningCachedResourceLoader(nullptr);
eric@webkit.orgbbb86d32009-03-04 22:58:23 +0000145
abarth@webkit.org17d66c62010-09-08 10:26:02 +0000146 // Make sure no requests still point to this CachedResourceLoader
eric@webkit.orgbbb86d32009-03-04 22:58:23 +0000147 ASSERT(m_requestCount == 0);
eseidel94980f22006-01-09 09:29:48 +0000148}
149
antti@apple.com76bf3f22010-12-15 11:27:52 +0000150CachedResource* CachedResourceLoader::cachedResource(const String& resourceURL) const
151{
commit-queue@webkit.org8bcf60b2015-11-18 23:17:21 +0000152 ASSERT(!resourceURL.isNull());
darin@apple.com5ffbb5c2013-09-27 16:39:41 +0000153 URL url = m_document->completeURL(resourceURL);
antti@apple.com76bf3f22010-12-15 11:27:52 +0000154 return cachedResource(url);
155}
156
darin@apple.com5ffbb5c2013-09-27 16:39:41 +0000157CachedResource* CachedResourceLoader::cachedResource(const URL& resourceURL) const
antti@apple.com76bf3f22010-12-15 11:27:52 +0000158{
darin@apple.com5ffbb5c2013-09-27 16:39:41 +0000159 URL url = MemoryCache::removeFragmentIdentifierIfNeeded(resourceURL);
antti@apple.com76bf3f22010-12-15 11:27:52 +0000160 return m_documentResources.get(url).get();
161}
162
abarth@webkit.org17d66c62010-09-08 10:26:02 +0000163Frame* CachedResourceLoader::frame() const
eric@webkit.orge0a51622008-06-26 22:45:47 +0000164{
commit-queue@webkit.org3dd45802016-03-22 19:12:32 +0000165 return m_documentLoader ? m_documentLoader->frame() : nullptr;
eric@webkit.orge0a51622008-06-26 22:45:47 +0000166}
167
commit-queue@webkit.org9ab4d3e2014-03-05 20:11:03 +0000168SessionID CachedResourceLoader::sessionID() const
169{
170 SessionID sessionID = SessionID::defaultSessionID();
171
172 if (Frame* f = frame())
173 sessionID = f->page()->sessionID();
174
175 return sessionID;
176}
177
commit-queue@webkit.org4b3425062015-04-02 00:22:54 +0000178CachedResourceHandle<CachedImage> CachedResourceLoader::requestImage(CachedResourceRequest& request)
eseidel94980f22006-01-09 09:29:48 +0000179{
andersca@apple.coma2235872014-02-08 20:02:40 +0000180 if (Frame* frame = this->frame()) {
cdumez@apple.com83847a92015-06-26 18:26:19 +0000181 if (frame->loader().pageDismissalEventBeingDispatched() != FrameLoader::PageDismissalType::None) {
bfulgham@apple.comb30d7f82016-06-07 15:47:30 +0000182 if (Document* document = frame->document())
183 document->contentSecurityPolicy()->upgradeInsecureRequestIfNeeded(request.mutableResourceRequest(), ContentSecurityPolicy::InsecureRequestType::Load);
darin@apple.com5ffbb5c2013-09-27 16:39:41 +0000184 URL requestURL = request.resourceRequest().url();
hmuller@adobe.com1233f922013-06-22 19:56:37 +0000185 if (requestURL.isValid() && canRequest(CachedResource::ImageResource, requestURL, request.options(), request.forPreload()))
andersca@apple.coma2235872014-02-08 20:02:40 +0000186 PingLoader::loadImage(*frame, requestURL);
187 return nullptr;
japhet@chromium.orgbc213022010-08-24 17:26:13 +0000188 }
darin@chromium.org6d318002010-01-29 08:43:28 +0000189 }
andersca@apple.coma2235872014-02-08 20:02:40 +0000190
commit-queue@webkit.org864dbda2012-11-16 12:21:57 +0000191 request.setDefer(clientDefersImage(request.resourceRequest().url()) ? CachedResourceRequest::DeferredByClient : CachedResourceRequest::NoDefer);
commit-queue@webkit.org4b3425062015-04-02 00:22:54 +0000192 return downcast<CachedImage>(requestResource(CachedResource::ImageResource, request).get());
eseidel94980f22006-01-09 09:29:48 +0000193}
194
mmaxfield@apple.comaf535632014-11-18 20:04:38 +0000195CachedResourceHandle<CachedFont> CachedResourceLoader::requestFont(CachedResourceRequest& request, bool isSVG)
oliverd6ae4962007-10-12 14:55:24 +0000196{
mmaxfield@apple.comc314aef2014-11-20 21:45:54 +0000197#if ENABLE(SVG_FONTS)
mmaxfield@apple.comaf535632014-11-18 20:04:38 +0000198 if (isSVG)
199 return downcast<CachedSVGFont>(requestResource(CachedResource::SVGFontResource, request).get());
mmaxfield@apple.comc314aef2014-11-20 21:45:54 +0000200#else
201 UNUSED_PARAM(isSVG);
202#endif
cdumez@apple.comc4a3af62014-10-06 00:31:05 +0000203 return downcast<CachedFont>(requestResource(CachedResource::FontResource, request).get());
oliverd6ae4962007-10-12 14:55:24 +0000204}
205
eric.carlson@apple.coma24babb2011-10-17 19:22:45 +0000206#if ENABLE(VIDEO_TRACK)
commit-queue@webkit.org5e7ea1b2012-10-22 23:35:28 +0000207CachedResourceHandle<CachedTextTrack> CachedResourceLoader::requestTextTrack(CachedResourceRequest& request)
eric.carlson@apple.coma24babb2011-10-17 19:22:45 +0000208{
cdumez@apple.comc4a3af62014-10-06 00:31:05 +0000209 return downcast<CachedTextTrack>(requestResource(CachedResource::TextTrackResource, request).get());
eric.carlson@apple.coma24babb2011-10-17 19:22:45 +0000210}
211#endif
212
commit-queue@webkit.org5e7ea1b2012-10-22 23:35:28 +0000213CachedResourceHandle<CachedCSSStyleSheet> CachedResourceLoader::requestCSSStyleSheet(CachedResourceRequest& request)
eseidel94980f22006-01-09 09:29:48 +0000214{
cdumez@apple.comc4a3af62014-10-06 00:31:05 +0000215 return downcast<CachedCSSStyleSheet>(requestResource(CachedResource::CSSStyleSheet, request).get());
bdash281524a2007-02-09 08:50:57 +0000216}
217
commit-queue@webkit.org5e7ea1b2012-10-22 23:35:28 +0000218CachedResourceHandle<CachedCSSStyleSheet> CachedResourceLoader::requestUserCSSStyleSheet(CachedResourceRequest& request)
bdash281524a2007-02-09 08:50:57 +0000219{
darin@apple.com5ffbb5c2013-09-27 16:39:41 +0000220 URL url = MemoryCache::removeFragmentIdentifierIfNeeded(request.resourceRequest().url());
antti@apple.comf73108e2010-12-30 20:57:02 +0000221
jpfau@apple.com97c6a7f2013-02-26 00:49:17 +0000222#if ENABLE(CACHE_PARTITIONING)
cdumez@apple.com8730b6e2014-10-21 02:10:47 +0000223 request.mutableResourceRequest().setDomainForCachePartition(document()->topOrigin()->domainForCachePartition());
jpfau@apple.com97c6a7f2013-02-26 00:49:17 +0000224#endif
225
cdumez@apple.com41d2d702015-02-02 20:50:16 +0000226 auto& memoryCache = MemoryCache::singleton();
jer.noble@apple.com2ed319d2016-01-28 19:52:57 +0000227 if (request.allowsCaching()) {
228 if (CachedResource* existing = memoryCache.resourceForRequest(request.resourceRequest(), sessionID())) {
229 if (is<CachedCSSStyleSheet>(*existing))
230 return downcast<CachedCSSStyleSheet>(existing);
231 memoryCache.remove(*existing);
232 }
antti@apple.comf73108e2010-12-30 20:57:02 +0000233 }
jer.noble@apple.com2ed319d2016-01-28 19:52:57 +0000234
commit-queue@webkit.org5e7ea1b2012-10-22 23:35:28 +0000235 if (url.string() != request.resourceRequest().url())
236 request.mutableResourceRequest().setURL(url);
japhet@chromium.org7e4338d2011-05-25 00:24:38 +0000237
commit-queue@webkit.org9ab4d3e2014-03-05 20:11:03 +0000238 CachedResourceHandle<CachedCSSStyleSheet> userSheet = new CachedCSSStyleSheet(request.resourceRequest(), request.charset(), sessionID());
ap@apple.com6edc42b2012-05-11 02:31:26 +0000239
jer.noble@apple.com2ed319d2016-01-28 19:52:57 +0000240 if (request.allowsCaching())
241 memoryCache.add(*userSheet);
ap@apple.com6edc42b2012-05-11 02:31:26 +0000242 // FIXME: loadResource calls setOwningCachedResourceLoader() if the resource couldn't be added to cache. Does this function need to call it, too?
japhet@chromium.org4a496a32011-08-29 19:26:46 +0000243
commit-queue@webkit.org16c43b42016-07-04 18:36:30 +0000244 userSheet->load(*this, ResourceLoaderOptions(DoNotSendCallbacks, SniffContent, BufferData, AllowStoredCredentials, AskClientForAllCredentials, ClientRequestedCredentials, SkipSecurityCheck, FetchOptions::Mode::NoCors, DoNotIncludeCertificateInfo, ContentSecurityPolicyImposition::SkipPolicyCheck, DefersLoadingPolicy::AllowDefersLoading, CachingPolicy::AllowCaching));
antti@apple.comf73108e2010-12-30 20:57:02 +0000245
246 return userSheet;
eseidel94980f22006-01-09 09:29:48 +0000247}
248
commit-queue@webkit.org5e7ea1b2012-10-22 23:35:28 +0000249CachedResourceHandle<CachedScript> CachedResourceLoader::requestScript(CachedResourceRequest& request)
eseidel94980f22006-01-09 09:29:48 +0000250{
cdumez@apple.comc4a3af62014-10-06 00:31:05 +0000251 return downcast<CachedScript>(requestResource(CachedResource::Script, request).get());
eseidel94980f22006-01-09 09:29:48 +0000252}
253
mjsd2948ef2007-02-26 19:29:04 +0000254#if ENABLE(XSLT)
commit-queue@webkit.org5e7ea1b2012-10-22 23:35:28 +0000255CachedResourceHandle<CachedXSLStyleSheet> CachedResourceLoader::requestXSLStyleSheet(CachedResourceRequest& request)
eseidel94980f22006-01-09 09:29:48 +0000256{
cdumez@apple.comc4a3af62014-10-06 00:31:05 +0000257 return downcast<CachedXSLStyleSheet>(requestResource(CachedResource::XSLStyleSheet, request).get());
eseidel94980f22006-01-09 09:29:48 +0000258}
259#endif
260
commit-queue@webkit.org5e7ea1b2012-10-22 23:35:28 +0000261CachedResourceHandle<CachedSVGDocument> CachedResourceLoader::requestSVGDocument(CachedResourceRequest& request)
reni@webkit.orgff4b9f22012-03-14 08:52:35 +0000262{
cdumez@apple.comc4a3af62014-10-06 00:31:05 +0000263 return downcast<CachedSVGDocument>(requestResource(CachedResource::SVGDocumentResource, request).get());
reni@webkit.orgff4b9f22012-03-14 08:52:35 +0000264}
reni@webkit.orgff4b9f22012-03-14 08:52:35 +0000265
commit-queue@webkit.orga67f42c2010-07-10 02:41:10 +0000266#if ENABLE(LINK_PREFETCH)
commit-queue@webkit.org5e7ea1b2012-10-22 23:35:28 +0000267CachedResourceHandle<CachedResource> CachedResourceLoader::requestLinkResource(CachedResource::Type type, CachedResourceRequest& request)
commit-queue@webkit.orga67f42c2010-07-10 02:41:10 +0000268{
abarth@webkit.org926400e2010-08-31 07:35:01 +0000269 ASSERT(frame());
gavinp@chromium.orgaf445b92012-05-15 04:42:52 +0000270 ASSERT(type == CachedResource::LinkPrefetch || type == CachedResource::LinkSubresource);
commit-queue@webkit.org5e7ea1b2012-10-22 23:35:28 +0000271 return requestResource(type, request);
commit-queue@webkit.orga67f42c2010-07-10 02:41:10 +0000272}
273#endif
274
dbates@webkit.org55b489b2016-03-16 19:46:49 +0000275CachedResourceHandle<CachedRawResource> CachedResourceLoader::requestMedia(CachedResourceRequest& request)
276{
277 return downcast<CachedRawResource>(requestResource(CachedResource::MediaResource, request).get());
278}
279
commit-queue@webkit.org5e7ea1b2012-10-22 23:35:28 +0000280CachedResourceHandle<CachedRawResource> CachedResourceLoader::requestRawResource(CachedResourceRequest& request)
japhet@chromium.orgb0444b32011-10-07 18:16:03 +0000281{
cdumez@apple.com3a3edad2014-10-06 05:13:09 +0000282 return downcast<CachedRawResource>(requestResource(CachedResource::RawResource, request).get());
japhet@chromium.orgb0444b32011-10-07 18:16:03 +0000283}
284
japhet@chromium.orga269e562012-10-25 20:05:17 +0000285CachedResourceHandle<CachedRawResource> CachedResourceLoader::requestMainResource(CachedResourceRequest& request)
286{
cdumez@apple.com3a3edad2014-10-06 05:13:09 +0000287 return downcast<CachedRawResource>(requestResource(CachedResource::MainResource, request).get());
japhet@chromium.orga269e562012-10-25 20:05:17 +0000288}
289
oliver@apple.com74dbf622015-03-06 04:43:12 +0000290static MixedContentChecker::ContentType contentTypeFromResourceType(CachedResource::Type type)
291{
292 switch (type) {
jer.noble@apple.com0ca560f2016-03-18 19:04:58 +0000293 // https://w3c.github.io/webappsec-mixed-content/#category-optionally-blockable
294 // Editor's Draft, 11 February 2016
295 // 3.1. Optionally-blockable Content
oliver@apple.com74dbf622015-03-06 04:43:12 +0000296 case CachedResource::ImageResource:
jer.noble@apple.com0ca560f2016-03-18 19:04:58 +0000297 case CachedResource::MediaResource:
oliver@apple.com74dbf622015-03-06 04:43:12 +0000298 return MixedContentChecker::ContentType::ActiveCanWarn;
299
300 case CachedResource::CSSStyleSheet:
301 case CachedResource::Script:
302 case CachedResource::FontResource:
303 return MixedContentChecker::ContentType::Active;
304
305#if ENABLE(SVG_FONTS)
306 case CachedResource::SVGFontResource:
307 return MixedContentChecker::ContentType::Active;
308#endif
309
310 case CachedResource::RawResource:
311 case CachedResource::SVGDocumentResource:
312 return MixedContentChecker::ContentType::Active;
313#if ENABLE(XSLT)
314 case CachedResource::XSLStyleSheet:
315 return MixedContentChecker::ContentType::Active;
316#endif
317
yoav@yoav.wsc7bd8322016-04-18 06:06:42 +0000318 case CachedResource::LinkPreload:
oliver@apple.com74dbf622015-03-06 04:43:12 +0000319#if ENABLE(LINK_PREFETCH)
320 case CachedResource::LinkPrefetch:
321 case CachedResource::LinkSubresource:
322 return MixedContentChecker::ContentType::Active;
323#endif
324
325#if ENABLE(VIDEO_TRACK)
326 case CachedResource::TextTrackResource:
327 return MixedContentChecker::ContentType::Active;
328#endif
329 default:
330 ASSERT_NOT_REACHED();
331 return MixedContentChecker::ContentType::Active;
332 }
333}
334
darin@apple.com5ffbb5c2013-09-27 16:39:41 +0000335bool CachedResourceLoader::checkInsecureContent(CachedResource::Type type, const URL& url) const
commit-queue@webkit.org4650bbcb2011-06-17 19:11:14 +0000336{
337 switch (type) {
338 case CachedResource::Script:
339#if ENABLE(XSLT)
340 case CachedResource::XSLStyleSheet:
341#endif
reni@webkit.orgf76a86e2012-02-24 14:31:59 +0000342 case CachedResource::SVGDocumentResource:
commit-queue@webkit.org4650bbcb2011-06-17 19:11:14 +0000343 case CachedResource::CSSStyleSheet:
344 // These resource can inject script into the current document (Script,
345 // XSL) or exfiltrate the content of the current document (CSS).
346 if (Frame* f = frame())
akling@apple.com10093a92013-09-08 08:15:27 +0000347 if (!f->loader().mixedContentChecker().canRunInsecureContent(m_document->securityOrigin(), url))
commit-queue@webkit.org4650bbcb2011-06-17 19:11:14 +0000348 return false;
349 break;
eric.carlson@apple.coma24babb2011-10-17 19:22:45 +0000350#if ENABLE(VIDEO_TRACK)
japhet@chromium.org5385c712011-10-31 23:49:47 +0000351 case CachedResource::TextTrackResource:
eric.carlson@apple.coma24babb2011-10-17 19:22:45 +0000352#endif
dbates@webkit.org55b489b2016-03-16 19:46:49 +0000353 case CachedResource::MediaResource:
tsepez@chromium.org60c46532012-06-26 23:18:31 +0000354 case CachedResource::RawResource:
commit-queue@webkit.org4650bbcb2011-06-17 19:11:14 +0000355 case CachedResource::ImageResource:
mmaxfield@apple.comaf535632014-11-18 20:04:38 +0000356#if ENABLE(SVG_FONTS)
357 case CachedResource::SVGFontResource:
358#endif
yoav@yoav.wsc7bd8322016-04-18 06:06:42 +0000359 case CachedResource::FontResource:
360 case CachedResource::LinkPreload: {
commit-queue@webkit.org4650bbcb2011-06-17 19:11:14 +0000361 // These resources can corrupt only the frame's pixels.
362 if (Frame* f = frame()) {
akling@apple.com52989472013-09-16 20:09:25 +0000363 Frame& topFrame = f->tree().top();
oliver@apple.com74dbf622015-03-06 04:43:12 +0000364 if (!topFrame.loader().mixedContentChecker().canDisplayInsecureContent(topFrame.document()->securityOrigin(), contentTypeFromResourceType(type), url))
commit-queue@webkit.org4650bbcb2011-06-17 19:11:14 +0000365 return false;
366 }
367 break;
368 }
japhet@chromium.orga269e562012-10-25 20:05:17 +0000369 case CachedResource::MainResource:
commit-queue@webkit.org4650bbcb2011-06-17 19:11:14 +0000370#if ENABLE(LINK_PREFETCH)
371 case CachedResource::LinkPrefetch:
commit-queue@webkit.org4650bbcb2011-06-17 19:11:14 +0000372 case CachedResource::LinkSubresource:
373 // Prefetch cannot affect the current document.
commit-queue@webkit.org4650bbcb2011-06-17 19:11:14 +0000374#endif
japhet@chromium.orgb0444b32011-10-07 18:16:03 +0000375 break;
commit-queue@webkit.org4650bbcb2011-06-17 19:11:14 +0000376 }
377 return true;
378}
379
dbates@webkit.org28db74a2016-04-15 22:23:44 +0000380bool CachedResourceLoader::canRequest(CachedResource::Type type, const URL& url, const ResourceLoaderOptions& options, bool forPreload, bool didReceiveRedirectResponse)
eseidel94980f22006-01-09 09:29:48 +0000381{
japhet@chromium.orga269e562012-10-25 20:05:17 +0000382 if (document() && !document()->securityOrigin()->canDisplay(url)) {
abarth@webkit.orge60f0a62011-04-22 21:20:12 +0000383 if (!forPreload)
mkwst@chromium.org6f6d9bc2013-05-30 12:08:58 +0000384 FrameLoader::reportLocalLoadFailed(frame(), url.stringCenterEllipsizedToLength());
abarth@webkit.orge60f0a62011-04-22 21:20:12 +0000385 LOG(ResourceLoading, "CachedResourceLoader::requestResource URL was not allowed by SecurityOrigin::canDisplay");
hs85.jeong@samsung.com13179142015-10-21 02:12:32 +0000386 return false;
abarth@webkit.orge60f0a62011-04-22 21:20:12 +0000387 }
388
dbates@webkit.org264add72015-07-07 00:42:50 +0000389 bool skipContentSecurityPolicyCheck = options.contentSecurityPolicyImposition() == ContentSecurityPolicyImposition::SkipPolicyCheck;
dbates@webkit.org28db74a2016-04-15 22:23:44 +0000390 ContentSecurityPolicy::RedirectResponseReceived redirectResponseReceived = didReceiveRedirectResponse ? ContentSecurityPolicy::RedirectResponseReceived::Yes : ContentSecurityPolicy::RedirectResponseReceived::No;
mkwst@chromium.org8cd0cc72012-10-31 09:59:45 +0000391
abarth@webkit.orgc17c9592008-06-21 20:33:42 +0000392 // Some types of resources can be loaded only from the same origin. Other
393 // types of resources, like Images, Scripts, and CSS, can be loaded from
394 // any URL.
395 switch (type) {
japhet@chromium.orga269e562012-10-25 20:05:17 +0000396 case CachedResource::MainResource:
abarth@webkit.orgc17c9592008-06-21 20:33:42 +0000397 case CachedResource::ImageResource:
398 case CachedResource::CSSStyleSheet:
399 case CachedResource::Script:
mmaxfield@apple.comaf535632014-11-18 20:04:38 +0000400#if ENABLE(SVG_FONTS)
401 case CachedResource::SVGFontResource:
402#endif
dbates@webkit.org55b489b2016-03-16 19:46:49 +0000403 case CachedResource::MediaResource:
abarth@webkit.orgc17c9592008-06-21 20:33:42 +0000404 case CachedResource::FontResource:
japhet@chromium.orgb0444b32011-10-07 18:16:03 +0000405 case CachedResource::RawResource:
yoav@yoav.wsc7bd8322016-04-18 06:06:42 +0000406 case CachedResource::LinkPreload:
commit-queue@webkit.orga67f42c2010-07-10 02:41:10 +0000407#if ENABLE(LINK_PREFETCH)
commit-queue@webkit.org768c4022011-05-21 19:24:56 +0000408 case CachedResource::LinkPrefetch:
commit-queue@webkit.org768c4022011-05-21 19:24:56 +0000409 case CachedResource::LinkSubresource:
commit-queue@webkit.orga67f42c2010-07-10 02:41:10 +0000410#endif
eric.carlson@apple.coma24babb2011-10-17 19:22:45 +0000411#if ENABLE(VIDEO_TRACK)
japhet@chromium.org5385c712011-10-31 23:49:47 +0000412 case CachedResource::TextTrackResource:
eric.carlson@apple.coma24babb2011-10-17 19:22:45 +0000413#endif
commit-queue@webkit.org16c43b42016-07-04 18:36:30 +0000414 if (options.mode == FetchOptions::Mode::SameOrigin && !m_document->securityOrigin()->canRequest(url)) {
hmuller@adobe.com1233f922013-06-22 19:56:37 +0000415 printAccessDeniedMessage(url);
416 return false;
417 }
abarth@webkit.orgc17c9592008-06-21 20:33:42 +0000418 break;
reni@webkit.orgf76a86e2012-02-24 14:31:59 +0000419 case CachedResource::SVGDocumentResource:
abarth@webkit.orgc17c9592008-06-21 20:33:42 +0000420#if ENABLE(XSLT)
421 case CachedResource::XSLStyleSheet:
abarth@webkit.org8b48cdb2010-11-08 08:59:24 +0000422 if (!m_document->securityOrigin()->canRequest(url)) {
abarth@webkit.orga796cc02008-11-01 09:31:42 +0000423 printAccessDeniedMessage(url);
424 return false;
abarth@webkit.org234c23a2008-06-21 20:33:53 +0000425 }
abarth@webkit.orgc17c9592008-06-21 20:33:42 +0000426#endif
ossy@webkit.org25970ce2012-02-24 16:33:06 +0000427 break;
abarth@webkit.orgc17c9592008-06-21 20:33:42 +0000428 }
abarth@webkit.org0f9b3022009-09-11 05:48:06 +0000429
abarth@webkit.org75a72fe2011-04-08 01:08:59 +0000430 switch (type) {
abarth@webkit.org7e4c7fa2011-10-13 20:03:36 +0000431#if ENABLE(XSLT)
432 case CachedResource::XSLStyleSheet:
dbates@webkit.org28db74a2016-04-15 22:23:44 +0000433 if (!m_document->contentSecurityPolicy()->allowScriptFromSource(url, skipContentSecurityPolicyCheck, redirectResponseReceived))
vivek.vg@samsung.com4094db72013-01-23 09:02:01 +0000434 return false;
435 break;
abarth@webkit.org7e4c7fa2011-10-13 20:03:36 +0000436#endif
abarth@webkit.org75a72fe2011-04-08 01:08:59 +0000437 case CachedResource::Script:
dbates@webkit.org28db74a2016-04-15 22:23:44 +0000438 if (!m_document->contentSecurityPolicy()->allowScriptFromSource(url, skipContentSecurityPolicyCheck, redirectResponseReceived))
abarth@webkit.org75a72fe2011-04-08 01:08:59 +0000439 return false;
darin@apple.comc50e0472014-04-21 18:08:49 +0000440 if (frame() && !frame()->settings().isScriptEnabled())
441 return false;
abarth@webkit.org75a72fe2011-04-08 01:08:59 +0000442 break;
abarth@webkit.org75a72fe2011-04-08 01:08:59 +0000443 case CachedResource::CSSStyleSheet:
dbates@webkit.org28db74a2016-04-15 22:23:44 +0000444 if (!m_document->contentSecurityPolicy()->allowStyleFromSource(url, skipContentSecurityPolicyCheck, redirectResponseReceived))
abarth@webkit.org75a72fe2011-04-08 01:08:59 +0000445 return false;
446 break;
reni@webkit.orgf76a86e2012-02-24 14:31:59 +0000447 case CachedResource::SVGDocumentResource:
abarth@webkit.org75a72fe2011-04-08 01:08:59 +0000448 case CachedResource::ImageResource:
dbates@webkit.org28db74a2016-04-15 22:23:44 +0000449 if (!m_document->contentSecurityPolicy()->allowImageFromSource(url, skipContentSecurityPolicyCheck, redirectResponseReceived))
abarth@webkit.org75a72fe2011-04-08 01:08:59 +0000450 return false;
451 break;
mmaxfield@apple.comaf535632014-11-18 20:04:38 +0000452#if ENABLE(SVG_FONTS)
453 case CachedResource::SVGFontResource:
454#endif
abarth@webkit.org75a72fe2011-04-08 01:08:59 +0000455 case CachedResource::FontResource: {
dbates@webkit.org28db74a2016-04-15 22:23:44 +0000456 if (!m_document->contentSecurityPolicy()->allowFontFromSource(url, skipContentSecurityPolicyCheck, redirectResponseReceived))
abarth@webkit.org75a72fe2011-04-08 01:08:59 +0000457 return false;
458 break;
459 }
japhet@chromium.orga269e562012-10-25 20:05:17 +0000460 case CachedResource::MainResource:
japhet@chromium.orgb0444b32011-10-07 18:16:03 +0000461 case CachedResource::RawResource:
yoav@yoav.wsc7bd8322016-04-18 06:06:42 +0000462 // FIXME: Preload should be subject to connect-src.
463 case CachedResource::LinkPreload:
abarth@webkit.org75a72fe2011-04-08 01:08:59 +0000464#if ENABLE(LINK_PREFETCH)
commit-queue@webkit.org768c4022011-05-21 19:24:56 +0000465 case CachedResource::LinkPrefetch:
commit-queue@webkit.org768c4022011-05-21 19:24:56 +0000466 case CachedResource::LinkSubresource:
abarth@webkit.org75a72fe2011-04-08 01:08:59 +0000467#endif
japhet@chromium.orgb0444b32011-10-07 18:16:03 +0000468 break;
dbates@webkit.org55b489b2016-03-16 19:46:49 +0000469 case CachedResource::MediaResource:
eric.carlson@apple.coma24babb2011-10-17 19:22:45 +0000470#if ENABLE(VIDEO_TRACK)
japhet@chromium.org5385c712011-10-31 23:49:47 +0000471 case CachedResource::TextTrackResource:
dbates@webkit.org55b489b2016-03-16 19:46:49 +0000472#endif
dbates@webkit.org28db74a2016-04-15 22:23:44 +0000473 if (!m_document->contentSecurityPolicy()->allowMediaFromSource(url, skipContentSecurityPolicyCheck, redirectResponseReceived))
eric.carlson@apple.coma24babb2011-10-17 19:22:45 +0000474 return false;
475 break;
abarth@webkit.org75a72fe2011-04-08 01:08:59 +0000476 }
abarth@webkit.org4c18a302011-03-28 05:15:38 +0000477
dbates@webkit.orgeda26cf2014-10-22 23:43:11 +0000478 // SVG Images have unique security rules that prevent all subresource requests except for data urls.
479 if (type != CachedResource::MainResource && frame() && frame()->page()) {
480 if (frame()->page()->chrome().client().isSVGImageChromeClient() && !url.protocolIsData())
481 return false;
482 }
483
aestes@apple.com13f72b72015-12-17 05:53:40 +0000484 if (!canRequestInContentDispositionAttachmentSandbox(type, url))
485 return false;
486
abarth@webkit.org1abaf462011-11-04 22:32:13 +0000487 // Last of all, check for insecure content. We do this last so that when
488 // folks block insecure content with a CSP policy, they don't get a warning.
489 // They'll still get a warning in the console about CSP blocking the load.
490
491 // FIXME: Should we consider forPreload here?
492 if (!checkInsecureContent(type, url))
493 return false;
494
abarth@webkit.orga796cc02008-11-01 09:31:42 +0000495 return true;
496}
497
aestes@apple.com13f72b72015-12-17 05:53:40 +0000498bool CachedResourceLoader::canRequestInContentDispositionAttachmentSandbox(CachedResource::Type type, const URL& url) const
499{
500 Document* document;
501
502 // FIXME: Do we want to expand this to all resource types that the mixed content checker would consider active content?
503 switch (type) {
504 case CachedResource::MainResource:
505 if (auto ownerElement = frame() ? frame()->ownerElement() : nullptr) {
506 document = &ownerElement->document();
507 break;
508 }
509 return true;
510 case CachedResource::CSSStyleSheet:
511 document = m_document;
512 break;
513 default:
514 return true;
515 }
516
517 if (!document->shouldEnforceContentDispositionAttachmentSandbox() || document->securityOrigin()->canRequest(url))
518 return true;
519
520 String message = "Unsafe attempt to load URL " + url.stringCenterEllipsizedToLength() + " from document with Content-Disposition: attachment at URL " + document->url().stringCenterEllipsizedToLength() + ".";
521 document->addConsoleMessage(MessageSource::Security, MessageLevel::Error, message);
522 return false;
523}
524
commit-queue@webkit.org5eac6082014-03-11 04:22:10 +0000525bool CachedResourceLoader::shouldContinueAfterNotifyingLoadedFromMemoryCache(const CachedResourceRequest& request, CachedResource* resource)
aestes@apple.com0c8e1912013-04-06 03:09:25 +0000526{
527 if (!resource || !frame() || resource->status() != CachedResource::Cached)
528 return true;
529
commit-queue@webkit.org5eac6082014-03-11 04:22:10 +0000530 ResourceRequest newRequest = ResourceRequest(resource->url());
commit-queue@webkit.org5eac6082014-03-11 04:22:10 +0000531 if (request.resourceRequest().hiddenFromInspector())
532 newRequest.setHiddenFromInspector(true);
andersca@apple.comdf550b92013-08-15 22:17:17 +0000533 frame()->loader().loadedResourceFromMemoryCache(resource, newRequest);
ossy@webkit.orgd77a3142015-01-21 08:45:11 +0000534
aestes@apple.com0c8e1912013-04-06 03:09:25 +0000535 // FIXME <http://webkit.org/b/113251>: If the delegate modifies the request's
536 // URL, it is no longer appropriate to use this CachedResource.
537 return !newRequest.isNull();
538}
539
cdumez@apple.com4c621c12015-01-22 22:19:46 +0000540static inline void logMemoryCacheResourceRequest(Frame* frame, const String& description, const String& value = String())
541{
cdumez@apple.com10d0f252016-04-23 21:33:49 +0000542 if (!frame || !frame->page())
cdumez@apple.com4c621c12015-01-22 22:19:46 +0000543 return;
544 if (value.isNull())
cdumez@apple.com10d0f252016-04-23 21:33:49 +0000545 frame->page()->diagnosticLoggingClient().logDiagnosticMessage(DiagnosticLoggingKeys::resourceRequestKey(), description, ShouldSample::Yes);
cdumez@apple.com4c621c12015-01-22 22:19:46 +0000546 else
cdumez@apple.com10d0f252016-04-23 21:33:49 +0000547 frame->page()->diagnosticLoggingClient().logDiagnosticMessageWithValue(DiagnosticLoggingKeys::resourceRequestKey(), description, value, ShouldSample::Yes);
cdumez@apple.com4c621c12015-01-22 22:19:46 +0000548}
549
commit-queue@webkit.org4b3425062015-04-02 00:22:54 +0000550CachedResourceHandle<CachedResource> CachedResourceLoader::requestResource(CachedResource::Type type, CachedResourceRequest& request)
abarth@webkit.orga796cc02008-11-01 09:31:42 +0000551{
bfulgham@apple.comb30d7f82016-06-07 15:47:30 +0000552 if (Document* document = this->document())
553 document->contentSecurityPolicy()->upgradeInsecureRequestIfNeeded(request.mutableResourceRequest(), ContentSecurityPolicy::InsecureRequestType::Load);
554
darin@apple.com5ffbb5c2013-09-27 16:39:41 +0000555 URL url = request.resourceRequest().url();
antti@apple.comf73108e2010-12-30 20:57:02 +0000556
antti@apple.com8c81c032015-04-29 18:51:23 +0000557 LOG(ResourceLoading, "CachedResourceLoader::requestResource '%s', charset '%s', priority=%d, forPreload=%u", url.stringCenterEllipsizedToLength().latin1().data(), request.charset().latin1().data(), request.priority() ? static_cast<int>(request.priority().value()) : -1, request.forPreload());
antti@apple.com76bf3f22010-12-15 11:27:52 +0000558
559 // If only the fragment identifiers differ, it is the same resource.
antti@apple.comf73108e2010-12-30 20:57:02 +0000560 url = MemoryCache::removeFragmentIdentifierIfNeeded(url);
abarth@webkit.orga796cc02008-11-01 09:31:42 +0000561
antti@apple.comf73108e2010-12-30 20:57:02 +0000562 if (!url.isValid())
cdumez@apple.com4c621c12015-01-22 22:19:46 +0000563 return nullptr;
abarth@webkit.orgc17c9592008-06-21 20:33:42 +0000564
commit-queue@webkit.org4b3425062015-04-02 00:22:54 +0000565 if (!canRequest(type, url, request.options(), request.forPreload()))
cdumez@apple.com4c621c12015-01-22 22:19:46 +0000566 return nullptr;
antti@apple.comf73108e2010-12-30 20:57:02 +0000567
benjamin@webkit.org74bde2b2015-01-09 01:56:00 +0000568#if ENABLE(CONTENT_EXTENSIONS)
weinig@apple.com1578a242016-03-15 00:48:40 +0000569 if (frame() && frame()->mainFrame().page() && m_documentLoader) {
570 if (frame()->mainFrame().page()->userContentProvider().processContentExtensionRulesForLoad(request.mutableResourceRequest(), toResourceType(type), *m_documentLoader) == ContentExtensions::BlockedStatus::Blocked) {
commit-queue@webkit.org8090ccb2015-10-06 08:18:08 +0000571 if (type == CachedResource::Type::MainResource) {
572 auto resource = createResource(type, request.mutableResourceRequest(), request.charset(), sessionID());
573 ASSERT(resource);
574 resource->error(CachedResource::Status::LoadError);
ddkilzer@apple.com778bccc2015-12-25 12:22:16 +0000575 resource->setResourceError(ResourceError(ContentExtensions::WebKitContentBlockerDomain, 0, request.resourceRequest().url(), WEB_UI_STRING("The URL was blocked by a content blocker", "WebKitErrorBlockedByContentBlocker description")));
commit-queue@webkit.org8090ccb2015-10-06 08:18:08 +0000576 return resource;
577 }
578 return nullptr;
579 }
commit-queue@webkit.orgcdda2902015-12-23 10:04:44 +0000580 url = request.resourceRequest().url(); // The content extension could have changed it from http to https.
581 url = MemoryCache::removeFragmentIdentifierIfNeeded(url); // Might need to remove fragment identifier again.
commit-queue@webkit.org8090ccb2015-10-06 08:18:08 +0000582 }
benjamin@webkit.org74bde2b2015-01-09 01:56:00 +0000583#endif
584
cdumez@apple.com41d2d702015-02-02 20:50:16 +0000585 auto& memoryCache = MemoryCache::singleton();
jer.noble@apple.com2ed319d2016-01-28 19:52:57 +0000586 if (request.allowsCaching() && memoryCache.disabled()) {
antti@apple.comf73108e2010-12-30 20:57:02 +0000587 DocumentResourceMap::iterator it = m_documentResources.find(url.string());
antti@apple.com7dca2462009-01-08 23:44:59 +0000588 if (it != m_documentResources.end()) {
hs85.jeong@samsung.com13179142015-10-21 02:12:32 +0000589 it->value->setOwningCachedResourceLoader(nullptr);
antti@apple.com7dca2462009-01-08 23:44:59 +0000590 m_documentResources.remove(it);
oliver1e69b1b2007-08-03 22:37:08 +0000591 }
andersca83197932007-07-26 23:52:02 +0000592 }
eric@webkit.orge0a51622008-06-26 22:45:47 +0000593
antti@apple.comf73108e2010-12-30 20:57:02 +0000594 // See if we can use an existing resource from the cache.
jpfau@apple.com97c6a7f2013-02-26 00:49:17 +0000595 CachedResourceHandle<CachedResource> resource;
596#if ENABLE(CACHE_PARTITIONING)
597 if (document())
cdumez@apple.com8730b6e2014-10-21 02:10:47 +0000598 request.mutableResourceRequest().setDomainForCachePartition(document()->topOrigin()->domainForCachePartition());
jpfau@apple.com97c6a7f2013-02-26 00:49:17 +0000599#endif
600
jer.noble@apple.com2ed319d2016-01-28 19:52:57 +0000601 if (request.allowsCaching())
602 resource = memoryCache.resourceForRequest(request.resourceRequest(), sessionID());
hyattc4404492006-10-19 09:21:54 +0000603
cdumez@apple.com4c621c12015-01-22 22:19:46 +0000604 logMemoryCacheResourceRequest(frame(), resource ? DiagnosticLoggingKeys::inMemoryCacheKey() : DiagnosticLoggingKeys::notInMemoryCacheKey());
cdumez@apple.com06defb32014-12-19 19:15:36 +0000605
antti@apple.com49ebfef2016-01-12 17:31:02 +0000606 const RevalidationPolicy policy = determineRevalidationPolicy(type, request, resource.get());
commit-queue@webkit.org67248b22012-09-25 06:51:39 +0000607 switch (policy) {
antti@apple.comf73108e2010-12-30 20:57:02 +0000608 case Reload:
cdumez@apple.com41d2d702015-02-02 20:50:16 +0000609 memoryCache.remove(*resource);
joepeck@webkit.orgaa676ee52014-01-28 04:04:52 +0000610 FALLTHROUGH;
commit-queue@webkit.org67248b22012-09-25 06:51:39 +0000611 case Load:
cdumez@apple.com06defb32014-12-19 19:15:36 +0000612 if (resource)
cdumez@apple.com4c621c12015-01-22 22:19:46 +0000613 logMemoryCacheResourceRequest(frame(), DiagnosticLoggingKeys::inMemoryCacheKey(), DiagnosticLoggingKeys::unusedKey());
andersca@apple.com7d7681a2014-04-09 01:45:43 +0000614 resource = loadResource(type, request);
antti@apple.comf73108e2010-12-30 20:57:02 +0000615 break;
616 case Revalidate:
cdumez@apple.com06defb32014-12-19 19:15:36 +0000617 if (resource)
cdumez@apple.com4c621c12015-01-22 22:19:46 +0000618 logMemoryCacheResourceRequest(frame(), DiagnosticLoggingKeys::inMemoryCacheKey(), DiagnosticLoggingKeys::revalidatingKey());
simonjam@chromium.org76cfc202012-12-03 22:20:47 +0000619 resource = revalidateResource(request, resource.get());
antti@apple.comf73108e2010-12-30 20:57:02 +0000620 break;
621 case Use:
commit-queue@webkit.org5eac6082014-03-11 04:22:10 +0000622 if (!shouldContinueAfterNotifyingLoadedFromMemoryCache(request, resource.get()))
cdumez@apple.com4c621c12015-01-22 22:19:46 +0000623 return nullptr;
624 logMemoryCacheResourceRequest(frame(), DiagnosticLoggingKeys::inMemoryCacheKey(), DiagnosticLoggingKeys::usedKey());
cdumez@apple.com41d2d702015-02-02 20:50:16 +0000625 memoryCache.resourceAccessed(*resource);
ossy@webkit.orgec38e432016-05-17 17:07:19 +0000626#if ENABLE(WEB_TIMING)
commit-queue@webkit.orgfab6e0d2016-06-01 20:15:23 +0000627 if (document() && RuntimeEnabledFeatures::sharedFeatures().resourceTimingEnabled()) {
yoav@yoav.ws4685b022016-05-13 22:34:29 +0000628 m_resourceTimingInfo.storeResourceTimingInitiatorInformation(resource, request, frame());
commit-queue@webkit.orgfab6e0d2016-06-01 20:15:23 +0000629 m_resourceTimingInfo.addResourceTiming(resource.get(), *document());
yoav@yoav.ws4685b022016-05-13 22:34:29 +0000630 }
ossy@webkit.orgec38e432016-05-17 17:07:19 +0000631#endif
antti@apple.comf73108e2010-12-30 20:57:02 +0000632 break;
aliceli1bf1f3912007-01-27 02:11:15 +0000633 }
antti@apple.comf73108e2010-12-30 20:57:02 +0000634
635 if (!resource)
cdumez@apple.com4c621c12015-01-22 22:19:46 +0000636 return nullptr;
antti@apple.comf73108e2010-12-30 20:57:02 +0000637
simonjam@chromium.org85733842013-02-02 07:40:08 +0000638 if (!request.forPreload() || policy != Use)
639 resource->setLoadPriority(request.priority());
640
commit-queue@webkit.org864dbda2012-11-16 12:21:57 +0000641 if ((policy != Use || resource->stillNeedsLoad()) && CachedResourceRequest::NoDefer == request.defer()) {
cdumez@apple.com0bb03ec2015-01-28 05:53:53 +0000642 resource->load(*this, request.options());
commit-queue@webkit.org67248b22012-09-25 06:51:39 +0000643
beidson@apple.com94a692d2014-07-28 23:14:04 +0000644 // We don't support immediate loads, but we do support immediate failure.
commit-queue@webkit.org67248b22012-09-25 06:51:39 +0000645 if (resource->errorOccurred()) {
jer.noble@apple.com2ed319d2016-01-28 19:52:57 +0000646 if (resource->allowsCaching() && resource->inCache())
cdumez@apple.com41d2d702015-02-02 20:50:16 +0000647 memoryCache.remove(*resource);
cdumez@apple.com4c621c12015-01-22 22:19:46 +0000648 return nullptr;
commit-queue@webkit.org67248b22012-09-25 06:51:39 +0000649 }
650 }
651
akling@apple.com7b726d12014-04-24 04:11:50 +0000652 if (document() && !document()->loadEventFinished() && !request.resourceRequest().url().protocolIsData())
commit-queue@webkit.org5e7ea1b2012-10-22 23:35:28 +0000653 m_validatedURLs.add(request.resourceRequest().url());
commit-queue@webkit.org67248b22012-09-25 06:51:39 +0000654
antti@apple.comf73108e2010-12-30 20:57:02 +0000655 ASSERT(resource->url() == url.string());
commit-queue@webkit.org945e62b2014-03-30 06:01:08 +0000656 m_documentResources.set(resource->url(), resource);
hyattc4404492006-10-19 09:21:54 +0000657 return resource;
658}
ap@apple.com6edc42b2012-05-11 02:31:26 +0000659
akling@apple.com7b726d12014-04-24 04:11:50 +0000660void CachedResourceLoader::documentDidFinishLoadEvent()
661{
662 m_validatedURLs.clear();
663}
664
simonjam@chromium.org76cfc202012-12-03 22:20:47 +0000665CachedResourceHandle<CachedResource> CachedResourceLoader::revalidateResource(const CachedResourceRequest& request, CachedResource* resource)
antti@apple.comf73108e2010-12-30 20:57:02 +0000666{
667 ASSERT(resource);
668 ASSERT(resource->inCache());
cdumez@apple.com41d2d702015-02-02 20:50:16 +0000669 auto& memoryCache = MemoryCache::singleton();
670 ASSERT(!memoryCache.disabled());
antti@apple.comf73108e2010-12-30 20:57:02 +0000671 ASSERT(resource->canUseCacheValidator());
672 ASSERT(!resource->resourceToRevalidate());
commit-queue@webkit.org9ab4d3e2014-03-05 20:11:03 +0000673 ASSERT(resource->sessionID() == sessionID());
jer.noble@apple.com2ed319d2016-01-28 19:52:57 +0000674 ASSERT(resource->allowsCaching());
commit-queue@webkit.org9ab4d3e2014-03-05 20:11:03 +0000675
commit-queue@webkit.org9ab4d3e2014-03-05 20:11:03 +0000676 CachedResourceHandle<CachedResource> newResource = createResource(resource->type(), resource->resourceRequest(), resource->encoding(), resource->sessionID());
antti@apple.com86e0ce32015-08-12 21:07:49 +0000677
ap@apple.com6edc42b2012-05-11 02:31:26 +0000678 LOG(ResourceLoading, "Resource %p created to revalidate %p", newResource.get(), resource);
antti@apple.comf73108e2010-12-30 20:57:02 +0000679 newResource->setResourceToRevalidate(resource);
680
cdumez@apple.com41d2d702015-02-02 20:50:16 +0000681 memoryCache.remove(*resource);
682 memoryCache.add(*newResource);
ossy@webkit.orgec38e432016-05-17 17:07:19 +0000683#if ENABLE(WEB_TIMING)
yoav@yoav.ws4ea6dc82016-05-02 08:21:50 +0000684 if (RuntimeEnabledFeatures::sharedFeatures().resourceTimingEnabled())
yoav@yoav.ws4685b022016-05-13 22:34:29 +0000685 m_resourceTimingInfo.storeResourceTimingInitiatorInformation(resource, request, frame());
ossy@webkit.orgec38e432016-05-17 17:07:19 +0000686#else
687 UNUSED_PARAM(request);
688#endif
antti@apple.comf73108e2010-12-30 20:57:02 +0000689 return newResource;
690}
691
andersca@apple.com7d7681a2014-04-09 01:45:43 +0000692CachedResourceHandle<CachedResource> CachedResourceLoader::loadResource(CachedResource::Type type, CachedResourceRequest& request)
antti@apple.comf73108e2010-12-30 20:57:02 +0000693{
cdumez@apple.com41d2d702015-02-02 20:50:16 +0000694 auto& memoryCache = MemoryCache::singleton();
commit-queue@webkit.orgc5b6a802016-06-01 00:28:25 +0000695 ASSERT(!request.allowsCaching() || !memoryCache.resourceForRequest(request.resourceRequest(), sessionID()));
simonjam@chromium.org5f127162012-11-30 19:17:45 +0000696
mkwst@chromium.org6f6d9bc2013-05-30 12:08:58 +0000697 LOG(ResourceLoading, "Loading CachedResource for '%s'.", request.resourceRequest().url().stringCenterEllipsizedToLength().latin1().data());
simonjam@chromium.org5f127162012-11-30 19:17:45 +0000698
andersca@apple.com7d7681a2014-04-09 01:45:43 +0000699 CachedResourceHandle<CachedResource> resource = createResource(type, request.mutableResourceRequest(), request.charset(), sessionID());
simonjam@chromium.org5f127162012-11-30 19:17:45 +0000700
jer.noble@apple.com2ed319d2016-01-28 19:52:57 +0000701 if (request.allowsCaching() && !memoryCache.add(*resource))
antti@apple.comf73108e2010-12-30 20:57:02 +0000702 resource->setOwningCachedResourceLoader(this);
ossy@webkit.orgec38e432016-05-17 17:07:19 +0000703#if ENABLE(WEB_TIMING)
yoav@yoav.ws4ea6dc82016-05-02 08:21:50 +0000704 if (RuntimeEnabledFeatures::sharedFeatures().resourceTimingEnabled())
yoav@yoav.ws4685b022016-05-13 22:34:29 +0000705 m_resourceTimingInfo.storeResourceTimingInitiatorInformation(resource, request, frame());
ossy@webkit.orgec38e432016-05-17 17:07:19 +0000706#endif
antti@apple.comf73108e2010-12-30 20:57:02 +0000707 return resource;
708}
709
antti@apple.com6e313872015-05-13 23:09:13 +0000710static void logRevalidation(const String& reason, DiagnosticLoggingClient& logClient)
711{
712 logClient.logDiagnosticMessageWithValue(DiagnosticLoggingKeys::cachedResourceRevalidationKey(), DiagnosticLoggingKeys::reasonKey(), reason, ShouldSample::Yes);
713}
714
715static void logResourceRevalidationDecision(CachedResource::RevalidationDecision reason, const Frame* frame)
716{
cdumez@apple.com10d0f252016-04-23 21:33:49 +0000717 if (!frame || !frame->page())
antti@apple.com6e313872015-05-13 23:09:13 +0000718 return;
cdumez@apple.com10d0f252016-04-23 21:33:49 +0000719 auto& logClient = frame->page()->diagnosticLoggingClient();
antti@apple.com6e313872015-05-13 23:09:13 +0000720 switch (reason) {
721 case CachedResource::RevalidationDecision::No:
722 break;
723 case CachedResource::RevalidationDecision::YesDueToExpired:
724 logRevalidation(DiagnosticLoggingKeys::isExpiredKey(), logClient);
725 break;
726 case CachedResource::RevalidationDecision::YesDueToNoStore:
727 logRevalidation(DiagnosticLoggingKeys::noStoreKey(), logClient);
728 break;
729 case CachedResource::RevalidationDecision::YesDueToNoCache:
730 logRevalidation(DiagnosticLoggingKeys::noCacheKey(), logClient);
731 break;
732 case CachedResource::RevalidationDecision::YesDueToCachePolicy:
733 logRevalidation(DiagnosticLoggingKeys::reloadKey(), logClient);
734 break;
735 }
736}
737
antti@apple.com49ebfef2016-01-12 17:31:02 +0000738CachedResourceLoader::RevalidationPolicy CachedResourceLoader::determineRevalidationPolicy(CachedResource::Type type, CachedResourceRequest& cachedResourceRequest, CachedResource* existingResource) const
antti@apple.comf73108e2010-12-30 20:57:02 +0000739{
antti@apple.com49ebfef2016-01-12 17:31:02 +0000740 auto& request = cachedResourceRequest.resourceRequest();
741
antti@apple.comf73108e2010-12-30 20:57:02 +0000742 if (!existingResource)
743 return Load;
commit-queue@webkit.org67248b22012-09-25 06:51:39 +0000744
antti@apple.comf73108e2010-12-30 20:57:02 +0000745 // We already have a preload going for this URL.
antti@apple.com49ebfef2016-01-12 17:31:02 +0000746 if (cachedResourceRequest.forPreload() && existingResource->isPreloaded())
antti@apple.comf73108e2010-12-30 20:57:02 +0000747 return Use;
commit-queue@webkit.org67248b22012-09-25 06:51:39 +0000748
antti@apple.comf73108e2010-12-30 20:57:02 +0000749 // If the same URL has been loaded as a different type, we need to reload.
750 if (existingResource->type() != type) {
751 LOG(ResourceLoading, "CachedResourceLoader::determineRevalidationPolicy reloading due to type mismatch.");
cdumez@apple.com4c621c12015-01-22 22:19:46 +0000752 logMemoryCacheResourceRequest(frame(), DiagnosticLoggingKeys::inMemoryCacheKey(), DiagnosticLoggingKeys::unusedReasonTypeMismatchKey());
antti@apple.comf73108e2010-12-30 20:57:02 +0000753 return Reload;
754 }
japhet@chromium.orgb0444b32011-10-07 18:16:03 +0000755
antti@apple.com7f812372016-06-08 13:37:04 +0000756 if (!existingResource->varyHeaderValuesMatch(request, *this))
757 return Reload;
758
antti@apple.com6d5c6b32016-04-22 17:37:09 +0000759 auto* textDecoder = existingResource->textResourceDecoder();
760 if (textDecoder && !textDecoder->hasEqualEncodingForCharset(cachedResourceRequest.charset()))
antti@apple.com49ebfef2016-01-12 17:31:02 +0000761 return Reload;
762
antti@apple.com2c4a2a22015-08-14 14:08:59 +0000763 // FIXME: We should use the same cache policy for all resource types. The raw resource policy is overly strict
764 // while the normal subresource policy is too loose.
commit-queue@webkit.org3dd45802016-03-22 19:12:32 +0000765 if (existingResource->isMainOrMediaOrRawResource() && frame()) {
antti@apple.com2c4a2a22015-08-14 14:08:59 +0000766 bool strictPolicyDisabled = frame()->loader().isStrictRawResourceValidationPolicyDisabledForTesting();
767 bool canReuseRawResource = strictPolicyDisabled || downcast<CachedRawResource>(*existingResource).canReuse(request);
768 if (!canReuseRawResource)
769 return Reload;
770 }
japhet@chromium.org548ffc12012-02-14 06:45:41 +0000771
ap@apple.com2a262342013-10-31 16:50:03 +0000772 // Conditional requests should have failed canReuse check.
773 ASSERT(!request.isConditional());
commit-queue@webkit.org67248b22012-09-25 06:51:39 +0000774
775 // Do not load from cache if images are not enabled. The load for this image will be blocked
776 // in CachedImage::load.
antti@apple.com49ebfef2016-01-12 17:31:02 +0000777 if (cachedResourceRequest.defer() == CachedResourceRequest::DeferredByClient)
commit-queue@webkit.org67248b22012-09-25 06:51:39 +0000778 return Reload;
antti@apple.comf73108e2010-12-30 20:57:02 +0000779
780 // Don't reload resources while pasting.
781 if (m_allowStaleResources)
782 return Use;
783
antti@apple.com86e0ce32015-08-12 21:07:49 +0000784 // Always use preloads.
antti@apple.comf73108e2010-12-30 20:57:02 +0000785 if (existingResource->isPreloaded())
786 return Use;
cdumez@apple.com74ef9852015-01-07 01:59:10 +0000787
antti@apple.com86e0ce32015-08-12 21:07:49 +0000788 // We can find resources that are being validated from cache only when validation is just successfully completing.
789 if (existingResource->validationCompleting())
790 return Use;
791 ASSERT(!existingResource->validationInProgress());
792
cdumez@apple.com74ef9852015-01-07 01:59:10 +0000793 // Validate the redirect chain.
794 bool cachePolicyIsHistoryBuffer = cachePolicy(type) == CachePolicyHistoryBuffer;
795 if (!existingResource->redirectChainAllowsReuse(cachePolicyIsHistoryBuffer ? ReuseExpiredRedirection : DoNotReuseExpiredRedirection)) {
796 LOG(ResourceLoading, "CachedResourceLoader::determineRevalidationPolicy reloading due to not cached or expired redirections.");
cdumez@apple.com4c621c12015-01-22 22:19:46 +0000797 logMemoryCacheResourceRequest(frame(), DiagnosticLoggingKeys::inMemoryCacheKey(), DiagnosticLoggingKeys::unusedReasonRedirectChainKey());
cdumez@apple.com74ef9852015-01-07 01:59:10 +0000798 return Reload;
799 }
800
801 // CachePolicyHistoryBuffer uses the cache except if this is a main resource with "cache-control: no-store".
802 if (cachePolicyIsHistoryBuffer) {
803 // FIXME: Ignoring "cache-control: no-cache" for sub-resources on history navigation but not the main
804 // resource is inconsistent. We should probably harmonize this.
805 if (!existingResource->response().cacheControlContainsNoStore() || type != CachedResource::MainResource)
806 return Use;
807 }
antti@apple.com7d58d6e2011-01-10 18:32:58 +0000808
809 // Don't reuse resources with Cache-control: no-store.
810 if (existingResource->response().cacheControlContainsNoStore()) {
811 LOG(ResourceLoading, "CachedResourceLoader::determineRevalidationPolicy reloading due to Cache-control: no-store.");
cdumez@apple.com4c621c12015-01-22 22:19:46 +0000812 logMemoryCacheResourceRequest(frame(), DiagnosticLoggingKeys::inMemoryCacheKey(), DiagnosticLoggingKeys::unusedReasonNoStoreKey());
antti@apple.com7d58d6e2011-01-10 18:32:58 +0000813 return Reload;
814 }
815
kbr@google.com9a62ac32011-07-23 00:18:34 +0000816 // If credentials were sent with the previous request and won't be
817 // with this one, or vice versa, re-fetch the resource.
818 //
819 // This helps with the case where the server sends back
820 // "Access-Control-Allow-Origin: *" all the time, but some of the
821 // client's requests are made without CORS and some with.
822 if (existingResource->resourceRequest().allowCookies() != request.allowCookies()) {
823 LOG(ResourceLoading, "CachedResourceLoader::determineRevalidationPolicy reloading due to difference in credentials settings.");
cdumez@apple.com4c621c12015-01-22 22:19:46 +0000824 logMemoryCacheResourceRequest(frame(), DiagnosticLoggingKeys::inMemoryCacheKey(), DiagnosticLoggingKeys::unusedReasonCredentialSettingsKey());
kbr@google.com9a62ac32011-07-23 00:18:34 +0000825 return Reload;
826 }
827
simonjam@chromium.org94d9cae2011-08-18 18:41:28 +0000828 // During the initial load, avoid loading the same resource multiple times for a single document, even if the cache policies would tell us to.
japhet@chromium.org97fe9052012-10-09 21:58:25 +0000829 if (document() && !document()->loadEventFinished() && m_validatedURLs.contains(existingResource->url()))
antti@apple.comf73108e2010-12-30 20:57:02 +0000830 return Use;
simonjam@chromium.org94d9cae2011-08-18 18:41:28 +0000831
antti@apple.comf73108e2010-12-30 20:57:02 +0000832 // CachePolicyReload always reloads
japhet@chromium.orgbb0c4872013-02-13 02:42:02 +0000833 if (cachePolicy(type) == CachePolicyReload) {
antti@apple.comf73108e2010-12-30 20:57:02 +0000834 LOG(ResourceLoading, "CachedResourceLoader::determineRevalidationPolicy reloading due to CachePolicyReload.");
cdumez@apple.com4c621c12015-01-22 22:19:46 +0000835 logMemoryCacheResourceRequest(frame(), DiagnosticLoggingKeys::inMemoryCacheKey(), DiagnosticLoggingKeys::unusedReasonReloadKey());
antti@apple.comf73108e2010-12-30 20:57:02 +0000836 return Reload;
837 }
838
antti@apple.comf73108e2010-12-30 20:57:02 +0000839 // We'll try to reload the resource if it failed last time.
840 if (existingResource->errorOccurred()) {
841 LOG(ResourceLoading, "CachedResourceLoader::determineRevalidationPolicye reloading due to resource being in the error state");
cdumez@apple.com4c621c12015-01-22 22:19:46 +0000842 logMemoryCacheResourceRequest(frame(), DiagnosticLoggingKeys::inMemoryCacheKey(), DiagnosticLoggingKeys::unusedReasonErrorKey());
antti@apple.comf73108e2010-12-30 20:57:02 +0000843 return Reload;
844 }
845
846 // For resources that are not yet loaded we ignore the cache policy.
847 if (existingResource->isLoading())
848 return Use;
849
antti@apple.com6e313872015-05-13 23:09:13 +0000850 auto revalidationDecision = existingResource->makeRevalidationDecision(cachePolicy(type));
851 logResourceRevalidationDecision(revalidationDecision, frame());
852
antti@apple.comf73108e2010-12-30 20:57:02 +0000853 // Check if the cache headers requires us to revalidate (cache expiration for example).
antti@apple.com6e313872015-05-13 23:09:13 +0000854 if (revalidationDecision != CachedResource::RevalidationDecision::No) {
antti@apple.comf73108e2010-12-30 20:57:02 +0000855 // See if the resource has usable ETag or Last-modified headers.
856 if (existingResource->canUseCacheValidator())
857 return Revalidate;
858
859 // No, must reload.
cdumez@apple.com06defb32014-12-19 19:15:36 +0000860 LOG(ResourceLoading, "CachedResourceLoader::determineRevalidationPolicy reloading due to missing cache validators.");
cdumez@apple.com4c621c12015-01-22 22:19:46 +0000861 logMemoryCacheResourceRequest(frame(), DiagnosticLoggingKeys::inMemoryCacheKey(), DiagnosticLoggingKeys::unusedReasonMustRevalidateNoValidatorKey());
antti@apple.comf73108e2010-12-30 20:57:02 +0000862 return Reload;
863 }
864
865 return Use;
866}
hyattc4404492006-10-19 09:21:54 +0000867
darin@apple.com5ffbb5c2013-09-27 16:39:41 +0000868void CachedResourceLoader::printAccessDeniedMessage(const URL& url) const
abarth@webkit.org234c23a2008-06-21 20:33:53 +0000869{
870 if (url.isNull())
871 return;
872
eric@webkit.orge0a51622008-06-26 22:45:47 +0000873 if (!frame())
abarth@webkit.org234c23a2008-06-21 20:33:53 +0000874 return;
875
zimmermann@webkit.orgb5e11e62011-05-16 07:56:06 +0000876 String message;
japhet@chromium.org97fe9052012-10-09 21:58:25 +0000877 if (!m_document || m_document->url().isNull())
mkwst@chromium.org6f6d9bc2013-05-30 12:08:58 +0000878 message = "Unsafe attempt to load URL " + url.stringCenterEllipsizedToLength() + '.';
zimmermann@webkit.orgb5e11e62011-05-16 07:56:06 +0000879 else
mkwst@chromium.org6f6d9bc2013-05-30 12:08:58 +0000880 message = "Unsafe attempt to load URL " + url.stringCenterEllipsizedToLength() + " from frame with URL " + m_document->url().stringCenterEllipsizedToLength() + ". Domains, protocols and ports must match.\n";
abarth@webkit.org234c23a2008-06-21 20:33:53 +0000881
joepeck@webkit.org1f45df92014-02-06 23:45:53 +0000882 frame()->document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, message);
abarth@webkit.org234c23a2008-06-21 20:33:53 +0000883}
884
abarth@webkit.org17d66c62010-09-08 10:26:02 +0000885void CachedResourceLoader::setAutoLoadImages(bool enable)
hyattc4404492006-10-19 09:21:54 +0000886{
887 if (enable == m_autoLoadImages)
eseidel94980f22006-01-09 09:29:48 +0000888 return;
889
hyattc4404492006-10-19 09:21:54 +0000890 m_autoLoadImages = enable;
eseidel94980f22006-01-09 09:29:48 +0000891
hyattc4404492006-10-19 09:21:54 +0000892 if (!m_autoLoadImages)
eseidel27707962006-03-20 23:25:37 +0000893 return;
eseidel94980f22006-01-09 09:29:48 +0000894
commit-queue@webkit.org67248b22012-09-25 06:51:39 +0000895 reloadImagesIfNotDeferred();
896}
897
898void CachedResourceLoader::setImagesEnabled(bool enable)
899{
900 if (enable == m_imagesEnabled)
901 return;
902
903 m_imagesEnabled = enable;
904
905 if (!m_imagesEnabled)
906 return;
907
908 reloadImagesIfNotDeferred();
909}
910
darin@apple.comc50e0472014-04-21 18:08:49 +0000911bool CachedResourceLoader::clientDefersImage(const URL&) const
commit-queue@webkit.org67248b22012-09-25 06:51:39 +0000912{
darin@apple.comc50e0472014-04-21 18:08:49 +0000913 return !m_imagesEnabled;
commit-queue@webkit.org67248b22012-09-25 06:51:39 +0000914}
915
commit-queue@webkit.org12f31ee2015-02-04 20:55:21 +0000916bool CachedResourceLoader::shouldPerformImageLoad(const URL& url) const
917{
918 return m_autoLoadImages || url.protocolIsData();
919}
920
darin@apple.com5ffbb5c2013-09-27 16:39:41 +0000921bool CachedResourceLoader::shouldDeferImageLoad(const URL& url) const
commit-queue@webkit.org67248b22012-09-25 06:51:39 +0000922{
commit-queue@webkit.org12f31ee2015-02-04 20:55:21 +0000923 return clientDefersImage(url) || !shouldPerformImageLoad(url);
commit-queue@webkit.org67248b22012-09-25 06:51:39 +0000924}
925
926void CachedResourceLoader::reloadImagesIfNotDeferred()
927{
commit-queue@webkit.orgacddfad2015-09-30 05:53:51 +0000928 for (auto& resource : m_documentResources.values()) {
cdumez@apple.comc4a3af62014-10-06 00:31:05 +0000929 if (is<CachedImage>(*resource) && resource->stillNeedsLoad() && !clientDefersImage(resource->url()))
cdumez@apple.com0bb03ec2015-01-28 05:53:53 +0000930 downcast<CachedImage>(*resource).load(*this, defaultCachedResourceOptions());
mjsdd13ab42006-05-09 07:23:24 +0000931 }
eseidel94980f22006-01-09 09:29:48 +0000932}
933
japhet@chromium.orgbb0c4872013-02-13 02:42:02 +0000934CachePolicy CachedResourceLoader::cachePolicy(CachedResource::Type type) const
eseidel94980f22006-01-09 09:29:48 +0000935{
darin@apple.com0fdefc32016-03-18 07:56:20 +0000936 Frame* frame = this->frame();
937 if (!frame)
japhet@chromium.orgbb0c4872013-02-13 02:42:02 +0000938 return CachePolicyVerify;
939
940 if (type != CachedResource::MainResource)
darin@apple.com0fdefc32016-03-18 07:56:20 +0000941 return frame->loader().subresourceCachePolicy();
darin@apple.com30c194a2016-03-20 20:08:59 +0000942
943 if (Page* page = frame->page()) {
944 if (page->isResourceCachingDisabled())
945 return CachePolicyReload;
946 }
947
darin@apple.com0fdefc32016-03-18 07:56:20 +0000948 switch (frame->loader().loadType()) {
cdumez@apple.com74ef9852015-01-07 01:59:10 +0000949 case FrameLoadType::ReloadFromOrigin:
950 case FrameLoadType::Reload:
japhet@chromium.orgbb0c4872013-02-13 02:42:02 +0000951 return CachePolicyReload;
cdumez@apple.com74ef9852015-01-07 01:59:10 +0000952 case FrameLoadType::Back:
953 case FrameLoadType::Forward:
954 case FrameLoadType::IndexedBackForward:
955 // Do not revalidate cached main resource on back/forward navigation.
956 return CachePolicyHistoryBuffer;
957 default:
958 return CachePolicyVerify;
959 }
eseidel94980f22006-01-09 09:29:48 +0000960}
961
cdumez@apple.coma2f2a5a2015-01-31 00:04:36 +0000962void CachedResourceLoader::removeCachedResource(CachedResource& resource)
eseidel94980f22006-01-09 09:29:48 +0000963{
ap@webkit.org50189dd2009-04-27 16:57:13 +0000964#ifndef NDEBUG
cdumez@apple.coma2f2a5a2015-01-31 00:04:36 +0000965 DocumentResourceMap::iterator it = m_documentResources.find(resource.url());
ap@webkit.org50189dd2009-04-27 16:57:13 +0000966 if (it != m_documentResources.end())
cdumez@apple.coma2f2a5a2015-01-31 00:04:36 +0000967 ASSERT(it->value.get() == &resource);
ap@webkit.org50189dd2009-04-27 16:57:13 +0000968#endif
cdumez@apple.coma2f2a5a2015-01-31 00:04:36 +0000969 m_documentResources.remove(resource.url());
eseidel94980f22006-01-09 09:29:48 +0000970}
971
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +0000972void CachedResourceLoader::loadDone(CachedResource* resource, bool shouldPerformPostLoadActions)
japhet@chromium.orgf8d43692010-12-10 19:26:15 +0000973{
japhet@chromium.org97fe9052012-10-09 21:58:25 +0000974 RefPtr<DocumentLoader> protectDocumentLoader(m_documentLoader);
975 RefPtr<Document> protectDocument(m_document);
simonjam@chromium.org76cfc202012-12-03 22:20:47 +0000976
yoav@yoav.ws30bf4a42016-05-02 16:21:33 +0000977#if ENABLE(WEB_TIMING)
commit-queue@webkit.orgfab6e0d2016-06-01 20:15:23 +0000978 if (document() && RuntimeEnabledFeatures::sharedFeatures().resourceTimingEnabled())
979 m_resourceTimingInfo.addResourceTiming(resource, *document());
ossy@webkit.orgc1100342016-05-10 20:42:33 +0000980#else
981 UNUSED_PARAM(resource);
yoav@yoav.ws30bf4a42016-05-02 16:21:33 +0000982#endif
simonjam@chromium.org76cfc202012-12-03 22:20:47 +0000983
japhet@chromium.orgf8d43692010-12-10 19:26:15 +0000984 if (frame())
andersca@apple.comdf550b92013-08-15 22:17:17 +0000985 frame()->loader().loadDone();
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +0000986
987 if (shouldPerformPostLoadActions)
988 performPostLoadActions();
commit-queue@webkit.org9acd5fe2011-08-01 21:22:08 +0000989
990 if (!m_garbageCollectDocumentResourcesTimer.isActive())
991 m_garbageCollectDocumentResourcesTimer.startOneShot(0);
992}
993
994// Garbage collecting m_documentResources is a workaround for the
995// CachedResourceHandles on the RHS being strong references. Ideally this
996// would be a weak map, however CachedResourceHandles perform additional
997// bookkeeping on CachedResources, so instead pseudo-GC them -- when the
998// reference count reaches 1, m_documentResources is the only reference, so
999// remove it from the map.
vsevik@chromium.org58d6bc32012-07-30 15:58:48 +00001000void CachedResourceLoader::garbageCollectDocumentResources()
1001{
commit-queue@webkit.org9acd5fe2011-08-01 21:22:08 +00001002 typedef Vector<String, 10> StringVector;
1003 StringVector resourcesToDelete;
1004
commit-queue@webkit.orgacddfad2015-09-30 05:53:51 +00001005 for (auto& resource : m_documentResources) {
1006 if (resource.value->hasOneHandle()) {
1007 resourcesToDelete.append(resource.key);
1008 resource.value->setOwningCachedResourceLoader(nullptr);
commit-queue@webkit.org9acd5fe2011-08-01 21:22:08 +00001009 }
1010 }
1011
commit-queue@webkit.orgacddfad2015-09-30 05:53:51 +00001012 for (auto& resource : resourcesToDelete)
1013 m_documentResources.remove(resource);
bweinstein@apple.com3ce39392011-01-26 19:07:15 +00001014}
1015
1016void CachedResourceLoader::performPostLoadActions()
1017{
japhet@chromium.orgf8d43692010-12-10 19:26:15 +00001018 checkForPendingPreloads();
beidson@apple.com33785562012-10-25 17:16:38 +00001019
antti@apple.comc86c65b2015-12-03 12:51:17 +00001020 platformStrategies()->loaderStrategy()->servePendingRequests();
japhet@chromium.orgf8d43692010-12-10 19:26:15 +00001021}
1022
youenn.fablet@crf.canon.fr55144c52016-06-02 08:45:14 +00001023void CachedResourceLoader::incrementRequestCount(const CachedResource& resource)
beidson22febd12007-05-04 04:35:28 +00001024{
youenn.fablet@crf.canon.fr55144c52016-06-02 08:45:14 +00001025 if (resource.ignoreForRequestCount())
commit-queue@webkit.orga67f42c2010-07-10 02:41:10 +00001026 return;
1027
beidson22febd12007-05-04 04:35:28 +00001028 ++m_requestCount;
1029}
1030
youenn.fablet@crf.canon.fr55144c52016-06-02 08:45:14 +00001031void CachedResourceLoader::decrementRequestCount(const CachedResource& resource)
beidson22febd12007-05-04 04:35:28 +00001032{
youenn.fablet@crf.canon.fr55144c52016-06-02 08:45:14 +00001033 if (resource.ignoreForRequestCount())
commit-queue@webkit.orga67f42c2010-07-10 02:41:10 +00001034 return;
1035
beidson22febd12007-05-04 04:35:28 +00001036 --m_requestCount;
1037 ASSERT(m_requestCount > -1);
1038}
commit-queue@webkit.org864dbda2012-11-16 12:21:57 +00001039
abarth@webkit.org1f4721c2013-01-02 23:06:14 +00001040void CachedResourceLoader::preload(CachedResource::Type type, CachedResourceRequest& request, const String& charset)
antti@apple.coma05e8b02008-08-15 22:58:06 +00001041{
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00001042 // We always preload resources on iOS. See <https://bugs.webkit.org/show_bug.cgi?id=91276>.
1043 // FIXME: We should consider adding a setting to toggle aggressive preloading behavior as opposed
1044 // to making this behavior specific to iOS.
1045#if !PLATFORM(IOS)
cdumez@apple.comf9780832015-01-27 00:26:21 +00001046 bool hasRendering = m_document->bodyOrFrameset() && m_document->renderView();
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00001047 bool canBlockParser = type == CachedResource::Script || type == CachedResource::CSSStyleSheet;
1048 if (!hasRendering && !canBlockParser) {
1049 // Don't preload subresources that can't block the parser before we have something to draw.
1050 // This helps prevent preloads from delaying first display when bandwidth is limited.
1051 PendingPreload pendingPreload = { type, request, charset };
1052 m_pendingPreloads.append(pendingPreload);
1053 return;
antti@apple.coma05e8b02008-08-15 22:58:06 +00001054 }
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00001055#endif
simonjam@chromium.org5f127162012-11-30 19:17:45 +00001056 requestPreload(type, request, charset);
antti@apple.coma05e8b02008-08-15 22:58:06 +00001057}
1058
abarth@webkit.org17d66c62010-09-08 10:26:02 +00001059void CachedResourceLoader::checkForPendingPreloads()
antti@apple.coma05e8b02008-08-15 22:58:06 +00001060{
cdumez@apple.com15e3a342015-01-27 07:05:08 +00001061 if (m_pendingPreloads.isEmpty())
1062 return;
1063 auto* body = m_document->bodyOrFrameset();
1064 if (!body || !body->renderer())
antti@apple.coma05e8b02008-08-15 22:58:06 +00001065 return;
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00001066#if PLATFORM(IOS)
1067 // We always preload resources on iOS. See <https://bugs.webkit.org/show_bug.cgi?id=91276>.
1068 // So, we should never have any pending preloads.
1069 // FIXME: We should look to avoid compiling this code entirely when building for iOS.
1070 ASSERT_NOT_REACHED();
1071#endif
bweinstein@apple.com3ce39392011-01-26 19:07:15 +00001072 while (!m_pendingPreloads.isEmpty()) {
1073 PendingPreload preload = m_pendingPreloads.takeFirst();
ap@webkit.org86b10982009-05-18 15:30:10 +00001074 // Don't request preload if the resource already loaded normally (this will result in double load if the page is being reloaded with cached results ignored).
simonjam@chromium.org5f127162012-11-30 19:17:45 +00001075 if (!cachedResource(preload.m_request.resourceRequest().url()))
japhet@chromium.org7e4338d2011-05-25 00:24:38 +00001076 requestPreload(preload.m_type, preload.m_request, preload.m_charset);
antti@apple.coma05e8b02008-08-15 22:58:06 +00001077 }
1078 m_pendingPreloads.clear();
1079}
1080
simonjam@chromium.org5f127162012-11-30 19:17:45 +00001081void CachedResourceLoader::requestPreload(CachedResource::Type type, CachedResourceRequest& request, const String& charset)
antti@apple.com6c76e542008-03-13 21:20:31 +00001082{
antti@apple.com5fcdfd22008-04-16 21:41:12 +00001083 String encoding;
1084 if (type == CachedResource::Script || type == CachedResource::CSSStyleSheet)
paroga@webkit.org927c50bd2011-02-05 20:34:19 +00001085 encoding = charset.isEmpty() ? m_document->charset() : charset;
antti@apple.com5fcdfd22008-04-16 21:41:12 +00001086
simonjam@chromium.org5f127162012-11-30 19:17:45 +00001087 request.setCharset(encoding);
1088 request.setForPreload(true);
commit-queue@webkit.org5e7ea1b2012-10-22 23:35:28 +00001089
simonjam@chromium.org5f127162012-11-30 19:17:45 +00001090 CachedResourceHandle<CachedResource> resource = requestResource(type, request);
ap@apple.com6edc42b2012-05-11 02:31:26 +00001091 if (!resource || (m_preloads && m_preloads->contains(resource.get())))
antti@apple.com6c76e542008-03-13 21:20:31 +00001092 return;
1093 resource->increasePreloadCount();
andersca@apple.com99226092010-05-18 19:25:01 +00001094
1095 if (!m_preloads)
gyuyoung.kim@samsung.com56cf34c2014-11-17 06:46:24 +00001096 m_preloads = std::make_unique<ListHashSet<CachedResource*>>();
ap@apple.com6edc42b2012-05-11 02:31:26 +00001097 m_preloads->add(resource.get());
andersca@apple.com99226092010-05-18 19:25:01 +00001098
antti@apple.com6c76e542008-03-13 21:20:31 +00001099#if PRELOAD_DEBUG
1100 printf("PRELOADING %s\n", resource->url().latin1().data());
1101#endif
1102}
beidson22febd12007-05-04 04:35:28 +00001103
japhet@chromium.org94a630a2011-06-23 00:28:56 +00001104bool CachedResourceLoader::isPreloaded(const String& urlString) const
1105{
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00001106 const URL& url = m_document->completeURL(urlString);
japhet@chromium.org94a630a2011-06-23 00:28:56 +00001107
1108 if (m_preloads) {
commit-queue@webkit.orgacddfad2015-09-30 05:53:51 +00001109 for (auto& resource : *m_preloads) {
japhet@chromium.org94a630a2011-06-23 00:28:56 +00001110 if (resource->url() == url)
1111 return true;
1112 }
1113 }
1114
commit-queue@webkit.orgacddfad2015-09-30 05:53:51 +00001115 for (auto& pendingPreload : m_pendingPreloads) {
simonjam@chromium.org5f127162012-11-30 19:17:45 +00001116 if (pendingPreload.m_request.resourceRequest().url() == url)
japhet@chromium.org94a630a2011-06-23 00:28:56 +00001117 return true;
1118 }
1119 return false;
1120}
1121
abarth@webkit.org17d66c62010-09-08 10:26:02 +00001122void CachedResourceLoader::clearPreloads()
antti@apple.com6c76e542008-03-13 21:20:31 +00001123{
1124#if PRELOAD_DEBUG
1125 printPreloadStats();
1126#endif
andersca@apple.com99226092010-05-18 19:25:01 +00001127 if (!m_preloads)
1128 return;
1129
cdumez@apple.coma2f2a5a2015-01-31 00:04:36 +00001130 for (auto* resource : *m_preloads) {
1131 resource->decreasePreloadCount();
1132 bool deleted = resource->deleteIfPossible();
1133 if (!deleted && resource->preloadResult() == CachedResource::PreloadNotReferenced)
cdumez@apple.com41d2d702015-02-02 20:50:16 +00001134 MemoryCache::singleton().remove(*resource);
antti@apple.com6c76e542008-03-13 21:20:31 +00001135 }
gyuyoung.kim@samsung.com56cf34c2014-11-17 06:46:24 +00001136 m_preloads = nullptr;
antti@apple.com6c76e542008-03-13 21:20:31 +00001137}
1138
abarth@webkit.org17d66c62010-09-08 10:26:02 +00001139void CachedResourceLoader::clearPendingPreloads()
treat@webkit.org915ef892009-02-26 20:09:50 +00001140{
1141 m_pendingPreloads.clear();
1142}
1143
antti@apple.com6c76e542008-03-13 21:20:31 +00001144#if PRELOAD_DEBUG
abarth@webkit.org17d66c62010-09-08 10:26:02 +00001145void CachedResourceLoader::printPreloadStats()
antti@apple.com6c76e542008-03-13 21:20:31 +00001146{
1147 unsigned scripts = 0;
1148 unsigned scriptMisses = 0;
1149 unsigned stylesheets = 0;
1150 unsigned stylesheetMisses = 0;
1151 unsigned images = 0;
1152 unsigned imageMisses = 0;
commit-queue@webkit.orgacddfad2015-09-30 05:53:51 +00001153 for (auto& resource : m_preloads) {
1154 if (resource->preloadResult() == CachedResource::PreloadNotReferenced)
1155 printf("!! UNREFERENCED PRELOAD %s\n", resource->url().latin1().data());
1156 else if (resource->preloadResult() == CachedResource::PreloadReferencedWhileComplete)
1157 printf("HIT COMPLETE PRELOAD %s\n", resource->url().latin1().data());
1158 else if (resource->preloadResult() == CachedResource::PreloadReferencedWhileLoading)
1159 printf("HIT LOADING PRELOAD %s\n", resource->url().latin1().data());
antti@apple.com6c76e542008-03-13 21:20:31 +00001160
commit-queue@webkit.orgacddfad2015-09-30 05:53:51 +00001161 if (resource->type() == CachedResource::Script) {
antti@apple.com6c76e542008-03-13 21:20:31 +00001162 scripts++;
commit-queue@webkit.orgacddfad2015-09-30 05:53:51 +00001163 if (resource->preloadResult() < CachedResource::PreloadReferencedWhileLoading)
antti@apple.com6c76e542008-03-13 21:20:31 +00001164 scriptMisses++;
commit-queue@webkit.orgacddfad2015-09-30 05:53:51 +00001165 } else if (resource->type() == CachedResource::CSSStyleSheet) {
antti@apple.com6c76e542008-03-13 21:20:31 +00001166 stylesheets++;
commit-queue@webkit.orgacddfad2015-09-30 05:53:51 +00001167 if (resource->preloadResult() < CachedResource::PreloadReferencedWhileLoading)
antti@apple.com6c76e542008-03-13 21:20:31 +00001168 stylesheetMisses++;
1169 } else {
1170 images++;
commit-queue@webkit.orgacddfad2015-09-30 05:53:51 +00001171 if (resource->preloadResult() < CachedResource::PreloadReferencedWhileLoading)
antti@apple.com6c76e542008-03-13 21:20:31 +00001172 imageMisses++;
1173 }
1174
jer.noble@apple.com2ed319d2016-01-28 19:52:57 +00001175 if (resource->errorOccurred() && resource->preloadResult() == CachedResource::PreloadNotReferenced)
commit-queue@webkit.orgacddfad2015-09-30 05:53:51 +00001176 MemoryCache::singleton().remove(resource);
antti@apple.com6c76e542008-03-13 21:20:31 +00001177
commit-queue@webkit.orgacddfad2015-09-30 05:53:51 +00001178 resource->decreasePreloadCount();
antti@apple.com6c76e542008-03-13 21:20:31 +00001179 }
gyuyoung.kim@samsung.com56cf34c2014-11-17 06:46:24 +00001180 m_preloads = nullptr;
antti@apple.com6c76e542008-03-13 21:20:31 +00001181
1182 if (scripts)
1183 printf("SCRIPTS: %d (%d hits, hit rate %d%%)\n", scripts, scripts - scriptMisses, (scripts - scriptMisses) * 100 / scripts);
1184 if (stylesheets)
1185 printf("STYLESHEETS: %d (%d hits, hit rate %d%%)\n", stylesheets, stylesheets - stylesheetMisses, (stylesheets - stylesheetMisses) * 100 / stylesheets);
1186 if (images)
1187 printf("IMAGES: %d (%d hits, hit rate %d%%)\n", images, images - imageMisses, (images - imageMisses) * 100 / images);
1188}
1189#endif
loislo@chromium.org7b6f5d92012-08-06 09:12:01 +00001190
commit-queue@webkit.org5e7ea1b2012-10-22 23:35:28 +00001191const ResourceLoaderOptions& CachedResourceLoader::defaultCachedResourceOptions()
1192{
commit-queue@webkit.org16c43b42016-07-04 18:36:30 +00001193 static ResourceLoaderOptions options(SendCallbacks, SniffContent, BufferData, AllowStoredCredentials, AskClientForAllCredentials, ClientRequestedCredentials, DoSecurityCheck, FetchOptions::Mode::NoCors, DoNotIncludeCertificateInfo, ContentSecurityPolicyImposition::DoPolicyCheck, DefersLoadingPolicy::AllowDefersLoading, CachingPolicy::AllowCaching);
commit-queue@webkit.org5e7ea1b2012-10-22 23:35:28 +00001194 return options;
1195}
1196
darin644b75e2006-02-21 06:59:15 +00001197}