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 #include "base/stl_util.h" 23 24 namespace spellcheck { 25 26 Feedback::Feedback() { 27 } 28 29 Feedback::~Feedback() { 30 } 31 32 Misspelling* Feedback::GetMisspelling(uint32 hash) { 33 HashMisspellingMap::iterator misspelling_it = misspellings_.find(hash); 34 if (misspelling_it == misspellings_.end()) 35 return NULL; 36 return &misspelling_it->second; 37 } 38 39 void Feedback::FinalizeRemovedMisspellings( 40 int renderer_process_id, 41 const std::vector<uint32>& remaining_markers) { 42 RendererHashesMap::iterator renderer_it = 43 renderers_.find(renderer_process_id); 44 if (renderer_it == renderers_.end() || renderer_it->second.empty()) 45 return; 46 HashCollection& renderer_hashes = renderer_it->second; 47 HashCollection remaining_hashes(remaining_markers.begin(), 48 remaining_markers.end()); 49 std::vector<uint32> removed_hashes = 50 base::STLSetDifference<std::vector<uint32> >(renderer_hashes, 51 remaining_hashes); 52 for (std::vector<uint32>::const_iterator hash_it = removed_hashes.begin(); 53 hash_it != removed_hashes.end(); 54 ++hash_it) { 55 HashMisspellingMap::iterator misspelling_it = misspellings_.find(*hash_it); 56 if (misspelling_it != misspellings_.end() && 57 !misspelling_it->second.action.IsFinal()) { 58 misspelling_it->second.action.Finalize(); 59 } 60 } 61 } 62 63 bool Feedback::RendererHasMisspellings(int renderer_process_id) const { 64 RendererHashesMap::const_iterator renderer_it = 65 renderers_.find(renderer_process_id); 66 return renderer_it != renderers_.end() && !renderer_it->second.empty(); 67 } 68 69 std::vector<Misspelling> Feedback::GetMisspellingsInRenderer( 70 int renderer_process_id) const { 71 std::vector<Misspelling> misspellings_in_renderer; 72 RendererHashesMap::const_iterator renderer_it = 73 renderers_.find(renderer_process_id); 74 if (renderer_it == renderers_.end() || renderer_it->second.empty()) 75 return misspellings_in_renderer; 76 const HashCollection& renderer_hashes = renderer_it->second; 77 for (HashCollection::const_iterator hash_it = renderer_hashes.begin(); 78 hash_it != renderer_hashes.end(); 79 ++hash_it) { 80 HashMisspellingMap::const_iterator misspelling_it = 81 misspellings_.find(*hash_it); 82 if (misspelling_it != misspellings_.end()) 83 misspellings_in_renderer.push_back(misspelling_it->second); 84 } 85 return misspellings_in_renderer; 86 } 87 88 void Feedback::EraseFinalizedMisspellings(int renderer_process_id) { 89 RendererHashesMap::iterator renderer_it = 90 renderers_.find(renderer_process_id); 91 if (renderer_it == renderers_.end()) 92 return; 93 HashCollection& renderer_hashes = renderer_it->second; 94 for (HashCollection::const_iterator hash_it = renderer_hashes.begin(); 95 hash_it != renderer_hashes.end();) { 96 HashMisspellingMap::iterator misspelling_it = misspellings_.find(*hash_it); 97 HashCollection::iterator erasable_hash_it = hash_it; 98 ++hash_it; 99 if (misspelling_it == misspellings_.end()) 100 continue; 101 const Misspelling& misspelling = misspelling_it->second; 102 if (!misspelling.action.IsFinal()) 103 continue; 104 renderer_hashes.erase(erasable_hash_it); 105 text_[misspelling.GetMisspelledString()].erase(misspelling.hash); 106 misspellings_.erase(misspelling_it); 107 } 108 if (renderer_hashes.empty()) 109 renderers_.erase(renderer_it); 110 } 111 112 bool Feedback::HasMisspelling(uint32 hash) const { 113 return !!misspellings_.count(hash); 114 } 115 116 void Feedback::AddMisspelling(int renderer_process_id, 117 const Misspelling& misspelling) { 118 HashMisspellingMap::iterator misspelling_it = 119 misspellings_.find(misspelling.hash); 120 if (misspelling_it != misspellings_.end()) { 121 const Misspelling& existing_misspelling = misspelling_it->second; 122 text_[existing_misspelling.GetMisspelledString()].erase(misspelling.hash); 123 for (RendererHashesMap::iterator renderer_it = renderers_.begin(); 124 renderer_it != renderers_.end();) { 125 HashCollection& renderer_hashes = renderer_it->second; 126 RendererHashesMap::iterator erasable_renderer_it = renderer_it; 127 ++renderer_it; 128 renderer_hashes.erase(misspelling.hash); 129 if (renderer_hashes.empty()) 130 renderers_.erase(erasable_renderer_it); 131 } 132 } 133 misspellings_[misspelling.hash] = misspelling; 134 text_[misspelling.GetMisspelledString()].insert(misspelling.hash); 135 renderers_[renderer_process_id].insert(misspelling.hash); 136 } 137 138 bool Feedback::Empty() const { 139 return misspellings_.empty(); 140 } 141 142 std::vector<int> Feedback::GetRendersWithMisspellings() const { 143 std::vector<int> renderers_with_misspellings; 144 for (RendererHashesMap::const_iterator renderer_it = renderers_.begin(); 145 renderer_it != renderers_.end(); 146 ++renderer_it) { 147 if (!renderer_it->second.empty()) 148 renderers_with_misspellings.push_back(renderer_it->first); 149 } 150 return renderers_with_misspellings; 151 } 152 153 void Feedback::FinalizeAllMisspellings() { 154 for (HashMisspellingMap::iterator misspelling_it = misspellings_.begin(); 155 misspelling_it != misspellings_.end(); 156 ++misspelling_it) { 157 if (!misspelling_it->second.action.IsFinal()) 158 misspelling_it->second.action.Finalize(); 159 } 160 } 161 162 std::vector<Misspelling> Feedback::GetAllMisspellings() const { 163 std::vector<Misspelling> all_misspellings; 164 for (HashMisspellingMap::const_iterator misspelling_it = 165 misspellings_.begin(); 166 misspelling_it != misspellings_.end(); 167 ++misspelling_it) { 168 all_misspellings.push_back(misspelling_it->second); 169 } 170 return all_misspellings; 171 } 172 173 void Feedback::Clear() { 174 misspellings_.clear(); 175 text_.clear(); 176 renderers_.clear(); 177 } 178 179 const std::set<uint32>& Feedback::FindMisspellings( 180 const base::string16& misspelled_text) const { 181 const TextHashesMap::const_iterator text_it = text_.find(misspelled_text); 182 return text_it == text_.end() ? empty_hash_collection_ : text_it->second; 183 } 184 185 } // namespace spellcheck 186