Bug 1414698 - Part 2: Reset WEBVR_TIME_SPENT_VIEWING_IN_2D telemetry when the tab moves to the background; r?kip, baku draft
authorDaosheng Mu <daoshengmu@gmail.com>
Mon, 06 Nov 2017 18:04:07 +0800
changeset 693797 3bcf46be654c939a1e325140fdab6726c7c979b1
parent 693796 dd00bb9adc0afc27d38201c638f8ba34c5920fbf
child 739140 554aecfe24494ed7909b755c8defc80e5f46624d
push id87920
push userbmo:dmu@mozilla.com
push dateMon, 06 Nov 2017 21:36:01 +0000
reviewerskip, baku
bugs1414698
milestone58.0a1
Bug 1414698 - Part 2: Reset WEBVR_TIME_SPENT_VIEWING_IN_2D telemetry when the tab moves to the background; r?kip, baku MozReview-Commit-ID: 7TKKxNlpCNT
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
dom/vr/VREventObserver.cpp
dom/vr/VREventObserver.h
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -10636,23 +10636,31 @@ void nsGlobalWindow::SetIsBackground(boo
 
   if (inner && changed) {
     inner->mTimeoutManager->UpdateBackgroundState();
   }
 
   if (aIsBackground) {
     // Notify gamepadManager we are at the background window,
     // we need to stop vibrate.
+    // Stop the vr telemery time spent when it switches to
+    // the background window.
     if (inner && changed) {
       inner->StopGamepadHaptics();
+      // true is for asking to set the delta time to
+      // the telemetry.
+      inner->ResetVRTelemetry(true);
     }
     return;
   }
 
   if (inner) {
+    // When switching to be as a top tab, restart the telemetry.
+    // false is for only resetting the timestamp.
+    inner->ResetVRTelemetry(false);
     inner->SyncGamepadState();
   }
 }
 
 void
 nsGlobalWindow::SetIsBackgroundInternal(bool aIsBackground)
 {
   if (mIsBackground != aIsBackground) {
@@ -10719,16 +10727,24 @@ nsGlobalWindow::DisableVRUpdates()
   MOZ_ASSERT(IsInnerWindow());
   if (mVREventObserver) {
     mVREventObserver->DisconnectFromOwner();
     mVREventObserver = nullptr;
   }
 }
 
 void
+nsGlobalWindow::ResetVRTelemetry(bool aUpdate)
+{
+  if (mVREventObserver) {
+    mVREventObserver->UpdateSpentTimeIn2DTelemetry(aUpdate);
+  }
+}
+
+void
 nsGlobalWindow::SetChromeEventHandler(EventTarget* aChromeEventHandler)
 {
   MOZ_ASSERT(IsOuterWindow());
 
   SetChromeEventHandlerInternal(aChromeEventHandler);
   // update the chrome event handler on all our inner windows
   for (nsGlobalWindow *inner = (nsGlobalWindow *)PR_LIST_HEAD(this);
        inner != this;
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -768,16 +768,20 @@ public:
   // Enable/disable updates for gamepad input.
   void EnableGamepadUpdates();
   void DisableGamepadUpdates();
 
   // Inner windows only.
   // Enable/disable updates for VR
   void EnableVRUpdates();
   void DisableVRUpdates();
+  // Reset telemetry data when switching windows.
+  // aUpdate, true for accumulating the result to the histogram.
+  // false for only resetting the timestamp.
+  void ResetVRTelemetry(bool aUpdate);
 
   // Update the VR displays for this window
   bool UpdateVRDisplays(nsTArray<RefPtr<mozilla::dom::VRDisplay>>& aDisplays);
 
   // Inner windows only.
   // Called to inform that the set of active VR displays has changed.
   void NotifyActiveVRDisplaysChanged();
 
--- a/dom/vr/VREventObserver.cpp
+++ b/dom/vr/VREventObserver.cpp
@@ -20,20 +20,21 @@ using namespace gfx;
 /**
  * This class is used by nsGlobalWindow to implement window.onvrdisplayactivate,
  * window.onvrdisplaydeactivate, window.onvrdisplayconnected,
  * window.onvrdisplaydisconnected, and window.onvrdisplaypresentchange.
  */
 VREventObserver::VREventObserver(nsGlobalWindow* aGlobalWindow)
   : mWindow(aGlobalWindow)
   , mIs2DView(true)
+  , mHasReset(false)
 {
   MOZ_ASSERT(aGlobalWindow && aGlobalWindow->IsInnerWindow());
 
-  mSpendTimeIn2DView = TimeStamp::Now();
+  UpdateSpentTimeIn2DTelemetry(false);
   VRManagerChild* vmc = VRManagerChild::Get();
   if (vmc) {
     vmc->AddListener(this);
   }
 }
 
 VREventObserver::~VREventObserver()
 {
@@ -41,33 +42,47 @@ VREventObserver::~VREventObserver()
 }
 
 void
 VREventObserver::DisconnectFromOwner()
 {
   // In the event that nsGlobalWindow is deallocated, VREventObserver may
   // still be AddRef'ed elsewhere.  Ensure that we don't UAF by
   // dereferencing mWindow.
-  if (mWindow && mIs2DView) {
-    // The WebVR content is closed, and we will collect the telemetry info
-    // for the users who view it in 2D view only.
-    Telemetry::Accumulate(Telemetry::WEBVR_USERS_VIEW_IN, 0);
-    Telemetry::AccumulateTimeDelta(Telemetry::WEBVR_TIME_SPENT_VIEWING_IN_2D,
-                                   mSpendTimeIn2DView);
-  }
+  UpdateSpentTimeIn2DTelemetry(true);
   mWindow = nullptr;
 
   // Unregister from VRManagerChild
   if (VRManagerChild::IsCreated()) {
     VRManagerChild* vmc = VRManagerChild::Get();
     vmc->RemoveListener(this);
   }
 }
 
 void
+VREventObserver::UpdateSpentTimeIn2DTelemetry(bool aUpdate)
+{
+  // mHasReset for avoiding setting the telemetry continuously
+  // for the telemetry is already been set when it is at the background.
+  // then, it would be set again when the process is exit and calling
+  // VREventObserver::DisconnectFromOwner().
+  if (mWindow && mIs2DView && aUpdate && mHasReset) {
+    // The WebVR content is closed, and we will collect the telemetry info
+    // for the users who view it in 2D view only.
+    Telemetry::Accumulate(Telemetry::WEBVR_USERS_VIEW_IN, 0);
+    Telemetry::AccumulateTimeDelta(Telemetry::WEBVR_TIME_SPENT_VIEWING_IN_2D,
+                                   mSpendTimeIn2DView);
+    mHasReset = false;
+  } else if (!aUpdate) {
+    mSpendTimeIn2DView = TimeStamp::Now();
+    mHasReset = true;
+  }
+}
+
+void
 VREventObserver::NotifyVRDisplayMounted(uint32_t aDisplayID)
 {
   if (mWindow && mWindow->AsInner()->IsCurrentInnerWindow()) {
     MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
     mWindow->DispatchVRDisplayActivate(aDisplayID,
                                        VRDisplayEventReason::Mounted);
   }
 }
--- a/dom/vr/VREventObserver.h
+++ b/dom/vr/VREventObserver.h
@@ -25,23 +25,25 @@ public:
   void NotifyVRDisplayUnmounted(uint32_t aDisplayID);
   void NotifyVRDisplayNavigation(uint32_t aDisplayID);
   void NotifyVRDisplayRequested(uint32_t aDisplayID);
   void NotifyVRDisplayConnect(uint32_t aDisplayID);
   void NotifyVRDisplayDisconnect(uint32_t aDisplayID);
   void NotifyVRDisplayPresentChange(uint32_t aDisplayID);
 
   void DisconnectFromOwner();
+  void UpdateSpentTimeIn2DTelemetry(bool aUpdate);
 
 private:
   ~VREventObserver();
 
   RefPtr<nsGlobalWindow> mWindow;
   // For WebVR telemetry for tracking users who view content
   // in the 2D view.
   TimeStamp mSpendTimeIn2DView;
   bool mIs2DView;
+  bool mHasReset;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_VREventObserver_h