Back to index

lightning-sunbird  0.9+nobinonly
Classes | Public Member Functions | Static Public Member Functions | Private Member Functions | Static Private Member Functions | Private Attributes | Static Private Attributes
nsMetricsService Class Reference

#include <nsMetricsService.h>

Inheritance diagram for nsMetricsService:
Inheritance graph
[legend]
Collaboration diagram for nsMetricsService:
Collaboration graph
[legend]

List of all members.

Classes

class  BadCertListener

Public Member Functions

nsresult LogEvent (const nsAString &eventName, nsIWritablePropertyBag2 *eventProperties)
nsresult CreateEventItem (const nsAString &name, nsIMetricsEventItem **item)
nsresult Init ()
const nsDataHashtable
< nsPtrHashKey< nsIDOMWindow >
, PRUint32 > & 
WindowMap () const
nsresult HashUTF8 (const nsCString &str, nsCString &hashed)
nsresult HashUTF16 (const nsString &str, nsCString &hashed)
nsIMetricsEventItem createEventItem (in DOMString itemNamespace, in DOMString itemName)
 Creates a new EventItem object to hold event data.
void logEvent (in nsIMetricsEventItem item)
 Logs an event using the given EventItem.
void logSimpleEvent (in DOMString eventNS, in DOMString event, in nsIPropertyBag eventValues)
 Constructs and logs an EventItem, using the given namespace, event name, and event properties.
void flush ()
 Flush data to disk.
void upload ()
 Initiate the upload of the current event log.
void suspend ()
 Suspend log collection.
void resume ()
 Resume log collection.
unsigned long getWindowID (in nsIDOMWindow window)
 Gets a numeric window id corresponding to the given DOMWindow.
nsIChannel newChannel (in nsIURI aURI)
 Constructs a new channel for the about protocol module.
void onDataAvailable (in nsIRequest aRequest, in nsISupports aContext, in nsIInputStream aInputStream, in unsigned long aOffset, in unsigned long aCount)
 Called when the next chunk of data (corresponding to the request) may be read without blocking the calling thread.
void onStartRequest (in nsIRequest aRequest, in nsISupports aContext)
 Called to signify the beginning of an asynchronous request.
void onStopRequest (in nsIRequest aRequest, in nsISupports aContext, in nsresult aStatusCode)
 Called to signify the end of an asynchronous request.
void observe (in nsISupports aSubject, in string aTopic, in wstring aData)
 Observe will be called when there is a notification for the topic |aTopic|.
void notify (in nsITimer timer)

Static Public Member Functions

NS_DECL_ISUPPORTS
NS_DECL_NSIMETRICSSERVICE
NS_DECL_NSIABOUTMODULE
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIOBSERVER static
NS_DECL_NSITIMERCALLBACK
nsMetricsService
get ()
static NS_METHOD Create (nsISupports *outer, const nsIID &iid, void **result)
static PRUint32 GetWindowID (nsIDOMWindow *window)

Private Member Functions

 nsMetricsService ()
 ~nsMetricsService ()
nsresult ProfileStartup ()
nsresult StartCollection ()
nsresult StopCollection ()
void EnableCollectors ()
nsresult CreateRoot ()
nsresult UploadData ()
nsresult GetDataFile (nsCOMPtr< nsILocalFile > *result)
nsresult OpenDataFile (PRUint32 flags, PRFileDesc **result)
nsresult GetDataFileForUpload (nsCOMPtr< nsILocalFile > *result)
nsresult OpenCompleteXMLStream (nsILocalFile *dataFile, nsIInputStream **result)
void InitUploadTimer (PRBool immediate)
void GetConfigFile (nsIFile **result)
void GetConfigTempFile (nsIFile **result)
nsresult GenerateClientID (nsCString &clientID)
PRBool IsEventEnabled (const nsAString &event) const
nsresult BuildEventItem (nsIMetricsEventItem *item, nsIDOMElement **itemElement)
PRBool PersistEventCount ()
nsresult HashBytes (const PRUint8 *bytes, PRUint32 length, nsACString &result)
PRUint32 GetWindowIDInternal (nsIDOMWindow *window)
PRBool LoadNewConfig (nsIFile *newConfig, nsIFile *oldConfig)
void RemoveDataFile ()
PRInt32 GetRandomUploadInterval ()

Static Private Member Functions

static PLDHashOperator PR_CALLBACK PruneDisabledCollectors (const nsAString &key, nsCOMPtr< nsIMetricsCollector > &value, void *userData)
static PLDHashOperator PR_CALLBACK DetachCollector (const nsAString &key, nsIMetricsCollector *value, void *userData)
static PLDHashOperator PR_CALLBACK NotifyNewLog (const nsAString &key, nsIMetricsCollector *value, void *userData)
static nsresult FlushIntPref (const char *prefName, PRInt32 prefValue)
static nsresult FlushCharPref (const char *prefName, const char *prefValue)
static nsresult FlushClearPref (const char *prefName)
static PRBool CollectionEnabled ()

Private Attributes

nsMetricsConfig mConfig
nsCOMPtr< nsIOutputStreammConfigOutputStream
nsCOMPtr< nsIDOMDocumentmDocument
nsCOMPtr< nsIDOMNodemRoot
MD5ContextmMD5Context
nsDataHashtable< nsPtrHashKey
< nsIDOMWindow >, PRUint32
mWindowMap
nsInterfaceHashtable
< nsStringHashKey,
nsIMetricsCollector
mCollectorMap
nsCOMPtr< nsITimermUploadTimer
PRInt32 mEventCount
PRInt32 mSuspendCount
PRBool mUploading
nsString mSessionID
PRUint32 mNextWindowID
PRUint32 mRetryCount

