Merge last green changeset from m-i to m-c.

This commit is contained in:
Joe Drew 2011-06-28 21:46:06 -04:00
commit 212d726dc3
66 changed files with 969 additions and 825 deletions

View File

@ -313,21 +313,21 @@ function newWindowWithState(state, callback) {
let opts = "chrome,all,dialog=no,height=800,width=800";
let win = window.openDialog(getBrowserURL(), "_blank", opts);
let numConditions = 2;
let check = function () {
if (!--numConditions)
callback(win);
};
whenWindowLoaded(win, function () {
whenWindowStateReady(win, function () {
afterAllTabsLoaded(check, win);
});
ss.setWindowState(win, JSON.stringify(state), true);
whenDelayedStartupFinished(win, check);
});
let numConditions = 2;
let check = function () {
if (!--numConditions)
callback(win);
};
whenDelayedStartupFinished(win, check);
}
// ----------

View File

@ -1001,7 +1001,7 @@
// undetermined state and then schedule a proper check at the next
// opportunity
this.setProgress(0, -1);
setTimeout(this.updateProgress.bind(this), 0);
this._updateProgressTimeout = setTimeout(this.updateProgress.bind(this), 0);
]]></constructor>
<destructor><![CDATA[
@ -1028,6 +1028,7 @@
this.notification.options.installs.forEach(function(aInstall) {
aInstall.removeListener(this);
}, this);
clearTimeout(this._updateProgressTimeout);
]]></body>
</method>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 974 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 289 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 355 KiB

After

Width:  |  Height:  |  Size: 289 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 924 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 289 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 355 KiB

After

Width:  |  Height:  |  Size: 289 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

View File

@ -1544,8 +1544,10 @@ if test "$GNU_CC"; then
MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-h,$@ -o $@'
DSO_LDOPTS='-shared'
if test "$GCC_USE_GNU_LD"; then
# Don't allow undefined symbols in libraries
DSO_LDOPTS="$DSO_LDOPTS -Wl,-z,defs"
# Don't allow undefined symbols in libraries, and remove dead symbols
DSO_LDOPTS="$DSO_LDOPTS -Wl,-z,defs -Wl,--gc-sections"
CFLAGS="$CFLAGS -ffunction-sections -fdata-sections"
CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections"
fi
WARNINGS_AS_ERRORS='-Werror'
DSO_CFLAGS=''

View File

