| 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 "content/browser/renderer_host/database_message_filter.h" | 5 #include "content/browser/renderer_host/database_message_filter.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
| 10 #include "base/threading/thread.h" | 10 #include "base/threading/thread.h" |
| 11 #include "content/browser/user_metrics.h" | 11 #include "content/browser/user_metrics.h" |
| 12 #include "content/common/database_messages.h" | 12 #include "content/common/database_messages.h" |
| 13 #include "content/common/result_codes.h" | 13 #include "content/common/result_codes.h" |
| 14 #include "googleurl/src/gurl.h" | 14 #include "googleurl/src/gurl.h" |
| 15 #include "third_party/sqlite/sqlite3.h" | 15 #include "third_party/sqlite/sqlite3.h" |
| 16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h" | 16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h" |
| 17 #include "webkit/database/database_util.h" | 17 #include "webkit/database/database_util.h" |
| 18 #include "webkit/database/vfs_backend.h" | 18 #include "webkit/database/vfs_backend.h" |
| 19 #include "webkit/quota/quota_manager.h" |
| 19 | 20 |
| 20 #if defined(OS_POSIX) | 21 #if defined(OS_POSIX) |
| 21 #include "base/file_descriptor_posix.h" | 22 #include "base/file_descriptor_posix.h" |
| 22 #endif | 23 #endif |
| 23 | 24 |
| 25 using quota::QuotaManager; |
| 26 using quota::QuotaManagerProxy; |
| 27 using quota::QuotaStatusCode; |
| 24 using WebKit::WebSecurityOrigin; | 28 using WebKit::WebSecurityOrigin; |
| 25 using webkit_database::DatabaseTracker; | 29 using webkit_database::DatabaseTracker; |
| 26 using webkit_database::DatabaseUtil; | 30 using webkit_database::DatabaseUtil; |
| 27 using webkit_database::VfsBackend; | 31 using webkit_database::VfsBackend; |
| 28 | 32 |
| 33 namespace { |
| 34 |
| 35 class MyGetUsageAndQuotaCallback |
| 36 : public QuotaManager::GetUsageAndQuotaCallback { |
| 37 public: |
| 38 MyGetUsageAndQuotaCallback( |
| 39 DatabaseMessageFilter* sender, IPC::Message* reply_msg) |
| 40 : sender_(sender), reply_msg_(reply_msg) {} |
| 41 |
| 42 virtual void RunWithParams( |
| 43 const Tuple3<QuotaStatusCode, int64, int64>& params) { |
| 44 Run(params.a, params.b, params.c); |
| 45 } |
| 46 |
| 47 void Run(QuotaStatusCode status, int64 usage, int64 quota) { |
| 48 int64 available = 0; |
| 49 if ((status == quota::kQuotaStatusOk) && (usage < quota)) |
| 50 available = quota - usage; |
| 51 DatabaseHostMsg_GetSpaceAvailable::WriteReplyParams( |
| 52 reply_msg_.get(), available); |
| 53 sender_->Send(reply_msg_.release()); |
| 54 } |
| 55 |
| 56 private: |
| 57 scoped_refptr<DatabaseMessageFilter> sender_; |
| 58 scoped_ptr<IPC::Message> reply_msg_; |
| 59 }; |
| 60 |
| 29 const int kNumDeleteRetries = 2; | 61 const int kNumDeleteRetries = 2; |
| 30 const int kDelayDeleteRetryMs = 100; | 62 const int kDelayDeleteRetryMs = 100; |
| 31 | 63 |
| 64 } // namespace |
| 65 |
| 32 DatabaseMessageFilter::DatabaseMessageFilter( | 66 DatabaseMessageFilter::DatabaseMessageFilter( |
| 33 webkit_database::DatabaseTracker* db_tracker) | 67 webkit_database::DatabaseTracker* db_tracker) |
| 34 : db_tracker_(db_tracker), | 68 : db_tracker_(db_tracker), |
| 35 observer_added_(false) { | 69 observer_added_(false) { |
| 36 DCHECK(db_tracker_); | 70 DCHECK(db_tracker_); |
| 37 } | 71 } |
| 38 | 72 |
| 39 void DatabaseMessageFilter::OnChannelClosing() { | 73 void DatabaseMessageFilter::OnChannelClosing() { |
| 40 BrowserMessageFilter::OnChannelClosing(); | 74 BrowserMessageFilter::OnChannelClosing(); |
| 41 if (observer_added_) { | 75 if (observer_added_) { |
| 42 observer_added_ = false; | 76 observer_added_ = false; |
| 43 BrowserThread::PostTask( | 77 BrowserThread::PostTask( |
| 44 BrowserThread::FILE, FROM_HERE, | 78 BrowserThread::FILE, FROM_HERE, |
| 45 NewRunnableMethod(this, &DatabaseMessageFilter::RemoveObserver)); | 79 NewRunnableMethod(this, &DatabaseMessageFilter::RemoveObserver)); |
| 46 } | 80 } |
| 47 } | 81 } |
| 48 | 82 |
| 49 void DatabaseMessageFilter::AddObserver() { | 83 void DatabaseMessageFilter::AddObserver() { |
| 50 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 84 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 51 db_tracker_->AddObserver(this); | 85 db_tracker_->AddObserver(this); |
| 52 } | 86 } |
| 53 | 87 |
| 54 void DatabaseMessageFilter::RemoveObserver() { | 88 void DatabaseMessageFilter::RemoveObserver() { |
| 55 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 89 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 90 db_tracker_->RemoveObserver(this); |
| 56 | 91 |
| 57 // If the renderer process died without closing all databases, | 92 // If the renderer process died without closing all databases, |
| 58 // then we need to manually close those connections | 93 // then we need to manually close those connections |
| 59 db_tracker_->CloseDatabases(database_connections_); | 94 db_tracker_->CloseDatabases(database_connections_); |
| 60 database_connections_.RemoveAllConnections(); | 95 database_connections_.RemoveAllConnections(); |
| 61 | |
| 62 db_tracker_->RemoveObserver(this); | |
| 63 } | 96 } |
| 64 | 97 |
| 65 void DatabaseMessageFilter::OverrideThreadForMessage( | 98 void DatabaseMessageFilter::OverrideThreadForMessage( |
| 66 const IPC::Message& message, | 99 const IPC::Message& message, |
| 67 BrowserThread::ID* thread) { | 100 BrowserThread::ID* thread) { |
| 68 if (IPC_MESSAGE_CLASS(message) == DatabaseMsgStart) | 101 if (message.type() == DatabaseHostMsg_GetSpaceAvailable::ID) |
| 102 *thread = BrowserThread::IO; |
| 103 else if (IPC_MESSAGE_CLASS(message) == DatabaseMsgStart) |
| 69 *thread = BrowserThread::FILE; | 104 *thread = BrowserThread::FILE; |
| 70 | 105 |
| 71 if (message.type() == DatabaseHostMsg_OpenFile::ID && !observer_added_) { | 106 if (message.type() == DatabaseHostMsg_Opened::ID && !observer_added_) { |
| 72 observer_added_ = true; | 107 observer_added_ = true; |
| 73 BrowserThread::PostTask( | 108 BrowserThread::PostTask( |
| 74 BrowserThread::FILE, FROM_HERE, | 109 BrowserThread::FILE, FROM_HERE, |
| 75 NewRunnableMethod(this, &DatabaseMessageFilter::AddObserver)); | 110 NewRunnableMethod(this, &DatabaseMessageFilter::AddObserver)); |
| 76 } | 111 } |
| 77 } | 112 } |
| 78 | 113 |
| 79 bool DatabaseMessageFilter::OnMessageReceived( | 114 bool DatabaseMessageFilter::OnMessageReceived( |
| 80 const IPC::Message& message, | 115 const IPC::Message& message, |
| 81 bool* message_was_ok) { | 116 bool* message_was_ok) { |
| 82 bool handled = true; | 117 bool handled = true; |
| 83 IPC_BEGIN_MESSAGE_MAP_EX(DatabaseMessageFilter, message, *message_was_ok) | 118 IPC_BEGIN_MESSAGE_MAP_EX(DatabaseMessageFilter, message, *message_was_ok) |
| 84 IPC_MESSAGE_HANDLER_DELAY_REPLY(DatabaseHostMsg_OpenFile, | 119 IPC_MESSAGE_HANDLER_DELAY_REPLY(DatabaseHostMsg_OpenFile, |
| 85 OnDatabaseOpenFile) | 120 OnDatabaseOpenFile) |
| 86 IPC_MESSAGE_HANDLER_DELAY_REPLY(DatabaseHostMsg_DeleteFile, | 121 IPC_MESSAGE_HANDLER_DELAY_REPLY(DatabaseHostMsg_DeleteFile, |
| 87 OnDatabaseDeleteFile) | 122 OnDatabaseDeleteFile) |
| 88 IPC_MESSAGE_HANDLER_DELAY_REPLY(DatabaseHostMsg_GetFileAttributes, | 123 IPC_MESSAGE_HANDLER_DELAY_REPLY(DatabaseHostMsg_GetFileAttributes, |
| 89 OnDatabaseGetFileAttributes) | 124 OnDatabaseGetFileAttributes) |
| 90 IPC_MESSAGE_HANDLER_DELAY_REPLY(DatabaseHostMsg_GetFileSize, | 125 IPC_MESSAGE_HANDLER_DELAY_REPLY(DatabaseHostMsg_GetFileSize, |
| 91 OnDatabaseGetFileSize) | 126 OnDatabaseGetFileSize) |
| 127 IPC_MESSAGE_HANDLER_DELAY_REPLY(DatabaseHostMsg_GetSpaceAvailable, |
| 128 OnDatabaseGetSpaceAvailable) |
| 92 IPC_MESSAGE_HANDLER(DatabaseHostMsg_Opened, OnDatabaseOpened) | 129 IPC_MESSAGE_HANDLER(DatabaseHostMsg_Opened, OnDatabaseOpened) |
| 93 IPC_MESSAGE_HANDLER(DatabaseHostMsg_Modified, OnDatabaseModified) | 130 IPC_MESSAGE_HANDLER(DatabaseHostMsg_Modified, OnDatabaseModified) |
| 94 IPC_MESSAGE_HANDLER(DatabaseHostMsg_Closed, OnDatabaseClosed) | 131 IPC_MESSAGE_HANDLER(DatabaseHostMsg_Closed, OnDatabaseClosed) |
| 95 IPC_MESSAGE_UNHANDLED(handled = false) | 132 IPC_MESSAGE_UNHANDLED(handled = false) |
| 96 IPC_END_MESSAGE_MAP_EX() | 133 IPC_END_MESSAGE_MAP_EX() |
| 97 return handled; | 134 return handled; |
| 98 } | 135 } |
| 99 | 136 |
| 100 DatabaseMessageFilter::~DatabaseMessageFilter() { | 137 DatabaseMessageFilter::~DatabaseMessageFilter() { |
| 101 } | 138 } |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 213 DatabaseUtil::GetFullFilePathForVfsFile(db_tracker_, vfs_file_name); | 250 DatabaseUtil::GetFullFilePathForVfsFile(db_tracker_, vfs_file_name); |
| 214 if (!db_file.empty()) | 251 if (!db_file.empty()) |
| 215 attributes = VfsBackend::GetFileAttributes(db_file); | 252 attributes = VfsBackend::GetFileAttributes(db_file); |
| 216 | 253 |
| 217 DatabaseHostMsg_GetFileAttributes::WriteReplyParams( | 254 DatabaseHostMsg_GetFileAttributes::WriteReplyParams( |
| 218 reply_msg, attributes); | 255 reply_msg, attributes); |
| 219 Send(reply_msg); | 256 Send(reply_msg); |
| 220 } | 257 } |
| 221 | 258 |
| 222 void DatabaseMessageFilter::OnDatabaseGetFileSize( | 259 void DatabaseMessageFilter::OnDatabaseGetFileSize( |
| 223 const string16& vfs_file_name, IPC::Message* reply_msg) { | 260 const string16& vfs_file_name, IPC::Message* reply_msg) { |
| 224 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 261 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 225 int64 size = 0; | 262 int64 size = 0; |
| 226 FilePath db_file = | 263 FilePath db_file = |
| 227 DatabaseUtil::GetFullFilePathForVfsFile(db_tracker_, vfs_file_name); | 264 DatabaseUtil::GetFullFilePathForVfsFile(db_tracker_, vfs_file_name); |
| 228 if (!db_file.empty()) | 265 if (!db_file.empty()) |
| 229 size = VfsBackend::GetFileSize(db_file); | 266 size = VfsBackend::GetFileSize(db_file); |
| 230 | 267 |
| 231 DatabaseHostMsg_GetFileSize::WriteReplyParams(reply_msg, size); | 268 DatabaseHostMsg_GetFileSize::WriteReplyParams(reply_msg, size); |
| 232 Send(reply_msg); | 269 Send(reply_msg); |
| 233 } | 270 } |
| 234 | 271 |
| 272 void DatabaseMessageFilter::OnDatabaseGetSpaceAvailable( |
| 273 const string16& origin_identifier, IPC::Message* reply_msg) { |
| 274 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 275 DCHECK(db_tracker_->quota_manager_proxy()); |
| 276 |
| 277 QuotaManager* quota_manager = |
| 278 db_tracker_->quota_manager_proxy()->quota_manager(); |
| 279 if (!quota_manager) { |
| 280 NOTREACHED(); // The system is shutting down, messages are unexpected. |
| 281 DatabaseHostMsg_GetSpaceAvailable::WriteReplyParams( |
| 282 reply_msg, static_cast<int64>(0)); |
| 283 Send(reply_msg); |
| 284 return; |
| 285 } |
| 286 |
| 287 quota_manager->GetUsageAndQuota( |
| 288 DatabaseUtil::GetOriginFromIdentifier(origin_identifier), |
| 289 quota::kStorageTypeTemporary, |
| 290 new MyGetUsageAndQuotaCallback(this, reply_msg)); |
| 291 } |
| 292 |
| 235 void DatabaseMessageFilter::OnDatabaseOpened(const string16& origin_identifier, | 293 void DatabaseMessageFilter::OnDatabaseOpened(const string16& origin_identifier, |
| 236 const string16& database_name, | 294 const string16& database_name, |
| 237 const string16& description, | 295 const string16& description, |
| 238 int64 estimated_size) { | 296 int64 estimated_size) { |
| 239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 297 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 240 int64 database_size = 0; | 298 int64 database_size = 0; |
| 241 int64 space_available = 0; | 299 int64 space_available_not_used = 0; |
| 300 db_tracker_->DatabaseOpened(origin_identifier, database_name, description, |
| 301 estimated_size, &database_size, |
| 302 &space_available_not_used); |
| 242 database_connections_.AddConnection(origin_identifier, database_name); | 303 database_connections_.AddConnection(origin_identifier, database_name); |
| 243 db_tracker_->DatabaseOpened(origin_identifier, database_name, description, | |
| 244 estimated_size, &database_size, &space_available); | |
| 245 Send(new DatabaseMsg_UpdateSize(origin_identifier, database_name, | 304 Send(new DatabaseMsg_UpdateSize(origin_identifier, database_name, |
| 246 database_size, space_available)); | 305 database_size)); |
| 247 } | 306 } |
| 248 | 307 |
| 249 void DatabaseMessageFilter::OnDatabaseModified( | 308 void DatabaseMessageFilter::OnDatabaseModified( |
| 250 const string16& origin_identifier, | 309 const string16& origin_identifier, |
| 251 const string16& database_name) { | 310 const string16& database_name) { |
| 252 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 311 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 253 if (!database_connections_.IsDatabaseOpened( | 312 if (!database_connections_.IsDatabaseOpened( |
| 254 origin_identifier, database_name)) { | 313 origin_identifier, database_name)) { |
| 255 UserMetrics::RecordAction(UserMetricsAction("BadMessageTerminate_DBMF")); | 314 UserMetrics::RecordAction(UserMetricsAction("BadMessageTerminate_DBMF")); |
| 256 BadMessageReceived(); | 315 BadMessageReceived(); |
| 257 return; | 316 return; |
| 258 } | 317 } |
| 259 | 318 |
| 260 db_tracker_->DatabaseModified(origin_identifier, database_name); | 319 db_tracker_->DatabaseModified(origin_identifier, database_name); |
| 261 } | 320 } |
| 262 | 321 |
| 263 void DatabaseMessageFilter::OnDatabaseClosed(const string16& origin_identifier, | 322 void DatabaseMessageFilter::OnDatabaseClosed(const string16& origin_identifier, |
| 264 const string16& database_name) { | 323 const string16& database_name) { |
| 265 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 324 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 266 if (!database_connections_.IsDatabaseOpened( | 325 if (!database_connections_.IsDatabaseOpened( |
| 267 origin_identifier, database_name)) { | 326 origin_identifier, database_name)) { |
| 268 UserMetrics::RecordAction(UserMetricsAction("BadMessageTerminate_DBMF")); | 327 UserMetrics::RecordAction(UserMetricsAction("BadMessageTerminate_DBMF")); |
| 269 BadMessageReceived(); | 328 BadMessageReceived(); |
| 270 return; | 329 return; |
| 271 } | 330 } |
| 272 | 331 |
| 332 database_connections_.RemoveConnection(origin_identifier, database_name); |
| 273 db_tracker_->DatabaseClosed(origin_identifier, database_name); | 333 db_tracker_->DatabaseClosed(origin_identifier, database_name); |
| 274 database_connections_.RemoveConnection(origin_identifier, database_name); | |
| 275 } | 334 } |
| 276 | 335 |
| 277 void DatabaseMessageFilter::OnDatabaseSizeChanged( | 336 void DatabaseMessageFilter::OnDatabaseSizeChanged( |
| 278 const string16& origin_identifier, | 337 const string16& origin_identifier, |
| 279 const string16& database_name, | 338 const string16& database_name, |
| 280 int64 database_size, | 339 int64 database_size, |
| 281 int64 space_available) { | 340 int64 space_available_not_used) { |
| 282 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 341 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 283 if (database_connections_.IsOriginUsed(origin_identifier)) { | 342 if (database_connections_.IsOriginUsed(origin_identifier)) { |
| 284 Send(new DatabaseMsg_UpdateSize(origin_identifier, database_name, | 343 Send(new DatabaseMsg_UpdateSize(origin_identifier, database_name, |
| 285 database_size, space_available)); | 344 database_size)); |
| 286 } | 345 } |
| 287 } | 346 } |
| 288 | 347 |
| 289 void DatabaseMessageFilter::OnDatabaseScheduledForDeletion( | 348 void DatabaseMessageFilter::OnDatabaseScheduledForDeletion( |
| 290 const string16& origin_identifier, | 349 const string16& origin_identifier, |
| 291 const string16& database_name) { | 350 const string16& database_name) { |
| 292 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 351 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 293 Send(new DatabaseMsg_CloseImmediately(origin_identifier, database_name)); | 352 Send(new DatabaseMsg_CloseImmediately(origin_identifier, database_name)); |
| 294 } | 353 } |
| OLD | NEW |