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 { 12namespace { 13 14// Timeout in seconds, before a request is considered as stale and hence 15// aborted. 16const int kDefaultTimeout = 10; 17 18} // namespace 19 20std::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 41RequestManager::RequestManager() 42 : next_id_(1), 43 timeout_(base::TimeDelta::FromSeconds(kDefaultTimeout)), 44 weak_ptr_factory_(this) {} 45 46RequestManager::~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 59int 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 94bool 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 114bool 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 128void RequestManager::SetTimeoutForTesting(const base::TimeDelta& timeout) { 129 timeout_ = timeout; 130} 131 132size_t RequestManager::GetActiveRequestsForLogging() const { 133 return requests_.size(); 134} 135 136void RequestManager::AddObserver(Observer* observer) { 137 DCHECK(observer); 138 observers_.AddObserver(observer); 139} 140 141void RequestManager::RemoveObserver(Observer* observer) { 142 DCHECK(observer); 143 observers_.RemoveObserver(observer); 144} 145 146RequestManager::Request::Request() {} 147 148RequestManager::Request::~Request() {} 149 150void 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 156void 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