@ -168,20 +168,20 @@ static PRBool FloatValidate (double f1, double f2, double f3, double f4, double
static nsIMemoryReporter *gCanvasMemoryReporter = nsnull;
static PRInt64 gCanvasMemoryUsed = 0;
static PRInt64 GetCanvasMemoryUsed(void *) {
static PRInt64 GetCanvasMemoryUsed() {
return gCanvasMemoryUsed;
}
// This is MR_OTHER because it's not always clear where in memory the pixels of
// This is KIND_OTHER because it's not always clear where in memory the pixels of
// a canvas are stored. Furthermore, this memory will be tracked by the
// underlying surface implementations. See bug 655638 for details.
NS_MEMORY_REPORTER_IMPLEMENT(CanvasMemory,
"canvas-2d-pixel-bytes",
MR_OTHER,
"Memory used by 2D canvases. Each canvas requires (width * height * 4) "
"bytes.",
KIND_OTHER,
UNITS_BYTES,
GetCanvasMemoryUsed,
NULL)
"Memory used by 2D canvases. Each canvas requires (width * height * 4) "
"bytes.")
static void
CopyContext(gfxContext* dest, gfxContext* src)

View File

@ -178,20 +178,20 @@ static PRBool FloatValidate (double f1, double f2, double f3, double f4, double
static nsIMemoryReporter *gCanvasAzureMemoryReporter = nsnull;
static PRInt64 gCanvasAzureMemoryUsed = 0;
static PRInt64 GetCanvasAzureMemoryUsed(void *) {
static PRInt64 GetCanvasAzureMemoryUsed() {
return gCanvasAzureMemoryUsed;
}
// This is MR_OTHER because it's not always clear where in memory the pixels of
// a canvas are stored. Furthermore, this memory will be tracked by the
// This is KIND_OTHER because it's not always clear where in memory the pixels
// of a canvas are stored. Furthermore, this memory will be tracked by the
// underlying surface implementations. See bug 655638 for details.
NS_MEMORY_REPORTER_IMPLEMENT(CanvasAzureMemory,
"canvas-2d-pixel-bytes",
MR_OTHER,
"Memory used by 2D canvases. Each canvas requires (width * height * 4) "
"bytes.",
KIND_OTHER,
UNITS_BYTES,
GetCanvasAzureMemoryUsed,
nsnull)
"Memory used by 2D canvases. Each canvas requires (width * height * 4) "
"bytes.")
/**
** nsCanvasGradientAzure

View File

@ -314,20 +314,23 @@ ContentChild::RecvPMemoryReportRequestConstructor(PMemoryReportRequestChild* chi
nsCString path;
PRInt32 kind;
PRInt32 units;
nsCString desc;
PRInt64 memoryUsed;
PRInt64 amount;
report->GetPath(getter_Copies(path));
report->GetKind(&kind);
report->GetUnits(&units);
report->GetAmount(&amount);
report->GetDescription(getter_Copies(desc));
report->GetMemoryUsed(&memoryUsed);
static const int maxLength = 31; // big enough; pid is only a few chars
MemoryReport memreport(nsPrintfCString(maxLength, "Content (%d)",
getpid()),
path,
kind,
desc,
memoryUsed);
units,
amount,
desc);
reports.AppendElement(memreport);

View File

@ -708,25 +708,24 @@ ContentParent::DeallocPMemoryReportRequest(PMemoryReportRequestParent* actor)
void
ContentParent::SetChildMemoryReporters(const InfallibleTArray<MemoryReport>& report)
{
nsCOMPtr<nsIMemoryReporterManager> mgr = do_GetService("@mozilla.org/memory-reporter-manager;1");
nsCOMPtr<nsIMemoryReporterManager> mgr =
do_GetService("@mozilla.org/memory-reporter-manager;1");
for (PRInt32 i = 0; i < mMemoryReporters.Count(); i++)
mgr->UnregisterReporter(mMemoryReporters[i]);
for (PRUint32 i = 0; i < report.Length(); i++) {
nsCString process = report[i].process();
nsCString path = report[i].path();
PRInt32 kind = report[i].kind();
PRInt32 units = report[i].units();
PRInt64 amount = report[i].amount();
nsCString desc = report[i].desc();
PRInt64 memoryUsed = report[i].memoryUsed();
nsRefPtr<nsMemoryReporter> r = new nsMemoryReporter(process,
path,
kind,
desc,
memoryUsed);
mMemoryReporters.AppendObject(r);
mgr->RegisterReporter(r);
nsRefPtr<nsMemoryReporter> r =
new nsMemoryReporter(process, path, kind, units, amount, desc);
mMemoryReporters.AppendObject(r);
mgr->RegisterReporter(r);
}
nsCOMPtr<nsIObserverService> obs =

View File

@ -45,8 +45,9 @@ struct MemoryReport {
nsCString process;
nsCString path;
PRInt32 kind;
PRInt32 units;
PRInt64 amount;
nsCString desc;
PRInt64 memoryUsed;
};
protocol PMemoryReportRequest {

View File

@ -254,6 +254,15 @@ PluginModuleChild::Init(const std::string& aPluginFilename,
# error Please copy the initialization code from nsNPAPIPlugin.cpp
#endif
#ifdef XP_MACOSX
nsPluginInfo info = nsPluginInfo();
rv = pluginFile.GetPluginInfo(info, &mLibrary);
if (rv == NS_OK) {
mozilla::plugins::PluginUtilsOSX::SetProcessName(info.fName);
}
#endif
return true;
}

View File

@ -55,7 +55,7 @@
#include "nsTHashtable.h"
#include "nsHashKeys.h"
#ifdef OS_MACOSX
#ifdef MOZ_WIDGET_COCOA
#include "PluginInterposeOSX.h"
#endif

View File

@ -58,6 +58,7 @@ void* GetCGLayer(DrawPluginFunc aFunc, void* aPluginInstance);
void ReleaseCGLayer(void* cgLayer);
void Repaint(void* cgLayer, nsIntRect aRect);
bool SetProcessName(const char* aProcessName);
} // namespace PluginUtilsOSX
} // namespace plugins

View File

@ -43,6 +43,9 @@
// Remove definitions for try/catch interfering with ObjCException macros.
#include "nsObjCExceptions.h"
#include "nsCocoaUtils.h"
#include "nsDebug.h"
using namespace mozilla::plugins::PluginUtilsOSX;
@ -168,3 +171,99 @@ void mozilla::plugins::PluginUtilsOSX::InvokeNativeEventLoop()
::CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.0, true);
NS_OBJC_END_TRY_ABORT_BLOCK;
}
#define UNDOCUMENTED_SESSION_CONSTANT ((int)-2)
static void *mozilla::plugins::PluginUtilsOSX::sApplicationASN = NULL;
static void *mozilla::plugins::PluginUtilsOSX::sApplicationInfoItem = NULL;
bool mozilla::plugins::PluginUtilsOSX::SetProcessName(const char* aProcessName) {
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
nsAutoreleasePool localPool;
if (!aProcessName || strcmp(aProcessName, "") == 0) {
return false;
}
NSString *currentName = [[[NSBundle mainBundle] localizedInfoDictionary]
objectForKey:(NSString *)kCFBundleNameKey];
char formattedName[1024];
snprintf(formattedName, sizeof(formattedName),
"%s (%s)", [currentName UTF8String], aProcessName);
aProcessName = formattedName;
// This function is based on Chrome/Webkit's and relies on potentially dangerous SPI.
typedef CFTypeRef (*LSGetASNType)();
typedef OSStatus (*LSSetInformationItemType)(int, CFTypeRef,
CFStringRef,
CFStringRef,
CFDictionaryRef*);
CFBundleRef launchServices = ::CFBundleGetBundleWithIdentifier(
CFSTR("com.apple.LaunchServices"));
if (!launchServices) {
NS_WARNING("Failed to set process name: Could not open LaunchServices bundle");
return false;
}
if (!sApplicationASN) {
sApplicationASN = ::CFBundleGetFunctionPointerForName(launchServices,
CFSTR("_LSGetCurrentApplicationASN"));
}
LSGetASNType getASNFunc = reinterpret_cast<LSGetASNType>
(sApplicationASN);
if (!sApplicationInfoItem) {
sApplicationInfoItem = ::CFBundleGetFunctionPointerForName(launchServices,
CFSTR("_LSSetApplicationInformationItem"));
}
LSSetInformationItemType setInformationItemFunc
= reinterpret_cast<LSSetInformationItemType>
(sApplicationInfoItem);
void * displayNameKeyAddr = ::CFBundleGetDataPointerForName(launchServices,
CFSTR("_kLSDisplayNameKey"));
CFStringRef displayNameKey = nil;
if (displayNameKeyAddr) {
displayNameKey = reinterpret_cast<CFStringRef>(*(CFStringRef*)displayNameKeyAddr);
}
// Rename will fail without this
ProcessSerialNumber psn;
if (::GetCurrentProcess(&psn) != noErr) {
return false;
}
CFTypeRef currentAsn = getASNFunc();
if (!getASNFunc || !setInformationItemFunc ||
!displayNameKey || !currentAsn) {
NS_WARNING("Failed to set process name: Accessing launchServices failed");
return false;
}
CFStringRef processName = ::CFStringCreateWithCString(nil,
aProcessName,
kCFStringEncodingASCII);
if (!processName) {
NS_WARNING("Failed to set process name: Could not create CFStringRef");
return false;
}
OSErr err = setInformationItemFunc(UNDOCUMENTED_SESSION_CONSTANT, currentAsn,
displayNameKey, processName,
nil); // Optional out param
::CFRelease(processName);
if (err != noErr) {
NS_WARNING("Failed to set process name: LSSetInformationItemType err");
return false;
}
return true;
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
}

View File

@ -1186,17 +1186,7 @@ DefaultTooltipTextProvider::GetNodeText(nsIDOMNode *aNode, PRUnichar **aText,
///////////////////////////////////////////////////////////////////////////////
NS_IMPL_ADDREF(ChromeTooltipListener)
NS_IMPL_RELEASE(ChromeTooltipListener)
NS_INTERFACE_MAP_BEGIN(ChromeTooltipListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMMouseListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener, nsIDOMMouseListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMMouseListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMMouseMotionListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMKeyListener)
NS_INTERFACE_MAP_END
NS_IMPL_ISUPPORTS1(ChromeTooltipListener, nsIDOMEventListener)
//
// ChromeTooltipListener ctor
@ -1264,14 +1254,20 @@ NS_IMETHODIMP
ChromeTooltipListener::AddTooltipListener()
{
if (mEventTarget) {
nsIDOMMouseListener *pListener = static_cast<nsIDOMMouseListener *>(this);
nsresult rv = mEventTarget->AddEventListenerByIID(pListener, NS_GET_IID(nsIDOMMouseListener));
nsresult rv2 = mEventTarget->AddEventListenerByIID(pListener, NS_GET_IID(nsIDOMMouseMotionListener));
nsresult rv3 = mEventTarget->AddEventListenerByIID(pListener, NS_GET_IID(nsIDOMKeyListener));
// if all 3 succeed, we're a go!
if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(rv2) && NS_SUCCEEDED(rv3))
mTooltipListenerInstalled = PR_TRUE;
nsresult rv = mEventTarget->AddEventListener(NS_LITERAL_STRING("keydown"),
this, PR_FALSE, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
rv = mEventTarget->AddEventListener(NS_LITERAL_STRING("mousedown"), this,
PR_FALSE, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
rv = mEventTarget->AddEventListener(NS_LITERAL_STRING("mouseout"), this,
PR_FALSE, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
rv = mEventTarget->AddEventListener(NS_LITERAL_STRING("mousemove"), this,
PR_FALSE, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
mTooltipListenerInstalled = PR_TRUE;
}
return NS_OK;
@ -1309,102 +1305,43 @@ NS_IMETHODIMP
ChromeTooltipListener::RemoveTooltipListener()
{
if (mEventTarget) {
nsIDOMMouseListener *pListener = static_cast<nsIDOMMouseListener *>(this);
nsresult rv = mEventTarget->RemoveEventListenerByIID(pListener, NS_GET_IID(nsIDOMMouseListener));
nsresult rv2 = mEventTarget->RemoveEventListenerByIID(pListener, NS_GET_IID(nsIDOMMouseMotionListener));
nsresult rv3 = mEventTarget->RemoveEventListenerByIID(pListener, NS_GET_IID(nsIDOMKeyListener));
if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(rv2) && NS_SUCCEEDED(rv3))
mTooltipListenerInstalled = PR_FALSE;
nsresult rv =
mEventTarget->RemoveEventListener(NS_LITERAL_STRING("keydown"), this,
PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
rv = mEventTarget->RemoveEventListener(NS_LITERAL_STRING("mousedown"),
this, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
rv = mEventTarget->RemoveEventListener(NS_LITERAL_STRING("mouseout"), this,
PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
rv = mEventTarget->RemoveEventListener(NS_LITERAL_STRING("mousemove"),
this, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
mTooltipListenerInstalled = PR_FALSE;
}
return NS_OK;
}
//
// KeyDown
//
// When the user starts typing, they generaly don't want to see any messy wax
// builup. Hide the tooltip.
//
nsresult
ChromeTooltipListener::KeyDown(nsIDOMEvent* aMouseEvent)
NS_IMETHODIMP
ChromeTooltipListener::HandleEvent(nsIDOMEvent* aEvent)
{
return HideTooltip();
} // KeyDown
nsAutoString eventType;
aEvent->GetType(eventType);
if (eventType.EqualsLiteral("keydown") ||
eventType.EqualsLiteral("mousedown") ||
eventType.EqualsLiteral("mouseout"))
return HideTooltip();
if (eventType.EqualsLiteral("mousemove"))
return MouseMove(aEvent);
//
// KeyUp
// KeyPress
//
// We can ignore these as they are already handled by KeyDown
//
nsresult
ChromeTooltipListener::KeyUp(nsIDOMEvent* aMouseEvent)
{
NS_ERROR("Unexpected event type");
return NS_OK;
} // KeyUp
nsresult
ChromeTooltipListener::KeyPress(nsIDOMEvent* aMouseEvent)
{
return NS_OK;
} // KeyPress
//
// MouseDown
//
// On a click, hide the tooltip
//
nsresult
ChromeTooltipListener::MouseDown(nsIDOMEvent* aMouseEvent)
{
return HideTooltip();
} // MouseDown
nsresult
ChromeTooltipListener::MouseUp(nsIDOMEvent* aMouseEvent)
{
return NS_OK;
}
nsresult
ChromeTooltipListener::MouseClick(nsIDOMEvent* aMouseEvent)
{
return NS_OK;
}
nsresult
ChromeTooltipListener::MouseDblClick(nsIDOMEvent* aMouseEvent)
{
return NS_OK;
}
nsresult
ChromeTooltipListener::MouseOver(nsIDOMEvent* aMouseEvent)
{
return NS_OK;
}
//
// MouseOut
//
// If we're responding to tooltips, hide the tip whenever the mouse leaves
// the area it was in.
nsresult
ChromeTooltipListener::MouseOut(nsIDOMEvent* aMouseEvent)
{
return HideTooltip();
}
//
// MouseMove
//
@ -1641,14 +1578,7 @@ ChromeTooltipListener::sAutoHideCallback(nsITimer *aTimer, void* aListener)
} // sAutoHideCallback
NS_IMPL_ADDREF(ChromeContextMenuListener)
NS_IMPL_RELEASE(ChromeContextMenuListener)
NS_INTERFACE_MAP_BEGIN(ChromeContextMenuListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMContextMenuListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener, nsIDOMContextMenuListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMContextMenuListener)
NS_INTERFACE_MAP_END
NS_IMPL_ISUPPORTS1(ChromeContextMenuListener, nsIDOMEventListener)
//
@ -1680,10 +1610,12 @@ NS_IMETHODIMP
ChromeContextMenuListener::AddContextMenuListener()
{
if (mEventTarget) {
nsIDOMContextMenuListener *pListener = static_cast<nsIDOMContextMenuListener *>(this);
nsresult rv = mEventTarget->AddEventListenerByIID(pListener, NS_GET_IID(nsIDOMContextMenuListener));
if (NS_SUCCEEDED(rv))
mContextMenuListenerInstalled = PR_TRUE;
nsresult rv =
mEventTarget->AddEventListener(NS_LITERAL_STRING("contextmenu"), this,
PR_FALSE, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
mContextMenuListenerInstalled = PR_TRUE;
}
return NS_OK;
@ -1699,10 +1631,12 @@ NS_IMETHODIMP
ChromeContextMenuListener::RemoveContextMenuListener()
{
if (mEventTarget) {
nsIDOMContextMenuListener *pListener = static_cast<nsIDOMContextMenuListener *>(this);
nsresult rv = mEventTarget->RemoveEventListenerByIID(pListener, NS_GET_IID(nsIDOMContextMenuListener));
if (NS_SUCCEEDED(rv))
mContextMenuListenerInstalled = PR_FALSE;
nsresult rv =
mEventTarget->RemoveEventListener(NS_LITERAL_STRING("contextmenu"), this,
PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
mContextMenuListenerInstalled = PR_FALSE;
}
return NS_OK;
@ -1763,8 +1697,11 @@ ChromeContextMenuListener::RemoveChromeListeners()
// end chrome.
//
NS_IMETHODIMP
ChromeContextMenuListener::ContextMenu(nsIDOMEvent* aMouseEvent)
{
ChromeContextMenuListener::HandleEvent(nsIDOMEvent* aMouseEvent)
{
nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aMouseEvent);
NS_ENSURE_TRUE(mouseEvent, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsIDOMNSUIEvent> uievent(do_QueryInterface(aMouseEvent));
if (uievent) {

View File

@ -50,14 +50,11 @@
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIWebBrowserChrome.h"
#include "nsIDOMMouseListener.h"
#include "nsIDOMEventListener.h"
#include "nsIDOMDocument.h"
#include "nsIEmbeddingSiteWindow.h"
#include "nsIWebProgressListener.h"
#include "nsWeakReference.h"
#include "nsIDOMKeyListener.h"
#include "nsIDOMMouseMotionListener.h"
#include "nsIDOMContextMenuListener.h"
#include "nsITimer.h"
#include "nsIPrompt.h"
#include "nsIAuthPrompt.h"
@ -176,9 +173,7 @@ protected:
// with the DOM with AddChromeListeners() and removing itself with
// RemoveChromeListeners().
//
class ChromeTooltipListener : public nsIDOMMouseListener,
public nsIDOMKeyListener,
public nsIDOMMouseMotionListener
class ChromeTooltipListener : public nsIDOMEventListener
{
public:
NS_DECL_ISUPPORTS
@ -186,23 +181,8 @@ public:
ChromeTooltipListener ( nsWebBrowser* inBrowser, nsIWebBrowserChrome* inChrome ) ;
virtual ~ChromeTooltipListener ( ) ;
// nsIDOMMouseListener
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) { return NS_OK; }
NS_IMETHOD MouseDown(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseUp(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseClick(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseDblClick(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseOver(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseOut(nsIDOMEvent* aMouseEvent);
// nsIDOMMouseMotionListener
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
NS_IMETHOD MouseMove(nsIDOMEvent* aMouseEvent);
NS_IMETHOD DragMove(nsIDOMEvent* aMouseEvent) { return NS_OK; }
// nsIDOMKeyListener
NS_IMETHOD KeyDown(nsIDOMEvent* aKeyEvent) ;
NS_IMETHOD KeyUp(nsIDOMEvent* aKeyEvent) ;
NS_IMETHOD KeyPress(nsIDOMEvent* aKeyEvent) ;
// Add/remove the relevant listeners, based on what interfaces
// the embedding chrome implements.
@ -266,7 +246,7 @@ private:
// with the DOM with AddChromeListeners() and removing itself with
// RemoveChromeListeners().
//
class ChromeContextMenuListener : public nsIDOMContextMenuListener
class ChromeContextMenuListener : public nsIDOMEventListener
{
public:
NS_DECL_ISUPPORTS
@ -275,8 +255,7 @@ public:
virtual ~ChromeContextMenuListener ( ) ;
// nsIDOMContextMenuListener
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) { return NS_OK; }
NS_IMETHOD ContextMenu ( nsIDOMEvent* aEvent );
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
// Add/remove the relevant listeners, based on what interfaces
// the embedding chrome implements.

View File

@ -508,15 +508,12 @@ public:
NS_INTERFACE_MAP_BEGIN(mozInlineSpellChecker)
NS_INTERFACE_MAP_ENTRY(nsIInlineSpellChecker)
NS_INTERFACE_MAP_ENTRY(nsIEditActionListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMFocusListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMMouseListener)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMKeyListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMKeyListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener, nsIDOMKeyListener)
NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(mozInlineSpellChecker)
NS_INTERFACE_MAP_ENTRY(nsIInlineSpellChecker)
NS_INTERFACE_MAP_ENTRY(nsIEditActionListener)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMEventListener)
NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(mozInlineSpellChecker)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(mozInlineSpellChecker)
@ -647,19 +644,12 @@ mozInlineSpellChecker::RegisterEventListeners()
nsCOMPtr<nsIDOMEventTarget> piTarget = do_QueryInterface(doc, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsEventListenerManager* elmP = piTarget->GetListenerManager(PR_TRUE);
if (elmP) {
// Focus event doesn't bubble so adding the listener to capturing phase
elmP->AddEventListenerByIID(static_cast<nsIDOMFocusListener *>(this),
NS_GET_IID(nsIDOMFocusListener),
NS_EVENT_FLAG_CAPTURE);
}
piTarget->AddEventListenerByIID(static_cast<nsIDOMMouseListener*>(this),
NS_GET_IID(nsIDOMMouseListener));
piTarget->AddEventListenerByIID(static_cast<nsIDOMKeyListener*>(this),
NS_GET_IID(nsIDOMKeyListener));
piTarget->AddEventListener(NS_LITERAL_STRING("blur"), this,
PR_TRUE, PR_FALSE);
piTarget->AddEventListener(NS_LITERAL_STRING("click"), this,
PR_FALSE, PR_FALSE);
piTarget->AddEventListener(NS_LITERAL_STRING("keypress"), this,
PR_FALSE, PR_FALSE);
return NS_OK;
}
@ -680,19 +670,9 @@ mozInlineSpellChecker::UnregisterEventListeners()
nsCOMPtr<nsIDOMEventTarget> piTarget = do_QueryInterface(doc);
NS_ENSURE_TRUE(piTarget, NS_ERROR_NULL_POINTER);
nsEventListenerManager* elmP =
piTarget->GetListenerManager(PR_TRUE);
if (elmP) {
elmP->RemoveEventListenerByIID(static_cast<nsIDOMFocusListener *>(this),
NS_GET_IID(nsIDOMFocusListener),
NS_EVENT_FLAG_CAPTURE);
}
piTarget->RemoveEventListenerByIID(static_cast<nsIDOMMouseListener*>(this),
NS_GET_IID(nsIDOMMouseListener));
piTarget->RemoveEventListenerByIID(static_cast<nsIDOMKeyListener*>(this),
NS_GET_IID(nsIDOMKeyListener));
piTarget->RemoveEventListener(NS_LITERAL_STRING("blur"), this, PR_TRUE);
piTarget->RemoveEventListener(NS_LITERAL_STRING("click"), this, PR_FALSE);
piTarget->RemoveEventListener(NS_LITERAL_STRING("keypress"), this, PR_FALSE);
return NS_OK;
}
@ -1657,8 +1637,7 @@ ContentIsDescendantOf(nsINode* aPossibleDescendant,
// DOM_VK_RIGHT and DOM_VK_LEFT cases.
nsresult
mozInlineSpellChecker::HandleNavigationEvent(nsIDOMEvent* aEvent,
PRBool aForceWordSpellCheck,
mozInlineSpellChecker::HandleNavigationEvent(PRBool aForceWordSpellCheck,
PRInt32 aNewPositionOffset)
{
nsresult rv;
@ -1694,22 +1673,30 @@ mozInlineSpellChecker::HandleNavigationEvent(nsIDOMEvent* aEvent,
NS_IMETHODIMP mozInlineSpellChecker::HandleEvent(nsIDOMEvent* aEvent)
{
nsAutoString eventType;
aEvent->GetType(eventType);
if (eventType.EqualsLiteral("blur")) {
return Blur(aEvent);
}
if (eventType.EqualsLiteral("click")) {
return MouseClick(aEvent);
}
if (eventType.EqualsLiteral("keypress")) {
return KeyPress(aEvent);
}
return NS_OK;
}
NS_IMETHODIMP mozInlineSpellChecker::Focus(nsIDOMEvent* aEvent)
{
return NS_OK;
}
NS_IMETHODIMP mozInlineSpellChecker::Blur(nsIDOMEvent* aEvent)
nsresult mozInlineSpellChecker::Blur(nsIDOMEvent* aEvent)
{
// force spellcheck on blur, for instance when tabbing out of a textbox
HandleNavigationEvent(aEvent, PR_TRUE);
HandleNavigationEvent(PR_TRUE);
return NS_OK;
}
NS_IMETHODIMP mozInlineSpellChecker::MouseClick(nsIDOMEvent *aMouseEvent)
nsresult mozInlineSpellChecker::MouseClick(nsIDOMEvent *aMouseEvent)
{
nsCOMPtr<nsIDOMMouseEvent>mouseEvent = do_QueryInterface(aMouseEvent);
NS_ENSURE_TRUE(mouseEvent, NS_OK);
@ -1718,51 +1705,11 @@ NS_IMETHODIMP mozInlineSpellChecker::MouseClick(nsIDOMEvent *aMouseEvent)
// anyone else from seeing this event.
PRUint16 button;
mouseEvent->GetButton(&button);
if (button == 0)
HandleNavigationEvent(mouseEvent, PR_FALSE);
else
HandleNavigationEvent(mouseEvent, PR_TRUE);
HandleNavigationEvent(button != 0);
return NS_OK;
}
NS_IMETHODIMP mozInlineSpellChecker::MouseDown(nsIDOMEvent* aMouseEvent)
{
return NS_OK;
}
NS_IMETHODIMP mozInlineSpellChecker::MouseUp(nsIDOMEvent* aMouseEvent)
{
return NS_OK;
}
NS_IMETHODIMP mozInlineSpellChecker::MouseDblClick(nsIDOMEvent* aMouseEvent)
{
return NS_OK;
}
NS_IMETHODIMP mozInlineSpellChecker::MouseOver(nsIDOMEvent* aMouseEvent)
{
return NS_OK;
}
NS_IMETHODIMP mozInlineSpellChecker::MouseOut(nsIDOMEvent* aMouseEvent)
{
return NS_OK;
}
NS_IMETHODIMP mozInlineSpellChecker::KeyDown(nsIDOMEvent* aKeyEvent)
{
return NS_OK;
}
NS_IMETHODIMP mozInlineSpellChecker::KeyUp(nsIDOMEvent* aKeyEvent)
{
return NS_OK;
}
NS_IMETHODIMP mozInlineSpellChecker::KeyPress(nsIDOMEvent* aKeyEvent)
nsresult mozInlineSpellChecker::KeyPress(nsIDOMEvent* aKeyEvent)
{
nsCOMPtr<nsIDOMKeyEvent>keyEvent = do_QueryInterface(aKeyEvent);
NS_ENSURE_TRUE(keyEvent, NS_OK);
@ -1775,7 +1722,7 @@ NS_IMETHODIMP mozInlineSpellChecker::KeyPress(nsIDOMEvent* aKeyEvent)
{
case nsIDOMKeyEvent::DOM_VK_RIGHT:
case nsIDOMKeyEvent::DOM_VK_LEFT:
HandleNavigationEvent(aKeyEvent, PR_FALSE, keyCode == nsIDOMKeyEvent::DOM_VK_RIGHT ? 1 : -1);
HandleNavigationEvent(PR_FALSE, keyCode == nsIDOMKeyEvent::DOM_VK_RIGHT ? 1 : -1);
break;
case nsIDOMKeyEvent::DOM_VK_UP:
case nsIDOMKeyEvent::DOM_VK_DOWN:
@ -1783,7 +1730,7 @@ NS_IMETHODIMP mozInlineSpellChecker::KeyPress(nsIDOMEvent* aKeyEvent)
case nsIDOMKeyEvent::DOM_VK_END:
case nsIDOMKeyEvent::DOM_VK_PAGE_UP:
case nsIDOMKeyEvent::DOM_VK_PAGE_DOWN:
HandleNavigationEvent(aKeyEvent, PR_TRUE /* force a spelling correction */);
HandleNavigationEvent(PR_TRUE /* force a spelling correction */);
break;
}

