| 
									
										
										
										
											2014-12-18 13:43:51 -08:00
										 |  |  | // Copyright (c) 2014 GitHub, Inc.
 | 
					
						
							|  |  |  | // Use of this source code is governed by the MIT license that can be
 | 
					
						
							|  |  |  | // found in the LICENSE file.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-19 13:46:59 -07:00
										 |  |  | #include "shell/renderer/api/atom_api_spell_check_client.h"
 | 
					
						
							| 
									
										
										
										
											2014-12-18 13:43:51 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-18 09:11:53 -07:00
										 |  |  | #include <map>
 | 
					
						
							| 
									
										
										
										
											2019-05-31 06:19:10 +02:00
										 |  |  | #include <set>
 | 
					
						
							|  |  |  | #include <unordered_set>
 | 
					
						
							| 
									
										
										
										
											2019-05-16 21:58:03 -07:00
										 |  |  | #include <utility>
 | 
					
						
							| 
									
										
										
										
											2014-12-18 16:44:38 -08:00
										 |  |  | #include <vector>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-18 17:41:42 -08:00
										 |  |  | #include "base/logging.h"
 | 
					
						
							| 
									
										
										
										
											2019-02-21 21:52:53 +05:30
										 |  |  | #include "base/numerics/safe_conversions.h"
 | 
					
						
							| 
									
										
										
										
											2018-04-08 23:18:50 -07:00
										 |  |  | #include "base/threading/thread_task_runner_handle.h"
 | 
					
						
							| 
									
										
										
										
											2018-10-26 19:34:57 +02:00
										 |  |  | #include "components/spellcheck/renderer/spellcheck_worditerator.h"
 | 
					
						
							| 
									
										
										
										
											2014-12-18 16:44:38 -08:00
										 |  |  | #include "native_mate/converter.h"
 | 
					
						
							| 
									
										
										
										
											2014-12-18 17:41:42 -08:00
										 |  |  | #include "native_mate/dictionary.h"
 | 
					
						
							| 
									
										
										
										
											2018-10-18 09:11:53 -07:00
										 |  |  | #include "native_mate/function_template.h"
 | 
					
						
							| 
									
										
										
										
											2019-06-19 13:46:59 -07:00
										 |  |  | #include "shell/common/native_mate_converters/string16_converter.h"
 | 
					
						
							| 
									
										
										
										
											2018-07-20 18:08:18 +02:00
										 |  |  | #include "third_party/blink/public/web/web_text_checking_completion.h"
 | 
					
						
							|  |  |  | #include "third_party/blink/public/web/web_text_checking_result.h"
 | 
					
						
							| 
									
										
										
										
											2018-04-17 21:55:30 -04:00
										 |  |  | #include "third_party/icu/source/common/unicode/uscript.h"
 | 
					
						
							| 
									
										
										
										
											2014-12-18 16:44:38 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-19 14:23:04 -07:00
										 |  |  | namespace electron { | 
					
						
							| 
									
										
										
										
											2014-12-18 13:43:51 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace api { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-18 17:41:42 -08:00
										 |  |  | namespace { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool HasWordCharacters(const base::string16& text, int index) { | 
					
						
							|  |  |  |   const base::char16* data = text.data(); | 
					
						
							|  |  |  |   int length = text.length(); | 
					
						
							|  |  |  |   while (index < length) { | 
					
						
							| 
									
										
										
										
											2016-03-07 20:40:10 -08:00
										 |  |  |     uint32_t code = 0; | 
					
						
							| 
									
										
										
										
											2014-12-18 17:41:42 -08:00
										 |  |  |     U16_NEXT(data, index, length, code); | 
					
						
							|  |  |  |     UErrorCode error = U_ZERO_ERROR; | 
					
						
							|  |  |  |     if (uscript_getScript(code, &error) != USCRIPT_COMMON) | 
					
						
							|  |  |  |       return true; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-31 06:19:10 +02:00
										 |  |  | struct Word { | 
					
						
							|  |  |  |   blink::WebTextCheckingResult result; | 
					
						
							|  |  |  |   base::string16 text; | 
					
						
							|  |  |  |   std::vector<base::string16> contraction_words; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-18 17:41:42 -08:00
										 |  |  | }  // namespace
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-08 23:18:50 -07:00
										 |  |  | class SpellCheckClient::SpellcheckRequest { | 
					
						
							|  |  |  |  public: | 
					
						
							| 
									
										
										
										
											2019-05-16 21:58:03 -07:00
										 |  |  |   SpellcheckRequest( | 
					
						
							|  |  |  |       const base::string16& text, | 
					
						
							|  |  |  |       std::unique_ptr<blink::WebTextCheckingCompletion> completion) | 
					
						
							|  |  |  |       : text_(text), completion_(std::move(completion)) {} | 
					
						
							| 
									
										
										
										
											2018-04-08 23:18:50 -07:00
										 |  |  |   ~SpellcheckRequest() {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-18 09:11:53 -07:00
										 |  |  |   const base::string16& text() const { return text_; } | 
					
						
							| 
									
										
										
										
											2019-05-21 12:22:15 -07:00
										 |  |  |   blink::WebTextCheckingCompletion* completion() { return completion_.get(); } | 
					
						
							| 
									
										
										
										
											2019-05-31 06:19:10 +02:00
										 |  |  |   std::vector<Word>& wordlist() { return word_list_; } | 
					
						
							| 
									
										
										
										
											2018-04-08 23:18:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |  private: | 
					
						
							| 
									
										
										
										
											2019-05-31 06:19:10 +02:00
										 |  |  |   base::string16 text_;          // Text to be checked in this task.
 | 
					
						
							|  |  |  |   std::vector<Word> word_list_;  // List of Words found in text
 | 
					
						
							| 
									
										
										
										
											2018-04-08 23:18:50 -07:00
										 |  |  |   // The interface to send the misspelled ranges to WebKit.
 | 
					
						
							| 
									
										
										
										
											2019-05-21 12:22:15 -07:00
										 |  |  |   std::unique_ptr<blink::WebTextCheckingCompletion> completion_; | 
					
						
							| 
									
										
										
										
											2018-04-08 23:18:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   DISALLOW_COPY_AND_ASSIGN(SpellcheckRequest); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-19 21:01:47 -08:00
										 |  |  | SpellCheckClient::SpellCheckClient(const std::string& language, | 
					
						
							|  |  |  |                                    v8::Isolate* isolate, | 
					
						
							| 
									
										
										
										
											2015-05-22 19:11:22 +08:00
										 |  |  |                                    v8::Local<v8::Object> provider) | 
					
						
							| 
									
										
										
										
											2018-10-18 09:11:53 -07:00
										 |  |  |     : pending_request_param_(nullptr), | 
					
						
							|  |  |  |       isolate_(isolate), | 
					
						
							| 
									
										
										
										
											2017-12-06 12:55:28 +01:00
										 |  |  |       context_(isolate, isolate->GetCurrentContext()), | 
					
						
							| 
									
										
										
										
											2014-12-19 21:01:47 -08:00
										 |  |  |       provider_(isolate, provider) { | 
					
						
							| 
									
										
										
										
											2017-12-06 12:55:28 +01:00
										 |  |  |   DCHECK(!context_.IsEmpty()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-19 20:42:19 -08:00
										 |  |  |   character_attributes_.SetDefaultLanguage(language); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Persistent the method.
 | 
					
						
							|  |  |  |   mate::Dictionary dict(isolate, provider); | 
					
						
							|  |  |  |   dict.Get("spellCheck", &spell_check_); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-12-18 13:43:51 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-06 12:55:28 +01:00
										 |  |  | SpellCheckClient::~SpellCheckClient() { | 
					
						
							|  |  |  |   context_.Reset(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-12-18 13:43:51 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-16 23:42:33 +03:00
										 |  |  | void SpellCheckClient::RequestCheckingOfText( | 
					
						
							| 
									
										
										
										
											2014-12-18 13:43:51 -08:00
										 |  |  |     const blink::WebString& textToCheck, | 
					
						
							| 
									
										
										
										
											2019-05-16 21:58:03 -07:00
										 |  |  |     std::unique_ptr<blink::WebTextCheckingCompletion> completionCallback) { | 
					
						
							| 
									
										
										
										
											2017-06-16 23:42:33 +03:00
										 |  |  |   base::string16 text(textToCheck.Utf16()); | 
					
						
							| 
									
										
										
										
											2018-04-08 23:18:50 -07:00
										 |  |  |   // Ignore invalid requests.
 | 
					
						
							| 
									
										
										
										
											2014-12-18 17:41:42 -08:00
										 |  |  |   if (text.empty() || !HasWordCharacters(text, 0)) { | 
					
						
							| 
									
										
										
										
											2017-06-16 23:42:33 +03:00
										 |  |  |     completionCallback->DidCancelCheckingText(); | 
					
						
							| 
									
										
										
										
											2014-12-18 17:41:42 -08:00
										 |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-08 23:18:50 -07:00
										 |  |  |   // Clean up the previous request before starting a new request.
 | 
					
						
							| 
									
										
										
										
											2018-10-18 09:11:53 -07:00
										 |  |  |   if (pending_request_param_) { | 
					
						
							| 
									
										
										
										
											2018-04-08 23:18:50 -07:00
										 |  |  |     pending_request_param_->completion()->DidCancelCheckingText(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-16 21:58:03 -07:00
										 |  |  |   pending_request_param_.reset( | 
					
						
							|  |  |  |       new SpellcheckRequest(text, std::move(completionCallback))); | 
					
						
							| 
									
										
										
										
											2018-04-08 23:18:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   base::ThreadTaskRunnerHandle::Get()->PostTask( | 
					
						
							|  |  |  |       FROM_HERE, | 
					
						
							| 
									
										
										
										
											2018-10-18 09:11:53 -07:00
										 |  |  |       base::BindOnce(&SpellCheckClient::SpellCheckText, AsWeakPtr())); | 
					
						
							| 
									
										
										
										
											2014-12-18 13:43:51 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-10 12:43:39 -07:00
										 |  |  | bool SpellCheckClient::IsSpellCheckingEnabled() const { | 
					
						
							|  |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-06 09:18:52 -08:00
										 |  |  | void SpellCheckClient::ShowSpellingUI(bool show) {} | 
					
						
							| 
									
										
										
										
											2014-12-18 13:43:51 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-16 23:42:33 +03:00
										 |  |  | bool SpellCheckClient::IsShowingSpellingUI() { | 
					
						
							| 
									
										
										
										
											2014-12-18 13:43:51 -08:00
										 |  |  |   return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-16 23:42:33 +03:00
										 |  |  | void SpellCheckClient::UpdateSpellingUIWithMisspelledWord( | 
					
						
							| 
									
										
										
										
											2018-02-06 09:18:52 -08:00
										 |  |  |     const blink::WebString& word) {} | 
					
						
							| 
									
										
										
										
											2014-12-18 13:43:51 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-18 09:11:53 -07:00
										 |  |  | void SpellCheckClient::SpellCheckText() { | 
					
						
							|  |  |  |   const auto& text = pending_request_param_->text(); | 
					
						
							|  |  |  |   if (text.empty() || spell_check_.IsEmpty()) { | 
					
						
							|  |  |  |     pending_request_param_->completion()->DidCancelCheckingText(); | 
					
						
							|  |  |  |     pending_request_param_ = nullptr; | 
					
						
							| 
									
										
										
										
											2014-12-19 22:13:07 -08:00
										 |  |  |     return; | 
					
						
							| 
									
										
										
										
											2018-10-18 09:11:53 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-12-18 16:44:38 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-19 22:13:07 -08:00
										 |  |  |   if (!text_iterator_.IsInitialized() && | 
					
						
							|  |  |  |       !text_iterator_.Initialize(&character_attributes_, true)) { | 
					
						
							| 
									
										
										
										
											2018-02-06 09:18:52 -08:00
										 |  |  |     // We failed to initialize text_iterator_, return as spelled correctly.
 | 
					
						
							|  |  |  |     VLOG(1) << "Failed to initialize SpellcheckWordIterator"; | 
					
						
							|  |  |  |     return; | 
					
						
							| 
									
										
										
										
											2014-12-19 22:13:07 -08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-12-18 16:44:38 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-06 12:55:28 +01:00
										 |  |  |   if (!contraction_iterator_.IsInitialized() && | 
					
						
							|  |  |  |       !contraction_iterator_.Initialize(&character_attributes_, false)) { | 
					
						
							|  |  |  |     // We failed to initialize the word iterator, return as spelled correctly.
 | 
					
						
							|  |  |  |     VLOG(1) << "Failed to initialize contraction_iterator_"; | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   text_iterator_.SetText(text.c_str(), text.size()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   SpellCheckScope scope(*this); | 
					
						
							|  |  |  |   base::string16 word; | 
					
						
							| 
									
										
										
										
											2019-02-21 21:52:53 +05:30
										 |  |  |   size_t word_start; | 
					
						
							|  |  |  |   size_t word_length; | 
					
						
							| 
									
										
										
										
											2019-05-31 06:19:10 +02:00
										 |  |  |   std::set<base::string16> words; | 
					
						
							|  |  |  |   auto& word_list = pending_request_param_->wordlist(); | 
					
						
							|  |  |  |   Word word_entry; | 
					
						
							| 
									
										
										
										
											2018-10-18 09:11:53 -07:00
										 |  |  |   for (;;) {  // Run until end of text
 | 
					
						
							|  |  |  |     const auto status = | 
					
						
							| 
									
										
										
										
											2019-02-21 21:52:53 +05:30
										 |  |  |         text_iterator_.GetNextWord(&word, &word_start, &word_length); | 
					
						
							| 
									
										
										
										
											2018-10-18 09:11:53 -07:00
										 |  |  |     if (status == SpellcheckWordIterator::IS_END_OF_TEXT) | 
					
						
							|  |  |  |       break; | 
					
						
							| 
									
										
										
										
											2018-02-06 09:18:52 -08:00
										 |  |  |     if (status == SpellcheckWordIterator::IS_SKIPPABLE) | 
					
						
							|  |  |  |       continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-31 06:19:10 +02:00
										 |  |  |     word_entry.result.location = base::checked_cast<int>(word_start); | 
					
						
							|  |  |  |     word_entry.result.length = base::checked_cast<int>(word_length); | 
					
						
							|  |  |  |     word_entry.text = word; | 
					
						
							|  |  |  |     word_entry.contraction_words.clear(); | 
					
						
							| 
									
										
										
										
											2019-02-21 21:52:53 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-31 06:19:10 +02:00
										 |  |  |     word_list.push_back(word_entry); | 
					
						
							|  |  |  |     words.insert(word); | 
					
						
							| 
									
										
										
										
											2014-12-19 22:13:07 -08:00
										 |  |  |     // If the given word is a concatenated word of two or more valid words
 | 
					
						
							|  |  |  |     // (e.g. "hello:hello"), we should treat it as a valid word.
 | 
					
						
							| 
									
										
										
										
											2019-05-31 06:19:10 +02:00
										 |  |  |     if (IsContraction(scope, word, &word_entry.contraction_words)) { | 
					
						
							|  |  |  |       for (const auto& w : word_entry.contraction_words) { | 
					
						
							|  |  |  |         words.insert(w); | 
					
						
							| 
									
										
										
										
											2018-10-18 09:11:53 -07:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-12-19 22:13:07 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-18 09:11:53 -07:00
										 |  |  |   // Send out all the words data to the spellchecker to check
 | 
					
						
							|  |  |  |   SpellCheckWords(scope, words); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-12-19 22:13:07 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-18 09:11:53 -07:00
										 |  |  | void SpellCheckClient::OnSpellCheckDone( | 
					
						
							|  |  |  |     const std::vector<base::string16>& misspelled_words) { | 
					
						
							|  |  |  |   std::vector<blink::WebTextCheckingResult> results; | 
					
						
							| 
									
										
										
										
											2019-05-31 06:19:10 +02:00
										 |  |  |   std::unordered_set<base::string16> misspelled(misspelled_words.begin(), | 
					
						
							|  |  |  |                                                 misspelled_words.end()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   auto& word_list = pending_request_param_->wordlist(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (const auto& word : word_list) { | 
					
						
							|  |  |  |     if (misspelled.find(word.text) != misspelled.end()) { | 
					
						
							|  |  |  |       // If this is a contraction, iterate through parts and accept the word
 | 
					
						
							|  |  |  |       // if none of them are misspelled
 | 
					
						
							|  |  |  |       if (!word.contraction_words.empty()) { | 
					
						
							|  |  |  |         auto all_correct = true; | 
					
						
							|  |  |  |         for (const auto& contraction_word : word.contraction_words) { | 
					
						
							|  |  |  |           if (misspelled.find(contraction_word) != misspelled.end()) { | 
					
						
							|  |  |  |             all_correct = false; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (all_correct) | 
					
						
							|  |  |  |           continue; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       results.push_back(word.result); | 
					
						
							| 
									
										
										
										
											2018-10-18 09:11:53 -07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-12-19 22:13:07 -08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-05-21 12:22:15 -07:00
										 |  |  |   pending_request_param_->completion()->DidFinishCheckingText(results); | 
					
						
							| 
									
										
										
										
											2018-10-18 09:11:53 -07:00
										 |  |  |   pending_request_param_ = nullptr; | 
					
						
							| 
									
										
										
										
											2014-12-18 16:44:38 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-31 06:19:10 +02:00
										 |  |  | void SpellCheckClient::SpellCheckWords(const SpellCheckScope& scope, | 
					
						
							|  |  |  |                                        const std::set<base::string16>& words) { | 
					
						
							| 
									
										
										
										
											2018-02-06 09:18:52 -08:00
										 |  |  |   DCHECK(!scope.spell_check_.IsEmpty()); | 
					
						
							| 
									
										
										
										
											2014-12-19 20:42:19 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-18 09:11:53 -07:00
										 |  |  |   v8::Local<v8::FunctionTemplate> templ = mate::CreateFunctionTemplate( | 
					
						
							| 
									
										
										
										
											2019-05-03 12:08:41 -07:00
										 |  |  |       isolate_, | 
					
						
							|  |  |  |       base::BindRepeating(&SpellCheckClient::OnSpellCheckDone, AsWeakPtr())); | 
					
						
							| 
									
										
										
										
											2014-12-19 20:42:19 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-09 11:17:05 -08:00
										 |  |  |   auto context = isolate_->GetCurrentContext(); | 
					
						
							| 
									
										
										
										
											2018-10-18 09:11:53 -07:00
										 |  |  |   v8::Local<v8::Value> args[] = {mate::ConvertToV8(isolate_, words), | 
					
						
							| 
									
										
										
										
											2019-01-09 11:17:05 -08:00
										 |  |  |                                  templ->GetFunction(context).ToLocalChecked()}; | 
					
						
							| 
									
										
										
										
											2018-10-18 09:11:53 -07:00
										 |  |  |   // Call javascript with the words and the callback function
 | 
					
						
							| 
									
										
										
										
											2019-03-21 00:27:06 +09:00
										 |  |  |   scope.spell_check_->Call(context, scope.provider_, 2, args).IsEmpty(); | 
					
						
							| 
									
										
										
										
											2014-12-19 20:42:19 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-18 09:11:53 -07:00
										 |  |  | // Returns whether or not the given string is a contraction.
 | 
					
						
							| 
									
										
										
										
											2014-12-19 20:42:19 -08:00
										 |  |  | // This function is a fall-back when the SpellcheckWordIterator class
 | 
					
						
							|  |  |  | // returns a concatenated word which is not in the selected dictionary
 | 
					
						
							|  |  |  | // (e.g. "in'n'out") but each word is valid.
 | 
					
						
							| 
									
										
										
										
											2018-10-18 09:11:53 -07:00
										 |  |  | // Output variable contraction_words will contain individual
 | 
					
						
							|  |  |  | // words in the contraction.
 | 
					
						
							|  |  |  | bool SpellCheckClient::IsContraction( | 
					
						
							|  |  |  |     const SpellCheckScope& scope, | 
					
						
							|  |  |  |     const base::string16& contraction, | 
					
						
							|  |  |  |     std::vector<base::string16>* contraction_words) { | 
					
						
							| 
									
										
										
										
											2017-12-06 12:55:28 +01:00
										 |  |  |   DCHECK(contraction_iterator_.IsInitialized()); | 
					
						
							| 
									
										
										
										
											2014-12-19 20:42:19 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   contraction_iterator_.SetText(contraction.c_str(), contraction.length()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   base::string16 word; | 
					
						
							| 
									
										
										
										
											2019-02-21 21:52:53 +05:30
										 |  |  |   size_t word_start; | 
					
						
							|  |  |  |   size_t word_length; | 
					
						
							| 
									
										
										
										
											2018-02-06 09:18:52 -08:00
										 |  |  |   for (auto status = | 
					
						
							|  |  |  |            contraction_iterator_.GetNextWord(&word, &word_start, &word_length); | 
					
						
							|  |  |  |        status != SpellcheckWordIterator::IS_END_OF_TEXT; | 
					
						
							|  |  |  |        status = contraction_iterator_.GetNextWord(&word, &word_start, | 
					
						
							|  |  |  |                                                   &word_length)) { | 
					
						
							|  |  |  |     if (status == SpellcheckWordIterator::IS_SKIPPABLE) | 
					
						
							|  |  |  |       continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-18 09:11:53 -07:00
										 |  |  |     contraction_words->push_back(word); | 
					
						
							| 
									
										
										
										
											2014-12-19 20:42:19 -08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-10-18 09:11:53 -07:00
										 |  |  |   return contraction_words->size() > 1; | 
					
						
							| 
									
										
										
										
											2018-04-08 23:18:50 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-06 12:55:28 +01:00
										 |  |  | SpellCheckClient::SpellCheckScope::SpellCheckScope( | 
					
						
							|  |  |  |     const SpellCheckClient& client) | 
					
						
							|  |  |  |     : handle_scope_(client.isolate_), | 
					
						
							|  |  |  |       context_scope_( | 
					
						
							|  |  |  |           v8::Local<v8::Context>::New(client.isolate_, client.context_)), | 
					
						
							|  |  |  |       provider_(client.provider_.NewHandle()), | 
					
						
							|  |  |  |       spell_check_(client.spell_check_.NewHandle()) {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-17 16:37:22 -07:00
										 |  |  | SpellCheckClient::SpellCheckScope::~SpellCheckScope() = default; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-18 13:43:51 -08:00
										 |  |  | }  // namespace api
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-19 14:23:04 -07:00
										 |  |  | }  // namespace electron
 |