fixes bug 334044 "build metrics as a standalone extension" r=bryner

This commit is contained in:
darin%meer.net 2006-04-18 22:36:26 +00:00
parent f8f42ac8a8
commit c256dfbe2b
14 changed files with 490 additions and 222 deletions

View File

@ -42,6 +42,8 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
XPI_NAME = metrics
DIRS = public src
PREF_JS_EXPORTS = $(srcdir)/metrics.js

View File

@ -43,6 +43,7 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = metrics
XPI_NAME = metrics
XPIDLSRCS = nsIMetricsService.idl

View File

@ -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

View File

@ -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);

View File

@ -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;
};

View File

@ -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

View File

@ -43,6 +43,7 @@
#include "nsHashKeys.h"
class nsIDOMElement;
class nsIFile;
class nsMetricsConfig
{

View File

@ -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;
}

View File

@ -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__

View File

@ -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);
}

View File

@ -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__

View 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;
}

View 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__

View File

@ -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"),