View File

@ -48,13 +48,16 @@
#include "nsIDOMTreeWalker.h"
#include "nsWeakReference.h"
#include "nsIEditor.h"
#include "nsIDOMFocusListener.h"
#include "nsIDOMMouseListener.h"
#include "nsIDOMKeyListener.h"
#include "nsIDOMEventListener.h"
#include "nsWeakReference.h"
#include "mozISpellI18NUtil.h"
#include "nsCycleCollectionParticipant.h"
// X.h defines KeyPress
#ifdef KeyPress
#undef KeyPress
#endif
class nsIDOMMouseEventListener;
class mozInlineSpellWordUtil;
class mozInlineSpellChecker;
@ -139,8 +142,10 @@ protected:
nsIDOMRange** aRange);
};
class mozInlineSpellChecker : public nsIInlineSpellChecker, nsIEditActionListener, nsIDOMFocusListener, nsIDOMMouseListener, nsIDOMKeyListener,
nsSupportsWeakReference
class mozInlineSpellChecker : public nsIInlineSpellChecker,
public nsIEditActionListener,
public nsIDOMEventListener,
public nsSupportsWeakReference
{
private:
friend class mozInlineSpellStatus;
@ -221,31 +226,15 @@ public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_NSIEDITACTIONLISTENER
NS_DECL_NSIINLINESPELLCHECKER
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(mozInlineSpellChecker, nsIDOMKeyListener)
NS_DECL_NSIDOMEVENTLISTENER
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(mozInlineSpellChecker, nsIDOMEventListener)
// returns true if it looks likely that we can enable real-time spell checking
static PRBool CanEnableInlineSpellChecking();
/*BEGIN implementations of focus event handler interface*/
NS_IMETHOD Focus(nsIDOMEvent* aEvent);
NS_IMETHOD Blur(nsIDOMEvent* aEvent);
/*END implementations of focus event handler interface*/
/*BEGIN implementations of mouseevent handler interface*/
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
NS_IMETHOD MouseDown(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseUp(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseClick(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseDblClick(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseOver(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseOut(nsIDOMEvent* aMouseEvent);
/*END implementations of mouseevent handler interface*/
/* BEGIN interfaces in to the keylistener interface. */
NS_IMETHOD KeyDown(nsIDOMEvent* aKeyEvent);
NS_IMETHOD KeyUp(nsIDOMEvent* aKeyEvent);
NS_IMETHOD KeyPress(nsIDOMEvent* aKeyEvent);
/* END interfaces from nsIDOMKeyListener */
nsresult Blur(nsIDOMEvent* aEvent);
nsresult MouseClick(nsIDOMEvent* aMouseEvent);
nsresult KeyPress(nsIDOMEvent* aKeyEvent);
mozInlineSpellChecker();
virtual ~mozInlineSpellChecker();
@ -297,7 +286,7 @@ public:
// DOM and editor event registration helper routines
nsresult RegisterEventListeners();
nsresult UnregisterEventListeners();
nsresult HandleNavigationEvent(nsIDOMEvent * aEvent, PRBool aForceWordSpellCheck, PRInt32 aNewPositionOffset = 0);
nsresult HandleNavigationEvent(PRBool aForceWordSpellCheck, PRInt32 aNewPositionOffset = 0);
nsresult GetSpellCheckSelection(nsISelection ** aSpellCheckSelection);
nsresult SaveCurrentSelectionPosition();

View File

@ -66,11 +66,8 @@
#include "nsIDOMEventTarget.h"
#include "nsPIDOMWindow.h"
#include "nsIDOMWindow.h"
#include "nsIDOMKeyListener.h"
#include "nsIDOMCompositionListener.h"
#include "nsIDOMTextListener.h"
#include "nsIDOMMouseMotionListener.h"
#include "nsIDOMMouseListener.h"
#include "nsIDOMMouseEvent.h"
#include "nsIDOMNSEvent.h"
#include "nsIView.h"
@ -98,8 +95,7 @@ static PRBool g_is_scrollable = PR_FALSE;
// TODO auto reload nsWidgetUtils in C.
class nsWidgetUtils : public nsIObserver,
public nsIDOMMouseMotionListener,
public nsIDOMMouseListener,
public nsIDOMEventListener,
public nsIContentPolicy,
public nsSupportsWeakReference
{
@ -107,20 +103,8 @@ public:
nsWidgetUtils();
virtual ~nsWidgetUtils();
// nsIDOMMouseMotionListener
NS_IMETHOD MouseMove(nsIDOMEvent* aDOMEvent);
NS_IMETHOD DragMove(nsIDOMEvent* aMouseEvent);
NS_IMETHOD HandleEvent(nsIDOMEvent* aDOMEvent);
// nsIDOMMouseListener
NS_IMETHOD MouseDown(nsIDOMEvent* aDOMEvent);
NS_IMETHOD MouseUp(nsIDOMEvent* aDOMEvent);
NS_IMETHOD MouseClick(nsIDOMEvent* aDOMEvent);
NS_IMETHOD MouseDblClick(nsIDOMEvent* aDOMEvent);
NS_IMETHOD MouseOver(nsIDOMEvent* aDOMEvent);
NS_IMETHOD MouseOut(nsIDOMEvent* aDOMEvent);
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMEVENTLISTENER
NS_DECL_NSIOBSERVER
NS_DECL_NSICONTENTPOLICY
@ -132,6 +116,9 @@ private:
PRBool IsXULNode(nsIDOMNode *aNode, PRUint32 *aType = 0);
nsresult GetDOMWindowByNode(nsIDOMNode *aNode, nsIDOMWindow * *aDOMWindow);
nsresult UpdateFromEvent(nsIDOMEvent *aDOMEvent);
nsresult MouseDown(nsIDOMEvent* aDOMEvent);
nsresult MouseUp(nsIDOMEvent* aDOMEvent);
nsresult MouseMove(nsIDOMEvent* aDOMEvent);
static void StopPanningCallback(nsITimer *timer, void *closure);
@ -216,7 +203,7 @@ nsWidgetUtils::UpdateFromEvent(nsIDOMEvent *aDOMEvent)
return NS_OK;
}
NS_IMETHODIMP
nsresult
nsWidgetUtils::MouseDown(nsIDOMEvent* aDOMEvent)
{
g_is_scrollable = PR_FALSE;
@ -237,7 +224,7 @@ nsWidgetUtils::StopPanningCallback(nsITimer *timer, void *closure)
g_panning = PR_FALSE;
}
NS_IMETHODIMP
nsresult
nsWidgetUtils::MouseUp(nsIDOMEvent* aDOMEvent)
{
nsCOMPtr <nsIDOMMouseEvent> mouseEvent;
@ -263,7 +250,7 @@ nsWidgetUtils::MouseUp(nsIDOMEvent* aDOMEvent)
return NS_OK;
}
NS_IMETHODIMP
nsresult
nsWidgetUtils::MouseMove(nsIDOMEvent* aDOMEvent)
{
if (!g_is_scrollable) return NS_OK;
@ -347,40 +334,22 @@ nsWidgetUtils::ShouldLoad(PRUint32 aContentType,
return NS_OK;
}
NS_IMETHODIMP
nsWidgetUtils::MouseClick(nsIDOMEvent* aDOMEvent)
{
return NS_OK;
}
NS_IMETHODIMP
nsWidgetUtils::MouseDblClick(nsIDOMEvent* aDOMEvent)
{
return NS_OK;
}
NS_IMETHODIMP
nsWidgetUtils::HandleEvent(nsIDOMEvent* aDOMEvent)
{
return NS_OK;
}
nsAutoString eventType;
aEvent->GetType(eventType);
NS_IMETHODIMP
nsWidgetUtils::MouseOver(nsIDOMEvent* aDOMEvent)
{
return NS_OK;
}
if (eventType.EqualsLiteral("mousedown")) {
return MouseDown(aEvent);
}
if (eventType.EqualsLiteral("mouseup")) {
return MouseUp(aEvent);
}
if (eventType.EqualsLiteral("mousemove")) {
return MouseMove(aEvent);
}
NS_IMETHODIMP
nsWidgetUtils::MouseOut(nsIDOMEvent* aDOMEvent)
{
return NS_OK;
}
NS_IMETHODIMP
nsWidgetUtils::DragMove(nsIDOMEvent* aDOMEvent)
{
return NS_OK;
}
@ -465,20 +434,12 @@ nsWidgetUtils::RemoveWindowListeners(nsIDOMWindow *aDOMWin)
// Use capturing, otherwise the normal find next will get activated when ours should
// Remove DOM Text listener for IME text events
rv = chromeEventHandler->
RemoveEventListenerByIID(static_cast<nsIDOMMouseListener*>(this),
NS_GET_IID(nsIDOMMouseListener));
if (NS_FAILED(rv)) {
NS_WARNING("Failed to add Mouse Motion listener\n");
return;
}
rv = chromeEventHandler->
RemoveEventListenerByIID(static_cast<nsIDOMMouseMotionListener*>(this),
NS_GET_IID(nsIDOMMouseMotionListener));
if (NS_FAILED(rv)) {
NS_WARNING("Failed to add Mouse Motion listener\n");
return;
}
chromeEventHandler->RemoveEventListener(NS_LITERAL_STRING("mousedown"),
this, PR_FALSE);
chromeEventHandler->RemoveEventListener(NS_LITERAL_STRING("mouseup"),
this, PR_FALSE);
chromeEventHandler->RemoveEventListener(NS_LITERAL_STRING("mousemove"),
this, PR_FALSE);
}
void
@ -494,27 +455,23 @@ nsWidgetUtils::AttachWindowListeners(nsIDOMWindow *aDOMWin)
// Use capturing, otherwise the normal find next will get activated when ours should
// Attach menu listeners, this will help us ignore keystrokes meant for menus
rv = chromeEventHandler->
AddEventListenerByIID(static_cast<nsIDOMMouseListener*>(this),
NS_GET_IID(nsIDOMMouseListener));
if (NS_FAILED(rv)) {
NS_WARNING("Failed to add Mouse Motion listener\n");
return;
}
rv = chromeEventHandler->
AddEventListenerByIID(static_cast<nsIDOMMouseMotionListener*>(this),
NS_GET_IID(nsIDOMMouseMotionListener));
if (NS_FAILED(rv)) {
NS_WARNING("Failed to add Mouse Motion listener\n");
return;
}
chromeEventHandler->AddEventListener(NS_LITERAL_STRING("mousedown"), this,
PR_FALSE, PR_FALSE);
chromeEventHandler->AddEventListener(NS_LITERAL_STRING("mouseup"), this,
PR_FALSE, PR_FALSE);
chromeEventHandler->AddEventListener(NS_LITERAL_STRING("mousemove"), this,
PR_FALSE, PR_FALSE);
}
nsWidgetUtils::~nsWidgetUtils()
{
}
NS_IMPL_ISUPPORTS5(nsWidgetUtils, nsIObserver, nsIDOMMouseMotionListener, nsIDOMMouseListener, nsIContentPolicy, nsISupportsWeakReference)
NS_IMPL_ISUPPORTS4(nsWidgetUtils,
nsIObserver,
nsIDOMEventListener,
nsIContentPolicy,
nsISupportsWeakReference)
NS_IMETHODIMP
nsWidgetUtils::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData)

View File

@ -611,7 +611,17 @@ public:
}
NS_IMETHOD GetKind(PRInt32 *kind) {
*kind = MR_OTHER;
*kind = KIND_OTHER;
return NS_OK;
}
NS_IMETHOD GetUnits(PRInt32 *units) {
*units = UNITS_BYTES;
return NS_OK;
}
NS_IMETHOD GetAmount(PRInt64 *amount) {
*amount = gSurfaceMemoryUsed[mType];
return NS_OK;
}
@ -620,11 +630,6 @@ public:
return NS_OK;
}
NS_IMETHOD GetMemoryUsed(PRInt64 *memoryUsed) {
*memoryUsed = gSurfaceMemoryUsed[mType];
return NS_OK;
}
gfxASurface::gfxSurfaceType mType;
};

View File

@ -89,85 +89,37 @@ using namespace mozilla::gfx;
using namespace mozilla;
#ifdef CAIRO_HAS_D2D_SURFACE
class D2DCacheReporter :
public nsIMemoryReporter
NS_MEMORY_REPORTER_IMPLEMENT(
D2DCache,
"gfx-d2d-surfacecache",
KIND_OTHER,
UNITS_BYTES,
cairo_d2d_get_image_surface_cache_usage,
"Memory used by the Direct2D internal surface cache.")
namespace
{
public:
D2DCacheReporter()
{ }
NS_DECL_ISUPPORTS
PRInt64 GetD2DSurfaceVramUsage() {
cairo_device_t *device =
gfxWindowsPlatform::GetPlatform()->GetD2DDevice();
if (device) {
return cairo_d2d_get_surface_vram_usage(device);
}
return 0;
}
NS_IMETHOD GetProcess(char **process) {
*process = strdup("");
return NS_OK;
}
} // anonymous namespace
NS_IMETHOD GetPath(char **memoryPath) {
*memoryPath = strdup("gfx-d2d-surfacecache");
return NS_OK;
}
NS_MEMORY_REPORTER_IMPLEMENT(
D2DVram,
"gfx-d2d-surfacevram",
KIND_OTHER,
UNITS_BYTES,
GetD2DSurfaceVramUsage,
"Video memory used by D2D surfaces")
NS_IMETHOD GetKind(PRInt32 *kind) {
*kind = MR_OTHER;
return NS_OK;
}
NS_IMETHOD GetDescription(char **desc) {
*desc = strdup("Memory used by the Direct2D internal surface cache.");
return NS_OK;
}
NS_IMETHOD GetMemoryUsed(PRInt64 *memoryUsed) {
*memoryUsed = cairo_d2d_get_image_surface_cache_usage();
return NS_OK;
}
};
NS_IMPL_ISUPPORTS1(D2DCacheReporter, nsIMemoryReporter)
class D2DVRAMReporter :
public nsIMemoryReporter
{
public:
D2DVRAMReporter()
{ }
NS_DECL_ISUPPORTS
NS_IMETHOD GetProcess(char **process) {
*process = strdup("");
return NS_OK;
}
NS_IMETHOD GetPath(char **memoryPath) {
*memoryPath = strdup("gfx-d2d-surfacevram");
return NS_OK;
}
NS_IMETHOD GetKind(PRInt32 *kind) {
*kind = MR_OTHER;
return NS_OK;
}
NS_IMETHOD GetDescription(char **desc) {
*desc = strdup("Video memory used by D2D surfaces");
return NS_OK;
}
NS_IMETHOD GetMemoryUsed(PRInt64 *memoryUsed) {
cairo_device_t *device =
gfxWindowsPlatform::GetPlatform()->GetD2DDevice();
if (device) {
*memoryUsed = cairo_d2d_get_surface_vram_usage(device);
} else {
*memoryUsed = 0;
}
return NS_OK;
}
};
NS_IMPL_ISUPPORTS1(D2DVRAMReporter, nsIMemoryReporter)
#endif
#define GFX_USE_CLEARTYPE_ALWAYS "gfx.font_rendering.cleartype.always_use_for_content"
@ -227,8 +179,8 @@ gfxWindowsPlatform::gfxWindowsPlatform()
mScreenDC = GetDC(NULL);
#ifdef CAIRO_HAS_D2D_SURFACE
NS_RegisterMemoryReporter(new D2DCacheReporter());
NS_RegisterMemoryReporter(new D2DVRAMReporter());
NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(D2DCache));
NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(D2DVram));
mD2DDevice = nsnull;
#endif

