| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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/renderer_host/database_dispatcher_host.h" | 5 #include "webkit/database/vfs_backend.h" |
| 6 | |
| 7 #if defined(OS_WIN) | |
| 8 #include <windows.h> | |
| 9 #endif | |
| 10 | 6 |
| 11 #if defined(USE_SYSTEM_SQLITE) | 7 #if defined(USE_SYSTEM_SQLITE) |
| 12 #include <sqlite3.h> | 8 #include <sqlite3.h> |
| 13 #else | 9 #else |
| 14 #include "third_party/sqlite/preprocessed/sqlite3.h" | 10 #include "third_party/sqlite/preprocessed/sqlite3.h" |
| 15 #endif | 11 #endif |
| 16 | 12 |
| 17 #include "base/file_path.h" | 13 #include "base/file_path.h" |
| 18 #include "base/file_util.h" | 14 #include "base/file_util.h" |
| 19 #include "base/message_loop.h" | |
| 20 #include "base/platform_file.h" | |
| 21 #include "base/process.h" | 15 #include "base/process.h" |
| 22 #include "base/scoped_ptr.h" | |
| 23 #include "base/task.h" | |
| 24 #include "base/thread.h" | |
| 25 #include "chrome/browser/browser_process.h" | |
| 26 #include "chrome/browser/renderer_host/resource_message_filter.h" | |
| 27 #include "chrome/common/render_messages.h" | |
| 28 #include "ipc/ipc_message.h" | |
| 29 | 16 |
| 30 #if defined(OS_POSIX) | 17 namespace webkit_database { |
| 31 #include "base/file_descriptor_posix.h" | |
| 32 #endif | |
| 33 | 18 |
| 34 const int kNumDeleteRetries = 5; | 19 bool VfsBackend::OpenFileFlagsAreConsistent( |
| 35 const int kDelayDeleteRetryMs = 100; | 20 const FilePath& file_name, const FilePath& db_dir, int desired_flags) { |
| 36 | |
| 37 namespace { | |
| 38 | |
| 39 struct OpenFileParams { | |
| 40 FilePath db_dir; // directory where all DB files are stored | |
| 41 FilePath file_name; // DB file | |
| 42 int desired_flags; // flags to be used to open the file | |
| 43 base::ProcessHandle handle; // the handle of the renderer process | |
| 44 }; | |
| 45 | |
| 46 struct DeleteFileParams { | |
| 47 FilePath db_dir; // directory where all DB files are stored | |
| 48 FilePath file_name; // DB file | |
| 49 bool sync_dir; // sync DB directory after the file is deleted? | |
| 50 }; | |
| 51 | |
| 52 // Scheduled by the file Thread on the IO thread. | |
| 53 // Sends back to the renderer process the given message. | |
| 54 static void SendMessage(ResourceMessageFilter* sender, | |
| 55 IPC::Message* message) { | |
| 56 sender->Send(message); | |
| 57 | |
| 58 // Every time we get a DB-related message, we AddRef() the resource | |
| 59 // message filterto make sure it doesn't get destroyed before we have | |
| 60 // a chance to send the reply back. So we need to Release() is here | |
| 61 // and allow it to be destroyed if needed. | |
| 62 sender->Release(); | |
| 63 } | |
| 64 | |
| 65 // Make sure the flags used to open a DB file are consistent. | |
| 66 static bool OpenFileFlagsAreConsistent(const OpenFileParams& params) { | |
| 67 // Is this a request for a temp file? | 21 // Is this a request for a temp file? |
| 68 // We should be able to delete temp files when they're closed | 22 // We should be able to delete temp files when they're closed |
| 69 // and create them as needed | 23 // and create them as needed |
| 70 if ((params.file_name == params.db_dir) && | 24 if ((file_name == db_dir) && |
| 71 (!(params.desired_flags & SQLITE_OPEN_DELETEONCLOSE) || | 25 (!(desired_flags & SQLITE_OPEN_DELETEONCLOSE) || |
| 72 !(params.desired_flags & SQLITE_OPEN_CREATE))) { | 26 !(desired_flags & SQLITE_OPEN_CREATE))) { |
| 73 return false; | 27 return false; |
| 74 } | 28 } |
| 75 | 29 |
| 76 const int file_type = params.desired_flags & 0x00007F00; | 30 const int file_type = desired_flags & 0x00007F00; |
| 77 const bool is_exclusive = | 31 const bool is_exclusive = (desired_flags & SQLITE_OPEN_EXCLUSIVE) != 0; |
| 78 (params.desired_flags & SQLITE_OPEN_EXCLUSIVE) != 0; | 32 const bool is_delete = (desired_flags & SQLITE_OPEN_DELETEONCLOSE) != 0; |
| 79 const bool is_delete = | 33 const bool is_create = (desired_flags & SQLITE_OPEN_CREATE) != 0; |
| 80 (params.desired_flags & SQLITE_OPEN_DELETEONCLOSE) != 0; | 34 const bool is_read_only = (desired_flags & SQLITE_OPEN_READONLY) != 0; |
| 81 const bool is_create = | 35 const bool is_read_write = (desired_flags & SQLITE_OPEN_READWRITE) != 0; |
| 82 (params.desired_flags & SQLITE_OPEN_CREATE) != 0; | |
| 83 const bool is_read_only = | |
| 84 (params.desired_flags & SQLITE_OPEN_READONLY) != 0; | |
| 85 const bool is_read_write = | |
| 86 (params.desired_flags & SQLITE_OPEN_READWRITE) != 0; | |
| 87 | 36 |
| 88 // All files should be opened either read-write or read-only. | 37 // All files should be opened either read-write or read-only. |
| 89 if (!(is_read_only ^ is_read_write)) { | 38 if (!(is_read_only ^ is_read_write)) { |
| 90 return false; | 39 return false; |
| 91 } | 40 } |
| 92 | 41 |
| 93 // If a new file is created, it must also be writtable. | 42 // If a new file is created, it must also be writtable. |
| 94 if (is_create && !is_read_write) { | 43 if (is_create && !is_read_write) { |
| 95 return false; | 44 return false; |
| 96 } | 45 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 120 (file_type != SQLITE_OPEN_TEMP_JOURNAL) && | 69 (file_type != SQLITE_OPEN_TEMP_JOURNAL) && |
| 121 (file_type != SQLITE_OPEN_SUBJOURNAL) && | 70 (file_type != SQLITE_OPEN_SUBJOURNAL) && |
| 122 (file_type != SQLITE_OPEN_MASTER_JOURNAL) && | 71 (file_type != SQLITE_OPEN_MASTER_JOURNAL) && |
| 123 (file_type != SQLITE_OPEN_TRANSIENT_DB)) { | 72 (file_type != SQLITE_OPEN_TRANSIENT_DB)) { |
| 124 return false; | 73 return false; |
| 125 } | 74 } |
| 126 | 75 |
| 127 return true; | 76 return true; |
| 128 } | 77 } |
| 129 | 78 |
| 130 // Scheduled by the IO thread on the file thread. | 79 void VfsBackend::OpenFile( |
| 131 // Opens the given database file, then schedules | 80 const FilePath& file_name, const FilePath& db_dir, int desired_flags, |
| 132 // a task on the IO thread's message loop to send an IPC back to | 81 base::ProcessHandle handle, base::PlatformFile* target_handle, |
| 133 // corresponding renderer process with the file handle. | 82 base::PlatformFile* target_dir_handle) { |
| 134 static void DatabaseOpenFile(MessageLoop* io_thread_message_loop, | |
| 135 const OpenFileParams& params, | |
| 136 int32 message_id, | |
| 137 ResourceMessageFilter* sender) { | |
| 138 base::PlatformFile target_handle = base::kInvalidPlatformFileValue; | |
| 139 #if defined(OS_POSIX) | |
| 140 base::PlatformFile target_dir_handle = base::kInvalidPlatformFileValue; | |
| 141 #endif | |
| 142 | |
| 143 // Verify the flags for consistency and create the database | 83 // Verify the flags for consistency and create the database |
| 144 // directory if it doesn't exist. | 84 // directory if it doesn't exist. |
| 145 if (OpenFileFlagsAreConsistent(params) && | 85 if (OpenFileFlagsAreConsistent(file_name, db_dir, desired_flags) && |
| 146 file_util::CreateDirectory(params.db_dir)) { | 86 file_util::CreateDirectory(db_dir)) { |
| 147 int flags = 0; | 87 int flags = 0; |
| 148 flags |= base::PLATFORM_FILE_READ; | 88 flags |= base::PLATFORM_FILE_READ; |
| 149 if (params.desired_flags & SQLITE_OPEN_READWRITE) { | 89 if (desired_flags & SQLITE_OPEN_READWRITE) { |
| 150 flags |= base::PLATFORM_FILE_WRITE; | 90 flags |= base::PLATFORM_FILE_WRITE; |
| 151 } | 91 } |
| 152 | 92 |
| 153 if (!(params.desired_flags & SQLITE_OPEN_MAIN_DB)) { | 93 if (!(desired_flags & SQLITE_OPEN_MAIN_DB)) { |
| 154 flags |= base::PLATFORM_FILE_EXCLUSIVE_READ | | 94 flags |= base::PLATFORM_FILE_EXCLUSIVE_READ | |
| 155 base::PLATFORM_FILE_EXCLUSIVE_WRITE; | 95 base::PLATFORM_FILE_EXCLUSIVE_WRITE; |
| 156 } | 96 } |
| 157 | 97 |
| 158 if (params.desired_flags & SQLITE_OPEN_CREATE) { | 98 if (desired_flags & SQLITE_OPEN_CREATE) { |
| 159 flags |= base::PLATFORM_FILE_OPEN_ALWAYS; | 99 flags |= base::PLATFORM_FILE_OPEN_ALWAYS; |
| 160 } else { | 100 } else { |
| 161 flags |= base::PLATFORM_FILE_OPEN; | 101 flags |= base::PLATFORM_FILE_OPEN; |
| 162 } | 102 } |
| 163 | 103 |
| 164 if (params.desired_flags & SQLITE_OPEN_EXCLUSIVE) { | 104 if (desired_flags & SQLITE_OPEN_EXCLUSIVE) { |
| 165 flags |= base::PLATFORM_FILE_EXCLUSIVE_READ | | 105 flags |= base::PLATFORM_FILE_EXCLUSIVE_READ | |
| 166 base::PLATFORM_FILE_EXCLUSIVE_WRITE; | 106 base::PLATFORM_FILE_EXCLUSIVE_WRITE; |
| 167 } | 107 } |
| 168 | 108 |
| 169 if (params.desired_flags & SQLITE_OPEN_DELETEONCLOSE) { | 109 if (desired_flags & SQLITE_OPEN_DELETEONCLOSE) { |
| 170 flags |= base::PLATFORM_FILE_TEMPORARY | base::PLATFORM_FILE_HIDDEN | | 110 flags |= base::PLATFORM_FILE_TEMPORARY | base::PLATFORM_FILE_HIDDEN | |
| 171 base::PLATFORM_FILE_DELETE_ON_CLOSE; | 111 base::PLATFORM_FILE_DELETE_ON_CLOSE; |
| 172 } | 112 } |
| 173 | 113 |
| 174 // If this is a request for a handle to a temp file, get a unique file name | 114 // If this is a request for a handle to a temp file, get a unique file name |
| 175 FilePath file_name; | 115 FilePath db_file_name; |
| 176 if (params.file_name == params.db_dir) { | 116 if (file_name == db_dir) { |
| 177 if (!file_util::CreateTemporaryFileInDir(params.db_dir, &file_name)) { | 117 if (!file_util::CreateTemporaryFileInDir(db_dir, &db_file_name)) { |
| 178 file_name = FilePath(); | 118 db_file_name = FilePath(); |
| 179 } | 119 } |
| 180 } else { | 120 } else { |
| 181 file_name = params.file_name; | 121 db_file_name = file_name; |
| 182 } | 122 } |
| 183 | 123 |
| 184 // Try to open/create the DB file. | 124 // Try to open/create the DB file. |
| 185 base::PlatformFile file_handle = | 125 base::PlatformFile file_handle = |
| 186 (file_name.empty() ? base::kInvalidPlatformFileValue : | 126 (db_file_name.empty() ? base::kInvalidPlatformFileValue : |
| 187 base::CreatePlatformFile(file_name.ToWStringHack(), flags, NULL)); | 127 base::CreatePlatformFile(db_file_name.ToWStringHack(), flags, NULL)); |
| 188 if (file_handle != base::kInvalidPlatformFileValue) { | 128 if (file_handle != base::kInvalidPlatformFileValue) { |
| 189 #if defined(OS_WIN) | 129 #if defined(OS_WIN) |
| 190 // Duplicate the file handle. | 130 // Duplicate the file handle. |
| 191 if (!DuplicateHandle(GetCurrentProcess(), file_handle, | 131 if (!DuplicateHandle(GetCurrentProcess(), file_handle, |
| 192 params.handle, &target_handle, 0, false, | 132 handle, target_handle, 0, false, |
| 193 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { | 133 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { |
| 194 // file_handle is closed whether or not DuplicateHandle succeeds. | 134 // file_handle is closed whether or not DuplicateHandle succeeds. |
| 195 target_handle = INVALID_HANDLE_VALUE; | 135 *target_handle = INVALID_HANDLE_VALUE; |
| 196 } | 136 } |
| 197 #elif defined(OS_POSIX) | 137 #elif defined(OS_POSIX) |
| 198 target_handle = file_handle; | 138 *target_handle = file_handle; |
| 199 | 139 |
| 200 int file_type = params.desired_flags & 0x00007F00; | 140 int file_type = desired_flags & 0x00007F00; |
| 201 bool creating_new_file = (params.desired_flags & SQLITE_OPEN_CREATE); | 141 bool creating_new_file = (desired_flags & SQLITE_OPEN_CREATE); |
| 202 if (creating_new_file && ((file_type == SQLITE_OPEN_MASTER_JOURNAL) || | 142 if (creating_new_file && ((file_type == SQLITE_OPEN_MASTER_JOURNAL) || |
| 203 (file_type == SQLITE_OPEN_MAIN_JOURNAL))) { | 143 (file_type == SQLITE_OPEN_MAIN_JOURNAL))) { |
| 204 // We return a handle to the containing directory because on POSIX | 144 // We return a handle to the containing directory because on POSIX |
| 205 // systems the VFS might want to fsync it after changing a file. | 145 // systems the VFS might want to fsync it after changing a file. |
| 206 // By returning it here, we avoid an extra IPC call. | 146 // By returning it here, we avoid an extra IPC call. |
| 207 target_dir_handle = base::CreatePlatformFile( | 147 *target_dir_handle = base::CreatePlatformFile( |
| 208 params.db_dir.ToWStringHack(), | 148 db_dir.ToWStringHack(), |
| 209 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ, NULL); | 149 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ, NULL); |
| 210 if (target_dir_handle == base::kInvalidPlatformFileValue) { | 150 if (*target_dir_handle == base::kInvalidPlatformFileValue) { |
| 211 base::ClosePlatformFile(target_handle); | 151 base::ClosePlatformFile(*target_handle); |
| 212 target_handle = base::kInvalidPlatformFileValue; | 152 *target_handle = base::kInvalidPlatformFileValue; |
| 213 } | 153 } |
| 214 } | 154 } |
| 215 #endif | 155 #endif |
| 216 } | 156 } |
| 217 } | 157 } |
| 218 | |
| 219 ViewMsg_DatabaseOpenFileResponse_Params response_params; | |
| 220 #if defined(OS_WIN) | |
| 221 response_params.file_handle = target_handle; | |
| 222 #elif defined(OS_POSIX) | |
| 223 response_params.file_handle = base::FileDescriptor(target_handle, true); | |
| 224 response_params.dir_handle = base::FileDescriptor(target_dir_handle, true); | |
| 225 #endif | |
| 226 | |
| 227 io_thread_message_loop->PostTask(FROM_HERE, | |
| 228 NewRunnableFunction(SendMessage, sender, | |
| 229 new ViewMsg_DatabaseOpenFileResponse(message_id, response_params))); | |
| 230 } | 158 } |
| 231 | 159 |
| 232 // Scheduled by the IO thread on the file thread. | 160 int VfsBackend::DeleteFile( |
| 233 // Deletes the given database file, then schedules | 161 const FilePath& file_name, const FilePath& db_dir, bool sync_dir) { |
| 234 // a task on the IO thread's message loop to send an IPC back to | 162 if (!file_util::PathExists(file_name)) { |
| 235 // corresponding renderer process with the error code. | 163 return SQLITE_OK; |
| 236 static void DatabaseDeleteFile( | 164 } |
| 237 MessageLoop* io_thread_message_loop, | 165 if (!file_util::Delete(file_name, false)) { |
| 238 const DeleteFileParams& params, | 166 return SQLITE_IOERR_DELETE; |
| 239 int32 message_id, | |
| 240 int reschedule_count, | |
| 241 ResourceMessageFilter* sender) { | |
| 242 // Return an error if the file could not be deleted | |
| 243 // after kNumDeleteRetries times. | |
| 244 if (!reschedule_count) { | |
| 245 io_thread_message_loop->PostTask(FROM_HERE, | |
| 246 NewRunnableFunction(SendMessage, sender, | |
| 247 new ViewMsg_DatabaseDeleteFileResponse( | |
| 248 message_id, SQLITE_IOERR_DELETE))); | |
| 249 return; | |
| 250 } | 167 } |
| 251 | 168 |
| 252 // If the file does not exist, we're done. | |
| 253 if (!file_util::PathExists(params.file_name)) { | |
| 254 io_thread_message_loop->PostTask(FROM_HERE, | |
| 255 NewRunnableFunction(SendMessage, sender, | |
| 256 new ViewMsg_DatabaseDeleteFileResponse(message_id, SQLITE_OK))); | |
| 257 return; | |
| 258 } | |
| 259 | |
| 260 | |
| 261 // If the file could not be deleted, try again. | |
| 262 if (!file_util::Delete(params.file_name, false)) { | |
| 263 MessageLoop::current()->PostDelayedTask(FROM_HERE, | |
| 264 NewRunnableFunction(DatabaseDeleteFile, io_thread_message_loop, | |
| 265 params, message_id, reschedule_count - 1, sender), | |
| 266 kDelayDeleteRetryMs); | |
| 267 return; | |
| 268 } | |
| 269 | |
| 270 // File existed and it was successfully deleted | |
| 271 int error_code = SQLITE_OK; | 169 int error_code = SQLITE_OK; |
| 272 #if defined(OS_POSIX) | 170 #if defined(OS_POSIX) |
| 273 // sync the DB directory if needed | 171 if (sync_dir) { |
| 274 if (params.sync_dir) { | |
| 275 base::PlatformFile dir_fd = base::CreatePlatformFile( | 172 base::PlatformFile dir_fd = base::CreatePlatformFile( |
| 276 params.db_dir.ToWStringHack(), base::PLATFORM_FILE_READ, NULL); | 173 db_dir.ToWStringHack(), base::PLATFORM_FILE_READ, NULL); |
| 277 if (dir_fd == base::kInvalidPlatformFileValue) { | 174 if (dir_fd == base::kInvalidPlatformFileValue) { |
| 278 error_code = SQLITE_CANTOPEN; | 175 error_code = SQLITE_CANTOPEN; |
| 279 } else { | 176 } else { |
| 280 if (fsync(dir_fd)) { | 177 if (fsync(dir_fd)) { |
| 281 error_code = SQLITE_IOERR_DIR_FSYNC; | 178 error_code = SQLITE_IOERR_DIR_FSYNC; |
| 282 } | 179 } |
| 283 base::ClosePlatformFile(dir_fd); | 180 base::ClosePlatformFile(dir_fd); |
| 284 } | 181 } |
| 285 } | 182 } |
| 286 #endif | 183 #endif |
| 287 | 184 return error_code; |
| 288 io_thread_message_loop->PostTask(FROM_HERE, | |
| 289 NewRunnableFunction(SendMessage, sender, | |
| 290 new ViewMsg_DatabaseDeleteFileResponse(message_id, error_code))); | |
| 291 } | 185 } |
| 292 | 186 |
| 293 // Scheduled by the IO thread on the file thread. | 187 uint32 VfsBackend::GetFileAttributes(const FilePath& file_name) { |
| 294 // Gets the attributes of the given database file, then schedules | |
| 295 // a task on the IO thread's message loop to send an IPC back to | |
| 296 // corresponding renderer process. | |
| 297 static void DatabaseGetFileAttributes( | |
| 298 MessageLoop* io_thread_message_loop, | |
| 299 const FilePath& file_name, | |
| 300 int32 message_id, | |
| 301 ResourceMessageFilter* sender) { | |
| 302 #if defined(OS_WIN) | 188 #if defined(OS_WIN) |
| 303 uint32 attributes = GetFileAttributes(file_name.value().c_str()); | 189 uint32 attributes = ::GetFileAttributes(file_name.value().c_str()); |
| 304 #elif defined(OS_POSIX) | 190 #elif defined(OS_POSIX) |
| 305 uint32 attributes = 0; | 191 uint32 attributes = 0; |
| 306 if (!access(file_name.value().c_str(), R_OK)) { | 192 if (!access(file_name.value().c_str(), R_OK)) { |
| 307 attributes |= static_cast<uint32>(R_OK); | 193 attributes |= static_cast<uint32>(R_OK); |
| 308 } | 194 } |
| 309 if (!access(file_name.value().c_str(), W_OK)) { | 195 if (!access(file_name.value().c_str(), W_OK)) { |
| 310 attributes |= static_cast<uint32>(W_OK); | 196 attributes |= static_cast<uint32>(W_OK); |
| 311 } | 197 } |
| 312 if (!attributes) { | 198 if (!attributes) { |
| 313 attributes = -1; | 199 attributes = -1; |
| 314 } | 200 } |
| 315 #endif | 201 #endif |
| 316 | 202 return attributes; |
| 317 io_thread_message_loop->PostTask(FROM_HERE, | |
| 318 NewRunnableFunction(SendMessage, sender, | |
| 319 new ViewMsg_DatabaseGetFileAttributesResponse( | |
| 320 message_id, attributes))); | |
| 321 } | 203 } |
| 322 | 204 |
| 323 // Scheduled by the IO thread on the file thread. | 205 int64 VfsBackend::GetFileSize(const FilePath& file_name) { |
| 324 // Gets the size of the given file, then schedules a task | |
| 325 // on the IO thread's message loop to send an IPC back to | |
| 326 // the corresponding renderer process. | |
| 327 static void DatabaseGetFileSize( | |
| 328 MessageLoop* io_thread_message_loop, | |
| 329 const FilePath& file_name, | |
| 330 int32 message_id, | |
| 331 ResourceMessageFilter* sender) { | |
| 332 int64 size = 0; | 206 int64 size = 0; |
| 333 if (!file_util::GetFileSize(file_name, &size)) { | 207 return (file_util::GetFileSize(file_name, &size) ? size : 0); |
| 334 size = 0; | |
| 335 } | |
| 336 | |
| 337 io_thread_message_loop->PostTask(FROM_HERE, | |
| 338 NewRunnableFunction(SendMessage, sender, | |
| 339 new ViewMsg_DatabaseGetFileSizeResponse(message_id, size))); | |
| 340 } | 208 } |
| 341 | 209 |
| 342 } // namespace | 210 } // namespace database |
| 343 | |
| 344 DatabaseDispatcherHost::DatabaseDispatcherHost( | |
| 345 const FilePath& profile_path, | |
| 346 ResourceMessageFilter* resource_message_filter) | |
| 347 : profile_path_(profile_path), | |
| 348 resource_message_filter_(resource_message_filter), | |
| 349 file_thread_message_loop_( | |
| 350 g_browser_process->file_thread()->message_loop()) { | |
| 351 } | |
| 352 | |
| 353 DatabaseDispatcherHost::~DatabaseDispatcherHost() { | |
| 354 } | |
| 355 | |
| 356 bool DatabaseDispatcherHost::IsDBMessage(const IPC::Message& message) { | |
| 357 switch (message.type()) { | |
| 358 case ViewHostMsg_DatabaseOpenFile::ID: | |
| 359 case ViewHostMsg_DatabaseDeleteFile::ID: | |
| 360 case ViewHostMsg_DatabaseGetFileAttributes::ID: | |
| 361 case ViewHostMsg_DatabaseGetFileSize::ID: | |
| 362 return true; | |
| 363 } | |
| 364 return false; | |
| 365 } | |
| 366 | |
| 367 bool DatabaseDispatcherHost::OnMessageReceived( | |
| 368 const IPC::Message& message, bool* message_was_ok) { | |
| 369 if (!IsDBMessage(message)) { | |
| 370 return false; | |
| 371 } | |
| 372 *message_was_ok = true; | |
| 373 | |
| 374 bool handled = true; | |
| 375 IPC_BEGIN_MESSAGE_MAP_EX(DatabaseDispatcherHost, message, *message_was_ok) | |
| 376 IPC_MESSAGE_HANDLER(ViewHostMsg_DatabaseOpenFile, OnDatabaseOpenFile); | |
| 377 IPC_MESSAGE_HANDLER(ViewHostMsg_DatabaseDeleteFile, OnDatabaseDeleteFile); | |
| 378 IPC_MESSAGE_HANDLER(ViewHostMsg_DatabaseGetFileAttributes, | |
| 379 OnDatabaseGetFileAttributes); | |
| 380 IPC_MESSAGE_HANDLER(ViewHostMsg_DatabaseGetFileSize, | |
| 381 OnDatabaseGetFileSize); | |
| 382 IPC_MESSAGE_UNHANDLED(handled = false) | |
| 383 IPC_END_MESSAGE_MAP_EX() | |
| 384 return handled; | |
| 385 } | |
| 386 | |
| 387 FilePath DatabaseDispatcherHost::GetDBDir() { | |
| 388 return profile_path_.Append(FILE_PATH_LITERAL("databases")); | |
| 389 } | |
| 390 | |
| 391 FilePath DatabaseDispatcherHost::GetDBFileFullPath(const FilePath& file_name) { | |
| 392 // Do not allow '\', '/' and ':' in file names. | |
| 393 FilePath::StringType file = file_name.value(); | |
| 394 if ((file.find('\\') != std::wstring::npos) || | |
| 395 (file.find('/') != std::wstring::npos) || | |
| 396 (file.find(':') != std::wstring::npos)) { | |
| 397 return FilePath(); | |
| 398 } | |
| 399 return GetDBDir().Append(file_name); | |
| 400 } | |
| 401 | |
| 402 void DatabaseDispatcherHost::OnDatabaseOpenFile( | |
| 403 const FilePath& file_name, int desired_flags, | |
| 404 int32 message_id) { | |
| 405 FilePath db_file_name = GetDBFileFullPath(file_name); | |
| 406 | |
| 407 if (db_file_name.empty()) { | |
| 408 ViewMsg_DatabaseOpenFileResponse_Params response_params; | |
| 409 #if defined(OS_WIN) | |
| 410 response_params.file_handle = base::kInvalidPlatformFileValue; | |
| 411 #elif defined(OS_POSIX) | |
| 412 response_params.file_handle = | |
| 413 base::FileDescriptor(base::kInvalidPlatformFileValue, true); | |
| 414 response_params.dir_handle = | |
| 415 base::FileDescriptor(base::kInvalidPlatformFileValue, true); | |
| 416 #endif | |
| 417 resource_message_filter_->Send(new ViewMsg_DatabaseOpenFileResponse( | |
| 418 message_id, response_params)); | |
| 419 return; | |
| 420 } | |
| 421 | |
| 422 OpenFileParams params = { GetDBDir(), db_file_name, desired_flags, | |
| 423 resource_message_filter_->handle() }; | |
| 424 resource_message_filter_->AddRef(); | |
| 425 file_thread_message_loop_->PostTask(FROM_HERE, | |
| 426 NewRunnableFunction(DatabaseOpenFile, MessageLoop::current(), | |
| 427 params, message_id, resource_message_filter_)); | |
| 428 } | |
| 429 | |
| 430 void DatabaseDispatcherHost::OnDatabaseDeleteFile( | |
| 431 const FilePath& file_name, const bool& sync_dir, int32 message_id) { | |
| 432 FilePath db_file_name = GetDBFileFullPath(file_name); | |
| 433 if (db_file_name.empty()) { | |
| 434 resource_message_filter_->Send(new ViewMsg_DatabaseDeleteFileResponse( | |
| 435 message_id, SQLITE_IOERR_DELETE)); | |
| 436 return; | |
| 437 } | |
| 438 | |
| 439 DeleteFileParams params = { GetDBDir(), db_file_name, sync_dir }; | |
| 440 resource_message_filter_->AddRef(); | |
| 441 file_thread_message_loop_->PostTask(FROM_HERE, | |
| 442 NewRunnableFunction(DatabaseDeleteFile, MessageLoop::current(), | |
| 443 params, message_id, kNumDeleteRetries, resource_message_filter_)); | |
| 444 } | |
| 445 | |
| 446 void DatabaseDispatcherHost::OnDatabaseGetFileAttributes( | |
| 447 const FilePath& file_name, int32 message_id) { | |
| 448 FilePath db_file_name = GetDBFileFullPath(file_name); | |
| 449 if (db_file_name.empty()) { | |
| 450 resource_message_filter_->Send( | |
| 451 new ViewMsg_DatabaseGetFileAttributesResponse( | |
| 452 message_id, -1)); | |
| 453 return; | |
| 454 } | |
| 455 | |
| 456 resource_message_filter_->AddRef(); | |
| 457 file_thread_message_loop_->PostTask(FROM_HERE, | |
| 458 NewRunnableFunction(DatabaseGetFileAttributes, MessageLoop::current(), | |
| 459 db_file_name, message_id, resource_message_filter_)); | |
| 460 } | |
| 461 | |
| 462 void DatabaseDispatcherHost::OnDatabaseGetFileSize( | |
| 463 const FilePath& file_name, int32 message_id) { | |
| 464 FilePath db_file_name = GetDBFileFullPath(file_name); | |
| 465 if (db_file_name.empty()) { | |
| 466 resource_message_filter_->Send(new ViewMsg_DatabaseGetFileSizeResponse( | |
| 467 message_id, 0)); | |
| 468 return; | |
| 469 } | |
| 470 | |
| 471 resource_message_filter_->AddRef(); | |
| 472 file_thread_message_loop_->PostTask(FROM_HERE, | |
| 473 NewRunnableFunction(DatabaseGetFileSize, MessageLoop::current(), | |
| 474 db_file_name, message_id, resource_message_filter_)); | |
| 475 } | |
| OLD | NEW |