OLD | NEW |
| (Empty) |
1 // Copyright 2015 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 #include "blimp/engine/feature/engine_render_widget_feature.h" | |
6 | |
7 #include "base/numerics/safe_conversions.h" | |
8 #include "base/strings/utf_string_conversions.h" | |
9 #include "base/threading/thread_task_runner_handle.h" | |
10 #include "blimp/common/create_blimp_message.h" | |
11 #include "blimp/common/proto/blimp_message.pb.h" | |
12 #include "blimp/common/proto/compositor.pb.h" | |
13 #include "blimp/common/proto/input.pb.h" | |
14 #include "blimp/common/proto/render_widget.pb.h" | |
15 #include "blimp/net/input_message_converter.h" | |
16 #include "content/public/browser/render_widget_host.h" | |
17 #include "content/public/browser/render_widget_host_view.h" | |
18 #include "content/public/common/form_field_data.h" | |
19 #include "net/base/net_errors.h" | |
20 #include "third_party/WebKit/public/platform/WebInputEvent.h" | |
21 #include "ui/events/event.h" | |
22 #include "ui/events/keycodes/dom/dom_code.h" | |
23 | |
24 namespace blimp { | |
25 namespace engine { | |
26 | |
27 EngineRenderWidgetFeature::EngineRenderWidgetFeature(SettingsManager* settings) | |
28 : settings_manager_(settings), weak_factory_(this) { | |
29 DCHECK(settings_manager_); | |
30 settings_manager_->AddObserver(this); | |
31 } | |
32 | |
33 EngineRenderWidgetFeature::~EngineRenderWidgetFeature() { | |
34 DCHECK(settings_manager_); | |
35 settings_manager_->RemoveObserver(this); | |
36 } | |
37 | |
38 void EngineRenderWidgetFeature::set_render_widget_message_sender( | |
39 std::unique_ptr<BlimpMessageProcessor> message_processor) { | |
40 DCHECK(message_processor); | |
41 render_widget_message_sender_ = std::move(message_processor); | |
42 } | |
43 | |
44 void EngineRenderWidgetFeature::set_input_message_sender( | |
45 std::unique_ptr<BlimpMessageProcessor> message_processor) { | |
46 DCHECK(message_processor); | |
47 input_message_sender_ = std::move(message_processor); | |
48 } | |
49 | |
50 void EngineRenderWidgetFeature::set_ime_message_sender( | |
51 std::unique_ptr<BlimpMessageProcessor> message_processor) { | |
52 DCHECK(message_processor); | |
53 ime_message_sender_ = std::move(message_processor); | |
54 } | |
55 | |
56 void EngineRenderWidgetFeature::set_compositor_message_sender( | |
57 std::unique_ptr<BlimpMessageProcessor> message_processor) { | |
58 DCHECK(message_processor); | |
59 compositor_message_sender_ = std::move(message_processor); | |
60 } | |
61 | |
62 void EngineRenderWidgetFeature::OnRenderWidgetCreated( | |
63 const int tab_id, | |
64 content::RenderWidgetHost* render_widget_host) { | |
65 DCHECK(render_widget_host); | |
66 | |
67 int render_widget_id = AddRenderWidget(tab_id, render_widget_host); | |
68 DCHECK_GT(render_widget_id, 0); | |
69 | |
70 RenderWidgetMessage* render_widget_message; | |
71 std::unique_ptr<BlimpMessage> blimp_message = | |
72 CreateBlimpMessage(&render_widget_message, tab_id); | |
73 render_widget_message->set_type(RenderWidgetMessage::CREATED); | |
74 render_widget_message->set_render_widget_id(render_widget_id); | |
75 | |
76 render_widget_message_sender_->ProcessMessage(std::move(blimp_message), | |
77 net::CompletionCallback()); | |
78 } | |
79 | |
80 void EngineRenderWidgetFeature::OnRenderWidgetInitialized( | |
81 const int tab_id, | |
82 content::RenderWidgetHost* render_widget_host) { | |
83 DCHECK(render_widget_host); | |
84 | |
85 int render_widget_id = GetRenderWidgetId(tab_id, render_widget_host); | |
86 DCHECK_GT(render_widget_id, 0); | |
87 | |
88 RenderWidgetMessage* render_widget_message; | |
89 std::unique_ptr<BlimpMessage> blimp_message = | |
90 CreateBlimpMessage(&render_widget_message, tab_id); | |
91 render_widget_message->set_type(RenderWidgetMessage::INITIALIZE); | |
92 render_widget_message->set_render_widget_id(render_widget_id); | |
93 | |
94 render_widget_message_sender_->ProcessMessage(std::move(blimp_message), | |
95 net::CompletionCallback()); | |
96 } | |
97 | |
98 void EngineRenderWidgetFeature::OnRenderWidgetDeleted( | |
99 const int tab_id, | |
100 content::RenderWidgetHost* render_widget_host) { | |
101 DCHECK(render_widget_host); | |
102 | |
103 int render_widget_id = DeleteRenderWidget(tab_id, render_widget_host); | |
104 DCHECK_GT(render_widget_id, 0); | |
105 | |
106 RenderWidgetMessage* render_widget_message; | |
107 std::unique_ptr<BlimpMessage> blimp_message = | |
108 CreateBlimpMessage(&render_widget_message, tab_id); | |
109 render_widget_message->set_type(RenderWidgetMessage::DELETED); | |
110 render_widget_message->set_render_widget_id(render_widget_id); | |
111 | |
112 render_widget_message_sender_->ProcessMessage(std::move(blimp_message), | |
113 net::CompletionCallback()); | |
114 } | |
115 | |
116 void EngineRenderWidgetFeature::SendCompositorMessage( | |
117 const int tab_id, | |
118 content::RenderWidgetHost* render_widget_host, | |
119 const std::vector<uint8_t>& message) { | |
120 CompositorMessage* compositor_message; | |
121 std::unique_ptr<BlimpMessage> blimp_message = | |
122 CreateBlimpMessage(&compositor_message, tab_id); | |
123 | |
124 int render_widget_id = GetRenderWidgetId(tab_id, render_widget_host); | |
125 DCHECK_GT(render_widget_id, 0); | |
126 | |
127 compositor_message->set_render_widget_id(render_widget_id); | |
128 // TODO(dtrainor): Move the transport medium to std::string* and use | |
129 // set_allocated_payload. | |
130 compositor_message->set_payload(message.data(), | |
131 base::checked_cast<int>(message.size())); | |
132 | |
133 compositor_message_sender_->ProcessMessage(std::move(blimp_message), | |
134 net::CompletionCallback()); | |
135 } | |
136 | |
137 void EngineRenderWidgetFeature::SendShowImeRequest( | |
138 const int tab_id, | |
139 content::RenderWidgetHost* render_widget_host, | |
140 const content::FormFieldData& field) { | |
141 ImeMessage* ime_message; | |
142 std::unique_ptr<BlimpMessage> blimp_message = | |
143 CreateBlimpMessage(&ime_message, tab_id); | |
144 | |
145 int render_widget_id = GetRenderWidgetId(tab_id, render_widget_host); | |
146 DCHECK_GT(render_widget_id, 0); | |
147 ime_message->set_render_widget_id(render_widget_id); | |
148 ime_message->set_type(ImeMessage::SHOW_IME); | |
149 ime_message->set_text_input_type( | |
150 InputMessageConverter::TextInputTypeToProto(field.text_input_type)); | |
151 ime_message->set_ime_text(field.text); | |
152 // TODO(shaktisahu): Add remaining fields to proto. | |
153 | |
154 ime_message_sender_->ProcessMessage(std::move(blimp_message), | |
155 net::CompletionCallback()); | |
156 } | |
157 | |
158 void EngineRenderWidgetFeature::SendHideImeRequest( | |
159 const int tab_id, | |
160 content::RenderWidgetHost* render_widget_host) { | |
161 ImeMessage* ime_message; | |
162 std::unique_ptr<BlimpMessage> blimp_message = | |
163 CreateBlimpMessage(&ime_message, tab_id); | |
164 | |
165 int render_widget_id = GetRenderWidgetId(tab_id, render_widget_host); | |
166 DCHECK_GT(render_widget_id, 0); | |
167 ime_message->set_render_widget_id(render_widget_id); | |
168 ime_message->set_type(ImeMessage::HIDE_IME); | |
169 | |
170 ime_message_sender_->ProcessMessage(std::move(blimp_message), | |
171 net::CompletionCallback()); | |
172 } | |
173 | |
174 void EngineRenderWidgetFeature::SetDelegate( | |
175 const int tab_id, | |
176 RenderWidgetMessageDelegate* delegate) { | |
177 DCHECK(!FindDelegate(tab_id)); | |
178 delegates_[tab_id] = delegate; | |
179 } | |
180 | |
181 void EngineRenderWidgetFeature::RemoveDelegate(const int tab_id) { | |
182 DelegateMap::iterator it = delegates_.find(tab_id); | |
183 if (it != delegates_.end()) | |
184 delegates_.erase(it); | |
185 } | |
186 | |
187 void EngineRenderWidgetFeature::ProcessMessage( | |
188 std::unique_ptr<BlimpMessage> message, | |
189 const net::CompletionCallback& callback) { | |
190 DCHECK(!callback.is_null()); | |
191 DCHECK(message->feature_case() == BlimpMessage::kRenderWidget || | |
192 message->feature_case() == BlimpMessage::kIme || | |
193 message->feature_case() == BlimpMessage::kInput || | |
194 message->feature_case() == BlimpMessage::kCompositor); | |
195 | |
196 int target_tab_id = message->target_tab_id(); | |
197 | |
198 RenderWidgetMessageDelegate* delegate = FindDelegate(target_tab_id); | |
199 DCHECK(delegate); | |
200 | |
201 content::RenderWidgetHost* render_widget_host = nullptr; | |
202 | |
203 switch (message->feature_case()) { | |
204 case BlimpMessage::kInput: | |
205 render_widget_host = GetRenderWidgetHost(target_tab_id, | |
206 message->input().render_widget_id()); | |
207 if (render_widget_host) { | |
208 std::unique_ptr<blink::WebGestureEvent> event = | |
209 input_message_converter_.ProcessMessage(message->input()); | |
210 if (event) | |
211 delegate->OnWebGestureEvent(render_widget_host, std::move(event)); | |
212 } | |
213 break; | |
214 case BlimpMessage::kCompositor: | |
215 render_widget_host = GetRenderWidgetHost(target_tab_id, | |
216 message->compositor().render_widget_id()); | |
217 if (render_widget_host) { | |
218 std::vector<uint8_t> payload(message->compositor().payload().size()); | |
219 memcpy(payload.data(), | |
220 message->compositor().payload().data(), | |
221 payload.size()); | |
222 delegate->OnCompositorMessageReceived(render_widget_host, payload); | |
223 } | |
224 break; | |
225 case BlimpMessage::kIme: | |
226 DCHECK(message->ime().type() == ImeMessage::SET_TEXT); | |
227 render_widget_host = | |
228 GetRenderWidgetHost(target_tab_id, message->ime().render_widget_id()); | |
229 if (render_widget_host && render_widget_host->GetView()) { | |
230 SetTextFromIME(render_widget_host, message->ime().ime_text(), | |
231 message->ime().auto_submit()); | |
232 | |
233 // TODO(shaktisahu): Remove this fake HIDE_IME request once the blimp | |
234 // IME design is completed (crbug/661328). | |
235 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
236 FROM_HERE, | |
237 base::Bind(&EngineRenderWidgetFeature::SendHideImeRequest, | |
238 weak_factory_.GetWeakPtr(), target_tab_id, | |
239 render_widget_host), | |
240 base::TimeDelta::FromMilliseconds(1500)); | |
241 } | |
242 break; | |
243 default: | |
244 NOTREACHED(); | |
245 } | |
246 | |
247 callback.Run(net::OK); | |
248 } | |
249 | |
250 void EngineRenderWidgetFeature::OnWebPreferencesChanged() { | |
251 for (TabMap::iterator tab_it = tabs_.begin(); tab_it != tabs_.end(); | |
252 tab_it++) { | |
253 RenderWidgetMaps render_widget_maps = tab_it->second; | |
254 RenderWidgetToIdMap render_widget_to_id = render_widget_maps.first; | |
255 for (RenderWidgetToIdMap::iterator it = render_widget_to_id.begin(); | |
256 it != render_widget_to_id.end(); it++) { | |
257 content::RenderWidgetHost* render_widget_host = it->first; | |
258 content::RenderViewHost* render_view_host = | |
259 content::RenderViewHost::From(render_widget_host); | |
260 if (render_view_host) | |
261 render_view_host->OnWebkitPreferencesChanged(); | |
262 } | |
263 } | |
264 } | |
265 | |
266 void EngineRenderWidgetFeature::SetTextFromIME( | |
267 content::RenderWidgetHost* render_widget_host, | |
268 std::string text, | |
269 bool auto_submit) { | |
270 ui::TextInputClient* client = | |
271 render_widget_host->GetView()->GetTextInputClient(); | |
272 DCHECK(client); | |
273 | |
274 if (!client || client->GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE) | |
275 return; | |
276 | |
277 // Clear out any existing text first and then insert new text entered | |
278 // through IME. | |
279 gfx::Range text_range; | |
280 client->GetTextRange(&text_range); | |
281 client->ExtendSelectionAndDelete(text_range.length(), text_range.length()); | |
282 | |
283 client->InsertText(base::UTF8ToUTF16(text)); | |
284 | |
285 if (auto_submit) { | |
286 // Send a synthetic key event to the renderer notifying that user has hit | |
287 // Return key. This should submit the current form. | |
288 ui::KeyEvent press(ui::ET_KEY_PRESSED, ui::VKEY_RETURN, ui::DomCode::ENTER, | |
289 0); | |
290 ui::KeyEvent char_event('\r', ui::VKEY_RETURN, 0); | |
291 ui::KeyEvent release(ui::ET_KEY_RELEASED, ui::VKEY_RETURN, | |
292 ui::DomCode::ENTER, 0); | |
293 render_widget_host->ForwardKeyboardEvent( | |
294 content::NativeWebKeyboardEvent(press)); | |
295 render_widget_host->ForwardKeyboardEvent( | |
296 content::NativeWebKeyboardEvent(char_event)); | |
297 render_widget_host->ForwardKeyboardEvent( | |
298 content::NativeWebKeyboardEvent(release)); | |
299 } | |
300 } | |
301 | |
302 EngineRenderWidgetFeature::RenderWidgetMessageDelegate* | |
303 EngineRenderWidgetFeature::FindDelegate(const int tab_id) { | |
304 DelegateMap::const_iterator it = delegates_.find(tab_id); | |
305 if (it != delegates_.end()) | |
306 return it->second; | |
307 return nullptr; | |
308 } | |
309 | |
310 int EngineRenderWidgetFeature::AddRenderWidget( | |
311 const int tab_id, | |
312 content::RenderWidgetHost* render_widget_host) { | |
313 TabMap::iterator tab_it = tabs_.find(tab_id); | |
314 if (tab_it == tabs_.end()) { | |
315 tabs_[tab_id] = std::make_pair(RenderWidgetToIdMap(), | |
316 IdToRenderWidgetMap()); | |
317 tab_it = tabs_.find(tab_id); | |
318 } | |
319 | |
320 int render_widget_id = next_widget_id_.GetNext() + 1; | |
321 | |
322 RenderWidgetMaps* render_widget_maps = &tab_it->second; | |
323 | |
324 RenderWidgetToIdMap* render_widget_to_id = &render_widget_maps->first; | |
325 IdToRenderWidgetMap* id_to_render_widget = &render_widget_maps->second; | |
326 | |
327 DCHECK(render_widget_to_id->find(render_widget_host) == | |
328 render_widget_to_id->end()); | |
329 DCHECK(id_to_render_widget->find(render_widget_id) == | |
330 id_to_render_widget->end()); | |
331 | |
332 (*render_widget_to_id)[render_widget_host] = render_widget_id; | |
333 (*id_to_render_widget)[render_widget_id] = render_widget_host; | |
334 | |
335 return render_widget_id; | |
336 } | |
337 | |
338 int EngineRenderWidgetFeature::DeleteRenderWidget( | |
339 const int tab_id, | |
340 content::RenderWidgetHost* render_widget_host) { | |
341 TabMap::iterator tab_it = tabs_.find(tab_id); | |
342 DCHECK(tab_it != tabs_.end()); | |
343 | |
344 RenderWidgetMaps* render_widget_maps = &tab_it->second; | |
345 | |
346 RenderWidgetToIdMap* render_widget_to_id = &render_widget_maps->first; | |
347 RenderWidgetToIdMap::iterator widget_to_id_it = | |
348 render_widget_to_id->find(render_widget_host); | |
349 DCHECK(widget_to_id_it != render_widget_to_id->end()); | |
350 | |
351 int render_widget_id = widget_to_id_it->second; | |
352 render_widget_to_id->erase(widget_to_id_it); | |
353 | |
354 IdToRenderWidgetMap* id_to_render_widget = &render_widget_maps->second; | |
355 IdToRenderWidgetMap::iterator id_to_widget_it = | |
356 id_to_render_widget->find(render_widget_id); | |
357 DCHECK(id_to_widget_it->second == render_widget_host); | |
358 id_to_render_widget->erase(id_to_widget_it); | |
359 | |
360 return render_widget_id; | |
361 } | |
362 | |
363 int EngineRenderWidgetFeature::GetRenderWidgetId( | |
364 const int tab_id, | |
365 content::RenderWidgetHost* render_widget_host) { | |
366 TabMap::const_iterator tab_it = tabs_.find(tab_id); | |
367 if (tab_it == tabs_.end()) | |
368 return 0; | |
369 | |
370 const RenderWidgetMaps* render_widget_maps = &tab_it->second; | |
371 const RenderWidgetToIdMap* render_widget_to_id = &render_widget_maps->first; | |
372 | |
373 RenderWidgetToIdMap::const_iterator widget_it = | |
374 render_widget_to_id->find(render_widget_host); | |
375 if (widget_it == render_widget_to_id->end()) | |
376 return 0; | |
377 | |
378 return widget_it->second; | |
379 } | |
380 | |
381 content::RenderWidgetHost* EngineRenderWidgetFeature::GetRenderWidgetHost( | |
382 const int tab_id, | |
383 const int render_widget_id) { | |
384 TabMap::const_iterator tab_it = tabs_.find(tab_id); | |
385 if (tab_it == tabs_.end()) | |
386 return nullptr; | |
387 | |
388 const RenderWidgetMaps* render_widget_maps = &tab_it->second; | |
389 const IdToRenderWidgetMap* id_to_render_widget = &render_widget_maps->second; | |
390 | |
391 IdToRenderWidgetMap::const_iterator widget_id_it = | |
392 id_to_render_widget->find(render_widget_id); | |
393 if (widget_id_it == id_to_render_widget->end()) | |
394 return nullptr; | |
395 | |
396 return widget_id_it->second; | |
397 } | |
398 | |
399 } // namespace engine | |
400 } // namespace blimp | |
OLD | NEW |