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 "remoting/client/plugin/chromoting_instance.h" | 5 #include "remoting/client/plugin/chromoting_instance.h" |
6 | 6 |
7 #include <algorithm> | |
7 #include <string> | 8 #include <string> |
8 #include <vector> | 9 #include <vector> |
9 | 10 |
10 #include "base/bind.h" | 11 #include "base/bind.h" |
11 #include "base/callback.h" | 12 #include "base/callback.h" |
12 #include "base/json/json_reader.h" | 13 #include "base/json/json_reader.h" |
13 #include "base/json/json_writer.h" | 14 #include "base/json/json_writer.h" |
14 #include "base/lazy_instance.h" | 15 #include "base/lazy_instance.h" |
15 #include "base/logging.h" | 16 #include "base/logging.h" |
16 #include "base/strings/string_split.h" | 17 #include "base/strings/string_split.h" |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
48 #undef PostMessage | 49 #undef PostMessage |
49 #endif | 50 #endif |
50 | 51 |
51 namespace remoting { | 52 namespace remoting { |
52 | 53 |
53 namespace { | 54 namespace { |
54 | 55 |
55 // 32-bit BGRA is 4 bytes per pixel. | 56 // 32-bit BGRA is 4 bytes per pixel. |
56 const int kBytesPerPixel = 4; | 57 const int kBytesPerPixel = 4; |
57 | 58 |
59 #if defined(ARCH_CPU_LITTLE_ENDIAN) | |
60 const uint32_t kPixelAlphaMask = 0xff000000; | |
61 #else // !defined(ARCH_CPU_LITTLE_ENDIAN) | |
62 const uint32_t kPixelAlphaMask = 0x000000ff; | |
63 #endif // !defined(ARCH_CPU_LITTLE_ENDIAN) | |
64 | |
58 // Default DPI to assume for old clients that use notifyClientResolution. | 65 // Default DPI to assume for old clients that use notifyClientResolution. |
59 const int kDefaultDPI = 96; | 66 const int kDefaultDPI = 96; |
60 | 67 |
61 // Interval at which to sample performance statistics. | 68 // Interval at which to sample performance statistics. |
62 const int kPerfStatsIntervalMs = 1000; | 69 const int kPerfStatsIntervalMs = 1000; |
63 | 70 |
64 // URL scheme used by Chrome apps and extensions. | 71 // URL scheme used by Chrome apps and extensions. |
65 const char kChromeExtensionUrlScheme[] = "chrome-extension"; | 72 const char kChromeExtensionUrlScheme[] = "chrome-extension"; |
66 | 73 |
67 // Maximum width and height of a mouse cursor supported by PPAPI. | 74 // Maximum width and height of a mouse cursor supported by PPAPI. |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
118 case protocol::CHANNEL_CONNECTION_ERROR: | 125 case protocol::CHANNEL_CONNECTION_ERROR: |
119 case protocol::SIGNALING_ERROR: | 126 case protocol::SIGNALING_ERROR: |
120 case protocol::SIGNALING_TIMEOUT: | 127 case protocol::SIGNALING_TIMEOUT: |
121 case protocol::UNKNOWN_ERROR: | 128 case protocol::UNKNOWN_ERROR: |
122 return "NETWORK_FAILURE"; | 129 return "NETWORK_FAILURE"; |
123 } | 130 } |
124 DLOG(FATAL) << "Unknown error code" << error; | 131 DLOG(FATAL) << "Unknown error code" << error; |
125 return std::string(); | 132 return std::string(); |
126 } | 133 } |
127 | 134 |
135 // Returns true |pixel| is not completely transparent. | |
Wez
2013/09/05 20:24:45
nit: "... true if ..."
alexeypa (please no reviews)
2013/09/06 20:00:17
Done.
| |
136 bool IsVisiblePixel(uint32_t pixel) { | |
137 return (pixel & kPixelAlphaMask) != 0; | |
138 } | |
139 | |
128 // This flag blocks LOGs to the UI if we're already in the middle of logging | 140 // This flag blocks LOGs to the UI if we're already in the middle of logging |
129 // to the UI. This prevents a potential infinite loop if we encounter an error | 141 // to the UI. This prevents a potential infinite loop if we encounter an error |
130 // while sending the log message to the UI. | 142 // while sending the log message to the UI. |
131 bool g_logging_to_plugin = false; | 143 bool g_logging_to_plugin = false; |
132 bool g_has_logging_instance = false; | 144 bool g_has_logging_instance = false; |
133 base::LazyInstance<scoped_refptr<base::SingleThreadTaskRunner> >::Leaky | 145 base::LazyInstance<scoped_refptr<base::SingleThreadTaskRunner> >::Leaky |
134 g_logging_task_runner = LAZY_INSTANCE_INITIALIZER; | 146 g_logging_task_runner = LAZY_INSTANCE_INITIALIZER; |
135 base::LazyInstance<base::WeakPtr<ChromotingInstance> >::Leaky | 147 base::LazyInstance<base::WeakPtr<ChromotingInstance> >::Leaky |
136 g_logging_instance = LAZY_INSTANCE_INITIALIZER; | 148 g_logging_instance = LAZY_INSTANCE_INITIALIZER; |
137 base::LazyInstance<base::Lock>::Leaky | 149 base::LazyInstance<base::Lock>::Leaky |
138 g_logging_lock = LAZY_INSTANCE_INITIALIZER; | 150 g_logging_lock = LAZY_INSTANCE_INITIALIZER; |
139 logging::LogMessageHandlerFunction g_logging_old_handler = NULL; | 151 logging::LogMessageHandlerFunction g_logging_old_handler = NULL; |
140 | 152 |
141 } // namespace | 153 } // namespace |
142 | 154 |
143 // String sent in the "hello" message to the webapp to describe features. | 155 // String sent in the "hello" message to the webapp to describe features. |
144 const char ChromotingInstance::kApiFeatures[] = | 156 const char ChromotingInstance::kApiFeatures[] = |
145 "highQualityScaling injectKeyEvent sendClipboardItem remapKey trapKey " | 157 "highQualityScaling injectKeyEvent sendClipboardItem remapKey trapKey " |
146 "notifyClientResolution pauseVideo pauseAudio asyncPin thirdPartyAuth " | 158 "notifyClientResolution pauseVideo pauseAudio asyncPin thirdPartyAuth " |
147 "pinlessAuth extensionMessage"; | 159 "pinlessAuth extensionMessage allowMouseLock"; |
148 | 160 |
149 const char ChromotingInstance::kRequestedCapabilities[] = ""; | 161 const char ChromotingInstance::kRequestedCapabilities[] = ""; |
150 const char ChromotingInstance::kSupportedCapabilities[] = "desktopShape"; | 162 const char ChromotingInstance::kSupportedCapabilities[] = "desktopShape"; |
151 | 163 |
152 bool ChromotingInstance::ParseAuthMethods(const std::string& auth_methods_str, | 164 bool ChromotingInstance::ParseAuthMethods(const std::string& auth_methods_str, |
153 ClientConfig* config) { | 165 ClientConfig* config) { |
154 std::vector<std::string> auth_methods; | 166 std::vector<std::string> auth_methods; |
155 base::SplitString(auth_methods_str, ',', &auth_methods); | 167 base::SplitString(auth_methods_str, ',', &auth_methods); |
156 for (std::vector<std::string>::iterator it = auth_methods.begin(); | 168 for (std::vector<std::string>::iterator it = auth_methods.begin(); |
157 it != auth_methods.end(); ++it) { | 169 it != auth_methods.end(); ++it) { |
158 protocol::AuthenticationMethod authentication_method = | 170 protocol::AuthenticationMethod authentication_method = |
159 protocol::AuthenticationMethod::FromString(*it); | 171 protocol::AuthenticationMethod::FromString(*it); |
160 if (authentication_method.is_valid()) | 172 if (authentication_method.is_valid()) |
161 config->authentication_methods.push_back(authentication_method); | 173 config->authentication_methods.push_back(authentication_method); |
162 } | 174 } |
163 if (config->authentication_methods.empty()) { | 175 if (config->authentication_methods.empty()) { |
164 LOG(ERROR) << "No valid authentication methods specified."; | 176 LOG(ERROR) << "No valid authentication methods specified."; |
165 return false; | 177 return false; |
166 } | 178 } |
167 | 179 |
168 return true; | 180 return true; |
169 } | 181 } |
170 | 182 |
171 ChromotingInstance::ChromotingInstance(PP_Instance pp_instance) | 183 ChromotingInstance::ChromotingInstance(PP_Instance pp_instance) |
172 : pp::Instance(pp_instance), | 184 : pp::Instance(pp_instance), |
185 pp::MouseLock(this), | |
173 initialized_(false), | 186 initialized_(false), |
174 plugin_task_runner_(new PluginThreadTaskRunner(&plugin_thread_delegate_)), | 187 plugin_task_runner_(new PluginThreadTaskRunner(&plugin_thread_delegate_)), |
175 context_(plugin_task_runner_.get()), | 188 context_(plugin_task_runner_.get()), |
189 focused_(false), | |
190 mouse_lock_state_(MouseLockDisabled), | |
176 input_tracker_(&mouse_input_filter_), | 191 input_tracker_(&mouse_input_filter_), |
177 key_mapper_(&input_tracker_), | 192 key_mapper_(&input_tracker_), |
178 normalizing_input_filter_(CreateNormalizingInputFilter(&key_mapper_)), | 193 normalizing_input_filter_(CreateNormalizingInputFilter(&key_mapper_)), |
179 input_handler_(normalizing_input_filter_.get()), | 194 input_handler_(normalizing_input_filter_.get()), |
180 use_async_pin_dialog_(false), | 195 use_async_pin_dialog_(false), |
196 callback_factory_(this), | |
181 weak_factory_(this) { | 197 weak_factory_(this) { |
182 RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_WHEEL); | 198 RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_WHEEL); |
183 RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD); | 199 RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD); |
184 | 200 |
185 // Resister this instance to handle debug log messsages. | 201 // Resister this instance to handle debug log messsages. |
186 RegisterLoggingInstance(); | 202 RegisterLoggingInstance(); |
187 | 203 |
188 // Send hello message. | 204 // Send hello message. |
189 scoped_ptr<base::DictionaryValue> data(new base::DictionaryValue()); | 205 scoped_ptr<base::DictionaryValue> data(new base::DictionaryValue()); |
190 data->SetInteger("apiVersion", kApiVersion); | 206 data->SetInteger("apiVersion", kApiVersion); |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
297 } else if (method == "useAsyncPinDialog") { | 313 } else if (method == "useAsyncPinDialog") { |
298 use_async_pin_dialog_ = true; | 314 use_async_pin_dialog_ = true; |
299 } else if (method == "onPinFetched") { | 315 } else if (method == "onPinFetched") { |
300 HandleOnPinFetched(*data); | 316 HandleOnPinFetched(*data); |
301 } else if (method == "onThirdPartyTokenFetched") { | 317 } else if (method == "onThirdPartyTokenFetched") { |
302 HandleOnThirdPartyTokenFetched(*data); | 318 HandleOnThirdPartyTokenFetched(*data); |
303 } else if (method == "requestPairing") { | 319 } else if (method == "requestPairing") { |
304 HandleRequestPairing(*data); | 320 HandleRequestPairing(*data); |
305 } else if (method == "extensionMessage") { | 321 } else if (method == "extensionMessage") { |
306 HandleExtensionMessage(*data); | 322 HandleExtensionMessage(*data); |
323 } else if (method == "allowMouseLock") { | |
324 HandleAllowMouseLockMessage(); | |
307 } | 325 } |
308 } | 326 } |
309 | 327 |
328 void ChromotingInstance::DidChangeFocus(bool has_focus) { | |
329 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
330 | |
331 focused_ = has_focus; | |
332 RequestMouseLock(); | |
Wez
2013/09/05 20:24:45
nit: It looks strange to call RequestMouseLock() i
alexeypa (please no reviews)
2013/09/06 20:00:17
RequestMouseLock() checks whether the plugin is fo
| |
333 } | |
334 | |
310 void ChromotingInstance::DidChangeView(const pp::View& view) { | 335 void ChromotingInstance::DidChangeView(const pp::View& view) { |
311 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | 336 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); |
312 | 337 |
313 plugin_view_ = view; | 338 plugin_view_ = view; |
314 if (view_) { | 339 if (view_) { |
315 view_->SetView(view); | 340 view_->SetView(view); |
316 mouse_input_filter_.set_input_size(view_->get_view_size_dips()); | 341 mouse_input_filter_.set_input_size(view_->get_view_size_dips()); |
317 } | 342 } |
318 } | 343 } |
319 | 344 |
320 bool ChromotingInstance::HandleInputEvent(const pp::InputEvent& event) { | 345 bool ChromotingInstance::HandleInputEvent(const pp::InputEvent& event) { |
321 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | 346 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); |
322 | 347 |
323 if (!IsConnected()) | 348 if (!IsConnected()) |
324 return false; | 349 return false; |
325 | 350 |
326 return input_handler_.HandleInputEvent(event); | 351 return input_handler_.HandleInputEvent(event, |
352 mouse_lock_state_ == MouseLockOn); | |
353 } | |
354 | |
355 void ChromotingInstance::MouseLockLost() { | |
356 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
357 DCHECK(mouse_lock_state_ == MouseLockOn || | |
358 mouse_lock_state_ == MouseLockCancelling); | |
359 | |
360 mouse_lock_state_ = MouseLockOff; | |
361 EnableMousePointer(); | |
327 } | 362 } |
328 | 363 |
329 void ChromotingInstance::SetDesktopSize(const SkISize& size, | 364 void ChromotingInstance::SetDesktopSize(const SkISize& size, |
330 const SkIPoint& dpi) { | 365 const SkIPoint& dpi) { |
331 mouse_input_filter_.set_output_size(size); | 366 mouse_input_filter_.set_output_size(size); |
332 | 367 |
333 scoped_ptr<base::DictionaryValue> data(new base::DictionaryValue()); | 368 scoped_ptr<base::DictionaryValue> data(new base::DictionaryValue()); |
334 data->SetInteger("width", size.width()); | 369 data->SetInteger("width", size.width()); |
335 data->SetInteger("height", size.height()); | 370 data->SetInteger("height", size.height()); |
336 if (dpi.x()) | 371 if (dpi.x()) |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
457 void ChromotingInstance::InjectClipboardEvent( | 492 void ChromotingInstance::InjectClipboardEvent( |
458 const protocol::ClipboardEvent& event) { | 493 const protocol::ClipboardEvent& event) { |
459 scoped_ptr<base::DictionaryValue> data(new base::DictionaryValue()); | 494 scoped_ptr<base::DictionaryValue> data(new base::DictionaryValue()); |
460 data->SetString("mimeType", event.mime_type()); | 495 data->SetString("mimeType", event.mime_type()); |
461 data->SetString("item", event.data()); | 496 data->SetString("item", event.data()); |
462 PostChromotingMessage("injectClipboardItem", data.Pass()); | 497 PostChromotingMessage("injectClipboardItem", data.Pass()); |
463 } | 498 } |
464 | 499 |
465 void ChromotingInstance::SetCursorShape( | 500 void ChromotingInstance::SetCursorShape( |
466 const protocol::CursorShapeInfo& cursor_shape) { | 501 const protocol::CursorShapeInfo& cursor_shape) { |
502 COMPILE_ASSERT(sizeof(uint32_t) == kBytesPerPixel, rgba_pixels_are_32bit); | |
503 | |
467 if (!cursor_shape.has_data() || | 504 if (!cursor_shape.has_data() || |
468 !cursor_shape.has_width() || | 505 !cursor_shape.has_width() || |
469 !cursor_shape.has_height() || | 506 !cursor_shape.has_height() || |
470 !cursor_shape.has_hotspot_x() || | 507 !cursor_shape.has_hotspot_x() || |
471 !cursor_shape.has_hotspot_y()) { | 508 !cursor_shape.has_hotspot_y()) { |
472 return; | 509 return; |
473 } | 510 } |
474 | 511 |
475 int width = cursor_shape.width(); | 512 int width = cursor_shape.width(); |
476 int height = cursor_shape.height(); | 513 int height = cursor_shape.height(); |
(...skipping 16 matching lines...) Expand all Loading... | |
493 } | 530 } |
494 | 531 |
495 if (pp::ImageData::GetNativeImageDataFormat() != | 532 if (pp::ImageData::GetNativeImageDataFormat() != |
496 PP_IMAGEDATAFORMAT_BGRA_PREMUL) { | 533 PP_IMAGEDATAFORMAT_BGRA_PREMUL) { |
497 VLOG(2) << "Unable to set cursor shape - non-native image format"; | 534 VLOG(2) << "Unable to set cursor shape - non-native image format"; |
498 return; | 535 return; |
499 } | 536 } |
500 | 537 |
501 int hotspot_x = cursor_shape.hotspot_x(); | 538 int hotspot_x = cursor_shape.hotspot_x(); |
502 int hotspot_y = cursor_shape.hotspot_y(); | 539 int hotspot_y = cursor_shape.hotspot_y(); |
540 int bytes_per_row = width * kBytesPerPixel; | |
541 int src_stride = width; | |
542 const uint32_t* src_row_data = reinterpret_cast<const uint32_t*>( | |
543 cursor_shape.data().data()); | |
544 const uint32_t* src_row_data_end = src_row_data + src_stride * height; | |
503 | 545 |
504 int bytes_per_row = width * kBytesPerPixel; | 546 // See if the cursor image completely consists of transparent pixels. |
Wez
2013/09/05 20:24:45
nit: consists completely
alexeypa (please no reviews)
2013/09/06 20:00:17
Done.
| |
505 const uint8* src_row_data = reinterpret_cast<const uint8*>( | 547 bool mouse_lock_requested = (mouse_lock_state_ != MouseLockDisabled) && |
506 cursor_shape.data().data()); | 548 (std::find_if(src_row_data, |
507 int stride = bytes_per_row; | 549 src_row_data_end, |
550 &IsVisiblePixel) == src_row_data_end); | |
Wez
2013/09/05 20:24:45
nit: Move this find_if() into an IsVisibleRow() he
alexeypa (please no reviews)
2013/09/06 20:00:17
Done.
| |
551 if (mouse_lock_requested) { | |
552 // Request mouse lock. | |
553 cursor_image_.reset(); | |
554 RequestMouseLock(); | |
555 } else { | |
556 // If the cursor exceeds the size permitted by PPAPI then crop it, keeping | |
557 // the hotspot as close to the center of the new cursor shape as possible. | |
Wez
2013/09/05 20:24:45
Nit, can we move this crop logic into a CropCursor
alexeypa (please no reviews)
2013/09/06 20:00:17
Not sure. This code updates a bunch of local varia
| |
558 if (height > kMaxCursorHeight) { | |
559 int y = hotspot_y - (kMaxCursorHeight / 2); | |
560 y = std::max(y, 0); | |
561 y = std::min(y, height - kMaxCursorHeight); | |
508 | 562 |
509 // If the cursor exceeds the size permitted by PPAPI then crop it, keeping | 563 src_row_data += src_stride * y; |
510 // the hotspot as close to the center of the new cursor shape as possible. | 564 height = kMaxCursorHeight; |
511 if (height > kMaxCursorHeight) { | 565 hotspot_y -= y; |
512 int y = hotspot_y - (kMaxCursorHeight / 2); | 566 } |
513 y = std::max(y, 0); | 567 if (width > kMaxCursorWidth) { |
514 y = std::min(y, height - kMaxCursorHeight); | 568 int x = hotspot_x - (kMaxCursorWidth / 2); |
569 x = std::max(x, 0); | |
570 x = std::min(x, height - kMaxCursorWidth); | |
515 | 571 |
516 src_row_data += stride * y; | 572 src_row_data += x; |
517 height = kMaxCursorHeight; | 573 width = kMaxCursorWidth; |
518 hotspot_y -= y; | 574 bytes_per_row = width * kBytesPerPixel; |
575 hotspot_x -= x; | |
576 } | |
577 | |
578 cursor_image_.reset(new pp::ImageData(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL, | |
579 pp::Size(width, height), false)); | |
580 cursor_hotspot_ = pp::Point(hotspot_x, hotspot_y); | |
581 | |
582 uint8* dst_row_data = reinterpret_cast<uint8*>(cursor_image_->data()); | |
583 for (int row = 0; row < height; row++) { | |
584 memcpy(dst_row_data, src_row_data, bytes_per_row); | |
585 src_row_data += src_stride; | |
586 dst_row_data += cursor_image_->stride(); | |
587 } | |
588 | |
589 // Cancel mouse lock if any and apply the new cursor image. | |
Wez
2013/09/05 20:24:45
nit: if any and -> if active, and
alexeypa (please no reviews)
2013/09/06 20:00:17
Done.
| |
590 CancelMouseLock(); | |
519 } | 591 } |
520 if (width > kMaxCursorWidth) { | |
521 int x = hotspot_x - (kMaxCursorWidth / 2); | |
522 x = std::max(x, 0); | |
523 x = std::min(x, height - kMaxCursorWidth); | |
524 | |
525 src_row_data += x * kBytesPerPixel; | |
526 width = kMaxCursorWidth; | |
527 bytes_per_row = width * kBytesPerPixel; | |
528 hotspot_x -= x; | |
529 } | |
530 | |
531 pp::ImageData cursor_image(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL, | |
532 pp::Size(width, height), false); | |
533 | |
534 uint8* dst_row_data = reinterpret_cast<uint8*>(cursor_image.data()); | |
535 for (int row = 0; row < height; row++) { | |
536 memcpy(dst_row_data, src_row_data, bytes_per_row); | |
537 src_row_data += stride; | |
538 dst_row_data += cursor_image.stride(); | |
539 } | |
540 | |
541 pp::MouseCursor::SetCursor(this, PP_MOUSECURSOR_TYPE_CUSTOM, | |
542 cursor_image, | |
543 pp::Point(hotspot_x, hotspot_y)); | |
544 } | 592 } |
545 | 593 |
546 void ChromotingInstance::OnFirstFrameReceived() { | 594 void ChromotingInstance::OnFirstFrameReceived() { |
547 scoped_ptr<base::DictionaryValue> data(new base::DictionaryValue()); | 595 scoped_ptr<base::DictionaryValue> data(new base::DictionaryValue()); |
548 PostChromotingMessage("onFirstFrameReceived", data.Pass()); | 596 PostChromotingMessage("onFirstFrameReceived", data.Pass()); |
549 } | 597 } |
550 | 598 |
551 void ChromotingInstance::HandleConnect(const base::DictionaryValue& data) { | 599 void ChromotingInstance::HandleConnect(const base::DictionaryValue& data) { |
552 ClientConfig config; | 600 ClientConfig config; |
553 std::string local_jid; | 601 std::string local_jid; |
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
853 } | 901 } |
854 if (!IsConnected()) { | 902 if (!IsConnected()) { |
855 return; | 903 return; |
856 } | 904 } |
857 protocol::ExtensionMessage message; | 905 protocol::ExtensionMessage message; |
858 message.set_type(type); | 906 message.set_type(type); |
859 message.set_data(message_data); | 907 message.set_data(message_data); |
860 host_connection_->host_stub()->DeliverClientMessage(message); | 908 host_connection_->host_stub()->DeliverClientMessage(message); |
861 } | 909 } |
862 | 910 |
911 void ChromotingInstance::HandleAllowMouseLockMessage() { | |
912 DCHECK_EQ(mouse_lock_state_, MouseLockDisabled); | |
913 mouse_lock_state_ = MouseLockOff; | |
914 } | |
915 | |
863 ChromotingStats* ChromotingInstance::GetStats() { | 916 ChromotingStats* ChromotingInstance::GetStats() { |
864 if (!client_.get()) | 917 if (!client_.get()) |
865 return NULL; | 918 return NULL; |
866 return client_->GetStats(); | 919 return client_->GetStats(); |
867 } | 920 } |
868 | 921 |
869 void ChromotingInstance::PostChromotingMessage( | 922 void ChromotingInstance::PostChromotingMessage( |
870 const std::string& method, | 923 const std::string& method, |
871 scoped_ptr<base::DictionaryValue> data) { | 924 scoped_ptr<base::DictionaryValue> data) { |
872 scoped_ptr<base::DictionaryValue> message(new base::DictionaryValue()); | 925 scoped_ptr<base::DictionaryValue> message(new base::DictionaryValue()); |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1029 std::string url_scheme = url.substr(url_components.scheme.begin, | 1082 std::string url_scheme = url.substr(url_components.scheme.begin, |
1030 url_components.scheme.len); | 1083 url_components.scheme.len); |
1031 return url_scheme == kChromeExtensionUrlScheme; | 1084 return url_scheme == kChromeExtensionUrlScheme; |
1032 } | 1085 } |
1033 | 1086 |
1034 bool ChromotingInstance::IsConnected() { | 1087 bool ChromotingInstance::IsConnected() { |
1035 return host_connection_.get() && | 1088 return host_connection_.get() && |
1036 (host_connection_->state() == protocol::ConnectionToHost::CONNECTED); | 1089 (host_connection_->state() == protocol::ConnectionToHost::CONNECTED); |
1037 } | 1090 } |
1038 | 1091 |
1092 void ChromotingInstance::EnableMousePointer() { | |
Wez
2013/09/05 20:24:45
This name doesn't feel right; you're setting the c
alexeypa (please no reviews)
2013/09/06 20:00:17
Done.
| |
1093 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
1094 DCHECK(mouse_lock_state_ == MouseLockDisabled || | |
1095 mouse_lock_state_ == MouseLockOff); | |
1096 | |
1097 if (cursor_image_) { | |
1098 pp::MouseCursor::SetCursor(this, PP_MOUSECURSOR_TYPE_CUSTOM, | |
1099 *cursor_image_, | |
1100 cursor_hotspot_); | |
1101 } else { | |
1102 // THe browser cancelled mouse lock but we don't have a cursor to show. Use | |
1103 // the standard arrow pointer instead. | |
Wez
2013/09/05 20:24:45
Will we also be in this state if the host never se
alexeypa (please no reviews)
2013/09/06 20:00:17
Done.
| |
1104 pp::MouseCursor::SetCursor(this, PP_MOUSECURSOR_TYPE_POINTER); | |
1105 } | |
1106 } | |
1107 | |
1108 void ChromotingInstance::RequestMouseLock() { | |
1109 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
1110 | |
1111 // Request mouse lock if the plugin is focused, mouse lock requested by | |
Wez
2013/09/05 20:24:45
nit: lock if -> lock only if
alexeypa (please no reviews)
2013/09/06 20:00:17
Done.
| |
1112 // the host and no callback is pending. | |
Wez
2013/09/05 20:24:45
nit: mouse lock requested by the host -> the host-
alexeypa (please no reviews)
2013/09/06 20:00:17
Done.
| |
1113 if (focused_ && !cursor_image_ && mouse_lock_state_ == MouseLockOff) { | |
Wez
2013/09/05 20:24:45
nit: I think this function would be more readable
alexeypa (please no reviews)
2013/09/06 20:00:17
Six lines instead of one? I don't think so.
| |
1114 pp::CompletionCallback callback = | |
1115 callback_factory_.NewCallback(&ChromotingInstance::OnMouseLocked); | |
1116 int result = pp::MouseLock::LockMouse(callback); | |
1117 DCHECK_EQ(result, PP_OK_COMPLETIONPENDING); | |
1118 | |
1119 // Hide the cursor to workaround http://crbug.com/285809. | |
Wez
2013/09/05 20:24:45
nit: Suggest: "Hide cursor to avoid it becoming a
alexeypa (please no reviews)
2013/09/06 20:00:17
Done.
| |
1120 pp::MouseCursor::SetCursor(this, PP_MOUSECURSOR_TYPE_NONE); | |
1121 mouse_lock_state_ = MouseLockPending; | |
Wez
2013/09/05 20:24:45
nit: Since the comment "Hide the cursor" doesn't a
alexeypa (please no reviews)
2013/09/06 20:00:17
Done.
| |
1122 } | |
1123 } | |
1124 | |
1125 void ChromotingInstance::CancelMouseLock() { | |
1126 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
1127 | |
1128 switch (mouse_lock_state_) { | |
1129 case MouseLockDisabled: | |
1130 case MouseLockOff: | |
1131 EnableMousePointer(); | |
1132 break; | |
1133 | |
1134 case MouseLockCancelling: | |
1135 break; | |
1136 | |
1137 case MouseLockPending: | |
1138 // Let the callback know that the operation should be cancelled. | |
Wez
2013/09/05 20:24:45
nit: Clarify here that we can't call UnlockMouse()
alexeypa (please no reviews)
2013/09/06 20:00:17
Done.
| |
1139 mouse_lock_state_ = MouseLockCancelling; | |
1140 break; | |
1141 | |
1142 case MouseLockOn: | |
1143 pp::MouseLock::UnlockMouse(); | |
1144 | |
1145 // Wait until MouseLockLost() is called. | |
Wez
2013/09/05 20:24:45
nit: Suggest "Note that mouse-lock has been cancel
alexeypa (please no reviews)
2013/09/06 20:00:17
Done.
| |
1146 mouse_lock_state_ = MouseLockCancelling; | |
1147 break; | |
1148 | |
1149 default: | |
1150 NOTREACHED(); | |
1151 } | |
1152 } | |
1153 | |
1154 void ChromotingInstance::OnMouseLocked(int error) { | |
1155 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
1156 DCHECK(mouse_lock_state_ == MouseLockPending || | |
1157 mouse_lock_state_ == MouseLockCancelling); | |
1158 | |
1159 bool cancel = (mouse_lock_state_ == MouseLockCancelling); | |
Wez
2013/09/05 20:24:45
nit: cancel -> should_cancel?
alexeypa (please no reviews)
2013/09/06 20:00:17
Done.
| |
1160 | |
1161 // See if the operation succeeded. | |
1162 if (error == PP_OK) { | |
1163 mouse_lock_state_ = MouseLockOn; | |
1164 } else { | |
1165 mouse_lock_state_ = MouseLockOff; | |
1166 EnableMousePointer(); | |
1167 } | |
1168 | |
1169 // Cancel as needed. | |
1170 if (cancel) | |
1171 CancelMouseLock(); | |
Wez
2013/09/05 20:24:45
So we can't dispatch the mouse-lock cancel until a
alexeypa (please no reviews)
2013/09/06 20:00:17
I don't know. I implemented it this way because th
| |
1172 } | |
1173 | |
1039 } // namespace remoting | 1174 } // namespace remoting |
OLD | NEW |