Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(230)

Side by Side Diff: chrome/browser/chromeos/file_system_provider/service.cc

Issue 210803003: [fsp] Decouple file_service_provider::Service. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed comments. Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chromeos/file_system_provider/service.h" 5 #include "chrome/browser/chromeos/file_system_provider/service.h"
6 6
7 #include "base/files/file_path.h" 7 #include "base/files/file_path.h"
8 #include "base/strings/string_number_conversions.h" 8 #include "base/stl_util.h"
9 #include "base/values.h" 9 #include "chrome/browser/chromeos/file_system_provider/mount_path_util.h"
10 #include "chrome/browser/chromeos/file_system_provider/observer.h" 10 #include "chrome/browser/chromeos/file_system_provider/observer.h"
11 #include "chrome/browser/chromeos/file_system_provider/provided_file_system.h" 11 #include "chrome/browser/chromeos/file_system_provider/provided_file_system.h"
12 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_info .h"
13 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_inte rface.h"
12 #include "chrome/browser/chromeos/file_system_provider/service_factory.h" 14 #include "chrome/browser/chromeos/file_system_provider/service_factory.h"
13 #include "chrome/browser/chromeos/login/user.h"
14 #include "chrome/browser/chromeos/login/user_manager.h"
15 #include "chrome/common/extensions/api/file_system_provider.h"
16 #include "content/public/browser/browser_thread.h" 15 #include "content/public/browser/browser_thread.h"
17 #include "extensions/browser/event_router.h" 16 #include "extensions/browser/event_router.h"
hashimoto 2014/04/15 13:42:00 nit: No need to include this as we are just passin
mtomasz 2014/04/16 01:04:04 Done.
18 #include "extensions/browser/extension_system.h" 17 #include "extensions/browser/extension_system.h"
19 #include "webkit/browser/fileapi/external_mount_points.h" 18 #include "webkit/browser/fileapi/external_mount_points.h"
20 19
21 namespace chromeos { 20 namespace chromeos {
22 namespace file_system_provider { 21 namespace file_system_provider {
23 namespace { 22 namespace {
24 23
25 // Root mount path for all of the provided file systems.
26 const base::FilePath::CharType kProvidedMountPointRoot[] =
27 FILE_PATH_LITERAL("/provided");
28
29 // Maximum number of file systems to be mounted in the same time, per profile. 24 // Maximum number of file systems to be mounted in the same time, per profile.
30 const size_t kMaxFileSystems = 16; 25 const size_t kMaxFileSystems = 16;
31 26
32 // Constructs a safe mount point path for the provided file system represented 27 // Default factory for provided file systems. The |event_router| nor the
33 // by |file_system_handle|. The handle is a numeric part of the file system id. 28 // |request_manager| arguments must not be NULL.
34 base::FilePath GetMountPointPath(Profile* profile, 29 ProvidedFileSystemInterface* CreateProvidedFileSystem(
35 std::string extension_id, 30 extensions::EventRouter* event_router,
36 int file_system_id) { 31 RequestManager* request_manager,
37 chromeos::User* const user = 32 const ProvidedFileSystemInfo& file_system_info) {
38 chromeos::UserManager::IsInitialized() 33 DCHECK(event_router);
39 ? chromeos::UserManager::Get()->GetUserByProfile( 34 DCHECK(request_manager);
40 profile->GetOriginalProfile()) 35 return new ProvidedFileSystem(
41 : NULL; 36 event_router, request_manager, file_system_info);
42 const std::string user_suffix = user ? "-" + user->username_hash() : "";
43 return base::FilePath(kProvidedMountPointRoot).AppendASCII(
44 extension_id + "-" + base::IntToString(file_system_id) + user_suffix);
45 }
46
47 // Creates values to be passed to request events. These values can be extended
48 // by additional fields.
49 scoped_ptr<base::ListValue> CreateRequestValues(int file_system_id,
50 int request_id) {
51 scoped_ptr<base::ListValue> values(new base::ListValue());
52 values->AppendInteger(file_system_id);
53 values->AppendInteger(request_id);
54 return values.Pass();
55 } 37 }
56 38
57 } // namespace 39 } // namespace
58 40
59 Service::Service(Profile* profile) 41 Service::Service(Profile* profile)
60 : profile_(profile), next_id_(1), weak_ptr_factory_(this) { 42 : profile_(profile),
43 file_system_factory_(base::Bind(CreateProvidedFileSystem)),
44 next_id_(1),
45 weak_ptr_factory_(this) {
61 AddObserver(&request_manager_); 46 AddObserver(&request_manager_);
62 } 47 }
63 48
64 Service::~Service() {} 49 Service::~Service() { STLDeleteValues(&file_system_map_); }
65 50
66 // static 51 // static
67 Service* Service::Get(content::BrowserContext* context) { 52 Service* Service::Get(content::BrowserContext* context) {
68 return ServiceFactory::Get(context); 53 return ServiceFactory::Get(context);
69 } 54 }
70 55
71 void Service::AddObserver(Observer* observer) { 56 void Service::AddObserver(Observer* observer) {
72 DCHECK(observer); 57 DCHECK(observer);
73 observers_.AddObserver(observer); 58 observers_.AddObserver(observer);
74 } 59 }
75 60
76 void Service::RemoveObserver(Observer* observer) { 61 void Service::RemoveObserver(Observer* observer) {
77 DCHECK(observer); 62 DCHECK(observer);
78 observers_.RemoveObserver(observer); 63 observers_.RemoveObserver(observer);
79 } 64 }
80 65
66 void Service::SetFileSystemFactoryForTests(
67 const FileSystemFactoryCallback& factory_callback) {
68 DCHECK(!factory_callback.is_null());
69 file_system_factory_ = factory_callback;
70 }
71
81 int Service::MountFileSystem(const std::string& extension_id, 72 int Service::MountFileSystem(const std::string& extension_id,
82 const std::string& file_system_name) { 73 const std::string& file_system_name) {
83 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 74 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
84 75
85 // Restrict number of file systems to prevent system abusing. 76 // Restrict number of file systems to prevent system abusing.
86 if (file_systems_.size() + 1 > kMaxFileSystems) { 77 if (file_system_map_.size() + 1 > kMaxFileSystems) {
87 FOR_EACH_OBSERVER( 78 FOR_EACH_OBSERVER(
88 Observer, 79 Observer,
89 observers_, 80 observers_,
90 OnProvidedFileSystemMount(ProvidedFileSystem(), 81 OnProvidedFileSystemMount(ProvidedFileSystemInfo(),
91 base::File::FILE_ERROR_TOO_MANY_OPENED)); 82 base::File::FILE_ERROR_TOO_MANY_OPENED));
92 return 0; 83 return 0;
93 } 84 }
94 85
95 // The file system id is unique per service, so per profile. 86 // The provided file system id is unique per service, so per profile.
96 int file_system_id = next_id_; 87 int file_system_id = next_id_;
97 88
98 fileapi::ExternalMountPoints* const mount_points = 89 fileapi::ExternalMountPoints* const mount_points =
99 fileapi::ExternalMountPoints::GetSystemInstance(); 90 fileapi::ExternalMountPoints::GetSystemInstance();
100 DCHECK(mount_points); 91 DCHECK(mount_points);
101 92
102 // The mount point path and name are unique per system, since they are system 93 // The mount point path and name are unique per system, since they are system
103 // wide. This is necessary for copying between profiles. 94 // wide. This is necessary for copying between profiles.
104 const base::FilePath& mount_point_path = 95 const base::FilePath& mount_point_path =
105 GetMountPointPath(profile_, extension_id, file_system_id); 96 util::GetMountPointPath(profile_, extension_id, file_system_id);
106 const std::string mount_point_name = 97 const std::string mount_point_name =
107 mount_point_path.BaseName().AsUTF8Unsafe(); 98 mount_point_path.BaseName().AsUTF8Unsafe();
108 99
109 if (!mount_points->RegisterFileSystem(mount_point_name, 100 if (!mount_points->RegisterFileSystem(mount_point_name,
110 fileapi::kFileSystemTypeProvided, 101 fileapi::kFileSystemTypeProvided,
111 fileapi::FileSystemMountOption(), 102 fileapi::FileSystemMountOption(),
112 mount_point_path)) { 103 mount_point_path)) {
113 FOR_EACH_OBSERVER( 104 FOR_EACH_OBSERVER(
114 Observer, 105 Observer,
115 observers_, 106 observers_,
116 OnProvidedFileSystemMount(ProvidedFileSystem(), 107 OnProvidedFileSystemMount(ProvidedFileSystemInfo(),
117 base::File::FILE_ERROR_INVALID_OPERATION)); 108 base::File::FILE_ERROR_INVALID_OPERATION));
118 return 0; 109 return 0;
119 } 110 }
120 111
121 // Store the file system descriptor. Use the mount point name as the file 112 // Store the file system descriptor. Use the mount point name as the file
122 // system provider file system id. 113 // system provider file system id.
123 // Examples: 114 // Examples:
124 // file_system_id = 41 115 // file_system_id = 41
125 // mount_point_name = file_system_id = b33f1337-41-5aa5 116 // mount_point_name = file_system_id = b33f1337-41-5aa5
126 // mount_point_path = /provided/b33f1337-41-5aa5 117 // mount_point_path = /provided/b33f1337-41-5aa5
127 ProvidedFileSystem file_system( 118 ProvidedFileSystemInfo file_system_info(
128 extension_id, file_system_id, file_system_name, mount_point_path); 119 extension_id, file_system_id, file_system_name, mount_point_path);
129 file_systems_[file_system_id] = file_system; 120
121 // The event router may be NULL for unit tests.
122 extensions::EventRouter* event_router =
123 extensions::ExtensionSystem::Get(profile_)->event_router();
124
125 ProvidedFileSystemInterface* file_system = file_system_factory_.Run(
126 event_router, &request_manager_, file_system_info);
127 DCHECK(file_system);
128 file_system_map_[file_system_id] = file_system;
130 129
131 FOR_EACH_OBSERVER( 130 FOR_EACH_OBSERVER(
132 Observer, 131 Observer,
133 observers_, 132 observers_,
134 OnProvidedFileSystemMount(file_system, base::File::FILE_OK)); 133 OnProvidedFileSystemMount(file_system_info, base::File::FILE_OK));
135 134
136 next_id_++; 135 next_id_++;
137 return file_system_id; 136 return file_system_id;
138 } 137 }
139 138
140 bool Service::UnmountFileSystem(const std::string& extension_id, 139 bool Service::UnmountFileSystem(const std::string& extension_id,
141 int file_system_id) { 140 int file_system_id) {
142 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 141 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
143 142
144 FileSystemMap::iterator file_system_it = file_systems_.find(file_system_id); 143 ProvidedFileSystemMap::iterator file_system_it =
145 if (file_system_it == file_systems_.end() || 144 file_system_map_.find(file_system_id);
146 file_system_it->second.extension_id() != extension_id) { 145 if (file_system_it == file_system_map_.end() ||
147 const ProvidedFileSystem empty_file_system; 146 file_system_it->second->GetFileSystemInfo().extension_id() !=
148 FOR_EACH_OBSERVER(Observer, 147 extension_id) {
149 observers_, 148 const ProvidedFileSystemInfo empty_file_system_info;
150 OnProvidedFileSystemUnmount( 149 FOR_EACH_OBSERVER(
151 empty_file_system, base::File::FILE_ERROR_NOT_FOUND)); 150 Observer,
151 observers_,
152 OnProvidedFileSystemUnmount(empty_file_system_info,
153 base::File::FILE_ERROR_NOT_FOUND));
152 return false; 154 return false;
153 } 155 }
154 156
155 fileapi::ExternalMountPoints* const mount_points = 157 fileapi::ExternalMountPoints* const mount_points =
156 fileapi::ExternalMountPoints::GetSystemInstance(); 158 fileapi::ExternalMountPoints::GetSystemInstance();
157 DCHECK(mount_points); 159 DCHECK(mount_points);
158 160
161 const ProvidedFileSystemInfo& file_system_info =
162 file_system_it->second->GetFileSystemInfo();
163
159 const std::string mount_point_name = 164 const std::string mount_point_name =
160 file_system_it->second.mount_path().BaseName().value(); 165 file_system_info.mount_path().BaseName().value();
161 if (!mount_points->RevokeFileSystem(mount_point_name)) { 166 if (!mount_points->RevokeFileSystem(mount_point_name)) {
162 FOR_EACH_OBSERVER( 167 FOR_EACH_OBSERVER(
163 Observer, 168 Observer,
164 observers_, 169 observers_,
165 OnProvidedFileSystemUnmount(file_system_it->second, 170 OnProvidedFileSystemUnmount(file_system_info,
166 base::File::FILE_ERROR_INVALID_OPERATION)); 171 base::File::FILE_ERROR_INVALID_OPERATION));
167 return false; 172 return false;
168 } 173 }
169 174
170 FOR_EACH_OBSERVER( 175 FOR_EACH_OBSERVER(
171 Observer, 176 Observer,
172 observers_, 177 observers_,
173 OnProvidedFileSystemUnmount(file_system_it->second, base::File::FILE_OK)); 178 OnProvidedFileSystemUnmount(file_system_info, base::File::FILE_OK));
174 179
175 file_systems_.erase(file_system_it); 180 delete file_system_it->second;
181 file_system_map_.erase(file_system_it);
176 return true; 182 return true;
177 } 183 }
178 184
179 std::vector<ProvidedFileSystem> Service::GetMountedFileSystems() {
180 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
181
182 std::vector<ProvidedFileSystem> result;
183 for (FileSystemMap::const_iterator it = file_systems_.begin();
184 it != file_systems_.end();
185 ++it) {
186 result.push_back(it->second);
187 }
188 return result;
189 }
190
191 bool Service::FulfillRequest(const std::string& extension_id,
192 int file_system_id,
193 int request_id,
194 scoped_ptr<base::DictionaryValue> result,
195 bool has_next) {
196 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
197
198 FileSystemMap::iterator file_system_it = file_systems_.find(file_system_id);
199 if (file_system_it == file_systems_.end() ||
200 file_system_it->second.extension_id() != extension_id) {
201 return false;
202 }
203
204 return request_manager_.FulfillRequest(
205 file_system_it->second, request_id, result.Pass(), has_next);
206 }
207
208 bool Service::RejectRequest(const std::string& extension_id,
209 int file_system_id,
210 int request_id,
211 base::File::Error error) {
212 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
213
214 FileSystemMap::iterator file_system_it = file_systems_.find(file_system_id);
215 if (file_system_it == file_systems_.end() ||
216 file_system_it->second.extension_id() != extension_id) {
217 return false;
218 }
219
220 return request_manager_.RejectRequest(
221 file_system_it->second, request_id, error);
222 }
223
224 bool Service::RequestUnmount(int file_system_id) { 185 bool Service::RequestUnmount(int file_system_id) {
225 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 186 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
226 187
227 FileSystemMap::iterator file_system_it = file_systems_.find(file_system_id); 188 ProvidedFileSystemMap::iterator file_system_it =
228 if (file_system_it == file_systems_.end()) 189 file_system_map_.find(file_system_id);
190 if (file_system_it == file_system_map_.end())
229 return false; 191 return false;
230 192
231 int request_id = 193 return file_system_it->second->RequestUnmount(
232 request_manager_.CreateRequest(file_system_it->second, 194 base::Bind(&Service::OnRequestUnmountStatus,
233 SuccessCallback(), 195 weak_ptr_factory_.GetWeakPtr(),
234 base::Bind(&Service::OnRequestUnmountError, 196 file_system_it->second->GetFileSystemInfo()));
235 weak_ptr_factory_.GetWeakPtr(), 197 }
236 file_system_it->second));
237 198
238 if (!request_id) 199 std::vector<ProvidedFileSystemInfo> Service::GetProvidedFileSystemInfoList() {
239 return false; 200 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
240 201
241 scoped_ptr<base::ListValue> values( 202 std::vector<ProvidedFileSystemInfo> result;
242 CreateRequestValues(file_system_id, request_id)); 203 for (ProvidedFileSystemMap::const_iterator it = file_system_map_.begin();
204 it != file_system_map_.end();
205 ++it) {
206 result.push_back(it->second->GetFileSystemInfo());
207 }
208 return result;
209 }
243 210
244 extensions::EventRouter* event_router = 211 ProvidedFileSystemInterface* Service::GetProvidedFileSystem(
245 extensions::ExtensionSystem::Get(profile_)->event_router(); 212 const std::string& extension_id,
246 DCHECK(event_router); 213 int file_system_id) {
214 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
247 215
248 event_router->DispatchEventToExtension( 216 ProvidedFileSystemMap::iterator file_system_it =
249 file_system_it->second.extension_id(), 217 file_system_map_.find(file_system_id);
250 make_scoped_ptr(new extensions::Event( 218 if (file_system_it == file_system_map_.end() ||
251 extensions::api::file_system_provider::OnUnmountRequested::kEventName, 219 file_system_it->second->GetFileSystemInfo().extension_id() !=
252 values.Pass()))); 220 extension_id) {
221 return NULL;
222 }
253 223
254 return true; 224 return file_system_it->second;
255 } 225 }
256 226
257 void Service::Shutdown() { RemoveObserver(&request_manager_); } 227 void Service::Shutdown() { RemoveObserver(&request_manager_); }
258 228
259 void Service::OnRequestUnmountError(const ProvidedFileSystem& file_system, 229 void Service::OnRequestUnmountStatus(
260 base::File::Error error) { 230 const ProvidedFileSystemInfo& file_system_info,
261 FOR_EACH_OBSERVER( 231 base::File::Error error) {
262 Observer, observers_, OnProvidedFileSystemUnmount(file_system, error)); 232 // Notify observers about failure in unmounting, since mount() will not be
233 // called by the provided file system. In case of success mount() will be
234 // invoked, and observers notified, so there is no need to call them now.
235 if (error != base::File::FILE_OK) {
236 FOR_EACH_OBSERVER(Observer,
237 observers_,
238 OnProvidedFileSystemUnmount(file_system_info, error));
239 }
263 } 240 }
264 241
265 } // namespace file_system_provider 242 } // namespace file_system_provider
266 } // namespace chromeos 243 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698