From e06c21d86ca10de909d16e780748e2a594707544 Mon Sep 17 00:00:00 2001 From: Matthew Noorenberghe Date: Wed, 22 Jan 2014 20:09:03 +0000 Subject: [PATCH 01/12] Bug 956162 - Implement @flip="none" for popups to allow them to appear off-screen without flipping or resizing. r=Enn [Australis] --- browser/base/content/browser.xul | 1 + layout/xul/nsMenuPopupFrame.cpp | 25 ++++++++++++++----------- layout/xul/nsMenuPopupFrame.h | 11 +++++++++-- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/browser/base/content/browser.xul b/browser/base/content/browser.xul index 8df3a9c96403..f2812852a26b 100644 --- a/browser/base/content/browser.xul +++ b/browser/base/content/browser.xul @@ -218,6 +218,7 @@ hidden="true" noautofocus="true" noautohide="true" + flip="none" consumeoutsideclicks="false"> diff --git a/layout/xul/nsMenuPopupFrame.cpp b/layout/xul/nsMenuPopupFrame.cpp index 2da86aced749..119ebaf54d65 100644 --- a/layout/xul/nsMenuPopupFrame.cpp +++ b/layout/xul/nsMenuPopupFrame.cpp @@ -87,7 +87,7 @@ nsMenuPopupFrame::nsMenuPopupFrame(nsIPresShell* aShell, nsStyleContext* aContex mPopupAnchor(POPUPALIGNMENT_NONE), mPosition(POPUPPOSITION_UNKNOWN), mConsumeRollupEvent(nsIPopupBoxObject::ROLLUP_DEFAULT), - mFlipBoth(false), + mFlip(FlipType_Default), mIsOpenChanged(false), mIsContextMenu(false), mAdjustOffsetForContextMenu(false), @@ -581,8 +581,13 @@ nsMenuPopupFrame::InitializePopup(nsIContent* aAnchorContent, position.Assign(aPosition); } - mFlipBoth = flip.EqualsLiteral("both"); - mSlide = flip.EqualsLiteral("slide"); + if (flip.EqualsLiteral("none")) { + mFlip = FlipType_None; + } else if (flip.EqualsLiteral("both")) { + mFlip = FlipType_Both; + } else if (flip.EqualsLiteral("slide")) { + mFlip = FlipType_Slide; + } position.CompressWhitespace(); int32_t spaceIdx = position.FindChar(' '); @@ -685,8 +690,7 @@ nsMenuPopupFrame::InitializePopupAtScreen(nsIContent* aTriggerContent, mTriggerContent = aTriggerContent; mScreenXPos = aXPos; mScreenYPos = aYPos; - mFlipBoth = false; - mSlide = false; + mFlip = FlipType_Default; mPopupAnchor = POPUPALIGNMENT_NONE; mPopupAlignment = POPUPALIGNMENT_NONE; mIsContextMenu = aIsContextMenu; @@ -703,8 +707,7 @@ nsMenuPopupFrame::InitializePopupWithAnchorAlign(nsIContent* aAnchorContent, mPopupState = ePopupShowing; mAdjustOffsetForContextMenu = false; - mFlipBoth = false; - mSlide = false; + mFlip = FlipType_Default; // this popup opening function is provided for backwards compatibility // only. It accepts either coordinates or an anchor and alignment value @@ -981,7 +984,7 @@ nsMenuPopupFrame::AdjustPositionForAnchorAlign(nsRect& anchorRect, break; default: { - FlipStyle anchorEdge = mFlipBoth ? FlipStyle_Inside : FlipStyle_None; + FlipStyle anchorEdge = mFlip == FlipType_Both ? FlipStyle_Inside : FlipStyle_None; aHFlip = (popupAnchor == -popupAlign) ? FlipStyle_Outside : anchorEdge; if (((popupAnchor > 0) == (popupAlign > 0)) || (popupAnchor == POPUPALIGNMENT_TOPLEFT && popupAlign == POPUPALIGNMENT_TOPLEFT)) @@ -1271,9 +1274,9 @@ nsMenuPopupFrame::SetPopupPosition(nsIFrame* aAnchorFrame, bool aIsMove) vFlip = FlipStyle_Outside; } - // If a panel is being moved, don't constrain or flip it. But always do this for + // If a panel is being moved or has flip="none", don't constrain or flip it. But always do this for // content shells, so that the popup doesn't extend outside the containing frame. - if (mInContentShell || !aIsMove || mPopupType != ePopupTypePanel) { + if (mInContentShell || (mFlip != FlipType_None && (!aIsMove || mPopupType != ePopupTypePanel))) { nsRect screenRect = GetConstraintRect(anchorRect, rootScreenRect); // ensure that anchorRect is on screen @@ -1303,7 +1306,7 @@ nsMenuPopupFrame::SetPopupPosition(nsIFrame* aAnchorFrame, bool aIsMove) // but we can only slide on one axis - the other axis must be "flipped or // resized" as normal. bool slideHorizontal = false, slideVertical = false; - if (mSlide) { + if (mFlip == FlipType_Slide) { int8_t position = GetAlignmentPosition(); slideHorizontal = position >= POPUPPOSITION_BEFORESTART && position <= POPUPPOSITION_AFTEREND; diff --git a/layout/xul/nsMenuPopupFrame.h b/layout/xul/nsMenuPopupFrame.h index e205f47dee49..5cf680698347 100644 --- a/layout/xul/nsMenuPopupFrame.h +++ b/layout/xul/nsMenuPopupFrame.h @@ -65,6 +65,14 @@ enum FlipStyle { FlipStyle_Inside = 2 }; +// Values for the flip attribute +enum FlipType { + FlipType_Default = 0, + FlipType_None = 1, // don't try to flip or translate to stay onscreen + FlipType_Both = 2, // flip in both directions + FlipType_Slide = 3 // allow the arrow to "slide" instead of resizing +}; + // values are selected so that the direction can be flipped just by // changing the sign #define POPUPALIGNMENT_NONE 0 @@ -459,8 +467,7 @@ protected: // One of nsIPopupBoxObject::ROLLUP_DEFAULT/ROLLUP_CONSUME/ROLLUP_NO_CONSUME int8_t mConsumeRollupEvent; - bool mFlipBoth; // flip in both directions - bool mSlide; // allow the arrow to "slide" instead of resizing + FlipType mFlip; // Whether to flip bool mIsOpenChanged; // true if the open state changed since the last layout bool mIsContextMenu; // true for context menus From 2d9cf8ba96e7082cde415d3509ab8a47d0dda59c Mon Sep 17 00:00:00 2001 From: Matthew Noorenberghe Date: Wed, 22 Jan 2014 20:09:03 +0000 Subject: [PATCH 02/12] Bug 956162 - Tests - Implement @flip="none" for popups to allow them to appear off-screen without flipping or resizing. r=Enn [Australis] --- toolkit/content/tests/chrome/window_panel.xul | 49 ++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/toolkit/content/tests/chrome/window_panel.xul b/toolkit/content/tests/chrome/window_panel.xul index 1bfd525fa39a..7e1ab80800ea 100644 --- a/toolkit/content/tests/chrome/window_panel.xul +++ b/toolkit/content/tests/chrome/window_panel.xul @@ -254,7 +254,54 @@ var tests = [ is(panel.getOuterScreenRect().top, 245, testname + "top"); } } - } + }, + { + // The panel should be allowed to appear and remain offscreen + testname: "normal panel with flip='none' off-screen", + attrs: { "flip": "none" }, + test: function(panel) { + panel.openPopup(document.documentElement, "", -100 - mozInnerScreenX, -100 - mozInnerScreenY, false, false, null); + }, + result: function(testname, panel) { + var panelrect = panel.getBoundingClientRect(); + is(panelrect.left, -100 - mozInnerScreenX, testname + "left"); + is(panelrect.top, -100 - mozInnerScreenY, testname + "top"); + is(panelrect.width, 120, testname + "width"); + is(panelrect.height, 40, testname + "height"); + + var screenRect = panel.getOuterScreenRect(); + is(screenRect.left, -100, testname + " screen left"); + is(screenRect.top, -100, testname + " screen top"); + is(screenRect.width, 120, testname + " screen width"); + is(screenRect.height, 40, testname + " screen height"); + } + }, + { + // The panel should be allowed to remain offscreen after moving and it should follow the anchor + testname: "normal panel with flip='none' moved off-screen", + attrs: { "flip": "none" }, + test: function(panel) { + panel.openPopup(document.documentElement, "", -100 - mozInnerScreenX, -100 - mozInnerScreenY, false, false, null); + window.moveBy(-50, -50); + }, + result: function(testname, panel) { + if (navigator.platform.indexOf("Linux") >= 0) { + // The window position doesn't get updated immediately on Linux. + return; + } + var panelrect = panel.getBoundingClientRect(); + is(panelrect.left, -150 - mozInnerScreenX, testname + "left"); + is(panelrect.top, -150 - mozInnerScreenY, testname + "top"); + is(panelrect.width, 120, testname + "width"); + is(panelrect.height, 40, testname + "height"); + + var screenRect = panel.getOuterScreenRect(); + is(screenRect.left, -150, testname + " screen left"); + is(screenRect.top, -150, testname + " screen top"); + is(screenRect.width, 120, testname + " screen width"); + is(screenRect.height, 40, testname + " screen height"); + } + }, ]; window.opener.wrappedJSObject.SimpleTest.waitForFocus(test_panels, window); From 5758957ce680df5fc989122738d01cfa15cd2379 Mon Sep 17 00:00:00 2001 From: Jeroen van der Gun Date: Thu, 23 Jan 2014 10:31:00 +0000 Subject: [PATCH 03/12] Bug 961377 - Extend webapp runtime to support tooltips in webapps like in the normal browser; r=felipe --- webapprt/content/webapp.js | 21 +++++++++++++++++++++ webapprt/content/webapp.xul | 3 ++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/webapprt/content/webapp.js b/webapprt/content/webapp.js index 24e3984fed1d..1a2ef3588643 100644 --- a/webapprt/content/webapp.js +++ b/webapprt/content/webapp.js @@ -24,6 +24,27 @@ let progressListener = { Ci.nsISupportsWeakReference]), onLocationChange: function onLocationChange(progress, request, location, flags) { + + // Close tooltip (code adapted from /browser/base/content/browser.js) + let pageTooltip = document.getElementById("contentAreaTooltip"); + let tooltipNode = pageTooltip.triggerNode; + if (tooltipNode) { + // Optimise for the common case + if (progress.isTopLevel) { + pageTooltip.hidePopup(); + } + else { + for (let tooltipWindow = tooltipNode.ownerDocument.defaultView; + tooltipWindow != tooltipWindow.parent; + tooltipWindow = tooltipWindow.parent) { + if (tooltipWindow == progress.DOMWindow) { + pageTooltip.hidePopup(); + break; + } + } + } + } + // Set the title of the window to the name of the webapp, adding the origin // of the page being loaded if it's from a different origin than the app // (per security bug 741955, which specifies that other-origin pages loaded diff --git a/webapprt/content/webapp.xul b/webapprt/content/webapp.xul index c6346f4b3474..a546b6c257c4 100644 --- a/webapprt/content/webapp.xul +++ b/webapprt/content/webapp.xul @@ -155,13 +155,14 @@ - + + From 31474fa4886f4faf012c3acf6447d7b107209ec4 Mon Sep 17 00:00:00 2001 From: Lucas Rocha Date: Thu, 23 Jan 2014 19:00:05 +0000 Subject: [PATCH 04/12] Bug 962968 - Replace HashMap with SparseArray in ICODecoder (r=rnewman) --- .../base/favicons/decoders/ICODecoder.java | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/mobile/android/base/favicons/decoders/ICODecoder.java b/mobile/android/base/favicons/decoders/ICODecoder.java index 3ee441cedda0..47758b0914b7 100644 --- a/mobile/android/base/favicons/decoders/ICODecoder.java +++ b/mobile/android/base/favicons/decoders/ICODecoder.java @@ -8,8 +8,9 @@ import android.graphics.Bitmap; import org.mozilla.gecko.favicons.Favicons; import org.mozilla.gecko.gfx.BitmapUtils; +import android.util.SparseArray; + import java.util.Collection; -import java.util.HashMap; import java.util.Iterator; import java.util.NoSuchElementException; @@ -152,7 +153,7 @@ public class ICODecoder implements Iterable { int minimumMaximum = Integer.MAX_VALUE; // Used to track the best entry for each size. The entries we want to keep. - HashMap preferenceMap = new HashMap(); + SparseArray preferenceArray = new SparseArray(); for (int i = 0; i < numEncodedImages; i++, bufferIndex += ICO_ICONDIRENTRY_LENGTH_BYTES) { // Decode the Icon Directory Entry at this offset. @@ -172,42 +173,39 @@ public class ICODecoder implements Iterable { } // Remove the previous minimum-maximum. - if (preferenceMap.containsKey(minimumMaximum)) { - preferenceMap.remove(minimumMaximum); - } + preferenceArray.delete(minimumMaximum); minimumMaximum = newEntry.mWidth; } - IconDirectoryEntry oldEntry = preferenceMap.get(newEntry.mWidth); + IconDirectoryEntry oldEntry = preferenceArray.get(newEntry.mWidth); if (oldEntry == null) { - preferenceMap.put(newEntry.mWidth, newEntry); + preferenceArray.put(newEntry.mWidth, newEntry); continue; } if (oldEntry.compareTo(newEntry) < 0) { - preferenceMap.put(newEntry.mWidth, newEntry); + preferenceArray.put(newEntry.mWidth, newEntry); } } - Collection entriesRetained = preferenceMap.values(); + final int count = preferenceArray.size(); // Abort if no entries are desired (Perhaps all are corrupt?) - if (entriesRetained.isEmpty()) { + if (count == 0) { return false; } // Allocate space for the icon directory entries in the decoded directory. - mIconDirectory = new IconDirectoryEntry[entriesRetained.size()]; + mIconDirectory = new IconDirectoryEntry[count]; // The size of the data in the buffer that we find useful. int retainedSpace = ICO_HEADER_LENGTH_BYTES; - int dirInd = 0; - for (IconDirectoryEntry e : entriesRetained) { + for (int i = 0; i < count; i++) { + IconDirectoryEntry e = preferenceArray.valueAt(i); retainedSpace += ICO_ICONDIRENTRY_LENGTH_BYTES + e.mPayloadSize; - mIconDirectory[dirInd] = e; - dirInd++; + mIconDirectory[i] = e; } mIsValid = true; From a8c66b58a417943b434391ed244a8ed580ac48e1 Mon Sep 17 00:00:00 2001 From: Lucas Rocha Date: Thu, 23 Jan 2014 19:00:05 +0000 Subject: [PATCH 05/12] Bug 962968 - Replace HashMap with SparseArray in Favicons (r=rnewman) --- mobile/android/base/favicons/Favicons.java | 27 ++++++++++++---------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/mobile/android/base/favicons/Favicons.java b/mobile/android/base/favicons/Favicons.java index fade13290326..cddab3076a80 100644 --- a/mobile/android/base/favicons/Favicons.java +++ b/mobile/android/base/favicons/Favicons.java @@ -23,15 +23,14 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.text.TextUtils; import android.util.Log; +import android.util.SparseArray; import java.io.File; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.Iterator; -import java.util.Map; import java.util.Set; public class Favicons { @@ -62,7 +61,7 @@ public class Favicons { // The density-adjusted maximum Favicon dimensions. public static int sLargestFaviconSize; - private static final Map sLoadTasks = Collections.synchronizedMap(new HashMap()); + private static final SparseArray sLoadTasks = new SparseArray(); // Cache to hold mappings between page URLs and Favicon URLs. Used to avoid going to the DB when // doing so is not necessary. @@ -217,7 +216,9 @@ public class Favicons { // No joy using in-memory resources. Go to background thread and ask the database. LoadFaviconTask task = new LoadFaviconTask(ThreadUtils.getBackgroundHandler(), pageURL, targetURL, 0, callback, targetSize, true); int taskId = task.getId(); - sLoadTasks.put(taskId, task); + synchronized(sLoadTasks) { + sLoadTasks.put(taskId, task); + } task.execute(); return taskId; } @@ -282,7 +283,9 @@ public class Favicons { LoadFaviconTask task = new LoadFaviconTask(ThreadUtils.getBackgroundHandler(), pageUrl, faviconUrl, flags, listener, targetSize, false); int taskId = task.getId(); - sLoadTasks.put(taskId, task); + synchronized(sLoadTasks) { + sLoadTasks.put(taskId, task); + } task.execute(); @@ -325,7 +328,7 @@ public class Favicons { boolean cancelled; synchronized (sLoadTasks) { - if (!sLoadTasks.containsKey(taskId)) + if (sLoadTasks.indexOfKey(taskId) < 0) return false; Log.d(LOGTAG, "Cancelling favicon load (" + taskId + ")"); @@ -341,11 +344,9 @@ public class Favicons { // Cancel any pending tasks synchronized (sLoadTasks) { - Set taskIds = sLoadTasks.keySet(); - Iterator iter = taskIds.iterator(); - while (iter.hasNext()) { - int taskId = iter.next(); - cancelFaviconLoad(taskId); + final int count = sLoadTasks.size(); + for (int i = 0; i < count; i++) { + cancelFaviconLoad(sLoadTasks.keyAt(i)); } sLoadTasks.clear(); } @@ -449,7 +450,9 @@ public class Favicons { } public static void removeLoadTask(int taskId) { - sLoadTasks.remove(taskId); + synchronized(sLoadTasks) { + sLoadTasks.delete(taskId); + } } /** From b1165b178529d87fab626213f86dbfec5383ee8d Mon Sep 17 00:00:00 2001 From: Lucas Rocha Date: Thu, 23 Jan 2014 19:00:06 +0000 Subject: [PATCH 06/12] Bug 962968 - Replace HashMap with SparseArray in GeckoJavaSampler (r=rnewman) --- mobile/android/base/GeckoJavaSampler.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mobile/android/base/GeckoJavaSampler.java b/mobile/android/base/GeckoJavaSampler.java index 051d70ad3f9b..23594ee70f33 100644 --- a/mobile/android/base/GeckoJavaSampler.java +++ b/mobile/android/base/GeckoJavaSampler.java @@ -7,12 +7,11 @@ package org.mozilla.gecko; import android.os.SystemClock; import android.util.Log; +import android.util.SparseArray; import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI; import java.lang.Thread; -import java.util.HashMap; -import java.util.Map; import java.util.Set; public class GeckoJavaSampler { @@ -63,7 +62,7 @@ public class GeckoJavaSampler { private boolean mPauseSampler = false; private boolean mStopSampler = false; - private Map mSamples = new HashMap(); + private SparseArray mSamples = new SparseArray(); private int mSamplePos; public SamplingThread(final int aInterval, final int aSampleCount) { From 819952c3f23719a2dcdc3cd248d16dc71660a4f4 Mon Sep 17 00:00:00 2001 From: Lucas Rocha Date: Thu, 23 Jan 2014 19:00:06 +0000 Subject: [PATCH 07/12] Bug 962968 - Replace HashMap with SparseArray in PanelManager (r=rnewman) --- mobile/android/base/home/PanelManager.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/mobile/android/base/home/PanelManager.java b/mobile/android/base/home/PanelManager.java index 4b7b1b247fbc..6f3be697d1d8 100644 --- a/mobile/android/base/home/PanelManager.java +++ b/mobile/android/base/home/PanelManager.java @@ -19,11 +19,10 @@ import android.content.SharedPreferences; import android.preference.PreferenceManager; import android.text.TextUtils; import android.util.Log; +import android.util.SparseArray; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; public class PanelManager implements GeckoEventListener { @@ -50,7 +49,7 @@ public class PanelManager implements GeckoEventListener { private static AtomicInteger sRequestId = new AtomicInteger(0); // Stores set of pending request callbacks. - private static final Map sCallbacks = new HashMap(); + private static final SparseArray sCallbacks = new SparseArray(); /** * Asynchronously fetches list of available panels from Gecko. @@ -62,7 +61,7 @@ public class PanelManager implements GeckoEventListener { synchronized(sCallbacks) { // If there are no pending callbacks, register the event listener. - if (sCallbacks.isEmpty()) { + if (sCallbacks.size() == 0) { GeckoAppShell.getEventDispatcher().registerEventListener("HomePanels:Data", this); } sCallbacks.put(requestId, callback); @@ -90,10 +89,11 @@ public class PanelManager implements GeckoEventListener { final int requestId = message.getInt("requestId"); synchronized(sCallbacks) { - callback = sCallbacks.remove(requestId); + callback = sCallbacks.get(requestId); + sCallbacks.delete(requestId); // Unregister the event listener if there are no more pending callbacks. - if (sCallbacks.isEmpty()) { + if (sCallbacks.size() == 0) { GeckoAppShell.getEventDispatcher().unregisterEventListener("HomePanels:Data", this); } } From 6fbb4b49c3fc1c74aef93bf3a4e1a0a9d143b83f Mon Sep 17 00:00:00 2001 From: Lucas Rocha Date: Thu, 23 Jan 2014 19:00:06 +0000 Subject: [PATCH 08/12] Bug 962968 - Replace HashMap with SparseArray in PrefsHelper (r=rnewman) --- mobile/android/base/PrefsHelper.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/mobile/android/base/PrefsHelper.java b/mobile/android/base/PrefsHelper.java index b3f97371af52..d459f673924a 100644 --- a/mobile/android/base/PrefsHelper.java +++ b/mobile/android/base/PrefsHelper.java @@ -12,10 +12,9 @@ import org.json.JSONException; import org.json.JSONObject; import android.util.Log; +import android.util.SparseArray; import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; /** * Helper class to get/set gecko prefs. @@ -24,7 +23,7 @@ public final class PrefsHelper { private static final String LOGTAG = "GeckoPrefsHelper"; private static boolean sRegistered = false; - private static final Map sCallbacks = new HashMap(); + private static final SparseArray sCallbacks = new SparseArray(); private static int sUniqueRequestId = 1; public static int getPref(String prefName, PrefHandler callback) { @@ -73,7 +72,7 @@ public final class PrefsHelper { int requestId = message.getInt("requestId"); callback = sCallbacks.get(requestId); if (callback != null && !callback.isObserver()) { - sCallbacks.remove(requestId); + sCallbacks.delete(requestId); } } catch (Exception e) { callback = null; @@ -144,7 +143,9 @@ public final class PrefsHelper { } synchronized (PrefsHelper.class) { - PrefHandler callback = sCallbacks.remove(requestId); + PrefHandler callback = sCallbacks.get(requestId); + sCallbacks.delete(requestId); + if (callback == null) { Log.e(LOGTAG, "Unknown request ID " + requestId); return; From 48d3086ab161cdc7d31e66a0c32a8b2cc484c481 Mon Sep 17 00:00:00 2001 From: Lucas Rocha Date: Thu, 23 Jan 2014 19:00:06 +0000 Subject: [PATCH 09/12] Bug 962968 - Replace HashMap with SparseArray in ActivityResultHandlerMap (r=rnewman) --- mobile/android/base/util/ActivityResultHandlerMap.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/mobile/android/base/util/ActivityResultHandlerMap.java b/mobile/android/base/util/ActivityResultHandlerMap.java index 781f3b709b2d..564ef1f07418 100644 --- a/mobile/android/base/util/ActivityResultHandlerMap.java +++ b/mobile/android/base/util/ActivityResultHandlerMap.java @@ -4,11 +4,10 @@ package org.mozilla.gecko.util; -import java.util.HashMap; -import java.util.Map; +import android.util.SparseArray; public final class ActivityResultHandlerMap { - private Map mMap = new HashMap(); + private SparseArray mMap = new SparseArray(); private int mCounter = 0; public synchronized int put(ActivityResultHandler handler) { @@ -17,6 +16,9 @@ public final class ActivityResultHandlerMap { } public synchronized ActivityResultHandler getAndRemove(int i) { - return mMap.remove(i); + ActivityResultHandler handler = mMap.get(i); + mMap.delete(i); + + return handler; } } From 594c8edb03b039a5d914b999e814e27e0aad6554 Mon Sep 17 00:00:00 2001 From: Brad Lassey Date: Thu, 23 Jan 2014 15:00:17 -0500 Subject: [PATCH 10/12] bug 951782 - Firefox 26 for Android crashes on HTC Desire Z due to on-demand decompression r=mfinkle a=bajaj --- mobile/android/base/mozglue/GeckoLoader.java.in | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mobile/android/base/mozglue/GeckoLoader.java.in b/mobile/android/base/mozglue/GeckoLoader.java.in index 9cb4e108b14f..a0ddf4d3ad02 100644 --- a/mobile/android/base/mozglue/GeckoLoader.java.in +++ b/mobile/android/base/mozglue/GeckoLoader.java.in @@ -205,6 +205,13 @@ public final class GeckoLoader { putenv("MOZ_LINKER_CACHE=" + linkerCache); } + // Disable on-demand decompression of the linker on devices where it + // is known to cause crashes. + if ("HTC".equals(android.os.Build.MANUFACTURER) && + "HTC Vision".equals(android.os.Build.MODEL)) { + putenv("MOZ_LINKER_ONDEMAND=0"); + } + #ifdef MOZ_LINKER_EXTRACT putenv("MOZ_LINKER_EXTRACT=1"); // Ensure that the cache dir is world-writable From 4b45dc245b374db6c336b98b637ec1b0972b9a20 Mon Sep 17 00:00:00 2001 From: Lucas Rocha Date: Thu, 23 Jan 2014 20:27:10 +0000 Subject: [PATCH 11/12] Bug 959219 - Rename 'page' terminology to 'panel' in AboutHomeComponent (r=mcomella) --- .../tests/components/AboutHomeComponent.java | 78 +++++++++---------- .../tests/testAboutHomePageNavigation.java | 64 +++++++-------- .../base/tests/testAboutHomeVisibility.java | 6 +- 3 files changed, 74 insertions(+), 74 deletions(-) diff --git a/mobile/android/base/tests/components/AboutHomeComponent.java b/mobile/android/base/tests/components/AboutHomeComponent.java index 656ae07c4fee..a8243f98d9c8 100644 --- a/mobile/android/base/tests/components/AboutHomeComponent.java +++ b/mobile/android/base/tests/components/AboutHomeComponent.java @@ -32,25 +32,25 @@ public class AboutHomeComponent extends BaseComponent { READING_LIST } - // TODO: Having a specific ordering of pages is prone to fail and thus temporary. + // TODO: Having a specific ordering of panels is prone to fail and thus temporary. // Hopefully the work in bug 940565 will alleviate the need for these enums. - // Explicit ordering of HomePager pages on a phone. - private enum PhonePage { + // Explicit ordering of HomePager panels on a phone. + private enum PhonePanel { HISTORY, TOP_SITES, BOOKMARKS, READING_LIST } - // Explicit ordering of HomePager pages on a tablet. - private enum TabletPage { + // Explicit ordering of HomePager panels on a tablet. + private enum TabletPanel { TOP_SITES, BOOKMARKS, READING_LIST, HISTORY } - // The percentage of the page to swipe between 0 and 1. This value was set through + // The percentage of the panel to swipe between 0 and 1. This value was set through // testing: 0.55f was tested on try and fails on armv6 devices. private static final float SWIPE_PERCENTAGE = 0.70f; @@ -62,12 +62,12 @@ public class AboutHomeComponent extends BaseComponent { return (ViewPager) mSolo.getView(R.id.home_pager); } - public AboutHomeComponent assertCurrentPage(final PanelType expectedPage) { + public AboutHomeComponent assertCurrentPanel(final PanelType expectedPanel) { assertVisible(); - final int expectedPageIndex = getPageIndexForDevice(expectedPage.ordinal()); - assertEquals("The current HomePager page is " + expectedPage, - expectedPageIndex, getHomePagerView().getCurrentItem()); + final int expectedPanelIndex = getPanelIndexForDevice(expectedPanel.ordinal()); + assertEquals("The current HomePager panel is " + expectedPanel, + expectedPanelIndex, getHomePagerView().getCurrentItem()); return this; } @@ -83,46 +83,46 @@ public class AboutHomeComponent extends BaseComponent { return this; } - public AboutHomeComponent swipeToPageOnRight() { - mTestContext.dumpLog(LOGTAG, "Swiping to the page on the right."); - swipeToPage(Solo.RIGHT); + public AboutHomeComponent swipeToPanelOnRight() { + mTestContext.dumpLog(LOGTAG, "Swiping to the panel on the right."); + swipeToPanel(Solo.RIGHT); return this; } - public AboutHomeComponent swipeToPageOnLeft() { - mTestContext.dumpLog(LOGTAG, "Swiping to the page on the left."); - swipeToPage(Solo.LEFT); + public AboutHomeComponent swipeToPanelOnLeft() { + mTestContext.dumpLog(LOGTAG, "Swiping to the panel on the left."); + swipeToPanel(Solo.LEFT); return this; } - private void swipeToPage(final int pageDirection) { - assertTrue("Swiping in a vaild direction", - pageDirection == Solo.LEFT || pageDirection == Solo.RIGHT); + private void swipeToPanel(final int panelDirection) { + assertTrue("Swiping in a valid direction", + panelDirection == Solo.LEFT || panelDirection == Solo.RIGHT); assertVisible(); - final int pageIndex = getHomePagerView().getCurrentItem(); + final int panelIndex = getHomePagerView().getCurrentItem(); - mSolo.scrollViewToSide(getHomePagerView(), pageDirection, SWIPE_PERCENTAGE); + mSolo.scrollViewToSide(getHomePagerView(), panelDirection, SWIPE_PERCENTAGE); - // The page on the left is a lower index and vice versa. - final int unboundedPageIndex = pageIndex + (pageDirection == Solo.LEFT ? -1 : 1); - final int pageCount = DeviceHelper.isTablet() ? - TabletPage.values().length : PhonePage.values().length; - final int maxPageIndex = pageCount - 1; - final int expectedPageIndex = Math.min(Math.max(0, unboundedPageIndex), maxPageIndex); + // The panel on the left is a lower index and vice versa. + final int unboundedPanelIndex = panelIndex + (panelDirection == Solo.LEFT ? -1 : 1); + final int panelCount = DeviceHelper.isTablet() ? + TabletPanel.values().length : PhonePanel.values().length; + final int maxPanelIndex = panelCount - 1; + final int expectedPanelIndex = Math.min(Math.max(0, unboundedPanelIndex), maxPanelIndex); - waitForPageIndex(expectedPageIndex); + waitForPanelIndex(expectedPanelIndex); } - private void waitForPageIndex(final int expectedIndex) { - final String pageName; + private void waitForPanelIndex(final int expectedIndex) { + final String panelName; if (DeviceHelper.isTablet()) { - pageName = TabletPage.values()[expectedIndex].name(); + panelName = TabletPanel.values()[expectedIndex].name(); } else { - pageName = PhonePage.values()[expectedIndex].name(); + panelName = PhonePanel.values()[expectedIndex].name(); } - WaitHelper.waitFor("HomePager " + pageName + " page", new Condition() { + WaitHelper.waitFor("HomePager " + panelName + " panel", new Condition() { @Override public boolean isSatisfied() { return (getHomePagerView().getCurrentItem() == expectedIndex); @@ -131,13 +131,13 @@ public class AboutHomeComponent extends BaseComponent { } /** - * Gets the page index in the device specific Page enum for the given index in the + * Gets the panel index in the device specific Panel enum for the given index in the * PanelType enum. */ - private int getPageIndexForDevice(final int pageIndex) { - final String pageName = PanelType.values()[pageIndex].name(); - final Class devicePageEnum = - DeviceHelper.isTablet() ? TabletPage.class : PhonePage.class; - return Enum.valueOf(devicePageEnum, pageName).ordinal(); + private int getPanelIndexForDevice(final int panelIndex) { + final String panelName = PanelType.values()[panelIndex].name(); + final Class devicePanelEnum = + DeviceHelper.isTablet() ? TabletPanel.class : PhonePanel.class; + return Enum.valueOf(devicePanelEnum, panelName).ordinal(); } } diff --git a/mobile/android/base/tests/testAboutHomePageNavigation.java b/mobile/android/base/tests/testAboutHomePageNavigation.java index d23e60f51111..485a243a0374 100644 --- a/mobile/android/base/tests/testAboutHomePageNavigation.java +++ b/mobile/android/base/tests/testAboutHomePageNavigation.java @@ -6,23 +6,23 @@ import org.mozilla.gecko.tests.components.AboutHomeComponent.PanelType; import org.mozilla.gecko.tests.helpers.*; /** - * Tests functionality related to navigating between the various about:home pages. + * Tests functionality related to navigating between the various about:home panels. */ public class testAboutHomePageNavigation extends UITest { // TODO: Define this test dynamically by creating dynamic representations of the Page - // enum for both phone and tablet, then swiping through the pages. This will also - // benefit having a HomePager with custom pages. + // enum for both phone and tablet, then swiping through the panels. This will also + // benefit having a HomePager with custom panels. public void testAboutHomePageNavigation() { GeckoHelper.blockForReady(); mAboutHome.assertVisible() - .assertCurrentPage(PanelType.TOP_SITES); + .assertCurrentPanel(PanelType.TOP_SITES); - mAboutHome.swipeToPageOnRight(); - mAboutHome.assertCurrentPage(PanelType.BOOKMARKS); + mAboutHome.swipeToPanelOnRight(); + mAboutHome.assertCurrentPanel(PanelType.BOOKMARKS); - mAboutHome.swipeToPageOnRight(); - mAboutHome.assertCurrentPage(PanelType.READING_LIST); + mAboutHome.swipeToPanelOnRight(); + mAboutHome.assertCurrentPanel(PanelType.READING_LIST); // Ideally these helpers would just be their own tests. However, by keeping this within // one method, we're saving test setUp and tearDown resources. @@ -34,47 +34,47 @@ public class testAboutHomePageNavigation extends UITest { } private void helperTestTablet() { - mAboutHome.swipeToPageOnRight(); - mAboutHome.assertCurrentPage(PanelType.HISTORY); + mAboutHome.swipeToPanelOnRight(); + mAboutHome.assertCurrentPanel(PanelType.HISTORY); // Edge case. - mAboutHome.swipeToPageOnRight(); - mAboutHome.assertCurrentPage(PanelType.HISTORY); + mAboutHome.swipeToPanelOnRight(); + mAboutHome.assertCurrentPanel(PanelType.HISTORY); - mAboutHome.swipeToPageOnLeft(); - mAboutHome.assertCurrentPage(PanelType.READING_LIST); + mAboutHome.swipeToPanelOnLeft(); + mAboutHome.assertCurrentPanel(PanelType.READING_LIST); - mAboutHome.swipeToPageOnLeft(); - mAboutHome.assertCurrentPage(PanelType.BOOKMARKS); + mAboutHome.swipeToPanelOnLeft(); + mAboutHome.assertCurrentPanel(PanelType.BOOKMARKS); - mAboutHome.swipeToPageOnLeft(); - mAboutHome.assertCurrentPage(PanelType.TOP_SITES); + mAboutHome.swipeToPanelOnLeft(); + mAboutHome.assertCurrentPanel(PanelType.TOP_SITES); // Edge case. - mAboutHome.swipeToPageOnLeft(); - mAboutHome.assertCurrentPage(PanelType.TOP_SITES); + mAboutHome.swipeToPanelOnLeft(); + mAboutHome.assertCurrentPanel(PanelType.TOP_SITES); } private void helperTestPhone() { // Edge case. - mAboutHome.swipeToPageOnRight(); - mAboutHome.assertCurrentPage(PanelType.READING_LIST); + mAboutHome.swipeToPanelOnRight(); + mAboutHome.assertCurrentPanel(PanelType.READING_LIST); - mAboutHome.swipeToPageOnLeft(); - mAboutHome.assertCurrentPage(PanelType.BOOKMARKS); + mAboutHome.swipeToPanelOnLeft(); + mAboutHome.assertCurrentPanel(PanelType.BOOKMARKS); - mAboutHome.swipeToPageOnLeft(); - mAboutHome.assertCurrentPage(PanelType.TOP_SITES); + mAboutHome.swipeToPanelOnLeft(); + mAboutHome.assertCurrentPanel(PanelType.TOP_SITES); - mAboutHome.swipeToPageOnLeft(); - mAboutHome.assertCurrentPage(PanelType.HISTORY); + mAboutHome.swipeToPanelOnLeft(); + mAboutHome.assertCurrentPanel(PanelType.HISTORY); // Edge case. - mAboutHome.swipeToPageOnLeft(); - mAboutHome.assertCurrentPage(PanelType.HISTORY); + mAboutHome.swipeToPanelOnLeft(); + mAboutHome.assertCurrentPanel(PanelType.HISTORY); - mAboutHome.swipeToPageOnRight(); - mAboutHome.assertCurrentPage(PanelType.TOP_SITES); + mAboutHome.swipeToPanelOnRight(); + mAboutHome.assertCurrentPanel(PanelType.TOP_SITES); } // TODO: bug 943706 - reimplement this old test code. diff --git a/mobile/android/base/tests/testAboutHomeVisibility.java b/mobile/android/base/tests/testAboutHomeVisibility.java index 18db319d0279..021059998d65 100644 --- a/mobile/android/base/tests/testAboutHomeVisibility.java +++ b/mobile/android/base/tests/testAboutHomeVisibility.java @@ -15,7 +15,7 @@ public class testAboutHomeVisibility extends UITest { // Check initial state on about:home. mToolbar.assertTitle(StringHelper.ABOUT_HOME_TITLE); mAboutHome.assertVisible() - .assertCurrentPage(PanelType.TOP_SITES); + .assertCurrentPanel(PanelType.TOP_SITES); // Go to blank 01. NavigationHelper.enterAndLoadUrl(StringHelper.ROBOCOP_BLANK_PAGE_01_URL); @@ -30,7 +30,7 @@ public class testAboutHomeVisibility extends UITest { // Enter editing mode, where the about:home UI should be visible. mToolbar.enterEditingMode(); mAboutHome.assertVisible() - .assertCurrentPage(PanelType.TOP_SITES); + .assertCurrentPanel(PanelType.TOP_SITES); // Dismiss editing mode, where the about:home UI should be gone. mToolbar.dismissEditingMode(); @@ -40,7 +40,7 @@ public class testAboutHomeVisibility extends UITest { NavigationHelper.enterAndLoadUrl(StringHelper.ABOUT_HOME_URL); mToolbar.assertTitle(StringHelper.ABOUT_HOME_TITLE); mAboutHome.assertVisible() - .assertCurrentPage(PanelType.TOP_SITES); + .assertCurrentPanel(PanelType.TOP_SITES); // TODO: Type in a url and assert the go button is visible. } From aa73e193545126645e8e934795a4e963bbdb2ff7 Mon Sep 17 00:00:00 2001 From: Brandon Benvie Date: Wed, 22 Jan 2014 10:21:33 -0800 Subject: [PATCH 12/12] Bug 943681 - Convert to Promise.jsm in the webconsole. r=msucan --- browser/devtools/webconsole/hudservice.js | 4 +-- browser/devtools/webconsole/panel.js | 2 +- .../test/browser_console_dead_objects.js | 6 +++- ...r_webconsole_bug_613642_maintain_scroll.js | 35 ++++++------------- browser/devtools/webconsole/test/head.js | 2 +- browser/devtools/webconsole/webconsole.js | 2 +- 6 files changed, 21 insertions(+), 30 deletions(-) diff --git a/browser/devtools/webconsole/hudservice.js b/browser/devtools/webconsole/hudservice.js index 25c6dbf708be..ac4c88392198 100644 --- a/browser/devtools/webconsole/hudservice.js +++ b/browser/devtools/webconsole/hudservice.js @@ -11,9 +11,9 @@ const {Cc, Ci, Cu} = require("chrome"); let WebConsoleUtils = require("devtools/toolkit/webconsole/utils").Utils; let Heritage = require("sdk/core/heritage"); -loader.lazyGetter(this, "promise", () => require("sdk/core/promise")); loader.lazyGetter(this, "Telemetry", () => require("devtools/shared/telemetry")); loader.lazyGetter(this, "WebConsoleFrame", () => require("devtools/webconsole/webconsole").WebConsoleFrame); +loader.lazyImporter(this, "promise", "resource://gre/modules/Promise.jsm", "Promise"); loader.lazyImporter(this, "gDevTools", "resource:///modules/devtools/gDevTools.jsm"); loader.lazyImporter(this, "devtools", "resource://gre/modules/devtools/Loader.jsm"); loader.lazyImporter(this, "Services", "resource://gre/modules/Services.jsm"); @@ -110,6 +110,7 @@ HUD_SERVICE.prototype = function HS_openBrowserConsole(aTarget, aIframeWindow, aChromeWindow) { let hud = new BrowserConsole(aTarget, aIframeWindow, aChromeWindow); + this._browserConsoleID = hud.hudId; this.consoles.set(hud.hudId, hud); return hud.init(); }, @@ -241,7 +242,6 @@ HUD_SERVICE.prototype = connect().then(getTarget).then(openWindow).then((aWindow) => { this.openBrowserConsole(target, aWindow, aWindow) .then((aBrowserConsole) => { - this._browserConsoleID = aBrowserConsole.hudId; this._browserConsoleDefer.resolve(aBrowserConsole); this._browserConsoleDefer = null; }) diff --git a/browser/devtools/webconsole/panel.js b/browser/devtools/webconsole/panel.js index 48a71f576ec5..466f84834dec 100644 --- a/browser/devtools/webconsole/panel.js +++ b/browser/devtools/webconsole/panel.js @@ -6,7 +6,7 @@ const {Cc, Ci, Cu} = require("chrome"); -loader.lazyGetter(this, "promise", () => require("sdk/core/promise")); +loader.lazyImporter(this, "promise", "resource://gre/modules/Promise.jsm", "Promise"); loader.lazyGetter(this, "HUDService", () => require("devtools/webconsole/hudservice")); loader.lazyGetter(this, "EventEmitter", () => require("devtools/shared/event-emitter")); diff --git a/browser/devtools/webconsole/test/browser_console_dead_objects.js b/browser/devtools/webconsole/test/browser_console_dead_objects.js index 9b61fbd9f706..5cd88262bc3a 100644 --- a/browser/devtools/webconsole/test/browser_console_dead_objects.js +++ b/browser/devtools/webconsole/test/browser_console_dead_objects.js @@ -49,7 +49,10 @@ function test() EventUtils.synthesizeKey(c, {}, hud.iframeWindow); } - hud.jsterm.execute(null, onReadProperty.bind(null, msg)); + hud.jsterm.execute(null, () => { + // executeSoon() is needed to get out of the execute() event loop. + executeSoon(onReadProperty.bind(null, msg)); + }); } function onReadProperty(deadObjectMessage) @@ -69,6 +72,7 @@ function test() function onFetched() { + ok(true, "variables view fetched"); hud.jsterm.execute("delete window.foobarzTezt; 2013-26", onCalcResult); } diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_613642_maintain_scroll.js b/browser/devtools/webconsole/test/browser_webconsole_bug_613642_maintain_scroll.js index 13f018556268..804e071fbf77 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_613642_maintain_scroll.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_613642_maintain_scroll.js @@ -95,37 +95,24 @@ function testGen() { testNext(); }; EventUtils.synthesizeKey("VK_END", {}); - yield; + yield undefined; let oldScrollTop = scrollBox.scrollTop; content.console.log("test message 151"); - waitForMessages({ - webconsole: hud, - messages: [{ - text: "test message 151", - category: CATEGORY_WEBDEV, - severity: SEVERITY_LOG, - }], - }).then(() => { - scrollBox.onscroll = () => { - if (scrollBox.scrollTop == oldScrollTop) { - // Wait for scroll to change. - return; - } - scrollBox.onscroll = null; - isnot(scrollBox.scrollTop, oldScrollTop, "scroll location updated (moved to bottom again)"); - testNext(); - }; - }); + scrollBox.onscroll = () => { + if (scrollBox.scrollTop == oldScrollTop) { + // Wait for scroll to change. + return; + } + scrollBox.onscroll = null; + isnot(scrollBox.scrollTop, oldScrollTop, "scroll location updated (moved to bottom again)"); + hud = testDriver = null; + finishTest(); + }; yield undefined; - - hud = testDriver = null; - finishTest(); - - yield undefined; } function test() { diff --git a/browser/devtools/webconsole/test/head.js b/browser/devtools/webconsole/test/head.js index b60fd08c308d..c90896453f2f 100644 --- a/browser/devtools/webconsole/test/head.js +++ b/browser/devtools/webconsole/test/head.js @@ -6,7 +6,7 @@ let WebConsoleUtils, TargetFactory, require; let {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {}); let {console} = Cu.import("resource://gre/modules/devtools/Console.jsm", {}); -let {Promise: promise} = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {}); +let {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {}); let {Task} = Cu.import("resource://gre/modules/Task.jsm", {}); (() => { diff --git a/browser/devtools/webconsole/webconsole.js b/browser/devtools/webconsole/webconsole.js index 8e4985ff1aa0..c556fa57fab2 100644 --- a/browser/devtools/webconsole/webconsole.js +++ b/browser/devtools/webconsole/webconsole.js @@ -14,7 +14,7 @@ loader.lazyServiceGetter(this, "clipboardHelper", "@mozilla.org/widget/clipboardhelper;1", "nsIClipboardHelper"); loader.lazyImporter(this, "Services", "resource://gre/modules/Services.jsm"); -loader.lazyGetter(this, "promise", () => require("sdk/core/promise")); +loader.lazyImporter(this, "promise", "resource://gre/modules/Promise.jsm", "Promise"); loader.lazyGetter(this, "EventEmitter", () => require("devtools/shared/event-emitter")); loader.lazyGetter(this, "AutocompletePopup", () => require("devtools/shared/autocomplete-popup").AutocompletePopup);