Bug 1264409 - Make last transaction ID available via nsIDOMWindowUtils, and pass transaction ID through MozAfterPaint. r=mattwoodrow,mrbkap
authorMike Conley <mconley@mozilla.com>
Wed, 13 Apr 2016 16:59:15 -0400
changeset 293404 2f5f51545d0e466479ec6fdf8b89af72685dfc6d
parent 293403 5b8ad9b0048855129351918a04daf6e4d564fbb4
child 293405 a338aa9ac43ff12190109267d2210d230db9286e
push id30180
push userkwierso@gmail.com
push dateFri, 15 Apr 2016 21:31:41 +0000
treeherdermozilla-central@ded7cf683d5a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow, mrbkap
bugs1264409
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1264409 - Make last transaction ID available via nsIDOMWindowUtils, and pass transaction ID through MozAfterPaint. r=mattwoodrow,mrbkap MozReview-Commit-ID: 7wCYif8F6ws
dom/base/nsDOMWindowUtils.cpp
dom/events/NotifyPaintEvent.cpp
dom/events/NotifyPaintEvent.h
dom/interfaces/base/nsIDOMWindowUtils.idl
dom/interfaces/events/nsIDOMNotifyPaintEvent.idl
dom/webidl/NotifyPaintEvent.webidl
gfx/layers/TransactionIdAllocator.h
gfx/layers/client/ClientLayerManager.cpp
layout/base/nsPresContext.cpp
layout/base/nsPresContext.h
layout/base/nsRefreshDriver.cpp
layout/base/nsRefreshDriver.h
view/nsView.cpp
view/nsView.h
widget/nsIWidgetListener.cpp
widget/nsIWidgetListener.h
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -2301,16 +2301,29 @@ nsDOMWindowUtils::AdvanceTimeAndRefresh(
       transaction->SendSetTestSampleTime(driver->MostRecentRefresh());
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsDOMWindowUtils::GetLastTransactionId(uint64_t *aLastTransactionId)
+{
+  nsPresContext* presContext = GetPresContext();
+  if (!presContext) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  nsRefreshDriver* driver = presContext->GetRootPresContext()->RefreshDriver();
+  *aLastTransactionId = driver->LastTransactionId();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsDOMWindowUtils::RestoreNormalRefresh()
 {
   // Kick the compositor out of test mode before the refresh driver, so that
   // the refresh driver doesn't send an update that gets ignored by the
   // compositor.
   RefPtr<LayerTransactionChild> transaction = GetLayerTransaction();
   if (transaction && transaction->IPCOpen()) {
     transaction->SendLeaveTestMode();
--- a/dom/events/NotifyPaintEvent.cpp
+++ b/dom/events/NotifyPaintEvent.cpp
@@ -14,25 +14,28 @@
 
 namespace mozilla {
 namespace dom {
 
 NotifyPaintEvent::NotifyPaintEvent(EventTarget* aOwner,
                                    nsPresContext* aPresContext,
                                    WidgetEvent* aEvent,
                                    EventMessage aEventMessage,
-                                   nsInvalidateRequestList* aInvalidateRequests)
+                                   nsInvalidateRequestList* aInvalidateRequests,
+                                   uint64_t aTransactionId)
   : Event(aOwner, aPresContext, aEvent)
 {
   if (mEvent) {
     mEvent->mMessage = aEventMessage;
   }
   if (aInvalidateRequests) {
     mInvalidateRequests.AppendElements(Move(aInvalidateRequests->mRequests));
   }
+
+  mTransactionId = aTransactionId;
 }
 
 NS_INTERFACE_MAP_BEGIN(NotifyPaintEvent)
   NS_INTERFACE_MAP_ENTRY(nsIDOMNotifyPaintEvent)
 NS_INTERFACE_MAP_END_INHERITING(Event)
 
 NS_IMPL_ADDREF_INHERITED(NotifyPaintEvent, Event)
 NS_IMPL_RELEASE_INHERITED(NotifyPaintEvent, Event)
@@ -149,26 +152,40 @@ NotifyPaintEvent::Deserialize(const IPC:
     NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &req.mRect), false);
     NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &req.mFlags), false);
     mInvalidateRequests.AppendElement(req);
   }
 
   return true;
 }
 
