Merge "Import revised translations."
diff --git a/src/com/android/browser/AddBookmarkPage.java b/src/com/android/browser/AddBookmarkPage.java
index 32db550..45b1f8b 100644
--- a/src/com/android/browser/AddBookmarkPage.java
+++ b/src/com/android/browser/AddBookmarkPage.java
@@ -759,7 +759,7 @@
             try {
                 final ContentResolver cr = getContentResolver();
                 Bookmarks.addBookmark(AddBookmarkPage.this, false, url,
-                        title, thumbnail, true, mCurrentFolder);
+                        title, thumbnail, mCurrentFolder);
                 if (touchIconUrl != null) {
                     new DownloadTouchIcon(mContext, cr, url).execute(mTouchIconUrl);
                 }
diff --git a/src/com/android/browser/BackgroundHandler.java b/src/com/android/browser/BackgroundHandler.java
new file mode 100644
index 0000000..a0d9243
--- /dev/null
+++ b/src/com/android/browser/BackgroundHandler.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.browser;
+
+import android.os.HandlerThread;
+import android.os.Looper;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+public class BackgroundHandler {
+
+    static HandlerThread sLooperThread;
+    static ExecutorService mThreadPool;
+
+    static {
+        sLooperThread = new HandlerThread("BackgroundHandler", HandlerThread.MIN_PRIORITY);
+        sLooperThread.start();
+        mThreadPool = Executors.newCachedThreadPool();
+    }
+
+    public static void execute(Runnable runnable) {
+        mThreadPool.execute(runnable);
+    }
+
+    public static Looper getLooper() {
+        return sLooperThread.getLooper();
+    }
+
+    private BackgroundHandler() {}
+}
diff --git a/src/com/android/browser/Bookmarks.java b/src/com/android/browser/Bookmarks.java
index bd3b872..190ff9d 100644
--- a/src/com/android/browser/Bookmarks.java
+++ b/src/com/android/browser/Bookmarks.java
@@ -67,7 +67,7 @@
      *  @param parent ID of the parent folder.
      */
     /* package */ static void addBookmark(Context context, boolean showToast, String url,
-            String name, Bitmap thumbnail, boolean retainIcon, long parent) {
+            String name, Bitmap thumbnail, long parent) {
         // Want to append to the beginning of the list
         ContentValues values = new ContentValues();
         try {
@@ -82,9 +82,6 @@
         } catch (IllegalStateException e) {
             Log.e(LOGTAG, "addBookmark", e);
         }
-        if (retainIcon) {
-            WebIconDatabase.getInstance().retainIconForPageUrl(url);
-        }
         if (showToast) {
             Toast.makeText(context, R.string.added_to_bookmarks,
                     Toast.LENGTH_LONG).show();
diff --git a/src/com/android/browser/Browser.java b/src/com/android/browser/Browser.java
index c4412e2..76aaa0b 100644
--- a/src/com/android/browser/Browser.java
+++ b/src/com/android/browser/Browser.java
@@ -17,13 +17,9 @@
 package com.android.browser;
 
 import android.app.Application;
-import android.content.Intent;
-import android.os.AsyncTask;
 import android.util.Log;
 import android.webkit.CookieSyncManager;
 
-import dalvik.system.VMRuntime;
-
 public class Browser extends Application { 
 
     private final static String LOGTAG = "browser";
@@ -37,15 +33,6 @@
     // Set to true to enable extra debug logging.
     final static boolean LOGD_ENABLED = true;
 
-    /**
-     * Specifies a heap utilization ratio that works better
-     * for the browser than the default ratio does.
-     */
-    private final static float TARGET_HEAP_UTILIZATION = 0.75f;
-
-    public Browser() {
-    }
-
     @Override
     public void onCreate() {
         super.onCreate();
@@ -53,20 +40,11 @@
         if (LOGV_ENABLED)
             Log.v(LOGTAG, "Browser.onCreate: this=" + this);
 
-        // Fix AsyncTask to use multiple threads
-        AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
-        // Fix heap utilization for better heap size characteristics.
-        VMRuntime.getRuntime().setTargetHeapUtilization(
-                TARGET_HEAP_UTILIZATION);
         // create CookieSyncManager with current Context
         CookieSyncManager.createInstance(this);
         BrowserSettings.initialize(getApplicationContext());
         Preloader.initialize(getApplicationContext());
     }
 
-    static Intent createBrowserViewIntent() {
-        Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
-        return intent;
-    }
 }
 
diff --git a/src/com/android/browser/BrowserHistoryPage.java b/src/com/android/browser/BrowserHistoryPage.java
index 5d106ce..942a8fd 100644
--- a/src/com/android/browser/BrowserHistoryPage.java
+++ b/src/com/android/browser/BrowserHistoryPage.java
@@ -33,7 +33,6 @@
 import android.content.pm.ResolveInfo;
 import android.database.Cursor;
 import android.database.DataSetObserver;
-import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
@@ -50,7 +49,6 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewStub;
-import android.webkit.WebIconDatabase.IconListener;
 import android.widget.AbsListView;
 import android.widget.AdapterView;
 import android.widget.AdapterView.AdapterContextMenuInfo;
@@ -86,16 +84,6 @@
     private FragmentBreadCrumbs mFragmentBreadCrumbs;
     private ExpandableListView mHistoryList;
 
-    // Implementation of WebIconDatabase.IconListener
-    class IconReceiver implements IconListener {
-        @Override
-        public void onReceivedIcon(String url, Bitmap icon) {
-            mAdapter.notifyDataSetChanged();
-        }
-    }
-
-    // Instance of IconReceiver
-    final IconReceiver mIconReceiver = new IconReceiver();
     private View mRoot;
 
     static interface HistoryQuery {
@@ -238,8 +226,6 @@
         getLoaderManager().restartLoader(LOADER_HISTORY, null, this);
         getLoaderManager().restartLoader(LOADER_MOST_VISITED, null, this);
 
-        // Register to receive icons in case they haven't all been loaded.
-        CombinedBookmarkHistoryView.getIconListenerSet().addListener(mIconReceiver);
         return mRoot;
     }
 
@@ -300,7 +286,6 @@
     @Override
     public void onDestroy() {
         super.onDestroy();
-        CombinedBookmarkHistoryView.getIconListenerSet().removeListener(mIconReceiver);
         getLoaderManager().destroyLoader(LOADER_HISTORY);
         getLoaderManager().destroyLoader(LOADER_MOST_VISITED);
     }
diff --git a/src/com/android/browser/BrowserSettings.java b/src/com/android/browser/BrowserSettings.java
index 2023ee6..8461d30 100644
--- a/src/com/android/browser/BrowserSettings.java
+++ b/src/com/android/browser/BrowserSettings.java
@@ -22,7 +22,6 @@
 import android.content.SharedPreferences;
 import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
 import android.os.Build;
-import android.os.Looper;
 import android.os.Message;
 import android.preference.PreferenceManager;
 import android.provider.Browser;
@@ -104,10 +103,6 @@
     private AutofillHandler mAutofillHandler;
     private WeakHashMap<WebSettings, String> mCustomUserAgents;
     private static boolean sInitialized = false;
-    // Looper shared between some lightweight background operations
-    // Specifically, this is created on the thread that initializes browser settings
-    // and is then reused by CrashRecoveryHandler
-    private Looper mBackgroundLooper;
 
     // Cached values
     private int mPageCacheCapacity = 1;
@@ -134,7 +129,7 @@
         mCustomUserAgents = new WeakHashMap<WebSettings, String>();
         mPrefs.registerOnSharedPreferenceChangeListener(this);
         mAutofillHandler.asyncLoadFromDb();
-        new Thread(mSetupAndLoop, "BackgroundLooper").start();
+        BackgroundHandler.execute(mSetup);
     }
 
     public void setController(Controller controller) {
@@ -146,11 +141,6 @@
         }
     }
 
