root/chrome/browser/spellchecker/feedback.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. GetMisspelling
  2. FinalizeRemovedMisspellings
  3. RendererHasMisspellings
  4. GetMisspellingsInRenderer
  5. EraseFinalizedMisspellings
  6. HasMisspelling
  7. AddMisspelling
  8. Empty
  9. GetRendersWithMisspellings
  10. FinalizeAllMisspellings
  11. GetAllMisspellings
  12. Clear
  13. FindMisspellings

// Copyright (c) 2013 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.
//
// The |Feedback| object keeps track of each instance of user feedback in a map
// |misspellings_|. This is a map from uint32 hashes to |Misspelling| objects.
//
// Each misspelling should be present in only one renderer process. The
// |Feedback| objects keeps track of misspelling-renderer relationship in the
// |renderers_| map of renderer process identifiers to a set of hashes.
//
// When the user adds a misspelling to their custom dictionary, all of the
// |Misspelling| objects with the same misspelled string are updated. The
// |Feedback| object facilitates efficient access to these misspellings through
// a |text_| map of misspelled strings to a set of hashes.

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

#include <algorithm>
#include <iterator>

#include "base/stl_util.h"

namespace spellcheck {

Feedback::Feedback() {
}

Feedback::~Feedback() {
}

Misspelling* Feedback::GetMisspelling(uint32 hash) {
  HashMisspellingMap::iterator misspelling_it = misspellings_.find(hash);
  if (misspelling_it == misspellings_.end())
    return NULL;
  return &misspelling_it->second;
}

void Feedback::FinalizeRemovedMisspellings(
    int renderer_process_id,
    const std::vector<uint32>& remaining_markers) {
  RendererHashesMap::iterator renderer_it =
      renderers_.find(renderer_process_id);
  if (renderer_it == renderers_.end() || renderer_it->second.empty())
    return;
  HashCollection& renderer_hashes = renderer_it->second;
  HashCollection remaining_hashes(remaining_markers.begin(),
                                  remaining_markers.end());
  std::vector<uint32> removed_hashes =
      base::STLSetDifference<std::vector<uint32> >(renderer_hashes,
                                                   remaining_hashes);
  for (std::vector<uint32>::const_iterator hash_it = removed_hashes.begin();
       hash_it != removed_hashes.end();
       ++hash_it) {
    HashMisspellingMap::iterator misspelling_it = misspellings_.find(*hash_it);
    if (misspelling_it != misspellings_.end() &&
        !misspelling_it->second.action.IsFinal()) {
      misspelling_it->second.action.Finalize();
    }
  }
}

bool Feedback::RendererHasMisspellings(int renderer_process_id) const {
  RendererHashesMap::const_iterator renderer_it =
      renderers_.find(renderer_process_id);
  return renderer_it != renderers_.end() && !renderer_it->second.empty();
}

std::vector<Misspelling> Feedback::GetMisspellingsInRenderer(
    int renderer_process_id) const {
  std::vector<Misspelling> misspellings_in_renderer;
  RendererHashesMap::const_iterator renderer_it =
      renderers_.find(renderer_process_id);
  if (renderer_it == renderers_.end() || renderer_it->second.empty())
    return misspellings_in_renderer;
  const HashCollection& renderer_hashes = renderer_it->second;
  for (HashCollection::const_iterator hash_it = renderer_hashes.begin();
       hash_it != renderer_hashes.end();
       ++hash_it) {
    HashMisspellingMap::const_iterator misspelling_it =
        misspellings_.find(*hash_it);
    if (misspelling_it != misspellings_.end())
      misspellings_in_renderer.push_back(misspelling_it->second);
  }
  return misspellings_in_renderer;
}

void Feedback::EraseFinalizedMisspellings(int renderer_process_id) {
  RendererHashesMap::iterator renderer_it =
      renderers_.find(renderer_process_id);
  if (renderer_it == renderers_.end())
    return;
  HashCollection& renderer_hashes = renderer_it->second;
  for (HashCollection::const_iterator hash_it = renderer_hashes.begin();
       hash_it != renderer_hashes.end();) {
    HashMisspellingMap::iterator misspelling_it = misspellings_.find(*hash_it);
    HashCollection::iterator erasable_hash_it = hash_it;
    ++hash_it;
    if (misspelling_it == misspellings_.end())
      continue;
    const Misspelling& misspelling = misspelling_it->second;
    if (!misspelling.action.IsFinal())
      continue;
    renderer_hashes.erase(erasable_hash_it);
    text_[misspelling.GetMisspelledString()].erase(misspelling.hash);
    misspellings_.erase(misspelling_it);
  }
  if (renderer_hashes.empty())
    renderers_.erase(renderer_it);
}

bool Feedback::HasMisspelling(uint32 hash) const {
  return !!misspellings_.count(hash);
}

void Feedback::AddMisspelling(int renderer_process_id,
                              const Misspelling& misspelling) {
  HashMisspellingMap::iterator misspelling_it =
      misspellings_.find(misspelling.hash);
  if (misspelling_it != misspellings_.end()) {
    const Misspelling& existing_misspelling = misspelling_it->second;
    text_[existing_misspelling.GetMisspelledString()].erase(misspelling.hash);
    for (RendererHashesMap::iterator renderer_it = renderers_.begin();
         renderer_it != renderers_.end();) {
      HashCollection& renderer_hashes = renderer_it->second;
      RendererHashesMap::iterator erasable_renderer_it = renderer_it;
      ++renderer_it;
      renderer_hashes.erase(misspelling.hash);
      if (renderer_hashes.empty())
        renderers_.erase(erasable_renderer_it);
    }
  }
  misspellings_[misspelling.hash] = misspelling;
  text_[misspelling.GetMisspelledString()].insert(misspelling.hash);
  renderers_[renderer_process_id].insert(misspelling.hash);
}

bool Feedback::Empty() const {
  return misspellings_.empty();
}

std::vector<int> Feedback::GetRendersWithMisspellings() const {
  std::vector<int> renderers_with_misspellings;
  for (RendererHashesMap::const_iterator renderer_it = renderers_.begin();
       renderer_it != renderers_.end();
       ++renderer_it) {
    if (!renderer_it->second.empty())
      renderers_with_misspellings.push_back(renderer_it->first);
  }
  return renderers_with_misspellings;
}

void Feedback::FinalizeAllMisspellings() {
  for (HashMisspellingMap::iterator misspelling_it = misspellings_.begin();
       misspelling_it != misspellings_.end();
       ++misspelling_it) {
    if (!misspelling_it->second.action.IsFinal())
      misspelling_it->second.action.Finalize();
  }
}

std::vector<Misspelling> Feedback::GetAllMisspellings() const {
  std::vector<Misspelling> all_misspellings;
  for (HashMisspellingMap::const_iterator misspelling_it =
           misspellings_.begin();
       misspelling_it != misspellings_.end();
       ++misspelling_it) {
    all_misspellings.push_back(misspelling_it->second);
  }
  return all_misspellings;
}

void Feedback::Clear() {
  misspellings_.clear();
  text_.clear();
  renderers_.clear();
}

const std::set<uint32>& Feedback::FindMisspellings(
    const base::string16& misspelled_text) const {
  const TextHashesMap::const_iterator text_it = text_.find(misspelled_text);
  return text_it == text_.end() ? empty_hash_collection_ : text_it->second;
}

}  // namespace spellcheck

/* [<][>][^][v][top][bottom][index][help] */