diff options
4 files changed, 129 insertions, 4 deletions
diff --git a/chrome/browser/resources/options/language_dictionary_overlay.js b/chrome/browser/resources/options/language_dictionary_overlay.js index 87dcf77..c715423 100644 --- a/chrome/browser/resources/options/language_dictionary_overlay.js +++ b/chrome/browser/resources/options/language_dictionary_overlay.js @@ -97,6 +97,11 @@ cr.define('options', function() { EditDictionaryOverlay.getInstance().wordList_.setWordList(entries); }; + EditDictionaryOverlay.updateWords = function(add_words, remove_words) { + EditDictionaryOverlay.getInstance().wordList_.addWords(add_words); + EditDictionaryOverlay.getInstance().wordList_.removeWords(remove_words); + }; + EditDictionaryOverlay.getWordListForTesting = function() { return EditDictionaryOverlay.getInstance().wordList_; }; diff --git a/chrome/browser/resources/options/language_dictionary_overlay_word_list.js b/chrome/browser/resources/options/language_dictionary_overlay_word_list.js index b1bff43..f27b84f 100644 --- a/chrome/browser/resources/options/language_dictionary_overlay_word_list.js +++ b/chrome/browser/resources/options/language_dictionary_overlay_word_list.js @@ -98,7 +98,15 @@ cr.define('options.dictionary_words', function() { allWordsList_: null, /** - * Add a dictionary word. + * The list of words that the user removed, but |DictionaryWordList| has not + * received a notification of their removal yet. + * @type {Array} + * @private + */ + removedWordsList_: [], + + /** + * Adds a dictionary word. * @param {string} dictionaryWord The word to add. * @private */ @@ -110,7 +118,7 @@ cr.define('options.dictionary_words', function() { }, /** - * Search the list for the matching words. + * Searches the list for the matching words. * @param {string} searchTerm The search term. */ search: function(searchTerm) { @@ -124,7 +132,7 @@ cr.define('options.dictionary_words', function() { }, /** - * Set the list of dictionary words. + * Sets the list of dictionary words. * @param {Array} entries The list of dictionary words. */ setWordList: function(entries) { @@ -136,7 +144,57 @@ cr.define('options.dictionary_words', function() { }, /** - * True if the data model contains no words, otherwise false. + * Adds non-duplicate dictionary words. + * @param {Array} entries The list of dictionary words. + */ + addWords: function(entries) { + var to_add = []; + for (var i = 0; i < entries.length; i++) { + if (this.allWordsList_.indexOf(entries[i]) == -1) { + this.allWordsList_.push(entries[i]); + to_add.push(entries[i]); + } + } + if (to_add.length == 0) + return; + for (var i = 0; i < to_add.length; i++) + this.dataModel.splice(this.dataModel.length - 1, 0, to_add[i]); + this.onWordListChanged(); + }, + + /** + * Removes dictionary words that are not in |removedWordsList_|. If a word + * is in |removedWordsList_|, then removes the word from there instead. + * @param {Array} entries The list of dictionary words. + */ + removeWords: function(entries) { + var index; + var to_remove = []; + for (var i = 0; i < entries.length; i++) { + index = this.removedWordsList_.indexOf(entries[i]); + if (index > -1) { + this.removedWordsList_.splice(index, 1); + } else { + index = this.allWordsList_.indexOf(entries[i]); + if (index > -1) { + this.allWordsList_.splice(index, 1); + to_remove.push(entries[i]); + } + } + } + if (to_remove.length == 0) + return; + for (var i = 0; i < to_remove.length; i++) { + index = this.dataModel.indexOf(to_remove[i]); + if (index > -1) + this.dataModel.splice(index, 1); + } + this.onWordListChanged(); + }, + + /** + * Returns true if the data model contains no words, otherwise returns + * false. * @type {boolean} */ get empty() { @@ -162,6 +220,7 @@ cr.define('options.dictionary_words', function() { assert(allWordsListIndex > -1); this.allWordsList_.splice(allWordsListIndex, 1); this.dataModel.splice(index, 1); + this.removedWordsList_.push(item); this.onWordListChanged(); chrome.send('removeDictionaryWord', [item]); }, diff --git a/chrome/browser/ui/webui/options/edit_dictionary_browsertest.js b/chrome/browser/ui/webui/options/edit_dictionary_browsertest.js index 0e15221..ad8ce80 100644 --- a/chrome/browser/ui/webui/options/edit_dictionary_browsertest.js +++ b/chrome/browser/ui/webui/options/edit_dictionary_browsertest.js @@ -35,6 +35,7 @@ EditDictionaryWebUITest.prototype = { }, }; +// Verify that users can add and remove words in the dictionary. TEST_F('EditDictionaryWebUITest', 'testAddRemoveWords', function() { var testWord = 'foo'; $('language-dictionary-overlay-word-list').querySelector('input').value = @@ -54,6 +55,7 @@ TEST_F('EditDictionaryWebUITest', 'testAddRemoveWords', function() { EditDictionaryOverlay.getWordListForTesting().deleteItemAtIndex(0); }); +// Verify that users can search words in the dictionary. TEST_F('EditDictionaryWebUITest', 'testSearch', function() { EditDictionaryOverlay.setWordList(['foo', 'bar']); expectEquals(3, EditDictionaryOverlay.getWordListForTesting().items.length); @@ -73,3 +75,50 @@ TEST_F('EditDictionaryWebUITest', 'testSearch', function() { fakeSearchEvent(searchField, ''); expectEquals(3, EditDictionaryOverlay.getWordListForTesting().items.length); }); + +// Verify that dictionary shows newly added words that arrived in a +// notification, but ignores duplicate add notifications. +TEST_F('EditDictionaryWebUITest', 'testAddNotification', function() { + // Begin with an empty dictionary. + EditDictionaryOverlay.setWordList([]); + expectEquals(1, EditDictionaryOverlay.getWordListForTesting().items.length); + + // User adds word 'foo'. + EditDictionaryOverlay.getWordListForTesting().addDictionaryWord_('foo'); + expectEquals(2, EditDictionaryOverlay.getWordListForTesting().items.length); + + // Backend notifies UI that the word 'foo' has been added. UI ignores this + // notification, because the word is displayed immediately after user added + // it. + EditDictionaryOverlay.updateWords(['foo'], []); + expectEquals(2, EditDictionaryOverlay.getWordListForTesting().items.length); + + // Backend notifies UI that the words 'bar' and 'baz' were added. UI shows + // these new words. + EditDictionaryOverlay.updateWords(['bar', 'baz'], []); + expectEquals(4, EditDictionaryOverlay.getWordListForTesting().items.length); +}); + +// Verify that dictionary hides newly removed words that arrived in a +// notification, but ignores duplicate remove notifications. +TEST_F('EditDictionaryWebUITest', 'testRemoveNotification', function() { + // Begin with a dictionary with words 'foo', 'bar', 'baz', and 'baz'. The + // second instance of 'baz' appears because the user added the word twice. + // The backend keeps only one copy of the word. + EditDictionaryOverlay.setWordList(['foo', 'bar', 'baz', 'baz']); + expectEquals(5, EditDictionaryOverlay.getWordListForTesting().items.length); + + // User deletes the second instance of 'baz'. + EditDictionaryOverlay.getWordListForTesting().deleteItemAtIndex(3); + expectEquals(4, EditDictionaryOverlay.getWordListForTesting().items.length); + + // Backend notifies UI that the word 'baz' has been removed. UI ignores this + // notification. + EditDictionaryOverlay.updateWords([], ['baz']); + expectEquals(4, EditDictionaryOverlay.getWordListForTesting().items.length); + + // Backend notifies UI that words 'foo' and 'bar' have been removed. UI + // removes these words. + EditDictionaryOverlay.updateWords([], ['foo', 'bar']); + expectEquals(2, EditDictionaryOverlay.getWordListForTesting().items.length); +}); diff --git a/chrome/browser/ui/webui/options/language_dictionary_overlay_handler.cc b/chrome/browser/ui/webui/options/language_dictionary_overlay_handler.cc index 32a5ecc..9b3b091 100644 --- a/chrome/browser/ui/webui/options/language_dictionary_overlay_handler.cc +++ b/chrome/browser/ui/webui/options/language_dictionary_overlay_handler.cc @@ -77,10 +77,22 @@ void LanguageDictionaryOverlayHandler::OnCustomDictionaryLoaded() { void LanguageDictionaryOverlayHandler::OnCustomDictionaryWordAdded( const std::string& word) { + ListValue add_words; + ListValue remove_words; + add_words.AppendString(word); + web_ui()->CallJavascriptFunction("EditDictionaryOverlay.updateWords", + add_words, + remove_words); } void LanguageDictionaryOverlayHandler::OnCustomDictionaryWordRemoved( const std::string& word) { + ListValue add_words; + ListValue remove_words; + remove_words.AppendString(word); + web_ui()->CallJavascriptFunction("EditDictionaryOverlay.updateWords", + add_words, + remove_words); } void LanguageDictionaryOverlayHandler::ResetDictionaryWords() { |