// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "components/test_runner/gamepad_controller.h" #include "components/test_runner/web_test_delegate.h" #include "gin/arguments.h" #include "gin/handle.h" #include "gin/object_template_builder.h" #include "gin/wrappable.h" #include "third_party/WebKit/public/platform/WebGamepadListener.h" #include "third_party/WebKit/public/web/WebFrame.h" #include "third_party/WebKit/public/web/WebKit.h" #include "v8/include/v8.h" using blink::WebFrame; using blink::WebGamepad; using blink::WebGamepads; namespace test_runner { class GamepadControllerBindings : public gin::Wrappable { public: static gin::WrapperInfo kWrapperInfo; static void Install(base::WeakPtr controller, blink::WebFrame* frame); private: explicit GamepadControllerBindings( base::WeakPtr controller); ~GamepadControllerBindings() override; // gin::Wrappable. gin::ObjectTemplateBuilder GetObjectTemplateBuilder( v8::Isolate* isolate) override; void Connect(int index); void DispatchConnected(int index); void Disconnect(int index); void SetId(int index, const std::string& src); void SetButtonCount(int index, int buttons); void SetButtonData(int index, int button, double data); void SetAxisCount(int index, int axes); void SetAxisData(int index, int axis, double data); base::WeakPtr controller_; DISALLOW_COPY_AND_ASSIGN(GamepadControllerBindings); }; gin::WrapperInfo GamepadControllerBindings::kWrapperInfo = { gin::kEmbedderNativeGin}; // static void GamepadControllerBindings::Install( base::WeakPtr controller, WebFrame* frame) { v8::Isolate* isolate = blink::mainThreadIsolate(); v8::HandleScope handle_scope(isolate); v8::Local context = frame->mainWorldScriptContext(); if (context.IsEmpty()) return; v8::Context::Scope context_scope(context); gin::Handle bindings = gin::CreateHandle(isolate, new GamepadControllerBindings(controller)); if (bindings.IsEmpty()) return; v8::Local global = context->Global(); global->Set(gin::StringToV8(isolate, "gamepadController"), bindings.ToV8()); } GamepadControllerBindings::GamepadControllerBindings( base::WeakPtr controller) : controller_(controller) {} GamepadControllerBindings::~GamepadControllerBindings() {} gin::ObjectTemplateBuilder GamepadControllerBindings::GetObjectTemplateBuilder( v8::Isolate* isolate) { return gin::Wrappable::GetObjectTemplateBuilder( isolate) .SetMethod("connect", &GamepadControllerBindings::Connect) .SetMethod("dispatchConnected", &GamepadControllerBindings::DispatchConnected) .SetMethod("disconnect", &GamepadControllerBindings::Disconnect) .SetMethod("setId", &GamepadControllerBindings::SetId) .SetMethod("setButtonCount", &GamepadControllerBindings::SetButtonCount) .SetMethod("setButtonData", &GamepadControllerBindings::SetButtonData) .SetMethod("setAxisCount", &GamepadControllerBindings::SetAxisCount) .SetMethod("setAxisData", &GamepadControllerBindings::SetAxisData); } void GamepadControllerBindings::Connect(int index) { if (controller_) controller_->Connect(index); } void GamepadControllerBindings::DispatchConnected(int index) { if (controller_) controller_->DispatchConnected(index); } void GamepadControllerBindings::Disconnect(int index) { if (controller_) controller_->Disconnect(index); } void GamepadControllerBindings::SetId(int index, const std::string& src) { if (controller_) controller_->SetId(index, src); } void GamepadControllerBindings::SetButtonCount(int index, int buttons) { if (controller_) controller_->SetButtonCount(index, buttons); } void GamepadControllerBindings::SetButtonData(int index, int button, double data) { if (controller_) controller_->SetButtonData(index, button, data); } void GamepadControllerBindings::SetAxisCount(int index, int axes) { if (controller_) controller_->SetAxisCount(index, axes); } void GamepadControllerBindings::SetAxisData(int index, int axis, double data) { if (controller_) controller_->SetAxisData(index, axis, data); } // static base::WeakPtr GamepadController::Create( WebTestDelegate* delegate) { CHECK(delegate); GamepadController* controller = new GamepadController(); delegate->SetGamepadProvider(controller); return controller->weak_factory_.GetWeakPtr(); } GamepadController::GamepadController() : listener_(nullptr), weak_factory_(this) { Reset(); } GamepadController::~GamepadController() { } void GamepadController::Reset() { memset(&gamepads_, 0, sizeof(gamepads_)); } void GamepadController::Install(WebFrame* frame) { GamepadControllerBindings::Install(weak_factory_.GetWeakPtr(), frame); } void GamepadController::SampleGamepads(blink::WebGamepads& gamepads) { memcpy(&gamepads, &gamepads_, sizeof(blink::WebGamepads)); } void GamepadController::SetListener(blink::WebGamepadListener* listener) { listener_ = listener; } void GamepadController::Connect(int index) { if (index < 0 || index >= static_cast(WebGamepads::itemsLengthCap)) return; gamepads_.items[index].connected = true; gamepads_.length = 0; for (unsigned i = 0; i < WebGamepads::itemsLengthCap; ++i) { if (gamepads_.items[i].connected) gamepads_.length = i + 1; } } void GamepadController::DispatchConnected(int index) { if (index < 0 || index >= static_cast(WebGamepads::itemsLengthCap) || !gamepads_.items[index].connected) return; const WebGamepad& pad = gamepads_.items[index]; if (listener_) listener_->didConnectGamepad(index, pad); } void GamepadController::Disconnect(int index) { if (index < 0 || index >= static_cast(WebGamepads::itemsLengthCap)) return; WebGamepad& pad = gamepads_.items[index]; pad.connected = false; gamepads_.length = 0; for (unsigned i = 0; i < WebGamepads::itemsLengthCap; ++i) { if (gamepads_.items[i].connected) gamepads_.length = i + 1; } if (listener_) listener_->didDisconnectGamepad(index, pad); } void GamepadController::SetId(int index, const std::string& src) { if (index < 0 || index >= static_cast(WebGamepads::itemsLengthCap)) return; const char* p = src.c_str(); memset(gamepads_.items[index].id, 0, sizeof(gamepads_.items[index].id)); for (unsigned i = 0; *p && i < WebGamepad::idLengthCap - 1; ++i) gamepads_.items[index].id[i] = *p++; } void GamepadController::SetButtonCount(int index, int buttons) { if (index < 0 || index >= static_cast(WebGamepads::itemsLengthCap)) return; if (buttons < 0 || buttons >= static_cast(WebGamepad::buttonsLengthCap)) return; gamepads_.items[index].buttonsLength = buttons; } void GamepadController::SetButtonData(int index, int button, double data) { if (index < 0 || index >= static_cast(WebGamepads::itemsLengthCap)) return; if (button < 0 || button >= static_cast(WebGamepad::buttonsLengthCap)) return; gamepads_.items[index].buttons[button].value = data; gamepads_.items[index].buttons[button].pressed = data > 0.1f; } void GamepadController::SetAxisCount(int index, int axes) { if (index < 0 || index >= static_cast(WebGamepads::itemsLengthCap)) return; if (axes < 0 || axes >= static_cast(WebGamepad::axesLengthCap)) return; gamepads_.items[index].axesLength = axes; } void GamepadController::SetAxisData(int index, int axis, double data) { if (index < 0 || index >= static_cast(WebGamepads::itemsLengthCap)) return; if (axis < 0 || axis >= static_cast(WebGamepad::axesLengthCap)) return; gamepads_.items[index].axes[axis] = data; } } // namespace test_runner