Bug 749101 - Move window.performance to the new DOM bindings; r=bzbarsky
authorEhsan Akhgari <ehsan@mozilla.com>
Mon, 16 Jul 2012 21:42:18 -0400
changeset 99508 dd08c10193c6
parent 99507 36fcd6eabf67
child 99509 2bf404e6e7e2
push id23135
push useremorley@mozilla.com
push date2012-07-17 09:04 +0000
treeherdermozilla-central@ba8463beab13 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky
bugs749101
milestone17.0a1
Bug 749101 - Move window.performance to the new DOM bindings; r=bzbarsky
dom/base/nsDOMNavigationTiming.cpp
dom/base/nsDOMNavigationTiming.h
dom/base/nsGlobalWindow.cpp
dom/base/nsPerformance.cpp
dom/base/nsPerformance.h
dom/base/nsWrapperCache.h
dom/bindings/Bindings.conf
dom/webidl/Performance.webidl
dom/webidl/PerformanceNavigation.webidl
dom/webidl/PerformanceTiming.webidl
dom/webidl/WebIDL.mk
js/xpconnect/src/dom_quickstubs.qsconf
--- a/dom/base/nsDOMNavigationTiming.cpp
+++ b/dom/base/nsDOMNavigationTiming.cpp
@@ -38,44 +38,38 @@ nsDOMNavigationTiming::Clear()
   mDOMLoading = 0;
   mDOMInteractive = 0;
   mDOMContentLoadedEventStart = 0;
   mDOMContentLoadedEventEnd = 0;
   mDOMComplete = 0;
   mRedirectCheck = NOT_CHECKED;
 }
 
-nsresult 
-nsDOMNavigationTiming::TimeStampToDOM(mozilla::TimeStamp aStamp, 
-                                      DOMTimeMilliSec* aResult)
+DOMTimeMilliSec
+nsDOMNavigationTiming::TimeStampToDOM(mozilla::TimeStamp aStamp) const
 {
   if (aStamp.IsNull()) {
-    *aResult = 0;
-    return NS_OK;
+    return 0;
   }
   mozilla::TimeDuration duration = aStamp - mNavigationStartTimeStamp;
-  *aResult = mNavigationStart + static_cast<PRInt32>(duration.ToMilliseconds());
-  return NS_OK;
+  return mNavigationStart + static_cast<PRInt32>(duration.ToMilliseconds());
 }
 
-nsresult 
-nsDOMNavigationTiming::TimeStampToDOMOrFetchStart(mozilla::TimeStamp aStamp, 
-                                                  DOMTimeMilliSec* aResult)
+DOMTimeMilliSec
+nsDOMNavigationTiming::TimeStampToDOMOrFetchStart(mozilla::TimeStamp aStamp) const
 {
   if (!aStamp.IsNull()) {
-    return TimeStampToDOM(aStamp, aResult);
+    return TimeStampToDOM(aStamp);
   } else {
-    return GetFetchStart(aResult);
+    return GetFetchStart();
   }
 }
 
 DOMTimeMilliSec nsDOMNavigationTiming::DurationFromStart(){
-  DOMTimeMilliSec result; 
-  TimeStampToDOM(mozilla::TimeStamp::Now(), &result);
-  return result;
+  return TimeStampToDOM(mozilla::TimeStamp::Now());
 }
 
 void
 nsDOMNavigationTiming::NotifyNavigationStart()
 {
   mNavigationStart = PR_Now() / PR_USEC_PER_MSEC;
   mNavigationStartTimeStamp = mozilla::TimeStamp::Now();
 }
@@ -168,17 +162,17 @@ nsDOMNavigationTiming::ReportRedirects()
   }
   return mRedirectCheck == CHECK_PASSED;
 }
 
 void
 nsDOMNavigationTiming::SetDOMLoadingTimeStamp(nsIURI* aURI, mozilla::TimeStamp aValue)
 {
   mLoadedURI = aURI;
-  TimeStampToDOM(aValue, &mDOMLoading);
+  mDOMLoading = TimeStampToDOM(aValue);
 }
 
 void
 nsDOMNavigationTiming::NotifyDOMLoading(nsIURI* aURI)
 {
   mLoadedURI = aURI;
   mDOMLoading = DurationFromStart();
 }
@@ -206,132 +200,57 @@ nsDOMNavigationTiming::NotifyDOMContentL
 
 void
 nsDOMNavigationTiming::NotifyDOMContentLoadedEnd(nsIURI* aURI)
 {
   mLoadedURI = aURI;
   mDOMContentLoadedEventEnd = DurationFromStart();
 }
 
-nsresult
-nsDOMNavigationTiming::GetType(
-    nsDOMPerformanceNavigationType* aNavigationType)
+PRUint16
+nsDOMNavigationTiming::GetRedirectCount()
 {
-  *aNavigationType = mNavigationType;
-  return NS_OK;
-}
-
-nsresult
-nsDOMNavigationTiming::GetRedirectCount(PRUint16* aRedirectCount)
-{
-  *aRedirectCount = 0;
   if (ReportRedirects()) {
-    *aRedirectCount = mRedirectCount;
+    return mRedirectCount;
   }
-  return NS_OK;
+  return 0;
 }
 
-nsresult
-nsDOMNavigationTiming::GetRedirectStart(DOMTimeMilliSec* aRedirectStart)
+DOMTimeMilliSec
+nsDOMNavigationTiming::GetRedirectStart()
 {
-  *aRedirectStart = 0;
   if (ReportRedirects()) {
-    *aRedirectStart = mRedirectStart;
+    return mRedirectStart;
   }
-  return NS_OK;
+  return 0;
 }
 
