LCOV - code coverage report
Current view: top level - dom/performance - PerformanceMainThread.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 53 157 33.8 %
Date: 2017-07-14 16:53:18 Functions: 8 19 42.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "PerformanceMainThread.h"
       8             : #include "PerformanceNavigation.h"
       9             : #include "nsICacheInfoChannel.h"
      10             : 
      11             : namespace mozilla {
      12             : namespace dom {
      13             : 
      14             : NS_IMPL_CYCLE_COLLECTION_CLASS(PerformanceMainThread)
      15             : 
      16           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PerformanceMainThread,
      17             :                                                 Performance)
      18           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK(mTiming,
      19             :                                 mNavigation)
      20           0 :   tmp->mMozMemory = nullptr;
      21           0 :   mozilla::DropJSObjects(this);
      22           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
      23             : 
      24           7 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PerformanceMainThread,
      25             :                                                   Performance)
      26           7 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTiming,
      27             :                                     mNavigation)
      28           7 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
      29             : 
      30          14 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(PerformanceMainThread,
      31             :                                                 Performance)
      32          14 :   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mMozMemory)
      33          14 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
      34             : 
      35          19 : NS_IMPL_ADDREF_INHERITED(PerformanceMainThread, Performance)
      36           2 : NS_IMPL_RELEASE_INHERITED(PerformanceMainThread, Performance)
      37             : 
      38             : // QueryInterface implementation for PerformanceMainThread
      39         126 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PerformanceMainThread)
      40           7 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
      41           0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
      42           0 : NS_INTERFACE_MAP_END_INHERITING(Performance)
      43             : 
      44           7 : PerformanceMainThread::PerformanceMainThread(nsPIDOMWindowInner* aWindow,
      45             :                                              nsDOMNavigationTiming* aDOMTiming,
      46           7 :                                              nsITimedChannel* aChannel)
      47             :   : Performance(aWindow)
      48             :   , mDOMTiming(aDOMTiming)
      49           7 :   , mChannel(aChannel)
      50             : {
      51           7 :   MOZ_ASSERT(aWindow, "Parent window object should be provided");
      52           7 : }
      53             : 
      54           0 : PerformanceMainThread::~PerformanceMainThread()
      55             : {
      56           0 :   mozilla::DropJSObjects(this);
      57           0 : }
      58             : 
      59             : void
      60           0 : PerformanceMainThread::GetMozMemory(JSContext *aCx,
      61             :                                     JS::MutableHandle<JSObject*> aObj)
      62             : {
      63           0 :   if (!mMozMemory) {
      64           0 :     mMozMemory = js::gc::NewMemoryInfoObject(aCx);
      65           0 :     if (mMozMemory) {
      66           0 :       mozilla::HoldJSObjects(this);
      67             :     }
      68             :   }
      69             : 
      70           0 :   aObj.set(mMozMemory);
      71           0 : }
      72             : 
      73             : PerformanceTiming*
      74           0 : PerformanceMainThread::Timing()
      75             : {
      76           0 :   if (!mTiming) {
      77             :     // For navigation timing, the third argument (an nsIHttpChannel) is null
      78             :     // since the cross-domain redirect were already checked.  The last argument
      79             :     // (zero time) for performance.timing is the navigation start value.
      80             :     mTiming = new PerformanceTiming(this, mChannel, nullptr,
      81           0 :                                     mDOMTiming->GetNavigationStart());
      82             :   }
      83             : 
      84           0 :   return mTiming;
      85             : }
      86             : 
      87             : void
      88           0 : PerformanceMainThread::DispatchBufferFullEvent()
      89             : {
      90           0 :   RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
      91             :   // it bubbles, and it isn't cancelable
      92           0 :   event->InitEvent(NS_LITERAL_STRING("resourcetimingbufferfull"), true, false);
      93           0 :   event->SetTrusted(true);
      94           0 :   DispatchDOMEvent(nullptr, event, nullptr, nullptr);
      95           0 : }
      96             : 
      97             : PerformanceNavigation*
      98           0 : PerformanceMainThread::Navigation()
      99             : {
     100           0 :   if (!mNavigation) {
     101           0 :     mNavigation = new PerformanceNavigation(this);
     102             :   }
     103             : 
     104           0 :   return mNavigation;
     105             : }
     106             : 
     107             : /**
     108             :  * An entry should be added only after the resource is loaded.
     109             :  * This method is not thread safe and can only be called on the main thread.
     110             :  */
     111             : void
     112           2 : PerformanceMainThread::AddEntry(nsIHttpChannel* channel,
     113             :                                 nsITimedChannel* timedChannel)
     114             : {
     115           2 :   MOZ_ASSERT(NS_IsMainThread());
     116             : 
     117             :   // Check if resource timing is prefed off.
     118           2 :   if (!nsContentUtils::IsResourceTimingEnabled()) {
     119           0 :     return;
     120             :   }
     121             : 
     122             :   // Don't add the entry if the buffer is full
     123           2 :   if (IsResourceEntryLimitReached()) {
     124           0 :     return;
     125             :   }
     126             : 
     127           2 :   if (channel && timedChannel) {
     128           4 :     nsAutoCString name;
     129           4 :     nsAutoString initiatorType;
     130           4 :     nsCOMPtr<nsIURI> originalURI;
     131             : 
     132           2 :     timedChannel->GetInitiatorType(initiatorType);
     133             : 
     134             :     // According to the spec, "The name attribute must return the resolved URL
     135             :     // of the requested resource. This attribute must not change even if the
     136             :     // fetch redirected to a different URL."
     137           2 :     channel->GetOriginalURI(getter_AddRefs(originalURI));
     138           2 :     originalURI->GetSpec(name);
     139           4 :     NS_ConvertUTF8toUTF16 entryName(name);
     140             : 
     141             :     // The nsITimedChannel argument will be used to gather all the timings.
     142             :     // The nsIHttpChannel argument will be used to check if any cross-origin
     143             :     // redirects occurred.
     144             :     // The last argument is the "zero time" (offset). Since we don't want
     145             :     // any offset for the resource timing, this will be set to "0" - the
     146             :     // resource timing returns a relative timing (no offset).
     147             :     RefPtr<PerformanceTiming> performanceTiming =
     148             :         new PerformanceTiming(this, timedChannel, channel,
     149           4 :             0);
     150             : 
     151             :     // The PerformanceResourceTiming object will use the PerformanceTiming
     152             :     // object to get all the required timings.
     153             :     RefPtr<PerformanceResourceTiming> performanceEntry =
     154           6 :       new PerformanceResourceTiming(performanceTiming, this, entryName);
     155             : 
     156           4 :     nsAutoCString protocol;
     157             :     // Can be an empty string.
     158           2 :     Unused << channel->GetProtocolVersion(protocol);
     159             : 
     160             :     // If this is a local fetch, nextHopProtocol should be set to empty string.
     161           4 :     nsCOMPtr<nsICacheInfoChannel> cachedChannel = do_QueryInterface(channel);
     162           2 :     if (cachedChannel) {
     163             :       bool isFromCache;
     164           4 :       if (NS_SUCCEEDED(cachedChannel->IsFromCache(&isFromCache))
     165           2 :           && isFromCache) {
     166           2 :         protocol.Truncate();
     167             :       }
     168             :     }
     169             : 
     170           2 :     performanceEntry->SetNextHopProtocol(NS_ConvertUTF8toUTF16(protocol));
     171             : 
     172           2 :     uint64_t encodedBodySize = 0;
     173           2 :     Unused << channel->GetEncodedBodySize(&encodedBodySize);
     174           2 :     performanceEntry->SetEncodedBodySize(encodedBodySize);
     175             : 
     176           2 :     uint64_t transferSize = 0;
     177           2 :     Unused << channel->GetTransferSize(&transferSize);
     178           2 :     performanceEntry->SetTransferSize(transferSize);
     179             : 
     180           2 :     uint64_t decodedBodySize = 0;
     181           2 :     Unused << channel->GetDecodedBodySize(&decodedBodySize);
     182           2 :     if (decodedBodySize == 0) {
     183           2 :       decodedBodySize = encodedBodySize;
     184             :     }
     185           2 :     performanceEntry->SetDecodedBodySize(decodedBodySize);
     186             : 
     187             :     // If the initiator type had no valid value, then set it to the default
     188             :     // ("other") value.
     189           2 :     if (initiatorType.IsEmpty()) {
     190           0 :       initiatorType = NS_LITERAL_STRING("other");
     191             :     }
     192           2 :     performanceEntry->SetInitiatorType(initiatorType);
     193           2 :     InsertResourceEntry(performanceEntry);
     194             :   }
     195             : }
     196             : 
     197             : // To be removed once bug 1124165 lands
     198             : bool
     199           0 : PerformanceMainThread::IsPerformanceTimingAttribute(const nsAString& aName)
     200             : {
     201             :   // Note that toJSON is added to this list due to bug 1047848
     202             :   static const char* attributes[] =
     203             :     {"navigationStart", "unloadEventStart", "unloadEventEnd", "redirectStart",
     204             :      "redirectEnd", "fetchStart", "domainLookupStart", "domainLookupEnd",
     205             :      "connectStart", "connectEnd", "requestStart", "responseStart",
     206             :      "responseEnd", "domLoading", "domInteractive",
     207             :      "domContentLoadedEventStart", "domContentLoadedEventEnd", "domComplete",
     208             :      "loadEventStart", "loadEventEnd", nullptr};
     209             : 
     210           0 :   for (uint32_t i = 0; attributes[i]; ++i) {
     211           0 :     if (aName.EqualsASCII(attributes[i])) {
     212           0 :       return true;
     213             :     }
     214             :   }
     215             : 
     216           0 :   return false;
     217             : }
     218             : 
     219             : DOMHighResTimeStamp
     220           0 : PerformanceMainThread::GetPerformanceTimingFromString(const nsAString& aProperty)
     221             : {
     222           0 :   if (!IsPerformanceTimingAttribute(aProperty)) {
     223           0 :     return 0;
     224             :   }
     225           0 :   if (aProperty.EqualsLiteral("navigationStart")) {
     226             :     // DOMHighResTimeStamp is in relation to navigationStart, so this will be
     227             :     // zero.
     228           0 :     return GetDOMTiming()->GetNavigationStart();
     229             :   }
     230           0 :   if (aProperty.EqualsLiteral("unloadEventStart")) {
     231           0 :     return GetDOMTiming()->GetUnloadEventStart();
     232             :   }
     233           0 :   if (aProperty.EqualsLiteral("unloadEventEnd")) {
     234           0 :     return GetDOMTiming()->GetUnloadEventEnd();
     235             :   }
     236           0 :   if (aProperty.EqualsLiteral("redirectStart")) {
     237           0 :     return Timing()->RedirectStart();
     238             :   }
     239           0 :   if (aProperty.EqualsLiteral("redirectEnd")) {
     240           0 :     return Timing()->RedirectEnd();
     241             :   }
     242           0 :   if (aProperty.EqualsLiteral("fetchStart")) {
     243           0 :     return Timing()->FetchStart();
     244             :   }
     245           0 :   if (aProperty.EqualsLiteral("domainLookupStart")) {
     246           0 :     return Timing()->DomainLookupStart();
     247             :   }
     248           0 :   if (aProperty.EqualsLiteral("domainLookupEnd")) {
     249           0 :     return Timing()->DomainLookupEnd();
     250             :   }
     251           0 :   if (aProperty.EqualsLiteral("connectStart")) {
     252           0 :     return Timing()->ConnectStart();
     253             :   }
     254           0 :   if (aProperty.EqualsLiteral("connectEnd")) {
     255           0 :     return Timing()->ConnectEnd();
     256             :   }
     257           0 :   if (aProperty.EqualsLiteral("requestStart")) {
     258           0 :     return Timing()->RequestStart();
     259             :   }
     260           0 :   if (aProperty.EqualsLiteral("responseStart")) {
     261           0 :     return Timing()->ResponseStart();
     262             :   }
     263           0 :   if (aProperty.EqualsLiteral("responseEnd")) {
     264           0 :     return Timing()->ResponseEnd();
     265             :   }
     266           0 :   if (aProperty.EqualsLiteral("domLoading")) {
     267           0 :     return GetDOMTiming()->GetDomLoading();
     268             :   }
     269           0 :   if (aProperty.EqualsLiteral("domInteractive")) {
     270           0 :     return GetDOMTiming()->GetDomInteractive();
     271             :   }
     272           0 :   if (aProperty.EqualsLiteral("domContentLoadedEventStart")) {
     273           0 :     return GetDOMTiming()->GetDomContentLoadedEventStart();
     274             :   }
     275           0 :   if (aProperty.EqualsLiteral("domContentLoadedEventEnd")) {
     276           0 :     return GetDOMTiming()->GetDomContentLoadedEventEnd();
     277             :   }
     278           0 :   if (aProperty.EqualsLiteral("domComplete")) {
     279           0 :     return GetDOMTiming()->GetDomComplete();
     280             :   }
     281           0 :   if (aProperty.EqualsLiteral("loadEventStart")) {
     282           0 :     return GetDOMTiming()->GetLoadEventStart();
     283             :   }
     284           0 :   if (aProperty.EqualsLiteral("loadEventEnd"))  {
     285           0 :     return GetDOMTiming()->GetLoadEventEnd();
     286             :   }
     287           0 :   MOZ_CRASH("IsPerformanceTimingAttribute and GetPerformanceTimingFromString are out of sync");
     288             :   return 0;
     289             : }
     290             : 
     291             : void
     292           0 : PerformanceMainThread::InsertUserEntry(PerformanceEntry* aEntry)
     293             : {
     294           0 :   MOZ_ASSERT(NS_IsMainThread());
     295             : 
     296           0 :   nsAutoCString uri;
     297           0 :   uint64_t markCreationEpoch = 0;
     298             : 
     299           0 :   if (nsContentUtils::IsUserTimingLoggingEnabled() ||
     300           0 :       nsContentUtils::SendPerformanceTimingNotifications()) {
     301           0 :     nsresult rv = NS_ERROR_FAILURE;
     302           0 :     nsCOMPtr<nsPIDOMWindowInner> owner = GetOwner();
     303           0 :     if (owner && owner->GetDocumentURI()) {
     304           0 :       rv = owner->GetDocumentURI()->GetHost(uri);
     305             :     }
     306             : 
     307           0 :     if(NS_FAILED(rv)) {
     308             :       // If we have no URI, just put in "none".
     309           0 :       uri.AssignLiteral("none");
     310             :     }
     311           0 :     markCreationEpoch = static_cast<uint64_t>(PR_Now() / PR_USEC_PER_MSEC);
     312             : 
     313           0 :     if (nsContentUtils::IsUserTimingLoggingEnabled()) {
     314           0 :       Performance::LogEntry(aEntry, uri);
     315             :     }
     316             :   }
     317             : 
     318           0 :   if (nsContentUtils::SendPerformanceTimingNotifications()) {
     319           0 :     TimingNotification(aEntry, uri, markCreationEpoch);
     320             :   }
     321             : 
     322           0 :   Performance::InsertUserEntry(aEntry);
     323           0 : }
     324             : 
     325             : TimeStamp
     326          58 : PerformanceMainThread::CreationTimeStamp() const
     327             : {
     328          58 :   return GetDOMTiming()->GetNavigationStartTimeStamp();
     329             : }
     330             : 
     331             : DOMHighResTimeStamp
     332           0 : PerformanceMainThread::CreationTime() const
     333             : {
     334           0 :   return GetDOMTiming()->GetNavigationStart();
     335             : }
     336             : 
     337             : } // dom namespace
     338             : } // mozilla namespace

Generated by: LCOV version 1.13