View File

@ -48,22 +48,22 @@ namespace ipc {
static PRInt64 gShmemAllocated;
static PRInt64 gShmemMapped;
static PRInt64 GetShmemAllocated(void*) { return gShmemAllocated; }
static PRInt64 GetShmemMapped(void*) { return gShmemMapped; }
static PRInt64 GetShmemAllocated() { return gShmemAllocated; }
static PRInt64 GetShmemMapped() { return gShmemMapped; }
NS_MEMORY_REPORTER_IMPLEMENT(ShmemAllocated,
"shmem-allocated",
MR_OTHER,
"Memory shared with other processes that is accessible (but not "
"necessarily mapped).",
KIND_OTHER,
UNITS_BYTES,
GetShmemAllocated,
nsnull)
"Memory shared with other processes that is accessible (but not "
"necessarily mapped).")
NS_MEMORY_REPORTER_IMPLEMENT(ShmemMapped,
"shmem-mapped",
MR_OTHER,
"Memory shared with other processes that is mapped into the address space.",
KIND_OTHER,
UNITS_BYTES,
GetShmemMapped,
nsnull)
"Memory shared with other processes that is mapped into the address space.")
SharedMemory::SharedMemory()
: mAllocSize(0)

View File

@ -1227,10 +1227,8 @@ class XPConnectGCChunkAllocator
public:
XPConnectGCChunkAllocator() {}
static PRInt64 GetGCChunkBytesInUse(void *data) {
XPConnectGCChunkAllocator *allocator =
static_cast<XPConnectGCChunkAllocator*>(data);
return allocator->mNumGCChunksInUse * js::GC_CHUNK_SIZE;
PRInt64 GetGCChunkBytesInUse() {
return mNumGCChunksInUse * js::GC_CHUNK_SIZE;
}
private:
virtual void *doAlloc() {
@ -1263,17 +1261,17 @@ protected:
static XPConnectGCChunkAllocator gXPCJSChunkAllocator;
#ifdef MOZ_MEMORY
#define JS_GC_HEAP_KIND MR_HEAP
#define JS_GC_HEAP_KIND KIND_HEAP
#else
#define JS_GC_HEAP_KIND MR_MAPPED
#define JS_GC_HEAP_KIND KIND_MAPPED
#endif
NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSGCHeap,
"explicit/js/gc-heap",
JS_GC_HEAP_KIND,
"Memory used by the garbage-collected JavaScript heap.",
XPConnectGCChunkAllocator::GetGCChunkBytesInUse,
&gXPCJSChunkAllocator)
UNITS_BYTES,
gXPCJSChunkAllocator.GetGCChunkBytesInUse,
"Memory used by the garbage-collected JavaScript heap.")
static PRInt64
GetPerCompartmentSize(PRInt64 (*f)(JSCompartment *c))
@ -1287,7 +1285,7 @@ GetPerCompartmentSize(PRInt64 (*f)(JSCompartment *c))
}
static PRInt64
GetJSStack(void *data)
GetJSStack()
{
JSRuntime *rt = nsXPConnect::GetRuntimeInstance()->GetJSRuntime();
PRInt64 n = 0;
@ -1298,12 +1296,12 @@ GetJSStack(void *data)
NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSStack,
"explicit/js/stack",
MR_MAPPED,
KIND_MAPPED,
UNITS_BYTES,
GetJSStack,
"Memory used for the JavaScript stack. This is the committed portion "
"of the stack; any uncommitted portion is not measured because it "
"hardly costs anything.",
GetJSStack,
NULL)
"hardly costs anything.")
static PRInt64
GetCompartmentScriptsSize(JSCompartment *c)
@ -1319,7 +1317,7 @@ GetCompartmentScriptsSize(JSCompartment *c)
}
static PRInt64
GetJSScripts(void *data)
GetJSScripts()
{
return GetPerCompartmentSize(GetCompartmentScriptsSize);
}
@ -1348,7 +1346,7 @@ GetJSObjectSlotsCallback(JSContext *cx, void *v, size_t traceKind, void *thing)
#endif
static PRInt64
GetJSObjectSlots(void *dummy)
GetJSObjectSlots()
{
JSRuntime *rt = nsXPConnect::GetRuntimeInstance()->GetJSRuntime();
JSContext *cx = JS_NewContext(rt, 0);
@ -1383,7 +1381,7 @@ GetJSStringCharsCallback(JSContext *cx, void *v, size_t traceKind, void *thing)
#endif
static PRInt64
GetJSStringChars(void *dummy)
GetJSStringChars()
{
JSRuntime *rt = nsXPConnect::GetRuntimeInstance()->GetJSRuntime();
JSContext *cx = JS_NewContext(rt, 0);
@ -1403,34 +1401,33 @@ GetJSStringChars(void *dummy)
NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSScripts,
"explicit/js/scripts",
MR_HEAP,
KIND_HEAP,
UNITS_BYTES,
GetJSScripts,
"Memory allocated for JSScripts. A JSScript is created for each "
"user-defined function in a script. One is also created for "
"the top-level code in a script. Each JSScript includes byte-code and "
"various other things.",
GetJSScripts,
NULL)
"various other things.")
NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSObjectSlots,
"explicit/js/object-slots",
MR_HEAP,
KIND_HEAP,
UNITS_BYTES,
GetJSObjectSlots,
"Memory allocated for non-fixed object slot arrays, which are used "
"to represent object properties. Some objects also contain a fixed "
"number of slots which are stored on the JavaScript heap; those slots "
"are not counted here.",
GetJSObjectSlots,
NULL)
"are not counted here.")
NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSStringChars,
"explicit/js/string-chars",
MR_HEAP,
KIND_HEAP,
UNITS_BYTES,
GetJSStringChars,
"Memory allocated to hold string characters. Not all of this allocated "
"memory is necessarily used to hold characters. Each string also "
"includes a header which is stored on the JavaScript heap; that header "
"is not counted here.",
GetJSStringChars,
NULL)
"is not counted here.")
#ifdef JS_METHODJIT
@ -1441,13 +1438,13 @@ GetCompartmentMjitCodeSize(JSCompartment *c)
}
static PRInt64
GetJSMjitCode(void *data)
GetJSMjitCode()
{
return GetPerCompartmentSize(GetCompartmentMjitCodeSize);
}
static PRInt64
GetJSMJitData(void *data)
GetJSMJitData()
{
JSRuntime *rt = nsXPConnect::GetRuntimeInstance()->GetJSRuntime();
return rt->mjitDataSize;
@ -1455,18 +1452,19 @@ GetJSMJitData(void *data)
NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSMjitCode,
"explicit/js/mjit-code",
MR_MAPPED,
"Memory used by the method JIT to hold generated code.",
KIND_MAPPED,
UNITS_BYTES,
GetJSMjitCode,
NULL)
"Memory used by the method JIT to hold generated code.")
NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSMjitData,
"explicit/js/mjit-data",
MR_HEAP,
"Memory used by the method JIT for the following data: "
"JITScripts, native maps, and inline cache structs.",
KIND_HEAP,
UNITS_BYTES,
GetJSMJitData,
NULL)
"Memory used by the method JIT for the following data: "
"JITScripts, native maps, and inline cache structs.")
#endif // JS_METHODJIT
#ifdef JS_TRACER
@ -1499,44 +1497,45 @@ GetCompartmentTjitDataAllocatorsReserve(JSCompartment *c)
}
static PRInt64
GetJSTjitCode(void *data)
GetJSTjitCode()
{
return GetPerCompartmentSize(GetCompartmentTjitCode);
}
static PRInt64
GetJSTjitDataAllocatorsMain(void *data)
GetJSTjitDataAllocatorsMain()
{
return GetPerCompartmentSize(GetCompartmentTjitDataAllocatorsMain);
}
static PRInt64
GetJSTjitDataAllocatorsReserve(void *data)
GetJSTjitDataAllocatorsReserve()
{
return GetPerCompartmentSize(GetCompartmentTjitDataAllocatorsReserve);
}
NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSTjitCode,
"explicit/js/tjit-code",
MR_MAPPED,
"Memory used by the trace JIT to hold generated code.",
KIND_MAPPED,
UNITS_BYTES,
GetJSTjitCode,
NULL)
"Memory used by the trace JIT to hold generated code.")
NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSTjitDataAllocatorsMain,
"explicit/js/tjit-data/allocators-main",
MR_HEAP,
"Memory used by the trace JIT's VMAllocators.",
KIND_HEAP,
UNITS_BYTES,
GetJSTjitDataAllocatorsMain,
NULL)
"Memory used by the trace JIT's VMAllocators.")
NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSTjitDataAllocatorsReserve,
"explicit/js/tjit-data/allocators-reserve",
MR_HEAP,
"Memory used by the trace JIT and held in reserve for VMAllocators "
"in case of OOM.",
KIND_HEAP,
UNITS_BYTES,
GetJSTjitDataAllocatorsReserve,
NULL)
"Memory used by the trace JIT and held in reserve for VMAllocators "
"in case of OOM.")
#endif // JS_TRACER
XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect)

