OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/spellcheck/renderer/spellcheck_provider.h" | 5 #include "components/spellcheck/renderer/spellcheck_provider.h" |
6 | 6 |
| 7 #include "base/bind.h" |
7 #include "base/metrics/histogram_macros.h" | 8 #include "base/metrics/histogram_macros.h" |
| 9 #include "components/spellcheck/common/spellcheck.mojom.h" |
8 #include "components/spellcheck/common/spellcheck_messages.h" | 10 #include "components/spellcheck/common/spellcheck_messages.h" |
9 #include "components/spellcheck/common/spellcheck_result.h" | 11 #include "components/spellcheck/common/spellcheck_result.h" |
10 #include "components/spellcheck/renderer/spellcheck.h" | 12 #include "components/spellcheck/renderer/spellcheck.h" |
11 #include "components/spellcheck/renderer/spellcheck_language.h" | 13 #include "components/spellcheck/renderer/spellcheck_language.h" |
12 #include "components/spellcheck/spellcheck_build_features.h" | 14 #include "components/spellcheck/spellcheck_build_features.h" |
| 15 #include "content/public/common/service_names.mojom.h" |
13 #include "content/public/renderer/render_frame.h" | 16 #include "content/public/renderer/render_frame.h" |
| 17 #include "content/public/renderer/render_thread.h" |
| 18 #include "services/service_manager/public/cpp/connector.h" |
14 #include "third_party/WebKit/public/platform/WebVector.h" | 19 #include "third_party/WebKit/public/platform/WebVector.h" |
15 #include "third_party/WebKit/public/web/WebDocument.h" | 20 #include "third_party/WebKit/public/web/WebDocument.h" |
16 #include "third_party/WebKit/public/web/WebElement.h" | 21 #include "third_party/WebKit/public/web/WebElement.h" |
17 #include "third_party/WebKit/public/web/WebLocalFrame.h" | 22 #include "third_party/WebKit/public/web/WebLocalFrame.h" |
18 #include "third_party/WebKit/public/web/WebTextCheckingCompletion.h" | 23 #include "third_party/WebKit/public/web/WebTextCheckingCompletion.h" |
19 #include "third_party/WebKit/public/web/WebTextCheckingResult.h" | 24 #include "third_party/WebKit/public/web/WebTextCheckingResult.h" |
20 #include "third_party/WebKit/public/web/WebTextDecorationType.h" | 25 #include "third_party/WebKit/public/web/WebTextDecorationType.h" |
21 | 26 |
22 using blink::WebElement; | 27 using blink::WebElement; |
23 using blink::WebLocalFrame; | 28 using blink::WebLocalFrame; |
(...skipping 16 matching lines...) Expand all Loading... |
40 content::RenderFrameObserverTracker<SpellCheckProvider>(render_frame), | 45 content::RenderFrameObserverTracker<SpellCheckProvider>(render_frame), |
41 spellcheck_(spellcheck) { | 46 spellcheck_(spellcheck) { |
42 DCHECK(spellcheck_); | 47 DCHECK(spellcheck_); |
43 if (render_frame) // NULL in unit tests. | 48 if (render_frame) // NULL in unit tests. |
44 render_frame->GetWebFrame()->SetTextCheckClient(this); | 49 render_frame->GetWebFrame()->SetTextCheckClient(this); |
45 } | 50 } |
46 | 51 |
47 SpellCheckProvider::~SpellCheckProvider() { | 52 SpellCheckProvider::~SpellCheckProvider() { |
48 } | 53 } |
49 | 54 |
| 55 spellcheck::mojom::SpellCheckHost& SpellCheckProvider::GetSpellCheckHost() { |
| 56 if (spellcheck_host_) |
| 57 return *spellcheck_host_; |
| 58 |
| 59 DCHECK(content::RenderThread::Get()); |
| 60 content::RenderThread::Get()->GetConnector()->BindInterface( |
| 61 content::mojom::kBrowserServiceName, &spellcheck_host_); |
| 62 return *spellcheck_host_; |
| 63 } |
| 64 |
50 void SpellCheckProvider::RequestTextChecking( | 65 void SpellCheckProvider::RequestTextChecking( |
51 const base::string16& text, | 66 const base::string16& text, |
52 WebTextCheckingCompletion* completion) { | 67 WebTextCheckingCompletion* completion) { |
53 // Ignore invalid requests. | 68 // Ignore invalid requests. |
54 if (text.empty() || !HasWordCharacters(text, 0)) { | 69 if (text.empty() || !HasWordCharacters(text, 0)) { |
55 completion->DidCancelCheckingText(); | 70 completion->DidCancelCheckingText(); |
56 return; | 71 return; |
57 } | 72 } |
58 | 73 |
59 // Try to satisfy check from cache. | 74 // Try to satisfy check from cache. |
60 if (SatisfyRequestFromCache(text, completion)) | 75 if (SatisfyRequestFromCache(text, completion)) |
61 return; | 76 return; |
62 | 77 |
63 // Send this text to a browser. A browser checks the user profile and send | 78 // Send this text to a browser. A browser checks the user profile and send |
64 // this text to the Spelling service only if a user enables this feature. | 79 // this text to the Spelling service only if a user enables this feature. |
65 last_request_.clear(); | 80 last_request_.clear(); |
66 last_results_.Assign(blink::WebVector<blink::WebTextCheckingResult>()); | 81 last_results_.Assign(blink::WebVector<blink::WebTextCheckingResult>()); |
| 82 last_identifier_ = text_check_completions_.Add(completion); |
67 | 83 |
68 #if BUILDFLAG(USE_BROWSER_SPELLCHECKER) | 84 #if BUILDFLAG(USE_BROWSER_SPELLCHECKER) |
| 85 // TODO(crbug.com/714480): convert the RequestTextCheck IPC to mojo. |
69 // Text check (unified request for grammar and spell check) is only | 86 // Text check (unified request for grammar and spell check) is only |
70 // available for browser process, so we ask the system spellchecker | 87 // available for browser process, so we ask the system spellchecker |
71 // over IPC or return an empty result if the checker is not | 88 // over IPC or return an empty result if the checker is not available. |
72 // available. | 89 Send(new SpellCheckHostMsg_RequestTextCheck(routing_id(), last_identifier_, |
73 Send(new SpellCheckHostMsg_RequestTextCheck( | 90 text)); |
74 routing_id(), text_check_completions_.Add(completion), text)); | |
75 #else | 91 #else |
76 Send(new SpellCheckHostMsg_CallSpellingService( | 92 GetSpellCheckHost().CallSpellingService( |
77 routing_id(), text_check_completions_.Add(completion), | 93 text, base::Bind(&SpellCheckProvider::OnRespondSpellingService, |
78 base::string16(text))); | 94 base::Unretained(this), last_identifier_, text)); |
79 #endif // !USE_BROWSER_SPELLCHECKER | 95 #endif // !USE_BROWSER_SPELLCHECKER |
80 } | 96 } |
81 | 97 |
82 bool SpellCheckProvider::OnMessageReceived(const IPC::Message& message) { | 98 bool SpellCheckProvider::OnMessageReceived(const IPC::Message& message) { |
| 99 #if BUILDFLAG(USE_BROWSER_SPELLCHECKER) |
83 bool handled = true; | 100 bool handled = true; |
84 IPC_BEGIN_MESSAGE_MAP(SpellCheckProvider, message) | 101 IPC_BEGIN_MESSAGE_MAP(SpellCheckProvider, message) |
85 #if !BUILDFLAG(USE_BROWSER_SPELLCHECKER) | 102 // TODO(crbug.com/714480): convert the RequestTextCheck IPC to mojo. |
86 IPC_MESSAGE_HANDLER(SpellCheckMsg_RespondSpellingService, | |
87 OnRespondSpellingService) | |
88 #endif | |
89 #if BUILDFLAG(USE_BROWSER_SPELLCHECKER) | |
90 IPC_MESSAGE_HANDLER(SpellCheckMsg_RespondTextCheck, OnRespondTextCheck) | 103 IPC_MESSAGE_HANDLER(SpellCheckMsg_RespondTextCheck, OnRespondTextCheck) |
91 #endif | |
92 IPC_MESSAGE_UNHANDLED(handled = false) | 104 IPC_MESSAGE_UNHANDLED(handled = false) |
93 IPC_END_MESSAGE_MAP() | 105 IPC_END_MESSAGE_MAP() |
94 return handled; | 106 return handled; |
| 107 #else |
| 108 return false; |
| 109 #endif |
95 } | 110 } |
96 | 111 |
97 void SpellCheckProvider::FocusedNodeChanged(const blink::WebNode& unused) { | 112 void SpellCheckProvider::FocusedNodeChanged(const blink::WebNode& unused) { |
98 #if BUILDFLAG(USE_BROWSER_SPELLCHECKER) | 113 #if BUILDFLAG(USE_BROWSER_SPELLCHECKER) |
99 WebLocalFrame* frame = render_frame()->GetWebFrame(); | 114 WebLocalFrame* frame = render_frame()->GetWebFrame(); |
100 WebElement element = frame->GetDocument().IsNull() | 115 WebElement element = frame->GetDocument().IsNull() |
101 ? WebElement() | 116 ? WebElement() |
102 : frame->GetDocument().FocusedElement(); | 117 : frame->GetDocument().FocusedElement(); |
103 bool enabled = !element.IsNull() && element.IsEditable(); | 118 bool enabled = !element.IsNull() && element.IsEditable(); |
104 bool checked = enabled && frame->IsSpellCheckingEnabled(); | 119 bool checked = enabled && frame->IsSpellCheckingEnabled(); |
(...skipping 17 matching lines...) Expand all Loading... |
122 WebVector<WebString> web_suggestions(suggestions.size()); | 137 WebVector<WebString> web_suggestions(suggestions.size()); |
123 std::transform( | 138 std::transform( |
124 suggestions.begin(), suggestions.end(), web_suggestions.begin(), | 139 suggestions.begin(), suggestions.end(), web_suggestions.begin(), |
125 [](const base::string16& s) { return WebString::FromUTF16(s); }); | 140 [](const base::string16& s) { return WebString::FromUTF16(s); }); |
126 *optional_suggestions = web_suggestions; | 141 *optional_suggestions = web_suggestions; |
127 UMA_HISTOGRAM_COUNTS("SpellCheck.api.check.suggestions", word.size()); | 142 UMA_HISTOGRAM_COUNTS("SpellCheck.api.check.suggestions", word.size()); |
128 } else { | 143 } else { |
129 UMA_HISTOGRAM_COUNTS("SpellCheck.api.check", word.size()); | 144 UMA_HISTOGRAM_COUNTS("SpellCheck.api.check", word.size()); |
130 // If optional_suggestions is not requested, the API is called | 145 // If optional_suggestions is not requested, the API is called |
131 // for marking. So we use this for counting markable words. | 146 // for marking. So we use this for counting markable words. |
132 Send(new SpellCheckHostMsg_NotifyChecked(routing_id(), word, 0 < length)); | 147 if (content::RenderThread::Get()) // Can be NULL in tests. |
| 148 GetSpellCheckHost().NotifyChecked(word, 0 < length); |
133 } | 149 } |
134 } | 150 } |
135 | 151 |
136 void SpellCheckProvider::RequestCheckingOfText( | 152 void SpellCheckProvider::RequestCheckingOfText( |
137 const WebString& text, | 153 const WebString& text, |
138 WebTextCheckingCompletion* completion) { | 154 WebTextCheckingCompletion* completion) { |
139 RequestTextChecking(text.Utf16(), completion); | 155 RequestTextChecking(text.Utf16(), completion); |
140 UMA_HISTOGRAM_COUNTS("SpellCheck.api.async", text.length()); | 156 UMA_HISTOGRAM_COUNTS("SpellCheck.api.async", text.length()); |
141 } | 157 } |
142 | 158 |
143 void SpellCheckProvider::CancelAllPendingRequests() { | 159 void SpellCheckProvider::CancelAllPendingRequests() { |
144 for (WebTextCheckCompletions::iterator iter(&text_check_completions_); | 160 for (WebTextCheckCompletions::iterator iter(&text_check_completions_); |
145 !iter.IsAtEnd(); iter.Advance()) { | 161 !iter.IsAtEnd(); iter.Advance()) { |
146 iter.GetCurrentValue()->DidCancelCheckingText(); | 162 iter.GetCurrentValue()->DidCancelCheckingText(); |
147 } | 163 } |
148 text_check_completions_.Clear(); | 164 text_check_completions_.Clear(); |
149 } | 165 } |
150 | 166 |
151 #if !BUILDFLAG(USE_BROWSER_SPELLCHECKER) | 167 #if !BUILDFLAG(USE_BROWSER_SPELLCHECKER) |
152 void SpellCheckProvider::OnRespondSpellingService( | 168 void SpellCheckProvider::OnRespondSpellingService( |
153 int identifier, | 169 int identifier, |
| 170 const base::string16& line, |
154 bool succeeded, | 171 bool succeeded, |
155 const base::string16& line, | |
156 const std::vector<SpellCheckResult>& results) { | 172 const std::vector<SpellCheckResult>& results) { |
157 WebTextCheckingCompletion* completion = | 173 WebTextCheckingCompletion* completion = |
158 text_check_completions_.Lookup(identifier); | 174 text_check_completions_.Lookup(identifier); |
159 if (!completion) | 175 if (!completion) |
160 return; | 176 return; |
161 text_check_completions_.Remove(identifier); | 177 text_check_completions_.Remove(identifier); |
162 | 178 |
163 // If |succeeded| is false, we use local spellcheck as a fallback. | 179 // If |succeeded| is false, we use local spellcheck as a fallback. |
164 if (!succeeded) { | 180 if (!succeeded) { |
165 spellcheck_->RequestTextChecking(line, completion); | 181 spellcheck_->RequestTextChecking(line, completion); |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 completion->DidFinishCheckingText(results); | 284 completion->DidFinishCheckingText(results); |
269 return true; | 285 return true; |
270 } | 286 } |
271 | 287 |
272 return false; | 288 return false; |
273 } | 289 } |
274 | 290 |
275 void SpellCheckProvider::OnDestruct() { | 291 void SpellCheckProvider::OnDestruct() { |
276 delete this; | 292 delete this; |
277 } | 293 } |
OLD | NEW |