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