This commit is contained in:
Ali Juma 2012-02-01 12:07:14 -05:00
Родитель 53e65f8033 ecc3d5e4cf
Коммит 75e154812c
35 изменённых файлов: 536 добавлений и 686 удалений

Просмотреть файл

@ -574,59 +574,6 @@ nsRootAccessible::Shutdown()
nsDocAccessibleWrap::Shutdown(); nsDocAccessibleWrap::Shutdown();
} }
// nsRootAccessible protected member
already_AddRefed<nsIDocShellTreeItem>
nsRootAccessible::GetContentDocShell(nsIDocShellTreeItem *aStart)
{
if (!aStart) {
return nsnull;
}
PRInt32 itemType;
aStart->GetItemType(&itemType);
if (itemType == nsIDocShellTreeItem::typeContent) {
nsDocAccessible *accDoc = nsAccUtils::GetDocAccessibleFor(aStart);
// Hidden documents don't have accessibles (like SeaMonkey's sidebar),
// they are of no interest for a11y.
if (!accDoc)
return nsnull;
// If ancestor chain of accessibles is not completely visible,
// don't use this one. This happens for example if it's inside
// a background tab (tabbed browsing)
nsAccessible* parent = accDoc->Parent();
while (parent) {
if (parent->State() & states::INVISIBLE)
return nsnull;
if (parent == this)
break; // Don't check past original root accessible we started with
parent = parent->Parent();
}
NS_ADDREF(aStart);
return aStart;
}
nsCOMPtr<nsIDocShellTreeNode> treeNode(do_QueryInterface(aStart));
if (treeNode) {
PRInt32 subDocuments;
treeNode->GetChildCount(&subDocuments);
for (PRInt32 count = 0; count < subDocuments; count ++) {
nsCOMPtr<nsIDocShellTreeItem> treeItemChild, contentTreeItem;
treeNode->GetChildAt(count, getter_AddRefs(treeItemChild));
NS_ENSURE_TRUE(treeItemChild, nsnull);
contentTreeItem = GetContentDocShell(treeItemChild);
if (contentTreeItem) {
NS_ADDREF(aStart = contentTreeItem);
return aStart;
}
}
}
return nsnull;
}
// nsIAccessible method // nsIAccessible method
Relation Relation
nsRootAccessible::RelationByType(PRUint32 aType) nsRootAccessible::RelationByType(PRUint32 aType)
@ -634,14 +581,25 @@ nsRootAccessible::RelationByType(PRUint32 aType)
if (!mDocument || aType != nsIAccessibleRelation::RELATION_EMBEDS) if (!mDocument || aType != nsIAccessibleRelation::RELATION_EMBEDS)
return nsDocAccessibleWrap::RelationByType(aType); return nsDocAccessibleWrap::RelationByType(aType);
nsCOMPtr<nsIDocShellTreeItem> treeItem = nsIDOMWindow* rootWindow = mDocument->GetWindow();
nsCoreUtils::GetDocShellTreeItemFor(mDocument); if (rootWindow) {
nsCOMPtr<nsIDocShellTreeItem> contentTreeItem = GetContentDocShell(treeItem); nsCOMPtr<nsIDOMWindow> contentWindow;
// there may be no content area, so we need a null check rootWindow->GetContent(getter_AddRefs(contentWindow));
if (!contentTreeItem) if (contentWindow) {
return Relation(); nsCOMPtr<nsIDOMDocument> contentDOMDocument;
contentWindow->GetDocument(getter_AddRefs(contentDOMDocument));
nsCOMPtr<nsIDocument> contentDocumentNode =
do_QueryInterface(contentDOMDocument);
if (contentDocumentNode) {
nsDocAccessible* contentDocument =
GetAccService()->GetDocAccessible(contentDocumentNode);
if (contentDocument)
return Relation(contentDocument);
}
}
}
return Relation(nsAccUtils::GetDocAccessibleFor(contentTreeItem)); return Relation();
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -127,8 +127,7 @@ protected:
PRUint32 GetChromeFlags(); PRUint32 GetChromeFlags();
#endif #endif
already_AddRefed<nsIDocShellTreeItem>
GetContentDocShell(nsIDocShellTreeItem *aStart);
nsRefPtr<nsCaretAccessible> mCaretAccessible; nsRefPtr<nsCaretAccessible> mCaretAccessible;
}; };

Просмотреть файл

@ -48,6 +48,7 @@ include $(topsrcdir)/config/rules.mk
# test_tabbrowser.xul disabled for misusing <tabbrowser> (bug 715857) # test_tabbrowser.xul disabled for misusing <tabbrowser> (bug 715857)
_TEST_FILES =\ _TEST_FILES =\
test_embeds.xul \
test_general.html \ test_general.html \
test_general.xul \ test_general.xul \
test_tree.xul \ test_tree.xul \

Просмотреть файл

@ -0,0 +1,152 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="Embeds relation tests">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript"
src="../states.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript"
src="../relations.js"></script>
<script type="application/javascript">
<![CDATA[
////////////////////////////////////////////////////////////////////////////
// Helpers
function tabBrowser()
{
return gBrowserWnd.gBrowser;
}
function currentBrowser()
{
return tabBrowser().selectedBrowser;
}
function currentTabDocument()
{
return currentBrowser().contentDocument;
}
////////////////////////////////////////////////////////////////////////////
// Invokers
function loadURI(aURI)
{
this.invoke = function loadURI_invoke()
{
tabBrowser().loadURI(aURI);
}
this.eventSeq = [
new invokerChecker(EVENT_REORDER, currentBrowser)
];
this.finalCheck = function loadURI_finalCheck()
{
testRelation(gBrowserWnd.document, RELATION_EMBEDS,
getAccessible(currentTabDocument()));
}
this.getID = function loadURI_getID()
{
return "load uri " + aURI;
}
}
function loadOneTab(aURI)
{
this.invoke = function loadOneTab_invoke()
{
tabBrowser().loadOneTab(aURI, null, null, null, false);
}
this.eventSeq = [
new invokerChecker(EVENT_REORDER, currentBrowser)
];
this.finalCheck = function loadURI_finalCheck()
{
testRelation(gBrowserWnd.document, RELATION_EMBEDS,
getAccessible(currentTabDocument()));
}
this.getID = function loadOneTab_getID()
{
return "load uri '" + aURI + "' in new tab";
}
}
////////////////////////////////////////////////////////////////////////////
// Testing
var gBrowserWnd = null;
function loadBrowser()
{
gBrowserWnd = window.openDialog("chrome://browser/content/", "_blank",
"chrome,all,dialog=no", "about:");
addA11yLoadEvent(startTests, gBrowserWnd);
}
function startTests()
{
// Wait for tab load.
var browser = currentBrowser();
addA11yLoadEvent(doTests, browser.contentWindow);
}
//gA11yEventDumpToConsole = true; // debug
var gQueue = null;
function doTests()
{
testRelation(gBrowserWnd.document, RELATION_EMBEDS,
getAccessible(currentTabDocument()));
gQueue = new eventQueue();
gQueue.push(new loadURI("about:about"));
gQueue.push(new loadOneTab("about:mozilla"));
gQueue.onFinish = function()
{
gBrowserWnd.close();
}
gQueue.invoke();
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(loadBrowser);
]]>
</script>
<vbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=707654"
title="Embeds relation on root accessible can return not content document">
Mozilla Bug 707654
</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
</vbox>
</window>

Просмотреть файл

@ -126,19 +126,6 @@
testRelation("legend", RELATION_LABEL_FOR, "fieldset"); testRelation("legend", RELATION_LABEL_FOR, "fieldset");
testRelation("fieldset", RELATION_LABELLED_BY, "legend"); testRelation("fieldset", RELATION_LABELLED_BY, "legend");
// 'embeds' relation for root accessible
var docAcc = null;
var parentOfDocAcc = null;
var parentDocAcc = getAccessible(document);
do {
docAcc = parentDocAcc;
parentOfDocAcc = getAccessible(docAcc.parent, [nsIAccessNode]);
parentDocAcc = getAccessible(parentOfDocAcc.document,
[nsIAccessible]);
} while (getRole(parentDocAcc) != ROLE_CHROME_WINDOW)
testRelation(parentDocAcc, RELATION_EMBEDS, docAcc);
// finish test // finish test
SimpleTest.finish(); SimpleTest.finish();
} }

Просмотреть файл

@ -103,19 +103,6 @@
// 'default button' relation // 'default button' relation
testRelation("textbox", RELATION_DEFAULT_BUTTON, "submit"); testRelation("textbox", RELATION_DEFAULT_BUTTON, "submit");
// 'embeds' relation for root accessible
var docAcc = null;
var parentOfDocAcc = null;
var parentDocAcc = getAccessible(document);
do {
docAcc = parentDocAcc;
parentOfDocAcc = getAccessible(docAcc.parent, [nsIAccessNode]);
parentDocAcc = getAccessible(parentOfDocAcc.document,
[nsIAccessible]);
} while (getRole(parentDocAcc) != ROLE_CHROME_WINDOW)
testRelation(parentDocAcc, RELATION_EMBEDS, docAcc);
// 'labelled by'/'label for' relation for xul:goupbox and xul:label of // 'labelled by'/'label for' relation for xul:goupbox and xul:label of
// xul:caption // xul:caption
var groupboxAcc = getAccessible("groupbox"); var groupboxAcc = getAccessible("groupbox");

