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