From 38a04214e0c3dcb44ab67abd8af949accd44443f Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 19 May 2020 22:55:23 +0900 Subject: [PATCH] fix: make sure hunspell file is not destroyed in UI thread (#23631) --- patches/chromium/.patches | 1 + patches/chromium/fix_hunspell_crash.patch | 147 ++++++++++++++++++++++ 2 files changed, 148 insertions(+) create mode 100644 patches/chromium/fix_hunspell_crash.patch diff --git a/patches/chromium/.patches b/patches/chromium/.patches index 6accd46a7fe8..1da350f97846 100644 --- a/patches/chromium/.patches +++ b/patches/chromium/.patches @@ -95,3 +95,4 @@ breakpad_treat_node_processes_as_browser_processes.patch upload_list_add_loadsync_method.patch breakpad_allow_getting_string_values_for_crash_keys.patch crash_allow_disabling_compression_on_linux.patch +fix_hunspell_crash.patch diff --git a/patches/chromium/fix_hunspell_crash.patch b/patches/chromium/fix_hunspell_crash.patch new file mode 100644 index 000000000000..868f551c8d56 --- /dev/null +++ b/patches/chromium/fix_hunspell_crash.patch @@ -0,0 +1,147 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cheng Zhao +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 653ef44ff095015ef25cc59bf42f9fbd9d907160..d6f9bf8e0d2cf2e52698d4d132361a5d7118d00c 100644 +--- a/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc ++++ b/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc +@@ -93,21 +93,28 @@ bool SaveDictionaryData(std::unique_ptr 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; + } + +@@ -121,15 +128,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()) +@@ -324,7 +326,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); + +@@ -335,7 +338,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 +@@ -377,7 +380,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); + +@@ -392,7 +395,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( +@@ -481,7 +484,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 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.