-    public Looper getBackgroundLooper() {
-        requireInitialization();
-        return mBackgroundLooper;
-    }
-
     public void startManagingSettings(WebSettings settings) {
         synchronized (mManagedSettings) {
             syncStaticSettings(settings);
@@ -159,7 +149,7 @@
         }
     }
 
-    private Runnable mSetupAndLoop = new Runnable() {
+    private Runnable mSetup = new Runnable() {
 
         @Override
         public void run() {
@@ -208,13 +198,10 @@
                     BrowserProvider.getClientId(mContext.getContentResolver()));
             }
 
-            Looper.prepare();
-            mBackgroundLooper = Looper.myLooper();
             synchronized (BrowserSettings.class) {
                 sInitialized = true;
                 BrowserSettings.class.notifyAll();
             }
-            Looper.loop();
         }
     };
 
@@ -525,6 +512,10 @@
         return (percent - 100) / TEXT_ZOOM_STEP + TEXT_ZOOM_START_VAL;
     }
 
+    public SharedPreferences getPreferences() {
+        return mPrefs;
+    }
+
     // -----------------------------
     // getter/setters for accessibility_preferences.xml
     // -----------------------------
diff --git a/src/com/android/browser/CombinedBookmarkHistoryView.java b/src/com/android/browser/CombinedBookmarkHistoryView.java
index 191368f..7903709 100644
--- a/src/com/android/browser/CombinedBookmarkHistoryView.java
+++ b/src/com/android/browser/CombinedBookmarkHistoryView.java
@@ -26,16 +26,13 @@
 import android.content.res.Configuration;
 import android.database.Cursor;
 import android.graphics.Bitmap;
