| 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 |