Bug 1331154 - 4. Notify browser.js when a tab gets moved. r?sebastian
Session store will be notified in the next patch.
MozReview-Commit-ID: APTJykdnMF2
--- a/mobile/android/base/java/org/mozilla/gecko/Tabs.java
+++ b/mobile/android/base/java/org/mozilla/gecko/Tabs.java
@@ -1106,27 +1106,29 @@ public class Tabs implements BundleEvent
if (fromPositionHint == toPositionHint) {
return;
}
// The provided position hints index into either all private tabs or all non-private tabs,
// but we need the indices with respect to mOrder, which lists all tabs, both private and
// non-private, in the order in which they were added.
+ // The positions in mOrder of the from and to tabs.
+ final int fromPosition;
+ final int toPosition;
synchronized (this) {
- final int fromPosition;
if (tabPositionCache.mTabId == fromTabId) {
fromPosition = tabPositionCache.mOrderPosition;
} else {
fromPosition = getOrderPositionForTab(fromTabId, fromPositionHint, true);
}
// Start the toPosition search from the mOrder from position.
final int adjustedToPositionHint = fromPosition + (toPositionHint - fromPositionHint);
- final int toPosition = getOrderPositionForTab(toTabId, adjustedToPositionHint, fromPositionHint < toPositionHint);
+ toPosition = getOrderPositionForTab(toTabId, adjustedToPositionHint, fromPositionHint < toPositionHint);
// Remember where the tab was moved to so that if this move continues we'll be ready.
tabPositionCache.cache(fromTabId, toPosition);
if (fromPosition == -1 || toPosition == -1) {
throw new IllegalStateException("Tabs search failed: (" + fromPositionHint + ", " + toPositionHint + ")" +
" --> (" + fromPosition + ", " + toPosition + ")");
}
@@ -1143,16 +1145,23 @@ public class Tabs implements BundleEvent
// and hence no way (short of synchronizing all readers of mOrder) to prevent readers on
// other threads from possibly choosing to start iterating mOrder in between when we
// might mOrder.clear() and then mOrder.addAll(newTabsArray) if we were to repopulate
// mOrder in place.)
mOrder = new CopyOnWriteArrayList<>(newTabsList);
}
queuePersistAllTabs();
+
+ final GeckoBundle data = new GeckoBundle();
+ data.putInt("fromTabId", fromTabId);
+ data.putInt("fromPosition", fromPosition);
+ data.putInt("toTabId", toTabId);
+ data.putInt("toPosition", toPosition);
+ EventDispatcher.getInstance().dispatch("Tab:Move", data);
}
static public void moveTabInList(List<Tab> tabsList, int fromPosition, int toPosition) {
final Tab movedTab = tabsList.get(fromPosition);
final int step = (fromPosition < toPosition) ? 1 : -1;
for (int i = fromPosition; i != toPosition; i += step) {
tabsList.set(i, tabsList.get(i + step));
}
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -380,16 +380,17 @@ var BrowserApp = {
ViewportHandler.init();
Services.androidBridge.browserApp = this;
GlobalEventDispatcher.registerListener(this, [
"Tab:Load",
"Tab:Selected",
"Tab:Closed",
+ "Tab:Move",
"Browser:LoadManifest",
"Session:GetHistory",
"Session:Reload",
]);
Services.obs.addObserver(this, "Locale:OS", false);
Services.obs.addObserver(this, "Locale:Changed", false);
Services.obs.addObserver(this, "Session:Back", false);
@@ -1288,16 +1289,32 @@ var BrowserApp = {
});
}
}
aTab.destroy();
this._tabs.splice(tabIndex, 1);
},
+ _handleTabMove(fromTabId, fromPosition, toTabId, toPosition) {
+ let movedTab = this._tabs[fromPosition];
+ if (movedTab.id != fromTabId || this._tabs[toPosition].id != toTabId) {
+ // The gecko and/or java Tabs tabs lists changed sometime between when the Tabs list was
+ // updated and when news of the update arrived here.
+ throw "Moved tab mismatch: (" + fromTabId + ", " + movedTab.id + "), " +
+ "(" + toTabId + ", " + this._tabs[toPosition].id + ")";
+ }
+
+ let step = (fromPosition < toPosition) ? 1 : -1;
+ for (let i = fromPosition; i != toPosition; i += step) {
+ this._tabs[i] = this._tabs[i + step];
+ }
+ this._tabs[toPosition] = movedTab;
+ },
+
// Use this method to select a tab from JS. This method sends a message
// to Java to select the tab in the Java UI (we'll get a Tab:Selected message
// back from Java when that happens).
selectTab: function selectTab(aTab) {
if (!aTab) {
Cu.reportError("Error trying to select tab (tab doesn't exist)");
return;
}
@@ -1751,16 +1768,20 @@ var BrowserApp = {
case "Tab:Selected":
this._handleTabSelected(this.getTabForId(data.id));
break;
case "Tab:Closed": {
this._handleTabClosed(this.getTabForId(data.tabId), data.showUndoToast);
break;
}
+
+ case "Tab:Move":
+ this._handleTabMove(data.fromTabId, data.fromPosition, data.toTabId, data.toPosition);
+ break;
}
},
observe: function(aSubject, aTopic, aData) {
let browser = this.selectedBrowser;
switch (aTopic) {
case "Session:Back":