Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(39)

Unified Diff: third_party/WebKit/Source/platform/loader/fetch/Resource.cpp

Issue 2701753003: [WIP] off-main-thread loading
Patch Set: small fix Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698