-import android.os.AsyncTask;
 import android.os.Bundle;
-import android.provider.Browser;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.View.OnTouchListener;
 import android.view.ViewGroup;
-import android.webkit.WebIconDatabase;
 import android.webkit.WebIconDatabase.IconListener;
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
@@ -137,21 +134,6 @@
         // Start up the default fragment
         initFragments(mExtras);
 
-        // XXX: Must do this before launching the AsyncTask to avoid a
-        // potential crash if the icon database has not been created.
-        WebIconDatabase.getInstance();
-
-        // Do this every time the view is created in case a new favicon was
-        // added to the webkit db.
-        (new AsyncTask<Void, Void, Void>() {
-            @Override
-            public Void doInBackground(Void... v) {
-                Browser.requestAllIcons(mActivity.getContentResolver(),
-                        Browser.BookmarkColumns.FAVICON + " is NULL", getIconListenerSet());
-                return null;
-            }
-        }).execute();
-
         setupActionBar(startingView);
     }
 
diff --git a/src/com/android/browser/Controller.java b/src/com/android/browser/Controller.java
index cf5df9e..92682c1 100644
--- a/src/com/android/browser/Controller.java
+++ b/src/com/android/browser/Controller.java
@@ -260,7 +260,7 @@
                 new SystemAllowGeolocationOrigins(mActivity.getApplicationContext());
         mSystemAllowGeolocationOrigins.start();
 
-        retainIconsOnStartup();
+        openIconDatabase();
         mSimulateActionBarOverlayMode = !BrowserActivity.isTablet(mActivity);
     }
 
@@ -418,43 +418,17 @@
         return mTabControl.getTabs();
     }
 
