Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(527)

Side by Side Diff: chrome/browser/renderer_host/database_dispatcher_host.cc

Issue 5757002: Make DatabaseDispatcherHost be a message filter so that ResourceMessageFilter... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/renderer_host/database_dispatcher_host.h"
6
7 #include <string>
8
9 #include "base/string_util.h"
10 #include "base/thread.h"
11 #include "chrome/browser/browser_thread.h"
12 #include "chrome/browser/content_settings/host_content_settings_map.h"
13 #include "chrome/browser/net/chrome_url_request_context.h"
14 #include "chrome/browser/renderer_host/browser_render_process_host.h"
15 #include "chrome/common/render_messages.h"
16 #include "googleurl/src/gurl.h"
17 #include "third_party/sqlite/sqlite3.h"
18 #include "third_party/WebKit/WebKit/chromium/public/WebSecurityOrigin.h"
19 #include "webkit/database/database_util.h"
20 #include "webkit/database/vfs_backend.h"
21
22 #if defined(OS_POSIX)
23 #include "base/file_descriptor_posix.h"
24 #endif
25
26 using WebKit::WebSecurityOrigin;
27 using webkit_database::DatabaseTracker;
28 using webkit_database::DatabaseUtil;
29 using webkit_database::VfsBackend;
30
31 const int kNumDeleteRetries = 2;
32 const int kDelayDeleteRetryMs = 100;
33
34 DatabaseDispatcherHost::DatabaseDispatcherHost(
35 DatabaseTracker* db_tracker,
36 IPC::Message::Sender* sender,
37 HostContentSettingsMap *host_content_settings_map)
38 : db_tracker_(db_tracker),
39 message_sender_(sender),
40 process_handle_(0),
41 observer_added_(false),
42 shutdown_(false),
43 host_content_settings_map_(host_content_settings_map) {
44 DCHECK(db_tracker_);
45 DCHECK(message_sender_);
46 }
47
48 void DatabaseDispatcherHost::Init(base::ProcessHandle process_handle) {
49 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
50 DCHECK(!shutdown_);
51 DCHECK(!process_handle_);
52 DCHECK(process_handle);
53 process_handle_ = process_handle;
54 }
55
56 void DatabaseDispatcherHost::Shutdown() {
57 shutdown_ = true;
58 message_sender_ = NULL;
59 if (observer_added_) {
60 observer_added_ = false;
61 BrowserThread::PostTask(
62 BrowserThread::FILE, FROM_HERE,
63 NewRunnableMethod(this, &DatabaseDispatcherHost::RemoveObserver));
64 }
65 }
66
67 void DatabaseDispatcherHost::AddObserver() {
68 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
69 db_tracker_->AddObserver(this);
70 }
71
72 void DatabaseDispatcherHost::RemoveObserver() {
73 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
74
75 // If the renderer process died without closing all databases,
76 // then we need to manually close those connections
77 db_tracker_->CloseDatabases(database_connections_);
78 database_connections_.RemoveAllConnections();
79
80 db_tracker_->RemoveObserver(this);
81 }
82
83 bool DatabaseDispatcherHost::OnMessageReceived(
84 const IPC::Message& message, bool* message_was_ok) {
85 DCHECK(!shutdown_);
86 *message_was_ok = true;
87 bool handled = true;
88 IPC_BEGIN_MESSAGE_MAP_EX(DatabaseDispatcherHost, message, *message_was_ok)
89 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_DatabaseOpenFile,
90 OnDatabaseOpenFile)
91 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_DatabaseDeleteFile,
92 OnDatabaseDeleteFile)
93 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_DatabaseGetFileAttributes,
94 OnDatabaseGetFileAttributes)
95 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_DatabaseGetFileSize,
96 OnDatabaseGetFileSize)
97 IPC_MESSAGE_HANDLER(ViewHostMsg_DatabaseOpened, OnDatabaseOpened)
98 IPC_MESSAGE_HANDLER(ViewHostMsg_DatabaseModified, OnDatabaseModified)
99 IPC_MESSAGE_HANDLER(ViewHostMsg_DatabaseClosed, OnDatabaseClosed)
100 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_AllowDatabase, OnAllowDatabase)
101 IPC_MESSAGE_UNHANDLED(handled = false)
102 IPC_END_MESSAGE_MAP_EX()
103 return handled;
104 }
105
106 void DatabaseDispatcherHost::ReceivedBadMessage(uint32 msg_type) {
107 BrowserRenderProcessHost::BadMessageTerminateProcess(
108 msg_type, process_handle_);
109 }
110
111 void DatabaseDispatcherHost::Send(IPC::Message* message) {
112 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
113 if (!BrowserThread::PostTask(
114 BrowserThread::IO, FROM_HERE,
115 NewRunnableMethod(this,
116 &DatabaseDispatcherHost::Send,
117 message)))
118 delete message;
119 return;
120 }
121
122 if (!shutdown_ && message_sender_)
123 message_sender_->Send(message);
124 else
125 delete message;
126 }
127
128 DatabaseDispatcherHost::~DatabaseDispatcherHost() {}
129
130 void DatabaseDispatcherHost::OnDatabaseOpenFile(const string16& vfs_file_name,
131 int desired_flags,
132 IPC::Message* reply_msg) {
133 if (!observer_added_) {
134 observer_added_ = true;
135 BrowserThread::PostTask(
136 BrowserThread::FILE, FROM_HERE,
137 NewRunnableMethod(this, &DatabaseDispatcherHost::AddObserver));
138 }
139
140 BrowserThread::PostTask(
141 BrowserThread::FILE, FROM_HERE,
142 NewRunnableMethod(this,
143 &DatabaseDispatcherHost::DatabaseOpenFile,
144 vfs_file_name,
145 desired_flags,
146 reply_msg));
147 }
148
149 // Scheduled by the IO thread on the file thread.
150 // Opens the given database file, then schedules
151 // a task on the IO thread's message loop to send an IPC back to
152 // corresponding renderer process with the file handle.
153 void DatabaseDispatcherHost::DatabaseOpenFile(const string16& vfs_file_name,
154 int desired_flags,
155 IPC::Message* reply_msg) {
156 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
157 base::PlatformFile file_handle = base::kInvalidPlatformFileValue;
158 base::PlatformFile target_handle = base::kInvalidPlatformFileValue;
159 string16 origin_identifier;
160 string16 database_name;
161
162 // When in incognito mode, we want to make sure that all DB files are
163 // removed when the incognito profile goes away, so we add the
164 // SQLITE_OPEN_DELETEONCLOSE flag when opening all files, and keep
165 // open handles to them in the database tracker to make sure they're
166 // around for as long as needed.
167 if (vfs_file_name.empty()) {
168 VfsBackend::OpenTempFileInDirectory(db_tracker_->DatabaseDirectory(),
169 desired_flags, &file_handle);
170 } else if (DatabaseUtil::CrackVfsFileName(vfs_file_name, &origin_identifier,
171 &database_name, NULL) &&
172 !db_tracker_->IsDatabaseScheduledForDeletion(origin_identifier,
173 database_name)) {
174 FilePath db_file =
175 DatabaseUtil::GetFullFilePathForVfsFile(db_tracker_, vfs_file_name);
176 if (!db_file.empty()) {
177 if (db_tracker_->IsIncognitoProfile()) {
178 db_tracker_->GetIncognitoFileHandle(vfs_file_name, &file_handle);
179 if (file_handle == base::kInvalidPlatformFileValue) {
180 VfsBackend::OpenFile(db_file,
181 desired_flags | SQLITE_OPEN_DELETEONCLOSE,
182 &file_handle);
183 if (VfsBackend::FileTypeIsMainDB(desired_flags) ||
184 VfsBackend::FileTypeIsJournal(desired_flags))
185 db_tracker_->SaveIncognitoFileHandle(vfs_file_name, file_handle);
186 }
187 } else {
188 VfsBackend::OpenFile(db_file, desired_flags, &file_handle);
189 }
190 }
191 }
192
193 // Then we duplicate the file handle to make it useable in the renderer
194 // process. The original handle is closed, unless we saved it in the
195 // database tracker.
196 bool auto_close = !db_tracker_->HasSavedIncognitoFileHandle(vfs_file_name);
197 VfsBackend::GetFileHandleForProcess(process_handle_, file_handle,
198 &target_handle, auto_close);
199
200 ViewHostMsg_DatabaseOpenFile::WriteReplyParams(
201 reply_msg,
202 #if defined(OS_WIN)
203 target_handle
204 #elif defined(OS_POSIX)
205 base::FileDescriptor(target_handle, auto_close)
206 #endif
207 );
208 Send(reply_msg);
209 }
210
211 void DatabaseDispatcherHost::OnDatabaseDeleteFile(const string16& vfs_file_name,
212 const bool& sync_dir,
213 IPC::Message* reply_msg) {
214 BrowserThread::PostTask(
215 BrowserThread::FILE, FROM_HERE,
216 NewRunnableMethod(this,
217 &DatabaseDispatcherHost::DatabaseDeleteFile,
218 vfs_file_name,
219 sync_dir,
220 reply_msg,
221 kNumDeleteRetries));
222 }
223
224 // Scheduled by the IO thread on the file thread.
225 // Deletes the given database file, then schedules
226 // a task on the IO thread's message loop to send an IPC back to
227 // corresponding renderer process with the error code.
228 void DatabaseDispatcherHost::DatabaseDeleteFile(const string16& vfs_file_name,
229 bool sync_dir,
230 IPC::Message* reply_msg,
231 int reschedule_count) {
232 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
233
234 // Return an error if the file name is invalid or if the file could not
235 // be deleted after kNumDeleteRetries attempts.
236 int error_code = SQLITE_IOERR_DELETE;
237 FilePath db_file =
238 DatabaseUtil::GetFullFilePathForVfsFile(db_tracker_, vfs_file_name);
239 if (!db_file.empty()) {
240 // In order to delete a journal file in incognito mode, we only need to
241 // close the open handle to it that's stored in the database tracker.
242 if (db_tracker_->IsIncognitoProfile()) {
243 if (db_tracker_->CloseIncognitoFileHandle(vfs_file_name))
244 error_code = SQLITE_OK;
245 } else {
246 error_code = VfsBackend::DeleteFile(db_file, sync_dir);
247 }
248
249 if ((error_code == SQLITE_IOERR_DELETE) && reschedule_count) {
250 // If the file could not be deleted, try again.
251 BrowserThread::PostDelayedTask(
252 BrowserThread::FILE, FROM_HERE,
253 NewRunnableMethod(this,
254 &DatabaseDispatcherHost::DatabaseDeleteFile,
255 vfs_file_name,
256 sync_dir,
257 reply_msg,
258 reschedule_count - 1),
259 kDelayDeleteRetryMs);
260 return;
261 }
262 }
263
264 ViewHostMsg_DatabaseDeleteFile::WriteReplyParams(reply_msg, error_code);
265 Send(reply_msg);
266 }
267
268 void DatabaseDispatcherHost::OnDatabaseGetFileAttributes(
269 const string16& vfs_file_name,
270 IPC::Message* reply_msg) {
271 BrowserThread::PostTask(
272 BrowserThread::FILE, FROM_HERE,
273 NewRunnableMethod(this,
274 &DatabaseDispatcherHost::DatabaseGetFileAttributes,
275 vfs_file_name,
276 reply_msg));
277 }
278
279 // Scheduled by the IO thread on the file thread.
280 // Gets the attributes of the given database file, then schedules
281 // a task on the IO thread's message loop to send an IPC back to
282 // corresponding renderer process.
283 void DatabaseDispatcherHost::DatabaseGetFileAttributes(
284 const string16& vfs_file_name,
285 IPC::Message* reply_msg) {
286 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
287 int32 attributes = -1;
288 FilePath db_file =
289 DatabaseUtil::GetFullFilePathForVfsFile(db_tracker_, vfs_file_name);
290 if (!db_file.empty())
291 attributes = VfsBackend::GetFileAttributes(db_file);
292
293 ViewHostMsg_DatabaseGetFileAttributes::WriteReplyParams(
294 reply_msg, attributes);
295 Send(reply_msg);
296 }
297
298 void DatabaseDispatcherHost::OnDatabaseGetFileSize(
299 const string16& vfs_file_name, IPC::Message* reply_msg) {
300 BrowserThread::PostTask(
301 BrowserThread::FILE, FROM_HERE,
302 NewRunnableMethod(this,
303 &DatabaseDispatcherHost::DatabaseGetFileSize,
304 vfs_file_name,
305 reply_msg));
306 }
307
308 // Scheduled by the IO thread on the file thread.
309 // Gets the size of the given file, then schedules a task
310 // on the IO thread's message loop to send an IPC back to
311 // the corresponding renderer process.
312 void DatabaseDispatcherHost::DatabaseGetFileSize(const string16& vfs_file_name,
313 IPC::Message* reply_msg) {
314 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
315 int64 size = 0;
316 FilePath db_file =
317 DatabaseUtil::GetFullFilePathForVfsFile(db_tracker_, vfs_file_name);
318 if (!db_file.empty())
319 size = VfsBackend::GetFileSize(db_file);
320
321 ViewHostMsg_DatabaseGetFileSize::WriteReplyParams(reply_msg, size);
322 Send(reply_msg);
323 }
324
325 void DatabaseDispatcherHost::OnDatabaseOpened(const string16& origin_identifier,
326 const string16& database_name,
327 const string16& description,
328 int64 estimated_size) {
329 BrowserThread::PostTask(
330 BrowserThread::FILE, FROM_HERE,
331 NewRunnableMethod(this,
332 &DatabaseDispatcherHost::DatabaseOpened,
333 origin_identifier,
334 database_name,
335 description,
336 estimated_size));
337 }
338
339 void DatabaseDispatcherHost::DatabaseOpened(const string16& origin_identifier,
340 const string16& database_name,
341 const string16& description,
342 int64 estimated_size) {
343 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
344 int64 database_size = 0;
345 int64 space_available = 0;
346 database_connections_.AddConnection(origin_identifier, database_name);
347 db_tracker_->DatabaseOpened(origin_identifier, database_name, description,
348 estimated_size, &database_size, &space_available);
349 Send(new ViewMsg_DatabaseUpdateSize(origin_identifier, database_name,
350 database_size, space_available));
351 }
352
353 void DatabaseDispatcherHost::OnDatabaseModified(
354 const string16& origin_identifier,
355 const string16& database_name) {
356 BrowserThread::PostTask(
357 BrowserThread::FILE, FROM_HERE,
358 NewRunnableMethod(this,
359 &DatabaseDispatcherHost::DatabaseModified,
360 origin_identifier,
361 database_name));
362 }
363
364 void DatabaseDispatcherHost::DatabaseModified(const string16& origin_identifier,
365 const string16& database_name) {
366 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
367 if (!database_connections_.IsDatabaseOpened(
368 origin_identifier, database_name)) {
369 ReceivedBadMessage(ViewHostMsg_DatabaseModified::ID);
370 return;
371 }
372
373 db_tracker_->DatabaseModified(origin_identifier, database_name);
374 }
375
376 void DatabaseDispatcherHost::OnDatabaseClosed(const string16& origin_identifier,
377 const string16& database_name) {
378 BrowserThread::PostTask(
379 BrowserThread::FILE, FROM_HERE,
380 NewRunnableMethod(this,
381 &DatabaseDispatcherHost::DatabaseClosed,
382 origin_identifier,
383 database_name));
384 }
385
386 void DatabaseDispatcherHost::OnAllowDatabase(const std::string& origin_url,
387 const string16& name,
388 const string16& display_name,
389 unsigned long estimated_size,
390 IPC::Message* reply_msg) {
391 GURL url = GURL(origin_url);
392 ContentSetting content_setting =
393 host_content_settings_map_->GetContentSetting(
394 url, CONTENT_SETTINGS_TYPE_COOKIES, "");
395 AllowDatabaseResponse(reply_msg, content_setting);
396 }
397
398 void DatabaseDispatcherHost::AllowDatabaseResponse(
399 IPC::Message* reply_msg, ContentSetting content_setting) {
400 DCHECK((content_setting == CONTENT_SETTING_ALLOW) ||
401 (content_setting == CONTENT_SETTING_BLOCK) ||
402 (content_setting == CONTENT_SETTING_SESSION_ONLY));
403 ViewHostMsg_AllowDatabase::WriteReplyParams(
404 reply_msg, content_setting != CONTENT_SETTING_BLOCK);
405 Send(reply_msg);
406 }
407
408 void DatabaseDispatcherHost::DatabaseClosed(const string16& origin_identifier,
409 const string16& database_name) {
410 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
411 if (!database_connections_.IsDatabaseOpened(
412 origin_identifier, database_name)) {
413 ReceivedBadMessage(ViewHostMsg_DatabaseClosed::ID);
414 return;
415 }
416
417 db_tracker_->DatabaseClosed(origin_identifier, database_name);
418 database_connections_.RemoveConnection(origin_identifier, database_name);
419 }
420
421 void DatabaseDispatcherHost::OnDatabaseSizeChanged(
422 const string16& origin_identifier,
423 const string16& database_name,
424 int64 database_size,
425 int64 space_available) {
426 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
427 if (database_connections_.IsOriginUsed(origin_identifier)) {
428 Send(new ViewMsg_DatabaseUpdateSize(origin_identifier, database_name,
429 database_size, space_available));
430 }
431 }
432
433 void DatabaseDispatcherHost::OnDatabaseScheduledForDeletion(
434 const string16& origin_identifier,
435 const string16& database_name) {
436 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
437 Send(new ViewMsg_DatabaseCloseImmediately(origin_identifier, database_name));
438 }
OLDNEW
« no previous file with comments | « chrome/browser/renderer_host/database_dispatcher_host.h ('k') | chrome/browser/renderer_host/database_message_filter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698