View File

@ -1452,11 +1452,11 @@ public:
}
static PRInt64 SizeOfLayoutMemoryReporter(void *) {
static PRInt64 SizeOfLayoutMemoryReporter() {
return EstimateShellsMemory(LiveShellSizeEnumerator);
}
static PRInt64 SizeOfBidiMemoryReporter(void *) {
static PRInt64 SizeOfBidiMemoryReporter() {
return EstimateShellsMemory(LiveShellBidiSizeEnumerator);
}
@ -1670,17 +1670,17 @@ static PRBool sSynthMouseMove = PR_TRUE;
NS_MEMORY_REPORTER_IMPLEMENT(LayoutPresShell,
"explicit/layout/all",
MR_HEAP,
"Memory used by layout PresShell, PresContext, and other related areas.",
KIND_HEAP,
UNITS_BYTES,
PresShell::SizeOfLayoutMemoryReporter,
nsnull)
"Memory used by layout PresShell, PresContext, and other related areas.")
NS_MEMORY_REPORTER_IMPLEMENT(LayoutBidi,
"explicit/layout/bidi",
MR_HEAP,
"Memory used by layout Bidi processor.",
KIND_HEAP,
UNITS_BYTES,
PresShell::SizeOfBidiMemoryReporter,
nsnull)
"Memory used by layout Bidi processor.")
PresShell::PresShell()
: mMouseLocation(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE)

View File

@ -87,7 +87,11 @@ nsNthIndexCache::IndexDetermined(nsIContent* aSibling, Element* aChild,
NS_ASSERTION(siblingIndex != 0,
"How can a non-anonymous node have an anonymous sibling?");
if (siblingIndex > 0) {
aResult = siblingIndex + 1;
// At this point, aResult is a count of how many elements matching
// aChild we have seen after aSibling, including aChild itself. So if
// |siblingIndex| is the index of aSibling, we need to add aResult to
// get the right answer here.
aResult = siblingIndex + aResult;
return true;
}
}

View File

@ -127,6 +127,7 @@ _TEST_FILES = test_acid3_test46.html \
test_bug635286.html \
test_bug652486.html \
test_bug657143.html \
test_bug667520.html \
test_cascade.html \
test_compute_data_with_start_struct.html \
test_computed_style.html \

View File

@ -0,0 +1,51 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=667520
-->
<head>
<title>Test for Bug 667520</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=667520">Mozilla Bug 667520</a>
<p id="display">
<!-- important: we need a <span> as the second element child and then
non-span elements between that and the next </span> -->
<i></i>
<span id="2"></span>
<i></i>
<i></i>
<i></i>
<i></i>
<span id="7"></span>
<span id="8"></span>
</p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 667520 **/
var spans = $("display").querySelectorAll("span");
is(spans.length, 3, "Should have 3 span kids");
is($("display").querySelector("span:nth-child(3)"), null, "Third child is not span");
is($("display").querySelector("span:nth-child(4)"), null, "Fourth child is not span");
for (var i = 0; i < spans.length; ++i) {
var id = spans[i].id;
/* Important: need to include 'span' in that selector so we only match
nth-child against spans. */
var target = $("display").querySelector("span:nth-child("+id+")");
is(target, spans[i], "Unexpected element");
is(target.id, spans[i].id, "Unexpected id");
}
</script>
</pre>
</body>
</html>

View File

@ -188,29 +188,13 @@ public:
NS_IMETHOD GetKind(PRInt32 *kind)
{
*kind = MR_HEAP;
*kind = KIND_HEAP;
return NS_OK;
}
NS_IMETHOD GetDescription(char **desc)
NS_IMETHOD GetUnits(PRInt32 *units)
{
if (mType == ChromeUsedRaw) {
*desc = strdup("Memory used by in-use chrome images (compressed data).");
} else if (mType == ChromeUsedUncompressed) {
*desc = strdup("Memory used by in-use chrome images (uncompressed data).");
} else if (mType == ChromeUnusedRaw) {
*desc = strdup("Memory used by not in-use chrome images (compressed data).");
} else if (mType == ChromeUnusedUncompressed) {
*desc = strdup("Memory used by not in-use chrome images (uncompressed data).");
} else if (mType == ContentUsedRaw) {
*desc = strdup("Memory used by in-use content images (compressed data).");
} else if (mType == ContentUsedUncompressed) {
*desc = strdup("Memory used by in-use content images (uncompressed data).");
} else if (mType == ContentUnusedRaw) {
*desc = strdup("Memory used by not in-use content images (compressed data).");
} else if (mType == ContentUnusedUncompressed) {
*desc = strdup("Memory used by not in-use content images (uncompressed data).");
}
*units = UNITS_BYTES;
return NS_OK;
}
@ -252,7 +236,7 @@ public:
return PL_DHASH_NEXT;
}
NS_IMETHOD GetMemoryUsed(PRInt64 *memoryUsed)
NS_IMETHOD GetAmount(PRInt64 *amount)
{
EnumArg arg(mType);
if (mType & CHROME_BIT) {
@ -261,7 +245,29 @@ public:
imgLoader::sCache.EnumerateRead(EnumEntries, &arg);
}
*memoryUsed = arg.value;
*amount = arg.value;
return NS_OK;
}
NS_IMETHOD GetDescription(char **desc)
{
if (mType == ChromeUsedRaw) {
*desc = strdup("Memory used by in-use chrome images (compressed data).");
} else if (mType == ChromeUsedUncompressed) {
*desc = strdup("Memory used by in-use chrome images (uncompressed data).");
} else if (mType == ChromeUnusedRaw) {
*desc = strdup("Memory used by not in-use chrome images (compressed data).");
} else if (mType == ChromeUnusedUncompressed) {
*desc = strdup("Memory used by not in-use chrome images (uncompressed data).");
} else if (mType == ContentUsedRaw) {
*desc = strdup("Memory used by in-use content images (compressed data).");
} else if (mType == ContentUsedUncompressed) {
*desc = strdup("Memory used by in-use content images (uncompressed data).");
} else if (mType == ContentUnusedRaw) {
*desc = strdup("Memory used by not in-use content images (compressed data).");
} else if (mType == ContentUnusedUncompressed) {
*desc = strdup("Memory used by not in-use content images (uncompressed data).");
}
return NS_OK;
}

View File

