blob: fa1b156cb160322f0263cfd0cd9c956e6821794a [file] [log] [blame]
// Copyright (c) 2006-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 CHROME_BROWSER_SPELLCHECKER_H_
#define CHROME_BROWSER_SPELLCHECKER_H_
#include <vector>
#include <string>
#include "app/l10n_util.h"
#include "base/string_util.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/net/url_fetcher.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/spellcheck_worditerator.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/pref_member.h"
#include "base/task.h"
#include "unicode/uscript.h"
class FilePath;
class Hunspell;
class PrefService;
class Profile;
class MessageLoop;
class URLRequestContext;
class URLFetcher;
namespace file_util {
class MemoryMappedFile;
}
// The Browser's Spell Checker. It checks and suggests corrections.
//
// This object is not threadsafe. In normal usage (not unit tests) it lives on
// the I/O thread of the browser. It is threadsafe refcounted so that I/O thread
// and the profile on the main thread (which gives out references to it) can
// keep it. However, all usage of this must be on the I/O thread.
//
// This object should also be deleted on the I/O thread only. It owns a
// reference to URLRequestContext which in turn owns the cache, etc. and must be
// deleted on the I/O thread itself.
class SpellChecker : public base::RefCountedThreadSafe<SpellChecker>,
public URLFetcher::Delegate {
public:
// Creates the spellchecker by reading dictionaries from the given directory,
// and defaulting to the given language. Both strings must be provided.
//
// The request context is used to download dictionaries if they do not exist.
// This can be NULL if you don't want this (like in tests).
// The |custom_dictionary_file_name| should be left blank so that Spellchecker
// can figure out the custom dictionary file. It is non empty only for unit
// testing.
SpellChecker(const FilePath& dict_dir,
const std::string& language,
URLRequestContext* request_context,
const FilePath& custom_dictionary_file_name);
// Only delete on the I/O thread (see above).
~SpellChecker();
// SpellCheck a word.
// Returns true if spelled correctly, false otherwise.
// If the spellchecker failed to initialize, always returns true.
// In addition, finds the suggested words for a given word
// and puts them into |*optional_suggestions|.
// If the word is spelled correctly, the vector is empty.
// If optional_suggestions is NULL, suggested words will not be looked up.
// Note that Doing suggest lookups can be slow.
bool SpellCheckWord(const wchar_t* in_word,
int in_word_len,
int* misspelling_start,
int* misspelling_len,
std::vector<std::wstring>* optional_suggestions);
// Find a possible correctly spelled word for a misspelled word. Computes an
// empty string if input misspelled word is too long, there is ambiguity, or
// the correct spelling cannot be determined.
void GetAutoCorrectionWord(const std::wstring& word,
std::wstring* autocorrect_word);
// Turn auto spell correct support ON or OFF.
// |turn_on| = true means turn ON; false means turn OFF.
void EnableAutoSpellCorrect(bool turn_on);
// Add custom word to the dictionary, which means:
// a) Add it to the current hunspell object for immediate use,
// b) Add the word to a file in disk for custom dictionary.
void AddWord(const std::wstring& word);
// Get SpellChecker supported languages.
static void SpellCheckLanguages(std::vector<std::string>* languages);
// This function computes a vector of strings which are to be displayed in
// the context menu over a text area for changing spell check languages. It
// returns the index of the current spell check language in the vector.
// TODO(port): this should take a vector of string16, but the implementation
// has some dependencies in l10n util that need porting first.
static int GetSpellCheckLanguages(
Profile* profile,
std::vector<std::string>* languages);
// This function returns the corresponding language-region code for the
// spell check language. For example, for hi, it returns hi-IN.
static std::string GetSpellCheckLanguageRegion(std::string input_language);
// This function returns ll (language code) from ll-RR where 'RR' (region
// code) is redundant. However, if the region code matters, it's preserved.
// That is, it returns 'hi' and 'en-GB' for 'hi-IN' and 'en-GB' respectively.
static std::string GetLanguageFromLanguageRegion(std::string input_language);
private:
// URLFetcher::Delegate implementation. Called when we finish downloading the
// spellcheck dictionary; saves the dictionary to disk.
// TODO(sidchat): Save to disk in the file thread instead of the IO thread.
virtual void OnURLFetchComplete(const URLFetcher* source,
const GURL& url,
const URLRequestStatus& status,
int response_code,
const ResponseCookies& cookies,
const std::string& data);
// When called, relays the request to check the spelling to the proper
// backend, either hunspell or a platform-specific backend.
bool CheckSpelling(const std::string& word_to_check);
// When called, relays the request to fill the list with suggestions to
// the proper backend, either hunspell or a platform-specific backend.
void FillSuggestionList(const std::string& wrong_word,
std::vector<std::wstring>* optional_suggestions);
// Initializes the Hunspell Dictionary.
bool Initialize();
// After |hunspell_| is initialized, this function is called to add custom
// words from the custom dictionary to the |hunspell_|.
void AddCustomWordsToHunspell();
// Memory maps the given .bdic file. On success, it will return true and will
// place the data and length into the given out parameters.
bool MapBdictFile(const unsigned char** data, size_t* length);
// Returns whether or not the given word is a contraction of valid words
// (e.g. "word:word").
bool IsValidContraction(const string16& word);
// Return the file name of the dictionary, including the path and the version
// numbers.
FilePath GetVersionedFileName(const std::string& language,
const FilePath& dict_dir);
static std::string GetCorrespondingSpellCheckLanguage(
const std::string& language);
// Start downloading a dictionary from the server. On completion, the
// OnURLFetchComplete() function is invoked.
void StartDictionaryDownload(const FilePath& file_name);
// This method is called in the IO thread after dictionary download has
// completed in FILE thread.
void OnDictionarySaveComplete(){ obtaining_dictionary_ = false; }
// The given path to the directory whether SpellChecker first tries to
// download the spellcheck bdic dictionary file.
FilePath given_dictionary_directory_;
// Path to the custom dictionary file.
FilePath custom_dictionary_file_name_;
// BDIC file name (e.g. en-US_1_1.bdic).
FilePath bdic_file_name_;
// We memory-map the BDict file.
scoped_ptr<file_util::MemoryMappedFile> bdict_file_;
// The hunspell dictionary in use.
scoped_ptr<Hunspell> hunspell_;
// Represents character attributes used for filtering out characters which
// are not supported by this SpellChecker object.
SpellcheckCharAttribute character_attributes_;
// Flag indicating whether we've tried to initialize. If we've already
// attempted initialiation, we won't retry to avoid failure loops.
bool tried_to_init_;
// The language that this spellchecker works in.
std::string language_;
#ifndef NDEBUG
// This object must only be used on the same thread. However, it is normally
// created on the UI thread. This checks calls to SpellCheckWord and the
// destructor to make sure we're only ever running on the same thread.
//
// This will be NULL if it is not initialized yet (not initialized in the
// constructor since that's on a different thread.
MessageLoop* worker_loop_;
#endif
// Flag indicating whether we tried to download the dictionary file.
bool tried_to_download_dictionary_file_;
// File Thread Message Loop.
MessageLoop* file_loop_;
// UI Thread Message Loop.
MessageLoop* ui_loop_;
// Used for requests. MAY BE NULL which means don't try to download.
URLRequestContext* url_request_context_;
// True when we're downloading or saving a dictionary.
bool obtaining_dictionary_;
// Remember state for auto spell correct.
bool auto_spell_correct_turned_on_;
// True if a platform-specific spellchecking engine is being used,
// and False if hunspell is being used.
bool is_using_platform_spelling_engine_;
// URLFetcher to download a file in memory.
scoped_ptr<URLFetcher> fetcher_;
// Used for generating callbacks to spellchecker, since spellchecker is a
// non-reference counted object.
ScopedRunnableMethodFactory<SpellChecker>
on_dictionary_save_complete_callback_factory_;
DISALLOW_COPY_AND_ASSIGN(SpellChecker);
};
#endif // CHROME_BROWSER_SPELLCHECKER_H_