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
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 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);
+
+  nsDOMPerformanceNavigationType GetType() const {
+    return mNavigationType;
+  }
+  PRUint16 GetRedirectCount();
 
-  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);
+  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_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_NSIDOMPERFORMANCE
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsPerformance)
 
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIDOMPERFORMANCE
+  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.*',