summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-12-12 20:12:38 +0000
committerestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-12-12 20:12:38 +0000
commit45cbfb0444d2ae27d9dbc9880c547c0d42978782 (patch)
tree3f5a3477831c68b73f87365c8222b3033758358a
parentf33651e32ab77d1413e01f5fed1e90f5b36f7534 (diff)
downloadchromium_src-45cbfb0444d2ae27d9dbc9880c547c0d42978782.zip
chromium_src-45cbfb0444d2ae27d9dbc9880c547c0d42978782.tar.gz
chromium_src-45cbfb0444d2ae27d9dbc9880c547c0d42978782.tar.bz2
Add a MemoryMappedFile class to file_util.
Factor out windowisms from the spell checker. Review URL: http://codereview.chromium.org/14041 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@6919 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--base/file_util.h39
-rw-r--r--base/file_util_win.cc66
-rw-r--r--chrome/browser/spellchecker.cc56
-rw-r--r--chrome/browser/spellchecker.h12
4 files changed, 115 insertions, 58 deletions
diff --git a/base/file_util.h b/base/file_util.h
index 7bc7e820..854703f 100644
--- a/base/file_util.h
+++ b/base/file_util.h
@@ -305,7 +305,6 @@ bool GetFileInfo(const FilePath& file_path, FileInfo* info);
// Deprecated temporary compatibility function.
bool GetFileInfo(const std::wstring& file_path, FileInfo* info);
-
// Wrapper for fopen-like calls. Returns non-NULL FILE* on success.
FILE* OpenFile(const FilePath& filename, const char* mode);
// Deprecated temporary compatibility functions.
@@ -415,6 +414,44 @@ class FileEnumerator {
DISALLOW_EVIL_CONSTRUCTORS(FileEnumerator);
};
+// TODO(port): port this class to posix.
+#if defined(OS_WIN)
+class MemoryMappedFile {
+ public:
+ // The default constructor sets all members to invalid/null values.
+ MemoryMappedFile();
+ ~MemoryMappedFile();
+
+ // Opens an existing file and maps it into memory. Access is restricted to
+ // read only. If this object already points to a valid memory mapped file
+ // then this method will fail and return false. If it cannot open the file,
+ // the file does not exist, or the memory mapping fails, it will return false.
+ // Later we may want to allow the user to specify access.
+ bool Initialize(const FilePath& file_name);
+
+ const uint8* Data() const { return data_; }
+ size_t Length() const { return length_; }
+
+ // Is file_ a valid file handle that points to an open, memory mapped file?
+ bool IsValid();
+
+ private:
+ // Map the file to memory, set data_ to that memory address. Return true on
+ // success, false on any kind of failure. This is a helper for Initialize().
+ bool MapFileToMemory(const FilePath& file_name);
+
+ // Closes all open handles. Later we may want to make this public.
+ void CloseHandles();
+
+ HANDLE file_;
+ HANDLE file_mapping_;
+ const uint8* data_;
+ size_t length_;
+
+ DISALLOW_COPY_AND_ASSIGN(MemoryMappedFile);
+};
+#endif // defined(OS_WIN)
+
// Renames a file using the SHFileOperation API to ensure that the target file
// gets the correct default security descriptor in the new path.
bool RenameFileAndResetSecurityDescriptor(
diff --git a/base/file_util_win.cc b/base/file_util_win.cc
index db22fa3..c287129 100644
--- a/base/file_util_win.cc
+++ b/base/file_util_win.cc
@@ -595,7 +595,7 @@ bool SetCurrentDirectory(const FilePath& directory) {
}
///////////////////////////////////////////////
-
+// FileEnumerator
FileEnumerator::FileEnumerator(const FilePath& root_path,
bool recursive,
@@ -694,6 +694,70 @@ FilePath FileEnumerator::Next() {
return (file_type_ & FileEnumerator::FILES) ? cur_file : Next();
}
+///////////////////////////////////////////////
+// MemoryMappedFile
+
+MemoryMappedFile::MemoryMappedFile()
+ : file_(INVALID_HANDLE_VALUE),
+ file_mapping_(INVALID_HANDLE_VALUE),
+ data_(NULL),
+ length_(INVALID_FILE_SIZE) {
+}
+
+MemoryMappedFile::~MemoryMappedFile() {
+ CloseHandles();
+}
+
+bool MemoryMappedFile::Initialize(const FilePath& file_name) {
+ if (IsValid())
+ return false;
+
+ if (!MapFileToMemory(file_name)) {
+ CloseHandles();
+ return false;
+ }
+
+ return true;
+}
+
+bool MemoryMappedFile::MapFileToMemory(const FilePath& file_name) {
+ file_ = ::CreateFile(file_name.value().c_str(), GENERIC_READ,
+ FILE_SHARE_READ, NULL, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+ if (file_ == INVALID_HANDLE_VALUE)
+ return false;
+
+ length_ = ::GetFileSize(file_, NULL);
+ if (length_ == INVALID_FILE_SIZE)
+ return false;
+
+ file_mapping_ = ::CreateFileMapping(file_, NULL, PAGE_READONLY,
+ 0, length_, NULL);
+ if (file_mapping_ == INVALID_HANDLE_VALUE)
+ return false;
+
+ data_ = reinterpret_cast<const uint8*>(
+ ::MapViewOfFile(file_mapping_, FILE_MAP_READ, 0, 0, length_));
+ return data_ != NULL;
+}
+
+bool MemoryMappedFile::IsValid() {
+ return data_ != NULL;
+}
+
+void MemoryMappedFile::CloseHandles() {
+ if (data_)
+ ::UnmapViewOfFile(data_);
+ if (file_mapping_ != INVALID_HANDLE_VALUE)
+ ::CloseHandle(file_mapping_);
+ if (file_ != INVALID_HANDLE_VALUE)
+ ::CloseHandle(file_);
+
+ data_ = NULL;
+ file_mapping_ = file_ = INVALID_HANDLE_VALUE;
+ length_ = INVALID_FILE_SIZE;
+}
+
// Deprecated functions ----------------------------------------------------
void InsertBeforeExtension(std::wstring* path_str,
diff --git a/chrome/browser/spellchecker.cc b/chrome/browser/spellchecker.cc
index 2598ad3..004c39b 100644
--- a/chrome/browser/spellchecker.cc
+++ b/chrome/browser/spellchecker.cc
@@ -346,10 +346,6 @@ SpellChecker::SpellChecker(const std::wstring& dict_dir,
URLRequestContext* request_context,
const std::wstring& custom_dictionary_file_name)
: custom_dictionary_file_name_(custom_dictionary_file_name),
- bdict_file_(NULL),
- bdict_mapping_(NULL),
- bdict_mapped_data_(NULL),
- hunspell_(NULL),
tried_to_init_(false),
#ifndef NDEBUG
worker_loop_(NULL),
@@ -393,15 +389,6 @@ SpellChecker::~SpellChecker() {
if (worker_loop_)
DCHECK(MessageLoop::current() == worker_loop_);
#endif
-
- delete hunspell_;
-
- if (bdict_mapped_data_)
- UnmapViewOfFile(bdict_mapped_data_);
- if (bdict_mapping_)
- CloseHandle(bdict_mapping_);
- if (bdict_file_)
- CloseHandle(bdict_file_);
}
// Initialize SpellChecker. In this method, if the dicitonary is not present
@@ -417,7 +404,7 @@ bool SpellChecker::Initialize() {
// Return false if tried to init and failed - don't try multiple times in
// this session.
if (tried_to_init_)
- return hunspell_ != NULL;
+ return hunspell_.get() != NULL;
StatsScope<StatsCounterTimer> timer(chrome::Counters::spellcheck_init());
@@ -441,10 +428,9 @@ bool SpellChecker::Initialize() {
// Control has come so far - both files probably exist.
TimeTicks begin_time = TimeTicks::Now();
- const unsigned char* bdict_data;
- size_t bdict_length;
- if (MapBdictFile(&bdict_data, &bdict_length)) {
- hunspell_ = new Hunspell(bdict_data, bdict_length);
+ bdict_file_.reset(new file_util::MemoryMappedFile());
+ if (bdict_file_->Initialize(FilePath::FromWStringHack(bdict_file_name_))) {
+ hunspell_.reset(new Hunspell(bdict_file_->Data(), bdict_file_->Length()));
AddCustomWordsToHunspell();
}
DHISTOGRAM_TIMES(L"Spellcheck.InitTime", TimeTicks::Now() - begin_time);
@@ -462,7 +448,7 @@ void SpellChecker::AddCustomWordsToHunspell() {
file_util::ReadFileToString(custom_dictionary_file_name_, &contents);
std::vector<std::string> list_of_words;
SplitString(contents, '\n', &list_of_words);
- if (hunspell_) {
+ if (hunspell_.get()) {
for (std::vector<std::string>::iterator it = list_of_words.begin();
it != list_of_words.end(); ++it) {
hunspell_->put_word(it->c_str());
@@ -470,36 +456,6 @@ void SpellChecker::AddCustomWordsToHunspell() {
}
}
-bool SpellChecker::MapBdictFile(const unsigned char** data, size_t* length) {
- bdict_file_ = CreateFile(bdict_file_name_.c_str(), GENERIC_READ,
- FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (bdict_file_ == INVALID_HANDLE_VALUE)
- return false;
-
- DWORD size = GetFileSize(bdict_file_, NULL);
- bdict_mapping_ =
- CreateFileMapping(bdict_file_, NULL, PAGE_READONLY, 0, size, NULL);
- if (!bdict_mapping_) {
- CloseHandle(bdict_file_);
- bdict_file_ = NULL;
- return false;
- }
-
- bdict_mapped_data_ = reinterpret_cast<const unsigned char*>(
- MapViewOfFile(bdict_mapping_, FILE_MAP_READ, 0, 0, size));
- if (!data) {
- CloseHandle(bdict_mapping_);
- bdict_mapping_ = NULL;
- CloseHandle(bdict_file_);
- bdict_file_ = NULL;
- return false;
- }
-
- *data = bdict_mapped_data_;
- *length = size;
- return true;
-}
-
// Returns whether or not the given string is a valid contraction.
// This function is a fall-back when the SpellcheckWordIterator class
// returns a concatenated word which is not in the selected dictionary
@@ -545,7 +501,7 @@ bool SpellChecker::SpellCheckWord(
if (in_word_len == 0)
return true; // no input means always spelled correctly
- if (!hunspell_)
+ if (!hunspell_.get())
return true; // unable to spellcheck, return word is OK
SpellcheckWordIterator word_iterator;
diff --git a/chrome/browser/spellchecker.h b/chrome/browser/spellchecker.h
index 45eb73d..921a08e 100644
--- a/chrome/browser/spellchecker.h
+++ b/chrome/browser/spellchecker.h
@@ -24,6 +24,9 @@ class Profile;
class MessageLoop;
class URLRequestContext;
+namespace file_util {
+class MemoryMappedFile;
+}
// The Browser's Spell Checker. It checks and suggests corrections.
//
@@ -119,14 +122,11 @@ class SpellChecker : public base::RefCountedThreadSafe<SpellChecker> {
// Path to the custom dictionary file.
std::wstring custom_dictionary_file_name_;
- // We memory-map the BDict file for spellchecking. These are the handles
- // necessary for that.
- HANDLE bdict_file_;
- HANDLE bdict_mapping_;
- const unsigned char* bdict_mapped_data_;
+ // We memory-map the BDict file.
+ scoped_ptr<file_util::MemoryMappedFile> bdict_file_;
// The hunspell dictionary in use.
- Hunspell* hunspell_;
+ scoped_ptr<Hunspell> hunspell_;
// Represents character attributes used for filtering out characters which
// are not supported by this SpellChecker object.