Static Private Attributes

static nsMetricsServicesMetricsService = nsnull
static const PRUint32 kMaxRetries = 3
static const PRUint32 kMetricsVersion = 2

Detailed Description

Definition at line 81 of file nsMetricsService.h.


Constructor & Destructor Documentation

Definition at line 287 of file nsMetricsService.cpp.

    : mMD5Context(nsnull),
      mEventCount(0),
      mSuspendCount(0),
      mUploading(PR_FALSE),
      mNextWindowID(0),
      mRetryCount(0)
{
  NS_ASSERTION(!sMetricsService, ">1 MetricsService object created");
  sMetricsService = this;
}

Here is the caller graph for this function:

Definition at line 307 of file nsMetricsService.cpp.

Here is the call graph for this function:


Member Function Documentation

nsresult nsMetricsService::BuildEventItem ( nsIMetricsEventItem item,
nsIDOMElement **  itemElement 
) [private]

Definition at line 336 of file nsMetricsService.cpp.

{
  *itemElement = nsnull;

  nsString itemNS, itemName;
  item->GetItemNamespace(itemNS);
  item->GetItemName(itemName);

  nsCOMPtr<nsIDOMElement> element;
  nsresult rv = mDocument->CreateElementNS(itemNS, itemName,
                                           getter_AddRefs(element));
  NS_ENSURE_SUCCESS(rv, rv);

  // Attach the given properties as attributes.
  nsCOMPtr<nsIPropertyBag> properties;
  item->GetProperties(getter_AddRefs(properties));
  if (properties) {
    nsCOMPtr<nsISimpleEnumerator> enumerator;
    rv = properties->GetEnumerator(getter_AddRefs(enumerator));
    NS_ENSURE_SUCCESS(rv, rv);

    nsCOMPtr<nsISupports> propertySupports;
    while (NS_SUCCEEDED(
               enumerator->GetNext(getter_AddRefs(propertySupports)))) {
      nsCOMPtr<nsIProperty> property = do_QueryInterface(propertySupports);
      if (!property) {
        NS_WARNING("PropertyBag enumerator has non-nsIProperty elements");
        continue;
      }

      nsString name;
      rv = property->GetName(name);
      if (NS_FAILED(rv)) {
        NS_WARNING("Failed to get property name");
        continue;
      }

      nsCOMPtr<nsIVariant> value;
      rv = property->GetValue(getter_AddRefs(value));
      if (NS_FAILED(rv) || !value) {
        NS_WARNING("Failed to get property value");
        continue;
      }

      // If the type is boolean, we want to use the strings "true" and "false",
      // rather than "1" and "0" which is what nsVariant generates on its own.
      PRUint16 dataType;
      value->GetDataType(&dataType);

      nsString valueString;
      if (dataType == nsIDataType::VTYPE_BOOL) {
        PRBool valueBool;
        rv = value->GetAsBool(&valueBool);
        if (NS_FAILED(rv)) {
          NS_WARNING("Variant has bool type but couldn't get bool value");
          continue;
        }
        valueString = valueBool ? NS_LITERAL_STRING("true")
                      : NS_LITERAL_STRING("false");
      } else {
        rv = value->GetAsDOMString(valueString);
        if (NS_FAILED(rv)) {
          NS_WARNING("Failed to convert property value to string");
          continue;
        }
      }

      rv = element->SetAttribute(name, valueString);
      if (NS_FAILED(rv)) {
        NS_WARNING("Failed to set attribute value");
      }
      continue;
    }
  }

  // Now recursively build the child event items
  PRInt32 childCount = 0;
  item->GetChildCount(&childCount);
  for (PRInt32 i = 0; i < childCount; ++i) {
    nsCOMPtr<nsIMetricsEventItem> childItem;
    item->ChildAt(i, getter_AddRefs(childItem));
    NS_ASSERTION(childItem, "The child list cannot contain null items");

    nsCOMPtr<nsIDOMElement> childElement;
    rv = BuildEventItem(childItem, getter_AddRefs(childElement));
    NS_ENSURE_SUCCESS(rv, rv);

    nsCOMPtr<nsIDOMNode> nodeReturn;
    rv = element->AppendChild(childElement, getter_AddRefs(nodeReturn));
    NS_ENSURE_SUCCESS(rv, rv);
  }

  element.swap(*itemElement);
  return NS_OK;
}

Here is the call graph for this function:

Definition at line 1684 of file nsMetricsService.cpp.

{
  nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
  NS_ENSURE_TRUE(prefs, PR_FALSE);

  PRBool enabled = PR_FALSE;
  prefs->GetBoolPref(kEnablePref, &enabled);
  return enabled;
}

Here is the call graph for this function:

Here is the caller graph for this function:

NS_METHOD nsMetricsService::Create ( nsISupports *  outer,
const nsIID iid,
void **  result 
) [static]

Definition at line 1142 of file nsMetricsService.cpp.

