From 8d23dc10ad50bbf7fc7ffb58df8e5d264413982a Mon Sep 17 00:00:00 2001 From: Ginn Chen Date: Tue, 31 Jan 2012 14:32:10 +0800 Subject: [PATCH 01/19] Bug 717861 GetVsize and GetResident underestimate memory size on Solaris r=justin.lebar --- xpcom/base/nsMemoryReporterManager.cpp | 41 ++++++++++++++++++-------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/xpcom/base/nsMemoryReporterManager.cpp b/xpcom/base/nsMemoryReporterManager.cpp index 06b93f893e5cd..26a09604ac346 100644 --- a/xpcom/base/nsMemoryReporterManager.cpp +++ b/xpcom/base/nsMemoryReporterManager.cpp @@ -145,21 +145,38 @@ static PRInt64 GetResident() static void XMappingIter(PRInt64& Vsize, PRInt64& Resident) { + Vsize = -1; + Resident = -1; int mapfd = open("/proc/self/xmap", O_RDONLY); struct stat st; - prxmap_t *prmapp; + prxmap_t *prmapp = NULL; if (mapfd >= 0) { if (!fstat(mapfd, &st)) { int nmap = st.st_size / sizeof(prxmap_t); - prmapp = (prxmap_t*)malloc((nmap + 1) * sizeof(prxmap_t)); - int n = read(mapfd, prmapp, (nmap + 1) * sizeof(prxmap_t)); - if (n > 0) { - 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; + while (1) { + // stat(2) on /proc//xmap returns an incorrect value, + // prior to the release of Solaris 11. + // Here is a workaround for it. + nmap *= 2; + prmapp = (prxmap_t*)malloc((nmap + 1) * sizeof(prxmap_t)); + if (!prmapp) { + // 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); } @@ -169,16 +186,14 @@ static void XMappingIter(PRInt64& Vsize, PRInt64& Resident) static PRInt64 GetVsize() { - PRInt64 Vsize = -1; - PRInt64 Resident = -1; + PRInt64 Vsize, Resident; XMappingIter(Vsize, Resident); return Vsize; } static PRInt64 GetResident() { - PRInt64 Vsize = -1; - PRInt64 Resident = -1; + PRInt64 Vsize, Resident; XMappingIter(Vsize, Resident); return Resident; } From 2c3b5d49c6d8d2ee3b8fc76c88a32bef2c011f95 Mon Sep 17 00:00:00 2001 From: Alexander Surkov Date: Tue, 31 Jan 2012 15:40:06 +0900 Subject: [PATCH 02/19] Bug 707654 - embeds relation on root accessible can return not content document, r=davidb --- accessible/src/base/nsRootAccessible.cpp | 78 +++------ accessible/src/base/nsRootAccessible.h | 3 +- .../tests/mochitest/relations/Makefile.in | 1 + .../tests/mochitest/relations/test_embeds.xul | 152 ++++++++++++++++++ .../mochitest/relations/test_general.html | 13 -- .../mochitest/relations/test_general.xul | 13 -- 6 files changed, 172 insertions(+), 88 deletions(-) create mode 100644 accessible/tests/mochitest/relations/test_embeds.xul diff --git a/accessible/src/base/nsRootAccessible.cpp b/accessible/src/base/nsRootAccessible.cpp index a0511f38a1d14..355effda1b5e2 100644 --- a/accessible/src/base/nsRootAccessible.cpp +++ b/accessible/src/base/nsRootAccessible.cpp @@ -574,59 +574,6 @@ nsRootAccessible::Shutdown() nsDocAccessibleWrap::Shutdown(); } -// nsRootAccessible protected member -already_AddRefed -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 treeNode(do_QueryInterface(aStart)); - if (treeNode) { - PRInt32 subDocuments; - treeNode->GetChildCount(&subDocuments); - for (PRInt32 count = 0; count < subDocuments; count ++) { - nsCOMPtr 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 Relation nsRootAccessible::RelationByType(PRUint32 aType) @@ -634,14 +581,25 @@ nsRootAccessible::RelationByType(PRUint32 aType) if (!mDocument || aType != nsIAccessibleRelation::RELATION_EMBEDS) return nsDocAccessibleWrap::RelationByType(aType); - nsCOMPtr treeItem = - nsCoreUtils::GetDocShellTreeItemFor(mDocument); - nsCOMPtr contentTreeItem = GetContentDocShell(treeItem); - // there may be no content area, so we need a null check - if (!contentTreeItem) - return Relation(); + nsIDOMWindow* rootWindow = mDocument->GetWindow(); + if (rootWindow) { + nsCOMPtr contentWindow; + rootWindow->GetContent(getter_AddRefs(contentWindow)); + if (contentWindow) { + nsCOMPtr contentDOMDocument; + contentWindow->GetDocument(getter_AddRefs(contentDOMDocument)); + nsCOMPtr contentDocumentNode = + do_QueryInterface(contentDOMDocument); + if (contentDocumentNode) { + nsDocAccessible* contentDocument = + GetAccService()->GetDocAccessible(contentDocumentNode); + if (contentDocument) + return Relation(contentDocument); + } + } + } - return Relation(nsAccUtils::GetDocAccessibleFor(contentTreeItem)); + return Relation(); } //////////////////////////////////////////////////////////////////////////////// diff --git a/accessible/src/base/nsRootAccessible.h b/accessible/src/base/nsRootAccessible.h index 6feb79a91005d..b7f02ffddbca6 100644 --- a/accessible/src/base/nsRootAccessible.h +++ b/accessible/src/base/nsRootAccessible.h @@ -127,8 +127,7 @@ class nsRootAccessible : public nsDocAccessibleWrap, PRUint32 GetChromeFlags(); #endif - already_AddRefed - GetContentDocShell(nsIDocShellTreeItem *aStart); + nsRefPtr mCaretAccessible; }; diff --git a/accessible/tests/mochitest/relations/Makefile.in b/accessible/tests/mochitest/relations/Makefile.in index 5a7654412d373..5fc8bf6d87891 100644 --- a/accessible/tests/mochitest/relations/Makefile.in +++ b/accessible/tests/mochitest/relations/Makefile.in @@ -48,6 +48,7 @@ include $(topsrcdir)/config/rules.mk # test_tabbrowser.xul disabled for misusing (bug 715857) _TEST_FILES =\ + test_embeds.xul \ test_general.html \ test_general.xul \ test_tree.xul \ diff --git a/accessible/tests/mochitest/relations/test_embeds.xul b/accessible/tests/mochitest/relations/test_embeds.xul new file mode 100644 index 0000000000000..5d0ddcfa9990a --- /dev/null +++ b/accessible/tests/mochitest/relations/test_embeds.xul @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + Mozilla Bug 707654 + +

+ +
+    
+ +
+
diff --git a/accessible/tests/mochitest/relations/test_general.html b/accessible/tests/mochitest/relations/test_general.html index 71bf6f8600d21..d487f349ade2f 100644 --- a/accessible/tests/mochitest/relations/test_general.html +++ b/accessible/tests/mochitest/relations/test_general.html @@ -126,19 +126,6 @@ testRelation("legend", RELATION_LABEL_FOR, "fieldset"); 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 SimpleTest.finish(); } diff --git a/accessible/tests/mochitest/relations/test_general.xul b/accessible/tests/mochitest/relations/test_general.xul index ca288d1bf6c12..23bf7276b28b9 100644 --- a/accessible/tests/mochitest/relations/test_general.xul +++ b/accessible/tests/mochitest/relations/test_general.xul @@ -103,19 +103,6 @@ // 'default button' relation 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 // xul:caption var groupboxAcc = getAccessible("groupbox"); From 9d93ec9d4ea2573d02de30751a3a9159ad763439 Mon Sep 17 00:00:00 2001 From: Ginn Chen Date: Tue, 31 Jan 2012 14:51:13 +0800 Subject: [PATCH 03/19] Bug 702179 Reland 1d0ec7fa8b96 since Bug 719742 is fixed. --- config/rules.mk | 7 ++++++- configure.in | 2 +- js/src/Makefile.in | 1 - js/src/config/rules.mk | 7 ++++++- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/config/rules.mk b/config/rules.mk index f06a7ba789b6d..f6df5cf9419d0 100644 --- a/config/rules.mk +++ b/config/rules.mk @@ -238,7 +238,12 @@ ifdef CPP_UNIT_TESTS CPPSRCS += $(CPP_UNIT_TESTS) SIMPLE_PROGRAMS += $(CPP_UNIT_TESTS:.cpp=$(BIN_SUFFIX)) INCLUDES += -I$(DIST)/include/testing -LIBS += $(XPCOM_GLUE_LDOPTS) $(NSPR_LIBS) $(MOZ_JS_LIBS) +LIBS += $(XPCOM_GLUE_LDOPTS) $(NSPR_LIBS) +ifdef JS_SHARED_LIBRARY +ifdef MOZ_SHARK +LIBS += $(MOZ_JS_LIBS) +endif +endif # ...and run them the usual way check:: diff --git a/configure.in b/configure.in index 29864c5845aa5..2b43d021b7c17 100644 --- a/configure.in +++ b/configure.in @@ -1301,7 +1301,7 @@ MOZ_BZ2_LIBS='$(call EXPAND_LIBNAME_PATH,bz2,$(DEPTH)/modules/libbz2/src)' MOZ_PNG_CFLAGS= MOZ_PNG_LIBS='$(call EXPAND_LIBNAME_PATH,mozpng,$(DEPTH)/media/libpng)' -MOZ_JS_STATIC_LIBS='$(call EXPAND_LIBNAME_PATH,js_static,$(LIBXUL_DIST)/lib)' +MOZ_JS_STATIC_LIBS='$(call EXPAND_LIBNAME_PATH,js_static,$(DEPTH)/js/src)' MOZ_JS_SHARED_LIBS='$(call EXPAND_LIBNAME_PATH,mozjs,$(LIBXUL_DIST)/lib)' DYNAMIC_XPCOM_LIBS='-L$(LIBXUL_DIST)/bin -lxpcom -lxpcom_core -lmozalloc' MOZ_FIX_LINK_PATHS='-Wl,-rpath-link,$(LIBXUL_DIST)/bin -Wl,-rpath-link,$(prefix)/lib' diff --git a/js/src/Makefile.in b/js/src/Makefile.in index 342695e250962..733fb28a07513 100644 --- a/js/src/Makefile.in +++ b/js/src/Makefile.in @@ -93,7 +93,6 @@ ifdef JS_SHARED_LIBRARY FORCE_SHARED_LIB = 1 endif FORCE_STATIC_LIB = 1 -DIST_INSTALL = 1 VPATH = \ $(srcdir) \ diff --git a/js/src/config/rules.mk b/js/src/config/rules.mk index f06a7ba789b6d..f6df5cf9419d0 100644 --- a/js/src/config/rules.mk +++ b/js/src/config/rules.mk @@ -238,7 +238,12 @@ ifdef CPP_UNIT_TESTS CPPSRCS += $(CPP_UNIT_TESTS) SIMPLE_PROGRAMS += $(CPP_UNIT_TESTS:.cpp=$(BIN_SUFFIX)) INCLUDES += -I$(DIST)/include/testing -LIBS += $(XPCOM_GLUE_LDOPTS) $(NSPR_LIBS) $(MOZ_JS_LIBS) +LIBS += $(XPCOM_GLUE_LDOPTS) $(NSPR_LIBS) +ifdef JS_SHARED_LIBRARY +ifdef MOZ_SHARK +LIBS += $(MOZ_JS_LIBS) +endif +endif # ...and run them the usual way check:: From 219a5420486de2549ec9adca393ef23fb210ae88 Mon Sep 17 00:00:00 2001 From: Makoto Kato Date: Tue, 31 Jan 2012 18:00:25 +0900 Subject: [PATCH 04/19] Backout bug Bug 702179 due to bustage on MacOSX deubg and Win32 debug --- config/rules.mk | 7 +------ configure.in | 2 +- js/src/Makefile.in | 1 + js/src/config/rules.mk | 7 +------ 4 files changed, 4 insertions(+), 13 deletions(-) diff --git a/config/rules.mk b/config/rules.mk index f6df5cf9419d0..f06a7ba789b6d 100644 --- a/config/rules.mk +++ b/config/rules.mk @@ -238,12 +238,7 @@ ifdef CPP_UNIT_TESTS CPPSRCS += $(CPP_UNIT_TESTS) SIMPLE_PROGRAMS += $(CPP_UNIT_TESTS:.cpp=$(BIN_SUFFIX)) INCLUDES += -I$(DIST)/include/testing -LIBS += $(XPCOM_GLUE_LDOPTS) $(NSPR_LIBS) -ifdef JS_SHARED_LIBRARY -ifdef MOZ_SHARK -LIBS += $(MOZ_JS_LIBS) -endif -endif +LIBS += $(XPCOM_GLUE_LDOPTS) $(NSPR_LIBS) $(MOZ_JS_LIBS) # ...and run them the usual way check:: diff --git a/configure.in b/configure.in index 2b43d021b7c17..29864c5845aa5 100644 --- a/configure.in +++ b/configure.in @@ -1301,7 +1301,7 @@ MOZ_BZ2_LIBS='$(call EXPAND_LIBNAME_PATH,bz2,$(DEPTH)/modules/libbz2/src)' MOZ_PNG_CFLAGS= MOZ_PNG_LIBS='$(call EXPAND_LIBNAME_PATH,mozpng,$(DEPTH)/media/libpng)' -MOZ_JS_STATIC_LIBS='$(call EXPAND_LIBNAME_PATH,js_static,$(DEPTH)/js/src)' +MOZ_JS_STATIC_LIBS='$(call EXPAND_LIBNAME_PATH,js_static,$(LIBXUL_DIST)/lib)' MOZ_JS_SHARED_LIBS='$(call EXPAND_LIBNAME_PATH,mozjs,$(LIBXUL_DIST)/lib)' DYNAMIC_XPCOM_LIBS='-L$(LIBXUL_DIST)/bin -lxpcom -lxpcom_core -lmozalloc' MOZ_FIX_LINK_PATHS='-Wl,-rpath-link,$(LIBXUL_DIST)/bin -Wl,-rpath-link,$(prefix)/lib' diff --git a/js/src/Makefile.in b/js/src/Makefile.in index 733fb28a07513..342695e250962 100644 --- a/js/src/Makefile.in +++ b/js/src/Makefile.in @@ -93,6 +93,7 @@ ifdef JS_SHARED_LIBRARY FORCE_SHARED_LIB = 1 endif FORCE_STATIC_LIB = 1 +DIST_INSTALL = 1 VPATH = \ $(srcdir) \ diff --git a/js/src/config/rules.mk b/js/src/config/rules.mk index f6df5cf9419d0..f06a7ba789b6d 100644 --- a/js/src/config/rules.mk +++ b/js/src/config/rules.mk @@ -238,12 +238,7 @@ ifdef CPP_UNIT_TESTS CPPSRCS += $(CPP_UNIT_TESTS) SIMPLE_PROGRAMS += $(CPP_UNIT_TESTS:.cpp=$(BIN_SUFFIX)) INCLUDES += -I$(DIST)/include/testing -LIBS += $(XPCOM_GLUE_LDOPTS) $(NSPR_LIBS) -ifdef JS_SHARED_LIBRARY -ifdef MOZ_SHARK -LIBS += $(MOZ_JS_LIBS) -endif -endif +LIBS += $(XPCOM_GLUE_LDOPTS) $(NSPR_LIBS) $(MOZ_JS_LIBS) # ...and run them the usual way check:: From 246ea1f4ffceaa485df44ac97b822c236dbb9f5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Tue, 31 Jan 2012 10:25:26 +0100 Subject: [PATCH 05/19] Bug 683975 - Need infra for developer contributed compilers. r=rail. make sure the libc.so script doesn't refer to build dir. --- .../build-toolchain/glibc-deterministic.patch | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/build/unix/build-toolchain/glibc-deterministic.patch b/build/unix/build-toolchain/glibc-deterministic.patch index 01f5295e914f2..016fbf1ea7260 100644 --- a/build/unix/build-toolchain/glibc-deterministic.patch +++ b/build/unix/build-toolchain/glibc-deterministic.patch @@ -22,6 +22,22 @@ diff -ru a/csu/Makefile b/csu/Makefile *) ;; \ esac; \ 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 --- 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 From c99e89a1b4abfd18bdf73446a45449d5cdef1c4c Mon Sep 17 00:00:00 2001 From: Chris Lord Date: Tue, 31 Jan 2012 09:36:00 +0000 Subject: [PATCH 06/19] Bug 720613 - Prevent resizing before the surface has been created. r=pcwalton Prevent trying to resize the buffer before the surface has been created. At that point, we wouldn't know our maximum texture size, so we would've thrown a RuntimeException. --- mobile/android/base/gfx/FloatSize.java | 4 ++++ mobile/android/base/gfx/GeckoSoftwareLayerClient.java | 10 ++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/mobile/android/base/gfx/FloatSize.java b/mobile/android/base/gfx/FloatSize.java index 1824b27eddae0..07dfc9fe8452d 100644 --- a/mobile/android/base/gfx/FloatSize.java +++ b/mobile/android/base/gfx/FloatSize.java @@ -61,6 +61,10 @@ public FloatSize(JSONObject json) { @Override public String toString() { return "(" + width + "," + height + ")"; } + public boolean isPositive() { + return (width > 0 && height > 0); + } + public boolean fuzzyEquals(FloatSize size) { return (FloatUtils.fuzzyEquals(size.width, width) && FloatUtils.fuzzyEquals(size.height, height)); diff --git a/mobile/android/base/gfx/GeckoSoftwareLayerClient.java b/mobile/android/base/gfx/GeckoSoftwareLayerClient.java index f5e0ee52b52ee..cec9e83988dd1 100644 --- a/mobile/android/base/gfx/GeckoSoftwareLayerClient.java +++ b/mobile/android/base/gfx/GeckoSoftwareLayerClient.java @@ -429,8 +429,14 @@ private void sendResizeEventIfNecessary(boolean force) { DisplayMetrics metrics = new DisplayMetrics(); GeckoApp.mAppContext.getWindowManager().getDefaultDisplay().getMetrics(metrics); - if (!force && metrics.widthPixels == mScreenSize.width && - metrics.heightPixels == mScreenSize.height) { + // Return immediately if the screen size hasn't changed or the viewport + // 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; } From ea83a1844d80ad617a5186f2859b6da1e4363b9b Mon Sep 17 00:00:00 2001 From: Chris Lord Date: Tue, 31 Jan 2012 09:36:02 +0000 Subject: [PATCH 07/19] Bug 722068 - Fix invalidation during animations in MultiTileLayer. r=pcwalton The buffer in MultiTileLayer is invalidated each time the origin or resolution changes. MultiTileLayer was using the last updated origin/resolution instead of the last set, so if Gecko was animating and locked the layer for long enough, the buffer would be incorrectly invalidated due to the origin/resolution not being updated. --- mobile/android/base/gfx/MultiTileLayer.java | 33 +++++++++++---------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/mobile/android/base/gfx/MultiTileLayer.java b/mobile/android/base/gfx/MultiTileLayer.java index 10fb5f112a711..5d156f9cfad1b 100644 --- a/mobile/android/base/gfx/MultiTileLayer.java +++ b/mobile/android/base/gfx/MultiTileLayer.java @@ -71,6 +71,11 @@ public class MultiTileLayer extends Layer { private final LinkedList mTiles; private final HashMap 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) { super(); @@ -102,7 +107,7 @@ public void invalidate(Rect dirtyRect) { * Invalidates the backing buffer. Data will not be uploaded from an invalid * backing buffer. This method is only valid inside a transaction. */ - public void invalidateBuffer() { + protected void invalidateBuffer() { if (!inTransaction()) { throw new RuntimeException("invalidateBuffer() is only valid inside a transaction"); } @@ -181,17 +186,16 @@ private void updateTile(GL10 gl, RenderContext context, SubTile tile, Point tile // entire width, regardless of the dirty-rect's width, and so // can override existing data. Point origin = getOffsetOrigin(); - Rect validRect = tile.getValidTextureArea(); - validRect.offset(tileOrigin.x - origin.x, tileOrigin.y - origin.y); - Region validRegion = new Region(validRect); + Region validRegion = new Region(tile.getValidTextureArea()); + validRegion.translate(tileOrigin.x - origin.x, tileOrigin.y - origin.y); validRegion.op(mValidRegion, Region.Op.INTERSECT); // SingleTileLayer can't draw complex regions, so in that case, // just invalidate the entire area. tile.invalidateTexture(); - if (!validRegion.isComplex()) { - validRect.set(validRegion.getBounds()); - validRect.offset(origin.x - tileOrigin.x, origin.y - tileOrigin.y); + if (!validRegion.isEmpty() && !validRegion.isComplex()) { + validRegion.translate(origin.x - tileOrigin.x, origin.y - tileOrigin.y); + tile.getValidTextureArea().set(validRegion.getBounds()); } } else { // Update tile metrics @@ -286,7 +290,6 @@ protected boolean performUpdates(GL10 gl, RenderContext context) { // valid by monitoring reflows on the browser element, or // something along these lines. LinkedList invalidTiles = new LinkedList(); - Rect bounds = mValidRegion.getBounds(); for (ListIterator i = mTiles.listIterator(); i.hasNext();) { SubTile tile = i.next(); @@ -301,7 +304,7 @@ protected boolean performUpdates(GL10 gl, RenderContext context) { // First bracketed clause: Invalidate off-screen, off-buffer tiles // 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)) || (!FloatUtils.fuzzyEquals(tile.getResolution(), getResolution()) && opRegion.op(tilespaceTileBounds, updateRegion, Region.Op.INTERSECT))) { @@ -415,9 +418,8 @@ public void draw(RenderContext context) { @Override public void setOrigin(Point origin) { - Point oldOrigin = getOrigin(); - - if (!origin.equals(oldOrigin)) { + if (mOrigin == null || !origin.equals(mOrigin)) { + mOrigin = origin; super.setOrigin(origin); invalidateBuffer(); } @@ -425,9 +427,8 @@ public void setOrigin(Point origin) { @Override public void setResolution(float resolution) { - float oldResolution = getResolution(); - - if (!FloatUtils.fuzzyEquals(resolution, oldResolution)) { + if (!FloatUtils.fuzzyEquals(resolution, mResolution)) { + mResolution = resolution; super.setResolution(resolution); invalidateBuffer(); } @@ -441,7 +442,7 @@ public void setRenderOffset(Point offset) { * Invalidates all sub-tiles. This should be called if the source backing * this layer has changed. This method is only valid inside a transaction. */ - public void invalidateTiles() { + protected void invalidateTiles() { if (!inTransaction()) { throw new RuntimeException("invalidateTiles() is only valid inside a transaction"); } From b6e74fb5ed98ad78f3889e1d572dd7a75eef9b34 Mon Sep 17 00:00:00 2001 From: Simon Montagu Date: Mon, 30 Jan 2012 10:59:34 -0800 Subject: [PATCH 08/19] test for bug 722137, r=roc --- layout/base/crashtests/722137.html | 18 ++++++++++++++++++ layout/base/crashtests/crashtests.list | 1 + 2 files changed, 19 insertions(+) create mode 100644 layout/base/crashtests/722137.html diff --git a/layout/base/crashtests/722137.html b/layout/base/crashtests/722137.html new file mode 100644 index 0000000000000..7dae47f1de75a --- /dev/null +++ b/layout/base/crashtests/722137.html @@ -0,0 +1,18 @@ + + + + + + + +‪𐡱 + diff --git a/layout/base/crashtests/crashtests.list b/layout/base/crashtests/crashtests.list index 47436de352730..5e4c040379925 100644 --- a/layout/base/crashtests/crashtests.list +++ b/layout/base/crashtests/crashtests.list @@ -347,3 +347,4 @@ load 691118-1.html load 695861.html load 698335.html load 707098.html +load 722137.html From 30ac2adf287ad97918850b838efd94ed81493c1b Mon Sep 17 00:00:00 2001 From: Simon Montagu Date: Mon, 30 Jan 2012 11:05:28 -0800 Subject: [PATCH 09/19] Remove unnecessary test for next sibling. Bug 722137, r=roc --- layout/base/nsBidiPresUtils.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/layout/base/nsBidiPresUtils.cpp b/layout/base/nsBidiPresUtils.cpp index baa343d5466f9..1b2339895e4e4 100644 --- a/layout/base/nsBidiPresUtils.cpp +++ b/layout/base/nsBidiPresUtils.cpp @@ -819,12 +819,10 @@ nsBidiPresUtils::ResolveParagraph(nsBlockFrame* aBlockFrame, RemoveBidiContinuation(aBpd, frame, frameIndex, newIndex, lineOffset); } - } else if (runLength == fragmentLength && - frame->GetNextSibling()) { + } else if (runLength == fragmentLength) { /* - * If the directional run ends at the end of the frame, and this is - * not the containing frame's last child, make sure that the next - * frame is a non-fluid continuation + * If the directional run ends at the end of the frame, make sure + * that any continuation is non-fluid */ nsIFrame* next = frame->GetNextInFlow(); if (next) { From e9e9f8f528c33f523b27f1c045c56410844de33a Mon Sep 17 00:00:00 2001 From: Makoto Kato Date: Tue, 31 Jan 2012 19:30:20 +0900 Subject: [PATCH 10/19] Bug 719319 - unnecessary to use additional OS_LIBS for firefox.exe. r=khuey --- browser/app/Makefile.in | 5 ----- ipc/app/Makefile.in | 5 ----- 2 files changed, 10 deletions(-) diff --git a/browser/app/Makefile.in b/browser/app/Makefile.in index 7e4aeec1ef1f5..d16f45622ca0e 100644 --- a/browser/app/Makefile.in +++ b/browser/app/Makefile.in @@ -107,11 +107,6 @@ ifdef _MSC_VER WIN32_EXE_LDFLAGS += -ENTRY:wmainCRTStartup 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) RCINCLUDE = splash.rc ifndef GNU_CC diff --git a/ipc/app/Makefile.in b/ipc/app/Makefile.in index 85fd62f499734..e5bf9fac733a3 100644 --- a/ipc/app/Makefile.in +++ b/ipc/app/Makefile.in @@ -96,11 +96,6 @@ ifdef _MSC_VER WIN32_EXE_LDFLAGS += -ENTRY:wmainCRTStartup 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 ifeq ($(OS_ARCH),WINNT) From 4614373261711e689a26ef7de1646f0bbccf85c9 Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Tue, 31 Jan 2012 11:40:03 +0100 Subject: [PATCH 11/19] Bug 715867 - Don't fire duplicate sizemodechange events on Mac. r=smichaud --- widget/cocoa/nsCocoaWindow.mm | 18 +-- widget/tests/Makefile.in | 3 +- ...{window_bug596600.xul => empty_window.xul} | 2 +- widget/tests/test_bug596600.xul | 4 +- widget/tests/test_sizemode_events.xul | 107 ++++++++++++++++++ 5 files changed, 122 insertions(+), 12 deletions(-) rename widget/tests/{window_bug596600.xul => empty_window.xul} (74%) create mode 100644 widget/tests/test_sizemode_events.xul diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm index 76c015a74fe7b..3bb7004eb51bc 100644 --- a/widget/cocoa/nsCocoaWindow.mm +++ b/widget/cocoa/nsCocoaWindow.mm @@ -1062,17 +1062,14 @@ nsIntRect screenBounds( 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_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - PRInt32 previousMode; - nsBaseWidget::GetSizeMode(&previousMode); - - nsresult rv = nsBaseWidget::SetSizeMode(aMode); - NS_ENSURE_SUCCESS(rv, rv); + // mSizeMode will be updated in DispatchSizeModeEvent, which will be called + // from a delegate method that handles the state change during one of the + // calls below. + nsSizeMode previousMode = mSizeMode; if (aMode == nsSizeMode_Normal) { if ([mWindow isMiniaturized]) @@ -1419,8 +1416,13 @@ nsIntRect screenBounds( void nsCocoaWindow::DispatchSizeModeEvent() { + nsSizeMode newMode = GetWindowSizeMode(mWindow); + if (mSizeMode == newMode) + return; + + mSizeMode = newMode; nsSizeModeEvent event(true, NS_SIZEMODE, this); - event.mSizeMode = GetWindowSizeMode(mWindow); + event.mSizeMode = mSizeMode; event.time = PR_IntervalNow(); nsEventStatus status = nsEventStatus_eIgnore; diff --git a/widget/tests/Makefile.in b/widget/tests/Makefile.in index d6f0a43724444..4e2d6cd259408 100644 --- a/widget/tests/Makefile.in +++ b/widget/tests/Makefile.in @@ -87,6 +87,8 @@ _CHROME_FILES = test_bug343416.xul \ window_composition_text_querycontent.xul \ test_input_events_on_deactive_window.xul \ test_position_on_resize.xul \ + empty_window.xul \ + test_sizemode_events.xul \ $(NULL) # test_bug413277.html mac-only based on 604789, 605178 @@ -109,7 +111,6 @@ _CHROME_FILES += native_menus_window.xul \ bug586713_window.xul \ test_key_event_counts.xul \ test_bug596600.xul \ - window_bug596600.xul \ test_bug673301.xul \ $(NULL) endif diff --git a/widget/tests/window_bug596600.xul b/widget/tests/empty_window.xul similarity index 74% rename from widget/tests/window_bug596600.xul rename to widget/tests/empty_window.xul index 28e96f68e00d2..f0e01761d2f3e 100644 --- a/widget/tests/window_bug596600.xul +++ b/widget/tests/empty_window.xul @@ -1,4 +1,4 @@ - diff --git a/widget/tests/test_bug596600.xul b/widget/tests/test_bug596600.xul index 82c378d287d9c..9db8b15efa2f1 100644 --- a/widget/tests/test_bug596600.xul +++ b/widget/tests/test_bug596600.xul @@ -36,9 +36,9 @@ function moveMouseTo(x, y, andThen) { } 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 () { - 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); }, gLeftWindow); } diff --git a/widget/tests/test_sizemode_events.xul b/widget/tests/test_sizemode_events.xul new file mode 100644 index 0000000000000..578d6f6fc6230 --- /dev/null +++ b/widget/tests/test_sizemode_events.xul @@ -0,0 +1,107 @@ + + + + + + Test for bug 715867 + + + From 11b8e45e1a6ff6f49fa0b2c2620b065b7a66569f Mon Sep 17 00:00:00 2001 From: Makoto Kato Date: Tue, 31 Jan 2012 20:37:03 +0900 Subject: [PATCH 12/19] Bug 716233 - Use Roboto as default on ICS. r=jdaggett --- modules/libpref/src/init/all.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index 8462f3822b92e..066d3a7b7faa8 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -2733,7 +2733,9 @@ pref("font.name.monospace.he", "Droid Sans Mono"); pref("font.name.serif.ja", "Droid Serif"); 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.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.sans-serif.x-baltic", "Droid Sans"); 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.sans-serif.x-central-euro", "Droid Sans"); 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.sans-serif.x-cyrillic", "Droid Sans"); 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.sans-serif.x-unicode", "Droid Sans"); 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.sans-serif.x-user-def", "Droid Sans"); 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.sans-serif.x-western", "Droid Sans"); 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.sans-serif.zh-CN", "Droid Sans"); 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.sans-serif.zh-HK", "Droid Sans"); 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.size.variable.ar", 16); From 5c46e6858037c1b1604b300ba289b2db35ae778f Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Tue, 31 Jan 2012 04:23:42 -0800 Subject: [PATCH 13/19] Bug 710176, Part 1: Do not do TLS intolerance timeout during cert validation, r=honzab --- security/manager/ssl/src/nsNSSIOLayer.cpp | 35 +++++++++++++++++++++-- security/manager/ssl/src/nsNSSIOLayer.h | 2 ++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/security/manager/ssl/src/nsNSSIOLayer.cpp b/security/manager/ssl/src/nsNSSIOLayer.cpp index 15149230d58ab..5eb665f6173c1 100644 --- a/security/manager/ssl/src/nsNSSIOLayer.cpp +++ b/security/manager/ssl/src/nsNSSIOLayer.cpp @@ -154,6 +154,8 @@ nsNSSSocketInfo::nsNSSSocketInfo() : mMutex("nsNSSSocketInfo::nsNSSSocketInfo"), mFd(nsnull), mCertVerificationState(before_cert_verification), + mCertVerificationStarted(0), + mCertVerificationEnded(0), mSecurityState(nsIWebProgressListener::STATE_IS_INSECURE), mSubRequestsHighSecurity(0), mSubRequestsLowSecurity(0), @@ -960,6 +962,7 @@ nsNSSSocketInfo::SetCertVerificationWaiting() NS_ASSERTION(mCertVerificationState != waiting_for_cert_verification, "Invalid state transition to waiting_for_cert_verification"); mCertVerificationState = waiting_for_cert_verification; + mCertVerificationStarted = PR_IntervalNow(); } void @@ -969,6 +972,8 @@ nsNSSSocketInfo::SetCertVerificationResult(PRErrorCode errorCode, NS_ASSERTION(mCertVerificationState == waiting_for_cert_verification, "Invalid state transition to cert_verification_finished"); + mCertVerificationEnded = PR_IntervalNow(); + if (errorCode != 0) { SetCanceled(errorCode, errorMessageType); } else if (mFd) { @@ -1025,11 +1030,36 @@ void nsNSSSocketInfo::SetAllowTLSIntoleranceTimeout(bool aAllow) 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) return false; - return ((PRIntervalTime)(PR_IntervalNow() - mHandshakeStartTime) - > PR_SecondsToInterval(HANDSHAKE_TIMEOUT_SECONDS)); + PRIntervalTime now = PR_IntervalNow(); + PRIntervalTime certVerificationTime = + mCertVerificationEnded - mCertVerificationStarted; + PRIntervalTime totalTime = now - mHandshakeStartTime; + PRIntervalTime totalTimeExceptCertVerificationTime = + totalTime - certVerificationTime; + + return totalTimeExceptCertVerificationTime > + PR_SecondsToInterval(HANDSHAKE_TIMEOUT_SECONDS); } void nsSSLIOLayerHelpers::Cleanup() @@ -2082,6 +2112,7 @@ nsSSLIOLayerPoll(PRFileDesc * fd, PRInt16 in_flags, PRInt16 *out_flags) : "[%p] poll SSL socket using lower %d\n", fd, (int) in_flags)); + // See comments in HandshakeTimeout before moving and/or changing this block if (socketInfo->HandshakeTimeout()) { NS_ASSERTION(in_flags & PR_POLL_EXCEPT, "caller did not poll for EXCEPT (handshake timeout)"); diff --git a/security/manager/ssl/src/nsNSSIOLayer.h b/security/manager/ssl/src/nsNSSIOLayer.h index 2ee94c08b55ff..2e20f3248160d 100644 --- a/security/manager/ssl/src/nsNSSIOLayer.h +++ b/security/manager/ssl/src/nsNSSIOLayer.h @@ -184,6 +184,8 @@ class nsNSSSocketInfo : public nsITransportSecurityInfo, nsCOMPtr mCallbacks; PRFileDesc* mFd; CertVerificationState mCertVerificationState; + PRIntervalTime mCertVerificationStarted; + PRIntervalTime mCertVerificationEnded; PRUint32 mSecurityState; PRInt32 mSubRequestsHighSecurity; PRInt32 mSubRequestsLowSecurity; From 4a76763871b08e00a654fcc50903e2d90a51dd6e Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Tue, 31 Jan 2012 04:24:16 -0800 Subject: [PATCH 14/19] Bug 710176, Part 2: Import ssl_Poll fix from bug 542832, r=kaie --- security/nss/lib/ssl/sslsock.c | 16 +++++++- security/patches/README | 3 +- .../bug-710176-ssl-restart-7-poll-v5.patch | 40 +++++++++++++++++++ 3 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 security/patches/bug-710176-ssl-restart-7-poll-v5.patch diff --git a/security/nss/lib/ssl/sslsock.c b/security/nss/lib/ssl/sslsock.c index f9e456584f65b..6d0d305886b48 100644 --- a/security/nss/lib/ssl/sslsock.c +++ b/security/nss/lib/ssl/sslsock.c @@ -1955,7 +1955,21 @@ ssl_Poll(PRFileDesc *fd, PRInt16 how_flags, PRInt16 *p_out_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; diff --git a/security/patches/README b/security/patches/README index 8f1272e1972be..9500a39f09e4b 100644 --- a/security/patches/README +++ b/security/patches/README @@ -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 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 -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. diff --git a/security/patches/bug-710176-ssl-restart-7-poll-v5.patch b/security/patches/bug-710176-ssl-restart-7-poll-v5.patch new file mode 100644 index 0000000000000..7d5f3f69e5e88 --- /dev/null +++ b/security/patches/bug-710176-ssl-restart-7-poll-v5.patch @@ -0,0 +1,40 @@ +# HG changeset patch +# Parent 4560e2c22b83f85f9238b9094de7a190042676df +# User Brian Smith + +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) From 1a32048465473cb93566f704014317cfa99e7691 Mon Sep 17 00:00:00 2001 From: Rail Alieev Date: Tue, 31 Jan 2012 12:19:38 -0500 Subject: [PATCH 15/19] bug 714978: change mac osx compiler in official branded beta+release builds from using -j1 to -j4. r=nthomas DONTBUILD because it doesn't affect dep/nightly builds. --- browser/config/mozconfigs/linux32/release | 3 +++ browser/config/mozconfigs/linux64/release | 3 +++ browser/config/mozconfigs/macosx-universal/release | 3 +++ 3 files changed, 9 insertions(+) diff --git a/browser/config/mozconfigs/linux32/release b/browser/config/mozconfigs/linux32/release index d26d29f57e9a9..b4188d60ffcf1 100644 --- a/browser/config/mozconfigs/linux32/release +++ b/browser/config/mozconfigs/linux32/release @@ -18,3 +18,6 @@ export MOZ_TELEMETRY_REPORTING=1 # Treat warnings as errors in directories with FAIL_ON_WARNINGS. ac_add_options --enable-warnings-as-errors + +# Enable parallel compiling +mk_add_options MOZ_MAKE_FLAGS="-j4" diff --git a/browser/config/mozconfigs/linux64/release b/browser/config/mozconfigs/linux64/release index d26d29f57e9a9..b4188d60ffcf1 100644 --- a/browser/config/mozconfigs/linux64/release +++ b/browser/config/mozconfigs/linux64/release @@ -18,3 +18,6 @@ export MOZ_TELEMETRY_REPORTING=1 # Treat warnings as errors in directories with FAIL_ON_WARNINGS. ac_add_options --enable-warnings-as-errors + +# Enable parallel compiling +mk_add_options MOZ_MAKE_FLAGS="-j4" diff --git a/browser/config/mozconfigs/macosx-universal/release b/browser/config/mozconfigs/macosx-universal/release index 2d1c94f9a5f98..8913864c0f182 100644 --- a/browser/config/mozconfigs/macosx-universal/release +++ b/browser/config/mozconfigs/macosx-universal/release @@ -14,3 +14,6 @@ export MOZ_TELEMETRY_REPORTING=1 # Treat warnings as errors in directories with FAIL_ON_WARNINGS. ac_add_options --enable-warnings-as-errors + +# Enable parallel compiling +mk_add_options MOZ_MAKE_FLAGS="-j4" From 94abea6d80edbb4304b0a32723ec0e82095795ae Mon Sep 17 00:00:00 2001 From: Doug Turner Date: Tue, 31 Jan 2012 09:24:31 -0800 Subject: [PATCH 16/19] Bug 720092 - java.lang.IndexOutOfBoundsException: getChars (0 ... 88168) ends beyond length 0. We do not know why this is happening yet. This patch catches the throw and logs what values we have for start and end. r=alexp --- mobile/android/base/GeckoInputConnection.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/mobile/android/base/GeckoInputConnection.java b/mobile/android/base/GeckoInputConnection.java index 54ed53ae508d6..3cb40da239f7a 100644 --- a/mobile/android/base/GeckoInputConnection.java +++ b/mobile/android/base/GeckoInputConnection.java @@ -206,8 +206,16 @@ public ExtractedText getExtractedText(ExtractedTextRequest req, int flags) { extract.selectionEnd = b; 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; } From 4eda86895c22c5996804592e26463d228002a280 Mon Sep 17 00:00:00 2001 From: Alex Keybl Date: Tue, 31 Jan 2012 10:17:43 -0800 Subject: [PATCH 17/19] Added tag AURORA_BASE_20120131 for changeset bbc7014db2de --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index d3529a539c84b..e629ff8bc389c 100644 --- a/.hgtags +++ b/.hgtags @@ -73,3 +73,4 @@ c0983049bcaa9551e5f276d5a77ce154c151e0b0 AURORA_BASE_20110927 54bfd8bf682e295ffd7f22fa921ca343957b6c1c AURORA_BASE_20111108 a8506ab2c65480cf2f85f54e203ea746522c62bb AURORA_BASE_20111220 462c726144bc1fb45b61e774f64ac5d61b4e047c UPDATE_PACKAGING_R16 +bbc7014db2de49e2301680d2a86be8a53108a88a AURORA_BASE_20120131 From b07ecb78f89ed3992e1797cbfbc9c2192c89ad9c Mon Sep 17 00:00:00 2001 From: Alex Keybl Date: Tue, 31 Jan 2012 10:57:49 -0800 Subject: [PATCH 18/19] Bug 700000 - Version bump --- .hgtags | 2 ++ browser/config/version.txt | 2 +- config/milestone.txt | 2 +- js/src/config/milestone.txt | 2 +- mobile/android/confvars.sh | 2 +- mobile/xul/confvars.sh | 2 +- xpcom/components/Module.h | 2 +- 7 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.hgtags b/.hgtags index e629ff8bc389c..151d88046cf92 100644 --- a/.hgtags +++ b/.hgtags @@ -74,3 +74,5 @@ c0983049bcaa9551e5f276d5a77ce154c151e0b0 AURORA_BASE_20110927 a8506ab2c65480cf2f85f54e203ea746522c62bb AURORA_BASE_20111220 462c726144bc1fb45b61e774f64ac5d61b4e047c UPDATE_PACKAGING_R16 bbc7014db2de49e2301680d2a86be8a53108a88a AURORA_BASE_20120131 +bbc7014db2de49e2301680d2a86be8a53108a88a AURORA_BASE_20120131 +0000000000000000000000000000000000000000 AURORA_BASE_20120131 diff --git a/browser/config/version.txt b/browser/config/version.txt index 2d216daf369d9..d4157f8df4848 100644 --- a/browser/config/version.txt +++ b/browser/config/version.txt @@ -1 +1 @@ -12.0a1 +13.0a1 diff --git a/config/milestone.txt b/config/milestone.txt index 62564253ccbf9..f780391e9db59 100644 --- a/config/milestone.txt +++ b/config/milestone.txt @@ -10,4 +10,4 @@ # hardcoded milestones in the tree from these two files. #-------------------------------------------------------- -12.0a1 +13.0a1 diff --git a/js/src/config/milestone.txt b/js/src/config/milestone.txt index 62564253ccbf9..f780391e9db59 100644 --- a/js/src/config/milestone.txt +++ b/js/src/config/milestone.txt @@ -10,4 +10,4 @@ # hardcoded milestones in the tree from these two files. #-------------------------------------------------------- -12.0a1 +13.0a1 diff --git a/mobile/android/confvars.sh b/mobile/android/confvars.sh index 2f0426955ae8d..febe50a0d0dbd 100644 --- a/mobile/android/confvars.sh +++ b/mobile/android/confvars.sh @@ -38,7 +38,7 @@ MOZ_APP_BASENAME=Fennec MOZ_APP_VENDOR=Mozilla -MOZ_APP_VERSION=12.0a1 +MOZ_APP_VERSION=13.0a1 MOZ_BRANDING_DIRECTORY=mobile/android/branding/unofficial MOZ_OFFICIAL_BRANDING_DIRECTORY=mobile/android/branding/official diff --git a/mobile/xul/confvars.sh b/mobile/xul/confvars.sh index 65064e1f78812..53f1f3b3da291 100644 --- a/mobile/xul/confvars.sh +++ b/mobile/xul/confvars.sh @@ -38,7 +38,7 @@ MOZ_APP_BASENAME=Fennec MOZ_APP_VENDOR=Mozilla -MOZ_APP_VERSION=12.0a1 +MOZ_APP_VERSION=13.0a1 MOZ_BRANDING_DIRECTORY=mobile/xul/branding/unofficial MOZ_OFFICIAL_BRANDING_DIRECTORY=mobile/xul/branding/official diff --git a/xpcom/components/Module.h b/xpcom/components/Module.h index e18a02c1911c4..4501daa756f4d 100644 --- a/xpcom/components/Module.h +++ b/xpcom/components/Module.h @@ -53,7 +53,7 @@ namespace mozilla { */ struct Module { - static const unsigned int kVersion = 12; + static const unsigned int kVersion = 13; struct CIDEntry; From 96d8504d42e07b445d220f0ffd00b4ef47ca2ba6 Mon Sep 17 00:00:00 2001 From: Ed Morley Date: Tue, 31 Jan 2012 18:20:33 +0000 Subject: [PATCH 19/19] Backout d74a924a149b (in effect relanding bug 707320) due to M-oth orange --- toolkit/components/telemetry/Telemetry.cpp | 345 +++++++++++++++++- toolkit/components/telemetry/TelemetryPing.js | 109 +++++- toolkit/components/telemetry/nsITelemetry.idl | 61 +++- .../telemetry/tests/unit/test_nsITelemetry.js | 41 +++ 4 files changed, 531 insertions(+), 25 deletions(-) diff --git a/toolkit/components/telemetry/Telemetry.cpp b/toolkit/components/telemetry/Telemetry.cpp index 0467ffb61d553..1300a935a2646 100644 --- a/toolkit/components/telemetry/Telemetry.cpp +++ b/toolkit/components/telemetry/Telemetry.cpp @@ -38,6 +38,7 @@ * ***** END LICENSE BLOCK ***** */ #include "base/histogram.h" +#include "base/pickle.h" #include "nsIComponentManager.h" #include "nsIServiceManager.h" #include "nsCOMPtr.h" @@ -47,6 +48,8 @@ #include "jsapi.h" #include "nsStringGlue.h" #include "nsITelemetry.h" +#include "nsIFile.h" +#include "nsILocalFile.h" #include "Telemetry.h" #include "nsTHashtable.h" #include "nsHashKeys.h" @@ -54,6 +57,7 @@ #include "nsXULAppAPI.h" #include "nsThreadUtils.h" #include "mozilla/Mutex.h" +#include "mozilla/FileUtils.h" namespace { @@ -227,11 +231,9 @@ enum reflectStatus { }; enum reflectStatus -ReflectHistogramSnapshot(JSContext *cx, JSObject *obj, Histogram *h) +ReflectHistogramAndSamples(JSContext *cx, JSObject *obj, Histogram *h, + const Histogram::SampleSet &ss) { - Histogram::SampleSet ss; - h->SnapshotSample(&ss); - // We don't want to reflect corrupt histograms. if (h->FindCorruption(ss) != Histogram::NO_INCONSISTENCIES) { return REFLECT_CORRUPT; @@ -260,6 +262,14 @@ ReflectHistogramSnapshot(JSContext *cx, JSObject *obj, Histogram *h) 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 JSHistogram_Add(JSContext *cx, uintN argc, jsval *vp) { @@ -677,6 +687,333 @@ TelemetryImpl::GetHistogramById(const nsACString &name, JSContext *cx, jsval *re 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 EntryType; + typedef nsTHashtable 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(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(&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 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 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 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 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(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 mFile; + nsCString mUUID; + nsCOMPtr mCallback; +}; + +NS_IMETHODIMP +TelemetryImpl::SaveHistograms(nsIFile *file, const nsACString &uuid, + nsITelemetrySaveSessionDataCallback *callback, + bool isSynchronous) +{ + nsCOMPtr 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 data(sessionData); + mCallback->Handle(data); + } + return rv; + } + +private: + nsCOMPtr mFile; + nsCOMPtr mCallback; +}; + +NS_IMETHODIMP +TelemetryImpl::LoadHistograms(nsIFile *file, + nsITelemetryLoadSessionDataCallback *callback) +{ + nsCOMPtr event = new LoadHistogramEvent(file, callback); + return NS_DispatchToCurrentThread(event); +} + NS_IMETHODIMP TelemetryImpl::GetCanRecord(bool *ret) { *ret = mCanRecord; diff --git a/toolkit/components/telemetry/TelemetryPing.js b/toolkit/components/telemetry/TelemetryPing.js index 5aa510fb82e96..7a6c2a85f905a 100644 --- a/toolkit/components/telemetry/TelemetryPing.js +++ b/toolkit/components/telemetry/TelemetryPing.js @@ -42,6 +42,7 @@ const Cu = Components.utils; Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.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 const PAYLOAD_VERSION = 1; @@ -179,6 +180,10 @@ TelemetryPing.prototype = { _histograms: {}, _initialized: false, _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 @@ -187,8 +192,7 @@ TelemetryPing.prototype = { * histogram_type: <0 for exponential, 1 for linear>, bucketX:countX, ....} ...} * where bucket[XY], count[XY] are positive integers. */ - getHistograms: function getHistograms() { - let hls = Telemetry.histogramSnapshots; + getHistograms: function getHistograms(hls) { let info = Telemetry.registeredHistograms; let ret = {}; @@ -397,24 +401,48 @@ TelemetryPing.prototype = { send: function send(reason, server) { // populate histograms one last time 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 = { ver: PAYLOAD_VERSION, - info: this.getMetadata(reason), - simpleMeasurements: getSimpleMeasurements(), - histograms: this.getHistograms(), - slowSQL: Telemetry.slowSQL + // Send a different reason string for previous session data. + info: this.getMetadata(havePreviousSession ? "saved-session" : reason), }; + 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) }; + }, - let isTestPing = (reason == "test-ping"); - // Generate a unique id once per session so the server can cope with duplicate submissions. - // 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; + doPing: function doPing(server, slug, payload, recordSuccess) { + let submitPath = "/submit/telemetry/" + slug; + let url = server + submitPath; let request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"] .createInstance(Ci.nsIXMLHttpRequest); request.mozBackgroundRequest = true; @@ -423,6 +451,7 @@ TelemetryPing.prototype = { request.setRequestHeader("Content-Type", "application/json"); let startTime = new Date(); + let file = this.savedHistogramsFile(); function finishRequest(channel) { let success = false; @@ -430,15 +459,23 @@ TelemetryPing.prototype = { success = channel.QueryInterface(Ci.nsIHttpChannel).requestSucceeded; } catch(e) { } - hsuccess.add(success); - hping.add(new Date() - startTime); - if (isTestPing) + if (recordSuccess) { + let hping = Telemetry.getHistogramById("TELEMETRY_PING"); + let hsuccess = Telemetry.getHistogramById("TELEMETRY_SUCCESS"); + + 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); } request.addEventListener("error", function(aEvent) finishRequest(request.channel), false); request.addEventListener("load", function(aEvent) finishRequest(request.channel), false); - request.send(JSON.stringify(payloadObj)); + request.send(payload); }, attachObservers: function attachObservers() { @@ -459,6 +496,25 @@ 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. */ @@ -479,6 +535,7 @@ TelemetryPing.prototype = { Services.obs.addObserver(this, "private-browsing", false); Services.obs.addObserver(this, "profile-before-change", 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 // run various late initializers. Otherwise our gathered memory @@ -492,6 +549,12 @@ TelemetryPing.prototype = { delete self._timer } 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); }, /** @@ -502,6 +565,7 @@ TelemetryPing.prototype = { Services.obs.removeObserver(this, "sessionstore-windows-restored"); Services.obs.removeObserver(this, "profile-before-change"); Services.obs.removeObserver(this, "private-browsing"); + Services.obs.removeObserver(this, "quit-application-granted"); }, /** @@ -567,6 +631,11 @@ TelemetryPing.prototype = { } this.send(aTopic == "idle" ? "idle-daily" : aTopic, server); break; + case "quit-application-granted": + Telemetry.saveHistograms(this.savedHistogramsFile(), + this._uuid, function (success) success, + /*isSynchronous=*/true); + break; } }, diff --git a/toolkit/components/telemetry/nsITelemetry.idl b/toolkit/components/telemetry/nsITelemetry.idl index 5e82bf126f0ae..b001b48ed8d92 100644 --- a/toolkit/components/telemetry/nsITelemetry.idl +++ b/toolkit/components/telemetry/nsITelemetry.idl @@ -38,8 +38,39 @@ * ***** END LICENSE BLOCK ***** */ #include "nsISupports.idl" +#include "nsIFile.idl" -[scriptable, uuid(db854295-478d-4de9-8211-d73ed7d81cd0)] +[scriptable, uuid(c177b6b0-5ef1-44f5-bc67-6bcf7d2518e5)] +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 { /** @@ -127,6 +158,34 @@ interface nsITelemetry : nsISupports [implicit_jscontext] 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. */ diff --git a/toolkit/components/telemetry/tests/unit/test_nsITelemetry.js b/toolkit/components/telemetry/tests/unit/test_nsITelemetry.js index e0711d7ceddac..56dc92afbd81d 100644 --- a/toolkit/components/telemetry/tests/unit/test_nsITelemetry.js +++ b/toolkit/components/telemetry/tests/unit/test_nsITelemetry.js @@ -105,6 +105,45 @@ function test_privateMode() { 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() { let kinds = [Telemetry.HISTOGRAM_EXPONENTIAL, Telemetry.HISTOGRAM_LINEAR] @@ -121,4 +160,6 @@ function run_test() test_getHistogramById(); test_getSlowSQL(); test_privateMode(); + test_loadSave(); + }