-nsresult
-nsDOMNavigationTiming::GetRedirectEnd(DOMTimeMilliSec* aEnd)
+DOMTimeMilliSec
+nsDOMNavigationTiming::GetRedirectEnd()
 {
-  *aEnd = 0;
   if (ReportRedirects()) {
-    *aEnd = mRedirectEnd;
+    return mRedirectEnd;
   }
-  return NS_OK;
+  return 0;
 }
 
-nsresult
-nsDOMNavigationTiming::GetNavigationStart(DOMTimeMilliSec* aNavigationStart)
+DOMTimeMilliSec
+nsDOMNavigationTiming::GetUnloadEventStart()
 {
-  *aNavigationStart = mNavigationStart;
-  return NS_OK;
-}
-
-nsresult
-nsDOMNavigationTiming::GetUnloadEventStart(DOMTimeMilliSec* aStart)
-{
-  *aStart = 0;
   nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
   nsresult rv = ssm->CheckSameOriginURI(mLoadedURI, mUnloadedURI, false);
   if (NS_SUCCEEDED(rv)) {
-    *aStart = mUnloadStart;
+    return mUnloadStart;
   }
-  return NS_OK;
+  return 0;
 }
 
-nsresult
-nsDOMNavigationTiming::GetUnloadEventEnd(DOMTimeMilliSec* aEnd)
+DOMTimeMilliSec
+nsDOMNavigationTiming::GetUnloadEventEnd()
 {
-  *aEnd = 0;
   nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
   nsresult rv = ssm->CheckSameOriginURI(mLoadedURI, mUnloadedURI, false);
   if (NS_SUCCEEDED(rv)) {
-    *aEnd = mUnloadEnd;
+    return mUnloadEnd;
   }
-  return NS_OK;
-}
-
-nsresult
-nsDOMNavigationTiming::GetFetchStart(DOMTimeMilliSec* aStart)
-{
-  *aStart = mFetchStart;
-  return NS_OK;
-}
-
-nsresult
-nsDOMNavigationTiming::GetDomLoading(DOMTimeMilliSec* aTime)
-{
-  *aTime = mDOMLoading;
-  return NS_OK;
-}
-
-nsresult
-nsDOMNavigationTiming::GetDomInteractive(DOMTimeMilliSec* aTime)
-{
-  *aTime = mDOMInteractive;
-  return NS_OK;
+  return 0;
 }
 
