Spellchecker: Always destruct url request context getter on io thread.
To do this, we have to initiate downloads on the UI thread and don't hold onto a reference in the file thread.
BUG=27667
Review URL: http://codereview.chromium.org/387055
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@32129 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/spellcheck_host.cc b/chrome/browser/spellcheck_host.cc
index e276473..446d19d 100644
--- a/chrome/browser/spellcheck_host.cc
+++ b/chrome/browser/spellcheck_host.cc
@@ -169,6 +169,8 @@
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
observer_ = NULL;
+ request_context_getter_ = NULL;
+ fetcher_.reset();
}
void SpellCheckHost::AddWord(const std::string& word) {
@@ -210,11 +212,17 @@
NULL);
// File didn't exist. Download it.
- if (file_ == base::kInvalidPlatformFileValue && !tried_to_download_) {
- DownloadDictionary();
+ if (file_ == base::kInvalidPlatformFileValue && !tried_to_download_ &&
+ request_context_getter_) {
+ // We download from the ui thread because we need to know that
+ // |request_context_getter_| is still valid before initiating the download.
+ ChromeThread::PostTask(ChromeThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &SpellCheckHost::DownloadDictionary));
return;
}
+ request_context_getter_ = NULL;
+
if (file_ != base::kInvalidPlatformFileValue) {
// Load custom dictionary.
std::string contents;
@@ -230,6 +238,13 @@
&SpellCheckHost::InformObserverOfInitialization));
}
+void SpellCheckHost::InitializeOnFileThread() {
+ DCHECK(!ChromeThread::CurrentlyOn(ChromeThread::FILE));
+
+ ChromeThread::PostTask(ChromeThread::FILE, FROM_HERE,
+ NewRunnableMethod(this, &SpellCheckHost::Initialize));
+}
+
void SpellCheckHost::InformObserverOfInitialization() {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
@@ -238,7 +253,12 @@
}
void SpellCheckHost::DownloadDictionary() {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+
+ if (!request_context_getter_) {
+ InitializeOnFileThread();
+ return;
+ }
// Determine URL of file to download.
static const char kDownloadServerUrl[] =
@@ -246,9 +266,10 @@
GURL url = GURL(std::string(kDownloadServerUrl) + WideToUTF8(
l10n_util::ToLower(bdict_file_path_.BaseName().ToWStringHack())));
fetcher_.reset(new URLFetcher(url, URLFetcher::GET, this));
- fetcher_->set_request_context(request_context_getter_.get());
+ fetcher_->set_request_context(request_context_getter_);
tried_to_download_ = true;
fetcher_->Start();
+ request_context_getter_ = NULL;
}
void SpellCheckHost::WriteWordToCustomDictionary(const std::string& word) {
@@ -269,12 +290,13 @@
const ResponseCookies& cookies,
const std::string& data) {
DCHECK(source);
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ fetcher_.reset();
if ((response_code / 100) != 2) {
// Initialize will not try to download the file a second time.
LOG(ERROR) << "Failure to download dictionary.";
- Initialize();
+ InitializeOnFileThread();
return;
}
@@ -284,25 +306,35 @@
if (data.size() < 4 || data[0] != 'B' || data[1] != 'D' || data[2] != 'i' ||
data[3] != 'c') {
LOG(ERROR) << "Failure to download dictionary.";
- Initialize();
+ InitializeOnFileThread();
return;
}
+ data_ = data;
+ ChromeThread::PostTask(ChromeThread::FILE, FROM_HERE,
+ NewRunnableMethod(this, &SpellCheckHost::SaveDictionaryData));
+}
+
+void SpellCheckHost::SaveDictionaryData() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
+
size_t bytes_written =
- file_util::WriteFile(bdict_file_path_, data.data(), data.length());
- if (bytes_written != data.length()) {
+ file_util::WriteFile(bdict_file_path_, data_.data(), data_.length());
+ if (bytes_written != data_.length()) {
bool success = false;
#if defined(OS_WIN)
bdict_file_path_ = GetFallbackFilePath(bdict_file_path_);
bytes_written =
file_util::WriteFile(GetFallbackFilePath(bdict_file_path_),
- data.data(), data.length());
- if (bytes_written == data.length())
+ data_.data(), data_.length());
+ if (bytes_written == data_.length())
success = true;
#endif
+ data_.clear();
if (!success) {
LOG(ERROR) << "Failure to save dictionary.";
+ file_util::Delete(bdict_file_path_, false);
// To avoid trying to load a partially saved dictionary, shortcut the
// Initialize() call.
ChromeThread::PostTask(ChromeThread::UI, FROM_HERE,
@@ -312,5 +344,6 @@
}
}
+ data_.clear();
Initialize();
}