| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/file_system/file_system_dispatcher_host.h" | 5 #include "chrome/browser/file_system/file_system_dispatcher_host.h" |
| 6 | 6 |
| 7 #include "base/file_path.h" | 7 #include "base/file_path.h" |
| 8 #include "base/thread.h" | 8 #include "base/thread.h" |
| 9 #include "base/time.h" | 9 #include "base/time.h" |
| 10 #include "chrome/browser/browser_process.h" | 10 #include "chrome/browser/browser_process.h" |
| 11 #include "chrome/browser/browser_thread.h" | 11 #include "chrome/browser/browser_thread.h" |
| 12 #include "chrome/browser/file_system/browser_file_system_callback_dispatcher.h" | 12 #include "chrome/browser/file_system/browser_file_system_callback_dispatcher.h" |
| 13 #include "chrome/browser/file_system/browser_file_system_context.h" | 13 #include "chrome/browser/file_system/browser_file_system_context.h" |
| 14 #include "chrome/browser/host_content_settings_map.h" | 14 #include "chrome/browser/host_content_settings_map.h" |
| 15 #include "chrome/browser/net/chrome_url_request_context.h" | 15 #include "chrome/browser/net/chrome_url_request_context.h" |
| 16 #include "chrome/browser/profile.h" | 16 #include "chrome/browser/profile.h" |
| 17 #include "chrome/browser/renderer_host/browser_render_process_host.h" | 17 #include "chrome/browser/renderer_host/browser_render_process_host.h" |
| 18 #include "chrome/common/net/url_request_context_getter.h" | 18 #include "chrome/common/net/url_request_context_getter.h" |
| 19 #include "chrome/common/render_messages.h" | 19 #include "chrome/common/render_messages.h" |
| 20 #include "chrome/common/render_messages_params.h" | 20 #include "chrome/common/render_messages_params.h" |
| 21 #include "googleurl/src/gurl.h" | 21 #include "googleurl/src/gurl.h" |
| 22 #include "net/url_request/url_request_context.h" | 22 #include "net/url_request/url_request_context.h" |
| 23 #include "webkit/fileapi/file_system_operation.h" |
| 23 #include "webkit/fileapi/file_system_path_manager.h" | 24 #include "webkit/fileapi/file_system_path_manager.h" |
| 24 #include "webkit/fileapi/file_system_quota_manager.h" | 25 #include "webkit/fileapi/file_system_quota_manager.h" |
| 26 #include "webkit/fileapi/sandboxed_file_system_operation.h" |
| 25 | 27 |
| 26 using fileapi::FileSystemQuotaManager; | 28 using fileapi::FileSystemQuotaManager; |
| 27 | 29 using fileapi::SandboxedFileSystemOperation; |
| 28 class FileSystemDispatcherHost::OpenFileSystemTask { | |
| 29 public: | |
| 30 static void Start( | |
| 31 int request_id, | |
| 32 const GURL& origin_url, | |
| 33 fileapi::FileSystemType type, | |
| 34 bool create, | |
| 35 FileSystemDispatcherHost* dispatcher_host) { | |
| 36 // The task is self-destructed. | |
| 37 new OpenFileSystemTask( | |
| 38 request_id, origin_url, type, create, dispatcher_host); | |
| 39 } | |
| 40 | |
| 41 private: | |
| 42 void DidGetRootPath(bool success, const FilePath& root_path, | |
| 43 const std::string& name) { | |
| 44 if (success) | |
| 45 dispatcher_host_->Send( | |
| 46 new ViewMsg_OpenFileSystemRequest_Complete( | |
| 47 request_id_, true, name, root_path)); | |
| 48 else | |
| 49 dispatcher_host_->Send( | |
| 50 new ViewMsg_OpenFileSystemRequest_Complete( | |
| 51 request_id_, false, std::string(), FilePath())); | |
| 52 delete this; | |
| 53 } | |
| 54 | |
| 55 OpenFileSystemTask( | |
| 56 int request_id, | |
| 57 const GURL& origin_url, | |
| 58 fileapi::FileSystemType type, | |
| 59 bool create, | |
| 60 FileSystemDispatcherHost* dispatcher_host) | |
| 61 : request_id_(request_id), | |
| 62 dispatcher_host_(dispatcher_host), | |
| 63 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | |
| 64 dispatcher_host->context_->path_manager()->GetFileSystemRootPath( | |
| 65 origin_url, type, create, | |
| 66 callback_factory_.NewCallback(&OpenFileSystemTask::DidGetRootPath)); | |
| 67 } | |
| 68 | |
| 69 int request_id_; | |
| 70 std::string name_; | |
| 71 FilePath root_path_; | |
| 72 scoped_refptr<FileSystemDispatcherHost> dispatcher_host_; | |
| 73 base::ScopedCallbackFactory<OpenFileSystemTask> callback_factory_; | |
| 74 }; | |
| 75 | 30 |
| 76 FileSystemDispatcherHost::FileSystemDispatcherHost( | 31 FileSystemDispatcherHost::FileSystemDispatcherHost( |
| 77 IPC::Message::Sender* sender, Profile* profile) | 32 IPC::Message::Sender* sender, Profile* profile) |
| 78 : message_sender_(sender), | 33 : message_sender_(sender), |
| 79 process_handle_(0), | 34 process_handle_(0), |
| 80 shutdown_(false), | 35 shutdown_(false), |
| 81 context_(profile->GetFileSystemContext()), | 36 context_(profile->GetFileSystemContext()), |
| 82 host_content_settings_map_(profile->GetHostContentSettingsMap()), | 37 host_content_settings_map_(profile->GetHostContentSettingsMap()), |
| 83 request_context_getter_(profile->GetRequestContext()) { | 38 request_context_getter_(profile->GetRequestContext()) { |
| 84 DCHECK(message_sender_); | 39 DCHECK(message_sender_); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 149 (content_setting == CONTENT_SETTING_BLOCK) || | 104 (content_setting == CONTENT_SETTING_BLOCK) || |
| 150 (content_setting == CONTENT_SETTING_SESSION_ONLY)); | 105 (content_setting == CONTENT_SETTING_SESSION_ONLY)); |
| 151 if (content_setting == CONTENT_SETTING_BLOCK) { | 106 if (content_setting == CONTENT_SETTING_BLOCK) { |
| 152 // TODO(kinuko): Need to notify the UI thread to indicate that | 107 // TODO(kinuko): Need to notify the UI thread to indicate that |
| 153 // there's a blocked content. | 108 // there's a blocked content. |
| 154 Send(new ViewMsg_OpenFileSystemRequest_Complete( | 109 Send(new ViewMsg_OpenFileSystemRequest_Complete( |
| 155 request_id, false, std::string(), FilePath())); | 110 request_id, false, std::string(), FilePath())); |
| 156 return; | 111 return; |
| 157 } | 112 } |
| 158 | 113 |
| 159 OpenFileSystemTask::Start(request_id, origin_url, type, create, this); | 114 GetNewOperation(request_id)->OpenFileSystem(origin_url, type, create); |
| 160 } | 115 } |
| 161 | 116 |
| 162 void FileSystemDispatcherHost::OnMove( | 117 void FileSystemDispatcherHost::OnMove( |
| 163 int request_id, const FilePath& src_path, const FilePath& dest_path) { | 118 int request_id, const FilePath& src_path, const FilePath& dest_path) { |
| 164 if (!VerifyFileSystemPathForRead(src_path, request_id) || | |
| 165 !VerifyFileSystemPathForWrite(dest_path, request_id, true /* create */, | |
| 166 FileSystemQuotaManager::kUnknownSize)) | |
| 167 return; | |
| 168 | |
| 169 GetNewOperation(request_id)->Move(src_path, dest_path); | 119 GetNewOperation(request_id)->Move(src_path, dest_path); |
| 170 } | 120 } |
| 171 | 121 |
| 172 void FileSystemDispatcherHost::OnCopy( | 122 void FileSystemDispatcherHost::OnCopy( |
| 173 int request_id, const FilePath& src_path, const FilePath& dest_path) { | 123 int request_id, const FilePath& src_path, const FilePath& dest_path) { |
| 174 if (!VerifyFileSystemPathForRead(src_path, request_id) || | |
| 175 !VerifyFileSystemPathForWrite(dest_path, request_id, true /* create */, | |
| 176 FileSystemQuotaManager::kUnknownSize)) | |
| 177 return; | |
| 178 | |
| 179 GetNewOperation(request_id)->Copy(src_path, dest_path); | 124 GetNewOperation(request_id)->Copy(src_path, dest_path); |
| 180 } | 125 } |
| 181 | 126 |
| 182 void FileSystemDispatcherHost::OnRemove( | 127 void FileSystemDispatcherHost::OnRemove( |
| 183 int request_id, const FilePath& path, bool recursive) { | 128 int request_id, const FilePath& path, bool recursive) { |
| 184 if (!VerifyFileSystemPathForWrite(path, request_id, false /* create */, 0)) | |
| 185 return; | |
| 186 GetNewOperation(request_id)->Remove(path, recursive); | 129 GetNewOperation(request_id)->Remove(path, recursive); |
| 187 } | 130 } |
| 188 | 131 |
| 189 void FileSystemDispatcherHost::OnReadMetadata( | 132 void FileSystemDispatcherHost::OnReadMetadata( |
| 190 int request_id, const FilePath& path) { | 133 int request_id, const FilePath& path) { |
| 191 if (!VerifyFileSystemPathForRead(path, request_id)) | |
| 192 return; | |
| 193 GetNewOperation(request_id)->GetMetadata(path); | 134 GetNewOperation(request_id)->GetMetadata(path); |
| 194 } | 135 } |
| 195 | 136 |
| 196 void FileSystemDispatcherHost::OnCreate( | 137 void FileSystemDispatcherHost::OnCreate( |
| 197 int request_id, const FilePath& path, bool exclusive, | 138 int request_id, const FilePath& path, bool exclusive, |
| 198 bool is_directory, bool recursive) { | 139 bool is_directory, bool recursive) { |
| 199 if (!VerifyFileSystemPathForWrite(path, request_id, true /* create */, 0)) | |
| 200 return; | |
| 201 if (is_directory) | 140 if (is_directory) |
| 202 GetNewOperation(request_id)->CreateDirectory(path, exclusive, recursive); | 141 GetNewOperation(request_id)->CreateDirectory(path, exclusive, recursive); |
| 203 else | 142 else |
| 204 GetNewOperation(request_id)->CreateFile(path, exclusive); | 143 GetNewOperation(request_id)->CreateFile(path, exclusive); |
| 205 } | 144 } |
| 206 | 145 |
| 207 void FileSystemDispatcherHost::OnExists( | 146 void FileSystemDispatcherHost::OnExists( |
| 208 int request_id, const FilePath& path, bool is_directory) { | 147 int request_id, const FilePath& path, bool is_directory) { |
| 209 if (!VerifyFileSystemPathForRead(path, request_id)) | |
| 210 return; | |
| 211 if (is_directory) | 148 if (is_directory) |
| 212 GetNewOperation(request_id)->DirectoryExists(path); | 149 GetNewOperation(request_id)->DirectoryExists(path); |
| 213 else | 150 else |
| 214 GetNewOperation(request_id)->FileExists(path); | 151 GetNewOperation(request_id)->FileExists(path); |
| 215 } | 152 } |
| 216 | 153 |
| 217 void FileSystemDispatcherHost::OnReadDirectory( | 154 void FileSystemDispatcherHost::OnReadDirectory( |
| 218 int request_id, const FilePath& path) { | 155 int request_id, const FilePath& path) { |
| 219 if (!VerifyFileSystemPathForRead(path, request_id)) | |
| 220 return; | |
| 221 GetNewOperation(request_id)->ReadDirectory(path); | 156 GetNewOperation(request_id)->ReadDirectory(path); |
| 222 } | 157 } |
| 223 | 158 |
| 224 void FileSystemDispatcherHost::OnWrite( | 159 void FileSystemDispatcherHost::OnWrite( |
| 225 int request_id, | 160 int request_id, |
| 226 const FilePath& path, | 161 const FilePath& path, |
| 227 const GURL& blob_url, | 162 const GURL& blob_url, |
| 228 int64 offset) { | 163 int64 offset) { |
| 229 if (!VerifyFileSystemPathForWrite(path, request_id, true /* create */, | |
| 230 FileSystemQuotaManager::kUnknownSize)) | |
| 231 return; | |
| 232 GetNewOperation(request_id)->Write( | 164 GetNewOperation(request_id)->Write( |
| 233 request_context_, path, blob_url, offset); | 165 request_context_, path, blob_url, offset); |
| 234 } | 166 } |
| 235 | 167 |
| 236 void FileSystemDispatcherHost::OnTruncate( | 168 void FileSystemDispatcherHost::OnTruncate( |
| 237 int request_id, | 169 int request_id, |
| 238 const FilePath& path, | 170 const FilePath& path, |
| 239 int64 length) { | 171 int64 length) { |
| 240 if (!VerifyFileSystemPathForWrite(path, request_id, false /* create */, 0)) | |
| 241 return; | |
| 242 GetNewOperation(request_id)->Truncate(path, length); | 172 GetNewOperation(request_id)->Truncate(path, length); |
| 243 } | 173 } |
| 244 | 174 |
| 245 void FileSystemDispatcherHost::OnTouchFile( | 175 void FileSystemDispatcherHost::OnTouchFile( |
| 246 int request_id, | 176 int request_id, |
| 247 const FilePath& path, | 177 const FilePath& path, |
| 248 const base::Time& last_access_time, | 178 const base::Time& last_access_time, |
| 249 const base::Time& last_modified_time) { | 179 const base::Time& last_modified_time) { |
| 250 if (!VerifyFileSystemPathForWrite(path, request_id, true /* create */, 0)) | |
| 251 return; | |
| 252 GetNewOperation(request_id)->TouchFile( | 180 GetNewOperation(request_id)->TouchFile( |
| 253 path, last_access_time, last_modified_time); | 181 path, last_access_time, last_modified_time); |
| 254 } | 182 } |
| 255 | 183 |
| 256 void FileSystemDispatcherHost::OnCancel( | 184 void FileSystemDispatcherHost::OnCancel( |
| 257 int request_id, | 185 int request_id, |
| 258 int request_id_to_cancel) { | 186 int request_id_to_cancel) { |
| 259 fileapi::FileSystemOperation* write = | 187 SandboxedFileSystemOperation* write = operations_.Lookup( |
| 260 operations_.Lookup(request_id_to_cancel); | 188 request_id_to_cancel); |
| 261 if (write) { | 189 if (write) { |
| 262 // The cancel will eventually send both the write failure and the cancel | 190 // The cancel will eventually send both the write failure and the cancel |
| 263 // success. | 191 // success. |
| 264 write->Cancel(GetNewOperation(request_id)); | 192 write->Cancel(GetNewOperation(request_id)); |
| 265 } else { | 193 } else { |
| 266 // The write already finished; report that we failed to stop it. | 194 // The write already finished; report that we failed to stop it. |
| 267 Send(new ViewMsg_FileSystem_DidFail( | 195 Send(new ViewMsg_FileSystem_DidFail( |
| 268 request_id, base::PLATFORM_FILE_ERROR_INVALID_OPERATION)); | 196 request_id, base::PLATFORM_FILE_ERROR_INVALID_OPERATION)); |
| 269 } | 197 } |
| 270 } | 198 } |
| 271 | 199 |
| 272 void FileSystemDispatcherHost::Send(IPC::Message* message) { | 200 void FileSystemDispatcherHost::Send(IPC::Message* message) { |
| 273 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 201 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 274 if (!shutdown_ && message_sender_) | 202 if (!shutdown_ && message_sender_) |
| 275 message_sender_->Send(message); | 203 message_sender_->Send(message); |
| 276 else | 204 else |
| 277 delete message; | 205 delete message; |
| 278 } | 206 } |
| 279 | 207 |
| 280 bool FileSystemDispatcherHost::VerifyFileSystemPathForRead( | 208 SandboxedFileSystemOperation* FileSystemDispatcherHost::GetNewOperation( |
| 281 const FilePath& path, int request_id) { | |
| 282 // We may want do more checks, but for now it just checks if the given | |
| 283 // |path| is under the valid FileSystem root path for this host context. | |
| 284 if (!context_->path_manager()->CrackFileSystemPath( | |
| 285 path, NULL, NULL, NULL)) { | |
| 286 Send(new ViewMsg_FileSystem_DidFail( | |
| 287 request_id, base::PLATFORM_FILE_ERROR_SECURITY)); | |
| 288 return false; | |
| 289 } | |
| 290 return true; | |
| 291 } | |
| 292 | |
| 293 bool FileSystemDispatcherHost::VerifyFileSystemPathForWrite( | |
| 294 const FilePath& path, int request_id, bool create, int64 growth) { | |
| 295 GURL origin_url; | |
| 296 FilePath virtual_path; | |
| 297 if (!context_->path_manager()->CrackFileSystemPath( | |
| 298 path, &origin_url, NULL, &virtual_path)) { | |
| 299 Send(new ViewMsg_FileSystem_DidFail( | |
| 300 request_id, base::PLATFORM_FILE_ERROR_SECURITY)); | |
| 301 return false; | |
| 302 } | |
| 303 // Any write access is disallowed on the root path. | |
| 304 if (virtual_path.value().length() == 0 || | |
| 305 virtual_path.DirName().value() == virtual_path.value()) { | |
| 306 Send(new ViewMsg_FileSystem_DidFail( | |
| 307 request_id, base::PLATFORM_FILE_ERROR_SECURITY)); | |
| 308 return false; | |
| 309 } | |
| 310 if (create && context_->path_manager()->IsRestrictedFileName( | |
| 311 path.BaseName())) { | |
| 312 Send(new ViewMsg_FileSystem_DidFail( | |
| 313 request_id, base::PLATFORM_FILE_ERROR_SECURITY)); | |
| 314 return false; | |
| 315 } | |
| 316 // TODO(kinuko): For operations with kUnknownSize we'll eventually | |
| 317 // need to resolve what amount of size it's going to write. | |
| 318 if (!context_->CheckOriginQuota(origin_url, growth)) { | |
| 319 Send(new ViewMsg_FileSystem_DidFail( | |
| 320 request_id, base::PLATFORM_FILE_ERROR_NO_SPACE)); | |
| 321 return false; | |
| 322 } | |
| 323 return true; | |
| 324 } | |
| 325 | |
| 326 bool FileSystemDispatcherHost::CheckIfFilePathIsSafe( | |
| 327 const FilePath& path, int request_id) { | |
| 328 if (context_->path_manager()->IsRestrictedFileName(path.BaseName())) { | |
| 329 Send(new ViewMsg_FileSystem_DidFail( | |
| 330 request_id, base::PLATFORM_FILE_ERROR_SECURITY)); | |
| 331 return false; | |
| 332 } | |
| 333 return true; | |
| 334 } | |
| 335 | |
| 336 fileapi::FileSystemOperation* FileSystemDispatcherHost::GetNewOperation( | |
| 337 int request_id) { | 209 int request_id) { |
| 338 BrowserFileSystemCallbackDispatcher* dispatcher = | 210 BrowserFileSystemCallbackDispatcher* dispatcher = |
| 339 new BrowserFileSystemCallbackDispatcher(this, request_id); | 211 new BrowserFileSystemCallbackDispatcher(this, request_id); |
| 340 fileapi::FileSystemOperation* operation = new fileapi::FileSystemOperation( | 212 SandboxedFileSystemOperation* operation = new SandboxedFileSystemOperation( |
| 341 dispatcher, | 213 dispatcher, |
| 342 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)); | 214 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE), |
| 215 context_.get()); |
| 343 operations_.AddWithID(operation, request_id); | 216 operations_.AddWithID(operation, request_id); |
| 344 return operation; | 217 return operation; |
| 345 } | 218 } |
| 346 | 219 |
| 347 void FileSystemDispatcherHost::RemoveCompletedOperation(int request_id) { | 220 void FileSystemDispatcherHost::RemoveCompletedOperation(int request_id) { |
| 348 DCHECK(operations_.Lookup(request_id)); | 221 DCHECK(operations_.Lookup(request_id)); |
| 349 operations_.Remove(request_id); | 222 operations_.Remove(request_id); |
| 350 } | 223 } |
| OLD | NEW |