Просмотреть файл

@ -107,11 +107,6 @@ ifdef _MSC_VER
WIN32_EXE_LDFLAGS += -ENTRY:wmainCRTStartup WIN32_EXE_LDFLAGS += -ENTRY:wmainCRTStartup
endif endif
ifeq ($(OS_ARCH),WINNT)
OS_LIBS += $(call EXPAND_LIBNAME,comctl32 comdlg32 uuid shell32 ole32 oleaut32 version winspool)
OS_LIBS += $(call EXPAND_LIBNAME,usp10 msimg32)
endif
ifeq ($(OS_ARCH),WINNT) ifeq ($(OS_ARCH),WINNT)
RCINCLUDE = splash.rc RCINCLUDE = splash.rc
ifndef GNU_CC ifndef GNU_CC

Просмотреть файл

@ -18,3 +18,6 @@ export MOZ_TELEMETRY_REPORTING=1
# Treat warnings as errors in directories with FAIL_ON_WARNINGS. # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors ac_add_options --enable-warnings-as-errors
# Enable parallel compiling
mk_add_options MOZ_MAKE_FLAGS="-j4"

Просмотреть файл

@ -18,3 +18,6 @@ export MOZ_TELEMETRY_REPORTING=1
# Treat warnings as errors in directories with FAIL_ON_WARNINGS. # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors ac_add_options --enable-warnings-as-errors
# Enable parallel compiling
mk_add_options MOZ_MAKE_FLAGS="-j4"

Просмотреть файл

@ -14,3 +14,6 @@ export MOZ_TELEMETRY_REPORTING=1
# Treat warnings as errors in directories with FAIL_ON_WARNINGS. # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors ac_add_options --enable-warnings-as-errors
# Enable parallel compiling
mk_add_options MOZ_MAKE_FLAGS="-j4"

Просмотреть файл

@ -22,6 +22,22 @@ diff -ru a/csu/Makefile b/csu/Makefile
*) ;; \ *) ;; \
esac; \ esac; \
files="$(all-Banner-files)"; \ files="$(all-Banner-files)"; \
diff -ru a/Makerules b/Makerules
--- a/Makerules 2011-01-17 23:34:07.000000000 -0500
+++ b/Makerules 2012-01-30 08:47:56.565068903 -0500
@@ -992,9 +992,9 @@
echo ' Use the shared library, but some functions are only in';\
echo ' the static library, so try that secondarily. */';\
cat $<; \
- echo 'GROUP ( $(slibdir)/libc.so$(libc.so-version)' \
- '$(libdir)/$(patsubst %,$(libtype.oS),$(libprefix)$(libc-name))'\
- ' AS_NEEDED (' $(slibdir)/$(rtld-installed-name) ') )' \
+ echo 'GROUP ( libc.so$(libc.so-version)' \
+ '$(patsubst %,$(libtype.oS),$(libprefix)$(libc-name))'\
+ ' AS_NEEDED (' $(rtld-installed-name) ') )' \
) > $@.new
mv -f $@.new $@
diff -ru a/nscd/nscd_stat.c b/nscd/nscd_stat.c diff -ru a/nscd/nscd_stat.c b/nscd/nscd_stat.c
--- a/nscd/nscd_stat.c 2011-01-17 23:34:07.000000000 -0500 --- a/nscd/nscd_stat.c 2011-01-17 23:34:07.000000000 -0500
+++ b/nscd/nscd_stat.c 2012-01-23 15:54:45.231607606 -0500 +++ b/nscd/nscd_stat.c 2012-01-23 15:54:45.231607606 -0500

Просмотреть файл

@ -96,11 +96,6 @@ ifdef _MSC_VER
WIN32_EXE_LDFLAGS += -ENTRY:wmainCRTStartup WIN32_EXE_LDFLAGS += -ENTRY:wmainCRTStartup
endif endif
ifeq ($(OS_ARCH),WINNT)
OS_LIBS += $(call EXPAND_LIBNAME,comctl32 comdlg32 uuid shell32 ole32 oleaut32 version winspool)
OS_LIBS += $(call EXPAND_LIBNAME,usp10 msimg32)
endif
include $(topsrcdir)/config/rules.mk include $(topsrcdir)/config/rules.mk
ifeq ($(OS_ARCH),WINNT) ifeq ($(OS_ARCH),WINNT)

Просмотреть файл

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html style="width: 1px">
<head>
<script>
function boom()
{
document.documentElement.offsetHeight;
var x = document.getElementById("x").firstChild;
x.data = "a" + x.data;
}
</script>
</head>
<body onload="boom();"><span id="x">
&#x202a;&#x10871;</span></body>
</html>

Просмотреть файл

@ -347,3 +347,4 @@ load 691118-1.html
load 695861.html load 695861.html
load 698335.html load 698335.html
load 707098.html load 707098.html
load 722137.html

Просмотреть файл

