Merge "Remove second url bar"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index c32b76a..8ac2c87 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -35,6 +35,7 @@
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
+ <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS"/>
<uses-permission android:name="com.android.browser.permission.WRITE_HISTORY_BOOKMARKS"/>
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
diff --git a/res/drawable-mdpi/bookmarks_widget_thumb_selector_focused.9.png b/res/drawable-mdpi/bookmarks_widget_thumb_selector_focused.9.png
new file mode 100644
index 0000000..5bcc7c8
--- /dev/null
+++ b/res/drawable-mdpi/bookmarks_widget_thumb_selector_focused.9.png
Binary files differ
diff --git a/res/drawable/bookmark_thumb_selector.xml b/res/drawable/bookmark_thumb_selector.xml
index 59d9405..d4a12a3 100644
--- a/res/drawable/bookmark_thumb_selector.xml
+++ b/res/drawable/bookmark_thumb_selector.xml
@@ -16,6 +16,7 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:exitFadeDuration="@android:integer/config_mediumAnimTime">
+ <item android:state_focused="true" android:state_pressed="false" android:drawable="@drawable/bookmarks_widget_thumb_selector_focused" />
<item android:state_pressed="true" android:drawable="@drawable/bookmark_thumb_selector_transition" />
<item android:drawable="@android:color/transparent" />
</selector>
diff --git a/res/menu-xlarge/browser.xml b/res/menu-xlarge/browser.xml
index 1b52c9a..a791cdd 100644
--- a/res/menu-xlarge/browser.xml
+++ b/res/menu-xlarge/browser.xml
@@ -44,6 +44,8 @@
android:title="@string/menu_preferences"
android:icon="@drawable/ic_settings_holo_dark"
android:alphabeticShortcut="p" />
+ <item android:id="@+id/save_webarchive_menu_id"
+ android:title="@string/menu_save_webarchive" />
<!-- followings are debug only -->
<item android:id="@+id/dump_nav_menu_id"
android:title="@string/dump_nav"
diff --git a/res/menu/browser.xml b/res/menu/browser.xml
index beaa8f3..7a59ffd 100644
--- a/res/menu/browser.xml
+++ b/res/menu/browser.xml
@@ -57,6 +57,8 @@
android:title="@string/menu_preferences"
android:icon="@drawable/ic_settings_holo_dark"
android:alphabeticShortcut="p" />
+ <item android:id="@+id/save_webarchive_menu_id"
+ android:title="@string/menu_save_webarchive" />
<!-- followings are debug only -->
<item android:id="@+id/dump_nav_menu_id"
android:title="@string/dump_nav"
diff --git a/src/com/android/browser/AddBookmarkPage.java b/src/com/android/browser/AddBookmarkPage.java
index 1444862..9a7227c 100644
--- a/src/com/android/browser/AddBookmarkPage.java
+++ b/src/com/android/browser/AddBookmarkPage.java
@@ -73,6 +73,7 @@
// Place on an edited bookmark to remove the saved thumbnail
public static final String REMOVE_THUMBNAIL = "remove_thumbnail";
public static final String USER_AGENT = "user_agent";
+ public static final String CHECK_FOR_DUPE = "check_for_dupe";
/* package */ static final String EXTRA_EDIT_BOOKMARK = "bookmark";
/* package */ static final String EXTRA_IS_FOLDER = "is_folder";
@@ -86,6 +87,8 @@
private final int LOADER_ID_ALL_FOLDERS = 1;
private final int LOADER_ID_FIND_ROOT = 2;
private final int LOADER_ID_CHECK_FOR_DUPE = 3;
+ private final int LOADER_ID_MOST_RECENTLY_SAVED_BOOKMARK = 4;
+ private final int LOADER_ID_FIND_FOLDER_BY_ID = 5;
private EditText mTitle;
private EditText mAddress;
@@ -117,6 +120,7 @@
private Drawable mHeaderIcon;
private View mRemoveLink;
private View mFakeTitleHolder;
+ private FolderSpinnerAdapter mFolderAdapter;
private static class Folder {
String Name;
long Id;
@@ -308,6 +312,15 @@
case FolderSpinnerAdapter.OTHER_FOLDER:
switchToFolderSelector();
break;
+ case FolderSpinnerAdapter.RECENT_FOLDER:
+ mCurrentFolder = mFolderAdapter.recentFolderId();
+ mSaveToHomeScreen = false;
+ // In case the user decides to select OTHER_FOLDER
+ // and choose a different one, so that we will start from
+ // the correct place.
+ LoaderManager manager = getLoaderManager();
+ manager.initLoader(LOADER_ID_ALL_FOLDERS, null, this);
+ manager.restartLoader(LOADER_ID_FOLDER_CONTENTS, null, this);
default:
break;
}
@@ -412,6 +425,18 @@
selection,
selArgs,
null);
+ case LOADER_ID_FIND_FOLDER_BY_ID:
+ projection = new String[] {
+ BrowserContract.Bookmarks._ID,
+ BrowserContract.Bookmarks.TITLE
+ };
+ return new CursorLoader(this,
+ BrowserContract.Bookmarks.CONTENT_URI,
+ projection,
+ BrowserContract.Bookmarks._ID + " = "
+ + args.getLong(BrowserContract.Bookmarks._ID),
+ null,
+ null);
case LOADER_ID_ALL_FOLDERS:
projection = new String[] {
BrowserContract.Bookmarks._ID,
@@ -442,6 +467,16 @@
where,
null,
BrowserContract.Bookmarks._ID + " ASC");
+ case LOADER_ID_MOST_RECENTLY_SAVED_BOOKMARK:
+ projection = new String[] {
+ BrowserContract.Bookmarks.PARENT
+ };
+ return new CursorLoader(this,
+ BrowserContract.Bookmarks.CONTENT_URI,
+ projection,
+ BrowserContract.Bookmarks.IS_FOLDER + " = 0",
+ null,
+ BrowserContract.Bookmarks.DATE_CREATED + " DESC");
default:
throw new AssertionError("Asking for nonexistant loader!");
}
@@ -484,6 +519,32 @@
case LOADER_ID_FOLDER_CONTENTS:
mAdapter.changeCursor(cursor);
break;
+ case LOADER_ID_MOST_RECENTLY_SAVED_BOOKMARK:
+ LoaderManager manager = getLoaderManager();
+ if (cursor != null && cursor.moveToFirst()) {
+ // Find the parent
+ long lastUsedFolder = cursor.getLong(0);
+ if (lastUsedFolder != mRootFolder
+ && lastUsedFolder != mCurrentFolder
+ && lastUsedFolder != 0) {
+ // Find out the parent's name
+ Bundle b = new Bundle();
+ b.putLong(BrowserContract.Bookmarks._ID, lastUsedFolder);
+ manager.initLoader(LOADER_ID_FIND_FOLDER_BY_ID, b, this);
+ }
+ }
+ manager.destroyLoader(LOADER_ID_MOST_RECENTLY_SAVED_BOOKMARK);
+ break;
+ case LOADER_ID_FIND_FOLDER_BY_ID:
+ if (cursor != null && cursor.moveToFirst()) {
+ long id = cursor.getLong(cursor.getColumnIndexOrThrow(
+ BrowserContract.Bookmarks._ID));
+ String title = cursor.getString(cursor.getColumnIndexOrThrow(
+ BrowserContract.Bookmarks.TITLE));
+ mFolderAdapter.addRecentFolder(id, title);
+ }
+ getLoaderManager().destroyLoader(LOADER_ID_FIND_FOLDER_BY_ID);
+ break;
case LOADER_ID_ALL_FOLDERS:
long parent = mCurrentFolder;
int idIndex = cursor.getColumnIndexOrThrow(
@@ -665,7 +726,8 @@
mCancelButton.setOnClickListener(this);
mFolder = (FolderSpinner) findViewById(R.id.folder);
- mFolder.setAdapter(new FolderSpinnerAdapter(!mEditingFolder));
+ mFolderAdapter = new FolderSpinnerAdapter(!mEditingFolder);
+ mFolder.setAdapter(mFolderAdapter);
mFolder.setOnSetSelectionListener(this);
mDefaultView = findViewById(R.id.default_view);
@@ -728,7 +790,8 @@
mCurrentFolder = mRootFolder;
}
setupTopCrumb();
- if (mEditingExisting || TextUtils.isEmpty(mOriginalUrl)) {
+ if (mEditingExisting || TextUtils.isEmpty(mOriginalUrl)
+ || !(mMap != null && mMap.getBoolean(CHECK_FOR_DUPE))) {
onCurrentFolderFound();
} else {
// User is attempting to bookmark a site, rather than deliberately
@@ -757,6 +820,11 @@
mFolder.setSelectionIgnoringSelectionChange(mEditingFolder ? 1 : 2);
} else {
setShowBookmarkIcon(true);
+ if (!mEditingExisting) {
+ // Find the most recently saved bookmark, so that we can include it in
+ // the list of options to save the current bookmark.
+ manager.initLoader(LOADER_ID_MOST_RECENTLY_SAVED_BOOKMARK, null, this);
+ }
if (!mEditingFolder) {
// Initially the "Bookmarks" folder should be showing, rather than
// the home screen. In the editing folder case, home screen is not
diff --git a/src/com/android/browser/CombinedBookmarkHistoryView.java b/src/com/android/browser/CombinedBookmarkHistoryView.java
index 173abba..686e646 100644
--- a/src/com/android/browser/CombinedBookmarkHistoryView.java
+++ b/src/com/android/browser/CombinedBookmarkHistoryView.java
@@ -324,7 +324,7 @@
mUiController.onUrlSelected(settings.getHomePage(), false);
return true;
case R.id.add_bookmark:
- mUiController.bookmarkCurrentPage(mBookmarks.getFolderId());
+ mUiController.bookmarkCurrentPage(mBookmarks.getFolderId(), false);
return true;
case R.id.preferences_menu_id:
Intent intent = new Intent(mActivity, BrowserPreferencesPage.class);
diff --git a/src/com/android/browser/Controller.java b/src/com/android/browser/Controller.java
index f4588bd..745a0f4 100644
--- a/src/com/android/browser/Controller.java
+++ b/src/com/android/browser/Controller.java
@@ -43,6 +43,7 @@
import android.net.http.SslError;
import android.os.AsyncTask;
import android.os.Bundle;
+import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.PowerManager;
@@ -77,6 +78,7 @@
import android.webkit.WebIconDatabase;
import android.webkit.WebSettings;
import android.webkit.WebView;
+import android.widget.Toast;
import java.io.ByteArrayOutputStream;
import java.io.File;
@@ -1520,7 +1522,7 @@
break;
case R.id.add_bookmark_menu_id:
- bookmarkCurrentPage(AddBookmarkPage.DEFAULT_FOLDER_ID);
+ bookmarkCurrentPage(AddBookmarkPage.DEFAULT_FOLDER_ID, false);
break;
case R.id.stop_reload_menu_id:
@@ -1567,6 +1569,54 @@
getCurrentTopWebView().showFindDialog(null, true);
break;
+ case R.id.save_webarchive_menu_id:
+ String state = Environment.getExternalStorageState();
+ if (!Environment.MEDIA_MOUNTED.equals(state)) {
+ Log.e(LOGTAG, "External storage not mounted");
+ Toast.makeText(mActivity, R.string.webarchive_failed,
+ Toast.LENGTH_SHORT).show();
+ break;
+ }
+ final String directory = Environment.getExternalStoragePublicDirectory(
+ Environment.DIRECTORY_DOWNLOADS) + File.separator;
+ File dir = new File(directory);
+ if (!dir.exists() && !dir.mkdirs()) {
+ Log.e(LOGTAG, "Save as Web Archive: mkdirs for " + directory + " failed!");
+ Toast.makeText(mActivity, R.string.webarchive_failed,
+ Toast.LENGTH_SHORT).show();
+ break;
+ }
+ WebView topWebView = getCurrentTopWebView();
+ final String title = topWebView.getTitle();
+ topWebView.saveWebArchive(directory, true,
+ new ValueCallback<String>() {
+ @Override
+ public void onReceiveValue(final String value) {
+ if (value != null) {
+ File file = new File(value);
+ final long length = file.length();
+ if (file.exists() && length > 0) {
+ Toast.makeText(mActivity, R.string.webarchive_saved,
+ Toast.LENGTH_SHORT).show();
+ final DownloadManager manager = (DownloadManager) mActivity
+ .getSystemService(Context.DOWNLOAD_SERVICE);
+ new Thread("Add WebArchive to download manager") {
+ @Override
+ public void run() {
+ manager.completedDownload(null == title ? value : title,
+ value, true, "application/x-webarchive-xml",
+ value, length, true);
+ }
+ }.start();
+ return;
+ }
+ }
+ Toast.makeText(mActivity,
+ R.string.webarchive_failed, Toast.LENGTH_SHORT).show();
+ }
+ });
+ break;
+
case R.id.page_info_menu_id:
mPageDialogsHandler.showPageInfo(mTabControl.getCurrentTab(),
false);
@@ -1804,9 +1854,13 @@
/**
* add the current page as a bookmark to the given folder id
* @param folderId use -1 for the default folder
+ * @param canBeAnEdit If true, check to see whether the site is already
+ * bookmarked, and if it is, edit that bookmark. If false, and
+ * the site is already bookmarked, do not attempt to edit the
+ * existing bookmark.
*/
@Override
- public void bookmarkCurrentPage(long folderId) {
+ public void bookmarkCurrentPage(long folderId, boolean canBeAnEdit) {
Intent i = new Intent(mActivity,
AddBookmarkPage.class);
WebView w = getCurrentTopWebView();
@@ -1827,6 +1881,9 @@
i.putExtra(BrowserContract.Bookmarks.FAVICON, w.getFavicon());
i.putExtra(BrowserContract.Bookmarks.PARENT,
folderId);
+ if (canBeAnEdit) {
+ i.putExtra(AddBookmarkPage.CHECK_FOR_DUPE, true);
+ }
// Put the dialog at the upper right of the screen, covering the
// star on the title bar.
i.putExtra("gravity", Gravity.RIGHT | Gravity.TOP);
diff --git a/src/com/android/browser/TitleBar.java b/src/com/android/browser/TitleBar.java
index bdef82e..b8ad2ef 100644
--- a/src/com/android/browser/TitleBar.java
+++ b/src/com/android/browser/TitleBar.java
@@ -215,7 +215,7 @@
mController.stopLoading();
} else {
mController.bookmarkCurrentPage(
- AddBookmarkPage.DEFAULT_FOLDER_ID);
+ AddBookmarkPage.DEFAULT_FOLDER_ID, true);
}
button.setPressed(false);
} else if (mTitleBg.isPressed()) {
diff --git a/src/com/android/browser/TitleBarXLarge.java b/src/com/android/browser/TitleBarXLarge.java
index 55347a0..453e1b8 100644
--- a/src/com/android/browser/TitleBarXLarge.java
+++ b/src/com/android/browser/TitleBarXLarge.java
@@ -244,7 +244,7 @@
mUiController.getCurrentTopWebView().goForward();
} else if (mStar == v) {
mUiController.bookmarkCurrentPage(
- AddBookmarkPage.DEFAULT_FOLDER_ID);
+ AddBookmarkPage.DEFAULT_FOLDER_ID, true);
} else if (mAllButton == v) {
mUiController.bookmarksOrHistoryPicker(false);
} else if (mSearchButton == v) {
diff --git a/src/com/android/browser/UiController.java b/src/com/android/browser/UiController.java
index ae38cff..a16b44b 100644
--- a/src/com/android/browser/UiController.java
+++ b/src/com/android/browser/UiController.java
@@ -49,7 +49,7 @@
void stopLoading();
- void bookmarkCurrentPage(long folderId);
+ void bookmarkCurrentPage(long folderId, boolean canBeAnEdit);
void bookmarksOrHistoryPicker(boolean openHistory);
diff --git a/src/com/android/browser/UrlHandler.java b/src/com/android/browser/UrlHandler.java
index 686ed7b..03bab9b 100644
--- a/src/com/android/browser/UrlHandler.java
+++ b/src/com/android/browser/UrlHandler.java
@@ -20,7 +20,6 @@
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.Cursor;
@@ -31,6 +30,7 @@
import java.net.URISyntaxException;
import java.util.List;
+import java.util.regex.Matcher;
/**
*
@@ -156,7 +156,11 @@
// security (only access to BROWSABLE activities).
intent.addCategory(Intent.CATEGORY_BROWSABLE);
intent.setComponent(null);
- if (!isSpecializedHandlerAvailable(intent)) {
+ // Make sure webkit can handle it internally before checking for specialized
+ // handlers. If webkit can't handle it internally, we need to call
+ // startActivityIfNeeded
+ Matcher m = UrlUtils.ACCEPTED_URI_SCHEMA.matcher(url);
+ if (m.matches() && !isSpecializedHandlerAvailable(intent)) {
return false;
}
try {
diff --git a/src/com/android/browser/addbookmark/FolderSpinnerAdapter.java b/src/com/android/browser/addbookmark/FolderSpinnerAdapter.java
index 0712469..261aa62 100644
--- a/src/com/android/browser/addbookmark/FolderSpinnerAdapter.java
+++ b/src/com/android/browser/addbookmark/FolderSpinnerAdapter.java
@@ -35,15 +35,27 @@
*/
public class FolderSpinnerAdapter implements SpinnerAdapter {
private boolean mIncludeHomeScreen;
+ private boolean mIncludesRecentFolder;
+ private long mRecentFolderId;
+ private String mRecentFolderName;
public static final int HOME_SCREEN = 0;
public static final int ROOT_FOLDER = 1;
public static final int OTHER_FOLDER = 2;
+ public static final int RECENT_FOLDER = 3;
public FolderSpinnerAdapter(boolean includeHomeScreen) {
mIncludeHomeScreen = includeHomeScreen;
}
+ public void addRecentFolder(long folderId, String folderName) {
+ mIncludesRecentFolder = true;
+ mRecentFolderId = folderId;
+ mRecentFolderName = folderName;
+ }
+
+ public long recentFolderId() { return mRecentFolderId; }
+
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
int labelResource;
@@ -60,6 +72,8 @@
labelResource = R.string.add_to_bookmarks_menu_option;
drawableResource = R.drawable.ic_bookmarks_holo_dark;
break;
+ case RECENT_FOLDER:
+ // Fall through and use the same icon resource
case OTHER_FOLDER:
labelResource = R.string.add_to_other_folder_menu_option;
drawableResource = R.drawable.ic_folder_holo_dark;
@@ -73,7 +87,11 @@
Context context = parent.getContext();
LayoutInflater factory = LayoutInflater.from(context);
TextView textView = (TextView) factory.inflate(R.layout.add_to_option, null);
- textView.setText(labelResource);
+ if (position == RECENT_FOLDER) {
+ textView.setText(mRecentFolderName);
+ } else {
+ textView.setText(labelResource);
+ }
Drawable drawable = context.getResources().getDrawable(drawableResource);
textView.setCompoundDrawablesWithIntrinsicBounds(drawable, null,
null, null);
@@ -90,7 +108,10 @@
@Override
public int getCount() {
- return mIncludeHomeScreen ? 3 : 2;
+ int count = 2;
+ if (mIncludeHomeScreen) count++;
+ if (mIncludesRecentFolder) count++;
+ return count;
}
@Override
diff --git a/src/com/android/browser/preferences/GeneralPreferencesFragment.java b/src/com/android/browser/preferences/GeneralPreferencesFragment.java
index 33bfd9c..1c82e1c 100644
--- a/src/com/android/browser/preferences/GeneralPreferencesFragment.java
+++ b/src/com/android/browser/preferences/GeneralPreferencesFragment.java
@@ -25,6 +25,8 @@
import android.accounts.Account;
import android.accounts.AccountManager;
+import android.accounts.AccountManagerCallback;
+import android.accounts.AccountManagerFuture;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
@@ -132,6 +134,40 @@
};
+ private AccountManagerCallback<Bundle> mCallback =
+ new AccountManagerCallback<Bundle>() {
+
+ @Override
+ public void run(AccountManagerFuture<Bundle> future) {
+ try {
+ Bundle bundle = future.getResult();
+ String name = bundle.getString(AccountManager.KEY_ACCOUNT_NAME);
+ String type = bundle.getString(AccountManager.KEY_ACCOUNT_TYPE);
+ Account account = new Account(name, type);
+ Fragment frag = new ImportWizardDialog();
+ Bundle extras = mChromeSync.getExtras();
+ extras.putParcelableArray("accounts", new Account[] { account });
+ frag.setArguments(extras);
+ getFragmentManager().beginTransaction()
+ .add(frag, null)
+ .commit();
+ } catch (Exception ex) {
+ // Canceled or failed to login, doesn't matter to us
+ }
+ }
+ };
+
+ OnPreferenceClickListener mAddAccount = new OnPreferenceClickListener() {
+
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ AccountManager am = AccountManager.get(getActivity());
+ am.addAccount("com.google", null, null, null, getActivity(),
+ mCallback, null);
+ return true;
+ }
+ };
+
private class GetAccountsTask extends AsyncTask<Void, Void, String> {
private Context mContext;
@@ -146,7 +182,7 @@
if (accounts == null || accounts.length == 0) {
// No Google accounts setup, don't offer Chrome sync
if (mChromeSync != null) {
- getPreferenceScreen().removePreference(mChromeSync);
+ mChromeSync.setOnPreferenceClickListener(mAddAccount);
}
} else {
// Google accounts are present.