{
  NS_ENSURE_TRUE(!outer, NS_ERROR_NO_AGGREGATION);

  nsRefPtr<nsMetricsService> ms;
  if (!sMetricsService) {
    ms = new nsMetricsService();
    if (!ms)
      return NS_ERROR_OUT_OF_MEMORY;
    NS_ASSERTION(sMetricsService, "should be non-null");

    nsresult rv = ms->Init();
    if (NS_FAILED(rv))
      return rv;
  }
  return sMetricsService->QueryInterface(iid, result);
}

Here is the call graph for this function:

nsresult nsMetricsService::CreateEventItem ( const nsAString &  name,
nsIMetricsEventItem **  item 
) [inline]

Definition at line 116 of file nsMetricsService.h.

Here is the caller graph for this function:

nsIMetricsEventItem nsIMetricsService::createEventItem ( in DOMString  itemNamespace,
in DOMString  itemName 
) [inherited]

Creates a new EventItem object to hold event data.

The event will not be logged until logEvent() is called.

Parameters:
itemNamespaceThe new item's namespace
itemNameThe new item's name
Returns:
a new MetricsEventItem instance

Definition at line 1226 of file nsMetricsService.cpp.

Here is the call graph for this function:

Here is the caller graph for this function:

PLDHashOperator PR_CALLBACK nsMetricsService::DetachCollector ( const nsAString &  key,
nsIMetricsCollector value,
void userData 
) [static, private]

Definition at line 300 of file nsMetricsService.cpp.

{
  value->OnDetach();
  return PL_DHASH_NEXT;
}

Here is the caller graph for this function:

Definition at line 894 of file nsMetricsService.cpp.

