Bug 852257 - implement Gamepad.timestamp property; r=ted, r=smaug
authorSnigdha Agarwal <snigdhaagarwal93@gmail.com>
Wed, 07 Jan 2015 14:17:04 -0500
changeset 223379 8e8ce6c0d19aca731410e3ef8b3810e2bfb2b799
parent 223378 fff1eae2346fce938e64f070280a1528330a769c
child 223380 b2aff7ebf9b45444997a83d8aeccc3339897cb41
push id13196
push userryanvm@gmail.com
push dateMon, 12 Jan 2015 20:57:04 +0000
treeherderb2g-inbound@afde7b62b332 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted, smaug
bugs852257
milestone37.0a1
Bug 852257 - implement Gamepad.timestamp property; r=ted, r=smaug
dom/gamepad/Gamepad.cpp
dom/gamepad/Gamepad.h
dom/tests/mochitest/gamepad/mochitest.ini
dom/tests/mochitest/gamepad/test_check_timestamp.html
dom/tests/mochitest/gamepad/test_gamepad.html
dom/webidl/Gamepad.webidl
--- a/dom/gamepad/Gamepad.cpp
+++ b/dom/gamepad/Gamepad.cpp
@@ -1,14 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "Gamepad.h"
 #include "nsAutoPtr.h"
+#include "nsPIDOMWindow.h"
 #include "nsTArray.h"
 #include "nsVariant.h"
 #include "mozilla/dom/GamepadBinding.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(Gamepad)
@@ -16,32 +17,45 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(Gamepad
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Gamepad)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Gamepad, mParent, mButtons)
 
+void
+Gamepad::UpdateTimestamp()
+{
+  nsCOMPtr<nsPIDOMWindow> newWindow(do_QueryInterface(mParent));
+  if(newWindow) {
+    nsPerformance* perf = newWindow->GetPerformance();
+    if (perf) {
+      mTimestamp =  perf->GetDOMTiming()->TimeStampToDOMHighRes(TimeStamp::Now());
+    }
+  }
+}
+
 Gamepad::Gamepad(nsISupports* aParent,
                  const nsAString& aID, uint32_t aIndex,
                  GamepadMappingType aMapping,
                  uint32_t aNumButtons, uint32_t aNumAxes)
   : mParent(aParent),
     mID(aID),
     mIndex(aIndex),
     mMapping(aMapping),
     mConnected(true),
     mButtons(aNumButtons),
     mAxes(aNumAxes)
 {
   for (unsigned i = 0; i < aNumButtons; i++) {
     mButtons.InsertElementAt(i, new GamepadButton(mParent));
   }
   mAxes.InsertElementsAt(0, aNumAxes, 0.0f);
+  UpdateTimestamp();
 }
 
 void
 Gamepad::SetIndex(uint32_t aIndex)
 {
   mIndex = aIndex;
 }
 
