Skip to content

Commit

Permalink
Changing the file naming scheme. Creating a directory for each origin,
Browse files Browse the repository at this point in the history
and naming files according to the row ID of the respective DB in the
tracker database. Also, fixing a bug: caching the renderer process
handle in DatabaseDispatcherHost after it was set in
ResourceMessageFilter.

TEST=none
BUG=none

Review URL: http://codereview.chromium.org/385051

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@31874 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
dumi@chromium.org committed Nov 13, 2009
1 parent dad1e3b commit 3c5ed2c
Show file tree
Hide file tree
Showing 16 changed files with 283 additions and 126 deletions.
94 changes: 37 additions & 57 deletions chrome/browser/renderer_host/database_dispatcher_host.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,27 +20,36 @@
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/renderer_host/browser_render_process_host.h"
#include "chrome/common/render_messages.h"
#include "webkit/database/database_util.h"
#include "webkit/database/vfs_backend.h"

using webkit_database::DatabaseTracker;
using webkit_database::DatabaseUtil;
using webkit_database::VfsBackend;

const int kNumDeleteRetries = 2;
const int kDelayDeleteRetryMs = 100;

DatabaseDispatcherHost::DatabaseDispatcherHost(
DatabaseTracker* db_tracker,
IPC::Message::Sender* message_sender,
base::ProcessHandle process_handle)
IPC::Message::Sender* message_sender)
: db_tracker_(db_tracker),
message_sender_(message_sender),
process_handle_(process_handle),
process_handle_(0),
observer_added_(false),
shutdown_(false) {
DCHECK(db_tracker_);
DCHECK(message_sender_);
}

void DatabaseDispatcherHost::Init(base::ProcessHandle process_handle) {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
DCHECK(!shutdown_);
DCHECK(!process_handle_);
DCHECK(process_handle);
process_handle_ = process_handle;
}

