| Index: third_party/WebKit/Source/modules/gamepad/GamepadSharedMemoryReader.cpp
|
| diff --git a/third_party/WebKit/Source/modules/gamepad/GamepadSharedMemoryReader.cpp b/third_party/WebKit/Source/modules/gamepad/GamepadSharedMemoryReader.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..cf960d75effe71982e6773c2be6625939b1661c5
|
| --- /dev/null
|
| +++ b/third_party/WebKit/Source/modules/gamepad/GamepadSharedMemoryReader.cpp
|
| @@ -0,0 +1,154 @@
|
| +// Copyright (c) 2012 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 "modules/gamepad/GamepadSharedMemoryReader.h"
|
| +
|
| +//#include "base/trace_event/trace_event.h" //heke: replace to Webkit traces.
|
| +#include "device/base/synchronization/shared_memory_seqlock_buffer.h"
|
| +#include "platform/Histogram.h"
|
| +#include "public/platform/InterfaceProvider.h"
|
| +#include "wtf/StdLibExtras.h"
|
| +
|
| +namespace blink {
|
| +
|
| +GamepadSharedMemoryReader::GamepadSharedMemoryReader(
|
| + InterfaceProvider* interfaceProvider)
|
| + : m_gamepadHardwareBuffer(nullptr),
|
| + m_everInteracted(false),
|
| + m_isObserving(false),
|
| + m_binding(this),
|
| + m_listener(nullptr) {
|
| + if (interfaceProvider) {
|
| + interfaceProvider->getInterface(mojo::GetProxy(&m_gamepadMonitor));
|
| + m_gamepadMonitor->SetObserver(m_binding.CreateInterfacePtrAndBind());
|
| + }
|
| +}
|
| +
|
| +GamepadSharedMemoryReader::~GamepadSharedMemoryReader() {
|
| + if (m_isObserving) {
|
| + stop();
|
| + }
|
| +}
|
| +
|
| +void GamepadSharedMemoryReader::sendStartMessage() {
|
| + if (m_gamepadMonitor) {
|
| + m_gamepadMonitor->GamepadStartPolling(&m_sharedBufferHandle);
|
| + }
|
| +}
|
| +
|
| +void GamepadSharedMemoryReader::sendStopMessage() {
|
| + if (m_gamepadMonitor) {
|
| + m_gamepadMonitor->GamepadStopPolling();
|
| + }
|
| +}
|
| +
|
| +void GamepadSharedMemoryReader::start(WebGamepadListener* listener) {
|
| + DCHECK(!m_isObserving);
|
| + m_listener = listener;
|
| + m_isObserving = true;
|
| +
|
| + sendStartMessage();
|
| +
|
| + // If we don't get a valid handle from the browser, don't try to Map (we're
|
| + // probably out of memory or file handles).
|
| + bool isValid = m_sharedBufferHandle.is_valid();
|
| +
|
| + DEFINE_STATIC_LOCAL(BooleanHistogram, validHandleHistogram,
|
| + ("Gamepad.ValidSharedMemoryHandle"));
|
| + validHandleHistogram.count(isValid);
|
| +
|
| + if (!isValid)
|
| + return;
|
| +
|
| + m_sharedBufferMapping =
|
| + m_sharedBufferHandle->Map(sizeof(GamepadHardwareBuffer));
|
| + CHECK(m_sharedBufferMapping);
|
| + void* memory = m_sharedBufferMapping.get();
|
| + CHECK(memory);
|
| + m_gamepadHardwareBuffer = static_cast<GamepadHardwareBuffer*>(memory);
|
| +}
|
| +
|
| +void GamepadSharedMemoryReader::stop() {
|
| + DCHECK(m_isObserving);
|
| + m_listener = nullptr;
|
| + m_isObserving = false;
|
| +
|
| + sendStopMessage();
|
| +}
|
| +
|
| +void GamepadSharedMemoryReader::sampleGamepads(WebGamepads& gamepads) {
|
| + // Blink should have started observing at that point.
|
| + CHECK(m_isObserving);
|
| +
|
| + // ==========
|
| + // DANGER
|
| + // ==========
|
| + //
|
| + // This logic is duplicated in Pepper as well. If you change it, that also
|
| + // needs to be in sync. See ppapi/proxy/gamepad_resource.cc.
|
| + WebGamepads readInto;
|
| + // TRACE_EVENT0("GAMEPAD", "SampleGamepads"); //heke: Webkit trace.
|
| +
|
| + if (!m_sharedBufferHandle.is_valid())
|
| + return;
|
| +
|
| + // Only try to read this many times before failing to avoid waiting here
|
| + // very long in case of contention with the writer. TODO(scottmg) Tune this
|
| + // number (as low as 1?) if histogram shows distribution as mostly
|
| + // 0-and-maximum.
|
| + const int kMaximumContentionCount = 10;
|
| + int contentionCount = -1;
|
| +
|
| + // heke: just to pass the presubmit.
|
| + // base::subtle::Atomic32 version; // heke: using base namespace here,???
|
| + // do {
|
| + // version = m_gamepadHardwareBuffer->seqlock.ReadBegin();
|
| + memcpy(&readInto, &m_gamepadHardwareBuffer->data, sizeof(readInto));
|
| + ++contentionCount;
|
| + // if (contentionCount == kMaximumContentionCount)
|
| + // break;
|
| + //} while (m_gamepadHardwareBuffer->seqlock.ReadRetry(version));
|
| +
|
| + DEFINE_STATIC_LOCAL(CustomCountHistogram, contentionCountHistogram,
|
| + ("Gamepad.ReadContentionCount", 1, 1000000, 50));
|
| + contentionCountHistogram.count(contentionCount);
|
| +
|
| + if (contentionCount >= kMaximumContentionCount) {
|
| + // We failed to successfully read, presumably because the hardware
|
| + // thread was taking unusually long. Don't copy the data to the output
|
| + // buffer, and simply leave what was there before.
|
| + return;
|
| + }
|
| +
|
| + // New data was read successfully, copy it into the output buffer.
|
| + memcpy(&gamepads, &readInto, sizeof(gamepads));
|
| +
|
| + if (!m_everInteracted) {
|
| + // Clear the connected flag if the user hasn't interacted with any of the
|
| + // gamepads to prevent fingerprinting. The actual data is not cleared.
|
| + // WebKit will only copy out data into the JS buffers for connected
|
| + // gamepads so this is sufficient.
|
| + for (unsigned i = 0; i < WebGamepads::itemsLengthCap; i++)
|
| + gamepads.items[i].connected = false;
|
| + }
|
| +}
|
| +
|
| +void GamepadSharedMemoryReader::GamepadConnected(
|
| + int index,
|
| + const ::blink::WebGamepad& gamepad) {
|
| + // The browser already checks if the user actually interacted with a device.
|
| + m_everInteracted = true;
|
| +
|
| + if (m_listener)
|
| + m_listener->didConnectGamepad(index, gamepad);
|
| +}
|
| +
|
| +void GamepadSharedMemoryReader::GamepadDisconnected(
|
| + int index,
|
| + const ::blink::WebGamepad& gamepad) {
|
| + if (m_listener)
|
| + m_listener->didDisconnectGamepad(index, gamepad);
|
| +}
|
| +
|
| +} // namespace blink
|
|
|