1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/webdata/common/web_data_request_manager.h"
#include <utility>
#include "base/functional/bind.h"
#include "base/location.h"
#include "base/memory/ptr_util.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/thread_pool.h"
////////////////////////////////////////////////////////////////////////////////
//
// WebDataRequest implementation.
//
////////////////////////////////////////////////////////////////////////////////
WebDataRequest::~WebDataRequest() {
WebDataRequestManager* manager = GetManager();
if (manager) {
manager->CancelRequest(handle_);
}
}
WebDataServiceBase::Handle WebDataRequest::GetHandle() const {
return handle_;
}
bool WebDataRequest::IsActive() {
return GetManager() != nullptr;
}
WebDataRequest::WebDataRequest(WebDataRequestManager* manager,
WebDataServiceRequestCallback consumer,
WebDataServiceBase::Handle handle)
: task_runner_(base::SequencedTaskRunner::HasCurrentDefault()
? base::SequencedTaskRunner::GetCurrentDefault()
: nullptr),
atomic_manager_(manager),
consumer_(std::move(consumer)),
handle_(handle) {
DCHECK(IsActive());
static_assert(sizeof(atomic_manager_) == sizeof(manager), "size mismatch");
}
WebDataRequestManager* WebDataRequest::GetManager() {
return atomic_manager_.load(std::memory_order_acquire);
}
WebDataServiceRequestCallback WebDataRequest::ExtractConsumer() && {
return std::move(consumer_);
}
scoped_refptr<base::SequencedTaskRunner> WebDataRequest::GetTaskRunner() {
return task_runner_;
}
void WebDataRequest::MarkAsInactive() {
atomic_manager_.store(nullptr, std::memory_order_release);
}
////////////////////////////////////////////////////////////////////////////////
//
// WebDataRequestManager implementation.
//
////////////////////////////////////////////////////////////////////////////////
WebDataRequestManager::WebDataRequestManager() : next_request_handle_(1) {}
std::unique_ptr<WebDataRequest> WebDataRequestManager::NewRequest(
WebDataServiceRequestCallback consumer) {
base::AutoLock l(pending_lock_);
std::unique_ptr<WebDataRequest> request = base::WrapUnique(
new WebDataRequest(this, std::move(consumer), next_request_handle_));
bool inserted =
pending_requests_.emplace(next_request_handle_, request.get()).second;
DCHECK(inserted);
++next_request_handle_;
return request;
}
void WebDataRequestManager::CancelRequest(WebDataServiceBase::Handle h) {
base::AutoLock l(pending_lock_);
// If the request was already cancelled, or has already completed, it won't
// be in the pending_requests_ collection any more.
auto i = pending_requests_.find(h);
if (i == pending_requests_.end()) {
return;
}
i->second->MarkAsInactive();
pending_requests_.erase(i);
}
void WebDataRequestManager::RequestCompleted(
std::unique_ptr<WebDataRequest> request,
std::unique_ptr<WDTypedResult> result) {
// Careful: Don't swap this below the BindOnce() call below, since that
// effectively does a std::move() on |request|!
scoped_refptr<base::SequencedTaskRunner> task_runner =
request->GetTaskRunner();
auto task = base::BindOnce(&WebDataRequestManager::RequestCompletedOnThread,
this, std::move(request), std::move(result));
if (task_runner) {
task_runner->PostTask(FROM_HERE, std::move(task));
} else {
base::ThreadPool::PostTask(FROM_HERE, std::move(task));
}
}
WebDataRequestManager::~WebDataRequestManager() {
base::AutoLock l(pending_lock_);
for (auto& pending_request : pending_requests_) {
pending_request.second->MarkAsInactive();
}
pending_requests_.clear();
}
void WebDataRequestManager::RequestCompletedOnThread(
std::unique_ptr<WebDataRequest> request,
std::unique_ptr<WDTypedResult> result) {
// Check whether the request is active. It might have been cancelled in
// another thread before this completion handler was invoked. This means the
// request initiator is no longer interested in the result.
if (!request->IsActive()) {
return;
}
WebDataServiceBase::Handle handle = request->GetHandle();
WebDataServiceRequestCallback consumer =
std::move(*request).ExtractConsumer();
// Stop tracking the request. The request is already finished, so "stop
// tracking" is the same as post-facto cancellation.
CancelRequest(handle);
// Notify the consumer if needed.
if (!consumer.is_null()) {
std::move(consumer).Run(handle, std::move(result));
}
}
|