-nsresult
-nsDOMNavigationTiming::GetDomContentLoadedEventStart(DOMTimeMilliSec* aStart)
-{
-  *aStart = mDOMContentLoadedEventStart;
-  return NS_OK;
-}
-
-nsresult
-nsDOMNavigationTiming::GetDomContentLoadedEventEnd(DOMTimeMilliSec* aEnd)
-{
-  *aEnd = mDOMContentLoadedEventEnd;
-  return NS_OK;
-}
-
-nsresult
-nsDOMNavigationTiming::GetDomComplete(DOMTimeMilliSec* aTime)
-{
-  *aTime = mDOMComplete;
-  return NS_OK;
-}
-
-nsresult
-nsDOMNavigationTiming::GetLoadEventStart(DOMTimeMilliSec* aStart)
-{
-  *aStart = mLoadEventStart;
-  return NS_OK;
-}
-
-nsresult
-nsDOMNavigationTiming::GetLoadEventEnd(DOMTimeMilliSec* aEnd)
-{
-  *aEnd = mLoadEventEnd;
-  return NS_OK;
-}
--- a/dom/base/nsDOMNavigationTiming.h
+++ b/dom/base/nsDOMNavigationTiming.h
@@ -17,32 +17,53 @@
 class nsDOMNavigationTimingClock;
 
 class nsDOMNavigationTiming
 {
 public:
   nsDOMNavigationTiming();
 
   NS_INLINE_DECL_REFCOUNTING(nsDOMNavigationTiming)
-  nsresult GetType(nsDOMPerformanceNavigationType* aNavigationType);
-  nsresult GetRedirectCount(PRUint16* aCount);
 
-  nsresult GetRedirectStart(DOMTimeMilliSec* aRedirectStart);
-  nsresult GetRedirectEnd(DOMTimeMilliSec* aEnd);
-  nsresult GetNavigationStart(DOMTimeMilliSec* aNavigationStart);
-  nsresult GetUnloadEventStart(DOMTimeMilliSec* aStart);
-  nsresult GetUnloadEventEnd(DOMTimeMilliSec* aEnd);
-  nsresult GetFetchStart(DOMTimeMilliSec* aStart);
-  nsresult GetDomLoading(DOMTimeMilliSec* aTime);
-  nsresult GetDomInteractive(DOMTimeMilliSec* aTime);
-  nsresult GetDomContentLoadedEventStart(DOMTimeMilliSec* aStart);
-  nsresult GetDomContentLoadedEventEnd(DOMTimeMilliSec* aEnd);
-  nsresult GetDomComplete(DOMTimeMilliSec* aTime);
-  nsresult GetLoadEventStart(DOMTimeMilliSec* aStart);
-  nsresult GetLoadEventEnd(DOMTimeMilliSec* aEnd);
+  nsDOMPerformanceNavigationType GetType() const {
+    return mNavigationType;
+  }
+  PRUint16 GetRedirectCount();
+
+  DOMTimeMilliSec GetRedirectStart();
+  DOMTimeMilliSec GetRedirectEnd();
+  DOMTimeMilliSec GetNavigationStart() const {
+    return mNavigationStart;
+  }
+  DOMTimeMilliSec GetUnloadEventStart();
+  DOMTimeMilliSec GetUnloadEventEnd();
+  DOMTimeMilliSec GetFetchStart() const {
+    return mFetchStart;
+  }
+  DOMTimeMilliSec GetDomLoading() const {
+    return mDOMLoading;
+  }
+  DOMTimeMilliSec GetDomInteractive() const {
+    return mDOMInteractive;
+  }
+  DOMTimeMilliSec GetDomContentLoadedEventStart() const {
+    return mDOMContentLoadedEventStart;
+  }
+  DOMTimeMilliSec GetDomContentLoadedEventEnd() const {
+    return mDOMContentLoadedEventEnd;
+  }
+  DOMTimeMilliSec GetDomComplete() const {
+    return mDOMComplete;
+  }
+  DOMTimeMilliSec GetLoadEventStart() const {
+    return mLoadEventStart;
+  }
+  DOMTimeMilliSec GetLoadEventEnd() const {
+    return mLoadEventEnd;
+  }
 
   void NotifyNavigationStart();
   void NotifyFetchStart(nsIURI* aURI, nsDOMPerformanceNavigationType aNavigationType);
   void NotifyRedirect(nsIURI* aOldURI, nsIURI* aNewURI);
   void NotifyBeforeUnload();
   void NotifyUnloadAccepted(nsIURI* aOldURI);
   void NotifyUnloadEventStart();
   void NotifyUnloadEventEnd();
@@ -51,19 +72,18 @@ public:
 
   // Document changes state to 'loading' before connecting to timing
   void SetDOMLoadingTimeStamp(nsIURI* aURI, mozilla::TimeStamp aValue);
   void NotifyDOMLoading(nsIURI* aURI);
   void NotifyDOMInteractive(nsIURI* aURI);
   void NotifyDOMComplete(nsIURI* aURI);
   void NotifyDOMContentLoadedStart(nsIURI* aURI);
   void NotifyDOMContentLoadedEnd(nsIURI* aURI);
-  nsresult TimeStampToDOM(mozilla::TimeStamp aStamp, DOMTimeMilliSec* aResult);
-  nsresult TimeStampToDOMOrFetchStart(mozilla::TimeStamp aStamp, 
-                                      DOMTimeMilliSec* aResult);
+  DOMTimeMilliSec TimeStampToDOM(mozilla::TimeStamp aStamp) const;
+  DOMTimeMilliSec TimeStampToDOMOrFetchStart(mozilla::TimeStamp aStamp) const;
 
   inline DOMHighResTimeStamp TimeStampToDOMHighRes(mozilla::TimeStamp aStamp)
   {
     mozilla::TimeDuration duration = aStamp - mNavigationStartTimeStamp;
     return duration.ToMilliseconds();
   }
 
 private:
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1251,16 +1251,18 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
   }
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContext)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mControllers)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mArguments)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mArgumentsLast)
 
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mPerformance, nsPerformance)
+
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mInnerWindowHolder)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOuterWindow)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOpenerScriptPrincipal)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mListenerManager,
                                                   nsEventListenerManager)
 
   for (nsTimeout* timeout = tmp->FirstTimeout();
@@ -1296,16 +1298,18 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
   nsGlobalWindow::CleanupCachedXBLHandlers(tmp);
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContext)
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mControllers)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mArguments)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mArgumentsLast)
 
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mPerformance)
+
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mInnerWindowHolder)
   if (tmp->mOuterWindow) {
     static_cast<nsGlobalWindow*>(tmp->mOuterWindow.get())->MaybeClearInnerWindow(tmp);
     NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOuterWindow)
   }
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOpenerScriptPrincipal)
   if (tmp->mListenerManager) {
@@ -2931,17 +2935,17 @@ nsGlobalWindow::GetPerformance(nsIDOMPer
       nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(mDoc->GetChannel()));
       bool timingEnabled = false;
       if (!timedChannel ||
           !NS_SUCCEEDED(timedChannel->GetTimingEnabled(&timingEnabled)) ||
           !timingEnabled) {
         timedChannel = nsnull;
       }
       if (timing) {
-        mPerformance = new nsPerformance(timing, timedChannel);
+        mPerformance = new nsPerformance(this, timing, timedChannel);
       }
     }
     NS_IF_ADDREF(*aPerformance = mPerformance);
   }
   return NS_OK;
 }
 
 /**
--- a/dom/base/nsPerformance.cpp
+++ b/dom/base/nsPerformance.cpp
@@ -6,290 +6,420 @@
 #include "nsPerformance.h"
 #include "TimeStamp.h"
 #include "nsCOMPtr.h"
 #include "nscore.h"
 #include "nsIDocShell.h"
 #include "nsITimedChannel.h"
 #include "nsDOMClassInfoID.h"
 #include "nsDOMNavigationTiming.h"
+#include "nsContentUtils.h"
+#include "nsIDOMWindow.h"
+#include "mozilla/dom/PerformanceBinding.h"
+#include "mozilla/dom/PerformanceTimingBinding.h"
+#include "mozilla/dom/PerformanceNavigationBinding.h"
+
+using namespace mozilla;
 
 DOMCI_DATA(PerformanceTiming, nsPerformanceTiming)
 
-NS_IMPL_ADDREF(nsPerformanceTiming)
-NS_IMPL_RELEASE(nsPerformanceTiming)
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(nsPerformanceTiming, mPerformance)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPerformanceTiming)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPerformanceTiming)
 
 // QueryInterface implementation for nsPerformanceTiming
-NS_INTERFACE_MAP_BEGIN(nsPerformanceTiming)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPerformanceTiming)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMPerformanceTiming)
   NS_INTERFACE_MAP_ENTRY(nsIDOMPerformanceTiming)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(PerformanceTiming)
 NS_INTERFACE_MAP_END
 
-nsPerformanceTiming::nsPerformanceTiming(nsDOMNavigationTiming* aDOMTiming, 
+nsPerformanceTiming::nsPerformanceTiming(nsPerformance* aPerformance,
                                          nsITimedChannel* aChannel)
+  : mPerformance(aPerformance),
+    mChannel(aChannel)
 {
-  NS_ASSERTION(aDOMTiming, "DOM timing data should be provided");
-  mDOMTiming = aDOMTiming;
-  mChannel = aChannel;  
+  MOZ_ASSERT(aPerformance, "Parent performance object should be provided");
+  SetIsDOMBinding();
 }
 
 nsPerformanceTiming::~nsPerformanceTiming()
 {
 }
 
 NS_IMETHODIMP
 nsPerformanceTiming::GetNavigationStart(DOMTimeMilliSec* aTime)
 {
-  return mDOMTiming->GetNavigationStart(aTime);
+  *aTime = GetNavigationStart();
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPerformanceTiming::GetUnloadEventStart(DOMTimeMilliSec* aTime)
 {
-  return mDOMTiming->GetUnloadEventStart(aTime);
+  *aTime = GetUnloadEventStart();
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPerformanceTiming::GetUnloadEventEnd(DOMTimeMilliSec* aTime)
 {
-  return mDOMTiming->GetUnloadEventEnd(aTime);
+  *aTime = GetUnloadEventEnd();
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPerformanceTiming::GetRedirectStart(DOMTimeMilliSec* aTime)
 {
-  return mDOMTiming->GetRedirectStart(aTime);
+  *aTime = GetRedirectStart();
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPerformanceTiming::GetRedirectEnd(DOMTimeMilliSec* aTime)
 {
-  return mDOMTiming->GetRedirectEnd(aTime);
+  *aTime = GetRedirectEnd();
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPerformanceTiming::GetFetchStart(DOMTimeMilliSec* aTime)
 {
-  return mDOMTiming->GetFetchStart(aTime);
+  *aTime = GetFetchStart();
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPerformanceTiming::GetDomainLookupStart(DOMTimeMilliSec* aTime)
 {
+  *aTime = GetDomainLookupStart();
+  return NS_OK;
+}
+
+DOMTimeMilliSec
+nsPerformanceTiming::GetDomainLookupStart() const
+{
   if (!mChannel) {
-    return GetFetchStart(aTime);
+    return GetFetchStart();
   }
   mozilla::TimeStamp stamp;
   mChannel->GetDomainLookupStart(&stamp);
-  return mDOMTiming->TimeStampToDOMOrFetchStart(stamp, aTime);
+  return GetDOMTiming()->TimeStampToDOMOrFetchStart(stamp);
 }
 
 NS_IMETHODIMP
 nsPerformanceTiming::GetDomainLookupEnd(DOMTimeMilliSec* aTime)
 {
+  *aTime = GetDomainLookupEnd();
+  return NS_OK;
+}
+
+DOMTimeMilliSec
+nsPerformanceTiming::GetDomainLookupEnd() const
+{
   if (!mChannel) {
-    return GetFetchStart(aTime);
+    return GetFetchStart();
   }
   mozilla::TimeStamp stamp;
   mChannel->GetDomainLookupEnd(&stamp);
-  return mDOMTiming->TimeStampToDOMOrFetchStart(stamp, aTime);
+  return GetDOMTiming()->TimeStampToDOMOrFetchStart(stamp);
 }
 
 NS_IMETHODIMP
 nsPerformanceTiming::GetConnectStart(DOMTimeMilliSec* aTime)
 {
+  *aTime = GetConnectStart();
+  return NS_OK;
+}
+
+DOMTimeMilliSec
+nsPerformanceTiming::GetConnectStart() const
+{
   if (!mChannel) {
-    return GetFetchStart(aTime);
+    return GetFetchStart();
   }
   mozilla::TimeStamp stamp;
   mChannel->GetConnectStart(&stamp);
-  return mDOMTiming->TimeStampToDOMOrFetchStart(stamp, aTime);
+  return GetDOMTiming()->TimeStampToDOMOrFetchStart(stamp);
 }
 
 NS_IMETHODIMP
 nsPerformanceTiming::GetConnectEnd(DOMTimeMilliSec* aTime)
 {
+  *aTime = GetConnectEnd();
+  return NS_OK;
+}
+
+DOMTimeMilliSec
+nsPerformanceTiming::GetConnectEnd() const
+{
   if (!mChannel) {
-    return GetFetchStart(aTime);
+    return GetFetchStart();
   }
   mozilla::TimeStamp stamp;
   mChannel->GetConnectEnd(&stamp);
-  return mDOMTiming->TimeStampToDOMOrFetchStart(stamp, aTime);
+  return GetDOMTiming()->TimeStampToDOMOrFetchStart(stamp);
 }
 
 NS_IMETHODIMP
 nsPerformanceTiming::GetRequestStart(DOMTimeMilliSec* aTime)
 {
+  *aTime = GetRequestStart();
+  return NS_OK;
+}
+
+DOMTimeMilliSec
+nsPerformanceTiming::GetRequestStart() const
+{
   if (!mChannel) {
-    return GetFetchStart(aTime);
+    return GetFetchStart();
   }
   mozilla::TimeStamp stamp;
   mChannel->GetRequestStart(&stamp);
-  return mDOMTiming->TimeStampToDOMOrFetchStart(stamp, aTime);
+  return GetDOMTiming()->TimeStampToDOMOrFetchStart(stamp);
 }
 
 NS_IMETHODIMP
 nsPerformanceTiming::GetResponseStart(DOMTimeMilliSec* aTime)
 {
+  *aTime = GetResponseStart();
+  return NS_OK;
+}
+
+DOMTimeMilliSec
+nsPerformanceTiming::GetResponseStart() const
+{
   if (!mChannel) {
-    return GetFetchStart(aTime);
+    return GetFetchStart();
   }
   mozilla::TimeStamp stamp;
   mChannel->GetResponseStart(&stamp);
   mozilla::TimeStamp cacheStamp;
   mChannel->GetCacheReadStart(&cacheStamp);
   if (stamp.IsNull() || (!cacheStamp.IsNull() && cacheStamp < stamp)) {
     stamp = cacheStamp;
   }
-  return mDOMTiming->TimeStampToDOMOrFetchStart(stamp, aTime);
+  return GetDOMTiming()->TimeStampToDOMOrFetchStart(stamp);
 }
 
 NS_IMETHODIMP
 nsPerformanceTiming::GetResponseEnd(DOMTimeMilliSec* aTime)
 {
+  *aTime = GetResponseEnd();
+  return NS_OK;
+}
+
+DOMTimeMilliSec
+nsPerformanceTiming::GetResponseEnd() const
+{
   if (!mChannel) {
-    return GetFetchStart(aTime);
+    return GetFetchStart();
   }
   mozilla::TimeStamp stamp;
   mChannel->GetResponseEnd(&stamp);
   mozilla::TimeStamp cacheStamp;
   mChannel->GetCacheReadEnd(&cacheStamp);
   if (stamp.IsNull() || (!cacheStamp.IsNull() && cacheStamp < stamp)) {
     stamp = cacheStamp;
   }
-  return mDOMTiming->TimeStampToDOMOrFetchStart(stamp, aTime);
+  return GetDOMTiming()->TimeStampToDOMOrFetchStart(stamp);
 }
 
 NS_IMETHODIMP
 nsPerformanceTiming::GetDomLoading(DOMTimeMilliSec* aTime)
 {
-  return mDOMTiming->GetDomLoading(aTime);
+  *aTime = GetDomLoading();
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPerformanceTiming::GetDomInteractive(DOMTimeMilliSec* aTime)
 {
-  return mDOMTiming->GetDomInteractive(aTime);
+  *aTime = GetDomInteractive();
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPerformanceTiming::GetDomContentLoadedEventStart(DOMTimeMilliSec* aTime)
 {
-  return mDOMTiming->GetDomContentLoadedEventStart(aTime);
+  *aTime = GetDomContentLoadedEventStart();
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPerformanceTiming::GetDomContentLoadedEventEnd(DOMTimeMilliSec* aTime)
 {
-  return mDOMTiming->GetDomContentLoadedEventEnd(aTime);
+  *aTime = GetDomContentLoadedEventEnd();
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPerformanceTiming::GetDomComplete(DOMTimeMilliSec* aTime)
 {
-  return mDOMTiming->GetDomComplete(aTime);
+  *aTime = GetDomComplete();
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPerformanceTiming::GetLoadEventStart(DOMTimeMilliSec* aTime)
 {
-  return mDOMTiming->GetLoadEventStart(aTime);
+  *aTime = GetLoadEventStart();
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPerformanceTiming::GetLoadEventEnd(DOMTimeMilliSec* aTime)
 {
-  return mDOMTiming->GetLoadEventEnd(aTime);
+  *aTime = GetLoadEventEnd();
+  return NS_OK;
+}
+
+JSObject*
+nsPerformanceTiming::WrapObject(JSContext *cx, JSObject *scope,
+                                bool *triedToWrap)
+{
+  return dom::PerformanceTimingBinding::Wrap(cx, scope, this,
+                                             triedToWrap);
 }
 
 
 
 DOMCI_DATA(PerformanceNavigation, nsPerformanceNavigation)
 
-NS_IMPL_ADDREF(nsPerformanceNavigation)
-NS_IMPL_RELEASE(nsPerformanceNavigation)
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(nsPerformanceNavigation, mPerformance)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPerformanceNavigation)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPerformanceNavigation)
 
 // QueryInterface implementation for nsPerformanceNavigation
-NS_INTERFACE_MAP_BEGIN(nsPerformanceNavigation)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPerformanceNavigation)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMPerformanceNavigation)
   NS_INTERFACE_MAP_ENTRY(nsIDOMPerformanceNavigation)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(PerformanceNavigation)
 NS_INTERFACE_MAP_END
 
-nsPerformanceNavigation::nsPerformanceNavigation(nsDOMNavigationTiming* aData)
+nsPerformanceNavigation::nsPerformanceNavigation(nsPerformance* aPerformance)
+  : mPerformance(aPerformance)
 {
-  NS_ASSERTION(aData, "Timing data should be provided");
-  mData = aData;
+  MOZ_ASSERT(aPerformance, "Parent performance object should be provided");
+  SetIsDOMBinding();
 }
 
 nsPerformanceNavigation::~nsPerformanceNavigation()
 {
 }
 
 NS_IMETHODIMP
 nsPerformanceNavigation::GetType(
     nsDOMPerformanceNavigationType* aNavigationType)
 {
-  return mData->GetType(aNavigationType);
+  *aNavigationType = GetType();
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPerformanceNavigation::GetRedirectCount(PRUint16* aRedirectCount)
 {
-  return mData->GetRedirectCount(aRedirectCount);
+  *aRedirectCount = GetRedirectCount();
+  return NS_OK;
+}
+
+JSObject*
+nsPerformanceNavigation::WrapObject(JSContext *cx, JSObject *scope,
+                                    bool *triedToWrap)
+{
+  return dom::PerformanceNavigationBinding::Wrap(cx, scope, this,
+                                                 triedToWrap);
 }
 
 
 DOMCI_DATA(Performance, nsPerformance)
 
-NS_IMPL_ADDREF(nsPerformance)
-NS_IMPL_RELEASE(nsPerformance)
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_3(nsPerformance,
+                                        mWindow, mTiming,
+                                        mNavigation)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPerformance)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPerformance)
 
-nsPerformance::nsPerformance(nsDOMNavigationTiming* aDOMTiming, 
+nsPerformance::nsPerformance(nsIDOMWindow* aWindow,
+                             nsDOMNavigationTiming* aDOMTiming,
                              nsITimedChannel* aChannel)
+  : mWindow(aWindow),
+    mDOMTiming(aDOMTiming),
+    mChannel(aChannel)
 {
-  NS_ASSERTION(aDOMTiming, "DOM timing data should be provided");
-  mDOMTiming = aDOMTiming;
-  mChannel = aChannel;  
+  MOZ_ASSERT(aWindow, "Parent window object should be provided");
+  SetIsDOMBinding();
 }
 
 nsPerformance::~nsPerformance()
 {
 }
 
 // QueryInterface implementation for nsPerformance
-NS_INTERFACE_MAP_BEGIN(nsPerformance)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPerformance)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMPerformance)
   NS_INTERFACE_MAP_ENTRY(nsIDOMPerformance)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Performance)
 NS_INTERFACE_MAP_END
 
+
 //
 // nsIDOMPerformance methods
 //
+
+nsPerformanceTiming*
+nsPerformance::GetTiming()
+{
+  if (!mTiming) {
+    mTiming = new nsPerformanceTiming(this, mChannel);
+  }
+  return mTiming;
+}
+
 NS_IMETHODIMP
 nsPerformance::GetTiming(nsIDOMPerformanceTiming** aTiming)
 {
-  if (!mTiming) {
-    mTiming = new nsPerformanceTiming(mDOMTiming, mChannel);
+  nsRefPtr<nsPerformanceTiming> timing = GetTiming();
+  timing.forget(aTiming);
+  return NS_OK;
+}
+
+nsPerformanceNavigation*
+nsPerformance::GetNavigation()
+{
+  if (!mNavigation) {
+    mNavigation = new nsPerformanceNavigation(this);
   }
-  NS_IF_ADDREF(*aTiming = mTiming);
-  return NS_OK;
+  return mNavigation;
 }
 
 NS_IMETHODIMP
 nsPerformance::GetNavigation(nsIDOMPerformanceNavigation** aNavigation)
 {
-  if (!mNavigation) {
-    mNavigation = new nsPerformanceNavigation(mDOMTiming);
-  }
-  NS_IF_ADDREF(*aNavigation = mNavigation);
+  nsRefPtr<nsPerformanceNavigation> navigation = GetNavigation();
+  navigation.forget(aNavigation);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPerformance::Now(DOMHighResTimeStamp* aNow)
 {
-  *aNow = mDOMTiming->TimeStampToDOMHighRes(mozilla::TimeStamp::Now());
+  *aNow = Now();
   return NS_OK;
 }
 
+DOMHighResTimeStamp
+nsPerformance::Now()
+{
+  return GetDOMTiming()->TimeStampToDOMHighRes(mozilla::TimeStamp::Now());
+}
+
+JSObject*
+nsPerformance::WrapObject(JSContext *cx, JSObject *scope,
+                          bool *triedToWrap)
+{
+  return dom::PerformanceBinding::Wrap(cx, scope, this,
+                                       triedToWrap);
+}
+
--- a/dom/base/nsPerformance.h
+++ b/dom/base/nsPerformance.h
@@ -7,58 +7,177 @@
 
 #include "nsIDOMPerformance.h"
 #include "nsIDOMPerformanceTiming.h"
 #include "nsIDOMPerformanceNavigation.h"
 #include "nscore.h"
 #include "nsCOMPtr.h"
 #include "nsAutoPtr.h"
 #include "mozilla/Attributes.h"
+#include "nsWrapperCache.h"
+#include "nsDOMNavigationTiming.h"
 
 class nsIURI;
-class nsDOMNavigationTiming;
 class nsITimedChannel;
+class nsPerformance;
+struct JSObject;
+struct JSContext;
 
 // Script "performance.timing" object
-class nsPerformanceTiming MOZ_FINAL : public nsIDOMPerformanceTiming
+class nsPerformanceTiming MOZ_FINAL : public nsIDOMPerformanceTiming,
+                                      public nsWrapperCache
 {
 public:
-  nsPerformanceTiming(nsDOMNavigationTiming* aDOMTiming, nsITimedChannel* aChannel);
-  NS_DECL_ISUPPORTS
+  nsPerformanceTiming(nsPerformance* aPerformance,
+                      nsITimedChannel* aChannel);
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_NSIDOMPERFORMANCETIMING
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsPerformanceTiming)
+
+  nsDOMNavigationTiming* GetDOMTiming() const;
+
+  nsPerformance* GetParentObject() const
+  {
+    return mPerformance;
+  }
+
+  JSObject* WrapObject(JSContext *cx, JSObject *scope, bool *triedToWrap);
+
+  // PerformanceNavigation WebIDL methods
+  DOMTimeMilliSec GetNavigationStart() const {
+    return GetDOMTiming()->GetNavigationStart();
+  }
+  DOMTimeMilliSec GetUnloadEventStart() {
+    return GetDOMTiming()->GetUnloadEventStart();
+  }
+  DOMTimeMilliSec GetUnloadEventEnd() {
+    return GetDOMTiming()->GetUnloadEventEnd();
+  }
+  DOMTimeMilliSec GetRedirectStart() {
+    return GetDOMTiming()->GetRedirectStart();
+  }
+  DOMTimeMilliSec GetRedirectEnd() {
+    return GetDOMTiming()->GetRedirectEnd();
+  }
+  DOMTimeMilliSec GetFetchStart() const {
+    return GetDOMTiming()->GetFetchStart();
+  }
+  DOMTimeMilliSec GetDomainLookupStart() const;
+  DOMTimeMilliSec GetDomainLookupEnd() const;
+  DOMTimeMilliSec GetConnectStart() const;
+  DOMTimeMilliSec GetConnectEnd() const;
+  DOMTimeMilliSec GetRequestStart() const;
+  DOMTimeMilliSec GetResponseStart() const;
+  DOMTimeMilliSec GetResponseEnd() const;
+  DOMTimeMilliSec GetDomLoading() const {
+    return GetDOMTiming()->GetDomLoading();
+  }
+  DOMTimeMilliSec GetDomInteractive() const {
+    return GetDOMTiming()->GetDomInteractive();
+  }
+  DOMTimeMilliSec GetDomContentLoadedEventStart() const {
+    return GetDOMTiming()->GetDomContentLoadedEventStart();
+  }
+  DOMTimeMilliSec GetDomContentLoadedEventEnd() const {
+    return GetDOMTiming()->GetDomContentLoadedEventEnd();
+  }
+  DOMTimeMilliSec GetDomComplete() const {
+    return GetDOMTiming()->GetDomComplete();
+  }
+  DOMTimeMilliSec GetLoadEventStart() const {
+    return GetDOMTiming()->GetLoadEventStart();
+  }
+  DOMTimeMilliSec GetLoadEventEnd() const {
+    return GetDOMTiming()->GetLoadEventEnd();
+  }
+
 private:
   ~nsPerformanceTiming();
-  nsRefPtr<nsDOMNavigationTiming> mDOMTiming;
+  nsRefPtr<nsPerformance> mPerformance;
   nsCOMPtr<nsITimedChannel> mChannel;
 };
 
 // Script "performance.navigation" object
-class nsPerformanceNavigation MOZ_FINAL : public nsIDOMPerformanceNavigation
+class nsPerformanceNavigation MOZ_FINAL : public nsIDOMPerformanceNavigation,
+                                          public nsWrapperCache
 {
 public:
-  nsPerformanceNavigation(nsDOMNavigationTiming* data);
-  NS_DECL_ISUPPORTS
+  explicit nsPerformanceNavigation(nsPerformance* aPerformance);
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_NSIDOMPERFORMANCENAVIGATION
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsPerformanceNavigation)
+
+  nsDOMNavigationTiming* GetDOMTiming() const;
+
+  nsPerformance* GetParentObject() const
+  {
+    return mPerformance;
+  }
+
+  JSObject* WrapObject(JSContext *cx, JSObject *scope, bool *triedToWrap);
+
+  // PerformanceNavigation WebIDL methods
+  PRUint16 GetType() const {
+    return GetDOMTiming()->GetType();
+  }
+  PRUint16 GetRedirectCount() const {
+    return GetDOMTiming()->GetRedirectCount();
+  }
+
 private:
   ~nsPerformanceNavigation();
-  nsRefPtr<nsDOMNavigationTiming> mData;
+  nsRefPtr<nsPerformance> mPerformance;
 };
 
 // Script "performance" object
-class nsPerformance MOZ_FINAL : public nsIDOMPerformance
+class nsPerformance MOZ_FINAL : public nsIDOMPerformance,
+                                public nsWrapperCache
 {
 public:
-  nsPerformance(nsDOMNavigationTiming* aDOMTiming, nsITimedChannel* aChannel);
+  nsPerformance(nsIDOMWindow* aWindow,
+                nsDOMNavigationTiming* aDOMTiming,
+                nsITimedChannel* aChannel);
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_NSIDOMPERFORMANCE
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsPerformance)
+
+  nsDOMNavigationTiming* GetDOMTiming() const
+  {
+    return mDOMTiming;
+  }
+
+  nsIDOMWindow* GetParentObject() const
+  {
+    return mWindow.get();
+  }
+
+  JSObject* WrapObject(JSContext *cx, JSObject *scope, bool *triedToWrap);
+
+  // Performance WebIDL methods
+  DOMHighResTimeStamp Now();
+  nsPerformanceTiming* GetTiming();
+  nsPerformanceNavigation* GetNavigation();
 
 private:
   ~nsPerformance();
 
+  nsCOMPtr<nsIDOMWindow> mWindow;
   nsRefPtr<nsDOMNavigationTiming> mDOMTiming;
   nsCOMPtr<nsITimedChannel> mChannel;
-  nsCOMPtr<nsIDOMPerformanceTiming> mTiming;
-  nsCOMPtr<nsIDOMPerformanceNavigation> mNavigation;
+  nsRefPtr<nsPerformanceTiming> mTiming;
+  nsRefPtr<nsPerformanceNavigation> mNavigation;
 };
 
+inline nsDOMNavigationTiming*
+nsPerformanceNavigation::GetDOMTiming() const
+{
+  return mPerformance->GetDOMTiming();
+}
+
+inline nsDOMNavigationTiming*
+nsPerformanceTiming::GetDOMTiming() const
+{
+  return mPerformance->GetDOMTiming();
+}
+
 #endif /* nsPerformance_h___ */
 