+NS_IMETHODIMP
+NotifyPaintEvent::GetTransactionId(uint64_t* aTransactionId)
+{
+  *aTransactionId = mTransactionId;
+  return NS_OK;
+}
+
+uint64_t
+NotifyPaintEvent::TransactionId()
+{
+  return mTransactionId;
+}
+
 } // namespace dom
 } // namespace mozilla
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 already_AddRefed<NotifyPaintEvent>
 NS_NewDOMNotifyPaintEvent(EventTarget* aOwner,
                           nsPresContext* aPresContext,
                           WidgetEvent* aEvent,
                           EventMessage aEventMessage,
-                          nsInvalidateRequestList* aInvalidateRequests) 
+                          nsInvalidateRequestList* aInvalidateRequests,
+                          uint64_t aTransactionId)
 {
   RefPtr<NotifyPaintEvent> it =
     new NotifyPaintEvent(aOwner, aPresContext, aEvent, aEventMessage,
-                         aInvalidateRequests);
+                         aInvalidateRequests, aTransactionId);
   return it.forget();
 }
--- a/dom/events/NotifyPaintEvent.h
+++ b/dom/events/NotifyPaintEvent.h
@@ -24,17 +24,18 @@ class NotifyPaintEvent : public Event,
                          public nsIDOMNotifyPaintEvent
 {
 
 public:
   NotifyPaintEvent(EventTarget* aOwner,
                    nsPresContext* aPresContext,
                    WidgetEvent* aEvent,
                    EventMessage aEventMessage,
-                   nsInvalidateRequestList* aInvalidateRequests);
+                   nsInvalidateRequestList* aInvalidateRequests,
+                   uint64_t aTransactionId);
 
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_DECL_NSIDOMNOTIFYPAINTEVENT
 
   // Forward to base class
   NS_FORWARD_TO_EVENT_NO_SERIALIZATION_NO_DUPLICATION
   NS_IMETHOD DuplicatePrivateData() override
@@ -50,31 +51,35 @@ public:
   }
 
   already_AddRefed<DOMRectList> ClientRects();
 
   already_AddRefed<DOMRect> BoundingClientRect();
 
   already_AddRefed<PaintRequestList> PaintRequests();
 
+  uint64_t TransactionId();
+
 protected:
   ~NotifyPaintEvent() {}
 
 private:
   nsRegion GetRegion();
 
   nsTArray<nsInvalidateRequestList::Request> mInvalidateRequests;
+  uint64_t mTransactionId;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 // This empties aInvalidateRequests.
 already_AddRefed<mozilla::dom::NotifyPaintEvent>
 NS_NewDOMNotifyPaintEvent(mozilla::dom::EventTarget* aOwner,
                           nsPresContext* aPresContext,
                           mozilla::WidgetEvent* aEvent,
                           mozilla::EventMessage aEventMessage =
                             mozilla::eVoidEvent,
                           nsInvalidateRequestList* aInvalidateRequests =
-                            nullptr);
+                            nullptr,
+                          uint64_t aTransactionId = 0);
 
 #endif // mozilla_dom_NotifyPaintEvent_h_
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -102,16 +102,21 @@ interface nsIDOMWindowUtils : nsISupport
   unsigned long redraw([optional] in unsigned long aCount);
 
   /**
    * Force a synchronous layer transaction for this window if necessary.
    */
   void updateLayerTree();
 
   /**
+   * Get the last used layer transaction id for this window's refresh driver.
+   */
+  readonly attribute unsigned long long lastTransactionId;
+
+  /**
    * Information retrieved from the <meta name="viewport"> tag.
    * See nsContentUtils::GetViewportInfo for more information.
    */
   void getViewportInfo(in uint32_t aDisplayWidth, in uint32_t aDisplayHeight,
                        out double aDefaultZoom, out boolean aAllowZoom,
                        out double aMinZoom, out double aMaxZoom,
                        out uint32_t aWidth, out uint32_t aHeight,
                        out boolean aAutoSize);
