// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/spellchecker/spellcheck_message_filter.h"

#include <algorithm>
#include <functional>

#include "base/bind.h"
#include "base/prefs/pref_service.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/spellchecker/spellcheck_factory.h"
#include "chrome/browser/spellchecker/spellcheck_host_metrics.h"
#include "chrome/browser/spellchecker/spellcheck_service.h"
#include "chrome/browser/spellchecker/spelling_service_client.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/spellcheck_marker.h"
#include "chrome/common/spellcheck_messages.h"
#include "content/public/browser/render_process_host.h"
#include "net/url_request/url_fetcher.h"

using content::BrowserThread;

SpellCheckMessageFilter::SpellCheckMessageFilter(int render_process_id)
    : BrowserMessageFilter(SpellCheckMsgStart),
      render_process_id_(render_process_id),
      client_(new SpellingServiceClient) {
}

void SpellCheckMessageFilter::OverrideThreadForMessage(
    const IPC::Message& message, BrowserThread::ID* thread) {
  // IPC messages arrive on IO thread, but spellcheck data lives on UI thread.
  // The message filter overrides the thread for these messages because they
  // access spellcheck data.
  if (message.type() == SpellCheckHostMsg_RequestDictionary::ID ||
      message.type() == SpellCheckHostMsg_NotifyChecked::ID ||
      message.type() == SpellCheckHostMsg_RespondDocumentMarkers::ID)
    *thread = BrowserThread::UI;
#if !defined(OS_MACOSX)
  if (message.type() == SpellCheckHostMsg_CallSpellingService::ID)
    *thread = BrowserThread::UI;
#endif
}

bool SpellCheckMessageFilter::OnMessageReceived(const IPC::Message& message) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(SpellCheckMessageFilter, message)
    IPC_MESSAGE_HANDLER(SpellCheckHostMsg_RequestDictionary,
                        OnSpellCheckerRequestDictionary)
    IPC_MESSAGE_HANDLER(SpellCheckHostMsg_NotifyChecked,
                        OnNotifyChecked)
    IPC_MESSAGE_HANDLER(SpellCheckHostMsg_RespondDocumentMarkers,
                        OnRespondDocumentMarkers)
#if !defined(OS_MACOSX)
    IPC_MESSAGE_HANDLER(SpellCheckHostMsg_CallSpellingService,
                        OnCallSpellingService)
#endif
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

SpellCheckMessageFilter::~SpellCheckMessageFilter() {}

void SpellCheckMessageFilter::OnSpellCheckerRequestDictionary() {
  content::RenderProcessHost* host =
      content::RenderProcessHost::FromID(render_process_id_);
  if (!host)
    return;  // Teardown.
  // The renderer has requested that we initialize its spellchecker. This should
  // generally only be called once per session, as after the first call, all
  // future renderers will be passed the initialization information on startup
  // (or when the dictionary changes in some way).
  SpellcheckService* spellcheck_service =
      SpellcheckServiceFactory::GetForContext(host->GetBrowserContext());

  DCHECK(spellcheck_service);
  // The spellchecker initialization already started and finished; just send
  // it to the renderer.
  spellcheck_service->InitForRenderer(host);

  // TODO(rlp): Ensure that we do not initialize the hunspell dictionary more
  // than once if we get requests from different renderers.
}

void SpellCheckMessageFilter::OnNotifyChecked(const base::string16& word,
                                              bool misspelled) {
  SpellcheckService* spellcheck = GetSpellcheckService();
  // Spellcheck service may not be available for a renderer process that is
  // shutting down.
  if (!spellcheck)
    return;
  if (spellcheck->GetMetrics())
    spellcheck->GetMetrics()->RecordCheckedWordStats(word, misspelled);
}

void SpellCheckMessageFilter::OnRespondDocumentMarkers(
    const std::vector<uint32>& markers) {
  SpellcheckService* spellcheck = GetSpellcheckService();
  // Spellcheck service may not be available for a renderer process that is
  // shutting down.
  if (!spellcheck)
    return;
  spellcheck->GetFeedbackSender()->OnReceiveDocumentMarkers(
      render_process_id_, markers);
}

#if !defined(OS_MACOSX)
void SpellCheckMessageFilter::OnCallSpellingService(
    int route_id,
    int identifier,
    const base::string16& text,
    std::vector<SpellCheckMarker> markers) {
  DCHECK(!text.empty());
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  // Erase invalid markers (with offsets out of boundaries of text length).
  markers.erase(
      std::remove_if(
          markers.begin(),
          markers.end(),
          std::not1(SpellCheckMarker::IsValidPredicate(text.length()))),
      markers.end());
  CallSpellingService(text, route_id, identifier, markers);
}

void SpellCheckMessageFilter::OnTextCheckComplete(
    int route_id,
    int identifier,
    const std::vector<SpellCheckMarker>& markers,
    bool success,
    const base::string16& text,
    const std::vector<SpellCheckResult>& results) {
  SpellcheckService* spellcheck = GetSpellcheckService();
  // Spellcheck service may not be available for a renderer process that is
  // shutting down.
  if (!spellcheck)
    return;
  std::vector<SpellCheckResult> results_copy = results;
  spellcheck->GetFeedbackSender()->OnSpellcheckResults(
      render_process_id_, text, markers, &results_copy);

  // Erase custom dictionary words from the spellcheck results and record
  // in-dictionary feedback.
  std::vector<SpellCheckResult>::iterator write_iter;
  std::vector<SpellCheckResult>::iterator iter;
  std::string text_copy = base::UTF16ToUTF8(text);
  for (iter = write_iter = results_copy.begin();
       iter != results_copy.end();
       ++iter) {
    if (spellcheck->GetCustomDictionary()->HasWord(
            text_copy.substr(iter->location, iter->length))) {
      spellcheck->GetFeedbackSender()->RecordInDictionary(iter->hash);
    } else {
      if (write_iter != iter)
        *write_iter = *iter;
      ++write_iter;
    }
  }
  results_copy.erase(write_iter, results_copy.end());

  Send(new SpellCheckMsg_RespondSpellingService(
      route_id, identifier, success, text, results_copy));
}

// CallSpellingService always executes the callback OnTextCheckComplete.
// (Which, in turn, sends a SpellCheckMsg_RespondSpellingService)
void SpellCheckMessageFilter::CallSpellingService(
    const base::string16& text,
    int route_id,
    int identifier,
    const std::vector<SpellCheckMarker>& markers) {
  content::RenderProcessHost* host =
      content::RenderProcessHost::FromID(render_process_id_);

  client_->RequestTextCheck(
    host ? host->GetBrowserContext() : NULL,
    SpellingServiceClient::SPELLCHECK,
    text,
    base::Bind(&SpellCheckMessageFilter::OnTextCheckComplete,
               base::Unretained(this),
               route_id,
               identifier,
               markers));
}
#endif

SpellcheckService* SpellCheckMessageFilter::GetSpellcheckService() const {
  return SpellcheckServiceFactory::GetForRenderProcessId(render_process_id_);
}
