зеркало из https://github.com/mozilla/pjs.git
Merge m-c to kiwifox
This commit is contained in:
Коммит
75e154812c
|
@ -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">
|
||||||
|
‪𐡱</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;
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче