Merge "Widget asset cleanup" into honeycomb
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 9771e18..02f94ce 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -254,6 +254,9 @@
     <!-- Context Menu item to save the webpage referred to by this link to the
             SD card (external storage) -->
     <string name="contextmenu_savelink">Save link</string>
+    <!-- Context Menu item to send the url of the selected link to someone else,
+            via Gmail or another app [CHAR LIMIT=50] -->
+    <string name="contextmenu_sharelink">Share link</string>
     <!-- Context Menu item -->
     <string name="contextmenu_copy">Copy</string>
     <!-- Context Menu item to copy the url of the selected link to the
@@ -410,6 +413,8 @@
     <string name="autofill_profile_editor_country">Country:</string>
     <!-- String for the user's phone number in the AutoFill profile editor. [CHAR-LIMIT=32] -->
     <string name="autofill_profile_editor_phone_number">Phone:</string>
+    <!-- String to display in an error tooltip to inform the user the phone number they provided is not valid. [CHAR-LIMIT=32] -->
+    <string name="autofill_profile_editor_phone_number_invalid">Invalid phone number</string>
 
     <!-- Button text to save the AutoFill profile [CHAR-LIMIT=20] -->
     <string name="autofill_profile_editor_save_profile">Save profile</string>
diff --git a/src/com/android/browser/AddBookmarkPage.java b/src/com/android/browser/AddBookmarkPage.java
index a93a518..ee080ca 100644
--- a/src/com/android/browser/AddBookmarkPage.java
+++ b/src/com/android/browser/AddBookmarkPage.java
@@ -105,7 +105,7 @@
     private View mFolderNamerHolder;
     private View mAddNewFolder;
     private View mAddSeparator;
-    private long mCurrentFolder = 0;
+    private long mCurrentFolder;
     private FolderAdapter mAdapter;
     private BreadCrumbView mCrumbs;
     private TextView mFakeTitle;
@@ -218,8 +218,26 @@
             if (mSaveToHomeScreen) {
                 mFolder.setSelectionIgnoringSelectionChange(0);
             } else {
-                // FIXME: Need to find the actual folder.
-                mFolder.setSelectionIgnoringSelectionChange(mEditingFolder ? 0 : 1);
+                if (mCurrentFolder == mRootFolder) {
+                    mFolder.setSelectionIgnoringSelectionChange(mEditingFolder ? 0 : 1);
+                } else {
+                    Object data = mCrumbs.getTopData();
+                    if (data != null && ((Folder) data).Id == mCurrentFolder) {
+                        // We are showing the correct folder heirarchy. The
+                        // folder selector will say "Other folder..."  Change it
+                        // to say the name of the folder once again.
+                        ((TextView) mFolder.getSelectedView()).setText(((Folder) data).Name);
+                    } else {
+                        // We are not be showing the correct folder heirarchy.
+                        // Clear the Crumbs and find the proper folder
+                        mCrumbs.clear();
+                        setupTopCrumb();
+                        LoaderManager manager = getLoaderManager();
+                        manager.restartLoader(LOADER_ID_ALL_FOLDERS, null, this);
+                        manager.restartLoader(LOADER_ID_FOLDER_CONTENTS, null, this);
+
+                    }
+                }
             }
         }
     }
@@ -709,11 +727,7 @@
         if (mCurrentFolder == DEFAULT_FOLDER_ID) {
             mCurrentFolder = mRootFolder;
         }
-        String name = getString(R.string.bookmarks);
-        mTopLevelLabel = (TextView) mCrumbs.pushView(name, false,
-                new Folder(name, mRootFolder));
-        // To better match the other folders.
-        mTopLevelLabel.setCompoundDrawablePadding(6);
+        setupTopCrumb();
         if (mEditingExisting || TextUtils.isEmpty(mOriginalUrl)) {
             onCurrentFolderFound();
         } else {
@@ -724,6 +738,14 @@
         }
     }
 
