request_manager.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
1// Copyright 2014 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 "chrome/browser/chromeos/file_system_provider/request_manager.h"
6
7#include "base/files/file.h"
8#include "base/stl_util.h"
9
10namespace chromeos {
11namespace file_system_provider {
12
13namespace {
14
15// Timeout in seconds, before a request is considered as stale and hence
16// aborted.
17const int kDefaultTimeout = 10;
18
19}  // namespace
20
21RequestManager::RequestManager()
22    : next_id_(1),
23      timeout_(base::TimeDelta::FromSeconds(kDefaultTimeout)),
24      weak_ptr_factory_(this) {}
25
26RequestManager::~RequestManager() {
27  // Abort all of the active requests.
28  RequestMap::iterator it = requests_.begin();
29  while (it != requests_.end()) {
30    const int request_id = it->first;
31    ++it;
32    RejectRequest(request_id, base::File::FILE_ERROR_ABORT);
33  }
34
35  DCHECK_EQ(0u, requests_.size());
36  STLDeleteValues(&requests_);
37}
38
39int RequestManager::CreateRequest(RequestType type,
40                                  scoped_ptr<HandlerInterface> handler) {
41  // The request id is unique per request manager, so per service, thereof
42  // per profile.
43  int request_id = next_id_++;
44
45  // If cycled the int, then signal an error.
46  if (requests_.find(request_id) != requests_.end())
47    return 0;
48
49  Request* request = new Request;
50  request->handler = handler.Pass();
51  request->timeout_timer.Start(FROM_HERE,
52                               timeout_,
53                               base::Bind(&RequestManager::OnRequestTimeout,
54                                          weak_ptr_factory_.GetWeakPtr(),
55                                          request_id));
56  requests_[request_id] = request;
57
58  FOR_EACH_OBSERVER(Observer, observers_, OnRequestCreated(request_id, type));
59
60  // Execute the request implementation. In case of an execution failure,
61  // unregister and return 0. This may often happen, eg. if the providing
62  // extension is not listening for the request event being sent.
63  // In such case, we should abort as soon as possible.
64  if (!request->handler->Execute(request_id)) {
65    DestroyRequest(request_id);
66    return 0;
67  }
68
69  FOR_EACH_OBSERVER(Observer, observers_, OnRequestExecuted(request_id));
70
71  return request_id;
72}
73
74bool RequestManager::FulfillRequest(int request_id,
75                                    scoped_ptr<RequestValue> response,
76                                    bool has_next) {
77  RequestMap::iterator request_it = requests_.find(request_id);
78  if (request_it == requests_.end())
79    return false;
80
81  request_it->second->handler->OnSuccess(request_id, response.Pass(), has_next);
82
83  FOR_EACH_OBSERVER(
84      Observer, observers_, OnRequestFulfilled(request_id, has_next));
85
86  if (!has_next)
87    DestroyRequest(request_id);
88  else
89    request_it->second->timeout_timer.Reset();
90
91  return true;
92}
93
94bool RequestManager::RejectRequest(int request_id, base::File::Error error) {
95  RequestMap::iterator request_it = requests_.find(request_id);
96  if (request_it == requests_.end())
97    return false;
98
99  request_it->second->handler->OnError(request_id, error);
100
101  FOR_EACH_OBSERVER(Observer, observers_, OnRequestRejected(request_id, error));
102
103  DestroyRequest(request_id);
104
105  return true;
106}
107
108void RequestManager::SetTimeoutForTests(const base::TimeDelta& timeout) {
109  timeout_ = timeout;
110}
111
112size_t RequestManager::GetActiveRequestsForLogging() const {
113  return requests_.size();
114}
115
116void RequestManager::AddObserver(Observer* observer) {
117  DCHECK(observer);
118  observers_.AddObserver(observer);
119}
120
121void RequestManager::RemoveObserver(Observer* observer) {
122  DCHECK(observer);
123  observers_.RemoveObserver(observer);
124}
125
126RequestManager::Request::Request() {}
127
128RequestManager::Request::~Request() {}
129
130void RequestManager::OnRequestTimeout(int request_id) {
131  FOR_EACH_OBSERVER(Observer, observers_, OnRequestTimeouted(request_id));
132
133  RejectRequest(request_id, base::File::FILE_ERROR_ABORT);
134}
135
136void RequestManager::DestroyRequest(int request_id) {
137  RequestMap::iterator request_it = requests_.find(request_id);
138  if (request_it == requests_.end())
139    return;
140
141  delete request_it->second;
142  requests_.erase(request_it);
143
144  FOR_EACH_OBSERVER(Observer, observers_, OnRequestDestroyed(request_id));
145}
146
147}  // namespace file_system_provider
148}  // namespace chromeos
149