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

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

Powered by Google App Engine
This is Rietveld 408576698