@@ -52,26 +66,28 @@ Gamepad::SetConnected(bool aConnected)
 }
 
 void
 Gamepad::SetButton(uint32_t aButton, bool aPressed, double aValue)
 {
   MOZ_ASSERT(aButton < mButtons.Length());
   mButtons[aButton]->SetPressed(aPressed);
   mButtons[aButton]->SetValue(aValue);
+  UpdateTimestamp();
 }
 
 void
 Gamepad::SetAxis(uint32_t aAxis, double aValue)
 {
   MOZ_ASSERT(aAxis < mAxes.Length());
   if (mAxes[aAxis] != aValue) {
     mAxes[aAxis] = aValue;
     GamepadBinding::ClearCachedAxesValue(this);
   }
+  UpdateTimestamp();
 }
 
 void
 Gamepad::SyncState(Gamepad* aOther)
 {
   if (mButtons.Length() != aOther->mButtons.Length() ||
       mAxes.Length() != aOther->mAxes.Length()) {
     return;
@@ -85,16 +101,17 @@ Gamepad::SyncState(Gamepad* aOther)
   bool changed = false;
   for (uint32_t i = 0; i < mAxes.Length(); ++i) {
     changed = changed || (mAxes[i] != aOther->mAxes[i]);
     mAxes[i] = aOther->mAxes[i];
   }
   if (changed) {
     GamepadBinding::ClearCachedAxesValue(this);
   }
+  UpdateTimestamp();
 }
 
 already_AddRefed<Gamepad>
 Gamepad::Clone(nsISupports* aParent)
 {
   nsRefPtr<Gamepad> out =
     new Gamepad(aParent, mID, mIndex, mMapping,
                 mButtons.Length(), mAxes.Length());
--- a/dom/gamepad/Gamepad.h
+++ b/dom/gamepad/Gamepad.h
@@ -8,16 +8,17 @@
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/GamepadBinding.h"
 #include "mozilla/dom/GamepadButton.h"
 #include <stdint.h>
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsWrapperCache.h"
+#include "nsPerformance.h"
 
 namespace mozilla {
 namespace dom {
 
 // Per spec:
 // https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html#remapping
 const int kStandardGamepadButtons = 17;
 const int kStandardGamepadAxes = 4;
@@ -60,16 +61,21 @@ public:
 
   virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
 
   void GetId(nsAString& aID) const
   {
     aID = mID;
   }
 
+  DOMHighResTimeStamp Timestamp() const
+  {
+     return mTimestamp;
+  }
+
   GamepadMappingType Mapping()
   {
     return mMapping;
   }
 
   bool Connected() const
   {
     return mConnected;
@@ -87,29 +93,31 @@ public:
 
   void GetAxes(nsTArray<double>& aAxes) const
   {
     aAxes = mAxes;
   }
 
 private:
   virtual ~Gamepad() {}
+  void UpdateTimestamp();
 
 protected:
   nsCOMPtr<nsISupports> mParent;
   nsString mID;
   uint32_t mIndex;
 
   // The mapping in use.
   GamepadMappingType mMapping;
 
   // true if this gamepad is currently connected.
   bool mConnected;
 
   // Current state of buttons, axes.
   nsTArray<nsRefPtr<GamepadButton>> mButtons;
   nsTArray<double> mAxes;
+  DOMHighResTimeStamp mTimestamp;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_gamepad_Gamepad_h
--- a/dom/tests/mochitest/gamepad/mochitest.ini
+++ b/dom/tests/mochitest/gamepad/mochitest.ini
@@ -1,15 +1,16 @@
 [DEFAULT]
 skip-if = e10s
 support-files =
   gamepad_frame.html
   gamepad_frame_state.html
   mock_gamepad.js
 
+[test_check_timestamp.html]
 [test_gamepad.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_gamepad_connect_events.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_gamepad_frame_state_sync.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_gamepad_hidden_frame.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/gamepad/test_check_timestamp.html
@@ -0,0 +1,51 @@
+<!-- Any copyright is dedicated to the Public Domain.
+   - http://creativecommons.org/publicdomain/zero/1.0/ -->
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test Gamepad.timestamp</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<script type="text/javascript" src="mock_gamepad.js"></script>
+<script class="testbody" type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+var index = GamepadService.addGamepad("test gamepad", // id
+                                      SpecialPowers.Ci.nsIGamepadServiceTest.NO_MAPPING,
+                                      4, // buttons
+                                      2);// axes
+
+var timea=0;
+window.addEventListener("gamepadbuttondown", buttonpresshandler);
+
+var firstPress = true;
+GamepadService.newButtonEvent(index, 0, true);
+GamepadService.newButtonEvent(index, 0, true);
+
+function cleanup(){
+  SpecialPowers.executeSoon(function() {
+    GamepadService.removeGamepad(index);
+    SimpleTest.finish();
+  });
+}
+
+function buttonpresshandler(e) {
+  if(timea == 0){
+    timea = e.gamepad.timestamp;
+  }
+  else{
+    ok(timea <= e.gamepad.timestamp);
+  }
+  GamepadService.newButtonEvent(index, 0, false);
+  if (!firstPress) {
+    SpecialPowers.executeSoon(cleanup);
+  }
+  else {
+    firstPress = false;
+  }
+}
+
+</script>
+</body>
+</html>
--- a/dom/tests/mochitest/gamepad/test_gamepad.html
+++ b/dom/tests/mochitest/gamepad/test_gamepad.html
@@ -15,16 +15,17 @@ window.addEventListener("gamepadconnecte
 // Add a gamepad
 var index = GamepadService.addGamepad("test gamepad", // id
                                       SpecialPowers.Ci.nsIGamepadServiceTest.STANDARD_MAPPING,
                                       4, // buttons
                                       2);// axes
 // Press a button
 GamepadService.newButtonEvent(index, 0, true);
 function connecthandler(e) {
+  ok(e.gamepad.timestamp <= performance.now());
   is(e.gamepad.id, "test gamepad", "correct gamepad name");
   is(e.gamepad.mapping, "standard", "standard mapping");
   is(e.gamepad.buttons.length, 4, "correct number of buttons");
   is(e.gamepad.axes.length, 2, "correct number of axes");
   SimpleTest.executeSoon(function() {
     GamepadService.removeGamepad(index);
     SimpleTest.finish();
   });
--- a/dom/webidl/Gamepad.webidl
+++ b/dom/webidl/Gamepad.webidl
@@ -46,9 +46,14 @@ interface Gamepad {
   readonly attribute sequence<GamepadButton> buttons;
 
   /**
    * The current position of all axes on the device, an
    * array of doubles.
    */
   [Pure, Cached, Frozen]
   readonly attribute sequence<double> axes;
+
+  /**
+   * Timestamp from when the data of this device was last updated.
+   */
+  readonly attribute DOMHighResTimeStamp timestamp;
 };