15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/common/cancelable_request.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CancelableRequestProvider::CancelableRequestProvider() 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : next_handle_(1) { 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CancelableRequestProvider::Handle CancelableRequestProvider::AddRequest( 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelableRequestBase* request, 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelableRequestConsumerBase* consumer) { 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Handle handle; 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(pending_request_lock_); 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handle = next_handle_; 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_requests_[next_handle_] = request; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++next_handle_; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(next_handle_) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "next_handle_ may have wrapped around to invalid state."; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer->OnRequestAdded(this, handle); 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->Init(this, handle, consumer); 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return handle; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CancelableRequestProvider::CancelRequest(Handle handle) { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(pending_request_lock_); 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelRequestLocked(pending_requests_.find(handle)); 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CancelableRequestProvider::~CancelableRequestProvider() { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There may be requests whose result callback has not been run yet. We need 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to cancel them otherwise they may try and call us back after we've been 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // deleted, or do other bad things. This can occur on shutdown (or browser 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // context destruction) when a request is scheduled, completed (but not 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // dispatched), then the BrowserContext is deleted. 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(pending_request_lock_); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!pending_requests_.empty()) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelRequestLocked(pending_requests_.begin()); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CancelableRequestProvider::CancelRequestLocked( 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CancelableRequestMap::iterator& item) { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_request_lock_.AssertAcquired(); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (item == pending_requests_.end()) { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Trying to cancel an unknown request"; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item->second->consumer()->OnRequestRemoved(this, item->first); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item->second->set_canceled(); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_requests_.erase(item); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CancelableRequestProvider::RequestCompleted(Handle handle) { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelableRequestConsumerBase* consumer = NULL; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(pending_request_lock_); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelableRequestMap::iterator i = pending_requests_.find(handle); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i == pending_requests_.end()) { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Trying to cancel an unknown request"; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer = i->second->consumer(); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This message should only get sent if the class is not cancelled, or 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // else the consumer might be gone). 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!i->second->canceled()); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_requests_.erase(i); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Notify the consumer that the request is gone 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer->OnRequestRemoved(this, handle); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MSVC doesn't like complex extern templates and DLLs. 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(COMPILER_MSVC) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Emit our most common CancelableRequestConsumer. 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template class CancelableRequestConsumerTSimple<int>; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// And the most common subclass of it. 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template class CancelableRequestConsumerT<int, 0>; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CancelableRequestBase::CancelableRequestBase() 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : provider_(NULL), 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_(NULL), 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handle_(0) { 9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) callback_thread_ = base::MessageLoop::current(); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CancelableRequestBase::~CancelableRequestBase() { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CancelableRequestBase::Init(CancelableRequestProvider* provider, 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelableRequestProvider::Handle handle, 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelableRequestConsumerBase* consumer) { 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(handle_ == 0 && provider_ == NULL && consumer_ == NULL); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) provider_ = provider; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_ = consumer; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handle_ = handle; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CancelableRequestBase::DoForward(const base::Closure& forwarded_call, 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool force_async) { 11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (force_async || callback_thread_ != base::MessageLoop::current()) { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_thread_->PostTask( 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CancelableRequestBase::ExecuteCallback, this, 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) forwarded_call)); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can do synchronous callbacks when we're on the same thread. 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExecuteCallback(forwarded_call); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CancelableRequestBase::ExecuteCallback( 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Closure& forwarded_call) { 12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_EQ(callback_thread_, base::MessageLoop::current()); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!canceled_.IsSet()) { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WillExecute(); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Execute the callback. 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) forwarded_call.Run(); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Notify the provider that the request is complete. The provider will 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // notify the consumer for us. Note that it is possible for the callback to 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cancel this request; we must check canceled again. 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!canceled_.IsSet()) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyCompleted(); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 141