Home | History | Annotate | Download | only in spellchecker
      1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 //
      5 // The |Feedback| object keeps track of each instance of user feedback in a map
      6 // |misspellings_|. This is a map from uint32 hashes to |Misspelling| objects.
      7 //
      8 // Each misspelling should be present in only one renderer process. The
      9 // |Feedback| objects keeps track of misspelling-renderer relationship in the
     10 // |renderers_| map of renderer process identifiers to a set of hashes.
     11 //
     12 // When the user adds a misspelling to their custom dictionary, all of the
     13 // |Misspelling| objects with the same misspelled string are updated. The
     14 // |Feedback| object facilitates efficient access to these misspellings through
     15 // a |text_| map of misspelled strings to a set of hashes.
     16 
     17 #include "chrome/browser/spellchecker/feedback.h"
     18 
     19 #include <algorithm>
     20 #include <iterator>
     21 
     22 namespace spellcheck {
     23 
     24 Feedback::Feedback() {
     25 }
     26 
     27 Feedback::~Feedback() {
     28 }
     29 
     30 Misspelling* Feedback::GetMisspelling(uint32 hash) {
     31   HashMisspellingMap::iterator misspelling_it = misspellings_.find(hash);
     32   if (misspelling_it == misspellings_.end())
     33     return NULL;
     34   return &misspelling_it->second;
     35 }
     36 
     37 void Feedback::FinalizeRemovedMisspellings(
     38     int renderer_process_id,
     39     const std::vector<uint32>& remaining_markers) {
     40   RendererHashesMap::iterator renderer_it =
     41       renderers_.find(renderer_process_id);
     42   if (renderer_it == renderers_.end() || renderer_it->second.empty())
     43     return;
     44   HashCollection& renderer_hashes = renderer_it->second;
     45   HashCollection remaining_hashes(remaining_markers.begin(),
     46                                   remaining_markers.end());
     47   std::vector<uint32> removed_hashes;
     48   std::set_difference(renderer_hashes.begin(),
     49                       renderer_hashes.end(),
     50                       remaining_hashes.begin(),
     51                       remaining_hashes.end(),
     52                       std::back_inserter(removed_hashes));
     53   for (std::vector<uint32>::const_iterator hash_it = removed_hashes.begin();
     54        hash_it != removed_hashes.end();
     55        ++hash_it) {
     56     HashMisspellingMap::iterator misspelling_it = misspellings_.find(*hash_it);
     57     if (misspelling_it != misspellings_.end() &&
     58         !misspelling_it->second.action.IsFinal()) {
     59       misspelling_it->second.action.Finalize();
     60     }
     61   }
     62 }
     63 
     64 bool Feedback::RendererHasMisspellings(int renderer_process_id) const {
     65   RendererHashesMap::const_iterator renderer_it =
     66       renderers_.find(renderer_process_id);
     67   return renderer_it != renderers_.end() && !renderer_it->second.empty();
     68 }
     69 
     70 std::vector<Misspelling> Feedback::GetMisspellingsInRenderer(
     71     int renderer_process_id) const {
     72   std::vector<Misspelling> misspellings_in_renderer;
     73   RendererHashesMap::const_iterator renderer_it =
     74       renderers_.find(renderer_process_id);
     75   if (renderer_it == renderers_.end() || renderer_it->second.empty())
     76     return misspellings_in_renderer;
     77   const HashCollection& renderer_hashes = renderer_it->second;
     78   for (HashCollection::const_iterator hash_it = renderer_hashes.begin();
     79        hash_it != renderer_hashes.end();
     80        ++hash_it) {
     81     HashMisspellingMap::const_iterator misspelling_it =
     82         misspellings_.find(*hash_it);
     83     if (misspelling_it != misspellings_.end())
     84       misspellings_in_renderer.push_back(misspelling_it->second);
     85   }
     86   return misspellings_in_renderer;
     87 }
     88 
     89 void Feedback::EraseFinalizedMisspellings(int renderer_process_id) {
     90   RendererHashesMap::iterator renderer_it =
     91       renderers_.find(renderer_process_id);
     92   if (renderer_it == renderers_.end())
     93     return;
     94   HashCollection& renderer_hashes = renderer_it->second;
     95   for (HashCollection::const_iterator hash_it = renderer_hashes.begin();
     96        hash_it != renderer_hashes.end();) {
     97     HashMisspellingMap::iterator misspelling_it = misspellings_.find(*hash_it);
     98     HashCollection::iterator erasable_hash_it = hash_it;
     99     ++hash_it;
    100     if (misspelling_it == misspellings_.end())
    101       continue;
    102     const Misspelling& misspelling = misspelling_it->second;
    103     if (!misspelling.action.IsFinal())
    104       continue;
    105     renderer_hashes.erase(erasable_hash_it);
    106     text_[misspelling.GetMisspelledString()].erase(misspelling.hash);
    107     misspellings_.erase(misspelling_it);
    108   }
    109   if (renderer_hashes.empty())
    110     renderers_.erase(renderer_it);
    111 }
    112 
    113 bool Feedback::HasMisspelling(uint32 hash) const {
    114   return !!misspellings_.count(hash);
    115 }
    116 
    117 void Feedback::AddMisspelling(int renderer_process_id,
    118                               const Misspelling& misspelling) {
    119   HashMisspellingMap::iterator misspelling_it =
    120       misspellings_.find(misspelling.hash);
    121   if (misspelling_it != misspellings_.end()) {
    122     const Misspelling& existing_misspelling = misspelling_it->second;
    123     text_[existing_misspelling.GetMisspelledString()].erase(misspelling.hash);
    124     for (RendererHashesMap::iterator renderer_it = renderers_.begin();
    125          renderer_it != renderers_.end();) {
    126       HashCollection& renderer_hashes = renderer_it->second;
    127       RendererHashesMap::iterator erasable_renderer_it = renderer_it;
    128       ++renderer_it;
    129       renderer_hashes.erase(misspelling.hash);
    130       if (renderer_hashes.empty())
    131         renderers_.erase(erasable_renderer_it);
    132     }
    133   }
    134   misspellings_[misspelling.hash] = misspelling;
    135   text_[misspelling.GetMisspelledString()].insert(misspelling.hash);
    136   renderers_[renderer_process_id].insert(misspelling.hash);
    137 }
    138 
    139 bool Feedback::Empty() const {
    140   return misspellings_.empty();
    141 }
    142 
    143 std::vector<int> Feedback::GetRendersWithMisspellings() const {
    144   std::vector<int> renderers_with_misspellings;
    145   for (RendererHashesMap::const_iterator renderer_it = renderers_.begin();
    146        renderer_it != renderers_.end();
    147        ++renderer_it) {
    148     if (!renderer_it->second.empty())
    149       renderers_with_misspellings.push_back(renderer_it->first);
    150   }
    151   return renderers_with_misspellings;
    152 }
    153 
    154 void Feedback::FinalizeAllMisspellings() {
    155   for (HashMisspellingMap::iterator misspelling_it = misspellings_.begin();
    156        misspelling_it != misspellings_.end();
    157        ++misspelling_it) {
    158     if (!misspelling_it->second.action.IsFinal())
    159       misspelling_it->second.action.Finalize();
    160   }
    161 }
    162 
    163 std::vector<Misspelling> Feedback::GetAllMisspellings() const {
    164   std::vector<Misspelling> all_misspellings;
    165   for (HashMisspellingMap::const_iterator misspelling_it =
    166            misspellings_.begin();
    167        misspelling_it != misspellings_.end();
    168        ++misspelling_it) {
    169     all_misspellings.push_back(misspelling_it->second);
    170   }
    171   return all_misspellings;
    172 }
    173 
    174 void Feedback::Clear() {
    175   misspellings_.clear();
    176   text_.clear();
    177   renderers_.clear();
    178 }
    179 
    180 const std::set<uint32>& Feedback::FindMisspellings(
    181     const string16& misspelled_text) const {
    182   const TextHashesMap::const_iterator text_it = text_.find(misspelled_text);
    183   return text_it == text_.end() ? empty_hash_collection_ : text_it->second;
    184 }
    185 
    186 }  // namespace spellcheck
    187