This commit is contained in:
Wes Kocher 2014-01-23 18:31:45 -08:00
Родитель 3f3b90ac89 a50fa9df10
Коммит 85b8bb0ff9
22 изменённых файлов: 245 добавлений и 164 удалений

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

@ -218,6 +218,7 @@
hidden="true"
noautofocus="true"
noautohide="true"
flip="none"
consumeoutsideclicks="false">
<box id="UITourHighlight"></box>
</panel>

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

@ -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;
})

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

@ -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"));

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

@ -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);
}

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

@ -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() {

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

@ -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", {});
(() => {

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

@ -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);

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

@ -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;

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

@ -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

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

@ -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<Integer,Sample[]> mSamples = new HashMap<Integer,Sample[]>();
private SparseArray<Sample[]> mSamples = new SparseArray<Sample[]>();
private int mSamplePos;
public SamplingThread(final int aInterval, final int aSampleCount) {

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

@ -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<Integer, PrefHandler> sCallbacks = new HashMap<Integer, PrefHandler>();
private static final SparseArray<PrefHandler> sCallbacks = new SparseArray<PrefHandler>();
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;

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

@ -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<Integer, LoadFaviconTask> sLoadTasks = Collections.synchronizedMap(new HashMap<Integer, LoadFaviconTask>());
private static final SparseArray<LoadFaviconTask> sLoadTasks = new SparseArray<LoadFaviconTask>();
// 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<Integer> taskIds = sLoadTasks.keySet();
Iterator<Integer> 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);
}
}
/**

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

@ -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<Bitmap> {
int minimumMaximum = Integer.MAX_VALUE;
// Used to track the best entry for each size. The entries we want to keep.
HashMap<Integer, IconDirectoryEntry> preferenceMap = new HashMap<Integer, IconDirectoryEntry>();
SparseArray<IconDirectoryEntry> preferenceArray = new SparseArray<IconDirectoryEntry>();
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<Bitmap> {
}
// 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<IconDirectoryEntry> 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;

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

@ -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<Integer, RequestCallback> sCallbacks = new HashMap<Integer, RequestCallback>();
private static final SparseArray<RequestCallback> sCallbacks = new SparseArray<RequestCallback>();
/**
* 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);
}
}

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

@ -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

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

@ -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();
}
}

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

@ -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.

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

@ -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.
}

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

@ -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<Integer, ActivityResultHandler> mMap = new HashMap<Integer, ActivityResultHandler>();
private SparseArray<ActivityResultHandler> mMap = new SparseArray<ActivityResultHandler>();
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;
}
}

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

@ -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);

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

@ -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

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

@ -155,13 +155,14 @@
</menu>
</menubar>
<browser type="content-primary" id="content" flex="1" context="contentAreaContextMenu" />
<browser type="content-primary" id="content" flex="1" context="contentAreaContextMenu" tooltip="contentAreaTooltip" />
<popupset>
<menupopup id="contentAreaContextMenu" pagemenu="start"
onpopupshowing="return showContextMenu(event, this)"
onpopuphiding="hideContextMenu(event, this)">
</menupopup>
<tooltip id="contentAreaTooltip" page="true" />
</popupset>
</window>