1// Copyright 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "components/webdata/common/web_data_request_manager.h"
6
7#include "base/bind.h"
8#include "base/message_loop/message_loop.h"
9#include "base/stl_util.h"
10
11////////////////////////////////////////////////////////////////////////////////
12//
13// WebDataRequest implementation.
14//
15////////////////////////////////////////////////////////////////////////////////
16
17WebDataRequest::WebDataRequest(WebDataServiceConsumer* consumer,
18                               WebDataRequestManager* manager)
19    : manager_(manager), cancelled_(false), consumer_(consumer) {
20  handle_ = manager_->GetNextRequestHandle();
21  message_loop_ = base::MessageLoop::current();
22  manager_->RegisterRequest(this);
23}
24
25WebDataRequest::~WebDataRequest() {
26  if (manager_) {
27    manager_->CancelRequest(handle_);
28  }
29  if (result_.get()) {
30    result_->Destroy();
31  }
32}
33
34WebDataServiceBase::Handle WebDataRequest::GetHandle() const {
35  return handle_;
36}
37
38WebDataServiceConsumer* WebDataRequest::GetConsumer() const {
39  return consumer_;
40}
41
42base::MessageLoop* WebDataRequest::GetMessageLoop() const {
43  return message_loop_;
44}
45
46bool WebDataRequest::IsCancelled() const {
47  base::AutoLock l(cancel_lock_);
48  return cancelled_;
49}
50
51void WebDataRequest::Cancel() {
52  base::AutoLock l(cancel_lock_);
53  cancelled_ = true;
54  consumer_ = NULL;
55  manager_ = NULL;
56}
57
58void WebDataRequest::OnComplete() {
59  manager_= NULL;
60}
61
62void WebDataRequest::SetResult(scoped_ptr<WDTypedResult> r) {
63  result_ = r.Pass();
64}
65
66scoped_ptr<WDTypedResult> WebDataRequest::GetResult(){
67  return result_.Pass();
68}
69
70////////////////////////////////////////////////////////////////////////////////
71//
72// WebDataRequestManager implementation.
73//
74////////////////////////////////////////////////////////////////////////////////
75
76WebDataRequestManager::WebDataRequestManager()
77    : next_request_handle_(1) {
78}
79
80WebDataRequestManager::~WebDataRequestManager() {
81  base::AutoLock l(pending_lock_);
82  for (RequestMap::iterator i = pending_requests_.begin();
83       i != pending_requests_.end(); ++i) {
84    i->second->Cancel();
85  }
86  pending_requests_.clear();
87}
88
89void WebDataRequestManager::RegisterRequest(WebDataRequest* request) {
90  base::AutoLock l(pending_lock_);
91  pending_requests_[request->GetHandle()] = request;
92}
93
94int WebDataRequestManager::GetNextRequestHandle() {
95  base::AutoLock l(pending_lock_);
96  return ++next_request_handle_;
97}
98
99void WebDataRequestManager::CancelRequest(WebDataServiceBase::Handle h) {
100  base::AutoLock l(pending_lock_);
101  RequestMap::iterator i = pending_requests_.find(h);
102  if (i == pending_requests_.end()) {
103    NOTREACHED() << "Canceling a nonexistent web data service request";
104    return;
105  }
106  i->second->Cancel();
107  pending_requests_.erase(i);
108}
109
110void WebDataRequestManager::RequestCompleted(
111    scoped_ptr<WebDataRequest> request) {
112  base::MessageLoop* loop = request->GetMessageLoop();
113  loop->PostTask(FROM_HERE,
114                 base::Bind(&WebDataRequestManager::RequestCompletedOnThread,
115                            this,
116                            base::Passed(&request)));
117}
118
119void WebDataRequestManager::RequestCompletedOnThread(
120    scoped_ptr<WebDataRequest> request) {
121  if (request->IsCancelled())
122    return;
123  {
124    base::AutoLock l(pending_lock_);
125    RequestMap::iterator i = pending_requests_.find(request->GetHandle());
126    if (i == pending_requests_.end()) {
127      NOTREACHED() << "Request completed called for an unknown request";
128      return;
129    }
130
131    // Take ownership of the request object and remove it from the map.
132    pending_requests_.erase(i);
133  }
134
135  // Notify the consumer if needed.
136  if (!request->IsCancelled()) {
137    WebDataServiceConsumer* consumer = request->GetConsumer();
138    request->OnComplete();
139    if (consumer) {
140      scoped_ptr<WDTypedResult> r = request->GetResult();
141      consumer->OnWebDataServiceRequestDone(request->GetHandle(), r.get());
142    }
143  }
144
145}
146