diff options
Diffstat (limited to 'Source/WebCore/loader/cache/CachedScript.cpp')
-rw-r--r-- | Source/WebCore/loader/cache/CachedScript.cpp | 83 |
1 files changed, 60 insertions, 23 deletions
diff --git a/Source/WebCore/loader/cache/CachedScript.cpp b/Source/WebCore/loader/cache/CachedScript.cpp index 48facd7bc..84de38ebe 100644 --- a/Source/WebCore/loader/cache/CachedScript.cpp +++ b/Source/WebCore/loader/cache/CachedScript.cpp @@ -29,24 +29,20 @@ #include "CachedResourceClient.h" #include "CachedResourceClientWalker.h" +#include "CachedResourceRequest.h" +#include "HTTPHeaderNames.h" #include "HTTPParsers.h" #include "MIMETypeRegistry.h" -#include "MemoryCache.h" -#include "ResourceBuffer.h" #include "RuntimeApplicationChecks.h" +#include "SharedBuffer.h" #include "TextResourceDecoder.h" -#include <wtf/Vector.h> namespace WebCore { -CachedScript::CachedScript(const ResourceRequest& resourceRequest, const String& charset) - : CachedResource(resourceRequest, Script) - , m_decoder(TextResourceDecoder::create(ASCIILiteral("application/javascript"), charset)) +CachedScript::CachedScript(CachedResourceRequest&& request, SessionID sessionID) + : CachedResource(WTFMove(request), Script, sessionID) + , m_decoder(TextResourceDecoder::create(ASCIILiteral("application/javascript"), request.charset())) { - // It's javascript we want. - // But some websites think their scripts are <some wrong mimetype here> - // and refuse to serve them if we only accept application/x-javascript. - setAccept("*/*"); } CachedScript::~CachedScript() @@ -65,27 +61,55 @@ String CachedScript::encoding() const String CachedScript::mimeType() const { - return extractMIMETypeFromMediaType(m_response.httpHeaderField("Content-Type")).lower(); + return extractMIMETypeFromMediaType(m_response.httpHeaderField(HTTPHeaderName::ContentType)).convertToASCIILowercase(); } -const String& CachedScript::script() +StringView CachedScript::script() { - ASSERT(!isPurgeable()); + if (!m_data) + return { }; - if (!m_script && m_data) { - m_script = m_decoder->decode(m_data->data(), encodedSize()); - m_script.append(m_decoder->flush()); + if (m_decodingState == NeverDecoded + && TextEncoding(encoding()).isByteBasedEncoding() + && m_data->size() + && charactersAreAllASCII(reinterpret_cast<const LChar*>(m_data->data()), m_data->size())) { + + m_decodingState = DataAndDecodedStringHaveSameBytes; + + // If the encoded and decoded data are the same, there is no decoded data cost! + setDecodedSize(0); + m_decodedDataDeletionTimer.stop(); + + m_scriptHash = StringHasher::computeHashAndMaskTop8Bits(reinterpret_cast<const LChar*>(m_data->data()), m_data->size()); + } + + if (m_decodingState == DataAndDecodedStringHaveSameBytes) + return { reinterpret_cast<const LChar*>(m_data->data()), m_data->size() }; + + if (!m_script) { + m_script = m_decoder->decodeAndFlush(m_data->data(), encodedSize()); + ASSERT(!m_scriptHash || m_scriptHash == m_script.impl()->hash()); + if (m_decodingState == NeverDecoded) + m_scriptHash = m_script.impl()->hash(); + m_decodingState = DataAndDecodedStringHaveDifferentBytes; setDecodedSize(m_script.sizeInBytes()); } + m_decodedDataDeletionTimer.restart(); - return m_script; } -void CachedScript::finishLoading(ResourceBuffer* data) +unsigned CachedScript::scriptHash() +{ + if (m_decodingState == NeverDecoded) + script(); + return m_scriptHash; +} + +void CachedScript::finishLoading(SharedBuffer* data) { m_data = data; - setEncodedSize(m_data.get() ? m_data->size() : 0); + setEncodedSize(data ? data->size() : 0); CachedResource::finishLoading(data); } @@ -93,27 +117,40 @@ void CachedScript::destroyDecodedData() { m_script = String(); setDecodedSize(0); - if (!MemoryCache::shouldMakeResourcePurgeableOnEviction() && isSafeToMakePurgeable()) - makePurgeable(true); +} + +void CachedScript::setBodyDataFrom(const CachedResource& resource) +{ + ASSERT(resource.type() == type()); + auto& script = static_cast<const CachedScript&>(resource); + + CachedResource::setBodyDataFrom(resource); + + m_script = script.m_script; + m_scriptHash = script.m_scriptHash; + m_decodingState = script.m_decodingState; + m_decoder = script.m_decoder; } #if ENABLE(NOSNIFF) bool CachedScript::mimeTypeAllowedByNosniff() const { - return !parseContentTypeOptionsHeader(m_response.httpHeaderField("X-Content-Type-Options")) == ContentTypeOptionsNosniff || MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimeType()); + return parseContentTypeOptionsHeader(m_response.httpHeaderField(HTTPHeaderName::XContentTypeOptions)) != ContentTypeOptionsNosniff || MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimeType()); } #endif bool CachedScript::shouldIgnoreHTTPStatusCodeErrors() const { +#if PLATFORM(MAC) // This is a workaround for <rdar://problem/13916291> // REGRESSION (r119759): Adobe Flash Player "smaller" installer relies on the incorrect firing // of a load event and needs an app-specific hack for compatibility. // The installer in question tries to load .js file that doesn't exist, causing the server to // return a 404 response. Normally, this would trigger an error event to be dispatched, but the // installer expects a load event instead so we work around it here. - if (applicationIsSolidStateNetworksDownloader()) + if (MacApplication::isSolidStateNetworksDownloader()) return true; +#endif return CachedResource::shouldIgnoreHTTPStatusCodeErrors(); } |