Chromium Code Reviews| 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..35d5b1a6d3966911ae162a4b32e08a8892aa12e3 |
| --- /dev/null |
| +++ b/third_party/WebKit/Source/modules/gamepad/GamepadSharedMemoryReader.cpp |
| @@ -0,0 +1,151 @@ |
| +// 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 "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. |
|
ke.he
2016/12/15 14:35:56
TODO(), does all the Content level trace need be t
|
| + |
| + 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,??? |
|
ke.he
2016/12/15 14:11:01
messy here, just to pass the presubmit. but I do n
|
| + //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 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 WebGamepad& gamepad) { |
| + if (m_listener) |
| + m_listener->didDisconnectGamepad(index, gamepad); |
| +} |
| + |
| +} // namespace blink |