Bug 804434 - Make Tabs.notifyListeners() run on UI thread. r=mfinkle
authorBrian Nicholson <bnicholson@mozilla.com>
Thu, 25 Oct 2012 09:57:06 -0700
changeset 111548 6ffa6c2557aef0e8909ff806544e41e5943b7a31
parent 111547 91698ac90375c09dd96e1bcf4bf78251156d9266
child 111549 19db20165eb1ae75b682d79bc8ac5afedfe40b8a
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersmfinkle
bugs804434
milestone19.0a1
Bug 804434 - Make Tabs.notifyListeners() run on UI thread. r=mfinkle
mobile/android/base/GeckoApp.java
mobile/android/base/Tab.java
mobile/android/base/Tabs.java
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -801,21 +801,17 @@ abstract public class GeckoApp
     }
 
     void handleLoadError(final int tabId, final String uri, final String title) {
         final Tab tab = Tabs.getInstance().getTab(tabId);
         if (tab == null)
             return;
 
         // When a load error occurs, the URLBar can get corrupt so we reset it
-        mMainHandler.post(new Runnable() {
-            public void run() {
-                Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.LOAD_ERROR);
-            }
-        });
+        Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.LOAD_ERROR);
     }
 
     void handlePageShow(final int tabId) { }
 
     void handleClearHistory() {
         BrowserDB.clearHistory(getContentResolver());
         getFavicons().clearFavicons();
     }
@@ -1182,35 +1178,27 @@ abstract public class GeckoApp
         if (tab == null)
             return;
 
         tab.setState(shouldShowProgress(uri) ? Tab.STATE_SUCCESS : Tab.STATE_LOADING);
         tab.updateIdentityData(null);
         tab.setReaderEnabled(false);
         if (Tabs.getInstance().isSelectedTab(tab))
             mLayerView.getRenderer().resetCheckerboard();
