diff --git a/mozilla/allmakefiles.sh b/mozilla/allmakefiles.sh index 8e558b799db..bd087a2f7c7 100755 --- a/mozilla/allmakefiles.sh +++ b/mozilla/allmakefiles.sh @@ -902,6 +902,11 @@ extensions/typeaheadfind/src/Makefile extensions/typeaheadfind/Makefile " +MAKEFILES_metrics=" +extensions/metrics/Makefile +extensions/metrics/src/Makefile +" + MAKEFILES_phoenix=" browser/Makefile browser/app/Makefile diff --git a/mozilla/extensions/metrics/Makefile.in b/mozilla/extensions/metrics/Makefile.in new file mode 100644 index 00000000000..6d048069a66 --- /dev/null +++ b/mozilla/extensions/metrics/Makefile.in @@ -0,0 +1,49 @@ +# vim:set ts=8 sw=8 sts=8 noet: +# ***** 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 +# +# 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 ***** + +DEPTH = ../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +DIRS = public src tool + +PREF_JS_EXPORTS = $(srcdir)/metrics.js + +include $(topsrcdir)/config/rules.mk diff --git a/mozilla/extensions/metrics/metrics.js b/mozilla/extensions/metrics/metrics.js new file mode 100644 index 00000000000..1eaf0f4ebf0 --- /dev/null +++ b/mozilla/extensions/metrics/metrics.js @@ -0,0 +1,3 @@ +pref("metrics.upload.interval", 86400000); // 24 hrs in msec +pref("metrics.upload.enable", false); +pref("metrics.upload.uri", ""); diff --git a/mozilla/extensions/metrics/public/Makefile.in b/mozilla/extensions/metrics/public/Makefile.in new file mode 100644 index 00000000000..d0cedbffd27 --- /dev/null +++ b/mozilla/extensions/metrics/public/Makefile.in @@ -0,0 +1,54 @@ +# vim:set ts=8 sw=8 sts=8 noet: +# ***** 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 +# +# 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 ***** + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = metrics + +XPIDLSRCS = nsIMetricsService.idl + +EXPORTS = \ + nsMetricsEvent.h \ + nsMetricsModule.h \ + $(NULL) + +include $(topsrcdir)/config/rules.mk diff --git a/mozilla/extensions/metrics/public/nsIMetricsService.idl b/mozilla/extensions/metrics/public/nsIMetricsService.idl new file mode 100644 index 00000000000..8fbc38cef5e --- /dev/null +++ b/mozilla/extensions/metrics/public/nsIMetricsService.idl @@ -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 + * + * 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 "nsISupports.idl" + +[ref] native nsMetricsEvent(const class nsMetricsEvent); + +[scriptable, uuid(614a8246-5c83-422c-8147-28b8a2946b58)] +interface nsIMetricsService : nsISupports +{ + /** + * Log a custom event. The event is recorded with a timestamp generated at + * the time at which this method is called. + * + * @param aEventData + * The data to be logged with this event. + */ + void logCustomEvent(in ACString aEventData); + + /** + * Log a raw metrics event. + */ + [noscript] void logEvent(in nsMetricsEvent aEvent); + + /** + * Initiate the upload of the current event log. This causes the current + * event log to be truncated once the upload completes. + */ + void upload(); + + /** + * 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. + */ + void suspend(); + + /** + * Resume log collection. Call this method once per call to suspend to + * re-enable log collection. + */ + void resume(); +}; diff --git a/mozilla/extensions/metrics/public/nsMetricsEvent.h b/mozilla/extensions/metrics/public/nsMetricsEvent.h new file mode 100644 index 00000000000..3e0383f1410 --- /dev/null +++ b/mozilla/extensions/metrics/public/nsMetricsEvent.h @@ -0,0 +1,99 @@ +/* -*- 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 + * + * 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 nsMetricsEvent_h__ +#define nsMetricsEvent_h__ + +#include "nsTArray.h" + +/** + * Every metrics event has a unique type. This value is constrained to 16-bits. + */ +enum nsMetricsEventType { + NS_METRICS_PROFILE_EVENT, + NS_METRICS_CUSTOM_EVENT, + NS_METRICS_LOAD_EVENT, + NS_METRICS_UI_EVENT, + // Insert additional event types here + NS_METRICS_EVENT_MAX +}; + +/** + * Base class for metric events. This class provides basic structure for each + * event and methods to pack integers and byte arrays into the event. + */ +class nsMetricsEvent { +public: + nsMetricsEvent(nsMetricsEventType type) : mType(type) { + mBuf.SetCapacity(16); + } + + void PutInt8(PRUint8 val) { + mBuf.AppendElement(val); + } + + void PutInt16(PRUint16 val) { + mBuf.AppendElements((PRUint8 *) &val, sizeof(val)); + } + + void PutInt32(PRUint32 val) { + mBuf.AppendElements((PRUint8 *) &val, sizeof(val)); + } + + void PutBytes(const void *ptr, PRUint32 num) { + mBuf.AppendElements((PRUint8 *) ptr, num); + } + + nsMetricsEventType Type() const { + return mType; + } + + const PRUint8 *Buffer() const { + return mBuf.Elements(); + } + + PRUint32 BufferLength() const { + return mBuf.Length(); + } + +private: + nsMetricsEventType mType; + nsTArray mBuf; +}; + +#endif // nsMetricsEvent_h__ diff --git a/mozilla/extensions/metrics/public/nsMetricsModule.h b/mozilla/extensions/metrics/public/nsMetricsModule.h new file mode 100644 index 00000000000..f3288440aa5 --- /dev/null +++ b/mozilla/extensions/metrics/public/nsMetricsModule.h @@ -0,0 +1,52 @@ +/* -*- 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 + * + * 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 nsMetricsModule_h__ +#define nsMetricsModule_h__ + +#define NS_METRICSSERVICE_CLASSNAME "nsMetricsService" +#define NS_METRICSSERVICE_CID \ +{ /* 6f72134c-8855-4c07-b181-90d22bf7a0aa */ \ + 0x6f72134c, \ + 0x8855, \ + 0x4c07, \ + {0xb1, 0x81, 0x90, 0xd2, 0x2b, 0xf7, 0xa0, 0xaa} \ +} +#define NS_METRICSSERVICE_CONTRACTID "@mozilla.org/metrics/service;1" + +#endif // nsMetricsModule_h__ diff --git a/mozilla/extensions/metrics/src/Makefile.in b/mozilla/extensions/metrics/src/Makefile.in new file mode 100644 index 00000000000..2e031ba4db8 --- /dev/null +++ b/mozilla/extensions/metrics/src/Makefile.in @@ -0,0 +1,66 @@ +# vim:set ts=8 sw=8 sts=8 noet: +# ***** 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 +# +# 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 ***** + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = metrics +LIBRARY_NAME = metrics +SHORT_LIBNAME = metrics +IS_COMPONENT = 1 +MOZILLA_INTERNAL_API = 1 + +REQUIRES = xpcom \ + string \ + necko \ + pref \ + update \ + $(NULL) + +CPPSRCS = \ + nsMetricsService.cpp \ + nsMetricsModule.cpp \ + $(NULL) + +EXTRA_DSO_LDOPTS = $(MOZ_COMPONENT_LIBS) \ + $(NULL) + +include $(topsrcdir)/config/rules.mk diff --git a/mozilla/extensions/metrics/src/nsMetricsModule.cpp b/mozilla/extensions/metrics/src/nsMetricsModule.cpp new file mode 100644 index 00000000000..63ee0596df5 --- /dev/null +++ b/mozilla/extensions/metrics/src/nsMetricsModule.cpp @@ -0,0 +1,85 @@ +/* -*- 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 + * + * 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 "nsMetricsModule.h" +#include "nsMetricsService.h" +#include "nsMetricsEvent.h" +#include "nsIGenericFactory.h" +#include "nsICategoryManager.h" +#include "nsServiceManagerUtils.h" +#include "nsCOMPtr.h" +#include "nsXPCOMCID.h" + +NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsMetricsService, Init) +NS_DECL_CLASSINFO(nsMetricsService) + +static NS_METHOD +nsMetricsServiceRegisterSelf(nsIComponentManager *compMgr, + nsIFile *path, + const char *loaderStr, + const char *type, + const nsModuleComponentInfo *info) +{ + nsCOMPtr cat = + do_GetService(NS_CATEGORYMANAGER_CONTRACTID); + NS_ENSURE_STATE(cat); + + cat->AddCategoryEntry("app-startup", + NS_METRICSSERVICE_CLASSNAME, + NS_METRICSSERVICE_CONTRACTID, + PR_TRUE, PR_TRUE, nsnull); + return NS_OK; +} + +static const nsModuleComponentInfo components[] = { + { + NS_METRICSSERVICE_CLASSNAME, + NS_METRICSSERVICE_CID, + NS_METRICSSERVICE_CONTRACTID, + nsMetricsServiceConstructor, + nsMetricsServiceRegisterSelf, + NULL, + NULL, + NS_CI_INTERFACE_GETTER_NAME(nsMetricsService), + NULL, + &NS_CLASSINFO_NAME(nsMetricsService), + nsIClassInfo::MAIN_THREAD_ONLY | nsIClassInfo::SINGLETON + } +}; + +NS_IMPL_NSGETMODULE(metrics, components) diff --git a/mozilla/extensions/metrics/src/nsMetricsService.cpp b/mozilla/extensions/metrics/src/nsMetricsService.cpp new file mode 100644 index 00000000000..61572c0958f --- /dev/null +++ b/mozilla/extensions/metrics/src/nsMetricsService.cpp @@ -0,0 +1,313 @@ +/* -*- 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 + * + * 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 "nsMetricsService.h" +#include "nsMetricsEvent.h" +#include "nsXPCOM.h" +#include "nsServiceManagerUtils.h" +#include "nsDirectoryServiceUtils.h" +#include "nsAppDirectoryServiceDefs.h" +#include "nsNetUtil.h" +#include "nsIObserverService.h" +#include "nsIUpdateService.h" +#include "nsIUploadChannel.h" +#include "nsIPrefService.h" +#include "nsIPrefBranch.h" +#include "nsIObserver.h" +#include "nsILocalFile.h" + +// Flush the event log whenever its size exceeds this amount of bytes. +#define NS_EVENTLOG_FLUSH_POINT 4096 + +//----------------------------------------------------------------------------- + +NS_IMPL_ISUPPORTS5_CI(nsMetricsService, nsIMetricsService, + nsIStreamListener, nsIRequestObserver, + nsIObserver, nsITimerCallback) + +NS_IMETHODIMP +nsMetricsService::LogCustomEvent(const nsACString &data) +{ + nsMetricsEvent event(NS_METRICS_CUSTOM_EVENT); + PRUint32 len = data.Length(); + NS_ENSURE_ARG(len < PR_UINT16_MAX); + event.PutInt16(len); + event.PutBytes(data.BeginReading(), len); + return LogEvent(event); +} + +NS_IMETHODIMP +nsMetricsService::LogEvent(const nsMetricsEvent &event) +{ + if (mSuspendCount != 0) // Ignore events while suspended + return NS_OK; + + NS_ENSURE_ARG(PRUint32(event.Type()) < PR_UINT8_MAX); + + // The event header consists of the following fields: + PRUint8 type; // 8-bit event type + PRUint32 timestamp; // 32-bit timestamp (seconds since the epoch) + + type = (PRUint8) event.Type(); + timestamp = PRUint32(PR_Now() / PR_USEC_PER_SEC); + + mEventLog.AppendElement(type); + mEventLog.AppendElements((PRUint8 *) ×tamp, sizeof(timestamp)); + mEventLog.AppendElements(event.Buffer(), event.BufferLength()); + + if (mEventLog.Length() > NS_EVENTLOG_FLUSH_POINT) + FlushData(); + return NS_OK; +} + +NS_IMETHODIMP +nsMetricsService::Upload() +{ + if (mUploading) // Ignore new uploads issued while uploading. + return NS_OK; + + // We suspend logging until the upload completes. + + nsresult rv = FlushData(); + NS_ENSURE_SUCCESS(rv, rv); + + rv = UploadData(); + if (NS_SUCCEEDED(rv)) { + mUploading = PR_TRUE; + Suspend(); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsMetricsService::Suspend() +{ + mSuspendCount++; + return NS_OK; +} + +NS_IMETHODIMP +nsMetricsService::Resume() +{ + if (mSuspendCount > 0) + mSuspendCount--; + return NS_OK; +} + +NS_IMETHODIMP +nsMetricsService::OnStartRequest(nsIRequest *request, nsISupports *context) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsMetricsService::OnStopRequest(nsIRequest *request, nsISupports *context, + nsresult status) +{ + nsCOMPtr dataFile; + GetDataFile(&dataFile); + if (dataFile) + dataFile->Remove(PR_FALSE); + + Resume(); + mUploading = PR_FALSE; + return NS_OK; +} + +NS_IMETHODIMP +nsMetricsService::OnDataAvailable(nsIRequest *request, nsISupports *context, + nsIInputStream *stream, PRUint32 offset, + PRUint32 count) +{ + // We don't expect to receive any data from an upload. + return NS_ERROR_ABORT; +} + +NS_IMETHODIMP +nsMetricsService::Observe(nsISupports *subject, const char *topic, + const PRUnichar *data) +{ + if (strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) { + FlushData(); + } else if (strcmp(topic, "app-startup") == 0) { + PRInt32 interval = 86400000; // 24 hours + nsCOMPtr prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); + if (prefs) + prefs->GetIntPref("metrics.upload.interval", &interval); + + nsCOMPtr mgr = + do_GetService("@mozilla.org/updates/timer-manager;1"); + if (mgr) + mgr->RegisterTimer(NS_LITERAL_STRING("metrics-upload"), this, interval); + } + return NS_OK; +} + +NS_IMETHODIMP +nsMetricsService::Notify(nsITimer *timer) +{ + // OK, we are ready to upload! + Upload(); + return NS_OK; +} + +nsresult +nsMetricsService::Init() +{ + nsresult rv; + + // Hook ourselves up to receive the xpcom shutdown event so we can properly + // flush our data to disk. + nsCOMPtr obsSvc = + do_GetService("@mozilla.org/observer-service;1", &rv); + NS_ENSURE_SUCCESS(rv, rv); + + rv = obsSvc->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +nsresult +nsMetricsService::GetDataFile(nsCOMPtr *result) +{ + nsCOMPtr 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.dat")); + NS_ENSURE_SUCCESS(rv, rv); + + *result = do_QueryInterface(file, &rv); + return rv; +} + +nsresult +nsMetricsService::OpenDataFile(PRUint32 flags, PRFileDesc **fd) +{ + nsCOMPtr dataFile; + nsresult rv = GetDataFile(&dataFile); + NS_ENSURE_SUCCESS(rv, rv); + + return dataFile->OpenNSPRFileDesc(flags, 0600, fd); +} + +nsresult +nsMetricsService::FlushData() +{ + nsresult rv; + + PRFileDesc *fd; + rv = OpenDataFile(PR_WRONLY | PR_APPEND | PR_CREATE_FILE, &fd); + NS_ENSURE_SUCCESS(rv, rv); + + PRInt32 num = mEventLog.Length(); + PRBool succeeded = ( PR_Write(fd, mEventLog.Elements(), num) == num ); + + PR_Close(fd); + NS_ENSURE_STATE(succeeded); + + mEventLog.SetLength(0); + return NS_OK; +} + +nsresult +nsMetricsService::UploadData() +{ + // TODO: 1) Submit a request to the server to figure out how much data to + // upload. For now, we just submit all of the data. + // 2) Prepare a data stream for upload that is prefixed with a PROFILE + // event. + + PRBool enable = PR_FALSE; + nsXPIDLCString spec; + nsCOMPtr prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); + if (prefs) { + prefs->GetBoolPref("metrics.upload.enable", &enable); + prefs->GetCharPref("metrics.upload.uri", getter_Copies(spec)); + } + if (!enable || spec.IsEmpty()) + return NS_ERROR_ABORT; + + nsCOMPtr file; + nsresult rv = GetDataFile(&file); + NS_ENSURE_SUCCESS(rv, rv); + + // NOTE: nsIUploadChannel requires a buffered stream to upload... + + nsCOMPtr fileStream; + NS_NewLocalFileInputStream(getter_AddRefs(fileStream), file); + NS_ENSURE_STATE(fileStream); + + PRUint32 streamLen; + rv = fileStream->Available(&streamLen); + NS_ENSURE_SUCCESS(rv, rv); + + if (streamLen == 0) + return NS_ERROR_ABORT; + + nsCOMPtr uploadStream; + NS_NewBufferedInputStream(getter_AddRefs(uploadStream), fileStream, 4096); + NS_ENSURE_STATE(uploadStream); + + nsCOMPtr ios = do_GetIOService(); + NS_ENSURE_STATE(ios); + + nsCOMPtr channel; + ios->NewChannel(spec, nsnull, nsnull, getter_AddRefs(channel)); + NS_ENSURE_STATE(channel); + + nsCOMPtr uploadChannel = do_QueryInterface(channel); + NS_ENSURE_STATE(uploadChannel); + + NS_NAMED_LITERAL_CSTRING(binaryType, "application/vnd.mozilla.metrics"); + rv = uploadChannel->SetUploadStream(uploadStream, binaryType, -1); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr 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; +} diff --git a/mozilla/extensions/metrics/src/nsMetricsService.h b/mozilla/extensions/metrics/src/nsMetricsService.h new file mode 100644 index 00000000000..17a7fa33e7a --- /dev/null +++ b/mozilla/extensions/metrics/src/nsMetricsService.h @@ -0,0 +1,88 @@ +/* -*- 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 + * + * 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 nsMetricsService_h__ +#define nsMetricsService_h__ + +#include "nsIMetricsService.h" +#include "nsIStreamListener.h" +#include "nsILocalFile.h" +#include "nsIObserver.h" +#include "nsITimer.h" +#include "nsTArray.h" +#include "nsCOMPtr.h" +#include "prio.h" + +// This class manages the metrics datastore. It is responsible for persisting +// the data when the browser closes and for uploading it to the metrics server +// periodically. + +class nsMetricsService : public nsIMetricsService + , public nsIStreamListener + , public nsIObserver + , public nsITimerCallback +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIMETRICSSERVICE + NS_DECL_NSIREQUESTOBSERVER + NS_DECL_NSISTREAMLISTENER + NS_DECL_NSIOBSERVER + NS_DECL_NSITIMERCALLBACK + + nsMetricsService() + : mSuspendCount(0) + , mUploading(PR_FALSE) + {} + + nsresult Init(); + +private: + nsresult FlushData(); + nsresult UploadData(); + nsresult GetDataFile(nsCOMPtr *result); + nsresult OpenDataFile(PRUint32 flags, PRFileDesc **result); + +private: + // Memory buffer containing events to be flushed. + nsTArray mEventLog; + PRInt32 mSuspendCount; + PRBool mUploading; +}; + +#endif // nsMetricsService_h__ diff --git a/mozilla/extensions/metrics/tool/DumpMetrics.cpp b/mozilla/extensions/metrics/tool/DumpMetrics.cpp new file mode 100644 index 00000000000..bd0920c4484 --- /dev/null +++ b/mozilla/extensions/metrics/tool/DumpMetrics.cpp @@ -0,0 +1,190 @@ +/* -*- 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 mozilla.org code. + * + * 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 + * + * 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 +#include + +//----------------------------------------------------------------------------- + +#define HEXDUMP_MAX_ROWS 16 + +static void hex_dump(unsigned int *state, const unsigned char *buf, int n) +{ + const unsigned char *p; + while (n) { + printf(" %08x: ", *state); + *state += HEXDUMP_MAX_ROWS; + + p = buf; + + int i, row_max = n; + if (row_max > HEXDUMP_MAX_ROWS) + row_max = HEXDUMP_MAX_ROWS; + + // print hex codes: + for (i = 0; i < row_max; ++i) { + printf("%02x ", *p++); + } + for (i = row_max; i < HEXDUMP_MAX_ROWS; ++i) { + printf(" "); + } + + // print ASCII glyphs if possible: + p = buf; + for (i = 0; i < row_max; ++i, ++p) { + if (*p < 0x7F && *p > 0x1F) { + printf("%c", *p); + } else { + printf("%c", '.'); + } + } + printf("\n"); + + buf += row_max; + n -= row_max; + } +} + +//----------------------------------------------------------------------------- + +typedef int (* TypeHandler)(const unsigned char *buf, int bufLen); + +struct TypeMap { + unsigned char type; + const char *name; + TypeHandler handler; +}; + +static int dump_profile_event(const unsigned char *buf, int bufLen); +static int dump_custom_event(const unsigned char *buf, int bufLen); +static int dump_load_event(const unsigned char *buf, int bufLen); +static int dump_ui_event(const unsigned char *buf, int bufLen); + +static TypeMap g_typemap[] = { + { '\x00', "PROFILE", dump_profile_event }, + { '\x01', "CUSTOM", dump_custom_event }, + { '\x02', "LOAD", dump_load_event }, + { '\x03', "UI", dump_ui_event } +}; + +int dump_profile_event(const unsigned char *buf, int bufLen) +{ + return -1; // XXX Implement me! +} + +int dump_load_event(const unsigned char *buf, int bufLen) +{ + return -1; // XXX Implement me! +} + +int dump_ui_event(const unsigned char *buf, int bufLen) +{ + return -1; // XXX Implement me! +} + +int dump_custom_event(const unsigned char *buf, int bufLen) +{ + unsigned short num; + memcpy(&num, buf, sizeof(num)); + unsigned int state = 0; + hex_dump(&state, buf + 2, num); + return 2 + num; +} + +static void dump_data(const unsigned char *buf, int bufLen) +{ + const unsigned char *end = buf + bufLen; + while (buf < end) { + int n = -1; + for (size_t i = 0; i < sizeof(g_typemap)/sizeof(g_typemap[0]); ++i) { + if (g_typemap[i].type == *buf) { + static unsigned long g_first_timestamp = 0; + // dump the header, which consists of a single byte identifier + // for the type, and a 32-bit timestamp (seconds since epoch) + unsigned long ts; + memcpy(&ts, buf + 1, 4); + if (g_first_timestamp == 0) { + g_first_timestamp = ts; + ts = 0; + } else { + ts -= g_first_timestamp; + } + printf("%s(%lu):\n", g_typemap[i].name, ts); + + buf += 5; + + n = g_typemap[i].handler(buf, bufLen); + if (n > 0) + buf += n; + break; + } + } + if (n == -1) { + fprintf(stderr, "error: unhandled event type!\n"); + return; + } + } +} + +//----------------------------------------------------------------------------- + +int main(int argc, char **argv) +{ + if (argc < 2) { + fprintf(stderr, "usage: DumpMetrics metrics.dat\n"); + return -1; + } + + FILE *fp = fopen(argv[1], "rb"); + if (!fp) + return -1; + + fseek(fp, 0, SEEK_END); + long len = ftell(fp); + fseek(fp, 0, SEEK_SET); + + unsigned char *buf = new unsigned char[len]; + if (fread(buf, len, 1, fp) != 1) + len = 0; + if (len) + dump_data(buf, len); + delete[] buf; + + fclose(fp); + return 0; +} diff --git a/mozilla/extensions/metrics/tool/Makefile.in b/mozilla/extensions/metrics/tool/Makefile.in new file mode 100644 index 00000000000..4bdd13809ab --- /dev/null +++ b/mozilla/extensions/metrics/tool/Makefile.in @@ -0,0 +1,50 @@ +# vim:set ts=8 sw=8 sts=8 noet: +# ***** 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 +# +# 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 ***** + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = metrics +SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX)) + +CPPSRCS = DumpMetrics.cpp + +include $(topsrcdir)/config/rules.mk