diff options
-rw-r--r-- | base/base.xcodeproj/project.pbxproj | 2 | ||||
-rw-r--r-- | base/file_util.cc | 21 | ||||
-rw-r--r-- | base/file_util.h | 17 | ||||
-rw-r--r-- | chrome/browser/browser.scons | 1 | ||||
-rw-r--r-- | chrome/browser/renderer_host/browser_render_process_host.cc | 16 | ||||
-rw-r--r-- | chrome/browser/spellchecker.cc | 3 | ||||
-rw-r--r-- | chrome/browser/spellchecker.h | 5 | ||||
-rw-r--r-- | chrome/browser/visitedlink_master.cc | 166 | ||||
-rw-r--r-- | chrome/browser/visitedlink_master.h | 25 | ||||
-rw-r--r-- | chrome/browser/visitedlink_perftest.cc | 8 | ||||
-rw-r--r-- | chrome/browser/visitedlink_unittest.cc | 46 | ||||
-rw-r--r-- | chrome/chrome.xcodeproj/project.pbxproj | 2 | ||||
-rw-r--r-- | chrome/common/temp_scaffolding_stubs.h | 44 |
13 files changed, 250 insertions, 106 deletions
diff --git a/base/base.xcodeproj/project.pbxproj b/base/base.xcodeproj/project.pbxproj index e347a84..5c9ab7a 100644 --- a/base/base.xcodeproj/project.pbxproj +++ b/base/base.xcodeproj/project.pbxproj @@ -644,6 +644,7 @@ ABF68B280EB0F93100E72835 /* field_trial.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = field_trial.cc; sourceTree = "<group>"; }; B290BFCBD30E45A63758BFC7 /* waitable_event_posix.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = waitable_event_posix.cc; sourceTree = "<group>"; }; B52C916B0E9428F500208D01 /* clipboard_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = clipboard_unittest.cc; sourceTree = "<group>"; }; + B57D788E0F26983200685566 /* scoped_file.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scoped_file.h; sourceTree = "<group>"; }; B57E4D770E9C26340090055D /* idletimer_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = idletimer_unittest.cc; sourceTree = "<group>"; }; B5A8618D0EC1257900B332C2 /* clipboard.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = clipboard.cc; sourceTree = "<group>"; }; B5D544AA0EAFB7E000272A1C /* sys_string_conversions_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sys_string_conversions_unittest.cc; sourceTree = "<group>"; }; @@ -1002,6 +1003,7 @@ 7B5AD60D0D9DD8050012BCF1 /* scoped_cftyperef.h */, B5E8F6CB0EBFB38E008DD1E9 /* scoped_clipboard_writer.cc */, B5E8F6CA0EBFB38E008DD1E9 /* scoped_clipboard_writer.h */, + B57D788E0F26983200685566 /* scoped_file.h */, 7BA35DD10E8C0D5F0023C8B9 /* scoped_nsautorelease_pool.h */, 7BA35DD20E8C0D5F0023C8B9 /* scoped_nsautorelease_pool.mm */, 825403610D92D27C0006B936 /* scoped_ptr.h */, diff --git a/base/file_util.cc b/base/file_util.cc index 078e3afa..8ecb1cc 100644 --- a/base/file_util.cc +++ b/base/file_util.cc @@ -4,6 +4,9 @@ #include "base/file_util.h" +#if defined(OS_WIN) +#include <io.h> +#endif #include <stdio.h> #include <fstream> @@ -276,6 +279,24 @@ bool CloseFile(FILE* file) { return fclose(file) == 0; } +bool TruncateFile(FILE* file) { + if (file == NULL) + return false; + long current_offset = ftell(file); + if (current_offset == -1) + return false; +#if defined(OS_WIN) + int fd = _fileno(file); + if (_chsize(fd, current_offset) != 0) + return false; +#else + int fd = fileno(file); + if (ftruncate(fd, current_offset) != 0) + return false; +#endif + return true; +} + bool ContainsPath(const FilePath &parent, const FilePath& child) { FilePath abs_parent = FilePath(parent); FilePath abs_child = FilePath(child); diff --git a/base/file_util.h b/base/file_util.h index 4154856..c546b9a 100644 --- a/base/file_util.h +++ b/base/file_util.h @@ -24,6 +24,7 @@ #include <vector> #include "base/basictypes.h" +#include "base/scoped_ptr.h" #include "base/file_path.h" namespace file_util { @@ -318,6 +319,10 @@ FILE* OpenFile(const std::wstring& filename, const char* mode); // Closes file opened by OpenFile. Returns true on success. bool CloseFile(FILE* file); +// Truncates an open file to end at the location of the current file pointer. +// This is a cross-platform analog to Windows' SetEndOfFile() function. +bool TruncateFile(FILE* file); + // Reads the given number of bytes from the file into the buffer. Returns // the number of read bytes, or -1 on error. int ReadFile(const std::wstring& filename, char* data, int size); @@ -336,6 +341,18 @@ bool SetCurrentDirectory(const FilePath& path); // Deprecated temporary compatibility function. bool SetCurrentDirectory(const std::wstring& current_directory); +// A class to handle auto-closing of FILE*'s. +class ScopedFILEClose { + public: + inline void operator()(FILE* x) const { + if (x) { + fclose(x); + } + } +}; + +typedef scoped_ptr_malloc<FILE, ScopedFILEClose> ScopedFILE; + // A class for enumerating the files in a provided path. The order of the // results is not guaranteed. // diff --git a/chrome/browser/browser.scons b/chrome/browser/browser.scons index 225d6fa..081e840 100644 --- a/chrome/browser/browser.scons +++ b/chrome/browser/browser.scons @@ -819,7 +819,6 @@ if not env.Bit('windows'): 'toolbar_model.cc', 'user_data_manager.cc', 'views/download_tab_view.cc', - 'visitedlink_master.cc', 'web_app.cc', 'web_app_icon_manager.cc', 'web_app_launcher.cc', diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc index 823a063..c8b8e6e 100644 --- a/chrome/browser/renderer_host/browser_render_process_host.cc +++ b/chrome/browser/renderer_host/browser_render_process_host.cc @@ -27,12 +27,22 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/cache_manager_host.h" #include "chrome/browser/extensions/user_script_master.h" +#if defined(OS_WIN) #include "chrome/browser/history/history.h" +#else +// TODO(port): remove scaffolding, use history.h for both POSIX and WIN. +#include "chrome/common/temp_scaffolding_stubs.h" +#endif // !defined(OS_WIN) + #include "chrome/browser/plugin_service.h" #include "chrome/browser/renderer_host/render_widget_helper.h" #include "chrome/browser/renderer_host/renderer_security_policy.h" #include "chrome/browser/resource_message_filter.h" +#if defined(OS_MACOSX) +// TODO(port): Enable when we finish porting spellchecker to os x. +#else #include "chrome/browser/spellchecker.h" +#endif // !defined(OS_WIN) #include "chrome/browser/visitedlink_master.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" @@ -470,11 +480,17 @@ void BrowserRenderProcessHost::WidgetHidden() { } void BrowserRenderProcessHost::AddWord(const std::wstring& word) { +#if defined(OS_MACOSX) + // TODO(port): reimplement when we get the spell checker up and running on + // OS X. + NOTIMPLEMENTED(); +#else base::Thread* io_thread = g_browser_process->io_thread(); if (profile()->GetSpellChecker()) { io_thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod( profile()->GetSpellChecker(), &SpellChecker::AddWord, word)); } +#endif // !defined(OS_MACOSX) } base::ProcessHandle BrowserRenderProcessHost::GetRendererProcessHandle() { diff --git a/chrome/browser/spellchecker.cc b/chrome/browser/spellchecker.cc index 4269f70..11147b9 100644 --- a/chrome/browser/spellchecker.cc +++ b/chrome/browser/spellchecker.cc @@ -14,7 +14,10 @@ #include "chrome/app/locales/locale_settings.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/net/url_fetcher.h" +#if defined(OS_WIN) +// TODO(port): remove scaffolding, use profile.h for both POSIX and WIN. #include "chrome/browser/profile.h" +#endif #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_counters.h" #include "chrome/common/chrome_paths.h" diff --git a/chrome/browser/spellchecker.h b/chrome/browser/spellchecker.h index 1e97605..e4a3a18 100644 --- a/chrome/browser/spellchecker.h +++ b/chrome/browser/spellchecker.h @@ -9,7 +9,12 @@ #include "base/string_util.h" #include "chrome/browser/browser_process.h" +#if defined(OS_WIN) #include "chrome/browser/profile.h" +#else +// TODO(port): remove scaffolding, use profile.h for both POSIX and WIN. +#include "chrome/common/temp_scaffolding_stubs.h" +#endif #include "chrome/browser/spellcheck_worditerator.h" #include "chrome/common/l10n_util.h" #include "chrome/common/pref_names.h" diff --git a/chrome/browser/visitedlink_master.cc b/chrome/browser/visitedlink_master.cc index 22a9638..85470cc 100644 --- a/chrome/browser/visitedlink_master.cc +++ b/chrome/browser/visitedlink_master.cc @@ -4,20 +4,40 @@ #include "chrome/browser/visitedlink_master.h" +#if defined(OS_WIN) #include <windows.h> +#include <io.h> #include <shlobj.h> +#endif // defined(OS_WIN) +#include <stdio.h> + #include <algorithm> +#include "base/file_util.h" #include "base/logging.h" #include "base/message_loop.h" #include "base/path_service.h" +#include "base/process_util.h" #include "base/rand_util.h" #include "base/stack_container.h" #include "base/string_util.h" +#include "base/thread.h" #include "chrome/browser/browser_process.h" +#if defined(OS_WIN) #include "chrome/browser/history/history.h" #include "chrome/browser/profile.h" +#else +// TODO(port): We should be using history.h & profile.h, remove scaffolding +// when those are ported. +#include "chrome/common/temp_scaffolding_stubs.h" +#endif // !defined(OS_WIN) +#if defined(OS_WIN) #include "chrome/common/win_util.h" +#endif + +using file_util::ScopedFILE; +using file_util::OpenFile; +using file_util::TruncateFile; const int32 VisitedLinkMaster::kFileHeaderSignatureOffset = 0; const int32 VisitedLinkMaster::kFileHeaderVersionOffset = 4; @@ -36,7 +56,7 @@ const size_t VisitedLinkMaster::kFileHeaderSize = // table in NewTableSizeForCount (prime number). const unsigned VisitedLinkMaster::kDefaultTableSize = 16381; -const int32 VisitedLinkMaster::kBigDeleteThreshold = 64; +const size_t VisitedLinkMaster::kBigDeleteThreshold = 64; namespace { @@ -48,43 +68,42 @@ void GenerateSalt(uint8 salt[LINK_SALT_LENGTH]) { uint64 randval = base::RandUint64(); memcpy(salt, &randval, 8); } + // AsyncWriter ---------------------------------------------------------------- // This task executes on a background thread and executes a write. This // prevents us from blocking the UI thread doing I/O. class AsyncWriter : public Task { public: - AsyncWriter(HANDLE hfile, int32 offset, const void* data, int32 data_len) - : hfile_(hfile), + AsyncWriter(FILE* file, int32 offset, const void* data, size_t data_len) + : file_(file), offset_(offset) { data_->resize(data_len); memcpy(&*data_->begin(), data, data_len); } virtual void Run() { - WriteToFile(hfile_, offset_, + WriteToFile(file_, offset_, &*data_->begin(), static_cast<int32>(data_->size())); } // Exposed as a static so it can be called directly from the Master to // reduce the number of platform-specific I/O sites we have. Returns true if // the write was complete. - static bool WriteToFile(HANDLE hfile, - int32 offset, + static bool WriteToFile(FILE* file, + off_t offset, const void* data, - int32 data_len) { - if (SetFilePointer(hfile, offset, NULL, FILE_BEGIN) == - INVALID_SET_FILE_POINTER) + size_t data_len) { + if (fseek(file, offset, SEEK_SET) != 0) return false; // Don't write to an invalid part of the file. - DWORD num_written; - return WriteFile(hfile, data, data_len, &num_written, NULL) && - (num_written == data_len); + size_t num_written = fwrite(data, 1, data_len, file); + return num_written == data_len; } private: // The data to write and where to write it. - HANDLE hfile_; + FILE* file_; int32 offset_; // Offset from the beginning of the file. // Most writes are just a single fingerprint, so we reserve that much in this @@ -98,14 +117,14 @@ class AsyncWriter : public Task { // same thread as the writing to keep things synchronized. class AsyncSetEndOfFile : public Task { public: - explicit AsyncSetEndOfFile(HANDLE hfile) : hfile_(hfile) {} + explicit AsyncSetEndOfFile(FILE* file) : file_(file) {} virtual void Run() { - SetEndOfFile(hfile_); + TruncateFile(file_); } private: - HANDLE hfile_; + FILE* file_; DISALLOW_EVIL_CONSTRUCTORS(AsyncSetEndOfFile); }; @@ -113,14 +132,14 @@ class AsyncSetEndOfFile : public Task { // the writing to keep things synchronized. class AsyncCloseHandle : public Task { public: - explicit AsyncCloseHandle(HANDLE hfile) : hfile_(hfile) {} + explicit AsyncCloseHandle(FILE* file) : file_(file) {} virtual void Run() { - CloseHandle(hfile_); + fclose(file_); } private: - HANDLE hfile_; + FILE* file_; DISALLOW_EVIL_CONSTRUCTORS(AsyncCloseHandle); }; @@ -194,11 +213,11 @@ VisitedLinkMaster::VisitedLinkMaster(base::Thread* file_thread, PostNewTableEvent* poster, HistoryService* history_service, bool suppress_rebuild, - const std::wstring& filename, + const FilePath& filename, int32 default_table_size) { InitMembers(file_thread, poster, NULL); - database_name_override_.assign(filename); + database_name_override_ = filename; table_size_override_ = default_table_size; history_service_override_ = history_service; suppress_rebuild_ = suppress_rebuild; @@ -248,7 +267,7 @@ std::wstring VisitedLinkMaster::GetSharedMemoryName() const { profile_id = profile_->GetID().c_str(); return StringPrintf(L"GVisitedLinks_%lu_%lu_%ls", - GetCurrentProcessId(), shared_memory_serial_, + base::GetCurrentProcId(), shared_memory_serial_, profile_id.c_str()); } @@ -512,19 +531,19 @@ bool VisitedLinkMaster::WriteFullTable() { // We should pick up the most common types of these failures when we notice // that the file size is different when we load it back in, and then we will // regenerate the table. - win_util::ScopedHandle hfile_closer; // Valid only when not open already. - HANDLE hfile; // Always valid. + ScopedFILE file_closer; // Valid only when not open already. + FILE* file; // Always valid. if (file_) { - hfile = file_; + file = file_; } else { - std::wstring filename; + FilePath filename; GetDatabaseFileName(&filename); - hfile_closer.Set( - CreateFile(filename.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, - CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)); - if (!hfile_closer.IsValid()) + file_closer.reset(OpenFile(filename, "wb+")); + if (!file_closer.get()) { + DLOG(ERROR) << "Failed to open file " << filename.value(); return false; - hfile = hfile_closer; + } + file = file_closer.get(); } // Write the new header. @@ -533,54 +552,54 @@ bool VisitedLinkMaster::WriteFullTable() { header[1] = kFileCurrentVersion; header[2] = table_length_; header[3] = used_items_; - WriteToFile(hfile, 0, header, sizeof(header)); - WriteToFile(hfile, sizeof(header), salt_, LINK_SALT_LENGTH); + WriteToFile(file, 0, header, sizeof(header)); + WriteToFile(file, sizeof(header), salt_, LINK_SALT_LENGTH); // Write the hash data. - WriteToFile(hfile, kFileHeaderSize, + WriteToFile(file, kFileHeaderSize, hash_table_, table_length_ * sizeof(Fingerprint)); // The hash table may have shrunk, so make sure this is the end. if (file_thread_) { - AsyncSetEndOfFile* setter = new AsyncSetEndOfFile(hfile); + AsyncSetEndOfFile* setter = new AsyncSetEndOfFile(file); file_thread_->PostTask(FROM_HERE, setter); } else { - SetEndOfFile(hfile); + TruncateFile(file); } // Keep the file open so we can dynamically write changes to it. When the - // file was alrady open, the hfile_closer is NULL, and file_ is already good. - if (hfile_closer.IsValid()) - file_ = hfile_closer.Take(); + // file was already open, the file_closer is NULL, and file_ is already good. + if (file_closer.get()) + file_ = file_closer.release(); return true; } bool VisitedLinkMaster::InitFromFile() { DCHECK(file_ == NULL); - std::wstring filename; + FilePath filename; GetDatabaseFileName(&filename); - win_util::ScopedHandle hfile( - CreateFile(filename.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, - OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)); - if (!hfile.IsValid()) + ScopedFILE file_closer(OpenFile(filename, "rb+")); + if (!file_closer.get()) { + DLOG(ERROR) << "Failed to open file " << filename.value(); return false; + } int32 num_entries, used_count; - if (!ReadFileHeader(hfile, &num_entries, &used_count, salt_)) + if (!ReadFileHeader(file_closer.get(), &num_entries, &used_count, salt_)) return false; // Header isn't valid. // Allocate and read the table. if (!CreateURLTable(num_entries, false)) return false; - if (!ReadFromFile(hfile, kFileHeaderSize, + if (!ReadFromFile(file_closer.get(), kFileHeaderSize, hash_table_, num_entries * sizeof(Fingerprint))) { FreeURLTable(); return false; } used_items_ = used_count; - file_ = hfile.Take(); + file_ = file_closer.release(); return true; } @@ -609,20 +628,27 @@ bool VisitedLinkMaster::InitFromScratch(bool suppress_rebuild) { return RebuildTableFromHistory(); } -bool VisitedLinkMaster::ReadFileHeader(HANDLE hfile, +bool VisitedLinkMaster::ReadFileHeader(FILE* file, int32* num_entries, int32* used_count, uint8 salt[LINK_SALT_LENGTH]) { - int32 file_size = GetFileSize(hfile, NULL); + // Get file size. + // Note that there is no need to seek back to the original location in the + // file since ReadFromFile() [which is the next call accessing the file] + // seeks before reading. + if (fseek(file, 0, SEEK_END) == -1) + return false; + size_t file_size = ftell(file); + if (file_size <= kFileHeaderSize) return false; uint8 header[kFileHeaderSize]; - if (!ReadFromFile(hfile, 0, &header, kFileHeaderSize)) + if (!ReadFromFile(file, 0, &header, kFileHeaderSize)) return false; // Verify the signature. - uint32 signature; + int32 signature; memcpy(&signature, &header[kFileHeaderSignatureOffset], sizeof(signature)); if (signature != kFileSignature) return false; @@ -652,7 +678,7 @@ bool VisitedLinkMaster::ReadFileHeader(HANDLE hfile, return true; } -bool VisitedLinkMaster::GetDatabaseFileName(std::wstring* filename) { +bool VisitedLinkMaster::GetDatabaseFileName(FilePath* filename) { if (!database_name_override_.empty()) { // use this filename, the directory must exist *filename = database_name_override_; @@ -662,8 +688,8 @@ bool VisitedLinkMaster::GetDatabaseFileName(std::wstring* filename) { if (!profile_ || profile_->GetPath().empty()) return false; - *filename = profile_->GetPath(); - filename->append(L"\\Visited Links"); + FilePath profile_dir = FilePath::FromWStringHack(profile_->GetPath()); + *filename = profile_dir.Append(FILE_PATH_LITERAL("Visited Links")); return true; } @@ -735,7 +761,7 @@ void VisitedLinkMaster::FreeURLTable() { AsyncCloseHandle* closer = new AsyncCloseHandle(file_); file_thread_->PostTask(FROM_HERE, closer); } else { - CloseHandle(file_); + fclose(file_); } } } @@ -752,7 +778,8 @@ bool VisitedLinkMaster::ResizeTableIfNecessary() { float load = ComputeTableLoad(); if (load < max_table_load && - (table_length_ <= kDefaultTableSize || load > min_table_load)) + (table_length_ <= static_cast<float>(kDefaultTableSize) || + load > min_table_load)) return false; // Table needs to grow or shrink. @@ -823,7 +850,7 @@ uint32 VisitedLinkMaster::NewTableSizeForCount(int32 item_count) const { int desired = item_count * 3; // Find the closest prime. - for (int i = 0; i < arraysize(table_sizes); i ++) { + for (size_t i = 0; i < arraysize(table_sizes); i ++) { if (table_sizes[i] > desired) return table_sizes[i]; } @@ -908,8 +935,8 @@ void VisitedLinkMaster::OnTableRebuildComplete( } } -void VisitedLinkMaster::WriteToFile(HANDLE hfile, - int32 offset, +void VisitedLinkMaster::WriteToFile(FILE* file, + off_t offset, void* data, int32 data_size) { #ifndef NDEBUG @@ -918,12 +945,12 @@ void VisitedLinkMaster::WriteToFile(HANDLE hfile, if (file_thread_) { // Send the write to the other thread for execution to avoid blocking. - AsyncWriter* writer = new AsyncWriter(hfile, offset, data, data_size); + AsyncWriter* writer = new AsyncWriter(file, offset, data, data_size); file_thread_->PostTask(FROM_HERE, writer); } else { // When there is no I/O thread, we are probably running in unit test mode, // just do the write synchronously. - AsyncWriter::WriteToFile(hfile, offset, data, data_size); + AsyncWriter::WriteToFile(file, offset, data, data_size); } } @@ -949,21 +976,20 @@ void VisitedLinkMaster::WriteHashRangeToFile(Hash first_hash, Hash last_hash) { } } -bool VisitedLinkMaster::ReadFromFile(HANDLE hfile, - int32 offset, +bool VisitedLinkMaster::ReadFromFile(FILE* file, + off_t offset, void* data, - int32 data_size) { + size_t data_size) { #ifndef NDEBUG // Since this function is synchronous, we require that no asynchronous // operations could possibly be pending. DCHECK(!posted_asynchronous_operation_); #endif - SetFilePointer(hfile, offset, NULL, FILE_BEGIN); + fseek(file, offset, SEEK_SET); - DWORD num_read; - return ReadFile(hfile, data, data_size, &num_read, NULL) && - num_read == data_size; + size_t num_read = fread(data, 1, data_size, file); + return num_read == data_size; } // VisitedLinkTableBuilder ---------------------------------------------------- @@ -972,8 +998,8 @@ VisitedLinkMaster::TableBuilder::TableBuilder( VisitedLinkMaster* master, const uint8 salt[LINK_SALT_LENGTH]) : master_(master), - success_(true), - main_message_loop_(MessageLoop::current()) { + main_message_loop_(MessageLoop::current()), + success_(true) { fingerprints_.reserve(4096); memcpy(salt_, salt, sizeof(salt)); } diff --git a/chrome/browser/visitedlink_master.h b/chrome/browser/visitedlink_master.h index ac99634..c68e4c7 100644 --- a/chrome/browser/visitedlink_master.h +++ b/chrome/browser/visitedlink_master.h @@ -5,13 +5,22 @@ #ifndef CHROME_BROWSER_VISITEDLINK_MASTER_H__ #define CHROME_BROWSER_VISITEDLINK_MASTER_H__ +#if defined(OS_WIN) +#include <windows.h> +#endif #include <set> #include <string> #include <vector> +#include "base/file_path.h" #include "base/ref_counted.h" #include "base/shared_memory.h" +#if defined(OS_WIN) #include "chrome/browser/history/history.h" +#else +// TODO(port): remove scaffolding, use history.h for both POSIX and WIN. +#include "chrome/common/temp_scaffolding_stubs.h" +#endif // !defined(OS_WIN) #include "chrome/common/visitedlink_common.h" #include "testing/gtest/include/gtest/gtest_prod.h" @@ -53,7 +62,7 @@ class VisitedLinkMaster : public VisitedLinkCommon { PostNewTableEvent* poster, HistoryService* history_service, bool suppress_rebuild, - const std::wstring& filename, + const FilePath& filename, int32 default_table_size); virtual ~VisitedLinkMaster(); @@ -141,7 +150,7 @@ class VisitedLinkMaster : public VisitedLinkCommon { // When the user is deleting a boatload of URLs, we don't really want to do // individual writes for each of them. When the count exceeds this threshold, // we will write the whole table to disk at once instead of individual items. - static const int32 kBigDeleteThreshold; + static const size_t kBigDeleteThreshold; // Backend for the constructors initializing the members. void InitMembers(base::Thread* file_thread, @@ -171,15 +180,15 @@ class VisitedLinkMaster : public VisitedLinkCommon { // Returns true on success and places the size of the table in num_entries // and the number of nonzero fingerprints in used_count. This will fail if // the version of the file is not the current version of the database. - bool ReadFileHeader(HANDLE hfile, int32* num_entries, int32* used_count, + bool ReadFileHeader(FILE* hfile, int32* num_entries, int32* used_count, uint8 salt[LINK_SALT_LENGTH]); // Fills *filename with the name of the link database filename - bool GetDatabaseFileName(std::wstring* filename); + bool GetDatabaseFileName(FilePath* filename); // Wrapper around Window's WriteFile using asynchronous I/O. This will proxy // the write to a background thread. - void WriteToFile(HANDLE hfile, int32 offset, void* data, int32 data_size); + void WriteToFile(FILE* hfile, off_t offset, void* data, int32 data_size); // Helper function to schedule and asynchronous write of the used count to // disk (this is a common operation). @@ -192,7 +201,7 @@ class VisitedLinkMaster : public VisitedLinkCommon { // Synchronous read from the file. Assumes there are no pending asynchronous // I/O functions. Returns true if the entire buffer was successfully filled. - bool ReadFromFile(HANDLE hfile, int32 offset, void* data, int32 data_size); + bool ReadFromFile(FILE* hfile, off_t offset, void* data, size_t data_size); // General table handling // ---------------------- @@ -326,7 +335,7 @@ class VisitedLinkMaster : public VisitedLinkCommon { // The currently open file with the table in it. This may be NULL if we're // rebuilding and haven't written a new version yet. Writing to the file may // be safely ignored in this case. - HANDLE file_; + FILE* file_; // Shared memory consists of a SharedHeader followed by the table. base::SharedMemory *shared_memory_; @@ -347,7 +356,7 @@ class VisitedLinkMaster : public VisitedLinkCommon { // in release builds that give "regular" behavior. // Overridden database file name for testing - std::wstring database_name_override_; + FilePath database_name_override_; // When nonzero, overrides the table size for new databases for testing int32 table_size_override_; diff --git a/chrome/browser/visitedlink_perftest.cc b/chrome/browser/visitedlink_perftest.cc index fc412d4..8184824 100644 --- a/chrome/browser/visitedlink_perftest.cc +++ b/chrome/browser/visitedlink_perftest.cc @@ -81,7 +81,7 @@ class VisitedLink : public testing::Test { TEST_F(VisitedLink, TestAddAndQuery) { // init VisitedLinkMaster master(NULL, DummyBroadcastNewTableEvent, NULL, true, - db_name_, 0); + FilePath(db_name_), 0); ASSERT_TRUE(master.Init()); PerfTimeLogger timer("Visited_link_add_and_query"); @@ -112,7 +112,7 @@ TEST_F(VisitedLink, TestLoad) { PerfTimeLogger table_initialization_timer("Table_initialization"); VisitedLinkMaster master(NULL, DummyBroadcastNewTableEvent, NULL, true, - db_name_, 0); + FilePath(db_name_), 0); // time init with empty table PerfTimeLogger initTimer("Empty_visited_link_init"); @@ -152,7 +152,7 @@ TEST_F(VisitedLink, TestLoad) { PerfTimer cold_timer; VisitedLinkMaster master(NULL, DummyBroadcastNewTableEvent, NULL, true, - db_name_, 0); + FilePath(db_name_), 0); bool success = master.Init(); TimeDelta elapsed = cold_timer.Elapsed(); ASSERT_TRUE(success); @@ -165,7 +165,7 @@ TEST_F(VisitedLink, TestLoad) { PerfTimer hot_timer; VisitedLinkMaster master(NULL, DummyBroadcastNewTableEvent, NULL, true, - db_name_, 0); + FilePath(db_name_), 0); bool success = master.Init(); TimeDelta elapsed = hot_timer.Elapsed(); ASSERT_TRUE(success); diff --git a/chrome/browser/visitedlink_unittest.cc b/chrome/browser/visitedlink_unittest.cc index 86c2a24..2dac97f 100644 --- a/chrome/browser/visitedlink_unittest.cc +++ b/chrome/browser/visitedlink_unittest.cc @@ -9,6 +9,7 @@ #include "base/message_loop.h" #include "base/file_util.h" #include "base/path_service.h" +#include "base/process_util.h" #include "base/shared_memory.h" #include "base/string_util.h" #include "chrome/browser/visitedlink_master.h" @@ -28,28 +29,28 @@ GURL TestURL(int i) { return GURL(StringPrintf("%s%d", g_test_prefix, i)); } -// when testing in single-threaded mode -VisitedLinkMaster* g_master = NULL; std::vector<VisitedLinkSlave*> g_slaves; VisitedLinkMaster::PostNewTableEvent SynchronousBroadcastNewTableEvent; void SynchronousBroadcastNewTableEvent(base::SharedMemory* table) { if (table) { for (std::vector<VisitedLinkSlave>::size_type i = 0; - i < (int)g_slaves.size(); i++) { + i < g_slaves.size(); i++) { base::SharedMemoryHandle new_handle = NULL; - table->ShareToProcess(GetCurrentProcess(), &new_handle); + table->ShareToProcess(base::GetCurrentProcessHandle(), &new_handle); g_slaves[i]->Init(new_handle); } } } +} // namespace + class VisitedLinkTest : public testing::Test { protected: // Initialize the history system. This should be called before InitVisited(). bool InitHistory() { history_service_ = new HistoryService; - return history_service_->Init(history_dir_, NULL); + return history_service_->Init(history_dir_.ToWStringHack(), NULL); } // Initializes the visited link objects. Pass in the size that you want a @@ -103,7 +104,7 @@ class VisitedLinkTest : public testing::Test { // Create a slave database. VisitedLinkSlave slave; base::SharedMemoryHandle new_handle = NULL; - master_->ShareToProcess(GetCurrentProcess(), &new_handle); + master_->ShareToProcess(base::GetCurrentProcessHandle(), &new_handle); bool success = slave.Init(new_handle); ASSERT_TRUE(success); g_slaves.push_back(&slave); @@ -132,12 +133,11 @@ class VisitedLinkTest : public testing::Test { // testing::Test virtual void SetUp() { PathService::Get(base::DIR_TEMP, &history_dir_); - file_util::AppendToPath(&history_dir_, L"VisitedLinkTest"); + history_dir_ = history_dir_.Append(FILE_PATH_LITERAL("VisitedLinkTest")); file_util::Delete(history_dir_, true); file_util::CreateDirectory(history_dir_); - visited_file_ = history_dir_; - file_util::AppendToPath(&visited_file_, L"VisitedLinks"); + visited_file_ = history_dir_.Append(FILE_PATH_LITERAL("VisitedLinks")); } virtual void TearDown() { @@ -148,15 +148,13 @@ class VisitedLinkTest : public testing::Test { MessageLoop message_loop_; // Filenames for the services; - std::wstring history_dir_; - std::wstring visited_file_; + FilePath history_dir_; + FilePath visited_file_; scoped_ptr<VisitedLinkMaster> master_; scoped_refptr<HistoryService> history_service_; }; -} // namespace - // This test creates and reads some databases to make sure the data is // preserved throughout those operations. TEST_F(VisitedLinkTest, DatabaseIO) { @@ -178,11 +176,11 @@ TEST_F(VisitedLinkTest, Delete) { // Add a cluster from 14-17 wrapping around to 0. These will all hash to the // same value. - const int kFingerprint0 = kInitialSize * 0 + 14; - const int kFingerprint1 = kInitialSize * 1 + 14; - const int kFingerprint2 = kInitialSize * 2 + 14; - const int kFingerprint3 = kInitialSize * 3 + 14; - const int kFingerprint4 = kInitialSize * 4 + 14; + const VisitedLinkCommon::Fingerprint kFingerprint0 = kInitialSize * 0 + 14; + const VisitedLinkCommon::Fingerprint kFingerprint1 = kInitialSize * 1 + 14; + const VisitedLinkCommon::Fingerprint kFingerprint2 = kInitialSize * 2 + 14; + const VisitedLinkCommon::Fingerprint kFingerprint3 = kInitialSize * 3 + 14; + const VisitedLinkCommon::Fingerprint kFingerprint4 = kInitialSize * 4 + 14; master_->AddFingerprint(kFingerprint0); // @14 master_->AddFingerprint(kFingerprint1); // @15 master_->AddFingerprint(kFingerprint2); // @16 @@ -193,8 +191,9 @@ TEST_F(VisitedLinkTest, Delete) { // order). EXPECT_EQ(kFingerprint3, master_->hash_table_[0]); master_->DeleteFingerprint(kFingerprint3, false); - EXPECT_EQ(0, master_->hash_table_[1]); - EXPECT_NE(0, master_->hash_table_[0]); + VisitedLinkCommon::Fingerprint zero_fingerprint = 0; + EXPECT_EQ(zero_fingerprint, master_->hash_table_[1]); + EXPECT_NE(zero_fingerprint, master_->hash_table_[0]); // Deleting the other four should leave the table empty. master_->DeleteFingerprint(kFingerprint0, false); @@ -204,7 +203,8 @@ TEST_F(VisitedLinkTest, Delete) { EXPECT_EQ(0, master_->used_items_); for (int i = 0; i < kInitialSize; i++) - EXPECT_EQ(0, master_->hash_table_[i]) << "Hash table has values in it."; + EXPECT_EQ(zero_fingerprint, master_->hash_table_[i]) << + "Hash table has values in it."; } // When we delete more than kBigDeleteThreshold we trigger different behavior @@ -240,7 +240,7 @@ TEST_F(VisitedLinkTest, DeleteAll) { { VisitedLinkSlave slave; base::SharedMemoryHandle new_handle = NULL; - master_->ShareToProcess(GetCurrentProcess(), &new_handle); + master_->ShareToProcess(base::GetCurrentProcessHandle(), &new_handle); ASSERT_TRUE(slave.Init(new_handle)); g_slaves.push_back(&slave); @@ -288,7 +288,7 @@ TEST_F(VisitedLinkTest, Resizing) { // ...and a slave VisitedLinkSlave slave; base::SharedMemoryHandle new_handle = NULL; - master_->ShareToProcess(GetCurrentProcess(), &new_handle); + master_->ShareToProcess(base::GetCurrentProcessHandle(), &new_handle); bool success = slave.Init(new_handle); ASSERT_TRUE(success); g_slaves.push_back(&slave); diff --git a/chrome/chrome.xcodeproj/project.pbxproj b/chrome/chrome.xcodeproj/project.pbxproj index e570354..4f14b07 100644 --- a/chrome/chrome.xcodeproj/project.pbxproj +++ b/chrome/chrome.xcodeproj/project.pbxproj @@ -227,6 +227,7 @@ B56E281B0F057F2800447108 /* message_router.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D7BFBD10E9D4C9F009A6919 /* message_router.cc */; }; B5DBEA900EFC60E200C95176 /* ipc_channel_proxy.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D7BFBAB0E9D4C9F009A6919 /* ipc_channel_proxy.cc */; }; B5E98B140F0574A8000A37D6 /* render_messages.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D7BFBF10E9D4C9F009A6919 /* render_messages.cc */; }; + B5FCDE5C0F269E9B0099BFAF /* visitedlink_master.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D7BF95F0E9D4839009A6919 /* visitedlink_master.cc */; }; B5FDC0580EE488E500BEC6E6 /* ipc_channel_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = B5FDC0570EE488E500BEC6E6 /* ipc_channel_posix.cc */; }; B5FDC1CA0EE48ADB00BEC6E6 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D7BFDD10E9D5295009A6919 /* CoreFoundation.framework */; }; B5FDC1CC0EE48ADB00BEC6E6 /* libbase.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D7BFDC70E9D525B009A6919 /* libbase.a */; }; @@ -4193,6 +4194,7 @@ 4D7BFA480E9D4922009A6919 /* visitsegment_database.cc in Sources */, E48B6C3C0F27844F002E47EC /* web_data_service.cc in Sources */, E45076200F150E0C003BE099 /* web_database.cc in Sources */, + B5FCDE5C0F269E9B0099BFAF /* visitedlink_master.cc in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/chrome/common/temp_scaffolding_stubs.h b/chrome/common/temp_scaffolding_stubs.h index aad59bd..e6264da 100644 --- a/chrome/common/temp_scaffolding_stubs.h +++ b/chrome/common/temp_scaffolding_stubs.h @@ -22,14 +22,19 @@ #include "webkit/glue/window_open_disposition.h" class Browser; +class BookmarkService; class CommandLine; +class HistoryService; class MetricsService; class NavigationEntry; class ProfileManager; class Profile; class SessionID; +class SpellChecker; class TabContents; class URLRequestContext; +class UserScriptMaster; +class VisitedLinkMaster; class WebContents; //--------------------------------------------------------------------------- @@ -175,24 +180,63 @@ class TabRestoreService { void BrowserClosed(Browser*) { } }; +class HistoryService { + public: + + class URLEnumerator { + public: + virtual ~URLEnumerator() {} + virtual void OnURL(const GURL& url) = 0; + virtual void OnComplete(bool success) = 0; + }; + + HistoryService() {} + bool Init(const std::wstring& history_dir, BookmarkService* bookmark_service) + { return false; } + void SetOnBackendDestroyTask(Task*) {} + void AddPage(GURL const&, void const*, int, GURL const&, + int, std::vector<GURL> const&) {} + void AddPage(const GURL& url) {} + void SetPageContents(const GURL& url, const std::wstring& contents) {} + void IterateURLs(URLEnumerator* iterator) {} + void Cleanup() {} + void AddRef() {} + void Release() {} +}; + class Profile { public: + enum ServiceAccessType { + EXPLICIT_ACCESS, + IMPLICIT_ACCESS + }; + + public: Profile(const std::wstring& user_data_dir); virtual std::wstring GetPath() { return path_; } virtual PrefService* GetPrefs(); void ResetTabRestoreService() { } + SpellChecker* GetSpellChecker() { return NULL; } + VisitedLinkMaster* GetVisitedLinkMaster() { return NULL; } TabRestoreService* GetTabRestoreService() { return NULL; } SessionService* GetSessionService() { return NULL; } + UserScriptMaster* GetUserScriptMaster() { return NULL; } bool IsOffTheRecord() { return false; } URLRequestContext* GetRequestContext() { return NULL; } virtual Profile* GetOriginalProfile() { return this; } virtual Profile* GetOffTheRecordProfile() { return this; } bool HasSessionService() { return false; } + std::wstring GetID() { return L""; } + HistoryService* GetHistoryService(ServiceAccessType access) { + return &history_service_; + } + private: std::wstring GetPrefFilePath(); std::wstring path_; scoped_ptr<PrefService> prefs_; + HistoryService history_service_; }; class ProfileManager : NonThreadSafe { |