Chromium Code Reviews| 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 |