| 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 e4c7bae40279fecae462c4084b01b553bc9696e9..c6ad0e4fcade4db2ee9ef4a16afc378058fff346 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())
|
| @@ -655,7 +659,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");
|
| @@ -730,7 +734,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;
|
| }
|
|
|
| @@ -753,7 +757,7 @@ void Resource::RemoveClient(ResourceClient* client) {
|
| clients_.erase(client);
|
|
|
| if (clients_awaiting_callback_.IsEmpty())
|
| - ResourceCallback::CallbackHandler().Cancel(this);
|
| + GetResourceCallback().Cancel(this);
|
|
|
| DidRemoveClientOrObserver();
|
| }
|
| @@ -770,7 +774,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);
|
| }
|
| }
|
| @@ -793,7 +798,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) {
|
| @@ -803,7 +809,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() {
|
| @@ -835,9 +842,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);
|
| @@ -1134,4 +1141,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
|
|
|