+    private void setupTopCrumb() {
+        String name = getString(R.string.bookmarks);
+        mTopLevelLabel = (TextView) mCrumbs.pushView(name, false,
+                new Folder(name, mRootFolder));
+        // To better match the other folders.
+        mTopLevelLabel.setCompoundDrawablePadding(6);
+    }
+
     private void onCurrentFolderFound() {
         LoaderManager manager = getLoaderManager();
         if (mCurrentFolder != mRootFolder) {
diff --git a/src/com/android/browser/AutoFillSettingsFragment.java b/src/com/android/browser/AutoFillSettingsFragment.java
index 06a4256..389be1f 100644
--- a/src/com/android/browser/AutoFillSettingsFragment.java
+++ b/src/com/android/browser/AutoFillSettingsFragment.java
@@ -17,14 +17,18 @@
 package com.android.browser;
 
 import android.app.Fragment;
+import android.content.Context;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
+import android.text.Editable;
+import android.text.TextWatcher;
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.View.OnClickListener;
 import android.view.LayoutInflater;
+import android.view.inputmethod.InputMethodManager;
 import android.webkit.WebSettings.AutoFillProfile;
 import android.widget.Button;
 import android.widget.EditText;
@@ -45,6 +49,8 @@
     private EditText mCountryEdit;
     private EditText mPhoneEdit;
 
+    private Button mSaveButton;
+
     // Used to display toast after DB interactions complete.
     private Handler mHandler;
 
@@ -56,6 +62,45 @@
     // dynamically.
     private int mUniqueId = 1;
 
+    private class PhoneNumberValidator implements TextWatcher {
+        // Keep in sync with kPhoneNumberLength in chrome/browser/autofill/phone_number.cc
+        private static final int PHONE_NUMBER_LENGTH = 7;
+
+        public void afterTextChanged(Editable s) {
+            int phoneNumberLength = s.toString().length();
+
+            if (phoneNumberLength > 0 && phoneNumberLength < PHONE_NUMBER_LENGTH) {
+                mPhoneEdit.setError(getResources().getText(
+                        R.string.autofill_profile_editor_phone_number_invalid));
+            } else {
+                mPhoneEdit.setError(null);
+            }
+
+            updateButtonState();
+        }
+
+        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+        }
+
+        public void onTextChanged(CharSequence s, int start, int before, int count) {
+        }
+    }
+
+    private class FieldChangedListener implements TextWatcher {
+        public void afterTextChanged(Editable s) {
+            updateButtonState();
+        }
+
+        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+        }
+
+        public void onTextChanged(CharSequence s, int start, int before, int count) {
+        }
+
+    }
+
+    private TextWatcher mFieldChangedListener = new FieldChangedListener();
+
     public AutoFillSettingsFragment() {
         mHandler = new Handler() {
             @Override
@@ -98,8 +143,19 @@
         mCountryEdit = (EditText)v.findViewById(R.id.autofill_profile_editor_country_edit);
         mPhoneEdit = (EditText)v.findViewById(R.id.autofill_profile_editor_phone_number_edit);
 
-        Button saveButton = (Button)v.findViewById(R.id.autofill_profile_editor_save_button);
-        saveButton.setOnClickListener(new OnClickListener() {
+        mFullNameEdit.addTextChangedListener(mFieldChangedListener);
+        mEmailEdit.addTextChangedListener(mFieldChangedListener);
+        mCompanyEdit.addTextChangedListener(mFieldChangedListener);
+        mAddressLine1Edit.addTextChangedListener(mFieldChangedListener);
+        mAddressLine2Edit.addTextChangedListener(mFieldChangedListener);
+        mCityEdit.addTextChangedListener(mFieldChangedListener);
+        mStateEdit.addTextChangedListener(mFieldChangedListener);
+        mZipEdit.addTextChangedListener(mFieldChangedListener);
+        mCountryEdit.addTextChangedListener(mFieldChangedListener);
+        mPhoneEdit.addTextChangedListener(new PhoneNumberValidator());
+
+        mSaveButton = (Button)v.findViewById(R.id.autofill_profile_editor_save_button);
+        mSaveButton.setOnClickListener(new OnClickListener() {
             public void onClick(View button) {
                 AutoFillProfile newProfile = new AutoFillProfile(
                         mUniqueId,
@@ -116,6 +172,7 @@
 
                 BrowserSettings.getInstance().setAutoFillProfile(getActivity(), newProfile,
                         mHandler.obtainMessage(PROFILE_SAVED_MSG));
+                closeEditor();
             }
         });
 
@@ -138,13 +195,15 @@
                 // trigger the current profile to get deleted from the DB.
                 BrowserSettings.getInstance().setAutoFillProfile(getActivity(), null,
                         mHandler.obtainMessage(PROFILE_DELETED_MSG));
+
+                updateButtonState();
             }
         });
 
-       Button cancelButton = (Button)v.findViewById(R.id.autofill_profile_editor_cancel_button);
-       cancelButton.setOnClickListener(new OnClickListener() {
+        Button cancelButton = (Button)v.findViewById(R.id.autofill_profile_editor_cancel_button);
+        cancelButton.setOnClickListener(new OnClickListener() {
            public void onClick(View button) {
-               getFragmentManager().popBackStack();
+               closeEditor();
            }
         });
 
@@ -163,6 +222,38 @@
             mPhoneEdit.setText(activeProfile.getPhoneNumber());
         }
 
+        updateButtonState();
+
         return v;
     }
+
+    public void updateButtonState() {
+
+        boolean valid = (mFullNameEdit.getText().toString().length() > 0 ||
+            mEmailEdit.getText().toString().length() > 0 ||
+            mCompanyEdit.getText().toString().length() > 0 ||
+            mAddressLine1Edit.getText().toString().length() > 0 ||
+            mAddressLine2Edit.getText().toString().length() > 0 ||
+            mCityEdit.getText().toString().length() > 0 ||
+            mStateEdit.getText().toString().length() > 0 ||
+            mZipEdit.getText().toString().length() > 0 ||
+            mCountryEdit.getText().toString().length() > 0) &&
+            mPhoneEdit.getError() == null;
+
+        // Only enable the save buttons if we have at least one field completed
+        // and the phone number (if present is valid).
+        mSaveButton.setEnabled(valid);
+    }
+
+    private void closeEditor() {
+        // Hide the IME if the user wants to close while an EditText has focus
+        InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(
+                Context.INPUT_METHOD_SERVICE);
+        imm.hideSoftInputFromWindow(getView().getWindowToken(), 0);
+        if (getFragmentManager().getBackStackEntryCount() > 0) {
+            getFragmentManager().popBackStack();
+        } else {
+            getActivity().finish();
+        }
+    }
 }
diff --git a/src/com/android/browser/BaseUi.java b/src/com/android/browser/BaseUi.java
index 5ccfdda..98fc349 100644
--- a/src/com/android/browser/BaseUi.java
+++ b/src/com/android/browser/BaseUi.java
@@ -430,7 +430,9 @@
                         CombinedBookmarkHistoryView.FRAGMENT_ID_HISTORY
                         : CombinedBookmarkHistoryView.FRAGMENT_ID_BOOKMARKS,
                 extras);
