From 653da06f63b4f59c7ea07cefb9b21a6ffe1a651d Mon Sep 17 00:00:00 2001 From: Jamie Hewland Date: Sun, 19 May 2013 14:18:49 -0700 Subject: [PATCH] Bug 849072 - Persist tab state with a delayed de-bounced background handler callback. r=rnewman,nalexander --- mobile/android/base/Tabs.java | 53 ++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/mobile/android/base/Tabs.java b/mobile/android/base/Tabs.java index 372a2e2e7f9..d09c267ac62 100644 --- a/mobile/android/base/Tabs.java +++ b/mobile/android/base/Tabs.java @@ -19,6 +19,7 @@ import android.content.ContentResolver; import android.database.ContentObserver; import android.graphics.Color; import android.net.Uri; +import android.os.Handler; import android.util.Log; import java.util.ArrayList; @@ -57,9 +58,7 @@ public class Tabs implements GeckoEventListener { public static final int LOADURL_DESKTOP = 32; public static final int LOADURL_BACKGROUND = 64; - private static final int SCORE_INCREMENT_TAB_LOCATION_CHANGE = 5; - private static final int SCORE_INCREMENT_TAB_SELECTED = 10; - private static final int SCORE_THRESHOLD = 30; + private static final long PERSIST_TABS_AFTER_MILLISECONDS = 1000 * 5; private static AtomicInteger sTabId = new AtomicInteger(0); private volatile boolean mInitialTabsAdded; @@ -67,6 +66,16 @@ public class Tabs implements GeckoEventListener { private GeckoApp mActivity; private ContentObserver mContentObserver; + private final Runnable mPersistTabsRunnable = new Runnable() { + @Override + public void run() { + boolean syncIsSetup = SyncAccounts.syncAccountsExist(getActivity()); + if (syncIsSetup) { + TabsAccessor.persistLocalTabs(getContentResolver(), getTabsInOrder()); + } + } + }; + private Tabs() { registerEventListener("Session:RestoreEnd"); registerEventListener("SessionHistory:New"); @@ -122,6 +131,8 @@ public class Tabs implements GeckoEventListener { // requires us to keep it around (see // https://bugzilla.mozilla.org/show_bug.cgi?id=844407). public synchronized void detachFromActivity(GeckoApp activity) { + ThreadUtils.getBackgroundHandler().removeCallbacks(mPersistTabsRunnable); + if (mContentObserver != null) { BrowserDB.unregisterContentObserver(getContentResolver(), mContentObserver); } @@ -545,44 +556,40 @@ public class Tabs implements GeckoEventListener { private void onTabChanged(Tab tab, Tabs.TabEvents msg, Object data) { switch (msg) { case LOCATION_CHANGE: - mScore += SCORE_INCREMENT_TAB_LOCATION_CHANGE; + queuePersistAllTabs(); break; case RESTORED: mInitialTabsAdded = true; break; // When one tab is deselected, another one is always selected, so only - // increment the score once. When tabs are added/closed, they are also - // selected/unselected, so it would be redundant to also listen + // queue a single persist operation. When tabs are added/closed, they + // are also selected/unselected, so it would be redundant to also listen // for ADDED/CLOSED events. case SELECTED: - mScore += SCORE_INCREMENT_TAB_SELECTED; + queuePersistAllTabs(); case UNSELECTED: tab.onChange(); break; default: break; } - - if (mScore > SCORE_THRESHOLD) { - persistAllTabs(); - mScore = 0; - } } // This method persists the current ordered list of tabs in our tabs content provider. public void persistAllTabs() { - final GeckoApp activity = getActivity(); - final Iterable tabs = getTabsInOrder(); - ThreadUtils.postToBackgroundThread(new Runnable() { - @Override - public void run() { - boolean syncIsSetup = SyncAccounts.syncAccountsExist(activity); - if (syncIsSetup) { - TabsAccessor.persistLocalTabs(getContentResolver(), tabs); - } - } - }); + ThreadUtils.postToBackgroundThread(mPersistTabsRunnable); + } + + /** + * Queues a request to persist tabs after PERSIST_TABS_AFTER_MILLISECONDS + * milliseconds have elapsed. If any existing requests are already queued then + * those requests are removed. + */ + private void queuePersistAllTabs() { + Handler backgroundHandler = ThreadUtils.getBackgroundHandler(); + backgroundHandler.removeCallbacks(mPersistTabsRunnable); + backgroundHandler.postDelayed(mPersistTabsRunnable, PERSIST_TABS_AFTER_MILLISECONDS); } private void registerEventListener(String event) {