@ -819,12 +819,10 @@ nsBidiPresUtils::ResolveParagraph(nsBlockFrame* aBlockFrame,
RemoveBidiContinuation(aBpd, frame, RemoveBidiContinuation(aBpd, frame,
frameIndex, newIndex, lineOffset); frameIndex, newIndex, lineOffset);
} }
} else if (runLength == fragmentLength && } else if (runLength == fragmentLength) {
frame->GetNextSibling()) {
/* /*
* If the directional run ends at the end of the frame, and this is * If the directional run ends at the end of the frame, make sure
* not the containing frame's last child, make sure that the next * that any continuation is non-fluid
* frame is a non-fluid continuation
*/ */
nsIFrame* next = frame->GetNextInFlow(); nsIFrame* next = frame->GetNextInFlow();
if (next) { if (next) {

Просмотреть файл

@ -206,8 +206,16 @@ public class GeckoInputConnection
extract.selectionEnd = b; extract.selectionEnd = b;
extract.startOffset = 0; extract.startOffset = 0;
extract.text = content.toString();
try {
extract.text = content.toString();
} catch (IndexOutOfBoundsException iob) {
Log.d(LOGTAG,
"IndexOutOfBoundsException thrown from getExtractedText(). start: " +
Selection.getSelectionStart(content) +
" end: " + Selection.getSelectionEnd(content));
return null;
}
return extract; return extract;
} }

Просмотреть файл

@ -61,6 +61,10 @@ public class FloatSize {
@Override @Override
public String toString() { return "(" + width + "," + height + ")"; } public String toString() { return "(" + width + "," + height + ")"; }
public boolean isPositive() {
return (width > 0 && height > 0);
}
public boolean fuzzyEquals(FloatSize size) { public boolean fuzzyEquals(FloatSize size) {
return (FloatUtils.fuzzyEquals(size.width, width) && return (FloatUtils.fuzzyEquals(size.width, width) &&
FloatUtils.fuzzyEquals(size.height, height)); FloatUtils.fuzzyEquals(size.height, height));

Просмотреть файл

@ -429,8 +429,14 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
DisplayMetrics metrics = new DisplayMetrics(); DisplayMetrics metrics = new DisplayMetrics();
GeckoApp.mAppContext.getWindowManager().getDefaultDisplay().getMetrics(metrics); GeckoApp.mAppContext.getWindowManager().getDefaultDisplay().getMetrics(metrics);
if (!force && metrics.widthPixels == mScreenSize.width && // Return immediately if the screen size hasn't changed or the viewport
metrics.heightPixels == mScreenSize.height) { // size is zero (which indicates that the rendering surface hasn't been
// allocated yet).
boolean screenSizeChanged = (metrics.widthPixels != mScreenSize.width ||
metrics.heightPixels != mScreenSize.height);
boolean viewportSizeValid = (getLayerController() != null &&
getLayerController().getViewportSize().isPositive());
if (!(force || (screenSizeChanged && viewportSizeValid))) {
return; return;
} }

Просмотреть файл

@ -71,6 +71,11 @@ public class MultiTileLayer extends Layer {
private final LinkedList<SubTile> mTiles; private final LinkedList<SubTile> mTiles;
private final HashMap<Long, SubTile> mPositionHash; private final HashMap<Long, SubTile> mPositionHash;
// Copies of the last set origin/resolution, to decide when to invalidate
// the buffer
private Point mOrigin;
private float mResolution;
public MultiTileLayer(CairoImage image, IntSize tileSize) { public MultiTileLayer(CairoImage image, IntSize tileSize) {
super(); super();
@ -102,7 +107,7 @@ public class MultiTileLayer extends Layer {
* Invalidates the backing buffer. Data will not be uploaded from an invalid * Invalidates the backing buffer. Data will not be uploaded from an invalid
* backing buffer. This method is only valid inside a transaction. * backing buffer. This method is only valid inside a transaction.
*/ */
public void invalidateBuffer() { protected void invalidateBuffer() {
if (!inTransaction()) { if (!inTransaction()) {
throw new RuntimeException("invalidateBuffer() is only valid inside a transaction"); throw new RuntimeException("invalidateBuffer() is only valid inside a transaction");
} }
@ -181,17 +186,16 @@ public class MultiTileLayer extends Layer {
// entire width, regardless of the dirty-rect's width, and so // entire width, regardless of the dirty-rect's width, and so
// can override existing data. // can override existing data.
Point origin = getOffsetOrigin(); Point origin = getOffsetOrigin();
Rect validRect = tile.getValidTextureArea(); Region validRegion = new Region(tile.getValidTextureArea());
validRect.offset(tileOrigin.x - origin.x, tileOrigin.y - origin.y); validRegion.translate(tileOrigin.x - origin.x, tileOrigin.y - origin.y);
Region validRegion = new Region(validRect);
validRegion.op(mValidRegion, Region.Op.INTERSECT); validRegion.op(mValidRegion, Region.Op.INTERSECT);
// SingleTileLayer can't draw complex regions, so in that case, // SingleTileLayer can't draw complex regions, so in that case,
// just invalidate the entire area. // just invalidate the entire area.
tile.invalidateTexture(); tile.invalidateTexture();
if (!validRegion.isComplex()) { if (!validRegion.isEmpty() && !validRegion.isComplex()) {
validRect.set(validRegion.getBounds()); validRegion.translate(origin.x - tileOrigin.x, origin.y - tileOrigin.y);
validRect.offset(origin.x - tileOrigin.x, origin.y - tileOrigin.y); tile.getValidTextureArea().set(validRegion.getBounds());
} }
} else { } else {
// Update tile metrics // Update tile metrics
@ -286,7 +290,6 @@ public class MultiTileLayer extends Layer {
// valid by monitoring reflows on the browser element, or // valid by monitoring reflows on the browser element, or
// something along these lines. // something along these lines.
LinkedList<SubTile> invalidTiles = new LinkedList<SubTile>(); LinkedList<SubTile> invalidTiles = new LinkedList<SubTile>();
Rect bounds = mValidRegion.getBounds();
for (ListIterator<SubTile> i = mTiles.listIterator(); i.hasNext();) { for (ListIterator<SubTile> i = mTiles.listIterator(); i.hasNext();) {
SubTile tile = i.next(); SubTile tile = i.next();
@ -301,7 +304,7 @@ public class MultiTileLayer extends Layer {
// First bracketed clause: Invalidate off-screen, off-buffer tiles // First bracketed clause: Invalidate off-screen, off-buffer tiles
// Second: Invalidate visible tiles at the wrong resolution that have updates // Second: Invalidate visible tiles at the wrong resolution that have updates
if ((!Rect.intersects(bounds, tilespaceTileBounds) && if ((!opRegion.op(tilespaceTileBounds, mValidRegion, Region.Op.INTERSECT) &&
!Rect.intersects(tilespaceViewport, tilespaceTileBounds)) || !Rect.intersects(tilespaceViewport, tilespaceTileBounds)) ||
(!FloatUtils.fuzzyEquals(tile.getResolution(), getResolution()) && (!FloatUtils.fuzzyEquals(tile.getResolution(), getResolution()) &&
opRegion.op(tilespaceTileBounds, updateRegion, Region.Op.INTERSECT))) { opRegion.op(tilespaceTileBounds, updateRegion, Region.Op.INTERSECT))) {
@ -415,9 +418,8 @@ public class MultiTileLayer extends Layer {
@Override @Override
public void setOrigin(Point origin) { public void setOrigin(Point origin) {
Point oldOrigin = getOrigin(); if (mOrigin == null || !origin.equals(mOrigin)) {
mOrigin = origin;
if (!origin.equals(oldOrigin)) {
super.setOrigin(origin); super.setOrigin(origin);
invalidateBuffer(); invalidateBuffer();
} }
@ -425,9 +427,8 @@ public class MultiTileLayer extends Layer {
@Override @Override
public void setResolution(float resolution) { public void setResolution(float resolution) {
float oldResolution = getResolution(); if (!FloatUtils.fuzzyEquals(resolution, mResolution)) {
mResolution = resolution;
if (!FloatUtils.fuzzyEquals(resolution, oldResolution)) {
super.setResolution(resolution); super.setResolution(resolution);
invalidateBuffer(); invalidateBuffer();
} }
@ -441,7 +442,7 @@ public class MultiTileLayer extends Layer {
* Invalidates all sub-tiles. This should be called if the source backing * Invalidates all sub-tiles. This should be called if the source backing
* this layer has changed. This method is only valid inside a transaction. * this layer has changed. This method is only valid inside a transaction.
*/ */
public void invalidateTiles() { protected void invalidateTiles() {
if (!inTransaction()) { if (!inTransaction()) {
throw new RuntimeException("invalidateTiles() is only valid inside a transaction"); throw new RuntimeException("invalidateTiles() is only valid inside a transaction");
} }

Просмотреть файл

@ -2733,7 +2733,9 @@ pref("font.name.monospace.he", "Droid Sans Mono");
pref("font.name.serif.ja", "Droid Serif"); pref("font.name.serif.ja", "Droid Serif");
pref("font.name.sans-serif.ja", "Droid Sans Japanese"); pref("font.name.sans-serif.ja", "Droid Sans Japanese");
pref("font.name.monospace.ja", "Droid Sans Mono"); pref("font.name.monospace.ja", "MotoyaLMaru");
pref("font.name-list.sans-serif.ja", "MotoyaLMaru, MotoyaLCedar, Droid Sans Japanese");
pref("font.name-list.monospace.ja", "MotoyaLMaru, MotoyaLCedar");
pref("font.name.serif.ko", "Droid Serif"); pref("font.name.serif.ko", "Droid Serif");
pref("font.name.sans-serif.ko", "Droid Sans"); pref("font.name.sans-serif.ko", "Droid Sans");
@ -2750,38 +2752,44 @@ pref("font.name.monospace.tr", "Droid Sans Mono");
pref("font.name.serif.x-baltic", "Droid Serif"); pref("font.name.serif.x-baltic", "Droid Serif");
pref("font.name.sans-serif.x-baltic", "Droid Sans"); pref("font.name.sans-serif.x-baltic", "Droid Sans");
pref("font.name.monospace.x-baltic", "Droid Sans Mono"); pref("font.name.monospace.x-baltic", "Droid Sans Mono");
pref("font.name-list.sans-serif.x-baltic", "Roboto, Droid Sans");
pref("font.name.serif.x-central-euro", "Droid Serif"); pref("font.name.serif.x-central-euro", "Droid Serif");
pref("font.name.sans-serif.x-central-euro", "Droid Sans"); pref("font.name.sans-serif.x-central-euro", "Droid Sans");
pref("font.name.monospace.x-central-euro", "Droid Sans Mono"); pref("font.name.monospace.x-central-euro", "Droid Sans Mono");
pref("font.name-list.sans-serif.x-central-euro", "Roboto, Droid Sans");
pref("font.name.serif.x-cyrillic", "Droid Serif"); pref("font.name.serif.x-cyrillic", "Droid Serif");
pref("font.name.sans-serif.x-cyrillic", "Droid Sans"); pref("font.name.sans-serif.x-cyrillic", "Droid Sans");
pref("font.name.monospace.x-cyrillic", "Droid Sans Mono"); pref("font.name.monospace.x-cyrillic", "Droid Sans Mono");
pref("font.name-list.sans-serif.x-cyrillic", "Roboto, Droid Sans");
pref("font.name.serif.x-unicode", "Droid Serif"); pref("font.name.serif.x-unicode", "Droid Serif");
pref("font.name.sans-serif.x-unicode", "Droid Sans"); pref("font.name.sans-serif.x-unicode", "Droid Sans");
pref("font.name.monospace.x-unicode", "Droid Sans Mono"); pref("font.name.monospace.x-unicode", "Droid Sans Mono");
pref("font.name-list.sans-serif.x-unicode", "Roboto, Droid Sans");
pref("font.name.serif.x-user-def", "Droid Serif"); pref("font.name.serif.x-user-def", "Droid Serif");
pref("font.name.sans-serif.x-user-def", "Droid Sans"); pref("font.name.sans-serif.x-user-def", "Droid Sans");
pref("font.name.monospace.x-user-def", "Droid Sans Mono"); pref("font.name.monospace.x-user-def", "Droid Sans Mono");
pref("font.name-list.sans-serif.x-user-def", "Roboto, Droid Sans");
pref("font.name.serif.x-western", "Droid Serif"); pref("font.name.serif.x-western", "Droid Serif");
pref("font.name.sans-serif.x-western", "Droid Sans"); pref("font.name.sans-serif.x-western", "Droid Sans");
pref("font.name.monospace.x-western", "Droid Sans Mono"); pref("font.name.monospace.x-western", "Droid Sans Mono");
pref("font.name-list.sans-serif.x-western", "Roboto, Droid Sans");
pref("font.name.serif.zh-CN", "Droid Serif"); pref("font.name.serif.zh-CN", "Droid Serif");
pref("font.name.sans-serif.zh-CN", "Droid Sans"); pref("font.name.sans-serif.zh-CN", "Droid Sans");
pref("font.name.monospace.zh-CN", "Droid Sans Mono"); pref("font.name.monospace.zh-CN", "Droid Sans Mono");
// ming_uni.ttf (HKSCS-2001)
// http://www.info.gov.hk/digital21/eng/hkscs/download/uime.exe
pref("font.name.serif.zh-HK", "Droid Serif"); pref("font.name.serif.zh-HK", "Droid Serif");
pref("font.name.sans-serif.zh-HK", "Droid Sans"); pref("font.name.sans-serif.zh-HK", "Droid Sans");
pref("font.name.monospace.zh-HK", "Droid Sans Mono"); pref("font.name.monospace.zh-HK", "Droid Sans Mono");
// zh-TW pref("font.name.serif.zh-TW", "Droid Serif");
pref("font.name.sans-serif.zh-TW", "Droid Sans");
pref("font.name.monospace.zh-TW", "Droid Sans Mono");
pref("font.default.ar", "sans-serif"); pref("font.default.ar", "sans-serif");
pref("font.size.variable.ar", 16); pref("font.size.variable.ar", 16);

Просмотреть файл

@ -154,6 +154,8 @@ nsNSSSocketInfo::nsNSSSocketInfo()
: mMutex("nsNSSSocketInfo::nsNSSSocketInfo"), : mMutex("nsNSSSocketInfo::nsNSSSocketInfo"),
mFd(nsnull), mFd(nsnull),
mCertVerificationState(before_cert_verification), mCertVerificationState(before_cert_verification),
mCertVerificationStarted(0),
mCertVerificationEnded(0),
mSecurityState(nsIWebProgressListener::STATE_IS_INSECURE), mSecurityState(nsIWebProgressListener::STATE_IS_INSECURE),
mSubRequestsHighSecurity(0), mSubRequestsHighSecurity(0),
mSubRequestsLowSecurity(0), mSubRequestsLowSecurity(0),
@ -960,6 +962,7 @@ nsNSSSocketInfo::SetCertVerificationWaiting()
NS_ASSERTION(mCertVerificationState != waiting_for_cert_verification, NS_ASSERTION(mCertVerificationState != waiting_for_cert_verification,
"Invalid state transition to waiting_for_cert_verification"); "Invalid state transition to waiting_for_cert_verification");
mCertVerificationState = waiting_for_cert_verification; mCertVerificationState = waiting_for_cert_verification;
mCertVerificationStarted = PR_IntervalNow();
} }
void void
@ -969,6 +972,8 @@ nsNSSSocketInfo::SetCertVerificationResult(PRErrorCode errorCode,
NS_ASSERTION(mCertVerificationState == waiting_for_cert_verification, NS_ASSERTION(mCertVerificationState == waiting_for_cert_verification,
"Invalid state transition to cert_verification_finished"); "Invalid state transition to cert_verification_finished");
mCertVerificationEnded = PR_IntervalNow();
if (errorCode != 0) { if (errorCode != 0) {
SetCanceled(errorCode, errorMessageType); SetCanceled(errorCode, errorMessageType);
} else if (mFd) { } else if (mFd) {
@ -1025,11 +1030,36 @@ void nsNSSSocketInfo::SetAllowTLSIntoleranceTimeout(bool aAllow)
bool nsNSSSocketInfo::HandshakeTimeout() bool nsNSSSocketInfo::HandshakeTimeout()
{ {
if (mCertVerificationState == waiting_for_cert_verification) {
// Do not do a TLS interlerance timeout during cert verification because:
//
// * If we would have timed out, but cert verification is still ongoing,
// then the handshake probably already completed, and it is probably the
// certificate validation (OCSP responder or similar) that is timing
// out.
// * If certificate validation AND the handshake is slow, then that is a
// good indication that the network is bad, and so the problem probably
// isn't the server being TLS intolerant.
// * When we timeout, we return non-zero flags from PR_Poll, which will
// cause the application to try to read from and/or write to the socket,
// possibly in a loop. But, it is likely that the socket is blocked on
// cert authentication, so those read and/or write calls would result in
// PR_WOULD_BLOCK_ERROR, causing the application to spin.
return false;
}
if (!mHandshakeInProgress || !mAllowTLSIntoleranceTimeout) if (!mHandshakeInProgress || !mAllowTLSIntoleranceTimeout)
return false; return false;
return ((PRIntervalTime)(PR_IntervalNow() - mHandshakeStartTime) PRIntervalTime now = PR_IntervalNow();
> PR_SecondsToInterval(HANDSHAKE_TIMEOUT_SECONDS)); PRIntervalTime certVerificationTime =
mCertVerificationEnded - mCertVerificationStarted;
PRIntervalTime totalTime = now - mHandshakeStartTime;
PRIntervalTime totalTimeExceptCertVerificationTime =
totalTime - certVerificationTime;
return totalTimeExceptCertVerificationTime >
PR_SecondsToInterval(HANDSHAKE_TIMEOUT_SECONDS);
} }
void nsSSLIOLayerHelpers::Cleanup() void nsSSLIOLayerHelpers::Cleanup()
@ -2082,6 +2112,7 @@ nsSSLIOLayerPoll(PRFileDesc * fd, PRInt16 in_flags, PRInt16 *out_flags)
: "[%p] poll SSL socket using lower %d\n", : "[%p] poll SSL socket using lower %d\n",
fd, (int) in_flags)); fd, (int) in_flags));
// See comments in HandshakeTimeout before moving and/or changing this block
if (socketInfo->HandshakeTimeout()) { if (socketInfo->HandshakeTimeout()) {
NS_ASSERTION(in_flags & PR_POLL_EXCEPT, NS_ASSERTION(in_flags & PR_POLL_EXCEPT,
"caller did not poll for EXCEPT (handshake timeout)"); "caller did not poll for EXCEPT (handshake timeout)");

Просмотреть файл

@ -184,6 +184,8 @@ protected:
nsCOMPtr<nsIInterfaceRequestor> mCallbacks; nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
PRFileDesc* mFd; PRFileDesc* mFd;
CertVerificationState mCertVerificationState; CertVerificationState mCertVerificationState;
PRIntervalTime mCertVerificationStarted;
PRIntervalTime mCertVerificationEnded;
PRUint32 mSecurityState; PRUint32 mSecurityState;
PRInt32 mSubRequestsHighSecurity; PRInt32 mSubRequestsHighSecurity;
PRInt32 mSubRequestsLowSecurity; PRInt32 mSubRequestsLowSecurity;

Просмотреть файл

@ -1955,7 +1955,21 @@ ssl_Poll(PRFileDesc *fd, PRInt16 how_flags, PRInt16 *p_out_flags)
} else if ((ss->lastWriteBlocked) && (how_flags & PR_POLL_READ) && } else if ((ss->lastWriteBlocked) && (how_flags & PR_POLL_READ) &&
(ss->pendingBuf.len != 0)) { /* write data waiting to be sent */ (ss->pendingBuf.len != 0)) { /* write data waiting to be sent */
new_flags |= PR_POLL_WRITE; /* also select on write. */ new_flags |= PR_POLL_WRITE; /* also select on write. */
} }
if (ss->version >= SSL_LIBRARY_VERSION_3_0 &&
ss->ssl3.hs.restartTarget != NULL) {
/* Read and write will block until the asynchronous callback completes
* (e.g. until SSL_AuthCertificateComplete is called), so don't tell
* the caller to poll the socket unless there is pending write data.
*/
if (ss->lastWriteBlocked && ss->pendingBuf.len != 0) {
new_flags &= (PR_POLL_WRITE | PR_POLL_EXCEPT);
} else {
new_flags = 0;
}
}
if (new_flags && (fd->lower->methods->poll != NULL)) { if (new_flags && (fd->lower->methods->poll != NULL)) {
PRInt16 lower_out_flags = 0; PRInt16 lower_out_flags = 0;
PRInt16 lower_new_flags; PRInt16 lower_new_flags;

Просмотреть файл

@ -4,5 +4,6 @@ on top of the NSS release.
bug-542832-ssl-restart-4.patch and bug-542832-ssl-restart-tstclnt-4.patch were bug-542832-ssl-restart-4.patch and bug-542832-ssl-restart-tstclnt-4.patch were
added so that we could test the new PSM SSL threading code (bug 674147) and added so that we could test the new PSM SSL threading code (bug 674147) and
SPDY (bug 528288). bug-717906-lowhash was added to fix an issue with recent SPDY (bug 528288). bug-717906-lowhash was added to fix an issue with recent
Mozilla builds on fedora. These patches will be removed when the NSS 3.13.2 Mozilla builds on fedora. bug-710176-ssl-restart-7-poll-v5.patch were added
to fix a bug 710176. These patches will be removed when the NSS 3.13.2
release that includes them is imported into mozilla-central. release that includes them is imported into mozilla-central.

Просмотреть файл

@ -0,0 +1,40 @@
# HG changeset patch
# Parent 4560e2c22b83f85f9238b9094de7a190042676df
# User Brian Smith <bsmith@mozilla.com>
diff --git a/security/nss/lib/ssl/sslsock.c b/security/nss/lib/ssl/sslsock.c
--- a/security/nss/lib/ssl/sslsock.c
+++ b/security/nss/lib/ssl/sslsock.c
@@ -1950,17 +1950,31 @@ ssl_Poll(PRFileDesc *fd, PRInt16 how_fla
}
}
} else if ((new_flags & PR_POLL_READ) && (SSL_DataPending(fd) > 0)) {
*p_out_flags = PR_POLL_READ; /* it's ready already. */
return new_flags;
} else if ((ss->lastWriteBlocked) && (how_flags & PR_POLL_READ) &&
(ss->pendingBuf.len != 0)) { /* write data waiting to be sent */
new_flags |= PR_POLL_WRITE; /* also select on write. */
- }
+ }
+
+ if (ss->version >= SSL_LIBRARY_VERSION_3_0 &&
+ ss->ssl3.hs.restartTarget != NULL) {
+ /* Read and write will block until the asynchronous callback completes
+ * (e.g. until SSL_AuthCertificateComplete is called), so don't tell
+ * the caller to poll the socket unless there is pending write data.
+ */
+ if (ss->lastWriteBlocked && ss->pendingBuf.len != 0) {
+ new_flags &= (PR_POLL_WRITE | PR_POLL_EXCEPT);
+ } else {
+ new_flags = 0;
+ }
+ }
+
if (new_flags && (fd->lower->methods->poll != NULL)) {
PRInt16 lower_out_flags = 0;
PRInt16 lower_new_flags;
lower_new_flags = fd->lower->methods->poll(fd->lower, new_flags,
&lower_out_flags);
if ((lower_new_flags & lower_out_flags) && (how_flags != new_flags)) {
PRInt16 out_flags = lower_out_flags & ~PR_POLL_RW;
if (lower_out_flags & PR_POLL_READ)

Просмотреть файл

@ -38,7 +38,6 @@
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
#include "base/histogram.h" #include "base/histogram.h"
#include "base/pickle.h"
#include "nsIComponentManager.h" #include "nsIComponentManager.h"
#include "nsIServiceManager.h" #include "nsIServiceManager.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
@ -48,8 +47,6 @@
#include "jsapi.h" #include "jsapi.h"
#include "nsStringGlue.h" #include "nsStringGlue.h"
#include "nsITelemetry.h" #include "nsITelemetry.h"
#include "nsIFile.h"
#include "nsILocalFile.h"
#include "Telemetry.h" #include "Telemetry.h"
#include "nsTHashtable.h" #include "nsTHashtable.h"
#include "nsHashKeys.h" #include "nsHashKeys.h"
@ -57,7 +54,6 @@
#include "nsXULAppAPI.h" #include "nsXULAppAPI.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "mozilla/Mutex.h" #include "mozilla/Mutex.h"
#include "mozilla/FileUtils.h"
namespace { namespace {
@ -231,9 +227,11 @@ enum reflectStatus {
}; };
enum reflectStatus enum reflectStatus
ReflectHistogramAndSamples(JSContext *cx, JSObject *obj, Histogram *h, ReflectHistogramSnapshot(JSContext *cx, JSObject *obj, Histogram *h)
const Histogram::SampleSet &ss)
{ {
Histogram::SampleSet ss;
h->SnapshotSample(&ss);
// We don't want to reflect corrupt histograms. // We don't want to reflect corrupt histograms.
if (h->FindCorruption(ss) != Histogram::NO_INCONSISTENCIES) { if (h->FindCorruption(ss) != Histogram::NO_INCONSISTENCIES) {
return REFLECT_CORRUPT; return REFLECT_CORRUPT;
@ -262,14 +260,6 @@ ReflectHistogramAndSamples(JSContext *cx, JSObject *obj, Histogram *h,
return REFLECT_OK; return REFLECT_OK;
} }
enum reflectStatus
ReflectHistogramSnapshot(JSContext *cx, JSObject *obj, Histogram *h)
{
Histogram::SampleSet ss;
h->SnapshotSample(&ss);
return ReflectHistogramAndSamples(cx, obj, h, ss);
}
JSBool JSBool
JSHistogram_Add(JSContext *cx, uintN argc, jsval *vp) JSHistogram_Add(JSContext *cx, uintN argc, jsval *vp)
{ {
@ -687,333 +677,6 @@ TelemetryImpl::GetHistogramById(const nsACString &name, JSContext *cx, jsval *re
return WrapAndReturnHistogram(h, cx, ret); return WrapAndReturnHistogram(h, cx, ret);
} }
class TelemetrySessionData : public nsITelemetrySessionData
{
NS_DECL_ISUPPORTS
NS_DECL_NSITELEMETRYSESSIONDATA
public:
static nsresult LoadFromDisk(nsIFile *, TelemetrySessionData **ptr);
static nsresult SaveToDisk(nsIFile *, const nsACString &uuid);
TelemetrySessionData(const char *uuid);
~TelemetrySessionData();
private:
struct EnumeratorArgs {
JSContext *cx;
JSObject *snapshots;
};
typedef nsBaseHashtableET<nsUint32HashKey, Histogram::SampleSet> EntryType;
typedef nsTHashtable<EntryType> SessionMapType;
static PLDHashOperator ReflectSamples(EntryType *entry, void *arg);
SessionMapType mSampleSetMap;
nsCString mUUID;
bool DeserializeHistogramData(Pickle &pickle, void **iter);
static bool SerializeHistogramData(Pickle &pickle);
// The file format version. Should be incremented whenever we change
// how individual SampleSets are stored in the file.
static const unsigned int sVersion = 1;
};
NS_IMPL_THREADSAFE_ISUPPORTS1(TelemetrySessionData, nsITelemetrySessionData)
TelemetrySessionData::TelemetrySessionData(const char *uuid)
: mUUID(uuid)
{
mSampleSetMap.Init();
}
TelemetrySessionData::~TelemetrySessionData()
{
mSampleSetMap.Clear();
}
NS_IMETHODIMP
TelemetrySessionData::GetUuid(nsACString &uuid)
{
uuid = mUUID;
return NS_OK;
}
PLDHashOperator
TelemetrySessionData::ReflectSamples(EntryType *entry, void *arg)
{
struct EnumeratorArgs *args = static_cast<struct EnumeratorArgs *>(arg);
// This has the undesirable effect of creating a histogram for the
// current session with the given ID. But there's no good way to
// compute the ranges and buckets from scratch.
Histogram *h = nsnull;
nsresult rv = GetHistogramByEnumId(Telemetry::ID(entry->GetKey()), &h);
if (NS_FAILED(rv)) {
return PL_DHASH_STOP;
}
// Don't reflect histograms with no data associated with them.
if (entry->mData.sum() == 0) {
return PL_DHASH_NEXT;
}
JSObject *snapshot = JS_NewObject(args->cx, NULL, NULL, NULL);
if (!(snapshot
&& ReflectHistogramAndSamples(args->cx, snapshot, h, entry->mData)
&& JS_DefineProperty(args->cx, args->snapshots,
h->histogram_name().c_str(),
OBJECT_TO_JSVAL(snapshot), NULL, NULL,
JSPROP_ENUMERATE))) {
return PL_DHASH_STOP;
}
return PL_DHASH_NEXT;
}
NS_IMETHODIMP
TelemetrySessionData::GetSnapshots(JSContext *cx, jsval *ret)
{
JSObject *snapshots = JS_NewObject(cx, NULL, NULL, NULL);
if (!snapshots) {
return NS_ERROR_FAILURE;
}
struct EnumeratorArgs args = { cx, snapshots };
PRUint32 count = mSampleSetMap.EnumerateEntries(ReflectSamples,
static_cast<void*>(&args));
if (count != mSampleSetMap.Count()) {
return NS_ERROR_FAILURE;
}
*ret = OBJECT_TO_JSVAL(snapshots);
return NS_OK;
}
bool
TelemetrySessionData::DeserializeHistogramData(Pickle &pickle, void **iter)
{
PRUint32 count = 0;
if (!pickle.ReadUInt32(iter, &count)) {
return false;
}
for (size_t i = 0; i < count; ++i) {
int stored_length;
const char *name;
if (!pickle.ReadData(iter, &name, &stored_length)) {
return false;
}
Telemetry::ID id;
nsresult rv = TelemetryImpl::GetHistogramEnumId(name, &id);
if (NS_FAILED(rv)) {
// We serialized a non-static histogram. Just drop its data on
// the floor. If we can't deserialize the data, though, we're in
// trouble.
Histogram::SampleSet ss;
if (!ss.Deserialize(iter, pickle)) {
return false;
}
}
EntryType *entry = mSampleSetMap.GetEntry(id);
if (!entry) {
entry = mSampleSetMap.PutEntry(id);
if (NS_UNLIKELY(!entry)) {
return false;
}
if (!entry->mData.Deserialize(iter, pickle)) {
return false;
}
}
}
return true;
}
nsresult
TelemetrySessionData::LoadFromDisk(nsIFile *file, TelemetrySessionData **ptr)
{
*ptr = nsnull;
nsresult rv;
nsCOMPtr<nsILocalFile> f(do_QueryInterface(file, &rv));
if (NS_FAILED(rv)) {
return rv;
}
AutoFDClose fd;
rv = f->OpenNSPRFileDesc(PR_RDONLY, 0, &fd);
if (NS_FAILED(rv)) {
return NS_ERROR_FAILURE;
}
PRInt32 size = PR_Available(fd);
if (size == -1) {
return NS_ERROR_FAILURE;
}
nsAutoArrayPtr<char> data(new char[size]);
PRInt32 amount = PR_Read(fd, data, size);
if (amount != size) {
return NS_ERROR_FAILURE;
}
Pickle pickle(data, size);
void *iter = NULL;
unsigned int storedVersion;
if (!(pickle.ReadUInt32(&iter, &storedVersion)
&& storedVersion == sVersion)) {
return NS_ERROR_FAILURE;
}
const char *uuid;
int uuidLength;
if (!pickle.ReadData(&iter, &uuid, &uuidLength)) {
return NS_ERROR_FAILURE;
}
nsAutoPtr<TelemetrySessionData> sessionData(new TelemetrySessionData(uuid));
if (!sessionData->DeserializeHistogramData(pickle, &iter)) {
return NS_ERROR_FAILURE;
}
*ptr = sessionData.forget();
return NS_OK;
}
bool
TelemetrySessionData::SerializeHistogramData(Pickle &pickle)
{
StatisticsRecorder::Histograms hs;
StatisticsRecorder::GetHistograms(&hs);
if (!pickle.WriteUInt32(hs.size())) {
return false;
}
for (StatisticsRecorder::Histograms::const_iterator it = hs.begin();
it != hs.end();
++it) {
const Histogram *h = *it;
const char *name = h->histogram_name().c_str();
Histogram::SampleSet ss;
h->SnapshotSample(&ss);
if (!(pickle.WriteData(name, strlen(name)+1)
&& ss.Serialize(&pickle))) {
return false;
}
}
return true;
}
nsresult
TelemetrySessionData::SaveToDisk(nsIFile *file, const nsACString &uuid)
{
nsresult rv;
nsCOMPtr<nsILocalFile> f(do_QueryInterface(file, &rv));
if (NS_FAILED(rv)) {
return rv;
}
AutoFDClose fd;
rv = f->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0600, &fd);
if (NS_FAILED(rv)) {
return rv;
}
Pickle pickle;
if (!pickle.WriteUInt32(sVersion)) {
return NS_ERROR_FAILURE;
}
// Include the trailing NULL for the UUID to make reading easier.
const char *data;
size_t length = uuid.GetData(&data);
if (!(pickle.WriteData(data, length+1)
&& SerializeHistogramData(pickle))) {
return NS_ERROR_FAILURE;
}
PRInt32 amount = PR_Write(fd, static_cast<const char*>(pickle.data()),
pickle.size());
if (amount != pickle.size()) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
class SaveHistogramEvent : public nsRunnable
{
public:
SaveHistogramEvent(nsIFile *file, const nsACString &uuid,
nsITelemetrySaveSessionDataCallback *callback)
: mFile(file), mUUID(uuid), mCallback(callback)
{}
NS_IMETHOD Run()
{
nsresult rv = TelemetrySessionData::SaveToDisk(mFile, mUUID);
mCallback->Handle(!!NS_SUCCEEDED(rv));
return rv;
}
private:
nsCOMPtr<nsIFile> mFile;
nsCString mUUID;
nsCOMPtr<nsITelemetrySaveSessionDataCallback> mCallback;
};
NS_IMETHODIMP
TelemetryImpl::SaveHistograms(nsIFile *file, const nsACString &uuid,
nsITelemetrySaveSessionDataCallback *callback,
bool isSynchronous)
{
nsCOMPtr<nsIRunnable> event = new SaveHistogramEvent(file, uuid, callback);
if (isSynchronous) {
return event ? event->Run() : NS_ERROR_FAILURE;
} else {
return NS_DispatchToCurrentThread(event);
}
}
class LoadHistogramEvent : public nsRunnable
{
public:
LoadHistogramEvent(nsIFile *file,
nsITelemetryLoadSessionDataCallback *callback)
: mFile(file), mCallback(callback)
{}
NS_IMETHOD Run()
{
TelemetrySessionData *sessionData = nsnull;
nsresult rv = TelemetrySessionData::LoadFromDisk(mFile, &sessionData);
if (NS_FAILED(rv)) {
mCallback->Handle(nsnull);
} else {
nsCOMPtr<nsITelemetrySessionData> data(sessionData);
mCallback->Handle(data);
}
return rv;
}
private:
nsCOMPtr<nsIFile> mFile;
nsCOMPtr<nsITelemetryLoadSessionDataCallback> mCallback;
};
NS_IMETHODIMP
TelemetryImpl::LoadHistograms(nsIFile *file,
nsITelemetryLoadSessionDataCallback *callback)
{
nsCOMPtr<nsIRunnable> event = new LoadHistogramEvent(file, callback);
return NS_DispatchToCurrentThread(event);
}
NS_IMETHODIMP NS_IMETHODIMP
TelemetryImpl::GetCanRecord(bool *ret) { TelemetryImpl::GetCanRecord(bool *ret) {
*ret = mCanRecord; *ret = mCanRecord;

Просмотреть файл

@ -42,7 +42,6 @@ const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/LightweightThemeManager.jsm"); Cu.import("resource://gre/modules/LightweightThemeManager.jsm");
Cu.import("resource://gre/modules/ctypes.jsm");
// When modifying the payload in incompatible ways, please bump this version number // When modifying the payload in incompatible ways, please bump this version number
const PAYLOAD_VERSION = 1; const PAYLOAD_VERSION = 1;
@ -180,10 +179,6 @@ TelemetryPing.prototype = {
_histograms: {}, _histograms: {},
_initialized: false, _initialized: false,
_prevValues: {}, _prevValues: {},
// Generate a unique id once per session so the server can cope with
// duplicate submissions.
_uuid: generateUUID(),
_prevSession: null,
/** /**
* Returns a set of histograms that can be converted into JSON * Returns a set of histograms that can be converted into JSON
@ -192,7 +187,8 @@ TelemetryPing.prototype = {
* histogram_type: <0 for exponential, 1 for linear>, bucketX:countX, ....} ...} * histogram_type: <0 for exponential, 1 for linear>, bucketX:countX, ....} ...}
* where bucket[XY], count[XY] are positive integers. * where bucket[XY], count[XY] are positive integers.
*/ */
getHistograms: function getHistograms(hls) { getHistograms: function getHistograms() {
let hls = Telemetry.histogramSnapshots;
let info = Telemetry.registeredHistograms; let info = Telemetry.registeredHistograms;
let ret = {}; let ret = {};
@ -401,48 +397,24 @@ TelemetryPing.prototype = {
send: function send(reason, server) { send: function send(reason, server) {
// populate histograms one last time // populate histograms one last time
this.gatherMemory(); this.gatherMemory();
let data = this.getSessionPayloadAndSlug(reason);
// Don't record a successful ping for previous session data.
this.doPing(server, data.slug, data.payload, !data.previous);
this._prevSession = null;
// We were sending off data from before; now send the actual data
// we've collected this session.
if (data.previous) {
data = this.getSessionPayloadAndSlug(reason);
this.doPing(server, data.slug, data.payload, true);
}
},
getSessionPayloadAndSlug: function getSessionPayloadAndSlug(reason) {
// Use a deterministic url for testing.
let isTestPing = (reason == "test-ping");
let havePreviousSession = !!this._prevSession;
let slug = (isTestPing
? reason
: (havePreviousSession
? this._prevSession.uuid
: this._uuid));
let payloadObj = { let payloadObj = {
ver: PAYLOAD_VERSION, ver: PAYLOAD_VERSION,
// Send a different reason string for previous session data. info: this.getMetadata(reason),
info: this.getMetadata(havePreviousSession ? "saved-session" : reason), simpleMeasurements: getSimpleMeasurements(),
histograms: this.getHistograms(),
slowSQL: Telemetry.slowSQL
}; };
if (havePreviousSession) {
payloadObj.histograms = this.getHistograms(this._prevSession.snapshots);
}
else {
payloadObj.simpleMeasurements = getSimpleMeasurements();
payloadObj.histograms = this.getHistograms(Telemetry.histogramSnapshots);
payloadObj.slowSQL = Telemetry.slowSQL;
}
return { previous: !!havePreviousSession, slug: slug, payload: JSON.stringify(payloadObj) };
},
doPing: function doPing(server, slug, payload, recordSuccess) { let isTestPing = (reason == "test-ping");
let submitPath = "/submit/telemetry/" + slug; // Generate a unique id once per session so the server can cope with duplicate submissions.
let url = server + submitPath; // Use a deterministic url for testing.
if (!this._path)
this._path = "/submit/telemetry/" + (isTestPing ? reason : generateUUID());
let hping = Telemetry.getHistogramById("TELEMETRY_PING");
let hsuccess = Telemetry.getHistogramById("TELEMETRY_SUCCESS");
let url = server + this._path;
let request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"] let request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Ci.nsIXMLHttpRequest); .createInstance(Ci.nsIXMLHttpRequest);
request.mozBackgroundRequest = true; request.mozBackgroundRequest = true;
@ -451,7 +423,6 @@ TelemetryPing.prototype = {
request.setRequestHeader("Content-Type", "application/json"); request.setRequestHeader("Content-Type", "application/json");
let startTime = new Date(); let startTime = new Date();
let file = this.savedHistogramsFile();
function finishRequest(channel) { function finishRequest(channel) {
let success = false; let success = false;
@ -459,23 +430,15 @@ TelemetryPing.prototype = {
success = channel.QueryInterface(Ci.nsIHttpChannel).requestSucceeded; success = channel.QueryInterface(Ci.nsIHttpChannel).requestSucceeded;
} catch(e) { } catch(e) {
} }
if (recordSuccess) { hsuccess.add(success);
let hping = Telemetry.getHistogramById("TELEMETRY_PING"); hping.add(new Date() - startTime);
let hsuccess = Telemetry.getHistogramById("TELEMETRY_SUCCESS"); if (isTestPing)
hsuccess.add(success);
hping.add(new Date() - startTime);
}
if (success && file.exists()) {
file.remove(true);
}
if (slug == "test-ping")
Services.obs.notifyObservers(null, "telemetry-test-xhr-complete", null); Services.obs.notifyObservers(null, "telemetry-test-xhr-complete", null);
} }
request.addEventListener("error", function(aEvent) finishRequest(request.channel), false); request.addEventListener("error", function(aEvent) finishRequest(request.channel), false);
request.addEventListener("load", function(aEvent) finishRequest(request.channel), false); request.addEventListener("load", function(aEvent) finishRequest(request.channel), false);
request.send(payload); request.send(JSON.stringify(payloadObj));
}, },
attachObservers: function attachObservers() { attachObservers: function attachObservers() {
@ -496,25 +459,6 @@ TelemetryPing.prototype = {
} }
}, },
savedHistogramsFile: function savedHistogramsFile() {
let profileDirectory = Services.dirsvc.get("ProfD", Ci.nsILocalFile);
let profileFile = profileDirectory.clone();
// There's a bunch of binary data in the file, so we need to be
// sensitive to multiple machine types. Use ctypes to get some
// discriminating information.
let size = ctypes.voidptr_t.size;
// Hack to figure out endianness.
let uint32_array_t = ctypes.uint32_t.array(1);
let array = uint32_array_t([0xdeadbeef]);
let uint8_array_t = ctypes.uint8_t.array(4);
let array_as_bytes = ctypes.cast(array, uint8_array_t);
let endian = (array_as_bytes[0] === 0xde) ? "big" : "little"
let name = "sessionHistograms.dat." + size + endian;
profileFile.append(name);
return profileFile;
},
/** /**
* Initializes telemetry within a timer. If there is no PREF_SERVER set, don't turn on telemetry. * Initializes telemetry within a timer. If there is no PREF_SERVER set, don't turn on telemetry.
*/ */
@ -535,7 +479,6 @@ TelemetryPing.prototype = {
Services.obs.addObserver(this, "private-browsing", false); Services.obs.addObserver(this, "private-browsing", false);
Services.obs.addObserver(this, "profile-before-change", false); Services.obs.addObserver(this, "profile-before-change", false);
Services.obs.addObserver(this, "sessionstore-windows-restored", false); Services.obs.addObserver(this, "sessionstore-windows-restored", false);
Services.obs.addObserver(this, "quit-application-granted", false);
// Delay full telemetry initialization to give the browser time to // Delay full telemetry initialization to give the browser time to
// run various late initializers. Otherwise our gathered memory // run various late initializers. Otherwise our gathered memory
@ -549,12 +492,6 @@ TelemetryPing.prototype = {
delete self._timer delete self._timer
} }
this._timer.initWithCallback(timerCallback, TELEMETRY_DELAY, Ci.nsITimer.TYPE_ONE_SHOT); this._timer.initWithCallback(timerCallback, TELEMETRY_DELAY, Ci.nsITimer.TYPE_ONE_SHOT);
// Load data from the previous session.
let loadCallback = function(data) {
self._prevSession = data;
}
Telemetry.loadHistograms(this.savedHistogramsFile(), loadCallback);
}, },
/** /**
@ -565,7 +502,6 @@ TelemetryPing.prototype = {
Services.obs.removeObserver(this, "sessionstore-windows-restored"); Services.obs.removeObserver(this, "sessionstore-windows-restored");
Services.obs.removeObserver(this, "profile-before-change"); Services.obs.removeObserver(this, "profile-before-change");
Services.obs.removeObserver(this, "private-browsing"); Services.obs.removeObserver(this, "private-browsing");
Services.obs.removeObserver(this, "quit-application-granted");
}, },
/** /**
@ -631,11 +567,6 @@ TelemetryPing.prototype = {
} }
this.send(aTopic == "idle" ? "idle-daily" : aTopic, server); this.send(aTopic == "idle" ? "idle-daily" : aTopic, server);
break; break;
case "quit-application-granted":
Telemetry.saveHistograms(this.savedHistogramsFile(),
this._uuid, function (success) success,
/*isSynchronous=*/true);
break;
} }
}, },

Просмотреть файл

@ -38,39 +38,8 @@
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl" #include "nsISupports.idl"
#include "nsIFile.idl"
[scriptable, uuid(c177b6b0-5ef1-44f5-bc67-6bcf7d2518e5)] [scriptable, uuid(db854295-478d-4de9-8211-d73ed7d81cd0)]
interface nsITelemetrySessionData : nsISupports
{
/**
* The UUID of our previous session.
*/
readonly attribute ACString uuid;
/**
* An object containing a snapshot from all registered histograms that had
* data recorded in the previous session.
* { name1: data1, name2: data2, .... }
* where the individual dataN are as nsITelemetry.histogramSnapshots.
*/
[implicit_jscontext]
readonly attribute jsval snapshots;
};
[scriptable, function, uuid(aff36c9d-7e4c-41ab-a9b6-53773bbca0cd)]
interface nsITelemetryLoadSessionDataCallback : nsISupports
{
void handle(in nsITelemetrySessionData data);
};
[scriptable, function, uuid(40065f26-afd2-4417-93de-c1de9adb1548)]
interface nsITelemetrySaveSessionDataCallback : nsISupports
{
void handle(in bool success);
};
[scriptable, uuid(22fc825e-288f-457e-80d5-5bb35f06d37e)]
interface nsITelemetry : nsISupports interface nsITelemetry : nsISupports
{ {
/** /**
@ -158,34 +127,6 @@ interface nsITelemetry : nsISupports
[implicit_jscontext] [implicit_jscontext]
jsval getHistogramById(in ACString id); jsval getHistogramById(in ACString id);
/**
* Save persistent histograms to the given file.
*
* @param file - filename for saving
* @param uuid - UUID of this session
* @param callback - function to be caled when file writing is complete
* @param isSynchronous - whether the save is done synchronously. Defaults
* to asynchronous saving.
*/
void saveHistograms(in nsIFile file, in ACString uuid,
in nsITelemetrySaveSessionDataCallback callback,
[optional] in boolean isSynchronous);
/* Reconstruct an nsITelemetryDataSession object containing histogram
* information from the given file; the file must have been produced
* via saveHistograms. The file is read asynchronously.
*
* This method does not modify the histogram information being
* collected in the current session.
*
* The reconstructed object is then passed to the given callback.
*
* @param file - the file to load histogram information from
* @param callback - function to process histogram information
*/
void loadHistograms(in nsIFile file,
in nsITelemetryLoadSessionDataCallback callback);
/** /**
* Set this to false to disable gathering of telemetry statistics. * Set this to false to disable gathering of telemetry statistics.
*/ */

Просмотреть файл

@ -105,45 +105,6 @@ function test_privateMode() {
do_check_neq(uneval(orig), uneval(h.snapshot())); do_check_neq(uneval(orig), uneval(h.snapshot()));
} }
function generateUUID() {
let str = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator).generateUUID().toString();
// strip {}
return str.substring(1, str.length - 1);
}
// Check that we do sane things when saving to disk.
function test_loadSave()
{
let dirService = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIProperties);
let tmpDir = dirService.get("TmpD", Ci.nsILocalFile);
let tmpFile = tmpDir.clone();
tmpFile.append("saved-histograms.dat");
if (tmpFile.exists()) {
tmpFile.remove(true);
}
let saveFinished = false;
let loadFinished = false;
let uuid = generateUUID();
let loadCallback = function(data) {
do_check_true(data != null);
do_check_eq(uuid, data.uuid);
loadFinished = true;
do_test_finished();
};
let saveCallback = function(success) {
do_check_true(success);
Telemetry.loadHistograms(tmpFile, loadCallback);
saveFinished = true;
};
do_test_pending();
Telemetry.saveHistograms(tmpFile, uuid, saveCallback);
do_register_cleanup(function () do_check_true(saveFinished));
do_register_cleanup(function () do_check_true(loadFinished));
do_register_cleanup(function () tmpFile.exists() && tmpFile.remove(true));
}
function run_test() function run_test()
{ {
let kinds = [Telemetry.HISTOGRAM_EXPONENTIAL, Telemetry.HISTOGRAM_LINEAR] let kinds = [Telemetry.HISTOGRAM_EXPONENTIAL, Telemetry.HISTOGRAM_LINEAR]
@ -160,6 +121,4 @@ function run_test()
test_getHistogramById(); test_getHistogramById();
test_getSlowSQL(); test_getSlowSQL();
test_privateMode(); test_privateMode();
test_loadSave();
} }

Просмотреть файл

@ -1062,17 +1062,14 @@ NS_METHOD nsCocoaWindow::PlaceBehind(nsTopLevelWidgetZPlacement aPlacement,
return NS_OK; return NS_OK;
} }
// Note bug 278777, we need to update state when the window is unminimized
// from the dock by users.
NS_METHOD nsCocoaWindow::SetSizeMode(PRInt32 aMode) NS_METHOD nsCocoaWindow::SetSizeMode(PRInt32 aMode)
{ {
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
PRInt32 previousMode; // mSizeMode will be updated in DispatchSizeModeEvent, which will be called
nsBaseWidget::GetSizeMode(&previousMode); // from a delegate method that handles the state change during one of the
// calls below.
nsresult rv = nsBaseWidget::SetSizeMode(aMode); nsSizeMode previousMode = mSizeMode;
NS_ENSURE_SUCCESS(rv, rv);
if (aMode == nsSizeMode_Normal) { if (aMode == nsSizeMode_Normal) {
if ([mWindow isMiniaturized]) if ([mWindow isMiniaturized])
@ -1419,8 +1416,13 @@ nsCocoaWindow::ReportMoveEvent()
void void
nsCocoaWindow::DispatchSizeModeEvent() nsCocoaWindow::DispatchSizeModeEvent()
{ {
nsSizeMode newMode = GetWindowSizeMode(mWindow);
if (mSizeMode == newMode)
return;
mSizeMode = newMode;
nsSizeModeEvent event(true, NS_SIZEMODE, this); nsSizeModeEvent event(true, NS_SIZEMODE, this);
event.mSizeMode = GetWindowSizeMode(mWindow); event.mSizeMode = mSizeMode;
event.time = PR_IntervalNow(); event.time = PR_IntervalNow();
nsEventStatus status = nsEventStatus_eIgnore; nsEventStatus status = nsEventStatus_eIgnore;

Просмотреть файл

@ -87,6 +87,8 @@ _CHROME_FILES = test_bug343416.xul \
window_composition_text_querycontent.xul \ window_composition_text_querycontent.xul \
test_input_events_on_deactive_window.xul \ test_input_events_on_deactive_window.xul \
test_position_on_resize.xul \ test_position_on_resize.xul \
empty_window.xul \
test_sizemode_events.xul \
$(NULL) $(NULL)
# test_bug413277.html mac-only based on 604789, 605178 # test_bug413277.html mac-only based on 604789, 605178
@ -109,7 +111,6 @@ _CHROME_FILES += native_menus_window.xul \
bug586713_window.xul \ bug586713_window.xul \
test_key_event_counts.xul \ test_key_event_counts.xul \
test_bug596600.xul \ test_bug596600.xul \
window_bug596600.xul \
test_bug673301.xul \ test_bug673301.xul \
$(NULL) $(NULL)
endif endif

Просмотреть файл

@ -1,4 +1,4 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?> <?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<window title="Window for Test for Mozilla Bug 596600" <window title="Empty window"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"/> xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"/>

Просмотреть файл

@ -36,9 +36,9 @@ function moveMouseTo(x, y, andThen) {
} }
function openWindows() { function openWindows() {
gLeftWindow = open('window_bug596600.xul', '_blank', 'chrome,screenX=50,screenY=50,width=200,height=200'); gLeftWindow = open('empty_window.xul', '_blank', 'chrome,screenX=50,screenY=50,width=200,height=200');
SimpleTest.waitForFocus(function () { SimpleTest.waitForFocus(function () {
gRightWindow = open('window_bug596600.xul', '', 'chrome,screenX=300,screenY=50,width=200,height=200'); gRightWindow = open('empty_window.xul', '', 'chrome,screenX=300,screenY=50,width=200,height=200');
SimpleTest.waitForFocus(attachIFrameToRightWindow, gRightWindow); SimpleTest.waitForFocus(attachIFrameToRightWindow, gRightWindow);
}, gLeftWindow); }, gLeftWindow);
} }

Просмотреть файл

@ -0,0 +1,107 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<window title="Test for bug 715867"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<title>Test for bug 715867</title>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<script class="testbody" type="application/javascript">
<![CDATA[
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
gWindow = null;
gSizeModeDidChange = false;
gSizeModeDidChangeTo = 0;
function sizemodeChanged(e) {
gSizeModeDidChange = true;
gSizeModeDidChangeTo = gWindow.windowState;
}
function expectSizeModeChange(newMode, duringActionCallback) {
gSizeModeDidChange = false;
duringActionCallback();
if (newMode == 0) {
// No change should have taken place, no event should have fired.
ok(!gSizeModeDidChange, "No sizemodechange event should have fired.");
} else {
// Size mode change event was expected to fire.
ok(gSizeModeDidChange, "A sizemodechanged event should have fired.");
is(gSizeModeDidChangeTo, newMode, "The new sizemode should have the expected value.");
}
}
function startTest() {
if (navigator.platform.indexOf("Lin") != -1) {
ok(true, "This test is disabled on Linux because it expects window sizemode changes to be synchronous (which is not the case on Linux).");
SimpleTest.finish();
return;
};
openWindow();
}
function openWindow() {
gWindow = open('empty_window.xul', '_blank', 'chrome,screenX=50,screenY=50,width=200,height=200,resizable');
SimpleTest.waitForFocus(runTest, gWindow);
}
function runTest() {
// Install event handler.
gWindow.addEventListener("sizemodechange", sizemodeChanged, false);
// Run tests.
expectSizeModeChange(gWindow.STATE_MINIMIZED, function () {
gWindow.minimize();
});
expectSizeModeChange(gWindow.STATE_NORMAL, function () {
gWindow.restore();
});
expectSizeModeChange(gWindow.STATE_MAXIMIZED, function () {
gWindow.maximize();
});
expectSizeModeChange(gWindow.STATE_NORMAL, function () {
gWindow.restore();
});
// Normal window resizing shouldn't fire a sizemodechanged event, bug 715867.
expectSizeModeChange(0, function () {
gWindow.resizeTo(gWindow.outerWidth + 10, gWindow.outerHeight);
});
expectSizeModeChange(0, function () {
gWindow.resizeTo(gWindow.outerWidth, gWindow.outerHeight + 10);
});
gWindow.removeEventListener("sizemodechange", sizemodeChanged, false);
gWindow.close();
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(startTest);
]]>
</script>
</window>

Просмотреть файл

@ -145,21 +145,38 @@ static PRInt64 GetResident()
static void XMappingIter(PRInt64& Vsize, PRInt64& Resident) static void XMappingIter(PRInt64& Vsize, PRInt64& Resident)
{ {
Vsize = -1;
Resident = -1;
int mapfd = open("/proc/self/xmap", O_RDONLY); int mapfd = open("/proc/self/xmap", O_RDONLY);
struct stat st; struct stat st;
prxmap_t *prmapp; prxmap_t *prmapp = NULL;
if (mapfd >= 0) { if (mapfd >= 0) {
if (!fstat(mapfd, &st)) { if (!fstat(mapfd, &st)) {
int nmap = st.st_size / sizeof(prxmap_t); int nmap = st.st_size / sizeof(prxmap_t);
prmapp = (prxmap_t*)malloc((nmap + 1) * sizeof(prxmap_t)); while (1) {
int n = read(mapfd, prmapp, (nmap + 1) * sizeof(prxmap_t)); // stat(2) on /proc/<pid>/xmap returns an incorrect value,
if (n > 0) { // prior to the release of Solaris 11.
Vsize = 0; // Here is a workaround for it.
Resident = 0; nmap *= 2;
for (int i = 0; i < n / sizeof(prxmap_t); i++) { prmapp = (prxmap_t*)malloc((nmap + 1) * sizeof(prxmap_t));
Vsize += prmapp[i].pr_size; if (!prmapp) {
Resident += prmapp[i].pr_rss * prmapp[i].pr_pagesize; // out of memory
break;
} }
int n = pread(mapfd, prmapp, (nmap + 1) * sizeof(prxmap_t), 0);
if (n < 0) {
break;
}
if (nmap >= n / sizeof (prxmap_t)) {
Vsize = 0;
Resident = 0;
for (int i = 0; i < n / sizeof (prxmap_t); i++) {
Vsize += prmapp[i].pr_size;
Resident += prmapp[i].pr_rss * prmapp[i].pr_pagesize;
}
break;
}
free(prmapp);
} }
free(prmapp); free(prmapp);
} }
@ -169,16 +186,14 @@ static void XMappingIter(PRInt64& Vsize, PRInt64& Resident)
static PRInt64 GetVsize() static PRInt64 GetVsize()
{ {
PRInt64 Vsize = -1; PRInt64 Vsize, Resident;
PRInt64 Resident = -1;
XMappingIter(Vsize, Resident); XMappingIter(Vsize, Resident);
return Vsize; return Vsize;
} }
static PRInt64 GetResident() static PRInt64 GetResident()
{ {
PRInt64 Vsize = -1; PRInt64 Vsize, Resident;
PRInt64 Resident = -1;
XMappingIter(Vsize, Resident); XMappingIter(Vsize, Resident);
return Resident; return Resident;
} }