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.
5 #include "chrome/browser/chromeos/file_system_provider/request_manager.h"
7 #include "base/files/file.h"
8 #include "base/stl_util.h"
9 #include "base/trace_event/trace_event.h"
12 namespace file_system_provider
{
15 // Timeout in seconds, before a request is considered as stale and hence
17 const int kDefaultTimeout
= 10;
21 std::string
RequestTypeToString(RequestType type
) {
24 return "REQUEST_UNMOUNT";
26 return "GET_METADATA";
28 return "READ_DIRECTORY";
35 case CREATE_DIRECTORY
:
36 return "CREATE_DIRECTORY";
38 return "DELETE_ENTRY";
54 return "REMOVE_WATCHER";
62 RequestManager::RequestManager(
63 NotificationManagerInterface
* notification_manager
)
64 : notification_manager_(notification_manager
),
66 timeout_(base::TimeDelta::FromSeconds(kDefaultTimeout
)),
67 weak_ptr_factory_(this) {
70 RequestManager::~RequestManager() {
71 // Abort all of the active requests.
72 RequestMap::iterator it
= requests_
.begin();
73 while (it
!= requests_
.end()) {
74 const int request_id
= it
->first
;
76 RejectRequest(request_id
,
77 scoped_ptr
<RequestValue
>(new RequestValue()),
78 base::File::FILE_ERROR_ABORT
);
81 DCHECK_EQ(0u, requests_
.size());
82 STLDeleteValues(&requests_
);
85 int RequestManager::CreateRequest(RequestType type
,
86 scoped_ptr
<HandlerInterface
> handler
) {
87 // The request id is unique per request manager, so per service, thereof
89 int request_id
= next_id_
++;
91 // If cycled the int, then signal an error.
92 if (requests_
.find(request_id
) != requests_
.end())
95 TRACE_EVENT_ASYNC_BEGIN1("file_system_provider",
96 "RequestManager::Request",
101 Request
* request
= new Request
;
102 request
->handler
= handler
.Pass();
103 requests_
[request_id
] = request
;
104 ResetTimer(request_id
);
106 FOR_EACH_OBSERVER(Observer
, observers_
, OnRequestCreated(request_id
, type
));
108 // Execute the request implementation. In case of an execution failure,
109 // unregister and return 0. This may often happen, eg. if the providing
110 // extension is not listening for the request event being sent.
111 // In such case, we should abort as soon as possible.
112 if (!request
->handler
->Execute(request_id
)) {
113 DestroyRequest(request_id
);
117 FOR_EACH_OBSERVER(Observer
, observers_
, OnRequestExecuted(request_id
));
122 base::File::Error
RequestManager::FulfillRequest(
124 scoped_ptr
<RequestValue
> response
,
126 CHECK(response
.get());
127 RequestMap::iterator request_it
= requests_
.find(request_id
);
128 if (request_it
== requests_
.end())
129 return base::File::FILE_ERROR_NOT_FOUND
;
131 FOR_EACH_OBSERVER(Observer
,
133 OnRequestFulfilled(request_id
, *response
.get(), has_more
));
135 request_it
->second
->handler
->OnSuccess(request_id
, response
.Pass(), has_more
);
138 DestroyRequest(request_id
);
140 if (notification_manager_
)
141 notification_manager_
->HideUnresponsiveNotification(request_id
);
142 ResetTimer(request_id
);
145 return base::File::FILE_OK
;
148 base::File::Error
RequestManager::RejectRequest(
150 scoped_ptr
<RequestValue
> response
,
151 base::File::Error error
) {
152 CHECK(response
.get());
153 RequestMap::iterator request_it
= requests_
.find(request_id
);
154 if (request_it
== requests_
.end())
155 return base::File::FILE_ERROR_NOT_FOUND
;
157 FOR_EACH_OBSERVER(Observer
,
159 OnRequestRejected(request_id
, *response
.get(), error
));
160 request_it
->second
->handler
->OnError(request_id
, response
.Pass(), error
);
161 DestroyRequest(request_id
);
163 return base::File::FILE_OK
;
166 void RequestManager::SetTimeoutForTesting(const base::TimeDelta
& timeout
) {
170 std::vector
<int> RequestManager::GetActiveRequestIds() const {
171 std::vector
<int> result
;
173 for (RequestMap::const_iterator request_it
= requests_
.begin();
174 request_it
!= requests_
.end();
176 result
.push_back(request_it
->first
);
182 void RequestManager::AddObserver(Observer
* observer
) {
184 observers_
.AddObserver(observer
);
187 void RequestManager::RemoveObserver(Observer
* observer
) {
189 observers_
.RemoveObserver(observer
);
192 RequestManager::Request::Request() {}
194 RequestManager::Request::~Request() {}
196 void RequestManager::OnRequestTimeout(int request_id
) {
197 FOR_EACH_OBSERVER(Observer
, observers_
, OnRequestTimeouted(request_id
));
199 if (!notification_manager_
) {
200 RejectRequest(request_id
,
201 scoped_ptr
<RequestValue
>(new RequestValue()),
202 base::File::FILE_ERROR_ABORT
);
206 notification_manager_
->ShowUnresponsiveNotification(
208 base::Bind(&RequestManager::OnUnresponsiveNotificationResult
,
209 weak_ptr_factory_
.GetWeakPtr(),
213 void RequestManager::OnUnresponsiveNotificationResult(
215 NotificationManagerInterface::NotificationResult result
) {
216 RequestMap::iterator request_it
= requests_
.find(request_id
);
217 if (request_it
== requests_
.end())
220 if (result
== NotificationManagerInterface::CONTINUE
) {
221 ResetTimer(request_id
);
225 RejectRequest(request_id
,
226 scoped_ptr
<RequestValue
>(new RequestValue()),
227 base::File::FILE_ERROR_ABORT
);
230 void RequestManager::ResetTimer(int request_id
) {
231 RequestMap::iterator request_it
= requests_
.find(request_id
);
232 if (request_it
== requests_
.end())
235 request_it
->second
->timeout_timer
.Start(
238 base::Bind(&RequestManager::OnRequestTimeout
,
239 weak_ptr_factory_
.GetWeakPtr(),
243 void RequestManager::DestroyRequest(int request_id
) {
244 RequestMap::iterator request_it
= requests_
.find(request_id
);
245 if (request_it
== requests_
.end())
248 delete request_it
->second
;
249 requests_
.erase(request_it
);
251 if (notification_manager_
)
252 notification_manager_
->HideUnresponsiveNotification(request_id
);
254 FOR_EACH_OBSERVER(Observer
, observers_
, OnRequestDestroyed(request_id
));
256 TRACE_EVENT_ASYNC_END0(
257 "file_system_provider", "RequestManager::Request", request_id
);
260 } // namespace file_system_provider
261 } // namespace chromeos