tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

gfxCrashReporterUtils.cpp (4654B)


      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 "gfxCrashReporterUtils.h"
      8 #include <string.h>                  // for strcmp
      9 #include "mozilla/SchedulerGroup.h"  // for SchedulerGroup
     10 #include "mozilla/Services.h"        // for GetObserverService
     11 #include "mozilla/StaticMutex.h"
     12 #include "mozilla/mozalloc.h"    // for operator new, etc
     13 #include "mozilla/RefPtr.h"      // for RefPtr
     14 #include "MainThreadUtils.h"     // for NS_IsMainThread
     15 #include "nsCOMPtr.h"            // for nsCOMPtr
     16 #include "nsError.h"             // for NS_OK, NS_FAILED, nsresult
     17 #include "nsExceptionHandler.h"  // for AppendAppNotesToCrashReport
     18 #include "nsIObserver.h"         // for nsIObserver, etc
     19 #include "nsIObserverService.h"  // for nsIObserverService
     20 #include "nsIRunnable.h"         // for nsIRunnable
     21 #include "nsISupports.h"
     22 #include "nsThreadUtils.h"  // for Runnable
     23 #include "nsTArray.h"       // for nsTArray
     24 #include "nscore.h"         // for NS_IMETHOD, NS_IMETHODIMP, etc
     25 
     26 namespace mozilla {
     27 
     28 static nsTArray<nsCString>* gFeaturesAlreadyReported = nullptr;
     29 static StaticMutex gFeaturesAlreadyReportedMutex MOZ_UNANNOTATED;
     30 
     31 class ObserverToDestroyFeaturesAlreadyReported final : public nsIObserver {
     32 public:
     33  NS_DECL_ISUPPORTS
     34  NS_DECL_NSIOBSERVER
     35 
     36  ObserverToDestroyFeaturesAlreadyReported() = default;
     37 
     38 private:
     39  virtual ~ObserverToDestroyFeaturesAlreadyReported() = default;
     40 };
     41 
     42 NS_IMPL_ISUPPORTS(ObserverToDestroyFeaturesAlreadyReported, nsIObserver)
     43 
     44 NS_IMETHODIMP
     45 ObserverToDestroyFeaturesAlreadyReported::Observe(nsISupports* aSubject,
     46                                                  const char* aTopic,
     47                                                  const char16_t* aData) {
     48  if (!strcmp(aTopic, "xpcom-shutdown")) {
     49    StaticMutexAutoLock al(gFeaturesAlreadyReportedMutex);
     50    if (gFeaturesAlreadyReported) {
     51      delete gFeaturesAlreadyReported;
     52      gFeaturesAlreadyReported = nullptr;
     53    }
     54  }
     55  return NS_OK;
     56 }
     57 
     58 class RegisterObserverRunnable : public Runnable {
     59 public:
     60  RegisterObserverRunnable() : Runnable("RegisterObserverRunnable") {}
     61  NS_IMETHOD Run() override {
     62    // LeakLog made me do this. Basically, I just wanted
     63    // gFeaturesAlreadyReported to be a static nsTArray<nsCString>, and LeakLog
     64    // was complaining about leaks like this:
     65    //    leaked 1 instance of nsTArray_base with size 8 bytes
     66    //    leaked 7 instances of nsStringBuffer with size 8 bytes each (56 bytes
     67    //    total)
     68    // So this is a work-around using a pointer, and using a nsIObserver to
     69    // deallocate on xpcom shutdown. Yay for fighting bloat.
     70    nsCOMPtr<nsIObserverService> observerService =
     71        mozilla::services::GetObserverService();
     72    if (!observerService) return NS_OK;
     73    RefPtr<ObserverToDestroyFeaturesAlreadyReported> observer =
     74        new ObserverToDestroyFeaturesAlreadyReported;
     75    observerService->AddObserver(observer, "xpcom-shutdown", false);
     76    return NS_OK;
     77  }
     78 };
     79 
     80 class AppendAppNotesRunnable : public Runnable {
     81 public:
     82  explicit AppendAppNotesRunnable(const nsACString& aFeatureStr)
     83      : Runnable("AppendAppNotesRunnable"), mFeatureString(aFeatureStr) {}
     84 
     85  NS_IMETHOD Run() override {
     86    CrashReporter::AppendAppNotesToCrashReport(mFeatureString);
     87    return NS_OK;
     88  }
     89 
     90 private:
     91  nsAutoCString mFeatureString;
     92 };
     93 
     94 void ScopedGfxFeatureReporter::WriteAppNote(char statusChar,
     95                                            int32_t statusNumber) {
     96  StaticMutexAutoLock al(gFeaturesAlreadyReportedMutex);
     97 
     98  if (!gFeaturesAlreadyReported) {
     99    gFeaturesAlreadyReported = new nsTArray<nsCString>;
    100    nsCOMPtr<nsIRunnable> r = new RegisterObserverRunnable();
    101    SchedulerGroup::Dispatch(r.forget());
    102  }
    103 
    104  nsAutoCString featureString;
    105  if (statusNumber == 0) {
    106    featureString.AppendPrintf("%s%c ", mFeature, statusChar);
    107  } else {
    108    featureString.AppendPrintf("%s%c%d ", mFeature, statusChar, statusNumber);
    109  }
    110 
    111  if (!gFeaturesAlreadyReported->Contains(featureString)) {
    112    gFeaturesAlreadyReported->AppendElement(featureString);
    113    AppNote(featureString);
    114  }
    115 }
    116 
    117 void ScopedGfxFeatureReporter::AppNote(const nsACString& aMessage) {
    118  if (NS_IsMainThread()) {
    119    CrashReporter::AppendAppNotesToCrashReport(aMessage);
    120  } else {
    121    nsCOMPtr<nsIRunnable> r = new AppendAppNotesRunnable(aMessage);
    122    NS_DispatchToMainThread(r.forget());
    123  }
    124 }
    125 
    126 }  // end namespace mozilla