| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 
 | // Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/spellcheck/renderer/hunspell_engine.h"
#include <stddef.h>
#include <algorithm>
#include <iterator>
#include <memory>
#include <utility>
#include "base/files/memory_mapped_file.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "components/spellcheck/common/spellcheck.mojom.h"
#include "components/spellcheck/common/spellcheck_common.h"
#include "content/public/renderer/render_thread.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/service_manager/public/cpp/local_interface_provider.h"
#include "third_party/hunspell/src/hunspell/hunspell.hxx"
using content::RenderThread;
namespace {
  // Maximum length of words we actually check.
  // 64 is the observed limits for OSX system checker.
  const size_t kMaxCheckedLen = 64;
  // Maximum length of words we provide suggestions for.
  // 24 is the observed limits for OSX system checker.
  const size_t kMaxSuggestLen = 24;
  static_assert(kMaxCheckedLen <= size_t(MAXWORDLEN),
                "MaxCheckedLen too long");
  static_assert(kMaxSuggestLen <= kMaxCheckedLen,
                "MaxSuggestLen too long");
}  // namespace
HunspellEngine::HunspellEngine(
    service_manager::LocalInterfaceProvider* embedder_provider)
    : hunspell_enabled_(false),
      initialized_(false),
      dictionary_requested_(false),
      embedder_provider_(embedder_provider) {
  // Wait till we check the first word before doing any initializing.
}
HunspellEngine::~HunspellEngine() {
}
void HunspellEngine::Init(base::File file) {
  initialized_ = true;
  hunspell_.reset();
  bdict_file_.reset();
  file_ = std::move(file);
  hunspell_enabled_ = file_.IsValid();
  // Delay the actual initialization of hunspell until it is needed.
}
void HunspellEngine::InitializeHunspell() {
  if (hunspell_)
    return;
  bdict_file_ = std::make_unique<base::MemoryMappedFile>();
  if (bdict_file_->Initialize(std::move(file_))) {
    hunspell_ = std::make_unique<Hunspell>(bdict_file_->bytes());
  } else {
    NOTREACHED() << "Could not mmap spellchecker dictionary.";
  }
}
bool HunspellEngine::CheckSpelling(const std::u16string& word_to_check,
                                   spellcheck::mojom::SpellCheckHost& host) {
  // Assume all words that cannot be checked are valid. Since Chrome can't
  // offer suggestions on them, either, there's no point in flagging them to
  // the user.
  bool word_correct = true;
  std::string word_to_check_utf8(base::UTF16ToUTF8(word_to_check));
  // Limit the size of checked words.
  if (word_to_check_utf8.length() <= kMaxCheckedLen) {
    // If |hunspell_| is NULL here, an error has occurred, but it's better
    // to check rather than crash.
    if (hunspell_) {
      // |hunspell_->spell| returns 0 if the word is misspelled.
      word_correct = (hunspell_->spell(word_to_check_utf8) != 0);
    }
  }
  return word_correct;
}
void HunspellEngine::FillSuggestionList(
    const std::u16string& wrong_word,
    spellcheck::mojom::SpellCheckHost& host,
    std::vector<std::u16string>* optional_suggestions) {
  std::string wrong_word_utf8(base::UTF16ToUTF8(wrong_word));
  if (wrong_word_utf8.length() > kMaxSuggestLen)
    return;
  // If |hunspell_| is NULL here, an error has occurred, but it's better
  // to check rather than crash.
  // TODO(groby): Technically, it's not. We should track down the issue.
  if (!hunspell_)
    return;
  std::vector<std::string> suggestions =
      hunspell_->suggest(wrong_word_utf8);
  // Populate the vector of WideStrings.
  for (size_t i = 0; i < suggestions.size(); ++i) {
    if (i < spellcheck::kMaxSuggestions)
      optional_suggestions->push_back(base::UTF8ToUTF16(suggestions[i]));
  }
}
bool HunspellEngine::InitializeIfNeeded() {
  if (!initialized_ && !dictionary_requested_) {
    mojo::Remote<spellcheck::mojom::SpellCheckInitializationHost>
        spell_check_init_host;
    embedder_provider_->GetInterface(
        spell_check_init_host.BindNewPipeAndPassReceiver());
    spell_check_init_host->RequestDictionary();
    dictionary_requested_ = true;
    return true;
  }
  // Don't initialize if hunspell is disabled.
  if (file_.IsValid())
    InitializeHunspell();
  return !initialized_;
}
bool HunspellEngine::IsEnabled() {
  return hunspell_enabled_;
}
 |