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 3735d52de6010ae759a7491a0f6b734cb58ab5ce..30b68ed4d447b2d8fee73ce1116c815046d56e81 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/FetchParameters.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 task_handle_; |
+ HashSet<Persistent<Resource>> resources_with_pending_clients_; |
+}; |
+ |
+StaticResourceCallback::StaticResourceCallback() {} |
+StaticResourceCallback::~StaticResourceCallback() {} |
+ |
+void StaticResourceCallback::Schedule(Resource* resource) { |
+ if (!task_handle_.IsActive()) { |
+ // WTF::unretained(this) is safe because a posted task is canceled when |
+ // |task_handle_| is destroyed on the dtor of this ResourceCallback. |
+ task_handle_ = |
+ Platform::Current() |
+ ->CurrentThread() |
+ ->Scheduler() |
+ ->LoadingTaskRunner() |
+ ->PostCancellableTask(BLINK_FROM_HERE, |
+ WTF::Bind(&StaticResourceCallback::RunTask, |
+ WTF::Unretained(this))); |
+ } |
+ resources_with_pending_clients_.insert(resource); |
+} |
+ |
+void StaticResourceCallback::Cancel(Resource* resource) { |
+ resources_with_pending_clients_.erase(resource); |
+ if (task_handle_.IsActive() && resources_with_pending_clients_.IsEmpty()) |
+ task_handle_.Cancel(); |
+} |
+ |
+bool StaticResourceCallback::IsScheduled(Resource* resource) const { |
+ return resources_with_pending_clients_.Contains(resource); |
+} |
+ |
+void StaticResourceCallback::RunTask() { |
+ HeapVector<Member<Resource>> resources; |
+ for (const Member<Resource>& resource : resources_with_pending_clients_) |
+ resources.push_back(resource); |
+ resources_with_pending_clients_.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. |
@@ -246,70 +305,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 task_handle_; |
- HashSet<Persistent<Resource>> resources_with_pending_clients_; |
-}; |
- |
-Resource::ResourceCallback& Resource::ResourceCallback::CallbackHandler() { |
- DEFINE_STATIC_LOCAL(ResourceCallback, callback_handler, ()); |
- return callback_handler; |
-} |
- |
-Resource::ResourceCallback::ResourceCallback() {} |
- |
-void Resource::ResourceCallback::Schedule(Resource* resource) { |
- if (!task_handle_.IsActive()) { |
- // WTF::unretained(this) is safe because a posted task is canceled when |
- // |m_taskHandle| is destroyed on the dtor of this ResourceCallback. |
- task_handle_ = |
- Platform::Current() |
- ->CurrentThread() |
- ->Scheduler() |
- ->LoadingTaskRunner() |
- ->PostCancellableTask( |
- BLINK_FROM_HERE, |
- WTF::Bind(&ResourceCallback::RunTask, WTF::Unretained(this))); |
- } |
- resources_with_pending_clients_.insert(resource); |
-} |
- |
-void Resource::ResourceCallback::Cancel(Resource* resource) { |
- resources_with_pending_clients_.erase(resource); |
- if (task_handle_.IsActive() && resources_with_pending_clients_.IsEmpty()) |
- task_handle_.Cancel(); |
-} |
- |
-bool Resource::ResourceCallback::IsScheduled(Resource* resource) const { |
- return resources_with_pending_clients_.Contains(resource); |
-} |
- |
-void Resource::ResourceCallback::RunTask() { |
- HeapVector<Member<Resource>> resources; |
- for (const Member<Resource>& resource : resources_with_pending_clients_) |
- resources.push_back(resource.Get()); |
- resources_with_pending_clients_.clear(); |
- |
- for (const auto& resource : resources) |
- resource->FinishPendingClients(); |
-} |
- |
Resource::Resource(const ResourceRequest& request, |
Type type, |
- const ResourceLoaderOptions& options) |
+ const ResourceLoaderOptions& options, |
+ FetchContext* fetch_context) |
: load_finish_time_(0), |
identifier_(0), |
encoded_size_(0), |
@@ -330,16 +329,20 @@ Resource::Resource(const ResourceRequest& request, |
integrity_disposition_(ResourceIntegrityDisposition::kNotChecked), |
options_(options), |
response_timestamp_(CurrentTime()), |
- cancel_timer_(Platform::Current()->MainThread()->GetWebTaskRunner(), |
+ cancel_timer_(fetch_context && fetch_context->TimerTaskRunner() |
+ ? fetch_context->TimerTaskRunner() |
+ : Platform::Current()->MainThread()->GetWebTaskRunner(), |
this, |
&Resource::CancelTimerFired), |
+ fetch_context_(fetch_context), |
resource_request_(request) { |
InstanceCounters::IncrementCounter(InstanceCounters::kResourceCounter); |
// Currently we support the metadata caching only for HTTP family. |
if (GetResourceRequest().Url().ProtocolIsInHTTPFamily()) |
cache_handler_ = CachedMetadataHandlerImpl::Create(this); |
- MemoryCoordinator::Instance().RegisterClient(this); |
+ if (IsMainThread()) |
+ MemoryCoordinator::Instance().RegisterClient(this); |
} |
Resource::~Resource() { |
@@ -348,6 +351,7 @@ Resource::~Resource() { |
DEFINE_TRACE(Resource) { |
visitor->Trace(loader_); |
+ visitor->Trace(fetch_context_); |
visitor->Trace(cache_handler_); |
visitor->Trace(clients_); |
visitor->Trace(clients_awaiting_callback_); |
@@ -418,7 +422,7 @@ void Resource::GetError(const ResourceError& error) { |
error_ = error; |
is_revalidating_ = false; |
- if (error_.IsCancellation() || !IsPreloaded()) |
+ if ((error_.IsCancellation() || !IsPreloaded()) && IsMainThread()) |
GetMemoryCache()->Remove(this); |
if (!ErrorOccurred()) |
@@ -647,7 +651,7 @@ String Resource::ReasonNotDeletable() const { |
builder.AppendNumber(preload_count_); |
builder.Append(')'); |
} |
- if (GetMemoryCache()->Contains(this)) { |
+ if (IsMainThread() && GetMemoryCache()->Contains(this)) { |
if (!builder.IsEmpty()) |
builder.Append(' '); |
builder.Append("in_memory_cache"); |
@@ -722,7 +726,7 @@ void Resource::AddClient(ResourceClient* client, |
!TypeNeedsSynchronousCacheHit(GetType()) && |
!needs_synchronous_cache_hit_) { |
clients_awaiting_callback_.insert(client); |
- ResourceCallback::CallbackHandler().Schedule(this); |
+ GetResourceCallback().Schedule(this); |
return; |
} |
@@ -745,7 +749,7 @@ void Resource::RemoveClient(ResourceClient* client) { |
clients_.erase(client); |
if (clients_awaiting_callback_.IsEmpty()) |
- ResourceCallback::CallbackHandler().Cancel(this); |
+ GetResourceCallback().Cancel(this); |
DidRemoveClientOrObserver(); |
} |
@@ -762,7 +766,8 @@ 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()) |
GetMemoryCache()->Remove(this); |
} |
} |
@@ -785,7 +790,8 @@ void Resource::SetDecodedSize(size_t decoded_size) { |
return; |
size_t old_size = size(); |
decoded_size_ = decoded_size; |
- GetMemoryCache()->Update(this, old_size, size()); |
+ if (IsMainThread()) |
+ GetMemoryCache()->Update(this, old_size, size()); |
} |
void Resource::SetEncodedSize(size_t encoded_size) { |
@@ -795,7 +801,8 @@ void Resource::SetEncodedSize(size_t encoded_size) { |
size_t old_size = size(); |
encoded_size_ = encoded_size; |
encoded_size_memory_usage_ = encoded_size; |
- GetMemoryCache()->Update(this, old_size, size()); |
+ if (IsMainThread()) |
+ GetMemoryCache()->Update(this, old_size, size()); |
} |
void Resource::FinishPendingClients() { |
@@ -827,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 = GetResourceCallback().IsScheduled(this); |
if (scheduled && clients_awaiting_callback_.IsEmpty()) |
- ResourceCallback::CallbackHandler().Cancel(this); |
+ GetResourceCallback().Cancel(this); |
// Prevent the case when there are clients waiting but no callback scheduled. |
DCHECK(clients_awaiting_callback_.IsEmpty() || scheduled); |
@@ -1126,4 +1133,14 @@ bool Resource::IsLoadEventBlockingResourceType() const { |
return false; |
} |
+Resource::ResourceCallback& Resource::GetResourceCallback() { |
+ if (fetch_context_ && fetch_context_->GetResourceCallback()) { |
+ DCHECK(!IsMainThread()); |
+ return *fetch_context_->GetResourceCallback(); |
+ } |
+ DCHECK(IsMainThread()); |
+ DEFINE_STATIC_LOCAL(StaticResourceCallback, callback_handler, ()); |
+ return callback_handler; |
+} |
+ |
} // namespace blink |