Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(112)

Side by Side Diff: chrome/browser/spellchecker.cc

Issue 342068: Third patch in getting rid of caching MessageLoop pointers and always using C... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/spellchecker.h ('k') | chrome/browser/strict_transport_security_persister.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/spellchecker.h" 5 #include "chrome/browser/spellchecker.h"
6 6
7 #include "app/l10n_util.h" 7 #include "app/l10n_util.h"
8 #include "base/basictypes.h" 8 #include "base/basictypes.h"
9 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 #include "base/file_util.h" 10 #include "base/file_util.h"
11 #include "base/histogram.h" 11 #include "base/histogram.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/path_service.h" 13 #include "base/path_service.h"
14 #include "base/stats_counters.h" 14 #include "base/stats_counters.h"
15 #include "base/string_util.h" 15 #include "base/string_util.h"
16 #include "base/thread.h"
17 #include "chrome/browser/browser_process.h"
18 #include "chrome/browser/chrome_thread.h" 16 #include "chrome/browser/chrome_thread.h"
19 #include "chrome/browser/net/url_fetcher.h" 17 #include "chrome/browser/net/url_fetcher.h"
20 #include "chrome/browser/profile.h" 18 #include "chrome/browser/profile.h"
21 #include "chrome/browser/spellchecker_common.h" 19 #include "chrome/browser/spellchecker_common.h"
22 #include "chrome/browser/spellchecker_platform_engine.h" 20 #include "chrome/browser/spellchecker_platform_engine.h"
23 #include "chrome/common/chrome_constants.h" 21 #include "chrome/common/chrome_constants.h"
24 #include "chrome/common/chrome_counters.h" 22 #include "chrome/common/chrome_counters.h"
25 #include "chrome/common/chrome_paths.h" 23 #include "chrome/common/chrome_paths.h"
26 #include "chrome/common/pref_names.h" 24 #include "chrome/common/pref_names.h"
27 #include "chrome/common/pref_service.h" 25 #include "chrome/common/pref_service.h"
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 86
89 bool SaveBufferToFile(const std::string& data, 87 bool SaveBufferToFile(const std::string& data,
90 FilePath file_to_write) { 88 FilePath file_to_write) {
91 int num_bytes = data.length(); 89 int num_bytes = data.length();
92 return file_util::WriteFile(file_to_write, data.data(), num_bytes) == 90 return file_util::WriteFile(file_to_write, data.data(), num_bytes) ==
93 num_bytes; 91 num_bytes;
94 } 92 }
95 93
96 } // namespace 94 } // namespace
97 95
98 // This is a helper class which acts as a proxy for invoking a task from the
99 // file loop back to the IO loop. Invoking a task from file loop to the IO
100 // loop directly is not safe as during browser shutdown, the IO loop tears
101 // down before the file loop. To avoid a crash, this object is invoked in the
102 // UI loop from the file loop, from where it gets the IO thread directly from
103 // g_browser_process and invokes the given task in the IO loop if it is not
104 // NULL. This object also takes ownership of the given task.
105 class UIProxyForIOTask : public Task {
106 public:
107 explicit UIProxyForIOTask(Task* callback_task, SpellChecker* spellchecker)
108 : callback_task_(callback_task),
109 spellchecker_(spellchecker) {
110 }
111
112 private:
113 void Run();
114
115 Task* callback_task_;
116 // The SpellChecker that invoked the file loop task. May be NULL. If not
117 // NULL, then we will Release() on it if we don't run |callback_task_|. This
118 // balances any refs the spellchecker might have had outstanding which it
119 // would have Released() when |callback_task_| was run.
120 SpellChecker* spellchecker_;
121 DISALLOW_COPY_AND_ASSIGN(UIProxyForIOTask);
122 };
123
124 void UIProxyForIOTask::Run() {
125 // This has been invoked in the UI thread.
126 base::Thread* io_thread = g_browser_process->io_thread();
127 if (io_thread) { // io_thread has not been torn down yet.
128 MessageLoop* io_loop = io_thread->message_loop();
129 io_loop->PostTask(FROM_HERE, callback_task_);
130 } else {
131 if (spellchecker_)
132 spellchecker_->Release();
133 delete callback_task_;
134 }
135
136 callback_task_ = NULL;
137 }
138
139 // Design: The spellchecker initializes hunspell_ in the Initialize() method. 96 // Design: The spellchecker initializes hunspell_ in the Initialize() method.
140 // This is done using the dictionary file on disk, e.g. "en-US_1_1.bdic". 97 // This is done using the dictionary file on disk, e.g. "en-US_1_1.bdic".
141 // Initialization of hunspell_ is held off during this process. If the 98 // Initialization of hunspell_ is held off during this process. If the
142 // dictionary is not available, we first attempt to download and save it. After 99 // dictionary is not available, we first attempt to download and save it. After
143 // the dictionary is downloaded and saved to disk (or the attempt to do so 100 // the dictionary is downloaded and saved to disk (or the attempt to do so
144 // fails)), corresponding flags are set 101 // fails)), corresponding flags are set in spellchecker - in the IO thread.
145 // in spellchecker - in the IO thread. Since IO thread goes first during closing 102 // After the flags are cleared, a (final) attempt is made to initialize
146 // of browser, a proxy task |UIProxyForIOTask| is created in the UI thread, 103 // hunspell_. If it fails even then (dictionary could not download), no more
147 // which obtains the IO thread independently and invokes the task in the IO 104 // attempts are made to initialize it.
148 // thread if it's not NULL. After the flags are cleared, a (final) attempt is
149 // made to initialize hunspell_. If it fails even then (dictionary could not
150 // download), no more attempts are made to initialize it.
151 class SaveDictionaryTask : public Task { 105 class SaveDictionaryTask : public Task {
152 public: 106 public:
153 SaveDictionaryTask(Task* on_dictionary_save_complete_callback_task, 107 SaveDictionaryTask(Task* on_dictionary_save_complete_callback_task,
154 const FilePath& first_attempt_file_name, 108 const FilePath& first_attempt_file_name,
155 const FilePath& fallback_file_name, 109 const FilePath& fallback_file_name,
156 const std::string& data) 110 const std::string& data)
157 : on_dictionary_save_complete_callback_task_( 111 : on_dictionary_save_complete_callback_task_(
158 on_dictionary_save_complete_callback_task), 112 on_dictionary_save_complete_callback_task),
159 first_attempt_file_name_(first_attempt_file_name), 113 first_attempt_file_name_(first_attempt_file_name),
160 fallback_file_name_(fallback_file_name), 114 fallback_file_name_(fallback_file_name),
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 // write permission. If even this fails, there is nothing to be done. 148 // write permission. If even this fails, there is nothing to be done.
195 FilePath fallback_dir = fallback_file_name_.DirName(); 149 FilePath fallback_dir = fallback_file_name_.DirName();
196 // Create the directory if it does not exist. 150 // Create the directory if it does not exist.
197 if (!file_util::PathExists(fallback_dir)) 151 if (!file_util::PathExists(fallback_dir))
198 file_util::CreateDirectory(fallback_dir); 152 file_util::CreateDirectory(fallback_dir);
199 SaveBufferToFile(data_, fallback_file_name_); 153 SaveBufferToFile(data_, fallback_file_name_);
200 } // Unsuccessful save is taken care of in SpellChecker::Initialize(). 154 } // Unsuccessful save is taken care of in SpellChecker::Initialize().
201 155
202 // Set Flag that dictionary is not downloading anymore. 156 // Set Flag that dictionary is not downloading anymore.
203 ChromeThread::PostTask( 157 ChromeThread::PostTask(
204 ChromeThread::UI, FROM_HERE, 158 ChromeThread::IO, FROM_HERE, on_dictionary_save_complete_callback_task_);
205 new UIProxyForIOTask(on_dictionary_save_complete_callback_task_, NULL));
206 } 159 }
207 160
208 // Design: this task tries to read the dictionary from disk and load it into 161 // Design: this task tries to read the dictionary from disk and load it into
209 // memory. It is executed on the file thread, and posts the results back to 162 // memory. It is executed on the file thread, and posts the results back to
210 // the IO thread (via the UI thread---see UIProxyForIOTask). 163 // the IO thread.
211 // The task first checks for the existence of the dictionary in one of the two 164 // The task first checks for the existence of the dictionary in one of the two
212 // given locations. If it does not exist, the task informs the SpellChecker, 165 // given locations. If it does not exist, the task informs the SpellChecker,
213 // which will try to download the directory and run a new ReadDictionaryTask. 166 // which will try to download the directory and run a new ReadDictionaryTask.
214 class ReadDictionaryTask : public Task { 167 class ReadDictionaryTask : public Task {
215 public: 168 public:
216 ReadDictionaryTask(SpellChecker* spellchecker, 169 ReadDictionaryTask(SpellChecker* spellchecker,
217 const FilePath& dict_file_name_app, 170 const FilePath& dict_file_name_app,
218 const FilePath& dict_file_name_usr) 171 const FilePath& dict_file_name_usr)
219 : spellchecker_(spellchecker), 172 : spellchecker_(spellchecker),
220 hunspell_(NULL), 173 hunspell_(NULL),
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 } else { 211 } else {
259 delete bdict_file_; 212 delete bdict_file_;
260 bdict_file_ = NULL; 213 bdict_file_ = NULL;
261 } 214 }
262 215
263 Finish(true); 216 Finish(true);
264 } 217 }
265 218
266 private: 219 private:
267 void Finish(bool file_existed) { 220 void Finish(bool file_existed) {
268 Task* task = NewRunnableMethod(spellchecker_, &SpellChecker::HunspellInited, 221 ChromeThread::PostTask(
269 hunspell_, bdict_file_, file_existed); 222 ChromeThread::IO, FROM_HERE,
270 if (spellchecker_->file_loop_) { 223 NewRunnableMethod(
271 // We were called on the file loop. Post back to the IO loop. 224 spellchecker_, &SpellChecker::HunspellInited, hunspell_,
272 // If this never gets posted to the IO loop, then we will leak |hunspell_| 225 bdict_file_, file_existed));
273 // and |bdict_file_|. But that can only happen during shutdown, so it's
274 // not worth caring about.
275 ChromeThread::PostTask(
276 ChromeThread::UI, FROM_HERE,
277 new UIProxyForIOTask(task, spellchecker_));
278 } else {
279 // We were called directly (e.g., during testing). Run the task directly.
280 task->Run();
281 delete task;
282 }
283 } 226 }
284 227
285 // The SpellChecker we are working for. We are guaranteed to be outlived 228 // The SpellChecker we are working for. We are guaranteed to be outlived
286 // by this object because it AddRefs() itself before calling us. 229 // by this object because it AddRefs() itself before calling us.
287 // Accessing it is not necessarily thread safe, but are careful to only access 230 // Accessing it is not necessarily thread safe, but are careful to only access
288 // it in ways that are. 231 // it in ways that are.
289 SpellChecker* spellchecker_; 232 SpellChecker* spellchecker_;
290 Hunspell* hunspell_; 233 Hunspell* hunspell_;
291 file_util::MemoryMappedFile* bdict_file_; 234 file_util::MemoryMappedFile* bdict_file_;
292 235
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 } 406 }
464 407
465 SpellChecker::SpellChecker(const FilePath& dict_dir, 408 SpellChecker::SpellChecker(const FilePath& dict_dir,
466 const std::string& language, 409 const std::string& language,
467 URLRequestContextGetter* request_context_getter, 410 URLRequestContextGetter* request_context_getter,
468 const FilePath& custom_dictionary_file_name) 411 const FilePath& custom_dictionary_file_name)
469 : given_dictionary_directory_(dict_dir), 412 : given_dictionary_directory_(dict_dir),
470 custom_dictionary_file_name_(custom_dictionary_file_name), 413 custom_dictionary_file_name_(custom_dictionary_file_name),
471 tried_to_init_(false), 414 tried_to_init_(false),
472 language_(language), 415 language_(language),
473 worker_loop_(NULL),
474 tried_to_download_dictionary_file_(false), 416 tried_to_download_dictionary_file_(false),
475 file_loop_(NULL),
476 request_context_getter_(request_context_getter), 417 request_context_getter_(request_context_getter),
477 obtaining_dictionary_(false), 418 obtaining_dictionary_(false),
478 auto_spell_correct_turned_on_(false), 419 auto_spell_correct_turned_on_(false),
479 is_using_platform_spelling_engine_(false), 420 is_using_platform_spelling_engine_(false),
480 fetcher_(NULL), 421 fetcher_(NULL),
481 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { 422 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
482 if (SpellCheckerPlatform::SpellCheckerAvailable()) { 423 if (SpellCheckerPlatform::SpellCheckerAvailable()) {
483 SpellCheckerPlatform::Init(); 424 SpellCheckerPlatform::Init();
484 if (SpellCheckerPlatform::PlatformSupportsLanguage(language)) { 425 if (SpellCheckerPlatform::PlatformSupportsLanguage(language)) {
485 // If we have reached here, then we know that the current platform 426 // If we have reached here, then we know that the current platform
486 // supports the given language and we will use it instead of hunspell. 427 // supports the given language and we will use it instead of hunspell.
487 SpellCheckerPlatform::SetLanguage(language); 428 SpellCheckerPlatform::SetLanguage(language);
488 is_using_platform_spelling_engine_ = true; 429 is_using_platform_spelling_engine_ = true;
489 } 430 }
490 } 431 }
491 432
492 // Get the corresponding BDIC file name. 433 // Get the corresponding BDIC file name.
493 bdic_file_name_ = GetVersionedFileName(language, dict_dir).BaseName(); 434 bdic_file_name_ = GetVersionedFileName(language, dict_dir).BaseName();
494 435
495 // Get File Loop - hunspell gets initialized here.
496 base::Thread* file_thread = g_browser_process->file_thread();
497 if (file_thread)
498 file_loop_ = file_thread->message_loop();
499
500 // Get the path to the custom dictionary file. 436 // Get the path to the custom dictionary file.
501 if (custom_dictionary_file_name_.empty()) { 437 if (custom_dictionary_file_name_.empty()) {
502 FilePath personal_file_directory; 438 FilePath personal_file_directory;
503 PathService::Get(chrome::DIR_USER_DATA, &personal_file_directory); 439 PathService::Get(chrome::DIR_USER_DATA, &personal_file_directory);
504 custom_dictionary_file_name_ = 440 custom_dictionary_file_name_ =
505 personal_file_directory.Append(chrome::kCustomDictionaryFileName); 441 personal_file_directory.Append(chrome::kCustomDictionaryFileName);
506 } 442 }
507 443
508 // Use this dictionary language as the default one of the 444 // Use this dictionary language as the default one of the
509 // SpellcheckCharAttribute object. 445 // SpellcheckCharAttribute object.
510 character_attributes_.SetDefaultLanguage(language); 446 character_attributes_.SetDefaultLanguage(language);
511 } 447 }
512 448
513 SpellChecker::~SpellChecker() { 449 SpellChecker::~SpellChecker() {
514 // This must be deleted on the I/O thread (see the header). This is the same 450 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
515 // thread that SpellCheckWord is called on, so we verify that they were all
516 // the same thread.
517 if (worker_loop_)
518 DCHECK(MessageLoop::current() == worker_loop_);
519 } 451 }
520 452
521 void SpellChecker::StartDictionaryDownload(const FilePath& file_name) { 453 void SpellChecker::StartDictionaryDownload(const FilePath& file_name) {
522 // Determine URL of file to download. 454 // Determine URL of file to download.
523 static const char kDownloadServerUrl[] = 455 static const char kDownloadServerUrl[] =
524 "http://cache.pack.google.com/edgedl/chrome/dict/"; 456 "http://cache.pack.google.com/edgedl/chrome/dict/";
525 GURL url = GURL(std::string(kDownloadServerUrl) + WideToUTF8( 457 GURL url = GURL(std::string(kDownloadServerUrl) + WideToUTF8(
526 l10n_util::ToLower(bdic_file_name_.ToWStringHack()))); 458 l10n_util::ToLower(bdic_file_name_.ToWStringHack())));
527 fetcher_.reset(new URLFetcher(url, URLFetcher::GET, this)); 459 fetcher_.reset(new URLFetcher(url, URLFetcher::GET, this));
528 fetcher_->set_request_context(request_context_getter_); 460 fetcher_->set_request_context(request_context_getter_);
(...skipping 22 matching lines...) Expand all
551 return; 483 return;
552 } 484 }
553 485
554 // Save the file in the file thread, and not here, the IO thread. 486 // Save the file in the file thread, and not here, the IO thread.
555 FilePath first_attempt_file_name = given_dictionary_directory_.Append( 487 FilePath first_attempt_file_name = given_dictionary_directory_.Append(
556 bdic_file_name_); 488 bdic_file_name_);
557 FilePath user_data_dir = GetFallbackDictionaryDownloadDirectory(); 489 FilePath user_data_dir = GetFallbackDictionaryDownloadDirectory();
558 FilePath fallback_file_name = user_data_dir.Append(bdic_file_name_); 490 FilePath fallback_file_name = user_data_dir.Append(bdic_file_name_);
559 Task* dic_task = method_factory_. 491 Task* dic_task = method_factory_.
560 NewRunnableMethod(&SpellChecker::OnDictionarySaveComplete); 492 NewRunnableMethod(&SpellChecker::OnDictionarySaveComplete);
561 file_loop_->PostTask(FROM_HERE, new SaveDictionaryTask(dic_task, 493 ChromeThread::PostTask(
562 first_attempt_file_name, fallback_file_name, data)); 494 ChromeThread::FILE, FROM_HERE,
495 new SaveDictionaryTask(
496 dic_task, first_attempt_file_name, fallback_file_name, data));
563 } 497 }
564 498
565 void SpellChecker::OnDictionarySaveComplete() { 499 void SpellChecker::OnDictionarySaveComplete() {
566 obtaining_dictionary_ = false; 500 obtaining_dictionary_ = false;
567 // Now that the dictionary is downloaded, continue trying to download. 501 // Now that the dictionary is downloaded, continue trying to download.
568 Initialize(); 502 Initialize();
569 } 503 }
570 504
571 // Initialize SpellChecker. In this method, if the dictionary is not present 505 // Initialize SpellChecker. In this method, if the dictionary is not present
572 // in the local disk, it is fetched asynchronously. 506 // in the local disk, it is fetched asynchronously.
573 bool SpellChecker::Initialize() { 507 bool SpellChecker::Initialize() {
574 if (!worker_loop_) 508 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
575 worker_loop_ = MessageLoop::current();
576 else
577 DCHECK(worker_loop_ == MessageLoop::current());
578 509
579 // Return false if the dictionary files are downloading. 510 // Return false if the dictionary files are downloading.
580 if (obtaining_dictionary_) 511 if (obtaining_dictionary_)
581 return false; 512 return false;
582 513
583 // Return false if tried to init and failed - don't try multiple times in 514 // Return false if tried to init and failed - don't try multiple times in
584 // this session. 515 // this session.
585 if (tried_to_init_) 516 if (tried_to_init_)
586 return hunspell_.get() != NULL; 517 return hunspell_.get() != NULL;
587 518
(...skipping 11 matching lines...) Expand all
599 // File name for downloading in DIR_APP_DICTIONARIES. 530 // File name for downloading in DIR_APP_DICTIONARIES.
600 FilePath dictionary_file_name_app = GetVersionedFileName(language_, 531 FilePath dictionary_file_name_app = GetVersionedFileName(language_,
601 given_dictionary_directory_); 532 given_dictionary_directory_);
602 533
603 // Filename for downloading in the fallback dictionary download directory, 534 // Filename for downloading in the fallback dictionary download directory,
604 // DIR_USER_DATA. 535 // DIR_USER_DATA.
605 FilePath dict_dir_userdata = GetFallbackDictionaryDownloadDirectory(); 536 FilePath dict_dir_userdata = GetFallbackDictionaryDownloadDirectory();
606 FilePath dictionary_file_name_usr = GetVersionedFileName(language_, 537 FilePath dictionary_file_name_usr = GetVersionedFileName(language_,
607 dict_dir_userdata); 538 dict_dir_userdata);
608 539
609 // Balances Release() in HunspellInited(), or in UIProxyForIOTask if the IO 540 // Balances Release() in HunspellInited().
610 // thread is torn down before the ReadDictionaryTask calls us back.
611 AddRef(); 541 AddRef();
612 Task* task = new ReadDictionaryTask(this, 542 ChromeThread::PostTask(
613 dictionary_file_name_app, dictionary_file_name_usr); 543 ChromeThread::FILE, FROM_HERE,
614 if (file_loop_) { 544 new ReadDictionaryTask(
615 file_loop_->PostTask(FROM_HERE, task); 545 this, dictionary_file_name_app, dictionary_file_name_usr));
616 } else {
617 task->Run();
618 delete task;
619 }
620 546
621 return hunspell_.get() != NULL; 547 return hunspell_.get() != NULL;
622 } 548 }
623 549
624 void SpellChecker::HunspellInited(Hunspell* hunspell, 550 void SpellChecker::HunspellInited(Hunspell* hunspell,
625 file_util::MemoryMappedFile* bdict_file, 551 file_util::MemoryMappedFile* bdict_file,
626 bool file_existed) { 552 bool file_existed) {
627 DCHECK(worker_loop_ == MessageLoop::current()); 553 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
628 554
629 if (file_existed) 555 if (file_existed)
630 tried_to_init_ = true; 556 tried_to_init_ = true;
631 557
632 if (!hunspell) { 558 if (!hunspell) {
633 if (!file_existed) { 559 if (!file_existed) {
634 // File didn't exist. We need to download a dictionary. 560 // File didn't exist. We need to download a dictionary.
635 DoDictionaryDownload(); 561 DoDictionaryDownload();
636 } 562 }
637 563
(...skipping 10 matching lines...) Expand all
648 hunspell_->add(custom_words_.front().c_str()); 574 hunspell_->add(custom_words_.front().c_str());
649 custom_words_.pop(); 575 custom_words_.pop();
650 } 576 }
651 577
652 // Balances AddRef() in Initialize(). 578 // Balances AddRef() in Initialize().
653 Release(); 579 Release();
654 } 580 }
655 581
656 void SpellChecker::DoDictionaryDownload() { 582 void SpellChecker::DoDictionaryDownload() {
657 // Download the dictionary file. 583 // Download the dictionary file.
658 if (file_loop_ && request_context_getter_) { 584 if (request_context_getter_) {
659 if (!tried_to_download_dictionary_file_) { 585 if (!tried_to_download_dictionary_file_) {
660 FilePath dictionary_file_name_app = GetVersionedFileName(language_, 586 FilePath dictionary_file_name_app = GetVersionedFileName(language_,
661 given_dictionary_directory_); 587 given_dictionary_directory_);
662 StartDictionaryDownload(dictionary_file_name_app); 588 StartDictionaryDownload(dictionary_file_name_app);
663 tried_to_download_dictionary_file_ = true; 589 tried_to_download_dictionary_file_ = true;
664 } else { 590 } else {
665 // Don't try to download a dictionary more than once. 591 // Don't try to download a dictionary more than once.
666 tried_to_init_ = true; 592 tried_to_init_ = true;
667 } 593 }
668 } else { 594 } else {
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
743 const char16* in_word, 669 const char16* in_word,
744 int in_word_len, 670 int in_word_len,
745 int tag, 671 int tag,
746 int* misspelling_start, 672 int* misspelling_start,
747 int* misspelling_len, 673 int* misspelling_len,
748 std::vector<string16>* optional_suggestions) { 674 std::vector<string16>* optional_suggestions) {
749 DCHECK(in_word_len >= 0); 675 DCHECK(in_word_len >= 0);
750 DCHECK(misspelling_start && misspelling_len) << "Out vars must be given."; 676 DCHECK(misspelling_start && misspelling_len) << "Out vars must be given.";
751 677
752 // This must always be called on the same thread (normally the I/O thread). 678 // This must always be called on the same thread (normally the I/O thread).
753 if (worker_loop_) 679 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
754 DCHECK(MessageLoop::current() == worker_loop_);
755 680
756 // Check if the platform spellchecker is being used. 681 // Check if the platform spellchecker is being used.
757 if (!is_using_platform_spelling_engine_) { 682 if (!is_using_platform_spelling_engine_) {
758 // If it isn't, try and init hunspell. 683 // If it isn't, try and init hunspell.
759 Initialize(); 684 Initialize();
760 685
761 // Check to see if hunspell was successfuly initialized. 686 // Check to see if hunspell was successfuly initialized.
762 if (!hunspell_.get()) 687 if (!hunspell_.get())
763 return true; // Unable to spellcheck, return word is OK. 688 return true; // Unable to spellcheck, return word is OK.
764 } 689 }
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
843 if (!word_to_add.empty() && word_to_add.length() < MAXWORDUTF8LEN) { 768 if (!word_to_add.empty() && word_to_add.length() < MAXWORDUTF8LEN) {
844 // Either add the word to |hunspell_|, or, if |hunspell_| is still loading, 769 // Either add the word to |hunspell_|, or, if |hunspell_| is still loading,
845 // defer it till after the load completes. 770 // defer it till after the load completes.
846 if (hunspell_.get()) 771 if (hunspell_.get())
847 hunspell_->add(word_to_add.c_str()); 772 hunspell_->add(word_to_add.c_str());
848 else 773 else
849 custom_words_.push(word_to_add); 774 custom_words_.push(word_to_add);
850 } 775 }
851 776
852 // Now add the word to the custom dictionary file. 777 // Now add the word to the custom dictionary file.
853 Task* write_word_task = 778 ChromeThread::PostTask(
854 new AddWordToCustomDictionaryTask(custom_dictionary_file_name_, word); 779 ChromeThread::FILE, FROM_HERE,
855 if (file_loop_) { 780 new AddWordToCustomDictionaryTask(custom_dictionary_file_name_, word));
856 file_loop_->PostTask(FROM_HERE, write_word_task);
857 } else {
858 write_word_task->Run();
859 delete write_word_task;
860 }
861 } 781 }
862 782
863 bool SpellChecker::CheckSpelling(const string16& word_to_check, int tag) { 783 bool SpellChecker::CheckSpelling(const string16& word_to_check, int tag) {
864 bool word_correct = false; 784 bool word_correct = false;
865 785
866 TimeTicks begin_time = TimeTicks::Now(); 786 TimeTicks begin_time = TimeTicks::Now();
867 if (is_using_platform_spelling_engine_) { 787 if (is_using_platform_spelling_engine_) {
868 word_correct = SpellCheckerPlatform::CheckSpelling(word_to_check, tag); 788 word_correct = SpellCheckerPlatform::CheckSpelling(word_to_check, tag);
869 } else { 789 } else {
870 std::string word_to_check_utf8(UTF16ToUTF8(word_to_check)); 790 std::string word_to_check_utf8(UTF16ToUTF8(word_to_check));
(...skipping 25 matching lines...) Expand all
896 816
897 // Populate the vector of WideStrings. 817 // Populate the vector of WideStrings.
898 for (int i = 0; i < number_of_suggestions; i++) { 818 for (int i = 0; i < number_of_suggestions; i++) {
899 if (i < kMaxSuggestions) 819 if (i < kMaxSuggestions)
900 optional_suggestions->push_back(UTF8ToUTF16(suggestions[i])); 820 optional_suggestions->push_back(UTF8ToUTF16(suggestions[i]));
901 free(suggestions[i]); 821 free(suggestions[i]);
902 } 822 }
903 if (suggestions != NULL) 823 if (suggestions != NULL)
904 free(suggestions); 824 free(suggestions);
905 } 825 }
OLDNEW
« no previous file with comments | « chrome/browser/spellchecker.h ('k') | chrome/browser/strict_transport_security_persister.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698