--- a/dom/interfaces/events/nsIDOMNotifyPaintEvent.idl
+++ b/dom/interfaces/events/nsIDOMNotifyPaintEvent.idl
@@ -30,10 +30,12 @@ interface nsIDOMNotifyPaintEvent : nsISu
    * is in CSS pixels relative to the viewport origin.
    * If the caller is not trusted (e.g., regular Web content) then only painting
    * caused by the current document is reported; in particular, painting in subdocuments
    * is not reported.
    */
   readonly attribute nsIDOMClientRect boundingClientRect;
 
   readonly attribute nsISupports /* PaintRequestList */ paintRequests;
+
+  readonly attribute unsigned long long transactionId;
 };
 
--- a/dom/webidl/NotifyPaintEvent.webidl
+++ b/dom/webidl/NotifyPaintEvent.webidl
@@ -8,9 +8,11 @@
 
 interface NotifyPaintEvent : Event
 {
   readonly attribute DOMRectList clientRects;
 
   readonly attribute DOMRect boundingClientRect;
 
   readonly attribute PaintRequestList paintRequests;
+
+  readonly attribute unsigned long long transactionId;
 };
--- a/gfx/layers/TransactionIdAllocator.h
+++ b/gfx/layers/TransactionIdAllocator.h
@@ -24,16 +24,23 @@ public:
    * only be called while IsInRefresh().
    *
    * If too many id's are allocated without being returned then
    * the refresh driver will suspend until they catch up.
    */
   virtual uint64_t GetTransactionId() = 0;
 
   /**
+   * Return the transaction id that for the last non-revoked transaction.
+   * This allows the caller to tell whether a composite was triggered by
+   * a paint that occurred after a call to TransactionId().
+   */
+  virtual uint64_t LastTransactionId() const = 0;
+
+  /**
    * Notify that all work (including asynchronous composites)
    * for a given transaction id has been completed.
    *
    * If the refresh driver has been suspended because
    * of having too many outstanding id's, then this may
    * resume it.
    */
   virtual void NotifyTransactionCompleted(uint64_t aTransactionId) = 0;
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -414,21 +414,21 @@ ClientLayerManager::DidComposite(uint64_
 {
   MOZ_ASSERT(mWidget);
 
   // |aTransactionId| will be > 0 if the compositor is acknowledging a shadow
   // layers transaction.
   if (aTransactionId) {
     nsIWidgetListener *listener = mWidget->GetWidgetListener();
     if (listener) {
-      listener->DidCompositeWindow(aCompositeStart, aCompositeEnd);
+      listener->DidCompositeWindow(aTransactionId, aCompositeStart, aCompositeEnd);
     }
     listener = mWidget->GetAttachedWidgetListener();
     if (listener) {
-      listener->DidCompositeWindow(aCompositeStart, aCompositeEnd);
+      listener->DidCompositeWindow(aTransactionId, aCompositeStart, aCompositeEnd);
     }
     mTransactionIdAllocator->NotifyTransactionCompleted(aTransactionId);
   }
 
   // These observers fire whether or not we were in a transaction.
   for (size_t i = 0; i < mDidCompositeObservers.Length(); i++) {
     mDidCompositeObservers[i]->DidComposite();
   }
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -2152,17 +2152,17 @@ nsPresContext::EnsureSafeToHandOutCSSRul
     // Nothing to do.
     return;
   }
 
   RebuildAllStyleData(nsChangeHint(0), eRestyle_Subtree);
 }
 
 void
