blob: 9aba721da25d8aa7e12f2490febc398d1cfff434 [file] [log] [blame]
// Copyright 2012 The Chromium Authors. All rights reserved.
// 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 "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/stl_util.h"
////////////////////////////////////////////////////////////////////////////////
//
// WebDataRequest implementation.
//
////////////////////////////////////////////////////////////////////////////////
WebDataRequest::WebDataRequest(WebDataServiceConsumer* consumer,
WebDataRequestManager* manager)
: manager_(manager), cancelled_(false), consumer_(consumer) {
handle_ = manager_->GetNextRequestHandle();
message_loop_ = base::MessageLoop::current();
manager_->RegisterRequest(this);
}
WebDataRequest::~WebDataRequest() {
if (manager_) {
manager_->CancelRequest(handle_);
}
if (result_.get()) {
result_->Destroy();
}
}
WebDataServiceBase::Handle WebDataRequest::GetHandle() const {
return handle_;
}
WebDataServiceConsumer* WebDataRequest::GetConsumer() const {
return consumer_;
}
base::MessageLoop* WebDataRequest::GetMessageLoop() const {
return message_loop_;
}
bool WebDataRequest::IsCancelled() const {
base::AutoLock l(cancel_lock_);
return cancelled_;
}
void WebDataRequest::Cancel() {
base::AutoLock l(cancel_lock_);
cancelled_ = true;
consumer_ = NULL;
manager_ = NULL;
}
void WebDataRequest::OnComplete() {
manager_= NULL;
}
void WebDataRequest::SetResult(scoped_ptr<WDTypedResult> r) {
result_ = r.Pass();
}
scoped_ptr<WDTypedResult> WebDataRequest::GetResult(){
return result_.Pass();
}
////////////////////////////////////////////////////////////////////////////////
//
// WebDataRequestManager implementation.
//
////////////////////////////////////////////////////////////////////////////////
WebDataRequestManager::WebDataRequestManager()
: next_request_handle_(1) {
}
WebDataRequestManager::~WebDataRequestManager() {
base::AutoLock l(pending_lock_);
for (RequestMap::iterator i = pending_requests_.begin();
i != pending_requests_.end(); ++i) {
i->second->Cancel();
}
pending_requests_.clear();
}
void WebDataRequestManager::RegisterRequest(WebDataRequest* request) {
base::AutoLock l(pending_lock_);
pending_requests_[request->GetHandle()] = request;
}
int WebDataRequestManager::GetNextRequestHandle() {
base::AutoLock l(pending_lock_);
return ++next_request_handle_;
}
void WebDataRequestManager::CancelRequest(WebDataServiceBase::Handle h) {
base::AutoLock l(pending_lock_);
RequestMap::iterator i = pending_requests_.find(h);
if (i == pending_requests_.end()) {
NOTREACHED() << "Canceling a nonexistent web data service request";
return;
}
i->second->Cancel();
pending_requests_.erase(i);
}
void WebDataRequestManager::RequestCompleted(
scoped_ptr<WebDataRequest> request) {
base::MessageLoop* loop = request->GetMessageLoop();
loop->PostTask(FROM_HERE,
base::Bind(&WebDataRequestManager::RequestCompletedOnThread,
this,
base::Passed(&request)));
}
void WebDataRequestManager::RequestCompletedOnThread(
scoped_ptr<WebDataRequest> request) {
if (request->IsCancelled())
return;
{
base::AutoLock l(pending_lock_);
RequestMap::iterator i = pending_requests_.find(request->GetHandle());
if (i == pending_requests_.end()) {
NOTREACHED() << "Request completed called for an unknown request";
return;
}
// Take ownership of the request object and remove it from the map.
pending_requests_.erase(i);
}
// Notify the consumer if needed.
if (!request->IsCancelled()) {
WebDataServiceConsumer* consumer = request->GetConsumer();
request->OnComplete();
if (consumer) {
scoped_ptr<WDTypedResult> r = request->GetResult();
consumer->OnWebDataServiceRequestDone(request->GetHandle(), r.get());
}
}
}