| Index: chrome/browser/spellchecker.cc
|
| ===================================================================
|
| --- chrome/browser/spellchecker.cc (revision 30650)
|
| +++ chrome/browser/spellchecker.cc (working copy)
|
| @@ -13,8 +13,6 @@
|
| #include "base/path_service.h"
|
| #include "base/stats_counters.h"
|
| #include "base/string_util.h"
|
| -#include "base/thread.h"
|
| -#include "chrome/browser/browser_process.h"
|
| #include "chrome/browser/chrome_thread.h"
|
| #include "chrome/browser/net/url_fetcher.h"
|
| #include "chrome/browser/profile.h"
|
| @@ -95,59 +93,15 @@
|
|
|
| } // namespace
|
|
|
| -// This is a helper class which acts as a proxy for invoking a task from the
|
| -// file loop back to the IO loop. Invoking a task from file loop to the IO
|
| -// loop directly is not safe as during browser shutdown, the IO loop tears
|
| -// down before the file loop. To avoid a crash, this object is invoked in the
|
| -// UI loop from the file loop, from where it gets the IO thread directly from
|
| -// g_browser_process and invokes the given task in the IO loop if it is not
|
| -// NULL. This object also takes ownership of the given task.
|
| -class UIProxyForIOTask : public Task {
|
| - public:
|
| - explicit UIProxyForIOTask(Task* callback_task, SpellChecker* spellchecker)
|
| - : callback_task_(callback_task),
|
| - spellchecker_(spellchecker) {
|
| - }
|
| -
|
| - private:
|
| - void Run();
|
| -
|
| - Task* callback_task_;
|
| - // The SpellChecker that invoked the file loop task. May be NULL. If not
|
| - // NULL, then we will Release() on it if we don't run |callback_task_|. This
|
| - // balances any refs the spellchecker might have had outstanding which it
|
| - // would have Released() when |callback_task_| was run.
|
| - SpellChecker* spellchecker_;
|
| - DISALLOW_COPY_AND_ASSIGN(UIProxyForIOTask);
|
| -};
|
| -
|
| -void UIProxyForIOTask::Run() {
|
| - // This has been invoked in the UI thread.
|
| - base::Thread* io_thread = g_browser_process->io_thread();
|
| - if (io_thread) { // io_thread has not been torn down yet.
|
| - MessageLoop* io_loop = io_thread->message_loop();
|
| - io_loop->PostTask(FROM_HERE, callback_task_);
|
| - } else {
|
| - if (spellchecker_)
|
| - spellchecker_->Release();
|
| - delete callback_task_;
|
| - }
|
| -
|
| - callback_task_ = NULL;
|
| -}
|
| -
|
| // Design: The spellchecker initializes hunspell_ in the Initialize() method.
|
| // This is done using the dictionary file on disk, e.g. "en-US_1_1.bdic".
|
| // Initialization of hunspell_ is held off during this process. If the
|
| // dictionary is not available, we first attempt to download and save it. After
|
| // the dictionary is downloaded and saved to disk (or the attempt to do so
|
| -// fails)), corresponding flags are set
|
| -// in spellchecker - in the IO thread. Since IO thread goes first during closing
|
| -// of browser, a proxy task |UIProxyForIOTask| is created in the UI thread,
|
| -// which obtains the IO thread independently and invokes the task in the IO
|
| -// thread if it's not NULL. After the flags are cleared, a (final) attempt is
|
| -// made to initialize hunspell_. If it fails even then (dictionary could not
|
| -// download), no more attempts are made to initialize it.
|
| +// fails)), corresponding flags are set in spellchecker - in the IO thread.
|
| +// After the flags are cleared, a (final) attempt is made to initialize
|
| +// hunspell_. If it fails even then (dictionary could not download), no more
|
| +// attempts are made to initialize it.
|
| class SaveDictionaryTask : public Task {
|
| public:
|
| SaveDictionaryTask(Task* on_dictionary_save_complete_callback_task,
|
| @@ -201,13 +155,12 @@
|
|
|
| // Set Flag that dictionary is not downloading anymore.
|
| ChromeThread::PostTask(
|
| - ChromeThread::UI, FROM_HERE,
|
| - new UIProxyForIOTask(on_dictionary_save_complete_callback_task_, NULL));
|
| + ChromeThread::IO, FROM_HERE, on_dictionary_save_complete_callback_task_);
|
| }
|
|
|
| // Design: this task tries to read the dictionary from disk and load it into
|
| // memory. It is executed on the file thread, and posts the results back to
|
| -// the IO thread (via the UI thread---see UIProxyForIOTask).
|
| +// the IO thread.
|
| // The task first checks for the existence of the dictionary in one of the two
|
| // given locations. If it does not exist, the task informs the SpellChecker,
|
| // which will try to download the directory and run a new ReadDictionaryTask.
|
| @@ -265,21 +218,11 @@
|
|
|
| private:
|
| void Finish(bool file_existed) {
|
| - Task* task = NewRunnableMethod(spellchecker_, &SpellChecker::HunspellInited,
|
| - hunspell_, bdict_file_, file_existed);
|
| - if (spellchecker_->file_loop_) {
|
| - // We were called on the file loop. Post back to the IO loop.
|
| - // If this never gets posted to the IO loop, then we will leak |hunspell_|
|
| - // and |bdict_file_|. But that can only happen during shutdown, so it's
|
| - // not worth caring about.
|
| - ChromeThread::PostTask(
|
| - ChromeThread::UI, FROM_HERE,
|
| - new UIProxyForIOTask(task, spellchecker_));
|
| - } else {
|
| - // We were called directly (e.g., during testing). Run the task directly.
|
| - task->Run();
|
| - delete task;
|
| - }
|
| + ChromeThread::PostTask(
|
| + ChromeThread::IO, FROM_HERE,
|
| + NewRunnableMethod(
|
| + spellchecker_, &SpellChecker::HunspellInited, hunspell_,
|
| + bdict_file_, file_existed));
|
| }
|
|
|
| // The SpellChecker we are working for. We are guaranteed to be outlived
|
| @@ -470,9 +413,7 @@
|
| custom_dictionary_file_name_(custom_dictionary_file_name),
|
| tried_to_init_(false),
|
| language_(language),
|
| - worker_loop_(NULL),
|
| tried_to_download_dictionary_file_(false),
|
| - file_loop_(NULL),
|
| request_context_getter_(request_context_getter),
|
| obtaining_dictionary_(false),
|
| auto_spell_correct_turned_on_(false),
|
| @@ -492,11 +433,6 @@
|
| // Get the corresponding BDIC file name.
|
| bdic_file_name_ = GetVersionedFileName(language, dict_dir).BaseName();
|
|
|
| - // Get File Loop - hunspell gets initialized here.
|
| - base::Thread* file_thread = g_browser_process->file_thread();
|
| - if (file_thread)
|
| - file_loop_ = file_thread->message_loop();
|
| -
|
| // Get the path to the custom dictionary file.
|
| if (custom_dictionary_file_name_.empty()) {
|
| FilePath personal_file_directory;
|
| @@ -511,11 +447,7 @@
|
| }
|
|
|
| SpellChecker::~SpellChecker() {
|
| - // This must be deleted on the I/O thread (see the header). This is the same
|
| - // thread that SpellCheckWord is called on, so we verify that they were all
|
| - // the same thread.
|
| - if (worker_loop_)
|
| - DCHECK(MessageLoop::current() == worker_loop_);
|
| + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
|
| }
|
|
|
| void SpellChecker::StartDictionaryDownload(const FilePath& file_name) {
|
| @@ -558,8 +490,10 @@
|
| FilePath fallback_file_name = user_data_dir.Append(bdic_file_name_);
|
| Task* dic_task = method_factory_.
|
| NewRunnableMethod(&SpellChecker::OnDictionarySaveComplete);
|
| - file_loop_->PostTask(FROM_HERE, new SaveDictionaryTask(dic_task,
|
| - first_attempt_file_name, fallback_file_name, data));
|
| + ChromeThread::PostTask(
|
| + ChromeThread::FILE, FROM_HERE,
|
| + new SaveDictionaryTask(
|
| + dic_task, first_attempt_file_name, fallback_file_name, data));
|
| }
|
|
|
| void SpellChecker::OnDictionarySaveComplete() {
|
| @@ -571,10 +505,7 @@
|
| // Initialize SpellChecker. In this method, if the dictionary is not present
|
| // in the local disk, it is fetched asynchronously.
|
| bool SpellChecker::Initialize() {
|
| - if (!worker_loop_)
|
| - worker_loop_ = MessageLoop::current();
|
| - else
|
| - DCHECK(worker_loop_ == MessageLoop::current());
|
| + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
|
|
|
| // Return false if the dictionary files are downloading.
|
| if (obtaining_dictionary_)
|
| @@ -606,17 +537,12 @@
|
| FilePath dictionary_file_name_usr = GetVersionedFileName(language_,
|
| dict_dir_userdata);
|
|
|
| - // Balances Release() in HunspellInited(), or in UIProxyForIOTask if the IO
|
| - // thread is torn down before the ReadDictionaryTask calls us back.
|
| + // Balances Release() in HunspellInited().
|
| AddRef();
|
| - Task* task = new ReadDictionaryTask(this,
|
| - dictionary_file_name_app, dictionary_file_name_usr);
|
| - if (file_loop_) {
|
| - file_loop_->PostTask(FROM_HERE, task);
|
| - } else {
|
| - task->Run();
|
| - delete task;
|
| - }
|
| + ChromeThread::PostTask(
|
| + ChromeThread::FILE, FROM_HERE,
|
| + new ReadDictionaryTask(
|
| + this, dictionary_file_name_app, dictionary_file_name_usr));
|
|
|
| return hunspell_.get() != NULL;
|
| }
|
| @@ -624,7 +550,7 @@
|
| void SpellChecker::HunspellInited(Hunspell* hunspell,
|
| file_util::MemoryMappedFile* bdict_file,
|
| bool file_existed) {
|
| - DCHECK(worker_loop_ == MessageLoop::current());
|
| + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
|
|
|
| if (file_existed)
|
| tried_to_init_ = true;
|
| @@ -655,7 +581,7 @@
|
|
|
| void SpellChecker::DoDictionaryDownload() {
|
| // Download the dictionary file.
|
| - if (file_loop_ && request_context_getter_) {
|
| + if (request_context_getter_) {
|
| if (!tried_to_download_dictionary_file_) {
|
| FilePath dictionary_file_name_app = GetVersionedFileName(language_,
|
| given_dictionary_directory_);
|
| @@ -750,8 +676,7 @@
|
| DCHECK(misspelling_start && misspelling_len) << "Out vars must be given.";
|
|
|
| // This must always be called on the same thread (normally the I/O thread).
|
| - if (worker_loop_)
|
| - DCHECK(MessageLoop::current() == worker_loop_);
|
| + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
|
|
|
| // Check if the platform spellchecker is being used.
|
| if (!is_using_platform_spelling_engine_) {
|
| @@ -850,14 +775,9 @@
|
| }
|
|
|
| // Now add the word to the custom dictionary file.
|
| - Task* write_word_task =
|
| - new AddWordToCustomDictionaryTask(custom_dictionary_file_name_, word);
|
| - if (file_loop_) {
|
| - file_loop_->PostTask(FROM_HERE, write_word_task);
|
| - } else {
|
| - write_word_task->Run();
|
| - delete write_word_task;
|
| - }
|
| + ChromeThread::PostTask(
|
| + ChromeThread::FILE, FROM_HERE,
|
| + new AddWordToCustomDictionaryTask(custom_dictionary_file_name_, word));
|
| }
|
|
|
| bool SpellChecker::CheckSpelling(const string16& word_to_check, int tag) {
|
|
|