void DatabaseDispatcherHost::Shutdown() {
shutdown_ = true;
message_sender_ = NULL;
Expand All @@ -61,47 +70,14 @@ void DatabaseDispatcherHost::RemoveObserver() {
db_tracker_->RemoveObserver(this);
}

FilePath DatabaseDispatcherHost::GetDBFileFullPath(
// TODO(dumi): remove this function when switching IPC parameters
// from FilePath to string16
FilePath DatabaseDispatcherHost::GetFullFilePathForVfsFile(
const FilePath& vfs_file_name) {
// 'vfs_file_name' can be one of 3 things:
// 1. Empty string: It means the VFS wants to open a temp file. In this case
// we need to return the path to the directory that stores all databases.
// 2. origin_identifier/database_name: In this case, we need to extract
// 'origin_identifier' and 'database_name' and pass them to
// DatabaseTracker::GetFullDBFilePath().
// 3. origin_identifier/database_name-suffix: '-suffix' could be '-journal',
// for example. In this case, we need to extract 'origin_identifier' and
// 'database_name-suffix' and pass them to
// DatabaseTracker::GetFullDBFilePath(). 'database_name-suffix' is not
// a database name as expected by DatabaseTracker::GetFullDBFilePath(),
// but due to its implementation, it's OK to pass in 'database_name-suffix'
// too.
//
// We also check that the given string doesn't contain invalid characters
// that would result in a DB file stored outside of the directory where
// all DB files are supposed to be stored.
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
if (vfs_file_name.empty())
return db_tracker_->DatabaseDirectory();

std::wstring str = vfs_file_name.ToWStringHack();
size_t slashIndex = str.find('/');
if (slashIndex == std::wstring::npos)
return FilePath(); // incorrect format
std::wstring origin_identifier = str.substr(0, slashIndex);
std::wstring database_name =
str.substr(slashIndex + 1, str.length() - slashIndex);
if ((origin_identifier.find('\\') != std::wstring::npos) ||
(origin_identifier.find('/') != std::wstring::npos) ||
(origin_identifier.find(':') != std::wstring::npos) ||
(database_name.find('\\') != std::wstring::npos) ||
(database_name.find('/') != std::wstring::npos) ||
(database_name.find(':') != std::wstring::npos)) {
return FilePath();
}

return db_tracker_->GetFullDBFilePath(
WideToUTF16(origin_identifier), WideToUTF16(database_name));
DCHECK(!vfs_file_name.empty());
return DatabaseUtil::GetFullFilePathForVfsFile(
db_tracker_, WideToUTF16(vfs_file_name.ToWStringHack()));
}

bool DatabaseDispatcherHost::OnMessageReceived(
Expand Down Expand Up @@ -180,11 +156,16 @@ void DatabaseDispatcherHost::DatabaseOpenFile(const FilePath& vfs_file_name,
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
base::PlatformFile target_handle = base::kInvalidPlatformFileValue;
base::PlatformFile target_dir_handle = base::kInvalidPlatformFileValue;
FilePath db_file_name = GetDBFileFullPath(vfs_file_name);
if (!db_file_name.empty()) {
FilePath db_dir = db_tracker_->DatabaseDirectory();
VfsBackend::OpenFile(db_file_name, db_dir, desired_flags,
process_handle_, &target_handle, &target_dir_handle);
if (vfs_file_name.empty()) {
VfsBackend::OpenTempFileInDirectory(db_tracker_->DatabaseDirectory(),
desired_flags, process_handle_,
&target_handle, &target_dir_handle);
} else {
FilePath db_file = GetFullFilePathForVfsFile(vfs_file_name);
if (!db_file.empty()) {
VfsBackend::OpenFile(db_file, desired_flags, process_handle_,
&target_handle, &target_dir_handle);
}
}

ViewMsg_DatabaseOpenFileResponse_Params response_params;
Expand Down Expand Up @@ -223,10 +204,9 @@ void DatabaseDispatcherHost::DatabaseDeleteFile(const FilePath& vfs_file_name,
// Return an error if the file name is invalid or if the file could not
// be deleted after kNumDeleteRetries attempts.
int error_code = SQLITE_IOERR_DELETE;
FilePath db_file_name = GetDBFileFullPath(vfs_file_name);
if (!db_file_name.empty()) {
FilePath db_dir = db_tracker_->DatabaseDirectory();
error_code = VfsBackend::DeleteFile(db_file_name, db_dir, sync_dir);
FilePath db_file = GetFullFilePathForVfsFile(vfs_file_name);
if (!db_file.empty()) {
error_code = VfsBackend::DeleteFile(db_file, sync_dir);
if ((error_code == SQLITE_IOERR_DELETE) && reschedule_count) {
// If the file could not be deleted, try again.
ChromeThread::PostDelayedTask(
Expand Down Expand Up @@ -270,9 +250,9 @@ void DatabaseDispatcherHost::DatabaseGetFileAttributes(
int32 message_id) {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
int32 attributes = -1;
FilePath db_file_name = GetDBFileFullPath(vfs_file_name);
if (!db_file_name.empty())
attributes = VfsBackend::GetFileAttributes(db_file_name);
FilePath db_file = GetFullFilePathForVfsFile(vfs_file_name);
if (!db_file.empty())
attributes = VfsBackend::GetFileAttributes(db_file);
ChromeThread::PostTask(
ChromeThread::IO, FROM_HERE,
NewRunnableMethod(this,
Expand All @@ -299,9 +279,9 @@ void DatabaseDispatcherHost::DatabaseGetFileSize(const FilePath& vfs_file_name,
int32 message_id) {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
int64 size = 0;
FilePath db_file_name = GetDBFileFullPath(vfs_file_name);
if (!db_file_name.empty())
size = VfsBackend::GetFileSize(db_file_name);
FilePath db_file = GetFullFilePathForVfsFile(vfs_file_name);
if (!db_file.empty())
size = VfsBackend::GetFileSize(db_file);
ChromeThread::PostTask(
ChromeThread::IO, FROM_HERE,
NewRunnableMethod(this,
Expand Down
8 changes: 4 additions & 4 deletions chrome/browser/renderer_host/database_dispatcher_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ class DatabaseDispatcherHost
public webkit_database::DatabaseTracker::Observer {
public:
DatabaseDispatcherHost(webkit_database::DatabaseTracker* db_tracker,
IPC::Message::Sender* message_sender,
base::ProcessHandle process_handle);
IPC::Message::Sender* message_sender);
void Init(base::ProcessHandle process_handle);
void Shutdown();

bool OnMessageReceived(const IPC::Message& message, bool* message_was_ok);
Expand Down Expand Up @@ -55,7 +55,7 @@ class DatabaseDispatcherHost
private:
void AddObserver();
void RemoveObserver();
FilePath GetDBFileFullPath(const FilePath& vfs_file_name);
FilePath GetFullFilePathForVfsFile(const FilePath& vfs_file_name);

void ReceivedBadMessage(uint16 msg_type);
void SendMessage(IPC::Message* message);
Expand Down Expand Up @@ -93,7 +93,7 @@ class DatabaseDispatcherHost
IPC::Message::Sender* message_sender_;

// The handle of this process.
const base::ProcessHandle process_handle_;
base::ProcessHandle process_handle_;

// True if and only if this instance was added as an observer
// to DatabaseTracker.
Expand Down
4 changes: 2 additions & 2 deletions chrome/browser/renderer_host/resource_message_filter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,7 @@ ResourceMessageFilter::ResourceMessageFilter(
new DOMStorageDispatcherHost(this, profile->GetWebKitContext(),
resource_dispatcher_host->webkit_thread()))),
ALLOW_THIS_IN_INITIALIZER_LIST(db_dispatcher_host_(
new DatabaseDispatcherHost(profile->GetDatabaseTracker(),
this, handle()))),
new DatabaseDispatcherHost(profile->GetDatabaseTracker(), this))),
notification_prefs_(
profile->GetDesktopNotificationService()->prefs_cache()),
socket_stream_dispatcher_host_(new SocketStreamDispatcherHost),
Expand Down Expand Up @@ -239,6 +238,7 @@ void ResourceMessageFilter::OnChannelConnected(int32 peer_pid) {
appcache_dispatcher_host_->Initialize(this, id(), handle());
socket_stream_dispatcher_host_->Initialize(this, id());
dom_storage_dispatcher_host_->Init(handle());
db_dispatcher_host_->Init(handle());
}

void ResourceMessageFilter::OnChannelError() {
Expand Down
12 changes: 10 additions & 2 deletions webkit/database/database_tracker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,16 @@ void DatabaseTracker::CloseTrackerDatabaseAndClearCaches() {
FilePath DatabaseTracker::GetFullDBFilePath(
const string16& origin_identifier,
const string16& database_name) const {
return db_dir_.Append(FilePath::FromWStringHack(UTF16ToWide(
origin_identifier + ASCIIToUTF16("_") + database_name)));
DCHECK(!origin_identifier.empty());
DCHECK(!database_name.empty());
int64 id = databases_table_->GetDatabaseID(
origin_identifier, database_name);
if (id < 0)
return FilePath();

FilePath file_name = FilePath::FromWStringHack(Int64ToWString(id));
return db_dir_.Append(FilePath::FromWStringHack(
UTF16ToWide(origin_identifier))).Append(file_name);
}

bool DatabaseTracker::LazyInit() {
Expand Down
17 changes: 11 additions & 6 deletions webkit/database/database_tracker_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,13 @@ TEST(DatabaseTrackerTest, TestIt) {
// Open three new databases.
int64 database_size = 0;
int64 space_available = 0;
const string16 kOrigin1 = ASCIIToUTF16("kOrigin1");
const string16 kOrigin2 = ASCIIToUTF16("kOrigin2");
const string16 kDB1 = ASCIIToUTF16("kDB1");
const string16 kDB2 = ASCIIToUTF16("kDB2");
const string16 kDB3 = ASCIIToUTF16("kDB3");
const string16 kDescription = ASCIIToUTF16("database_kDescription");
const string16 kOrigin1 = ASCIIToUTF16("origin1");
const string16 kOrigin2 = ASCIIToUTF16("origin2");
const string16 kDB1 = ASCIIToUTF16("db1");
const string16 kDB2 = ASCIIToUTF16("db2");
const string16 kDB3 = ASCIIToUTF16("db3");
const string16 kDescription = ASCIIToUTF16("database_description");

tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
&database_size, &space_available);
EXPECT_EQ(0, database_size);
Expand All @@ -109,6 +110,10 @@ TEST(DatabaseTrackerTest, TestIt) {

// Write some data to each file and check that the listeners are
// called with the appropriate values.
EXPECT_TRUE(file_util::CreateDirectory(tracker->DatabaseDirectory().Append(
FilePath::FromWStringHack(UTF16ToWide(kOrigin1)))));
EXPECT_TRUE(file_util::CreateDirectory(tracker->DatabaseDirectory().Append(
FilePath::FromWStringHack(UTF16ToWide(kOrigin2)))));
EXPECT_EQ(1, file_util::WriteFile(
tracker->GetFullDBFilePath(kOrigin1, kDB1), "a", 1));
EXPECT_EQ(2, file_util::WriteFile(
Expand Down
58 changes: 58 additions & 0 deletions webkit/database/database_util.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "webkit/database/database_util.h"

#include "base/string_util.h"
#include "webkit/database/database_tracker.h"
#include "webkit/database/vfs_backend.h"

namespace webkit_database {

bool DatabaseUtil::CrackVfsFilePath(const string16& vfs_file_path,
string16* origin_identifier,
string16* database_name,
string16* sqlite_suffix) {
// 'vfs_file_path' is of the form <origin_identifier>/<db_name>#<suffix>.
// <suffix> is optional.
DCHECK(!vfs_file_path.empty());
size_t first_slash_index = vfs_file_path.find('/');
size_t last_pound_index = vfs_file_path.rfind('#');
// '/' and '#' must be present in the string. Also, the string cannot start
// with a '/' (origin_identifier cannot be empty) and '/' must come before '#'
if ((first_slash_index == string16::npos) ||
(last_pound_index == string16::npos) ||
(first_slash_index == 0) ||
(first_slash_index > last_pound_index)) {
return false;
}

*origin_identifier = vfs_file_path.substr(0, first_slash_index);
*database_name = vfs_file_path.substr(
first_slash_index + 1, last_pound_index - first_slash_index - 1);
*sqlite_suffix = vfs_file_path.substr(
last_pound_index + 1, vfs_file_path.length() - last_pound_index - 1);
return true;
}

FilePath DatabaseUtil::GetFullFilePathForVfsFile(
DatabaseTracker* db_tracker, const string16& vfs_file_path) {
string16 origin_identifier;
string16 database_name;
string16 sqlite_suffix;
if (!CrackVfsFilePath(vfs_file_path, &origin_identifier,
&database_name, &sqlite_suffix)) {
return FilePath(); // invalid vfs_file_name
}

FilePath full_path = db_tracker->GetFullDBFilePath(
origin_identifier, database_name);
if (!full_path.empty() && !sqlite_suffix.empty()) {
full_path = FilePath::FromWStringHack(
full_path.ToWStringHack() + UTF16ToWide(sqlite_suffix));
}
return full_path;
}

} // namespace webkit_database
28 changes: 28 additions & 0 deletions webkit/database/database_util.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef WEBKIT_DATABASE_DATABASE_UTIL_H_
#define WEBKIT_DATABASE_DATABASE_UTIL_H_

#include "base/file_path.h"
#include "base/string16.h"

namespace webkit_database {

class DatabaseTracker;

class DatabaseUtil {
public:
static bool CrackVfsFilePath(const string16& vfs_file_path,
string16* origin_identifier,
string16* database_name,
string16* sqlite_suffix);
static FilePath GetFullFilePathForVfsFile(DatabaseTracker* db_tracker,
const string16& vfs_file_path);

};

} // namespace webkit_database

#endif // WEBKIT_DATABASE_DATABASE_UTIL_H_
45 changes: 45 additions & 0 deletions webkit/database/database_util_unittest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (c) 2009 The Chromium Authos. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/string_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "webkit/database/database_util.h"

using webkit_database::DatabaseUtil;

static void TestVfsFilePath(bool expected_result,
const char* vfs_file_path,
const char* expected_origin_identifier = "",
const char* expected_database_name = "",
const char* expected_sqlite_suffix = "") {
string16 origin_identifier;
string16 database_name;
string16 sqlite_suffix;
EXPECT_EQ(expected_result,
DatabaseUtil::CrackVfsFilePath(ASCIIToUTF16(vfs_file_path),
&origin_identifier,
&database_name,
&sqlite_suffix));
EXPECT_EQ(ASCIIToUTF16(expected_origin_identifier), origin_identifier);
EXPECT_EQ(ASCIIToUTF16(expected_database_name), database_name);
EXPECT_EQ(ASCIIToUTF16(expected_sqlite_suffix), sqlite_suffix);
}

namespace webkit_database {

// Test DatabaseUtil::CrackVfsFilePath on various inputs.
TEST(DatabaseUtilTest, CrackVfsFilePathTest) {
TestVfsFilePath(true, "origin/#", "origin", "", "");
TestVfsFilePath(true, "origin/#suffix", "origin", "", "suffix");
TestVfsFilePath(true, "origin/db_name#", "origin", "db_name", "");
TestVfsFilePath(true, "origin/db_name#suffix", "origin", "db_name", "suffix");
TestVfsFilePath(false, "origindb_name#");
TestVfsFilePath(false, "origindb_name#suffix");
TestVfsFilePath(false, "origin/db_name");
TestVfsFilePath(false, "origin#db_name/suffix");
TestVfsFilePath(false, "/db_name#");
TestVfsFilePath(false, "/db_name#suffix");
}

} // namespace webkit_database
Loading

0 comments on commit 3c5ed2c

Please sign in to comment.