@ -33,7 +33,7 @@ window.onload = function() {
while (e.hasMoreElements()) {
var mr =
e.getNext().QueryInterface(Components.interfaces.nsIMemoryReporter);
memoryCounter += mr.memoryUsed;
memoryCounter += mr.amount;
}
ok(memoryCounter > 0, "we should be using a nonzero amount of memory");
ok(true, "yay, didn't crash!");

View File

@ -377,10 +377,35 @@ public:
NS_IMETHOD GetKind(PRInt32 *kind)
{
*kind = MR_HEAP;
*kind = KIND_HEAP;
return NS_OK;
}
NS_IMETHOD GetUnits(PRInt32 *units)
{
*units = UNITS_BYTES;
return NS_OK;
}
NS_IMETHOD GetAmount(PRInt64 *amount)
{
int type = 0;
if (mType == Cache_Used) {
type = SQLITE_DBSTATUS_CACHE_USED;
}
else if (mType == Schema_Used) {
type = SQLITE_DBSTATUS_SCHEMA_USED;
}
else if (mType == Stmt_Used) {
type = SQLITE_DBSTATUS_STMT_USED;
}
int cur=0, max=0;
int rc = ::sqlite3_db_status(mDBConn, type, &cur, &max, 0);
*amount = cur;
return convertResultCode(rc);
}
NS_IMETHOD GetDescription(char **desc)
{
if (mType == Cache_Used) {
@ -396,24 +421,6 @@ public:
return NS_OK;
}
NS_IMETHOD GetMemoryUsed(PRInt64 *memoryUsed)
{
int type = 0;
if (mType == Cache_Used) {
type = SQLITE_DBSTATUS_CACHE_USED;
}
else if (mType == Schema_Used) {
type = SQLITE_DBSTATUS_SCHEMA_USED;
}
else if (mType == Stmt_Used) {
type = SQLITE_DBSTATUS_STMT_USED;
}
int cur=0, max=0;
int rc = ::sqlite3_db_status(mDBConn, type, &cur, &max, 0);
*memoryUsed = cur;
return convertResultCode(rc);
}
Connection &mDBConn;
nsCString mFileName;
ReporterType mType;

View File

@ -133,17 +133,17 @@ namespace storage {
//// Memory Reporting
static PRInt64
GetStorageSQLiteMemoryUsed(void *)
GetStorageSQLiteMemoryUsed()
{
return ::sqlite3_memory_used();
}
NS_MEMORY_REPORTER_IMPLEMENT(StorageSQLiteMemoryUsed,
"explicit/storage/sqlite",
MR_HEAP,
"Memory used by SQLite.",
KIND_HEAP,
UNITS_BYTES,
GetStorageSQLiteMemoryUsed,
nsnull)
"Memory used by SQLite.")
////////////////////////////////////////////////////////////////////////////////
//// Helpers

View File

@ -48,11 +48,13 @@ var gVerbose = (location.href.split(/[\?,]/).indexOf("verbose") !== -1);
var gAddedObserver = false;
const MR_MAPPED = Ci.nsIMemoryReporter.MR_MAPPED;
const MR_HEAP = Ci.nsIMemoryReporter.MR_HEAP;
const MR_OTHER = Ci.nsIMemoryReporter.MR_OTHER;
const KIND_MAPPED = Ci.nsIMemoryReporter.KIND_MAPPED;
const KIND_HEAP = Ci.nsIMemoryReporter.KIND_HEAP;
const KIND_OTHER = Ci.nsIMemoryReporter.KIND_OTHER;
const UNITS_BYTES = Ci.nsIMemoryReporter.UNITS_BYTES;
const UNITS_COUNT = Ci.nsIMemoryReporter.UNITS_COUNT;
const kUnknown = -1; // used for _memoryUsed if a memory reporter failed
const kUnknown = -1; // used for _amount if a memory reporter failed
function onLoad()
{
@ -152,14 +154,15 @@ function update()
// interface Reporter {
// _path: string;
// _kind: number;
// _units: number;
// _amount: number;
// _description: string;
// _memoryUsed: number;
// }
//
// After this point we never use the original memory reporter again.
//
// - Note that copying rOrig.memoryUsed (which calls a C++ function under the
// IDL covers) to r._memoryUsed for every reporter now means that the
// - Note that copying rOrig.amount (which calls a C++ function under the
// IDL covers) to r._amount for every reporter now means that the
// results as consistent as possible -- measurements are made all at
// once before most of the memory required to generate this page is
// allocated.
@ -171,8 +174,9 @@ function update()
var r = {
_path: rOrig.path,
_kind: rOrig.kind,
_description: rOrig.description,
_memoryUsed: rOrig.memoryUsed
_units: rOrig.units,
_amount: rOrig.amount,
_description: rOrig.description
};
if (!reportersByProcess[process]) {
reportersByProcess[process] = {};
@ -180,8 +184,8 @@ function update()
var reporters = reportersByProcess[process];
if (reporters[r._path]) {
// Already an entry; must be a duplicated reporter. This can
// happen legitimately. Sum the sizes.
reporters[r._path]._memoryUsed += r._memoryUsed;
// happen legitimately. Sum the values.
reporters[r._path]._amount += r._amount;
} else {
reporters[r._path] = r;
}
@ -232,9 +236,15 @@ function update()
content.appendChild(div);
}
function cmp_memoryUsed(a, b)
// Compare two memory reporter nodes. We want to group together measurements
// with the same units, so sort first by the nodes' _units field, then sort by
// the amount if the units are equal.
function cmp_amount(a, b)
{
return b._memoryUsed - a._memoryUsed
if (a._units != b._units)
return b._units - a._units;
else
return b._amount - a._amount;
};
/**
@ -256,8 +266,8 @@ function genProcessText(aProcess, aReporters)
* interface Node {
* _name: string;
* _kind: number;
* _amount: number; (non-negative or 'kUnknown')
* _description: string;
* _memoryUsed: number; (non-negative or 'kUnknown')
* _kids: [Node];
* _hasReporter: boolean; (only defined if 'true')
* _hasProblem: boolean; (only defined if 'true')
@ -283,7 +293,7 @@ function genProcessText(aProcess, aReporters)
// and maybe '._hasReporter'. This is done top-down from the reporters.
var t = {
_name: "falseRoot",
_kind: MR_OTHER,
_kind: KIND_OTHER,
_kids: []
};
for (var path in aReporters) {
@ -299,7 +309,7 @@ function genProcessText(aProcess, aReporters)
} else {
var v = {
_name: name,
_kind: MR_OTHER,
_kind: KIND_OTHER,
_kids: []
};
u._kids.push(v);
@ -314,20 +324,20 @@ function genProcessText(aProcess, aReporters)
// treeName at the root.
t = t._kids[0];
// Next, fill in '_description' and '_memoryUsed', and maybe '_hasProblem'
// Next, fill in '_description' and '_amount', and maybe '_hasProblem'
// for each node. This is done bottom-up because for most non-leaf nodes
// '_memoryUsed' and '_description' are determined from the child nodes.
// '_amount' and '_description' are determined from the child nodes.
function fillInTree(aT, aPrepath)
{
var path = aPrepath ? aPrepath + '/' + aT._name : aT._name;
if (aT._kids.length === 0) {
// Leaf node. Must have a reporter.
aT._description = getDescription(aReporters, path);
var memoryUsed = getBytes(aReporters, path);
if (memoryUsed !== kUnknown) {
aT._memoryUsed = memoryUsed;
var amount = getBytes(aReporters, path);
if (amount !== kUnknown) {
aT._amount = amount;
} else {
aT._memoryUsed = 0;
aT._amount = 0;
aT._hasProblem = true;
}
} else {
@ -340,33 +350,33 @@ function genProcessText(aProcess, aReporters)
}
if (aT._hasReporter === true) {
aT._description = getDescription(aReporters, path);
var memoryUsed = getBytes(aReporters, path);
if (memoryUsed !== kUnknown) {
var amount = getBytes(aReporters, path);
if (amount !== kUnknown) {
// Non-leaf node with its own reporter. Use the reporter and add
// an "other" child node.
aT._memoryUsed = memoryUsed;
aT._amount = amount;
var other = {
_name: "other",
_kind: MR_OTHER,
_kind: KIND_OTHER,
_description: "All unclassified " + aT._name + " memory.",
_memoryUsed: aT._memoryUsed - childrenBytes,
_amount: aT._amount - childrenBytes,
_kids: []
};
aT._kids.push(other);
} else {
// Non-leaf node with a reporter that returns kUnknown.
// Use the sum of the children and mark it as problematic.
aT._memoryUsed = childrenBytes;
aT._amount = childrenBytes;
aT._hasProblem = true;
}
} else {
// Non-leaf node without its own reporter. Derive its size and
// description entirely from its children.
aT._memoryUsed = childrenBytes;
aT._amount = childrenBytes;
aT._description = "The sum of all entries below '" + aT._name + "'.";
}
}
return aT._memoryUsed;
return aT._amount;
}
fillInTree(t, "");
@ -376,8 +386,8 @@ function genProcessText(aProcess, aReporters)
var s = "";
function getKnownHeapUsedBytes(aT)
{
if (aT._kind === MR_HEAP) {
return aT._memoryUsed;
if (aT._kind === KIND_HEAP) {
return aT._amount;
} else {
var n = 0;
for (var i = 0; i < aT._kids.length; i++) {
@ -399,24 +409,24 @@ function genProcessText(aProcess, aReporters)
}
var heapUnclassified = {
_name: "heap-unclassified",
_kind: MR_HEAP,
_kind: KIND_HEAP,
_description:
"Memory not classified by a more specific reporter. This includes " +
"memory allocated by the heap allocator in excess of that requested " +
"by the application; this can happen when the heap allocator rounds " +
"up request sizes.",
_memoryUsed: unknownHeapUsedBytes,
_amount: unknownHeapUsedBytes,
_hasProblem: hasProblem,
_kids: []
}
t._kids.push(heapUnclassified);
t._memoryUsed += unknownHeapUsedBytes;
t._amount += unknownHeapUsedBytes;
function shouldOmit(aBytes)
{
return !gVerbose &&
t._memoryUsed !== kUnknown &&
(100 * aBytes / t._memoryUsed) < omitThresholdPerc;
t._amount !== kUnknown &&
(100 * aBytes / t._amount) < omitThresholdPerc;
}
/**
@ -428,10 +438,10 @@ function genProcessText(aProcess, aReporters)
*/
function filterTree(aT)
{
aT._kids.sort(cmp_memoryUsed);
aT._kids.sort(cmp_amount);
for (var i = 0; i < aT._kids.length; i++) {
if (shouldOmit(aT._kids[i]._memoryUsed)) {
if (shouldOmit(aT._kids[i]._amount)) {
// This sub-tree is below the significance threshold
// Remove it and all remaining (smaller) sub-trees, and
// replace them with a single aggregate node.
@ -439,16 +449,16 @@ function genProcessText(aProcess, aReporters)
var aggBytes = 0;
var aggNames = [];
for ( ; i < aT._kids.length; i++) {
aggBytes += aT._kids[i]._memoryUsed;
aggBytes += aT._kids[i]._amount;
aggNames.push(aT._kids[i]._name);
}
aT._kids.splice(i0);
var n = i - i0;
var rSub = {
_name: "(" + n + " omitted)",
_kind: MR_OTHER,
_kind: KIND_OTHER,
_description: "Omitted sub-trees: " + aggNames.join(", ") + ".",
_memoryUsed: aggBytes,
_amount: aggBytes,
_kids: []
};
aT._kids[i0] = rSub;
@ -471,6 +481,57 @@ function genProcessText(aProcess, aReporters)
return text;
}
/**
* Returns the reporter's amount formatted as a human-readable string (with
* units, if applicable).
*
* @param aReporter
* The reporter whose usage we're formatting
* @return The reporter's amount formatted as a human-readable string
*/
function formatReporterAmount(aReporter)
{
switch(aReporter._units) {
case UNITS_BYTES: return formatBytes(aReporter._amount);
case UNITS_COUNT: return formatInt(aReporter._amount);
default: return "(???)"
}
}
/**
* Formats an int as a human-readable string.
*
* @param aN
* The integer to format
* @return A human-readable string representing the int
*/
function formatInt(aN)
{
var neg = false;
if (aN < 0) {
neg = true;
aN = -aN;
}
var s = "";
while (true) {
var k = aN % 1000;
aN = Math.floor(aN / 1000);
if (aN > 0) {
if (k < 10) {
s = ",00" + k + s;
} else if (k < 100) {
s = ",0" + k + s;
} else {
s = "," + k + s;
}
} else {
s = k + s;
break;
}
}
return neg ? "-" + s : s;
}
/**
* Converts a byte count to an appropriate string representation.
*
@ -482,33 +543,6 @@ function formatBytes(aBytes)
{
var unit = gVerbose ? "B" : "MB";
function formatInt(aN)
{
var neg = false;
if (aN < 0) {
neg = true;
aN = -aN;
}
var s = "";
while (true) {
var k = aN % 1000;
aN = Math.floor(aN / 1000);
if (aN > 0) {
if (k < 10) {
s = ",00" + k + s;
} else if (k < 100) {
s = ",0" + k + s;
} else {
s = "," + k + s;
}
} else {
s = k + s;
break;
}
}
return neg ? "-" + s : s;
}
var s;
if (gVerbose) {
s = formatInt(aBytes) + " " + unit;
@ -557,7 +591,7 @@ function getBytes(aReporters, aPath, aDoNotMark)
{
var r = aReporters[aPath];
if (r) {
var bytes = r._memoryUsed;
var bytes = r._amount;
if (!aDoNotMark) {
r._done = true;
}
@ -592,10 +626,10 @@ function genMrValueText(aValue)
function kindToString(aKind)
{
switch (aKind) {
case MR_MAPPED: return "(Mapped) ";
case MR_HEAP: return "(Heap) ";
case MR_OTHER: return "";
default: return "(???) ";
case KIND_MAPPED: return "(Mapped) ";
case KIND_HEAP: return "(Heap) ";
case KIND_OTHER: return "";
default: return "(???) ";
}
}
@ -628,7 +662,7 @@ function genMrNameText(aKind, aDesc, aName, aHasProblem)
*/
function genTreeText(aT)
{
var treeBytes = aT._memoryUsed;
var treeBytes = aT._amount;
var treeBytesLength = formatBytes(treeBytes).length;
/**
@ -677,7 +711,7 @@ function genTreeText(aT)
// Indent more if this entry is narrower than its parent, and update
// aIndentGuide accordingly.
var tMemoryUsedStr = formatBytes(aT._memoryUsed);
var tMemoryUsedStr = formatBytes(aT._amount);
var tBytesLength = tMemoryUsedStr.length;
var extraIndentLength = Math.max(aParentBytesLength - tBytesLength, 0);
if (extraIndentLength > 0) {
@ -690,10 +724,10 @@ function genTreeText(aT)
// Generate the percentage.
var perc = "";
if (aT._memoryUsed === treeBytes) {
if (aT._amount === treeBytes) {
perc = "100.0";
} else {
perc = (100 * aT._memoryUsed / treeBytes).toFixed(2);
perc = (100 * aT._amount / treeBytes).toFixed(2);
perc = pad(perc, 5, '0');
}
perc = "<span class='mrPerc'>(" + perc + "%)</span> ";
@ -742,37 +776,38 @@ function genOtherText(aReporters)
// Generate an array of Reporter-like elements, stripping out all the
// reporters that have already been handled. Also find the width of the
// widest element, so we can format things nicely.
var maxBytesLength = 0;
var maxAmountLength = 0;
var rArray = [];
for (var path in aReporters) {
var r = aReporters[path];
if (!r._done) {
var hasProblem = false;
if (r._memoryUsed === kUnknown) {
if (r._amount === kUnknown) {
hasProblem = true;
}
var elem = {
_path: r._path,
_kind: r._kind,
_units: r._units,
_amount: hasProblem ? 0 : r._amount,
_description: r._description,
_memoryUsed: hasProblem ? 0 : r._memoryUsed,
_hasProblem: hasProblem
};
rArray.push(elem);
var thisBytesLength = formatBytes(elem._memoryUsed).length;
if (thisBytesLength > maxBytesLength) {
maxBytesLength = thisBytesLength;
var thisAmountLength = formatReporterAmount(elem).length;
if (thisAmountLength > maxAmountLength) {
maxAmountLength = thisAmountLength;
}
}
}
rArray.sort(cmp_memoryUsed);
rArray.sort(cmp_amount);
// Generate text for the not-yet-printed values.
var text = "";
for (var i = 0; i < rArray.length; i++) {
var elem = rArray[i];
text += genMrValueText(
pad(formatBytes(elem._memoryUsed), maxBytesLength, ' ')) + " ";
pad(formatReporterAmount(elem), maxAmountLength, ' ')) + " ";
text += genMrNameText(elem._kind, elem._description, elem._path,
elem._hasProblem);
}

View File

@ -35,17 +35,17 @@
const KB = 1024;
const MB = KB * KB;
const kUnknown = -1;
const MAPPED = Ci.nsIMemoryReporter.MR_MAPPED;
const HEAP = Ci.nsIMemoryReporter.MR_HEAP;
const OTHER = Ci.nsIMemoryReporter.MR_OTHER;
const MAPPED = Ci.nsIMemoryReporter.KIND_MAPPED;
const HEAP = Ci.nsIMemoryReporter.KIND_HEAP;
const OTHER = Ci.nsIMemoryReporter.KIND_OTHER;
function f(aProcess, aPath, aKind, aMemoryUsed) {
function f(aProcess, aPath, aKind, aAmount) {
return {
process: aProcess,
path: aPath,
kind: aKind,
description: "(description)",
memoryUsed: aMemoryUsed
amount: aAmount
};
}

View File

@ -37,17 +37,19 @@
* ***** END LICENSE BLOCK ***** */
/**
* This file lists Telemetry histograms collected by Firefox. Format
* is HISTOGRAM(id, minium, maximum, bucket count, histogram kind,
* human-readable description for about:telemetry)
* This file lists Telemetry histograms collected by Firefox. The format is
*
* HISTOGRAM(id, minium, maximum, bucket count, histogram kind,
* human-readable description for about:telemetry)
*
*/
HISTOGRAM(CYCLE_COLLECTOR, 1, 10000, 50, EXPONENTIAL, "Time(ms) spent on cycle collection")
HISTOGRAM(TELEMETRY_PING, 1, 3000, 10, EXPONENTIAL, "Time(ms) taken to submit telemetry info")
HISTOGRAM(TELEMETRY_SUCCESS, 0, 1, 2, BOOLEAN, "Success(No, Yes) rate of telemetry submissions")
HISTOGRAM(MEMORY_JS_GC_HEAP, 1024, 512 * 1024, 10, EXPONENTIAL, "Memory(MB) used by the JavaScript GC")
HISTOGRAM(MEMORY_RESIDENT, 32 * 1024, 1024 * 1024, 10, EXPONENTIAL, "Resident memory(MB) reported by OS")
HISTOGRAM(MEMORY_LAYOUT_ALL, 1024, 64 * 1024, 10, EXPONENTIAL, "Memory(MB) reported used by layout")
HISTOGRAM(CYCLE_COLLECTOR, 1, 10000, 50, EXPONENTIAL, "Time spent on one cycle collection (ms)")
HISTOGRAM(TELEMETRY_PING, 1, 3000, 10, EXPONENTIAL, "Time taken to submit telemetry info (ms)")
HISTOGRAM(TELEMETRY_SUCCESS, 0, 1, 2, BOOLEAN, "Successful telemetry submission")
HISTOGRAM(MEMORY_JS_GC_HEAP, 1024, 512 * 1024, 10, EXPONENTIAL, "Memory used by the garbage-collected JavaScript heap (KB)")
HISTOGRAM(MEMORY_RESIDENT, 32 * 1024, 1024 * 1024, 10, EXPONENTIAL, "Resident memory size (KB)")
HISTOGRAM(MEMORY_LAYOUT_ALL, 1024, 64 * 1024, 10, EXPONENTIAL, "Memory used by layout (KB)")
#if defined(XP_WIN)
HISTOGRAM(EARLY_GLUESTARTUP_READ_OPS, 1, 100, 12, LINEAR, "ProcessIoCounters.ReadOperationCount before glue startup")
HISTOGRAM(EARLY_GLUESTARTUP_READ_TRANSFER, 1, 50 * 1024, 12, EXPONENTIAL, "ProcessIoCounters.ReadTransferCount before glue startup (KB)")
@ -56,5 +58,6 @@ HISTOGRAM(GLUESTARTUP_READ_TRANSFER, 1, 50 * 1024, 12, EXPONENTIAL, "ProcessIoCo
#elif defined(XP_UNIX)
HISTOGRAM(EARLY_GLUESTARTUP_HARD_FAULTS, 1, 100, 12, LINEAR, "Hard faults count before glue startup")
HISTOGRAM(GLUESTARTUP_HARD_FAULTS, 1, 500, 12, EXPONENTIAL, "Hard faults count after glue startup")
HISTOGRAM(HARD_PAGE_FAULTS, 8, 64 * 1024, 13, EXPONENTIAL, "Hard page faults (since last telemetry ping)")
#endif
HISTOGRAM(ZIPARCHIVE_CRC, 0, 1, 2, BOOLEAN, "Zip item CRC check pass")

View File

@ -56,7 +56,8 @@ const TELEMETRY_DELAY = 60000;
const MEM_HISTOGRAMS = {
"explicit/js/gc-heap": "MEMORY_JS_GC_HEAP",
"resident": "MEMORY_RESIDENT",
"explicit/layout/all": "MEMORY_LAYOUT_ALL"
"explicit/layout/all": "MEMORY_LAYOUT_ALL",
"hard-page-faults": "HARD_PAGE_FAULTS"
};
XPCOMUtils.defineLazyGetter(this, "Telemetry", function () {
@ -184,6 +185,7 @@ function TelemetryPing() {}
TelemetryPing.prototype = {
_histograms: {},
_prevValues: {},
/**
* Pull values from about:memory into corresponding histograms
@ -195,27 +197,51 @@ TelemetryPing.prototype = {
getService(Ci.nsIMemoryReporterManager);
} catch (e) {
// OK to skip memory reporters in xpcshell
return
return;
}
let e = mgr.enumerateReporters();
let memReporters = {};
while (e.hasMoreElements()) {
let mr = e.getNext().QueryInterface(Ci.nsIMemoryReporter);
// memReporters[mr.path] = mr.memoryUsed;
// memReporters[mr.path] = mr.amount;
let id = MEM_HISTOGRAMS[mr.path];
if (!id) {
continue;
}
let name = "Memory:" + mr.path + " (KB)";
let h = this._histograms[name];
let val;
if (mr.units == Ci.nsIMemoryReporter.UNITS_BYTES) {
val = Math.floor(mr.amount / 1024);
}
else if (mr.units == Ci.nsIMemoryReporter.UNITS_COUNT) {
// If the reporter gives us a count, we'll report the difference in its
// value between now and our previous ping.
// Read mr.amount just once so our arithmetic is consistent.
let curVal = mr.amount;
let prevVal = this._prevValues[mr.path];
if (!prevVal) {
// If this is the first time we're reading this reporter, store its
// current value but don't report it in the telemetry ping, so we
// ignore the effect startup had on the reporter.
this._prevValues[mr.path] = curVal;
continue;
}
val = curVal - prevVal;
this._prevValues[mr.path] = curVal;
}
else {
NS_ASSERT(false, "Can't handle memory reporter with units " + mr.units);
continue;
}
let h = this._histograms[mr.name];
if (!h) {
h = Telemetry.getHistogramById(id);
this._histograms[name] = h;
this._histograms[mr.name] = h;
}
let v = Math.floor(mr.memoryUsed / 1024);
h.add(v);
h.add(val);
}
return memReporters;
},
@ -250,7 +276,7 @@ TelemetryPing.prototype = {
request.overrideMimeType("text/plain");
request.setRequestHeader("Content-Type", "application/json");
let startTime = new Date()
let startTime = new Date();
function finishRequest(channel) {
let success = false;

View File

@ -87,7 +87,7 @@ function checkHistograms(request, response) {
const TELEMETRY_SUCCESS = "TELEMETRY_SUCCESS";
do_check_true(TELEMETRY_PING in payload.histograms)
// There should be one successful report from the previos telemetry ping
// There should be one successful report from the previous telemetry ping.
const expected_tc = {
range: [1, 2],
bucket_count: 3,

View File

@ -40,15 +40,15 @@
interface nsISimpleEnumerator;
[scriptable, uuid(d298b942-3e66-4cd3-9ff5-46abc69147a7)]
[scriptable, uuid(37d18434-9819-4ce1-922f-15d8b63da066)]
interface nsIMemoryReporter : nsISupports
{
/*
* The name of the process containing this reporter. All reporters start
* with "", which is short-hand for the "main" process; this is true even
* for reporters in child processes. When reporters from child reporters
* are copied into the main process, the copies have their 'process' field
* set appropriately.
* The name of the process containing this reporter. Each reporter initially
* has "" in this field, indicating that it applies to the current process.
* (This is true even for reporters in a child process.) When a reporter
* from a child process is copied into the main process, the copy has its
* 'process' field set appropriately.
*/
readonly attribute string process;
@ -56,15 +56,15 @@ interface nsIMemoryReporter : nsISupports
* The path that this memory usage should be reported under. Paths are
* '/'-delimited, eg. "a/b/c". There are two categories of paths.
*
* - Paths starting with "explicit" represent non-overlapping regions of
* memory that have been explicitly allocated with an OS-level allocation
* (eg. mmap/VirtualAlloc/vm_allocate) or a heap-level allocation (eg.
* malloc/calloc/operator new). Each one can be viewed as representing a
* path in a tree from the root node ("explicit") to a node lower in the
* tree; this lower node does not have to be a leaf node.
* - Paths starting with "explicit" represent regions of memory that have
* been explicitly allocated with an OS-level allocation (eg.
* mmap/VirtualAlloc/vm_allocate) or a heap-level allocation (eg.
* malloc/calloc/operator new).
*
* So, for example, "explicit/a/b", "explicit/a/c", "explicit/d",
* "explicit/d/e", and "explicit/d/f" define this tree:
* Each reporter can be viewed as representing a node in a tree rooted at
* "explicit". Not all nodes of the tree need have an associated reporter.
* So, for example, the reporters "explicit/a/b", "explicit/a/c",
* "explicit/d", "explicit/d/e", and "explicit/d/f" define this tree:
*
* explicit
* |--a
@ -74,40 +74,71 @@ interface nsIMemoryReporter : nsISupports
* |--e [*]
* \--f [*]
*
* Nodes marked with a [*] have a reporter.
* Nodes marked with a [*] have a reporter. Notice that "explicit/a" is
* implicitly defined.
*
* - All other paths represent cross-cuttings memory regions, ie. ones that
* may overlap arbitrarily with regions in the "explicit" tree.
* A node's children divide their parent's memory into disjoint pieces.
* So in the example above, |a| may not count any allocations counted by
* |d|, and vice versa.
*
* - All other paths represent cross-cutting values and may overlap with any
* other reporter.
*/
readonly attribute string path;
/*
* Allocation kinds. "MAPPED" means it is allocated directly by the OS, eg.
* by calling mmap, VirtualAlloc, vm_allocate, etc. "HEAP" means it is
* allocated by the heap allocator, eg. by calling malloc, calloc, realloc,
* memalign, operator new, operator new[], etc. "OTHER" means it doesn't fit
* into either of these categories; such reporters should have a path that
* does *not* start with "explicit".
* There are three categories of memory reporters:
*
* - MAPPED: memory allocated directly by the OS, e.g. by calling mmap,
* VirtualAlloc, or vm_allocate. Reporters in this category must have
* units UNITS_BYTES and must have a path starting with "explicit".
*
* - HEAP: memory allocated by the heap allocator, e.g. by calling malloc,
* calloc, realloc, memalign, operator new, or operator new[]. Reporters
* in this category must have units UNITS_BYTES and must have a path
* starting with "explicit".
*
* - OTHER: reporters which don't fit into either of these categories. Such
* reporters must have a path that does not start with "explicit" and may
* have any units.
*/
const PRInt32 MR_MAPPED = 0;
const PRInt32 MR_HEAP = 1;
const PRInt32 MR_OTHER = 2;
const PRInt32 KIND_MAPPED = 0;
const PRInt32 KIND_HEAP = 1;
const PRInt32 KIND_OTHER = 2;
/*
* The memory kind, see MR_* above.
* The reporter kind. See KIND_* above.
*/
readonly attribute PRInt32 kind;
/*
* The amount reported by a memory reporter may have one of the following
* units, but you may of course add new units as necessary:
*
* - BYTES: The amount contains a number of bytes.
*
* - COUNT: The amount contains the cumulative number of times some event
* has occurred since the application started up. For instance, a
* reporter reporting the number of page faults since startup should have
* units UNITS_COUNT.
*/
const PRInt32 UNITS_BYTES = 0;
const PRInt32 UNITS_COUNT = 1;
/*
* The units on the reporter's amount. See UNITS_* above.
*/
readonly attribute PRInt32 units;
/*
* The numeric value reported by this memory reporter.
*/
readonly attribute long long amount;
/*
* A human-readable description of this memory usage report.
*/
readonly attribute string description;
/*
* The current amount of memory in use, as reported by this memory
* reporter.
*/
readonly attribute long long memoryUsed;
};
[scriptable, uuid(7c62de18-1edd-40f8-9da2-a8c622763074)]
@ -142,16 +173,17 @@ interface nsIMemoryReporterManager : nsISupports
/*
* Note that this defaults 'process' to "", which is usually what's desired.
*/
#define NS_MEMORY_REPORTER_IMPLEMENT(_classname,_path,_kind,_desc,_usageFunction,_dataptr) \
class MemoryReporter_##_classname : public nsIMemoryReporter { \
public: \
NS_DECL_ISUPPORTS \
NS_IMETHOD GetProcess(char **process) { *process = strdup(""); return NS_OK; } \
NS_IMETHOD GetPath(char **memoryPath) { *memoryPath = strdup(_path); return NS_OK; } \
NS_IMETHOD GetKind(int *kind) { *kind = _kind; return NS_OK; } \
NS_IMETHOD GetDescription(char **desc) { *desc = strdup(_desc); return NS_OK; } \
NS_IMETHOD GetMemoryUsed(PRInt64 *memoryUsed) { *memoryUsed = _usageFunction(_dataptr); return NS_OK; } \
}; \
#define NS_MEMORY_REPORTER_IMPLEMENT(_classname, _path, _kind, _units, _usageFunction, _desc) \
class MemoryReporter_##_classname : public nsIMemoryReporter { \
public: \
NS_DECL_ISUPPORTS \
NS_IMETHOD GetProcess(char **process) { *process = strdup(""); return NS_OK; } \
NS_IMETHOD GetPath(char **memoryPath) { *memoryPath = strdup(_path); return NS_OK; } \
NS_IMETHOD GetKind(int *kind) { *kind = _kind; return NS_OK; } \
NS_IMETHOD GetUnits(int *units) { *units = _units; return NS_OK; } \
NS_IMETHOD GetAmount(PRInt64 *amount) { *amount = _usageFunction(); return NS_OK; } \
NS_IMETHOD GetDescription(char **desc) { *desc = strdup(_desc); return NS_OK; } \
}; \
NS_IMPL_ISUPPORTS1(MemoryReporter_##_classname, nsIMemoryReporter)
#define NS_MEMORY_REPORTER_NAME(_classname) MemoryReporter_##_classname

View File

@ -41,6 +41,35 @@
#include "nsMemoryReporterManager.h"
#include "nsArrayEnumerator.h"
#if defined(XP_LINUX) || defined(XP_MACOSX)
#include <sys/time.h>
#include <sys/resource.h>
static PRInt64 GetHardPageFaults()
{
struct rusage usage;
int err = getrusage(RUSAGE_SELF, &usage);
if (err != 0) {
return PRInt64(-1);
}
return usage.ru_majflt;
}
static PRInt64 GetSoftPageFaults()
{
struct rusage usage;
int err = getrusage(RUSAGE_SELF, &usage);
if (err != 0) {
return PRInt64(-1);
}
return usage.ru_minflt;
}
#endif
#if defined(XP_LINUX)
#include <unistd.h>
@ -60,12 +89,12 @@ static PRInt64 GetProcSelfStatmField(int n)
return (PRInt64) -1;
}
static PRInt64 GetVsize(void *)
static PRInt64 GetVsize()
{
return GetProcSelfStatmField(0);
}
static PRInt64 GetResident(void *)
static PRInt64 GetResident()
{
return GetProcSelfStatmField(1);
}
@ -86,13 +115,13 @@ static bool GetTaskBasicInfo(struct task_basic_info *ti)
// The VSIZE figure on Mac includes huge amounts of shared memory and is always
// absurdly high, eg. 2GB+ even at start-up. But both 'top' and 'ps' report
// it, so we might as well too.
static PRInt64 GetVsize(void *)
static PRInt64 GetVsize()
{
task_basic_info ti;
return (PRInt64) (GetTaskBasicInfo(&ti) ? ti.virtual_size : -1);
}
static PRInt64 GetResident(void *)
static PRInt64 GetResident()
{
task_basic_info ti;
return (PRInt64) (GetTaskBasicInfo(&ti) ? ti.resident_size : -1);
@ -104,7 +133,7 @@ static PRInt64 GetResident(void *)
#include <psapi.h>
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
static PRInt64 GetPrivate(void *)
static PRInt64 GetPrivate()
{
PROCESS_MEMORY_COUNTERS_EX pmcex;
pmcex.cb = sizeof(PROCESS_MEMORY_COUNTERS_EX);
@ -118,15 +147,15 @@ static PRInt64 GetPrivate(void *)
NS_MEMORY_REPORTER_IMPLEMENT(Private,
"private",
MR_OTHER,
KIND_OTHER,
UNITS_BYTES,
GetPrivate,
"Memory that cannot be shared with other processes, including memory that "
"is committed and marked MEM_PRIVATE, data that is not mapped, and "
"executable pages that have been written to.",
GetPrivate,
NULL)
"executable pages that have been written to.")
#endif
static PRInt64 GetResident(void *)
static PRInt64 GetResident()
{
PROCESS_MEMORY_COUNTERS pmc;
pmc.cb = sizeof(PROCESS_MEMORY_COUNTERS);
@ -139,7 +168,7 @@ static PRInt64 GetResident(void *)
#else
static PRInt64 GetResident(void *)
static PRInt64 GetResident()
{
return (PRInt64) -1;
}
@ -149,7 +178,9 @@ static PRInt64 GetResident(void *)
#if defined(XP_LINUX) || defined(XP_MACOSX)
NS_MEMORY_REPORTER_IMPLEMENT(Vsize,
"vsize",
MR_OTHER,
KIND_OTHER,
UNITS_BYTES,
GetVsize,
"Memory mapped by the process, including code and data segments, the "
"heap, thread stacks, memory explicitly mapped by the process via mmap "
"and similar operations, and memory shared with other processes. "
@ -157,22 +188,51 @@ NS_MEMORY_REPORTER_IMPLEMENT(Vsize,
"by the process.) "
"This is the vsize figure as reported by 'top' or 'ps'; on Mac the amount "
"of memory shared with other processes is very high and so this figure is "
"of limited use.",
GetVsize,
NULL)
"of limited use.")
NS_MEMORY_REPORTER_IMPLEMENT(SoftPageFaults,
"soft-page-faults",
KIND_OTHER,
UNITS_COUNT,
GetSoftPageFaults,
"The number of soft page faults (also known as \"minor page faults\") that "
"have occurred since the process started. A soft page fault occurs when the "
"process tries to access a page which is present in physical memory but is "
"not mapped into the process's address space. For instance, a process might "
"observe soft page faults when it loads a shared library which is already "
"present in physical memory. A process may experience many thousands of soft "
"page faults even when the machine has plenty of available physical memory, "
"and because the OS services a soft page fault without accessing the disk, "
"they impact performance much less than hard page faults.")
NS_MEMORY_REPORTER_IMPLEMENT(HardPageFaults,
"hard-page-faults",
KIND_OTHER,
UNITS_COUNT,
GetHardPageFaults,
"The number of hard page faults (also known as \"major page faults\") that "
"have occurred since the process started. A hard page fault occurs when a "
"process tries to access a page which is not present in physical memory. "
"The operating system must access the disk in order to fulfill a hard page "
"fault. When memory is plentiful, you should see very few hard page faults. "
"But if the process tries to use more memory than your machine has "
"available, you may see many thousands of hard page faults. Because "
"accessing the disk is up to a million times slower than accessing RAM, "
"the program may run very slowly when it is experiencing more than 100 or "
"so hard page faults a second.")
#endif
NS_MEMORY_REPORTER_IMPLEMENT(Resident,
"resident",
MR_OTHER,
KIND_OTHER,
UNITS_BYTES,
GetResident,
"Memory mapped by the process that is present in physical memory, "
"also known as the resident set size (RSS). This is the best single "
"figure to use when considering the memory resources used by the process, "
"but it depends both on other processes being run and details of the OS "
"kernel and so is best used for comparing the memory usage of a single "
"process at different points in time.",
GetResident,
NULL)
"process at different points in time.")
/**
** memory reporter implementation for jemalloc and OSX malloc,
@ -200,28 +260,28 @@ extern void jemalloc_stats(jemalloc_stats_t* stats)
#if HAVE_JEMALLOC_STATS
static PRInt64 GetHeapUsed(void *)
static PRInt64 GetHeapUsed()
{
jemalloc_stats_t stats;
jemalloc_stats(&stats);
return (PRInt64) stats.allocated;
}
static PRInt64 GetHeapUnused(void *)
static PRInt64 GetHeapUnused()
{
jemalloc_stats_t stats;
jemalloc_stats(&stats);
return (PRInt64) (stats.mapped - stats.allocated);
}
static PRInt64 GetHeapCommitted(void *)
static PRInt64 GetHeapCommitted()
{
jemalloc_stats_t stats;
jemalloc_stats(&stats);
return (PRInt64) stats.committed;
}
static PRInt64 GetHeapDirty(void *)
static PRInt64 GetHeapDirty()
{
jemalloc_stats_t stats;
jemalloc_stats(&stats);
@ -230,42 +290,42 @@ static PRInt64 GetHeapDirty(void *)
NS_MEMORY_REPORTER_IMPLEMENT(HeapCommitted,
"heap-committed",
MR_OTHER,
"Memory mapped by the heap allocator that is committed, i.e. in physical "
"memory or paged to disk.",
KIND_OTHER,
UNITS_BYTES,
GetHeapCommitted,
NULL)
"Memory mapped by the heap allocator that is committed, i.e. in physical "
"memory or paged to disk.")
NS_MEMORY_REPORTER_IMPLEMENT(HeapDirty,
"heap-dirty",
MR_OTHER,
"Memory mapped by the heap allocator that is committed but unused.",
KIND_OTHER,
UNITS_BYTES,
GetHeapDirty,
NULL)
"Memory mapped by the heap allocator that is committed but unused.")
#elif defined(XP_MACOSX) && !defined(MOZ_MEMORY)
#include <malloc/malloc.h>
static PRInt64 GetHeapUsed(void *)
static PRInt64 GetHeapUsed()
{
struct mstats stats = mstats();
return (PRInt64) stats.bytes_used;
}
static PRInt64 GetHeapUnused(void *)
static PRInt64 GetHeapUnused()
{
struct mstats stats = mstats();
return (PRInt64) (stats.bytes_total - stats.bytes_used);
}
static PRInt64 GetHeapZone0Committed(void *)
static PRInt64 GetHeapZone0Committed()
{
malloc_statistics_t stats;
malloc_zone_statistics(malloc_default_zone(), &stats);
return stats.size_in_use;
}
static PRInt64 GetHeapZone0Used(void *)
static PRInt64 GetHeapZone0Used()
{
malloc_statistics_t stats;
malloc_zone_statistics(malloc_default_zone(), &stats);
@ -274,27 +334,27 @@ static PRInt64 GetHeapZone0Used(void *)
NS_MEMORY_REPORTER_IMPLEMENT(HeapZone0Committed,
"heap-zone0-committed",
MR_OTHER,
"Memory mapped by the heap allocator that is committed in the default "
"zone.",
KIND_OTHER,
UNITS_BYTES,
GetHeapZone0Committed,
NULL)
"Memory mapped by the heap allocator that is committed in the default "
"zone.")
NS_MEMORY_REPORTER_IMPLEMENT(HeapZone0Used,
"heap-zone0-used",
MR_OTHER,
"Memory mapped by the heap allocator in the default zone that is "
"available for use by the application.",
KIND_OTHER,
UNITS_BYTES,
GetHeapZone0Used,
NULL)
"Memory mapped by the heap allocator in the default zone that is "
"available for use by the application.")
#else
static PRInt64 GetHeapUsed(void *)
static PRInt64 GetHeapUsed()
{
return (PRInt64) -1;
}
static PRInt64 GetHeapUnused(void *)
static PRInt64 GetHeapUnused()
{
return (PRInt64) -1;
}
@ -303,22 +363,22 @@ static PRInt64 GetHeapUnused(void *)
NS_MEMORY_REPORTER_IMPLEMENT(HeapUsed,
"heap-used",
MR_OTHER,
KIND_OTHER,
UNITS_BYTES,
GetHeapUsed,
"Memory mapped by the heap allocator that is available for use by the "
"application. This may exceed the amount of memory requested by the "
"application due to the allocator rounding up request sizes. "
"(The exact amount requested is not measured.) ",
GetHeapUsed,
NULL)
"(The exact amount requested is not measured.) ")
NS_MEMORY_REPORTER_IMPLEMENT(HeapUnused,
"heap-unused",
MR_OTHER,
KIND_OTHER,
UNITS_BYTES,
GetHeapUnused,
"Memory mapped by the heap allocator and not available for use by the "
"application. This can grow large if the heap allocator is holding onto "
"memory that the application has freed.",
GetHeapUnused,
NULL)
"memory that the application has freed.")
/**
** nsMemoryReporterManager implementation
@ -342,6 +402,8 @@ nsMemoryReporterManager::Init()
#if defined(XP_LINUX) || defined(XP_MACOSX)
REGISTER(Vsize);
REGISTER(SoftPageFaults);
REGISTER(HardPageFaults);
#elif defined(XP_WIN) && MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
REGISTER(Private);
#endif
@ -401,13 +463,15 @@ NS_IMPL_ISUPPORTS1(nsMemoryReporter, nsIMemoryReporter)
nsMemoryReporter::nsMemoryReporter(nsCString& process,
nsCString& path,
PRInt32 kind,
nsCString& desc,
PRInt64 memoryUsed)
PRInt32 units,
PRInt64 amount,
nsCString& desc)
: mProcess(process)
, mPath(path)
, mKind(kind)
, mUnits(units)
, mDesc(desc)
, mMemoryUsed(memoryUsed)
, mAmount(amount)
{
}
@ -433,15 +497,21 @@ NS_IMETHODIMP nsMemoryReporter::GetKind(PRInt32 *aKind)
return NS_OK;
}
NS_IMETHODIMP nsMemoryReporter::GetDescription(char **aDescription)
NS_IMETHODIMP nsMemoryReporter::GetUnits(PRInt32 *aUnits)
{
*aDescription = strdup(mDesc.get());
*aUnits = mUnits;
return NS_OK;
}
NS_IMETHODIMP nsMemoryReporter::GetAmount(PRInt64 *aAmount)
{
*aAmount = mAmount;
return NS_OK;
}
NS_IMETHODIMP nsMemoryReporter::GetMemoryUsed(PRInt64 *aMemoryUsed)
NS_IMETHODIMP nsMemoryReporter::GetDescription(char **aDescription)
{
*aMemoryUsed = mMemoryUsed;
*aDescription = strdup(mDesc.get());
return NS_OK;
}

View File

@ -14,8 +14,9 @@ public:
nsMemoryReporter(nsCString& process,
nsCString& path,
PRInt32 kind,
nsCString& desc,
PRInt64 memoryUsed);
PRInt32 units,
PRInt64 amount,
nsCString& desc);
~nsMemoryReporter();
@ -23,8 +24,9 @@ protected:
nsCString mProcess;
nsCString mPath;
PRInt32 mKind;
PRInt32 mUnits;
PRInt64 mAmount;
nsCString mDesc;
PRInt64 mMemoryUsed;
};

View File

@ -730,6 +730,7 @@ nsComponentManagerImpl::ManifestBinaryComponent(ManifestProcessingContext& cx, i
}
const mozilla::Module* m = mNativeModuleLoader.LoadModule(clfile);
// The native module loader should report an error here, we don't have to
if (!m)
return;

View File

@ -58,6 +58,7 @@
#include "prerror.h"
#include "nsComponentManager.h"
#include "ManifestParser.h" // for LogMessage
#include "nsCRTGlue.h"
#include "nsThreadUtils.h"
#include "nsTraceRefcntImpl.h"
@ -168,17 +169,8 @@ nsNativeModuleLoader::LoadModule(nsILocalFile* aFile)
if (PR_GetErrorTextLength() < (int) sizeof(errorMsg))
PR_GetErrorText(errorMsg);
LOG(PR_LOG_ERROR,
("nsNativeModuleLoader::LoadModule(\"%s\") - load FAILED, "
"rv: %lx, error:\n\t%s\n",
filePath.get(), rv, errorMsg));
#ifdef DEBUG
fprintf(stderr,
"nsNativeModuleLoader::LoadModule(\"%s\") - load FAILED, "
"rv: %lx, error:\n\t%s\n",
filePath.get(), (unsigned long)rv, errorMsg);
#endif
LogMessage("Failed to load native module at path '%s': (%lx) %s",
filePath.get(), rv, errorMsg);
return NULL;
}
@ -202,23 +194,24 @@ nsNativeModuleLoader::LoadModule(nsILocalFile* aFile)
#endif
void *module = PR_FindSymbol(data.library, "NSModule");
if (module) {
data.module = *(mozilla::Module const *const *) module;
if (mozilla::Module::kVersion == data.module->mVersion &&
mLibraries.Put(hashedFile, data))
return data.module;
}
else {
LOG(PR_LOG_ERROR,
("nsNativeModuleLoader::LoadModule(\"%s\") - "
"Symbol NSModule not found", filePath.get()));
if (!module) {
LogMessage("Native module at path '%s' doesn't export symbol `NSModule`.",
filePath.get());
PR_UnloadLibrary(data.library);
return NULL;
}
// at some point we failed, clean up
data.module = nsnull;
PR_UnloadLibrary(data.library);
return NULL;
data.module = *(mozilla::Module const *const *) module;
if (mozilla::Module::kVersion != data.module->mVersion) {
LogMessage("Native module at path '%s' is incompatible with this version of Firefox, has version %i, expected %i.",
filePath.get(), data.module->mVersion,
mozilla::Module::kVersion);
PR_UnloadLibrary(data.library);
return NULL;
}
mLibraries.Put(hashedFile, data); // infallible
return data.module;
}
const mozilla::Module*

View File

@ -45,17 +45,17 @@
using namespace mozilla;
static PRInt64 GetXPTArenaSize(void*)
static PRInt64 GetXPTArenaSize()
{
return XPT_SizeOfArena(gXPTIStructArena);
}
NS_MEMORY_REPORTER_IMPLEMENT(xptiWorkingSet,
"explicit/xpti-working-set",
MR_HEAP,
"Memory used by the XPCOM typelib system.",
KIND_HEAP,
UNITS_BYTES,
GetXPTArenaSize,
nsnull)
"Memory used by the XPCOM typelib system.")
#define XPTI_STRUCT_ARENA_BLOCK_SIZE (1024 * 1)
#define XPTI_HASHTABLE_SIZE 2048

View File

@ -1,6 +1,39 @@
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
const Cc = Components.classes;
const Ci = Components.interfaces;
function info(s) {
dump("TEST-INFO | test_bug656331.js | " + s + "\n");
}
var gMessageExpected = /Native module.*has version 3.*expected/;
var gFound = false;
const kConsoleListener = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIConsoleListener]),
observe: function listener_observe(message) {
if (gMessageExpected.test(message.message))
gFound = true;
}
};
function run_test() {
manifest = do_get_file('bug656331.manifest');
let cs = Components.classes["@mozilla.org/consoleservice;1"].
getService(Ci.nsIConsoleService);
cs.registerListener(kConsoleListener);
let manifest = do_get_file('bug656331.manifest');
Components.manager.autoRegister(manifest);
do_check_false("{f18fb09b-28b4-4435-bc5b-8027f18df743}" in Components.classesByID);
do_test_pending();
Components.classes["@mozilla.org/thread-manager;1"].
getService(Ci.nsIThreadManager).mainThread.dispatch(function() {
cs.unregisterListener(kConsoleListener);
do_check_true(gFound);
do_test_finished();
}, 0);
}