-    // Open the icon database and retain all the icons for visited sites.
-    // This is done on a background thread so as not to stall startup.
-    private void retainIconsOnStartup() {
-        // WebIconDatabase needs to be retrieved on the UI thread so that if
-        // it has not been created successfully yet the Handler is started on the
-        // UI thread.
-        new RetainIconsOnStartupTask(WebIconDatabase.getInstance()).execute();
-    }
+    // Open the icon database.
+    private void openIconDatabase() {
+        // We have to call getInstance on the UI thread
+        final WebIconDatabase instance = WebIconDatabase.getInstance();
+        BackgroundHandler.execute(new Runnable() {
 
-    private class RetainIconsOnStartupTask extends AsyncTask<Void, Void, Void> {
-        private WebIconDatabase mDb;
-
-        public RetainIconsOnStartupTask(WebIconDatabase db) {
-            mDb = db;
-        }
-
-        @Override
-        protected Void doInBackground(Void... unused) {
-            mDb.open(mActivity.getDir("icons", 0).getPath());
-            Cursor c = null;
-            try {
-                c = Browser.getAllBookmarks(mActivity.getContentResolver());
-                if (c.moveToFirst()) {
-                    int urlIndex = c.getColumnIndex(Browser.BookmarkColumns.URL);
-                    do {
-                        String url = c.getString(urlIndex);
-                        mDb.retainIconForPageUrl(url);
-                    } while (c.moveToNext());
-                }
-            } catch (IllegalStateException e) {
-                Log.e(LOGTAG, "retainIconsOnStartup", e);
-            } finally {
-                if (c != null) c.close();
+            @Override
+            public void run() {
+                instance.open(mActivity.getDir("icons", 0).getPath());
             }
-
-            return null;
-        }
+        });
     }
 
     private void startHandler() {
@@ -941,7 +915,6 @@
             return;
         }
         DataController.getInstance(mActivity).updateVisitedHistory(url);
-        WebIconDatabase.getInstance().retainIconForPageUrl(url);
         if (!mActivityPaused) {
             // Since we clear the state in onPause, don't backup the current
             // state if we are already paused
diff --git a/src/com/android/browser/CrashRecoveryHandler.java b/src/com/android/browser/CrashRecoveryHandler.java
index c43de34..02636c0 100644
--- a/src/com/android/browser/CrashRecoveryHandler.java
+++ b/src/com/android/browser/CrashRecoveryHandler.java
@@ -25,7 +25,6 @@
 import android.content.SharedPreferences;
 import android.os.Bundle;
 import android.os.Handler;
-import android.os.Looper;
 import android.os.Message;
 import android.os.Parcel;
 import android.util.Log;
@@ -84,8 +83,7 @@
         mController = controller;
         mContext = mController.getActivity().getApplicationContext();
         mForegroundHandler = new Handler();
-        Looper looper = BrowserSettings.getInstance().getBackgroundLooper();
-        mBackgroundHandler = new Handler(looper) {
+        mBackgroundHandler = new Handler(BackgroundHandler.getLooper()) {
 
             @Override
             public void handleMessage(Message msg) {
diff --git a/src/com/android/browser/SystemAllowGeolocationOrigins.java b/src/com/android/browser/SystemAllowGeolocationOrigins.java
index b53611f..a01541f 100644
--- a/src/com/android/browser/SystemAllowGeolocationOrigins.java
+++ b/src/com/android/browser/SystemAllowGeolocationOrigins.java
@@ -73,49 +73,48 @@
     }
 
     void maybeApplySettingAsync() {
-        new AsyncTask<Void,Void,Void>() {
-            @Override
-            protected Void doInBackground(Void... params) {
-                maybeApplySetting();
-                return null;
-            }
-        }.execute();
+        BackgroundHandler.execute(mMaybeApplySetting);
     }
 
     /**
      * Checks to see if the system setting has changed and if so,
      * updates the Geolocation permissions accordingly.
      */
-    private void maybeApplySetting() {
-        // Get the new value
-        String newSetting = getSystemSetting();
+    private Runnable mMaybeApplySetting = new Runnable() {
 
-        // Get the last read value
-        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mContext);
-        String lastReadSetting =
-                preferences.getString(LAST_READ_ALLOW_GEOLOCATION_ORIGINS, "");
+        @Override
+        public void run() {
+         // Get the new value
+            String newSetting = getSystemSetting();
 
-        // If the new value is the same as the last one we read, we're done.
-        if (TextUtils.equals(lastReadSetting, newSetting)) {
-            return;
+            // Get the last read value
+            SharedPreferences preferences = BrowserSettings.getInstance()
+                    .getPreferences();
+            String lastReadSetting =
+                    preferences.getString(LAST_READ_ALLOW_GEOLOCATION_ORIGINS, "");
+
+            // If the new value is the same as the last one we read, we're done.
+            if (TextUtils.equals(lastReadSetting, newSetting)) {
+                return;
+            }
+
+            // Save the new value as the last read value
+            preferences.edit()
+                    .putString(LAST_READ_ALLOW_GEOLOCATION_ORIGINS, newSetting)
+                    .apply();
+
+            Set<String> oldOrigins = parseAllowGeolocationOrigins(lastReadSetting);
+            Set<String> newOrigins = parseAllowGeolocationOrigins(newSetting);
+            Set<String> addedOrigins = setMinus(newOrigins, oldOrigins);
+            Set<String> removedOrigins = setMinus(oldOrigins, newOrigins);
+
+            // Remove the origins in the last read value
+            removeOrigins(removedOrigins);
+
+            // Add the origins in the new value
+            addOrigins(addedOrigins);
         }
-
-        // Save the new value as the last read value
-        preferences.edit()
-                .putString(LAST_READ_ALLOW_GEOLOCATION_ORIGINS, newSetting)
-                .apply();
-
-        Set<String> oldOrigins = parseAllowGeolocationOrigins(lastReadSetting);
-        Set<String> newOrigins = parseAllowGeolocationOrigins(newSetting);
-        Set<String> addedOrigins = setMinus(newOrigins, oldOrigins);
-        Set<String> removedOrigins = setMinus(oldOrigins, newOrigins);
-
-        // Remove the origins in the last read value
-        removeOrigins(removedOrigins);
-
-        // Add the origins in the new value
-        addOrigins(addedOrigins);
-    }
+    };
 
     /**
      * Parses the value of the default geolocation permissions setting.
diff --git a/src/com/android/browser/TabControl.java b/src/com/android/browser/TabControl.java
index 6473c88..7055ef3 100644
--- a/src/com/android/browser/TabControl.java
+++ b/src/com/android/browser/TabControl.java
@@ -155,7 +155,7 @@
     }
 
     boolean canCreateNewTab() {
-        return mMaxTabs != mTabs.size();
+        return mMaxTabs > mTabs.size();
     }
 
     /**
@@ -186,11 +186,10 @@
      *         number of open tabs.
      */
     Tab createNewTab(boolean privateBrowsing) {
-        int size = mTabs.size();
-        // Return false if we have maxed out on tabs
-        if (mMaxTabs == size) {
+        if (!canCreateNewTab()) {
             return null;
         }
+
         final WebView w = createNewWebView(privateBrowsing);
 
         // Create a new tab and add it to the tab list
diff --git a/src/com/android/browser/view/PieMenu.java b/src/com/android/browser/view/PieMenu.java
index cded435..99750f9 100644
--- a/src/com/android/browser/view/PieMenu.java
+++ b/src/com/android/browser/view/PieMenu.java
@@ -310,7 +310,6 @@
         float x = evt.getX();
         float y = evt.getY();
         int action = evt.getActionMasked();
-        int edges = evt.getEdgeFlags();
         if (MotionEvent.ACTION_DOWN == action) {
             if ((x > getWidth() - mSlop) || (x < mSlop)) {
                 setCenter((int) x, (int) y);