-nsPresContext::FireDOMPaintEvent(nsInvalidateRequestList* aList)
+nsPresContext::FireDOMPaintEvent(nsInvalidateRequestList* aList, uint64_t aTransactionId)
 {
   nsPIDOMWindowInner* ourWindow = mDocument->GetInnerWindow();
   if (!ourWindow)
     return;
 
   nsCOMPtr<EventTarget> dispatchTarget = do_QueryInterface(ourWindow);
   nsCOMPtr<EventTarget> eventTarget = dispatchTarget;
   if (!IsChrome() && !mSendAfterPaintToContent) {
@@ -2177,17 +2177,17 @@ nsPresContext::FireDOMPaintEvent(nsInval
   }
   // Events sent to the window get propagated to the chrome event handler
   // automatically.
   //
   // This will empty our list in case dispatching the event causes more damage
   // (hopefully it won't, or we're likely to get an infinite loop! At least
   // it won't be blocking app execution though).
   RefPtr<NotifyPaintEvent> event =
-    NS_NewDOMNotifyPaintEvent(eventTarget, this, nullptr, eAfterPaint, aList);
+    NS_NewDOMNotifyPaintEvent(eventTarget, this, nullptr, eAfterPaint, aList, aTransactionId);
 
   // Even if we're not telling the window about the event (so eventTarget is
   // the chrome event handler, not the window), the window is still
   // logically the event target.
   event->SetTarget(eventTarget);
   event->SetTrusted(true);
   EventDispatcher::DispatchDOMEvent(dispatchTarget, nullptr,
                                     static_cast<Event*>(event), this, nullptr);
@@ -2374,62 +2374,67 @@ nsPresContext::SetNotifySubDocInvalidati
 /* static */ void
 nsPresContext::ClearNotifySubDocInvalidationData(ContainerLayer* aContainer)
 {
   aContainer->SetUserData(&gNotifySubDocInvalidationData, nullptr);
 }
 
 struct NotifyDidPaintSubdocumentCallbackClosure {
   uint32_t mFlags;
+  uint64_t mTransactionId;
   bool mNeedsAnotherDidPaintNotification;
 };
 static bool
 NotifyDidPaintSubdocumentCallback(nsIDocument* aDocument, void* aData)
 {
   NotifyDidPaintSubdocumentCallbackClosure* closure =
     static_cast<NotifyDidPaintSubdocumentCallbackClosure*>(aData);
   nsIPresShell* shell = aDocument->GetShell();
   if (shell) {
     nsPresContext* pc = shell->GetPresContext();
     if (pc) {
-      pc->NotifyDidPaintForSubtree(closure->mFlags);
+      pc->NotifyDidPaintForSubtree(closure->mFlags, closure->mTransactionId);
       if (pc->IsDOMPaintEventPending()) {
         closure->mNeedsAnotherDidPaintNotification = true;
       }
     }
   }
   return true;
 }
 
 class DelayedFireDOMPaintEvent : public nsRunnable {
 public:
   DelayedFireDOMPaintEvent(nsPresContext* aPresContext,
-                           nsInvalidateRequestList* aList)
+                           nsInvalidateRequestList* aList,
+                           uint64_t aTransactionId)
     : mPresContext(aPresContext)
+    , mTransactionId(aTransactionId)
   {
     MOZ_ASSERT(mPresContext->GetContainerWeak(),
                "DOMPaintEvent requested for a detached pres context");
     mList.TakeFrom(aList);
   }
   NS_IMETHOD Run() override
   {
     // The pres context might have been detached during the delay -
     // that's fine, just don't fire the event.
     if (mPresContext->GetContainerWeak()) {
-      mPresContext->FireDOMPaintEvent(&mList);
+      mPresContext->FireDOMPaintEvent(&mList, mTransactionId);
     }
     return NS_OK;
   }
 
   RefPtr<nsPresContext> mPresContext;
+  uint64_t mTransactionId;
   nsInvalidateRequestList mList;
 };
 
 void
-nsPresContext::NotifyDidPaintForSubtree(uint32_t aFlags)
+nsPresContext::NotifyDidPaintForSubtree(uint32_t aFlags, uint64_t aTransactionId,
+                                        const mozilla::TimeStamp& aTimeStamp)
 {
   if (IsRoot()) {
     static_cast<nsRootPresContext*>(this)->CancelDidPaintTimer();
 
     if (!mFireAfterPaintEvents) {
       return;
     }
   }
@@ -2446,21 +2451,22 @@ nsPresContext::NotifyDidPaintForSubtree(
 
   if (aFlags & nsIPresShell::PAINT_LAYERS) {
     mUndeliveredInvalidateRequestsBeforeLastPaint.TakeFrom(
         &mInvalidateRequestsSinceLastPaint);
     mAllInvalidated = false;
   }
   if (aFlags & nsIPresShell::PAINT_COMPOSITE) {
     nsCOMPtr<nsIRunnable> ev =
-      new DelayedFireDOMPaintEvent(this, &mUndeliveredInvalidateRequestsBeforeLastPaint);
+      new DelayedFireDOMPaintEvent(this, &mUndeliveredInvalidateRequestsBeforeLastPaint,
+                                   aTransactionId);
     nsContentUtils::AddScriptRunner(ev);
   }
 
-  NotifyDidPaintSubdocumentCallbackClosure closure = { aFlags, false };
+  NotifyDidPaintSubdocumentCallbackClosure closure = { aFlags, aTransactionId, false };
   mDocument->EnumerateSubDocuments(NotifyDidPaintSubdocumentCallback, &closure);
 
   if (!closure.mNeedsAnotherDidPaintNotification &&
       mInvalidateRequestsSinceLastPaint.IsEmpty() &&
       mUndeliveredInvalidateRequestsBeforeLastPaint.IsEmpty()) {
     // Nothing more to do for the moment.
     mFireAfterPaintEvents = false;
   } else {
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -921,18 +921,19 @@ public:
   // and, if necessary, synchronously rebuilding all style data.
   void EnsureSafeToHandOutCSSRules();
 
   void NotifyInvalidation(uint32_t aFlags);
   void NotifyInvalidation(const nsRect& aRect, uint32_t aFlags);
   // aRect is in device pixels
   void NotifyInvalidation(const nsIntRect& aRect, uint32_t aFlags);
   // aFlags are nsIPresShell::PAINT_ flags
-  void NotifyDidPaintForSubtree(uint32_t aFlags);
-  void FireDOMPaintEvent(nsInvalidateRequestList* aList);
+  void NotifyDidPaintForSubtree(uint32_t aFlags, uint64_t aTransactionId = 0,
+                                const mozilla::TimeStamp& aTimeStamp = mozilla::TimeStamp());
+  void FireDOMPaintEvent(nsInvalidateRequestList* aList, uint64_t aTransactionId);
 
   // Callback for catching invalidations in ContainerLayers
   // Passed to LayerProperties::ComputeDifference
   static void NotifySubDocInvalidation(mozilla::layers::ContainerLayer* aContainer,
                                        const nsIntRegion& aRegion);
   void SetNotifySubDocInvalidationData(mozilla::layers::ContainerLayer* aContainer);
   static void ClearNotifySubDocInvalidationData(mozilla::layers::ContainerLayer* aContainer);
   bool IsDOMPaintEventPending();
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -2002,16 +2002,22 @@ nsRefreshDriver::GetTransactionId()
       !mTestControllingRefreshes) {
     mWaitingForTransaction = true;
     mSkippedPaints = false;
   }
 
   return mPendingTransaction;
 }
 
+uint64_t
+nsRefreshDriver::LastTransactionId() const
+{
+  return mPendingTransaction;
+}
+
 void
 nsRefreshDriver::RevokeTransactionId(uint64_t aTransactionId)
 {
   MOZ_ASSERT(aTransactionId == mPendingTransaction);
   if (mPendingTransaction == mCompletedTransaction + 2 &&
       mWaitingForTransaction) {
     MOZ_ASSERT(!mSkippedPaints, "How did we skip a paint when we're in the middle of one?");
     FinishedWaitingForTransaction();
--- a/layout/base/nsRefreshDriver.h
+++ b/layout/base/nsRefreshDriver.h
@@ -314,17 +314,18 @@ public:
    * time.
    *
    * Return `false` if `aJank` needs to be grown to accomodate the
    * data but we didn't have enough memory.
    */
   static bool GetJankLevels(mozilla::Vector<uint64_t>& aJank);
 
   // mozilla::layers::TransactionIdAllocator
-  virtual uint64_t GetTransactionId() override;
+  uint64_t GetTransactionId() override;
+  uint64_t LastTransactionId() const override;
   void NotifyTransactionCompleted(uint64_t aTransactionId) override;
   void RevokeTransactionId(uint64_t aTransactionId) override;
   mozilla::TimeStamp GetTransactionStart() override;
 
   bool IsWaitingForPaint(mozilla::TimeStamp aTime);
 
   // nsARefreshObserver
   NS_IMETHOD_(MozExternalRefCountType) AddRef(void) override { return TransactionIdAllocator::AddRef(); }
--- a/view/nsView.cpp
+++ b/view/nsView.cpp
@@ -1073,27 +1073,29 @@ nsView::PaintWindow(nsIWidget* aWidget, 
 void
 nsView::DidPaintWindow()
 {
   RefPtr<nsViewManager> vm = mViewManager;
   vm->DidPaintWindow();
 }
 
 void
-nsView::DidCompositeWindow(const TimeStamp& aCompositeStart,
+nsView::DidCompositeWindow(uint64_t aTransactionId,
+                           const TimeStamp& aCompositeStart,
                            const TimeStamp& aCompositeEnd)
 {
   nsIPresShell* presShell = mViewManager->GetPresShell();
   if (presShell) {
     nsAutoScriptBlocker scriptBlocker;
 
     nsPresContext* context = presShell->GetPresContext();
     nsRootPresContext* rootContext = context->GetRootPresContext();
     MOZ_ASSERT(rootContext, "rootContext must be valid.");
-    rootContext->NotifyDidPaintForSubtree(nsIPresShell::PAINT_COMPOSITE);
+    rootContext->NotifyDidPaintForSubtree(nsIPresShell::PAINT_COMPOSITE, aTransactionId,
+                                          aCompositeEnd);
 
     // If the two timestamps are identical, this was likely a fake composite
     // event which wouldn't be terribly useful to display.
     if (aCompositeStart == aCompositeEnd) {
       return;
     }
 
     nsIDocShell* docShell = context->GetDocShell();
--- a/view/nsView.h
+++ b/view/nsView.h
@@ -381,17 +381,18 @@ public:
   virtual nsView* GetView() override { return this; }
   virtual bool WindowMoved(nsIWidget* aWidget, int32_t x, int32_t y) override;
   virtual bool WindowResized(nsIWidget* aWidget, int32_t aWidth, int32_t aHeight) override;
   virtual bool RequestWindowClose(nsIWidget* aWidget) override;
   virtual void WillPaintWindow(nsIWidget* aWidget) override;
   virtual bool PaintWindow(nsIWidget* aWidget,
                            LayoutDeviceIntRegion aRegion) override;
   virtual void DidPaintWindow() override;
-  virtual void DidCompositeWindow(const mozilla::TimeStamp& aCompositeStart,
+  virtual void DidCompositeWindow(uint64_t aTransactionId,
+                                  const mozilla::TimeStamp& aCompositeStart,
                                   const mozilla::TimeStamp& aCompositeEnd) override;
   virtual void RequestRepaint() override;
   virtual nsEventStatus HandleEvent(mozilla::WidgetGUIEvent* aEvent,
                                     bool aUseAttachedEvents) override;
 
   virtual ~nsView();
 
   nsPoint GetOffsetTo(const nsView* aOther, const int32_t aAPD) const;
--- a/widget/nsIWidgetListener.cpp
+++ b/widget/nsIWidgetListener.cpp
@@ -107,17 +107,18 @@ nsIWidgetListener::PaintWindow(nsIWidget
 }
 
 void
 nsIWidgetListener::DidPaintWindow()
 {
 }
 
 void
-nsIWidgetListener::DidCompositeWindow(const TimeStamp& aCompositeStart,
+nsIWidgetListener::DidCompositeWindow(uint64_t aTransactionId,
+                                      const TimeStamp& aCompositeStart,
                                       const TimeStamp& aCompositeEnd)
 {
 }
 
 void
 nsIWidgetListener::RequestRepaint()
 {
 }
--- a/widget/nsIWidgetListener.h
+++ b/widget/nsIWidgetListener.h
@@ -141,17 +141,18 @@ public:
   /**
    * Indicates that a paint occurred.
    * This is called at a time when it is OK to change the geometry of
    * this widget or of other widgets.
    * Must be called after every call to PaintWindow.
    */
   virtual void DidPaintWindow();
 
-  virtual void DidCompositeWindow(const mozilla::TimeStamp& aCompositeStart,
+  virtual void DidCompositeWindow(uint64_t aTransactionId,
+                                  const mozilla::TimeStamp& aCompositeStart,
                                   const mozilla::TimeStamp& aCompositeEnd);
 
   /**
    * Request that layout schedules a repaint on the next refresh driver tick.
    */
   virtual void RequestRepaint();
 
   /**