// 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.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 r) { result_ = r.Pass(); } scoped_ptr 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 request) { base::MessageLoop* loop = request->GetMessageLoop(); loop->PostTask(FROM_HERE, base::Bind(&WebDataRequestManager::RequestCompletedOnThread, this, base::Passed(&request))); } void WebDataRequestManager::RequestCompletedOnThread( scoped_ptr 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 r = request->GetResult(); consumer->OnWebDataServiceRequestDone(request->GetHandle(), r.get()); } } }