--- a/dom/base/nsWrapperCache.h
+++ b/dom/base/nsWrapperCache.h
@@ -259,9 +259,27 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsWrapperC
   NS_IMPL_CYCLE_COLLECTION_UNLINK_END                           \
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class)               \
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(_field1)         \
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(_field2)         \
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS            \
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END                         \
   NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(_class)
 
+#define NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_3(_class, _field1,\
+                                                _field2,        \
+                                                _field3)        \
+  NS_IMPL_CYCLE_COLLECTION_CLASS(_class)                        \
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class)                 \
+    NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(_field1)           \
+    NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(_field2)           \
+    NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(_field3)           \
+    NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER           \
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_END                           \
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class)               \
+    NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(_field1)         \
+    NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(_field2)         \
+    NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(_field3)         \
+    NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS            \
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END                         \
+  NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(_class)
+
 #endif /* nsWrapperCache_h___ */
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -183,16 +183,31 @@ DOMInterfaces = {
 },
 {
     'workers': True,
     'nativeType': 'JSObject',
     'headerFile': 'jsapi.h',
     'castable': False
 }],
 
+'Performance': {
+    'nativeType': 'nsPerformance',
+    'resultNotAddRefed': [ 'timing', 'navigation' ]
+},
+
+'PerformanceTiming': {
+    'nativeType': 'nsPerformanceTiming',
+    'headerFile': 'nsPerformance.h'
+},
+
+'PerformanceNavigation': {
+    'nativeType': 'nsPerformanceNavigation',
+    'headerFile': 'nsPerformance.h'
+},
+
 'WebGLRenderingContext': {
   'nativeType': 'mozilla::WebGLContext',
   'headerFile': 'WebGLContext.h',
   'prefable': True,
   'resultNotAddRefed': [ 'canvas', 'getContextAttributes', 'getExtension',
                          'getAttachedShaders' ],
   'implicitJSContext': [ 'texImage2D', 'texSubImage2D' ],
 },
