spellcheck_message_filter.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/spellchecker/spellcheck_message_filter.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/spellchecker/spellcheck_factory.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/spellchecker/spellcheck_host_metrics.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/spellchecker/spellcheck_service.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/spellchecker/spelling_service_client.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h" 1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/common/spellcheck_marker.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/spellcheck_messages.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_process_host.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_fetcher.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpellCheckMessageFilter::SpellCheckMessageFilter(int render_process_id) 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : render_process_id_(render_process_id), 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) client_(new SpellingServiceClient) { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpellCheckMessageFilter::OverrideThreadForMessage( 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const IPC::Message& message, BrowserThread::ID* thread) { 29b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // IPC messages arrive on IO thread, but spellcheck data lives on UI thread. 30b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // The message filter overrides the thread for these messages because they 31b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // access spellcheck data. 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (message.type() == SpellCheckHostMsg_RequestDictionary::ID || 33b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) message.type() == SpellCheckHostMsg_NotifyChecked::ID || 34b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) message.type() == SpellCheckHostMsg_RespondDocumentMarkers::ID) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *thread = BrowserThread::UI; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (message.type() == SpellCheckHostMsg_CallSpellingService::ID) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *thread = BrowserThread::UI; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpellCheckMessageFilter::OnMessageReceived(const IPC::Message& message, 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool* message_was_ok) { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool handled = true; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_BEGIN_MESSAGE_MAP_EX(SpellCheckMessageFilter, message, *message_was_ok) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_MESSAGE_HANDLER(SpellCheckHostMsg_RequestDictionary, 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnSpellCheckerRequestDictionary) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_MESSAGE_HANDLER(SpellCheckHostMsg_NotifyChecked, 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnNotifyChecked) 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) IPC_MESSAGE_HANDLER(SpellCheckHostMsg_RespondDocumentMarkers, 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) OnRespondDocumentMarkers) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_MESSAGE_HANDLER(SpellCheckHostMsg_CallSpellingService, 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnCallSpellingService) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_MESSAGE_UNHANDLED(handled = false) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_END_MESSAGE_MAP() 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return handled; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpellCheckMessageFilter::~SpellCheckMessageFilter() {} 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpellCheckMessageFilter::OnSpellCheckerRequestDictionary() { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RenderProcessHost* host = 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RenderProcessHost::FromID(render_process_id_); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!host) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // Teardown. 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile = Profile::FromBrowserContext(host->GetBrowserContext()); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The renderer has requested that we initialize its spellchecker. This should 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // generally only be called once per session, as after the first call, all 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // future renderers will be passed the initialization information on startup 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (or when the dictionary changes in some way). 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpellcheckService* spellcheck_service = 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpellcheckServiceFactory::GetForProfile(profile); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(spellcheck_service); 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The spellchecker initialization already started and finished; just send 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // it to the renderer. 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) spellcheck_service->InitForRenderer(host); 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(rlp): Ensure that we do not initialize the hunspell dictionary more 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // than once if we get requests from different renderers. 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpellCheckMessageFilter::OnNotifyChecked(const string16& word, 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool misspelled) { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RenderProcessHost* host = 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RenderProcessHost::FromID(render_process_id_); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!host) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // Teardown. 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Delegates to SpellCheckHost which tracks the stats of our spellchecker. 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile = Profile::FromBrowserContext(host->GetBrowserContext()); 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpellcheckService* spellcheck_service = 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpellcheckServiceFactory::GetForProfile(profile); 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(spellcheck_service); 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (spellcheck_service->GetMetrics()) 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) spellcheck_service->GetMetrics()->RecordCheckedWordStats(word, misspelled); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SpellCheckMessageFilter::OnRespondDocumentMarkers( 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::vector<uint32>& markers) { 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SpellcheckService* spellcheck = 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SpellcheckServiceFactory::GetForRenderProcessId(render_process_id_); 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(spellcheck); 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) spellcheck->GetFeedbackSender()->OnReceiveDocumentMarkers(render_process_id_, 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) markers); 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpellCheckMessageFilter::OnCallSpellingService( 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int route_id, 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int identifier, 11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const string16& text, 11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::vector<SpellCheckMarker>& markers) { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!text.empty()); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CallSpellingService(text, route_id, identifier, markers); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpellCheckMessageFilter::OnTextCheckComplete( 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int route_id, 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int identifier, 12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::vector<SpellCheckMarker>& markers, 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success, 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& text, 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<SpellCheckResult>& results) { 12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SpellcheckService* spellcheck = 12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SpellcheckServiceFactory::GetForRenderProcessId(render_process_id_); 12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(spellcheck); 13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<SpellCheckResult> results_copy = results; 13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spellcheck->GetFeedbackSender()->OnSpellcheckResults( 13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &results_copy, render_process_id_, text, markers); 13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) Send(new SpellCheckMsg_RespondSpellingService( 13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) route_id, identifier, success, text, results_copy)); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// CallSpellingService always executes the callback OnTextCheckComplete. 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// (Which, in turn, sends a SpellCheckMsg_RespondSpellingService) 13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SpellCheckMessageFilter::CallSpellingService( 14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const string16& text, 14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int route_id, 14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int identifier, 14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::vector<SpellCheckMarker>& markers) { 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Profile* profile = NULL; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RenderProcessHost* host = 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RenderProcessHost::FromID(render_process_id_); 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (host) 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) profile = Profile::FromBrowserContext(host->GetBrowserContext()); 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) client_->RequestTextCheck( 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) profile, 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SpellingServiceClient::SPELLCHECK, 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) text, 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&SpellCheckMessageFilter::OnTextCheckComplete, 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Unretained(this), 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) route_id, 15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) identifier, 15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) markers)); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 161