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