new file mode 100644
--- /dev/null
+++ b/dom/webidl/Performance.webidl
@@ -0,0 +1,24 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/.
+ *
+ * The origin of this IDL file is
+ * http://www.w3.org/TR/hr-time/
+ *
+ * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
+ * liability, trademark and document use rules apply.
+ */
+
+// typedef double DOMHighResTimeStamp;
+
+interface Performance {
+  // DOMHighResTimeStamp now();
+  [Infallible]
+  double now();
+
+  [Infallible]
+  readonly attribute PerformanceTiming timing;
+  [Infallible]
+  readonly attribute PerformanceNavigation navigation;
+};
new file mode 100644
--- /dev/null
+++ b/dom/webidl/PerformanceNavigation.webidl
@@ -0,0 +1,22 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/.
+ *
+ * The origin of this IDL file is
+ * http://www.w3.org/TR/hr-time/
+ *
+ * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
+ * liability, trademark and document use rules apply.
+ */
+
+interface PerformanceNavigation {
+  const unsigned short TYPE_NAVIGATE = 0;
+  const unsigned short TYPE_RELOAD = 1;
+  const unsigned short TYPE_BACK_FORWARD = 2;
+  const unsigned short TYPE_RESERVED = 255;
+  [Infallible]
+  readonly attribute unsigned short type;
+  [Infallible]
+  readonly attribute unsigned short redirectCount;
+};
new file mode 100644
--- /dev/null
+++ b/dom/webidl/PerformanceTiming.webidl
@@ -0,0 +1,56 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/.
+ *
+ * The origin of this IDL file is
+ * http://www.w3.org/TR/hr-time/
+ *
+ * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
+ * liability, trademark and document use rules apply.
+ */
+
+interface PerformanceTiming {
+  [Infallible]
+  readonly attribute unsigned long long navigationStart;
+  [Infallible]
+  readonly attribute unsigned long long unloadEventStart;
+  [Infallible]
+  readonly attribute unsigned long long unloadEventEnd;
+  [Infallible]
+  readonly attribute unsigned long long redirectStart;
+  [Infallible]
+  readonly attribute unsigned long long redirectEnd;
+  [Infallible]
+  readonly attribute unsigned long long fetchStart;
+  [Infallible]
+  readonly attribute unsigned long long domainLookupStart;
+  [Infallible]
+  readonly attribute unsigned long long domainLookupEnd;
+  [Infallible]
+  readonly attribute unsigned long long connectStart;
+  [Infallible]
+  readonly attribute unsigned long long connectEnd;
+  // [Infallible]
+  // readonly attribute unsigned long long secureConnectionStart;
+  [Infallible]
+  readonly attribute unsigned long long requestStart;
+  [Infallible]
+  readonly attribute unsigned long long responseStart;
+  [Infallible]
+  readonly attribute unsigned long long responseEnd;
+  [Infallible]
+  readonly attribute unsigned long long domLoading;
+  [Infallible]
+  readonly attribute unsigned long long domInteractive;
+  [Infallible]
+  readonly attribute unsigned long long domContentLoadedEventStart;
+  [Infallible]
+  readonly attribute unsigned long long domContentLoadedEventEnd;
+  [Infallible]
+  readonly attribute unsigned long long domComplete;
+  [Infallible]
+  readonly attribute unsigned long long loadEventStart;
+  [Infallible]
+  readonly attribute unsigned long long loadEventEnd;
+};
--- a/dom/webidl/WebIDL.mk
+++ b/dom/webidl/WebIDL.mk
@@ -4,16 +4,19 @@
 
 webidl_base = $(topsrcdir)/dom/webidl
 
 webidl_files = \
   CanvasRenderingContext2D.webidl \
   Function.webidl \
   EventListener.webidl \
   EventTarget.webidl \