-        getEmbeddedTitleBar().setVisibility(View.GONE);
+        FrameLayout wrapper =
+            (FrameLayout) mContentView.findViewById(R.id.webview_wrapper);
+        wrapper.setVisibility(View.GONE);
         hideFakeTitleBar();
         dismissIME();
         if (mActiveTab != null) {
@@ -447,7 +449,9 @@
     public void hideComboView() {
         if (mComboView != null) {
             mContentView.removeView(mComboView);
-            getEmbeddedTitleBar().setVisibility(View.VISIBLE);
+            FrameLayout wrapper =
+                (FrameLayout) mContentView.findViewById(R.id.webview_wrapper);
+            wrapper.setVisibility(View.VISIBLE);
             mComboView = null;
         }
         if (mActiveTab != null) {
diff --git a/src/com/android/browser/BrowserBookmarksPage.java b/src/com/android/browser/BrowserBookmarksPage.java
index 2df0561..dfb0b77 100644
--- a/src/com/android/browser/BrowserBookmarksPage.java
+++ b/src/com/android/browser/BrowserBookmarksPage.java
@@ -647,7 +647,7 @@
     private void copy(CharSequence text) {
         ClipboardManager cm = (ClipboardManager) getActivity().getSystemService(
                 Context.CLIPBOARD_SERVICE);
-        cm.setPrimaryClip(ClipData.newRawUri(null, null, Uri.parse(text.toString())));
+        cm.setPrimaryClip(ClipData.newRawUri(null, Uri.parse(text.toString())));
     }
 
     @Override
diff --git a/src/com/android/browser/BrowserPreferencesPage.java b/src/com/android/browser/BrowserPreferencesPage.java
index 2b42951..dae838f 100644
--- a/src/com/android/browser/BrowserPreferencesPage.java
+++ b/src/com/android/browser/BrowserPreferencesPage.java
@@ -70,7 +70,7 @@
     public boolean onOptionsItemSelected(MenuItem item) {
         switch (item.getItemId()) {
             case android.R.id.home:
-                if (getFragmentManager().countBackStackEntries() > 0) {
+                if (getFragmentManager().getBackStackEntryCount() > 0) {
                     getFragmentManager().popBackStack();
                 } else {
                     finish();
diff --git a/src/com/android/browser/CombinedBookmarkHistoryView.java b/src/com/android/browser/CombinedBookmarkHistoryView.java
index f4b2e9c..5731c37 100644
--- a/src/com/android/browser/CombinedBookmarkHistoryView.java
+++ b/src/com/android/browser/CombinedBookmarkHistoryView.java
@@ -241,7 +241,7 @@
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
         FragmentManager fm = mActivity.getFragmentManager();
-        FragmentTransaction transaction = fm.openTransaction();
+        FragmentTransaction transaction = fm.beginTransaction();
         if (mCurrentFragment == FRAGMENT_ID_BOOKMARKS) {
             transaction.remove(mBookmarks);
         } else if (mCurrentFragment == FRAGMENT_ID_HISTORY) {
diff --git a/src/com/android/browser/GoogleAccountLogin.java b/src/com/android/browser/GoogleAccountLogin.java
index 04b3957..855c407 100644
--- a/src/com/android/browser/GoogleAccountLogin.java
+++ b/src/com/android/browser/GoogleAccountLogin.java
@@ -86,9 +86,17 @@
                 .appendQueryParameter("SID", mSid)
                 .appendQueryParameter("LSID", mLsid)
                 .build().toString();
+        // Check mRunnable to see if the request has been canceled.  Otherwise
+        // we might access a destroyed WebView.
+        String ua = null;
+        synchronized (this) {
+            if (mRunnable == null) {
+                return;
+            }
+            ua = mWebView.getSettings().getUserAgentString();
+        }
         // Intentionally not using Proxy.
-        AndroidHttpClient client = AndroidHttpClient.newInstance(
-                mWebView.getSettings().getUserAgentString());
+        AndroidHttpClient client = AndroidHttpClient.newInstance(ua);
         HttpPost request = new HttpPost(url);
 
         String result = null;
@@ -119,7 +127,15 @@
                 .build().toString();
         mActivity.runOnUiThread(new Runnable() {
             @Override public void run() {
-                mWebView.loadUrl(newUrl);
+                // Check mRunnable in case the request has been canceled.  This
+                // is most likely not necessary as run() is the only non-UI
+                // thread that calls done() but I am paranoid.
+                synchronized (GoogleAccountLogin.this) {
+                    if (mRunnable == null) {
+                        return;
+                    }
+                    mWebView.loadUrl(newUrl);
+                }
             }
         });
     }
diff --git a/src/com/android/browser/IntentHandler.java b/src/com/android/browser/IntentHandler.java
index e4b3201..2a34aba 100644
--- a/src/com/android/browser/IntentHandler.java
+++ b/src/com/android/browser/IntentHandler.java
@@ -178,6 +178,8 @@
                         current.getWebView().dumpRenderTree(true);
                     } else if ("about:debug.display".equals(urlData.mUrl)) {
                         current.getWebView().dumpDisplayTree();
+                    } else if ("about:debug.nav".equals(urlData.mUrl)) {
+                        current.getWebView().debugDump();
                     } else {
                         mSettings.toggleDebugSettings();
                     }
diff --git a/src/com/android/browser/Tab.java b/src/com/android/browser/Tab.java
index 0347ef5..83db214 100644
--- a/src/com/android/browser/Tab.java
+++ b/src/com/android/browser/Tab.java
@@ -16,6 +16,7 @@
 
 package com.android.browser;
 
+import com.android.browser.homepages.HomeProvider;
 import com.android.common.speech.LoggingEvents;
 
 import android.app.Activity;
@@ -50,6 +51,7 @@
 import android.webkit.WebBackForwardListClient;
 import android.webkit.WebChromeClient;
 import android.webkit.WebHistoryItem;
+import android.webkit.WebResourceResponse;
 import android.webkit.WebStorage;
 import android.webkit.WebView;
 import android.webkit.WebViewClient;
@@ -792,6 +794,14 @@
         }
 
         @Override
+        public WebResourceResponse shouldInterceptRequest(WebView view,
+                String url) {
+            WebResourceResponse res = HomeProvider.shouldInterceptRequest(
+                    mActivity, url);
+            return res;
+        }
+
+        @Override
         public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event) {
             if (!mInForeground) {
                 return false;
diff --git a/src/com/android/browser/XLargeUi.java b/src/com/android/browser/XLargeUi.java
index 9b344ec..d50d94e 100644
--- a/src/com/android/browser/XLargeUi.java
+++ b/src/com/android/browser/XLargeUi.java
@@ -20,6 +20,7 @@
 
 import android.app.ActionBar;
 import android.app.Activity;
+import android.os.Bundle;
 import android.util.Log;
 import android.view.ActionMode;
 import android.view.Gravity;
@@ -71,6 +72,14 @@
     }
 
     @Override
+    public void showComboView(boolean startWithHistory, Bundle extras) {
+        super.showComboView(startWithHistory, extras);
+        if (mUseQuickControls) {
+            mActionBar.show();
+        }
+    }
+
+    @Override
     public void hideComboView() {
         super.hideComboView();
         // ComboView changes the action bar, set it back up to what we want
diff --git a/src/com/android/browser/homepages/HomeProvider.java b/src/com/android/browser/homepages/HomeProvider.java
index 5c368eb..98fcfbe 100644
--- a/src/com/android/browser/homepages/HomeProvider.java
+++ b/src/com/android/browser/homepages/HomeProvider.java
@@ -16,15 +16,20 @@
  */

 package com.android.browser.homepages;

 

+import com.android.browser.BrowserSettings;

+

 import android.content.ContentProvider;

 import android.content.ContentValues;

+import android.content.Context;

 import android.content.res.AssetFileDescriptor;

 import android.database.Cursor;

 import android.net.Uri;

 import android.os.ParcelFileDescriptor;

 import android.util.Log;

+import android.webkit.WebResourceResponse;

 

 import java.io.IOException;

+import java.io.InputStream;

 

 public class HomeProvider extends ContentProvider {

 

@@ -78,4 +83,20 @@
         }

     }

 

+    public static WebResourceResponse shouldInterceptRequest(Context context,

+            String url) {

+        try {

+            boolean useMostVisited = BrowserSettings.getInstance().useMostVisitedHomepage();

+            if (useMostVisited && url.startsWith("content://")) {

+                Uri uri = Uri.parse(url);

+                if (AUTHORITY.equals(uri.getAuthority())) {

+                    InputStream ins = context.getContentResolver()

+                            .openInputStream(uri);

+                    return new WebResourceResponse("text/html", "utf-8", ins);

+                }

+            }

+        } catch (Exception e) {}

+        return null;

+    }

+

 }

diff --git a/src/com/android/browser/preferences/GeneralPreferencesFragment.java b/src/com/android/browser/preferences/GeneralPreferencesFragment.java
index 7545ba8..99a4ec9 100644
--- a/src/com/android/browser/preferences/GeneralPreferencesFragment.java
+++ b/src/com/android/browser/preferences/GeneralPreferencesFragment.java
@@ -195,7 +195,7 @@
             frag = new ImportWizardDialog();
         }
         frag.setArguments(preference.getExtras());
-        getFragmentManager().openTransaction()
+        getFragmentManager().beginTransaction()
                 .add(frag, null)
                 .commit();
         return true;