Merge last green changeset from m-i to m-c.
@ -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);
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
@ -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>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 88 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 974 B |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 289 KiB |
Before Width: | Height: | Size: 355 KiB After Width: | Height: | Size: 289 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 83 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 924 B |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 289 KiB |
Before Width: | Height: | Size: 355 KiB After Width: | Height: | Size: 289 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 24 KiB |
@ -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=''
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 =
|
||||
|
@ -45,8 +45,9 @@ struct MemoryReport {
|
||||
nsCString process;
|
||||
nsCString path;
|
||||
PRInt32 kind;
|
||||
PRInt32 units;
|
||||
PRInt64 amount;
|
||||
nsCString desc;
|
||||
PRInt64 memoryUsed;
|
||||
};
|
||||
|
||||
protocol PMemoryReportRequest {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@
|
||||
#include "nsTHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
|
||||
#ifdef OS_MACOSX
|
||||
#ifdef MOZ_WIDGET_COCOA
|
||||
#include "PluginInterposeOSX.h"
|
||||
#endif
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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 \
|
||||
|
51
layout/style/test/test_bug667520.html
Normal 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>
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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!");
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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")
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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*
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|