+  Performance.webidl \
+  PerformanceNavigation.webidl \
+  PerformanceTiming.webidl \
   XMLHttpRequest.webidl \
   XMLHttpRequestEventTarget.webidl \
   XMLHttpRequestUpload.webidl \
   $(NULL)
 
 ifdef MOZ_WEBGL
 webidl_files += \
   WebGLRenderingContext.webidl \
--- a/js/xpconnect/src/dom_quickstubs.qsconf
+++ b/js/xpconnect/src/dom_quickstubs.qsconf
@@ -454,21 +454,16 @@ members = [
     'nsIIDBObjectStore.*',
     'nsIIDBRequest.*',
     'nsIIDBTransaction.*',
     'nsIIDBOpenDBRequest.*',
     'nsIIDBVersionChangeEvent.*',
     'nsIIndexedDatabaseUsageCallback.*',
     'nsIIndexedDatabaseManager.*',
 
-    # Performance
-    'nsIDOMPerformance.*',
-    'nsIDOMPerformanceTiming.*',
-    'nsIDOMPerformanceNavigation.*',
-
     'nsIDOMDOMError.*',
 
     # dom/file
     'nsIDOMFileHandle.*',
     '-nsIDOMFileHandle.getFileId',
     '-nsIDOMFileHandle.getFileInfo',
     'nsIDOMFileRequest.*',
     'nsIDOMLockedFile.*',