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