| 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 "chrome/browser/renderer_host/database_dispatcher_host.h" |
| 6 | 6 |
| 7 #if defined(OS_WIN) | 7 #if defined(OS_POSIX) |
| 8 #include <windows.h> | 8 #include "base/file_descriptor_posix.h" |
| 9 #endif | 9 #endif |
| 10 | 10 |
| 11 #if defined(USE_SYSTEM_SQLITE) | 11 #if defined(USE_SYSTEM_SQLITE) |
| 12 #include <sqlite3.h> | 12 #include <sqlite3.h> |
| 13 #else | 13 #else |
| 14 #include "third_party/sqlite/preprocessed/sqlite3.h" | 14 #include "third_party/sqlite/preprocessed/sqlite3.h" |
| 15 #endif | 15 #endif |
| 16 | 16 |
| 17 #include "base/string_util.h" |
| 18 #include "base/thread.h" |
| 19 #include "chrome/browser/browser_process.h" |
| 17 #include "chrome/browser/chrome_thread.h" | 20 #include "chrome/browser/chrome_thread.h" |
| 18 #include "chrome/browser/renderer_host/resource_message_filter.h" | 21 #include "chrome/browser/renderer_host/browser_render_process_host.h" |
| 19 #include "chrome/common/render_messages.h" | 22 #include "chrome/common/render_messages.h" |
| 20 #include "webkit/database/vfs_backend.h" | 23 #include "webkit/database/vfs_backend.h" |
| 21 | 24 |
| 22 #if defined(OS_POSIX) | 25 using webkit_database::DatabaseTracker; |
| 23 #include "base/file_descriptor_posix.h" | 26 using webkit_database::VfsBackend; |
| 27 |
| 28 const int kNumDeleteRetries = 2; |
| 29 const int kDelayDeleteRetryMs = 100; |
| 30 |
| 31 DatabaseDispatcherHost::DatabaseDispatcherHost( |
| 32 DatabaseTracker* db_tracker, |
| 33 IPC::Message::Sender* message_sender, |
| 34 base::ProcessHandle process_handle) |
| 35 : db_tracker_(db_tracker), |
| 36 message_sender_(message_sender), |
| 37 process_handle_(process_handle), |
| 38 observer_added_(false), |
| 39 shutdown_(false) { |
| 40 DCHECK(db_tracker_); |
| 41 DCHECK(message_sender_); |
| 42 } |
| 43 |
| 44 void DatabaseDispatcherHost::Shutdown() { |
| 45 shutdown_ = true; |
| 46 message_sender_ = NULL; |
| 47 if (observer_added_) { |
| 48 ChromeThread::PostTask( |
| 49 ChromeThread::FILE, FROM_HERE, |
| 50 NewRunnableMethod(this, &DatabaseDispatcherHost::RemoveObserver)); |
| 51 } |
| 52 } |
| 53 |
| 54 void DatabaseDispatcherHost::AddObserver() { |
| 55 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
| 56 db_tracker_->AddObserver(this); |
| 57 } |
| 58 |
| 59 void DatabaseDispatcherHost::RemoveObserver() { |
| 60 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
| 61 db_tracker_->RemoveObserver(this); |
| 62 } |
| 63 |
| 64 FilePath DatabaseDispatcherHost::GetDBFileFullPath( |
| 65 const FilePath& vfs_file_name) { |
| 66 // 'vfs_file_name' can be one of 3 things: |
| 67 // 1. Empty string: It means the VFS wants to open a temp file. In this case |
| 68 // we need to return the path to the directory that stores all databases. |
| 69 // 2. origin_identifier/database_name: In this case, we need to extract |
| 70 // 'origin_identifier' and 'database_name' and pass them to |
| 71 // DatabaseTracker::GetFullDBFilePath(). |
| 72 // 3. origin_identifier/database_name-suffix: '-suffix' could be '-journal', |
| 73 // for example. In this case, we need to extract 'origin_identifier' and |
| 74 // 'database_name-suffix' and pass them to |
| 75 // DatabaseTracker::GetFullDBFilePath(). 'database_name-suffix' is not |
| 76 // a database name as expected by DatabaseTracker::GetFullDBFilePath(), |
| 77 // but due to its implementation, it's OK to pass in 'database_name-suffix' |
| 78 // too. |
| 79 // |
| 80 // We also check that the given string doesn't contain invalid characters |
| 81 // that would result in a DB file stored outside of the directory where |
| 82 // all DB files are supposed to be stored. |
| 83 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
| 84 if (vfs_file_name.empty()) |
| 85 return db_tracker_->DatabaseDirectory(); |
| 86 |
| 87 std::wstring str = vfs_file_name.ToWStringHack(); |
| 88 size_t slashIndex = str.find('/'); |
| 89 if (slashIndex == std::wstring::npos) |
| 90 return FilePath(); // incorrect format |
| 91 std::wstring origin_identifier = str.substr(0, slashIndex); |
| 92 std::wstring database_name = |
| 93 str.substr(slashIndex + 1, str.length() - slashIndex); |
| 94 if ((origin_identifier.find('\\') != std::wstring::npos) || |
| 95 (origin_identifier.find('/') != std::wstring::npos) || |
| 96 (origin_identifier.find(':') != std::wstring::npos) || |
| 97 (database_name.find('\\') != std::wstring::npos) || |
| 98 (database_name.find('/') != std::wstring::npos) || |
| 99 (database_name.find(':') != std::wstring::npos)) { |
| 100 return FilePath(); |
| 101 } |
| 102 |
| 103 return db_tracker_->GetFullDBFilePath( |
| 104 WideToUTF16(origin_identifier), WideToUTF16(database_name)); |
| 105 } |
| 106 |
| 107 bool DatabaseDispatcherHost::OnMessageReceived( |
| 108 const IPC::Message& message, bool* message_was_ok) { |
| 109 DCHECK(!shutdown_); |
| 110 *message_was_ok = true; |
| 111 bool handled = true; |
| 112 IPC_BEGIN_MESSAGE_MAP_EX(DatabaseDispatcherHost, message, *message_was_ok) |
| 113 IPC_MESSAGE_HANDLER(ViewHostMsg_DatabaseOpenFile, OnDatabaseOpenFile) |
| 114 IPC_MESSAGE_HANDLER(ViewHostMsg_DatabaseDeleteFile, OnDatabaseDeleteFile) |
| 115 IPC_MESSAGE_HANDLER(ViewHostMsg_DatabaseGetFileAttributes, |
| 116 OnDatabaseGetFileAttributes) |
| 117 IPC_MESSAGE_HANDLER(ViewHostMsg_DatabaseGetFileSize, |
| 118 OnDatabaseGetFileSize) |
| 119 IPC_MESSAGE_HANDLER(ViewHostMsg_DatabaseOpened, OnDatabaseOpened) |
| 120 IPC_MESSAGE_HANDLER(ViewHostMsg_DatabaseModified, OnDatabaseModified) |
| 121 IPC_MESSAGE_HANDLER(ViewHostMsg_DatabaseClosed, OnDatabaseClosed) |
| 122 IPC_MESSAGE_UNHANDLED(handled = false) |
| 123 IPC_END_MESSAGE_MAP_EX() |
| 124 return handled; |
| 125 } |
| 126 |
| 127 void DatabaseDispatcherHost::ReceivedBadMessage(uint16 msg_type) { |
| 128 BrowserRenderProcessHost::BadMessageTerminateProcess( |
| 129 msg_type, process_handle_); |
| 130 } |
| 131 |
| 132 // Scheduled by the file thread on the IO thread. |
| 133 // Sends back to the renderer process the given message. |
| 134 void DatabaseDispatcherHost::SendMessage(IPC::Message* message) { |
| 135 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); |
| 136 if (!shutdown_) |
| 137 message_sender_->Send(message); |
| 138 else |
| 139 delete message; |
| 140 } |
| 141 |
| 142 void DatabaseDispatcherHost::OnDatabaseOpenFile(const FilePath& vfs_file_name, |
| 143 int desired_flags, |
| 144 int32 message_id) { |
| 145 if (!observer_added_) { |
| 146 observer_added_ = true; |
| 147 ChromeThread::PostTask( |
| 148 ChromeThread::FILE, FROM_HERE, |
| 149 NewRunnableMethod(this, &DatabaseDispatcherHost::AddObserver)); |
| 150 } |
| 151 |
| 152 ChromeThread::PostTask( |
| 153 ChromeThread::FILE, FROM_HERE, |
| 154 NewRunnableMethod(this, |
| 155 &DatabaseDispatcherHost::DatabaseOpenFile, |
| 156 vfs_file_name, |
| 157 desired_flags, |
| 158 message_id)); |
| 159 } |
| 160 |
| 161 static void SetOpenFileResponseParams( |
| 162 ViewMsg_DatabaseOpenFileResponse_Params* params, |
| 163 base::PlatformFile file_handle, |
| 164 base::PlatformFile dir_handle) { |
| 165 #if defined(OS_WIN) |
| 166 params->file_handle = file_handle; |
| 167 #elif defined(OS_POSIX) |
| 168 params->file_handle = base::FileDescriptor(file_handle, true); |
| 169 params->dir_handle = base::FileDescriptor(dir_handle, true); |
| 24 #endif | 170 #endif |
| 25 | |
| 26 using webkit_database::VfsBackend; | |
| 27 | |
| 28 const int kNumDeleteRetries = 3; | |
| 29 const int kDelayDeleteRetryMs = 100; | |
| 30 | |
| 31 namespace { | |
| 32 | |
| 33 struct OpenFileParams { | |
| 34 FilePath db_dir; | |
| 35 FilePath file_name; | |
| 36 int desired_flags; | |
| 37 base::ProcessHandle handle; | |
| 38 }; | |
| 39 | |
| 40 struct DeleteFileParams { | |
| 41 FilePath db_dir; | |
| 42 FilePath file_name; | |
| 43 bool sync_dir; | |
| 44 }; | |
| 45 | |
| 46 // Scheduled by the file Thread on the IO thread. | |
| 47 // Sends back to the renderer process the given message. | |
| 48 static void SendMessage(ResourceMessageFilter* sender, | |
| 49 IPC::Message* message) { | |
| 50 sender->Send(message); | |
| 51 | |
| 52 // Every time we get a DB-related message, we AddRef() the resource | |
| 53 // message filterto make sure it doesn't get destroyed before we have | |
| 54 // a chance to send the reply back. So we need to Release() is here | |
| 55 // and allow it to be destroyed if needed. | |
| 56 sender->Release(); | |
| 57 } | 171 } |
| 58 | 172 |
| 59 // Scheduled by the IO thread on the file thread. | 173 // Scheduled by the IO thread on the file thread. |
| 60 // Opens the given database file, then schedules | 174 // Opens the given database file, then schedules |
| 61 // a task on the IO thread's message loop to send an IPC back to | 175 // a task on the IO thread's message loop to send an IPC back to |
| 62 // corresponding renderer process with the file handle. | 176 // corresponding renderer process with the file handle. |
| 63 static void DatabaseOpenFile(const OpenFileParams& params, | 177 void DatabaseDispatcherHost::DatabaseOpenFile(const FilePath& vfs_file_name, |
| 64 int32 message_id, | 178 int desired_flags, |
| 65 ResourceMessageFilter* sender) { | 179 int32 message_id) { |
| 180 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
| 66 base::PlatformFile target_handle = base::kInvalidPlatformFileValue; | 181 base::PlatformFile target_handle = base::kInvalidPlatformFileValue; |
| 67 base::PlatformFile target_dir_handle = base::kInvalidPlatformFileValue; | 182 base::PlatformFile target_dir_handle = base::kInvalidPlatformFileValue; |
| 68 VfsBackend::OpenFile(params.file_name, params.db_dir, params.desired_flags, | 183 FilePath db_file_name = GetDBFileFullPath(vfs_file_name); |
| 69 params.handle, &target_handle, &target_dir_handle); | 184 if (!db_file_name.empty()) { |
| 185 FilePath db_dir = db_tracker_->DatabaseDirectory(); |
| 186 VfsBackend::OpenFile(db_file_name, db_dir, desired_flags, |
| 187 process_handle_, &target_handle, &target_dir_handle); |
| 188 } |
| 70 | 189 |
| 71 ViewMsg_DatabaseOpenFileResponse_Params response_params; | 190 ViewMsg_DatabaseOpenFileResponse_Params response_params; |
| 72 #if defined(OS_WIN) | 191 SetOpenFileResponseParams(&response_params, target_handle, target_dir_handle); |
| 73 response_params.file_handle = target_handle; | |
| 74 #elif defined(OS_POSIX) | |
| 75 response_params.file_handle = base::FileDescriptor(target_handle, true); | |
| 76 response_params.dir_handle = base::FileDescriptor(target_dir_handle, true); | |
| 77 #endif | |
| 78 ChromeThread::PostTask( | 192 ChromeThread::PostTask( |
| 79 ChromeThread::IO, FROM_HERE, | 193 ChromeThread::IO, FROM_HERE, |
| 80 NewRunnableFunction(SendMessage, sender, | 194 NewRunnableMethod(this, |
| 81 new ViewMsg_DatabaseOpenFileResponse(message_id, response_params))); | 195 &DatabaseDispatcherHost::SendMessage, |
| 196 new ViewMsg_DatabaseOpenFileResponse( |
| 197 message_id, response_params))); |
| 198 } |
| 199 |
| 200 void DatabaseDispatcherHost::OnDatabaseDeleteFile(const FilePath& vfs_file_name, |
| 201 const bool& sync_dir, |
| 202 int32 message_id) { |
| 203 ChromeThread::PostTask( |
| 204 ChromeThread::FILE, FROM_HERE, |
| 205 NewRunnableMethod(this, |
| 206 &DatabaseDispatcherHost::DatabaseDeleteFile, |
| 207 vfs_file_name, |
| 208 sync_dir, |
| 209 message_id, |
| 210 kNumDeleteRetries)); |
| 82 } | 211 } |
| 83 | 212 |
| 84 // Scheduled by the IO thread on the file thread. | 213 // Scheduled by the IO thread on the file thread. |
| 85 // Deletes the given database file, then schedules | 214 // Deletes the given database file, then schedules |
| 86 // a task on the IO thread's message loop to send an IPC back to | 215 // a task on the IO thread's message loop to send an IPC back to |
| 87 // corresponding renderer process with the error code. | 216 // corresponding renderer process with the error code. |
| 88 static void DatabaseDeleteFile(const DeleteFileParams& params, | 217 void DatabaseDispatcherHost::DatabaseDeleteFile(const FilePath& vfs_file_name, |
| 89 int32 message_id, | 218 bool sync_dir, |
| 90 int reschedule_count, | 219 int32 message_id, |
| 91 ResourceMessageFilter* sender) { | 220 int reschedule_count) { |
| 92 // Return an error if the file could not be deleted | 221 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
| 93 // after kNumDeleteRetries times. | 222 |
| 94 if (!reschedule_count) { | 223 // Return an error if the file name is invalid or if the file could not |
| 95 ChromeThread::PostTask( | 224 // be deleted after kNumDeleteRetries attempts. |
| 96 ChromeThread::IO, FROM_HERE, | 225 int error_code = SQLITE_IOERR_DELETE; |
| 97 NewRunnableFunction(SendMessage, sender, | 226 FilePath db_file_name = GetDBFileFullPath(vfs_file_name); |
| 98 new ViewMsg_DatabaseDeleteFileResponse(message_id, | 227 if (!db_file_name.empty()) { |
| 99 SQLITE_IOERR_DELETE))); | 228 FilePath db_dir = db_tracker_->DatabaseDirectory(); |
| 100 return; | 229 error_code = VfsBackend::DeleteFile(db_file_name, db_dir, sync_dir); |
| 101 } | 230 if ((error_code == SQLITE_IOERR_DELETE) && reschedule_count) { |
| 102 | 231 // If the file could not be deleted, try again. |
| 103 int error_code = | 232 ChromeThread::PostDelayedTask( |
| 104 VfsBackend::DeleteFile(params.file_name, params.db_dir, params.sync_dir); | 233 ChromeThread::FILE, FROM_HERE, |
| 105 if (error_code == SQLITE_IOERR_DELETE) { | 234 NewRunnableMethod(this, |
| 106 // If the file could not be deleted, try again. | 235 &DatabaseDispatcherHost::DatabaseDeleteFile, |
| 107 MessageLoop::current()->PostDelayedTask(FROM_HERE, | 236 vfs_file_name, |
| 108 NewRunnableFunction(DatabaseDeleteFile, params, message_id, | 237 sync_dir, |
| 109 reschedule_count - 1, sender), | 238 message_id, |
| 110 kDelayDeleteRetryMs); | 239 reschedule_count - 1), |
| 111 return; | 240 kDelayDeleteRetryMs); |
| 241 return; |
| 242 } |
| 112 } | 243 } |
| 113 | 244 |
| 114 ChromeThread::PostTask( | 245 ChromeThread::PostTask( |
| 115 ChromeThread::IO, FROM_HERE, | 246 ChromeThread::IO, FROM_HERE, |
| 116 NewRunnableFunction(SendMessage, sender, | 247 NewRunnableMethod(this, |
| 117 new ViewMsg_DatabaseDeleteFileResponse(message_id, error_code))); | 248 &DatabaseDispatcherHost::SendMessage, |
| 249 new ViewMsg_DatabaseDeleteFileResponse( |
| 250 message_id, error_code))); |
| 251 } |
| 252 |
| 253 void DatabaseDispatcherHost::OnDatabaseGetFileAttributes( |
| 254 const FilePath& vfs_file_name, |
| 255 int32 message_id) { |
| 256 ChromeThread::PostTask( |
| 257 ChromeThread::FILE, FROM_HERE, |
| 258 NewRunnableMethod(this, |
| 259 &DatabaseDispatcherHost::DatabaseGetFileAttributes, |
| 260 vfs_file_name, |
| 261 message_id)); |
| 118 } | 262 } |
| 119 | 263 |
| 120 // Scheduled by the IO thread on the file thread. | 264 // Scheduled by the IO thread on the file thread. |
| 121 // Gets the attributes of the given database file, then schedules | 265 // Gets the attributes of the given database file, then schedules |
| 122 // a task on the IO thread's message loop to send an IPC back to | 266 // a task on the IO thread's message loop to send an IPC back to |
| 123 // corresponding renderer process. | 267 // corresponding renderer process. |
| 124 static void DatabaseGetFileAttributes(const FilePath& file_name, | 268 void DatabaseDispatcherHost::DatabaseGetFileAttributes( |
| 125 int32 message_id, | 269 const FilePath& vfs_file_name, |
| 126 ResourceMessageFilter* sender) { | 270 int32 message_id) { |
| 127 uint32 attributes = VfsBackend::GetFileAttributes(file_name); | 271 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
| 272 int32 attributes = -1; |
| 273 FilePath db_file_name = GetDBFileFullPath(vfs_file_name); |
| 274 if (!db_file_name.empty()) |
| 275 attributes = VfsBackend::GetFileAttributes(db_file_name); |
| 128 ChromeThread::PostTask( | 276 ChromeThread::PostTask( |
| 129 ChromeThread::IO, FROM_HERE, | 277 ChromeThread::IO, FROM_HERE, |
| 130 NewRunnableFunction(SendMessage, sender, | 278 NewRunnableMethod(this, |
| 131 new ViewMsg_DatabaseGetFileAttributesResponse( | 279 &DatabaseDispatcherHost::SendMessage, |
| 132 message_id, attributes))); | 280 new ViewMsg_DatabaseGetFileAttributesResponse( |
| 281 message_id, attributes))); |
| 282 } |
| 283 |
| 284 void DatabaseDispatcherHost::OnDatabaseGetFileSize( |
| 285 const FilePath& vfs_file_name, int32 message_id) { |
| 286 ChromeThread::PostTask( |
| 287 ChromeThread::FILE, FROM_HERE, |
| 288 NewRunnableMethod(this, |
| 289 &DatabaseDispatcherHost::DatabaseGetFileSize, |
| 290 vfs_file_name, |
| 291 message_id)); |
| 133 } | 292 } |
| 134 | 293 |
| 135 // Scheduled by the IO thread on the file thread. | 294 // Scheduled by the IO thread on the file thread. |
| 136 // Gets the size of the given file, then schedules a task | 295 // Gets the size of the given file, then schedules a task |
| 137 // on the IO thread's message loop to send an IPC back to | 296 // on the IO thread's message loop to send an IPC back to |
| 138 // the corresponding renderer process. | 297 // the corresponding renderer process. |
| 139 static void DatabaseGetFileSize(const FilePath& file_name, | 298 void DatabaseDispatcherHost::DatabaseGetFileSize(const FilePath& vfs_file_name, |
| 140 int32 message_id, | 299 int32 message_id) { |
| 141 ResourceMessageFilter* sender) { | 300 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
| 142 int64 size = VfsBackend::GetFileSize(file_name); | 301 int64 size = 0; |
| 302 FilePath db_file_name = GetDBFileFullPath(vfs_file_name); |
| 303 if (!db_file_name.empty()) |
| 304 size = VfsBackend::GetFileSize(db_file_name); |
| 143 ChromeThread::PostTask( | 305 ChromeThread::PostTask( |
| 144 ChromeThread::IO, FROM_HERE, | 306 ChromeThread::IO, FROM_HERE, |
| 145 NewRunnableFunction(SendMessage, sender, | 307 NewRunnableMethod(this, |
| 146 new ViewMsg_DatabaseGetFileSizeResponse(message_id, size))); | 308 &DatabaseDispatcherHost::SendMessage, |
| 147 } | 309 new ViewMsg_DatabaseGetFileSizeResponse( |
| 148 | 310 message_id, size))); |
| 149 } // namespace | 311 } |
| 150 | 312 |
| 151 DatabaseDispatcherHost::DatabaseDispatcherHost( | 313 void DatabaseDispatcherHost::OnDatabaseOpened(const string16& origin_identifier, |
| 152 const FilePath& profile_path, | 314 const string16& database_name, |
| 153 ResourceMessageFilter* resource_message_filter) | 315 const string16& description, |
| 154 : profile_path_(profile_path), | 316 int64 estimated_size) { |
| 155 resource_message_filter_(resource_message_filter) { | 317 ChromeThread::PostTask( |
| 156 } | 318 ChromeThread::FILE, FROM_HERE, |
| 157 | 319 NewRunnableMethod(this, |
| 158 bool DatabaseDispatcherHost::OnMessageReceived( | 320 &DatabaseDispatcherHost::DatabaseOpened, |
| 159 const IPC::Message& message, bool* message_was_ok) { | 321 origin_identifier, |
| 160 *message_was_ok = true; | 322 database_name, |
| 161 | 323 description, |
| 162 bool handled = true; | 324 estimated_size)); |
| 163 IPC_BEGIN_MESSAGE_MAP_EX(DatabaseDispatcherHost, message, *message_was_ok) | 325 } |
| 164 IPC_MESSAGE_HANDLER(ViewHostMsg_DatabaseOpenFile, OnDatabaseOpenFile); | 326 |
| 165 IPC_MESSAGE_HANDLER(ViewHostMsg_DatabaseDeleteFile, OnDatabaseDeleteFile); | 327 void DatabaseDispatcherHost::DatabaseOpened(const string16& origin_identifier, |
| 166 IPC_MESSAGE_HANDLER(ViewHostMsg_DatabaseGetFileAttributes, | 328 const string16& database_name, |
| 167 OnDatabaseGetFileAttributes); | 329 const string16& description, |
| 168 IPC_MESSAGE_HANDLER(ViewHostMsg_DatabaseGetFileSize, | 330 int64 estimated_size) { |
| 169 OnDatabaseGetFileSize); | 331 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
| 170 IPC_MESSAGE_UNHANDLED(handled = false) | 332 int64 database_size = 0; |
| 171 IPC_END_MESSAGE_MAP_EX() | 333 int64 space_available = 0; |
| 172 return handled; | 334 AddAccessedOrigin(origin_identifier); |
| 173 } | 335 db_tracker_->DatabaseOpened(origin_identifier, database_name, description, |
| 174 | 336 estimated_size, &database_size, &space_available); |
| 175 FilePath DatabaseDispatcherHost::GetDBDir() { | 337 ChromeThread::PostTask( |
| 176 return profile_path_.Append(FILE_PATH_LITERAL("databases")); | 338 ChromeThread::IO, FROM_HERE, |
| 177 } | 339 NewRunnableMethod(this, |
| 178 | 340 &DatabaseDispatcherHost::SendMessage, |
| 179 FilePath DatabaseDispatcherHost::GetDBFileFullPath(const FilePath& file_name) { | 341 new ViewMsg_DatabaseUpdateSize( |
| 180 // Do not allow '\', '/' and ':' in file names. | 342 origin_identifier, database_name, |
| 181 FilePath::StringType file = file_name.value(); | 343 database_size, space_available))); |
| 182 if ((file.find('\\') != std::wstring::npos) || | 344 } |
| 183 (file.find('/') != std::wstring::npos) || | 345 |
| 184 (file.find(':') != std::wstring::npos)) { | 346 void DatabaseDispatcherHost::OnDatabaseModified( |
| 185 return FilePath(); | 347 const string16& origin_identifier, |
| 186 } | 348 const string16& database_name) { |
| 187 return GetDBDir().Append(file_name); | 349 ChromeThread::PostTask( |
| 188 } | 350 ChromeThread::FILE, FROM_HERE, |
| 189 | 351 NewRunnableMethod(this, |
| 190 void DatabaseDispatcherHost::OnDatabaseOpenFile(const FilePath& file_name, | 352 &DatabaseDispatcherHost::DatabaseModified, |
| 191 int desired_flags, | 353 origin_identifier, |
| 192 int32 message_id) { | 354 database_name)); |
| 193 FilePath db_file_name = GetDBFileFullPath(file_name); | 355 } |
| 194 | 356 |
| 195 if (db_file_name.empty()) { | 357 void DatabaseDispatcherHost::DatabaseModified(const string16& origin_identifier, |
| 196 ViewMsg_DatabaseOpenFileResponse_Params response_params; | 358 const string16& database_name) { |
| 197 #if defined(OS_WIN) | 359 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
| 198 response_params.file_handle = base::kInvalidPlatformFileValue; | 360 if (!HasAccessedOrigin(origin_identifier)) { |
| 199 #elif defined(OS_POSIX) | 361 ReceivedBadMessage(ViewHostMsg_DatabaseModified::ID); |
| 200 response_params.file_handle = | |
| 201 base::FileDescriptor(base::kInvalidPlatformFileValue, true); | |
| 202 response_params.dir_handle = | |
| 203 base::FileDescriptor(base::kInvalidPlatformFileValue, true); | |
| 204 #endif | |
| 205 resource_message_filter_->Send(new ViewMsg_DatabaseOpenFileResponse( | |
| 206 message_id, response_params)); | |
| 207 return; | 362 return; |
| 208 } | 363 } |
| 209 | 364 |
| 210 OpenFileParams params; | 365 db_tracker_->DatabaseModified(origin_identifier, database_name); |
| 211 params.db_dir = GetDBDir(); | 366 } |
| 212 params.file_name = db_file_name; | 367 |
| 213 params.desired_flags = desired_flags; | 368 void DatabaseDispatcherHost::OnDatabaseClosed(const string16& origin_identifier, |
| 214 params.handle = resource_message_filter_->handle(); | 369 const string16& database_name) { |
| 215 resource_message_filter_->AddRef(); | 370 ChromeThread::PostTask( |
| 216 ChromeThread::PostTask( | 371 ChromeThread::FILE, FROM_HERE, |
| 217 ChromeThread::FILE, FROM_HERE, | 372 NewRunnableMethod(this, |
| 218 NewRunnableFunction( | 373 &DatabaseDispatcherHost::DatabaseClosed, |
| 219 DatabaseOpenFile, params, message_id, resource_message_filter_)); | 374 origin_identifier, |
| 220 } | 375 database_name)); |
| 221 | 376 } |
| 222 void DatabaseDispatcherHost::OnDatabaseDeleteFile( | 377 |
| 223 const FilePath& file_name, const bool& sync_dir, int32 message_id) { | 378 void DatabaseDispatcherHost::DatabaseClosed(const string16& origin_identifier, |
| 224 FilePath db_file_name = GetDBFileFullPath(file_name); | 379 const string16& database_name) { |
| 225 if (db_file_name.empty()) { | 380 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
| 226 resource_message_filter_->Send(new ViewMsg_DatabaseDeleteFileResponse( | 381 if (!HasAccessedOrigin(origin_identifier)) { |
| 227 message_id, SQLITE_IOERR_DELETE)); | 382 ReceivedBadMessage(ViewHostMsg_DatabaseClosed::ID); |
| 228 return; | 383 return; |
| 229 } | 384 } |
| 230 | 385 |
| 231 DeleteFileParams params; | 386 db_tracker_->DatabaseClosed(origin_identifier, database_name); |
| 232 params.db_dir = GetDBDir(); | 387 } |
| 233 params.file_name = db_file_name; | 388 |
| 234 params.sync_dir = sync_dir; | 389 void DatabaseDispatcherHost::OnDatabaseSizeChanged( |
| 235 resource_message_filter_->AddRef(); | 390 const string16& origin_identifier, |
| 236 ChromeThread::PostTask( | 391 const string16& database_name, |
| 237 ChromeThread::FILE, FROM_HERE, | 392 int64 database_size, |
| 238 NewRunnableFunction( | 393 int64 space_available) { |
| 239 DatabaseDeleteFile, params, message_id, kNumDeleteRetries, | 394 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
| 240 resource_message_filter_)); | 395 if (HasAccessedOrigin(origin_identifier)) { |
| 241 } | 396 ChromeThread::PostTask( |
| 242 | 397 ChromeThread::IO, FROM_HERE, |
| 243 void DatabaseDispatcherHost::OnDatabaseGetFileAttributes( | 398 NewRunnableMethod(this, |
| 244 const FilePath& file_name, int32 message_id) { | 399 &DatabaseDispatcherHost::SendMessage, |
| 245 FilePath db_file_name = GetDBFileFullPath(file_name); | 400 new ViewMsg_DatabaseUpdateSize( |
| 246 if (db_file_name.empty()) { | 401 origin_identifier, database_name, |
| 247 resource_message_filter_->Send( | 402 database_size, space_available))); |
| 248 new ViewMsg_DatabaseGetFileAttributesResponse(message_id, -1)); | 403 } |
| 249 return; | 404 } |
| 250 } | 405 |
| 251 | 406 void DatabaseDispatcherHost::AddAccessedOrigin( |
| 252 resource_message_filter_->AddRef(); | 407 const string16& origin_identifier) { |
| 253 ChromeThread::PostTask( | 408 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
| 254 ChromeThread::FILE, FROM_HERE, | 409 accessed_origins_.insert(origin_identifier); |
| 255 NewRunnableFunction( | 410 } |
| 256 DatabaseGetFileAttributes, db_file_name, message_id, | 411 |
| 257 resource_message_filter_)); | 412 bool DatabaseDispatcherHost::HasAccessedOrigin( |
| 258 } | 413 const string16& origin_identifier) { |
| 259 | 414 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
| 260 void DatabaseDispatcherHost::OnDatabaseGetFileSize( | 415 return (accessed_origins_.find(origin_identifier) != accessed_origins_.end()); |
| 261 const FilePath& file_name, int32 message_id) { | 416 } |
| 262 FilePath db_file_name = GetDBFileFullPath(file_name); | |
| 263 if (db_file_name.empty()) { | |
| 264 resource_message_filter_->Send(new ViewMsg_DatabaseGetFileSizeResponse( | |
| 265 message_id, 0)); | |
| 266 return; | |
| 267 } | |
| 268 | |
| 269 resource_message_filter_->AddRef(); | |
| 270 ChromeThread::PostTask( | |
| 271 ChromeThread::FILE, FROM_HERE, | |
| 272 NewRunnableFunction( | |
| 273 DatabaseGetFileSize, db_file_name, message_id, | |
| 274 resource_message_filter_)); | |
| 275 } | |
| OLD | NEW |