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 |