{
  // Start and stop collectors based on the current config.
  nsTArray<nsString> enabledCollectors;
  mConfig.GetEvents(enabledCollectors);

  // We need to find two sets of collectors:
  //  (1) collectors which are running but not in |collectors|.
  //      We'll call onDetach() on them and let them be released.
  //  (2) collectors which are in |collectors| but not running.
  //      We need to instantiate these collectors.

  DisabledCollectorsClosure dc(enabledCollectors);
  mCollectorMap.Enumerate(PruneDisabledCollectors, &dc);

  // Notify this set of collectors that they're going away, and release them.
  PRUint32 i;
  for (i = 0; i < dc.disabledCollectors.Length(); ++i) {
    dc.disabledCollectors[i]->OnDetach();
  }
  dc.disabledCollectors.Clear();

  // Now instantiate any newly-enabled collectors.
  for (i = 0; i < enabledCollectors.Length(); ++i) {
    const nsString &name = enabledCollectors[i];
    if (!mCollectorMap.GetWeak(name)) {
      nsCString contractID("@mozilla.org/metrics/collector;1?name=");
      contractID.Append(NS_ConvertUTF16toUTF8(name));

      nsCOMPtr<nsIMetricsCollector> coll = do_GetService(contractID.get());
      if (coll) {
        MS_LOG(("Created collector %s", contractID.get()));
        mCollectorMap.Put(name, coll);
        coll->OnAttach();
      } else {
        MS_LOG(("Couldn't instantiate collector %s", contractID.get()));
      }
    }
  }

  // Finally, notify all collectors that we've restarted the log.
  mCollectorMap.EnumerateRead(NotifyNewLog, nsnull);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nsIMetricsService::flush ( ) [inherited]

Flush data to disk.

nsresult nsMetricsService::FlushCharPref ( const char *  prefName,
const char *  prefValue 
) [static, private]

Definition at line 1644 of file nsMetricsService.cpp.

{
  nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
  NS_ENSURE_STATE(prefs);

  nsresult rv = prefs->SetCharPref(prefName, prefValue);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIPrefService> prefService = do_QueryInterface(prefs);
  NS_ENSURE_STATE(prefService);

  rv = prefService->SavePrefFile(nsnull);
  NS_ENSURE_SUCCESS(rv, rv);

  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult nsMetricsService::FlushClearPref ( const char *  prefName) [static, private]

Definition at line 1662 of file nsMetricsService.cpp.

{
  nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
  NS_ENSURE_STATE(prefs);

  nsresult rv = prefs->ClearUserPref(prefName);
  if (NS_FAILED(rv)) {
    // There was no user-set value for this pref.
    // It's not an error, and we don't need to flush.
    return NS_OK;
  }

  nsCOMPtr<nsIPrefService> prefService = do_QueryInterface(prefs);
  NS_ENSURE_STATE(prefService);

  rv = prefService->SavePrefFile(nsnull);
  NS_ENSURE_SUCCESS(rv, rv);

  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult nsMetricsService::FlushIntPref ( const char *  prefName,
PRInt32  prefValue 
) [static, private]

Definition at line 1626 of file nsMetricsService.cpp.

{
  nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
  NS_ENSURE_STATE(prefs);

  nsresult rv = prefs->SetIntPref(prefName, prefValue);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIPrefService> prefService = do_QueryInterface(prefs);
  NS_ENSURE_STATE(prefService);

  rv = prefService->SavePrefFile(nsnull);
  NS_ENSURE_SUCCESS(rv, rv);

  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1535 of file nsMetricsService.cpp.

{
  // Feed some data into the hasher...

  struct {
    PRTime  a;
    PRUint8 b[32];
  } input;

  input.a = PR_Now();
  nsMetricsUtils::GetRandomNoise(input.b, sizeof(input.b));

  return HashBytes(
      NS_REINTERPRET_CAST(const PRUint8 *, &input), sizeof(input), clientID);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1130 of file nsMetricsService.cpp.

{
  if (!sMetricsService) {
    nsCOMPtr<nsIMetricsService> ms =
      do_GetService(NS_METRICSSERVICE_CONTRACTID);
    if (!sMetricsService)
      NS_WARNING("failed to initialize metrics service");
  }
  return sMetricsService;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nsMetricsService::GetConfigFile ( nsIFile **  result) [private]

Definition at line 1511 of file nsMetricsService.cpp.

{
  nsCOMPtr<nsIFile> file;
  NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(file));
  if (file)
    file->AppendNative(NS_LITERAL_CSTRING("metrics-config.xml"));

  *result = nsnull;
  file.swap(*result);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1523 of file nsMetricsService.cpp.

{
  nsCOMPtr<nsIFile> file;
  NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(file));
  if (file)
    file->AppendNative(NS_LITERAL_CSTRING("metrics-config.tmp"));

  *result = nsnull;
  file.swap(*result);
}

Here is the call graph for this function:

Definition at line 1239 of file nsMetricsService.cpp.

{
  nsCOMPtr<nsIFile> file;
  nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
                                       getter_AddRefs(file));
  NS_ENSURE_SUCCESS(rv, rv);

  rv = file->AppendNative(NS_LITERAL_CSTRING("metrics.xml"));
  NS_ENSURE_SUCCESS(rv, rv);

  *result = do_QueryInterface(file, &rv);
  return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1347 of file nsMetricsService.cpp.

{
  nsCOMPtr<nsILocalFile> input;
  nsresult rv = GetDataFile(&input);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIInputStream> src;
  rv = OpenCompleteXMLStream(input, getter_AddRefs(src));
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIFile> temp;
  rv = input->Clone(getter_AddRefs(temp));
  NS_ENSURE_SUCCESS(rv, rv);

  nsCString leafName;
  rv = temp->GetNativeLeafName(leafName);
  NS_ENSURE_SUCCESS(rv, rv);

  leafName.Append(".bz2");
  rv = temp->SetNativeLeafName(leafName);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsILocalFile> ltemp = do_QueryInterface(temp, &rv);
  NS_ENSURE_SUCCESS(rv, rv);

  PRFileDesc *destFd = NULL;
  rv = ltemp->OpenNSPRFileDesc(PR_WRONLY | PR_TRUNCATE | PR_CREATE_FILE, 0600,
                               &destFd);

  // Copy file using bzip2 compression:

  if (NS_SUCCEEDED(rv)) {
#ifdef NS_METRICS_SEND_UNCOMPRESSED_DATA
    char buf[4096];
    PRUint32 n;

    while (NS_SUCCEEDED(rv = src->Read(buf, sizeof(buf), &n)) && n) {
      if (PR_Write(destFd, buf, n) != n) {
        NS_WARNING("failed to write data");
        rv = NS_ERROR_UNEXPECTED;
        break;
      }
    }
#else
    rv = CompressBZ2(src, destFd);
#endif
  }

  if (destFd)
    PR_Close(destFd);

  if (NS_SUCCEEDED(rv)) {
    *result = nsnull;
    ltemp.swap(*result);
  }

  return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 722 of file nsMetricsService.cpp.

{
  static const int kSecondsPerHour = 60 * 60;
  mRetryCount = 0;

  PRInt32 interval_sec = kSecondsPerHour * 12;
  PRUint32 random = 0;
  if (nsMetricsUtils::GetRandomNoise(&random, sizeof(random))) {
    interval_sec += (random % (24 * kSecondsPerHour));
  }
  // If we couldn't get any random bytes, just use the default of
  // 12 hours.

  return interval_sec;
}

Here is the call graph for this function:

Definition at line 1584 of file nsMetricsService.cpp.

{
  if (!sMetricsService) {
    NS_NOTREACHED("metrics service not created");
    return PR_UINT32_MAX;
  }

  return sMetricsService->GetWindowIDInternal(window);
}

Here is the call graph for this function:

Here is the caller graph for this function:

unsigned long nsIMetricsService::getWindowID ( in nsIDOMWindow  window) [inherited]

Gets a numeric window id corresponding to the given DOMWindow.

The id remains constant for as long as the window exists.

Definition at line 1602 of file nsMetricsService.cpp.

{
  PRUint32 id;
  if (!mWindowMap.Get(window, &id)) {
    id = mNextWindowID++;
    MS_LOG(("Adding window %p to map with id %d", window, id));
    mWindowMap.Put(window, id);
  }

  return id;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult nsMetricsService::HashBytes ( const PRUint8 bytes,
PRUint32  length,
nsACString &  result 
) [private]

Definition at line 1552 of file nsMetricsService.cpp.

{
  unsigned char buf[HASH_LENGTH_MAX];
  unsigned int resultLength = 0;

  MD5_Begin(mMD5Context);
  MD5_Update(mMD5Context, bytes, length);
  MD5_End(mMD5Context, buf, &resultLength, sizeof(buf));

  // Base64-encode the result.  The maximum result length is calculated
  // as described in plbase64.h.
  char *resultBuffer;
  if (NS_CStringGetMutableData(
          result, ((resultLength + 2) / 3) * 4, &resultBuffer) == 0) {
    return NS_ERROR_OUT_OF_MEMORY;
  }

  PL_Base64Encode(NS_REINTERPRET_CAST(char*, buf), resultLength, resultBuffer);

  // Size the string to its null-terminated length
  result.SetLength(strlen(resultBuffer));
  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult nsMetricsService::HashUTF16 ( const nsString str,
nsCString hashed 
) [inline]

Definition at line 140 of file nsMetricsService.h.

                                                             {
    return HashUTF8(NS_ConvertUTF16toUTF8(str), hashed);
  }

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1615 of file nsMetricsService.cpp.

{
  if (str.IsEmpty()) {
    return NS_ERROR_INVALID_ARG;
  }

  return HashBytes(
      NS_REINTERPRET_CAST(const PRUint8 *, str.get()), str.Length(), hashed);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1161 of file nsMetricsService.cpp.

{
  // Anything that requires reading profile prefs must be initialized
  // later, once the profile-after-change notification has happened.
  // We can create objects and register for notifications now.
  
#ifdef PR_LOGGING
  gMetricsLog = PR_NewLogModule("nsMetricsService");
#endif

  MS_LOG(("nsMetricsService::Init"));

  // Set up our hashtables
  NS_ENSURE_TRUE(mWindowMap.Init(32), NS_ERROR_OUT_OF_MEMORY);
  NS_ENSURE_TRUE(mCollectorMap.Init(16), NS_ERROR_OUT_OF_MEMORY);

  mUploadTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
  NS_ENSURE_TRUE(mUploadTimer, NS_ERROR_OUT_OF_MEMORY);

  mMD5Context = MD5_NewContext();
  NS_ENSURE_TRUE(mMD5Context, NS_ERROR_FAILURE);

  NS_ENSURE_STATE(mConfig.Init());

  // Create an XML document to serve as the owner document for elements.
  mDocument = do_CreateInstance("@mozilla.org/xml/xml-document;1");
  NS_ENSURE_TRUE(mDocument, NS_ERROR_FAILURE);

  // Create a root log element.
  nsresult rv = CreateRoot();
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIObserverService> obsSvc =
      do_GetService("@mozilla.org/observer-service;1", &rv);
  NS_ENSURE_SUCCESS(rv, rv);

  // The rest of startup will happen on profile-after-change
  rv = obsSvc->AddObserver(this, "profile-after-change", PR_FALSE);
  NS_ENSURE_SUCCESS(rv, rv);

  // Listen for quit-application so we can properly flush our data to disk
  rv = obsSvc->AddObserver(this, kQuitApplicationTopic, PR_FALSE);
  NS_ENSURE_SUCCESS(rv, rv);

  // We wait to cancel our timer until xpcom-shutdown, to catch cases
  // where quit-application is never called.
  rv = obsSvc->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE);
  NS_ENSURE_SUCCESS(rv, rv);

  // Listen for window destruction so that we can remove the windows
  // from our window id map.
  rv = obsSvc->AddObserver(this, NS_WEBNAVIGATION_DESTROY, PR_FALSE);
  NS_ENSURE_SUCCESS(rv, rv);
  rv = obsSvc->AddObserver(this, NS_CHROME_WEBNAVIGATION_DESTROY, PR_FALSE);
  NS_ENSURE_SUCCESS(rv, rv);

  // Listen for http-on-modify-request so that we can clear out cookies
  // from our requests.
  rv = obsSvc->AddObserver(this, NS_HTTP_ON_MODIFY_REQUEST_TOPIC, PR_FALSE);
  NS_ENSURE_SUCCESS(rv, rv);

  return NS_OK;
}

Here is the call graph for this function:

void nsMetricsService::InitUploadTimer ( PRBool  immediate) [private]

Definition at line 1473 of file nsMetricsService.cpp.

{
  // Check whether we've set a delayed upload time due to previous errors.
  nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
  if (!prefs) {
    NS_WARNING("couldn't get prefs service");
    return;
  }

  PRUint32 delay_sec;

  PRInt32 uploadTime_sec;
  if (NS_SUCCEEDED(prefs->GetIntPref(kUploadTimePref, &uploadTime_sec))) {
    // Set a timer for when we should upload.  If the time to upload has
    // passed, we'll set a timer for 0ms.
    PRInt32 now_sec = PRInt32(PR_Now() / PR_USEC_PER_SEC);
    if (now_sec >= uploadTime_sec) {
      delay_sec = 0;
    } else {
      delay_sec = (uploadTime_sec - now_sec);
    }
  } else if (immediate) {
    delay_sec = 0;
  } else {
    delay_sec = mConfig.UploadInterval();
  }

  nsresult rv = mUploadTimer->InitWithCallback(this,
                                               delay_sec * PR_MSEC_PER_SEC,
                                               nsITimer::TYPE_ONE_SHOT);
  if (NS_SUCCEEDED(rv)) {
    MS_LOG(("Initialized upload timer for %d sec", delay_sec));
  } else {
    MS_LOG(("Failed to initialize upload timer"));
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRBool nsMetricsService::IsEventEnabled ( const nsAString &  event) const [inline, private]

Definition at line 190 of file nsMetricsService.h.

Here is the call graph for this function:

PRBool nsMetricsService::LoadNewConfig ( nsIFile newConfig,
nsIFile oldConfig 
) [private]

Definition at line 665 of file nsMetricsService.cpp.

{
  // Try to load the new config
  PRBool exists = PR_FALSE;
  newConfig->Exists(&exists);
  if (exists && NS_SUCCEEDED(mConfig.Load(newConfig))) {
    MS_LOG(("Successfully loaded new config"));

    // Replace the old config file with the new one
    oldConfig->Remove(PR_FALSE);

    nsString filename;
    oldConfig->GetLeafName(filename);

    nsCOMPtr<nsIFile> directory;
    oldConfig->GetParent(getter_AddRefs(directory));

    newConfig->MoveTo(directory, filename);
    return PR_TRUE;
  }

  MS_LOG(("Couldn't load new config"));

  // We want to disable collection until the next upload interval,
  // but we don't want to reset the upload interval to the default
  // if the server had supplied one.  So, write out a new config
  // that just has the collectors disabled.
  mConfig.ClearEvents();

  nsCOMPtr<nsILocalFile> lf = do_QueryInterface(oldConfig);
  nsresult rv = mConfig.Save(lf);
  if (NS_FAILED(rv)) {
    MS_LOG(("failed to save config: %d", rv));
  }

  return PR_FALSE;
}

Here is the call graph for this function:

NS_IMETHODIMP nsMetricsService::LogEvent ( const nsAString &  eventName,
nsIWritablePropertyBag2 eventProperties 
) [inline]

Definition at line 106 of file nsMetricsService.h.

  {
    nsCOMPtr<nsIPropertyBag> bag = do_QueryInterface(eventProperties);
    NS_ENSURE_STATE(bag);
    return LogSimpleEvent(NS_LITERAL_STRING(NS_METRICS_NAMESPACE), eventName,
                          bag);
  }

Here is the call graph for this function:

Here is the caller graph for this function:

Logs an event using the given EventItem.

The event is recorded with a timestamp generated at the time at which this method is called, and a session id for this instance of the application. The keys "time" and "sessionid" are reserved for this data.

Parameters:
itemThe item to log. This item and its entire tree of child items will be logged as part of the event.
void nsIMetricsService::logSimpleEvent ( in DOMString  eventNS,
in DOMString  event,
in nsIPropertyBag  eventValues 
) [inherited]

Constructs and logs an EventItem, using the given namespace, event name, and event properties.

This is a more convenient version of logEvent() for the case where there are no child EventItems.

See also:
nsIMetricsEventItem

Constructs a new channel for the about protocol module.

Parameters:
aURIthe uri of the new channel
void nsITimerCallback::notify ( in nsITimer  timer) [inherited]
Parameters:
aTimerthe timer which has expired
PLDHashOperator PR_CALLBACK nsMetricsService::NotifyNewLog ( const nsAString &  key,
nsIMetricsCollector value,
void userData 
) [static, private]

Definition at line 886 of file nsMetricsService.cpp.

{
  value->OnNewLog();
  return PL_DHASH_NEXT;
}

Here is the caller graph for this function:

void nsIObserver::observe ( in nsISupports  aSubject,
in string  aTopic,
in wstring  aData 
) [inherited]

Observe will be called when there is a notification for the topic |aTopic|.

This assumes that the object implementing this interface has been registered with an observer service such as the nsIObserverService.

If you expect multiple topics/subjects, the impl is responsible for filtering.

You should not modify, add, remove, or enumerate notifications in the implemention of observe.

Parameters:
aSubject: Notification specific interface pointer.
aTopic: The notification topic or subject.
aData: Notification specific wide string. subject event.
void nsIStreamListener::onDataAvailable ( in nsIRequest  aRequest,
in nsISupports  aContext,
in nsIInputStream  aInputStream,
in unsigned long  aOffset,
in unsigned long  aCount 
) [inherited]

Called when the next chunk of data (corresponding to the request) may be read without blocking the calling thread.

The onDataAvailable impl must read exactly |aCount| bytes of data before returning.

Parameters:
aRequestrequest corresponding to the source of the data
aContextuser defined context
aInputStreaminput stream containing the data chunk
aOffsetNumber of bytes that were sent in previous onDataAvailable calls for this request. In other words, the sum of all previous count parameters. If that number is greater than or equal to 2^32, this parameter will be PR_UINT32_MAX (2^32 - 1).
aCountnumber of bytes available in the stream

NOTE: The aInputStream parameter must implement readSegments.

An exception thrown from onDataAvailable has the side-effect of causing the request to be canceled.

void nsIRequestObserver::onStartRequest ( in nsIRequest  aRequest,
in nsISupports  aContext 
) [inherited]

Called to signify the beginning of an asynchronous request.

Parameters:
aRequestrequest being observed
aContextuser defined context

An exception thrown from onStartRequest has the side-effect of causing the request to be canceled.

Here is the caller graph for this function:

void nsIRequestObserver::onStopRequest ( in nsIRequest  aRequest,
in nsISupports  aContext,
in nsresult  aStatusCode 
) [inherited]

Called to signify the end of an asynchronous request.

This call is always preceded by a call to onStartRequest.

Parameters:
aRequestrequest being observed
aContextuser defined context
aStatusCodereason for stopping (NS_OK if completed successfully)

An exception thrown from onStopRequest is generally ignored.

Here is the caller graph for this function:

Definition at line 1407 of file nsMetricsService.cpp.

{
  // Construct a full XML document using the header, file contents, and
  // footer.  We need to generate a client id now if one doesn't exist.
  static const char kClientIDPref[] = "metrics.client-id";

  nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
  NS_ENSURE_STATE(prefs);
  
  nsCString clientID;
  nsresult rv = prefs->GetCharPref(kClientIDPref, getter_Copies(clientID));
  if (NS_FAILED(rv) || clientID.IsEmpty()) {
    rv = GenerateClientID(clientID);
    NS_ENSURE_SUCCESS(rv, rv);
    
    rv = FlushCharPref(kClientIDPref, clientID.get());
    NS_ENSURE_SUCCESS(rv, rv);
  }

  static const char METRICS_XML_HEAD[] =
      "<?xml version=\"1.0\"?>\n"
      "<log xmlns=\"" NS_METRICS_NAMESPACE "\" "
           "version=\"%d\" clientid=\"%s\">\n";
  static const char METRICS_XML_TAIL[] = "</log>";

  nsCOMPtr<nsIFileInputStream> fileStream =
      do_CreateInstance(NS_LOCALFILEINPUTSTREAM_CONTRACTID);
  NS_ENSURE_STATE(fileStream);

  rv = fileStream->Init(dataFile, -1, -1, 0);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIMultiplexInputStream> miStream =
    do_CreateInstance(NS_MULTIPLEXINPUTSTREAM_CONTRACTID);
  NS_ENSURE_STATE(miStream);

  nsCOMPtr<nsIStringInputStream> stringStream =
      do_CreateInstance("@mozilla.org/io/string-input-stream;1");
  NS_ENSURE_STATE(stringStream);

  char *head = PR_smprintf(METRICS_XML_HEAD, kMetricsVersion, clientID.get());
  rv = stringStream->SetData(head, -1);
  PR_smprintf_free(head);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = miStream->AppendStream(stringStream);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = miStream->AppendStream(fileStream);
  NS_ENSURE_SUCCESS(rv, rv);

  stringStream = do_CreateInstance("@mozilla.org/io/string-input-stream;1");
  NS_ENSURE_STATE(stringStream);

  rv = stringStream->SetData(METRICS_XML_TAIL, sizeof(METRICS_XML_TAIL)-1);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = miStream->AppendStream(stringStream);
  NS_ENSURE_SUCCESS(rv, rv);

  NS_ADDREF(*result = miStream);
  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult nsMetricsService::OpenDataFile ( PRUint32  flags,
PRFileDesc **  result 
) [private]

Definition at line 1254 of file nsMetricsService.cpp.

{
  nsCOMPtr<nsILocalFile> dataFile;
  nsresult rv = GetDataFile(&dataFile);
  NS_ENSURE_SUCCESS(rv, rv);

  return dataFile->OpenNSPRFileDesc(flags, 0600, fd);
}

Here is the call graph for this function:

Definition at line 1578 of file nsMetricsService.cpp.

Here is the call graph for this function:

Definition at line 1041 of file nsMetricsService.cpp.

Here is the call graph for this function:

PLDHashOperator PR_CALLBACK nsMetricsService::PruneDisabledCollectors ( const nsAString &  key,
nsCOMPtr< nsIMetricsCollector > &  value,
void userData 
) [static, private]

Definition at line 862 of file nsMetricsService.cpp.

{
  DisabledCollectorsClosure *dc =
    NS_STATIC_CAST(DisabledCollectorsClosure *, userData);

  // The frozen string API doesn't expose operator==, so we can't use
  // IndexOf() here.
  for (PRUint32 i = 0; i < dc->enabledCollectors.Length(); ++i) {
    if (dc->enabledCollectors[i].Equals(key)) {
      // The collector is enabled, continue
      return PL_DHASH_NEXT;
    }
  }

  // We didn't find the collector |key| in the list of enabled collectors,
  // so move it from the hash table to the disabledCollectors list.
  MS_LOG(("Disabling collector %s", NS_ConvertUTF16toUTF8(key).get()));
  dc->disabledCollectors.AppendElement(value);
  return PL_DHASH_REMOVE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 704 of file nsMetricsService.cpp.

{
  nsCOMPtr<nsILocalFile> dataFile;
  GetDataFile(&dataFile);
  if (!dataFile) {
    MS_LOG(("Couldn't get data file to remove"));
    return;
  }

  nsresult rv = dataFile->Remove(PR_FALSE);
  if (NS_SUCCEEDED(rv)) {
    MS_LOG(("Removed data file"));
  } else {
    MS_LOG(("Couldn't remove data file: %d", rv));
  }
}

Here is the call graph for this function:

Resume log collection.

Call this method once per call to suspend to re-enable log collection.

Definition at line 1051 of file nsMetricsService.cpp.

{
  // Initialize configuration by reading our old config file if one exists.
  nsCOMPtr<nsIFile> file;
  GetConfigFile(getter_AddRefs(file));

  PRBool loaded = PR_FALSE;
  if (file) {
    PRBool exists;
    if (NS_SUCCEEDED(file->Exists(&exists)) && exists) {
      loaded = NS_SUCCEEDED(mConfig.Load(file));
    }
  }
  
  nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
  NS_ENSURE_STATE(prefs);
  prefs->GetIntPref("metrics.event-count", &mEventCount);

  // Update the session id pref for the new session
  static const char kSessionIDPref[] = "metrics.last-session-id";
  PRInt32 sessionID = -1;
  prefs->GetIntPref(kSessionIDPref, &sessionID);
  mSessionID.Cut(0, PR_UINT32_MAX);
  AppendInt(mSessionID, ++sessionID);
  nsresult rv = FlushIntPref(kSessionIDPref, sessionID);
  NS_ENSURE_SUCCESS(rv, rv);
  
  // Start up the collectors
  EnableCollectors();

  // If we didn't load a config file, we should upload as soon as possible.
  InitUploadTimer(!loaded);

  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1088 of file nsMetricsService.cpp.

{
  // Clear out prefs and files associated with metrics collection
  MS_LOG(("Clearing metrics state"));
  FlushClearPref(kUploadTimePref);
  FlushClearPref(kPingTimePref);
  FlushClearPref(kEventCountPref);

  nsCOMPtr<nsIFile> configFile;
  GetConfigFile(getter_AddRefs(configFile));
  if (configFile) {
    configFile->Remove(PR_FALSE);
  }

  nsCOMPtr<nsILocalFile> dataFile;
  GetDataFile(&dataFile);
  if (dataFile) {
    dataFile->Remove(PR_FALSE);
  }

  // Clear our current config and make sure all collectors are disabled
  mConfig.Reset();
  EnableCollectors();
  CreateRoot();  // clear any unflushed events

  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Suspend log collection.

LogEvent calls will be silently ignored while log collection is suspended. For each call to suspend, resume must be called to re-enable log collection.

Initiate the upload of the current event log.

This causes the current event log to be truncated once the upload completes.

Definition at line 1264 of file nsMetricsService.cpp.

{
  // TODO: Prepare a data stream for upload that is prefixed with a PROFILE
  //       event.
 
  if (!CollectionEnabled()) {
    MS_LOG(("Upload disabled"));
    return NS_ERROR_ABORT;
  }
 
  nsCString spec;
  nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
  if (prefs) {
    prefs->GetCharPref("metrics.upload.uri", getter_Copies(spec));
  }
  if (spec.IsEmpty()) {
    MS_LOG(("Upload URI not set"));
    return NS_ERROR_ABORT;
  }

  nsCOMPtr<nsILocalFile> file;
  nsresult rv = GetDataFileForUpload(&file);
  NS_ENSURE_SUCCESS(rv, rv);

  // NOTE: nsIUploadChannel requires a buffered stream to upload...

  nsCOMPtr<nsIFileInputStream> fileStream =
      do_CreateInstance(NS_LOCALFILEINPUTSTREAM_CONTRACTID);
  NS_ENSURE_STATE(fileStream);

  rv = fileStream->Init(file, -1, -1, nsIFileInputStream::DELETE_ON_CLOSE);
  NS_ENSURE_SUCCESS(rv, rv);

  PRUint32 streamLen;
  rv = fileStream->Available(&streamLen);
  NS_ENSURE_SUCCESS(rv, rv);

  if (streamLen == 0)
    return NS_ERROR_ABORT;

  nsCOMPtr<nsIBufferedInputStream> uploadStream =
      do_CreateInstance(NS_BUFFEREDINPUTSTREAM_CONTRACTID);
  NS_ENSURE_STATE(uploadStream);

  rv = uploadStream->Init(fileStream, 4096);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIIOService> ios = do_GetService(NS_IOSERVICE_CONTRACTID);
  NS_ENSURE_STATE(ios);

  nsCOMPtr<nsIChannel> channel;
  ios->NewChannel(spec, nsnull, nsnull, getter_AddRefs(channel));
  NS_ENSURE_STATE(channel); 

  // Tag the channel so that we know it's one of ours.
  nsCOMPtr<nsIWritablePropertyBag2> props = do_QueryInterface(channel);
  NS_ENSURE_STATE(props);
  props->SetPropertyAsBool(NS_LITERAL_STRING("moz-metrics-request"), PR_TRUE);

  nsCOMPtr<nsIInterfaceRequestor> certListener = new BadCertListener();
  NS_ENSURE_TRUE(certListener, NS_ERROR_OUT_OF_MEMORY);

  channel->SetNotificationCallbacks(certListener);

  nsCOMPtr<nsIUploadChannel> uploadChannel = do_QueryInterface(channel);
  NS_ENSURE_STATE(uploadChannel); 

  NS_NAMED_LITERAL_CSTRING(binaryType, NS_METRICS_MIME_TYPE);
  rv = uploadChannel->SetUploadStream(uploadStream, binaryType, -1);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel);
  NS_ENSURE_STATE(httpChannel);
  rv = httpChannel->SetRequestMethod(NS_LITERAL_CSTRING("POST"));
  NS_ENSURE_SUCCESS(rv, rv);

  rv = channel->AsyncOpen(this, nsnull);
  NS_ENSURE_SUCCESS(rv, rv);

  return NS_OK;
}

Here is the call graph for this function:

Definition at line 130 of file nsMetricsService.h.

  {
    return mWindowMap;
  }

Here is the caller graph for this function:


Member Data Documentation

Definition at line 275 of file nsMetricsService.h.

Definition at line 283 of file nsMetricsService.h.

Definition at line 268 of file nsMetricsService.h.

Definition at line 250 of file nsMetricsService.h.

Definition at line 253 of file nsMetricsService.h.

Definition at line 256 of file nsMetricsService.h.

Definition at line 285 of file nsMetricsService.h.

Definition at line 262 of file nsMetricsService.h.

Definition at line 290 of file nsMetricsService.h.

Definition at line 293 of file nsMetricsService.h.

Definition at line 259 of file nsMetricsService.h.

Definition at line 288 of file nsMetricsService.h.

Definition at line 286 of file nsMetricsService.h.

Definition at line 287 of file nsMetricsService.h.

Definition at line 271 of file nsMetricsService.h.

Definition at line 265 of file nsMetricsService.h.

Definition at line 245 of file nsMetricsService.h.


The documentation for this class was generated from the following files: