From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Cheng Zhao <zcbenz@gmail.com>
Date: Thu, 4 Oct 2018 14:57:02 -0700
Subject: Make sure hunspell file is not destroyed in UI thread

Submitted to Chromium at:
https://chromium-review.googlesource.com/c/chromium/src/+/2206199/1

diff --git a/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc b/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc
index c9c9f18b5cb176d74729cea8e5fee12f7fcf74f2..dfc895984cf7c1f0ca661ae527d00f9f4ebba49f 100644
--- a/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc
+++ b/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc
@@ -92,21 +92,28 @@ bool SaveDictionaryData(std::unique_ptr<std::string> data,
 
 }  // namespace
 
-SpellcheckHunspellDictionary::DictionaryFile::DictionaryFile() {
-}
+SpellcheckHunspellDictionary::DictionaryFile::DictionaryFile(
+    base::TaskRunner* task_runner) : task_runner_(task_runner) {}
 
 SpellcheckHunspellDictionary::DictionaryFile::~DictionaryFile() {
+  if (file.IsValid()) {
+    task_runner_->PostTask(FROM_HERE,
+                           base::BindOnce(&CloseDictionary, std::move(file)));
+  }
 }
 
 SpellcheckHunspellDictionary::DictionaryFile::DictionaryFile(
     DictionaryFile&& other)
-    : path(other.path), file(std::move(other.file)) {}
+    : path(other.path),
+      file(std::move(other.file)),
+      task_runner_(std::move(other.task_runner_)) {}
 
 SpellcheckHunspellDictionary::DictionaryFile&
 SpellcheckHunspellDictionary::DictionaryFile::operator=(
     DictionaryFile&& other) {
   path = other.path;
   file = std::move(other.file);
+  task_runner_ = std::move(other.task_runner_);
   return *this;
 }
 
@@ -120,15 +127,10 @@ SpellcheckHunspellDictionary::SpellcheckHunspellDictionary(
       use_browser_spellchecker_(false),
       browser_context_(browser_context),
       spellcheck_service_(spellcheck_service),
-      download_status_(DOWNLOAD_NONE) {}
+      download_status_(DOWNLOAD_NONE),
+      dictionary_file_(task_runner_.get()) {}
 
 SpellcheckHunspellDictionary::~SpellcheckHunspellDictionary() {
-  if (dictionary_file_.file.IsValid()) {
-    task_runner_->PostTask(
-        FROM_HERE,
-        base::BindOnce(&CloseDictionary, std::move(dictionary_file_.file)));
-  }
-
 #if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
   // Disable the language from platform spellchecker.
   if (spellcheck::UseBrowserSpellChecker())
@@ -323,7 +325,8 @@ void SpellcheckHunspellDictionary::DownloadDictionary(GURL url) {
 #if !defined(OS_ANDROID)
 // static
 SpellcheckHunspellDictionary::DictionaryFile
-SpellcheckHunspellDictionary::OpenDictionaryFile(const base::FilePath& path) {
+SpellcheckHunspellDictionary::OpenDictionaryFile(base::TaskRunner* task_runner,
+                                                 const base::FilePath& path) {
   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                 base::BlockingType::MAY_BLOCK);
 
@@ -334,7 +337,7 @@ SpellcheckHunspellDictionary::OpenDictionaryFile(const base::FilePath& path) {
   // For systemwide installations on Windows, the default directory may not
   // have permissions for download. In that case, the alternate directory for
   // download is chrome::DIR_USER_DATA.
-  DictionaryFile dictionary;
+  DictionaryFile dictionary(task_runner);
 
 #if defined(OS_WIN)
   // Check if the dictionary exists in the fallback location. If so, use it
@@ -376,7 +379,7 @@ SpellcheckHunspellDictionary::OpenDictionaryFile(const base::FilePath& path) {
 // static
 SpellcheckHunspellDictionary::DictionaryFile
 SpellcheckHunspellDictionary::InitializeDictionaryLocation(
-    const std::string& language) {
+    base::TaskRunner* task_runner, const std::string& language) {
   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                 base::BlockingType::MAY_BLOCK);
 
@@ -391,7 +394,7 @@ SpellcheckHunspellDictionary::InitializeDictionaryLocation(
   base::FilePath dict_path =
       spellcheck::GetVersionedFileName(language, dict_dir);
 
-  return OpenDictionaryFile(dict_path);
+  return OpenDictionaryFile(task_runner, dict_path);
 }
 
 void SpellcheckHunspellDictionary::InitializeDictionaryLocationComplete(
@@ -480,7 +483,8 @@ void SpellcheckHunspellDictionary::PlatformSupportsLanguageComplete(
 #if !defined(OS_ANDROID) && BUILDFLAG(USE_RENDERER_SPELLCHECKER)
     base::PostTaskAndReplyWithResult(
         task_runner_.get(), FROM_HERE,
-        base::BindOnce(&InitializeDictionaryLocation, language_),
+        base::BindOnce(&InitializeDictionaryLocation,
+                       base::RetainedRef(task_runner_.get()), language_),
         base::BindOnce(
             &SpellcheckHunspellDictionary::InitializeDictionaryLocationComplete,
             weak_ptr_factory_.GetWeakPtr()));
diff --git a/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h b/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h
index 4662bdc08b54304a7f8b2995f60fea9dc5617fff..7679f526c05980889adb2f6a8a0c20dd7f5415c3 100644
--- a/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h
+++ b/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h
@@ -99,7 +99,7 @@ class SpellcheckHunspellDictionary
   // blocking sequence.
   struct DictionaryFile {
    public:
-    DictionaryFile();
+    explicit DictionaryFile(base::TaskRunner* task_runner);
     ~DictionaryFile();
 
     DictionaryFile(DictionaryFile&& other);
@@ -112,6 +112,9 @@ class SpellcheckHunspellDictionary
     base::File file;
 
    private:
+    // Task runner where the file is created.
+    scoped_refptr<base::TaskRunner> task_runner_;
+
     DISALLOW_COPY_AND_ASSIGN(DictionaryFile);
   };
 
@@ -126,11 +129,12 @@ class SpellcheckHunspellDictionary
 #if !defined(OS_ANDROID)
   // Figures out the location for the dictionary, verifies its contents, and
   // opens it.
-  static DictionaryFile OpenDictionaryFile(const base::FilePath& path);
+  static DictionaryFile OpenDictionaryFile(base::TaskRunner* task_runner,
+                                           const base::FilePath& path);
 
   // Gets the default location for the dictionary file.
   static DictionaryFile InitializeDictionaryLocation(
-      const std::string& language);
+      base::TaskRunner* task_runner, const std::string& language);
 
   // The reply point for PostTaskAndReplyWithResult, called after the dictionary
   // file has been initialized.