-        mMainHandler.post(new Runnable() {
-            public void run() {
-                Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.START, showProgress);
-            }
-        });
+        Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.START, showProgress);
     }
 
     void handleDocumentStop(int tabId, boolean success) {
         final Tab tab = Tabs.getInstance().getTab(tabId);
         if (tab == null)
             return;
 
         tab.setState(success ? Tab.STATE_SUCCESS : Tab.STATE_ERROR);
 
-        mMainHandler.post(new Runnable() {
-            public void run() {
-                Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.STOP);
-            }
-        });
+        Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.STOP);
 
         final String oldURL = tab.getURL();
         GeckoAppShell.getHandler().postDelayed(new Runnable() {
             public void run() {
                 // tab.getURL() may return null
                 if (!TextUtils.equals(oldURL, tab.getURL()))
                     return;
 
@@ -1245,21 +1233,17 @@ abstract public class GeckoApp
         });
     }
 
     void handleContentLoaded(int tabId) {
         final Tab tab = Tabs.getInstance().getTab(tabId);
         if (tab == null)
             return;
 
-        mMainHandler.post(new Runnable() {
-            public void run() {
-                Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.LOADED);
-            }
-        });
+        Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.LOADED);
     }
 
     void handleTitleChanged(int tabId, String title) {
         final Tab tab = Tabs.getInstance().getTab(tabId);
         if (tab == null)
             return;
 
         tab.updateTitle(title);
--- a/mobile/android/base/Tab.java
+++ b/mobile/android/base/Tab.java
@@ -94,26 +94,27 @@ public class Tab {
         mFaviconLoadId = 0;
         mDocumentURI = "";
         mContentType = "";
         mZoomConstraints = new ZoomConstraints(false);
         mPluginViews = new ArrayList<View>();
         mPluginLayers = new HashMap<Object, Layer>();
         mState = GeckoApp.shouldShowProgress(url) ? STATE_SUCCESS : STATE_LOADING;
         mContentResolver = Tabs.getInstance().getContentResolver();
-        mContentObserver = new ContentObserver(GeckoAppShell.getHandler()) {
+        mContentObserver = new ContentObserver(null) {
             public void onChange(boolean selfChange) {
                 updateBookmark();
             }
         };
         BrowserDB.registerBookmarkObserver(mContentResolver, mContentObserver);
     }
 
     public void onDestroy() {
         BrowserDB.unregisterContentObserver(mContentResolver, mContentObserver);
+        Tabs.getInstance().notifyListeners(this, Tabs.TabEvents.CLOSED);
     }
 
     public int getId() {
         return mId;
     }
 
     public synchronized void onChange() {
         mLastUsed = System.currentTimeMillis();
@@ -170,36 +171,32 @@ public class Tab {
     }
 
     synchronized void freeBuffer() {
         DirectBufferAllocator.free(mThumbnailBuffer);
         mThumbnailBuffer = null;
     }
 
     public void updateThumbnail(final Bitmap b) {
-        final Tab tab = this;
         GeckoAppShell.getHandler().post(new Runnable() {
             public void run() {
                 if (b != null) {
                     try {
                         mThumbnail = new BitmapDrawable(b);
                         if (mState == Tab.STATE_SUCCESS)
                             saveThumbnailToDB();
                     } catch (OutOfMemoryError oom) {
                         Log.e(LOGTAG, "Unable to create/scale bitmap", oom);
                         mThumbnail = null;
                     }
                 } else {
                     mThumbnail = null;
                 }
-                GeckoApp.mAppContext.mMainHandler.post(new Runnable() {
-                    public void run() {
-                        Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.THUMBNAIL);
-                    }
-                });
+
+                Tabs.getInstance().notifyListeners(Tab.this, Tabs.TabEvents.THUMBNAIL);
             }
         });
     }
 
     public synchronized String getFaviconURL() {
         return mFaviconUrl;
     }
 
@@ -260,23 +257,17 @@ public class Tab {
         // Keep the title unchanged while entering reader mode
         if (mEnteringReaderMode)
             return;
 
         mTitle = (title == null ? "" : title);
 
         Log.d(LOGTAG, "Updated title for tab with id: " + mId);
         updateHistory(mUrl, mTitle);
-        final Tab tab = this;
-
-        GeckoAppShell.getMainHandler().post(new Runnable() {
-            public void run() {
-                Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.TITLE);
-            }
-        });
+        Tabs.getInstance().notifyListeners(this, Tabs.TabEvents.TITLE);
     }
 
     protected void addHistory(final String uri) {
         GeckoAppShell.getHandler().post(new Runnable() {
             public void run() {
                 GlobalHistory.getInstance().add(uri);
             }
         });
@@ -355,43 +346,34 @@ public class Tab {
     }
 
     public void updateIdentityData(JSONObject identityData) {
         mIdentityData = identityData;
     }
 
     public void setReaderEnabled(boolean readerEnabled) {
         mReaderEnabled = readerEnabled;
-        GeckoAppShell.getMainHandler().post(new Runnable() {
-            public void run() {
-                Tabs.getInstance().notifyListeners(Tab.this, Tabs.TabEvents.MENU_UPDATED);
-            }
-        });
+        Tabs.getInstance().notifyListeners(this, Tabs.TabEvents.MENU_UPDATED);
     }
 
     private void updateBookmark() {
-        final String url = getURL();
-        if (url == null)
-            return;
+        GeckoAppShell.getHandler().post(new Runnable() {
+            public void run() {
+                final String url = getURL();
+                if (url == null)
+                    return;
 
-        (new GeckoAsyncTask<Void, Void, Void>(GeckoApp.mAppContext, GeckoAppShell.getHandler()) {
-            @Override
-            public Void doInBackground(Void... params) {
                 if (url.equals(getURL())) {
                     mBookmark = BrowserDB.isBookmark(mContentResolver, url);
                     mReadingListItem = BrowserDB.isReadingListItem(mContentResolver, url);
                 }
-                return null;
-            }
 
-            @Override
-            public void onPostExecute(Void result) {
                 Tabs.getInstance().notifyListeners(Tab.this, Tabs.TabEvents.MENU_UPDATED);
             }
-        }).execute();
+        });
     }
 
     public void addBookmark() {
         GeckoAppShell.getHandler().post(new Runnable() {
             public void run() {
                 String url = getURL();
                 if (url == null)
                     return;
@@ -416,38 +398,16 @@ public class Tab {
     public void addToReadingList() {
         if (!mReaderEnabled)
             return;
 
         GeckoEvent e = GeckoEvent.createBroadcastEvent("Reader:Add", String.valueOf(getId()));
         GeckoAppShell.sendEventToGecko(e);
     }
 
-    public void removeFromReadingList() {
-        if (!mReaderEnabled)
-            return;
-
-        GeckoAppShell.getHandler().post(new Runnable() {
-            public void run() {
-                String url = getURL();
-                if (url == null)
-                    return;
-
-                BrowserDB.removeReadingListItemWithURL(mContentResolver, url);
-
-                GeckoApp.mAppContext.mMainHandler.post(new Runnable() {
-                    public void run() {
-                        GeckoEvent e = GeckoEvent.createBroadcastEvent("Reader:Remove", getURL());
-                        GeckoAppShell.sendEventToGecko(e);
-                    }
-                });
-            }
-        });
-    }
-
     public void readerMode() {
         if (!mReaderEnabled)
             return;
 
         mEnteringReaderMode = true;
         Tabs.getInstance().loadUrl(ReaderModeUtils.getAboutReaderForUrl(getURL(), mId, mReadingListItem));
     }
 
@@ -550,21 +510,17 @@ public class Tab {
         clearFavicon();
         updateTitle(null);
         updateIdentityData(null);
         setReaderEnabled(false);
         setZoomConstraints(new ZoomConstraints(true));
         setHasTouchListeners(false);
         setCheckerboardColor(Color.WHITE);
 
-        GeckoApp.mAppContext.mMainHandler.post(new Runnable() {
-            public void run() {
-                Tabs.getInstance().notifyListeners(Tab.this, Tabs.TabEvents.LOCATION_CHANGE, uri);
-            }
-        });
+        Tabs.getInstance().notifyListeners(this, Tabs.TabEvents.LOCATION_CHANGE, uri);
     }
 
     protected void saveThumbnailToDB() {
         try {
             String url = getURL();
             if (url == null)
                 return;
 
--- a/mobile/android/base/Tabs.java
+++ b/mobile/android/base/Tabs.java
@@ -96,21 +96,17 @@ public class Tabs implements GeckoEventL
 
     private Tab addTab(int id, String url, boolean external, int parentId, String title, boolean isPrivate) {
         final Tab tab = isPrivate ? new PrivateTab(id, url, external, parentId, title) :
                                     new Tab(id, url, external, parentId, title);
         mTabs.put(id, tab);
         mOrder.add(tab);
 
         if (!mRestoringSession) {
-            mActivity.runOnUiThread(new Runnable() {
-                public void run() {
-                    notifyListeners(tab, TabEvents.ADDED);
-                }
-            });
+            notifyListeners(tab, TabEvents.ADDED);
         }
 
         Log.i(LOGTAG, "Added a tab with id: " + id);
         return tab;
     }
 
     public void removeTab(int id) {
         if (mTabs.containsKey(id)) {
@@ -194,22 +190,17 @@ public class Tabs implements GeckoEventL
         if (tab == null || nextTab == null)
             return;
 
         selectTab(nextTab.getId());
 
         int tabId = tab.getId();
         removeTab(tabId);
 
-        mActivity.runOnUiThread(new Runnable() { 
-            public void run() {
-                notifyListeners(tab, TabEvents.CLOSED);
-                tab.onDestroy();
-            }
-        });
+        tab.onDestroy();
 
         // Pass a message to Gecko to update tab state in BrowserApp
         GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Tab:Closed", String.valueOf(tabId)));
     }
 
     /** Return the tab that will be selected by default after this one is closed */
     public Tab getNextTab(Tab tab) {
         Tab selectedTab = getSelectedTab();
@@ -292,21 +283,17 @@ public class Tabs implements GeckoEventL
                 Tab tab = getTab(message.getInt("tabID"));
                 if (tab != null) {
                     tab.handleLocationChange(message);
                 }
             } else if (event.equals("Session:RestoreBegin")) {
                 mRestoringSession = true;
             } else if (event.equals("Session:RestoreEnd")) {
                 mRestoringSession = false;
-                mActivity.runOnUiThread(new Runnable() {
-                    public void run() {
-                        notifyListeners(null, TabEvents.RESTORED);
-                    }
-                });
+                notifyListeners(null, TabEvents.RESTORED);
             } else if (event.equals("Reader:Added")) {
                 final boolean success = message.getBoolean("success");
                 final String title = message.getString("title");
                 final String url = message.getString("url");
                 handleReaderAdded(success, title, url);
             } else if (event.equals("Reader:Removed")) {
                 final String url = message.getString("url");
                 handleReaderRemoved(url);
@@ -393,26 +380,30 @@ public class Tabs implements GeckoEventL
         LOCATION_CHANGE,
         MENU_UPDATED
     }
 
     public void notifyListeners(Tab tab, TabEvents msg) {
         notifyListeners(tab, msg, "");
     }
 
-    public void notifyListeners(Tab tab, TabEvents msg, Object data) {
-        onTabChanged(tab, msg, data);
+    public void notifyListeners(final Tab tab, final TabEvents msg, final Object data) {
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                onTabChanged(tab, msg, data);
 
-        if (mTabsChangedListeners == null)
-            return;
+                if (mTabsChangedListeners == null)
+                    return;
 
-        Iterator<OnTabsChangedListener> items = mTabsChangedListeners.iterator();
-        while (items.hasNext()) {
-            items.next().onTabChanged(tab, msg, data);
-        }
+                Iterator<OnTabsChangedListener> items = mTabsChangedListeners.iterator();
+                while (items.hasNext()) {
+                    items.next().onTabChanged(tab, msg, data);
+                }
+            }
+        });
     }
 
     private void onTabChanged(Tab tab, Tabs.TabEvents msg, Object data) {
         switch(msg) {
             case LOCATION_CHANGE:
                 mScore += SCORE_INCREMENT_TAB_LOCATION_CHANGE;
                 break;