| Index: third_party/WebKit/Source/platform/loader/fetch/Resource.cpp
|
| diff --git a/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp b/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp
|
| index 34f21f4f07c7fc31db107c60389302a999569710..25b8de4b956b3ccf6896374304e2e59d53af7c8a 100644
|
| --- a/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp
|
| +++ b/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp
|
| @@ -36,6 +36,7 @@
|
| #include "platform/instrumentation/tracing/TraceEvent.h"
|
| #include "platform/loader/fetch/CachedMetadata.h"
|
| #include "platform/loader/fetch/CrossOriginAccessControl.h"
|
| +#include "platform/loader/fetch/FetchContext.h"
|
| #include "platform/loader/fetch/FetchInitiatorTypeNames.h"
|
| #include "platform/loader/fetch/FetchRequest.h"
|
| #include "platform/loader/fetch/IntegrityMetadata.h"
|
| @@ -58,6 +59,64 @@
|
|
|
| namespace blink {
|
|
|
| +namespace {
|
| +
|
| +class StaticResourceCallback final : public Resource::ResourceCallback {
|
| + public:
|
| + StaticResourceCallback();
|
| + ~StaticResourceCallback() override;
|
| + void schedule(Resource*) override;
|
| + void cancel(Resource*) override;
|
| + bool isScheduled(Resource*) const override;
|
| +
|
| + private:
|
| + void runTask();
|
| +
|
| + TaskHandle m_taskHandle;
|
| + HashSet<Persistent<Resource>> m_resourcesWithPendingClients;
|
| +};
|
| +
|
| +StaticResourceCallback::StaticResourceCallback() {}
|
| +StaticResourceCallback::~StaticResourceCallback() {}
|
| +
|
| +void StaticResourceCallback::schedule(Resource* resource) {
|
| + if (!m_taskHandle.isActive()) {
|
| + // WTF::unretained(this) is safe because a posted task is canceled when
|
| + // |m_taskHandle| is destroyed on the dtor of this ResourceCallback.
|
| + m_taskHandle =
|
| + Platform::current()
|
| + ->currentThread()
|
| + ->scheduler()
|
| + ->loadingTaskRunner()
|
| + ->postCancellableTask(BLINK_FROM_HERE,
|
| + WTF::bind(&StaticResourceCallback::runTask,
|
| + WTF::unretained(this)));
|
| + }
|
| + m_resourcesWithPendingClients.insert(resource);
|
| +}
|
| +
|
| +void StaticResourceCallback::cancel(Resource* resource) {
|
| + m_resourcesWithPendingClients.erase(resource);
|
| + if (m_taskHandle.isActive() && m_resourcesWithPendingClients.isEmpty())
|
| + m_taskHandle.cancel();
|
| +}
|
| +
|
| +bool StaticResourceCallback::isScheduled(Resource* resource) const {
|
| + return m_resourcesWithPendingClients.contains(resource);
|
| +}
|
| +
|
| +void StaticResourceCallback::runTask() {
|
| + HeapVector<Member<Resource>> resources;
|
| + for (const Member<Resource>& resource : m_resourcesWithPendingClients)
|
| + resources.push_back(resource.get());
|
| + m_resourcesWithPendingClients.clear();
|
| +
|
| + for (const auto& resource : resources)
|
| + resource->finishPendingClients();
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| // These response headers are not copied from a revalidated response to the
|
| // cached response headers. For compatibility, this list is based on Chromium's
|
| // net/http/http_response_headers.cc.
|
| @@ -241,70 +300,10 @@ void Resource::ServiceWorkerResponseCachedMetadataHandler::sendToPlatform() {
|
| }
|
| }
|
|
|
| -// This class cannot be on-heap because the first callbackHandler() call
|
| -// instantiates the singleton object while we can call it in the
|
| -// pre-finalization step.
|
| -class Resource::ResourceCallback final {
|
| - public:
|
| - static ResourceCallback& callbackHandler();
|
| - void schedule(Resource*);
|
| - void cancel(Resource*);
|
| - bool isScheduled(Resource*) const;
|
| -
|
| - private:
|
| - ResourceCallback();
|
| -
|
| - void runTask();
|
| - TaskHandle m_taskHandle;
|
| - HashSet<Persistent<Resource>> m_resourcesWithPendingClients;
|
| -};
|
| -
|
| -Resource::ResourceCallback& Resource::ResourceCallback::callbackHandler() {
|
| - DEFINE_STATIC_LOCAL(ResourceCallback, callbackHandler, ());
|
| - return callbackHandler;
|
| -}
|
| -
|
| -Resource::ResourceCallback::ResourceCallback() {}
|
| -
|
| -void Resource::ResourceCallback::schedule(Resource* resource) {
|
| - if (!m_taskHandle.isActive()) {
|
| - // WTF::unretained(this) is safe because a posted task is canceled when
|
| - // |m_taskHandle| is destroyed on the dtor of this ResourceCallback.
|
| - m_taskHandle =
|
| - Platform::current()
|
| - ->currentThread()
|
| - ->scheduler()
|
| - ->loadingTaskRunner()
|
| - ->postCancellableTask(
|
| - BLINK_FROM_HERE,
|
| - WTF::bind(&ResourceCallback::runTask, WTF::unretained(this)));
|
| - }
|
| - m_resourcesWithPendingClients.insert(resource);
|
| -}
|
| -
|
| -void Resource::ResourceCallback::cancel(Resource* resource) {
|
| - m_resourcesWithPendingClients.erase(resource);
|
| - if (m_taskHandle.isActive() && m_resourcesWithPendingClients.isEmpty())
|
| - m_taskHandle.cancel();
|
| -}
|
| -
|
| -bool Resource::ResourceCallback::isScheduled(Resource* resource) const {
|
| - return m_resourcesWithPendingClients.contains(resource);
|
| -}
|
| -
|
| -void Resource::ResourceCallback::runTask() {
|
| - HeapVector<Member<Resource>> resources;
|
| - for (const Member<Resource>& resource : m_resourcesWithPendingClients)
|
| - resources.push_back(resource.get());
|
| - m_resourcesWithPendingClients.clear();
|
| -
|
| - for (const auto& resource : resources)
|
| - resource->finishPendingClients();
|
| -}
|
| -
|
| Resource::Resource(const ResourceRequest& request,
|
| Type type,
|
| - const ResourceLoaderOptions& options)
|
| + const ResourceLoaderOptions& options,
|
| + FetchContext* fetchContext)
|
| : m_loadFinishTime(0),
|
| m_identifier(0),
|
| m_encodedSize(0),
|
| @@ -325,16 +324,20 @@ Resource::Resource(const ResourceRequest& request,
|
| m_integrityDisposition(ResourceIntegrityDisposition::NotChecked),
|
| m_options(options),
|
| m_responseTimestamp(currentTime()),
|
| - m_cancelTimer(Platform::current()->mainThread()->getWebTaskRunner(),
|
| + m_cancelTimer(fetchContext && fetchContext->timerTaskRunner()
|
| + ? fetchContext->timerTaskRunner()
|
| + : Platform::current()->mainThread()->getWebTaskRunner(),
|
| this,
|
| &Resource::cancelTimerFired),
|
| + m_fetchContext(fetchContext),
|
| m_resourceRequest(request) {
|
| InstanceCounters::incrementCounter(InstanceCounters::ResourceCounter);
|
|
|
| // Currently we support the metadata caching only for HTTP family.
|
| if (resourceRequest().url().protocolIsInHTTPFamily())
|
| m_cacheHandler = CachedMetadataHandlerImpl::create(this);
|
| - MemoryCoordinator::instance().registerClient(this);
|
| + if (isMainThread())
|
| + MemoryCoordinator::instance().registerClient(this);
|
| }
|
|
|
| Resource::~Resource() {
|
| @@ -343,6 +346,7 @@ Resource::~Resource() {
|
|
|
| DEFINE_TRACE(Resource) {
|
| visitor->trace(m_loader);
|
| + visitor->trace(m_fetchContext);
|
| visitor->trace(m_cacheHandler);
|
| visitor->trace(m_clients);
|
| visitor->trace(m_clientsAwaitingCallback);
|
| @@ -412,7 +416,7 @@ void Resource::error(const ResourceError& error) {
|
| m_error = error;
|
| m_isRevalidating = false;
|
|
|
| - if (m_error.isCancellation() || !isPreloaded())
|
| + if ((m_error.isCancellation() || !isPreloaded()) && isMainThread())
|
| memoryCache()->remove(this);
|
|
|
| if (!errorOccurred())
|
| @@ -648,7 +652,7 @@ String Resource::reasonNotDeletable() const {
|
| builder.appendNumber(m_preloadCount);
|
| builder.append(')');
|
| }
|
| - if (memoryCache()->contains(this)) {
|
| + if (isMainThread() && memoryCache()->contains(this)) {
|
| if (!builder.isEmpty())
|
| builder.append(' ');
|
| builder.append("in_memory_cache");
|
| @@ -722,7 +726,7 @@ void Resource::addClient(ResourceClient* client,
|
| if ((errorOccurred() || !response().isNull()) &&
|
| !typeNeedsSynchronousCacheHit(getType()) && !m_needsSynchronousCacheHit) {
|
| m_clientsAwaitingCallback.insert(client);
|
| - ResourceCallback::callbackHandler().schedule(this);
|
| + resourceCallback().schedule(this);
|
| return;
|
| }
|
|
|
| @@ -745,7 +749,7 @@ void Resource::removeClient(ResourceClient* client) {
|
| m_clients.erase(client);
|
|
|
| if (m_clientsAwaitingCallback.isEmpty())
|
| - ResourceCallback::callbackHandler().cancel(this);
|
| + resourceCallback().cancel(this);
|
|
|
| didRemoveClientOrObserver();
|
| }
|
| @@ -762,8 +766,10 @@ void Resource::didRemoveClientOrObserver() {
|
| // operation."
|
| // We allow non-secure content to be reused in history, but we do not allow
|
| // secure content to be reused.
|
| - if (hasCacheControlNoStoreHeader() && url().protocolIs("https"))
|
| + if (hasCacheControlNoStoreHeader() && url().protocolIs("https") &&
|
| + isMainThread()) {
|
| memoryCache()->remove(this);
|
| + }
|
| }
|
| }
|
|
|
| @@ -785,7 +791,8 @@ void Resource::setDecodedSize(size_t decodedSize) {
|
| return;
|
| size_t oldSize = size();
|
| m_decodedSize = decodedSize;
|
| - memoryCache()->update(this, oldSize, size());
|
| + if (isMainThread())
|
| + memoryCache()->update(this, oldSize, size());
|
| }
|
|
|
| void Resource::setEncodedSize(size_t encodedSize) {
|
| @@ -794,7 +801,8 @@ void Resource::setEncodedSize(size_t encodedSize) {
|
| size_t oldSize = size();
|
| m_encodedSize = encodedSize;
|
| m_encodedSizeMemoryUsage = encodedSize;
|
| - memoryCache()->update(this, oldSize, size());
|
| + if (isMainThread())
|
| + memoryCache()->update(this, oldSize, size());
|
| }
|
|
|
| void Resource::finishPendingClients() {
|
| @@ -826,9 +834,9 @@ void Resource::finishPendingClients() {
|
|
|
| // It is still possible for the above loop to finish a new client
|
| // synchronously. If there's no client waiting we should deschedule.
|
| - bool scheduled = ResourceCallback::callbackHandler().isScheduled(this);
|
| + bool scheduled = resourceCallback().isScheduled(this);
|
| if (scheduled && m_clientsAwaitingCallback.isEmpty())
|
| - ResourceCallback::callbackHandler().cancel(this);
|
| + resourceCallback().cancel(this);
|
|
|
| // Prevent the case when there are clients waiting but no callback scheduled.
|
| DCHECK(m_clientsAwaitingCallback.isEmpty() || scheduled);
|
| @@ -1125,4 +1133,14 @@ bool Resource::isLoadEventBlockingResourceType() const {
|
| return false;
|
| }
|
|
|
| +Resource::ResourceCallback& Resource::resourceCallback() {
|
| + if (m_fetchContext && m_fetchContext->resourceCallback()) {
|
| + DCHECK(!isMainThread());
|
| + return *m_fetchContext->resourceCallback();
|
| + }
|
| + DCHECK(isMainThread());
|
| + DEFINE_STATIC_LOCAL(StaticResourceCallback, callbackHandler, ());
|
| + return callbackHandler;
|
| +}
|
| +
|
| } // namespace blink
|
|
|