spellcheck_message_filter.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/spellchecker/spellcheck_message_filter.h" 6 7#include "base/bind.h" 8#include "base/prefs/pref_service.h" 9#include "chrome/browser/profiles/profile.h" 10#include "chrome/browser/spellchecker/spellcheck_factory.h" 11#include "chrome/browser/spellchecker/spellcheck_host_metrics.h" 12#include "chrome/browser/spellchecker/spellcheck_service.h" 13#include "chrome/browser/spellchecker/spelling_service_client.h" 14#include "chrome/common/pref_names.h" 15#include "chrome/common/spellcheck_messages.h" 16#include "content/public/browser/render_process_host.h" 17#include "net/url_request/url_fetcher.h" 18 19using content::BrowserThread; 20 21SpellCheckMessageFilter::SpellCheckMessageFilter(int render_process_id) 22 : render_process_id_(render_process_id), 23 client_(new SpellingServiceClient) 24#if !defined(OS_MACOSX) 25 , 26 route_id_(0), 27 identifier_(0) 28#endif 29 { 30} 31 32void SpellCheckMessageFilter::OverrideThreadForMessage( 33 const IPC::Message& message, BrowserThread::ID* thread) { 34 if (message.type() == SpellCheckHostMsg_RequestDictionary::ID || 35 message.type() == SpellCheckHostMsg_NotifyChecked::ID) 36 *thread = BrowserThread::UI; 37#if !defined(OS_MACOSX) 38 if (message.type() == SpellCheckHostMsg_CallSpellingService::ID) 39 *thread = BrowserThread::UI; 40#endif 41} 42 43bool SpellCheckMessageFilter::OnMessageReceived(const IPC::Message& message, 44 bool* message_was_ok) { 45 bool handled = true; 46 IPC_BEGIN_MESSAGE_MAP_EX(SpellCheckMessageFilter, message, *message_was_ok) 47 IPC_MESSAGE_HANDLER(SpellCheckHostMsg_RequestDictionary, 48 OnSpellCheckerRequestDictionary) 49 IPC_MESSAGE_HANDLER(SpellCheckHostMsg_NotifyChecked, 50 OnNotifyChecked) 51#if !defined(OS_MACOSX) 52 IPC_MESSAGE_HANDLER(SpellCheckHostMsg_CallSpellingService, 53 OnCallSpellingService) 54#endif 55 IPC_MESSAGE_UNHANDLED(handled = false) 56 IPC_END_MESSAGE_MAP() 57 return handled; 58} 59 60SpellCheckMessageFilter::~SpellCheckMessageFilter() {} 61 62void SpellCheckMessageFilter::OnSpellCheckerRequestDictionary() { 63 content::RenderProcessHost* host = 64 content::RenderProcessHost::FromID(render_process_id_); 65 if (!host) 66 return; // Teardown. 67 Profile* profile = Profile::FromBrowserContext(host->GetBrowserContext()); 68 // The renderer has requested that we initialize its spellchecker. This should 69 // generally only be called once per session, as after the first call, all 70 // future renderers will be passed the initialization information on startup 71 // (or when the dictionary changes in some way). 72 SpellcheckService* spellcheck_service = 73 SpellcheckServiceFactory::GetForProfile(profile); 74 75 DCHECK(spellcheck_service); 76 // The spellchecker initialization already started and finished; just send 77 // it to the renderer. 78 spellcheck_service->InitForRenderer(host); 79 80 // TODO(rlp): Ensure that we do not initialize the hunspell dictionary more 81 // than once if we get requests from different renderers. 82} 83 84void SpellCheckMessageFilter::OnNotifyChecked(const string16& word, 85 bool misspelled) { 86 content::RenderProcessHost* host = 87 content::RenderProcessHost::FromID(render_process_id_); 88 if (!host) 89 return; // Teardown. 90 // Delegates to SpellCheckHost which tracks the stats of our spellchecker. 91 Profile* profile = Profile::FromBrowserContext(host->GetBrowserContext()); 92 SpellcheckService* spellcheck_service = 93 SpellcheckServiceFactory::GetForProfile(profile); 94 DCHECK(spellcheck_service); 95 if (spellcheck_service->GetMetrics()) 96 spellcheck_service->GetMetrics()->RecordCheckedWordStats(word, misspelled); 97} 98 99#if !defined(OS_MACOSX) 100void SpellCheckMessageFilter::OnCallSpellingService( 101 int route_id, 102 int identifier, 103 int document_tag, 104 const string16& text) { 105 DCHECK(!text.empty()); 106 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 107 route_id_ = route_id; 108 identifier_ = identifier; 109 CallSpellingService(document_tag, text); 110} 111 112void SpellCheckMessageFilter::OnTextCheckComplete( 113 int tag, 114 bool success, 115 const string16& text, 116 const std::vector<SpellCheckResult>& results) { 117 Send(new SpellCheckMsg_RespondSpellingService(route_id_, 118 identifier_, 119 tag, 120 success, 121 text, 122 results)); 123} 124 125// CallSpellingService always executes the callback OnTextCheckComplete. 126// (Which, in turn, sends a SpellCheckMsg_RespondSpellingService) 127void SpellCheckMessageFilter::CallSpellingService(int document_tag, 128 const string16& text) { 129 Profile* profile = NULL; 130 content::RenderProcessHost* host = 131 content::RenderProcessHost::FromID(render_process_id_); 132 if (host) 133 profile = Profile::FromBrowserContext(host->GetBrowserContext()); 134 135 client_->RequestTextCheck( 136 profile, SpellingServiceClient::SPELLCHECK, text, 137 base::Bind(&SpellCheckMessageFilter::OnTextCheckComplete, 138 base::Unretained(this), document_tag)); 139} 140#endif 141