tools/profiler/nsProfiler.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include <string>
     7 #include <sstream>
     8 #ifdef MOZ_INSTRUMENT_EVENT_LOOP
     9 #include "EventTracer.h"
    10 #endif
    11 #include "GeckoProfiler.h"
    12 #include "nsProfiler.h"
    13 #include "nsMemory.h"
    14 #include "nsString.h"
    15 #include "mozilla/Services.h"
    16 #include "nsIObserverService.h"
    17 #include "nsIInterfaceRequestor.h"
    18 #include "nsILoadContext.h"
    19 #include "nsIWebNavigation.h"
    20 #include "nsIInterfaceRequestorUtils.h"
    21 #include "shared-libraries.h"
    22 #include "js/Value.h"
    24 using std::string;
    26 NS_IMPL_ISUPPORTS(nsProfiler, nsIProfiler)
    28 nsProfiler::nsProfiler()
    29   : mLockedForPrivateBrowsing(false)
    30 {
    31 }
    33 nsProfiler::~nsProfiler()
    34 {
    35   nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
    36   if (observerService) {
    37     observerService->RemoveObserver(this, "chrome-document-global-created");
    38     observerService->RemoveObserver(this, "last-pb-context-exited");
    39   }
    40 }
    42 nsresult
    43 nsProfiler::Init() {
    44   nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
    45   if (observerService) {
    46     observerService->AddObserver(this, "chrome-document-global-created", false);
    47     observerService->AddObserver(this, "last-pb-context-exited", false);
    48   }
    49   return NS_OK;
    50 }
    52 NS_IMETHODIMP
    53 nsProfiler::Observe(nsISupports *aSubject,
    54                     const char *aTopic,
    55                     const char16_t *aData)
    56 {
    57   if (strcmp(aTopic, "chrome-document-global-created") == 0) {
    58     nsCOMPtr<nsIInterfaceRequestor> requestor = do_QueryInterface(aSubject);
    59     nsCOMPtr<nsIWebNavigation> parentWebNav = do_GetInterface(requestor);
    60     nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(parentWebNav);
    61     if (loadContext && loadContext->UsePrivateBrowsing() && !mLockedForPrivateBrowsing) {
    62       mLockedForPrivateBrowsing = true;
    63       profiler_lock();
    64     }
    65   } else if (strcmp(aTopic, "last-pb-context-exited") == 0) {
    66     mLockedForPrivateBrowsing = false;
    67     profiler_unlock();
    68   }
    69   return NS_OK;
    70 }
    72 NS_IMETHODIMP
    73 nsProfiler::StartProfiler(uint32_t aEntries, double aInterval,
    74                           const char** aFeatures, uint32_t aFeatureCount,
    75                           const char** aThreadNameFilters, uint32_t aFilterCount)
    76 {
    77   if (mLockedForPrivateBrowsing) {
    78     return NS_ERROR_NOT_AVAILABLE;
    79   }
    81   profiler_start(aEntries, aInterval,
    82                  aFeatures, aFeatureCount,
    83                  aThreadNameFilters, aFilterCount);
    84 #ifdef MOZ_INSTRUMENT_EVENT_LOOP
    85   bool printToConsole = false;
    86   mozilla::InitEventTracing(printToConsole);
    87 #endif
    88   return NS_OK;
    89 }
    91 NS_IMETHODIMP
    92 nsProfiler::StopProfiler()
    93 {
    94   profiler_stop();
    95   return NS_OK;
    96 }
    98 NS_IMETHODIMP
    99 nsProfiler::IsPaused(bool *aIsPaused)
   100 {
   101   *aIsPaused = profiler_is_paused();
   102   return NS_OK;
   103 }
   105 NS_IMETHODIMP
   106 nsProfiler::PauseSampling()
   107 {
   108   profiler_pause();
   109   return NS_OK;
   110 }
   112 NS_IMETHODIMP
   113 nsProfiler::ResumeSampling()
   114 {
   115   profiler_resume();
   116   return NS_OK;
   117 }
   119 NS_IMETHODIMP
   120 nsProfiler::AddMarker(const char *aMarker)
   121 {
   122   PROFILER_MARKER(aMarker);
   123   return NS_OK;
   124 }
   126 NS_IMETHODIMP
   127 nsProfiler::GetProfile(char **aProfile)
   128 {
   129   char *profile = profiler_get_profile();
   130   if (profile) {
   131     size_t len = strlen(profile);
   132     char *profileStr = static_cast<char *>
   133                          (nsMemory::Clone(profile, (len + 1) * sizeof(char)));
   134     profileStr[len] = '\0';
   135     *aProfile = profileStr;
   136     free(profile);
   137   }
   138   return NS_OK;
   139 }
   141 static void
   142 AddSharedLibraryInfoToStream(std::ostream& aStream, const SharedLibrary& aLib)
   143 {
   144   aStream << "{";
   145   aStream << "\"start\":" << aLib.GetStart();
   146   aStream << ",\"end\":" << aLib.GetEnd();
   147   aStream << ",\"offset\":" << aLib.GetOffset();
   148   aStream << ",\"name\":\"" << aLib.GetName() << "\"";
   149   const std::string &breakpadId = aLib.GetBreakpadId();
   150   aStream << ",\"breakpadId\":\"" << breakpadId << "\"";
   151 #ifdef XP_WIN
   152   // FIXME: remove this XP_WIN code when the profiler plugin has switched to
   153   // using breakpadId.
   154   std::string pdbSignature = breakpadId.substr(0, 32);
   155   std::string pdbAgeStr = breakpadId.substr(32,  breakpadId.size() - 1);
   157   std::stringstream stream;
   158   stream << pdbAgeStr;
   160   unsigned pdbAge;
   161   stream << std::hex;
   162   stream >> pdbAge;
   164 #ifdef DEBUG
   165   std::ostringstream oStream;
   166   oStream << pdbSignature << std::hex << std::uppercase << pdbAge;
   167   MOZ_ASSERT(breakpadId == oStream.str());
   168 #endif
   170   aStream << ",\"pdbSignature\":\"" << pdbSignature << "\"";
   171   aStream << ",\"pdbAge\":" << pdbAge;
   172   aStream << ",\"pdbName\":\"" << aLib.GetName() << "\"";
   173 #endif
   174   aStream << "}";
   175 }
   177 std::string
   178 GetSharedLibraryInfoString()
   179 {
   180   SharedLibraryInfo info = SharedLibraryInfo::GetInfoForSelf();
   181   if (info.GetSize() == 0)
   182     return "[]";
   184   std::ostringstream os;
   185   os << "[";
   186   AddSharedLibraryInfoToStream(os, info.GetEntry(0));
   188   for (size_t i = 1; i < info.GetSize(); i++) {
   189     os << ",";
   190     AddSharedLibraryInfoToStream(os, info.GetEntry(i));
   191   }
   193   os << "]";
   194   return os.str();
   195 }
   197 NS_IMETHODIMP
   198 nsProfiler::GetSharedLibraryInformation(nsAString& aOutString)
   199 {
   200   aOutString.Assign(NS_ConvertUTF8toUTF16(GetSharedLibraryInfoString().c_str()));
   201   return NS_OK;
   202 }
   204 NS_IMETHODIMP nsProfiler::GetProfileData(JSContext* aCx,
   205                                          JS::MutableHandle<JS::Value> aResult)
   206 {
   207   JS::RootedObject obj(aCx, profiler_get_profile_jsobject(aCx));
   208   if (!obj) {
   209     return NS_ERROR_FAILURE;
   210   }
   211   aResult.setObject(*obj);
   212   return NS_OK;
   213 }
   215 NS_IMETHODIMP
   216 nsProfiler::IsActive(bool *aIsActive)
   217 {
   218   *aIsActive = profiler_is_active();
   219   return NS_OK;
   220 }
   222 NS_IMETHODIMP
   223 nsProfiler::GetResponsivenessTimes(uint32_t *aCount, double **aResult)
   224 {
   225   unsigned int len = 100;
   226   const double* times = profiler_get_responsiveness();
   227   if (!times) {
   228     *aCount = 0;
   229     *aResult = nullptr;
   230     return NS_OK;
   231   }
   233   double *fs = static_cast<double *>
   234                        (nsMemory::Clone(times, len * sizeof(double)));
   236   *aCount = len;
   237   *aResult = fs;
   239   return NS_OK;
   240 }
   242 NS_IMETHODIMP
   243 nsProfiler::GetFeatures(uint32_t *aCount, char ***aFeatures)
   244 {
   245   uint32_t len = 0;
   247   const char **features = profiler_get_features();
   248   if (!features) {
   249     *aCount = 0;
   250     *aFeatures = nullptr;
   251     return NS_OK;
   252   }
   254   while (features[len]) {
   255     len++;
   256   }
   258   char **featureList = static_cast<char **>
   259                        (nsMemory::Alloc(len * sizeof(char*)));
   261   for (size_t i = 0; i < len; i++) {
   262     size_t strLen = strlen(features[i]);
   263     featureList[i] = static_cast<char *>
   264                          (nsMemory::Clone(features[i], (strLen + 1) * sizeof(char)));
   265   }
   267   *aFeatures = featureList;
   268   *aCount = len;
   269   return NS_OK;
   270 }

mercurial