| OLD | NEW |
| (Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "modules/gamepad/GamepadSharedMemoryReader.h" |
| 6 |
| 7 //#include "base/trace_event/trace_event.h" //heke: replace to Webkit traces. |
| 8 #include "device/base/synchronization/shared_memory_seqlock_buffer.h" |
| 9 #include "platform/Histogram.h" |
| 10 #include "public/platform/InterfaceProvider.h" |
| 11 #include "wtf/StdLibExtras.h" |
| 12 |
| 13 namespace blink { |
| 14 |
| 15 GamepadSharedMemoryReader::GamepadSharedMemoryReader( |
| 16 InterfaceProvider* interfaceProvider) |
| 17 : m_gamepadHardwareBuffer(nullptr), |
| 18 m_everInteracted(false), |
| 19 m_isObserving(false), |
| 20 m_binding(this), |
| 21 m_listener(nullptr) { |
| 22 if (interfaceProvider) { |
| 23 interfaceProvider->getInterface(mojo::GetProxy(&m_gamepadMonitor)); |
| 24 m_gamepadMonitor->SetObserver(m_binding.CreateInterfacePtrAndBind()); |
| 25 } |
| 26 } |
| 27 |
| 28 GamepadSharedMemoryReader::~GamepadSharedMemoryReader() { |
| 29 if (m_isObserving) { |
| 30 stop(); |
| 31 } |
| 32 } |
| 33 |
| 34 void GamepadSharedMemoryReader::sendStartMessage() { |
| 35 if (m_gamepadMonitor) { |
| 36 m_gamepadMonitor->GamepadStartPolling(&m_sharedBufferHandle); |
| 37 } |
| 38 } |
| 39 |
| 40 void GamepadSharedMemoryReader::sendStopMessage() { |
| 41 if (m_gamepadMonitor) { |
| 42 m_gamepadMonitor->GamepadStopPolling(); |
| 43 } |
| 44 } |
| 45 |
| 46 void GamepadSharedMemoryReader::start(WebGamepadListener* listener) { |
| 47 DCHECK(!m_isObserving); |
| 48 m_listener = listener; |
| 49 m_isObserving = true; |
| 50 |
| 51 sendStartMessage(); |
| 52 |
| 53 // If we don't get a valid handle from the browser, don't try to Map (we're |
| 54 // probably out of memory or file handles). |
| 55 bool isValid = m_sharedBufferHandle.is_valid(); |
| 56 |
| 57 DEFINE_STATIC_LOCAL(BooleanHistogram, validHandleHistogram, |
| 58 ("Gamepad.ValidSharedMemoryHandle")); |
| 59 validHandleHistogram.count(isValid); |
| 60 |
| 61 if (!isValid) |
| 62 return; |
| 63 |
| 64 m_sharedBufferMapping = |
| 65 m_sharedBufferHandle->Map(sizeof(GamepadHardwareBuffer)); |
| 66 CHECK(m_sharedBufferMapping); |
| 67 void* memory = m_sharedBufferMapping.get(); |
| 68 CHECK(memory); |
| 69 m_gamepadHardwareBuffer = static_cast<GamepadHardwareBuffer*>(memory); |
| 70 } |
| 71 |
| 72 void GamepadSharedMemoryReader::stop() { |
| 73 DCHECK(m_isObserving); |
| 74 m_listener = nullptr; |
| 75 m_isObserving = false; |
| 76 |
| 77 sendStopMessage(); |
| 78 } |
| 79 |
| 80 void GamepadSharedMemoryReader::sampleGamepads(WebGamepads& gamepads) { |
| 81 // Blink should have started observing at that point. |
| 82 CHECK(m_isObserving); |
| 83 |
| 84 // ========== |
| 85 // DANGER |
| 86 // ========== |
| 87 // |
| 88 // This logic is duplicated in Pepper as well. If you change it, that also |
| 89 // needs to be in sync. See ppapi/proxy/gamepad_resource.cc. |
| 90 WebGamepads readInto; |
| 91 // TRACE_EVENT0("GAMEPAD", "SampleGamepads"); //heke: Webkit trace. |
| 92 |
| 93 if (!m_sharedBufferHandle.is_valid()) |
| 94 return; |
| 95 |
| 96 // Only try to read this many times before failing to avoid waiting here |
| 97 // very long in case of contention with the writer. TODO(scottmg) Tune this |
| 98 // number (as low as 1?) if histogram shows distribution as mostly |
| 99 // 0-and-maximum. |
| 100 const int kMaximumContentionCount = 10; |
| 101 int contentionCount = -1; |
| 102 |
| 103 // heke: just to pass the presubmit. |
| 104 // base::subtle::Atomic32 version; // heke: using base namespace here,??? |
| 105 // do { |
| 106 // version = m_gamepadHardwareBuffer->seqlock.ReadBegin(); |
| 107 memcpy(&readInto, &m_gamepadHardwareBuffer->data, sizeof(readInto)); |
| 108 ++contentionCount; |
| 109 // if (contentionCount == kMaximumContentionCount) |
| 110 // break; |
| 111 //} while (m_gamepadHardwareBuffer->seqlock.ReadRetry(version)); |
| 112 |
| 113 DEFINE_STATIC_LOCAL(CustomCountHistogram, contentionCountHistogram, |
| 114 ("Gamepad.ReadContentionCount", 1, 1000000, 50)); |
| 115 contentionCountHistogram.count(contentionCount); |
| 116 |
| 117 if (contentionCount >= kMaximumContentionCount) { |
| 118 // We failed to successfully read, presumably because the hardware |
| 119 // thread was taking unusually long. Don't copy the data to the output |
| 120 // buffer, and simply leave what was there before. |
| 121 return; |
| 122 } |
| 123 |
| 124 // New data was read successfully, copy it into the output buffer. |
| 125 memcpy(&gamepads, &readInto, sizeof(gamepads)); |
| 126 |
| 127 if (!m_everInteracted) { |
| 128 // Clear the connected flag if the user hasn't interacted with any of the |
| 129 // gamepads to prevent fingerprinting. The actual data is not cleared. |
| 130 // WebKit will only copy out data into the JS buffers for connected |
| 131 // gamepads so this is sufficient. |
| 132 for (unsigned i = 0; i < WebGamepads::itemsLengthCap; i++) |
| 133 gamepads.items[i].connected = false; |
| 134 } |
| 135 } |
| 136 |
| 137 void GamepadSharedMemoryReader::GamepadConnected( |
| 138 int index, |
| 139 const ::blink::WebGamepad& gamepad) { |
| 140 // The browser already checks if the user actually interacted with a device. |
| 141 m_everInteracted = true; |
| 142 |
| 143 if (m_listener) |
| 144 m_listener->didConnectGamepad(index, gamepad); |
| 145 } |
| 146 |
| 147 void GamepadSharedMemoryReader::GamepadDisconnected( |
| 148 int index, |
| 149 const ::blink::WebGamepad& gamepad) { |
| 150 if (m_listener) |
| 151 m_listener->didDisconnectGamepad(index, gamepad); |
| 152 } |
| 153 |
| 154 } // namespace blink |
| OLD | NEW |