This source file includes following definitions.
- CompareLocation
- document_tag_
- RequestCheck
- RequestRemoteCheck
- RequestLocalCheck
- OnCheckCompleted
- OnRemoteCheckCompleted
- OnLocalCheckCompleted
- client_
- OverrideThreadForMessage
- OnMessageReceived
- CombineResults
- OnCheckSpelling
- OnFillSuggestionList
- OnShowSpellingPanel
- OnUpdateSpellingPanelWithMisspelledWord
- OnRequestTextCheck
- ToDocumentTag
- RetireDocumentTag
#include "chrome/browser/spellchecker/spellcheck_message_filter_mac.h"
#include <algorithm>
#include <functional>
#include "base/barrier_closure.h"
#include "base/bind.h"
#include "chrome/browser/spellchecker/spellcheck_factory.h"
#include "chrome/browser/spellchecker/spellcheck_platform_mac.h"
#include "chrome/browser/spellchecker/spellcheck_service.h"
#include "chrome/browser/spellchecker/spelling_service_client.h"
#include "chrome/common/spellcheck_messages.h"
#include "chrome/common/spellcheck_result.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/render_process_host.h"
using content::BrowserThread;
using content::BrowserContext;
namespace {
bool CompareLocation(const SpellCheckResult& r1,
const SpellCheckResult& r2) {
return r1.location < r2.location;
}
}
class SpellingRequest {
public:
SpellingRequest(SpellingServiceClient* client,
content::BrowserMessageFilter* destination,
int render_process_id);
void RequestCheck(const base::string16& text,
int route_id,
int identifier,
int document_tag,
const std::vector<SpellCheckMarker>& markers);
private:
void RequestRemoteCheck(const base::string16& text);
void RequestLocalCheck(const base::string16& text, int document_tag);
void OnCheckCompleted();
void OnRemoteCheckCompleted(bool success,
const base::string16& text,
const std::vector<SpellCheckResult>& results);
void OnLocalCheckCompleted(const std::vector<SpellCheckResult>& results);
std::vector<SpellCheckResult> local_results_;
std::vector<SpellCheckResult> remote_results_;
base::Closure completion_barrier_;
bool remote_success_;
SpellingServiceClient* client_;
content::BrowserMessageFilter* destination_;
int render_process_id_;
int route_id_;
int identifier_;
int document_tag_;
std::vector<SpellCheckMarker> markers_;
};
SpellingRequest::SpellingRequest(SpellingServiceClient* client,
content::BrowserMessageFilter* destination,
int render_process_id)
: remote_success_(false),
client_(client),
destination_(destination),
render_process_id_(render_process_id),
route_id_(-1),
identifier_(-1),
document_tag_(-1) {
destination_->AddRef();
}
void SpellingRequest::RequestCheck(
const base::string16& text,
int route_id,
int identifier,
int document_tag,
const std::vector<SpellCheckMarker>& markers) {
DCHECK(!text.empty());
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
route_id_ = route_id;
identifier_ = identifier;
document_tag_ = document_tag;
markers_ = markers;
completion_barrier_ =
BarrierClosure(2,
base::Bind(&SpellingRequest::OnCheckCompleted,
base::Owned(this)));
RequestRemoteCheck(text);
RequestLocalCheck(text, document_tag_);
}
void SpellingRequest::RequestRemoteCheck(const base::string16& text) {
BrowserContext* context = NULL;
content::RenderProcessHost* host =
content::RenderProcessHost::FromID(render_process_id_);
if (host)
context = host->GetBrowserContext();
client_->RequestTextCheck(
context,
SpellingServiceClient::SPELLCHECK,
text,
base::Bind(&SpellingRequest::OnRemoteCheckCompleted,
base::Unretained(this)));
}
void SpellingRequest::RequestLocalCheck(const base::string16& text,
int document_tag) {
spellcheck_mac::RequestTextCheck(
document_tag,
text,
base::Bind(&SpellingRequest::OnLocalCheckCompleted,
base::Unretained(this)));
}
void SpellingRequest::OnCheckCompleted() {
const std::vector<SpellCheckResult>* check_results = &local_results_;
if (remote_success_) {
std::sort(remote_results_.begin(), remote_results_.end(), CompareLocation);
std::sort(local_results_.begin(), local_results_.end(), CompareLocation);
SpellCheckMessageFilterMac::CombineResults(&remote_results_,
local_results_);
check_results = &remote_results_;
}
destination_->Send(
new SpellCheckMsg_RespondTextCheck(
route_id_,
identifier_,
*check_results));
destination_->Release();
}
void SpellingRequest::OnRemoteCheckCompleted(
bool success,
const base::string16& text,
const std::vector<SpellCheckResult>& results) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
remote_success_ = success;
remote_results_ = results;
SpellcheckService* spellcheck_service =
SpellcheckServiceFactory::GetForRenderProcessId(render_process_id_);
if (spellcheck_service) {
spellcheck_service->GetFeedbackSender()->OnSpellcheckResults(
render_process_id_,
text,
markers_,
&remote_results_);
}
completion_barrier_.Run();
}
void SpellingRequest::OnLocalCheckCompleted(
const std::vector<SpellCheckResult>& results) {
local_results_ = results;
completion_barrier_.Run();
}
SpellCheckMessageFilterMac::SpellCheckMessageFilterMac(int render_process_id)
: BrowserMessageFilter(SpellCheckMsgStart),
render_process_id_(render_process_id),
client_(new SpellingServiceClient) {
}
void SpellCheckMessageFilterMac::OverrideThreadForMessage(
const IPC::Message& message, BrowserThread::ID* thread) {
if (message.type() == SpellCheckHostMsg_RequestTextCheck::ID)
*thread = BrowserThread::UI;
}
bool SpellCheckMessageFilterMac::OnMessageReceived(const IPC::Message& message,
bool* message_was_ok) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP_EX(SpellCheckMessageFilterMac, message, *message_was_ok)
IPC_MESSAGE_HANDLER(SpellCheckHostMsg_CheckSpelling,
OnCheckSpelling)
IPC_MESSAGE_HANDLER(SpellCheckHostMsg_FillSuggestionList,
OnFillSuggestionList)
IPC_MESSAGE_HANDLER(SpellCheckHostMsg_ShowSpellingPanel,
OnShowSpellingPanel)
IPC_MESSAGE_HANDLER(SpellCheckHostMsg_UpdateSpellingPanelWithMisspelledWord,
OnUpdateSpellingPanelWithMisspelledWord)
IPC_MESSAGE_HANDLER(SpellCheckHostMsg_RequestTextCheck,
OnRequestTextCheck)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
void SpellCheckMessageFilterMac::CombineResults(
std::vector<SpellCheckResult>* remote_results,
const std::vector<SpellCheckResult>& local_results) {
std::vector<SpellCheckResult>::const_iterator local_iter(
local_results.begin());
std::vector<SpellCheckResult>::iterator remote_iter;
for (remote_iter = remote_results->begin();
remote_iter != remote_results->end();
++remote_iter) {
while (local_iter != local_results.end() &&
local_iter->location < remote_iter->location) {
local_iter++;
}
remote_iter->decoration = SpellCheckResult::GRAMMAR;
if (local_iter != local_results.end() &&
local_iter->location == remote_iter->location &&
local_iter->length == remote_iter->length) {
remote_iter->decoration = SpellCheckResult::SPELLING;
}
}
}
SpellCheckMessageFilterMac::~SpellCheckMessageFilterMac() {}
void SpellCheckMessageFilterMac::OnCheckSpelling(const base::string16& word,
int route_id,
bool* correct) {
*correct = spellcheck_mac::CheckSpelling(word, ToDocumentTag(route_id));
}
void SpellCheckMessageFilterMac::OnFillSuggestionList(
const base::string16& word,
std::vector<base::string16>* suggestions) {
spellcheck_mac::FillSuggestionList(word, suggestions);
}
void SpellCheckMessageFilterMac::OnShowSpellingPanel(bool show) {
spellcheck_mac::ShowSpellingPanel(show);
}
void SpellCheckMessageFilterMac::OnUpdateSpellingPanelWithMisspelledWord(
const base::string16& word) {
spellcheck_mac::UpdateSpellingPanelWithMisspelledWord(word);
}
void SpellCheckMessageFilterMac::OnRequestTextCheck(
int route_id,
int identifier,
const base::string16& text,
std::vector<SpellCheckMarker> markers) {
DCHECK(!text.empty());
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
markers.erase(
std::remove_if(
markers.begin(),
markers.end(),
std::not1(SpellCheckMarker::IsValidPredicate(text.length()))),
markers.end());
SpellingRequest* request =
new SpellingRequest(client_.get(), this, render_process_id_);
request->RequestCheck(
text, route_id, identifier, ToDocumentTag(route_id), markers);
}
int SpellCheckMessageFilterMac::ToDocumentTag(int route_id) {
if (!tag_map_.count(route_id))
tag_map_[route_id] = spellcheck_mac::GetDocumentTag();
return tag_map_[route_id];
}
void SpellCheckMessageFilterMac::RetireDocumentTag(int route_id) {
spellcheck_mac::CloseDocumentWithTag(ToDocumentTag(route_id));
tag_map_.erase(route_id);
}