mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 15:25:52 +00:00
fixes bug 334044 "build metrics as a standalone extension" r=bryner
This commit is contained in:
parent
f8f42ac8a8
commit
c256dfbe2b
@ -42,6 +42,8 @@ VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
XPI_NAME = metrics
|
||||
|
||||
DIRS = public src
|
||||
|
||||
PREF_JS_EXPORTS = $(srcdir)/metrics.js
|
||||
|
@ -43,6 +43,7 @@ VPATH = @srcdir@
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = metrics
|
||||
XPI_NAME = metrics
|
||||
|
||||
XPIDLSRCS = nsIMetricsService.idl
|
||||
|
||||
|
@ -46,7 +46,8 @@ MODULE = metrics
|
||||
LIBRARY_NAME = metrics
|
||||
SHORT_LIBNAME = metrics
|
||||
IS_COMPONENT = 1
|
||||
MOZILLA_INTERNAL_API = 1
|
||||
|
||||
XPI_NAME = metrics
|
||||
|
||||
REQUIRES = xpcom \
|
||||
string \
|
||||
@ -60,6 +61,7 @@ REQUIRES = xpcom \
|
||||
widget \
|
||||
xmlextras \
|
||||
libbz2 \
|
||||
caps \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
@ -69,11 +71,13 @@ CPPSRCS = \
|
||||
nsMetricsModule.cpp \
|
||||
nsMetricsService.cpp \
|
||||
nsWindowCollector.cpp \
|
||||
nsStringUtils.cpp \
|
||||
$(NULL)
|
||||
|
||||
SHARED_LIBRARY_LIBS += $(DIST)/lib/$(LIB_PREFIX)bz2.$(LIB_SUFFIX)
|
||||
|
||||
EXTRA_DSO_LDOPTS = $(MOZ_COMPONENT_LIBS) \
|
||||
EXTRA_DSO_LDOPTS = $(XPCOM_GLUE_LDOPTS) \
|
||||
$(NSPR_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
@ -43,16 +43,23 @@
|
||||
#include "nsCURILoader.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIWebProgress.h"
|
||||
#include "nsDocShellLoadTypes.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
// This is needed to gain access to the LOAD_ defines in this file.
|
||||
#define MOZILLA_INTERNAL_API
|
||||
#include "nsDocShellLoadTypes.h"
|
||||
#undef MOZILLA_INTERNAL_API
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#if defined(__linux)
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
static FILE *sProcFP;
|
||||
static void GetMemUsage_Shutdown() {
|
||||
if (sProcFP) {
|
||||
@ -62,7 +69,23 @@ static void GetMemUsage_Shutdown() {
|
||||
}
|
||||
#elif defined(XP_WIN)
|
||||
#include <windows.h>
|
||||
#if _MSC_VER > 1200
|
||||
#include <psapi.h>
|
||||
#else
|
||||
typedef struct _PROCESS_MEMORY_COUNTERS {
|
||||
DWORD cb;
|
||||
DWORD PageFaultCount;
|
||||
SIZE_T PeakWorkingSetSize;
|
||||
SIZE_T WorkingSetSize;
|
||||
SIZE_T QuotaPeakPagedPoolUsage;
|
||||
SIZE_T QuotaPagedPoolUsage;
|
||||
SIZE_T QuotaPeakNonPagedPoolUsage;
|
||||
SIZE_T QuotaNonPagedPoolUsage;
|
||||
SIZE_T PagefileUsage;
|
||||
SIZE_T PeakPagefileUsage;
|
||||
} PROCESS_MEMORY_COUNTERS;
|
||||
typedef PROCESS_MEMORY_COUNTERS *PPROCESS_MEMORY_COUNTERS;
|
||||
#endif
|
||||
typedef BOOL (WINAPI * GETPROCESSMEMORYINFO_FUNC)(
|
||||
HANDLE process, PPROCESS_MEMORY_COUNTERS counters, DWORD cb);
|
||||
static HMODULE sPSModule;
|
||||
@ -177,7 +200,7 @@ nsLoadCollector::OnStateChange(nsIWebProgress *webProgress,
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
if (MS_LOG_ENABLED()) {
|
||||
nsCAutoString name;
|
||||
nsCString name;
|
||||
request->GetName(name);
|
||||
|
||||
MS_LOG(("LoadCollector: progress = %p, request = %p [%s], flags = %x, status = %x",
|
||||
@ -205,10 +228,10 @@ nsLoadCollector::OnStateChange(nsIWebProgress *webProgress,
|
||||
|
||||
rv = nsMetricsUtils::NewPropertyBag(getter_AddRefs(entry.properties));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsHashPropertyBag *props = entry.properties;
|
||||
nsIWritablePropertyBag2 *props = entry.properties;
|
||||
|
||||
rv = nsMetricsUtils::PutUint16(props, NS_LITERAL_STRING("window"),
|
||||
nsMetricsService::GetWindowID(window));
|
||||
rv = props->SetPropertyAsUint32(NS_LITERAL_STRING("window"),
|
||||
nsMetricsService::GetWindowID(window));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (flags & STATE_RESTORING) {
|
||||
@ -216,7 +239,7 @@ nsLoadCollector::OnStateChange(nsIWebProgress *webProgress,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
nsAutoString origin;
|
||||
nsString origin;
|
||||
PRUint32 loadType;
|
||||
docShell->GetLoadType(&loadType);
|
||||
|
||||
@ -224,29 +247,29 @@ nsLoadCollector::OnStateChange(nsIWebProgress *webProgress,
|
||||
case LOAD_NORMAL:
|
||||
case LOAD_NORMAL_REPLACE:
|
||||
case LOAD_BYPASS_HISTORY:
|
||||
origin.AssignLiteral("typed");
|
||||
origin = NS_LITERAL_STRING("typed");
|
||||
break;
|
||||
case LOAD_NORMAL_EXTERNAL:
|
||||
origin.AssignLiteral("external");
|
||||
origin = NS_LITERAL_STRING("external");
|
||||
break;
|
||||
case LOAD_HISTORY:
|
||||
origin.AssignLiteral("session-history");
|
||||
origin = NS_LITERAL_STRING("session-history");
|
||||
break;
|
||||
case LOAD_RELOAD_NORMAL:
|
||||
case LOAD_RELOAD_BYPASS_CACHE:
|
||||
case LOAD_RELOAD_BYPASS_PROXY:
|
||||
case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
|
||||
case LOAD_RELOAD_CHARSET_CHANGE:
|
||||
origin.AssignLiteral("reload");
|
||||
origin = NS_LITERAL_STRING("reload");
|
||||
break;
|
||||
case LOAD_LINK:
|
||||
origin.AssignLiteral("link");
|
||||
origin = NS_LITERAL_STRING("link");
|
||||
break;
|
||||
case LOAD_REFRESH:
|
||||
origin.AssignLiteral("refresh");
|
||||
origin = NS_LITERAL_STRING("refresh");
|
||||
break;
|
||||
default:
|
||||
origin.AssignLiteral("other");
|
||||
origin = NS_LITERAL_STRING("other");
|
||||
break;
|
||||
}
|
||||
rv = props->SetPropertyAsAString(NS_LITERAL_STRING("origin"), origin);
|
||||
@ -258,7 +281,7 @@ nsLoadCollector::OnStateChange(nsIWebProgress *webProgress,
|
||||
if (mRequestMap.Get(request, &entry)) {
|
||||
// Log a <document action="load"> event
|
||||
|
||||
nsHashPropertyBag *props = entry.properties;
|
||||
nsIWritablePropertyBag2 *props = entry.properties;
|
||||
rv = props->SetPropertyAsACString(NS_LITERAL_STRING("action"),
|
||||
NS_LITERAL_CSTRING("load"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -63,10 +63,10 @@
|
||||
// loadtime: The elapsed time for the load, in milliseconds (uint32).
|
||||
|
||||
#include "nsIWebProgressListener.h"
|
||||
#include "nsIWritablePropertyBag2.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsHashPropertyBag.h"
|
||||
|
||||
class nsLoadCollector : public nsIWebProgressListener,
|
||||
public nsSupportsWeakReference
|
||||
@ -87,7 +87,7 @@ class nsLoadCollector : public nsIWebProgressListener,
|
||||
nsresult Init();
|
||||
|
||||
struct RequestEntry {
|
||||
nsRefPtr<nsHashPropertyBag> properties;
|
||||
nsCOMPtr<nsIWritablePropertyBag2> properties;
|
||||
PRTime startTime;
|
||||
};
|
||||
|
||||
|
@ -37,38 +37,44 @@
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsMetricsService.h"
|
||||
#include "nsStringUtils.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMParser.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOM3Node.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsIFileStreams.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "prprf.h"
|
||||
|
||||
#define NS_DEFAULT_UPLOAD_INTERVAL 3600 // 1 hour
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static const nsAutoString
|
||||
static const nsString
|
||||
MakeKey(const nsAString &eventNS, const nsAString &eventName)
|
||||
{
|
||||
// Since eventName must be a valid XML NCName, we can use ':' to separate
|
||||
// eventName from eventNS when formulating our hash key.
|
||||
NS_ASSERTION(eventName.FindChar(':') == kNotFound, "Not a valid NCName");
|
||||
NS_ASSERTION(FindChar(eventName, ':') == -1, "Not a valid NCName");
|
||||
|
||||
return nsAutoString(eventName + NS_LITERAL_STRING(":") + eventNS);
|
||||
nsString key;
|
||||
key.Append(eventName);
|
||||
key.Append(':');
|
||||
key.Append(eventNS);
|
||||
return key;
|
||||
}
|
||||
|
||||
// This method leaves the result value unchanged if a parsing error occurs.
|
||||
static void
|
||||
ReadIntegerAttr(nsIDOMElement *elem, const nsAString &attrName, PRInt32 *result)
|
||||
{
|
||||
nsAutoString attrValue;
|
||||
nsString attrValue;
|
||||
elem->GetAttribute(attrName, attrValue);
|
||||
|
||||
PRInt32 errcode;
|
||||
PRInt32 parsedVal = attrValue.ToInteger(&errcode);
|
||||
|
||||
if (NS_SUCCEEDED(errcode))
|
||||
*result = parsedVal;
|
||||
NS_ConvertUTF16toUTF8 attrValueUtf8(attrValue);
|
||||
PR_sscanf(attrValueUtf8.get(), "%ld", result);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -123,15 +129,17 @@ nsMetricsConfig::Load(nsIFile *file)
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_STATE(fileSize <= PR_INT32_MAX);
|
||||
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
NS_NewLocalFileInputStream(getter_AddRefs(stream), file);
|
||||
nsCOMPtr<nsIFileInputStream> stream =
|
||||
do_CreateInstance(NS_LOCALFILEINPUTSTREAM_CONTRACTID);
|
||||
NS_ENSURE_STATE(stream);
|
||||
rv = stream->Init(file, -1, -1, 0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDOMParser> parser = do_CreateInstance(NS_DOMPARSER_CONTRACTID);
|
||||
NS_ENSURE_STATE(parser);
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> doc;
|
||||
parser->ParseFromStream(stream, nsnull, fileSize, "application/xml",
|
||||
parser->ParseFromStream(stream, nsnull, PRInt32(fileSize), "application/xml",
|
||||
getter_AddRefs(doc));
|
||||
NS_ENSURE_STATE(doc);
|
||||
|
||||
@ -159,9 +167,9 @@ nsMetricsConfig::ForEachChildElement(nsIDOMElement *elem,
|
||||
nsCOMPtr<nsIDOMElement> childElem = do_QueryInterface(node);
|
||||
if (childElem) {
|
||||
// Skip elements that are not in our namespace
|
||||
nsAutoString namespaceURI;
|
||||
nsString namespaceURI;
|
||||
childElem->GetNamespaceURI(namespaceURI);
|
||||
if (namespaceURI.EqualsLiteral(NS_METRICS_NAMESPACE))
|
||||
if (namespaceURI.Equals(NS_LITERAL_STRING(NS_METRICS_NAMESPACE)))
|
||||
(this->*callback)(childElem);
|
||||
}
|
||||
node->GetNextSibling(getter_AddRefs(next));
|
||||
@ -174,14 +182,14 @@ nsMetricsConfig::ProcessToplevelElement(nsIDOMElement *elem)
|
||||
{
|
||||
// Process a top-level element
|
||||
|
||||
nsAutoString name;
|
||||
nsString name;
|
||||
elem->GetLocalName(name);
|
||||
if (name.EqualsLiteral("collectors")) {
|
||||
if (name.Equals(NS_LITERAL_STRING("collectors"))) {
|
||||
// Enumerate <collector> elements
|
||||
ForEachChildElement(elem, &nsMetricsConfig::ProcessCollectorElement);
|
||||
} else if (name.EqualsLiteral("limit")) {
|
||||
} else if (name.Equals(NS_LITERAL_STRING("limit"))) {
|
||||
ReadIntegerAttr(elem, NS_LITERAL_STRING("events"), &mEventLimit);
|
||||
} else if (name.EqualsLiteral("upload")) {
|
||||
} else if (name.Equals(NS_LITERAL_STRING("upload"))) {
|
||||
ReadIntegerAttr(elem, NS_LITERAL_STRING("interval"), &mUploadInterval);
|
||||
}
|
||||
}
|
||||
@ -189,37 +197,36 @@ nsMetricsConfig::ProcessToplevelElement(nsIDOMElement *elem)
|
||||
void
|
||||
nsMetricsConfig::ProcessCollectorElement(nsIDOMElement *elem)
|
||||
{
|
||||
nsAutoString value;
|
||||
|
||||
// Make sure we are dealing with a <collector> element.
|
||||
elem->GetLocalName(value);
|
||||
if (!value.EqualsLiteral("collector"))
|
||||
return;
|
||||
value.Truncate();
|
||||
|
||||
elem->GetAttribute(NS_LITERAL_STRING("type"), value);
|
||||
if (value.IsEmpty())
|
||||
nsString localName;
|
||||
elem->GetLocalName(localName);
|
||||
if (!localName.Equals(NS_LITERAL_STRING("collector")))
|
||||
return;
|
||||
|
||||
// Get the namespace URI specified by any prefix of value.
|
||||
nsString type;
|
||||
elem->GetAttribute(NS_LITERAL_STRING("type"), type);
|
||||
if (type.IsEmpty())
|
||||
return;
|
||||
|
||||
// Get the namespace URI specified by any prefix of |type|.
|
||||
nsCOMPtr<nsIDOM3Node> node = do_QueryInterface(elem);
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
// Check to see if this value references a specific namespace.
|
||||
PRInt32 colon = value.FindChar(':');
|
||||
// Check to see if this type references a specific namespace.
|
||||
PRInt32 colon = FindChar(type, ':');
|
||||
|
||||
nsAutoString namespaceURI;
|
||||
if (colon == kNotFound) {
|
||||
nsString namespaceURI;
|
||||
if (colon == -1) {
|
||||
node->LookupNamespaceURI(EmptyString(), namespaceURI);
|
||||
// value is the EventName
|
||||
} else {
|
||||
// value is NamespacePrefix + ":" + EventName
|
||||
node->LookupNamespaceURI(StringHead(value, colon), namespaceURI);
|
||||
value.Cut(0, colon + 1);
|
||||
node->LookupNamespaceURI(StringHead(type, colon), namespaceURI);
|
||||
type.Cut(0, colon + 1);
|
||||
}
|
||||
|
||||
mEventSet.PutEntry(MakeKey(namespaceURI, value));
|
||||
mEventSet.PutEntry(MakeKey(namespaceURI, type));
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "nsHashKeys.h"
|
||||
|
||||
class nsIDOMElement;
|
||||
class nsIFile;
|
||||
|
||||
class nsMetricsConfig
|
||||
{
|
||||
|
@ -82,9 +82,7 @@ nsMetricsEventItem::SetProperties(nsIPropertyBag *aProperties)
|
||||
NS_IMETHODIMP
|
||||
nsMetricsEventItem::ChildAt(PRInt32 index, nsIMetricsEventItem **result)
|
||||
{
|
||||
if (index < 0 || index >= mChildren.Count()) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
NS_ENSURE_ARG_RANGE(index, 0, PRInt32(mChildren.Length()) - 1);
|
||||
|
||||
NS_ADDREF(*result = mChildren[index]);
|
||||
return NS_OK;
|
||||
@ -93,7 +91,7 @@ nsMetricsEventItem::ChildAt(PRInt32 index, nsIMetricsEventItem **result)
|
||||
NS_IMETHODIMP
|
||||
nsMetricsEventItem::IndexOf(nsIMetricsEventItem *item, PRInt32 *result)
|
||||
{
|
||||
*result = mChildren.IndexOf(item);
|
||||
*result = PRInt32(mChildren.IndexOf(item)); // NoIndex mapped to -1
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -102,7 +100,7 @@ nsMetricsEventItem::AppendChild(nsIMetricsEventItem *item)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(item);
|
||||
|
||||
NS_ENSURE_TRUE(mChildren.AppendObject(item), NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_TRUE(mChildren.AppendElement(item), NS_ERROR_OUT_OF_MEMORY);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -110,11 +108,11 @@ NS_IMETHODIMP
|
||||
nsMetricsEventItem::InsertChildAt(nsIMetricsEventItem *item, PRInt32 index)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(item);
|
||||
if (index < 0 || index > mChildren.Count()) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
NS_ENSURE_TRUE(mChildren.InsertObjectAt(item, index),
|
||||
// allow appending
|
||||
NS_ENSURE_ARG_RANGE(index, 0, PRInt32(mChildren.Length()));
|
||||
|
||||
NS_ENSURE_TRUE(mChildren.InsertElementAt(index, item),
|
||||
NS_ERROR_OUT_OF_MEMORY);
|
||||
return NS_OK;
|
||||
}
|
||||
@ -122,11 +120,9 @@ nsMetricsEventItem::InsertChildAt(nsIMetricsEventItem *item, PRInt32 index)
|
||||
NS_IMETHODIMP
|
||||
nsMetricsEventItem::RemoveChildAt(PRInt32 index)
|
||||
{
|
||||
if (index < 0 || index >= mChildren.Count()) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
NS_ENSURE_ARG_RANGE(index, 0, PRInt32(mChildren.Length()) - 1);
|
||||
|
||||
mChildren.RemoveObjectAt(index);
|
||||
mChildren.RemoveElementAt(index);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -134,11 +130,9 @@ NS_IMETHODIMP
|
||||
nsMetricsEventItem::ReplaceChildAt(nsIMetricsEventItem *newItem, PRInt32 index)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(newItem);
|
||||
if (index < 0 || index >= mChildren.Count()) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
NS_ENSURE_ARG_RANGE(index, 0, PRInt32(mChildren.Length()) - 1);
|
||||
|
||||
mChildren.ReplaceObjectAt(newItem, index);
|
||||
mChildren.ReplaceElementsAt(index, 1, newItem);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -152,6 +146,6 @@ nsMetricsEventItem::ClearChildren()
|
||||
NS_IMETHODIMP
|
||||
nsMetricsEventItem::GetChildCount(PRInt32 *childCount)
|
||||
{
|
||||
*childCount = mChildren.Count();
|
||||
*childCount = PRInt32(mChildren.Length());
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -40,9 +40,9 @@
|
||||
#define nsMetricsEventItem_h__
|
||||
|
||||
#include "nsIMetricsService.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "nsStringAPI.h"
|
||||
|
||||
class nsIPropertyBag;
|
||||
|
||||
@ -63,7 +63,7 @@ class nsMetricsEventItem : public nsIMetricsEventItem
|
||||
nsString mNamespace;
|
||||
nsString mName;
|
||||
nsCOMPtr<nsIPropertyBag> mProperties;
|
||||
nsCOMArray<nsIMetricsEventItem> mChildren;
|
||||
nsTArray< nsCOMPtr<nsIMetricsEventItem> > mChildren;
|
||||
};
|
||||
|
||||
#endif // nsMetricsEventItem_h__
|
||||
|
@ -38,11 +38,14 @@
|
||||
|
||||
#include "nsMetricsService.h"
|
||||
#include "nsMetricsEventItem.h"
|
||||
#include "nsStringUtils.h"
|
||||
#include "nsXPCOM.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsDirectoryServiceUtils.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIUpdateService.h"
|
||||
#include "nsIUploadChannel.h"
|
||||
@ -58,19 +61,31 @@
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMSerializer.h"
|
||||
#include "nsIVariant.h"
|
||||
#include "nsICryptoHash.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsIInputStreamChannel.h"
|
||||
#include "nsIFileStreams.h"
|
||||
#include "nsIBufferedStreams.h"
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "nsMultiplexInputStream.h"
|
||||
#include "nsStringStream.h"
|
||||
#include "nsStreamUtils.h"
|
||||
#include "nsVariant.h"
|
||||
#include "prtime.h"
|
||||
#include "prmem.h"
|
||||
#include "prprf.h"
|
||||
#include "prrng.h"
|
||||
#include "bzlib.h"
|
||||
#ifndef MOZILLA_1_8_BRANCH
|
||||
#include "nsIClassInfoImpl.h"
|
||||
#endif
|
||||
#include "nsIUUIDGenerator.h"
|
||||
#include "nsDocShellCID.h"
|
||||
#include "nsMemory.h"
|
||||
|
||||
// We need to suppress inclusion of nsString.h
|
||||
#define nsString_h___
|
||||
#include "nsIStringStream.h"
|
||||
#undef nsString_h___
|
||||
|
||||
// Make our MIME type inform the server of possible compression.
|
||||
#ifdef NS_METRICS_SEND_UNCOMPRESSED_DATA
|
||||
@ -93,6 +108,64 @@ static const char kQuitApplicationTopic[] = "quit-application";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef NS_METRICS_SEND_UNCOMPRESSED_DATA
|
||||
|
||||
// Compress data read from |src|, and write to |outFd|.
|
||||
static nsresult
|
||||
CompressBZ2(nsIInputStream *src, PRFileDesc *outFd)
|
||||
{
|
||||
// compress the data chunk-by-chunk
|
||||
|
||||
char inbuf[4096], outbuf[4096];
|
||||
bz_stream strm;
|
||||
int ret = BZ_OK;
|
||||
|
||||
memset(&strm, 0, sizeof(strm));
|
||||
|
||||
if (BZ2_bzCompressInit(&strm, 9 /*max blocksize*/, 0, 0) != BZ_OK)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
for (;;) {
|
||||
if (strm.avail_in == 0) {
|
||||
// fill inbuf
|
||||
PRUint32 n;
|
||||
rv = src->Read(inbuf, sizeof(inbuf), &n);
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
strm.next_in = inbuf;
|
||||
strm.avail_in = (int) n;
|
||||
}
|
||||
|
||||
strm.next_out = outbuf;
|
||||
strm.avail_out = sizeof(outbuf);
|
||||
|
||||
ret = BZ2_bzCompress(&strm, 0);
|
||||
if (ret != BZ_OK && ret != BZ_STREAM_END) {
|
||||
rv = NS_ERROR_UNEXPECTED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (strm.avail_out < sizeof(outbuf)) {
|
||||
PRInt32 n = sizeof(outbuf) - strm.avail_out;
|
||||
if (PR_Write(outFd, outbuf, n) != n) {
|
||||
rv = NS_ERROR_UNEXPECTED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == BZ_STREAM_END)
|
||||
break;
|
||||
}
|
||||
|
||||
BZ2_bzCompressEnd(&strm);
|
||||
return rv;
|
||||
}
|
||||
|
||||
#endif // !defined(NS_METRICS_SEND_UNCOMPRESSED_DATA)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
nsMetricsService::nsMetricsService()
|
||||
: mEventCount(0),
|
||||
mSuspendCount(0),
|
||||
@ -133,7 +206,7 @@ nsMetricsService::BuildEventItem(nsIMetricsEventItem *item,
|
||||
{
|
||||
*itemElement = nsnull;
|
||||
|
||||
nsAutoString itemNS, itemName;
|
||||
nsString itemNS, itemName;
|
||||
item->GetItemNamespace(itemNS);
|
||||
item->GetItemName(itemName);
|
||||
|
||||
@ -159,7 +232,7 @@ nsMetricsService::BuildEventItem(nsIMetricsEventItem *item,
|
||||
continue;
|
||||
}
|
||||
|
||||
nsAutoString name;
|
||||
nsString name;
|
||||
rv = property->GetName(name);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Failed to get property name");
|
||||
@ -178,7 +251,7 @@ nsMetricsService::BuildEventItem(nsIMetricsEventItem *item,
|
||||
PRUint16 dataType;
|
||||
value->GetDataType(&dataType);
|
||||
|
||||
nsAutoString valueString;
|
||||
nsString valueString;
|
||||
if (dataType == nsIDataType::VTYPE_BOOL) {
|
||||
PRBool valueBool;
|
||||
rv = value->GetAsBool(&valueBool);
|
||||
@ -238,7 +311,7 @@ nsMetricsService::LogEvent(nsIMetricsEventItem *item)
|
||||
return NS_OK;
|
||||
|
||||
// Restrict the types of events logged
|
||||
nsAutoString eventNS, eventName;
|
||||
nsString eventNS, eventName;
|
||||
item->GetItemNamespace(eventNS);
|
||||
item->GetItemName(eventName);
|
||||
|
||||
@ -251,8 +324,8 @@ nsMetricsService::LogEvent(nsIMetricsEventItem *item)
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Add the event timestamp
|
||||
nsAutoString timeString;
|
||||
timeString.AppendInt(PR_Now() / PR_USEC_PER_SEC);
|
||||
nsString timeString;
|
||||
AppendInt(timeString, PR_Now() / PR_USEC_PER_SEC);
|
||||
rv = eventElement->SetAttribute(NS_LITERAL_STRING("time"), timeString);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
@ -301,15 +374,15 @@ nsMetricsService::Flush()
|
||||
do_CreateInstance(NS_XMLSERIALIZER_CONTRACTID);
|
||||
NS_ENSURE_TRUE(ds, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsAutoString docText;
|
||||
nsString docText;
|
||||
rv = ds->SerializeToString(mRoot, docText);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// The first '>' will be the end of the root start tag.
|
||||
docText.Cut(0, docText.FindChar('>') + 1);
|
||||
docText.Cut(0, FindChar(docText, '>') + 1);
|
||||
|
||||
// The last '<' will be the beginning of the root end tag.
|
||||
PRInt32 start = docText.RFindChar('<');
|
||||
PRInt32 start = RFindChar(docText, '<');
|
||||
docText.Cut(start, docText.Length() - start);
|
||||
|
||||
NS_ConvertUTF16toUTF8 utf8Doc(docText);
|
||||
@ -384,12 +457,40 @@ nsMetricsService::NewChannel(nsIURI *uri, nsIChannel **result)
|
||||
GetDataFile(&dataFile);
|
||||
NS_ENSURE_STATE(dataFile);
|
||||
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
OpenCompleteXMLStream(dataFile, getter_AddRefs(stream));
|
||||
NS_ENSURE_STATE(stream);
|
||||
nsCOMPtr<nsIInputStreamChannel> streamChannel =
|
||||
do_CreateInstance(NS_INPUTSTREAMCHANNEL_CONTRACTID);
|
||||
NS_ENSURE_STATE(streamChannel);
|
||||
|
||||
return NS_NewInputStreamChannel(result, uri, stream,
|
||||
NS_LITERAL_CSTRING("text/xml"), nsnull);
|
||||
rv = streamChannel->SetURI(uri);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(streamChannel, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool val;
|
||||
if (NS_SUCCEEDED(dataFile->Exists(&val)) && val) {
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
OpenCompleteXMLStream(dataFile, getter_AddRefs(stream));
|
||||
NS_ENSURE_STATE(stream);
|
||||
|
||||
rv = streamChannel->SetContentStream(stream);
|
||||
rv |= channel->SetContentType(NS_LITERAL_CSTRING("text/xml"));
|
||||
} else {
|
||||
nsCOMPtr<nsIStringInputStream> errorStream =
|
||||
do_CreateInstance("@mozilla.org/io/string-input-stream;1");
|
||||
NS_ENSURE_STATE(errorStream);
|
||||
|
||||
rv = errorStream->SetData("no metrics data", -1);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = streamChannel->SetContentStream(errorStream);
|
||||
rv |= channel->SetContentType(NS_LITERAL_CSTRING("text/plain"));
|
||||
}
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
|
||||
|
||||
NS_ADDREF(*result = channel);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -400,8 +501,15 @@ nsMetricsService::OnStartRequest(nsIRequest *request, nsISupports *context)
|
||||
nsCOMPtr<nsIFile> file;
|
||||
GetConfigFile(getter_AddRefs(file));
|
||||
|
||||
NS_NewLocalFileOutputStream(getter_AddRefs(mConfigOutputStream), file,
|
||||
PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE);
|
||||
nsCOMPtr<nsIFileOutputStream> out =
|
||||
do_CreateInstance(NS_LOCALFILEOUTPUTSTREAM_CONTRACTID);
|
||||
NS_ENSURE_STATE(out);
|
||||
|
||||
nsresult rv = out->Init(file, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, -1,
|
||||
0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mConfigOutputStream = out;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -461,13 +569,36 @@ nsMetricsService::EnableCollectors()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Copied from nsStreamUtils.cpp:
|
||||
static NS_METHOD
|
||||
CopySegmentToStream(nsIInputStream *inStr,
|
||||
void *closure,
|
||||
const char *buffer,
|
||||
PRUint32 offset,
|
||||
PRUint32 count,
|
||||
PRUint32 *countWritten)
|
||||
{
|
||||
nsIOutputStream *outStr = NS_STATIC_CAST(nsIOutputStream *, closure);
|
||||
*countWritten = 0;
|
||||
while (count) {
|
||||
PRUint32 n;
|
||||
nsresult rv = outStr->Write(buffer, count, &n);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
buffer += n;
|
||||
count -= n;
|
||||
*countWritten += n;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMetricsService::OnDataAvailable(nsIRequest *request, nsISupports *context,
|
||||
nsIInputStream *stream, PRUint32 offset,
|
||||
PRUint32 count)
|
||||
{
|
||||
PRUint32 n;
|
||||
return stream->ReadSegments(NS_CopySegmentToStream, mConfigOutputStream,
|
||||
return stream->ReadSegments(CopySegmentToStream, mConfigOutputStream,
|
||||
count, &n);
|
||||
}
|
||||
|
||||
@ -523,8 +654,8 @@ nsMetricsService::ProfileStartup()
|
||||
static const char kSessionIDPref[] = "metrics.last-session-id";
|
||||
PRInt32 sessionID = -1;
|
||||
prefs->GetIntPref(kSessionIDPref, &sessionID);
|
||||
mSessionID.Truncate();
|
||||
mSessionID.AppendInt(++sessionID);
|
||||
mSessionID.Cut(0, PR_UINT32_MAX);
|
||||
AppendInt(mSessionID, ++sessionID);
|
||||
rv = prefs->SetIntPref(kSessionIDPref, sessionID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
@ -678,7 +809,7 @@ nsMetricsService::UploadData()
|
||||
// event.
|
||||
|
||||
PRBool enable = PR_FALSE;
|
||||
nsXPIDLCString spec;
|
||||
nsCString spec;
|
||||
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
if (prefs) {
|
||||
prefs->GetBoolPref("metrics.upload.enable", &enable);
|
||||
@ -693,11 +824,13 @@ nsMetricsService::UploadData()
|
||||
|
||||
// NOTE: nsIUploadChannel requires a buffered stream to upload...
|
||||
|
||||
nsCOMPtr<nsIInputStream> fileStream;
|
||||
NS_NewLocalFileInputStream(getter_AddRefs(fileStream), file, -1, -1,
|
||||
nsIFileInputStream::DELETE_ON_CLOSE);
|
||||
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);
|
||||
@ -705,11 +838,14 @@ nsMetricsService::UploadData()
|
||||
if (streamLen == 0)
|
||||
return NS_ERROR_ABORT;
|
||||
|
||||
nsCOMPtr<nsIInputStream> uploadStream;
|
||||
NS_NewBufferedInputStream(getter_AddRefs(uploadStream), fileStream, 4096);
|
||||
nsCOMPtr<nsIBufferedInputStream> uploadStream =
|
||||
do_CreateInstance(NS_BUFFEREDINPUTSTREAM_CONTRACTID);
|
||||
NS_ENSURE_STATE(uploadStream);
|
||||
|
||||
nsCOMPtr<nsIIOService> ios = do_GetIOService();
|
||||
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;
|
||||
@ -749,19 +885,20 @@ nsMetricsService::GetDataFileForUpload(nsCOMPtr<nsILocalFile> *result)
|
||||
rv = input->Clone(getter_AddRefs(temp));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCAutoString leafName;
|
||||
nsCString leafName;
|
||||
rv = temp->GetNativeLeafName(leafName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
leafName.AppendLiteral(".bz2");
|
||||
leafName.Append(".bz2");
|
||||
rv = temp->SetNativeLeafName(leafName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsILocalFile> ltemp = do_QueryInterface(temp, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
FILE *destFp = NULL;
|
||||
rv = ltemp->OpenANSIFileDesc("wb", &destFp);
|
||||
PRFileDesc *destFd = NULL;
|
||||
rv = ltemp->OpenNSPRFileDesc(PR_WRONLY | PR_TRUNCATE | PR_CREATE_FILE, 0600,
|
||||
&destFd);
|
||||
|
||||
// Copy file using bzip2 compression:
|
||||
|
||||
@ -771,41 +908,19 @@ nsMetricsService::GetDataFileForUpload(nsCOMPtr<nsILocalFile> *result)
|
||||
PRUint32 n;
|
||||
|
||||
while (NS_SUCCEEDED(rv = src->Read(buf, sizeof(buf), &n)) && n) {
|
||||
if (fwrite(buf, 1, n, destFp) != n) {
|
||||
if (PR_Write(destFd, buf, n) != n) {
|
||||
NS_WARNING("failed to write data");
|
||||
rv = NS_ERROR_UNEXPECTED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
int bzerr = BZ_OK;
|
||||
BZFILE *destBz = BZ2_bzWriteOpen(&bzerr, destFp,
|
||||
9, // block size (1-9)
|
||||
0, // verbosity
|
||||
0); // work factor
|
||||
if (destBz) {
|
||||
char buf[4096];
|
||||
PRUint32 n;
|
||||
|
||||
while (NS_SUCCEEDED(rv = src->Read(buf, sizeof(buf), &n)) && n) {
|
||||
BZ2_bzWrite(&bzerr, destBz, buf, n);
|
||||
if (bzerr != BZ_OK) {
|
||||
NS_WARNING("failed to write data");
|
||||
rv = NS_ERROR_UNEXPECTED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BZ2_bzWriteClose(&bzerr, destBz,
|
||||
0, // abandon
|
||||
nsnull, // nbytes_in
|
||||
nsnull); // nbytes_out
|
||||
}
|
||||
rv = CompressBZ2(src, destFd);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (destFp)
|
||||
fclose(destFp);
|
||||
if (destFd)
|
||||
PR_Close(destFd);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
*result = nsnull;
|
||||
@ -826,13 +941,13 @@ nsMetricsService::OpenCompleteXMLStream(nsILocalFile *dataFile,
|
||||
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
NS_ENSURE_STATE(prefs);
|
||||
|
||||
nsXPIDLCString clientID;
|
||||
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 = prefs->SetCharPref(kClientIDPref, clientID);
|
||||
rv = prefs->SetCharPref(kClientIDPref, clientID.get());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
@ -841,37 +956,38 @@ nsMetricsService::OpenCompleteXMLStream(nsILocalFile *dataFile,
|
||||
"<log xmlns=\"" NS_METRICS_NAMESPACE "\" clientid=\"%s\">\n";
|
||||
static const char METRICS_XML_TAIL[] = "</log>";
|
||||
|
||||
nsCOMPtr<nsIInputStream> fileStream;
|
||||
NS_NewLocalFileInputStream(getter_AddRefs(fileStream), dataFile);
|
||||
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);
|
||||
|
||||
char *head = PR_smprintf(METRICS_XML_HEAD, clientID.get());
|
||||
|
||||
nsCOMPtr<nsIInputStream> stringStream;
|
||||
#ifdef MOZILLA_1_8_BRANCH
|
||||
NS_NewCStringInputStream(getter_AddRefs(stringStream),
|
||||
nsDependentCString(head));
|
||||
#else
|
||||
NS_NewByteInputStream(getter_AddRefs(stringStream), head, -1,
|
||||
NS_ASSIGNMENT_COPY);
|
||||
#endif
|
||||
PR_smprintf_free(head);
|
||||
nsCOMPtr<nsIStringInputStream> stringStream =
|
||||
do_CreateInstance("@mozilla.org/io/string-input-stream;1");
|
||||
NS_ENSURE_STATE(stringStream);
|
||||
|
||||
char *head = PR_smprintf(METRICS_XML_HEAD, 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);
|
||||
|
||||
NS_NewByteInputStream(getter_AddRefs(stringStream), METRICS_XML_TAIL,
|
||||
sizeof(METRICS_XML_TAIL)-1);
|
||||
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);
|
||||
|
||||
@ -904,36 +1020,38 @@ nsMetricsService::GetConfigFile(nsIFile **result)
|
||||
nsresult
|
||||
nsMetricsService::GenerateClientID(nsCString &clientID)
|
||||
{
|
||||
nsCOMPtr<nsIUUIDGenerator> idgen =
|
||||
do_GetService("@mozilla.org/uuid-generator;1");
|
||||
NS_ENSURE_STATE(idgen);
|
||||
nsCOMPtr<nsICryptoHash> hasher =
|
||||
do_CreateInstance("@mozilla.org/security/hash;1");
|
||||
NS_ENSURE_STATE(hasher);
|
||||
|
||||
nsID id;
|
||||
nsresult rv = idgen->GenerateUUIDInPlace(&id);
|
||||
nsresult rv = hasher->Init(nsICryptoHash::MD5);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
char *idstr = id.ToString();
|
||||
NS_ENSURE_STATE(idstr);
|
||||
// Feed some data into the hasher...
|
||||
|
||||
// {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
|
||||
static const PRUint32 kGUIDLength = 38;
|
||||
NS_ASSERTION(strlen(idstr) == kGUIDLength, "Invalid GUID string");
|
||||
|
||||
// Strip off the enclosing curly brackets
|
||||
clientID.Assign(idstr + 1, kGUIDLength - 2);
|
||||
PR_Free(idstr);
|
||||
return NS_OK;
|
||||
struct {
|
||||
PRTime a;
|
||||
PRUint8 b[32];
|
||||
} input;
|
||||
|
||||
input.a = PR_Now();
|
||||
PR_GetRandomNoise(input.b, sizeof(input.b));
|
||||
|
||||
rv = hasher->Update((const PRUint8 *) &input, sizeof(input));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return hasher->Finish(PR_TRUE, clientID);
|
||||
}
|
||||
|
||||
/* static */ PRUint16
|
||||
/* static */ PRUint32
|
||||
nsMetricsService::GetWindowID(nsIDOMWindow *window)
|
||||
{
|
||||
if (!sMetricsService) {
|
||||
NS_NOTREACHED("metrics service not created");
|
||||
return PR_UINT16_MAX;
|
||||
return PR_UINT32_MAX;
|
||||
}
|
||||
|
||||
PRUint16 id;
|
||||
PRUint32 id;
|
||||
if (!sMetricsService->mWindowMap.Get(window, &id)) {
|
||||
id = sMetricsService->mNextWindowID++;
|
||||
sMetricsService->mWindowMap.Put(window, id);
|
||||
@ -943,25 +1061,7 @@ nsMetricsService::GetWindowID(nsIDOMWindow *window)
|
||||
}
|
||||
|
||||
/* static */ nsresult
|
||||
nsMetricsUtils::PutUint16(nsIWritablePropertyBag *bag,
|
||||
const nsAString &propertyName,
|
||||
PRUint16 propertyValue)
|
||||
nsMetricsUtils::NewPropertyBag(nsIWritablePropertyBag2 **result)
|
||||
{
|
||||
nsCOMPtr<nsIWritableVariant> var = new nsVariant();
|
||||
NS_ENSURE_TRUE(var, NS_ERROR_OUT_OF_MEMORY);
|
||||
var->SetAsUint16(propertyValue);
|
||||
return bag->SetProperty(propertyName, var);
|
||||
}
|
||||
|
||||
/* static */ nsresult
|
||||
nsMetricsUtils::NewPropertyBag(nsHashPropertyBag **result)
|
||||
{
|
||||
nsRefPtr<nsHashPropertyBag> bag = new nsHashPropertyBag();
|
||||
NS_ENSURE_TRUE(bag, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsresult rv = bag->Init();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bag.swap(*result);
|
||||
return NS_OK;
|
||||
return CallCreateInstance("@mozilla.org/hash-property-bag;1", result);
|
||||
}
|
||||
|
@ -50,7 +50,7 @@
|
||||
#include "nsCOMPtr.h"
|
||||
#include "prio.h"
|
||||
#include "prlog.h"
|
||||
#include "nsHashPropertyBag.h"
|
||||
#include "nsIWritablePropertyBag2.h"
|
||||
#include "nsDataHashtable.h"
|
||||
|
||||
class nsILocalFile;
|
||||
@ -99,23 +99,25 @@ public:
|
||||
|
||||
// Helper function for logging events in the default namespace
|
||||
nsresult LogEvent(const nsAString &eventName,
|
||||
nsHashPropertyBag *eventProperties)
|
||||
nsIWritablePropertyBag2 *eventProperties)
|
||||
{
|
||||
nsCOMPtr<nsIPropertyBag> bag = do_QueryInterface(eventProperties);
|
||||
NS_ENSURE_STATE(bag);
|
||||
return LogSimpleEvent(NS_LITERAL_STRING(NS_METRICS_NAMESPACE), eventName,
|
||||
NS_STATIC_CAST(nsIWritablePropertyBag*,
|
||||
eventProperties));
|
||||
bag);
|
||||
}
|
||||
|
||||
// Get the window id for the given DOMWindow. If a window id has not
|
||||
// yet been assigned for the window, the next id will be used.
|
||||
static PRUint16 GetWindowID(nsIDOMWindow *window);
|
||||
static PRUint32 GetWindowID(nsIDOMWindow *window);
|
||||
|
||||
// VC6 needs this to be public :-(
|
||||
nsresult Init();
|
||||
|
||||
private:
|
||||
nsMetricsService();
|
||||
~nsMetricsService();
|
||||
|
||||
nsresult Init();
|
||||
|
||||
// Post-profile-initialization startup code
|
||||
nsresult ProfileStartup();
|
||||
|
||||
@ -170,28 +172,21 @@ private:
|
||||
nsCOMPtr<nsIDOMNode> mRoot;
|
||||
|
||||
// Window to incrementing-id map. The keys are nsIDOMWindow*.
|
||||
nsDataHashtable<nsVoidPtrHashKey, PRUint16> mWindowMap;
|
||||
nsDataHashtable<nsVoidPtrHashKey, PRUint32> mWindowMap;
|
||||
|
||||
PRInt32 mEventCount;
|
||||
PRInt32 mSuspendCount;
|
||||
PRBool mUploading;
|
||||
nsString mSessionID;
|
||||
// the next window id to hand out
|
||||
PRUint16 mNextWindowID;
|
||||
PRUint32 mNextWindowID;
|
||||
};
|
||||
|
||||
// Helper functions
|
||||
|
||||
class nsMetricsUtils
|
||||
{
|
||||
public:
|
||||
// Stores a PRUint16 into the given property bag.
|
||||
static nsresult PutUint16(nsIWritablePropertyBag *bag,
|
||||
const nsAString &propertyName,
|
||||
PRUint16 propertyValue);
|
||||
|
||||
// Creates a new nsHashPropertyBag instance.
|
||||
static nsresult NewPropertyBag(nsHashPropertyBag **result);
|
||||
// Creates a new nsIWritablePropertyBag2 instance.
|
||||
static nsresult NewPropertyBag(nsIWritablePropertyBag2 **result);
|
||||
};
|
||||
|
||||
#endif // nsMetricsService_h__
|
||||
|
78
extensions/metrics/src/nsStringUtils.cpp
Normal file
78
extensions/metrics/src/nsStringUtils.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Metrics extension.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Google Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Darin Fisher <darin@meer.net>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsStringUtils.h"
|
||||
#include "prprf.h"
|
||||
|
||||
void AppendInt(nsAString &str, PRInt64 val)
|
||||
{
|
||||
char buf[32];
|
||||
PR_snprintf(buf, sizeof(buf), "%lld", val);
|
||||
str.Append(NS_ConvertASCIItoUTF16(buf));
|
||||
}
|
||||
|
||||
void AppendInt(nsAString &str, PRInt32 val)
|
||||
{
|
||||
char buf[32];
|
||||
PR_snprintf(buf, sizeof(buf), "%ld", val);
|
||||
str.Append(NS_ConvertASCIItoUTF16(buf));
|
||||
}
|
||||
|
||||
PRInt32 FindChar(const nsAString &str, PRUnichar c)
|
||||
{
|
||||
const PRUnichar *start;
|
||||
PRUint32 len = NS_StringGetData(str, &start);
|
||||
const PRUnichar *iter = start, *end = start + len;
|
||||
for (; iter != end; ++iter) {
|
||||
if (*iter == c)
|
||||
return iter - start;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
PRInt32 RFindChar(const nsAString &str, PRUnichar c)
|
||||
{
|
||||
const PRUnichar *start;
|
||||
PRUint32 len = NS_StringGetData(str, &start);
|
||||
const PRUnichar *end = start + len, *iter = end - 1;
|
||||
for (; iter >= start; --iter) {
|
||||
if (*iter == c)
|
||||
return iter - start;
|
||||
}
|
||||
return -1;
|
||||
}
|
64
extensions/metrics/src/nsStringUtils.h
Normal file
64
extensions/metrics/src/nsStringUtils.h
Normal file
@ -0,0 +1,64 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Metrics extension.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Google Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Darin Fisher <darin@meer.net>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nsStringUtils_h__
|
||||
#define nsStringUtils_h__
|
||||
|
||||
// TODO: move this into xpcom/glue and extend it with more APIs.
|
||||
|
||||
#include "nsStringAPI.h"
|
||||
|
||||
/**
|
||||
* Append integer to string.
|
||||
*/
|
||||
void AppendInt(nsAString &str, PRInt32 val);
|
||||
void AppendInt(nsAString &str, PRInt64 val);
|
||||
|
||||
/**
|
||||
* Find a char in the given string.
|
||||
* @returns offset of char, or -1 if not found.
|
||||
*/
|
||||
PRInt32 FindChar(const nsAString &str, PRUnichar c);
|
||||
|
||||
/**
|
||||
* Find a char in the given string, searching from the end of the string.
|
||||
* @returns offset of char, or -1 if not found.
|
||||
*/
|
||||
PRInt32 RFindChar(const nsAString &str, PRUnichar c);
|
||||
|
||||
#endif // nsStringUtils_h__
|
@ -44,6 +44,7 @@
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIDocShellTreeItem.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsDocShellCID.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
@ -119,17 +120,17 @@ nsWindowCollector::Observe(nsISupports *subject,
|
||||
const char *topic,
|
||||
const PRUnichar *data)
|
||||
{
|
||||
nsRefPtr<nsHashPropertyBag> properties;
|
||||
nsCOMPtr<nsIWritablePropertyBag2> properties;
|
||||
nsresult rv = nsMetricsUtils::NewPropertyBag(getter_AddRefs(properties));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> window;
|
||||
nsCAutoString action;
|
||||
nsCString action;
|
||||
|
||||
if (strcmp(topic, NS_WEBNAVIGATION_CREATE) == 0 ||
|
||||
strcmp(topic, NS_CHROME_WEBNAVIGATION_CREATE) == 0) {
|
||||
// Log a window creation event.
|
||||
action.AssignLiteral("create");
|
||||
action.Assign("create");
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> item = do_QueryInterface(subject);
|
||||
NS_ENSURE_STATE(item);
|
||||
@ -143,9 +144,8 @@ nsWindowCollector::Observe(nsISupports *subject,
|
||||
item->GetParent(getter_AddRefs(parentItem));
|
||||
nsCOMPtr<nsPIDOMWindow> parentWindow = do_GetInterface(parentItem);
|
||||
if (parentWindow) {
|
||||
PRUint16 id = nsMetricsService::GetWindowID(parentWindow);
|
||||
rv = nsMetricsUtils::PutUint16(properties,
|
||||
NS_LITERAL_STRING("parent"), id);
|
||||
PRUint32 id = nsMetricsService::GetWindowID(parentWindow);
|
||||
rv = properties->SetPropertyAsUint32(NS_LITERAL_STRING("parent"), id);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
@ -155,7 +155,7 @@ nsWindowCollector::Observe(nsISupports *subject,
|
||||
}
|
||||
} else if (strcmp(topic, "toplevel-window-ready") == 0) {
|
||||
// Log a window open event.
|
||||
action.AssignLiteral("open");
|
||||
action.Assign("open");
|
||||
|
||||
window = do_QueryInterface(subject);
|
||||
NS_ENSURE_STATE(window);
|
||||
@ -164,25 +164,24 @@ nsWindowCollector::Observe(nsISupports *subject,
|
||||
window->GetOpener(getter_AddRefs(opener));
|
||||
if (opener) {
|
||||
// Toplevel windows opened from native code have no opener.
|
||||
rv = nsMetricsUtils::PutUint16(properties,
|
||||
NS_LITERAL_STRING("opener"),
|
||||
nsMetricsService::GetWindowID(opener));
|
||||
rv = properties->SetPropertyAsUint32(NS_LITERAL_STRING("opener"),
|
||||
nsMetricsService::GetWindowID(opener));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
} else if (strcmp(topic, "domwindowclosed") == 0) {
|
||||
// Log a window close event.
|
||||
action.AssignLiteral("close");
|
||||
action.Assign("close");
|
||||
window = do_QueryInterface(subject);
|
||||
} else if (strcmp(topic, NS_WEBNAVIGATION_DESTROY) == 0 ||
|
||||
strcmp(topic, NS_CHROME_WEBNAVIGATION_DESTROY) == 0) {
|
||||
// Log a window destroy event.
|
||||
action.AssignLiteral("destroy");
|
||||
action.Assign("destroy");
|
||||
window = do_GetInterface(subject);
|
||||
}
|
||||
|
||||
if (window) {
|
||||
rv = nsMetricsUtils::PutUint16(properties, NS_LITERAL_STRING("windowid"),
|
||||
nsMetricsService::GetWindowID(window));
|
||||
rv = properties->SetPropertyAsUint32(NS_LITERAL_STRING("windowid"),
|
||||
nsMetricsService::GetWindowID(window));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = properties->SetPropertyAsACString(NS_LITERAL_STRING("action"),
|
||||
|
Loading…
Reference in New Issue
Block a user